@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.
- package/CHANGELOG.md +102 -0
- package/dist/cargo/index.js +1 -1
- package/dist/chunk-66TQOPFM.js +37 -0
- package/dist/chunk-66TQOPFM.js.map +1 -0
- package/dist/{chunk-H7XCIM3Z.js → chunk-AJQY44CE.js} +43 -16
- package/dist/chunk-AJQY44CE.js.map +1 -0
- package/dist/{chunk-E5OHKSBD.js → chunk-BMELYFHU.js} +2 -2
- package/dist/chunk-BWXGSSFX.js +1589 -0
- package/dist/chunk-BWXGSSFX.js.map +1 -0
- package/dist/{chunk-HN4FNA4X.js → chunk-COTPDJR5.js} +8 -8
- package/dist/{chunk-E3EBMC4G.js → chunk-E2MYJGSG.js} +2 -2
- package/dist/{chunk-JJR2JIN4.js → chunk-FFBYRWDJ.js} +2 -2
- package/dist/{chunk-WQF3QABE.js → chunk-IHFXR2VQ.js} +9 -79
- package/dist/chunk-IHFXR2VQ.js.map +1 -0
- package/dist/chunk-MGOXJIBV.js +176 -0
- package/dist/chunk-MGOXJIBV.js.map +1 -0
- package/dist/{chunk-KL7AS3HV.js → chunk-PDD75NUZ.js} +5 -2
- package/dist/chunk-PDD75NUZ.js.map +1 -0
- package/dist/chunk-RTBJ5IOO.js +87 -0
- package/dist/chunk-RTBJ5IOO.js.map +1 -0
- package/dist/{chunk-7NTBVFGD.js → chunk-SXCYYMVS.js} +2 -2
- package/dist/{chunk-THNJ3IKU.js → chunk-ULUMAZ5S.js} +2 -2
- package/dist/{chunk-NO272T7Q.js → chunk-V4PXLYWM.js} +2 -31
- package/dist/chunk-V4PXLYWM.js.map +1 -0
- package/dist/{chunk-SWVNZQVR.js → chunk-YPXNAP72.js} +2 -169
- package/dist/chunk-YPXNAP72.js.map +1 -0
- package/dist/{chunk-XMF3GKUR.js → chunk-ZVCC36XQ.js} +50 -870
- package/dist/chunk-ZVCC36XQ.js.map +1 -0
- package/dist/{collection-facade-MGGHQ3HU.js → collection-facade-4ACKIDDY.js} +4 -3
- package/dist/derivations/index.js +6 -2
- package/dist/{dispatch-XEBHUGBV.js → dispatch-MSTR5VBI.js} +10 -5
- package/dist/dispatch-MSTR5VBI.js.map +1 -0
- package/dist/{dispatch-44J4TL72.js → dispatch-PDP5TA73.js} +5 -5
- package/dist/{executor-KSPGNVDO.js → executor-YDDC5XGY.js} +4 -3
- package/dist/index.js +25 -21
- package/dist/index.js.map +1 -1
- package/dist/lazy/index.js +3 -2
- package/dist/materialized-views/index.js +4 -3
- package/dist/{noydb-JJXPICIC.js → noydb-2C6QQJ5S.js} +12 -9
- package/dist/pod/index.js +12 -9
- package/dist/{registry-BZQIVNNO.js → registry-D2YXKRYC.js} +7 -3
- package/dist/search/index.js +1 -1
- package/dist/{stale-KSPG6LFX.js → stale-2CHKZTMK.js} +2 -2
- package/dist/with-formula/derivations/registry.d.ts +6 -7
- package/dist/with-shape/introspection/describe.d.ts +29 -9
- package/package.json +3 -3
- package/dist/chunk-7BE7ZDVQ.js +0 -722
- package/dist/chunk-7BE7ZDVQ.js.map +0 -1
- package/dist/chunk-H7XCIM3Z.js.map +0 -1
- package/dist/chunk-KL7AS3HV.js.map +0 -1
- package/dist/chunk-NO272T7Q.js.map +0 -1
- package/dist/chunk-SWVNZQVR.js.map +0 -1
- package/dist/chunk-WQF3QABE.js.map +0 -1
- package/dist/chunk-XMF3GKUR.js.map +0 -1
- package/dist/dispatch-XEBHUGBV.js.map +0 -1
- /package/dist/{chunk-E5OHKSBD.js.map → chunk-BMELYFHU.js.map} +0 -0
- /package/dist/{chunk-HN4FNA4X.js.map → chunk-COTPDJR5.js.map} +0 -0
- /package/dist/{chunk-E3EBMC4G.js.map → chunk-E2MYJGSG.js.map} +0 -0
- /package/dist/{chunk-JJR2JIN4.js.map → chunk-FFBYRWDJ.js.map} +0 -0
- /package/dist/{chunk-7NTBVFGD.js.map → chunk-SXCYYMVS.js.map} +0 -0
- /package/dist/{chunk-THNJ3IKU.js.map → chunk-ULUMAZ5S.js.map} +0 -0
- /package/dist/{collection-facade-MGGHQ3HU.js.map → collection-facade-4ACKIDDY.js.map} +0 -0
- /package/dist/{dispatch-44J4TL72.js.map → dispatch-PDP5TA73.js.map} +0 -0
- /package/dist/{executor-KSPGNVDO.js.map → executor-YDDC5XGY.js.map} +0 -0
- /package/dist/{noydb-JJXPICIC.js.map → noydb-2C6QQJ5S.js.map} +0 -0
- /package/dist/{registry-BZQIVNNO.js.map → registry-D2YXKRYC.js.map} +0 -0
- /package/dist/{stale-KSPG6LFX.js.map → stale-2CHKZTMK.js.map} +0 -0
package/dist/chunk-7BE7ZDVQ.js
DELETED
|
@@ -1,722 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
jsonSchemaToFields
|
|
3
|
-
} from "./chunk-VYYM3MEN.js";
|
|
4
|
-
import {
|
|
5
|
-
derivePersistedSchema,
|
|
6
|
-
isZod4Schema
|
|
7
|
-
} from "./chunk-URHRIAV6.js";
|
|
8
|
-
import {
|
|
9
|
-
loadPersistedSchema
|
|
10
|
-
} from "./chunk-WWNYSV7S.js";
|
|
11
|
-
import {
|
|
12
|
-
isStaticDictDescriptor
|
|
13
|
-
} from "./chunk-TRGTKX5E.js";
|
|
14
|
-
import {
|
|
15
|
-
DerivationCycleError,
|
|
16
|
-
MaterializedViewCycleError
|
|
17
|
-
} from "./chunk-7O3Y4PPD.js";
|
|
18
|
-
|
|
19
|
-
// src/with-shape/introspection/field-meta.ts
|
|
20
|
-
var FieldMetaUnknownFieldError = class extends Error {
|
|
21
|
-
constructor(collection, key) {
|
|
22
|
-
super(`fieldMeta for collection "${collection}" references unknown field "${key}". Declare it in the schema/config or remove the fieldMeta entry.`);
|
|
23
|
-
this.collection = collection;
|
|
24
|
-
this.key = key;
|
|
25
|
-
this.name = "FieldMetaUnknownFieldError";
|
|
26
|
-
}
|
|
27
|
-
collection;
|
|
28
|
-
key;
|
|
29
|
-
};
|
|
30
|
-
function validateFieldMetaKeys(collection, fieldMeta, knownFields) {
|
|
31
|
-
for (const key of Object.keys(fieldMeta)) {
|
|
32
|
-
if (!knownFields.has(key)) throw new FieldMetaUnknownFieldError(collection, key);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function humanizeFieldKey(key) {
|
|
36
|
-
return key.replace(/[_-]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim().split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
37
|
-
}
|
|
38
|
-
function resolveFieldMeta(key, inputs) {
|
|
39
|
-
const { channel, zodMeta, inferred } = inputs;
|
|
40
|
-
const pick = (k) => channel?.[k] ?? zodMeta?.[k] ?? inferred?.[k];
|
|
41
|
-
const description = pick("description");
|
|
42
|
-
const semanticType = pick("semanticType");
|
|
43
|
-
const unit = pick("unit");
|
|
44
|
-
const sensitivity = pick("sensitivity");
|
|
45
|
-
const aggregate = pick("aggregate");
|
|
46
|
-
const aliases = pick("aliases");
|
|
47
|
-
const displayFor = pick("displayFor");
|
|
48
|
-
const widget = pick("widget");
|
|
49
|
-
const group = pick("group");
|
|
50
|
-
const order = pick("order");
|
|
51
|
-
return {
|
|
52
|
-
label: pick("label") ?? humanizeFieldKey(key),
|
|
53
|
-
...description !== void 0 ? { description } : {},
|
|
54
|
-
...semanticType !== void 0 ? { semanticType } : {},
|
|
55
|
-
...unit !== void 0 ? { unit } : {},
|
|
56
|
-
...sensitivity !== void 0 ? { sensitivity } : {},
|
|
57
|
-
...aggregate !== void 0 ? { aggregate } : {},
|
|
58
|
-
...aliases !== void 0 ? { aliases } : {},
|
|
59
|
-
...displayFor !== void 0 ? { displayFor } : {},
|
|
60
|
-
...widget !== void 0 ? { widget } : {},
|
|
61
|
-
...group !== void 0 ? { group } : {},
|
|
62
|
-
...order !== void 0 ? { order } : {}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// src/with-shape/introspection/describe.ts
|
|
67
|
-
var ZOD_META_KEYS = /* @__PURE__ */ new Set([
|
|
68
|
-
"label",
|
|
69
|
-
"description",
|
|
70
|
-
"unit",
|
|
71
|
-
"semanticType",
|
|
72
|
-
"sensitivity",
|
|
73
|
-
"aggregate",
|
|
74
|
-
"aliases",
|
|
75
|
-
"displayFor",
|
|
76
|
-
"group",
|
|
77
|
-
"order"
|
|
78
|
-
]);
|
|
79
|
-
function schemaFieldKeys(schema) {
|
|
80
|
-
let s = schema;
|
|
81
|
-
for (let depth = 0; depth < 10; depth++) {
|
|
82
|
-
if (s === null || typeof s !== "object") return void 0;
|
|
83
|
-
const shape = s.shape;
|
|
84
|
-
if (shape !== null && typeof shape === "object") {
|
|
85
|
-
const keys = Object.keys(shape);
|
|
86
|
-
return keys.length > 0 ? keys : void 0;
|
|
87
|
-
}
|
|
88
|
-
const def = s._def;
|
|
89
|
-
if (def?.schema !== void 0 && def.effect?.type === "refinement") {
|
|
90
|
-
s = def.schema;
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
return void 0;
|
|
94
|
-
}
|
|
95
|
-
return void 0;
|
|
96
|
-
}
|
|
97
|
-
async function deriveZodFields(schema) {
|
|
98
|
-
const envelope = await derivePersistedSchema(schema);
|
|
99
|
-
if (!envelope.jsonSchema) return {};
|
|
100
|
-
const isZod4 = isZod4Schema(schema);
|
|
101
|
-
const jsonSchema = envelope.jsonSchema;
|
|
102
|
-
const fieldDescriptors = jsonSchemaToFields(jsonSchema, "live-validator");
|
|
103
|
-
const propertiesRaw = jsonSchema["properties"];
|
|
104
|
-
const result = {};
|
|
105
|
-
for (const [key, descriptor] of Object.entries(fieldDescriptors)) {
|
|
106
|
-
let meta;
|
|
107
|
-
if (isZod4 && propertiesRaw) {
|
|
108
|
-
const prop = propertiesRaw[key];
|
|
109
|
-
if (prop) {
|
|
110
|
-
const extracted = {};
|
|
111
|
-
let hasAny = false;
|
|
112
|
-
for (const mk of ZOD_META_KEYS) {
|
|
113
|
-
if (mk in prop) {
|
|
114
|
-
extracted[mk] = prop[mk];
|
|
115
|
-
hasAny = true;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (hasAny) meta = extracted;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
result[key] = {
|
|
122
|
-
type: descriptor.type,
|
|
123
|
-
optional: descriptor.optional === true,
|
|
124
|
-
...descriptor.constraints !== void 0 ? { constraints: descriptor.constraints } : {},
|
|
125
|
-
...meta !== void 0 ? { meta } : {}
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
async function resolveDescribeFieldIds(store, vaultName, collectionName, getDEK) {
|
|
131
|
-
let dek;
|
|
132
|
-
try {
|
|
133
|
-
dek = await getDEK(collectionName);
|
|
134
|
-
} catch {
|
|
135
|
-
return {};
|
|
136
|
-
}
|
|
137
|
-
const persisted = await loadPersistedSchema(store, vaultName, collectionName, dek);
|
|
138
|
-
return persisted?.fieldIds !== void 0 ? { fieldIds: persisted.fieldIds } : {};
|
|
139
|
-
}
|
|
140
|
-
function deriveWidget(opts) {
|
|
141
|
-
if (opts.resolvedWidget !== void 0) return opts.resolvedWidget;
|
|
142
|
-
switch (opts.semanticType) {
|
|
143
|
-
case "date":
|
|
144
|
-
case "datetime":
|
|
145
|
-
return "date";
|
|
146
|
-
case "currency":
|
|
147
|
-
return "money";
|
|
148
|
-
case "entity":
|
|
149
|
-
return "ref-select";
|
|
150
|
-
case "url":
|
|
151
|
-
return "url";
|
|
152
|
-
case "email":
|
|
153
|
-
return "email";
|
|
154
|
-
case "percent":
|
|
155
|
-
return "number";
|
|
156
|
-
}
|
|
157
|
-
if (opts.dict !== void 0 || opts.lookup !== void 0) return "select";
|
|
158
|
-
if (opts.blob !== void 0) return "file";
|
|
159
|
-
if (opts.type === "boolean") return "checkbox";
|
|
160
|
-
if (opts.type === "number") return "number";
|
|
161
|
-
return "text";
|
|
162
|
-
}
|
|
163
|
-
function buildDescription(input) {
|
|
164
|
-
const { collection, fieldMeta, moneyFields, dictKeyFields, lookupFields, computed, refs, zodFields, schema, dictLabels, meta, i18nFields, classified, taint, fieldIds } = input;
|
|
165
|
-
const lookupFragments = input.viaFragments?.["lookup"]?.lookupFields;
|
|
166
|
-
const blobFragments = input.viaFragments?.["blob"]?.blobFields;
|
|
167
|
-
const validatorKeys = zodFields !== void 0 && Object.keys(zodFields).length > 0 ? Object.keys(zodFields) : schemaFieldKeys(schema);
|
|
168
|
-
const canEnumerateFields = validatorKeys !== void 0;
|
|
169
|
-
if (canEnumerateFields && fieldMeta !== void 0) {
|
|
170
|
-
const knownFields = /* @__PURE__ */ new Set([
|
|
171
|
-
...Object.keys(moneyFields ?? {}),
|
|
172
|
-
...Object.keys(dictKeyFields ?? {}),
|
|
173
|
-
...Object.keys(refs),
|
|
174
|
-
...Object.keys(computed ?? {}),
|
|
175
|
-
...validatorKeys ?? [],
|
|
176
|
-
...Object.keys(i18nFields ?? {}),
|
|
177
|
-
...Object.keys(lookupFields ?? {}),
|
|
178
|
-
...Object.keys(blobFragments ?? {}),
|
|
179
|
-
...Object.keys(classified ?? {})
|
|
180
|
-
]);
|
|
181
|
-
validateFieldMetaKeys(collection, fieldMeta, knownFields);
|
|
182
|
-
}
|
|
183
|
-
const allKeys = /* @__PURE__ */ new Set([
|
|
184
|
-
...Object.keys(moneyFields ?? {}),
|
|
185
|
-
...Object.keys(dictKeyFields ?? {}),
|
|
186
|
-
...Object.keys(lookupFields ?? {}),
|
|
187
|
-
...Object.keys(refs),
|
|
188
|
-
...Object.keys(computed ?? {}),
|
|
189
|
-
...Object.keys(fieldMeta ?? {}),
|
|
190
|
-
...Object.keys(zodFields ?? {}),
|
|
191
|
-
...Object.keys(i18nFields ?? {}),
|
|
192
|
-
...Object.keys(classified ?? {}),
|
|
193
|
-
...Object.keys(blobFragments ?? {})
|
|
194
|
-
]);
|
|
195
|
-
const fields = [];
|
|
196
|
-
for (const key of [...allKeys].sort()) {
|
|
197
|
-
const zod = zodFields?.[key];
|
|
198
|
-
const money = moneyFields?.[key];
|
|
199
|
-
const dict = dictKeyFields?.[key];
|
|
200
|
-
const lookupDesc = lookupFields?.[key];
|
|
201
|
-
const refDesc = refs[key];
|
|
202
|
-
const isComputed = computed !== void 0 && key in computed;
|
|
203
|
-
const i18nDesc = i18nFields?.[key];
|
|
204
|
-
const cls = classified?.[key];
|
|
205
|
-
const blobFragmentEntry = blobFragments?.[key];
|
|
206
|
-
const taintPosture = taint?.postures.get(key);
|
|
207
|
-
let type = zod?.type ?? "unknown";
|
|
208
|
-
const inferred = {};
|
|
209
|
-
let moneyBlock;
|
|
210
|
-
let dictBlock;
|
|
211
|
-
let refBlock;
|
|
212
|
-
let lookupBlock;
|
|
213
|
-
let blobBlock;
|
|
214
|
-
if (money) {
|
|
215
|
-
type = "number";
|
|
216
|
-
inferred.semanticType = "currency";
|
|
217
|
-
inferred.aggregate = "sum";
|
|
218
|
-
const currency = money.soleCurrency();
|
|
219
|
-
const scale = currency !== void 0 ? money.scaleFor(currency) : void 0;
|
|
220
|
-
moneyBlock = {
|
|
221
|
-
mode: money.mode,
|
|
222
|
-
...currency !== void 0 ? { currency } : {},
|
|
223
|
-
...scale !== void 0 ? { scale } : {},
|
|
224
|
-
...money.rounding !== void 0 ? { rounding: money.rounding } : {}
|
|
225
|
-
};
|
|
226
|
-
} else if (refDesc) {
|
|
227
|
-
type = refDesc.isArray ? "array" : "string";
|
|
228
|
-
inferred.semanticType = "entity";
|
|
229
|
-
refBlock = {
|
|
230
|
-
target: refDesc.target,
|
|
231
|
-
mode: refDesc.mode,
|
|
232
|
-
...refDesc.isArray ? { isArray: true } : {}
|
|
233
|
-
};
|
|
234
|
-
} else if (dict) {
|
|
235
|
-
type = "enum";
|
|
236
|
-
if (isStaticDictDescriptor(dict)) {
|
|
237
|
-
const displayLocale = dict.displayLocale;
|
|
238
|
-
const values = dict.keys.map((k) => {
|
|
239
|
-
const localeMap = dict.table[k];
|
|
240
|
-
const label = displayLocale !== void 0 ? localeMap?.[displayLocale] ?? void 0 : void 0;
|
|
241
|
-
return label !== void 0 ? { value: k, label } : { value: k };
|
|
242
|
-
});
|
|
243
|
-
dictBlock = { name: dict.name, static: true, values };
|
|
244
|
-
} else {
|
|
245
|
-
const labelMap = dictLabels?.[dict.name];
|
|
246
|
-
const labelMapHasEntries = labelMap !== void 0 && Object.keys(labelMap).length > 0;
|
|
247
|
-
if (labelMapHasEntries) {
|
|
248
|
-
const values = Object.entries(labelMap).map(([value, label]) => ({ value, label }));
|
|
249
|
-
dictBlock = { name: dict.name, static: false, values };
|
|
250
|
-
} else if (dict.keys !== void 0) {
|
|
251
|
-
const values = dict.keys.map((k) => {
|
|
252
|
-
const label = dict.labels?.[k];
|
|
253
|
-
return label !== void 0 ? { value: k, label } : { value: k };
|
|
254
|
-
});
|
|
255
|
-
dictBlock = { name: dict.name, static: false, values };
|
|
256
|
-
} else {
|
|
257
|
-
dictBlock = { name: dict.name, static: false };
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
} else if (lookupDesc) {
|
|
261
|
-
type = "enum";
|
|
262
|
-
const lookupLabelMap = dictLabels?.[lookupDesc.dimension];
|
|
263
|
-
const lookupLabelMapHasEntries = lookupLabelMap !== void 0 && Object.keys(lookupLabelMap).length > 0;
|
|
264
|
-
if (lookupDesc.table !== void 0) {
|
|
265
|
-
const displayLocale = lookupDesc.displayLocale;
|
|
266
|
-
const table = lookupDesc.table;
|
|
267
|
-
const values = (lookupDesc.keys ?? Object.keys(table)).map((k) => {
|
|
268
|
-
const localeMap = table[k];
|
|
269
|
-
const label = displayLocale !== void 0 ? localeMap?.[displayLocale] ?? void 0 : void 0;
|
|
270
|
-
return label !== void 0 ? { value: k, label } : { value: k };
|
|
271
|
-
});
|
|
272
|
-
dictBlock = { name: lookupDesc.dimension, static: true, values };
|
|
273
|
-
} else if (lookupLabelMapHasEntries) {
|
|
274
|
-
const values = Object.entries(lookupLabelMap).map(([value, label]) => ({ value, label }));
|
|
275
|
-
dictBlock = { name: lookupDesc.dimension, static: false, values };
|
|
276
|
-
} else if (lookupDesc.keys !== void 0) {
|
|
277
|
-
const values = lookupDesc.keys.map((k) => {
|
|
278
|
-
const label = lookupDesc.labels?.[k];
|
|
279
|
-
return label !== void 0 ? { value: k, label } : { value: k };
|
|
280
|
-
});
|
|
281
|
-
dictBlock = { name: lookupDesc.dimension, static: false, values };
|
|
282
|
-
} else {
|
|
283
|
-
dictBlock = { name: lookupDesc.dimension, static: false };
|
|
284
|
-
}
|
|
285
|
-
} else if (i18nDesc) {
|
|
286
|
-
type = "string";
|
|
287
|
-
} else if (isComputed) {
|
|
288
|
-
} else if (blobFragmentEntry !== void 0) {
|
|
289
|
-
type = "blob";
|
|
290
|
-
blobBlock = { ...blobFragmentEntry, queryable: "none" };
|
|
291
|
-
}
|
|
292
|
-
const lookupFragmentEntry = lookupFragments?.[key];
|
|
293
|
-
if (lookupFragmentEntry !== void 0) {
|
|
294
|
-
lookupBlock = {
|
|
295
|
-
...lookupFragmentEntry.dimension !== void 0 ? { dimension: lookupFragmentEntry.dimension } : {},
|
|
296
|
-
backing: lookupFragmentEntry.backing,
|
|
297
|
-
vocabulary: lookupFragmentEntry.vocabulary,
|
|
298
|
-
key: lookupFragmentEntry.key,
|
|
299
|
-
onDelete: lookupFragmentEntry.onDelete,
|
|
300
|
-
...lookupFragmentEntry.altKeys !== void 0 ? { altKeys: lookupFragmentEntry.altKeys } : {},
|
|
301
|
-
...lookupFragmentEntry.present !== void 0 ? { present: lookupFragmentEntry.present } : {},
|
|
302
|
-
...lookupFragmentEntry.sortBy !== void 0 ? { sortBy: lookupFragmentEntry.sortBy } : {},
|
|
303
|
-
...lookupFragmentEntry.keys !== void 0 ? { keys: lookupFragmentEntry.keys } : {}
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
if (cls !== void 0) inferred.sensitivity = cls.sensitivity;
|
|
307
|
-
const channelEntry = fieldMeta?.[key];
|
|
308
|
-
const zodMeta = zod?.meta;
|
|
309
|
-
const resolved = resolveFieldMeta(key, {
|
|
310
|
-
...channelEntry !== void 0 ? { channel: channelEntry } : {},
|
|
311
|
-
...zodMeta !== void 0 ? { zodMeta } : {},
|
|
312
|
-
inferred
|
|
313
|
-
});
|
|
314
|
-
let i18nBlock;
|
|
315
|
-
if (i18nDesc !== void 0) {
|
|
316
|
-
const locales = i18nDesc.options.languages;
|
|
317
|
-
const densify = i18nDesc.options.densifyOnWrite;
|
|
318
|
-
i18nBlock = {
|
|
319
|
-
...locales !== void 0 ? { locales } : {},
|
|
320
|
-
...densify !== void 0 ? { densify } : {}
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
const widget = deriveWidget({
|
|
324
|
-
type,
|
|
325
|
-
...resolved.semanticType !== void 0 ? { semanticType: resolved.semanticType } : {},
|
|
326
|
-
...dictBlock !== void 0 ? { dict: dictBlock } : {},
|
|
327
|
-
...lookupBlock !== void 0 ? { lookup: lookupBlock } : {},
|
|
328
|
-
...blobBlock !== void 0 ? { blob: blobBlock } : {},
|
|
329
|
-
...resolved.widget !== void 0 ? { resolvedWidget: resolved.widget } : {}
|
|
330
|
-
});
|
|
331
|
-
const editable = !isComputed && key !== "id" && blobBlock === void 0;
|
|
332
|
-
const field = {
|
|
333
|
-
key,
|
|
334
|
-
...fieldIds?.[key] !== void 0 ? { id: fieldIds[key] } : {},
|
|
335
|
-
type,
|
|
336
|
-
optional: zod?.optional ?? false,
|
|
337
|
-
...zod?.constraints !== void 0 ? { constraints: zod.constraints } : {},
|
|
338
|
-
label: resolved.label,
|
|
339
|
-
...resolved.description !== void 0 ? { description: resolved.description } : {},
|
|
340
|
-
...resolved.group !== void 0 ? { group: resolved.group } : {},
|
|
341
|
-
...resolved.order !== void 0 ? { order: resolved.order } : {},
|
|
342
|
-
...resolved.semanticType !== void 0 ? { semanticType: resolved.semanticType } : {},
|
|
343
|
-
...resolved.unit !== void 0 ? { unit: resolved.unit } : {},
|
|
344
|
-
...resolved.sensitivity !== void 0 ? { sensitivity: resolved.sensitivity } : {},
|
|
345
|
-
...resolved.aggregate !== void 0 ? { aggregate: resolved.aggregate } : {},
|
|
346
|
-
...resolved.aliases !== void 0 ? { aliases: resolved.aliases } : {},
|
|
347
|
-
...resolved.displayFor !== void 0 ? { displayFor: resolved.displayFor } : {},
|
|
348
|
-
...refBlock !== void 0 ? { ref: refBlock } : {},
|
|
349
|
-
...moneyBlock !== void 0 ? { money: moneyBlock } : {},
|
|
350
|
-
...dictBlock !== void 0 ? { dict: dictBlock } : {},
|
|
351
|
-
...lookupBlock !== void 0 ? { lookup: lookupBlock } : {},
|
|
352
|
-
...blobBlock !== void 0 ? { blob: blobBlock } : {},
|
|
353
|
-
...isComputed ? { computed: true } : {},
|
|
354
|
-
...i18nBlock !== void 0 ? { i18n: i18nBlock } : {},
|
|
355
|
-
widget,
|
|
356
|
-
editable,
|
|
357
|
-
...cls !== void 0 ? {
|
|
358
|
-
classified: {
|
|
359
|
-
preset: cls.preset,
|
|
360
|
-
storage: cls.storage,
|
|
361
|
-
list: cls.list.kind === "omit" ? "omit" : cls.list.kind === "mask" ? { mask: cls.list.pattern } : { rider: cls.list.rider },
|
|
362
|
-
...cls.equatable === true ? { equatable: true } : {}
|
|
363
|
-
}
|
|
364
|
-
} : {},
|
|
365
|
-
...taintPosture !== void 0 ? { taint: { posture: taintPosture, forcedBy: taint?.provenance?.get(key) ?? [] } } : {}
|
|
366
|
-
};
|
|
367
|
-
fields.push(field);
|
|
368
|
-
}
|
|
369
|
-
const collectionMeta = {
|
|
370
|
-
...meta,
|
|
371
|
-
label: meta?.label ?? humanizeFieldKey(collection)
|
|
372
|
-
};
|
|
373
|
-
return {
|
|
374
|
-
collection,
|
|
375
|
-
fields,
|
|
376
|
-
meta: collectionMeta
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// src/kernel/via/graph.ts
|
|
381
|
-
var DEFAULT_POSTURE = { encryptedAtRest: "envelope", queryable: "full", exportable: true, forgettable: false };
|
|
382
|
-
var QUERYABLE_RANK = {
|
|
383
|
-
none: 0,
|
|
384
|
-
"det-exact": 1,
|
|
385
|
-
ordered: 2,
|
|
386
|
-
full: 3
|
|
387
|
-
};
|
|
388
|
-
function foldPosture(a, b) {
|
|
389
|
-
return {
|
|
390
|
-
encryptedAtRest: a.encryptedAtRest === "sealed" || b.encryptedAtRest === "sealed" ? "sealed" : "envelope",
|
|
391
|
-
queryable: QUERYABLE_RANK[a.queryable] <= QUERYABLE_RANK[b.queryable] ? a.queryable : b.queryable,
|
|
392
|
-
exportable: a.exportable && b.exportable,
|
|
393
|
-
forgettable: a.forgettable || b.forgettable
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
function foldWildcardSecurity(base, contributor) {
|
|
397
|
-
return {
|
|
398
|
-
encryptedAtRest: base.encryptedAtRest === "sealed" || contributor.encryptedAtRest === "sealed" ? "sealed" : "envelope",
|
|
399
|
-
queryable: base.queryable,
|
|
400
|
-
exportable: base.exportable && contributor.exportable,
|
|
401
|
-
forgettable: base.forgettable || contributor.forgettable
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
var FOLDED_KINDS = /* @__PURE__ */ new Set(["derivation", "rollup", "mv", "overlay"]);
|
|
405
|
-
function isDefaultPosture(p) {
|
|
406
|
-
return p.encryptedAtRest === DEFAULT_POSTURE.encryptedAtRest && p.queryable === DEFAULT_POSTURE.queryable && p.exportable === DEFAULT_POSTURE.exportable && p.forgettable === DEFAULT_POSTURE.forgettable;
|
|
407
|
-
}
|
|
408
|
-
var SEP = "\0";
|
|
409
|
-
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
410
|
-
function nodeId(ref) {
|
|
411
|
-
return `${ref.collection}${SEP}${ref.field}`;
|
|
412
|
-
}
|
|
413
|
-
function displayNodeId(id) {
|
|
414
|
-
const sep = id.indexOf(SEP);
|
|
415
|
-
return `${id.slice(0, sep)}.${id.slice(sep + 1)}`;
|
|
416
|
-
}
|
|
417
|
-
var ViaGraph = class {
|
|
418
|
-
/** Declared source-field postures (registerField), keyed by node id. */
|
|
419
|
-
_posture = /* @__PURE__ */ new Map();
|
|
420
|
-
/** Every derived target's registration, keyed by the target's node id. */
|
|
421
|
-
_in = /* @__PURE__ */ new Map();
|
|
422
|
-
/** source node id -> derived edges that depend on it (dispatch/erasure), each carrying
|
|
423
|
-
* its own registration's `kind` (#678 — see {@link OutEdge}). */
|
|
424
|
-
_out = /* @__PURE__ */ new Map();
|
|
425
|
-
/** Memoized effective posture per derived target node id. */
|
|
426
|
-
_effectiveCache = /* @__PURE__ */ new Map();
|
|
427
|
-
/** Memoized whole-collection security-axes fold for `'*'` wildcard LEAF nodes (#642),
|
|
428
|
-
* keyed by collection name — see {@link _wildcardContribution}. Cleared alongside
|
|
429
|
-
* `_effectiveCache` on every `registerField`/`registerDerived` (a later-registered
|
|
430
|
-
* field must re-fold on the next read — registration ordering is free). */
|
|
431
|
-
_wildcardCache = /* @__PURE__ */ new Map();
|
|
432
|
-
/** Collections with at least one classified field (#638 Task 2 fix wave 2,
|
|
433
|
-
* Finding I1 — the reconcile path's combined-state leak guard memory). */
|
|
434
|
-
_classifiedCollections = /* @__PURE__ */ new Set();
|
|
435
|
-
/** Computed field names declared with no `deps` entry, per collection
|
|
436
|
-
* (Finding I1 — such a field registers no edge when no classified field is
|
|
437
|
-
* present yet, so a LATER, separate reconcile call attaching classifiedFields
|
|
438
|
-
* still needs to see it regardless of declaration order). */
|
|
439
|
-
_depslessComputed = /* @__PURE__ */ new Map();
|
|
440
|
-
/** Declare a source field's posture (money/i18n/classified/plain). Plain fields
|
|
441
|
-
* default to `DEFAULT_POSTURE`; a later declaration for the same node wins-first (idempotent). */
|
|
442
|
-
registerField(collection, field, posture) {
|
|
443
|
-
const id = nodeId({ collection, field });
|
|
444
|
-
if (this._posture.has(id)) return;
|
|
445
|
-
this._posture.set(id, posture);
|
|
446
|
-
this._effectiveCache.clear();
|
|
447
|
-
this._wildcardCache.clear();
|
|
448
|
-
}
|
|
449
|
-
/** A derived target depends on `sources` (may be cross-collection). `kind`/`grain`
|
|
450
|
-
* drive dispatch + erasure semantics; sources drive taint. Re-registering the same
|
|
451
|
-
* target replaces `_in` but does not prune stale `_out` edges — callers must
|
|
452
|
-
* register each target at most once per graph lifetime. `onDelete`/`keyField` (#650 Task 5)
|
|
453
|
-
* are meaningful only for `kind === 'ref'` edges — {@link referencingEdgesOf} reads them back. */
|
|
454
|
-
registerDerived(target, sources, kind, grain, onDelete, keyField) {
|
|
455
|
-
const id = nodeId(target);
|
|
456
|
-
this._in.set(id, {
|
|
457
|
-
target,
|
|
458
|
-
sources,
|
|
459
|
-
kind,
|
|
460
|
-
grain,
|
|
461
|
-
...onDelete !== void 0 ? { onDelete } : {},
|
|
462
|
-
...keyField !== void 0 ? { keyField } : {}
|
|
463
|
-
});
|
|
464
|
-
for (const source of sources) {
|
|
465
|
-
const sourceId = nodeId(source);
|
|
466
|
-
const outEdge = { target, kind };
|
|
467
|
-
const dependents = this._out.get(sourceId);
|
|
468
|
-
if (dependents) dependents.push(outEdge);
|
|
469
|
-
else this._out.set(sourceId, [outEdge]);
|
|
470
|
-
}
|
|
471
|
-
this._effectiveCache.clear();
|
|
472
|
-
this._wildcardCache.clear();
|
|
473
|
-
}
|
|
474
|
-
/** Whether `target` already has a registered in-edge — lets a caller skip
|
|
475
|
-
* re-registering the same target (#638 Task 2 fix wave 2, Finding I2i:
|
|
476
|
-
* `registerDerived`'s at-most-once contract must hold across repeated
|
|
477
|
-
* identical `vault.collection()` calls, not just within a single one). */
|
|
478
|
-
hasDerived(target) {
|
|
479
|
-
return this._in.has(nodeId(target));
|
|
480
|
-
}
|
|
481
|
-
/** Mark/query a collection as having declared at least one classified field. */
|
|
482
|
-
markClassified(collection) {
|
|
483
|
-
this._classifiedCollections.add(collection);
|
|
484
|
-
}
|
|
485
|
-
isClassified(collection) {
|
|
486
|
-
return this._classifiedCollections.has(collection);
|
|
487
|
-
}
|
|
488
|
-
/** Mark/query a collection's depsless (no declared `deps`) computed
|
|
489
|
-
* field names — see `_depslessComputed`'s doc comment above. */
|
|
490
|
-
markDepslessComputed(collection, field) {
|
|
491
|
-
let set = this._depslessComputed.get(collection);
|
|
492
|
-
if (!set) {
|
|
493
|
-
set = /* @__PURE__ */ new Set();
|
|
494
|
-
this._depslessComputed.set(collection, set);
|
|
495
|
-
}
|
|
496
|
-
set.add(field);
|
|
497
|
-
}
|
|
498
|
-
depslessComputedFields(collection) {
|
|
499
|
-
return this._depslessComputed.get(collection) ?? EMPTY_SET;
|
|
500
|
-
}
|
|
501
|
-
/** Every field name the graph already has memory of for `collection` — from an
|
|
502
|
-
* EARLIER, separate `vault.collection()` call (registered postures, derived
|
|
503
|
-
* targets, depsless-computed names) — regardless of which via feature declared
|
|
504
|
-
* it. #645 — `via/graph-wiring.ts`'s reconcile-path `knownFields` universe
|
|
505
|
-
* (`collectKnownFieldNames`) is scoped to THIS call's own options only, so a
|
|
506
|
-
* computed field attached in a LATER call whose `deps` correctly names a field
|
|
507
|
-
* declared in an EARLIER call was spuriously refused as "unknown"; this method
|
|
508
|
-
* lets that call site union in the graph's cross-call memory. Excludes the `'*'`
|
|
509
|
-
* wildcard target (an overlay/derivation whole-record fold node, never a real
|
|
510
|
-
* record field — see {@link registerDerived}'s doc comment). */
|
|
511
|
-
knownFieldNames(collection) {
|
|
512
|
-
const out = /* @__PURE__ */ new Set();
|
|
513
|
-
const prefix = `${collection}${SEP}`;
|
|
514
|
-
for (const id of this._posture.keys()) {
|
|
515
|
-
if (id.startsWith(prefix)) out.add(id.slice(prefix.length));
|
|
516
|
-
}
|
|
517
|
-
for (const edge of this._in.values()) {
|
|
518
|
-
if (edge.target.collection === collection && edge.target.field !== "*") out.add(edge.target.field);
|
|
519
|
-
}
|
|
520
|
-
const depsless = this._depslessComputed.get(collection);
|
|
521
|
-
if (depsless) for (const field of depsless) out.add(field);
|
|
522
|
-
return out;
|
|
523
|
-
}
|
|
524
|
-
/** Reject cycles at declare time (vault open). Throws `DerivationCycleError` for a
|
|
525
|
-
* derivation/rollup/computed cycle, `MaterializedViewCycleError` for an MV cycle —
|
|
526
|
-
* same classes + message shape the registries throw today (behavior lock). */
|
|
527
|
-
assertAcyclic() {
|
|
528
|
-
const visited = /* @__PURE__ */ new Set();
|
|
529
|
-
const stack = [];
|
|
530
|
-
const notRefEdge = (entry) => entry.kind !== "ref";
|
|
531
|
-
const neighboursOf = (id) => {
|
|
532
|
-
const own = (this._out.get(id) ?? []).filter(notRefEdge).map((entry) => entry.target);
|
|
533
|
-
const sep = id.indexOf(SEP);
|
|
534
|
-
if (id.slice(sep + 1) === "*") return own;
|
|
535
|
-
const wildcard = (this._out.get(`${id.slice(0, sep)}${SEP}*`) ?? []).filter(notRefEdge).map((entry) => entry.target);
|
|
536
|
-
if (wildcard.length === 0) return own;
|
|
537
|
-
return [...own, ...wildcard];
|
|
538
|
-
};
|
|
539
|
-
const visit = (id) => {
|
|
540
|
-
const idx = stack.indexOf(id);
|
|
541
|
-
if (idx !== -1) {
|
|
542
|
-
const cycle = stack.slice(idx).concat(id);
|
|
543
|
-
const isMv = cycle.some((cycleId) => this._in.get(cycleId)?.kind === "mv");
|
|
544
|
-
const path = cycle.map(displayNodeId);
|
|
545
|
-
if (isMv) throw new MaterializedViewCycleError(path);
|
|
546
|
-
throw new DerivationCycleError(path);
|
|
547
|
-
}
|
|
548
|
-
if (visited.has(id)) return;
|
|
549
|
-
stack.push(id);
|
|
550
|
-
for (const dependent of neighboursOf(id)) visit(nodeId(dependent));
|
|
551
|
-
stack.pop();
|
|
552
|
-
visited.add(id);
|
|
553
|
-
};
|
|
554
|
-
for (const id of this._out.keys()) visit(id);
|
|
555
|
-
}
|
|
556
|
-
/** A leaf (non-derived) node's own posture contribution: its declared posture,
|
|
557
|
-
* or `DEFAULT_POSTURE` if never declared via `registerField`. */
|
|
558
|
-
_declaredPosture(id) {
|
|
559
|
-
return this._posture.get(id) ?? DEFAULT_POSTURE;
|
|
560
|
-
}
|
|
561
|
-
/** A node's posture contribution when folded into a dependent: recurse if it is itself
|
|
562
|
-
* derived; else its declared/default posture — UNLESS it is a `'*'` LEAF node consumed
|
|
563
|
-
* by a folded formula kind (#642, `derivation|rollup|mv|overlay`), in which case it
|
|
564
|
-
* contributes its collection's whole-record security fold ({@link _wildcardContribution}).
|
|
565
|
-
* `kind` is the CONSUMING edge's kind, threaded from {@link _computeEffective}. `'ref'`
|
|
566
|
-
* edges (and the provenance-only untyped call, `kind` left `undefined`) keep `'*'` =
|
|
567
|
-
* identity — the phase-D lookup reliance (`via/lookup/registry.ts:392-397`) that a
|
|
568
|
-
* referencing field must not seal just because its dimension collection has a classified
|
|
569
|
-
* column. */
|
|
570
|
-
_contribution(id, kind) {
|
|
571
|
-
const edge = this._in.get(id);
|
|
572
|
-
if (edge) return this._computeEffective(id, edge);
|
|
573
|
-
if (kind !== void 0 && FOLDED_KINDS.has(kind) && id.endsWith(`${SEP}*`)) {
|
|
574
|
-
return this._wildcardContribution(id.slice(0, -2));
|
|
575
|
-
}
|
|
576
|
-
return this._declaredPosture(id);
|
|
577
|
-
}
|
|
578
|
-
/** Lazy fold (#642) of a collection's REGISTERED field postures on the security axes only
|
|
579
|
-
* ({@link foldWildcardSecurity} — sealed-wins encryptedAtRest, AND exportable, OR
|
|
580
|
-
* forgettable; queryable stays at DEFAULT_POSTURE's 'full', never folded), seeded at
|
|
581
|
-
* DEFAULT_POSTURE. This is the collection-level posture a `'*'` LEAF node contributes to a
|
|
582
|
-
* folded-kind formula edge (derivation/rollup/mv/overlay) — see {@link _contribution}. A
|
|
583
|
-
* plain (unregistered) field contributes nothing (the identity), so the fold is strictly
|
|
584
|
-
* more conservative than deps-based taint and never hits the KNOWN-LIMIT wall (it names no
|
|
585
|
-
* fields — seam map §1d). Memoized per collection in `_wildcardCache`. */
|
|
586
|
-
_wildcardContribution(collection) {
|
|
587
|
-
const cached = this._wildcardCache.get(collection);
|
|
588
|
-
if (cached) return cached;
|
|
589
|
-
let result = DEFAULT_POSTURE;
|
|
590
|
-
const prefix = `${collection}${SEP}`;
|
|
591
|
-
for (const [id, posture] of this._posture) {
|
|
592
|
-
if (!id.startsWith(prefix) || id === `${prefix}*`) continue;
|
|
593
|
-
result = foldWildcardSecurity(result, posture);
|
|
594
|
-
}
|
|
595
|
-
this._wildcardCache.set(collection, result);
|
|
596
|
-
return result;
|
|
597
|
-
}
|
|
598
|
-
_computeEffective(id, edge) {
|
|
599
|
-
const cached = this._effectiveCache.get(id);
|
|
600
|
-
if (cached) return cached;
|
|
601
|
-
let result = DEFAULT_POSTURE;
|
|
602
|
-
for (const source of edge.sources) {
|
|
603
|
-
result = foldPosture(result, this._contribution(nodeId(source), edge.kind));
|
|
604
|
-
}
|
|
605
|
-
if (edge.grain === "virtual" && result.queryable !== "none") {
|
|
606
|
-
result = { ...result, queryable: "none" };
|
|
607
|
-
}
|
|
608
|
-
this._effectiveCache.set(id, result);
|
|
609
|
-
return result;
|
|
610
|
-
}
|
|
611
|
-
/** Strictest source posture on every axis, per §2. `undefined` when `target` has no
|
|
612
|
-
* in-edges (not a derived field). Transitive: folds through chained derivations. */
|
|
613
|
-
effectivePosture(target) {
|
|
614
|
-
const id = nodeId(target);
|
|
615
|
-
const edge = this._in.get(id);
|
|
616
|
-
if (!edge) return void 0;
|
|
617
|
-
return this._computeEffective(id, edge);
|
|
618
|
-
}
|
|
619
|
-
/** Per-collection { field → effectivePosture } overlay the pipeline consumes (Task 3). */
|
|
620
|
-
taintedPostures(collection) {
|
|
621
|
-
const out = /* @__PURE__ */ new Map();
|
|
622
|
-
for (const edge of this._in.values()) {
|
|
623
|
-
if (edge.target.collection !== collection) continue;
|
|
624
|
-
out.set(edge.target.field, this._computeEffective(nodeId(edge.target), edge));
|
|
625
|
-
}
|
|
626
|
-
return out;
|
|
627
|
-
}
|
|
628
|
-
/** Materialized (`grain !== 'virtual'`) derived fields on `collection` whose effective
|
|
629
|
-
* encryptedAtRest resolves to 'sealed' — the taint-seal set (Task 3). #638 Task 7
|
|
630
|
-
* makes the `grain !== 'virtual'` filter meaningful: a `computed(fn, { mode: 'virtual' })`
|
|
631
|
-
* field is never stored (rides the `present` phase, seam map Part 4's money-Formatted/
|
|
632
|
-
* i18n-Label precedent), so it is EXCLUDED here even when its effective `encryptedAtRest`
|
|
633
|
-
* folds to `'sealed'` — there is no envelope slot to seal. It still surfaces in
|
|
634
|
-
* {@link taintedPostures} (query refusal via `postureFor`'s `queryable` clamp above, and
|
|
635
|
-
* export refusal via `exportable`) — only the AT-REST SEALING ACTION is skipped. */
|
|
636
|
-
taintSealedFields(collection) {
|
|
637
|
-
const out = /* @__PURE__ */ new Set();
|
|
638
|
-
for (const edge of this._in.values()) {
|
|
639
|
-
if (edge.target.collection !== collection || edge.grain === "virtual") continue;
|
|
640
|
-
const posture = this._computeEffective(nodeId(edge.target), edge);
|
|
641
|
-
if (posture.encryptedAtRest === "sealed") out.add(edge.target.field);
|
|
642
|
-
}
|
|
643
|
-
return out;
|
|
644
|
-
}
|
|
645
|
-
/** Fields on `collection` whose registered edge is `grain === 'virtual'` (#638 Task 7) —
|
|
646
|
-
* `via/graph-wiring.ts#applyTaintOverlay` intersects this with `exportable === false`
|
|
647
|
-
* postures to know which virtual fields need PRESENT-TIME (not just export-time)
|
|
648
|
-
* redaction, since a virtual field's value is only ever materialized inside `present()`. */
|
|
649
|
-
virtualFields(collection) {
|
|
650
|
-
const out = /* @__PURE__ */ new Set();
|
|
651
|
-
for (const edge of this._in.values()) {
|
|
652
|
-
if (edge.target.collection === collection && edge.grain === "virtual") out.add(edge.target.field);
|
|
653
|
-
}
|
|
654
|
-
return out;
|
|
655
|
-
}
|
|
656
|
-
/** Per-collection { field → immediate source field names that forced its
|
|
657
|
-
* effective posture away from `DEFAULT_POSTURE` } — `describe()`'s
|
|
658
|
-
* provenance (Task 3). Only the DIRECT declared sources are named (not the
|
|
659
|
-
* ultimate origin several hops up a transitive chain); a source absent
|
|
660
|
-
* from the result contributed nothing restrictive. */
|
|
661
|
-
taintProvenance(collection) {
|
|
662
|
-
const out = /* @__PURE__ */ new Map();
|
|
663
|
-
for (const edge of this._in.values()) {
|
|
664
|
-
if (edge.target.collection !== collection) continue;
|
|
665
|
-
const forcedBy = edge.sources.filter((source) => !isDefaultPosture(this._contribution(nodeId(source)))).map((source) => source.field);
|
|
666
|
-
if (forcedBy.length > 0) out.set(edge.target.field, forcedBy);
|
|
667
|
-
}
|
|
668
|
-
return out;
|
|
669
|
-
}
|
|
670
|
-
_targetsDependingOn(collection) {
|
|
671
|
-
const out = [];
|
|
672
|
-
for (const edge of this._in.values()) {
|
|
673
|
-
if (edge.sources.some((source) => source.collection === collection)) {
|
|
674
|
-
out.push({ target: edge.target, kind: edge.kind, grain: edge.grain });
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
return out;
|
|
678
|
-
}
|
|
679
|
-
/** Dispatch (Task 4): every derived target triggered by a write to `collection`. Excludes
|
|
680
|
-
* `'ref'` edges (#650 Task 5 review, folded Minor) — a `'ref'` edge is consulted only by the
|
|
681
|
-
* delete/forget-time restrict/cascade/nullify path ({@link referencingEdgesOf}), never by the
|
|
682
|
-
* sync/cutover/restore dispatch wave (`runGraphDispatchWave`); counting it here defeated that
|
|
683
|
-
* wave's zero-cost early-continue, costing every write to a referenced backing collection an
|
|
684
|
-
* unconditional decrypt + two no-op dispatch passes. {@link derivedArtifactsOf} (erasure
|
|
685
|
-
* fanout) still includes `'ref'` edges — the forget path genuinely needs them. */
|
|
686
|
-
dependentsOf(collection) {
|
|
687
|
-
return this._targetsDependingOn(collection).filter((edge) => edge.kind !== "ref");
|
|
688
|
-
}
|
|
689
|
-
/** Erasure (Task 6): derived artifacts of a forgotten record whose source is `collection`. */
|
|
690
|
-
derivedArtifactsOf(collection) {
|
|
691
|
-
return this._targetsDependingOn(collection);
|
|
692
|
-
}
|
|
693
|
-
/** Referencing edges pointing AT a backing dimension (delete/forget-time restrict/cascade/
|
|
694
|
-
* nullify, #650 Task 5) — an O(1) reverse lookup via the existing `_out` map (keyed at the
|
|
695
|
-
* dimension's wildcard `field:'*'` node, the same convention every whole-collection source
|
|
696
|
-
* already uses), NEVER a scan across collections or records. `backing` is the collection name
|
|
697
|
-
* a lookup field's edge was registered against (a reserved dimension's `_dict_<name>`/
|
|
698
|
-
* `_lookup_<name>` collection name, or a matrix dimension's own collection name). */
|
|
699
|
-
referencingEdgesOf(backing) {
|
|
700
|
-
const targets = this._out.get(nodeId({ collection: backing, field: "*" }));
|
|
701
|
-
if (!targets) return [];
|
|
702
|
-
const out = [];
|
|
703
|
-
for (const entry of targets) {
|
|
704
|
-
if (entry.kind !== "ref") continue;
|
|
705
|
-
const edge = this._in.get(nodeId(entry.target));
|
|
706
|
-
if (edge?.onDelete !== void 0) {
|
|
707
|
-
out.push({ referencing: entry.target, onDelete: edge.onDelete, keyField: edge.keyField ?? "id" });
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
return out;
|
|
711
|
-
}
|
|
712
|
-
};
|
|
713
|
-
|
|
714
|
-
export {
|
|
715
|
-
schemaFieldKeys,
|
|
716
|
-
deriveZodFields,
|
|
717
|
-
resolveDescribeFieldIds,
|
|
718
|
-
buildDescription,
|
|
719
|
-
DEFAULT_POSTURE,
|
|
720
|
-
ViaGraph
|
|
721
|
-
};
|
|
722
|
-
//# sourceMappingURL=chunk-7BE7ZDVQ.js.map
|