@signaldb/indexeddb 2.0.0-beta.9 → 2.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,18 +1,15 @@
1
- import { createStorageAdapter as e } from "@signaldb/core";
1
+ import { createStorageAdapter as e, serializeValue as t } from "@signaldb/core";
2
2
  //#region src/index.ts
3
- async function t(e, t, n) {
3
+ async function n(e, t, n) {
4
4
  let r = indexedDB.open(e, t), i = new Promise((e, t) => {
5
5
  r.addEventListener("success", () => e()), r.addEventListener("error", () => t(Error(r.error?.message || "Database error"))), r.addEventListener("upgradeneeded", (i) => {
6
6
  let a = r.result, o = r.transaction;
7
- if (n) {
8
- n(a, o, i.oldVersion, i.newVersion ?? null).then(() => e()).catch(
9
- /* istanbul ignore next -- @preserve */
10
- (e) => {
11
- t(e);
12
- }
13
- );
14
- return;
15
- }
7
+ n ? n(a, o, i.oldVersion, i.newVersion ?? null).then(() => e()).catch(
8
+ /* istanbul ignore next -- @preserve */
9
+ (e) => {
10
+ t(e);
11
+ }
12
+ ) :
16
13
  /* istanbul ignore next -- @preserve */
17
14
  e();
18
15
  });
@@ -21,94 +18,118 @@ async function t(e, t, n) {
21
18
  });
22
19
  return await Promise.all([a, i]), a;
23
20
  }
24
- function n(e) {
25
- let n = t(e.databaseName || "signaldb", e.version, async (t, n) => {
26
- e.onUpgrade && await e.onUpgrade(t, n, t.version, e.version);
27
- let r = /* @__PURE__ */ new Set();
21
+ function r(e) {
22
+ let t = n(e.databaseName || "signaldb", e.version, async (t, n, r, i) => {
23
+ e.onUpgrade && await e.onUpgrade(t, n, r, i);
24
+ let a = /* @__PURE__ */ new Set();
28
25
  for (let n = 0; n < t.objectStoreNames.length; n += 1) {
29
- let i = t.objectStoreNames.item(n);
30
- !i || i in e.schema || r.add(i);
26
+ let r = t.objectStoreNames.item(n);
27
+ !r || r in e.schema || a.add(r);
31
28
  }
32
- r.forEach((e) => {
29
+ a.forEach((e) => {
33
30
  t.objectStoreNames.contains(e) && t.deleteObjectStore(e);
34
31
  });
35
32
  for (let [r, i] of Object.entries(e.schema)) {
36
33
  let e = t.objectStoreNames.contains(r) ? n.objectStore(r) : t.createObjectStore(r, { keyPath: "id" }), a = /* @__PURE__ */ new Set();
37
34
  for (let t = 0; t < e.indexNames.length; t += 1) {
38
35
  let n = e.indexNames.item(t);
39
- !n || i.includes(n) || a.add(n);
36
+ n && !i.includes(n) && a.add(n);
40
37
  }
41
38
  a.forEach((t) => {
42
39
  e.indexNames.contains(t) && e.deleteIndex(t);
43
- }), i.forEach((t) => {
44
- t !== "id" && (e.indexNames.contains(t) || e.createIndex(t, t, { unique: !1 }));
45
40
  });
41
+ for (let t of i) t === "id" || e.indexNames.contains(t) || e.createIndex(t, t, { unique: !1 });
46
42
  }
47
43
  });
48
44
  return function(e) {
49
- return r(e, n);
45
+ return i(e, t);
50
46
  };
51
47
  }
52
- function r(t, n) {
53
- let r = async (e = !1) => {
54
- let r = await n;
55
- if (!r) throw Error("Database not initialized");
56
- return r.transaction(t, e ? "readwrite" : "readonly").objectStore(t);
57
- }, i = async (e) => {
58
- let t = await r();
59
- if (!t.indexNames.contains(e)) throw Error(`Index on field "${e}" does not exist`);
60
- return new Promise((n, r) => {
61
- let i = t.index(e), a = /* @__PURE__ */ new Map(), o = i.openCursor();
62
- o.addEventListener("success", () => {
63
- let e = o.result;
48
+ function i(n, r) {
49
+ let i = async (e = !1) => {
50
+ let t = await r;
51
+ if (!t) throw Error("Database not initialized");
52
+ return t.transaction(n, e ? "readwrite" : "readonly").objectStore(n);
53
+ }, a = async (e) => {
54
+ let n = await i();
55
+ if (!n.indexNames.contains(e)) throw Error(`Index on field "${e}" does not exist`);
56
+ return new Promise((r, i) => {
57
+ let a = n.index(e), o = /* @__PURE__ */ new Map(), s = a.openCursor();
58
+ s.addEventListener("success", () => {
59
+ let e = s.result;
64
60
  if (e) {
65
- let t = e.key, n = e.value.id;
66
- a.has(t) || a.set(t, /* @__PURE__ */ new Set()), a.get(t)?.add(n), e.continue();
67
- } else n(a);
68
- }), o.addEventListener("error", () => r(Error(o.error?.message || "Error reading index")));
61
+ let n = t(e.key), r = e.value.id;
62
+ o.has(n) || o.set(n, /* @__PURE__ */ new Set()), o.get(n)?.add(r), e.continue();
63
+ } else r(o);
64
+ }), s.addEventListener("error", () => i(Error(s.error?.message || "Error reading index")));
69
65
  });
70
- }, a = async (e) => {
71
- let t = await r(!0);
66
+ }, o = async (e) => {
67
+ let t = await i(!0);
72
68
  return new Promise((n, r) => {
73
69
  let i = t.get(e);
74
70
  i.addEventListener("success", () => n(i.result || null)), i.addEventListener("error", () => r(Error(i.error?.message || "Error fetching item")));
75
71
  });
76
- }, o = async (e) => {
77
- let t = await r(!0);
72
+ }, s = async (e) => {
73
+ let t = await i(!0);
78
74
  await Promise.all(e.map((e) => new Promise((n, r) => {
79
75
  let i = t.put(e);
80
76
  i.addEventListener("success", () => n()), i.addEventListener("error", () => r(Error(i.error?.message || "Error inserting or replacing item")));
81
77
  })));
82
- };
78
+ }, c = (e) => typeof e == "string" ? !0 : typeof e == "number" ? Number.isFinite(e) : e instanceof Date && !Number.isNaN(e.getTime()), l = (e, t) => new Promise((n, r) => {
79
+ let i = e.getAll(t);
80
+ i.addEventListener("success", () => n(i.result)), i.addEventListener("error", () => r(Error(i.error?.message || "Error fetching items")));
81
+ });
83
82
  return e({
84
83
  setup: async () => {
85
- if (!(await n).objectStoreNames.contains(t)) throw Error(`Object store "${t}" does not exist in database. Make sure to define it in the schema when initializing the adapter.`);
84
+ if (!(await r).objectStoreNames.contains(n)) throw Error(`Object store "${n}" does not exist in database. Make sure to define it in the schema when initializing the adapter.`);
86
85
  },
87
86
  teardown: async () => {
88
- (await n).close();
87
+ (await r).close();
89
88
  },
90
89
  readAll: async () => {
91
- let e = await r();
90
+ let e = await i();
92
91
  return new Promise((t, n) => {
93
92
  let r = e.getAll();
94
93
  r.addEventListener("success", () => t(r.result)), r.addEventListener("error", () => n(Error(r.error?.message || "Error fetching items")));
95
94
  });
96
95
  },
97
- readIds: async (e) => (await Promise.all(e.map((e) => a(e)))).filter((e) => e !== null),
96
+ query: async ({ selector: e }) => {
97
+ let t = Object.entries(e ?? {}), n = await i(), r = typeof n.keyPath == "string" ? n.keyPath : null, a = null;
98
+ for (let [e, i] of t) if (c(i) && (e === r || n.indexNames.contains(e))) {
99
+ a = {
100
+ field: e,
101
+ key: i
102
+ };
103
+ break;
104
+ }
105
+ if (!a) return {
106
+ items: await new Promise((e, t) => {
107
+ let r = n.getAll();
108
+ r.addEventListener("success", () => e(r.result)), r.addEventListener("error", () => t(Error(r.error?.message || "Error fetching items")));
109
+ }),
110
+ residualSelector: e
111
+ };
112
+ let o = a, s = o.field === r ? n : n.index(o.field);
113
+ return {
114
+ items: await l(s, IDBKeyRange.only(o.key)),
115
+ residualSelector: Object.fromEntries(t.filter(([e]) => e !== o.field))
116
+ };
117
+ },
118
+ readIds: async (e) => (await Promise.all(e.map((e) => o(e)))).filter((e) => e !== null),
98
119
  createIndex: async () => {},
99
120
  dropIndex: async () => {},
100
- readIndex: i,
101
- insert: (e) => o(e),
102
- replace: (e) => o(e),
121
+ readIndex: a,
122
+ insert: (e) => s(e),
123
+ replace: (e) => s(e),
103
124
  remove: async (e) => {
104
- let t = await r(!0);
125
+ let t = await i(!0);
105
126
  await Promise.all(e.map(async (e) => new Promise((n, r) => {
106
127
  let i = t.delete(e.id);
107
128
  i.addEventListener("success", () => n()), i.addEventListener("error", () => r(Error(i.error?.message || "Error removing item")));
108
129
  })));
109
130
  },
110
131
  removeAll: async () => {
111
- let e = await r(!0);
132
+ let e = await i(!0);
112
133
  return new Promise((t, n) => {
113
134
  let r = e.clear();
114
135
  r.addEventListener("success", () => t()), r.addEventListener("error", () => n(Error(r.error?.message || "Error clearing items")));
@@ -117,6 +138,6 @@ function r(t, n) {
117
138
  });
118
139
  }
119
140
  //#endregion
120
- export { n as default };
141
+ export { r as default };
121
142
 
122
143
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter } from '@signaldb/core'\n\n/**\n * Opens the IndexedDB database and creates the object store if it doesn't exist.\n * @param databaseName - The name of the database.\n * @param version - The version of the database.\n * @param onUpgrade - Optional callback for handling database upgrades.\n * @returns A promise that resolves with the opened database.\n */\nasync function openDatabase(\n databaseName: string,\n version: number,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n): Promise<IDBDatabase> {\n const request = indexedDB.open(databaseName, version)\n const upgradePromise = new Promise<void>((resolve, reject) => {\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n request.addEventListener('upgradeneeded', (event) => {\n const database = request.result\n const tx = request.transaction as IDBTransaction\n if (onUpgrade) {\n onUpgrade(\n database,\n tx,\n event.oldVersion,\n event.newVersion ?? null,\n )\n .then(() => resolve())\n .catch(\n /* istanbul ignore next -- @preserve */\n (error) => {\n reject(error as Error)\n },\n )\n return\n }\n\n // No custom upgrade logic provided, resolve immediately\n /* istanbul ignore next -- @preserve */\n resolve()\n })\n })\n const databasePromise = new Promise<IDBDatabase>((resolve, reject) => {\n request.addEventListener('success', () => resolve(request.result))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n })\n await Promise.all([\n databasePromise,\n upgradePromise,\n ])\n return databasePromise\n}\n\nexport type IndexedDBOptions = {\n databaseName?: string,\n version: number,\n schema: Record<string, string[]>,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n}\n\n/**\n * Prepares an IndexedDB storage adapter for SignalDB with the specified options.\n * @param options - Configuration options for the IndexedDB adapter.\n * @param options.databaseName - The name of the IndexedDB database. Defaults to 'signaldb'.\n * @param options.version - The version of the database schema.\n * @param options.schema - An object defining the schema of the database, where keys are store names and values are arrays of index names.\n * @param options.onUpgrade - Optional callback for handling database upgrades.\n * @returns A function that takes a store name and returns a SignalDB storage adapter for that store.\n */\nexport default function prepareIndexedDB(options: IndexedDBOptions) {\n const databaseName = options.databaseName || 'signaldb'\n const databasePromise = openDatabase(\n databaseName,\n options.version,\n async (database, tx) => {\n if (options.onUpgrade) {\n await options.onUpgrade(database, tx, database.version, options.version)\n }\n\n const storesToDelete = new Set<string>()\n for (let i = 0; i < database.objectStoreNames.length; i += 1) {\n const storeName = database.objectStoreNames.item(i)\n if (!storeName || storeName in options.schema) continue\n storesToDelete.add(storeName)\n }\n\n // Delete stores that are not in the new schema\n storesToDelete.forEach((storeName) => {\n if (!database.objectStoreNames.contains(storeName)) return\n database.deleteObjectStore(storeName)\n })\n\n // Create or update stores as per the new schema\n for (const [storeName, indexes] of Object.entries(options.schema)) {\n const store = database.objectStoreNames.contains(storeName)\n ? tx.objectStore(storeName)\n : database.createObjectStore(storeName, {\n keyPath: 'id',\n })\n\n const indexesToDrop = new Set<string>()\n for (let i = 0; i < store.indexNames.length; i += 1) {\n const indexName = store.indexNames.item(i)\n if (!indexName || indexes.includes(indexName)) continue\n indexesToDrop.add(indexName)\n }\n\n // Drop indexes that are not in the new schema\n indexesToDrop.forEach((indexName) => {\n if (!store.indexNames.contains(indexName)) return\n store.deleteIndex(indexName)\n })\n\n // Create indexes as per the new schema\n indexes.forEach((index) => {\n if (index === 'id') return\n if (store.indexNames.contains(index)) return\n store.createIndex(index, index, { unique: false })\n })\n }\n },\n )\n\n return function indexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n >(storeName: string) {\n return createIndexedDBAdapter<T, I>(storeName, databasePromise)\n }\n}\n\n/**\n * Creates a storage adapter for managing a SignalDB collection using IndexedDB.\n * This adapter reads and writes data to an IndexedDB object store, with customizable serialization and deserialization.\n * @template T - The type of the items in the collection.\n * @template I - The type of the unique identifier for the items.\n * @param storeName - A unique name for the collection, used as the database name.\n * @param databasePromise - A promise that resolves to an opened IndexedDB database.\n * @returns A SignalDB storage adapter for managing data in IndexedDB.\n */\nfunction createIndexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n>(storeName: string, databasePromise: Promise<IDBDatabase>) {\n const getStore = async (writeAccess = false) => {\n const database = await databasePromise\n if (!database) throw new Error('Database not initialized')\n const transaction = database.transaction(storeName, writeAccess ? 'readwrite' : 'readonly')\n const store = transaction.objectStore(storeName)\n return store\n }\n\n const readIndex = async (field: string) => {\n const store = await getStore()\n if (!store.indexNames.contains(field)) {\n throw new Error(`Index on field \"${field}\" does not exist`)\n }\n return new Promise<Map<any, Set<I>>>((resolve, reject) => {\n const index = store.index(field)\n const result = new Map<any, Set<I>>()\n const request = index.openCursor()\n request.addEventListener('success', () => {\n const cursor = request.result\n if (cursor) {\n const key = cursor.key as T[keyof T & string]\n const id = (cursor.value as T).id\n if (!result.has(key)) {\n result.set(key, new Set())\n }\n result.get(key)?.add(id)\n cursor.continue()\n } else {\n resolve(result)\n }\n })\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error reading index')))\n })\n }\n\n const getById = async (id: I) => {\n const store = await getStore(true)\n return new Promise<T | null>((resolve, reject) => {\n const request = store.get(id)\n request.addEventListener('success', () => resolve(request.result as T || null))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching item')))\n })\n }\n\n const insertOrReplace = async (items: T[]) => {\n const store = await getStore(true)\n await Promise.all(items.map(item => new Promise<void>((resolve, reject) => {\n const request = store.put(item)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error inserting or replacing item')))\n })))\n }\n\n return createStorageAdapter<T, I>({\n // lifecycle methods\n setup: async () => {\n const database = await databasePromise\n if (database.objectStoreNames.contains(storeName)) return\n throw new Error(`Object store \"${storeName}\" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)\n },\n teardown: async () => {\n const database = await databasePromise\n database.close()\n },\n\n // data retrieval methods\n readAll: async () => {\n const store = await getStore()\n return new Promise<T[]>((resolve, reject) => {\n const request = store.getAll()\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n },\n readIds: async (ids) => {\n const results = await Promise.all(ids.map(id => getById(id)))\n return results.filter(item => item !== null)\n },\n\n // index methods\n createIndex: async () => {\n /* noop */\n },\n dropIndex: async () => {\n /* noop */\n },\n readIndex,\n\n // data manipulation methods\n insert: items => insertOrReplace(items),\n replace: items => insertOrReplace(items),\n remove: async (itemsToRemove) => {\n const store = await getStore(true)\n await Promise.all(itemsToRemove.map(async item => new Promise<void>((resolve, reject) => {\n const request = store.delete(item.id)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error removing item')))\n })))\n },\n removeAll: async () => {\n const store = await getStore(true)\n return new Promise<void>((resolve, reject) => {\n const request = store.clear()\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error clearing items')))\n })\n },\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["openDatabase","request","databaseName","version","upgradePromise","resolve","reject","database","tx","onUpgrade","event","error","databasePromise","prepareIndexedDB","options","oldVersion","newVersion","storesToDelete","i","storeName","indexes","store","indexesToDrop","indexName","index","createIndexedDBAdapter","getStore","isWritable","readIndex","field","result","cursor","key","serializeValue","id","getById","insertOrReplace","items","item","isUsableKey","value","readRange","source","range","createStorageAdapter","entries","selector","keyPath","usable","narrowed","other","ids","itemsToRemove"],"sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, serializeValue } from '@signaldb/core'\n\n/**\n * Opens the IndexedDB database and creates the object store if it doesn't exist.\n * @param databaseName - The name of the database.\n * @param version - The version of the database.\n * @param onUpgrade - Optional callback for handling database upgrades.\n * @returns A promise that resolves with the opened database.\n */\nasync function openDatabase(\n databaseName: string,\n version: number,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n): Promise<IDBDatabase> {\n const request = indexedDB.open(databaseName, version)\n const upgradePromise = new Promise<void>((resolve, reject) => {\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n request.addEventListener('upgradeneeded', (event) => {\n const database = request.result\n const tx = request.transaction as IDBTransaction\n if (onUpgrade) {\n onUpgrade(\n database,\n tx,\n event.oldVersion,\n event.newVersion ?? null,\n )\n // eslint-disable-next-line unicorn/prefer-await -- runs in the synchronous upgradeneeded listener\n .then(() => resolve())\n // eslint-disable-next-line unicorn/prefer-await -- runs in the synchronous upgradeneeded listener\n .catch(\n /* istanbul ignore next -- @preserve */\n (error) => {\n reject(error as Error)\n },\n )\n return\n }\n\n // No custom upgrade logic provided, resolve immediately\n /* istanbul ignore next -- @preserve */\n resolve()\n })\n })\n const databasePromise = new Promise<IDBDatabase>((resolve, reject) => {\n request.addEventListener('success', () => resolve(request.result))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n })\n await Promise.all([\n databasePromise,\n upgradePromise,\n ])\n return databasePromise\n}\n\nexport type IndexedDBOptions = {\n databaseName?: string,\n version: number,\n schema: Record<string, string[]>,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n}\n\n/**\n * Prepares an IndexedDB storage adapter for SignalDB with the specified options.\n * @param options - Configuration options for the IndexedDB adapter.\n * @param options.databaseName - The name of the IndexedDB database. Defaults to 'signaldb'.\n * @param options.version - The version of the database schema.\n * @param options.schema - An object defining the schema of the database, where keys are store names and values are arrays of index names.\n * @param options.onUpgrade - Optional callback for handling database upgrades.\n * @returns A function that takes a store name and returns a SignalDB storage adapter for that store.\n */\nexport default function prepareIndexedDB(options: IndexedDBOptions) {\n const databaseName = options.databaseName || 'signaldb'\n const databasePromise = openDatabase(\n databaseName,\n options.version,\n async (database, tx, oldVersion, newVersion) => {\n if (options.onUpgrade) {\n await options.onUpgrade(database, tx, oldVersion, newVersion)\n }\n\n const storesToDelete = new Set<string>()\n for (let i = 0; i < database.objectStoreNames.length; i += 1) {\n const storeName = database.objectStoreNames.item(i)\n // eslint-disable-next-line unicorn/no-computed-property-existence-check -- `in` also matches inherited keys\n if (!storeName || storeName in options.schema) continue\n storesToDelete.add(storeName)\n }\n\n // Delete stores that are not in the new schema\n storesToDelete.forEach((storeName) => {\n if (!database.objectStoreNames.contains(storeName)) return\n database.deleteObjectStore(storeName)\n })\n\n // Create or update stores as per the new schema\n for (const [storeName, indexes] of Object.entries(options.schema)) {\n const store = database.objectStoreNames.contains(storeName)\n ? tx.objectStore(storeName)\n : database.createObjectStore(storeName, {\n keyPath: 'id',\n })\n\n const indexesToDrop = new Set<string>()\n for (let i = 0; i < store.indexNames.length; i += 1) {\n const indexName = store.indexNames.item(i)\n if (!indexName || indexes.includes(indexName)) continue\n indexesToDrop.add(indexName)\n }\n\n // Drop indexes that are not in the new schema\n indexesToDrop.forEach((indexName) => {\n if (!store.indexNames.contains(indexName)) return\n store.deleteIndex(indexName)\n })\n\n // Create indexes as per the new schema\n for (const index of indexes) {\n if ((index === 'id') || store.indexNames.contains(index)) continue\n store.createIndex(index, index, { unique: false })\n }\n }\n },\n )\n\n return function indexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n >(storeName: string) {\n return createIndexedDBAdapter<T, I>(storeName, databasePromise)\n }\n}\n\n/**\n * Creates a storage adapter for managing a SignalDB collection using IndexedDB.\n * This adapter reads and writes data to an IndexedDB object store, with customizable serialization and deserialization.\n * @template T - The type of the items in the collection.\n * @template I - The type of the unique identifier for the items.\n * @param storeName - A unique name for the collection, used as the database name.\n * @param databasePromise - A promise that resolves to an opened IndexedDB database.\n * @returns A SignalDB storage adapter for managing data in IndexedDB.\n */\nfunction createIndexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n>(storeName: string, databasePromise: Promise<IDBDatabase>) {\n const getStore = async (isWritable = false) => {\n const database = await databasePromise\n if (!database) throw new Error('Database not initialized')\n const transaction = database.transaction(storeName, isWritable ? 'readwrite' : 'readonly')\n const store = transaction.objectStore(storeName)\n return store\n }\n\n const readIndex = async (field: string) => {\n const store = await getStore()\n if (!store.indexNames.contains(field)) {\n throw new Error(`Index on field \"${field}\" does not exist`)\n }\n return new Promise<Map<any, Set<I>>>((resolve, reject) => {\n const index = store.index(field)\n const result = new Map<any, Set<I>>()\n const request = index.openCursor()\n request.addEventListener('success', () => {\n const cursor = request.result\n if (cursor) {\n // Serialized, not raw: SignalDB looks an index up by\n // `serializeValue(value)`, so an IndexedDB key of `3` or `true` would\n // never be found by a query for it.\n const key = serializeValue(cursor.key)\n const id = (cursor.value as T).id\n if (!result.has(key)) {\n result.set(key, new Set())\n }\n result.get(key)?.add(id)\n cursor.continue()\n } else {\n resolve(result)\n }\n })\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error reading index')))\n })\n }\n\n const getById = async (id: I) => {\n const store = await getStore(true)\n return new Promise<T | null>((resolve, reject) => {\n const request = store.get(id)\n request.addEventListener('success', () => resolve(request.result as T || null))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching item')))\n })\n }\n\n const insertOrReplace = async (items: T[]) => {\n const store = await getStore(true)\n await Promise.all(items.map(item => new Promise<void>((resolve, reject) => {\n const request = store.put(item)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error inserting or replacing item')))\n })))\n }\n\n /**\n * Whether a value can be an IndexedDB key that compares as `match` would.\n *\n * IndexedDB keys are numbers, strings, dates, binary and arrays of those.\n * `null`, `undefined` and booleans are not keys at all, and `NaN` is not a\n * valid one — asking for any of them throws rather than answering nothing.\n * Everything outside this set is left to the caller.\n * @param value - The value from the selector.\n * @returns `true` when the value may be used as a key.\n */\n const isUsableKey = (value: unknown): value is IDBValidKey => {\n if (typeof value === 'string') return true\n return typeof value === 'number' ? Number.isFinite(value) : value instanceof Date && !Number.isNaN(value.getTime())\n }\n\n /**\n * Reads everything in a key range from a store or one of its indexes.\n * @param source - The store or index to read from.\n * @param range - The key range to read.\n * @returns The matching items.\n */\n const readRange = (source: IDBObjectStore | IDBIndex, range: IDBKeyRange) => (\n new Promise<T[]>((resolve, reject) => {\n const request = source.getAll(range)\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n )\n\n return createStorageAdapter<T, I>({\n // lifecycle methods\n setup: async () => {\n const database = await databasePromise\n if (database.objectStoreNames.contains(storeName)) return\n throw new Error(`Object store \"${storeName}\" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)\n },\n teardown: async () => {\n const database = await databasePromise\n database.close()\n },\n\n // data retrieval methods\n readAll: async () => {\n const store = await getStore()\n return new Promise<T[]>((resolve, reject) => {\n const request = store.getAll()\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n },\n /**\n * Narrows a read to one equality the store can answer with a key range.\n *\n * IndexedDB is the one shipped adapter that can read less than everything:\n * an object store has a key path and named indexes, and both answer a key\n * range directly. So a selector holding an equality on either becomes a\n * range read instead of `getAll()` over the whole store, which is what\n * this capability exists for. The blob-backed adapters — localstorage, fs,\n * generic-fs, opfs — deliberately do not implement it: they read one\n * serialized array and cannot answer less than all of it, so a `query`\n * there would be the fallback path behind a new name.\n *\n * It claims nothing beyond the narrowing, deliberately. It never reports\n * `sorted`: an index read comes back in index-key order and `readAll` in\n * primary-key order, and neither is what `sortItems` produces. So it never\n * reports `windowed` either, because a window is only meaningful over an\n * order — and never `projected`, since a stored record is read whole.\n * @param query - The query to answer.\n * @param query.selector - The selector to narrow on.\n * @returns The narrowed items and whatever is left of the selector.\n */\n query: async ({ selector }) => {\n const entries = Object.entries(selector ?? {})\n const store = await getStore()\n const keyPath = typeof store.keyPath === 'string' ? store.keyPath : null\n // Narrowed in a loop rather than with `find`: a predicate's type guard\n // does not narrow the tuple it was called on, and the cast that would\n // paper over that is the kind this capability must not carry.\n let usable: { field: string, key: IDBValidKey } | null = null\n for (const [field, value] of entries) {\n if (!isUsableKey(value)) continue\n if (field !== keyPath && !store.indexNames.contains(field)) continue\n usable = { field, key: value }\n break\n }\n\n if (!usable) {\n const items = await new Promise<T[]>((resolve, reject) => {\n const request = store.getAll()\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n return { items, residualSelector: selector }\n }\n\n const narrowed = usable\n const source = narrowed.field === keyPath ? store : store.index(narrowed.field)\n const items = await readRange(source, IDBKeyRange.only(narrowed.key))\n const residual = Object.fromEntries(entries.filter(([other]) => other !== narrowed.field))\n return { items, residualSelector: residual as typeof selector }\n },\n\n readIds: async (ids) => {\n const results = await Promise.all(ids.map(id => getById(id)))\n return results.filter(item => item !== null)\n },\n\n // index methods\n createIndex: async () => {\n /*\n noop\n */\n },\n dropIndex: async () => {\n /*\n noop\n */\n },\n readIndex,\n\n // data manipulation methods\n insert: items => insertOrReplace(items),\n replace: items => insertOrReplace(items),\n remove: async (itemsToRemove) => {\n const store = await getStore(true)\n await Promise.all(itemsToRemove.map(async item => new Promise<void>((resolve, reject) => {\n const request = store.delete(item.id)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error removing item')))\n })))\n },\n removeAll: async () => {\n const store = await getStore(true)\n return new Promise<void>((resolve, reject) => {\n const request = store.clear()\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error clearing items')))\n })\n },\n })\n}\n"],"mappings":";;AASA,eAAeA,EACb,GACA,GACA,GAMsB;CACtB,IAAMC,IAAU,UAAU,KAAKC,GAAcC,CAAO,GAC9CC,IAAiB,IAAI,SAAe,GAAS,MAAW;EAG5D,AAFAH,EAAQ,iBAAiB,iBAAiBI,EAAQ,CAAC,GACnDJ,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,gBAAgB,CAAC,CAAC,GACrGA,EAAQ,iBAAiB,kBAAkB,MAAU;GACnD,IAAMM,IAAWN,EAAQ,QACnBO,IAAKP,EAAQ;GACnB,AAAIQ,IACFA,EACEF,GACAC,GACAE,EAAM,YACNA,EAAM,cAAc,IACtB,CAAC,CAEE,WAAWL,EAAQ,CAAC,CAAC,CAErB;;KAEE,MAAU;KACT,EAAOM,CAAc;IACvB;GACF;;GAMJN,EAAQ;EACV,CAAC;CACH,CAAC,GACKO,IAAkB,IAAI,SAAsB,GAAS,MAAW;EAEpE,AADAX,EAAQ,iBAAiB,iBAAiBI,EAAQJ,EAAQ,MAAM,CAAC,GACjEA,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,gBAAgB,CAAC,CAAC;CACvG,CAAC;CAKD,OAJA,MAAM,QAAQ,IAAI,CAChBW,GACAR,CACF,CAAC,GACMQ;AACT;AAuBA,SAAwBC,EAAiB,GAA2B;CAElE,IAAMD,IAAkBZ,EADHc,EAAQ,gBAAgB,YAG3CA,EAAQ,SACR,OAAO,GAAU,GAAI,GAAY,MAAe;EAC9C,AAAIA,EAAQ,aACV,MAAMA,EAAQ,UAAUP,GAAUC,GAAIO,GAAYC,CAAU;EAG9D,IAAMC,oBAAiB,IAAI,IAAY;EACvC,KAAK,IAAIC,IAAI,GAAGA,IAAIX,EAAS,iBAAiB,QAAQ,KAAK,GAAG;GAC5D,IAAMY,IAAYZ,EAAS,iBAAiB,KAAKW,CAAC;GAElD,AAAI,CAACC,KAAaA,KAAaL,EAAQ,UACvCG,EAAe,IAAIE,CAAS;EAC9B;EAGA,EAAe,SAAS,MAAc;GACpC,AAAKZ,EAAS,iBAAiB,SAASY,CAAS,KACjDZ,EAAS,kBAAkBY,CAAS;EACtC,CAAC;EAGD,KAAK,IAAM,CAACA,GAAWC,MAAY,OAAO,QAAQN,EAAQ,MAAM,GAAG;GACjE,IAAMO,IAAQd,EAAS,iBAAiB,SAASY,CAAS,IACtDX,EAAG,YAAYW,CAAS,IACxBZ,EAAS,kBAAkBY,GAAW,EACtC,SAAS,KACX,CAAC,GAEGG,oBAAgB,IAAI,IAAY;GACtC,KAAK,IAAIJ,IAAI,GAAGA,IAAIG,EAAM,WAAW,QAAQ,KAAK,GAAG;IACnD,IAAME,IAAYF,EAAM,WAAW,KAAKH,CAAC;IACzC,AAAKK,KAAa,GAAQ,SAASA,CAAS,KAC5CD,EAAc,IAAIC,CAAS;GAC7B;GAGA,EAAc,SAAS,MAAc;IACnC,AAAKF,EAAM,WAAW,SAASE,CAAS,KACxCF,EAAM,YAAYE,CAAS;GAC7B,CAAC;GAGD,KAAK,IAAMC,KAASJ,GAClB,AAAKI,MAAU,QAASH,EAAM,WAAW,SAASG,CAAK,KACvDH,EAAM,YAAYG,GAAOA,GAAO,EAAE,QAAQ,GAAM,CAAC;EAErD;CACF,CACF;CAEA,OAAO,SAGL,GAAmB;EACnB,OAAOC,EAA6BN,GAAWP,CAAe;CAChE;AACF;AAWA,SAASa,EAGP,GAAmB,GAAuC;CAC1D,IAAMC,IAAW,OAAO,IAAa,OAAU;EAC7C,IAAMnB,IAAW,MAAMK;EACvB,IAAI,CAACL,GAAU,MAAU,MAAM,0BAA0B;EAGzD,OAFoBA,EAAS,YAAYY,GAAWQ,IAAa,cAAc,UACjE,CAAA,CAAY,YAAYR,CAC/B;CACT,GAEMS,IAAY,OAAO,MAAkB;EACzC,IAAMP,IAAQ,MAAMK,EAAS;EAC7B,IAAI,CAACL,EAAM,WAAW,SAASQ,CAAK,GAClC,MAAU,MAAM,mBAAmBA,EAAM,iBAAiB;EAE5D,OAAO,IAAI,SAA2B,GAAS,MAAW;GACxD,IAAML,IAAQH,EAAM,MAAMQ,CAAK,GACzBC,oBAAS,IAAI,IAAiB,GAC9B7B,IAAUuB,EAAM,WAAW;GAkBjC,AAjBAvB,EAAQ,iBAAiB,iBAAiB;IACxC,IAAM8B,IAAS9B,EAAQ;IACvB,IAAI8B,GAAQ;KAIV,IAAMC,IAAMC,EAAeF,EAAO,GAAG,GAC/BG,IAAMH,EAAO,MAAY;KAK/B,AAJKD,EAAO,IAAIE,CAAG,KACjBF,EAAO,IAAIE,mBAAK,IAAI,IAAI,CAAC,GAE3BF,EAAO,IAAIE,CAAG,CAAC,EAAE,IAAIE,CAAE,GACvBH,EAAO,SAAS;IAClB,OACE,EAAQD,CAAM;GAElB,CAAC,GACD7B,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,qBAAqB,CAAC,CAAC;EAC5G,CAAC;CACH,GAEMkC,IAAU,OAAO,MAAU;EAC/B,IAAMd,IAAQ,MAAMK,EAAS,EAAI;EACjC,OAAO,IAAI,SAAmB,GAAS,MAAW;GAChD,IAAMzB,IAAUoB,EAAM,IAAIa,CAAE;GAE5B,AADAjC,EAAQ,iBAAiB,iBAAiBI,EAAQJ,EAAQ,UAAe,IAAI,CAAC,GAC9EA,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,qBAAqB,CAAC,CAAC;EAC5G,CAAC;CACH,GAEMmC,IAAkB,OAAO,MAAe;EAC5C,IAAMf,IAAQ,MAAMK,EAAS,EAAI;EACjC,MAAM,QAAQ,IAAIW,EAAM,KAAI,MAAQ,IAAI,SAAe,GAAS,MAAW;GACzE,IAAMpC,IAAUoB,EAAM,IAAIiB,CAAI;GAE9B,AADArC,EAAQ,iBAAiB,iBAAiBI,EAAQ,CAAC,GACnDJ,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,mCAAmC,CAAC,CAAC;EAC1H,CAAC,CAAC,CAAC;CACL,GAYMsC,KAAe,MACf,OAAOC,KAAU,WAAiB,KAC/B,OAAOA,KAAU,WAAW,OAAO,SAASA,CAAK,IAAIA,aAAiB,QAAQ,CAAC,OAAO,MAAMA,EAAM,QAAQ,CAAC,GAS9GC,KAAa,GAAmC,MACpD,IAAI,SAAc,GAAS,MAAW;EACpC,IAAMxC,IAAUyC,EAAO,OAAOC,CAAK;EAEnC,AADA1C,EAAQ,iBAAiB,iBAAiBI,EAAQJ,EAAQ,MAAa,CAAC,GACxEA,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,sBAAsB,CAAC,CAAC;CAC7G,CAAC;CAGH,OAAO2C,EAA2B;EAEhC,OAAO,YAAY;GAEjB,IAAA,EAAI,MADmBhC,EAAA,CACV,iBAAiB,SAASO,CAAS,GAChD,MAAU,MAAM,iBAAiBA,EAAU,kGAAkG;EAC/I;EACA,UAAU,YAAY;GAEpB,CAAA,MADuBP,EAAA,CACd,MAAM;EACjB;EAGA,SAAS,YAAY;GACnB,IAAMS,IAAQ,MAAMK,EAAS;GAC7B,OAAO,IAAI,SAAc,GAAS,MAAW;IAC3C,IAAMzB,IAAUoB,EAAM,OAAO;IAE7B,AADApB,EAAQ,iBAAiB,iBAAiBI,EAAQJ,EAAQ,MAAa,CAAC,GACxEA,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,sBAAsB,CAAC,CAAC;GAC7G,CAAC;EACH;EAsBA,OAAO,OAAO,EAAE,kBAAe;GAC7B,IAAM4C,IAAU,OAAO,QAAQC,KAAY,CAAC,CAAC,GACvCzB,IAAQ,MAAMK,EAAS,GACvBqB,IAAU,OAAO1B,EAAM,WAAY,WAAWA,EAAM,UAAU,MAIhE2B,IAAqD;GACzD,KAAK,IAAM,CAACnB,GAAOW,MAAUK,GAC3B,IAAKN,EAAYC,CAAK,MAClBX,MAAUkB,KAAY1B,EAAM,WAAW,SAASQ,CAAK,IACzD;QAAS;KAAE;KAAO,KAAKW;IAAM;IAC7B;GAD6B;GAI/B,IAAI,CAACQ,GAMH,OAAO;IAAE,OAAA,MALW,IAAI,SAAc,GAAS,MAAW;KACxD,IAAM/C,IAAUoB,EAAM,OAAO;KAE7B,AADApB,EAAQ,iBAAiB,iBAAiBI,EAAQJ,EAAQ,MAAa,CAAC,GACxEA,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,sBAAsB,CAAC,CAAC;IAC7G,CAAC;IACe,kBAAkB6C;GAAS;GAG7C,IAAMG,IAAWD,GACXN,IAASO,EAAS,UAAUF,IAAU1B,IAAQA,EAAM,MAAM4B,EAAS,KAAK;GAG9E,OAAO;IAAE,OAAA,MAFWR,EAAUC,GAAQ,YAAY,KAAKO,EAAS,GAAG,CAAC;IAEpD,kBADC,OAAO,YAAYJ,EAAQ,QAAQ,CAACK,OAAWA,MAAUD,EAAS,KAAK,CACtD;GAA4B;EAChE;EAEA,SAAS,OAAO,OAEP,MADe,QAAQ,IAAIE,EAAI,KAAI,MAAMhB,EAAQD,CAAE,CAAC,CAAC,EAAA,CAC7C,QAAO,MAAQI,MAAS,IAAI;EAI7C,aAAa,YAAY,CAIzB;EACA,WAAW,YAAY,CAIvB;EACA;EAGA,SAAQ,MAASF,EAAgBC,CAAK;EACtC,UAAS,MAASD,EAAgBC,CAAK;EACvC,QAAQ,OAAO,MAAkB;GAC/B,IAAMhB,IAAQ,MAAMK,EAAS,EAAI;GACjC,MAAM,QAAQ,IAAI0B,EAAc,IAAI,OAAM,MAAQ,IAAI,SAAe,GAAS,MAAW;IACvF,IAAMnD,IAAUoB,EAAM,OAAOiB,EAAK,EAAE;IAEpC,AADArC,EAAQ,iBAAiB,iBAAiBI,EAAQ,CAAC,GACnDJ,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,qBAAqB,CAAC,CAAC;GAC5G,CAAC,CAAC,CAAC;EACL;EACA,WAAW,YAAY;GACrB,IAAMoB,IAAQ,MAAMK,EAAS,EAAI;GACjC,OAAO,IAAI,SAAe,GAAS,MAAW;IAC5C,IAAMzB,IAAUoB,EAAM,MAAM;IAE5B,AADApB,EAAQ,iBAAiB,iBAAiBI,EAAQ,CAAC,GACnDJ,EAAQ,iBAAiB,eAAeK,EAAW,MAAML,EAAQ,OAAO,WAAW,sBAAsB,CAAC,CAAC;GAC7G,CAAC;EACH;CACF,CAAC;AACH"}
package/dist/index.umd.js CHANGED
@@ -1,2 +1,2 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t(require("@signaldb/core")):typeof define==`function`&&define.amd?define([`@signaldb/core`],t):(e=typeof globalThis<`u`?globalThis:e||self,e.SignalDB=t(e._signaldb_core))})(this,function(e){async function t(e,t,n){let r=indexedDB.open(e,t),i=new Promise((e,t)=>{r.addEventListener(`success`,()=>e()),r.addEventListener(`error`,()=>t(Error(r.error?.message||`Database error`))),r.addEventListener(`upgradeneeded`,i=>{let a=r.result,o=r.transaction;if(n){n(a,o,i.oldVersion,i.newVersion??null).then(()=>e()).catch(e=>{t(e)});return}e()})}),a=new Promise((e,t)=>{r.addEventListener(`success`,()=>e(r.result)),r.addEventListener(`error`,()=>t(Error(r.error?.message||`Database error`)))});return await Promise.all([a,i]),a}function n(e){let n=t(e.databaseName||`signaldb`,e.version,async(t,n)=>{e.onUpgrade&&await e.onUpgrade(t,n,t.version,e.version);let r=new Set;for(let n=0;n<t.objectStoreNames.length;n+=1){let i=t.objectStoreNames.item(n);!i||i in e.schema||r.add(i)}r.forEach(e=>{t.objectStoreNames.contains(e)&&t.deleteObjectStore(e)});for(let[r,i]of Object.entries(e.schema)){let e=t.objectStoreNames.contains(r)?n.objectStore(r):t.createObjectStore(r,{keyPath:`id`}),a=new Set;for(let t=0;t<e.indexNames.length;t+=1){let n=e.indexNames.item(t);!n||i.includes(n)||a.add(n)}a.forEach(t=>{e.indexNames.contains(t)&&e.deleteIndex(t)}),i.forEach(t=>{t!==`id`&&(e.indexNames.contains(t)||e.createIndex(t,t,{unique:!1}))})}});return function(e){return r(e,n)}}function r(t,n){let r=async(e=!1)=>{let r=await n;if(!r)throw Error(`Database not initialized`);return r.transaction(t,e?`readwrite`:`readonly`).objectStore(t)},i=async e=>{let t=await r();if(!t.indexNames.contains(e))throw Error(`Index on field "${e}" does not exist`);return new Promise((n,r)=>{let i=t.index(e),a=new Map,o=i.openCursor();o.addEventListener(`success`,()=>{let e=o.result;if(e){let t=e.key,n=e.value.id;a.has(t)||a.set(t,new Set),a.get(t)?.add(n),e.continue()}else n(a)}),o.addEventListener(`error`,()=>r(Error(o.error?.message||`Error reading index`)))})},a=async e=>{let t=await r(!0);return new Promise((n,r)=>{let i=t.get(e);i.addEventListener(`success`,()=>n(i.result||null)),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error fetching item`)))})},o=async e=>{let t=await r(!0);await Promise.all(e.map(e=>new Promise((n,r)=>{let i=t.put(e);i.addEventListener(`success`,()=>n()),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error inserting or replacing item`)))})))};return(0,e.createStorageAdapter)({setup:async()=>{if(!(await n).objectStoreNames.contains(t))throw Error(`Object store "${t}" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)},teardown:async()=>{(await n).close()},readAll:async()=>{let e=await r();return new Promise((t,n)=>{let r=e.getAll();r.addEventListener(`success`,()=>t(r.result)),r.addEventListener(`error`,()=>n(Error(r.error?.message||`Error fetching items`)))})},readIds:async e=>(await Promise.all(e.map(e=>a(e)))).filter(e=>e!==null),createIndex:async()=>{},dropIndex:async()=>{},readIndex:i,insert:e=>o(e),replace:e=>o(e),remove:async e=>{let t=await r(!0);await Promise.all(e.map(async e=>new Promise((n,r)=>{let i=t.delete(e.id);i.addEventListener(`success`,()=>n()),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error removing item`)))})))},removeAll:async()=>{let e=await r(!0);return new Promise((t,n)=>{let r=e.clear();r.addEventListener(`success`,()=>t()),r.addEventListener(`error`,()=>n(Error(r.error?.message||`Error clearing items`)))})}})}return n});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t(require("@signaldb/core")):typeof define==`function`&&define.amd?define([`@signaldb/core`],t):(e=typeof globalThis<`u`?globalThis:e||self,e.SignalDB=t(e._signaldb_core))})(this,function(e){async function t(e,t,n){let r=indexedDB.open(e,t),i=new Promise((e,t)=>{r.addEventListener(`success`,()=>e()),r.addEventListener(`error`,()=>t(Error(r.error?.message||`Database error`))),r.addEventListener(`upgradeneeded`,i=>{let a=r.result,o=r.transaction;n?n(a,o,i.oldVersion,i.newVersion??null).then(()=>e()).catch(e=>{t(e)}):e()})}),a=new Promise((e,t)=>{r.addEventListener(`success`,()=>e(r.result)),r.addEventListener(`error`,()=>t(Error(r.error?.message||`Database error`)))});return await Promise.all([a,i]),a}function n(e){let n=t(e.databaseName||`signaldb`,e.version,async(t,n,r,i)=>{e.onUpgrade&&await e.onUpgrade(t,n,r,i);let a=new Set;for(let n=0;n<t.objectStoreNames.length;n+=1){let r=t.objectStoreNames.item(n);!r||r in e.schema||a.add(r)}a.forEach(e=>{t.objectStoreNames.contains(e)&&t.deleteObjectStore(e)});for(let[r,i]of Object.entries(e.schema)){let e=t.objectStoreNames.contains(r)?n.objectStore(r):t.createObjectStore(r,{keyPath:`id`}),a=new Set;for(let t=0;t<e.indexNames.length;t+=1){let n=e.indexNames.item(t);n&&!i.includes(n)&&a.add(n)}a.forEach(t=>{e.indexNames.contains(t)&&e.deleteIndex(t)});for(let t of i)t===`id`||e.indexNames.contains(t)||e.createIndex(t,t,{unique:!1})}});return function(e){return r(e,n)}}function r(t,n){let r=async(e=!1)=>{let r=await n;if(!r)throw Error(`Database not initialized`);return r.transaction(t,e?`readwrite`:`readonly`).objectStore(t)},i=async t=>{let n=await r();if(!n.indexNames.contains(t))throw Error(`Index on field "${t}" does not exist`);return new Promise((r,i)=>{let a=n.index(t),o=new Map,s=a.openCursor();s.addEventListener(`success`,()=>{let t=s.result;if(t){let n=(0,e.serializeValue)(t.key),r=t.value.id;o.has(n)||o.set(n,new Set),o.get(n)?.add(r),t.continue()}else r(o)}),s.addEventListener(`error`,()=>i(Error(s.error?.message||`Error reading index`)))})},a=async e=>{let t=await r(!0);return new Promise((n,r)=>{let i=t.get(e);i.addEventListener(`success`,()=>n(i.result||null)),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error fetching item`)))})},o=async e=>{let t=await r(!0);await Promise.all(e.map(e=>new Promise((n,r)=>{let i=t.put(e);i.addEventListener(`success`,()=>n()),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error inserting or replacing item`)))})))},s=e=>typeof e==`string`?!0:typeof e==`number`?Number.isFinite(e):e instanceof Date&&!Number.isNaN(e.getTime()),c=(e,t)=>new Promise((n,r)=>{let i=e.getAll(t);i.addEventListener(`success`,()=>n(i.result)),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error fetching items`)))});return(0,e.createStorageAdapter)({setup:async()=>{if(!(await n).objectStoreNames.contains(t))throw Error(`Object store "${t}" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)},teardown:async()=>{(await n).close()},readAll:async()=>{let e=await r();return new Promise((t,n)=>{let r=e.getAll();r.addEventListener(`success`,()=>t(r.result)),r.addEventListener(`error`,()=>n(Error(r.error?.message||`Error fetching items`)))})},query:async({selector:e})=>{let t=Object.entries(e??{}),n=await r(),i=typeof n.keyPath==`string`?n.keyPath:null,a=null;for(let[e,r]of t)if(s(r)&&(e===i||n.indexNames.contains(e))){a={field:e,key:r};break}if(!a)return{items:await new Promise((e,t)=>{let r=n.getAll();r.addEventListener(`success`,()=>e(r.result)),r.addEventListener(`error`,()=>t(Error(r.error?.message||`Error fetching items`)))}),residualSelector:e};let o=a,l=o.field===i?n:n.index(o.field);return{items:await c(l,IDBKeyRange.only(o.key)),residualSelector:Object.fromEntries(t.filter(([e])=>e!==o.field))}},readIds:async e=>(await Promise.all(e.map(e=>a(e)))).filter(e=>e!==null),createIndex:async()=>{},dropIndex:async()=>{},readIndex:i,insert:e=>o(e),replace:e=>o(e),remove:async e=>{let t=await r(!0);await Promise.all(e.map(async e=>new Promise((n,r)=>{let i=t.delete(e.id);i.addEventListener(`success`,()=>n()),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error removing item`)))})))},removeAll:async()=>{let e=await r(!0);return new Promise((t,n)=>{let r=e.clear();r.addEventListener(`success`,()=>t()),r.addEventListener(`error`,()=>n(Error(r.error?.message||`Error clearing items`)))})}})}return n});
2
2
  //# sourceMappingURL=index.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter } from '@signaldb/core'\n\n/**\n * Opens the IndexedDB database and creates the object store if it doesn't exist.\n * @param databaseName - The name of the database.\n * @param version - The version of the database.\n * @param onUpgrade - Optional callback for handling database upgrades.\n * @returns A promise that resolves with the opened database.\n */\nasync function openDatabase(\n databaseName: string,\n version: number,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n): Promise<IDBDatabase> {\n const request = indexedDB.open(databaseName, version)\n const upgradePromise = new Promise<void>((resolve, reject) => {\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n request.addEventListener('upgradeneeded', (event) => {\n const database = request.result\n const tx = request.transaction as IDBTransaction\n if (onUpgrade) {\n onUpgrade(\n database,\n tx,\n event.oldVersion,\n event.newVersion ?? null,\n )\n .then(() => resolve())\n .catch(\n /* istanbul ignore next -- @preserve */\n (error) => {\n reject(error as Error)\n },\n )\n return\n }\n\n // No custom upgrade logic provided, resolve immediately\n /* istanbul ignore next -- @preserve */\n resolve()\n })\n })\n const databasePromise = new Promise<IDBDatabase>((resolve, reject) => {\n request.addEventListener('success', () => resolve(request.result))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n })\n await Promise.all([\n databasePromise,\n upgradePromise,\n ])\n return databasePromise\n}\n\nexport type IndexedDBOptions = {\n databaseName?: string,\n version: number,\n schema: Record<string, string[]>,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n}\n\n/**\n * Prepares an IndexedDB storage adapter for SignalDB with the specified options.\n * @param options - Configuration options for the IndexedDB adapter.\n * @param options.databaseName - The name of the IndexedDB database. Defaults to 'signaldb'.\n * @param options.version - The version of the database schema.\n * @param options.schema - An object defining the schema of the database, where keys are store names and values are arrays of index names.\n * @param options.onUpgrade - Optional callback for handling database upgrades.\n * @returns A function that takes a store name and returns a SignalDB storage adapter for that store.\n */\nexport default function prepareIndexedDB(options: IndexedDBOptions) {\n const databaseName = options.databaseName || 'signaldb'\n const databasePromise = openDatabase(\n databaseName,\n options.version,\n async (database, tx) => {\n if (options.onUpgrade) {\n await options.onUpgrade(database, tx, database.version, options.version)\n }\n\n const storesToDelete = new Set<string>()\n for (let i = 0; i < database.objectStoreNames.length; i += 1) {\n const storeName = database.objectStoreNames.item(i)\n if (!storeName || storeName in options.schema) continue\n storesToDelete.add(storeName)\n }\n\n // Delete stores that are not in the new schema\n storesToDelete.forEach((storeName) => {\n if (!database.objectStoreNames.contains(storeName)) return\n database.deleteObjectStore(storeName)\n })\n\n // Create or update stores as per the new schema\n for (const [storeName, indexes] of Object.entries(options.schema)) {\n const store = database.objectStoreNames.contains(storeName)\n ? tx.objectStore(storeName)\n : database.createObjectStore(storeName, {\n keyPath: 'id',\n })\n\n const indexesToDrop = new Set<string>()\n for (let i = 0; i < store.indexNames.length; i += 1) {\n const indexName = store.indexNames.item(i)\n if (!indexName || indexes.includes(indexName)) continue\n indexesToDrop.add(indexName)\n }\n\n // Drop indexes that are not in the new schema\n indexesToDrop.forEach((indexName) => {\n if (!store.indexNames.contains(indexName)) return\n store.deleteIndex(indexName)\n })\n\n // Create indexes as per the new schema\n indexes.forEach((index) => {\n if (index === 'id') return\n if (store.indexNames.contains(index)) return\n store.createIndex(index, index, { unique: false })\n })\n }\n },\n )\n\n return function indexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n >(storeName: string) {\n return createIndexedDBAdapter<T, I>(storeName, databasePromise)\n }\n}\n\n/**\n * Creates a storage adapter for managing a SignalDB collection using IndexedDB.\n * This adapter reads and writes data to an IndexedDB object store, with customizable serialization and deserialization.\n * @template T - The type of the items in the collection.\n * @template I - The type of the unique identifier for the items.\n * @param storeName - A unique name for the collection, used as the database name.\n * @param databasePromise - A promise that resolves to an opened IndexedDB database.\n * @returns A SignalDB storage adapter for managing data in IndexedDB.\n */\nfunction createIndexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n>(storeName: string, databasePromise: Promise<IDBDatabase>) {\n const getStore = async (writeAccess = false) => {\n const database = await databasePromise\n if (!database) throw new Error('Database not initialized')\n const transaction = database.transaction(storeName, writeAccess ? 'readwrite' : 'readonly')\n const store = transaction.objectStore(storeName)\n return store\n }\n\n const readIndex = async (field: string) => {\n const store = await getStore()\n if (!store.indexNames.contains(field)) {\n throw new Error(`Index on field \"${field}\" does not exist`)\n }\n return new Promise<Map<any, Set<I>>>((resolve, reject) => {\n const index = store.index(field)\n const result = new Map<any, Set<I>>()\n const request = index.openCursor()\n request.addEventListener('success', () => {\n const cursor = request.result\n if (cursor) {\n const key = cursor.key as T[keyof T & string]\n const id = (cursor.value as T).id\n if (!result.has(key)) {\n result.set(key, new Set())\n }\n result.get(key)?.add(id)\n cursor.continue()\n } else {\n resolve(result)\n }\n })\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error reading index')))\n })\n }\n\n const getById = async (id: I) => {\n const store = await getStore(true)\n return new Promise<T | null>((resolve, reject) => {\n const request = store.get(id)\n request.addEventListener('success', () => resolve(request.result as T || null))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching item')))\n })\n }\n\n const insertOrReplace = async (items: T[]) => {\n const store = await getStore(true)\n await Promise.all(items.map(item => new Promise<void>((resolve, reject) => {\n const request = store.put(item)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error inserting or replacing item')))\n })))\n }\n\n return createStorageAdapter<T, I>({\n // lifecycle methods\n setup: async () => {\n const database = await databasePromise\n if (database.objectStoreNames.contains(storeName)) return\n throw new Error(`Object store \"${storeName}\" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)\n },\n teardown: async () => {\n const database = await databasePromise\n database.close()\n },\n\n // data retrieval methods\n readAll: async () => {\n const store = await getStore()\n return new Promise<T[]>((resolve, reject) => {\n const request = store.getAll()\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n },\n readIds: async (ids) => {\n const results = await Promise.all(ids.map(id => getById(id)))\n return results.filter(item => item !== null)\n },\n\n // index methods\n createIndex: async () => {\n /* noop */\n },\n dropIndex: async () => {\n /* noop */\n },\n readIndex,\n\n // data manipulation methods\n insert: items => insertOrReplace(items),\n replace: items => insertOrReplace(items),\n remove: async (itemsToRemove) => {\n const store = await getStore(true)\n await Promise.all(itemsToRemove.map(async item => new Promise<void>((resolve, reject) => {\n const request = store.delete(item.id)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error removing item')))\n })))\n },\n removeAll: async () => {\n const store = await getStore(true)\n return new Promise<void>((resolve, reject) => {\n const request = store.clear()\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error clearing items')))\n })\n },\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","names":["serializeValue","createStorageAdapter","factory","global","openDatabase","request","databaseName","version","upgradePromise","resolve","reject","database","tx","onUpgrade","event","error","databasePromise","prepareIndexedDB","options","oldVersion","newVersion","storesToDelete","i","storeName","indexes","store","indexesToDrop","indexName","index","createIndexedDBAdapter","getStore","isWritable","readIndex","field","result","cursor","key","_signaldb_core","id","getById","insertOrReplace","items","item","isUsableKey","value","readRange","source","range","entries","selector","keyPath","usable","narrowed","other","ids","itemsToRemove"],"sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, serializeValue } from '@signaldb/core'\n\n/**\n * Opens the IndexedDB database and creates the object store if it doesn't exist.\n * @param databaseName - The name of the database.\n * @param version - The version of the database.\n * @param onUpgrade - Optional callback for handling database upgrades.\n * @returns A promise that resolves with the opened database.\n */\nasync function openDatabase(\n databaseName: string,\n version: number,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n): Promise<IDBDatabase> {\n const request = indexedDB.open(databaseName, version)\n const upgradePromise = new Promise<void>((resolve, reject) => {\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n request.addEventListener('upgradeneeded', (event) => {\n const database = request.result\n const tx = request.transaction as IDBTransaction\n if (onUpgrade) {\n onUpgrade(\n database,\n tx,\n event.oldVersion,\n event.newVersion ?? null,\n )\n // eslint-disable-next-line unicorn/prefer-await -- runs in the synchronous upgradeneeded listener\n .then(() => resolve())\n // eslint-disable-next-line unicorn/prefer-await -- runs in the synchronous upgradeneeded listener\n .catch(\n /* istanbul ignore next -- @preserve */\n (error) => {\n reject(error as Error)\n },\n )\n return\n }\n\n // No custom upgrade logic provided, resolve immediately\n /* istanbul ignore next -- @preserve */\n resolve()\n })\n })\n const databasePromise = new Promise<IDBDatabase>((resolve, reject) => {\n request.addEventListener('success', () => resolve(request.result))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n })\n await Promise.all([\n databasePromise,\n upgradePromise,\n ])\n return databasePromise\n}\n\nexport type IndexedDBOptions = {\n databaseName?: string,\n version: number,\n schema: Record<string, string[]>,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n}\n\n/**\n * Prepares an IndexedDB storage adapter for SignalDB with the specified options.\n * @param options - Configuration options for the IndexedDB adapter.\n * @param options.databaseName - The name of the IndexedDB database. Defaults to 'signaldb'.\n * @param options.version - The version of the database schema.\n * @param options.schema - An object defining the schema of the database, where keys are store names and values are arrays of index names.\n * @param options.onUpgrade - Optional callback for handling database upgrades.\n * @returns A function that takes a store name and returns a SignalDB storage adapter for that store.\n */\nexport default function prepareIndexedDB(options: IndexedDBOptions) {\n const databaseName = options.databaseName || 'signaldb'\n const databasePromise = openDatabase(\n databaseName,\n options.version,\n async (database, tx, oldVersion, newVersion) => {\n if (options.onUpgrade) {\n await options.onUpgrade(database, tx, oldVersion, newVersion)\n }\n\n const storesToDelete = new Set<string>()\n for (let i = 0; i < database.objectStoreNames.length; i += 1) {\n const storeName = database.objectStoreNames.item(i)\n // eslint-disable-next-line unicorn/no-computed-property-existence-check -- `in` also matches inherited keys\n if (!storeName || storeName in options.schema) continue\n storesToDelete.add(storeName)\n }\n\n // Delete stores that are not in the new schema\n storesToDelete.forEach((storeName) => {\n if (!database.objectStoreNames.contains(storeName)) return\n database.deleteObjectStore(storeName)\n })\n\n // Create or update stores as per the new schema\n for (const [storeName, indexes] of Object.entries(options.schema)) {\n const store = database.objectStoreNames.contains(storeName)\n ? tx.objectStore(storeName)\n : database.createObjectStore(storeName, {\n keyPath: 'id',\n })\n\n const indexesToDrop = new Set<string>()\n for (let i = 0; i < store.indexNames.length; i += 1) {\n const indexName = store.indexNames.item(i)\n if (!indexName || indexes.includes(indexName)) continue\n indexesToDrop.add(indexName)\n }\n\n // Drop indexes that are not in the new schema\n indexesToDrop.forEach((indexName) => {\n if (!store.indexNames.contains(indexName)) return\n store.deleteIndex(indexName)\n })\n\n // Create indexes as per the new schema\n for (const index of indexes) {\n if ((index === 'id') || store.indexNames.contains(index)) continue\n store.createIndex(index, index, { unique: false })\n }\n }\n },\n )\n\n return function indexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n >(storeName: string) {\n return createIndexedDBAdapter<T, I>(storeName, databasePromise)\n }\n}\n\n/**\n * Creates a storage adapter for managing a SignalDB collection using IndexedDB.\n * This adapter reads and writes data to an IndexedDB object store, with customizable serialization and deserialization.\n * @template T - The type of the items in the collection.\n * @template I - The type of the unique identifier for the items.\n * @param storeName - A unique name for the collection, used as the database name.\n * @param databasePromise - A promise that resolves to an opened IndexedDB database.\n * @returns A SignalDB storage adapter for managing data in IndexedDB.\n */\nfunction createIndexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n>(storeName: string, databasePromise: Promise<IDBDatabase>) {\n const getStore = async (isWritable = false) => {\n const database = await databasePromise\n if (!database) throw new Error('Database not initialized')\n const transaction = database.transaction(storeName, isWritable ? 'readwrite' : 'readonly')\n const store = transaction.objectStore(storeName)\n return store\n }\n\n const readIndex = async (field: string) => {\n const store = await getStore()\n if (!store.indexNames.contains(field)) {\n throw new Error(`Index on field \"${field}\" does not exist`)\n }\n return new Promise<Map<any, Set<I>>>((resolve, reject) => {\n const index = store.index(field)\n const result = new Map<any, Set<I>>()\n const request = index.openCursor()\n request.addEventListener('success', () => {\n const cursor = request.result\n if (cursor) {\n // Serialized, not raw: SignalDB looks an index up by\n // `serializeValue(value)`, so an IndexedDB key of `3` or `true` would\n // never be found by a query for it.\n const key = serializeValue(cursor.key)\n const id = (cursor.value as T).id\n if (!result.has(key)) {\n result.set(key, new Set())\n }\n result.get(key)?.add(id)\n cursor.continue()\n } else {\n resolve(result)\n }\n })\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error reading index')))\n })\n }\n\n const getById = async (id: I) => {\n const store = await getStore(true)\n return new Promise<T | null>((resolve, reject) => {\n const request = store.get(id)\n request.addEventListener('success', () => resolve(request.result as T || null))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching item')))\n })\n }\n\n const insertOrReplace = async (items: T[]) => {\n const store = await getStore(true)\n await Promise.all(items.map(item => new Promise<void>((resolve, reject) => {\n const request = store.put(item)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error inserting or replacing item')))\n })))\n }\n\n /**\n * Whether a value can be an IndexedDB key that compares as `match` would.\n *\n * IndexedDB keys are numbers, strings, dates, binary and arrays of those.\n * `null`, `undefined` and booleans are not keys at all, and `NaN` is not a\n * valid one — asking for any of them throws rather than answering nothing.\n * Everything outside this set is left to the caller.\n * @param value - The value from the selector.\n * @returns `true` when the value may be used as a key.\n */\n const isUsableKey = (value: unknown): value is IDBValidKey => {\n if (typeof value === 'string') return true\n return typeof value === 'number' ? Number.isFinite(value) : value instanceof Date && !Number.isNaN(value.getTime())\n }\n\n /**\n * Reads everything in a key range from a store or one of its indexes.\n * @param source - The store or index to read from.\n * @param range - The key range to read.\n * @returns The matching items.\n */\n const readRange = (source: IDBObjectStore | IDBIndex, range: IDBKeyRange) => (\n new Promise<T[]>((resolve, reject) => {\n const request = source.getAll(range)\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n )\n\n return createStorageAdapter<T, I>({\n // lifecycle methods\n setup: async () => {\n const database = await databasePromise\n if (database.objectStoreNames.contains(storeName)) return\n throw new Error(`Object store \"${storeName}\" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)\n },\n teardown: async () => {\n const database = await databasePromise\n database.close()\n },\n\n // data retrieval methods\n readAll: async () => {\n const store = await getStore()\n return new Promise<T[]>((resolve, reject) => {\n const request = store.getAll()\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n },\n /**\n * Narrows a read to one equality the store can answer with a key range.\n *\n * IndexedDB is the one shipped adapter that can read less than everything:\n * an object store has a key path and named indexes, and both answer a key\n * range directly. So a selector holding an equality on either becomes a\n * range read instead of `getAll()` over the whole store, which is what\n * this capability exists for. The blob-backed adapters — localstorage, fs,\n * generic-fs, opfs — deliberately do not implement it: they read one\n * serialized array and cannot answer less than all of it, so a `query`\n * there would be the fallback path behind a new name.\n *\n * It claims nothing beyond the narrowing, deliberately. It never reports\n * `sorted`: an index read comes back in index-key order and `readAll` in\n * primary-key order, and neither is what `sortItems` produces. So it never\n * reports `windowed` either, because a window is only meaningful over an\n * order — and never `projected`, since a stored record is read whole.\n * @param query - The query to answer.\n * @param query.selector - The selector to narrow on.\n * @returns The narrowed items and whatever is left of the selector.\n */\n query: async ({ selector }) => {\n const entries = Object.entries(selector ?? {})\n const store = await getStore()\n const keyPath = typeof store.keyPath === 'string' ? store.keyPath : null\n // Narrowed in a loop rather than with `find`: a predicate's type guard\n // does not narrow the tuple it was called on, and the cast that would\n // paper over that is the kind this capability must not carry.\n let usable: { field: string, key: IDBValidKey } | null = null\n for (const [field, value] of entries) {\n if (!isUsableKey(value)) continue\n if (field !== keyPath && !store.indexNames.contains(field)) continue\n usable = { field, key: value }\n break\n }\n\n if (!usable) {\n const items = await new Promise<T[]>((resolve, reject) => {\n const request = store.getAll()\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n return { items, residualSelector: selector }\n }\n\n const narrowed = usable\n const source = narrowed.field === keyPath ? store : store.index(narrowed.field)\n const items = await readRange(source, IDBKeyRange.only(narrowed.key))\n const residual = Object.fromEntries(entries.filter(([other]) => other !== narrowed.field))\n return { items, residualSelector: residual as typeof selector }\n },\n\n readIds: async (ids) => {\n const results = await Promise.all(ids.map(id => getById(id)))\n return results.filter(item => item !== null)\n },\n\n // index methods\n createIndex: async () => {\n /*\n noop\n */\n },\n dropIndex: async () => {\n /*\n noop\n */\n },\n readIndex,\n\n // data manipulation methods\n insert: items => insertOrReplace(items),\n replace: items => insertOrReplace(items),\n remove: async (itemsToRemove) => {\n const store = await getStore(true)\n await Promise.all(itemsToRemove.map(async item => new Promise<void>((resolve, reject) => {\n const request = store.delete(item.id)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error removing item')))\n })))\n },\n removeAll: async () => {\n const store = await getStore(true)\n return new Promise<void>((resolve, reject) => {\n const request = store.clear()\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error clearing items')))\n })\n },\n })\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaldb/indexeddb",
3
- "version": "2.0.0-beta.9",
3
+ "version": "2.0.0-rc.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build": "rimraf dist && vite build",
@@ -56,6 +56,6 @@
56
56
  "fake-indexeddb": "6.2.5"
57
57
  },
58
58
  "peerDependencies": {
59
- "@signaldb/core": "2.0.0-beta.9"
59
+ "@signaldb/core": "^2.0.0-0"
60
60
  }
61
61
  }