@noy-db/hub 0.7.0-pre.12 → 0.7.0-pre.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/dist/cargo/index.js +1 -1
  3. package/dist/chunk-66TQOPFM.js +37 -0
  4. package/dist/chunk-66TQOPFM.js.map +1 -0
  5. package/dist/{chunk-H7XCIM3Z.js → chunk-AJQY44CE.js} +43 -16
  6. package/dist/chunk-AJQY44CE.js.map +1 -0
  7. package/dist/{chunk-E5OHKSBD.js → chunk-BMELYFHU.js} +2 -2
  8. package/dist/chunk-BWXGSSFX.js +1589 -0
  9. package/dist/chunk-BWXGSSFX.js.map +1 -0
  10. package/dist/{chunk-HN4FNA4X.js → chunk-COTPDJR5.js} +8 -8
  11. package/dist/{chunk-E3EBMC4G.js → chunk-E2MYJGSG.js} +2 -2
  12. package/dist/{chunk-JJR2JIN4.js → chunk-FFBYRWDJ.js} +2 -2
  13. package/dist/{chunk-WQF3QABE.js → chunk-IHFXR2VQ.js} +9 -79
  14. package/dist/chunk-IHFXR2VQ.js.map +1 -0
  15. package/dist/chunk-MGOXJIBV.js +176 -0
  16. package/dist/chunk-MGOXJIBV.js.map +1 -0
  17. package/dist/{chunk-KL7AS3HV.js → chunk-PDD75NUZ.js} +5 -2
  18. package/dist/chunk-PDD75NUZ.js.map +1 -0
  19. package/dist/chunk-RTBJ5IOO.js +87 -0
  20. package/dist/chunk-RTBJ5IOO.js.map +1 -0
  21. package/dist/{chunk-7NTBVFGD.js → chunk-SXCYYMVS.js} +2 -2
  22. package/dist/{chunk-THNJ3IKU.js → chunk-ULUMAZ5S.js} +2 -2
  23. package/dist/{chunk-NO272T7Q.js → chunk-V4PXLYWM.js} +2 -31
  24. package/dist/chunk-V4PXLYWM.js.map +1 -0
  25. package/dist/{chunk-SWVNZQVR.js → chunk-YPXNAP72.js} +2 -169
  26. package/dist/chunk-YPXNAP72.js.map +1 -0
  27. package/dist/{chunk-XMF3GKUR.js → chunk-ZVCC36XQ.js} +50 -870
  28. package/dist/chunk-ZVCC36XQ.js.map +1 -0
  29. package/dist/{collection-facade-MGGHQ3HU.js → collection-facade-4ACKIDDY.js} +4 -3
  30. package/dist/derivations/index.js +6 -2
  31. package/dist/{dispatch-XEBHUGBV.js → dispatch-MSTR5VBI.js} +10 -5
  32. package/dist/dispatch-MSTR5VBI.js.map +1 -0
  33. package/dist/{dispatch-44J4TL72.js → dispatch-PDP5TA73.js} +5 -5
  34. package/dist/{executor-KSPGNVDO.js → executor-YDDC5XGY.js} +4 -3
  35. package/dist/index.js +25 -21
  36. package/dist/index.js.map +1 -1
  37. package/dist/lazy/index.js +3 -2
  38. package/dist/materialized-views/index.js +4 -3
  39. package/dist/{noydb-JJXPICIC.js → noydb-2C6QQJ5S.js} +12 -9
  40. package/dist/pod/index.js +12 -9
  41. package/dist/{registry-BZQIVNNO.js → registry-D2YXKRYC.js} +7 -3
  42. package/dist/search/index.js +1 -1
  43. package/dist/{stale-KSPG6LFX.js → stale-2CHKZTMK.js} +2 -2
  44. package/dist/with-formula/derivations/registry.d.ts +6 -7
  45. package/dist/with-shape/introspection/describe.d.ts +29 -9
  46. package/package.json +3 -3
  47. package/dist/chunk-7BE7ZDVQ.js +0 -722
  48. package/dist/chunk-7BE7ZDVQ.js.map +0 -1
  49. package/dist/chunk-H7XCIM3Z.js.map +0 -1
  50. package/dist/chunk-KL7AS3HV.js.map +0 -1
  51. package/dist/chunk-NO272T7Q.js.map +0 -1
  52. package/dist/chunk-SWVNZQVR.js.map +0 -1
  53. package/dist/chunk-WQF3QABE.js.map +0 -1
  54. package/dist/chunk-XMF3GKUR.js.map +0 -1
  55. package/dist/dispatch-XEBHUGBV.js.map +0 -1
  56. /package/dist/{chunk-E5OHKSBD.js.map → chunk-BMELYFHU.js.map} +0 -0
  57. /package/dist/{chunk-HN4FNA4X.js.map → chunk-COTPDJR5.js.map} +0 -0
  58. /package/dist/{chunk-E3EBMC4G.js.map → chunk-E2MYJGSG.js.map} +0 -0
  59. /package/dist/{chunk-JJR2JIN4.js.map → chunk-FFBYRWDJ.js.map} +0 -0
  60. /package/dist/{chunk-7NTBVFGD.js.map → chunk-SXCYYMVS.js.map} +0 -0
  61. /package/dist/{chunk-THNJ3IKU.js.map → chunk-ULUMAZ5S.js.map} +0 -0
  62. /package/dist/{collection-facade-MGGHQ3HU.js.map → collection-facade-4ACKIDDY.js.map} +0 -0
  63. /package/dist/{dispatch-44J4TL72.js.map → dispatch-PDP5TA73.js.map} +0 -0
  64. /package/dist/{executor-KSPGNVDO.js.map → executor-YDDC5XGY.js.map} +0 -0
  65. /package/dist/{noydb-JJXPICIC.js.map → noydb-2C6QQJ5S.js.map} +0 -0
  66. /package/dist/{registry-BZQIVNNO.js.map → registry-D2YXKRYC.js.map} +0 -0
  67. /package/dist/{stale-KSPG6LFX.js.map → stale-2CHKZTMK.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,107 @@
1
1
  # Changelog — hub
2
2
 
3
+ ## 0.7.0-pre.13
4
+
5
+ ### Patch Changes
6
+
7
+ - A FAILED non-strict lazy re-derive no longer clears the stale flag (#1258).
8
+
9
+ `resolveStaleOnRead` consumes the pending flag before reading the source (a
10
+ recursion guard for self-write outputs). A STRICT failure throws and the catch
11
+ restores it; a NON-STRICT failure warned and continued, leaving the flag
12
+ consumed — so the record was served as fresh and never retried, permanently,
13
+ because nothing would mark it stale again.
14
+
15
+ The decision this needed was what `strict: false` means. It means "a failed
16
+ derivation must not break the read", NOT "report this output as current". The
17
+ record is still served, the warning still fires, and the flag now survives so
18
+ the next read retries — strict-mode behaviour minus the throw.
19
+
20
+ Deliberate cost, stated so it is not later mistaken for a bug: a
21
+ permanently-failing non-strict derivation now re-runs on every read of that id
22
+ rather than once. That is louder and more expensive than silently serving a
23
+ stale value forever, and it is the trade made everywhere else here — a degraded
24
+ state must not render as a healthy one.
25
+
26
+ - A rollup child that RE-PARENTS now recomputes the old parent as well as the new
27
+ one (#1257).
28
+
29
+ The dispatcher read the rollup key from the incoming record only, so moving a
30
+ child from parent A to parent B recomputed B and left A's aggregate holding a
31
+ number that was correct before the move. That is the dangerous shape: a stale
32
+ total reads as data, not as an error, so nothing prompts anyone to re-check it.
33
+
34
+ Same old-value class as the `triggerBy` update fan-out fixed in #1249 — and it
35
+ is a small change rather than a new mechanism only because that fix added
36
+ prior-record capture to the write path, which this reuses.
37
+
38
+ Consistent with the rest of the derivation surface: a write that does not thread
39
+ a prior record (a sync-applied wave write, a tiers restore) degrades to
40
+ new-parent-only, the previous behaviour, rather than guessing at the old key.
41
+
42
+ - `schemaFieldKeys` now unwraps `z.preprocess()` on both Zod majors, so the two
43
+ field-typo guards (#1253's `fieldMeta`, #1249's `triggerBy` match) see through
44
+ it (#1262, reported by the pilot).
45
+
46
+ The `0.7.0-pre.12` fix followed refinement effects only and put `preprocess` on
47
+ the carve-out side with `transform`. That was wrong: `z.preprocess(fn, inner)`
48
+ rewrites the INPUT and then parses with `inner`, so the parsed record's keys ARE
49
+ `inner`'s keys — measured, `preprocess({a,b})` parses to `['a','b']` while
50
+ `transform` parses to `['c']`.
51
+
52
+ Scope, measured rather than assumed: this left the **sync** `describe()` path
53
+ unguarded for wrapped schemas. The async path was never affected —
54
+ `derivePersistedSchema` sees through `preprocess` on its own, so
55
+ `buildDescription` gets a populated field map and never reaches the
56
+ `schemaFieldKeys` fallback. The sync path is public, is what tooling reaches
57
+ for first, and is the only path some Zod 3 consumers can reach at all (the
58
+ async path needs the `zod-to-json-schema` peer), so the gap was real — but it
59
+ was one path, not both.
60
+
61
+ Replaced the effect-kind allowlist with one rule that covers every wrapper on
62
+ both majors: **follow the output side.** These keys describe the parsed record,
63
+ so the only question a wrapper raises is whether it changes the parsed shape.
64
+ Zod 3 `ZodEffects` follows `_def.schema` for `refinement` and `preprocess`;
65
+ Zod 4 wraps both `z.preprocess()` and `.transform()` as a `ZodPipe` and
66
+ following `_def.out` resolves them with no effect-kind test at all — preprocess
67
+ reaches the object, `.transform()` reaches a shapeless `ZodTransform` and stays
68
+ silent on its own. **This also fixes Zod 4 `z.preprocess()`, which the narrower
69
+ one-line widening would have missed.**
70
+
71
+ `.transform()` remains deliberately silent on both majors: it replaces the
72
+ output, so the inner keys would describe a record that is never stored. The two
73
+ are one string apart and mean opposite things, so tests pin them against each
74
+ other on both majors.
75
+
76
+ - `triggerBy` match targets are now checked against where the field actually
77
+ LIVES, not just whether it is declared (#1266, reported by the pilot).
78
+
79
+ A derivation matcher reads STORED records. A `mode: 'virtual'` computed field is
80
+ evaluated on the read path and never persisted — but it appears in `computed:`
81
+ (and in `via(computed(...))`) exactly like a materialized one, so registration
82
+ accepted it and the fan-out then matched nothing, forever. That is the precise
83
+ failure the #1249 match guard exists to prevent, reached THROUGH the guard
84
+ rather than around it, and it is the first thing a consumer reaches for when a
85
+ match target is not already stored.
86
+
87
+ Refused at registration rather than supported: matching a virtual field means
88
+ running user code for every candidate row, turning an indexed narrow into a full
89
+ scan. `mode: 'materialized'` is stored, already works, and is what the error
90
+ names. Both sides are refused — `to` reads the source record and `from` reads
91
+ the written record, and both are the stored shape. (The report covered `to`;
92
+ `from` had the identical defect.)
93
+
94
+ The virtual check runs even when the schema's field list is unreadable, unlike
95
+ the typo guard beside it. The typo guard needs a field list to compare against
96
+ and stays silent without one; this one does not — "declared, but never stored"
97
+ is provable from the declaration alone.
98
+
99
+ Second defect fixed in the same change: `viaFields` was missing from the guard's
100
+ key set entirely, so a `via()`-declared MATERIALIZED field — a perfectly valid
101
+ match target — was rejected as an undeclared typo. A guard that refuses valid
102
+ configurations is how people learn to stop trusting it, so both directions ship
103
+ together, each with a test that fails without its half of the fix.
104
+
3
105
  ## 0.7.0-pre.12
4
106
 
5
107
  ### Minor Changes
@@ -5,7 +5,7 @@ import {
5
5
  describeExtraction,
6
6
  unsealDeks,
7
7
  withCargo
8
- } from "../chunk-7NTBVFGD.js";
8
+ } from "../chunk-SXCYYMVS.js";
9
9
  import {
10
10
  extractPartition,
11
11
  walkClosure
@@ -0,0 +1,37 @@
1
+ import {
2
+ Lru,
3
+ parseBytes
4
+ } from "./chunk-V4PXLYWM.js";
5
+
6
+ // src/port/with/lazy-strategy.ts
7
+ function buildLazyCache(collection, cache) {
8
+ if (!cache || cache.maxRecords === void 0 && cache.maxBytes === void 0) {
9
+ throw new Error(
10
+ `Collection "${collection}": lazy mode (prefetch: false) requires a cache option with maxRecords and/or maxBytes. An unbounded lazy cache defeats the purpose.`
11
+ );
12
+ }
13
+ const lruOptions = {};
14
+ if (cache.maxRecords !== void 0) lruOptions.maxRecords = cache.maxRecords;
15
+ if (cache.maxBytes !== void 0) lruOptions.maxBytes = parseBytes(cache.maxBytes);
16
+ return new Lru(lruOptions);
17
+ }
18
+ var implicitLazyWarned = false;
19
+ var IMPLICIT_LAZY = {
20
+ createCache(collection, cache) {
21
+ if (!implicitLazyWarned) {
22
+ implicitLazyWarned = true;
23
+ if (!(typeof process !== "undefined" && process.env["NODE_ENV"] === "test")) {
24
+ console.warn(
25
+ `[noy-db] Collection "${collection}": lazy mode (prefetch: false) without the lazy service is deprecated \u2014 pass \`lazyStrategy: withLazy()\` (from "@noy-db/hub/lazy") to createNoydb(). The implicit path will be removed at 1.0.`
26
+ );
27
+ }
28
+ }
29
+ return buildLazyCache(collection, cache);
30
+ }
31
+ };
32
+
33
+ export {
34
+ buildLazyCache,
35
+ IMPLICIT_LAZY
36
+ };
37
+ //# sourceMappingURL=chunk-66TQOPFM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/port/with/lazy-strategy.ts"],"sourcesContent":["/**\n * Lazy-mode capability contract (#267 Track A tail — lazy-mode promoted out\n * of `routing` into its own `lazy` service). Lives on the `/with` port (the\n * one seam the kernel spine may import statically) so `Collection` can hold\n * the back-compat default without a spine→service static import.\n *\n * Lazy mode (`prefetch: false`) skips bulk hydration: reads go per-id\n * against the store and land in a bounded LRU working set. The strategy owns\n * constructing that LRU:\n *\n * - `withLazy()` (`with-store/lazy/active.ts`, subpath `@noy-db/hub/lazy`)\n * is the explicit catalog opt-in — silent, forward-stable.\n * - {@link IMPLICIT_LAZY} is the floor default reached when a collection\n * declares `prefetch: false` WITHOUT `lazyStrategy: withLazy()`. It keeps\n * the pre-#267 behavior byte-for-byte (back-compat delegation, pre-1.0)\n * but emits a one-time deprecation warn outside test env. It will become\n * a throwing stub at 1.0, letting the LRU leave the floor bundle\n * entirely once the per-record-CEK cache stops pinning `Lru` there.\n *\n * The on-demand read/write branches themselves stay kernel-resident (they\n * are `if (this.lazy)` forks on the hot get/put/scan paths); the service\n * seam owns cache construction + budget validation, which is where the\n * opt-in and the future tree-shake win live.\n * @internal\n */\nimport { Lru, parseBytes } from '../../kernel/cache/index.js'\nimport type { CacheOptions } from '../../kernel/collection.js'\n\nexport interface LazyStrategy {\n /**\n * Build the bounded LRU working-set cache for a lazy collection.\n * MUST throw when `cache` declares neither `maxRecords` nor `maxBytes` —\n * an unbounded lazy cache defeats the purpose.\n */\n createCache<V>(collection: string, cache: CacheOptions | undefined): Lru<string, V>\n}\n\n/**\n * Shared budget validation + LRU construction — the one implementation both\n * {@link IMPLICIT_LAZY} and `withLazy()` run, so the two paths cannot drift.\n * @internal\n */\nexport function buildLazyCache<V>(collection: string, cache: CacheOptions | undefined): Lru<string, V> {\n if (!cache || (cache.maxRecords === undefined && cache.maxBytes === undefined)) {\n throw new Error(\n `Collection \"${collection}\": lazy mode (prefetch: false) requires a cache option ` +\n `with maxRecords and/or maxBytes. An unbounded lazy cache defeats the purpose.`,\n )\n }\n const lruOptions: { maxRecords?: number; maxBytes?: number } = {}\n if (cache.maxRecords !== undefined) lruOptions.maxRecords = cache.maxRecords\n if (cache.maxBytes !== undefined) lruOptions.maxBytes = parseBytes(cache.maxBytes)\n return new Lru<string, V>(lruOptions)\n}\n\nlet implicitLazyWarned = false\n\n/**\n * Back-compat default (deprecated): `prefetch: false` without\n * `lazyStrategy: withLazy()`. Identical behavior to the explicit opt-in,\n * plus a one-time deprecation warn (suppressed under NODE_ENV=test,\n * mirroring the listPage fallback warn). @internal\n */\nexport const IMPLICIT_LAZY: LazyStrategy = {\n createCache<V>(collection: string, cache: CacheOptions | undefined): Lru<string, V> {\n if (!implicitLazyWarned) {\n implicitLazyWarned = true\n if (!(typeof process !== 'undefined' && process.env['NODE_ENV'] === 'test')) {\n console.warn(\n `[noy-db] Collection \"${collection}\": lazy mode (prefetch: false) without the lazy ` +\n `service is deprecated — pass \\`lazyStrategy: withLazy()\\` (from \"@noy-db/hub/lazy\") ` +\n `to createNoydb(). The implicit path will be removed at 1.0.`,\n )\n }\n }\n return buildLazyCache<V>(collection, cache)\n },\n}\n"],"mappings":";;;;;;AA0CO,SAAS,eAAkB,YAAoB,OAAiD;AACrG,MAAI,CAAC,SAAU,MAAM,eAAe,UAAa,MAAM,aAAa,QAAY;AAC9E,UAAM,IAAI;AAAA,MACR,eAAe,UAAU;AAAA,IAE3B;AAAA,EACF;AACA,QAAM,aAAyD,CAAC;AAChE,MAAI,MAAM,eAAe,OAAW,YAAW,aAAa,MAAM;AAClE,MAAI,MAAM,aAAa,OAAW,YAAW,WAAW,WAAW,MAAM,QAAQ;AACjF,SAAO,IAAI,IAAe,UAAU;AACtC;AAEA,IAAI,qBAAqB;AAQlB,IAAM,gBAA8B;AAAA,EACzC,YAAe,YAAoB,OAAiD;AAClF,QAAI,CAAC,oBAAoB;AACvB,2BAAqB;AACrB,UAAI,EAAE,OAAO,YAAY,eAAe,QAAQ,IAAI,UAAU,MAAM,SAAS;AAC3E,gBAAQ;AAAA,UACN,wBAAwB,UAAU;AAAA,QAGpC;AAAA,MACF;AAAA,IACF;AACA,WAAO,eAAkB,YAAY,KAAK;AAAA,EAC5C;AACF;","names":[]}
@@ -3,8 +3,9 @@ import {
3
3
  } from "./chunk-TPHAGLUH.js";
4
4
  import {
5
5
  ViaGraph,
6
+ computedEntryParts,
6
7
  schemaFieldKeys
7
- } from "./chunk-7BE7ZDVQ.js";
8
+ } from "./chunk-BWXGSSFX.js";
8
9
  import {
9
10
  sha256Hex
10
11
  } from "./chunk-SL3JAAKN.js";
@@ -35,6 +36,23 @@ function stripArtifactSuffix(displayId) {
35
36
  const suffix = `.${WHOLE_RECORD}`;
36
37
  return displayId.endsWith(suffix) ? displayId.slice(0, -suffix.length) : displayId;
37
38
  }
39
+ function matchTargetFieldNames(opts) {
40
+ const declared = [];
41
+ const virtual = [];
42
+ for (const [field, entry] of Object.entries(opts.computed ?? {})) {
43
+ declared.push(field);
44
+ const parts = computedEntryParts(entry);
45
+ if (parts.mode === "virtual") virtual.push(field);
46
+ }
47
+ for (const [field, spec] of Object.entries(opts.viaFields ?? {})) {
48
+ declared.push(field);
49
+ const descriptors = spec.descriptors ?? [];
50
+ for (const d of descriptors) {
51
+ if (d._viaBrand === "computed" && d.mode === "virtual") virtual.push(field);
52
+ }
53
+ }
54
+ return { declared, virtual };
55
+ }
38
56
  var DerivationRegistry = class {
39
57
  _bySource = /* @__PURE__ */ new Map();
40
58
  _byOutput = /* @__PURE__ */ new Map();
@@ -99,34 +117,38 @@ var DerivationRegistry = class {
99
117
  * own strategies rather than taken as a parameter — a field this
100
118
  * collection's own derivations write via `denorm` is never a typo.
101
119
  */
102
- validateFieldsFor(collectionName, schema, configKeys) {
120
+ validateFieldsFor(collectionName, schema, configKeys, viaSources = void 0) {
121
+ const targets = matchTargetFieldNames(viaSources ?? {});
122
+ const virtual = new Set(targets.virtual);
103
123
  const shapeKeys = schemaFieldKeys(schema);
104
- if (shapeKeys === void 0) return;
105
- const keys = /* @__PURE__ */ new Set([...shapeKeys, ...configKeys]);
124
+ if (shapeKeys === void 0 && virtual.size === 0) return;
125
+ const keys = shapeKeys === void 0 ? void 0 : /* @__PURE__ */ new Set([...shapeKeys, ...configKeys, ...targets.declared]);
106
126
  const denormExempt = /* @__PURE__ */ new Set();
107
- for (const reg of new Set([...this._bySource.values()].flat())) {
127
+ const regs = new Set([...this._bySource.values()].flat());
128
+ for (const reg of regs) {
108
129
  if (reg.spec.source !== collectionName) continue;
109
130
  for (const out of Object.values(reg.spec.outputs)) {
110
131
  if (out.collection === collectionName) for (const d of out.denorm ?? []) denormExempt.add(d);
111
132
  }
112
133
  }
113
- const regs = new Set([...this._bySource.values()].flat());
134
+ const unknown = (f) => keys !== void 0 && !keys.has(f) && !denormExempt.has(f);
114
135
  for (const reg of regs) {
136
+ const name = reg.spec.name ?? reg.spec.source;
115
137
  for (const t of reg.triggers) {
116
- if (reg.spec.source === collectionName) {
117
- for (const p of t.match) {
118
- if (!keys.has(p.to) && !denormExempt.has(p.to)) {
138
+ for (const p of t.match) {
139
+ if (reg.spec.source === collectionName) {
140
+ if (virtual.has(p.to)) throw new ValidationError(this._virtualMatchMessage(name, collectionName, p.to, "to"));
141
+ if (unknown(p.to)) {
119
142
  throw new ValidationError(
120
- `derivation "${reg.spec.name ?? reg.spec.source}": triggerBy match names source field "${p.to}", which "${collectionName}" does not declare \u2014 a typo here silently matches nothing forever`
143
+ `derivation "${name}": triggerBy match names source field "${p.to}", which "${collectionName}" does not declare \u2014 a typo here silently matches nothing forever`
121
144
  );
122
145
  }
123
146
  }
124
- }
125
- if (t.collection === collectionName) {
126
- for (const p of t.match) {
127
- if (p.from !== "id" && !keys.has(p.from) && !denormExempt.has(p.from)) {
147
+ if (t.collection === collectionName && p.from !== "id") {
148
+ if (virtual.has(p.from)) throw new ValidationError(this._virtualMatchMessage(name, collectionName, p.from, "from"));
149
+ if (unknown(p.from)) {
128
150
  throw new ValidationError(
129
- `derivation "${reg.spec.name ?? reg.spec.source}": triggerBy match reads "${p.from}" from written "${collectionName}" records, which that collection does not declare \u2014 a typo here silently matches nothing forever`
151
+ `derivation "${name}": triggerBy match reads "${p.from}" from written "${collectionName}" records, which that collection does not declare \u2014 a typo here silently matches nothing forever`
130
152
  );
131
153
  }
132
154
  }
@@ -134,6 +156,11 @@ var DerivationRegistry = class {
134
156
  }
135
157
  }
136
158
  }
159
+ /** #1266 — one message shape for both match sides; see {@link matchTargetFieldNames}. */
160
+ _virtualMatchMessage(name, collectionName, field, side) {
161
+ const where = side === "to" ? `names source field "${field}", which "${collectionName}"` : `reads "${field}" from written "${collectionName}" records, which that collection`;
162
+ return `derivation "${name}": triggerBy match ${where} declares as a VIRTUAL computed field \u2014 virtual fields are evaluated on read and never stored, so the matcher would read every candidate record and match nothing, forever. Declare it as \`mode: 'materialized'\` (stored, indexable) or match on a stored field.`;
163
+ }
137
164
  /**
138
165
  * All registered strategies as a flat, deduplicated array.
139
166
  * Each strategy is indexed once per source (not once per output key),
@@ -225,4 +252,4 @@ var DerivationRegistry = class {
225
252
  export {
226
253
  DerivationRegistry
227
254
  };
228
- //# sourceMappingURL=chunk-H7XCIM3Z.js.map
255
+ //# sourceMappingURL=chunk-AJQY44CE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-formula/derivations/strategy-hash.ts","../src/with-formula/derivations/registry.ts"],"sourcesContent":["/**\n * Deterministic hash of a derivation strategy's \"shape\": source\n * collection, declared sibling sources, output keys, derive function\n * source. Used to detect\n * strategy drift: a record whose `_derivedFrom.strategyHash` doesn't\n * match the current strategy is considered stale.\n *\n * Web Crypto SHA-256 — no extra deps.\n */\nimport { sha256Hex } from '../../kernel/enclave/index.js'\n\nexport async function computeStrategyHash(\n source: string,\n outputKeys: readonly string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n derive: (...args: any[]) => any,\n sources?: ReadonlyArray<string>,\n): Promise<string> {\n const canonical = JSON.stringify({\n source,\n outputs: [...outputKeys].sort(),\n derive: derive.toString(),\n // Declared sibling sources — adding/removing a trigger\n // collection invalidates cached derived records. Omitted when empty\n // so strategies without siblings keep their existing hash.\n ...(sources?.length ? { sources: [...sources].sort() } : {}),\n })\n const bytes = new TextEncoder().encode(canonical)\n return sha256Hex(bytes)\n}\n","import { computedEntryParts, type ComputedEntryParts } from '../../kernel/collection-config.js'\nimport { DerivationCycleError, DuplicateBehaviorNameError, ValidationError } from '../../kernel/errors.js'\nimport { ViaGraph, type FieldRef, type EdgeKind, type Grain } from '../../kernel/via/graph.js'\nimport { schemaFieldKeys } from '../../with-shape/introspection/describe.js'\nimport { computeStrategyHash } from './strategy-hash.js'\nimport { normalizeTriggerBy, type NormalizedTrigger } from './trigger-match.js'\nimport type { DerivationSpec } from './types.js'\n\n/**\n * Whole-record artifact-grain field marker (#638 Task 2). A derivation's\n * `derive()`/a rollup's `compute()` reads the WHOLE source record — there is\n * no single declared field to point at — so a trigger/output collection is\n * modelled as one artifact node per collection (`kernel/via/graph.ts`'s\n * \"Artifact-grain targets... modelled as a field node whose field is the\n * artifact key\" convention). MUST match `materialized-views/registry.ts`'s\n * and `vault.ts`'s overlay-edge marker so cross-registry edges (a derivation\n * feeding into / out of an MV or overlay collection) resolve to the SAME\n * graph node.\n */\nconst WHOLE_RECORD = '*'\n\n/** Strip this registry's `.${WHOLE_RECORD}` artifact suffix off a graph cycle\n * path entry, recovering the bare collection name — preserves the exact\n * pre-#638 `DerivationCycleError` message shape (behavior lock) for a pure\n * record-shape derivation cycle. A rollup's real-field target (not suffixed\n * `.${WHOLE_RECORD}`) is left untouched. */\nfunction stripArtifactSuffix(displayId: string): string {\n const suffix = `.${WHOLE_RECORD}`\n return displayId.endsWith(suffix) ? displayId.slice(0, -suffix.length) : displayId\n}\n\ninterface RegisteredStrategy {\n // Type-erased to allow the registry to hold heterogeneous strategies.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n spec: DerivationSpec<any, any>\n strategyHash: string\n readonly triggers: ReadonlyArray<NormalizedTrigger>\n}\n\n/**\n * Vault-internal registry of derivation strategies. Owned by `Vault`;\n * not exported.\n *\n * @internal\n */\n/**\n * Field names a `triggerBy` match may NOT target, and the ones it may (#1266).\n *\n * Lives HERE, not in `kernel/collection-config.ts` where computed-mode logic\n * otherwise sits, because that module is in the FLOOR bundle: putting twenty\n * lines there cost every consumer 5.2% of the floor whether or not they use\n * derivations. Registry code is already behind the derivations opt-in.\n *\n * A derivation matcher reads the STORED record, so a match target must be a\n * field that is stored. `mode: 'virtual'` computed fields are evaluated on the\n * READ path and never persisted — but they appear in `computed:` (and in\n * `via(computed(...))`) exactly like materialized ones, so the registration\n * guard accepted them and the fan-out then matched nothing, forever: the guard's\n * own stated failure mode, reached through the guard rather than around it.\n *\n * Rejected rather than supported. Matching a virtual field means running user\n * code for every candidate row, which turns an indexed narrow into a full scan\n * of the collection; `mode: 'materialized'` is stored, already works, and is\n * what the error points the caller at.\n *\n * `declared` also folds in `viaFields`, which the guard's key set previously\n * omitted entirely — a `via()`-declared MATERIALIZED field is a perfectly good\n * match target and was being rejected as a typo. An over-firing guard teaches\n * people to stop trusting it, so both directions are fixed together.\n */\nfunction matchTargetFieldNames(opts: {\n // Deliberately `unknown`-valued: the caller is generic over the record type\n // (`ComputedFields<T>`), and this reads only `mode`, so narrowing the value\n // type here would force a variance cast at every call site instead of one\n // here. Both shapes are duck-checked below.\n readonly computed?: Readonly<Record<string, unknown>> | undefined\n readonly viaFields?: Readonly<Record<string, unknown>> | undefined\n}): { readonly declared: readonly string[]; readonly virtual: readonly string[] } {\n const declared: string[] = []\n const virtual: string[] = []\n for (const [field, entry] of Object.entries(opts.computed ?? {})) {\n declared.push(field)\n const parts: ComputedEntryParts = computedEntryParts(entry as Parameters<typeof computedEntryParts>[0])\n if (parts.mode === 'virtual') virtual.push(field)\n }\n for (const [field, spec] of Object.entries(opts.viaFields ?? {})) {\n declared.push(field)\n const descriptors = (spec as { descriptors?: readonly unknown[] }).descriptors ?? []\n for (const d of descriptors) {\n if ((d as { _viaBrand?: unknown })._viaBrand === 'computed'\n && (d as { mode?: unknown }).mode === 'virtual') virtual.push(field)\n }\n }\n return { declared, virtual }\n}\n\nexport class DerivationRegistry {\n private readonly _bySource = new Map<string, RegisteredStrategy[]>()\n private readonly _byOutput = new Map<string, RegisteredStrategy[]>()\n private readonly _byName = new Map<string, RegisteredStrategy>()\n\n /**\n * Register a derivation strategy. If `spec.name` is given and already\n * registered by another derivation in this vault, throws\n * {@link DuplicateBehaviorNameError} before indexing.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async register(spec: DerivationSpec<any, any>): Promise<void> {\n if (spec.name !== undefined && this._byName.has(spec.name)) {\n throw new DuplicateBehaviorNameError(spec.name, 'derivation')\n }\n\n const outputKeys = Object.keys(spec.outputs)\n const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive, spec.sources)\n const triggers = normalizeTriggerBy(spec.triggerBy)\n const reg: RegisteredStrategy = { spec, strategyHash, triggers }\n\n if (spec.name !== undefined) this._byName.set(spec.name, reg)\n\n const fromSource = this._bySource.get(spec.source)\n if (fromSource) fromSource.push(reg)\n else this._bySource.set(spec.source, [reg])\n\n // Declared sibling sources index the SAME `reg` under each\n // extra collection so `strategiesForSource(extra)` returns it and a\n // sibling write re-fires the derivation. Sibling keys also enter\n // `_bySource`, so `validate()`'s cycle DFS walks them automatically.\n for (const extra of spec.sources ?? []) {\n const fromExtra = this._bySource.get(extra)\n if (fromExtra) fromExtra.push(reg)\n else this._bySource.set(extra, [reg])\n }\n\n // FK triggers index the SAME `reg` under each parent collection so\n // a parent write re-fires the derivation (fanned out to matching source\n // records in `dispatchDerivations`). Like sources[], these keys enter\n // `_bySource` so the cycle DFS walks the trigger→output edge.\n for (const t of triggers) {\n const fromTrigger = this._bySource.get(t.collection)\n if (fromTrigger) fromTrigger.push(reg)\n else this._bySource.set(t.collection, [reg])\n }\n\n // Rollup: a write to the child `from` collection recomputes\n // the parent (= spec.source = into) at id child[key]. Index under `from`\n // so a child write fires it; spec.source (into) is already indexed above,\n // so a parent write also recomputes its own aggregate (covers the\n // parent-created-after-children case). The from→into edge enters the cycle\n // DFS automatically.\n if (spec.rollup) {\n const fromRollup = this._bySource.get(spec.rollup.from)\n if (fromRollup) fromRollup.push(reg)\n else this._bySource.set(spec.rollup.from, [reg])\n }\n\n for (const key of outputKeys) {\n const output = spec.outputs[key]\n if (!output) continue\n const outputCollection = output.collection\n const arr = this._byOutput.get(outputCollection)\n if (arr) arr.push(reg)\n else this._byOutput.set(outputCollection, [reg])\n }\n }\n\n strategiesForSource(source: string): ReadonlyArray<RegisteredStrategy> {\n return this._bySource.get(source) ?? []\n }\n\n strategiesProducingOutput(collection: string): ReadonlyArray<RegisteredStrategy> {\n return this._byOutput.get(collection) ?? []\n }\n\n /**\n * The #1253-pattern typo guard for match fields (#1249): a misspelt\n * `to`/`from` silently matches nothing forever, so validate against the\n * collection's enumerable field set at the earliest point it exists.\n * `schemaFieldKeys(schema) === undefined` (TS-generic collection,\n * unreadable validator) is DELIBERATELY silent — those fields are real\n * and unenumerable. `configKeys` folds in the collection's other\n * non-schema field declarations (fieldMeta/moneyFields/dictKeyFields/\n * refs/computed); `denormExempt` is derived here from this registry's\n * own strategies rather than taken as a parameter — a field this\n * collection's own derivations write via `denorm` is never a typo.\n */\n validateFieldsFor(\n collectionName: string,\n schema: unknown,\n configKeys: ReadonlyArray<string>,\n viaSources: {\n readonly computed?: Readonly<Record<string, unknown>> | undefined\n readonly viaFields?: Readonly<Record<string, unknown>> | undefined\n } | undefined = undefined,\n ): void {\n const targets = matchTargetFieldNames(viaSources ?? {})\n const virtual = new Set(targets.virtual)\n const shapeKeys = schemaFieldKeys(schema)\n // The two checks have DIFFERENT preconditions, which is why one loop runs\n // both rather than an early return covering both. The typo check needs a\n // readable field list and must stay silent without one — a false \"unknown\n // field\" on a TS-generic collection would be worse than no check. The\n // virtual check needs nothing but the declaration in hand: \"declared, and\n // never stored\" is provable from the declaration alone (#1266).\n if (shapeKeys === undefined && virtual.size === 0) return\n const keys = shapeKeys === undefined ? undefined\n : new Set([...shapeKeys, ...configKeys, ...targets.declared])\n const denormExempt = new Set<string>()\n const regs = new Set([...this._bySource.values()].flat())\n for (const reg of regs) {\n if (reg.spec.source !== collectionName) continue\n for (const out of Object.values(reg.spec.outputs) as Array<{ collection?: string; denorm?: readonly string[] }>) {\n if (out.collection === collectionName) for (const d of out.denorm ?? []) denormExempt.add(d)\n }\n }\n const unknown = (f: string): boolean =>\n keys !== undefined && !keys.has(f) && !denormExempt.has(f)\n for (const reg of regs) {\n const name = reg.spec.name ?? reg.spec.source\n for (const t of reg.triggers) {\n for (const p of t.match) {\n // `to` reads the SOURCE record; `from` reads the WRITTEN record.\n // Both are the stored shape, so both refuse a virtual target.\n if (reg.spec.source === collectionName) {\n if (virtual.has(p.to)) throw new ValidationError(this._virtualMatchMessage(name, collectionName, p.to, 'to'))\n if (unknown(p.to)) {\n throw new ValidationError(\n `derivation \"${name}\": triggerBy match names source field \"${p.to}\", which \"${collectionName}\" does not declare — a typo here silently matches nothing forever`)\n }\n }\n if (t.collection === collectionName && p.from !== 'id') {\n if (virtual.has(p.from)) throw new ValidationError(this._virtualMatchMessage(name, collectionName, p.from, 'from'))\n if (unknown(p.from)) {\n throw new ValidationError(\n `derivation \"${name}\": triggerBy match reads \"${p.from}\" from written \"${collectionName}\" records, which that collection does not declare — a typo here silently matches nothing forever`)\n }\n }\n }\n }\n }\n }\n\n /** #1266 — one message shape for both match sides; see {@link matchTargetFieldNames}. */\n private _virtualMatchMessage(name: string, collectionName: string, field: string, side: 'to' | 'from'): string {\n const where = side === 'to'\n ? `names source field \"${field}\", which \"${collectionName}\"`\n : `reads \"${field}\" from written \"${collectionName}\" records, which that collection`\n return `derivation \"${name}\": triggerBy match ${where} declares as a VIRTUAL computed field — virtual fields are evaluated on read and never stored, so the matcher would read every candidate record and match nothing, forever. Declare it as \\`mode: 'materialized'\\` (stored, indexable) or match on a stored field.`\n }\n\n /**\n * All registered strategies as a flat, deduplicated array.\n * Each strategy is indexed once per source (not once per output key),\n * so iterating `_bySource.values()` naturally yields each strategy\n * exactly once per source — deduplication is handled by flattening\n * the per-source arrays and collecting into a Set by identity.\n *\n * Used by `dumpSchema()` / `describeDerivations()` in the introspection\n * walker to populate the derivations map.\n */\n all(): ReadonlyArray<RegisteredStrategy> {\n const seen = new Set<RegisteredStrategy>()\n for (const strategies of this._bySource.values()) {\n for (const s of strategies) seen.add(s)\n }\n return [...seen]\n }\n\n /**\n * Graph edges for #638 Task 2: one `'derivation'`/`'record'` edge per\n * (non-self-write) output key — target = the output collection (a\n * `WHOLE_RECORD` artifact node), sources = every collection that can\n * trigger this strategy (`source`, `sources[]`, `triggerBy[].collection`,\n * and — for a rollup — `rollup.from`), mirroring EXACTLY the trigger keys\n * `register()` indexes under `_bySource`. The self-write reverse-denorm\n * output (`output.collection === source` with `denorm` declared) is\n * skipped — the SAME condition the old local DFS used; it is not a cycle\n * (see the comment `validate()` used to carry, now on this skip).\n * Rollups ADDITIONALLY get a dedicated `'rollup'`/`'aggregate'` edge\n * targeting the real `rollup.field` on the parent (`source`) — the\n * self-write output above only covers the cycle-DFS skip, not\n * dispatch/taint (Tasks 3/4/6), which need the real field.\n */\n edges(): ReadonlyArray<{ readonly target: FieldRef; readonly sources: readonly FieldRef[]; readonly kind: EdgeKind; readonly grain: Grain }> {\n const out: Array<{ target: FieldRef; sources: FieldRef[]; kind: EdgeKind; grain: Grain }> = []\n for (const reg of this.all()) {\n const spec = reg.spec\n const triggerCollections = [\n spec.source,\n ...(spec.sources ?? []),\n ...(spec.triggerBy ?? []).map((t) => t.collection),\n ...(spec.rollup ? [spec.rollup.from] : []),\n ]\n const sources: FieldRef[] = triggerCollections.map((c) => ({ collection: c, field: WHOLE_RECORD }))\n for (const key of Object.keys(spec.outputs)) {\n const output = spec.outputs[key]\n if (!output) continue\n if (output.shape === 'record' && output.collection === spec.source && output.denorm !== undefined) continue\n out.push({ target: { collection: output.collection, field: WHOLE_RECORD }, sources, kind: 'derivation', grain: 'record' })\n }\n if (spec.rollup) {\n out.push({\n target: { collection: spec.source, field: spec.rollup.field },\n sources: [{ collection: spec.rollup.from, field: WHOLE_RECORD }],\n kind: 'rollup',\n grain: 'aggregate',\n })\n }\n }\n return out\n }\n\n /**\n * Cycle detection, delegated to `ViaGraph.assertAcyclic()` (#638 Task 2 —\n * retires the local DFS). Call after all `register()` calls complete (i.e.\n * at vault open). Throws `DerivationCycleError` on the first cycle found —\n * SAME class/timing as before; the message/path is byte-identical to the\n * pre-#638 shape for a pure record-shape derivation cycle (the\n * `WHOLE_RECORD` artifact suffix is stripped back to a bare collection\n * name before re-throwing).\n *\n * `graph` is the caller's shared per-vault graph, ALREADY carrying this\n * registry's `edges()` (the caller registers them — see `Vault._initDerivations`)\n * — omit it (e.g. this registry's own unit tests) to validate this\n * registry's edges in isolation against a throwaway graph.\n */\n validate(graph?: ViaGraph): void {\n const g = graph ?? new ViaGraph()\n if (!graph) {\n for (const edge of this.edges()) g.registerDerived(edge.target, edge.sources, edge.kind, edge.grain)\n }\n try {\n g.assertAcyclic()\n } catch (e) {\n if (e instanceof DerivationCycleError) throw new DerivationCycleError(e.path.map(stripArtifactSuffix))\n throw e\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAWA,eAAsB,oBACpB,QACA,YAEA,QACA,SACiB;AACjB,QAAM,YAAY,KAAK,UAAU;AAAA,IAC/B;AAAA,IACA,SAAS,CAAC,GAAG,UAAU,EAAE,KAAK;AAAA,IAC9B,QAAQ,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA,IAIxB,GAAI,SAAS,SAAS,EAAE,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC;AAAA,EAC5D,CAAC;AACD,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,SAAS;AAChD,SAAO,UAAU,KAAK;AACxB;;;ACVA,IAAM,eAAe;AAOrB,SAAS,oBAAoB,WAA2B;AACtD,QAAM,SAAS,IAAI,YAAY;AAC/B,SAAO,UAAU,SAAS,MAAM,IAAI,UAAU,MAAM,GAAG,CAAC,OAAO,MAAM,IAAI;AAC3E;AAyCA,SAAS,sBAAsB,MAOmD;AAChF,QAAM,WAAqB,CAAC;AAC5B,QAAM,UAAoB,CAAC;AAC3B,aAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,KAAK,YAAY,CAAC,CAAC,GAAG;AAChE,aAAS,KAAK,KAAK;AACnB,UAAM,QAA4B,mBAAmB,KAAiD;AACtG,QAAI,MAAM,SAAS,UAAW,SAAQ,KAAK,KAAK;AAAA,EAClD;AACA,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,aAAa,CAAC,CAAC,GAAG;AAChE,aAAS,KAAK,KAAK;AACnB,UAAM,cAAe,KAA8C,eAAe,CAAC;AACnF,eAAW,KAAK,aAAa;AAC3B,UAAK,EAA8B,cAAc,cAC3C,EAAyB,SAAS,UAAW,SAAQ,KAAK,KAAK;AAAA,IACvE;AAAA,EACF;AACA,SAAO,EAAE,UAAU,QAAQ;AAC7B;AAEO,IAAM,qBAAN,MAAyB;AAAA,EACb,YAAY,oBAAI,IAAkC;AAAA,EAClD,YAAY,oBAAI,IAAkC;AAAA,EAClD,UAAU,oBAAI,IAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ/D,MAAM,SAAS,MAA+C;AAC5D,QAAI,KAAK,SAAS,UAAa,KAAK,QAAQ,IAAI,KAAK,IAAI,GAAG;AAC1D,YAAM,IAAI,2BAA2B,KAAK,MAAM,YAAY;AAAA,IAC9D;AAEA,UAAM,aAAa,OAAO,KAAK,KAAK,OAAO;AAC3C,UAAM,eAAe,MAAM,oBAAoB,KAAK,QAAQ,YAAY,KAAK,QAAQ,KAAK,OAAO;AACjG,UAAM,WAAW,mBAAmB,KAAK,SAAS;AAClD,UAAM,MAA0B,EAAE,MAAM,cAAc,SAAS;AAE/D,QAAI,KAAK,SAAS,OAAW,MAAK,QAAQ,IAAI,KAAK,MAAM,GAAG;AAE5D,UAAM,aAAa,KAAK,UAAU,IAAI,KAAK,MAAM;AACjD,QAAI,WAAY,YAAW,KAAK,GAAG;AAAA,QAC9B,MAAK,UAAU,IAAI,KAAK,QAAQ,CAAC,GAAG,CAAC;AAM1C,eAAW,SAAS,KAAK,WAAW,CAAC,GAAG;AACtC,YAAM,YAAY,KAAK,UAAU,IAAI,KAAK;AAC1C,UAAI,UAAW,WAAU,KAAK,GAAG;AAAA,UAC5B,MAAK,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC;AAAA,IACtC;AAMA,eAAW,KAAK,UAAU;AACxB,YAAM,cAAc,KAAK,UAAU,IAAI,EAAE,UAAU;AACnD,UAAI,YAAa,aAAY,KAAK,GAAG;AAAA,UAChC,MAAK,UAAU,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC;AAAA,IAC7C;AAQA,QAAI,KAAK,QAAQ;AACf,YAAM,aAAa,KAAK,UAAU,IAAI,KAAK,OAAO,IAAI;AACtD,UAAI,WAAY,YAAW,KAAK,GAAG;AAAA,UAC9B,MAAK,UAAU,IAAI,KAAK,OAAO,MAAM,CAAC,GAAG,CAAC;AAAA,IACjD;AAEA,eAAW,OAAO,YAAY;AAC5B,YAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,UAAI,CAAC,OAAQ;AACb,YAAM,mBAAmB,OAAO;AAChC,YAAM,MAAM,KAAK,UAAU,IAAI,gBAAgB;AAC/C,UAAI,IAAK,KAAI,KAAK,GAAG;AAAA,UAChB,MAAK,UAAU,IAAI,kBAAkB,CAAC,GAAG,CAAC;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,oBAAoB,QAAmD;AACrE,WAAO,KAAK,UAAU,IAAI,MAAM,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,0BAA0B,YAAuD;AAC/E,WAAO,KAAK,UAAU,IAAI,UAAU,KAAK,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,kBACE,gBACA,QACA,YACA,aAGgB,QACV;AACN,UAAM,UAAU,sBAAsB,cAAc,CAAC,CAAC;AACtD,UAAM,UAAU,IAAI,IAAI,QAAQ,OAAO;AACvC,UAAM,YAAY,gBAAgB,MAAM;AAOxC,QAAI,cAAc,UAAa,QAAQ,SAAS,EAAG;AACnD,UAAM,OAAO,cAAc,SAAY,SACnC,oBAAI,IAAI,CAAC,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,QAAQ,CAAC;AAC9D,UAAM,eAAe,oBAAI,IAAY;AACrC,UAAM,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,CAAC;AACxD,eAAW,OAAO,MAAM;AACtB,UAAI,IAAI,KAAK,WAAW,eAAgB;AACxC,iBAAW,OAAO,OAAO,OAAO,IAAI,KAAK,OAAO,GAAiE;AAC/G,YAAI,IAAI,eAAe,eAAgB,YAAW,KAAK,IAAI,UAAU,CAAC,EAAG,cAAa,IAAI,CAAC;AAAA,MAC7F;AAAA,IACF;AACA,UAAM,UAAU,CAAC,MACf,SAAS,UAAa,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC;AAC3D,eAAW,OAAO,MAAM;AACtB,YAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK;AACvC,iBAAW,KAAK,IAAI,UAAU;AAC5B,mBAAW,KAAK,EAAE,OAAO;AAGvB,cAAI,IAAI,KAAK,WAAW,gBAAgB;AACtC,gBAAI,QAAQ,IAAI,EAAE,EAAE,EAAG,OAAM,IAAI,gBAAgB,KAAK,qBAAqB,MAAM,gBAAgB,EAAE,IAAI,IAAI,CAAC;AAC5G,gBAAI,QAAQ,EAAE,EAAE,GAAG;AACjB,oBAAM,IAAI;AAAA,gBACR,eAAe,IAAI,0CAA0C,EAAE,EAAE,aAAa,cAAc;AAAA,cAAmE;AAAA,YACnK;AAAA,UACF;AACA,cAAI,EAAE,eAAe,kBAAkB,EAAE,SAAS,MAAM;AACtD,gBAAI,QAAQ,IAAI,EAAE,IAAI,EAAG,OAAM,IAAI,gBAAgB,KAAK,qBAAqB,MAAM,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAClH,gBAAI,QAAQ,EAAE,IAAI,GAAG;AACnB,oBAAM,IAAI;AAAA,gBACR,eAAe,IAAI,6BAA6B,EAAE,IAAI,mBAAmB,cAAc;AAAA,cAAkG;AAAA,YAC7L;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGQ,qBAAqB,MAAc,gBAAwB,OAAe,MAA6B;AAC7G,UAAM,QAAQ,SAAS,OACnB,uBAAuB,KAAK,aAAa,cAAc,MACvD,UAAU,KAAK,mBAAmB,cAAc;AACpD,WAAO,eAAe,IAAI,sBAAsB,KAAK;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAyC;AACvC,UAAM,OAAO,oBAAI,IAAwB;AACzC,eAAW,cAAc,KAAK,UAAU,OAAO,GAAG;AAChD,iBAAW,KAAK,WAAY,MAAK,IAAI,CAAC;AAAA,IACxC;AACA,WAAO,CAAC,GAAG,IAAI;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,QAA6I;AAC3I,UAAM,MAAsF,CAAC;AAC7F,eAAW,OAAO,KAAK,IAAI,GAAG;AAC5B,YAAM,OAAO,IAAI;AACjB,YAAM,qBAAqB;AAAA,QACzB,KAAK;AAAA,QACL,GAAI,KAAK,WAAW,CAAC;AAAA,QACrB,IAAI,KAAK,aAAa,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU;AAAA,QACjD,GAAI,KAAK,SAAS,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC;AAAA,MAC1C;AACA,YAAM,UAAsB,mBAAmB,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,aAAa,EAAE;AAClG,iBAAW,OAAO,OAAO,KAAK,KAAK,OAAO,GAAG;AAC3C,cAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,YAAI,CAAC,OAAQ;AACb,YAAI,OAAO,UAAU,YAAY,OAAO,eAAe,KAAK,UAAU,OAAO,WAAW,OAAW;AACnG,YAAI,KAAK,EAAE,QAAQ,EAAE,YAAY,OAAO,YAAY,OAAO,aAAa,GAAG,SAAS,MAAM,cAAc,OAAO,SAAS,CAAC;AAAA,MAC3H;AACA,UAAI,KAAK,QAAQ;AACf,YAAI,KAAK;AAAA,UACP,QAAQ,EAAE,YAAY,KAAK,QAAQ,OAAO,KAAK,OAAO,MAAM;AAAA,UAC5D,SAAS,CAAC,EAAE,YAAY,KAAK,OAAO,MAAM,OAAO,aAAa,CAAC;AAAA,UAC/D,MAAM;AAAA,UACN,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,SAAS,OAAwB;AAC/B,UAAM,IAAI,SAAS,IAAI,SAAS;AAChC,QAAI,CAAC,OAAO;AACV,iBAAW,QAAQ,KAAK,MAAM,EAAG,GAAE,gBAAgB,KAAK,QAAQ,KAAK,SAAS,KAAK,MAAM,KAAK,KAAK;AAAA,IACrG;AACA,QAAI;AACF,QAAE,cAAc;AAAA,IAClB,SAAS,GAAG;AACV,UAAI,aAAa,qBAAsB,OAAM,IAAI,qBAAqB,EAAE,KAAK,IAAI,mBAAmB,CAAC;AACrG,YAAM;AAAA,IACR;AAAA,EACF;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createNoydb
3
- } from "./chunk-XMF3GKUR.js";
3
+ } from "./chunk-ZVCC36XQ.js";
4
4
  import {
5
5
  deriveSchemaManifest
6
6
  } from "./chunk-BBWVXF57.js";
@@ -286,4 +286,4 @@ export {
286
286
  followRedirects,
287
287
  open
288
288
  };
289
- //# sourceMappingURL=chunk-E5OHKSBD.js.map
289
+ //# sourceMappingURL=chunk-BMELYFHU.js.map