IndexedDB
Persist structured records with object stores, indexes, cursors, and transactions.
IndexedDB stores structured records with object stores, indexes, cursors, and transactions.
Create and associate the resource first; see resources and associations in the module overview.
import { IndexedDB } from 'lexmount:storage';IndexedDB is an IDBFactory, identical to globalThis.indexedDB. These APIs use event requests and transactions: an IDBRequest is not a promise. IDB* types and IDBKeyRange are available without another import.
Keys, queries, and batch read options
| Type / parameter | Description |
|---|---|
IDBValidKey | A valid number, Date, string, binary key, or compound array of these types; NaN, invalid Dates, null, and undefined are invalid keys |
query | IDBValidKey or IDBKeyRange; methods marking it optional query all records when omitted |
direction | 'next' (default), 'nextunique', 'prev', or 'prevunique'; controls order and duplicate index keys |
count | Optional integer 0–4294967295 limiting batch results; omitted or 0 means no count limit |
IDBGetAllOptions | { query?, count?, direction? }, with the meanings above; accepted as the first argument of getAll() / getAllKeys() and by getAllRecords() |
IDBRecord | { key, primaryKey, value }; key belongs to the query source, primaryKey identifies the object store record, and value is the record value |
Cloneable values include ordinary objects, arrays, cycles, undefined, BigInt, Date, RegExp, Map, Set, Error, ArrayBuffer / TypedArray, and Blob / File. Functions and unsupported host objects cause DataCloneError. Values are not limited to JSON.
IndexedDB.open(name, version?)
Function: opens an existing associated database, upgrading its structure when needed.
Parameters: required name: string, the resource name; optional positive-integer version?: number, defaulting to the current version. Empty databases created in the console start at version 0; their initial open upgrades to version 1, allowing object stores and indexes to be created in upgradeneeded.
Return value: IDBOpenDBRequest, synchronously. On success, result is an IDBDatabase. Missing or unassociated databases produce NotFoundError through the request's error event; no database is created.
IndexedDB.databases()
Function: lists databases associated with this instance.
Parameters: none.
Return value: Promise<IDBDatabaseInfo[]>, with database name and numeric version fields.
IndexedDB.cmp(first, second)
Function: compares two keys in IndexedDB key order.
Parameters: required first and second, both IDBValidKey.
Return value: synchronous -1, 0, or 1 for less than, equal, or greater than. Invalid keys throw DataError.
IndexedDB.deleteDatabase(name)
Function: database deletion from code is prohibited in this runtime. Delete resources in the console.
Parameters: name: string, the standard interface's database-name argument.
Return value: no request object is returned; always throws NotAllowedError synchronously.
IDBDatabase
Obtain db from a successful open request. Database, object store, and index names are limited to 1024 UTF-8 bytes and cannot contain NUL or invalid Unicode.
| Property | Type | Description |
|---|---|---|
name | string | Database name, read-only |
version | number | Current version, read-only |
objectStoreNames | DOMStringList | Object store names, a read-only list |
| Method | Function | Parameters | Return value |
|---|---|---|---|
db.createObjectStore(name, options?) | Create an object store during an upgrade transaction | Required name; options.keyPath?: string | string[] | null defaults to null; options.autoIncrement?: boolean defaults to false | IDBObjectStore, synchronously |
db.deleteObjectStore(name) | Delete a store, records, and indexes during an upgrade transaction | Required name: string | void |
db.transaction(storeNames, mode?, options?) | Start a transaction | Required store name or array; mode is readonly (default) or readwrite; options.durability is default (default), strict, or relaxed | IDBTransaction |
db.close() | Close the connection once existing transactions complete | None | void |
Create or delete object stores in the upgrade transaction during upgradeneeded; use readonly or readwrite transactions for ordinary application access. Durability accepts standard values, but all currently wait for backend commit.
Database event properties include onversionchange, onclose, onerror, and onabort. Version events contain oldVersion: number and newVersion: number | null. Version coordination works within one runtime. Upgrades across instances do not broadcast browser-style version events; coordinate them in the application and reopen older connections.
IDBTransaction
| Property | Type | Description |
|---|---|---|
db | IDBDatabase | Owning connection |
mode | IDBTransactionMode | readonly, readwrite, or upgrade-only versionchange |
durability | IDBTransactionDurability | Transaction durability option |
objectStoreNames | DOMStringList | Stores accessible in this transaction |
error | DOMException / null | Transaction failure, or null when absent |
| Method | Function | Parameters | Return value |
|---|---|---|---|
tx.objectStore(name) | Access a store in this transaction's scope | Required name: string | IDBObjectStore |
tx.commit() | Explicitly begin commit, preventing new requests | None | void; still wait for complete |
tx.abort() | Abort and roll back the transaction | None | void |
oncomplete confirms backend commit; onabort reports abortion; onerror observes request errors. An individual request's success does not establish persistence. Transactions commit automatically and must be active when issuing requests. Do not await unrelated network requests or timers inside a transaction and then expect to continue reading or writing.
IDBRequest and IDBOpenDBRequest
| Property | Type | Description |
|---|---|---|
result | Depends on operation | Successful result; reading before completion throws InvalidStateError |
error | DOMException / null | Request error; reading before completion throws InvalidStateError |
source | IDBObjectStore / IDBIndex / IDBCursor / null | Request source |
transaction | IDBTransaction / null | Owning transaction; an open request exposes its upgrade transaction during upgrade |
readyState | 'pending' / 'done' | Request state |
Ordinary requests report results through onsuccess / onerror. Open requests add onupgradeneeded and onblocked; upgrade events provide oldVersion and newVersion.
Requests, transactions, and databases support event properties and EventTarget's addEventListener(type, listener, options?), removeEventListener(type, listener, options?), and dispatchEvent(event). The first two return void; dispatchEvent returns boolean. A listener is a callback or event-listener object; options control standard behavior such as capture and once. Handling a request error with the event's preventDefault() suppresses default abortion, allowing the application to decide transaction handling.
IDBObjectStore
store.name: string can be changed during an upgrade transaction. Other properties are read-only: keyPath: string | string[] | null, autoIncrement: boolean, indexNames: DOMStringList, and transaction: IDBTransaction.
| Method | Function | Parameters | Return value |
|---|---|---|---|
store.add(value, key?) | Insert; duplicate primary keys cause ConstraintError | Required cloneable value; optional primary key; do not pass key separately with inline keyPath | IDBRequest<IDBValidKey> containing the primary key |
store.put(value, key?) | Insert or replace by primary key | As for add | IDBRequest<IDBValidKey> |
store.get(query) | Read the first matching value | Required key or key range | IDBRequest<any>; undefined when missing |
store.getKey(query) | Read the first matching primary key | Required key or key range | IDBRequest containing a key or undefined |
store.getAll(query?, count?) | Read matching values in a batch | Optional query and count, or IDBGetAllOptions as the first argument | IDBRequest<any[]>; [] when missing |
store.getAllKeys(query?, count?) | Read primary keys in a batch | As for getAll | IDBRequest<IDBValidKey[]> |
store.getAllRecords(options?) | Read keys, primary keys, and values in a batch | Optional IDBGetAllOptions | IDBRequest<IDBRecord[]> |
store.count(query?) | Count matching records | Optional key or range; omitted means all | IDBRequest<number> |
store.delete(query) | Delete matching records | Required key or range | IDBRequest<undefined> |
store.clear() | Delete all records in the store | None | IDBRequest<undefined> |
store.openCursor(query?, direction?) | Iterate keys and values | Optional query and direction | IDBRequest containing IDBCursorWithValue or null |
store.openKeyCursor(query?, direction?) | Iterate keys only | Optional query and direction | IDBRequest containing IDBCursor or null |
store.createIndex(name, keyPath, options?) | Create an index during an upgrade transaction | Required name and string or string-array keyPath; unique?: boolean and multiEntry?: boolean both default to false | IDBIndex, synchronously |
store.index(name) | Access an existing index | Required name: string | IDBIndex |
store.deleteIndex(name) | Delete an index during an upgrade transaction | Required name: string | void |
Writes require a readwrite or upgrade transaction. KeyPath extracts keys from values; autoIncrement can generate keys, subject to IndexedDB key rules. Compound keyPath and multiEntry cannot be combined.
IDBIndex
index.name: string can be changed during an upgrade transaction. Read-only properties include objectStore: IDBObjectStore, keyPath: string | string[], unique: boolean, and multiEntry: boolean.
| Method | Function | Parameters | Return value |
|---|---|---|---|
index.get(query) | Read the first value by index key | Required key or range | IDBRequest<any>; undefined when missing |
index.getKey(query) | Read the first primary key by index key | Required key or range | IDBRequest containing a primary key or undefined |
index.getAll(query?, count?) | Read values through the index in a batch | Optional query and count, or IDBGetAllOptions as the first argument | IDBRequest<any[]> |
index.getAllKeys(query?, count?) | Read primary keys through the index in a batch | As for getAll | IDBRequest<IDBValidKey[]> |
index.getAllRecords(options?) | Read index keys, primary keys, and values | Optional IDBGetAllOptions | IDBRequest<IDBRecord[]> |
index.count(query?) | Count matching index entries | Optional query; omitted means all | IDBRequest<number> |
index.openCursor(query?, direction?) | Iterate records in index order | Optional query and direction | IDBRequest containing IDBCursorWithValue or null |
index.openKeyCursor(query?, direction?) | Iterate keys in index order | Optional query and direction | IDBRequest containing IDBCursor or null |
Empty batches return []. A multiEntry index can have several entries for one record; index count counts entries. A unique index conflict fails the corresponding write request.
IDBCursor and IDBCursorWithValue
| Property | Type | Description |
|---|---|---|
source | IDBObjectStore / IDBIndex | Cursor source |
direction | IDBCursorDirection | Iteration direction |
key | IDBValidKey | Current query key; the index key for index cursors |
primaryKey | IDBValidKey | Current record's primary key |
request | IDBRequest | Request driving the cursor |
value | any | Current value, only on IDBCursorWithValue |
| Method | Function | Parameters | Return value |
|---|---|---|---|
cursor.advance(count) | Move several entries in the current direction | Required positive integer count | void |
cursor.continue(key?) | Move to the next entry or a given key | Optional valid key that advances in the current direction | void |
cursor.continuePrimaryKey(key, primaryKey) | Move to an index-key and primary-key position | Two required valid keys; only next / prev index cursors support this | void |
cursor.update(value) | Replace the current record | Required cloneable value; needs a writable transaction and value cursor | IDBRequest<IDBValidKey> |
cursor.delete() | Delete the current record | None; needs a writable transaction and value cursor | IDBRequest<undefined> |
Advance / continue do not return the next item. They trigger success again on the original request; read its request.result for the next cursor, or null at the end. Do not advance again before the previous move completes.
IDBKeyRange
Construct ranges with static methods. Returned ranges expose read-only lower and upper (valid keys, or undefined for an unset bound), plus boolean lowerOpen and upperOpen.
| Method | Function | Parameters | Return value |
|---|---|---|---|
IDBKeyRange.only(value) | Match one key | Required valid key value | IDBKeyRange |
IDBKeyRange.lowerBound(lower, open?) | Set a lower bound | Required valid key lower; open defaults to false | IDBKeyRange |
IDBKeyRange.upperBound(upper, open?) | Set an upper bound | Required valid key upper; open defaults to false | IDBKeyRange |
IDBKeyRange.bound(lower, upper, lowerOpen?, upperOpen?) | Set both bounds | Two required valid keys; both open flags default to false | IDBKeyRange |
range.includes(key) | Test whether a key is within the range | Required valid key | boolean |
Open means the boundary is excluded. Invalid keys, inverted ranges, and impossible boundary combinations throw DataError.
DOMStringList, used by objectStoreNames / indexNames, provides length: number, numeric indexing, item(index): string | null, and contains(name): boolean, and is iterable. Item takes a numeric index; contains takes a string name.
Transaction example and limits
import { IndexedDB } from 'lexmount:storage';
const request = IndexedDB.open('application', 1);
request.onupgradeneeded = () => {
request.result.createObjectStore('notes', { keyPath: 'id' });
};
const db = await new Promise((resolve, reject) => {
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
try {
const tx = db.transaction('notes', 'readwrite');
const completed = new Promise((resolve, reject) => {
tx.oncomplete = resolve;
tx.onabort = () => reject(tx.error);
});
tx.objectStore('notes').put({ id: 'first', title: 'Hello' });
await completed;
} finally {
db.close();
}Individual serialized records, keys, structure metadata, and query result pages are limited to 64 MiB. This is not a database-wide size limit. Connection acquisition, lock waits, SQL, and idle transactions have 30-second timeouts. Long transactions block writes; use object storage for large files.
Associated instances share committed data; aborted transactions roll back. Coordinate upgrades across instances, and reopen invalidated old connections. A connection lost after commit can leave the result uncertain; use stable primary keys when retrying writes. This database is separate from a webpage's own window.indexedDB.
See IDBRequest for request and transaction error handling and storage.d.ts for declarations.
