@noy-db/hub 0.6.0-pre.7 → 0.6.0-pre.9
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 +1 -1
- package/dist/{chunk-YM75S6N6.js → chunk-2GAJGUNM.js} +139 -11
- package/dist/chunk-2GAJGUNM.js.map +1 -0
- package/dist/{chunk-PXCBVDFY.js → chunk-5O5HRRTV.js} +35 -2
- package/dist/chunk-5O5HRRTV.js.map +1 -0
- package/dist/{chunk-XBRNBG4Z.js → chunk-BEFVYAR5.js} +2 -2
- package/dist/{chunk-J7FM3RAU.js → chunk-BRVW2GS5.js} +2 -2
- package/dist/{chunk-4R55OPT2.js → chunk-BWVKEOPE.js} +2 -2
- package/dist/{chunk-ZMSE2ZZ4.js → chunk-GAG7QOVO.js} +6 -6
- package/dist/chunk-GAG7QOVO.js.map +1 -0
- package/dist/{chunk-JXIDGFKS.js → chunk-HPLWFNG4.js} +3 -1
- package/dist/chunk-HPLWFNG4.js.map +1 -0
- package/dist/{chunk-GOLN6LQ5.js → chunk-N35NC4JH.js} +2 -2
- package/dist/{chunk-WNFZI3I5.js → chunk-RV3ARMPN.js} +2 -2
- package/dist/{chunk-NNYENE7N.js → chunk-RXYYFSBB.js} +36 -2
- package/dist/chunk-RXYYFSBB.js.map +1 -0
- package/dist/{dispatch-4NSDG6EP.js → dispatch-FZEAWKVM.js} +5 -5
- package/dist/{executor-HYQBNG6J.js → executor-YIQB2S6N.js} +3 -3
- package/dist/index.js +10 -10
- package/dist/kernel/vault.d.ts +8 -2
- package/dist/materialized-views/index.js +3 -3
- package/dist/money/index.js +2 -2
- package/dist/{noydb-LYIAD4CW.js → noydb-ASEXNJS6.js} +4 -4
- package/dist/periods/index.js +8 -2
- package/dist/pod/index.js +4 -4
- package/dist/{stale-C27ICSB4.js → stale-ARHFVL5U.js} +2 -2
- package/dist/sync/index.js +2 -2
- package/dist/via/money/normalize.d.ts +20 -0
- package/dist/with-audit/periods/index.d.ts +3 -3
- package/dist/with-audit/periods/periods.d.ts +81 -1
- package/dist/with-audit/periods/vault-facade.d.ts +54 -1
- package/dist/with-audit/periods/window.d.ts +10 -0
- package/dist/with-shape/introspection/index.d.ts +1 -0
- package/package.json +3 -3
- package/dist/chunk-JXIDGFKS.js.map +0 -1
- package/dist/chunk-NNYENE7N.js.map +0 -1
- package/dist/chunk-PXCBVDFY.js.map +0 -1
- package/dist/chunk-YM75S6N6.js.map +0 -1
- package/dist/chunk-ZMSE2ZZ4.js.map +0 -1
- /package/dist/{chunk-XBRNBG4Z.js.map → chunk-BEFVYAR5.js.map} +0 -0
- /package/dist/{chunk-J7FM3RAU.js.map → chunk-BRVW2GS5.js.map} +0 -0
- /package/dist/{chunk-4R55OPT2.js.map → chunk-BWVKEOPE.js.map} +0 -0
- /package/dist/{chunk-GOLN6LQ5.js.map → chunk-N35NC4JH.js.map} +0 -0
- /package/dist/{chunk-WNFZI3I5.js.map → chunk-RV3ARMPN.js.map} +0 -0
- /package/dist/{dispatch-4NSDG6EP.js.map → dispatch-FZEAWKVM.js.map} +0 -0
- /package/dist/{executor-HYQBNG6J.js.map → executor-YIQB2S6N.js.map} +0 -0
- /package/dist/{noydb-LYIAD4CW.js.map → noydb-ASEXNJS6.js.map} +0 -0
- /package/dist/{stale-C27ICSB4.js.map → stale-ARHFVL5U.js.map} +0 -0
package/dist/cargo/index.js
CHANGED
|
@@ -109,17 +109,20 @@ import {
|
|
|
109
109
|
} from "./chunk-PEOZ34EM.js";
|
|
110
110
|
import {
|
|
111
111
|
NO_PERIODS,
|
|
112
|
+
isEffectivelyReopened,
|
|
112
113
|
purgeMarkersOn,
|
|
113
114
|
resolvePeriodKey,
|
|
115
|
+
resolveReopenState,
|
|
114
116
|
samePartition
|
|
115
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-5O5HRRTV.js";
|
|
116
118
|
import {
|
|
117
119
|
PERIODS_COLLECTION,
|
|
118
120
|
PERIOD_ARCHIVES_COLLECTION,
|
|
119
121
|
PERIOD_FREEZES_COLLECTION,
|
|
122
|
+
PERIOD_REOPENS_COLLECTION,
|
|
120
123
|
PERIOD_TARGET_PURGES_COLLECTION,
|
|
121
124
|
periodExclusiveUpperBound
|
|
122
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-HPLWFNG4.js";
|
|
123
126
|
import {
|
|
124
127
|
NO_SHADOW
|
|
125
128
|
} from "./chunk-SMY5X46Z.js";
|
|
@@ -3406,7 +3409,7 @@ var Collection = class {
|
|
|
3406
3409
|
}
|
|
3407
3410
|
}
|
|
3408
3411
|
if (this.materializedViewSource !== void 0) {
|
|
3409
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
3412
|
+
const { resolveStaleMVOnRead } = await import("./stale-ARHFVL5U.js");
|
|
3410
3413
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
|
|
3411
3414
|
}
|
|
3412
3415
|
let record;
|
|
@@ -3936,7 +3939,7 @@ var Collection = class {
|
|
|
3936
3939
|
*/
|
|
3937
3940
|
async dispatchMaterializedViews(id, record, wave) {
|
|
3938
3941
|
if (this.materializedViewSource === void 0) return;
|
|
3939
|
-
const { dispatchMaterializedViews } = await import("./dispatch-
|
|
3942
|
+
const { dispatchMaterializedViews } = await import("./dispatch-FZEAWKVM.js");
|
|
3940
3943
|
return dispatchMaterializedViews(this.#mvDispatchCtx(this.materializedViewSource), id, record, wave);
|
|
3941
3944
|
}
|
|
3942
3945
|
/**
|
|
@@ -4438,7 +4441,7 @@ var Collection = class {
|
|
|
4438
4441
|
*/
|
|
4439
4442
|
async dispatchMaterializedViewsOnDelete(id) {
|
|
4440
4443
|
if (this.materializedViewSource === void 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
|
|
4441
|
-
const { dispatchMaterializedViewsOnDelete } = await import("./dispatch-
|
|
4444
|
+
const { dispatchMaterializedViewsOnDelete } = await import("./dispatch-FZEAWKVM.js");
|
|
4442
4445
|
return dispatchMaterializedViewsOnDelete(this.#mvDispatchCtx(this.materializedViewSource), id);
|
|
4443
4446
|
}
|
|
4444
4447
|
/**
|
|
@@ -4458,7 +4461,7 @@ var Collection = class {
|
|
|
4458
4461
|
);
|
|
4459
4462
|
}
|
|
4460
4463
|
if (this.materializedViewSource !== void 0) {
|
|
4461
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
4464
|
+
const { resolveStaleMVOnRead } = await import("./stale-ARHFVL5U.js");
|
|
4462
4465
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
|
|
4463
4466
|
}
|
|
4464
4467
|
await this.ensureHydrated();
|
|
@@ -6417,7 +6420,8 @@ var VaultPeriods = class {
|
|
|
6417
6420
|
if (tp) targetPurges.set(tp.period, tp);
|
|
6418
6421
|
}
|
|
6419
6422
|
const scoped = options === void 0 ? all : all.filter((p) => samePartition(p.partition, options.partition));
|
|
6420
|
-
|
|
6423
|
+
const withReopen = await this.mergeReopenState(scoped);
|
|
6424
|
+
return withReopen.map((p) => {
|
|
6421
6425
|
const f = freezes.get(p.name);
|
|
6422
6426
|
let merged = f ? this.mergeFreeze(p, f) : p;
|
|
6423
6427
|
const a = archives.get(p.name);
|
|
@@ -6447,8 +6451,119 @@ var VaultPeriods = class {
|
|
|
6447
6451
|
if (archive) merged = this.mergeArchive(merged, archive);
|
|
6448
6452
|
const targetPurge = await this.readReserved(PERIOD_TARGET_PURGES_COLLECTION, key);
|
|
6449
6453
|
if (targetPurge) merged = this.mergeTargetPurge(merged, targetPurge);
|
|
6454
|
+
const reopenLog = await this.readReserved(PERIOD_REOPENS_COLLECTION, key);
|
|
6455
|
+
if (reopenLog) merged = { ...merged, ...resolveReopenState(reopenLog.events) };
|
|
6450
6456
|
return merged;
|
|
6451
6457
|
}
|
|
6458
|
+
/**
|
|
6459
|
+
* The full append-only reopen/reclose log for one period (#1022) — the record
|
|
6460
|
+
* an audit actually asks for, in order. `[]` when never reopened.
|
|
6461
|
+
*/
|
|
6462
|
+
async listPeriodReopens(name, options) {
|
|
6463
|
+
const key = resolvePeriodKey(name, options?.partition);
|
|
6464
|
+
const log = await this.readReserved(PERIOD_REOPENS_COLLECTION, key);
|
|
6465
|
+
return log?.events ?? [];
|
|
6466
|
+
}
|
|
6467
|
+
/**
|
|
6468
|
+
* Return a closed period to a writable state (#1022).
|
|
6469
|
+
*
|
|
6470
|
+
* Close is a three-state lifecycle in practice — open / closed / reopened —
|
|
6471
|
+
* because a month gets closed and then a missing invoice arrives, or a filing
|
|
6472
|
+
* is rejected and must be amended. That is routine, and it is supposed to
|
|
6473
|
+
* leave a trail.
|
|
6474
|
+
*
|
|
6475
|
+
* The `_periods/<key>` record is NOT touched: the reopen is appended to a
|
|
6476
|
+
* companion log, so the inter-period hash chain that proves the close
|
|
6477
|
+
* happened survives the reopen intact. The chain reads *closed at T1,
|
|
6478
|
+
* reopened at T2 by U, reclosed at T3*.
|
|
6479
|
+
*
|
|
6480
|
+
* A reopen withdraws the PERIOD's veto and nothing else. Record-level rules —
|
|
6481
|
+
* an `immutableGuard` on a sent receipt, a frozen field — are separate gate
|
|
6482
|
+
* handlers registered ahead of the period gate, so a reopened month cannot
|
|
6483
|
+
* resurrect a document that is independently locked. Period state can only
|
|
6484
|
+
* ever widen what the record-level rule already permits.
|
|
6485
|
+
*
|
|
6486
|
+
* Reopening an already-open window is allowed and appends another event: that
|
|
6487
|
+
* is how a window gets extended, and the log keeps both.
|
|
6488
|
+
*/
|
|
6489
|
+
async reopenPeriod(name, options) {
|
|
6490
|
+
const existing = await this.loadPeriodsCache();
|
|
6491
|
+
const period = this.findPeriod(existing, name, options);
|
|
6492
|
+
if (!period) throw new ValidationError(`reopenPeriod: no period named "${name}"${scopeSuffix(options)}.`);
|
|
6493
|
+
if (period.kind !== "closed") {
|
|
6494
|
+
throw new ValidationError(
|
|
6495
|
+
`reopenPeriod: period "${name}" is "${period.kind}"; only a closed period can be reopened.`
|
|
6496
|
+
);
|
|
6497
|
+
}
|
|
6498
|
+
if (options?.until !== void 0 && Number.isNaN(Date.parse(options.until))) {
|
|
6499
|
+
throw new ValidationError(`reopenPeriod: unparseable \`until\` "${options.until}".`);
|
|
6500
|
+
}
|
|
6501
|
+
return this.appendReopenEvent(period, options, {
|
|
6502
|
+
op: "reopen",
|
|
6503
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6504
|
+
by: this.deps.userId(),
|
|
6505
|
+
...options?.until !== void 0 && { until: options.until },
|
|
6506
|
+
...options?.reason !== void 0 && { reason: options.reason }
|
|
6507
|
+
});
|
|
6508
|
+
}
|
|
6509
|
+
/**
|
|
6510
|
+
* Seal a reopened period again (#1022), ending the window explicitly rather
|
|
6511
|
+
* than waiting for an `until` to lapse. Appends to the same log, so the
|
|
6512
|
+
* close → reopen → reclose sequence is recoverable in order.
|
|
6513
|
+
*/
|
|
6514
|
+
async reclosePeriod(name, options) {
|
|
6515
|
+
const existing = await this.loadPeriodsCache();
|
|
6516
|
+
const period = this.findPeriod(existing, name, options);
|
|
6517
|
+
if (!period) throw new ValidationError(`reclosePeriod: no period named "${name}"${scopeSuffix(options)}.`);
|
|
6518
|
+
const merged = await this.mergeReopenState([period]);
|
|
6519
|
+
if (!isEffectivelyReopened(merged[0], (/* @__PURE__ */ new Date()).toISOString())) {
|
|
6520
|
+
throw new ValidationError(
|
|
6521
|
+
`reclosePeriod: period "${name}"${scopeSuffix(options)} is not currently reopened \u2014 nothing to reclose. A period whose \`until\` has already lapsed re-sealed on its own.`
|
|
6522
|
+
);
|
|
6523
|
+
}
|
|
6524
|
+
return this.appendReopenEvent(period, options, {
|
|
6525
|
+
op: "reclose",
|
|
6526
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6527
|
+
by: this.deps.userId(),
|
|
6528
|
+
...options?.reason !== void 0 && { reason: options.reason }
|
|
6529
|
+
});
|
|
6530
|
+
}
|
|
6531
|
+
/** Append one entry to a period's reopen log, ledger it, and invalidate the guard's view. */
|
|
6532
|
+
async appendReopenEvent(period, scope, event) {
|
|
6533
|
+
const key = resolvePeriodKey(period.name, period.partition);
|
|
6534
|
+
const prior = await this.readReserved(PERIOD_REOPENS_COLLECTION, key);
|
|
6535
|
+
const record = {
|
|
6536
|
+
period: period.name,
|
|
6537
|
+
...hasPartition(period.partition) && { partition: period.partition },
|
|
6538
|
+
events: [...prior?.events ?? [], event]
|
|
6539
|
+
};
|
|
6540
|
+
const envelope = await this.writeReserved(PERIOD_REOPENS_COLLECTION, key, record);
|
|
6541
|
+
await this.deps.strategy.appendPeriodLedgerEntry(
|
|
6542
|
+
this.deps.getLedgerOrNull(),
|
|
6543
|
+
this.deps.userId(),
|
|
6544
|
+
envelope,
|
|
6545
|
+
key,
|
|
6546
|
+
PERIOD_REOPENS_COLLECTION
|
|
6547
|
+
);
|
|
6548
|
+
this.periodCache = null;
|
|
6549
|
+
void scope;
|
|
6550
|
+
return { ...period, ...resolveReopenState(record.events) };
|
|
6551
|
+
}
|
|
6552
|
+
/** Merge each period's reopen log onto it. One adapter listing, not one per period. */
|
|
6553
|
+
async mergeReopenState(periods) {
|
|
6554
|
+
if (periods.length === 0) return [];
|
|
6555
|
+
const ids = await this.deps.adapter.list(this.deps.vault, PERIOD_REOPENS_COLLECTION);
|
|
6556
|
+
if (ids.length === 0) return [...periods];
|
|
6557
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
6558
|
+
for (const id of ids) {
|
|
6559
|
+
const r = await this.readReserved(PERIOD_REOPENS_COLLECTION, id);
|
|
6560
|
+
if (r) byKey.set(id, r);
|
|
6561
|
+
}
|
|
6562
|
+
return periods.map((p) => {
|
|
6563
|
+
const log = byKey.get(resolvePeriodKey(p.name, p.partition));
|
|
6564
|
+
return log ? { ...p, ...resolveReopenState(log.events) } : p;
|
|
6565
|
+
});
|
|
6566
|
+
}
|
|
6452
6567
|
/** Resolve one period within the timeline named by `options` (vault-wide when absent). */
|
|
6453
6568
|
findPeriod(all, name, options) {
|
|
6454
6569
|
return all.find((p) => p.name === name && samePartition(p.partition, options?.partition));
|
|
@@ -6457,11 +6572,12 @@ var VaultPeriods = class {
|
|
|
6457
6572
|
async assertTsWritable(existing, incoming, collection) {
|
|
6458
6573
|
if (existing === null && incoming === null) return;
|
|
6459
6574
|
if (this.periodCache === null) {
|
|
6460
|
-
|
|
6575
|
+
const loaded = await this.deps.strategy.loadPeriods(
|
|
6461
6576
|
this.deps.adapter,
|
|
6462
6577
|
this.deps.vault,
|
|
6463
6578
|
(env) => this.decryptPeriodRecord(env)
|
|
6464
6579
|
);
|
|
6580
|
+
this.periodCache = await this.mergeReopenState(loaded);
|
|
6465
6581
|
}
|
|
6466
6582
|
if (this.periodCache.length === 0) return;
|
|
6467
6583
|
this.deps.strategy.assertTsWritable(
|
|
@@ -10184,14 +10300,14 @@ var Vault = class {
|
|
|
10184
10300
|
if (!reg) {
|
|
10185
10301
|
throw new Error(`refreshView: no MV registered with name "${name}"`);
|
|
10186
10302
|
}
|
|
10187
|
-
const { MaterializedViewExecutor } = await import("./executor-
|
|
10303
|
+
const { MaterializedViewExecutor } = await import("./executor-YIQB2S6N.js");
|
|
10188
10304
|
const result = await MaterializedViewExecutor.refresh(reg, {
|
|
10189
10305
|
getCollection: (n) => this.collection(n),
|
|
10190
10306
|
getActiveTxContext: () => this.noydb._activeTxContextOrNull,
|
|
10191
10307
|
getQueryContext: () => this,
|
|
10192
10308
|
dispatchCtx: this._dispatchCtx({ collection: name, id: "refreshView" })
|
|
10193
10309
|
});
|
|
10194
|
-
const { clearMVStaleFully } = await import("./stale-
|
|
10310
|
+
const { clearMVStaleFully } = await import("./stale-ARHFVL5U.js");
|
|
10195
10311
|
await clearMVStaleFully(this.adapter, this.name, registry, name);
|
|
10196
10312
|
return result;
|
|
10197
10313
|
}
|
|
@@ -10699,6 +10815,18 @@ var Vault = class {
|
|
|
10699
10815
|
async purgePeriodTargets(name, options) {
|
|
10700
10816
|
return this.periods.purgePeriodTargets(name, options);
|
|
10701
10817
|
}
|
|
10818
|
+
/** Return a closed period to writable (#1022); logged append-only, close chain untouched. */
|
|
10819
|
+
async reopenPeriod(name, options) {
|
|
10820
|
+
return this.periods.reopenPeriod(name, options);
|
|
10821
|
+
}
|
|
10822
|
+
/** Seal a reopened period again (#1022) rather than waiting for its `until` to lapse. */
|
|
10823
|
+
async reclosePeriod(name, options) {
|
|
10824
|
+
return this.periods.reclosePeriod(name, options);
|
|
10825
|
+
}
|
|
10826
|
+
/** The append-only reopen/reclose log for one period (#1022), in order. */
|
|
10827
|
+
async listPeriodReopens(name, options) {
|
|
10828
|
+
return this.periods.listPeriodReopens(name, options);
|
|
10829
|
+
}
|
|
10702
10830
|
/** @internal — called by the gate bus before put/delete. */
|
|
10703
10831
|
async _assertTsWritable(existing, incoming, collection) {
|
|
10704
10832
|
return this.periods.assertTsWritable(existing, incoming, collection);
|
|
@@ -14414,4 +14542,4 @@ export {
|
|
|
14414
14542
|
Noydb,
|
|
14415
14543
|
createNoydb
|
|
14416
14544
|
};
|
|
14417
|
-
//# sourceMappingURL=chunk-
|
|
14545
|
+
//# sourceMappingURL=chunk-2GAJGUNM.js.map
|