@signaldb/localstorage 2.0.0-beta.0 → 2.0.0-beta.2

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,166 +1,166 @@
1
- import { createStorageAdapter as O, get as f, serializeValue as x } from "@signaldb/core";
2
- function C(v, h) {
3
- const p = h?.serialize || ((e) => JSON.stringify(e)), S = h?.deserialize || ((e) => JSON.parse(e)), E = h?.databaseName || "signaldb", M = `${v}`, i = `${E}-${M}`, l = (e) => `${i}-index-${e}`, c = [], d = () => {
4
- const e = localStorage.getItem(i);
1
+ import { createStorageAdapter as C, get as f, serializeValue as E } from "@signaldb/core";
2
+ function T(M, g) {
3
+ const c = globalThis.localStorage;
4
+ if (c == null)
5
+ throw new Error("localStorage is not available in this environment");
6
+ const y = g?.serialize || ((e) => JSON.stringify(e)), w = g?.deserialize || ((e) => JSON.parse(e)), $ = g?.databaseName || "signaldb", b = `${M}`, d = `${$}-${b}`, u = (e) => `${d}-index-${e}`, i = [], l = () => {
7
+ const e = c.getItem(d);
5
8
  if (!e)
6
9
  return [];
7
10
  try {
8
- const n = S(e);
9
- return Array.isArray(n) ? n : [];
11
+ const o = w(e);
12
+ return Array.isArray(o) ? o : [];
10
13
  } catch {
11
14
  return [];
12
15
  }
13
- }, u = (e) => {
14
- localStorage.setItem(i, p(e));
15
- }, $ = async (e) => {
16
- const n = localStorage.getItem(l(e));
17
- if (!n)
16
+ }, h = (e) => {
17
+ c.setItem(d, y(e));
18
+ }, z = async (e) => {
19
+ const o = c.getItem(u(e));
20
+ if (!o)
18
21
  throw new Error(`Index on field "${e}" does not exist`);
19
22
  let t;
20
23
  try {
21
- t = S(n);
24
+ t = w(o);
22
25
  } catch {
23
26
  throw new Error(`Corrupted index on field "${e}"`);
24
27
  }
25
- const o = /* @__PURE__ */ new Map();
26
- return Object.entries(t).forEach(([r, a]) => {
27
- o.has(r) || o.set(r, /* @__PURE__ */ new Set()), a.forEach((s) => o.get(r)?.add(s));
28
- }), o;
29
- }, z = async (e, n = d()) => {
28
+ const n = /* @__PURE__ */ new Map();
29
+ return Object.entries(t).forEach(([s, r]) => {
30
+ n.has(s) || n.set(s, /* @__PURE__ */ new Set()), r.forEach((a) => n.get(s)?.add(a));
31
+ }), n;
32
+ }, v = (e, o) => {
33
+ const t = {};
34
+ o.forEach((n, s) => {
35
+ t[String(E(s))] = [...n];
36
+ }), c.setItem(u(e), y(t));
37
+ }, A = async (e, o = l()) => {
30
38
  const t = /* @__PURE__ */ new Map();
31
- n.forEach((r) => {
32
- const a = f(r, e);
33
- a != null && (t.has(a) || t.set(a, /* @__PURE__ */ new Set()), t.get(a)?.add(r.id));
34
- });
35
- const o = {};
36
- t.forEach((r, a) => {
37
- const s = String(x(a));
38
- o[s] = [...r];
39
- }), localStorage.setItem(l(e), p(o));
40
- }, g = (e) => String(x(e)), b = (e) => {
41
- const n = localStorage.getItem(l(e));
42
- if (!n)
39
+ o.forEach((n) => {
40
+ const s = f(n, e);
41
+ s != null && (t.has(s) || t.set(s, /* @__PURE__ */ new Set()), t.get(s)?.add(n.id));
42
+ }), v(e, t);
43
+ }, m = (e) => String(E(e)), D = (e) => {
44
+ const o = c.getItem(u(e));
45
+ if (!o)
43
46
  return;
44
47
  let t;
45
48
  try {
46
- t = S(n);
49
+ t = w(o);
47
50
  } catch {
48
51
  throw new Error(`Corrupted index on field "${e}"`);
49
52
  }
50
- const o = /* @__PURE__ */ new Map();
51
- return Object.entries(t).forEach(([r, a]) => {
52
- o.set(r, new Set(a));
53
- }), o;
54
- }, A = (e, n) => {
55
- const t = {};
56
- n.forEach((o, r) => {
57
- t[r] = [...o];
58
- }), localStorage.setItem(l(e), p(t));
59
- }, m = (e, n, t, o, r) => {
60
- e.has(n) || e.set(n, { adds: /* @__PURE__ */ new Map(), removes: /* @__PURE__ */ new Map() });
61
- const a = e.get(n);
62
- if (!a)
53
+ const n = /* @__PURE__ */ new Map();
54
+ return Object.entries(t).forEach(([s, r]) => {
55
+ n.set(s, new Set(r));
56
+ }), n;
57
+ }, p = (e, o, t, n, s) => {
58
+ e.has(o) || e.set(o, { adds: /* @__PURE__ */ new Map(), removes: /* @__PURE__ */ new Map() });
59
+ const r = e.get(o);
60
+ if (!r)
63
61
  return;
64
- const s = t === "add" ? a.adds : a.removes;
65
- s.has(o) || s.set(o, /* @__PURE__ */ new Set()), s.get(o)?.add(r);
66
- }, y = (e) => {
67
- e.forEach((n, t) => {
68
- const o = b(t);
69
- o && (n.removes.forEach((r, a) => {
70
- const s = o.get(a);
71
- s && (r.forEach((w) => s.delete(w)), s.size === 0 && o.delete(a));
72
- }), n.adds.forEach((r, a) => {
73
- let s = o.get(a);
74
- s || (s = /* @__PURE__ */ new Set(), o.set(a, s)), r.forEach((w) => s.add(w));
75
- }), A(t, o));
62
+ const a = t === "add" ? r.adds : r.removes;
63
+ a.has(n) || a.set(n, /* @__PURE__ */ new Set()), a.get(n)?.add(s);
64
+ }, I = (e) => {
65
+ e.forEach((o, t) => {
66
+ const n = D(t);
67
+ n && (o.removes.forEach((s, r) => {
68
+ const a = n.get(r);
69
+ a && (s.forEach((x) => a.delete(x)), a.size === 0 && n.delete(r));
70
+ }), o.adds.forEach((s, r) => {
71
+ let a = n.get(r);
72
+ a || (a = /* @__PURE__ */ new Set(), n.set(r, a)), s.forEach((x) => a.add(x));
73
+ }), v(t, n));
76
74
  });
77
- }, K = (e, n, t, o, r) => {
78
- const a = t == null ? void 0 : g(t), s = o == null ? void 0 : g(o);
79
- a !== s && (a != null && m(e, n, "remove", a, r), s != null && m(e, n, "add", s, r));
80
- }, D = (e, n, t) => {
81
- if (n)
82
- for (const o of c)
83
- K(e, o, f(n, o), f(t, o), t.id);
75
+ }, K = (e, o, t, n, s) => {
76
+ const r = t == null ? void 0 : m(t), a = n == null ? void 0 : m(n);
77
+ r !== a && (r != null && p(e, o, "remove", r, s), a != null && p(e, o, "add", a, s));
78
+ }, N = (e, o, t) => {
79
+ if (o)
80
+ for (const n of i)
81
+ K(e, n, f(o, n), f(t, n), t.id);
84
82
  else
85
- for (const o of c) {
86
- const r = f(t, o);
87
- r != null && m(e, o, "add", g(r), t.id);
83
+ for (const n of i) {
84
+ const s = f(t, n);
85
+ s != null && p(e, n, "add", m(s), t.id);
88
86
  }
89
- }, N = (e, n) => {
90
- for (const t of c) {
91
- const o = f(n, t);
92
- o != null && m(e, t, "remove", g(o), n.id);
87
+ }, O = (e, o) => {
88
+ for (const t of i) {
89
+ const n = f(o, t);
90
+ n != null && p(e, t, "remove", m(n), o.id);
93
91
  }
94
- }, I = (e) => {
95
- const n = d(), t = new Map(n.map((r) => [r.id, r])), o = /* @__PURE__ */ new Map();
96
- for (const r of e) {
97
- const a = t.get(r.id);
98
- D(o, a, r), t.set(r.id, r);
92
+ }, S = (e) => {
93
+ const o = l(), t = new Map(o.map((s) => [s.id, s])), n = /* @__PURE__ */ new Map();
94
+ for (const s of e) {
95
+ const r = t.get(s.id);
96
+ N(n, r, s), t.set(s.id, s);
99
97
  }
100
- u([...t.values()]), y(o);
98
+ h([...t.values()]), I(n);
101
99
  };
102
- return O({
100
+ return C({
103
101
  // lifecycle methods
104
102
  setup: async () => {
105
- localStorage.getItem(i) == null && u([]);
106
- const e = `${i}-index-`;
107
- for (let n = 0; n < localStorage.length; n++) {
108
- const t = localStorage.key(n);
103
+ c.getItem(d) == null && h([]);
104
+ const e = `${d}-index-`;
105
+ for (let o = 0; o < c.length; o++) {
106
+ const t = c.key(o);
109
107
  if (t && t.startsWith(e)) {
110
- const o = t.slice(e.length);
111
- c.includes(o) || c.push(o);
108
+ const n = t.slice(e.length);
109
+ i.includes(n) || i.push(n);
112
110
  }
113
111
  }
114
112
  },
115
113
  teardown: async () => {
116
114
  },
117
115
  // data retrieval methods
118
- readAll: async () => d(),
116
+ readAll: async () => l(),
119
117
  readIds: async (e) => {
120
- const n = d(), t = new Set(e);
121
- return n.filter((o) => t.has(o.id));
118
+ const o = l(), t = new Set(e);
119
+ return o.filter((n) => t.has(n.id));
122
120
  },
123
121
  // index methods
124
122
  createIndex: async (e) => {
125
- c.includes(e) || c.push(e), await z(e);
123
+ if (e === "id")
124
+ throw new Error("Cannot create index on id field");
125
+ i.includes(e) || i.push(e), await A(e);
126
126
  },
127
127
  dropIndex: async (e) => {
128
- if (c.includes(e)) {
129
- const t = c.indexOf(e);
130
- c.splice(t, 1);
128
+ if (i.includes(e)) {
129
+ const t = i.indexOf(e);
130
+ i.splice(t, 1);
131
131
  }
132
- const n = l(e);
133
- if (localStorage.getItem(n) == null)
132
+ const o = u(e);
133
+ if (c.getItem(o) == null)
134
134
  throw new Error(`Index on field "${e}" does not exist`);
135
- localStorage.removeItem(n);
135
+ c.removeItem(o);
136
136
  },
137
- readIndex: $,
137
+ readIndex: z,
138
138
  // data manipulation methods
139
139
  insert: async (e) => {
140
- I(e);
140
+ S(e);
141
141
  },
142
142
  replace: async (e) => {
143
- I(e);
143
+ S(e);
144
144
  },
145
145
  remove: async (e) => {
146
- const n = d(), t = new Map(n.map((a) => [a.id, a])), o = /* @__PURE__ */ new Map();
147
- new Set(e.map((a) => a.id)).forEach((a) => {
148
- const s = t.get(a);
149
- s && (N(o, s), t.delete(a));
150
- }), u([...t.values()]), y(o);
146
+ const o = l(), t = new Map(o.map((r) => [r.id, r])), n = /* @__PURE__ */ new Map();
147
+ new Set(e.map((r) => r.id)).forEach((r) => {
148
+ const a = t.get(r);
149
+ a && (O(n, a), t.delete(r));
150
+ }), h([...t.values()]), I(n);
151
151
  },
152
152
  removeAll: async () => {
153
- u([]);
154
- const e = `${i}-index-`, n = [];
155
- for (let t = 0; t < localStorage.length; t++) {
156
- const o = localStorage.key(t);
157
- o && o.startsWith(e) && n.push(o);
153
+ h([]);
154
+ const e = `${d}-index-`, o = [];
155
+ for (let t = 0; t < c.length; t++) {
156
+ const n = c.key(t);
157
+ n && n.startsWith(e) && o.push(n);
158
158
  }
159
- n.forEach((t) => localStorage.removeItem(t)), c.splice(0);
159
+ o.forEach((t) => c.removeItem(t)), i.splice(0);
160
160
  }
161
161
  });
162
162
  }
163
163
  export {
164
- C as default
164
+ T as default
165
165
  };
166
166
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, get, serializeValue } from '@signaldb/core';\n/**\n * Creates a storage adapter for managing a SignalDB collection using localStorage.\n * @param name - A unique name for the collection, used as part of the localStorage key.\n * @param options - Optional configuration for the adapter.\n * @param options.databaseName - An optional name for the database to namespace the storage (default: 'signaldb').\n * @param options.serialize - A function to serialize items to a string (default: `JSON.stringify`).\n * @param options.deserialize - A function to deserialize a string into items (default: `JSON.parse`).\n * @returns A SignalDB storage adapter for managing data in localStorage.\n */\nexport default function createLocalStorageAdapter(name, options) {\n const serialize = options?.serialize || (data => JSON.stringify(data));\n const deserialize = options?.deserialize || (input => JSON.parse(input));\n const databaseName = options?.databaseName || 'signaldb';\n const storeName = `${name}`;\n // We use a single key that namespaces by database and store names\n const storageKey = `${databaseName}-${storeName}`;\n const indexKeyFor = (field) => `${storageKey}-index-${field}`;\n const indices = [];\n const readFromStorage = () => {\n const serialized = localStorage.getItem(storageKey);\n if (!serialized)\n return [];\n try {\n const parsed = deserialize(serialized);\n return Array.isArray(parsed) ? parsed : [];\n }\n catch {\n // If parsing fails, treat as empty to avoid corrupting runtime\n return [];\n }\n };\n const writeToStorage = (items) => {\n localStorage.setItem(storageKey, serialize(items));\n };\n const readIndex = async (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n throw new Error(`Index on field \"${field}\" does not exist`);\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n if (!index.has(key))\n index.set(key, new Set());\n ids.forEach(id => index.get(key)?.add(id));\n });\n return index;\n };\n const ensureIndex = async (field, items = readFromStorage()) => {\n const index = new Map();\n items.forEach((item) => {\n const fieldValue = get(item, field);\n if (fieldValue == null)\n return;\n if (!index.has(fieldValue))\n index.set(fieldValue, new Set());\n index.get(fieldValue)?.add(item.id);\n });\n const safeIndex = {};\n index.forEach((ids, key) => {\n const safeKey = String(serializeValue(key));\n safeIndex[safeKey] = [...ids];\n });\n localStorage.setItem(indexKeyFor(field), serialize(safeIndex));\n };\n // --- Delta indexing helpers ---\n const safeKeyFor = (value) => String(serializeValue(value));\n const loadIndexMap = (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n return undefined;\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n index.set(key, new Set(ids));\n });\n return index;\n };\n const saveIndexMap = (field, index) => {\n const safeIndex = {};\n index.forEach((ids, key) => {\n safeIndex[key] = [...ids];\n });\n localStorage.setItem(indexKeyFor(field), serialize(safeIndex));\n };\n const addToDelta = (deltas, field, kind, key, id) => {\n if (!deltas.has(field)) {\n deltas.set(field, { adds: new Map(), removes: new Map() });\n }\n const delta = deltas.get(field);\n if (!delta)\n return;\n const target = kind === 'add' ? delta.adds : delta.removes;\n if (!target.has(key))\n target.set(key, new Set());\n target.get(key)?.add(id);\n };\n const applyIndexDeltas = (deltas) => {\n // Update only the indices that have changes\n deltas.forEach((delta, field) => {\n const index = loadIndexMap(field);\n // If the index doesn't exist, skip (we only maintain indices that were created)\n if (!index)\n return;\n // Apply removals\n delta.removes.forEach((ids, key) => {\n const set = index.get(key);\n if (!set)\n return;\n ids.forEach(id => set.delete(id));\n if (set.size === 0)\n index.delete(key);\n });\n // Apply additions\n delta.adds.forEach((ids, key) => {\n let set = index.get(key);\n if (!set) {\n set = new Set();\n index.set(key, set);\n }\n ids.forEach(id => set.add(id));\n });\n saveIndexMap(field, index);\n });\n };\n const addDeltaForChange = (deltas, field, oldValue, newValue, id) => {\n const oldKey = oldValue == null ? undefined : safeKeyFor(oldValue);\n const newKey = newValue == null ? undefined : safeKeyFor(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, field, 'remove', oldKey, id);\n if (newKey != null)\n addToDelta(deltas, field, 'add', newKey, id);\n };\n const accumulateUpsertDelta = (deltas, existing, next) => {\n if (existing) {\n for (const field of indices) {\n addDeltaForChange(deltas, field, get(existing, field), get(next, field), next.id);\n }\n }\n else {\n for (const field of indices) {\n const value = get(next, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'add', safeKeyFor(value), next.id);\n }\n }\n };\n const accumulateRemoveDelta = (deltas, existing) => {\n for (const field of indices) {\n const value = get(existing, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'remove', safeKeyFor(value), existing.id);\n }\n };\n const upsertItems = (itemsToUpsert) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n for (const item of itemsToUpsert) {\n const existing = byId.get(item.id);\n accumulateUpsertDelta(deltas, existing, item);\n byId.set(item.id, item);\n }\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n };\n return createStorageAdapter({\n // lifecycle methods\n setup: async () => {\n // For localStorage, there is no database to open; we just ensure the key exists\n if (localStorage.getItem(storageKey) == null) {\n writeToStorage([]);\n }\n // Hydrate known index fields from existing keys so that we can keep them updated across sessions\n const prefix = `${storageKey}-index-`;\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix)) {\n const field = k.slice(prefix.length);\n if (!indices.includes(field))\n indices.push(field);\n }\n }\n },\n teardown: async () => {\n // no-op\n },\n // data retrieval methods\n readAll: async () => {\n return readFromStorage();\n },\n readIds: async (ids) => {\n const items = readFromStorage();\n const idSet = new Set(ids);\n return items.filter(item => idSet.has(item.id));\n },\n // index methods\n createIndex: async (field) => {\n if (!indices.includes(field))\n indices.push(field);\n await ensureIndex(field);\n },\n dropIndex: async (field) => {\n if (indices.includes(field)) {\n const i = indices.indexOf(field);\n indices.splice(i, 1);\n }\n const key = indexKeyFor(field);\n if (localStorage.getItem(key) == null) {\n throw new Error(`Index on field \"${field}\" does not exist`);\n }\n localStorage.removeItem(key);\n },\n readIndex,\n // data manipulation methods\n insert: async (newItems) => {\n upsertItems(newItems);\n },\n replace: async (itemsToReplace) => {\n upsertItems(itemsToReplace);\n },\n remove: async (itemsToRemove) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n const removeSet = new Set(itemsToRemove.map(item => item.id));\n removeSet.forEach((id) => {\n const existing = byId.get(id);\n if (!existing)\n return;\n accumulateRemoveDelta(deltas, existing);\n byId.delete(id);\n });\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n writeToStorage([]);\n // remove all index keys for this store\n const prefix = `${storageKey}-index-`;\n const keysToRemove = [];\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix))\n keysToRemove.push(k);\n }\n keysToRemove.forEach(k => localStorage.removeItem(k));\n indices.splice(0);\n },\n });\n}\n"],"names":["createLocalStorageAdapter","name","options","serialize","data","deserialize","input","databaseName","storeName","storageKey","indexKeyFor","field","indices","readFromStorage","serialized","parsed","writeToStorage","items","readIndex","index","key","ids","id","ensureIndex","item","fieldValue","get","safeIndex","safeKey","serializeValue","safeKeyFor","value","loadIndexMap","saveIndexMap","addToDelta","deltas","kind","delta","target","applyIndexDeltas","set","addDeltaForChange","oldValue","newValue","oldKey","newKey","accumulateUpsertDelta","existing","next","accumulateRemoveDelta","upsertItems","itemsToUpsert","byId","createStorageAdapter","prefix","i","k","idSet","newItems","itemsToReplace","itemsToRemove","keysToRemove"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, get, serializeValue } from '@signaldb/core';\n/**\n * Creates a storage adapter for managing a SignalDB collection using localStorage.\n * @param name - A unique name for the collection, used as part of the localStorage key.\n * @param options - Optional configuration for the adapter.\n * @param options.databaseName - An optional name for the database to namespace the storage (default: 'signaldb').\n * @param options.serialize - A function to serialize items to a string (default: `JSON.stringify`).\n * @param options.deserialize - A function to deserialize a string into items (default: `JSON.parse`).\n * @returns A SignalDB storage adapter for managing data in localStorage.\n */\nexport default function createLocalStorageAdapter(name, options) {\n const localStorage = globalThis.localStorage;\n if (localStorage == null) {\n throw new Error('localStorage is not available in this environment');\n }\n const serialize = options?.serialize || (data => JSON.stringify(data));\n const deserialize = options?.deserialize || (input => JSON.parse(input));\n const databaseName = options?.databaseName || 'signaldb';\n const storeName = `${name}`;\n // We use a single key that namespaces by database and store names\n const storageKey = `${databaseName}-${storeName}`;\n const indexKeyFor = (field) => `${storageKey}-index-${field}`;\n const indices = [];\n const readFromStorage = () => {\n const serialized = localStorage.getItem(storageKey);\n if (!serialized)\n return [];\n try {\n const parsed = deserialize(serialized);\n return Array.isArray(parsed) ? parsed : [];\n }\n catch {\n // If parsing fails, treat as empty to avoid corrupting runtime\n return [];\n }\n };\n const writeToStorage = (items) => {\n localStorage.setItem(storageKey, serialize(items));\n };\n const readIndex = async (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n throw new Error(`Index on field \"${field}\" does not exist`);\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n if (!index.has(key))\n index.set(key, new Set());\n ids.forEach(id => index.get(key)?.add(id));\n });\n return index;\n };\n const saveIndexMap = (field, index) => {\n const safeIndex = {};\n index.forEach((ids, key) => {\n safeIndex[String(serializeValue(key))] = [...ids];\n });\n localStorage.setItem(indexKeyFor(field), serialize(safeIndex));\n };\n const ensureIndex = async (field, items = readFromStorage()) => {\n const index = new Map();\n items.forEach((item) => {\n const fieldValue = get(item, field);\n if (fieldValue == null)\n return;\n if (!index.has(fieldValue))\n index.set(fieldValue, new Set());\n index.get(fieldValue)?.add(item.id);\n });\n saveIndexMap(field, index);\n };\n // --- Delta indexing helpers ---\n const safeKeyFor = (value) => String(serializeValue(value));\n const loadIndexMap = (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n return undefined;\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n index.set(key, new Set(ids));\n });\n return index;\n };\n const addToDelta = (deltas, field, kind, key, id) => {\n if (!deltas.has(field)) {\n deltas.set(field, { adds: new Map(), removes: new Map() });\n }\n const delta = deltas.get(field);\n if (!delta)\n return;\n const target = kind === 'add' ? delta.adds : delta.removes;\n if (!target.has(key))\n target.set(key, new Set());\n target.get(key)?.add(id);\n };\n const applyIndexDeltas = (deltas) => {\n // Update only the indices that have changes\n deltas.forEach((delta, field) => {\n const index = loadIndexMap(field);\n // If the index doesn't exist, skip (we only maintain indices that were created)\n if (!index)\n return;\n // Apply removals\n delta.removes.forEach((ids, key) => {\n const set = index.get(key);\n if (!set)\n return;\n ids.forEach(id => set.delete(id));\n if (set.size === 0)\n index.delete(key);\n });\n // Apply additions\n delta.adds.forEach((ids, key) => {\n let set = index.get(key);\n if (!set) {\n set = new Set();\n index.set(key, set);\n }\n ids.forEach(id => set.add(id));\n });\n saveIndexMap(field, index);\n });\n };\n const addDeltaForChange = (deltas, field, oldValue, newValue, id) => {\n const oldKey = oldValue == null ? undefined : safeKeyFor(oldValue);\n const newKey = newValue == null ? undefined : safeKeyFor(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, field, 'remove', oldKey, id);\n if (newKey != null)\n addToDelta(deltas, field, 'add', newKey, id);\n };\n const accumulateUpsertDelta = (deltas, existing, next) => {\n if (existing) {\n for (const field of indices) {\n addDeltaForChange(deltas, field, get(existing, field), get(next, field), next.id);\n }\n }\n else {\n for (const field of indices) {\n const value = get(next, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'add', safeKeyFor(value), next.id);\n }\n }\n };\n const accumulateRemoveDelta = (deltas, existing) => {\n for (const field of indices) {\n const value = get(existing, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'remove', safeKeyFor(value), existing.id);\n }\n };\n const upsertItems = (itemsToUpsert) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n for (const item of itemsToUpsert) {\n const existing = byId.get(item.id);\n accumulateUpsertDelta(deltas, existing, item);\n byId.set(item.id, item);\n }\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n };\n return createStorageAdapter({\n // lifecycle methods\n setup: async () => {\n // For localStorage, there is no database to open; we just ensure the key exists\n if (localStorage.getItem(storageKey) == null) {\n writeToStorage([]);\n }\n // Hydrate known index fields from existing keys so that we can keep them updated across sessions\n const prefix = `${storageKey}-index-`;\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix)) {\n const field = k.slice(prefix.length);\n if (!indices.includes(field))\n indices.push(field);\n }\n }\n },\n teardown: async () => {\n // no-op\n },\n // data retrieval methods\n readAll: async () => {\n return readFromStorage();\n },\n readIds: async (ids) => {\n const items = readFromStorage();\n const idSet = new Set(ids);\n return items.filter(item => idSet.has(item.id));\n },\n // index methods\n createIndex: async (field) => {\n if (field === 'id')\n throw new Error('Cannot create index on id field');\n if (!indices.includes(field))\n indices.push(field);\n await ensureIndex(field);\n },\n dropIndex: async (field) => {\n if (indices.includes(field)) {\n const i = indices.indexOf(field);\n indices.splice(i, 1);\n }\n const key = indexKeyFor(field);\n if (localStorage.getItem(key) == null) {\n throw new Error(`Index on field \"${field}\" does not exist`);\n }\n localStorage.removeItem(key);\n },\n readIndex,\n // data manipulation methods\n insert: async (newItems) => {\n upsertItems(newItems);\n },\n replace: async (itemsToReplace) => {\n upsertItems(itemsToReplace);\n },\n remove: async (itemsToRemove) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n const removeSet = new Set(itemsToRemove.map(item => item.id));\n removeSet.forEach((id) => {\n const existing = byId.get(id);\n if (!existing)\n return;\n accumulateRemoveDelta(deltas, existing);\n byId.delete(id);\n });\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n writeToStorage([]);\n // remove all index keys for this store\n const prefix = `${storageKey}-index-`;\n const keysToRemove = [];\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix))\n keysToRemove.push(k);\n }\n keysToRemove.forEach(k => localStorage.removeItem(k));\n indices.splice(0);\n },\n });\n}\n"],"names":["createLocalStorageAdapter","name","options","localStorage","serialize","data","deserialize","input","databaseName","storeName","storageKey","indexKeyFor","field","indices","readFromStorage","serialized","parsed","writeToStorage","items","readIndex","index","key","ids","id","saveIndexMap","safeIndex","serializeValue","ensureIndex","item","fieldValue","get","safeKeyFor","value","loadIndexMap","addToDelta","deltas","kind","delta","target","applyIndexDeltas","set","addDeltaForChange","oldValue","newValue","oldKey","newKey","accumulateUpsertDelta","existing","next","accumulateRemoveDelta","upsertItems","itemsToUpsert","byId","createStorageAdapter","prefix","i","k","idSet","newItems","itemsToReplace","itemsToRemove","keysToRemove"],"mappings":"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"}
package/dist/index.umd.js CHANGED
@@ -1,2 +1,2 @@
1
- (function(c,l){typeof exports=="object"&&typeof module<"u"?module.exports=l(require("@signaldb/core")):typeof define=="function"&&define.amd?define(["@signaldb/core"],l):(c=typeof globalThis<"u"?globalThis:c||self,c.SignalDB=l(c.core))})(this,(function(c){"use strict";function l(v,m){const S=m?.serialize||(e=>JSON.stringify(e)),w=m?.deserialize||(e=>JSON.parse(e)),E=m?.databaseName||"signaldb",M=`${v}`,d=`${E}-${M}`,f=e=>`${d}-index-${e}`,i=[],u=()=>{const e=localStorage.getItem(d);if(!e)return[];try{const o=w(e);return Array.isArray(o)?o:[]}catch{return[]}},g=e=>{localStorage.setItem(d,S(e))},$=async e=>{const o=localStorage.getItem(f(e));if(!o)throw new Error(`Index on field "${e}" does not exist`);let t;try{t=w(o)}catch{throw new Error(`Corrupted index on field "${e}"`)}const n=new Map;return Object.entries(t).forEach(([a,s])=>{n.has(a)||n.set(a,new Set),s.forEach(r=>n.get(a)?.add(r))}),n},z=async(e,o=u())=>{const t=new Map;o.forEach(a=>{const s=c.get(a,e);s!=null&&(t.has(s)||t.set(s,new Set),t.get(s)?.add(a.id))});const n={};t.forEach((a,s)=>{const r=String(c.serializeValue(s));n[r]=[...a]}),localStorage.setItem(f(e),S(n))},p=e=>String(c.serializeValue(e)),b=e=>{const o=localStorage.getItem(f(e));if(!o)return;let t;try{t=w(o)}catch{throw new Error(`Corrupted index on field "${e}"`)}const n=new Map;return Object.entries(t).forEach(([a,s])=>{n.set(a,new Set(s))}),n},A=(e,o)=>{const t={};o.forEach((n,a)=>{t[a]=[...n]}),localStorage.setItem(f(e),S(t))},h=(e,o,t,n,a)=>{e.has(o)||e.set(o,{adds:new Map,removes:new Map});const s=e.get(o);if(!s)return;const r=t==="add"?s.adds:s.removes;r.has(n)||r.set(n,new Set),r.get(n)?.add(a)},x=e=>{e.forEach((o,t)=>{const n=b(t);n&&(o.removes.forEach((a,s)=>{const r=n.get(s);r&&(a.forEach(y=>r.delete(y)),r.size===0&&n.delete(s))}),o.adds.forEach((a,s)=>{let r=n.get(s);r||(r=new Set,n.set(s,r)),a.forEach(y=>r.add(y))}),A(t,n))})},D=(e,o,t,n,a)=>{const s=t==null?void 0:p(t),r=n==null?void 0:p(n);s!==r&&(s!=null&&h(e,o,"remove",s,a),r!=null&&h(e,o,"add",r,a))},K=(e,o,t)=>{if(o)for(const n of i)D(e,n,c.get(o,n),c.get(t,n),t.id);else for(const n of i){const a=c.get(t,n);a!=null&&h(e,n,"add",p(a),t.id)}},N=(e,o)=>{for(const t of i){const n=c.get(o,t);n!=null&&h(e,t,"remove",p(n),o.id)}},I=e=>{const o=u(),t=new Map(o.map(a=>[a.id,a])),n=new Map;for(const a of e){const s=t.get(a.id);K(n,s,a),t.set(a.id,a)}g([...t.values()]),x(n)};return c.createStorageAdapter({setup:async()=>{localStorage.getItem(d)==null&&g([]);const e=`${d}-index-`;for(let o=0;o<localStorage.length;o++){const t=localStorage.key(o);if(t&&t.startsWith(e)){const n=t.slice(e.length);i.includes(n)||i.push(n)}}},teardown:async()=>{},readAll:async()=>u(),readIds:async e=>{const o=u(),t=new Set(e);return o.filter(n=>t.has(n.id))},createIndex:async e=>{i.includes(e)||i.push(e),await z(e)},dropIndex:async e=>{if(i.includes(e)){const t=i.indexOf(e);i.splice(t,1)}const o=f(e);if(localStorage.getItem(o)==null)throw new Error(`Index on field "${e}" does not exist`);localStorage.removeItem(o)},readIndex:$,insert:async e=>{I(e)},replace:async e=>{I(e)},remove:async e=>{const o=u(),t=new Map(o.map(s=>[s.id,s])),n=new Map;new Set(e.map(s=>s.id)).forEach(s=>{const r=t.get(s);r&&(N(n,r),t.delete(s))}),g([...t.values()]),x(n)},removeAll:async()=>{g([]);const e=`${d}-index-`,o=[];for(let t=0;t<localStorage.length;t++){const n=localStorage.key(t);n&&n.startsWith(e)&&o.push(n)}o.forEach(t=>localStorage.removeItem(t)),i.splice(0)}})}return l}));
1
+ (function(c,f){typeof exports=="object"&&typeof module<"u"?module.exports=f(require("@signaldb/core")):typeof define=="function"&&define.amd?define(["@signaldb/core"],f):(c=typeof globalThis<"u"?globalThis:c||self,c.SignalDB=f(c.core))})(this,(function(c){"use strict";function f(b,w){const i=globalThis.localStorage;if(i==null)throw new Error("localStorage is not available in this environment");const v=w?.serialize||(e=>JSON.stringify(e)),y=w?.deserialize||(e=>JSON.parse(e)),M=w?.databaseName||"signaldb",$=`${b}`,l=`${M}-${$}`,h=e=>`${l}-index-${e}`,d=[],u=()=>{const e=i.getItem(l);if(!e)return[];try{const s=y(e);return Array.isArray(s)?s:[]}catch{return[]}},g=e=>{i.setItem(l,v(e))},z=async e=>{const s=i.getItem(h(e));if(!s)throw new Error(`Index on field "${e}" does not exist`);let t;try{t=y(s)}catch{throw new Error(`Corrupted index on field "${e}"`)}const n=new Map;return Object.entries(t).forEach(([o,r])=>{n.has(o)||n.set(o,new Set),r.forEach(a=>n.get(o)?.add(a))}),n},I=(e,s)=>{const t={};s.forEach((n,o)=>{t[String(c.serializeValue(o))]=[...n]}),i.setItem(h(e),v(t))},A=async(e,s=u())=>{const t=new Map;s.forEach(n=>{const o=c.get(n,e);o!=null&&(t.has(o)||t.set(o,new Set),t.get(o)?.add(n.id))}),I(e,t)},p=e=>String(c.serializeValue(e)),D=e=>{const s=i.getItem(h(e));if(!s)return;let t;try{t=y(s)}catch{throw new Error(`Corrupted index on field "${e}"`)}const n=new Map;return Object.entries(t).forEach(([o,r])=>{n.set(o,new Set(r))}),n},m=(e,s,t,n,o)=>{e.has(s)||e.set(s,{adds:new Map,removes:new Map});const r=e.get(s);if(!r)return;const a=t==="add"?r.adds:r.removes;a.has(n)||a.set(n,new Set),a.get(n)?.add(o)},S=e=>{e.forEach((s,t)=>{const n=D(t);n&&(s.removes.forEach((o,r)=>{const a=n.get(r);a&&(o.forEach(x=>a.delete(x)),a.size===0&&n.delete(r))}),s.adds.forEach((o,r)=>{let a=n.get(r);a||(a=new Set,n.set(r,a)),o.forEach(x=>a.add(x))}),I(t,n))})},T=(e,s,t,n,o)=>{const r=t==null?void 0:p(t),a=n==null?void 0:p(n);r!==a&&(r!=null&&m(e,s,"remove",r,o),a!=null&&m(e,s,"add",a,o))},K=(e,s,t)=>{if(s)for(const n of d)T(e,n,c.get(s,n),c.get(t,n),t.id);else for(const n of d){const o=c.get(t,n);o!=null&&m(e,n,"add",p(o),t.id)}},N=(e,s)=>{for(const t of d){const n=c.get(s,t);n!=null&&m(e,t,"remove",p(n),s.id)}},E=e=>{const s=u(),t=new Map(s.map(o=>[o.id,o])),n=new Map;for(const o of e){const r=t.get(o.id);K(n,r,o),t.set(o.id,o)}g([...t.values()]),S(n)};return c.createStorageAdapter({setup:async()=>{i.getItem(l)==null&&g([]);const e=`${l}-index-`;for(let s=0;s<i.length;s++){const t=i.key(s);if(t&&t.startsWith(e)){const n=t.slice(e.length);d.includes(n)||d.push(n)}}},teardown:async()=>{},readAll:async()=>u(),readIds:async e=>{const s=u(),t=new Set(e);return s.filter(n=>t.has(n.id))},createIndex:async e=>{if(e==="id")throw new Error("Cannot create index on id field");d.includes(e)||d.push(e),await A(e)},dropIndex:async e=>{if(d.includes(e)){const t=d.indexOf(e);d.splice(t,1)}const s=h(e);if(i.getItem(s)==null)throw new Error(`Index on field "${e}" does not exist`);i.removeItem(s)},readIndex:z,insert:async e=>{E(e)},replace:async e=>{E(e)},remove:async e=>{const s=u(),t=new Map(s.map(r=>[r.id,r])),n=new Map;new Set(e.map(r=>r.id)).forEach(r=>{const a=t.get(r);a&&(N(n,a),t.delete(r))}),g([...t.values()]),S(n)},removeAll:async()=>{g([]);const e=`${l}-index-`,s=[];for(let t=0;t<i.length;t++){const n=i.key(t);n&&n.startsWith(e)&&s.push(n)}s.forEach(t=>i.removeItem(t)),d.splice(0)}})}return f}));
2
2
  //# sourceMappingURL=index.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, get, serializeValue } from '@signaldb/core';\n/**\n * Creates a storage adapter for managing a SignalDB collection using localStorage.\n * @param name - A unique name for the collection, used as part of the localStorage key.\n * @param options - Optional configuration for the adapter.\n * @param options.databaseName - An optional name for the database to namespace the storage (default: 'signaldb').\n * @param options.serialize - A function to serialize items to a string (default: `JSON.stringify`).\n * @param options.deserialize - A function to deserialize a string into items (default: `JSON.parse`).\n * @returns A SignalDB storage adapter for managing data in localStorage.\n */\nexport default function createLocalStorageAdapter(name, options) {\n const serialize = options?.serialize || (data => JSON.stringify(data));\n const deserialize = options?.deserialize || (input => JSON.parse(input));\n const databaseName = options?.databaseName || 'signaldb';\n const storeName = `${name}`;\n // We use a single key that namespaces by database and store names\n const storageKey = `${databaseName}-${storeName}`;\n const indexKeyFor = (field) => `${storageKey}-index-${field}`;\n const indices = [];\n const readFromStorage = () => {\n const serialized = localStorage.getItem(storageKey);\n if (!serialized)\n return [];\n try {\n const parsed = deserialize(serialized);\n return Array.isArray(parsed) ? parsed : [];\n }\n catch {\n // If parsing fails, treat as empty to avoid corrupting runtime\n return [];\n }\n };\n const writeToStorage = (items) => {\n localStorage.setItem(storageKey, serialize(items));\n };\n const readIndex = async (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n throw new Error(`Index on field \"${field}\" does not exist`);\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n if (!index.has(key))\n index.set(key, new Set());\n ids.forEach(id => index.get(key)?.add(id));\n });\n return index;\n };\n const ensureIndex = async (field, items = readFromStorage()) => {\n const index = new Map();\n items.forEach((item) => {\n const fieldValue = get(item, field);\n if (fieldValue == null)\n return;\n if (!index.has(fieldValue))\n index.set(fieldValue, new Set());\n index.get(fieldValue)?.add(item.id);\n });\n const safeIndex = {};\n index.forEach((ids, key) => {\n const safeKey = String(serializeValue(key));\n safeIndex[safeKey] = [...ids];\n });\n localStorage.setItem(indexKeyFor(field), serialize(safeIndex));\n };\n // --- Delta indexing helpers ---\n const safeKeyFor = (value) => String(serializeValue(value));\n const loadIndexMap = (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n return undefined;\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n index.set(key, new Set(ids));\n });\n return index;\n };\n const saveIndexMap = (field, index) => {\n const safeIndex = {};\n index.forEach((ids, key) => {\n safeIndex[key] = [...ids];\n });\n localStorage.setItem(indexKeyFor(field), serialize(safeIndex));\n };\n const addToDelta = (deltas, field, kind, key, id) => {\n if (!deltas.has(field)) {\n deltas.set(field, { adds: new Map(), removes: new Map() });\n }\n const delta = deltas.get(field);\n if (!delta)\n return;\n const target = kind === 'add' ? delta.adds : delta.removes;\n if (!target.has(key))\n target.set(key, new Set());\n target.get(key)?.add(id);\n };\n const applyIndexDeltas = (deltas) => {\n // Update only the indices that have changes\n deltas.forEach((delta, field) => {\n const index = loadIndexMap(field);\n // If the index doesn't exist, skip (we only maintain indices that were created)\n if (!index)\n return;\n // Apply removals\n delta.removes.forEach((ids, key) => {\n const set = index.get(key);\n if (!set)\n return;\n ids.forEach(id => set.delete(id));\n if (set.size === 0)\n index.delete(key);\n });\n // Apply additions\n delta.adds.forEach((ids, key) => {\n let set = index.get(key);\n if (!set) {\n set = new Set();\n index.set(key, set);\n }\n ids.forEach(id => set.add(id));\n });\n saveIndexMap(field, index);\n });\n };\n const addDeltaForChange = (deltas, field, oldValue, newValue, id) => {\n const oldKey = oldValue == null ? undefined : safeKeyFor(oldValue);\n const newKey = newValue == null ? undefined : safeKeyFor(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, field, 'remove', oldKey, id);\n if (newKey != null)\n addToDelta(deltas, field, 'add', newKey, id);\n };\n const accumulateUpsertDelta = (deltas, existing, next) => {\n if (existing) {\n for (const field of indices) {\n addDeltaForChange(deltas, field, get(existing, field), get(next, field), next.id);\n }\n }\n else {\n for (const field of indices) {\n const value = get(next, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'add', safeKeyFor(value), next.id);\n }\n }\n };\n const accumulateRemoveDelta = (deltas, existing) => {\n for (const field of indices) {\n const value = get(existing, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'remove', safeKeyFor(value), existing.id);\n }\n };\n const upsertItems = (itemsToUpsert) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n for (const item of itemsToUpsert) {\n const existing = byId.get(item.id);\n accumulateUpsertDelta(deltas, existing, item);\n byId.set(item.id, item);\n }\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n };\n return createStorageAdapter({\n // lifecycle methods\n setup: async () => {\n // For localStorage, there is no database to open; we just ensure the key exists\n if (localStorage.getItem(storageKey) == null) {\n writeToStorage([]);\n }\n // Hydrate known index fields from existing keys so that we can keep them updated across sessions\n const prefix = `${storageKey}-index-`;\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix)) {\n const field = k.slice(prefix.length);\n if (!indices.includes(field))\n indices.push(field);\n }\n }\n },\n teardown: async () => {\n // no-op\n },\n // data retrieval methods\n readAll: async () => {\n return readFromStorage();\n },\n readIds: async (ids) => {\n const items = readFromStorage();\n const idSet = new Set(ids);\n return items.filter(item => idSet.has(item.id));\n },\n // index methods\n createIndex: async (field) => {\n if (!indices.includes(field))\n indices.push(field);\n await ensureIndex(field);\n },\n dropIndex: async (field) => {\n if (indices.includes(field)) {\n const i = indices.indexOf(field);\n indices.splice(i, 1);\n }\n const key = indexKeyFor(field);\n if (localStorage.getItem(key) == null) {\n throw new Error(`Index on field \"${field}\" does not exist`);\n }\n localStorage.removeItem(key);\n },\n readIndex,\n // data manipulation methods\n insert: async (newItems) => {\n upsertItems(newItems);\n },\n replace: async (itemsToReplace) => {\n upsertItems(itemsToReplace);\n },\n remove: async (itemsToRemove) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n const removeSet = new Set(itemsToRemove.map(item => item.id));\n removeSet.forEach((id) => {\n const existing = byId.get(id);\n if (!existing)\n return;\n accumulateRemoveDelta(deltas, existing);\n byId.delete(id);\n });\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n writeToStorage([]);\n // remove all index keys for this store\n const prefix = `${storageKey}-index-`;\n const keysToRemove = [];\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix))\n keysToRemove.push(k);\n }\n keysToRemove.forEach(k => localStorage.removeItem(k));\n indices.splice(0);\n },\n });\n}\n"],"names":["createLocalStorageAdapter","name","options","serialize","data","deserialize","input","databaseName","storeName","storageKey","indexKeyFor","field","indices","readFromStorage","serialized","parsed","writeToStorage","items","readIndex","index","key","ids","id","ensureIndex","item","fieldValue","get","safeIndex","safeKey","serializeValue","safeKeyFor","value","loadIndexMap","saveIndexMap","addToDelta","deltas","kind","delta","target","applyIndexDeltas","set","addDeltaForChange","oldValue","newValue","oldKey","newKey","accumulateUpsertDelta","existing","next","accumulateRemoveDelta","upsertItems","itemsToUpsert","byId","createStorageAdapter","prefix","i","k","idSet","newItems","itemsToReplace","itemsToRemove","keysToRemove"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter, get, serializeValue } from '@signaldb/core';\n/**\n * Creates a storage adapter for managing a SignalDB collection using localStorage.\n * @param name - A unique name for the collection, used as part of the localStorage key.\n * @param options - Optional configuration for the adapter.\n * @param options.databaseName - An optional name for the database to namespace the storage (default: 'signaldb').\n * @param options.serialize - A function to serialize items to a string (default: `JSON.stringify`).\n * @param options.deserialize - A function to deserialize a string into items (default: `JSON.parse`).\n * @returns A SignalDB storage adapter for managing data in localStorage.\n */\nexport default function createLocalStorageAdapter(name, options) {\n const localStorage = globalThis.localStorage;\n if (localStorage == null) {\n throw new Error('localStorage is not available in this environment');\n }\n const serialize = options?.serialize || (data => JSON.stringify(data));\n const deserialize = options?.deserialize || (input => JSON.parse(input));\n const databaseName = options?.databaseName || 'signaldb';\n const storeName = `${name}`;\n // We use a single key that namespaces by database and store names\n const storageKey = `${databaseName}-${storeName}`;\n const indexKeyFor = (field) => `${storageKey}-index-${field}`;\n const indices = [];\n const readFromStorage = () => {\n const serialized = localStorage.getItem(storageKey);\n if (!serialized)\n return [];\n try {\n const parsed = deserialize(serialized);\n return Array.isArray(parsed) ? parsed : [];\n }\n catch {\n // If parsing fails, treat as empty to avoid corrupting runtime\n return [];\n }\n };\n const writeToStorage = (items) => {\n localStorage.setItem(storageKey, serialize(items));\n };\n const readIndex = async (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n throw new Error(`Index on field \"${field}\" does not exist`);\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n if (!index.has(key))\n index.set(key, new Set());\n ids.forEach(id => index.get(key)?.add(id));\n });\n return index;\n };\n const saveIndexMap = (field, index) => {\n const safeIndex = {};\n index.forEach((ids, key) => {\n safeIndex[String(serializeValue(key))] = [...ids];\n });\n localStorage.setItem(indexKeyFor(field), serialize(safeIndex));\n };\n const ensureIndex = async (field, items = readFromStorage()) => {\n const index = new Map();\n items.forEach((item) => {\n const fieldValue = get(item, field);\n if (fieldValue == null)\n return;\n if (!index.has(fieldValue))\n index.set(fieldValue, new Set());\n index.get(fieldValue)?.add(item.id);\n });\n saveIndexMap(field, index);\n };\n // --- Delta indexing helpers ---\n const safeKeyFor = (value) => String(serializeValue(value));\n const loadIndexMap = (field) => {\n const serialized = localStorage.getItem(indexKeyFor(field));\n if (!serialized)\n return undefined;\n let data;\n try {\n data = deserialize(serialized);\n }\n catch {\n throw new Error(`Corrupted index on field \"${field}\"`);\n }\n const index = new Map();\n Object.entries(data).forEach(([key, ids]) => {\n index.set(key, new Set(ids));\n });\n return index;\n };\n const addToDelta = (deltas, field, kind, key, id) => {\n if (!deltas.has(field)) {\n deltas.set(field, { adds: new Map(), removes: new Map() });\n }\n const delta = deltas.get(field);\n if (!delta)\n return;\n const target = kind === 'add' ? delta.adds : delta.removes;\n if (!target.has(key))\n target.set(key, new Set());\n target.get(key)?.add(id);\n };\n const applyIndexDeltas = (deltas) => {\n // Update only the indices that have changes\n deltas.forEach((delta, field) => {\n const index = loadIndexMap(field);\n // If the index doesn't exist, skip (we only maintain indices that were created)\n if (!index)\n return;\n // Apply removals\n delta.removes.forEach((ids, key) => {\n const set = index.get(key);\n if (!set)\n return;\n ids.forEach(id => set.delete(id));\n if (set.size === 0)\n index.delete(key);\n });\n // Apply additions\n delta.adds.forEach((ids, key) => {\n let set = index.get(key);\n if (!set) {\n set = new Set();\n index.set(key, set);\n }\n ids.forEach(id => set.add(id));\n });\n saveIndexMap(field, index);\n });\n };\n const addDeltaForChange = (deltas, field, oldValue, newValue, id) => {\n const oldKey = oldValue == null ? undefined : safeKeyFor(oldValue);\n const newKey = newValue == null ? undefined : safeKeyFor(newValue);\n if (oldKey === newKey)\n return;\n if (oldKey != null)\n addToDelta(deltas, field, 'remove', oldKey, id);\n if (newKey != null)\n addToDelta(deltas, field, 'add', newKey, id);\n };\n const accumulateUpsertDelta = (deltas, existing, next) => {\n if (existing) {\n for (const field of indices) {\n addDeltaForChange(deltas, field, get(existing, field), get(next, field), next.id);\n }\n }\n else {\n for (const field of indices) {\n const value = get(next, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'add', safeKeyFor(value), next.id);\n }\n }\n };\n const accumulateRemoveDelta = (deltas, existing) => {\n for (const field of indices) {\n const value = get(existing, field);\n if (value == null)\n continue;\n addToDelta(deltas, field, 'remove', safeKeyFor(value), existing.id);\n }\n };\n const upsertItems = (itemsToUpsert) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n for (const item of itemsToUpsert) {\n const existing = byId.get(item.id);\n accumulateUpsertDelta(deltas, existing, item);\n byId.set(item.id, item);\n }\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n };\n return createStorageAdapter({\n // lifecycle methods\n setup: async () => {\n // For localStorage, there is no database to open; we just ensure the key exists\n if (localStorage.getItem(storageKey) == null) {\n writeToStorage([]);\n }\n // Hydrate known index fields from existing keys so that we can keep them updated across sessions\n const prefix = `${storageKey}-index-`;\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix)) {\n const field = k.slice(prefix.length);\n if (!indices.includes(field))\n indices.push(field);\n }\n }\n },\n teardown: async () => {\n // no-op\n },\n // data retrieval methods\n readAll: async () => {\n return readFromStorage();\n },\n readIds: async (ids) => {\n const items = readFromStorage();\n const idSet = new Set(ids);\n return items.filter(item => idSet.has(item.id));\n },\n // index methods\n createIndex: async (field) => {\n if (field === 'id')\n throw new Error('Cannot create index on id field');\n if (!indices.includes(field))\n indices.push(field);\n await ensureIndex(field);\n },\n dropIndex: async (field) => {\n if (indices.includes(field)) {\n const i = indices.indexOf(field);\n indices.splice(i, 1);\n }\n const key = indexKeyFor(field);\n if (localStorage.getItem(key) == null) {\n throw new Error(`Index on field \"${field}\" does not exist`);\n }\n localStorage.removeItem(key);\n },\n readIndex,\n // data manipulation methods\n insert: async (newItems) => {\n upsertItems(newItems);\n },\n replace: async (itemsToReplace) => {\n upsertItems(itemsToReplace);\n },\n remove: async (itemsToRemove) => {\n const items = readFromStorage();\n const byId = new Map(items.map(item => [item.id, item]));\n const deltas = new Map();\n const removeSet = new Set(itemsToRemove.map(item => item.id));\n removeSet.forEach((id) => {\n const existing = byId.get(id);\n if (!existing)\n return;\n accumulateRemoveDelta(deltas, existing);\n byId.delete(id);\n });\n writeToStorage([...byId.values()]);\n applyIndexDeltas(deltas);\n },\n removeAll: async () => {\n writeToStorage([]);\n // remove all index keys for this store\n const prefix = `${storageKey}-index-`;\n const keysToRemove = [];\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i);\n if (k && k.startsWith(prefix))\n keysToRemove.push(k);\n }\n keysToRemove.forEach(k => localStorage.removeItem(k));\n indices.splice(0);\n },\n });\n}\n"],"names":["createLocalStorageAdapter","name","options","localStorage","serialize","data","deserialize","input","databaseName","storeName","storageKey","indexKeyFor","field","indices","readFromStorage","serialized","parsed","writeToStorage","items","readIndex","index","key","ids","id","saveIndexMap","safeIndex","serializeValue","ensureIndex","item","fieldValue","get","safeKeyFor","value","loadIndexMap","addToDelta","deltas","kind","delta","target","applyIndexDeltas","set","addDeltaForChange","oldValue","newValue","oldKey","newKey","accumulateUpsertDelta","existing","next","accumulateRemoveDelta","upsertItems","itemsToUpsert","byId","createStorageAdapter","prefix","i","k","idSet","newItems","itemsToReplace","itemsToRemove","keysToRemove"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaldb/localstorage",
3
- "version": "2.0.0-beta.0",
3
+ "version": "2.0.0-beta.2",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build": "rimraf dist && vite build",
@@ -53,6 +53,6 @@
53
53
  "dist"
54
54
  ],
55
55
  "peerDependencies": {
56
- "@signaldb/core": "2.0.0-beta.0"
56
+ "@signaldb/core": "2.0.0-beta.2"
57
57
  }
58
58
  }