npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ark-indexdb

v0.0.2

Published

simple library to manage index db

Readme

My own convenient js for IndexDB!

Simple javascript functions to manage IndexDB

╔═══════════════════════════════════════════════════════════╗
║               ArkIndexDb  v1.0.0                          ║
║   A complete, production-grade IndexedDB wrapper library  ║
║   100% browser-native · zero dependencies · ES2020+       ║
╚═══════════════════════════════════════════════════════════╝

Version License Size Browser


Table of Contents


What is ArkIndexDb?

ArkIndexDb is a thin but powerful wrapper around the browser's native IndexedDB API. IndexedDB is the browser's built-in persistent key-value / object store — it can hold hundreds of megabytes of structured data, survives page reloads and browser restarts, and works completely offline with no server required.

The raw IndexedDB API is notoriously verbose and callback-heavy. ArkIndexDb fixes that by providing:

  • A clean Promise-based async/await API
  • A fluent Query Builder for chained, readable queries
  • Schema-driven store and index creation
  • Field-level patch operators ($inc, $push, $toggle, …)
  • Multi-store atomic transactions
  • A built-in event emitter for reactive data flows
  • JSON import / export and one-call browser file download

Everything runs 100% locally in the browser. No network requests, no backend, no npm, no bundler required.


Features

| Feature | Description | |---|---| | 🏗 Schema-driven | Declare stores and indexes upfront; ArkIndexDb creates them automatically | | ⚡ Full CRUD | insert, insertMany, findById, findAll, update, delete, and more | | 🔍 Rich queries | Filter by field values, operators, or predicate functions | | 📑 Native indexes | findByIndex and findByRange use IDB's O(log n) index lookups | | 📄 Pagination | Built-in paginate() with page/pageSize, totalPages, hasNext, hasPrev | | 🔗 Query Builder | Fluent chainable API: .where().sortBy().limit().page().exec() | | 🧩 Patch operators | $set, $inc, $dec, $mul, $push, $pull, $toggle, $unset | | 🔁 Upsert | Insert-or-replace via native IDB put() | | ⚛️ Transactions | Multi-store atomic operations with automatic rollback on error | | 🖱 Cursor iteration | Memory-efficient record traversal for very large stores | | 📤 Export | JSON export of one store or all stores; triggers browser file download | | 📥 Import | Import records from a JSON string or file | | 📡 Event emitter | React to insert, update, delete, clear, error, and more | | 🕑 Auto-timestamps | _createdAt and _updatedAt ISO strings added automatically | | 🆔 Auto UUID | Primary keys auto-generated via crypto.getRandomValues() |


Browser Support

ArkIndexDb uses ES2020 private class fields (#) and async/await.

| Browser | Minimum Version | |---|---| | Chrome / Edge | 74+ | | Firefox | 90+ | | Safari | 14.1+ | | Opera | 62+ |

Note: IndexedDB itself is available in all modern browsers and many older ones. The ES2020 syntax is the limiting factor for ArkIndexDb. If you need to support older browsers, transpile with Babel.


Demo Link

You may be using Demo Link.


Installation

Option 1 — npm install

npm install: Generic badge

    npm i ark-indexdb

Option 1 — Script tag (recommended, zero build step)

Download ark-indexdb.js and place it alongside your HTML:

<script src="https://cdn.jsdelivr.net/npm/ark-indexdb@latest/ark-indexdb.js"></script>
<!-- ArkIndexDb and ArkQueryBuilder are now on window -->

Option 2 — Inline

Copy the contents of ark-indexdb.js directly into a <script> block in your HTML file. Useful for single-file apps.

Option 3 — ES Module (with a bundler)

Add export statements to ark-indexdb.js and import:

import { ArkIndexDb } from './ark-indexdb.js';

Quick Start

// 1. Create an instance
const ark = new ArkIndexDb();

// 2. Open the database — define your schema here
await ark.open('MyAppDB', 1, {
  users: {
    keyPath: 'id',
    autoIncrement: false,
    indexes: [
      { name: 'by_email', keyPath: 'email', unique: true  },
      { name: 'by_role',  keyPath: 'role',  unique: false },
    ]
  }
});

// 3. INSERT — UUID id is auto-generated
const key = await ark.insert('users', {
  name:  'Alice Chen',
  email: '[email protected]',
  role:  'admin',
});

// 4. READ by primary key
const user = await ark.findById('users', key);
console.log(user.name); // "Alice Chen"

// 5. FIND with a filter
const { data, total } = await ark.findAll('users', {
  filter: { role: 'admin' },
  sort: 'name',
  order: 'asc',
});

// 6. UPDATE (partial merge — only listed fields change)
await ark.update('users', key, { city: 'Berlin' });

// 7. DELETE
await ark.delete('users', key);

Schema & Indexes

Pass your schema as the third argument to open(). Each top-level key becomes an object store. Declaring indexes lets you use findByIndex() and findByRange() for native, fast O(log n) lookups.

const schema = {
  posts: {
    keyPath:       'id',    // primary key field name (default: 'id')
    autoIncrement: false,   // set true for auto-incrementing numeric keys
    indexes: [
      { name: 'by_author',   keyPath: 'authorId', unique: false },
      { name: 'by_category', keyPath: 'category', unique: false },
      { name: 'by_slug',     keyPath: 'slug',     unique: true  },
    ]
  },
  comments: {
    keyPath: 'id',
    indexes: [
      { name: 'by_post', keyPath: 'postId', unique: false },
    ]
  },
  settings: {
    keyPath: 'key',   // any field can be the primary key
  }
};

await ark.open('BlogDB', 1, schema);

Schema Upgrades

To add new stores or indexes to an existing database, increment the version number. ArkIndexDb's onupgradeneeded handler runs automatically:

// Version 1 → 2 adds a new store and a new index
await ark.open('BlogDB', 2, {
  ...schema,
  tags: { keyPath: 'id' }
});

API Reference

Lifecycle

ark.open(name, version, schema)Promise<ArkIndexDb>

Opens or creates an IndexedDB database. Always await this before any other call.

const ark = new ArkIndexDb();
await ark.open('AppDB', 1, schema);

ark.close()void

Closes the active database connection.

ArkIndexDb.dropDatabase(name)Promise<boolean> (static)

Permanently deletes a database by name.

await ArkIndexDb.dropDatabase('AppDB');

ArkIndexDb.listDatabases()Promise<Array<{name, version}>> (static)

Lists all IndexedDB databases in the current origin.

const dbs = await ArkIndexDb.listDatabases();

Getters

| Property | Type | Description | |---|---|---| | ark.isOpen | boolean | Whether the database is currently open | | ark.dbName | string | Database name | | ark.dbVersion | number | Database version | | ark.storeNames | string[] | All object store names |


Create

ark.insert(storeName, data)Promise<string>

Inserts a single record. A UUID id is auto-generated if the keyPath is 'id' and no id is provided. Adds _createdAt and _updatedAt ISO timestamps automatically.

const key = await ark.insert('users', {
  name:  'Bob',
  email: '[email protected]',
  role:  'user',
  tags:  ['beta', 'early-adopter'],
});
// key → UUID string e.g. "df_lxyz1_a8b3c"

ark.insertMany(storeName, records[])Promise<string[]>

Inserts multiple records in a single IDB transaction. Significantly faster than calling insert() in a loop for bulk data.

const keys = await ark.insertMany('products', [
  { name: 'Widget A', price: 9.99  },
  { name: 'Widget B', price: 14.99 },
  { name: 'Gadget X', price: 49.99 },
]);
// keys → ['uuid-1', 'uuid-2', 'uuid-3']

Read

ark.findById(storeName, id)Promise<Object | null>

Fetches a single record by its primary key. Returns null if not found.

const user = await ark.findById('users', 'abc-123');

ark.findAll(storeName, options?)Promise<{ data, total }>

Fetches all records with optional in-memory filter, sort, limit, and offset.

const { data, total } = await ark.findAll('users', {
  filter: { role: 'admin', age: { $gte: 18 } },
  sort:   'name',
  order:  'asc',   // 'asc' | 'desc'
  limit:  10,
  offset: 0,
});
  • data — the matching records array (after pagination)
  • total — total matching count before limit/offset

ark.findByIndex(storeName, indexName, value, options?)Promise<{ data, total }>

Uses a native IDB index for fast lookups. The index must be declared in the schema.

// Find all admins using the native 'by_role' index
const { data } = await ark.findByIndex('users', 'by_role', 'admin');

// Combine with additional in-memory filtering
const { data } = await ark.findByIndex(
  'users', 'by_role', 'admin',
  { filter: { status: 'active' }, sort: 'name' }
);

ark.findByRange(storeName, indexName, range, options?)Promise<{ data, total }>

Performs a key range query on a named index.

// Products priced between $10 and $50 (inclusive)
const { data } = await ark.findByRange('products', 'by_price', {
  lower: 10,
  upper: 50,
});

// Price strictly greater than $10 (exclusive lower bound)
const { data } = await ark.findByRange('products', 'by_price', {
  lower:     10,
  lowerOpen: true,   // open = exclusive
});

// All prices up to $50
const { data } = await ark.findByRange('products', 'by_price', {
  upper: 50,
});

Range options:

| Option | Type | Default | Description | |---|---|---|---| | lower | any | — | Lower bound value | | upper | any | — | Upper bound value | | lowerOpen | boolean | false | Exclude the lower bound itself | | upperOpen | boolean | false | Exclude the upper bound itself |

ark.findOne(storeName, filter)Promise<Object | null>

Returns the first matching record, or null if none found.

const admin = await ark.findOne('users', { role: 'admin' });
const alice = await ark.findOne('users', r => r.email === '[email protected]');

ark.exists(storeName, id)Promise<boolean>

if (await ark.exists('users', id)) {
  console.log('User found');
}

ark.count(storeName, filter?)Promise<number>

Uses native IDB count() when no filter is supplied (fastest path).

const total  = await ark.count('users');
const admins = await ark.count('users', { role: 'admin' });
const active = await ark.count('users', r => r.status === 'active');

ark.getAllKeys(storeName)Promise<Array>

Returns all primary keys without fetching full record data.

const ids = await ark.getAllKeys('users');

ark.paginate(storeName, page, pageSize, options?)Promise<PaginationResult>

const result = await ark.paginate('users', 1, 10, {
  filter: { status: 'active' },
  sort:   'name',
  order:  'asc',
});

result.data        // current page records
result.total       // total matching records
result.page        // current page number
result.pageSize    // records per page
result.totalPages  // total page count
result.hasNext     // true if a next page exists
result.hasPrev     // true if a previous page exists

Update

ark.update(storeName, id, changes)Promise<Object>

Partial merge — only the fields you specify are changed. All unmentioned fields are preserved. Throws if the record doesn't exist. Updates _updatedAt automatically.

// Only 'name' and 'city' change; email, role, etc. are untouched
const updated = await ark.update('users', id, {
  name: 'Alice Smith',
  city: 'Berlin',
});

ark.upsert(storeName, data)Promise<string>

Insert or replace via native IDB put(). Does not require the record to exist first. If the key exists, the full record is replaced.

// Creates the setting if it doesn't exist, overwrites if it does
await ark.upsert('settings', { id: 'theme', value: 'dark' });
await ark.upsert('settings', { id: 'theme', value: 'light' }); // overwrites

ark.patch(storeName, id, ops)Promise<Object>

Field-level patch operators — atomically mutate specific fields without manually reading and rewriting the full record.

await ark.patch('users', id, {
  $set:    { city: 'Tokyo', bio: 'Developer' },  // set fields
  $inc:    { loginCount: 1 },                    // add 1
  $dec:    { credits: 5 },                       // subtract 5
  $mul:    { score: 1.5 },                       // multiply by 1.5
  $toggle: { isVerified: true },                 // flip boolean
  $push:   { tags: 'vip' },                      // append to array
  $pull:   { tags: 'beta' },                     // remove from array
  $unset:  ['temporaryField'],                   // delete field
});

See Patch Operators for the full table.

ark.updateWhere(storeName, filter, changes)Promise<Object[]>

Updates all records matching a filter. Returns an array of all updated records.

// Deactivate all guest users
const updated = await ark.updateWhere(
  'users',
  { role: 'guest' },
  { status: 'inactive' }
);
console.log(`Updated ${updated.length} users`);

Delete

ark.delete(storeName, id)Promise<boolean>

Deletes a single record by primary key. Throws if the record doesn't exist.

await ark.delete('users', id);

ark.deleteWhere(storeName, filter)Promise<number>

Deletes all records matching a filter. Returns the count of deleted records.

// Prune expired sessions
const n = await ark.deleteWhere('sessions', {
  expiresAt: { $lt: new Date().toISOString() }
});
console.log(`Pruned ${n} expired sessions`);

ark.clear(storeName)Promise<number>

Deletes all records in a store while keeping the store structure intact. Returns the count of deleted records.

await ark.clear('logs');

Query Builder

A fluent, chainable API. Call ark.query(storeName) to get a builder, chain methods, then call one of the terminal methods (.exec(), .count(), .first()).

// Fetch records
const { data } = await ark
  .query('users')
  .where({ role: 'admin', age: { $gte: 25 } })
  .sortBy('name', 'asc')
  .limit(10)
  .offset(0)
  .exec();

// Count without fetching data
const n = await ark.query('users')
  .where({ status: 'active' })
  .count();

// First matching record
const alice = await ark.query('users')
  .where({ email: '[email protected]' })
  .first();

// Paginate via builder (.page(pageNumber, pageSize))
const { data } = await ark.query('posts')
  .where({ category: 'tech' })
  .sortBy('_createdAt', 'desc')
  .page(2, 20)
  .exec();

Builder Methods

| Method | Description | |---|---| | .where(filter) | Set a filter object or predicate function | | .sortBy(field, order?) | Sort by field, 'asc' (default) or 'desc' | | .limit(n) | Maximum number of records to return | | .offset(n) | Number of records to skip | | .page(p, size?) | Shorthand for limit + offset for page p | | .exec() | Execute → returns { data, total } | | .count() | Execute count only → returns number | | .first() | Execute, return first result or null |


Transactions

Run multiple operations across one or more stores atomically. If any step throws, the entire transaction is automatically rolled back.

await ark.transaction(
  ['users', 'orders'],  // all stores involved
  'readwrite',
  async (stores) => {
    // Both inserts succeed together — or both roll back
    const userId = crypto.randomUUID();

    await stores.users.add({
      id:         userId,
      name:       'Dave',
      _createdAt: new Date().toISOString(),
      _updatedAt: new Date().toISOString(),
    });

    await stores.orders.add({
      id:      crypto.randomUUID(),
      userId,
      total:   149.99,
      status:  'pending',
    });
  }
);

The stores proxy exposes promisified versions of the native IDB methods:

add · put · get · delete · clear · getAll · count · getAllKeys · index(name)


Cursor Iteration

For very large stores, loading all records into memory with getAll() may be expensive. Use iterateCursor() to process records one at a time:

await ark.iterateCursor('logs', record => {
  if (record.level === 'error') {
    console.error(record.message);
  }
  // return false to stop iteration early
});

// Reverse direction
await ark.iterateCursor('events', record => {
  process(record);
}, 'prev');

Direction options: 'next' (default) · 'prev' · 'nextunique' · 'prevunique'


Import / Export

ark.exportStore(storeName)Promise<string>

Exports all records from a store as a formatted JSON string.

const json = await ark.exportStore('users');
localStorage.setItem('users_backup', json);

ark.exportAll()Promise<string>

Exports every store in the database into a single JSON string.

const fullBackup = await ark.exportAll();

ark.downloadStore(storeName)Promise<void>

Triggers a browser file download of the store's JSON export.

await ark.downloadStore('users');
// Browser saves: "users_1700000000000.json"

ark.importStore(storeName, json)Promise<number>

Imports records from a JSON string previously created by exportStore(). Returns the count of imported records.

// From a fetch response
const json = await fetch('/backup/users.json').then(r => r.text());
const n = await ark.importStore('users', json);
console.log(`Imported ${n} records`);

// From a file input
fileInput.addEventListener('change', async e => {
  const text = await e.target.files[0].text();
  await ark.importStore('users', text);
});

Events

Listen to lifecycle operations with ark.on(event, callback). The returned value is an unsubscribe function.

// Subscribe to a specific event
const off = ark.on('insert', ({ storeName, key, data }) => {
  console.log(`Inserted into ${storeName}: key=${key}`);
});

// Wildcard — receives every event
ark.on('*', e => console.log('[ArkIndexDb]', e.event, e));

// Unsubscribe
off();

All Available Events

| Event | Payload | Description | |---|---|---| | open | { name, version } | DB opened successfully | | upgrade | { oldVersion, newVersion } | DB schema upgraded | | insert | { storeName, key, data } | One record inserted | | insertMany | { storeName, count } | Batch insert completed | | update | { storeName, id, before, after } | Record updated | | updateMany | { storeName, count } | Bulk update completed | | upsert | { storeName, key } | Record upserted | | delete | { storeName, id, record } | Record deleted | | deleteMany | { storeName, count } | Bulk delete completed | | clear | { storeName, count } | Store cleared | | import | { storeName, count } | Import completed | | transaction | { storeNames, mode, status } | Transaction committed or errored | | error | IDB error object | Any IndexedDB error | | versionchange | {} | Another tab opened a newer DB version | | blocked | {} | DB open blocked by another connection | | * | { event, ...payload } | Wildcard — all of the above |


Filter Operators

Use operators inside filter objects for findAll(), findOne(), updateWhere(), deleteWhere(), and the Query Builder's .where().

// Shorthand (exact equality)
{ role: 'admin' }

// With operator
{ age: { $gte: 18 }, status: { $ne: 'banned' } }

| Operator | Description | Example | |---|---|---| | $eq | Equal to (same as plain value) | { age: { $eq: 30 } } | | $ne | Not equal to | { status: { $ne: 'banned' } } | | $gt | Greater than | { price: { $gt: 100 } } | | $gte | Greater than or equal to | { age: { $gte: 18 } } | | $lt | Less than | { stock: { $lt: 10 } } | | $lte | Less than or equal to | { score: { $lte: 50 } } | | $in | Value is in the array | { role: { $in: ['admin', 'mod'] } } | | $nin | Value is NOT in the array | { status: { $nin: ['banned', 'deleted'] } } | | $contains | String contains substring (case-insensitive) | { name: { $contains: 'ali' } } | | $startsWith | String starts with prefix (case-insensitive) | { email: { $startsWith: 'admin' } } | | $endsWith | String ends with suffix (case-insensitive) | { email: { $endsWith: '.gov' } } | | $regex | String matches regexp (case-insensitive) | { phone: { $regex: '^\\+1' } } | | $exists | Field exists (true) or is null/undefined (false) | { avatar: { $exists: true } } | | $type | typeof field equals the given string | { score: { $type: 'number' } } | | $size | Array field has exactly N elements | { tags: { $size: 3 } } |

Dot Notation

Access nested fields with dot notation:

{ 'address.city': 'Berlin' }
{ 'meta.score': { $gte: 90 } }

Function Predicate

Pass a function for full programmatic control:

const { data } = await ark.findAll('users', {
  filter: r => r.tags?.includes('vip') && r.age > 25
});

Patch Operators

Used with ark.patch() for atomic field-level mutations.

| Operator | Value Type | Description | |---|---|---| | $set | { field: value } | Set field to a value | | $unset | ['field', ...] | Delete (remove) the listed fields | | $inc | { field: n } | Add n to the numeric field | | $dec | { field: n } | Subtract n from the numeric field | | $mul | { field: n } | Multiply the numeric field by n | | $toggle | { field: true } | Flip a boolean field to its opposite | | $push | { field: value } | Append value to an array field | | $pull | { field: value } | Remove all occurrences of value from an array field |


Full Method List

| Method | Returns | Description | |---|---|---| | open(name, version, schema) | Promise<this> | Open or create database | | close() | void | Close connection | | ArkIndexDb.dropDatabase(name) | Promise<boolean> | Delete a database (static) | | ArkIndexDb.listDatabases() | Promise<Array> | List origin databases (static) | | insert(store, data) | Promise<key> | Insert one record | | insertMany(store, records[]) | Promise<key[]> | Batch insert in one transaction | | findById(store, id) | Promise<Object\|null> | Fetch by primary key | | findAll(store, options?) | Promise<{data, total}> | Fetch with filter/sort/page | | findByIndex(store, index, value) | Promise<{data, total}> | Native IDB index lookup | | findByRange(store, index, range) | Promise<{data, total}> | Key range query on index | | findOne(store, filter) | Promise<Object\|null> | First match or null | | exists(store, id) | Promise<boolean> | Check record existence | | count(store, filter?) | Promise<number> | Count records | | getAllKeys(store) | Promise<Array> | All primary keys | | paginate(store, page, size, opts?) | Promise<PaginationResult> | Paginated fetch | | update(store, id, changes) | Promise<Object> | Partial record merge | | upsert(store, data) | Promise<key> | Insert or replace | | patch(store, id, ops) | Promise<Object> | Field-level patch operators | | updateWhere(store, filter, changes) | Promise<Object[]> | Bulk update by filter | | delete(store, id) | Promise<boolean> | Delete by primary key | | deleteWhere(store, filter) | Promise<number> | Delete all matching | | clear(store) | Promise<number> | Delete all records in store | | query(store) | ArkQueryBuilder | Get fluent query builder | | transaction(stores[], mode, fn) | Promise<void> | Multi-store atomic transaction | | iterateCursor(store, cb, dir?) | Promise<void> | Memory-efficient cursor iteration | | exportStore(store) | Promise<string> | Export store as JSON string | | exportAll() | Promise<string> | Export all stores as JSON | | importStore(store, json) | Promise<number> | Import records from JSON | | downloadStore(store) | Promise<void> | Trigger browser file download | | on(event, callback) | Function (unsubscribe) | Subscribe to an event | | off(event, callback) | void | Unsubscribe a listener |


Files

| File | Description | |---|---| | ark-indexdb.js | The standalone library — include this in any project | | demo.html | Interactive demo + full documentation viewer | | README.md | This file |

Usage with the HTML demo

Open demo.html in a browser. It loads ark-indexdb.js from the same directory automatically (with a built-in inline fallback so it also works as a standalone single file).

The demo has two views:

  • ⬡ Live Database — interact with a real IndexedDB in your browser with 3 seeded object stores, full CRUD UI, search, filters, pagination, and an operation log
  • ◈ Documentation — the full Getting Started guide, all API docs, and interactive code blocks with copy buttons

License

MIT License © 2024 ArkIndexDb Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.