@sequenceholdings/orm 2.8.4 → 2.9.0
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/authoring.cjs +142 -56
- package/dist/authoring.cjs.map +1 -1
- package/dist/authoring.d.cts +7 -3
- package/dist/authoring.d.ts +7 -3
- package/dist/authoring.js +142 -56
- package/dist/authoring.js.map +1 -1
- package/dist/canonical.cjs +63 -13
- package/dist/canonical.cjs.map +1 -1
- package/dist/canonical.d.cts +77 -72
- package/dist/canonical.d.ts +77 -72
- package/dist/canonical.js +63 -13
- package/dist/canonical.js.map +1 -1
- package/dist/cli.cjs +170 -72
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +23 -1
- package/dist/cli.d.ts +23 -1
- package/dist/cli.js +167 -73
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +77 -20
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +2 -2
- package/dist/compiler.d.ts +2 -2
- package/dist/compiler.js +77 -20
- package/dist/compiler.js.map +1 -1
- package/dist/{constants-Dou1RkTo.d.cts → constants-D2o0vK6U.d.cts} +8 -1
- package/dist/{constants-Dou1RkTo.d.ts → constants-D2o0vK6U.d.ts} +8 -1
- package/dist/dynamic-input.d.cts +1 -1
- package/dist/dynamic-input.d.ts +1 -1
- package/dist/index.cjs +193 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -59
- package/dist/index.d.ts +62 -59
- package/dist/index.js +192 -83
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +70 -15
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +76 -76
- package/dist/ir.d.ts +76 -76
- package/dist/ir.js +70 -15
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +70 -15
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +1 -1
- package/dist/predicate-v2.d.ts +1 -1
- package/dist/predicate-v2.js +70 -15
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +70 -15
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +1 -1
- package/dist/sdl.d.ts +1 -1
- package/dist/sdl.js +70 -15
- package/dist/sdl.js.map +1 -1
- package/package.json +3 -3
- package/templates/orm-namespace/package.json +2 -1
- package/dist/{definition-DjfC7Lll.d.cts → definition-B99BsOAO.d.cts} +4 -4
- package/dist/{definition-DjfC7Lll.d.ts → definition-B99BsOAO.d.ts} +4 -4
package/dist/sdl.cjs
CHANGED
|
@@ -240,6 +240,48 @@ var policyExpressionSchema = zod.z.union([
|
|
|
240
240
|
variants: zod.z.array(policyVariantSchema).max(10).default([])
|
|
241
241
|
})
|
|
242
242
|
]);
|
|
243
|
+
|
|
244
|
+
// src/canonical/resolved-rows.ts
|
|
245
|
+
function logicalKey(table) {
|
|
246
|
+
return (table.primaryKey ?? []).map((columnName) => table.columns.find((c) => c.columnName === columnName)?.name ?? columnName);
|
|
247
|
+
}
|
|
248
|
+
function sameKey(key, expected) {
|
|
249
|
+
return key.length === expected.length && key.every((name) => expected.includes(name));
|
|
250
|
+
}
|
|
251
|
+
function validateRowIdentity(input) {
|
|
252
|
+
validateExistsIn(input);
|
|
253
|
+
if (input.keys.length > 1) validateCompositeKey(input);
|
|
254
|
+
}
|
|
255
|
+
function validateExistsIn({ resolved, sourceByName, fail }) {
|
|
256
|
+
const name = resolved.existsIn?.[0];
|
|
257
|
+
if (name === void 0) return;
|
|
258
|
+
if (sourceByName.get(name)?.kind !== "etl") fail(`existsIn '${name}' must be an etl source`);
|
|
259
|
+
if (resolved.policies.insert !== void 0 || resolved.policies.write !== void 0) {
|
|
260
|
+
fail("existsIn allows only an update policy: rows come from the etl source");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function validateCompositeKey({ resolved, keys, tableByName, fail }) {
|
|
264
|
+
const keyList = `(${keys.join(", ")})`;
|
|
265
|
+
if (resolved.existsIn === void 0) {
|
|
266
|
+
fail(`requires exactly one primary-key column: composite key ${keyList} requires existsIn`);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const writes = ["insert", "update", "write"].filter((kind) => resolved.policies[kind] !== void 0);
|
|
270
|
+
if (writes.length > 0) fail(`composite key ${keyList} requires a read-only table: remove the ${writes.join("/")} policy`);
|
|
271
|
+
if (resolved.materialized) fail(`composite key ${keyList} cannot be materialized`);
|
|
272
|
+
for (const source of resolved.sources) {
|
|
273
|
+
if (source.kind === "prefetch") {
|
|
274
|
+
fail(`composite key ${keyList} cannot have prefetch source '${source.name}'`);
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const table = tableByName.get(source.table);
|
|
278
|
+
if (table && !sameKey(logicalKey(table), keys)) {
|
|
279
|
+
fail(`composite key ${keyList} requires ${source.kind} source '${source.name}' to be keyed by it; table '${source.table}' is keyed by (${logicalKey(table).join(", ")})`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/canonical/resolved.ts
|
|
243
285
|
var identifier = zod.z.string().min(1).max(63).regex(/^[a-z][a-z0-9_]*$/);
|
|
244
286
|
var durationMs = zod.z.number().int().positive().max(24 * 60 * 60 * 1e3);
|
|
245
287
|
var RESOLVED_VIEW_SYSTEM_COLUMNS = {
|
|
@@ -308,6 +350,13 @@ var canonicalResolvedSchema = zod.z.object({
|
|
|
308
350
|
resolve: zod.z.array(canonicalResolveRuleSchema).max(500),
|
|
309
351
|
/** Sources whose tombstone hides the resolved row (v1: the manual source only). */
|
|
310
352
|
deletedBy: zod.z.array(identifier).max(1).default([]),
|
|
353
|
+
/**
|
|
354
|
+
* `rows.existsIn`: the one etl source whose rows are the table's rows (read
|
|
355
|
+
* directly as the row source). Only an update policy may write. It is also
|
|
356
|
+
* what admits a composite primary key: a read-only table keyed exactly like
|
|
357
|
+
* that source.
|
|
358
|
+
*/
|
|
359
|
+
existsIn: zod.z.array(identifier).length(1).optional(),
|
|
311
360
|
/**
|
|
312
361
|
* Materialized: the view reads an indexed internal table (`table`) that the
|
|
313
362
|
* data plane keeps in step with `compute`, the internal view holding the
|
|
@@ -326,8 +375,8 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
326
375
|
if (!resolved) return [];
|
|
327
376
|
const errors = [];
|
|
328
377
|
const fail = (message) => errors.push(`resolved table '${view.view}': ${message}`);
|
|
329
|
-
const
|
|
330
|
-
if (
|
|
378
|
+
const keyColumns = (view.primaryKey ?? []).map((columnName) => view.columns.find((c) => c.columnName === columnName)).filter((column) => column !== void 0);
|
|
379
|
+
if (keyColumns.length === 0 || keyColumns.length !== view.primaryKey?.length) {
|
|
331
380
|
fail("requires exactly one primary-key column");
|
|
332
381
|
return errors;
|
|
333
382
|
}
|
|
@@ -335,7 +384,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
335
384
|
const scope = {
|
|
336
385
|
view,
|
|
337
386
|
resolved,
|
|
338
|
-
|
|
387
|
+
keys: new Map(keyColumns.map((column) => [column.name, column])),
|
|
339
388
|
dataColumns: new Map(view.columns.filter((c) => !systemNames.has(c.name) && c.cell === void 0).map((c) => [c.name, c])),
|
|
340
389
|
sourceByName: /* @__PURE__ */ new Map(),
|
|
341
390
|
fail
|
|
@@ -349,6 +398,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
349
398
|
if (!table) fail(`source '${source.name}' references unknown table '${source.table}'`);
|
|
350
399
|
else validateSource({ scope, source, table });
|
|
351
400
|
}
|
|
401
|
+
validateRowIdentity({ resolved, keys: [...scope.keys.keys()], sourceByName: scope.sourceByName, tableByName, fail });
|
|
352
402
|
validateRules(scope);
|
|
353
403
|
validateViewCells(scope);
|
|
354
404
|
if (resolved.materialized) validateMaterialized({ scope, tableByName, views });
|
|
@@ -378,7 +428,7 @@ function validateSource({ scope, source, table }) {
|
|
|
378
428
|
validatePrefetchFields({ scope, source });
|
|
379
429
|
}
|
|
380
430
|
function validatePrefetchFields({ scope, source }) {
|
|
381
|
-
const { fail,
|
|
431
|
+
const { fail, keys } = scope;
|
|
382
432
|
if (source.kind !== "prefetch") {
|
|
383
433
|
if (source.key || source.fetch || source.function || source.prefetchDefaults || source.writeback) {
|
|
384
434
|
fail(`only prefetch sources may declare key/fetch/function/prefetchDefaults/writeback ('${source.name}')`);
|
|
@@ -387,7 +437,7 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
387
437
|
}
|
|
388
438
|
if (!source.key || !source.fetch || !source.function || !source.prefetchDefaults) {
|
|
389
439
|
fail(`prefetch source '${source.name}' requires key, fetch, function and prefetchDefaults`);
|
|
390
|
-
} else if (source.key
|
|
440
|
+
} else if (!keys.has(source.key) && !source.columns.includes(source.key)) {
|
|
391
441
|
fail(`prefetch source '${source.name}' key '${source.key}' must be the primary key or one of its columns`);
|
|
392
442
|
}
|
|
393
443
|
for (const column of source.writeback?.columns ?? []) {
|
|
@@ -395,19 +445,19 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
395
445
|
}
|
|
396
446
|
}
|
|
397
447
|
function validateSourceColumns({ scope, source, byName }) {
|
|
398
|
-
const { fail,
|
|
399
|
-
for (const column of [
|
|
400
|
-
const own = column
|
|
448
|
+
const { fail, keys, dataColumns } = scope;
|
|
449
|
+
for (const column of [...keys.keys(), ...source.columns]) {
|
|
450
|
+
const own = keys.get(column) ?? dataColumns.get(column);
|
|
401
451
|
const theirs = byName.get(column);
|
|
402
452
|
if (!own) fail(`source '${source.name}' supplies unknown column '${column}'`);
|
|
403
453
|
else if (!theirs) fail(`source '${source.name}' table '${source.table}' has no column '${column}'`);
|
|
404
454
|
else if (JSON.stringify(theirs.type) !== JSON.stringify(own.type)) fail(`column '${column}' has a different type on source '${source.name}'`);
|
|
405
455
|
}
|
|
406
456
|
}
|
|
407
|
-
function validateRules({ resolved,
|
|
457
|
+
function validateRules({ resolved, keys, dataColumns, sourceByName, fail }) {
|
|
408
458
|
const ruled = /* @__PURE__ */ new Set();
|
|
409
459
|
for (const rule of resolved.resolve) {
|
|
410
|
-
if (!dataColumns.has(rule.column) || rule.column
|
|
460
|
+
if (!dataColumns.has(rule.column) || keys.has(rule.column)) {
|
|
411
461
|
fail(`resolve rule targets unknown column '${rule.column}'`);
|
|
412
462
|
continue;
|
|
413
463
|
}
|
|
@@ -424,7 +474,7 @@ function validateRules({ resolved, pkColumn, dataColumns, sourceByName, fail })
|
|
|
424
474
|
}
|
|
425
475
|
}
|
|
426
476
|
for (const column of dataColumns.keys()) {
|
|
427
|
-
if (column
|
|
477
|
+
if (!keys.has(column) && !ruled.has(column)) fail(`column '${column}' has no resolve rule`);
|
|
428
478
|
}
|
|
429
479
|
}
|
|
430
480
|
var VIEW_CELL_TYPES = {
|
|
@@ -433,10 +483,10 @@ var VIEW_CELL_TYPES = {
|
|
|
433
483
|
by: "text",
|
|
434
484
|
conflicts: "jsonb"
|
|
435
485
|
};
|
|
436
|
-
function validateViewCells({ view, dataColumns,
|
|
486
|
+
function validateViewCells({ view, dataColumns, keys, fail }) {
|
|
437
487
|
const expected = /* @__PURE__ */ new Map();
|
|
438
488
|
for (const column of dataColumns.values()) {
|
|
439
|
-
if (column.name
|
|
489
|
+
if (keys.has(column.name)) continue;
|
|
440
490
|
for (const part of RESOLVED_VIEW_CELL_PARTS) {
|
|
441
491
|
expected.set(cellColumnName(column.name, part), { part, columnName: cellColumnName(column.columnName, part) });
|
|
442
492
|
}
|
|
@@ -1613,8 +1663,13 @@ var resolvedSourceIrSchema = zod.z.object({
|
|
|
1613
1663
|
}).optional()
|
|
1614
1664
|
});
|
|
1615
1665
|
var resolvedMetaIrSchema = zod.z.object({
|
|
1616
|
-
/**
|
|
1617
|
-
|
|
1666
|
+
/**
|
|
1667
|
+
* Logical pk column of the resolved view. Absent for a composite key, which
|
|
1668
|
+
* only a read-only `existsIn` table may declare: it has no writes, prefetch
|
|
1669
|
+
* or materialization (the paths that address one key column), and its reads
|
|
1670
|
+
* use the view's `primaryKey` like any keyed view.
|
|
1671
|
+
*/
|
|
1672
|
+
pk: zod.z.string().optional(),
|
|
1618
1673
|
/** Source name of the manual source. */
|
|
1619
1674
|
manual: zod.z.string(),
|
|
1620
1675
|
sources: zod.z.array(resolvedSourceIrSchema),
|