@noy-db/hub 0.4.0-pre.10 → 0.4.0-pre.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cargo/index.js +4 -4
- package/dist/{chunk-Y6B6HVKC.js → chunk-2J6UEN2V.js} +41 -17
- package/dist/chunk-2J6UEN2V.js.map +1 -0
- package/dist/{chunk-YZJSJOUI.js → chunk-DSJG26FE.js} +2 -2
- package/dist/{chunk-NFIBXF4V.js → chunk-Q54PXSQL.js} +18 -18
- package/dist/debug/index.js +29 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/index.js +37 -37
- package/dist/kernel/debug.d.ts +11 -0
- package/dist/materialized-views/index.js +6 -6
- package/dist/{noydb-FZZIMLCI.js → noydb-LPUMSDBR.js} +7 -7
- package/dist/pod/index.js +1 -1
- package/package.json +7 -3
- package/dist/chunk-Y6B6HVKC.js.map +0 -1
- /package/dist/{chunk-YZJSJOUI.js.map → chunk-DSJG26FE.js.map} +0 -0
- /package/dist/{chunk-NFIBXF4V.js.map → chunk-Q54PXSQL.js.map} +0 -0
- /package/dist/{noydb-FZZIMLCI.js.map → noydb-LPUMSDBR.js.map} +0 -0
package/dist/cargo/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
diffVault,
|
|
7
7
|
unsealDeks,
|
|
8
8
|
withCargo
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-DSJG26FE.js";
|
|
10
10
|
import {
|
|
11
11
|
NO_CARGO,
|
|
12
12
|
isQuorum,
|
|
@@ -26,12 +26,12 @@ import "../chunk-FQZ6XTQ7.js";
|
|
|
26
26
|
import "../chunk-I5GEJX3R.js";
|
|
27
27
|
import "../chunk-X45JYIAY.js";
|
|
28
28
|
import "../chunk-DMH3VZU5.js";
|
|
29
|
-
import {
|
|
30
|
-
fuseRetrieval
|
|
31
|
-
} from "../chunk-AURFOK3D.js";
|
|
32
29
|
import {
|
|
33
30
|
CustodyApi
|
|
34
31
|
} from "../chunk-YWWQM7KP.js";
|
|
32
|
+
import {
|
|
33
|
+
fuseRetrieval
|
|
34
|
+
} from "../chunk-AURFOK3D.js";
|
|
35
35
|
import "../chunk-GWWOGNBK.js";
|
|
36
36
|
import {
|
|
37
37
|
groupAndReduce,
|
|
@@ -12,20 +12,31 @@ function wrapPodStore(bundle, options) {
|
|
|
12
12
|
const versions = /* @__PURE__ */ new Map();
|
|
13
13
|
const loaded = /* @__PURE__ */ new Set();
|
|
14
14
|
let batchDepth = 0;
|
|
15
|
+
const loading = /* @__PURE__ */ new Map();
|
|
15
16
|
async function load(vault) {
|
|
16
17
|
if (loaded.has(vault)) return snapshots.get(vault);
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
const inFlight = loading.get(vault);
|
|
19
|
+
if (inFlight) return inFlight;
|
|
20
|
+
const pending = (async () => {
|
|
21
|
+
const result = await bundle.readBundle(vault);
|
|
22
|
+
if (result) {
|
|
23
|
+
const text = new TextDecoder().decode(result.bytes);
|
|
24
|
+
const format = JSON.parse(text);
|
|
25
|
+
snapshots.set(vault, format.data);
|
|
26
|
+
versions.set(vault, result.version);
|
|
27
|
+
} else {
|
|
28
|
+
snapshots.set(vault, {});
|
|
29
|
+
versions.set(vault, null);
|
|
30
|
+
}
|
|
31
|
+
loaded.add(vault);
|
|
32
|
+
return snapshots.get(vault);
|
|
33
|
+
})();
|
|
34
|
+
loading.set(vault, pending);
|
|
35
|
+
try {
|
|
36
|
+
return await pending;
|
|
37
|
+
} finally {
|
|
38
|
+
loading.delete(vault);
|
|
26
39
|
}
|
|
27
|
-
loaded.add(vault);
|
|
28
|
-
return snapshots.get(vault);
|
|
29
40
|
}
|
|
30
41
|
async function flush(vault) {
|
|
31
42
|
const snapshot = snapshots.get(vault) ?? {};
|
|
@@ -59,15 +70,22 @@ function wrapPodStore(bundle, options) {
|
|
|
59
70
|
}
|
|
60
71
|
}
|
|
61
72
|
}
|
|
73
|
+
const flushChain = /* @__PURE__ */ new Map();
|
|
74
|
+
function serialFlush(vault) {
|
|
75
|
+
const prev = flushChain.get(vault) ?? Promise.resolve();
|
|
76
|
+
const next = prev.then(() => flush(vault), () => flush(vault));
|
|
77
|
+
flushChain.set(vault, next);
|
|
78
|
+
return next;
|
|
79
|
+
}
|
|
62
80
|
async function maybeFlush(vault) {
|
|
63
81
|
if (autoFlush && batchDepth === 0) {
|
|
64
|
-
await
|
|
82
|
+
await serialFlush(vault);
|
|
65
83
|
}
|
|
66
84
|
}
|
|
67
85
|
const store = {
|
|
68
86
|
name: bundle.name ?? "bundle",
|
|
69
87
|
async flush(vaultId) {
|
|
70
|
-
await
|
|
88
|
+
await serialFlush(vaultId);
|
|
71
89
|
},
|
|
72
90
|
async batch(vaultId, fn) {
|
|
73
91
|
await load(vaultId);
|
|
@@ -77,7 +95,7 @@ function wrapPodStore(bundle, options) {
|
|
|
77
95
|
} finally {
|
|
78
96
|
batchDepth--;
|
|
79
97
|
}
|
|
80
|
-
await
|
|
98
|
+
await serialFlush(vaultId);
|
|
81
99
|
},
|
|
82
100
|
async get(vault, collection, id) {
|
|
83
101
|
const snap = await load(vault);
|
|
@@ -111,12 +129,18 @@ function wrapPodStore(bundle, options) {
|
|
|
111
129
|
return Object.keys(snap[collection] ?? {});
|
|
112
130
|
},
|
|
113
131
|
async loadAll(vault) {
|
|
114
|
-
|
|
132
|
+
const snap = await load(vault);
|
|
133
|
+
const out = {};
|
|
134
|
+
for (const [collection, records] of Object.entries(snap)) {
|
|
135
|
+
if (collection.startsWith("_")) continue;
|
|
136
|
+
out[collection] = { ...records };
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
115
139
|
},
|
|
116
140
|
async saveAll(vault, data) {
|
|
117
141
|
snapshots.set(vault, data);
|
|
118
142
|
loaded.add(vault);
|
|
119
|
-
await
|
|
143
|
+
await serialFlush(vault);
|
|
120
144
|
}
|
|
121
145
|
};
|
|
122
146
|
return store;
|
|
@@ -152,4 +176,4 @@ export {
|
|
|
152
176
|
wrapBundleStore,
|
|
153
177
|
createBundleStore
|
|
154
178
|
};
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
179
|
+
//# sourceMappingURL=chunk-2J6UEN2V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-pod/pod-store.ts"],"sourcesContent":["import type { NoydbStore, NoydbPodStore, VaultSnapshot, EncryptedEnvelope } from '../kernel/types.js'\nimport { ConflictError, PodVersionConflictError } from '../kernel/errors.js'\n\n// ─── Bundle format ─────────────────────────────────────────────────────\n\nconst BUNDLE_STORE_VERSION = 1 as const\n\n/**\n * Wire format written by `wrapPodStore`. A JSON-serialised object that\n * contains the entire `VaultSnapshot` (all encrypted envelopes) plus a small\n * header for integrity checking. The envelopes inside are already AES-GCM\n * encrypted by core — the bundle bytes themselves are not additionally\n * encrypted, but they are safe to store on untrusted blob hosts because\n * every record inside is already ciphertext.\n *\n * @internal\n */\ninterface BundleStoreData {\n readonly _noydb_bundle_store: typeof BUNDLE_STORE_VERSION\n readonly vault: string\n readonly ts: string\n readonly data: VaultSnapshot\n}\n\n// ─── Options ───────────────────────────────────────────────────────────\n\nexport interface WrapPodStoreOptions {\n /**\n * When `true` (default), every `put()` and `delete()` flushes the full\n * vault snapshot to the bundle backend. Set to `false` for bulk operations\n * and call `store.flush(vaultId)` manually.\n */\n autoFlush?: boolean\n}\n\n// ─── Extended NoydbStore with flush/batch ───────────────────────────────\n\nexport interface WrappedPodNoydbStore extends NoydbStore {\n /** Manually flush the in-memory snapshot to the bundle backend. */\n flush(vaultId: string): Promise<void>\n /**\n * Run a batch of mutations without flushing until the callback completes.\n * A single flush is performed at the end.\n */\n batch(vaultId: string, fn: () => Promise<void>): Promise<void>\n}\n\n// ─── wrapPodStore ───────────────────────────────────────────────────\n\nconst MAX_CONFLICT_RETRIES = 3\n\n/**\n * Convert a `NoydbPodStore` (blob-oriented read/write with OCC) into the\n * standard six-method `NoydbStore` interface expected by `createNoydb({ store })`.\n *\n * Bundle stores operate on the entire vault as a single serialised unit —\n * ideal for backends like Google Drive, WebDAV, or iCloud Drive that work\n * best with whole-file I/O rather than per-record KV operations.\n *\n * ## Optimistic concurrency\n *\n * The wrapper tracks the `version` token from the last `readBundle` and\n * passes it as `expectedVersion` on every flush. On\n * `PodVersionConflictError`, it re-reads, merges the remote snapshot\n * (last-write-wins per record key), and retries (max 3 attempts).\n *\n * ## Flush modes\n *\n * By default, flushes on every mutation (O(vault size) per write). Options:\n * - `autoFlush: false` + explicit `store.flush(vaultId)` calls\n * - `store.batch(vaultId, async () => { ... })` — defers flush until end\n * - Pair with `syncPolicy: { push: { mode: 'debounce' } }` from \n */\nexport function wrapPodStore(\n bundle: NoydbPodStore,\n options?: WrapPodStoreOptions,\n): WrappedPodNoydbStore {\n const autoFlush = options?.autoFlush !== false\n\n // Per-vault state\n const snapshots = new Map<string, VaultSnapshot>()\n const versions = new Map<string, string | null>()\n const loaded = new Set<string>()\n\n // Batch mode: when > 0, suppress auto-flush\n let batchDepth = 0\n\n // #908 — in-flight loads, keyed by vault. Without this, every concurrent\n // caller issued its own `readBundle` and then REPLACED `snapshots` with a\n // freshly parsed object — orphaning the mutations earlier callers had\n // already made to the object they were handed. 100 racing puts kept 1.\n const loading = new Map<string, Promise<VaultSnapshot>>()\n\n async function load(vault: string): Promise<VaultSnapshot> {\n if (loaded.has(vault)) return snapshots.get(vault)!\n\n const inFlight = loading.get(vault)\n if (inFlight) return inFlight\n\n const pending = (async () => {\n const result = await bundle.readBundle(vault)\n if (result) {\n const text = new TextDecoder().decode(result.bytes)\n const format = JSON.parse(text) as BundleStoreData\n snapshots.set(vault, format.data)\n versions.set(vault, result.version)\n } else {\n snapshots.set(vault, {})\n versions.set(vault, null)\n }\n\n loaded.add(vault)\n return snapshots.get(vault)!\n })()\n\n loading.set(vault, pending)\n try {\n return await pending\n } finally {\n // Clear on failure too, so a transient read error does not poison\n // every later load of this vault with a rejected promise.\n loading.delete(vault)\n }\n }\n\n async function flush(vault: string): Promise<void> {\n const snapshot = snapshots.get(vault) ?? {}\n const format: BundleStoreData = {\n _noydb_bundle_store: BUNDLE_STORE_VERSION,\n vault,\n ts: new Date().toISOString(),\n data: snapshot,\n }\n const bytes = new TextEncoder().encode(JSON.stringify(format))\n const expectedVersion = versions.get(vault) ?? null\n\n for (let attempt = 0; attempt < MAX_CONFLICT_RETRIES; attempt++) {\n try {\n const { version: newVersion } = await bundle.writeBundle(vault, bytes, expectedVersion)\n versions.set(vault, newVersion)\n return\n } catch (err) {\n if (err instanceof PodVersionConflictError && attempt < MAX_CONFLICT_RETRIES - 1) {\n // Pull remote, merge (last-write-wins by record key), retry\n const remote = await bundle.readBundle(vault)\n if (remote) {\n const remoteText = new TextDecoder().decode(remote.bytes)\n const remoteFormat = JSON.parse(remoteText) as BundleStoreData\n const localSnap = snapshots.get(vault) ?? {}\n const mergedSnap = mergeSnapshots(remoteFormat.data, localSnap)\n snapshots.set(vault, mergedSnap)\n versions.set(vault, remote.version)\n }\n // Re-encode with merged data for the retry\n continue\n }\n throw err\n }\n }\n }\n\n // #908 — one flush at a time per vault. `flush` reads and writes the vault's\n // version token, so concurrent flushes race: each sends the same\n // `expectedVersion`, the losers take the conflict/merge path, and with enough\n // of them the retry budget is exhausted and the error surfaces to a caller\n // whose write was perfectly valid. Serialising makes every flush see the\n // token its predecessor produced.\n const flushChain = new Map<string, Promise<void>>()\n\n function serialFlush(vault: string): Promise<void> {\n const prev = flushChain.get(vault) ?? Promise.resolve()\n // Chain past a rejection as well — one failed flush must not wedge every\n // subsequent write to this vault.\n const next = prev.then(() => flush(vault), () => flush(vault))\n flushChain.set(vault, next)\n return next\n }\n\n async function maybeFlush(vault: string): Promise<void> {\n if (autoFlush && batchDepth === 0) {\n await serialFlush(vault)\n }\n }\n\n const store: WrappedPodNoydbStore = {\n name: bundle.name ?? 'bundle',\n\n async flush(vaultId: string): Promise<void> {\n await serialFlush(vaultId)\n },\n\n async batch(vaultId: string, fn: () => Promise<void>): Promise<void> {\n await load(vaultId) // ensure loaded before batch\n batchDepth++\n try {\n await fn()\n } finally {\n batchDepth--\n }\n await serialFlush(vaultId)\n },\n\n async get(vault: string, collection: string, id: string): Promise<EncryptedEnvelope | null> {\n const snap = await load(vault)\n return snap[collection]?.[id] ?? null\n },\n\n async put(\n vault: string,\n collection: string,\n id: string,\n envelope: EncryptedEnvelope,\n expectedVersion?: number,\n ): Promise<void> {\n const snap = await load(vault)\n\n if (expectedVersion !== undefined) {\n const current = snap[collection]?.[id]\n const currentVersion = current?._v ?? 0\n if (currentVersion !== expectedVersion) {\n throw new ConflictError(\n currentVersion,\n `Expected version ${expectedVersion} but found ${currentVersion} on ${collection}/${id}`,\n )\n }\n }\n\n snap[collection] ??= {}\n snap[collection][id] = envelope\n await maybeFlush(vault)\n },\n\n async delete(vault: string, collection: string, id: string): Promise<void> {\n const snap = await load(vault)\n if (snap[collection]) {\n delete snap[collection][id]\n await maybeFlush(vault)\n }\n },\n\n async list(vault: string, collection: string): Promise<string[]> {\n const snap = await load(vault)\n return Object.keys(snap[collection] ?? {})\n },\n\n async loadAll(vault: string): Promise<VaultSnapshot> {\n const snap = await load(vault)\n // #908 — two contract fixes in one place:\n // 1. internal collections (`_keyring`, `_sync`) are the vault's own\n // bookkeeping and must not appear in a snapshot — `@noy-db/to-file`\n // sets the reference behaviour with this same `_`-prefix rule;\n // 2. copy rather than hand out the live cache, which let a caller\n // mutating the result silently rewrite the wrapper's own state.\n // `get()`/`list()` still serve internal collections; this is about what\n // a *snapshot* claims, not about hiding data.\n const out: VaultSnapshot = {}\n for (const [collection, records] of Object.entries(snap)) {\n if (collection.startsWith('_')) continue\n out[collection] = { ...records }\n }\n return out\n },\n\n async saveAll(vault: string, data: VaultSnapshot): Promise<void> {\n snapshots.set(vault, data)\n loaded.add(vault)\n await serialFlush(vault)\n },\n }\n\n return store\n}\n\n// ─── Snapshot merge (last-write-wins per record) ────────────────────────\n\nfunction mergeSnapshots(remote: VaultSnapshot, local: VaultSnapshot): VaultSnapshot {\n const merged: VaultSnapshot = {}\n\n // Start with all remote collections\n for (const [coll, records] of Object.entries(remote)) {\n merged[coll] = { ...records }\n }\n\n // Overlay local collections — LWW by _ts per record\n for (const [coll, records] of Object.entries(local)) {\n if (!merged[coll]) {\n merged[coll] = { ...records }\n continue\n }\n for (const [id, envelope] of Object.entries(records)) {\n const existing = merged[coll][id]\n if (!existing || envelope._ts >= existing._ts) {\n merged[coll][id] = envelope\n }\n }\n }\n\n return merged\n}\n\n// ─── Factory helper ─────────────────────────────────────────────────────\n\n/**\n * Type-safe factory helper for `NoydbPodStore` implementations,\n * analogous to `createStore` for KV stores.\n */\nexport function createPodStore<TOptions>(\n factory: (options: TOptions) => NoydbPodStore,\n): (options: TOptions) => NoydbPodStore {\n return factory\n}\n\n// ─── Deprecated aliases (pre-rename compatibility) ──────────────────────\n\n/** @deprecated Use wrapPodStore. */\nexport const wrapBundleStore = wrapPodStore\n/** @deprecated Use createPodStore. */\nexport const createBundleStore = createPodStore\n/** @deprecated Use WrappedPodNoydbStore. */\nexport type WrappedBundleNoydbStore = WrappedPodNoydbStore\n/** @deprecated Use WrapPodStoreOptions. */\nexport type WrapBundleStoreOptions = WrapPodStoreOptions\n"],"mappings":"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","names":[]}
|
|
@@ -399,7 +399,7 @@ async function createOwnerOnAdoptedPartition(store, vaultName, opts) {
|
|
|
399
399
|
}
|
|
400
400
|
}
|
|
401
401
|
if (isManaged(opts)) {
|
|
402
|
-
const { createNoydb } = await import("./noydb-
|
|
402
|
+
const { createNoydb } = await import("./noydb-LPUMSDBR.js");
|
|
403
403
|
const db = await createNoydb({
|
|
404
404
|
store,
|
|
405
405
|
user: userId,
|
|
@@ -455,4 +455,4 @@ export {
|
|
|
455
455
|
withCargo,
|
|
456
456
|
describeExtraction
|
|
457
457
|
};
|
|
458
|
-
//# sourceMappingURL=chunk-
|
|
458
|
+
//# sourceMappingURL=chunk-DSJG26FE.js.map
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hashFields,
|
|
3
|
+
validateSatelliteDeclaration
|
|
4
|
+
} from "./chunk-SHEEBRZ4.js";
|
|
1
5
|
import {
|
|
2
6
|
resolveStaleOnRead
|
|
3
7
|
} from "./chunk-NJ4DYYO5.js";
|
|
@@ -8,9 +12,9 @@ import {
|
|
|
8
12
|
linkRowKey
|
|
9
13
|
} from "./chunk-4JQK3L4V.js";
|
|
10
14
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "./chunk-
|
|
15
|
+
isBaseLive,
|
|
16
|
+
liveBaseIdSet
|
|
17
|
+
} from "./chunk-GYGLAVCX.js";
|
|
14
18
|
import {
|
|
15
19
|
loadFence
|
|
16
20
|
} from "./chunk-LNZKOUJR.js";
|
|
@@ -24,9 +28,10 @@ import {
|
|
|
24
28
|
SchemaUpdateGate
|
|
25
29
|
} from "./chunk-6LJY7X5A.js";
|
|
26
30
|
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
NO_CLASSIFIED,
|
|
32
|
+
guardClassifiedCompat,
|
|
33
|
+
resolveClassifiedFields
|
|
34
|
+
} from "./chunk-EE7UHLKH.js";
|
|
30
35
|
import {
|
|
31
36
|
NO_TIERS,
|
|
32
37
|
classifySealedShred,
|
|
@@ -50,6 +55,10 @@ import {
|
|
|
50
55
|
derivePersistedSchema,
|
|
51
56
|
isZod4Schema
|
|
52
57
|
} from "./chunk-6ZNSB3H6.js";
|
|
58
|
+
import {
|
|
59
|
+
CustodyApi,
|
|
60
|
+
NO_CUSTODY
|
|
61
|
+
} from "./chunk-YWWQM7KP.js";
|
|
53
62
|
import {
|
|
54
63
|
DEFAULT_POSTURE,
|
|
55
64
|
ViaGraph
|
|
@@ -89,10 +98,8 @@ import {
|
|
|
89
98
|
NO_ATTESTATION
|
|
90
99
|
} from "./chunk-5GQEU4DN.js";
|
|
91
100
|
import {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
resolveClassifiedFields
|
|
95
|
-
} from "./chunk-EE7UHLKH.js";
|
|
101
|
+
NO_CONSENT
|
|
102
|
+
} from "./chunk-PEOZ34EM.js";
|
|
96
103
|
import {
|
|
97
104
|
NO_PERIODS
|
|
98
105
|
} from "./chunk-UDHBXYGG.js";
|
|
@@ -128,10 +135,6 @@ import {
|
|
|
128
135
|
compileSequenceFormat,
|
|
129
136
|
resolveSequenceKey
|
|
130
137
|
} from "./chunk-L2DGWBCT.js";
|
|
131
|
-
import {
|
|
132
|
-
CustodyApi,
|
|
133
|
-
NO_CUSTODY
|
|
134
|
-
} from "./chunk-YWWQM7KP.js";
|
|
135
138
|
import {
|
|
136
139
|
Query,
|
|
137
140
|
ScanBuilder
|
|
@@ -165,9 +168,6 @@ import {
|
|
|
165
168
|
import {
|
|
166
169
|
NO_CRDT
|
|
167
170
|
} from "./chunk-PVEWA2DU.js";
|
|
168
|
-
import {
|
|
169
|
-
NO_CONSENT
|
|
170
|
-
} from "./chunk-PEOZ34EM.js";
|
|
171
171
|
import {
|
|
172
172
|
dictCollectionName
|
|
173
173
|
} from "./chunk-FRMPM7WG.js";
|
|
@@ -13923,4 +13923,4 @@ export {
|
|
|
13923
13923
|
Noydb,
|
|
13924
13924
|
createNoydb
|
|
13925
13925
|
};
|
|
13926
|
-
//# sourceMappingURL=chunk-
|
|
13926
|
+
//# sourceMappingURL=chunk-Q54PXSQL.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DebugPlaintextError,
|
|
3
|
+
DebugReservedFieldError
|
|
4
|
+
} from "../chunk-QZWTRENR.js";
|
|
5
|
+
import "../chunk-PZ5AY32C.js";
|
|
6
|
+
|
|
7
|
+
// src/kernel/debug.ts
|
|
8
|
+
function readPlaintextRecord(envelope) {
|
|
9
|
+
if (envelope._iv !== "") {
|
|
10
|
+
throw new Error(
|
|
11
|
+
"readPlaintextRecord: envelope is encrypted (non-empty _iv) \u2014 decrypt via the vault, not this helper"
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
if (envelope._debug !== void 0) {
|
|
15
|
+
const record = {};
|
|
16
|
+
for (const [key, value] of Object.entries(envelope)) {
|
|
17
|
+
if (!key.startsWith("_")) record[key] = value;
|
|
18
|
+
}
|
|
19
|
+
return record;
|
|
20
|
+
}
|
|
21
|
+
if (!envelope._data) return null;
|
|
22
|
+
return JSON.parse(envelope._data);
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
DebugPlaintextError,
|
|
26
|
+
DebugReservedFieldError,
|
|
27
|
+
readPlaintextRecord
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/kernel/debug.ts"],"sourcesContent":["/**\n * Helpers for reading records out of a *plaintext* store (`encrypt: false`)\n * with native tooling — the programmatic core of a `noydb cat`-style unwrap.\n * See the plaintext/debug-store-mode design.\n */\nimport type { EncryptedEnvelope } from './types.js'\n\n/**\n * The option's two failure modes, re-exported here so a consumer can `catch`\n * them by identity (#914). Both are thrown from the kernel — `createNoydb`\n * raises `DebugPlaintextError` when `debugPlaintext` is combined with\n * encryption, and the record codec raises `DebugReservedFieldError` for a\n * field colliding with the `_`-prefixed metadata. This entry is the only one\n * that publishes them.\n */\nexport { DebugPlaintextError, DebugReservedFieldError } from './errors.js'\n\n/** Re-exported so `readPlaintextRecord`'s parameter is nameable from this entry. */\nexport type { EncryptedEnvelope } from './types.js'\n\n/**\n * Extract the record from a plaintext stored envelope, handling both layouts:\n *\n * - **classic plaintext** (`encrypt: false`): the record is JSON in `_data`.\n * - **debugPlaintext**: the record's fields are inlined beside the\n * `_`-prefixed metadata (marked by `_debug`).\n *\n * Returns `null` for an empty/absent body. Throws if handed an **encrypted**\n * envelope (non-empty `_iv`) — there is no key here; decrypt through the vault\n * instead. Intended for record envelopes, not blob chunks.\n *\n * @example\n * ```ts\n * // node script over a to-file store, no vault needed:\n * const env = JSON.parse(readFileSync('data/acme/invoices/inv-1.json', 'utf8'))\n * console.log(readPlaintextRecord(env)) // → { id: 'inv-1', total: '120.00', … }\n * ```\n */\nexport function readPlaintextRecord<T = Record<string, unknown>>(\n envelope: EncryptedEnvelope,\n): T | null {\n if (envelope._iv !== '') {\n throw new Error(\n 'readPlaintextRecord: envelope is encrypted (non-empty _iv) — decrypt via the vault, not this helper',\n )\n }\n if (envelope._debug !== undefined) {\n const record: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(envelope)) {\n if (!key.startsWith('_')) record[key] = value\n }\n return record as T\n }\n if (!envelope._data) return null\n return JSON.parse(envelope._data) as T\n}\n"],"mappings":";;;;;;;AAsCO,SAAS,oBACd,UACU;AACV,MAAI,SAAS,QAAQ,IAAI;AACvB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,SAAS,WAAW,QAAW;AACjC,UAAM,SAAkC,CAAC;AACzC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,UAAI,CAAC,IAAI,WAAW,GAAG,EAAG,QAAO,GAAG,IAAI;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AACA,MAAI,CAAC,SAAS,MAAO,QAAO;AAC5B,SAAO,KAAK,MAAM,SAAS,KAAK;AAClC;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
refArray,
|
|
17
17
|
via,
|
|
18
18
|
withArchive
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-Q54PXSQL.js";
|
|
20
|
+
import "./chunk-SHEEBRZ4.js";
|
|
20
21
|
import "./chunk-NJ4DYYO5.js";
|
|
21
22
|
import {
|
|
22
23
|
persistSchemaIfNeeded
|
|
@@ -28,11 +29,11 @@ import {
|
|
|
28
29
|
LinkIntegrityError,
|
|
29
30
|
isLinkCollectionName
|
|
30
31
|
} from "./chunk-4JQK3L4V.js";
|
|
31
|
-
import "./chunk-SHEEBRZ4.js";
|
|
32
32
|
import {
|
|
33
33
|
ComputedFieldError,
|
|
34
34
|
evalComputedFields
|
|
35
35
|
} from "./chunk-5DRROK5W.js";
|
|
36
|
+
import "./chunk-GYGLAVCX.js";
|
|
36
37
|
import {
|
|
37
38
|
WithdrawalRequestError,
|
|
38
39
|
approveWithdrawal,
|
|
@@ -42,6 +43,19 @@ import {
|
|
|
42
43
|
} from "./chunk-HMU5P6RL.js";
|
|
43
44
|
import "./chunk-LNZKOUJR.js";
|
|
44
45
|
import "./chunk-7YVBQJ7K.js";
|
|
46
|
+
import {
|
|
47
|
+
MoneyCurrencyError,
|
|
48
|
+
MoneyPrecisionError,
|
|
49
|
+
MoneyUnsupportedError,
|
|
50
|
+
allocate,
|
|
51
|
+
asMoney,
|
|
52
|
+
isMoneyDescriptor,
|
|
53
|
+
isMoneyString,
|
|
54
|
+
money,
|
|
55
|
+
moneyNumber,
|
|
56
|
+
mulRate,
|
|
57
|
+
scaleForCurrency
|
|
58
|
+
} from "./chunk-SGDPRCC4.js";
|
|
45
59
|
import {
|
|
46
60
|
COVER_FIELDS,
|
|
47
61
|
DEFAULT_COVER_SCHEMA,
|
|
@@ -67,14 +81,24 @@ import "./chunk-GJW4HX2O.js";
|
|
|
67
81
|
import {
|
|
68
82
|
UserApi
|
|
69
83
|
} from "./chunk-DABACXEF.js";
|
|
70
|
-
import
|
|
84
|
+
import {
|
|
85
|
+
classified,
|
|
86
|
+
luhnCheck
|
|
87
|
+
} from "./chunk-GU3IP74F.js";
|
|
88
|
+
import {
|
|
89
|
+
ClassifiedNeverStoredError,
|
|
90
|
+
ClassifiedValidationError,
|
|
91
|
+
isClassifiedFieldSpec,
|
|
92
|
+
isClassifiedGroup,
|
|
93
|
+
resolveClassifiedFields
|
|
94
|
+
} from "./chunk-EE7UHLKH.js";
|
|
71
95
|
import "./chunk-Y2NJBNX3.js";
|
|
72
96
|
import "./chunk-BLBAQRBM.js";
|
|
73
97
|
import {
|
|
74
98
|
decryptExtractedPartition,
|
|
75
99
|
diffVault,
|
|
76
100
|
withCargo
|
|
77
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-DSJG26FE.js";
|
|
78
102
|
import {
|
|
79
103
|
NO_CARGO
|
|
80
104
|
} from "./chunk-TG634KCO.js";
|
|
@@ -123,18 +147,10 @@ import {
|
|
|
123
147
|
savePersistedSchema
|
|
124
148
|
} from "./chunk-DMH3VZU5.js";
|
|
125
149
|
import {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
asMoney,
|
|
131
|
-
isMoneyDescriptor,
|
|
132
|
-
isMoneyString,
|
|
133
|
-
money,
|
|
134
|
-
moneyNumber,
|
|
135
|
-
mulRate,
|
|
136
|
-
scaleForCurrency
|
|
137
|
-
} from "./chunk-SGDPRCC4.js";
|
|
150
|
+
CustodyApi,
|
|
151
|
+
NO_CUSTODY,
|
|
152
|
+
withCustody
|
|
153
|
+
} from "./chunk-YWWQM7KP.js";
|
|
138
154
|
import {
|
|
139
155
|
withDerivation,
|
|
140
156
|
withRollup
|
|
@@ -145,12 +161,12 @@ import "./chunk-MHMLXJ3I.js";
|
|
|
145
161
|
import {
|
|
146
162
|
withMaterializedView
|
|
147
163
|
} from "./chunk-MXUT7FTE.js";
|
|
164
|
+
import "./chunk-IYZISPGD.js";
|
|
148
165
|
import "./chunk-N4BBNYIB.js";
|
|
149
166
|
import {
|
|
150
167
|
buildLookupSnapshot
|
|
151
168
|
} from "./chunk-IPUG56GJ.js";
|
|
152
169
|
import "./chunk-3HUYRN24.js";
|
|
153
|
-
import "./chunk-IYZISPGD.js";
|
|
154
170
|
import {
|
|
155
171
|
withOverlayedView
|
|
156
172
|
} from "./chunk-MSMJJB4J.js";
|
|
@@ -172,16 +188,9 @@ import {
|
|
|
172
188
|
} from "./chunk-PY4KJPYU.js";
|
|
173
189
|
import "./chunk-5GQEU4DN.js";
|
|
174
190
|
import {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
import {
|
|
179
|
-
ClassifiedNeverStoredError,
|
|
180
|
-
ClassifiedValidationError,
|
|
181
|
-
isClassifiedFieldSpec,
|
|
182
|
-
isClassifiedGroup,
|
|
183
|
-
resolveClassifiedFields
|
|
184
|
-
} from "./chunk-EE7UHLKH.js";
|
|
191
|
+
CONSENT_AUDIT_COLLECTION
|
|
192
|
+
} from "./chunk-EKRSCRNM.js";
|
|
193
|
+
import "./chunk-PEOZ34EM.js";
|
|
185
194
|
import "./chunk-QDIH2744.js";
|
|
186
195
|
import "./chunk-UDHBXYGG.js";
|
|
187
196
|
import "./chunk-GHVIKOHT.js";
|
|
@@ -224,11 +233,6 @@ import {
|
|
|
224
233
|
resolveSequenceKey,
|
|
225
234
|
withSequence
|
|
226
235
|
} from "./chunk-L2DGWBCT.js";
|
|
227
|
-
import {
|
|
228
|
-
CustodyApi,
|
|
229
|
-
NO_CUSTODY,
|
|
230
|
-
withCustody
|
|
231
|
-
} from "./chunk-YWWQM7KP.js";
|
|
232
236
|
import {
|
|
233
237
|
DEFAULT_CROSS_JOIN_MAX_ROWS,
|
|
234
238
|
Query,
|
|
@@ -293,7 +297,7 @@ import {
|
|
|
293
297
|
createPodStore,
|
|
294
298
|
wrapBundleStore,
|
|
295
299
|
wrapPodStore
|
|
296
|
-
} from "./chunk-
|
|
300
|
+
} from "./chunk-2J6UEN2V.js";
|
|
297
301
|
import {
|
|
298
302
|
NOYDB_BUNDLE_FORMAT_VERSION,
|
|
299
303
|
NOYDB_BUNDLE_MAGIC,
|
|
@@ -315,10 +319,6 @@ import {
|
|
|
315
319
|
saveCover,
|
|
316
320
|
validateCoverInput
|
|
317
321
|
} from "./chunk-TUXQSFHZ.js";
|
|
318
|
-
import {
|
|
319
|
-
CONSENT_AUDIT_COLLECTION
|
|
320
|
-
} from "./chunk-EKRSCRNM.js";
|
|
321
|
-
import "./chunk-PEOZ34EM.js";
|
|
322
322
|
import "./chunk-X3F5YJG2.js";
|
|
323
323
|
import {
|
|
324
324
|
dictKey,
|
package/dist/kernel/debug.d.ts
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
* See the plaintext/debug-store-mode design.
|
|
5
5
|
*/
|
|
6
6
|
import type { EncryptedEnvelope } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* The option's two failure modes, re-exported here so a consumer can `catch`
|
|
9
|
+
* them by identity (#914). Both are thrown from the kernel — `createNoydb`
|
|
10
|
+
* raises `DebugPlaintextError` when `debugPlaintext` is combined with
|
|
11
|
+
* encryption, and the record codec raises `DebugReservedFieldError` for a
|
|
12
|
+
* field colliding with the `_`-prefixed metadata. This entry is the only one
|
|
13
|
+
* that publishes them.
|
|
14
|
+
*/
|
|
15
|
+
export { DebugPlaintextError, DebugReservedFieldError } from './errors.js';
|
|
16
|
+
/** Re-exported so `readPlaintextRecord`'s parameter is nameable from this entry. */
|
|
17
|
+
export type { EncryptedEnvelope } from './types.js';
|
|
7
18
|
/**
|
|
8
19
|
* Extract the record from a plaintext stored envelope, handling both layouts:
|
|
9
20
|
*
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
withMaterializedView
|
|
3
3
|
} from "../chunk-MXUT7FTE.js";
|
|
4
|
+
import {
|
|
5
|
+
clearMVStale,
|
|
6
|
+
isMVStale,
|
|
7
|
+
markMVStale,
|
|
8
|
+
resolveStaleMVOnRead
|
|
9
|
+
} from "../chunk-IYZISPGD.js";
|
|
4
10
|
import {
|
|
5
11
|
MaterializedViewExecutor
|
|
6
12
|
} from "../chunk-N4BBNYIB.js";
|
|
@@ -12,12 +18,6 @@ import {
|
|
|
12
18
|
computeQueryHash,
|
|
13
19
|
summarizeQueryPlan
|
|
14
20
|
} from "../chunk-3HUYRN24.js";
|
|
15
|
-
import {
|
|
16
|
-
clearMVStale,
|
|
17
|
-
isMVStale,
|
|
18
|
-
markMVStale,
|
|
19
|
-
resolveStaleMVOnRead
|
|
20
|
-
} from "../chunk-IYZISPGD.js";
|
|
21
21
|
import "../chunk-5D2ALSM5.js";
|
|
22
22
|
import "../chunk-V6UQZA2H.js";
|
|
23
23
|
import "../chunk-KRCBZYTZ.js";
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Noydb,
|
|
3
3
|
createNoydb
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Q54PXSQL.js";
|
|
5
|
+
import "./chunk-SHEEBRZ4.js";
|
|
5
6
|
import "./chunk-NJ4DYYO5.js";
|
|
6
7
|
import "./chunk-4JQK3L4V.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-GYGLAVCX.js";
|
|
8
9
|
import "./chunk-LNZKOUJR.js";
|
|
9
10
|
import "./chunk-7YVBQJ7K.js";
|
|
10
11
|
import "./chunk-6LJY7X5A.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-EE7UHLKH.js";
|
|
12
13
|
import "./chunk-Y2NJBNX3.js";
|
|
13
14
|
import "./chunk-BLBAQRBM.js";
|
|
14
15
|
import "./chunk-TG634KCO.js";
|
|
@@ -16,12 +17,13 @@ import "./chunk-FQZ6XTQ7.js";
|
|
|
16
17
|
import "./chunk-VYYM3MEN.js";
|
|
17
18
|
import "./chunk-6ZNSB3H6.js";
|
|
18
19
|
import "./chunk-Y2NBBT6K.js";
|
|
20
|
+
import "./chunk-YWWQM7KP.js";
|
|
19
21
|
import "./chunk-4ZKNC6A6.js";
|
|
20
22
|
import "./chunk-IPUG56GJ.js";
|
|
21
23
|
import "./chunk-ZTLOXFPB.js";
|
|
22
24
|
import "./chunk-55LKVALY.js";
|
|
23
25
|
import "./chunk-5GQEU4DN.js";
|
|
24
|
-
import "./chunk-
|
|
26
|
+
import "./chunk-PEOZ34EM.js";
|
|
25
27
|
import "./chunk-UDHBXYGG.js";
|
|
26
28
|
import "./chunk-GHVIKOHT.js";
|
|
27
29
|
import "./chunk-NM5UYF6Q.js";
|
|
@@ -32,7 +34,6 @@ import "./chunk-5D2ALSM5.js";
|
|
|
32
34
|
import "./chunk-MCHBCNCE.js";
|
|
33
35
|
import "./chunk-AURFOK3D.js";
|
|
34
36
|
import "./chunk-L2DGWBCT.js";
|
|
35
|
-
import "./chunk-YWWQM7KP.js";
|
|
36
37
|
import "./chunk-WBKZUO5V.js";
|
|
37
38
|
import "./chunk-V6UQZA2H.js";
|
|
38
39
|
import "./chunk-CXQW2NWO.js";
|
|
@@ -44,7 +45,6 @@ import "./chunk-YMUFFJCO.js";
|
|
|
44
45
|
import "./chunk-CADUYBQD.js";
|
|
45
46
|
import "./chunk-IGJCYUT5.js";
|
|
46
47
|
import "./chunk-PVEWA2DU.js";
|
|
47
|
-
import "./chunk-PEOZ34EM.js";
|
|
48
48
|
import "./chunk-W3G5REIU.js";
|
|
49
49
|
import "./chunk-FRMPM7WG.js";
|
|
50
50
|
import "./chunk-UADPR6F4.js";
|
|
@@ -78,4 +78,4 @@ export {
|
|
|
78
78
|
Noydb,
|
|
79
79
|
createNoydb
|
|
80
80
|
};
|
|
81
|
-
//# sourceMappingURL=noydb-
|
|
81
|
+
//# sourceMappingURL=noydb-LPUMSDBR.js.map
|
package/dist/pod/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noy-db/hub",
|
|
3
|
-
"version": "0.4.0-pre.
|
|
3
|
+
"version": "0.4.0-pre.12",
|
|
4
4
|
"description": "Zero-knowledge, offline-first, encrypted document store — core library with AES-256-GCM, PBKDF2, multi-user keyring, and sync engine",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "vLannaAi <vicio@lanna.ai>",
|
|
@@ -52,6 +52,10 @@
|
|
|
52
52
|
"types": "./dist/kernel/query/index.d.ts",
|
|
53
53
|
"default": "./dist/query/index.js"
|
|
54
54
|
},
|
|
55
|
+
"./debug": {
|
|
56
|
+
"types": "./dist/kernel/debug.d.ts",
|
|
57
|
+
"default": "./dist/debug/index.js"
|
|
58
|
+
},
|
|
55
59
|
"./blobs": {
|
|
56
60
|
"types": "./dist/via/blob/index.d.ts",
|
|
57
61
|
"default": "./dist/blobs/index.js"
|
|
@@ -204,14 +208,14 @@
|
|
|
204
208
|
"node": ">=22.0.0"
|
|
205
209
|
},
|
|
206
210
|
"dependencies": {
|
|
207
|
-
"@noy-db/attestation": "0.4.0-pre.
|
|
211
|
+
"@noy-db/attestation": "0.4.0-pre.12"
|
|
208
212
|
},
|
|
209
213
|
"devDependencies": {
|
|
210
214
|
"@types/node": "^22.0.0",
|
|
211
215
|
"esbuild": "^0.25.0",
|
|
212
216
|
"zod": "^4.0.0",
|
|
213
217
|
"zod-to-json-schema": "^3.25.2",
|
|
214
|
-
"@noy-db/on-shamir": "0.4.0-pre.
|
|
218
|
+
"@noy-db/on-shamir": "0.4.0-pre.12"
|
|
215
219
|
},
|
|
216
220
|
"peerDependencies": {
|
|
217
221
|
"zod-to-json-schema": "^3.25.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-pod/pod-store.ts"],"sourcesContent":["import type { NoydbStore, NoydbPodStore, VaultSnapshot, EncryptedEnvelope } from '../kernel/types.js'\nimport { ConflictError, PodVersionConflictError } from '../kernel/errors.js'\n\n// ─── Bundle format ─────────────────────────────────────────────────────\n\nconst BUNDLE_STORE_VERSION = 1 as const\n\n/**\n * Wire format written by `wrapPodStore`. A JSON-serialised object that\n * contains the entire `VaultSnapshot` (all encrypted envelopes) plus a small\n * header for integrity checking. The envelopes inside are already AES-GCM\n * encrypted by core — the bundle bytes themselves are not additionally\n * encrypted, but they are safe to store on untrusted blob hosts because\n * every record inside is already ciphertext.\n *\n * @internal\n */\ninterface BundleStoreData {\n readonly _noydb_bundle_store: typeof BUNDLE_STORE_VERSION\n readonly vault: string\n readonly ts: string\n readonly data: VaultSnapshot\n}\n\n// ─── Options ───────────────────────────────────────────────────────────\n\nexport interface WrapPodStoreOptions {\n /**\n * When `true` (default), every `put()` and `delete()` flushes the full\n * vault snapshot to the bundle backend. Set to `false` for bulk operations\n * and call `store.flush(vaultId)` manually.\n */\n autoFlush?: boolean\n}\n\n// ─── Extended NoydbStore with flush/batch ───────────────────────────────\n\nexport interface WrappedPodNoydbStore extends NoydbStore {\n /** Manually flush the in-memory snapshot to the bundle backend. */\n flush(vaultId: string): Promise<void>\n /**\n * Run a batch of mutations without flushing until the callback completes.\n * A single flush is performed at the end.\n */\n batch(vaultId: string, fn: () => Promise<void>): Promise<void>\n}\n\n// ─── wrapPodStore ───────────────────────────────────────────────────\n\nconst MAX_CONFLICT_RETRIES = 3\n\n/**\n * Convert a `NoydbPodStore` (blob-oriented read/write with OCC) into the\n * standard six-method `NoydbStore` interface expected by `createNoydb({ store })`.\n *\n * Bundle stores operate on the entire vault as a single serialised unit —\n * ideal for backends like Google Drive, WebDAV, or iCloud Drive that work\n * best with whole-file I/O rather than per-record KV operations.\n *\n * ## Optimistic concurrency\n *\n * The wrapper tracks the `version` token from the last `readBundle` and\n * passes it as `expectedVersion` on every flush. On\n * `PodVersionConflictError`, it re-reads, merges the remote snapshot\n * (last-write-wins per record key), and retries (max 3 attempts).\n *\n * ## Flush modes\n *\n * By default, flushes on every mutation (O(vault size) per write). Options:\n * - `autoFlush: false` + explicit `store.flush(vaultId)` calls\n * - `store.batch(vaultId, async () => { ... })` — defers flush until end\n * - Pair with `syncPolicy: { push: { mode: 'debounce' } }` from \n */\nexport function wrapPodStore(\n bundle: NoydbPodStore,\n options?: WrapPodStoreOptions,\n): WrappedPodNoydbStore {\n const autoFlush = options?.autoFlush !== false\n\n // Per-vault state\n const snapshots = new Map<string, VaultSnapshot>()\n const versions = new Map<string, string | null>()\n const loaded = new Set<string>()\n\n // Batch mode: when > 0, suppress auto-flush\n let batchDepth = 0\n\n async function load(vault: string): Promise<VaultSnapshot> {\n if (loaded.has(vault)) return snapshots.get(vault)!\n\n const result = await bundle.readBundle(vault)\n if (result) {\n const text = new TextDecoder().decode(result.bytes)\n const format = JSON.parse(text) as BundleStoreData\n snapshots.set(vault, format.data)\n versions.set(vault, result.version)\n } else {\n snapshots.set(vault, {})\n versions.set(vault, null)\n }\n\n loaded.add(vault)\n return snapshots.get(vault)!\n }\n\n async function flush(vault: string): Promise<void> {\n const snapshot = snapshots.get(vault) ?? {}\n const format: BundleStoreData = {\n _noydb_bundle_store: BUNDLE_STORE_VERSION,\n vault,\n ts: new Date().toISOString(),\n data: snapshot,\n }\n const bytes = new TextEncoder().encode(JSON.stringify(format))\n const expectedVersion = versions.get(vault) ?? null\n\n for (let attempt = 0; attempt < MAX_CONFLICT_RETRIES; attempt++) {\n try {\n const { version: newVersion } = await bundle.writeBundle(vault, bytes, expectedVersion)\n versions.set(vault, newVersion)\n return\n } catch (err) {\n if (err instanceof PodVersionConflictError && attempt < MAX_CONFLICT_RETRIES - 1) {\n // Pull remote, merge (last-write-wins by record key), retry\n const remote = await bundle.readBundle(vault)\n if (remote) {\n const remoteText = new TextDecoder().decode(remote.bytes)\n const remoteFormat = JSON.parse(remoteText) as BundleStoreData\n const localSnap = snapshots.get(vault) ?? {}\n const mergedSnap = mergeSnapshots(remoteFormat.data, localSnap)\n snapshots.set(vault, mergedSnap)\n versions.set(vault, remote.version)\n }\n // Re-encode with merged data for the retry\n continue\n }\n throw err\n }\n }\n }\n\n async function maybeFlush(vault: string): Promise<void> {\n if (autoFlush && batchDepth === 0) {\n await flush(vault)\n }\n }\n\n const store: WrappedPodNoydbStore = {\n name: bundle.name ?? 'bundle',\n\n async flush(vaultId: string): Promise<void> {\n await flush(vaultId)\n },\n\n async batch(vaultId: string, fn: () => Promise<void>): Promise<void> {\n await load(vaultId) // ensure loaded before batch\n batchDepth++\n try {\n await fn()\n } finally {\n batchDepth--\n }\n await flush(vaultId)\n },\n\n async get(vault: string, collection: string, id: string): Promise<EncryptedEnvelope | null> {\n const snap = await load(vault)\n return snap[collection]?.[id] ?? null\n },\n\n async put(\n vault: string,\n collection: string,\n id: string,\n envelope: EncryptedEnvelope,\n expectedVersion?: number,\n ): Promise<void> {\n const snap = await load(vault)\n\n if (expectedVersion !== undefined) {\n const current = snap[collection]?.[id]\n const currentVersion = current?._v ?? 0\n if (currentVersion !== expectedVersion) {\n throw new ConflictError(\n currentVersion,\n `Expected version ${expectedVersion} but found ${currentVersion} on ${collection}/${id}`,\n )\n }\n }\n\n snap[collection] ??= {}\n snap[collection][id] = envelope\n await maybeFlush(vault)\n },\n\n async delete(vault: string, collection: string, id: string): Promise<void> {\n const snap = await load(vault)\n if (snap[collection]) {\n delete snap[collection][id]\n await maybeFlush(vault)\n }\n },\n\n async list(vault: string, collection: string): Promise<string[]> {\n const snap = await load(vault)\n return Object.keys(snap[collection] ?? {})\n },\n\n async loadAll(vault: string): Promise<VaultSnapshot> {\n return await load(vault)\n },\n\n async saveAll(vault: string, data: VaultSnapshot): Promise<void> {\n snapshots.set(vault, data)\n loaded.add(vault)\n await flush(vault)\n },\n }\n\n return store\n}\n\n// ─── Snapshot merge (last-write-wins per record) ────────────────────────\n\nfunction mergeSnapshots(remote: VaultSnapshot, local: VaultSnapshot): VaultSnapshot {\n const merged: VaultSnapshot = {}\n\n // Start with all remote collections\n for (const [coll, records] of Object.entries(remote)) {\n merged[coll] = { ...records }\n }\n\n // Overlay local collections — LWW by _ts per record\n for (const [coll, records] of Object.entries(local)) {\n if (!merged[coll]) {\n merged[coll] = { ...records }\n continue\n }\n for (const [id, envelope] of Object.entries(records)) {\n const existing = merged[coll][id]\n if (!existing || envelope._ts >= existing._ts) {\n merged[coll][id] = envelope\n }\n }\n }\n\n return merged\n}\n\n// ─── Factory helper ─────────────────────────────────────────────────────\n\n/**\n * Type-safe factory helper for `NoydbPodStore` implementations,\n * analogous to `createStore` for KV stores.\n */\nexport function createPodStore<TOptions>(\n factory: (options: TOptions) => NoydbPodStore,\n): (options: TOptions) => NoydbPodStore {\n return factory\n}\n\n// ─── Deprecated aliases (pre-rename compatibility) ──────────────────────\n\n/** @deprecated Use wrapPodStore. */\nexport const wrapBundleStore = wrapPodStore\n/** @deprecated Use createPodStore. */\nexport const createBundleStore = createPodStore\n/** @deprecated Use WrappedPodNoydbStore. */\nexport type WrappedBundleNoydbStore = WrappedPodNoydbStore\n/** @deprecated Use WrapPodStoreOptions. */\nexport type WrapBundleStoreOptions = WrapPodStoreOptions\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|