@vielzeug/vault 1.0.4 → 2.0.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.
Files changed (86) hide show
  1. package/README.md +18 -59
  2. package/dist/_dev.cjs +1 -1
  3. package/dist/_dev.cjs.map +1 -1
  4. package/dist/_dev.js +3 -8
  5. package/dist/_dev.js.map +1 -1
  6. package/dist/adapter-core.cjs +1 -1
  7. package/dist/adapter-core.cjs.map +1 -1
  8. package/dist/adapter-core.d.ts +6 -3
  9. package/dist/adapter-core.d.ts.map +1 -1
  10. package/dist/adapter-core.js +138 -148
  11. package/dist/adapter-core.js.map +1 -1
  12. package/dist/adapters/indexeddb.cjs +1 -1
  13. package/dist/adapters/indexeddb.cjs.map +1 -1
  14. package/dist/adapters/indexeddb.d.ts +2 -5
  15. package/dist/adapters/indexeddb.d.ts.map +1 -1
  16. package/dist/adapters/indexeddb.js +113 -127
  17. package/dist/adapters/indexeddb.js.map +1 -1
  18. package/dist/adapters/memory.cjs +1 -1
  19. package/dist/adapters/memory.cjs.map +1 -1
  20. package/dist/adapters/memory.d.ts +3 -9
  21. package/dist/adapters/memory.d.ts.map +1 -1
  22. package/dist/adapters/memory.js +104 -140
  23. package/dist/adapters/memory.js.map +1 -1
  24. package/dist/adapters/webstorage.cjs +1 -1
  25. package/dist/adapters/webstorage.cjs.map +1 -1
  26. package/dist/adapters/webstorage.d.ts +3 -3
  27. package/dist/adapters/webstorage.d.ts.map +1 -1
  28. package/dist/adapters/webstorage.js +72 -67
  29. package/dist/adapters/webstorage.js.map +1 -1
  30. package/dist/errors.cjs.map +1 -1
  31. package/dist/errors.js.map +1 -1
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.d.ts +2 -7
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +8 -10
  36. package/dist/internal.cjs +1 -1
  37. package/dist/internal.cjs.map +1 -1
  38. package/dist/internal.d.ts +8 -37
  39. package/dist/internal.d.ts.map +1 -1
  40. package/dist/internal.js +48 -98
  41. package/dist/internal.js.map +1 -1
  42. package/dist/migration.cjs +1 -1
  43. package/dist/migration.cjs.map +1 -1
  44. package/dist/migration.js +1 -3
  45. package/dist/migration.js.map +1 -1
  46. package/dist/prune.cjs +1 -1
  47. package/dist/prune.cjs.map +1 -1
  48. package/dist/prune.d.ts +2 -2
  49. package/dist/prune.d.ts.map +1 -1
  50. package/dist/prune.js +13 -13
  51. package/dist/prune.js.map +1 -1
  52. package/dist/query.cjs +1 -1
  53. package/dist/query.cjs.map +1 -1
  54. package/dist/query.d.ts +6 -6
  55. package/dist/query.d.ts.map +1 -1
  56. package/dist/query.js +1 -1
  57. package/dist/query.js.map +1 -1
  58. package/dist/streaming.d.ts +1 -21
  59. package/dist/streaming.d.ts.map +1 -1
  60. package/dist/ttl.cjs +1 -1
  61. package/dist/ttl.cjs.map +1 -1
  62. package/dist/ttl.d.ts +2 -47
  63. package/dist/ttl.d.ts.map +1 -1
  64. package/dist/ttl.js +1 -8
  65. package/dist/ttl.js.map +1 -1
  66. package/dist/types.cjs.map +1 -1
  67. package/dist/types.d.ts +29 -316
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/types.js.map +1 -1
  70. package/dist/vault.cjs +1 -1
  71. package/dist/vault.cjs.map +1 -1
  72. package/dist/vault.iife.js +1 -1
  73. package/dist/vault.iife.js.map +1 -1
  74. package/dist/vault.js +1 -1
  75. package/dist/vault.js.map +1 -1
  76. package/dist/versioned-codec.d.ts +1 -43
  77. package/dist/versioned-codec.d.ts.map +1 -1
  78. package/package.json +4 -4
  79. package/dist/streaming.cjs +0 -2
  80. package/dist/streaming.cjs.map +0 -1
  81. package/dist/streaming.js +0 -21
  82. package/dist/streaming.js.map +0 -1
  83. package/dist/versioned-codec.cjs +0 -2
  84. package/dist/versioned-codec.cjs.map +0 -1
  85. package/dist/versioned-codec.js +0 -32
  86. package/dist/versioned-codec.js.map +0 -1
@@ -1,85 +1,86 @@
1
- import { warn as e } from "./_dev.js";
2
- import { VaultDisposedError as t, VaultError as n, VaultScopeError as r } from "./errors.js";
3
- import { createObserveMany as i, createObserverHub as a, createWatchIterable as o, getRecordKey as s } from "./internal.js";
4
- import { createQueryBuilder as c } from "./query.js";
5
- import { assertTtlMs as l } from "./ttl.js";
1
+ import { VaultDisposedError as e, VaultError as t, VaultScopeError as n } from "./errors.js";
2
+ import { createObserverHub as r, getRecordKey as i } from "./internal.js";
3
+ import { createQueryBuilder as a } from "./query.js";
4
+ import { assertTtlMs as o } from "./ttl.js";
6
5
  //#region src/adapter-core.ts
7
- var u = typeof performance < "u" ? () => performance.now() : () => Date.now();
8
- function d(e, t, n) {
9
- return n !== void 0 && l(n, "put/putAll"), n ?? e[t].defaultTtl;
6
+ var s = typeof performance < "u" ? () => performance.now() : () => Date.now();
7
+ function c(e, t, n) {
8
+ return n !== void 0 && o(n, "put/putAll"), n ?? e[t].defaultTtl;
10
9
  }
11
- function f(e, t, r, i, a) {
12
- let o = s(e, t, i);
13
- if (o !== r) throw new n(`${a}: key field "${e[t].key}" must be "${String(r)}" but got "${String(o)}" in table "${t}"`);
10
+ function l(e, n, r, a, o) {
11
+ let s = i(e, n, a);
12
+ if (s !== r) throw new t(`${o}: key field "${e[n].key}" must be "${String(r)}" but got "${String(s)}" in table "${n}"`);
14
13
  }
15
- function p(e, t, n) {
14
+ function u(e, t, n) {
16
15
  return e.getMany ? e.getMany(t, n) : Promise.all(n.map((n) => e.get(t, n)));
17
16
  }
18
- function m(e, t, n, r) {
19
- let i = n[e], a = i.key, o = i.indexes ? new Set(i.indexes) : void 0;
17
+ function d(e, t, n, r) {
18
+ let a = n[e], o = a.key, s = a.indexes ? new Set(a.indexes) : void 0;
20
19
  return {
21
- deleteMany: async (i) => {
22
- if (i.length === 0) return 0;
23
- let a = i.map((t) => s(n, e, t)), o = await t.deleteMany(e, a);
24
- return o > 0 && r(e), o;
20
+ deleteMany: async (a) => {
21
+ if (a.length === 0) return 0;
22
+ let o = a.map((t) => i(n, e, t)), s = await t.deleteMany(e, o);
23
+ return s > 0 && r(e), s;
25
24
  },
26
25
  getIndexRange: t.getByIndexRange ? (n, r) => t.getByIndexRange(e, n, r) : void 0,
27
26
  getRange: t.getByKeyRange ? (n) => t.getByKeyRange(e, n) : void 0,
28
- indexedFields: o,
29
- keyField: a,
27
+ indexedFields: s,
28
+ keyField: o,
30
29
  source: () => t.getAll(e)
31
30
  };
32
31
  }
33
- function h(e, t, n, i, a) {
34
- let o = i ?? ((e, t) => t), s = a ? (e) => {
35
- if (!a.has(e)) throw new r(`table "${e}" is not part of this batch scope`);
32
+ function f(e, t, r, i, o) {
33
+ let s = i ?? ((e, t) => t), f = o ? (e) => {
34
+ if (!o.has(e)) throw new n(`table "${e}" is not part of this batch scope`);
36
35
  } : (e) => {};
37
36
  return {
38
37
  async clear(e) {
39
- s(e), await t.count(e) !== 0 && (await t.clear(e), n(e));
38
+ f(e);
39
+ let n = await t.count(e);
40
+ await t.clear(e), n > 0 && r(e);
40
41
  },
41
42
  async count(e) {
42
- return s(e), t.count(e);
43
+ return f(e), t.count(e);
43
44
  },
44
- async delete(e, r) {
45
- s(e);
46
- let i = await t.delete(e, r);
47
- return i && n(e), i;
45
+ async delete(e, n) {
46
+ f(e);
47
+ let i = await t.delete(e, n);
48
+ return i && r(e), i;
48
49
  },
49
- async deleteMany(e, r) {
50
- s(e);
51
- let i = await t.deleteMany(e, r);
52
- return i > 0 && n(e), i;
50
+ async deleteMany(e, n) {
51
+ f(e);
52
+ let i = await t.deleteMany(e, n);
53
+ return i > 0 && r(e), i;
53
54
  },
54
55
  async entries(n) {
55
- s(n);
56
+ f(n);
56
57
  let r = await t.getAll(n), i = e[n].key;
57
58
  return r.map((e) => [e[i], e]);
58
59
  },
59
60
  async get(e, n) {
60
- return s(e), t.get(e, n);
61
+ return f(e), t.get(e, n);
61
62
  },
62
63
  async getAll(e) {
63
- return s(e), t.getAll(e);
64
+ return f(e), t.getAll(e);
64
65
  },
65
66
  async getMany(e, n) {
66
- return s(e), p(t, e, n);
67
+ return f(e), u(t, e, n);
67
68
  },
68
- async getOrDefault(r, i, a, c) {
69
- s(r);
70
- let l = await t.get(r, i);
71
- if (l !== void 0) return l;
72
- let u = a();
73
- return f(e, r, i, u, "getOrDefault: defaultFn()"), await t.put(r, o(r, u), d(e, r, c)), n(r), u;
69
+ async getOrDefault(n, i, a, o) {
70
+ f(n);
71
+ let u = await t.get(n, i);
72
+ if (u !== void 0) return u;
73
+ let d = a();
74
+ return l(e, n, i, d, "getOrDefault: defaultFn()"), await t.put(n, s(n, d), c(e, n, o)), r(n), d;
74
75
  },
75
76
  async has(e, n) {
76
- return s(e), t.has(e, n);
77
+ return f(e), t.has(e, n);
77
78
  },
78
79
  async isEmpty(e) {
79
- return s(e), await t.count(e) === 0;
80
+ return f(e), await t.count(e) === 0;
80
81
  },
81
82
  async keys(n, r) {
82
- if (s(n), r) {
83
+ if (f(n), r) {
83
84
  let i = await t.getAll(n), a = e[n].key;
84
85
  return i.filter(r).map((e) => e[a]);
85
86
  }
@@ -87,89 +88,79 @@ function h(e, t, n, i, a) {
87
88
  let i = await t.getAll(n), a = e[n].key;
88
89
  return i.map((e) => e[a]);
89
90
  },
90
- async put(r, i, a) {
91
- s(r), await t.put(r, o(r, i), d(e, r, a)), n(r);
91
+ async put(n, i, a) {
92
+ f(n), await t.put(n, s(n, i), c(e, n, a)), r(n);
92
93
  },
93
- async putAll(r, i, a) {
94
- if (s(r), i.length === 0) return;
95
- let c = i.map((e) => o(r, e));
96
- await t.putAll(r, c, d(e, r, a)), n(r);
94
+ async putAll(n, i, a) {
95
+ if (f(n), i.length === 0) return;
96
+ let o = i.map((e) => s(n, e));
97
+ await t.putAll(n, o, c(e, n, a)), r(n);
97
98
  },
98
- query(r) {
99
- return s(r), c(m(r, t, e, n));
99
+ query(n) {
100
+ return f(n), a(d(n, t, e, r));
100
101
  },
101
- async update(r, i, a, c) {
102
- s(r);
103
- let l = await t.get(r, i);
104
- if (!l) return;
105
- let u = {
106
- ...l,
102
+ async update(n, i, a, o) {
103
+ f(n);
104
+ let u = await t.get(n, i);
105
+ if (!u) return;
106
+ let d = {
107
+ ...u,
107
108
  ...a
108
109
  };
109
- return f(e, r, i, u, "update"), await t.put(r, o(r, u), d(e, r, c)), n(r), u;
110
+ return l(e, n, i, d, "update"), await t.put(n, s(n, d), c(e, n, o)), r(n), d;
110
111
  },
111
- async upsert(r, i, a, c) {
112
- s(r);
113
- let l = a(await t.get(r, i));
114
- return f(e, r, i, l, "upsert: fn()"), await t.put(r, o(r, l), d(e, r, c)), n(r), l;
112
+ async upsert(n, i, a, o) {
113
+ f(n);
114
+ let u = a(await t.get(n, i));
115
+ return l(e, n, i, u, "upsert: fn()"), await t.put(n, s(n, u), c(e, n, o)), r(n), u;
115
116
  }
116
117
  };
117
118
  }
118
- function g(s, l, d) {
119
- let { logger: f, onMetrics: p, signals: g, validators: _ } = d ?? {}, v = a((e) => l.getAll(e), f ? (e) => f.error(e instanceof Error ? e : Error(String(e)), "[vault] observer notification failed") : void 0), y = /* @__PURE__ */ new Map(), b = async (e) => {
120
- if (y.has(e)) return y.get(e);
121
- let t = await l.count(e);
122
- return y.set(e, t), t;
123
- }, x = (e) => {
124
- y.delete(e), v.notify(e), d?.onMutation?.(e);
125
- }, S = (e) => {
126
- y.delete(e), v.notify(e);
127
- }, C = l.pruneAllExpired?.bind(l), w = l.getRawCount?.bind(l), T = d?.onCrossTabMessage?.(S) ?? void 0;
128
- if (g) for (let [e, t] of Object.entries(g)) t && v.observe(e, (e) => {
129
- t.update(() => e);
130
- });
131
- let E = (e, t) => {
132
- let r = _?.[e];
133
- if (!r) return t;
119
+ function p(n, i, o) {
120
+ let { logger: c, onMetrics: l, validators: u } = o ?? {}, p = r((e) => i.getAll(e), c ? (e) => c.error(e instanceof Error ? e : Error(String(e)), "[vault] observer notification failed") : void 0), m = /* @__PURE__ */ new Map(), h = async (e) => {
121
+ if (m.has(e)) return m.get(e);
122
+ let t = await i.count(e);
123
+ return m.set(e, t), t;
124
+ }, g = (e) => {
125
+ m.delete(e), p.notify(e), o?.onMutation?.(e);
126
+ }, _ = (e) => {
127
+ m.delete(e), p.notify(e);
128
+ }, v = i.pruneAllExpired?.bind(i), y = i.getRawCount?.bind(i), b = o?.onCrossTabMessage?.(_) ?? void 0, x = (e, n) => {
129
+ let r = u?.[e];
130
+ if (!r) return n;
134
131
  try {
135
- return r.parse(t);
136
- } catch (t) {
137
- throw new n(`validation failed for table "${e}"`, { cause: t });
132
+ return r.parse(n);
133
+ } catch (n) {
134
+ throw new t(`validation failed for table "${e}"`, { cause: n });
138
135
  }
139
- }, D = (e, t, n) => {
140
- if (!p) return n();
141
- let r = u();
142
- return n().finally(() => p({
143
- duration: u() - r,
136
+ }, S = (e, t, n) => {
137
+ if (!l) return n();
138
+ let r = s();
139
+ return n().finally(() => l({
140
+ duration: s() - r,
144
141
  operation: t,
145
142
  table: e
146
143
  }));
147
- }, O = async (e, t) => {
148
- let n = /* @__PURE__ */ new Set(), r = await e(h(s, l, (e) => n.add(e), E, t));
149
- for (let e of n) x(e);
150
- return r;
151
- }, k = d?.buildBatch?.({
152
- notifyMutation: x,
153
- validate: E
154
- }), A = !1, j = h(s, l, x, E), M = i(v), N = new AbortController(), P = !1, F = () => {
155
- if (P) throw new t();
156
- }, I = {
157
- async batch(t, n) {
158
- if (F(), t.length === 0) throw new r("batch requires at least one table");
159
- return !k && !A && (A = !0, e("batch() on this adapter is not atomic — concurrent mutations may interleave. Use createIndexedDB for atomic batches.")), D("*", "batch", () => k ? k(t, n) : O(n, new Set(t)));
160
- },
144
+ };
145
+ o?.onTransactions?.({
146
+ notifyMutation: g,
147
+ validate: x
148
+ });
149
+ let C = f(n, i, g, x), w = new AbortController(), T = !1, E = () => {
150
+ if (T) throw new e();
151
+ }, D = {
161
152
  async clear(e) {
162
- F(), await D(e, "clear", () => j.clear(e)), y.set(e, 0);
153
+ E(), await S(e, "clear", () => C.clear(e)), m.set(e, 0);
163
154
  },
164
155
  async count(e) {
165
- return F(), D(e, "count", () => b(e));
156
+ return E(), S(e, "count", () => h(e));
166
157
  },
167
158
  async debug() {
168
- F();
169
- let e = Object.keys(s);
159
+ E();
160
+ let e = Object.keys(n);
170
161
  return { tables: await Promise.all(e.map(async (e) => {
171
- let t = w ? await w(e) : void 0, n = await l.count(e);
172
- return y.set(e, n), {
162
+ let t = y ? await y(e) : void 0, n = await i.count(e);
163
+ return m.set(e, n), {
173
164
  expiredCount: t === void 0 ? 0 : Math.max(0, t - n),
174
165
  name: e,
175
166
  recordCount: n
@@ -177,93 +168,92 @@ function g(s, l, d) {
177
168
  })) };
178
169
  },
179
170
  async delete(e, t) {
180
- return F(), D(e, "delete", () => j.delete(e, t));
171
+ return E(), S(e, "delete", () => C.delete(e, t));
181
172
  },
182
173
  async deleteMany(e, t) {
183
- return F(), D(e, "deleteMany", () => j.deleteMany(e, t));
174
+ return E(), S(e, "deleteMany", () => C.deleteMany(e, t));
184
175
  },
185
176
  get disposalSignal() {
186
- return N.signal;
177
+ return w.signal;
187
178
  },
188
179
  async dispose() {
189
- P || (P = !0, N.abort(), T?.(), v.dispose(), await l.dispose?.());
180
+ T || (T = !0, w.abort(), b?.(), p.dispose(), await i.dispose?.());
190
181
  },
191
182
  get disposed() {
192
- return P;
183
+ return T;
193
184
  },
194
185
  async entries(e) {
195
- return F(), D(e, "entries", () => j.entries(e));
186
+ return E(), S(e, "entries", () => C.entries(e));
196
187
  },
197
188
  async get(e, t) {
198
- return F(), D(e, "get", () => j.get(e, t));
189
+ return E(), S(e, "get", () => C.get(e, t));
199
190
  },
200
191
  async getAll(e) {
201
- return F(), D(e, "getAll", () => j.getAll(e));
192
+ return E(), S(e, "getAll", () => C.getAll(e));
202
193
  },
203
194
  async getMany(e, t) {
204
- return F(), D(e, "getMany", () => j.getMany(e, t));
195
+ return E(), S(e, "getMany", () => C.getMany(e, t));
205
196
  },
206
197
  async getOrDefault(e, t, n, r) {
207
- return F(), D(e, "getOrDefault", () => j.getOrDefault(e, t, n, r));
198
+ return E(), S(e, "getOrDefault", () => C.getOrDefault(e, t, n, r));
208
199
  },
209
200
  async has(e, t) {
210
- return F(), D(e, "has", () => j.has(e, t));
201
+ return E(), S(e, "has", () => C.has(e, t));
211
202
  },
212
203
  async isEmpty(e) {
213
- return F(), D(e, "isEmpty", async () => await b(e) === 0);
204
+ return E(), S(e, "isEmpty", async () => await h(e) === 0);
214
205
  },
215
206
  async keys(e, t) {
216
- return F(), D(e, "keys", () => j.keys(e, t));
207
+ return E(), S(e, "keys", () => C.keys(e, t));
217
208
  },
218
209
  observe(e, t, n) {
219
- return F(), v.observe(e, t, n);
210
+ return E(), p.observe(e, t, n);
220
211
  },
221
- observeMany: (e, t, n) => (F(), M(e, t, n)),
222
212
  async pruneExpired(e) {
223
- F();
224
- let t = e ?? Object.keys(s);
225
- if (!e && C) {
226
- let e = await C();
227
- for (let [t, n] of Object.entries(e)) n > 0 && y.delete(t);
213
+ E();
214
+ let t = e ?? Object.keys(n);
215
+ if (!e && v) {
216
+ let e = await v();
217
+ for (let [t, n] of Object.entries(e)) n > 0 && m.delete(t);
228
218
  return e;
229
219
  }
230
- let n = await Promise.all(t.map(async (e) => {
231
- let t = await l.pruneExpiredInTable(e);
232
- return t > 0 && y.delete(e), [e, t];
220
+ let r = await Promise.all(t.map(async (e) => {
221
+ let t = await i.pruneExpiredInTable(e);
222
+ return t > 0 && m.delete(e), [e, t];
233
223
  }));
234
- return Object.fromEntries(n);
224
+ return Object.fromEntries(r);
235
225
  },
236
226
  async put(e, t, n) {
237
- F(), await D(e, "put", () => j.put(e, t, n));
227
+ E(), await S(e, "put", () => C.put(e, t, n));
238
228
  },
239
229
  async putAll(e, t, n) {
240
- F(), await D(e, "putAll", () => j.putAll(e, t, n));
230
+ E(), await S(e, "putAll", () => C.putAll(e, t, n));
241
231
  },
242
232
  query(e) {
243
- F();
244
- let t = m(e, l, s, x);
245
- return c(p ? {
233
+ E();
234
+ let t = d(e, i, n, g);
235
+ return a(l ? {
246
236
  ...t,
247
- deleteMany: t.deleteMany ? (n) => D(e, "queryDelete", () => t.deleteMany(n)) : void 0,
248
- source: () => D(e, "query", () => l.getAll(e))
237
+ deleteMany: t.deleteMany ? (n) => S(e, "queryDelete", () => t.deleteMany(n)) : void 0,
238
+ source: () => S(e, "query", () => i.getAll(e))
249
239
  } : t);
250
240
  },
251
241
  async [Symbol.asyncDispose]() {
252
- await I.dispose();
242
+ await D.dispose();
253
243
  },
254
244
  async update(e, t, n, r) {
255
- return F(), D(e, "update", () => j.update(e, t, n, r));
245
+ return E(), S(e, "update", () => C.update(e, t, n, r));
256
246
  },
257
247
  async upsert(e, t, n, r) {
258
- return F(), D(e, "upsert", () => j.upsert(e, t, n, r));
259
- },
260
- watch(e, t) {
261
- return F(), o((t) => v.observe(e, t), t?.mode ?? "latest", t?.signal);
248
+ return E(), S(e, "upsert", () => C.upsert(e, t, n, r));
262
249
  }
263
250
  };
264
- return I;
251
+ return D;
252
+ }
253
+ function m(e, t) {
254
+ return Object.assign(e, { batch: t });
265
255
  }
266
256
  //#endregion
267
- export { g as buildAdapterOps, h as buildTxContext };
257
+ export { p as buildAdapterOps, f as buildTxContext, m as withIndexedDbTransactions };
268
258
 
269
259
  //# sourceMappingURL=adapter-core.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-core.js","names":[],"sources":["../src/adapter-core.ts"],"sourcesContent":["import type {\n Adapter,\n AnySchema,\n BaseAdapterOptions,\n DebugInfo,\n KeyOf,\n MetricsEvent,\n RecordOf,\n TransactionContext,\n TtlMs,\n} from './types';\n\nimport { warn } from './_dev';\nimport { VaultDisposedError, VaultError, VaultScopeError } from './errors';\nimport { createObserveMany, createObserverHub, createWatchIterable, getRecordKey } from './internal';\nimport { createQueryBuilder, type NativeRange, type QueryContext } from './query';\nimport { assertTtlMs } from './ttl';\n\n/* -------------------- Internal backend protocol -------------------- */\n\n/** @internal Full backend protocol implemented by each adapter. A single flat interface — no StorageCore/StorageBackend split. */\nexport type StorageBackend<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n /** Returns live (non-expired) record count for the table. */\n count<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<number>;\n dispose?(): Promise<void>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n /**\n * Optional: fetch all live primary keys without materialising full records.\n * When present, `keys()` uses this instead of `getAll()` + key extraction.\n * For tables with TTL, implementations may still fall back to `getAll()` to\n * filter expired keys accurately.\n */\n getAllKeys?<T extends K>(table: T): Promise<KeyOf<S, T>[]>;\n /**\n * Optional secondary-index range fetch. When present, `query()` activates `getIndexRange` in\n * the QueryContext so that a leading `equals`, `between`, or `startsWith` on an indexed field\n * uses an IDB index instead of a full-table scan.\n */\n getByIndexRange?<T extends K>(table: T, field: string, range: NativeRange): Promise<RecordOf<S, T>[]>;\n /**\n * Optional primary-key range fetch for push-down queries. When present, `query()` activates\n * `getRange` in the QueryContext so that a leading `equals`, `between`, or `startsWith` on the\n * key field avoids a full-table scan. Falls back to `getAll` when absent.\n */\n getByKeyRange?<T extends K>(table: T, range: NativeRange): Promise<RecordOf<S, T>[]>;\n /**\n * Optional: fetch multiple records by key in a single operation. Preserves key order; missing keys yield\n * `undefined`. Falls back to N individual `get` calls when absent.\n */\n getMany?<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n /** Raw record count including TTL-expired entries. Used only for debug(). */\n getRawCount?<T extends K>(table: T): Promise<number>;\n has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n /**\n * Optional: prune all expired records across all tables in a single atomic operation.\n * When present, `pruneExpired()` delegates here instead of calling `pruneExpiredInTable` N times.\n */\n pruneAllExpired?(): Promise<Record<string, number>>;\n pruneExpiredInTable<T extends K>(table: T): Promise<number>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: TtlMs): Promise<void>;\n putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: TtlMs): Promise<void>;\n};\n\n/** @internal */\nexport type BatchDeps<S extends AnySchema> = {\n notifyMutation: (table: keyof S & string) => void;\n validate: <K extends keyof S & string>(table: K, value: RecordOf<S, K>) => RecordOf<S, K>;\n};\n\n/** @internal */\nexport type BatchImpl<S extends AnySchema> = <K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n) => Promise<R>;\n\n/* -------------------- Helpers -------------------- */\n\nconst getTimestamp: () => number = typeof performance !== 'undefined' ? () => performance.now() : () => Date.now();\n\nfunction resolveTtl<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n ttl?: TtlMs,\n): TtlMs | undefined {\n if (ttl !== undefined) assertTtlMs(ttl, 'put/putAll');\n\n return ttl ?? schema[table].defaultTtl;\n}\n\nfunction verifyKey<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n expected: KeyOf<S, K>,\n value: RecordOf<S, K>,\n op: string,\n): void {\n const actual = getRecordKey(schema, table, value);\n\n if (actual !== expected) {\n throw new VaultError(\n `${op}: key field \"${schema[table].key}\" must be \"${String(expected)}\" but got \"${String(actual)}\" in table \"${table}\"`,\n );\n }\n}\n\nfunction getManyWithFallback<S extends AnySchema, K extends keyof S & string>(\n core: Pick<StorageBackend<S, K>, 'get' | 'getMany'>,\n table: K,\n keys: KeyOf<S, K>[],\n): Promise<Array<RecordOf<S, K> | undefined>> {\n if (core.getMany) return core.getMany(table, keys);\n\n return Promise.all(keys.map((k) => core.get(table, k)));\n}\n\nfunction buildQueryCtx<S extends AnySchema, K extends keyof S & string>(\n table: K,\n core: Pick<StorageBackend<S, K>, 'deleteMany' | 'getAll' | 'getByIndexRange' | 'getByKeyRange'>,\n schema: S,\n onMutate: (t: K) => void,\n): QueryContext<RecordOf<S, K>> {\n const entry = schema[table];\n const keyField = entry.key;\n const indexedFields = entry.indexes ? new Set(entry.indexes) : undefined;\n\n const deleteManyFn = async (records: RecordOf<S, K>[]): Promise<number> => {\n if (records.length === 0) return 0;\n\n const keys = records.map((r) => getRecordKey(schema, table, r));\n const deleted = await core.deleteMany(table, keys);\n\n if (deleted > 0) onMutate(table);\n\n return deleted;\n };\n\n return {\n deleteMany: deleteManyFn,\n getIndexRange: core.getByIndexRange\n ? (field, range) => core.getByIndexRange!(table, field, range) as Promise<RecordOf<S, K>[]>\n : undefined,\n getRange: core.getByKeyRange\n ? (range) => core.getByKeyRange!(table, range) as Promise<RecordOf<S, K>[]>\n : undefined,\n indexedFields,\n keyField,\n source: () => core.getAll(table),\n };\n}\n\n/* -------------------- buildTxContext -------------------- */\n\nexport function buildTxContext<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n core: StorageBackend<S, K>,\n onMutate: (table: K) => void,\n validate?: <T extends K>(table: T, value: RecordOf<S, T>) => RecordOf<S, T>,\n scope?: ReadonlySet<string>,\n): TransactionContext<S, K> {\n const applyValidation = validate ?? ((_: K, v: RecordOf<S, K>) => v);\n\n const checkScope = scope\n ? (t: K): void => {\n if (!scope.has(t)) {\n throw new VaultScopeError(`table \"${t}\" is not part of this batch scope`);\n }\n }\n : (_t: K): void => {};\n\n return {\n async clear(table) {\n checkScope(table);\n\n const live = await core.count(table);\n\n if (live === 0) return;\n\n await core.clear(table);\n onMutate(table);\n },\n async count(table) {\n checkScope(table);\n\n return core.count(table);\n },\n async delete(table, key) {\n checkScope(table);\n\n const deleted = await core.delete(table, key);\n\n if (deleted) onMutate(table);\n\n return deleted;\n },\n async deleteMany(table, keys) {\n checkScope(table);\n\n const deleted = await core.deleteMany(table, keys);\n\n if (deleted > 0) onMutate(table);\n\n return deleted;\n },\n async entries(table) {\n checkScope(table);\n\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.map((r) => [(r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>, r]);\n },\n async get(table, key) {\n checkScope(table);\n\n return core.get(table, key);\n },\n async getAll(table) {\n checkScope(table);\n\n return core.getAll(table);\n },\n async getMany(table, keys) {\n checkScope(table);\n\n return getManyWithFallback(core, table, keys);\n },\n async getOrDefault(table, key, defaultFn, ttl) {\n checkScope(table);\n\n const existing = await core.get(table, key);\n\n if (existing !== undefined) return existing;\n\n const value = defaultFn();\n\n verifyKey(schema, table, key, value, 'getOrDefault: defaultFn()');\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return value;\n },\n async has(table, key) {\n checkScope(table);\n\n return core.has(table, key);\n },\n async isEmpty(table) {\n checkScope(table);\n\n return (await core.count(table)) === 0;\n },\n async keys(table, filter) {\n checkScope(table);\n\n if (filter) {\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.filter(filter).map((r) => (r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n }\n\n // R1: prefer native getAllKeys when the backend supports it (e.g. IDB store.getAllKeys).\n if (core.getAllKeys) {\n return core.getAllKeys(table);\n }\n\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.map((r) => (r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n },\n async put(table, value, ttl) {\n checkScope(table);\n\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n },\n async putAll(table, values, ttl) {\n checkScope(table);\n\n if (values.length === 0) return;\n\n const toWrite = values.map((v) => applyValidation(table, v));\n\n await core.putAll(table, toWrite, resolveTtl(schema, table, ttl));\n onMutate(table);\n },\n query(table) {\n checkScope(table);\n\n return createQueryBuilder(buildQueryCtx(table, core, schema, onMutate));\n },\n async update(table, key, changes, ttl) {\n checkScope(table);\n\n const current = await core.get(table, key);\n\n if (!current) return undefined;\n\n const merged = { ...current, ...changes } as RecordOf<S, typeof table>;\n\n verifyKey(schema, table, key, merged, 'update');\n await core.put(table, applyValidation(table, merged), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return merged;\n },\n async upsert(table, key, fn, ttl) {\n checkScope(table);\n\n const existing = await core.get(table, key);\n const value = fn(existing);\n\n verifyKey(schema, table, key, value, 'upsert: fn()');\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return value;\n },\n };\n}\n\n/* -------------------- buildAdapterOps -------------------- */\n\nexport function buildAdapterOps<S extends AnySchema>(\n schema: S,\n core: StorageBackend<S>,\n options?: BaseAdapterOptions<S> & {\n buildBatch?: (deps: BatchDeps<S>) => BatchImpl<S>;\n onCrossTabMessage?: (notify: (table: keyof S & string) => void) => (() => void) | undefined;\n onMutation?: (table: keyof S & string) => void;\n },\n): Adapter<S> {\n const { logger, onMetrics, signals, validators } = options ?? {};\n\n const observers = createObserverHub<S>(\n (table) => core.getAll(table),\n logger\n ? (err) =>\n logger.error(err instanceof Error ? err : new Error(String(err)), '[vault] observer notification failed')\n : undefined,\n );\n\n // Per-table live-count cache. Populated lazily on first count() call.\n // Invalidated on every mutation via notifyMutation.\n const countCache = new Map<string, number>();\n\n const getCachedCount = async (table: keyof S & string): Promise<number> => {\n if (countCache.has(table)) return countCache.get(table)!;\n\n const n = await core.count(table);\n\n countCache.set(table, n);\n\n return n;\n };\n\n const notifyMutation = (table: keyof S & string): void => {\n countCache.delete(table); // invalidate on any mutation\n observers.notify(table);\n options?.onMutation?.(table);\n };\n\n // Cross-tab notifications must NOT call onMutation (which would re-publish to BroadcastChannel,\n // creating an infinite loop). They only need to invalidate the count cache and notify observers.\n const notifyExternal = (table: keyof S & string): void => {\n countCache.delete(table);\n observers.notify(table);\n };\n\n // R6: Resolve optional backend capabilities once at construction — no per-call checks.\n const pruneAll = core.pruneAllExpired?.bind(core);\n const rawCountFn = core.getRawCount?.bind(core);\n\n const disconnectExternal = options?.onCrossTabMessage?.(notifyExternal) ?? undefined;\n\n if (signals) {\n for (const [tableName, signal] of Object.entries(signals)) {\n if (signal) {\n observers.observe(tableName as keyof S & string, (records) => {\n signal.update(() => records as RecordOf<S, keyof S>[]);\n });\n }\n }\n }\n\n const validate = <K extends keyof S & string>(table: K, value: RecordOf<S, K>): RecordOf<S, K> => {\n const validator = validators?.[table];\n\n if (!validator) return value;\n\n try {\n return validator.parse(value) as RecordOf<S, K>;\n } catch (err) {\n throw new VaultError(`validation failed for table \"${table}\"`, { cause: err });\n }\n };\n\n /* Timed wrapper — only wraps when onMetrics is present, otherwise zero overhead. */\n const timed = <T>(table: string, op: MetricsEvent['operation'], fn: () => Promise<T>): Promise<T> => {\n if (!onMetrics) return fn();\n\n const start = getTimestamp();\n\n return fn().finally(() => onMetrics({ duration: getTimestamp() - start, operation: op, table }));\n };\n\n const deferredBatch = async <K extends keyof S & string, R>(\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n scope: ReadonlySet<string>,\n ): Promise<R> => {\n const dirty = new Set<K>();\n const tx = buildTxContext<S, K>(schema, core as StorageBackend<S, K>, (t) => dirty.add(t), validate, scope);\n const result = await fn(tx);\n\n for (const t of dirty) {\n notifyMutation(t);\n }\n\n return result;\n };\n\n const nativeBatch = options?.buildBatch?.({ notifyMutation, validate });\n\n let warnedNonAtomic = false;\n\n const txCtx = buildTxContext<S, keyof S & string>(schema, core, notifyMutation, validate);\n\n const observeMany = createObserveMany<S>(observers);\n\n const disposeController = new AbortController();\n let disposed = false;\n\n const checkDisposed = (): void => {\n if (disposed) throw new VaultDisposedError();\n };\n\n const adapter: Adapter<S> = {\n async batch<K extends keyof S & string, R>(tables: readonly K[], fn: (tx: TransactionContext<S, K>) => Promise<R>) {\n checkDisposed();\n\n if (tables.length === 0) throw new VaultScopeError('batch requires at least one table');\n\n if (!nativeBatch && !warnedNonAtomic) {\n warnedNonAtomic = true;\n warn(\n 'batch() on this adapter is not atomic — concurrent mutations may interleave. Use createIndexedDB for atomic batches.',\n );\n }\n\n return timed('*', 'batch', () => (nativeBatch ? nativeBatch(tables, fn) : deferredBatch(fn, new Set(tables))));\n },\n\n async clear(table) {\n checkDisposed();\n await timed(table, 'clear', () => txCtx.clear(table));\n countCache.set(table, 0); // we know count is 0 after clear\n },\n\n async count(table) {\n checkDisposed();\n\n return timed(table, 'count', () => getCachedCount(table));\n },\n\n async debug() {\n checkDisposed();\n\n const tableNames = Object.keys(schema) as Array<keyof S & string>;\n const entries = await Promise.all(\n tableNames.map(async (name) => {\n // getRawCount must be called before core.count() because count() has\n // lazy-eviction side effects (deletes expired entries from the store).\n const raw = rawCountFn ? await rawCountFn(name) : undefined;\n const live = await core.count(name);\n\n // Warm the count cache so subsequent adapter.count() calls don't re-hit the backend.\n countCache.set(name, live);\n\n const expiredCount = raw !== undefined ? Math.max(0, raw - live) : 0;\n\n return { expiredCount, name, recordCount: live };\n }),\n );\n\n return { tables: entries } as DebugInfo<S>;\n },\n\n async delete(table, key) {\n checkDisposed();\n\n return timed(table, 'delete', () => txCtx.delete(table, key));\n // count cache invalidated by notifyMutation inside txCtx.delete\n },\n\n async deleteMany(table, keys) {\n checkDisposed();\n\n return timed(table, 'deleteMany', () => txCtx.deleteMany(table, keys));\n // count cache invalidated by notifyMutation inside txCtx.deleteMany\n },\n\n get disposalSignal(): AbortSignal {\n return disposeController.signal;\n },\n\n async dispose() {\n if (disposed) return;\n\n disposed = true;\n disposeController.abort();\n disconnectExternal?.();\n observers.dispose();\n await core.dispose?.();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n async entries(table) {\n checkDisposed();\n\n return timed(table, 'entries', () => txCtx.entries(table));\n },\n\n async get(table, key) {\n checkDisposed();\n\n return timed(table, 'get', () => txCtx.get(table, key));\n },\n\n async getAll(table) {\n checkDisposed();\n\n return timed(table, 'getAll', () => txCtx.getAll(table));\n },\n\n async getMany(table, keys) {\n checkDisposed();\n\n return timed(table, 'getMany', () => txCtx.getMany(table, keys));\n },\n\n async getOrDefault(table, key, defaultFn, ttl) {\n checkDisposed();\n\n return timed(table, 'getOrDefault', () => txCtx.getOrDefault(table, key, defaultFn, ttl));\n },\n\n async has(table, key) {\n checkDisposed();\n\n return timed(table, 'has', () => txCtx.has(table, key));\n },\n\n async isEmpty(table) {\n checkDisposed();\n\n return timed(table, 'isEmpty', async () => (await getCachedCount(table)) === 0);\n },\n\n async keys(table, filter) {\n checkDisposed();\n\n return timed(table, 'keys', () => txCtx.keys(table, filter));\n },\n\n observe(table, listener, opts) {\n checkDisposed();\n\n return observers.observe(table, listener, opts);\n },\n\n observeMany: (tables, listener, opts) => {\n checkDisposed();\n\n return observeMany(tables, listener, opts);\n },\n\n async pruneExpired(tables?: readonly (keyof S & string)[]) {\n checkDisposed();\n\n const tableNames = tables ?? (Object.keys(schema) as Array<keyof S & string>);\n\n if (!tables && pruneAll) {\n const result = await pruneAll();\n\n for (const [name, count] of Object.entries(result)) {\n if (count > 0) countCache.delete(name);\n }\n\n return result as { [K in keyof S & string]: number };\n }\n\n const pairs = await Promise.all(\n tableNames.map(async (name) => {\n const pruned = await core.pruneExpiredInTable(name);\n\n if (pruned > 0) countCache.delete(name);\n\n return [name, pruned] as const;\n }),\n );\n\n return Object.fromEntries(pairs) as { [K in keyof S & string]: number };\n },\n\n async put(table, value, ttl) {\n checkDisposed();\n await timed(table, 'put', () => txCtx.put(table, value, ttl));\n // count cache invalidated via notifyMutation inside txCtx.put\n },\n\n async putAll(table, values, ttl) {\n checkDisposed();\n await timed(table, 'putAll', () => txCtx.putAll(table, values, ttl));\n // count cache invalidated via notifyMutation inside txCtx.putAll\n },\n\n query(table) {\n checkDisposed();\n\n const ctx = buildQueryCtx(table, core, schema, notifyMutation);\n\n if (onMetrics) {\n return createQueryBuilder({\n ...ctx,\n deleteMany: ctx.deleteMany\n ? (records) => timed(table, 'queryDelete', () => ctx.deleteMany!(records))\n : undefined,\n source: () => timed(table, 'query', () => core.getAll(table)),\n });\n }\n\n return createQueryBuilder(ctx);\n },\n\n async [Symbol.asyncDispose]() {\n await adapter.dispose();\n },\n\n async update(table, key, changes, ttl) {\n checkDisposed();\n\n return timed(table, 'update', () => txCtx.update(table, key, changes, ttl));\n },\n\n async upsert(table, key, fn, ttl) {\n checkDisposed();\n\n return timed(table, 'upsert', () => txCtx.upsert(table, key, fn, ttl));\n },\n\n watch(table, options) {\n checkDisposed();\n\n return createWatchIterable<RecordOf<S, typeof table>>(\n (listener) => observers.observe(table, listener),\n options?.mode ?? 'latest',\n options?.signal,\n );\n },\n };\n\n return adapter;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"adapter-core.js","names":[],"sources":["../src/adapter-core.ts"],"sourcesContent":["import type {\n AnySchema,\n BaseAdapterOptions,\n DebugInfo,\n IndexedDbVaultStore,\n KeyOf,\n MetricsEvent,\n RecordOf,\n TransactionContext,\n TtlMs,\n VaultStore,\n} from './types';\n\nimport { VaultDisposedError, VaultError, VaultScopeError } from './errors';\nimport { createObserverHub, getRecordKey } from './internal';\nimport { createQueryBuilder, type NativeRange, type QueryContext } from './query';\nimport { assertTtlMs } from './ttl';\n\n/* -------------------- Internal backend protocol -------------------- */\n\n/** @internal Full backend protocol implemented by each adapter. A single flat interface — no StorageCore/StorageBackend split. */\nexport type StorageBackend<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n /** Returns live (non-expired) record count for the table. */\n count<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<number>;\n dispose?(): Promise<void>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n /**\n * Optional: fetch all live primary keys without materialising full records.\n * When present, `keys()` uses this instead of `getAll()` + key extraction.\n * For tables with TTL, implementations may still fall back to `getAll()` to\n * filter expired keys accurately.\n */\n getAllKeys?<T extends K>(table: T): Promise<KeyOf<S, T>[]>;\n /**\n * Optional secondary-index range fetch. When present, `query()` activates `getIndexRange` in\n * the QueryContext so that a leading `equals`, `between`, or `startsWith` on an indexed field\n * uses an IDB index instead of a full-table scan.\n */\n getByIndexRange?<T extends K>(table: T, field: string, range: NativeRange): Promise<RecordOf<S, T>[]>;\n /**\n * Optional primary-key range fetch for push-down queries. When present, `query()` activates\n * `getRange` in the QueryContext so that a leading `equals`, `between`, or `startsWith` on the\n * key field avoids a full-table scan. Falls back to `getAll` when absent.\n */\n getByKeyRange?<T extends K>(table: T, range: NativeRange): Promise<RecordOf<S, T>[]>;\n /**\n * Optional: fetch multiple records by key in a single operation. Preserves key order; missing keys yield\n * `undefined`. Falls back to N individual `get` calls when absent.\n */\n getMany?<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n /** Raw record count including TTL-expired entries. Used only for debug(). */\n getRawCount?<T extends K>(table: T): Promise<number>;\n has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n /**\n * Optional: prune all expired records across all tables in a single atomic operation.\n * When present, `pruneExpired()` delegates here instead of calling `pruneExpiredInTable` N times.\n */\n pruneAllExpired?(): Promise<Record<string, number>>;\n pruneExpiredInTable<T extends K>(table: T): Promise<number>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: TtlMs): Promise<void>;\n putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: TtlMs): Promise<void>;\n};\n\n/** @internal */\nexport type BatchDeps<S extends AnySchema> = {\n notifyMutation: (table: keyof S & string) => void;\n validate: <K extends keyof S & string>(table: K, value: RecordOf<S, K>) => RecordOf<S, K>;\n};\n\n/** @internal */\nexport type BatchImpl<S extends AnySchema> = <K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n) => Promise<R>;\n\n/* -------------------- Helpers -------------------- */\n\nconst getTimestamp: () => number = typeof performance !== 'undefined' ? () => performance.now() : () => Date.now();\n\nfunction resolveTtl<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n ttl?: TtlMs,\n): TtlMs | undefined {\n if (ttl !== undefined) assertTtlMs(ttl, 'put/putAll');\n\n return ttl ?? schema[table].defaultTtl;\n}\n\nfunction verifyKey<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n expected: KeyOf<S, K>,\n value: RecordOf<S, K>,\n op: string,\n): void {\n const actual = getRecordKey(schema, table, value);\n\n if (actual !== expected) {\n throw new VaultError(\n `${op}: key field \"${schema[table].key}\" must be \"${String(expected)}\" but got \"${String(actual)}\" in table \"${table}\"`,\n );\n }\n}\n\nfunction getManyWithFallback<S extends AnySchema, K extends keyof S & string>(\n core: Pick<StorageBackend<S, K>, 'get' | 'getMany'>,\n table: K,\n keys: KeyOf<S, K>[],\n): Promise<Array<RecordOf<S, K> | undefined>> {\n if (core.getMany) return core.getMany(table, keys);\n\n return Promise.all(keys.map((k) => core.get(table, k)));\n}\n\nfunction buildQueryCtx<S extends AnySchema, K extends keyof S & string>(\n table: K,\n core: Pick<StorageBackend<S, K>, 'deleteMany' | 'getAll' | 'getByIndexRange' | 'getByKeyRange'>,\n schema: S,\n onMutate: (t: K) => void,\n): QueryContext<RecordOf<S, K>> {\n const entry = schema[table];\n const keyField = entry.key;\n const indexedFields = entry.indexes ? new Set(entry.indexes) : undefined;\n\n const deleteManyFn = async (records: RecordOf<S, K>[]): Promise<number> => {\n if (records.length === 0) return 0;\n\n const keys = records.map((r) => getRecordKey(schema, table, r));\n const deleted = await core.deleteMany(table, keys);\n\n if (deleted > 0) onMutate(table);\n\n return deleted;\n };\n\n return {\n deleteMany: deleteManyFn,\n getIndexRange: core.getByIndexRange\n ? (field, range) => core.getByIndexRange!(table, field, range) as Promise<RecordOf<S, K>[]>\n : undefined,\n getRange: core.getByKeyRange\n ? (range) => core.getByKeyRange!(table, range) as Promise<RecordOf<S, K>[]>\n : undefined,\n indexedFields,\n keyField,\n source: () => core.getAll(table),\n };\n}\n\n/* -------------------- buildTxContext -------------------- */\n\nexport function buildTxContext<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n core: StorageBackend<S, K>,\n onMutate: (table: K) => void,\n validate?: <T extends K>(table: T, value: RecordOf<S, T>) => RecordOf<S, T>,\n scope?: ReadonlySet<string>,\n): TransactionContext<S, K> {\n const applyValidation = validate ?? ((_: K, v: RecordOf<S, K>) => v);\n\n const checkScope = scope\n ? (t: K): void => {\n if (!scope.has(t)) {\n throw new VaultScopeError(`table \"${t}\" is not part of this batch scope`);\n }\n }\n : (_t: K): void => {};\n\n return {\n async clear(table) {\n checkScope(table);\n\n const live = await core.count(table);\n\n await core.clear(table);\n\n if (live > 0) onMutate(table);\n },\n async count(table) {\n checkScope(table);\n\n return core.count(table);\n },\n async delete(table, key) {\n checkScope(table);\n\n const deleted = await core.delete(table, key);\n\n if (deleted) onMutate(table);\n\n return deleted;\n },\n async deleteMany(table, keys) {\n checkScope(table);\n\n const deleted = await core.deleteMany(table, keys);\n\n if (deleted > 0) onMutate(table);\n\n return deleted;\n },\n async entries(table) {\n checkScope(table);\n\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.map((r) => [(r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>, r]);\n },\n async get(table, key) {\n checkScope(table);\n\n return core.get(table, key);\n },\n async getAll(table) {\n checkScope(table);\n\n return core.getAll(table);\n },\n async getMany(table, keys) {\n checkScope(table);\n\n return getManyWithFallback(core, table, keys);\n },\n async getOrDefault(table, key, defaultFn, ttl) {\n checkScope(table);\n\n const existing = await core.get(table, key);\n\n if (existing !== undefined) return existing;\n\n const value = defaultFn();\n\n verifyKey(schema, table, key, value, 'getOrDefault: defaultFn()');\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return value;\n },\n async has(table, key) {\n checkScope(table);\n\n return core.has(table, key);\n },\n async isEmpty(table) {\n checkScope(table);\n\n return (await core.count(table)) === 0;\n },\n async keys(table, filter) {\n checkScope(table);\n\n if (filter) {\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.filter(filter).map((r) => (r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n }\n\n // R1: prefer native getAllKeys when the backend supports it (e.g. IDB store.getAllKeys).\n if (core.getAllKeys) {\n return core.getAllKeys(table);\n }\n\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.map((r) => (r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n },\n async put(table, value, ttl) {\n checkScope(table);\n\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n },\n async putAll(table, values, ttl) {\n checkScope(table);\n\n if (values.length === 0) return;\n\n const toWrite = values.map((v) => applyValidation(table, v));\n\n await core.putAll(table, toWrite, resolveTtl(schema, table, ttl));\n onMutate(table);\n },\n query(table) {\n checkScope(table);\n\n return createQueryBuilder(buildQueryCtx(table, core, schema, onMutate));\n },\n async update(table, key, changes, ttl) {\n checkScope(table);\n\n const current = await core.get(table, key);\n\n if (!current) return undefined;\n\n const merged = { ...current, ...changes } as RecordOf<S, typeof table>;\n\n verifyKey(schema, table, key, merged, 'update');\n await core.put(table, applyValidation(table, merged), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return merged;\n },\n async upsert(table, key, fn, ttl) {\n checkScope(table);\n\n const existing = await core.get(table, key);\n const value = fn(existing);\n\n verifyKey(schema, table, key, value, 'upsert: fn()');\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return value;\n },\n };\n}\n\n/* -------------------- buildAdapterOps -------------------- */\n\n/** Builds the portable surface first; IndexedDB opts into transactions at its factory boundary. */\nexport function buildAdapterOps<S extends AnySchema>(\n schema: S,\n core: StorageBackend<S>,\n options?: BaseAdapterOptions<S> & {\n onCrossTabMessage?: (notify: (table: keyof S & string) => void) => (() => void) | undefined;\n onMutation?: (table: keyof S & string) => void;\n onTransactions?: (deps: BatchDeps<S>) => void;\n },\n): VaultStore<S> {\n const { logger, onMetrics, validators } = options ?? {};\n\n const observers = createObserverHub<S>(\n (table) => core.getAll(table),\n logger\n ? (err) =>\n logger.error(err instanceof Error ? err : new Error(String(err)), '[vault] observer notification failed')\n : undefined,\n );\n\n // Per-table live-count cache. Populated lazily on first count() call.\n // Invalidated on every mutation via notifyMutation.\n const countCache = new Map<string, number>();\n\n const getCachedCount = async (table: keyof S & string): Promise<number> => {\n if (countCache.has(table)) return countCache.get(table)!;\n\n const n = await core.count(table);\n\n countCache.set(table, n);\n\n return n;\n };\n\n const notifyMutation = (table: keyof S & string): void => {\n countCache.delete(table); // invalidate on any mutation\n observers.notify(table);\n options?.onMutation?.(table);\n };\n\n // Cross-tab notifications must NOT call onMutation (which would re-publish to BroadcastChannel,\n // creating an infinite loop). They only need to invalidate the count cache and notify observers.\n const notifyExternal = (table: keyof S & string): void => {\n countCache.delete(table);\n observers.notify(table);\n };\n\n // R6: Resolve optional backend capabilities once at construction — no per-call checks.\n const pruneAll = core.pruneAllExpired?.bind(core);\n const rawCountFn = core.getRawCount?.bind(core);\n\n const disconnectExternal = options?.onCrossTabMessage?.(notifyExternal) ?? undefined;\n\n const validate = <K extends keyof S & string>(table: K, value: RecordOf<S, K>): RecordOf<S, K> => {\n const validator = validators?.[table];\n\n if (!validator) return value;\n\n try {\n return validator.parse(value) as RecordOf<S, K>;\n } catch (err) {\n throw new VaultError(`validation failed for table \"${table}\"`, { cause: err });\n }\n };\n\n /* Timed wrapper — only wraps when onMetrics is present, otherwise zero overhead. */\n const timed = <T>(table: string, op: MetricsEvent['operation'], fn: () => Promise<T>): Promise<T> => {\n if (!onMetrics) return fn();\n\n const start = getTimestamp();\n\n return fn().finally(() => onMetrics({ duration: getTimestamp() - start, operation: op, table }));\n };\n\n options?.onTransactions?.({ notifyMutation, validate });\n\n const txCtx = buildTxContext<S, keyof S & string>(schema, core, notifyMutation, validate);\n\n const disposeController = new AbortController();\n let disposed = false;\n\n const checkDisposed = (): void => {\n if (disposed) throw new VaultDisposedError();\n };\n\n const adapter: VaultStore<S> = {\n async clear(table) {\n checkDisposed();\n await timed(table, 'clear', () => txCtx.clear(table));\n countCache.set(table, 0); // we know count is 0 after clear\n },\n\n async count(table) {\n checkDisposed();\n\n return timed(table, 'count', () => getCachedCount(table));\n },\n\n async debug() {\n checkDisposed();\n\n const tableNames = Object.keys(schema) as Array<keyof S & string>;\n const entries = await Promise.all(\n tableNames.map(async (name) => {\n // getRawCount must be called before core.count() because count() has\n // lazy-eviction side effects (deletes expired entries from the store).\n const raw = rawCountFn ? await rawCountFn(name) : undefined;\n const live = await core.count(name);\n\n // Warm the count cache so subsequent adapter.count() calls don't re-hit the backend.\n countCache.set(name, live);\n\n const expiredCount = raw !== undefined ? Math.max(0, raw - live) : 0;\n\n return { expiredCount, name, recordCount: live };\n }),\n );\n\n return { tables: entries } as DebugInfo<S>;\n },\n\n async delete(table, key) {\n checkDisposed();\n\n return timed(table, 'delete', () => txCtx.delete(table, key));\n // count cache invalidated by notifyMutation inside txCtx.delete\n },\n\n async deleteMany(table, keys) {\n checkDisposed();\n\n return timed(table, 'deleteMany', () => txCtx.deleteMany(table, keys));\n // count cache invalidated by notifyMutation inside txCtx.deleteMany\n },\n\n get disposalSignal(): AbortSignal {\n return disposeController.signal;\n },\n\n async dispose() {\n if (disposed) return;\n\n disposed = true;\n disposeController.abort();\n disconnectExternal?.();\n observers.dispose();\n await core.dispose?.();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n async entries(table) {\n checkDisposed();\n\n return timed(table, 'entries', () => txCtx.entries(table));\n },\n\n async get(table, key) {\n checkDisposed();\n\n return timed(table, 'get', () => txCtx.get(table, key));\n },\n\n async getAll(table) {\n checkDisposed();\n\n return timed(table, 'getAll', () => txCtx.getAll(table));\n },\n\n async getMany(table, keys) {\n checkDisposed();\n\n return timed(table, 'getMany', () => txCtx.getMany(table, keys));\n },\n\n async getOrDefault(table, key, defaultFn, ttl) {\n checkDisposed();\n\n return timed(table, 'getOrDefault', () => txCtx.getOrDefault(table, key, defaultFn, ttl));\n },\n\n async has(table, key) {\n checkDisposed();\n\n return timed(table, 'has', () => txCtx.has(table, key));\n },\n\n async isEmpty(table) {\n checkDisposed();\n\n return timed(table, 'isEmpty', async () => (await getCachedCount(table)) === 0);\n },\n\n async keys(table, filter) {\n checkDisposed();\n\n return timed(table, 'keys', () => txCtx.keys(table, filter));\n },\n\n observe(table, listener, opts) {\n checkDisposed();\n\n return observers.observe(table, listener, opts);\n },\n\n async pruneExpired(tables?: readonly (keyof S & string)[]) {\n checkDisposed();\n\n const tableNames = tables ?? (Object.keys(schema) as Array<keyof S & string>);\n\n if (!tables && pruneAll) {\n const result = await pruneAll();\n\n for (const [name, count] of Object.entries(result)) {\n if (count > 0) countCache.delete(name);\n }\n\n return result as { [K in keyof S & string]: number };\n }\n\n const pairs = await Promise.all(\n tableNames.map(async (name) => {\n const pruned = await core.pruneExpiredInTable(name);\n\n if (pruned > 0) countCache.delete(name);\n\n return [name, pruned] as const;\n }),\n );\n\n return Object.fromEntries(pairs) as { [K in keyof S & string]: number };\n },\n\n async put(table, value, ttl) {\n checkDisposed();\n await timed(table, 'put', () => txCtx.put(table, value, ttl));\n // count cache invalidated via notifyMutation inside txCtx.put\n },\n\n async putAll(table, values, ttl) {\n checkDisposed();\n await timed(table, 'putAll', () => txCtx.putAll(table, values, ttl));\n // count cache invalidated via notifyMutation inside txCtx.putAll\n },\n\n query(table) {\n checkDisposed();\n\n const ctx = buildQueryCtx(table, core, schema, notifyMutation);\n\n if (onMetrics) {\n return createQueryBuilder({\n ...ctx,\n deleteMany: ctx.deleteMany\n ? (records) => timed(table, 'queryDelete', () => ctx.deleteMany!(records))\n : undefined,\n source: () => timed(table, 'query', () => core.getAll(table)),\n });\n }\n\n return createQueryBuilder(ctx);\n },\n\n async [Symbol.asyncDispose]() {\n await adapter.dispose();\n },\n\n async update(table, key, changes, ttl) {\n checkDisposed();\n\n return timed(table, 'update', () => txCtx.update(table, key, changes, ttl));\n },\n\n async upsert(table, key, fn, ttl) {\n checkDisposed();\n\n return timed(table, 'upsert', () => txCtx.upsert(table, key, fn, ttl));\n },\n };\n\n return adapter;\n}\n\n/** IndexedDB is the only backend that can bind this callback to one native transaction. */\nexport function withIndexedDbTransactions<S extends AnySchema>(\n store: VaultStore<S>,\n batch: BatchImpl<S>,\n): IndexedDbVaultStore<S> {\n return Object.assign(store, { batch }) as IndexedDbVaultStore<S>;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../errors.cjs"),t=require("../internal.cjs"),n=require("../ttl.cjs"),r=require("../adapter-core.cjs");function i(t){return new Promise((n,r)=>{t.onsuccess=()=>n(t.result),t.onerror=()=>r(t.error??new e.VaultError(`IndexedDB request failed`))})}function a(t,n,r){return new e.VaultError(`${n} on "${t}"${r instanceof Error&&r.message?`: ${r.message}`:``}`,{cause:r})}function o(e,t,n){return new Promise((r,i)=>{let o,s;Promise.resolve().then(n).then(e=>{o=e}).catch(t=>{s=t;try{e.abort()}catch{}});let c=(e,n=`transaction failed`)=>{s instanceof Error?i(s):i(a(t,n,s??e))};e.oncomplete=()=>{if(s){c(void 0);return}r(o)},e.onerror=()=>i(a(t,`transaction error`,e.error)),e.onabort=()=>c(e.error,`transaction aborted`)})}async function s(e,t){let n=await i(e.getAll()),r=[];for(let e of n){let n=t(e);n!==void 0&&r.push(n)}return r}async function c(e,t,n,r){let a=e.index(t),o=n.type===`eq`?IDBKeyRange.only(n.value):n.type===`between`?IDBKeyRange.bound(n.lower,n.upper):IDBKeyRange.bound(n.prefix,n.prefix+`￿`),s=await i(a.getAll(o)),c=[];for(let e of s){let t=r(e);t!==void 0&&c.push(t)}return c}async function l(e,t,n){if(t.type===`eq`){let r=await u(e,t.value,n);return r===void 0?[]:[r]}let r=t.type===`between`?IDBKeyRange.bound(t.lower,t.upper):IDBKeyRange.bound(t.prefix,t.prefix+`￿`),a=await i(e.getAll(r)),o=[];for(let e of a){let t=n(e);t!==void 0&&o.push(t)}return o}async function u(e,t,n){let r=await i(e.get(t));if(r!=null)return n(r)}async function d(e,t,n){return await u(e,t,n)!==void 0}async function f(e,t,n){let r=await d(e,t,n);return await i(e.delete(t)),r}async function p(e,t,n){return t.length===0?0:(await Promise.all(t.map(t=>f(e,t,n)))).filter(Boolean).length}async function m(e,t,n,r,a){await i(e.put(r(n,a),t))}function h(t,r){return new Promise((i,a)=>{let o=0,s=t.openCursor();s.onerror=()=>a(s.error??new e.VaultError(`IndexedDB cursor failed during prune`)),s.onsuccess=()=>{let e=s.result;if(!e){i(o);return}let t=r.decode(e.value);(!t||n.isExpired(t.expiresAt))&&(e.delete(),o+=1),e.continue()}})}function g(t,n){return{[Symbol.asyncIterator](){let r=t.openCursor(),i={type:`idle`},a=e=>{if(i.type===`waiting`){let{resolve:t}=i;i=e.done?{type:`done`}:{type:`idle`},t(e)}else i={result:e,type:`buffered`}};return r.onerror=()=>{let t=r.error??new e.VaultError(`IndexedDB cursor iteration failed`);if(i.type===`waiting`){let{reject:e}=i;i={type:`done`},e(t)}else i={error:t,type:`error`}},r.onsuccess=()=>{let e=r.result;if(!e){a({done:!0,value:void 0});return}let t=n(e.value);e.continue(),t!==void 0&&a({done:!1,value:t})},{next(){if(i.type===`error`){let{error:e}=i;return i={type:`done`},Promise.reject(e)}if(i.type===`buffered`){let{result:e}=i;return i=e.done?{type:`done`}:{type:`idle`},Promise.resolve(e)}return i.type===`done`?Promise.resolve({done:!0,value:void 0}):new Promise((e,t)=>{i={reject:t,resolve:e,type:`waiting`}})},return(e){return i.type===`waiting`&&i.resolve({done:!0,value:void 0}),i={type:`done`},Promise.resolve({done:!0,value:e})},throw(e){return i.type===`waiting`&&i.reject(e),i={type:`done`},Promise.reject(e)}}}}}function _(e,n,r,a){let o=e=>n.objectStore(e);return{clear:async e=>{await i(o(e).clear())},count:async e=>(await i(o(e).getAll())).filter(e=>r(e)!==void 0).length,delete:(e,t)=>f(o(e),t,r),deleteMany:(e,t)=>p(o(e),t,r),get:(e,t)=>u(o(e),t,r),getAll:e=>s(o(e),r),getByIndexRange:(e,t,n)=>c(o(e),t,n,r),getByKeyRange:(e,t)=>l(o(e),t,r),getMany:(e,t)=>Promise.all(t.map(t=>u(o(e),t,r))),has:(e,t)=>d(o(e),t,r),pruneExpiredInTable:e=>h(o(e),{decode:r,encode:a}),put(n,r,i){return m(o(n),t.getRecordKey(e,n,r),r,a,i)},putAll(n,r,i){return Promise.all(r.map(r=>m(o(n),t.getRecordKey(e,n,r),r,a,i))).then(()=>void 0)}}}function v(a){let{codec:v=n.defaultCodec,logger:y,migrate:b,name:x,onMetrics:S,schema:C,signals:w,validators:T,version:E=1}=a;if(!Number.isInteger(E)||E<1)throw new e.VaultError(`createIndexedDB: version must be a positive integer, got ${String(E)}`);let D=e=>{let t=v.decode(e);if(t&&!n.isExpired(t.expiresAt))return t.value},O=(e,t)=>{let n=t===void 0?void 0:Date.now()+t;return v.encode(e,n)},k=typeof BroadcastChannel<`u`?new BroadcastChannel(`vault:${x}`):void 0;!k&&y&&y.error(`[vault] BroadcastChannel unavailable — cross-tab sync disabled for "${x}"`);let A=null,j=null,M=!1,N=(e,t)=>{for(let[n,r]of Object.entries(C)){let i;i=e.objectStoreNames.contains(n)?t.objectStore(n):e.createObjectStore(n);let a=r.indexes??[];for(let e of a)i.indexNames.contains(e)||i.createIndex(e,`value.${e}`)}},P=async()=>(j||=new Promise((t,n)=>{let r=indexedDB.open(x,E);r.onupgradeneeded=t=>{let i=r.result,a=r.transaction;if(b)try{b({db:i,newVersion:t.newVersion??null,oldVersion:t.oldVersion,tx:a})}catch(t){try{a.abort()}catch{}n(new e.VaultMigrationError(`migration failed for "${x}"`,{cause:t}));return}N(i,a)},r.onsuccess=()=>{if(M){r.result.close(),t();return}let e=r.result;e.onversionchange=()=>{e.close(),A=null,j=null},A=e,t()},r.onerror=()=>{j=null,n(new e.VaultError(`failed to open "${x}"`,{cause:r.error}))}}),j),F=async(t,n,r)=>{if(M||(A||await P(),!A))throw new e.VaultDisposedError(`"${x}" is disposed`);let i=String(t),a=A.transaction(i,n);return o(a,`${x}/${i}`,()=>r(a.objectStore(i)))},I=async()=>{if(M||(A||await P(),!A))throw new e.VaultDisposedError(`"${x}" is disposed`);return A},L=e=>{k?.postMessage({table:String(e)})},R={clear:e=>F(e,`readwrite`,e=>i(e.clear()).then(()=>void 0)),count:e=>F(e,`readonly`,async e=>(await i(e.getAll())).filter(e=>D(e)!==void 0).length),delete:(e,t)=>F(e,`readwrite`,e=>f(e,t,D)),deleteMany:(e,t)=>t.length===0?Promise.resolve(0):F(e,`readwrite`,e=>p(e,t,D)),async dispose(){M=!0,k?.close(),j&&await j.catch(()=>{}),A?.close(),A=null,j=null},get:(e,t)=>F(e,`readonly`,e=>u(e,t,D)),getAll:e=>F(e,`readonly`,e=>s(e,D)),getAllKeys:e=>F(e,`readonly`,async t=>{let n=await s(t,D),r=C[e].key;return n.map(e=>e[r])}),getByIndexRange:(e,t,n)=>F(e,`readonly`,e=>c(e,t,n,D)),getByKeyRange:(e,t)=>F(e,`readonly`,e=>l(e,t,D)),getMany:(e,t)=>t.length===0?Promise.resolve([]):F(e,`readonly`,e=>Promise.all(t.map(t=>u(e,t,D)))),getRawCount:e=>F(e,`readonly`,e=>i(e.count())),has:(e,t)=>F(e,`readonly`,e=>d(e,t,D)),async pruneAllExpired(){let e=await I(),t=Object.keys(C),n=e.transaction(t,`readwrite`),r=await o(n,`${x}/pruneAll`,()=>Promise.all(t.map(async e=>[e,await h(n.objectStore(e),v)])));return Object.fromEntries(r)},pruneExpiredInTable:e=>F(e,`readwrite`,e=>h(e,v)),put(e,n,r){let i=t.getRecordKey(C,e,n);return F(e,`readwrite`,e=>m(e,i,n,O,r))},putAll(e,n,r){return F(e,`readwrite`,i=>Promise.all(n.map(n=>m(i,t.getRecordKey(C,e,n),n,O,r))).then(()=>void 0))}},z=async(e,t,n,i)=>{let a=(await I()).transaction([...e],`readwrite`),s=new Set,c=_(C,a,D,O),l=new Set(e),u=r.buildTxContext(C,c,e=>s.add(e),i,l),d=await o(a,x,()=>t(u));for(let e of s)n(e);return d};return{...r.buildAdapterOps(C,R,{buildBatch:({notifyMutation:e,validate:t})=>(n,r)=>z(n,r,e,t),logger:y,onCrossTabMessage(e){if(k)return k.onmessage=t=>{let n=t.data?.table;!n||!Object.hasOwn(C,n)||e(n)},()=>{k.onmessage=null}},onMetrics:S,onMutation:L,schema:C,signals:w,validators:T}),iterate(t){if(M)throw new e.VaultDisposedError(`"${x}" is disposed`);let n=async()=>{if(A||await P(),!A||M)throw new e.VaultDisposedError(`"${x}" is disposed`);return g(A.transaction(String(t),`readonly`).objectStore(String(t)),D)},r,i=()=>n().then(e=>(r=e[Symbol.asyncIterator](),r));return{[Symbol.asyncIterator](){return{next(){return r?r.next():i().then(e=>e.next())},return(e){return r?r.return?.(e)??Promise.resolve({done:!0,value:e}):Promise.resolve({done:!0,value:e})},throw(e){return r?r.throw?.(e)??Promise.reject(e):Promise.reject(e)}}}}}}}exports.createIndexedDB=v;
1
+ const e=require("../errors.cjs"),t=require("../internal.cjs"),n=require("../ttl.cjs"),r=require("../adapter-core.cjs");function i(t){return new Promise((n,r)=>{t.onsuccess=()=>n(t.result),t.onerror=()=>r(t.error??new e.VaultError(`IndexedDB request failed`))})}function a(t,n,r){let i=r instanceof Error&&r.message?`: ${r.message}`:``;return new e.VaultError(`${n} on "${t}"${i}`,{cause:r})}function o(e,t,n){return new Promise((r,i)=>{let o,s;Promise.resolve().then(n).then(e=>{o=e}).catch(t=>{s=t;try{e.abort()}catch{}});let c=(e,n=`transaction failed`)=>{s instanceof Error?i(s):i(a(t,n,s??e))};e.oncomplete=()=>{if(s){c(void 0);return}r(o)},e.onerror=()=>i(a(t,`transaction error`,e.error)),e.onabort=()=>c(e.error,`transaction aborted`)})}async function s(e,t){let n=await i(e.getAll()),r=[];for(let e of n){let n=t(e);n!==void 0&&r.push(n)}return r}async function c(e,t,n,r){let a=e.index(t),o=n.type===`eq`?IDBKeyRange.only(n.value):n.type===`between`?IDBKeyRange.bound(n.lower,n.upper):IDBKeyRange.bound(n.prefix,n.prefix+`￿`),s=await i(a.getAll(o)),c=[];for(let e of s){let t=r(e);t!==void 0&&c.push(t)}return c}async function l(e,t,n){let r=await i(e.get(t));if(r!=null)return n(r)}async function u(e,t,n){return await l(e,t,n)!==void 0}async function d(e,t,n){let r=await u(e,t,n);return await i(e.delete(t)),r}async function f(e,t,n){return t.length===0?0:(await Promise.all(t.map(t=>d(e,t,n)))).filter(Boolean).length}async function p(e,t,n,r,a){await i(e.put(r(n,a),t))}function m(t){return new Promise((r,i)=>{let a=0,o=t.openCursor();o.onerror=()=>i(o.error??new e.VaultError(`IndexedDB cursor failed during prune`)),o.onsuccess=()=>{let e=o.result;if(!e){r(a);return}let t=n.parseStored(e.value);(!t||n.isExpired(t.expiresAt))&&(e.delete(),a+=1),e.continue()}})}function h(t,n){return{[Symbol.asyncIterator](){let r=t.openCursor(),i={type:`idle`},a=e=>{if(i.type===`waiting`){let{resolve:t}=i;i=e.done?{type:`done`}:{type:`idle`},t(e)}else i={result:e,type:`buffered`}};return r.onerror=()=>{let t=r.error??new e.VaultError(`IndexedDB cursor iteration failed`);if(i.type===`waiting`){let{reject:e}=i;i={type:`done`},e(t)}else i={error:t,type:`error`}},r.onsuccess=()=>{let e=r.result;if(!e){a({done:!0,value:void 0});return}let t=n(e.value);e.continue(),t!==void 0&&a({done:!1,value:t})},{next(){if(i.type===`error`){let{error:e}=i;return i={type:`done`},Promise.reject(e)}if(i.type===`buffered`){let{result:e}=i;return i=e.done?{type:`done`}:{type:`idle`},Promise.resolve(e)}return i.type===`done`?Promise.resolve({done:!0,value:void 0}):new Promise((e,t)=>{i={reject:t,resolve:e,type:`waiting`}})},return(e){return i.type===`waiting`&&i.resolve({done:!0,value:void 0}),i={type:`done`},Promise.resolve({done:!0,value:e})},throw(e){return i.type===`waiting`&&i.reject(e),i={type:`done`},Promise.reject(e)}}}}}function g(e,n,r,a){let o=e=>n.objectStore(e);return{clear:async e=>{await i(o(e).clear())},count:async e=>(await i(o(e).getAll())).filter(e=>r(e)!==void 0).length,delete:(e,n)=>d(o(e),t.encodeVaultKey(n),r),deleteMany:(e,n)=>f(o(e),n.map(t.encodeVaultKey),r),get:(e,n)=>l(o(e),t.encodeVaultKey(n),r),getAll:e=>s(o(e),r),getByIndexRange:(e,t,n)=>c(o(e),t,n,r),getMany:(e,n)=>Promise.all(n.map(n=>l(o(e),t.encodeVaultKey(n),r))),has:(e,n)=>u(o(e),t.encodeVaultKey(n),r),pruneExpiredInTable:e=>m(o(e)),put(n,r,i){return p(o(n),t.encodeVaultKey(t.getRecordKey(e,n,r)),r,a,i)},putAll(n,r,i){return Promise.all(r.map(r=>p(o(n),t.encodeVaultKey(t.getRecordKey(e,n,r)),r,a,i))).then(()=>void 0)}}}function _(a){let{logger:_,migrate:v,name:y,onMetrics:b,schema:x,validators:S,version:C=1}=a;if(!Number.isInteger(C)||C<1)throw new e.VaultError(`createIndexedDB: version must be a positive integer, got ${String(C)}`);let w=e=>{let t=n.parseStored(e);return!t||n.isExpired(t.expiresAt)?void 0:t.value},T=(e,t)=>t===void 0?{value:e}:{expiresAt:Date.now()+t,value:e},E=typeof BroadcastChannel<`u`?new BroadcastChannel(`vault:${y}`):void 0;!E&&_&&_.error(`[vault] BroadcastChannel unavailable — cross-tab sync disabled for "${y}"`);let D=null,O=null,k=!1,A=(e,t)=>{for(let[n,r]of Object.entries(x)){let i;i=e.objectStoreNames.contains(n)?t.objectStore(n):e.createObjectStore(n);let a=r.indexes??[];for(let e of a)i.indexNames.contains(e)||i.createIndex(e,`value.${e}`)}},j=async()=>(O||=new Promise((t,n)=>{let r=indexedDB.open(y,C);r.onupgradeneeded=t=>{let i=r.result,a=r.transaction;if(v)try{v({db:i,newVersion:t.newVersion??null,oldVersion:t.oldVersion,tx:a})}catch(t){try{a.abort()}catch{}n(new e.VaultMigrationError(`migration failed for "${y}"`,{cause:t}));return}A(i,a)},r.onsuccess=()=>{if(k){r.result.close(),t();return}let e=r.result;e.onversionchange=()=>{e.close(),D=null,O=null},D=e,t()},r.onerror=()=>{O=null,n(new e.VaultError(`failed to open "${y}"`,{cause:r.error}))}}),O),M=async(t,n,r)=>{if(k||(D||await j(),!D))throw new e.VaultDisposedError(`"${y}" is disposed`);let i=String(t),a=D.transaction(i,n);return o(a,`${y}/${i}`,()=>r(a.objectStore(i)))},N=async()=>{if(k||(D||await j(),!D))throw new e.VaultDisposedError(`"${y}" is disposed`);return D},P=e=>{E?.postMessage({table:String(e)})},F={clear:e=>M(e,`readwrite`,e=>i(e.clear()).then(()=>void 0)),count:e=>M(e,`readonly`,async e=>(await i(e.getAll())).filter(e=>w(e)!==void 0).length),delete:(e,n)=>M(e,`readwrite`,e=>d(e,t.encodeVaultKey(n),w)),deleteMany:(e,n)=>n.length===0?Promise.resolve(0):M(e,`readwrite`,e=>f(e,n.map(t.encodeVaultKey),w)),async dispose(){k=!0,E?.close(),O&&await O.catch(()=>{}),D?.close(),D=null,O=null},get:(e,n)=>M(e,`readonly`,e=>l(e,t.encodeVaultKey(n),w)),getAll:e=>M(e,`readonly`,e=>s(e,w)),getAllKeys:e=>M(e,`readonly`,async t=>{let n=await s(t,w),r=x[e].key;return n.map(e=>e[r])}),getByIndexRange:(e,t,n)=>M(e,`readonly`,e=>c(e,t,n,w)),getMany:(e,n)=>n.length===0?Promise.resolve([]):M(e,`readonly`,e=>Promise.all(n.map(n=>l(e,t.encodeVaultKey(n),w)))),getRawCount:e=>M(e,`readonly`,e=>i(e.count())),has:(e,n)=>M(e,`readonly`,e=>u(e,t.encodeVaultKey(n),w)),async pruneAllExpired(){let e=await N(),t=Object.keys(x),n=e.transaction(t,`readwrite`),r=await o(n,`${y}/pruneAll`,()=>Promise.all(t.map(async e=>[e,await m(n.objectStore(e))])));return Object.fromEntries(r)},pruneExpiredInTable:e=>M(e,`readwrite`,e=>m(e)),put(e,n,r){let i=t.encodeVaultKey(t.getRecordKey(x,e,n));return M(e,`readwrite`,e=>p(e,i,n,T,r))},putAll(e,n,r){return M(e,`readwrite`,i=>Promise.all(n.map(n=>p(i,t.encodeVaultKey(t.getRecordKey(x,e,n)),n,T,r))).then(()=>void 0))}},I=async(e,t,n,i)=>{let a=(await N()).transaction([...e],`readwrite`),s=new Set,c=g(x,a,w,T),l=new Set(e),u=r.buildTxContext(x,c,e=>s.add(e),i,l),d=await o(a,y,()=>t(u));for(let e of s)n(e);return d},L,R={...r.buildAdapterOps(x,F,{logger:_,onCrossTabMessage(e){if(E)return E.onmessage=t=>{let n=t.data?.table;!n||!Object.hasOwn(x,n)||e(n)},()=>{E.onmessage=null}},onMetrics:b,onMutation:P,onTransactions:e=>{L=(t,n)=>I(t,n,e.notifyMutation,e.validate)},schema:x,validators:S}),iterate(t){if(k)throw new e.VaultDisposedError(`"${y}" is disposed`);let n=async()=>{if(D||await j(),!D||k)throw new e.VaultDisposedError(`"${y}" is disposed`);return h(D.transaction(String(t),`readonly`).objectStore(String(t)),w)},r,i=()=>n().then(e=>(r=e[Symbol.asyncIterator](),r));return{[Symbol.asyncIterator](){return{next(){return r?r.next():i().then(e=>e.next())},return(e){return r?r.return?.(e)??Promise.resolve({done:!0,value:e}):Promise.resolve({done:!0,value:e})},throw(e){return r?r.throw?.(e)??Promise.reject(e):Promise.reject(e)}}}}}};if(!L)throw new e.VaultError(`IndexedDB transaction capability was not initialized`);return r.withIndexedDbTransactions(R,L)}exports.createIndexedDB=_;
2
2
  //# sourceMappingURL=indexeddb.cjs.map