This is a migration based wrapper around the IndexedDB API.
npm install @sx3/databaseRead:
import { Database } from "@sx3/database";
const db = await new Database("mydb").open();
const users = await db.transaction("users").store().getAll();Write:
const db = await new Database("mydb").open();
const userStore = db.transaction("users", "readwrite").store();
const id = await userStore.add({ name: "SX3", age: 99 });Delete:
const db = await new Database("mydb").open();
const userStore = db.transaction("users", "readwrite").store();
await userStore.delete(1);const db = await new Database("mydb").open();
const trx = db.transaction(["users", "posts"], "readwrite");
const usersStore = trx.store("users");
const postsStore = trx.store("posts");
// Some actions ...
trx.commit(); // not necessarilyconst db = new Database("mydb");
await db.open();
db.addEventListener("abort", () => {});
db.deleteObjectStore("users");
db.close();
// etc..
const trx = db.transaction("users");
trx.objectStore("users");
trx.addEventListener("complete", () => {});
// etc..new Database("mydb").delete();import { Database } from "@sx3/database";
const db = new Database("mydb");
await db.open();
const usersStore = db.transaction("users").store();
for await (const cursor of usersStore) {
console.log(cursor.value);
}const db = new Database("mydb");
await db.open();
const usersStore = db.transaction("users").store();
const range = IDBKeyRange.bound(20, 30);
for await (const cursor of usersStore.iterate(range)) {
console.log(cursor.value);
}Iterating over an index is similar to iterating over a store
const db = new Database("mydb");
await db.open();
const usersStore = db.transaction("users").store();
const index = usersStore.index("age");
for await (const cursor of index) {
console.log(cursor.value);
}DB migrations are an array of schemas:
import { MigrationSchema, Database } from "@sx3/database";
const postsSchema: MigrationSchema = {
1: builder => builder.create("posts").index("id"),
};
const commentsSchema: MigrationSchema = {
2: builder =>
builder.create("comments").index("entity", ["entity_name", "entity_id"]),
};
// Version calculated from migrations
const db = new Database("mydb", { migrations: [postsSchema, commentsSchema] });Async migrations allow lazy loading while opening a connection to the database:
import { MigrationSchema, Database } from "@sx3/database";
const asyncSchema = () =>
new Promise<MigrationSchema>(resolve => {
resolve({
1: builder => builder.create("users").index("id"),
});
});
const db = await new Database("mydb", { migrations: [asyncSchema] }).open();You can also load migrations from other files, for example your project structure might look like this:
modules
ββ moduleA
β ββ store
β ββ posts.ts
β ββ comments.ts
ββ moduleB
ββ store
ββ cart.ts
ββ wishlist.ts
This code imports migration schemas from all your module stores:
import { MigrationSchema, Database } from "@sx3/database";
const schemas = import.meta.glob<MigrationSchema>("./modules/**/store/*.ts", {
import: "migrations",
});
const db = new Database("mydb", {
migrations: Object.values(schemas),
});Within this library, 3 new errors have been introduced:
- NotOpenedError - Database is not open
- BlockedError - Database is locked
- NoStoreProvidedError - No store provided for transaction
import {
Database,
NotOpenedError,
BlockedError,
NoStoreProvidedError,
} from "@sx3/database";
const db = new Database("mydb");
try {
await db.open();
} catch (error: unknown) {
if (error instanceof BlockedError) {
// Do something
}
}