@noy-db/hub 0.2.0-pre.30 → 0.2.0-pre.31

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 (143) hide show
  1. package/dist/adapter/index.d.ts +9 -0
  2. package/dist/adapter/index.js +14 -0
  3. package/dist/attestation/index.d.ts +1 -1
  4. package/dist/attestation/index.js +3 -3
  5. package/dist/blobs/index.d.ts +3 -3
  6. package/dist/bundle/index.d.ts +3 -3
  7. package/dist/bundle/index.js +1 -1
  8. package/dist/{chunk-Y6YUWZTS.js → chunk-L5HHBOMS.js} +2 -2
  9. package/dist/{chunk-BVKLJBJJ.js → chunk-W5NVNJDX.js} +2 -1
  10. package/dist/{chunk-BVKLJBJJ.js.map → chunk-W5NVNJDX.js.map} +1 -1
  11. package/dist/consent/index.d.ts +2 -2
  12. package/dist/{decrypt-partition-Mhjh6nnG.d.ts → decrypt-partition-CXS5KopB.d.ts} +1 -1
  13. package/dist/derivations/index.d.ts +3 -3
  14. package/dist/{dev-unlock-DJ3IhgY9.d.ts → dev-unlock-CnHTTVea.d.ts} +1 -1
  15. package/dist/guards/index.d.ts +3 -3
  16. package/dist/{hash-DLwkYf1d.d.ts → hash-oc5paYl0.d.ts} +1 -1
  17. package/dist/history/index.d.ts +3 -3
  18. package/dist/i18n/index.d.ts +2 -2
  19. package/dist/{index-CMRIx_zx.d.ts → index-BmhGztUi.d.ts} +1 -1
  20. package/dist/index.d.ts +11 -11
  21. package/dist/index.js +2 -2
  22. package/dist/kernel/index.d.ts +2 -2
  23. package/dist/materialized-views/index.d.ts +3 -3
  24. package/dist/{mime-magic-CacDBwYp.d.ts → mime-magic-JeLKHRng.d.ts} +1 -1
  25. package/dist/{noydb-5MIBD77B.js → noydb-NAU2DTFP.js} +2 -2
  26. package/dist/noydb-NAU2DTFP.js.map +1 -0
  27. package/dist/overlay-views/index.d.ts +3 -3
  28. package/dist/periods/index.d.ts +2 -2
  29. package/dist/session/index.d.ts +3 -3
  30. package/dist/shadow/index.d.ts +2 -2
  31. package/dist/snapshots/index.d.ts +2 -2
  32. package/dist/store/index.d.ts +2 -2
  33. package/dist/sync/index.d.ts +1 -1
  34. package/dist/team/index.d.ts +2 -2
  35. package/dist/{transition-guard-J04-jime.d.ts → transition-guard-Dy3NioQr.d.ts} +1 -1
  36. package/dist/tx/index.d.ts +2 -2
  37. package/dist/{with-materialized-view-DNfzC5lH.d.ts → with-materialized-view-DIVeez0W.d.ts} +1 -1
  38. package/dist/{with-overlayed-view-qk3lbhOd.d.ts → with-overlayed-view-DVZrc5Hb.d.ts} +1 -1
  39. package/dist/{with-rollup-Dd3_ZG4b.d.ts → with-rollup-CbU-O4wP.d.ts} +1 -1
  40. package/package.json +62 -221
  41. package/dist/aggregate/index.cjs +0 -1144
  42. package/dist/aggregate/index.cjs.map +0 -1
  43. package/dist/aggregate/index.d.cts +0 -39
  44. package/dist/attestation/index.cjs +0 -305
  45. package/dist/attestation/index.cjs.map +0 -1
  46. package/dist/attestation/index.d.cts +0 -54
  47. package/dist/blobs/index.cjs +0 -1967
  48. package/dist/blobs/index.cjs.map +0 -1
  49. package/dist/blobs/index.d.cts +0 -48
  50. package/dist/bundle/index.cjs +0 -41045
  51. package/dist/bundle/index.cjs.map +0 -1
  52. package/dist/bundle/index.d.cts +0 -187
  53. package/dist/consent/index.cjs +0 -204
  54. package/dist/consent/index.cjs.map +0 -1
  55. package/dist/consent/index.d.cts +0 -27
  56. package/dist/crdt/index.cjs +0 -152
  57. package/dist/crdt/index.cjs.map +0 -1
  58. package/dist/crdt/index.d.cts +0 -30
  59. package/dist/decrypt-partition-C0iDpbSd.d.cts +0 -558
  60. package/dist/derivations/index.cjs +0 -469
  61. package/dist/derivations/index.cjs.map +0 -1
  62. package/dist/derivations/index.d.cts +0 -74
  63. package/dist/dev-unlock-0Z6yxfS7.d.cts +0 -263
  64. package/dist/discriminant-BN9REW3o.d.cts +0 -60
  65. package/dist/errors-BAWO5Z5a.d.cts +0 -1500
  66. package/dist/forget/index.cjs +0 -43
  67. package/dist/forget/index.cjs.map +0 -1
  68. package/dist/forget/index.d.cts +0 -1
  69. package/dist/guards/index.cjs +0 -455
  70. package/dist/guards/index.cjs.map +0 -1
  71. package/dist/guards/index.d.cts +0 -39
  72. package/dist/hash-Db8ncXGr.d.cts +0 -63
  73. package/dist/history/index.cjs +0 -1245
  74. package/dist/history/index.cjs.map +0 -1
  75. package/dist/history/index.d.cts +0 -65
  76. package/dist/i18n/index.cjs +0 -1280
  77. package/dist/i18n/index.cjs.map +0 -1
  78. package/dist/i18n/index.d.cts +0 -41
  79. package/dist/index-BMmajblo.d.cts +0 -362
  80. package/dist/index-C1SC1EPe.d.cts +0 -1325
  81. package/dist/index-xJEPkvMb.d.cts +0 -93
  82. package/dist/index.cjs +0 -48100
  83. package/dist/index.cjs.map +0 -1
  84. package/dist/index.d.cts +0 -1050
  85. package/dist/indexing/index.cjs +0 -803
  86. package/dist/indexing/index.cjs.map +0 -1
  87. package/dist/indexing/index.d.cts +0 -36
  88. package/dist/kernel/index.cjs +0 -751
  89. package/dist/kernel/index.cjs.map +0 -1
  90. package/dist/kernel/index.d.cts +0 -11
  91. package/dist/lazy-builder-eYZzLEL1.d.cts +0 -304
  92. package/dist/materialized-views/index.cjs +0 -1518
  93. package/dist/materialized-views/index.cjs.map +0 -1
  94. package/dist/materialized-views/index.d.cts +0 -187
  95. package/dist/mime-magic-sdMzsfVK.d.cts +0 -103
  96. package/dist/overlay-views/index.cjs +0 -399
  97. package/dist/overlay-views/index.cjs.map +0 -1
  98. package/dist/overlay-views/index.d.cts +0 -102
  99. package/dist/periods/index.cjs +0 -1041
  100. package/dist/periods/index.cjs.map +0 -1
  101. package/dist/periods/index.d.cts +0 -24
  102. package/dist/predicate-BmhBSPCH.d.cts +0 -267
  103. package/dist/query/index.cjs +0 -3480
  104. package/dist/query/index.cjs.map +0 -1
  105. package/dist/query/index.d.cts +0 -4
  106. package/dist/sealed-record/index.cjs +0 -139
  107. package/dist/sealed-record/index.cjs.map +0 -1
  108. package/dist/sealed-record/index.d.cts +0 -123
  109. package/dist/session/index.cjs +0 -495
  110. package/dist/session/index.cjs.map +0 -1
  111. package/dist/session/index.d.cts +0 -48
  112. package/dist/shadow/index.cjs +0 -133
  113. package/dist/shadow/index.cjs.map +0 -1
  114. package/dist/shadow/index.d.cts +0 -19
  115. package/dist/snapshots/index.cjs +0 -937
  116. package/dist/snapshots/index.cjs.map +0 -1
  117. package/dist/snapshots/index.d.cts +0 -30
  118. package/dist/store/index.cjs +0 -1091
  119. package/dist/store/index.cjs.map +0 -1
  120. package/dist/store/index.d.cts +0 -501
  121. package/dist/strategy-BSxFXGzb.d.cts +0 -110
  122. package/dist/strategy-mJExw4LQ.d.cts +0 -1069
  123. package/dist/sync/index.cjs +0 -1062
  124. package/dist/sync/index.cjs.map +0 -1
  125. package/dist/sync/index.d.cts +0 -45
  126. package/dist/team/index.cjs +0 -2805
  127. package/dist/team/index.cjs.map +0 -1
  128. package/dist/team/index.d.cts +0 -120
  129. package/dist/transition-guard-tWZIsaXe.d.cts +0 -165
  130. package/dist/tx/index.cjs +0 -614
  131. package/dist/tx/index.cjs.map +0 -1
  132. package/dist/tx/index.d.cts +0 -39
  133. package/dist/types-CdVfiQgt.d.cts +0 -15275
  134. package/dist/ulid-DRH25k3y.d.cts +0 -66
  135. package/dist/util/index.cjs +0 -237
  136. package/dist/util/index.cjs.map +0 -1
  137. package/dist/util/index.d.cts +0 -79
  138. package/dist/with-materialized-view-DfgPcvi9.d.cts +0 -27
  139. package/dist/with-overlayed-view-Cvfkx1lg.d.cts +0 -13
  140. package/dist/with-rollup-nIxo7h9z.d.cts +0 -47
  141. /package/dist/{noydb-5MIBD77B.js.map → adapter/index.js.map} +0 -0
  142. /package/dist/{chunk-Y6YUWZTS.js.map → chunk-L5HHBOMS.js.map} +0 -0
  143. /package/dist/{types-DHn9lEP0.d.ts → index-DHn9lEP0.d.ts} +0 -0
@@ -1,1091 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/store/index.ts
21
- var store_exports = {};
22
- __export(store_exports, {
23
- BUNDLE_STORE_POLICY: () => BUNDLE_STORE_POLICY,
24
- INDEXED_STORE_POLICY: () => INDEXED_STORE_POLICY,
25
- StoreCapabilityError: () => StoreCapabilityError,
26
- SyncScheduler: () => SyncScheduler,
27
- createBundleStore: () => createBundleStore,
28
- routeStore: () => routeStore,
29
- withCache: () => withCache,
30
- withCircuitBreaker: () => withCircuitBreaker,
31
- withHealthCheck: () => withHealthCheck,
32
- withLogging: () => withLogging,
33
- withMetrics: () => withMetrics,
34
- withRetry: () => withRetry,
35
- wrapBundleStore: () => wrapBundleStore,
36
- wrapStore: () => wrapStore
37
- });
38
- module.exports = __toCommonJS(store_exports);
39
-
40
- // src/store/route-store.ts
41
- var BLOB_CHUNKS = "_blob_chunks";
42
- var BLOB_INDEX = "_blob_index";
43
- var BLOB_SLOTS = "_blob_slots_";
44
- var BLOB_VERSIONS = "_blob_versions_";
45
- function routeStore(opts) {
46
- const primary = opts.default;
47
- const blobsIsSimple = opts.blobs && "get" in opts.blobs;
48
- const simpleBlobStore = blobsIsSimple ? opts.blobs : void 0;
49
- const tieredBlobs = !blobsIsSimple ? opts.blobs : void 0;
50
- const blobThreshold = tieredBlobs?.threshold ?? 400 * 1024;
51
- const allStores = /* @__PURE__ */ new Set([primary]);
52
- if (simpleBlobStore) allStores.add(simpleBlobStore);
53
- if (tieredBlobs?.large) allStores.add(tieredBlobs.large);
54
- if (tieredBlobs?.small) allStores.add(tieredBlobs.small);
55
- if (opts.age?.cold) allStores.add(opts.age.cold);
56
- if (opts.routes) for (const s of Object.values(opts.routes)) allStores.add(s);
57
- if (opts.vaultRoutes) for (const s of Object.values(opts.vaultRoutes)) allStores.add(s);
58
- if (opts.blobRoutes) for (const s of Object.values(opts.blobRoutes)) allStores.add(s);
59
- if (opts.overflow) allStores.add(opts.overflow);
60
- if (opts.blobLifecycle?.archiveStore) allStores.add(opts.blobLifecycle.archiveStore);
61
- const overrides = /* @__PURE__ */ new Map();
62
- const suspended = /* @__PURE__ */ new Set();
63
- const writeQueues = /* @__PURE__ */ new Map();
64
- const NULL_STORE = {
65
- name: "suspended",
66
- async get() {
67
- return null;
68
- },
69
- async put() {
70
- },
71
- async delete() {
72
- },
73
- async list() {
74
- return [];
75
- },
76
- async loadAll() {
77
- return {};
78
- },
79
- async saveAll() {
80
- }
81
- };
82
- function routeNameFor(vault, collection) {
83
- if (opts.vaultRoutes) {
84
- for (const prefix of Object.keys(opts.vaultRoutes)) {
85
- if (vault.startsWith(prefix)) return prefix;
86
- }
87
- }
88
- if (opts.routes && !collection.startsWith("_") && opts.routes[collection]) {
89
- return collection;
90
- }
91
- if (isBlobChunks(collection) && (simpleBlobStore || tieredBlobs)) return "blobs";
92
- if (opts.routeBlobMeta && isBlobMeta(collection) && (simpleBlobStore || tieredBlobs)) return "blobs";
93
- if (opts.age && !collection.startsWith("_")) {
94
- }
95
- return "default";
96
- }
97
- const quotaExceeded = false;
98
- function resolveOriginalStore(route) {
99
- if (route === "blobs") return simpleBlobStore ?? tieredBlobs?.large ?? primary;
100
- if (route === "cold") return opts.age?.cold ?? primary;
101
- if (opts.routes?.[route]) return opts.routes[route];
102
- if (opts.vaultRoutes?.[route]) return opts.vaultRoutes[route];
103
- return primary;
104
- }
105
- function maybeQueueWrite(routeName, method, vault, collection, id, envelope, expectedVersion) {
106
- if (!suspended.has(routeName)) return false;
107
- const queue = writeQueues.get(routeName);
108
- if (!queue) return false;
109
- if (queue.writes.length >= queue.maxSize) {
110
- queue.writes.shift();
111
- }
112
- queue.writes.push({
113
- method,
114
- vault,
115
- collection,
116
- id,
117
- ...envelope !== void 0 ? { envelope } : {},
118
- ...expectedVersion !== void 0 ? { expectedVersion } : {}
119
- });
120
- return true;
121
- }
122
- function isBlobChunks(collection) {
123
- return collection === BLOB_CHUNKS;
124
- }
125
- function isBlobMeta(collection) {
126
- return collection === BLOB_INDEX || collection.startsWith(BLOB_SLOTS) || collection.startsWith(BLOB_VERSIONS);
127
- }
128
- function isInternal(collection) {
129
- return collection.startsWith("_");
130
- }
131
- function storeFor(vault, collection) {
132
- const rName = routeNameFor(vault, collection);
133
- if (suspended.has(rName)) return NULL_STORE;
134
- if (overrides.has(rName)) return overrides.get(rName);
135
- if (opts.vaultRoutes) {
136
- for (const [prefix, store2] of Object.entries(opts.vaultRoutes)) {
137
- if (vault.startsWith(prefix)) return store2;
138
- }
139
- }
140
- if (opts.routes && !isInternal(collection) && opts.routes[collection]) {
141
- return opts.routes[collection];
142
- }
143
- if (isBlobChunks(collection)) {
144
- if (simpleBlobStore) return simpleBlobStore;
145
- if (tieredBlobs) return tieredBlobs.large;
146
- }
147
- if (opts.routeBlobMeta && isBlobMeta(collection)) {
148
- if (simpleBlobStore) return simpleBlobStore;
149
- if (tieredBlobs) return tieredBlobs.large;
150
- }
151
- if (quotaExceeded && opts.overflow) return opts.overflow;
152
- return primary;
153
- }
154
- function blobStoreForSize(dataSize) {
155
- if (!tieredBlobs) return simpleBlobStore ?? primary;
156
- if (dataSize <= blobThreshold) {
157
- return tieredBlobs.small ?? primary;
158
- }
159
- return tieredBlobs.large;
160
- }
161
- function isCold(collection, envelope) {
162
- if (!opts.age) return false;
163
- if (isInternal(collection)) return false;
164
- if (opts.age.collections && opts.age.collections.length > 0) {
165
- if (!opts.age.collections.includes(collection)) return false;
166
- }
167
- const cutoff = Date.now() - opts.age.coldAfterDays * 24 * 60 * 60 * 1e3;
168
- const ts = new Date(envelope._ts).getTime();
169
- return ts < cutoff;
170
- }
171
- const store = {
172
- name: buildName(),
173
- async get(vault, collection, id) {
174
- const s = storeFor(vault, collection);
175
- const result = await s.get(vault, collection, id);
176
- if (result === null && opts.age && !isInternal(collection)) {
177
- if (!opts.age.collections?.length || opts.age.collections.includes(collection)) {
178
- return opts.age.cold.get(vault, collection, id);
179
- }
180
- }
181
- return result;
182
- },
183
- async put(vault, collection, id, envelope, expectedVersion) {
184
- const rn = routeNameFor(vault, collection);
185
- if (maybeQueueWrite(rn, "put", vault, collection, id, envelope, expectedVersion)) return;
186
- if (isBlobChunks(collection) && tieredBlobs) {
187
- const dataSize = envelope._data.length;
188
- const s2 = blobStoreForSize(dataSize);
189
- return s2.put(vault, collection, id, envelope, expectedVersion);
190
- }
191
- const s = storeFor(vault, collection);
192
- if (opts.age && !isInternal(collection)) {
193
- opts.age.cold.delete(vault, collection, id).catch(() => {
194
- });
195
- }
196
- return s.put(vault, collection, id, envelope, expectedVersion);
197
- },
198
- async delete(vault, collection, id) {
199
- const rn = routeNameFor(vault, collection);
200
- if (maybeQueueWrite(rn, "delete", vault, collection, id)) return;
201
- const s = storeFor(vault, collection);
202
- await s.delete(vault, collection, id);
203
- if (opts.age && !isInternal(collection)) {
204
- await opts.age.cold.delete(vault, collection, id).catch(() => {
205
- });
206
- }
207
- },
208
- async list(vault, collection) {
209
- const s = storeFor(vault, collection);
210
- const ids = await s.list(vault, collection);
211
- if (opts.age && !isInternal(collection)) {
212
- if (!opts.age.collections?.length || opts.age.collections.includes(collection)) {
213
- const coldIds = await opts.age.cold.list(vault, collection).catch(() => []);
214
- if (coldIds.length > 0) {
215
- const merged = new Set(ids);
216
- for (const id of coldIds) merged.add(id);
217
- return [...merged];
218
- }
219
- }
220
- }
221
- return ids;
222
- },
223
- async loadAll(vault) {
224
- const stores = getStoresForVault(vault);
225
- const snapshots = await Promise.all(
226
- stores.map((s) => s.loadAll(vault).catch(() => ({})))
227
- );
228
- return mergeSnapshots(snapshots);
229
- },
230
- async saveAll(vault, data) {
231
- const partitioned = /* @__PURE__ */ new Map();
232
- for (const [collection, records] of Object.entries(data)) {
233
- const s = storeFor(vault, collection);
234
- if (!partitioned.has(s)) partitioned.set(s, {});
235
- partitioned.get(s)[collection] = records;
236
- }
237
- await Promise.all(
238
- [...partitioned.entries()].map(([s, snap]) => s.saveAll(vault, snap))
239
- );
240
- },
241
- async compact(vault) {
242
- if (!opts.age) return 0;
243
- let migrated = 0;
244
- const collections = opts.age.collections?.length ? opts.age.collections : await primary.list(vault, "").catch(() => []);
245
- for (const collection of collections) {
246
- const ids = await primary.list(vault, collection).catch(() => []);
247
- for (const id of ids) {
248
- const envelope = await primary.get(vault, collection, id);
249
- if (!envelope) continue;
250
- if (isCold(collection, envelope)) {
251
- await opts.age.cold.put(vault, collection, id, envelope);
252
- await primary.delete(vault, collection, id);
253
- migrated++;
254
- }
255
- }
256
- }
257
- return migrated;
258
- },
259
- // ── Runtime override / suspend ──────────────────────
260
- override(route, overrideStore, overrideOpts) {
261
- if (overrideOpts?.hydrate) {
262
- return (async () => {
263
- overrides.set(route, overrideStore);
264
- })();
265
- }
266
- overrides.set(route, overrideStore);
267
- },
268
- clearOverride(route) {
269
- overrides.delete(route);
270
- },
271
- suspend(route, suspendOpts) {
272
- suspended.add(route);
273
- if (suspendOpts?.queue) {
274
- writeQueues.set(route, {
275
- writes: [],
276
- maxSize: suspendOpts.maxQueueSize ?? 1e4
277
- });
278
- }
279
- },
280
- async resume(route) {
281
- suspended.delete(route);
282
- const queue = writeQueues.get(route);
283
- if (!queue || queue.writes.length === 0) {
284
- writeQueues.delete(route);
285
- return 0;
286
- }
287
- let replayed = 0;
288
- const target = overrides.get(route) ?? resolveOriginalStore(route);
289
- for (const write of queue.writes) {
290
- try {
291
- if (write.method === "put" && write.envelope) {
292
- await target.put(write.vault, write.collection, write.id, write.envelope, write.expectedVersion);
293
- } else if (write.method === "delete") {
294
- await target.delete(write.vault, write.collection, write.id);
295
- }
296
- replayed++;
297
- } catch {
298
- }
299
- }
300
- writeQueues.delete(route);
301
- return replayed;
302
- },
303
- routeStatus() {
304
- const ov = {};
305
- for (const [k, v] of overrides) ov[k] = v.name ?? "unnamed";
306
- const q = {};
307
- for (const [k, v] of writeQueues) q[k] = v.writes.length;
308
- return { overrides: ov, suspended: [...suspended], queued: q };
309
- },
310
- resolveBackend(vaultId) {
311
- if (opts.vaultRoutes) {
312
- for (const [prefix, s] of Object.entries(opts.vaultRoutes)) {
313
- if (vaultId.startsWith(prefix)) return s;
314
- }
315
- }
316
- return primary;
317
- }
318
- };
319
- if (anyHas("listVaults")) {
320
- store.listVaults = async () => {
321
- const results = await Promise.all(
322
- [...allStores].filter((s) => s.listVaults !== void 0).map((s) => s.listVaults().catch(() => []))
323
- );
324
- return [...new Set(results.flat())];
325
- };
326
- }
327
- if (anyHas("ping")) {
328
- store.ping = async () => {
329
- const results = await Promise.all(
330
- [...allStores].filter((s) => s.ping !== void 0).map((s) => s.ping().catch(() => false))
331
- );
332
- return results.some(Boolean);
333
- };
334
- }
335
- return store;
336
- function buildName() {
337
- const names = [...allStores].map((s) => s.name ?? "?").join("+");
338
- return `route(${names})`;
339
- }
340
- function anyHas(method) {
341
- return [...allStores].some((s) => s[method]);
342
- }
343
- function getStoresForVault(vault) {
344
- const stores = /* @__PURE__ */ new Set();
345
- if (opts.vaultRoutes) {
346
- for (const [prefix, s] of Object.entries(opts.vaultRoutes)) {
347
- if (vault.startsWith(prefix)) {
348
- stores.add(s);
349
- return [...stores];
350
- }
351
- }
352
- }
353
- stores.add(primary);
354
- if (simpleBlobStore) stores.add(simpleBlobStore);
355
- if (tieredBlobs?.large) stores.add(tieredBlobs.large);
356
- if (tieredBlobs?.small && tieredBlobs.small !== primary) stores.add(tieredBlobs.small);
357
- if (opts.age?.cold) stores.add(opts.age.cold);
358
- if (opts.routes) {
359
- for (const s of Object.values(opts.routes)) stores.add(s);
360
- }
361
- return [...stores];
362
- }
363
- }
364
- function mergeSnapshots(snapshots) {
365
- const merged = {};
366
- for (const snap of snapshots) {
367
- for (const [collection, records] of Object.entries(snap)) {
368
- if (!merged[collection]) {
369
- merged[collection] = { ...records };
370
- continue;
371
- }
372
- for (const [id, envelope] of Object.entries(records)) {
373
- const existing = merged[collection][id];
374
- if (!existing || envelope._ts >= existing._ts) {
375
- merged[collection][id] = envelope;
376
- }
377
- }
378
- }
379
- }
380
- return merged;
381
- }
382
-
383
- // src/store/store-middleware.ts
384
- function wrapStore(store, ...middlewares) {
385
- let result = store;
386
- for (let i = middlewares.length - 1; i >= 0; i--) {
387
- result = middlewares[i](result);
388
- }
389
- return result;
390
- }
391
- function withRetry(opts = {}) {
392
- const maxRetries = opts.maxRetries ?? 3;
393
- const backoffMs = opts.backoffMs ?? 500;
394
- const jitter = opts.jitter ?? 0.3;
395
- const retryOn = opts.retryOn ? new Set(opts.retryOn) : null;
396
- function shouldRetry(err) {
397
- if (!retryOn) return true;
398
- if (err && typeof err === "object" && "code" in err) {
399
- return retryOn.has(err.code);
400
- }
401
- return true;
402
- }
403
- async function retryable(fn) {
404
- let lastError;
405
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
406
- try {
407
- return await fn();
408
- } catch (err) {
409
- lastError = err;
410
- if (attempt >= maxRetries || !shouldRetry(err)) throw err;
411
- const delay = backoffMs * Math.pow(2, attempt) * (1 + Math.random() * jitter);
412
- await new Promise((r) => setTimeout(r, delay));
413
- }
414
- }
415
- throw lastError;
416
- }
417
- return (next) => ({
418
- ...next,
419
- name: next.name ? `retry(${next.name})` : "retry",
420
- get: (v, c, id) => retryable(() => next.get(v, c, id)),
421
- put: (v, c, id, env, ev) => retryable(() => next.put(v, c, id, env, ev)),
422
- delete: (v, c, id) => retryable(() => next.delete(v, c, id)),
423
- list: (v, c) => retryable(() => next.list(v, c)),
424
- loadAll: (v) => retryable(() => next.loadAll(v)),
425
- saveAll: (v, d) => retryable(() => next.saveAll(v, d))
426
- });
427
- }
428
- var LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
429
- function withLogging(opts = {}) {
430
- const minLevel = LOG_LEVELS[opts.level ?? "info"];
431
- const logger = opts.logger ?? console;
432
- const logData = opts.logData ?? false;
433
- function log(level, method, args, durationMs) {
434
- if (LOG_LEVELS[level] < minLevel) return;
435
- const parts = [`[noydb:${method}]`, ...Object.entries(args).map(([k, v]) => `${k}=${String(v)}`)];
436
- if (durationMs !== void 0) parts.push(`${durationMs}ms`);
437
- logger[level](parts.join(" "));
438
- }
439
- function timed(method, args, fn) {
440
- const start = Date.now();
441
- return fn().then(
442
- (result) => {
443
- log("debug", method, args, Date.now() - start);
444
- return result;
445
- },
446
- (err) => {
447
- log("error", method, { ...args, error: err.message }, Date.now() - start);
448
- throw err;
449
- }
450
- );
451
- }
452
- return (next) => ({
453
- ...next,
454
- name: next.name ? `log(${next.name})` : "log",
455
- get: (v, c, id) => timed("get", { vault: v, collection: c, id }, () => next.get(v, c, id)),
456
- put: (v, c, id, env, ev) => timed("put", {
457
- vault: v,
458
- collection: c,
459
- id,
460
- version: env._v,
461
- ...logData ? { data: env._data.slice(0, 40) + "..." } : {}
462
- }, () => next.put(v, c, id, env, ev)),
463
- delete: (v, c, id) => timed("delete", { vault: v, collection: c, id }, () => next.delete(v, c, id)),
464
- list: (v, c) => timed("list", { vault: v, collection: c }, () => next.list(v, c)),
465
- loadAll: (v) => timed("loadAll", { vault: v }, () => next.loadAll(v)),
466
- saveAll: (v, d) => timed("saveAll", { vault: v }, () => next.saveAll(v, d))
467
- });
468
- }
469
- function withMetrics(opts) {
470
- function tracked(method, vault, fn, collection, id) {
471
- const start = Date.now();
472
- return fn().then(
473
- (result) => {
474
- opts.onOperation({
475
- method,
476
- vault,
477
- ...collection !== void 0 ? { collection } : {},
478
- ...id !== void 0 ? { id } : {},
479
- durationMs: Date.now() - start,
480
- success: true
481
- });
482
- return result;
483
- },
484
- (err) => {
485
- opts.onOperation({
486
- method,
487
- vault,
488
- ...collection !== void 0 ? { collection } : {},
489
- ...id !== void 0 ? { id } : {},
490
- durationMs: Date.now() - start,
491
- success: false,
492
- error: err
493
- });
494
- throw err;
495
- }
496
- );
497
- }
498
- return (next) => ({
499
- ...next,
500
- name: next.name ? `metrics(${next.name})` : "metrics",
501
- get: (v, c, id) => tracked("get", v, () => next.get(v, c, id), c, id),
502
- put: (v, c, id, env, ev) => tracked("put", v, () => next.put(v, c, id, env, ev), c, id),
503
- delete: (v, c, id) => tracked("delete", v, () => next.delete(v, c, id), c, id),
504
- list: (v, c) => tracked("list", v, () => next.list(v, c), c),
505
- loadAll: (v) => tracked("loadAll", v, () => next.loadAll(v)),
506
- saveAll: (v, d) => tracked("saveAll", v, () => next.saveAll(v, d))
507
- });
508
- }
509
- function withCircuitBreaker(opts = {}) {
510
- const threshold = opts.failureThreshold ?? 5;
511
- const resetMs = opts.resetTimeoutMs ?? 3e4;
512
- let state = "closed";
513
- let failures = 0;
514
- let lastFailureTime = 0;
515
- function recordSuccess() {
516
- if (state === "half-open") {
517
- state = "closed";
518
- failures = 0;
519
- opts.onClose?.();
520
- }
521
- failures = 0;
522
- }
523
- function recordFailure() {
524
- failures++;
525
- lastFailureTime = Date.now();
526
- if (failures >= threshold && state === "closed") {
527
- state = "open";
528
- opts.onOpen?.();
529
- }
530
- }
531
- function canAttempt() {
532
- if (state === "closed") return true;
533
- if (state === "open") {
534
- if (Date.now() - lastFailureTime >= resetMs) {
535
- state = "half-open";
536
- return true;
537
- }
538
- return false;
539
- }
540
- return true;
541
- }
542
- async function guarded(fn, fallback) {
543
- if (!canAttempt()) return fallback;
544
- try {
545
- const result = await fn();
546
- recordSuccess();
547
- return result;
548
- } catch (err) {
549
- recordFailure();
550
- throw err;
551
- }
552
- }
553
- return (next) => ({
554
- ...next,
555
- name: next.name ? `cb(${next.name})` : "cb",
556
- get: (v, c, id) => guarded(() => next.get(v, c, id), null),
557
- put: (v, c, id, env, ev) => guarded(() => next.put(v, c, id, env, ev), void 0),
558
- delete: (v, c, id) => guarded(() => next.delete(v, c, id), void 0),
559
- list: (v, c) => guarded(() => next.list(v, c), []),
560
- loadAll: (v) => guarded(() => next.loadAll(v), {}),
561
- saveAll: (v, d) => guarded(() => next.saveAll(v, d), void 0)
562
- });
563
- }
564
- function withCache(opts = {}) {
565
- const maxEntries = opts.maxEntries ?? 500;
566
- const ttlMs = opts.ttlMs ?? 6e4;
567
- const cache = /* @__PURE__ */ new Map();
568
- function cacheKey(vault, collection, id) {
569
- return `${vault}\0${collection}\0${id}`;
570
- }
571
- function getFromCache(key) {
572
- const entry = cache.get(key);
573
- if (!entry) return void 0;
574
- if (ttlMs > 0 && Date.now() - entry.cachedAt > ttlMs) {
575
- cache.delete(key);
576
- return void 0;
577
- }
578
- cache.delete(key);
579
- cache.set(key, entry);
580
- return entry.envelope;
581
- }
582
- function setInCache(key, envelope) {
583
- if (cache.size >= maxEntries) {
584
- const oldest = cache.keys().next().value;
585
- if (oldest !== void 0) cache.delete(oldest);
586
- }
587
- cache.set(key, { envelope, cachedAt: Date.now() });
588
- }
589
- function invalidate(key) {
590
- cache.delete(key);
591
- }
592
- return (next) => ({
593
- ...next,
594
- name: next.name ? `cache(${next.name})` : "cache",
595
- async get(vault, collection, id) {
596
- const key = cacheKey(vault, collection, id);
597
- const cached = getFromCache(key);
598
- if (cached !== void 0) return cached;
599
- const result = await next.get(vault, collection, id);
600
- setInCache(key, result);
601
- return result;
602
- },
603
- async put(vault, collection, id, env, ev) {
604
- invalidate(cacheKey(vault, collection, id));
605
- await next.put(vault, collection, id, env, ev);
606
- setInCache(cacheKey(vault, collection, id), env);
607
- },
608
- async delete(vault, collection, id) {
609
- invalidate(cacheKey(vault, collection, id));
610
- await next.delete(vault, collection, id);
611
- },
612
- list: (v, c) => next.list(v, c),
613
- loadAll: (v) => next.loadAll(v),
614
- saveAll: (v, d) => next.saveAll(v, d)
615
- });
616
- }
617
- function withHealthCheck(opts = {}) {
618
- const intervalMs = opts.checkIntervalMs ?? 3e4;
619
- const failThreshold = opts.suspendAfterFailures ?? 3;
620
- const successThreshold = opts.resumeAfterSuccess ?? 1;
621
- let isSuspended = false;
622
- let consecutiveFailures = 0;
623
- let consecutiveSuccesses = 0;
624
- return (next) => {
625
- const checkFn = opts.check ?? (next.ping ? () => next.ping() : async () => {
626
- await next.list("__health__", "__ping__");
627
- return true;
628
- });
629
- async function doCheck() {
630
- try {
631
- const ok = await checkFn();
632
- if (ok) {
633
- consecutiveFailures = 0;
634
- consecutiveSuccesses++;
635
- if (isSuspended && consecutiveSuccesses >= successThreshold) {
636
- isSuspended = false;
637
- consecutiveSuccesses = 0;
638
- opts.onResume?.();
639
- }
640
- } else {
641
- throw new Error("Health check returned false");
642
- }
643
- } catch {
644
- consecutiveSuccesses = 0;
645
- consecutiveFailures++;
646
- if (!isSuspended && consecutiveFailures >= failThreshold) {
647
- isSuspended = true;
648
- consecutiveFailures = 0;
649
- opts.onSuspend?.();
650
- }
651
- }
652
- }
653
- setInterval(() => {
654
- void doCheck();
655
- }, intervalMs);
656
- const wrapped = {
657
- ...next,
658
- name: next.name ? `health(${next.name})` : "health",
659
- async get(v, c, id) {
660
- return isSuspended ? null : next.get(v, c, id);
661
- },
662
- async put(v, c, id, env, ev) {
663
- if (!isSuspended) await next.put(v, c, id, env, ev);
664
- },
665
- async delete(v, c, id) {
666
- if (!isSuspended) await next.delete(v, c, id);
667
- },
668
- async list(v, c) {
669
- return isSuspended ? [] : next.list(v, c);
670
- },
671
- async loadAll(v) {
672
- return isSuspended ? {} : next.loadAll(v);
673
- },
674
- async saveAll(v, d) {
675
- if (!isSuspended) await next.saveAll(v, d);
676
- }
677
- };
678
- return wrapped;
679
- };
680
- }
681
-
682
- // src/errors.ts
683
- var NoydbError = class extends Error {
684
- /** Machine-readable error code. Stable across library versions. */
685
- code;
686
- constructor(code, message) {
687
- super(message);
688
- this.name = "NoydbError";
689
- this.code = code;
690
- }
691
- };
692
- var StoreCapabilityError = class extends NoydbError {
693
- /** The store method/capability that was missing. */
694
- capability;
695
- constructor(capability, callerApi, storeName) {
696
- super(
697
- "STORE_CAPABILITY",
698
- `${callerApi} requires the optional store capability "${capability}" but the active store${storeName ? ` (${storeName})` : ""} does not implement it. Use a store that supports "${capability}" (store-memory, store-file) or pass an explicit vault list to bypass enumeration.`
699
- );
700
- this.name = "StoreCapabilityError";
701
- this.capability = capability;
702
- }
703
- };
704
- var ConflictError = class extends NoydbError {
705
- /** The actual stored version at the time of conflict. */
706
- version;
707
- constructor(version, message = "Version conflict") {
708
- super("CONFLICT", message);
709
- this.name = "ConflictError";
710
- this.version = version;
711
- }
712
- };
713
- var BundleVersionConflictError = class extends NoydbError {
714
- /** The bundle handle of the newer remote version that rejected the push. */
715
- remoteVersion;
716
- constructor(remoteVersion, message = "Bundle version conflict \u2014 remote has been updated") {
717
- super("BUNDLE_VERSION_CONFLICT", message);
718
- this.name = "BundleVersionConflictError";
719
- this.remoteVersion = remoteVersion;
720
- }
721
- };
722
-
723
- // src/store/bundle-store.ts
724
- var BUNDLE_STORE_VERSION = 1;
725
- var MAX_CONFLICT_RETRIES = 3;
726
- function wrapBundleStore(bundle, options) {
727
- const autoFlush = options?.autoFlush !== false;
728
- const snapshots = /* @__PURE__ */ new Map();
729
- const versions = /* @__PURE__ */ new Map();
730
- const loaded = /* @__PURE__ */ new Set();
731
- let batchDepth = 0;
732
- async function load(vault) {
733
- if (loaded.has(vault)) return snapshots.get(vault);
734
- const result = await bundle.readBundle(vault);
735
- if (result) {
736
- const text = new TextDecoder().decode(result.bytes);
737
- const format = JSON.parse(text);
738
- snapshots.set(vault, format.data);
739
- versions.set(vault, result.version);
740
- } else {
741
- snapshots.set(vault, {});
742
- versions.set(vault, null);
743
- }
744
- loaded.add(vault);
745
- return snapshots.get(vault);
746
- }
747
- async function flush(vault) {
748
- const snapshot = snapshots.get(vault) ?? {};
749
- const format = {
750
- _noydb_bundle_store: BUNDLE_STORE_VERSION,
751
- vault,
752
- ts: (/* @__PURE__ */ new Date()).toISOString(),
753
- data: snapshot
754
- };
755
- const bytes = new TextEncoder().encode(JSON.stringify(format));
756
- const expectedVersion = versions.get(vault) ?? null;
757
- for (let attempt = 0; attempt < MAX_CONFLICT_RETRIES; attempt++) {
758
- try {
759
- const { version: newVersion } = await bundle.writeBundle(vault, bytes, expectedVersion);
760
- versions.set(vault, newVersion);
761
- return;
762
- } catch (err) {
763
- if (err instanceof BundleVersionConflictError && attempt < MAX_CONFLICT_RETRIES - 1) {
764
- const remote = await bundle.readBundle(vault);
765
- if (remote) {
766
- const remoteText = new TextDecoder().decode(remote.bytes);
767
- const remoteFormat = JSON.parse(remoteText);
768
- const localSnap = snapshots.get(vault) ?? {};
769
- const mergedSnap = mergeSnapshots2(remoteFormat.data, localSnap);
770
- snapshots.set(vault, mergedSnap);
771
- versions.set(vault, remote.version);
772
- }
773
- continue;
774
- }
775
- throw err;
776
- }
777
- }
778
- }
779
- async function maybeFlush(vault) {
780
- if (autoFlush && batchDepth === 0) {
781
- await flush(vault);
782
- }
783
- }
784
- const store = {
785
- name: bundle.name ?? "bundle",
786
- async flush(vaultId) {
787
- await flush(vaultId);
788
- },
789
- async batch(vaultId, fn) {
790
- await load(vaultId);
791
- batchDepth++;
792
- try {
793
- await fn();
794
- } finally {
795
- batchDepth--;
796
- }
797
- await flush(vaultId);
798
- },
799
- async get(vault, collection, id) {
800
- const snap = await load(vault);
801
- return snap[collection]?.[id] ?? null;
802
- },
803
- async put(vault, collection, id, envelope, expectedVersion) {
804
- const snap = await load(vault);
805
- if (expectedVersion !== void 0) {
806
- const current = snap[collection]?.[id];
807
- const currentVersion = current?._v ?? 0;
808
- if (currentVersion !== expectedVersion) {
809
- throw new ConflictError(
810
- currentVersion,
811
- `Expected version ${expectedVersion} but found ${currentVersion} on ${collection}/${id}`
812
- );
813
- }
814
- }
815
- snap[collection] ??= {};
816
- snap[collection][id] = envelope;
817
- await maybeFlush(vault);
818
- },
819
- async delete(vault, collection, id) {
820
- const snap = await load(vault);
821
- if (snap[collection]) {
822
- delete snap[collection][id];
823
- await maybeFlush(vault);
824
- }
825
- },
826
- async list(vault, collection) {
827
- const snap = await load(vault);
828
- return Object.keys(snap[collection] ?? {});
829
- },
830
- async loadAll(vault) {
831
- return await load(vault);
832
- },
833
- async saveAll(vault, data) {
834
- snapshots.set(vault, data);
835
- loaded.add(vault);
836
- await flush(vault);
837
- }
838
- };
839
- return store;
840
- }
841
- function mergeSnapshots2(remote, local) {
842
- const merged = {};
843
- for (const [coll, records] of Object.entries(remote)) {
844
- merged[coll] = { ...records };
845
- }
846
- for (const [coll, records] of Object.entries(local)) {
847
- if (!merged[coll]) {
848
- merged[coll] = { ...records };
849
- continue;
850
- }
851
- for (const [id, envelope] of Object.entries(records)) {
852
- const existing = merged[coll][id];
853
- if (!existing || envelope._ts >= existing._ts) {
854
- merged[coll][id] = envelope;
855
- }
856
- }
857
- }
858
- return merged;
859
- }
860
- function createBundleStore(factory) {
861
- return factory;
862
- }
863
-
864
- // src/store/sync-policy.ts
865
- var INDEXED_STORE_POLICY = {
866
- push: { mode: "on-change", minIntervalMs: 0, onUnload: true },
867
- pull: { mode: "manual" }
868
- };
869
- var BUNDLE_STORE_POLICY = {
870
- push: { mode: "debounce", debounceMs: 3e4, minIntervalMs: 12e4, onUnload: true },
871
- pull: { mode: "interval", intervalMs: 6e4 }
872
- };
873
- var SyncScheduler = class {
874
- policy;
875
- callbacks;
876
- _state = "idle";
877
- _lastPushAt = null;
878
- _lastPullAt = null;
879
- _lastError = null;
880
- _lastPushTime = 0;
881
- // monotonic ms for minIntervalMs enforcement
882
- // Timers
883
- debounceTimer = null;
884
- pushIntervalTimer = null;
885
- pullIntervalTimer = null;
886
- // Bound handlers for cleanup
887
- boundOnVisibilityChange = null;
888
- boundOnBeforeExit = null;
889
- boundOnPageHide = null;
890
- started = false;
891
- constructor(policy, callbacks) {
892
- this.policy = policy;
893
- this.callbacks = callbacks;
894
- if (this.shouldRegisterUnload()) {
895
- this.boundOnVisibilityChange = this.handleVisibilityChange.bind(this);
896
- this.boundOnPageHide = this.handlePageHide.bind(this);
897
- this.boundOnBeforeExit = this.handleBeforeExit.bind(this);
898
- }
899
- }
900
- /** Current scheduler status snapshot. */
901
- get status() {
902
- return {
903
- state: this._state,
904
- lastPushAt: this._lastPushAt,
905
- lastPullAt: this._lastPullAt,
906
- lastError: this._lastError,
907
- pendingWrites: this.callbacks.getDirtyCount()
908
- };
909
- }
910
- /** Start the scheduler — registers timers, event listeners. */
911
- start() {
912
- if (this.started) return;
913
- this.started = true;
914
- if (this.policy.push.mode === "interval" && this.policy.push.intervalMs) {
915
- this.pushIntervalTimer = setInterval(() => {
916
- void this.executePush();
917
- }, this.policy.push.intervalMs);
918
- }
919
- if (this.policy.pull.mode === "interval" && this.policy.pull.intervalMs) {
920
- this.pullIntervalTimer = setInterval(() => {
921
- void this.executePull();
922
- }, this.policy.pull.intervalMs);
923
- }
924
- if (this.policy.pull.mode === "on-focus" && typeof document !== "undefined") {
925
- document.addEventListener("visibilitychange", this.handleFocusPull);
926
- }
927
- if (this.shouldRegisterUnload()) {
928
- if (typeof document !== "undefined" && this.boundOnVisibilityChange) {
929
- document.addEventListener("visibilitychange", this.boundOnVisibilityChange);
930
- }
931
- if (typeof globalThis.addEventListener === "function" && this.boundOnPageHide) {
932
- globalThis.addEventListener("pagehide", this.boundOnPageHide);
933
- }
934
- if (typeof process !== "undefined" && this.boundOnBeforeExit) {
935
- process.on("beforeExit", this.boundOnBeforeExit);
936
- }
937
- }
938
- }
939
- /** Stop the scheduler — clears timers, removes event listeners. */
940
- stop() {
941
- if (!this.started) return;
942
- this.started = false;
943
- if (this.debounceTimer) {
944
- clearTimeout(this.debounceTimer);
945
- this.debounceTimer = null;
946
- }
947
- if (this.pushIntervalTimer) {
948
- clearInterval(this.pushIntervalTimer);
949
- this.pushIntervalTimer = null;
950
- }
951
- if (this.pullIntervalTimer) {
952
- clearInterval(this.pullIntervalTimer);
953
- this.pullIntervalTimer = null;
954
- }
955
- if (this.policy.pull.mode === "on-focus" && typeof document !== "undefined") {
956
- document.removeEventListener("visibilitychange", this.handleFocusPull);
957
- }
958
- if (typeof document !== "undefined" && this.boundOnVisibilityChange) {
959
- document.removeEventListener("visibilitychange", this.boundOnVisibilityChange);
960
- }
961
- if (typeof globalThis.removeEventListener === "function" && this.boundOnPageHide) {
962
- globalThis.removeEventListener("pagehide", this.boundOnPageHide);
963
- }
964
- if (typeof process !== "undefined" && this.boundOnBeforeExit) {
965
- process.removeListener("beforeExit", this.boundOnBeforeExit);
966
- }
967
- }
968
- /**
969
- * Notify the scheduler that a local write occurred.
970
- * For `on-change` mode: triggers immediate push (respecting minIntervalMs).
971
- * For `debounce` mode: resets the debounce timer.
972
- * For `manual` / `interval`: no-op.
973
- */
974
- notifyChange() {
975
- if (!this.started) return;
976
- if (this.policy.push.mode === "on-change") {
977
- void this.executePush();
978
- } else if (this.policy.push.mode === "debounce") {
979
- this.resetDebounce();
980
- }
981
- }
982
- /** Force an immediate push, bypassing the scheduler. */
983
- async forcePush() {
984
- await this.executePush();
985
- }
986
- /** Force an immediate pull, bypassing the scheduler. */
987
- async forcePull() {
988
- await this.executePull();
989
- }
990
- // ─── Internal ─────────────────────────────────────────────────────
991
- async executePush() {
992
- if (this._state === "pushing") return;
993
- const minInterval = this.policy.push.minIntervalMs ?? 0;
994
- if (minInterval > 0) {
995
- const elapsed = Date.now() - this._lastPushTime;
996
- if (elapsed < minInterval) {
997
- if (this.policy.push.mode === "debounce") {
998
- this.scheduleDebounce(minInterval - elapsed);
999
- }
1000
- return;
1001
- }
1002
- }
1003
- if (this.callbacks.getDirtyCount() === 0) {
1004
- this._state = "idle";
1005
- return;
1006
- }
1007
- this._state = "pushing";
1008
- try {
1009
- await this.callbacks.push();
1010
- this._lastPushAt = (/* @__PURE__ */ new Date()).toISOString();
1011
- this._lastPushTime = Date.now();
1012
- this._lastError = null;
1013
- this._state = this.callbacks.getDirtyCount() > 0 ? "pending" : "idle";
1014
- } catch (err) {
1015
- this._lastError = err instanceof Error ? err : new Error(String(err));
1016
- this._state = "error";
1017
- }
1018
- }
1019
- async executePull() {
1020
- if (this._state === "pulling") return;
1021
- const previousState = this._state;
1022
- this._state = "pulling";
1023
- try {
1024
- await this.callbacks.pull();
1025
- this._lastPullAt = (/* @__PURE__ */ new Date()).toISOString();
1026
- this._lastError = null;
1027
- this._state = previousState === "pending" ? "pending" : "idle";
1028
- } catch (err) {
1029
- this._lastError = err instanceof Error ? err : new Error(String(err));
1030
- this._state = "error";
1031
- }
1032
- }
1033
- resetDebounce() {
1034
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
1035
- const ms = this.policy.push.debounceMs ?? 3e4;
1036
- this._state = "pending";
1037
- this.scheduleDebounce(ms);
1038
- }
1039
- scheduleDebounce(ms) {
1040
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
1041
- this.debounceTimer = setTimeout(() => {
1042
- this.debounceTimer = null;
1043
- void this.executePush();
1044
- }, ms);
1045
- }
1046
- shouldRegisterUnload() {
1047
- const onUnload = this.policy.push.onUnload;
1048
- if (onUnload !== void 0) return onUnload;
1049
- return this.policy.push.mode !== "manual";
1050
- }
1051
- // ─── Event handlers ───────────────────────────────────────────────
1052
- handleVisibilityChange() {
1053
- if (typeof document !== "undefined" && document.visibilityState === "hidden") {
1054
- this.fireUnloadPush();
1055
- }
1056
- }
1057
- handlePageHide() {
1058
- this.fireUnloadPush();
1059
- }
1060
- handleBeforeExit() {
1061
- this.fireUnloadPush();
1062
- }
1063
- handleFocusPull = () => {
1064
- if (typeof document !== "undefined" && document.visibilityState === "visible") {
1065
- void this.executePull();
1066
- }
1067
- };
1068
- fireUnloadPush() {
1069
- if (this.callbacks.getDirtyCount() === 0) return;
1070
- void this.callbacks.push().catch(() => {
1071
- });
1072
- }
1073
- };
1074
- // Annotate the CommonJS export names for ESM import in node:
1075
- 0 && (module.exports = {
1076
- BUNDLE_STORE_POLICY,
1077
- INDEXED_STORE_POLICY,
1078
- StoreCapabilityError,
1079
- SyncScheduler,
1080
- createBundleStore,
1081
- routeStore,
1082
- withCache,
1083
- withCircuitBreaker,
1084
- withHealthCheck,
1085
- withLogging,
1086
- withMetrics,
1087
- withRetry,
1088
- wrapBundleStore,
1089
- wrapStore
1090
- });
1091
- //# sourceMappingURL=index.cjs.map