@noy-db/hub 0.2.0-pre.26 → 0.2.0-pre.27
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/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +1 -1
- package/dist/attestation/index.d.ts +1 -1
- package/dist/attestation/index.js +4 -4
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +3 -3
- package/dist/blobs/index.d.ts +3 -3
- package/dist/blobs/index.js +4 -4
- package/dist/bundle/index.cjs +320 -144
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +3 -3
- package/dist/bundle/index.d.ts +3 -3
- package/dist/bundle/index.js +8 -8
- package/dist/{chunk-HUXDQIVU.js → chunk-2NYVA6FW.js} +2 -2
- package/dist/{chunk-OCRDV3NU.js → chunk-5EITJMUJ.js} +3 -3
- package/dist/{chunk-EYZJULEN.js → chunk-6H4CAHMQ.js} +2 -2
- package/dist/{chunk-VGAN5RLD.js → chunk-6M5JKTUQ.js} +2 -2
- package/dist/{chunk-N4EXCKWP.js → chunk-6ZKXFMUG.js} +2 -2
- package/dist/{chunk-KJ37E3R5.js → chunk-7DDTFGXY.js} +2 -2
- package/dist/{chunk-LR7CODVN.js → chunk-AD6RNBAW.js} +1 -1
- package/dist/chunk-AD6RNBAW.js.map +1 -0
- package/dist/{chunk-TSUICI5N.js → chunk-BMDVFBCL.js} +2 -2
- package/dist/{chunk-FCIZXX56.js → chunk-BOMH3637.js} +2 -2
- package/dist/{chunk-RZOGD7IF.js → chunk-CVTPNW2Y.js} +6 -6
- package/dist/{chunk-GPZHHTJU.js → chunk-DONPLWRC.js} +2 -2
- package/dist/{chunk-GHXOVGTX.js → chunk-HAKEZTA7.js} +3 -3
- package/dist/{chunk-QYQRAOEF.js → chunk-I2RX62RX.js} +2 -2
- package/dist/{chunk-2RHBFCWQ.js → chunk-IWGVH2RR.js} +3 -3
- package/dist/{chunk-Y5CTT6K5.js → chunk-K6PCTYAH.js} +2 -2
- package/dist/{chunk-ANLOD6IS.js → chunk-KA5A5CSD.js} +3 -3
- package/dist/{chunk-56ENKU46.js → chunk-KSKKLVPA.js} +97 -144
- package/dist/chunk-KSKKLVPA.js.map +1 -0
- package/dist/{chunk-UNBX2HMA.js → chunk-LXA2E3VI.js} +2 -2
- package/dist/{chunk-JJKXJAH2.js → chunk-PFKAT4NT.js} +3 -3
- package/dist/{chunk-ZCBJIDT4.js → chunk-RRCRITDM.js} +2 -2
- package/dist/{chunk-YP2AYE5W.js → chunk-SID2NJNF.js} +2 -2
- package/dist/chunk-Z3BJF7SF.js +220 -0
- package/dist/chunk-Z3BJF7SF.js.map +1 -0
- package/dist/consent/index.d.cts +2 -2
- package/dist/consent/index.d.ts +2 -2
- package/dist/{decrypt-partition-CyyJUWLR.d.ts → decrypt-partition-CptDdcCx.d.ts} +1 -1
- package/dist/{decrypt-partition-C71vhnND.d.cts → decrypt-partition-DmkeOB4I.d.cts} +1 -1
- package/dist/derivations/index.d.cts +3 -3
- package/dist/derivations/index.d.ts +3 -3
- package/dist/{dev-unlock-BdrE0kbS.d.cts → dev-unlock-DUTLA3Sc.d.cts} +1 -1
- package/dist/{dev-unlock-ByBkl99-.d.ts → dev-unlock-Y9znMkQ2.d.ts} +1 -1
- package/dist/{fanout-sidecar-ZQT4Y7PF.js → fanout-sidecar-OC4QVTS2.js} +2 -2
- package/dist/forget/index.js +2 -2
- package/dist/guards/index.d.cts +3 -3
- package/dist/guards/index.d.ts +3 -3
- package/dist/{hash-CZxVv8RH.d.ts → hash-Btl9IvQS.d.ts} +1 -1
- package/dist/{hash-BUkDp_8Q.d.cts → hash-DFK7cGdo.d.cts} +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +3 -3
- package/dist/history/index.d.ts +3 -3
- package/dist/history/index.js +3 -3
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +2 -2
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +3 -3
- package/dist/{index-CBUhOmrM.d.cts → index-CqzZml-D.d.cts} +1 -1
- package/dist/{index-DFhKV-6A.d.ts → index-wRwJVVJQ.d.ts} +1 -1
- package/dist/index.cjs +316 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +19 -18
- package/dist/index.js.map +1 -1
- package/dist/{issue-LEBPVF3Y.js → issue-ZZ2XPOGP.js} +4 -4
- package/dist/kernel/index.cjs +61 -0
- package/dist/kernel/index.cjs.map +1 -1
- package/dist/kernel/index.d.cts +2 -2
- package/dist/kernel/index.d.ts +2 -2
- package/dist/kernel/index.js +7 -0
- package/dist/{ledger-FLRTSOYH.js → ledger-XQ4KVFQ6.js} +3 -3
- package/dist/materialized-views/index.d.cts +3 -3
- package/dist/materialized-views/index.d.ts +3 -3
- package/dist/{mime-magic-BAhLjkHw.d.cts → mime-magic-Co4Pyj-O.d.cts} +1 -1
- package/dist/{mime-magic-C1UbcBxP.d.ts → mime-magic-OiPT1qed.d.ts} +1 -1
- package/dist/{noydb-6FA46A4M.js → noydb-EY52NVH4.js} +15 -14
- package/dist/overlay-views/index.d.cts +3 -3
- package/dist/overlay-views/index.d.ts +3 -3
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +2 -2
- package/dist/periods/index.d.ts +2 -2
- package/dist/periods/index.js +3 -3
- package/dist/{public-envelope-DBKJEBBF.js → public-envelope-O6X6AUUS.js} +3 -3
- package/dist/{revoke-P5D3UTRX.js → revoke-QJ2HUM4W.js} +4 -4
- package/dist/session/index.d.cts +3 -3
- package/dist/session/index.d.ts +3 -3
- package/dist/shadow/index.d.cts +2 -2
- package/dist/shadow/index.d.ts +2 -2
- package/dist/{signer-NEQPCHMW.js → signer-SCJ6C6HQ.js} +3 -3
- package/dist/snapshots/index.d.cts +2 -2
- package/dist/snapshots/index.d.ts +2 -2
- package/dist/snapshots/index.js +3 -3
- package/dist/store/index.d.cts +2 -2
- package/dist/store/index.d.ts +2 -2
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js +2 -2
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +2 -2
- package/dist/team/index.d.ts +2 -2
- package/dist/team/index.js +5 -5
- package/dist/{transition-guard-BSLdikC_.d.ts → transition-guard-CJmb8O8q.d.ts} +1 -1
- package/dist/{transition-guard-DPs6al8h.d.cts → transition-guard-Dzj68JWC.d.cts} +1 -1
- package/dist/tx/index.d.cts +2 -2
- package/dist/tx/index.d.ts +2 -2
- package/dist/{types-CCq0WHh9.d.ts → types-CkSWJt0H.d.ts} +137 -7
- package/dist/{types-BCYvhKzr.d.cts → types-CwrTuYFI.d.cts} +137 -7
- package/dist/{with-materialized-view-DiD41wQp.d.ts → with-materialized-view-BVfcPlaE.d.ts} +1 -1
- package/dist/{with-materialized-view-CTHe6uh9.d.cts → with-materialized-view-dPG213gd.d.cts} +1 -1
- package/dist/{with-overlayed-view-Dlz5hcM8.d.cts → with-overlayed-view-CJ2UDBol.d.cts} +1 -1
- package/dist/{with-overlayed-view-DlbsJMhF.d.ts → with-overlayed-view-zYPQzGGh.d.ts} +1 -1
- package/dist/{with-rollup-BBWdrCvu.d.cts → with-rollup-B_zbRi3f.d.cts} +1 -1
- package/dist/{with-rollup-mT4_CWaU.d.ts → with-rollup-BvaJefEs.d.ts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-56ENKU46.js.map +0 -1
- package/dist/chunk-LR7CODVN.js.map +0 -1
- /package/dist/{chunk-HUXDQIVU.js.map → chunk-2NYVA6FW.js.map} +0 -0
- /package/dist/{chunk-OCRDV3NU.js.map → chunk-5EITJMUJ.js.map} +0 -0
- /package/dist/{chunk-EYZJULEN.js.map → chunk-6H4CAHMQ.js.map} +0 -0
- /package/dist/{chunk-VGAN5RLD.js.map → chunk-6M5JKTUQ.js.map} +0 -0
- /package/dist/{chunk-N4EXCKWP.js.map → chunk-6ZKXFMUG.js.map} +0 -0
- /package/dist/{chunk-KJ37E3R5.js.map → chunk-7DDTFGXY.js.map} +0 -0
- /package/dist/{chunk-TSUICI5N.js.map → chunk-BMDVFBCL.js.map} +0 -0
- /package/dist/{chunk-FCIZXX56.js.map → chunk-BOMH3637.js.map} +0 -0
- /package/dist/{chunk-RZOGD7IF.js.map → chunk-CVTPNW2Y.js.map} +0 -0
- /package/dist/{chunk-GPZHHTJU.js.map → chunk-DONPLWRC.js.map} +0 -0
- /package/dist/{chunk-GHXOVGTX.js.map → chunk-HAKEZTA7.js.map} +0 -0
- /package/dist/{chunk-QYQRAOEF.js.map → chunk-I2RX62RX.js.map} +0 -0
- /package/dist/{chunk-2RHBFCWQ.js.map → chunk-IWGVH2RR.js.map} +0 -0
- /package/dist/{chunk-Y5CTT6K5.js.map → chunk-K6PCTYAH.js.map} +0 -0
- /package/dist/{chunk-ANLOD6IS.js.map → chunk-KA5A5CSD.js.map} +0 -0
- /package/dist/{chunk-UNBX2HMA.js.map → chunk-LXA2E3VI.js.map} +0 -0
- /package/dist/{chunk-JJKXJAH2.js.map → chunk-PFKAT4NT.js.map} +0 -0
- /package/dist/{chunk-ZCBJIDT4.js.map → chunk-RRCRITDM.js.map} +0 -0
- /package/dist/{chunk-YP2AYE5W.js.map → chunk-SID2NJNF.js.map} +0 -0
- /package/dist/{fanout-sidecar-ZQT4Y7PF.js.map → fanout-sidecar-OC4QVTS2.js.map} +0 -0
- /package/dist/{issue-LEBPVF3Y.js.map → issue-ZZ2XPOGP.js.map} +0 -0
- /package/dist/{ledger-FLRTSOYH.js.map → ledger-XQ4KVFQ6.js.map} +0 -0
- /package/dist/{noydb-6FA46A4M.js.map → noydb-EY52NVH4.js.map} +0 -0
- /package/dist/{public-envelope-DBKJEBBF.js.map → public-envelope-O6X6AUUS.js.map} +0 -0
- /package/dist/{revoke-P5D3UTRX.js.map → revoke-QJ2HUM4W.js.map} +0 -0
- /package/dist/{signer-NEQPCHMW.js.map → signer-SCJ6C6HQ.js.map} +0 -0
package/dist/i18n/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { I as I18nMap, a as I18nTextDescriptor, b as I18nTextOptions, L as Layer, O as OnMissing, c as OnMissingPolicy, R as ResolveI18nOptions, d as applyI18nLocale, g as getAtPath, i as i18nText, e as isI18nTextDescriptor, r as resolveI18nText, f as resolvePolicy, s as setAtPathInPlace, v as validateI18nTextValue } from '../strategy-D1zjEV3n.cjs';
|
|
2
|
-
import { I as I18nStrategy } from '../types-
|
|
3
|
-
export { D as DICT_COLLECTION_PREFIX, a as DictEntry, b as DictKeyDescriptor, c as DictionaryHandle, d as DictionaryOptions, S as ScriptWarning, e as StaticDictDescriptor, f as dictCollectionName, g as dictKey, h as enforceScript, i as inferScripts, j as isDictCollectionName, k as isDictKeyDescriptor, l as isStaticDictDescriptor, s as staticDict } from '../types-
|
|
2
|
+
import { I as I18nStrategy } from '../types-CwrTuYFI.cjs';
|
|
3
|
+
export { D as DICT_COLLECTION_PREFIX, a as DictEntry, b as DictKeyDescriptor, c as DictionaryHandle, d as DictionaryOptions, S as ScriptWarning, e as StaticDictDescriptor, f as dictCollectionName, g as dictKey, h as enforceScript, i as inferScripts, j as isDictCollectionName, k as isDictKeyDescriptor, l as isStaticDictDescriptor, s as staticDict } from '../types-CwrTuYFI.cjs';
|
|
4
4
|
export { D as DictKeyInUseError, a as DictKeyMissingError, L as LocaleNotSpecifiedError, M as MissingTranslationError, R as ReservedCollectionNameError, S as ScriptViolationError, b as StaticDictReadonlyError, T as TranslatorNotConfiguredError, U as UnknownDictCodeError } from '../errors-Dwk2k1xY.cjs';
|
|
5
5
|
import '../lazy-builder-eYZzLEL1.cjs';
|
|
6
6
|
import '../predicate-BmhBSPCH.cjs';
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { I as I18nMap, a as I18nTextDescriptor, b as I18nTextOptions, L as Layer, O as OnMissing, c as OnMissingPolicy, R as ResolveI18nOptions, d as applyI18nLocale, g as getAtPath, i as i18nText, e as isI18nTextDescriptor, r as resolveI18nText, f as resolvePolicy, s as setAtPathInPlace, v as validateI18nTextValue } from '../strategy-YQ1qJWyq.js';
|
|
2
|
-
import { I as I18nStrategy } from '../types-
|
|
3
|
-
export { D as DICT_COLLECTION_PREFIX, a as DictEntry, b as DictKeyDescriptor, c as DictionaryHandle, d as DictionaryOptions, S as ScriptWarning, e as StaticDictDescriptor, f as dictCollectionName, g as dictKey, h as enforceScript, i as inferScripts, j as isDictCollectionName, k as isDictKeyDescriptor, l as isStaticDictDescriptor, s as staticDict } from '../types-
|
|
2
|
+
import { I as I18nStrategy } from '../types-CkSWJt0H.js';
|
|
3
|
+
export { D as DICT_COLLECTION_PREFIX, a as DictEntry, b as DictKeyDescriptor, c as DictionaryHandle, d as DictionaryOptions, S as ScriptWarning, e as StaticDictDescriptor, f as dictCollectionName, g as dictKey, h as enforceScript, i as inferScripts, j as isDictCollectionName, k as isDictKeyDescriptor, l as isStaticDictDescriptor, s as staticDict } from '../types-CkSWJt0H.js';
|
|
4
4
|
export { D as DictKeyInUseError, a as DictKeyMissingError, L as LocaleNotSpecifiedError, M as MissingTranslationError, R as ReservedCollectionNameError, S as ScriptViolationError, b as StaticDictReadonlyError, T as TranslatorNotConfiguredError, U as UnknownDictCodeError } from '../errors-Dwk2k1xY.js';
|
|
5
5
|
import '../lazy-builder-ChSqcF5t.js';
|
|
6
6
|
import '../predicate-BmhBSPCH.js';
|
package/dist/i18n/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
isDictKeyDescriptor,
|
|
8
8
|
isStaticDictDescriptor,
|
|
9
9
|
staticDict
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-PFKAT4NT.js";
|
|
11
11
|
import {
|
|
12
12
|
applyI18nLocale,
|
|
13
13
|
enforceScript,
|
|
@@ -20,9 +20,9 @@ import {
|
|
|
20
20
|
setAtPathInPlace,
|
|
21
21
|
validateI18nTextValue
|
|
22
22
|
} from "../chunk-KD253AI5.js";
|
|
23
|
-
import "../chunk-
|
|
23
|
+
import "../chunk-LXA2E3VI.js";
|
|
24
24
|
import "../chunk-PDVP3C2I.js";
|
|
25
|
-
import "../chunk-
|
|
25
|
+
import "../chunk-AD6RNBAW.js";
|
|
26
26
|
import "../chunk-7JSP3E67.js";
|
|
27
27
|
import {
|
|
28
28
|
DictKeyInUseError,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import './predicate-BmhBSPCH.cjs';
|
|
2
2
|
import './strategy-D1zjEV3n.cjs';
|
|
3
3
|
import './ulid-DRH25k3y.cjs';
|
|
4
|
+
import './types-CwrTuYFI.cjs';
|
|
4
5
|
import './errors-Dwk2k1xY.cjs';
|
|
5
|
-
import './types-BCYvhKzr.cjs';
|
|
6
6
|
import './index-DoxKSsMj.cjs';
|
|
7
7
|
|
|
8
8
|
interface EncryptResult {
|
package/dist/index.cjs
CHANGED
|
@@ -7255,6 +7255,249 @@ var init_peer_recover = __esm({
|
|
|
7255
7255
|
}
|
|
7256
7256
|
});
|
|
7257
7257
|
|
|
7258
|
+
// src/coordination/types.ts
|
|
7259
|
+
function isQuorum(writers, generation, excludeWriterId) {
|
|
7260
|
+
return writers.filter((w) => w.writerId !== excludeWriterId).every((w) => w.quiescedAtVersion === generation);
|
|
7261
|
+
}
|
|
7262
|
+
async function runDrainBarrier(provider, o, run) {
|
|
7263
|
+
await provider.setFence(o.vault, { currentSchemaVersion: o.generation, fenceState: "draining" });
|
|
7264
|
+
await o.onFlush();
|
|
7265
|
+
const deadline = o.now() + o.quiesceTimeoutMs;
|
|
7266
|
+
const seeded = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
|
|
7267
|
+
if (!isQuorum(seeded, o.generation, o.writerId)) {
|
|
7268
|
+
await new Promise((resolve, reject) => {
|
|
7269
|
+
let settled = false;
|
|
7270
|
+
const finish = (fn) => {
|
|
7271
|
+
if (!settled) {
|
|
7272
|
+
settled = true;
|
|
7273
|
+
unsub();
|
|
7274
|
+
fn();
|
|
7275
|
+
}
|
|
7276
|
+
};
|
|
7277
|
+
const unsub = provider.observePresence(o.vault, (writers) => {
|
|
7278
|
+
if (isQuorum(writers, o.generation, o.writerId)) finish(resolve);
|
|
7279
|
+
});
|
|
7280
|
+
const tick = async () => {
|
|
7281
|
+
if (settled) return;
|
|
7282
|
+
if (o.now() >= deadline) {
|
|
7283
|
+
finish(
|
|
7284
|
+
() => reject(
|
|
7285
|
+
new QuiesceTimeoutError(
|
|
7286
|
+
`Cutover of vault "${o.vault}" to generation ${o.generation} timed out after ${o.quiesceTimeoutMs}ms waiting for active writers to quiesce.`
|
|
7287
|
+
)
|
|
7288
|
+
)
|
|
7289
|
+
);
|
|
7290
|
+
return;
|
|
7291
|
+
}
|
|
7292
|
+
if (o.onPoll) await o.onPoll();
|
|
7293
|
+
const w = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
|
|
7294
|
+
if (isQuorum(w, o.generation, o.writerId)) finish(resolve);
|
|
7295
|
+
else setTimeout(() => void tick(), 25);
|
|
7296
|
+
};
|
|
7297
|
+
void tick();
|
|
7298
|
+
});
|
|
7299
|
+
}
|
|
7300
|
+
await run();
|
|
7301
|
+
}
|
|
7302
|
+
var init_types4 = __esm({
|
|
7303
|
+
"src/coordination/types.ts"() {
|
|
7304
|
+
"use strict";
|
|
7305
|
+
init_errors();
|
|
7306
|
+
}
|
|
7307
|
+
});
|
|
7308
|
+
|
|
7309
|
+
// src/schema-update/fence.ts
|
|
7310
|
+
async function loadFence(store, vault) {
|
|
7311
|
+
const envelope = await store.get(vault, META_COLLECTION3, FENCE_RECORD_ID);
|
|
7312
|
+
if (!envelope) return DEFAULT_FENCE;
|
|
7313
|
+
try {
|
|
7314
|
+
const parsed = JSON.parse(envelope._data);
|
|
7315
|
+
if (!isFenceDoc(parsed)) return DEFAULT_FENCE;
|
|
7316
|
+
return parsed;
|
|
7317
|
+
} catch {
|
|
7318
|
+
return DEFAULT_FENCE;
|
|
7319
|
+
}
|
|
7320
|
+
}
|
|
7321
|
+
async function saveFence(store, vault, fence) {
|
|
7322
|
+
const envelope = {
|
|
7323
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
7324
|
+
_v: 1,
|
|
7325
|
+
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7326
|
+
_iv: "",
|
|
7327
|
+
_data: JSON.stringify(fence)
|
|
7328
|
+
};
|
|
7329
|
+
await store.put(vault, META_COLLECTION3, FENCE_RECORD_ID, envelope);
|
|
7330
|
+
}
|
|
7331
|
+
function isFenceDoc(x) {
|
|
7332
|
+
if (x === null || typeof x !== "object") return false;
|
|
7333
|
+
const o = x;
|
|
7334
|
+
return typeof o["currentSchemaVersion"] === "number" && (o["fenceState"] === "normal" || o["fenceState"] === "draining" || o["fenceState"] === "migrating" || o["fenceState"] === "complete");
|
|
7335
|
+
}
|
|
7336
|
+
var FENCE_RECORD_ID, META_COLLECTION3, DEFAULT_FENCE;
|
|
7337
|
+
var init_fence = __esm({
|
|
7338
|
+
"src/schema-update/fence.ts"() {
|
|
7339
|
+
"use strict";
|
|
7340
|
+
init_types();
|
|
7341
|
+
FENCE_RECORD_ID = "schema-fence";
|
|
7342
|
+
META_COLLECTION3 = "_meta";
|
|
7343
|
+
DEFAULT_FENCE = { currentSchemaVersion: 0, fenceState: "normal" };
|
|
7344
|
+
}
|
|
7345
|
+
});
|
|
7346
|
+
|
|
7347
|
+
// src/schema-update/client-registry.ts
|
|
7348
|
+
async function writeClientDoc(store, vault, clientId, doc) {
|
|
7349
|
+
const envelope = {
|
|
7350
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
7351
|
+
_v: 1,
|
|
7352
|
+
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7353
|
+
_iv: "",
|
|
7354
|
+
_data: JSON.stringify({ clientId, ...doc })
|
|
7355
|
+
};
|
|
7356
|
+
await store.put(vault, META_COLLECTION4, `${CLIENT_PREFIX}${clientId}`, envelope);
|
|
7357
|
+
}
|
|
7358
|
+
async function listClientDocs(store, vault) {
|
|
7359
|
+
const ids = await store.list(vault, META_COLLECTION4);
|
|
7360
|
+
const out = [];
|
|
7361
|
+
for (const id of ids) {
|
|
7362
|
+
if (!id.startsWith(CLIENT_PREFIX)) continue;
|
|
7363
|
+
const env = await store.get(vault, META_COLLECTION4, id);
|
|
7364
|
+
if (!env) continue;
|
|
7365
|
+
try {
|
|
7366
|
+
const parsed = JSON.parse(env._data);
|
|
7367
|
+
if (isClientDoc(parsed)) out.push(parsed);
|
|
7368
|
+
} catch {
|
|
7369
|
+
}
|
|
7370
|
+
}
|
|
7371
|
+
return out;
|
|
7372
|
+
}
|
|
7373
|
+
function isClientDoc(x) {
|
|
7374
|
+
if (x === null || typeof x !== "object") return false;
|
|
7375
|
+
const o = x;
|
|
7376
|
+
return typeof o["clientId"] === "string" && typeof o["lastSeen"] === "number" && (o["quiescedAtVersion"] === null || typeof o["quiescedAtVersion"] === "number") && (o["sessionId"] === void 0 || typeof o["sessionId"] === "string");
|
|
7377
|
+
}
|
|
7378
|
+
var META_COLLECTION4, CLIENT_PREFIX;
|
|
7379
|
+
var init_client_registry = __esm({
|
|
7380
|
+
"src/schema-update/client-registry.ts"() {
|
|
7381
|
+
"use strict";
|
|
7382
|
+
init_types();
|
|
7383
|
+
META_COLLECTION4 = "_meta";
|
|
7384
|
+
CLIENT_PREFIX = "schema-fence:client:";
|
|
7385
|
+
}
|
|
7386
|
+
});
|
|
7387
|
+
|
|
7388
|
+
// src/coordination/store-provider.ts
|
|
7389
|
+
function toPresence(doc) {
|
|
7390
|
+
return {
|
|
7391
|
+
writerId: doc.clientId,
|
|
7392
|
+
// Pre-#469 docs (and explicit empty) have no session — fall back to the
|
|
7393
|
+
// writerId so every presence is session-addressable.
|
|
7394
|
+
sessionId: doc.sessionId && doc.sessionId.length > 0 ? doc.sessionId : doc.clientId,
|
|
7395
|
+
lastSeen: doc.lastSeen,
|
|
7396
|
+
quiescedAtVersion: doc.quiescedAtVersion
|
|
7397
|
+
};
|
|
7398
|
+
}
|
|
7399
|
+
function fenceEqual(a, b) {
|
|
7400
|
+
return a.currentSchemaVersion === b.currentSchemaVersion && a.fenceState === b.fenceState;
|
|
7401
|
+
}
|
|
7402
|
+
function presenceListEqual(a, b) {
|
|
7403
|
+
if (a.length !== b.length) return false;
|
|
7404
|
+
const key = (w) => `${w.writerId}\0${w.sessionId}\0${w.lastSeen}\0${String(w.quiescedAtVersion)}`;
|
|
7405
|
+
const bk = new Set(b.map(key));
|
|
7406
|
+
return a.every((w) => bk.has(key(w)));
|
|
7407
|
+
}
|
|
7408
|
+
function unref(timer) {
|
|
7409
|
+
const t = timer;
|
|
7410
|
+
if (typeof t.unref === "function") t.unref();
|
|
7411
|
+
}
|
|
7412
|
+
var DEFAULT_POLL_INTERVAL_MS, StoreCoordinationProvider;
|
|
7413
|
+
var init_store_provider = __esm({
|
|
7414
|
+
"src/coordination/store-provider.ts"() {
|
|
7415
|
+
"use strict";
|
|
7416
|
+
init_fence();
|
|
7417
|
+
init_client_registry();
|
|
7418
|
+
DEFAULT_POLL_INTERVAL_MS = 50;
|
|
7419
|
+
StoreCoordinationProvider = class {
|
|
7420
|
+
#store;
|
|
7421
|
+
#pollIntervalMs;
|
|
7422
|
+
constructor(store, opts) {
|
|
7423
|
+
this.#store = store;
|
|
7424
|
+
this.#pollIntervalMs = opts?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
7425
|
+
}
|
|
7426
|
+
async setFence(vault, fence) {
|
|
7427
|
+
await saveFence(this.#store, vault, fence);
|
|
7428
|
+
}
|
|
7429
|
+
async readFence(vault) {
|
|
7430
|
+
return loadFence(this.#store, vault);
|
|
7431
|
+
}
|
|
7432
|
+
observeFence(vault, onChange) {
|
|
7433
|
+
let last = null;
|
|
7434
|
+
let busy = false;
|
|
7435
|
+
const poll = async () => {
|
|
7436
|
+
if (busy) return;
|
|
7437
|
+
busy = true;
|
|
7438
|
+
try {
|
|
7439
|
+
const fence = await loadFence(this.#store, vault);
|
|
7440
|
+
if (last === null || !fenceEqual(last, fence)) {
|
|
7441
|
+
last = fence;
|
|
7442
|
+
onChange(fence);
|
|
7443
|
+
}
|
|
7444
|
+
} catch {
|
|
7445
|
+
} finally {
|
|
7446
|
+
busy = false;
|
|
7447
|
+
}
|
|
7448
|
+
};
|
|
7449
|
+
void poll();
|
|
7450
|
+
const timer = setInterval(() => void poll(), this.#pollIntervalMs);
|
|
7451
|
+
unref(timer);
|
|
7452
|
+
return () => clearInterval(timer);
|
|
7453
|
+
}
|
|
7454
|
+
async reportPresence(vault, p) {
|
|
7455
|
+
await writeClientDoc(this.#store, vault, p.writerId, {
|
|
7456
|
+
lastSeen: p.lastSeen,
|
|
7457
|
+
quiescedAtVersion: p.quiescedAtVersion,
|
|
7458
|
+
sessionId: p.sessionId
|
|
7459
|
+
});
|
|
7460
|
+
}
|
|
7461
|
+
observePresence(vault, onChange) {
|
|
7462
|
+
let last = null;
|
|
7463
|
+
let busy = false;
|
|
7464
|
+
const poll = async () => {
|
|
7465
|
+
if (busy) return;
|
|
7466
|
+
busy = true;
|
|
7467
|
+
try {
|
|
7468
|
+
const docs = await listClientDocs(this.#store, vault);
|
|
7469
|
+
const writers = docs.map(toPresence);
|
|
7470
|
+
if (last === null || !presenceListEqual(last, writers)) {
|
|
7471
|
+
last = writers;
|
|
7472
|
+
onChange(writers);
|
|
7473
|
+
}
|
|
7474
|
+
} catch {
|
|
7475
|
+
} finally {
|
|
7476
|
+
busy = false;
|
|
7477
|
+
}
|
|
7478
|
+
};
|
|
7479
|
+
void poll();
|
|
7480
|
+
const timer = setInterval(() => void poll(), this.#pollIntervalMs);
|
|
7481
|
+
unref(timer);
|
|
7482
|
+
return () => clearInterval(timer);
|
|
7483
|
+
}
|
|
7484
|
+
async reachableWriters(vault, o) {
|
|
7485
|
+
const docs = await listClientDocs(this.#store, vault);
|
|
7486
|
+
return docs.map(toPresence).filter((w) => o.now - w.lastSeen <= o.staleMs);
|
|
7487
|
+
}
|
|
7488
|
+
};
|
|
7489
|
+
}
|
|
7490
|
+
});
|
|
7491
|
+
|
|
7492
|
+
// src/coordination/index.ts
|
|
7493
|
+
var init_coordination = __esm({
|
|
7494
|
+
"src/coordination/index.ts"() {
|
|
7495
|
+
"use strict";
|
|
7496
|
+
init_types4();
|
|
7497
|
+
init_store_provider();
|
|
7498
|
+
}
|
|
7499
|
+
});
|
|
7500
|
+
|
|
7258
7501
|
// src/crdt/strategy.ts
|
|
7259
7502
|
var NOT_ENABLED, NO_CRDT;
|
|
7260
7503
|
var init_strategy = __esm({
|
|
@@ -17764,108 +18007,18 @@ var init_magic_link_grant = __esm({
|
|
|
17764
18007
|
}
|
|
17765
18008
|
});
|
|
17766
18009
|
|
|
17767
|
-
// src/schema-update/fence.ts
|
|
17768
|
-
async function loadFence(store, vault) {
|
|
17769
|
-
const envelope = await store.get(vault, META_COLLECTION3, FENCE_RECORD_ID);
|
|
17770
|
-
if (!envelope) return DEFAULT_FENCE;
|
|
17771
|
-
try {
|
|
17772
|
-
const parsed = JSON.parse(envelope._data);
|
|
17773
|
-
if (!isFenceDoc(parsed)) return DEFAULT_FENCE;
|
|
17774
|
-
return parsed;
|
|
17775
|
-
} catch {
|
|
17776
|
-
return DEFAULT_FENCE;
|
|
17777
|
-
}
|
|
17778
|
-
}
|
|
17779
|
-
async function saveFence(store, vault, fence) {
|
|
17780
|
-
const envelope = {
|
|
17781
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
17782
|
-
_v: 1,
|
|
17783
|
-
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17784
|
-
_iv: "",
|
|
17785
|
-
_data: JSON.stringify(fence)
|
|
17786
|
-
};
|
|
17787
|
-
await store.put(vault, META_COLLECTION3, FENCE_RECORD_ID, envelope);
|
|
17788
|
-
}
|
|
17789
|
-
function isFenceDoc(x) {
|
|
17790
|
-
if (x === null || typeof x !== "object") return false;
|
|
17791
|
-
const o = x;
|
|
17792
|
-
return typeof o["currentSchemaVersion"] === "number" && (o["fenceState"] === "normal" || o["fenceState"] === "draining" || o["fenceState"] === "migrating" || o["fenceState"] === "complete");
|
|
17793
|
-
}
|
|
17794
|
-
var FENCE_RECORD_ID, META_COLLECTION3, DEFAULT_FENCE;
|
|
17795
|
-
var init_fence = __esm({
|
|
17796
|
-
"src/schema-update/fence.ts"() {
|
|
17797
|
-
"use strict";
|
|
17798
|
-
init_types();
|
|
17799
|
-
FENCE_RECORD_ID = "schema-fence";
|
|
17800
|
-
META_COLLECTION3 = "_meta";
|
|
17801
|
-
DEFAULT_FENCE = { currentSchemaVersion: 0, fenceState: "normal" };
|
|
17802
|
-
}
|
|
17803
|
-
});
|
|
17804
|
-
|
|
17805
|
-
// src/schema-update/client-registry.ts
|
|
17806
|
-
async function writeClientDoc(store, vault, clientId, doc) {
|
|
17807
|
-
const envelope = {
|
|
17808
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
17809
|
-
_v: 1,
|
|
17810
|
-
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17811
|
-
_iv: "",
|
|
17812
|
-
_data: JSON.stringify({ clientId, ...doc })
|
|
17813
|
-
};
|
|
17814
|
-
await store.put(vault, META_COLLECTION4, `${CLIENT_PREFIX}${clientId}`, envelope);
|
|
17815
|
-
}
|
|
17816
|
-
async function listClientDocs(store, vault) {
|
|
17817
|
-
const ids = await store.list(vault, META_COLLECTION4);
|
|
17818
|
-
const out = [];
|
|
17819
|
-
for (const id of ids) {
|
|
17820
|
-
if (!id.startsWith(CLIENT_PREFIX)) continue;
|
|
17821
|
-
const env = await store.get(vault, META_COLLECTION4, id);
|
|
17822
|
-
if (!env) continue;
|
|
17823
|
-
try {
|
|
17824
|
-
const parsed = JSON.parse(env._data);
|
|
17825
|
-
if (isClientDoc(parsed)) out.push(parsed);
|
|
17826
|
-
} catch {
|
|
17827
|
-
}
|
|
17828
|
-
}
|
|
17829
|
-
return out;
|
|
17830
|
-
}
|
|
17831
|
-
async function activeQuiesced(store, vault, opts) {
|
|
17832
|
-
const docs = await listClientDocs(store, vault);
|
|
17833
|
-
const active = docs.filter(
|
|
17834
|
-
(d) => d.lastSeen >= opts.now - opts.staleMs && d.clientId !== opts.excludeClientId
|
|
17835
|
-
);
|
|
17836
|
-
return active.every((d) => d.quiescedAtVersion === opts.generation);
|
|
17837
|
-
}
|
|
17838
|
-
function isClientDoc(x) {
|
|
17839
|
-
if (x === null || typeof x !== "object") return false;
|
|
17840
|
-
const o = x;
|
|
17841
|
-
return typeof o["clientId"] === "string" && typeof o["lastSeen"] === "number" && (o["quiescedAtVersion"] === null || typeof o["quiescedAtVersion"] === "number");
|
|
17842
|
-
}
|
|
17843
|
-
var META_COLLECTION4, CLIENT_PREFIX;
|
|
17844
|
-
var init_client_registry = __esm({
|
|
17845
|
-
"src/schema-update/client-registry.ts"() {
|
|
17846
|
-
"use strict";
|
|
17847
|
-
init_types();
|
|
17848
|
-
META_COLLECTION4 = "_meta";
|
|
17849
|
-
CLIENT_PREFIX = "schema-fence:client:";
|
|
17850
|
-
}
|
|
17851
|
-
});
|
|
17852
|
-
|
|
17853
18010
|
// src/schema-update/fence-controller.ts
|
|
17854
|
-
function delay(ms) {
|
|
17855
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17856
|
-
}
|
|
17857
18011
|
var SchemaFenceController;
|
|
17858
18012
|
var init_fence_controller = __esm({
|
|
17859
18013
|
"src/schema-update/fence-controller.ts"() {
|
|
17860
18014
|
"use strict";
|
|
17861
|
-
init_fence();
|
|
17862
18015
|
init_errors();
|
|
17863
|
-
|
|
18016
|
+
init_coordination();
|
|
17864
18017
|
SchemaFenceController = class {
|
|
17865
|
-
#
|
|
18018
|
+
#coordination;
|
|
17866
18019
|
#vault;
|
|
17867
18020
|
#onFlush;
|
|
17868
|
-
#
|
|
18021
|
+
#writerId;
|
|
17869
18022
|
#now;
|
|
17870
18023
|
#staleMs;
|
|
17871
18024
|
#quiesceTimeoutMs;
|
|
@@ -17873,10 +18026,10 @@ var init_fence_controller = __esm({
|
|
|
17873
18026
|
#snapshot = 0;
|
|
17874
18027
|
#pending = /* @__PURE__ */ new Map();
|
|
17875
18028
|
constructor(opts) {
|
|
17876
|
-
this.#
|
|
18029
|
+
this.#coordination = opts.coordination;
|
|
17877
18030
|
this.#vault = opts.vault;
|
|
17878
18031
|
this.#onFlush = opts.onFlush;
|
|
17879
|
-
this.#
|
|
18032
|
+
this.#writerId = opts.clientId ?? "migrator";
|
|
17880
18033
|
this.#now = opts.now ?? (() => Date.now());
|
|
17881
18034
|
this.#staleMs = opts.staleMs ?? 3e4;
|
|
17882
18035
|
this.#quiesceTimeoutMs = opts.quiesceTimeoutMs ?? 6e4;
|
|
@@ -17885,7 +18038,7 @@ var init_fence_controller = __esm({
|
|
|
17885
18038
|
}
|
|
17886
18039
|
/** Capture the generation snapshot at vault-open. */
|
|
17887
18040
|
async init() {
|
|
17888
|
-
this.#snapshot = (await
|
|
18041
|
+
this.#snapshot = (await this.#coordination.readFence(this.#vault)).currentSchemaVersion;
|
|
17889
18042
|
}
|
|
17890
18043
|
/** Record a per-collection pending cutover (from a registration `cutover` decision). */
|
|
17891
18044
|
registerPendingCutover(collection, transform) {
|
|
@@ -17893,7 +18046,7 @@ var init_fence_controller = __esm({
|
|
|
17893
18046
|
}
|
|
17894
18047
|
/** Write-path gate. Throws when behind, fenced, or this collection is cutover-pending. */
|
|
17895
18048
|
async assertWritable(collection) {
|
|
17896
|
-
const fence = await
|
|
18049
|
+
const fence = await this.#coordination.readFence(this.#vault);
|
|
17897
18050
|
if (fence.currentSchemaVersion > this.#snapshot) {
|
|
17898
18051
|
throw new MigrationRequiredError(
|
|
17899
18052
|
`Vault "${this.#vault}" advanced to schema generation ${fence.currentSchemaVersion} (this client opened at ${this.#snapshot}). Reload to continue.`
|
|
@@ -17912,49 +18065,49 @@ var init_fence_controller = __esm({
|
|
|
17912
18065
|
* Admin trigger. Drain → wait for the active set to quiesce (or time out)
|
|
17913
18066
|
* → migrate each pending transform → bump → complete → normal. The
|
|
17914
18067
|
* migrator excludes itself from the barrier (it drained synchronously
|
|
17915
|
-
*
|
|
17916
|
-
* production falls back to a short real delay.
|
|
18068
|
+
* inside {@link runDrainBarrier}). `onPoll` (tests) advances other clients
|
|
18069
|
+
* between barrier checks; production falls back to a short real delay.
|
|
17917
18070
|
*/
|
|
17918
18071
|
async runCutover(run, opts) {
|
|
17919
18072
|
if (this.#pending.size === 0) return { migrated: 0 };
|
|
17920
|
-
const base = await
|
|
18073
|
+
const base = await this.#coordination.readFence(this.#vault);
|
|
17921
18074
|
const generation = base.currentSchemaVersion;
|
|
17922
|
-
|
|
17923
|
-
await this.#onFlush();
|
|
17924
|
-
const deadline = this.#now() + this.#quiesceTimeoutMs;
|
|
17925
|
-
while (!await activeQuiesced(this.#store, this.#vault, {
|
|
17926
|
-
generation,
|
|
17927
|
-
now: this.#now(),
|
|
17928
|
-
staleMs: this.#staleMs,
|
|
17929
|
-
excludeClientId: this.#clientId
|
|
17930
|
-
})) {
|
|
17931
|
-
if (this.#now() >= deadline) {
|
|
17932
|
-
throw new QuiesceTimeoutError(
|
|
17933
|
-
`Cutover on "${this.#vault}" timed out waiting for clients to quiesce at generation ${generation}.`
|
|
17934
|
-
);
|
|
17935
|
-
}
|
|
17936
|
-
await (opts?.onPoll ? opts.onPoll() : delay(50));
|
|
17937
|
-
}
|
|
17938
|
-
await this.#setState(generation, "migrating");
|
|
18075
|
+
this.#emit({ currentSchemaVersion: generation, fenceState: "draining" });
|
|
17939
18076
|
let migrated = 0;
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
18077
|
+
await runDrainBarrier(
|
|
18078
|
+
this.#coordination,
|
|
18079
|
+
{
|
|
18080
|
+
vault: this.#vault,
|
|
18081
|
+
generation,
|
|
18082
|
+
writerId: this.#writerId,
|
|
18083
|
+
onFlush: this.#onFlush,
|
|
18084
|
+
staleMs: this.#staleMs,
|
|
18085
|
+
quiesceTimeoutMs: this.#quiesceTimeoutMs,
|
|
18086
|
+
now: this.#now,
|
|
18087
|
+
...opts?.onPoll ? { onPoll: opts.onPoll } : {}
|
|
18088
|
+
},
|
|
18089
|
+
async () => {
|
|
18090
|
+
await this.#setState(generation, "migrating");
|
|
18091
|
+
for (const [collection, transform] of this.#pending) {
|
|
18092
|
+
await run(collection, transform);
|
|
18093
|
+
migrated++;
|
|
18094
|
+
}
|
|
18095
|
+
const nextVersion = generation + 1;
|
|
18096
|
+
await this.#setState(nextVersion, "complete");
|
|
18097
|
+
this.#pending.clear();
|
|
18098
|
+
await this.#setState(nextVersion, "normal");
|
|
18099
|
+
this.#snapshot = nextVersion;
|
|
18100
|
+
}
|
|
18101
|
+
);
|
|
17949
18102
|
return { migrated };
|
|
17950
18103
|
}
|
|
17951
18104
|
/** Recover a stuck drain: reset fenceState to normal at the current version (no bump). */
|
|
17952
18105
|
async abort() {
|
|
17953
|
-
const fence = await
|
|
18106
|
+
const fence = await this.#coordination.readFence(this.#vault);
|
|
17954
18107
|
await this.#setState(fence.currentSchemaVersion, "normal");
|
|
17955
18108
|
}
|
|
17956
18109
|
async #setState(currentSchemaVersion, fenceState) {
|
|
17957
|
-
await
|
|
18110
|
+
await this.#coordination.setFence(this.#vault, { currentSchemaVersion, fenceState });
|
|
17958
18111
|
this.#emit({ currentSchemaVersion, fenceState });
|
|
17959
18112
|
}
|
|
17960
18113
|
};
|
|
@@ -17966,12 +18119,11 @@ var FenceWatcher;
|
|
|
17966
18119
|
var init_fence_watcher = __esm({
|
|
17967
18120
|
"src/schema-update/fence-watcher.ts"() {
|
|
17968
18121
|
"use strict";
|
|
17969
|
-
init_fence();
|
|
17970
|
-
init_client_registry();
|
|
17971
18122
|
FenceWatcher = class {
|
|
17972
|
-
#
|
|
18123
|
+
#coordination;
|
|
17973
18124
|
#vault;
|
|
17974
|
-
#
|
|
18125
|
+
#writerId;
|
|
18126
|
+
#sessionId;
|
|
17975
18127
|
#onFlush;
|
|
17976
18128
|
#now;
|
|
17977
18129
|
#emit;
|
|
@@ -17979,9 +18131,10 @@ var init_fence_watcher = __esm({
|
|
|
17979
18131
|
#quiescedAtVersion = null;
|
|
17980
18132
|
#timer;
|
|
17981
18133
|
constructor(opts) {
|
|
17982
|
-
this.#
|
|
18134
|
+
this.#coordination = opts.coordination;
|
|
17983
18135
|
this.#vault = opts.vault;
|
|
17984
|
-
this.#
|
|
18136
|
+
this.#writerId = opts.clientId;
|
|
18137
|
+
this.#sessionId = opts.sessionId ?? opts.clientId;
|
|
17985
18138
|
this.#onFlush = opts.onFlush;
|
|
17986
18139
|
this.#now = opts.now ?? (() => Date.now());
|
|
17987
18140
|
this.#emit = opts.emit ?? (() => {
|
|
@@ -17989,14 +18142,16 @@ var init_fence_watcher = __esm({
|
|
|
17989
18142
|
}
|
|
17990
18143
|
/** Publish liveness (and the current ack) without changing quiesce state. */
|
|
17991
18144
|
async beat() {
|
|
17992
|
-
await
|
|
18145
|
+
await this.#coordination.reportPresence(this.#vault, {
|
|
18146
|
+
writerId: this.#writerId,
|
|
18147
|
+
sessionId: this.#sessionId,
|
|
17993
18148
|
lastSeen: this.#now(),
|
|
17994
18149
|
quiescedAtVersion: this.#quiescedAtVersion
|
|
17995
18150
|
});
|
|
17996
18151
|
}
|
|
17997
18152
|
/** Poll the fence; quiesce on draining; emit on transitions. */
|
|
17998
18153
|
async check() {
|
|
17999
|
-
const fence = await
|
|
18154
|
+
const fence = await this.#coordination.readFence(this.#vault);
|
|
18000
18155
|
if (fence.fenceState !== this.#lastState) {
|
|
18001
18156
|
this.#lastState = fence.fenceState;
|
|
18002
18157
|
this.#emit({ currentSchemaVersion: fence.currentSchemaVersion, fenceState: fence.fenceState });
|
|
@@ -19308,10 +19463,11 @@ var init_vault = __esm({
|
|
|
19308
19463
|
this.keyring = opts.keyring;
|
|
19309
19464
|
this.encrypted = opts.encrypted;
|
|
19310
19465
|
this.schemaFence = new SchemaFenceController({
|
|
19311
|
-
|
|
19466
|
+
coordination: this.noydb.coordination,
|
|
19312
19467
|
vault: this.name,
|
|
19313
19468
|
onFlush: () => this.noydb._writeQueueTracker.onFlush(),
|
|
19314
19469
|
clientId: this.noydb._clientId,
|
|
19470
|
+
sessionId: this.noydb._sessionId,
|
|
19315
19471
|
emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
|
|
19316
19472
|
});
|
|
19317
19473
|
this.emitter = opts.emitter;
|
|
@@ -19707,9 +19863,10 @@ var init_vault = __esm({
|
|
|
19707
19863
|
if (this.#fenceCoordinationStarted) return;
|
|
19708
19864
|
this.#fenceCoordinationStarted = true;
|
|
19709
19865
|
this.#fenceWatcher = new FenceWatcher({
|
|
19710
|
-
|
|
19866
|
+
coordination: this.noydb.coordination,
|
|
19711
19867
|
vault: this.name,
|
|
19712
19868
|
clientId: this.noydb._clientId,
|
|
19869
|
+
sessionId: this.noydb._sessionId,
|
|
19713
19870
|
onFlush: () => this.noydb._writeQueueTracker.onFlush(),
|
|
19714
19871
|
emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
|
|
19715
19872
|
});
|
|
@@ -23450,6 +23607,7 @@ var init_noydb = __esm({
|
|
|
23450
23607
|
init_recovery();
|
|
23451
23608
|
init_managed_passphrase();
|
|
23452
23609
|
init_ulid();
|
|
23610
|
+
init_coordination();
|
|
23453
23611
|
init_errors2();
|
|
23454
23612
|
init_auth_introspection();
|
|
23455
23613
|
init_public_envelope();
|
|
@@ -23493,6 +23651,10 @@ var init_noydb = __esm({
|
|
|
23493
23651
|
writeHooks = new WriteHookRegistry();
|
|
23494
23652
|
subsystemBus = new SubsystemBus();
|
|
23495
23653
|
clientId = generateULID();
|
|
23654
|
+
/** Session that owns this instance's writers (one user's writers across vaults). */
|
|
23655
|
+
sessionId;
|
|
23656
|
+
/** Drain-barrier coordination transport for the schema fence (#469). */
|
|
23657
|
+
coordinationProvider;
|
|
23496
23658
|
vaultCache = /* @__PURE__ */ new Map();
|
|
23497
23659
|
keyringCache = /* @__PURE__ */ new Map();
|
|
23498
23660
|
syncEngines = /* @__PURE__ */ new Map();
|
|
@@ -23567,6 +23729,8 @@ var init_noydb = __esm({
|
|
|
23567
23729
|
"[noydb] debugPlaintext is ON \u2014 records are stored UNENCRYPTED and laid out for native store inspection. NEVER use this for production or client data."
|
|
23568
23730
|
);
|
|
23569
23731
|
}
|
|
23732
|
+
this.sessionId = options.sessionId ?? generateULID();
|
|
23733
|
+
this.coordinationProvider = options.coordinationStrategy ?? new StoreCoordinationProvider(options.store);
|
|
23570
23734
|
this.txStrategy = options.txStrategy ?? NO_TX;
|
|
23571
23735
|
this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
|
|
23572
23736
|
this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
|
|
@@ -24620,6 +24784,18 @@ var init_noydb = __esm({
|
|
|
24620
24784
|
get _clientId() {
|
|
24621
24785
|
return this.clientId;
|
|
24622
24786
|
}
|
|
24787
|
+
/** @internal Session that owns this instance's writers (#469). */
|
|
24788
|
+
get _sessionId() {
|
|
24789
|
+
return this.sessionId;
|
|
24790
|
+
}
|
|
24791
|
+
/**
|
|
24792
|
+
* @internal Drain-barrier coordination transport for the schema fence (#469).
|
|
24793
|
+
* The default store-backed provider reproduces today's fence behavior; a
|
|
24794
|
+
* `by-*` real-time transport is injected via `coordinationStrategy`.
|
|
24795
|
+
*/
|
|
24796
|
+
get coordination() {
|
|
24797
|
+
return this.coordinationProvider;
|
|
24798
|
+
}
|
|
24623
24799
|
/**
|
|
24624
24800
|
* Soft-lock a single vault: clear its in-memory keyring, DEKs, vault
|
|
24625
24801
|
* instance, sync engine, policy enforcer, and active-tier entry —
|
|
@@ -28036,8 +28212,8 @@ function withRetry(opts = {}) {
|
|
|
28036
28212
|
} catch (err) {
|
|
28037
28213
|
lastError = err;
|
|
28038
28214
|
if (attempt >= maxRetries || !shouldRetry(err)) throw err;
|
|
28039
|
-
const
|
|
28040
|
-
await new Promise((r) => setTimeout(r,
|
|
28215
|
+
const delay = backoffMs * Math.pow(2, attempt) * (1 + Math.random() * jitter);
|
|
28216
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
28041
28217
|
}
|
|
28042
28218
|
}
|
|
28043
28219
|
throw lastError;
|