@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/ir.js
CHANGED
|
@@ -237,6 +237,48 @@ var policyExpressionSchema = z.union([
|
|
|
237
237
|
variants: z.array(policyVariantSchema).max(10).default([])
|
|
238
238
|
})
|
|
239
239
|
]);
|
|
240
|
+
|
|
241
|
+
// src/canonical/resolved-rows.ts
|
|
242
|
+
function logicalKey(table) {
|
|
243
|
+
return (table.primaryKey ?? []).map((columnName) => table.columns.find((c) => c.columnName === columnName)?.name ?? columnName);
|
|
244
|
+
}
|
|
245
|
+
function sameKey(key, expected) {
|
|
246
|
+
return key.length === expected.length && key.every((name) => expected.includes(name));
|
|
247
|
+
}
|
|
248
|
+
function validateRowIdentity(input) {
|
|
249
|
+
validateExistsIn(input);
|
|
250
|
+
if (input.keys.length > 1) validateCompositeKey(input);
|
|
251
|
+
}
|
|
252
|
+
function validateExistsIn({ resolved, sourceByName, fail }) {
|
|
253
|
+
const name = resolved.existsIn?.[0];
|
|
254
|
+
if (name === void 0) return;
|
|
255
|
+
if (sourceByName.get(name)?.kind !== "etl") fail(`existsIn '${name}' must be an etl source`);
|
|
256
|
+
if (resolved.policies.insert !== void 0 || resolved.policies.write !== void 0) {
|
|
257
|
+
fail("existsIn allows only an update policy: rows come from the etl source");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function validateCompositeKey({ resolved, keys, tableByName, fail }) {
|
|
261
|
+
const keyList = `(${keys.join(", ")})`;
|
|
262
|
+
if (resolved.existsIn === void 0) {
|
|
263
|
+
fail(`requires exactly one primary-key column: composite key ${keyList} requires existsIn`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const writes = ["insert", "update", "write"].filter((kind) => resolved.policies[kind] !== void 0);
|
|
267
|
+
if (writes.length > 0) fail(`composite key ${keyList} requires a read-only table: remove the ${writes.join("/")} policy`);
|
|
268
|
+
if (resolved.materialized) fail(`composite key ${keyList} cannot be materialized`);
|
|
269
|
+
for (const source of resolved.sources) {
|
|
270
|
+
if (source.kind === "prefetch") {
|
|
271
|
+
fail(`composite key ${keyList} cannot have prefetch source '${source.name}'`);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const table = tableByName.get(source.table);
|
|
275
|
+
if (table && !sameKey(logicalKey(table), keys)) {
|
|
276
|
+
fail(`composite key ${keyList} requires ${source.kind} source '${source.name}' to be keyed by it; table '${source.table}' is keyed by (${logicalKey(table).join(", ")})`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/canonical/resolved.ts
|
|
240
282
|
var identifier = z.string().min(1).max(63).regex(/^[a-z][a-z0-9_]*$/);
|
|
241
283
|
var durationMs = z.number().int().positive().max(24 * 60 * 60 * 1e3);
|
|
242
284
|
var RESOLVED_VIEW_SYSTEM_COLUMNS = {
|
|
@@ -305,6 +347,13 @@ var canonicalResolvedSchema = z.object({
|
|
|
305
347
|
resolve: z.array(canonicalResolveRuleSchema).max(500),
|
|
306
348
|
/** Sources whose tombstone hides the resolved row (v1: the manual source only). */
|
|
307
349
|
deletedBy: z.array(identifier).max(1).default([]),
|
|
350
|
+
/**
|
|
351
|
+
* `rows.existsIn`: the one etl source whose rows are the table's rows (read
|
|
352
|
+
* directly as the row source). Only an update policy may write. It is also
|
|
353
|
+
* what admits a composite primary key: a read-only table keyed exactly like
|
|
354
|
+
* that source.
|
|
355
|
+
*/
|
|
356
|
+
existsIn: z.array(identifier).length(1).optional(),
|
|
308
357
|
/**
|
|
309
358
|
* Materialized: the view reads an indexed internal table (`table`) that the
|
|
310
359
|
* data plane keeps in step with `compute`, the internal view holding the
|
|
@@ -323,8 +372,8 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
323
372
|
if (!resolved) return [];
|
|
324
373
|
const errors = [];
|
|
325
374
|
const fail = (message) => errors.push(`resolved table '${view.view}': ${message}`);
|
|
326
|
-
const
|
|
327
|
-
if (
|
|
375
|
+
const keyColumns = (view.primaryKey ?? []).map((columnName) => view.columns.find((c) => c.columnName === columnName)).filter((column) => column !== void 0);
|
|
376
|
+
if (keyColumns.length === 0 || keyColumns.length !== view.primaryKey?.length) {
|
|
328
377
|
fail("requires exactly one primary-key column");
|
|
329
378
|
return errors;
|
|
330
379
|
}
|
|
@@ -332,7 +381,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
332
381
|
const scope = {
|
|
333
382
|
view,
|
|
334
383
|
resolved,
|
|
335
|
-
|
|
384
|
+
keys: new Map(keyColumns.map((column) => [column.name, column])),
|
|
336
385
|
dataColumns: new Map(view.columns.filter((c) => !systemNames.has(c.name) && c.cell === void 0).map((c) => [c.name, c])),
|
|
337
386
|
sourceByName: /* @__PURE__ */ new Map(),
|
|
338
387
|
fail
|
|
@@ -346,6 +395,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
346
395
|
if (!table) fail(`source '${source.name}' references unknown table '${source.table}'`);
|
|
347
396
|
else validateSource({ scope, source, table });
|
|
348
397
|
}
|
|
398
|
+
validateRowIdentity({ resolved, keys: [...scope.keys.keys()], sourceByName: scope.sourceByName, tableByName, fail });
|
|
349
399
|
validateRules(scope);
|
|
350
400
|
validateViewCells(scope);
|
|
351
401
|
if (resolved.materialized) validateMaterialized({ scope, tableByName, views });
|
|
@@ -375,7 +425,7 @@ function validateSource({ scope, source, table }) {
|
|
|
375
425
|
validatePrefetchFields({ scope, source });
|
|
376
426
|
}
|
|
377
427
|
function validatePrefetchFields({ scope, source }) {
|
|
378
|
-
const { fail,
|
|
428
|
+
const { fail, keys } = scope;
|
|
379
429
|
if (source.kind !== "prefetch") {
|
|
380
430
|
if (source.key || source.fetch || source.function || source.prefetchDefaults || source.writeback) {
|
|
381
431
|
fail(`only prefetch sources may declare key/fetch/function/prefetchDefaults/writeback ('${source.name}')`);
|
|
@@ -384,7 +434,7 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
384
434
|
}
|
|
385
435
|
if (!source.key || !source.fetch || !source.function || !source.prefetchDefaults) {
|
|
386
436
|
fail(`prefetch source '${source.name}' requires key, fetch, function and prefetchDefaults`);
|
|
387
|
-
} else if (source.key
|
|
437
|
+
} else if (!keys.has(source.key) && !source.columns.includes(source.key)) {
|
|
388
438
|
fail(`prefetch source '${source.name}' key '${source.key}' must be the primary key or one of its columns`);
|
|
389
439
|
}
|
|
390
440
|
for (const column of source.writeback?.columns ?? []) {
|
|
@@ -392,19 +442,19 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
392
442
|
}
|
|
393
443
|
}
|
|
394
444
|
function validateSourceColumns({ scope, source, byName }) {
|
|
395
|
-
const { fail,
|
|
396
|
-
for (const column of [
|
|
397
|
-
const own = column
|
|
445
|
+
const { fail, keys, dataColumns } = scope;
|
|
446
|
+
for (const column of [...keys.keys(), ...source.columns]) {
|
|
447
|
+
const own = keys.get(column) ?? dataColumns.get(column);
|
|
398
448
|
const theirs = byName.get(column);
|
|
399
449
|
if (!own) fail(`source '${source.name}' supplies unknown column '${column}'`);
|
|
400
450
|
else if (!theirs) fail(`source '${source.name}' table '${source.table}' has no column '${column}'`);
|
|
401
451
|
else if (JSON.stringify(theirs.type) !== JSON.stringify(own.type)) fail(`column '${column}' has a different type on source '${source.name}'`);
|
|
402
452
|
}
|
|
403
453
|
}
|
|
404
|
-
function validateRules({ resolved,
|
|
454
|
+
function validateRules({ resolved, keys, dataColumns, sourceByName, fail }) {
|
|
405
455
|
const ruled = /* @__PURE__ */ new Set();
|
|
406
456
|
for (const rule of resolved.resolve) {
|
|
407
|
-
if (!dataColumns.has(rule.column) || rule.column
|
|
457
|
+
if (!dataColumns.has(rule.column) || keys.has(rule.column)) {
|
|
408
458
|
fail(`resolve rule targets unknown column '${rule.column}'`);
|
|
409
459
|
continue;
|
|
410
460
|
}
|
|
@@ -421,7 +471,7 @@ function validateRules({ resolved, pkColumn, dataColumns, sourceByName, fail })
|
|
|
421
471
|
}
|
|
422
472
|
}
|
|
423
473
|
for (const column of dataColumns.keys()) {
|
|
424
|
-
if (column
|
|
474
|
+
if (!keys.has(column) && !ruled.has(column)) fail(`column '${column}' has no resolve rule`);
|
|
425
475
|
}
|
|
426
476
|
}
|
|
427
477
|
var VIEW_CELL_TYPES = {
|
|
@@ -430,10 +480,10 @@ var VIEW_CELL_TYPES = {
|
|
|
430
480
|
by: "text",
|
|
431
481
|
conflicts: "jsonb"
|
|
432
482
|
};
|
|
433
|
-
function validateViewCells({ view, dataColumns,
|
|
483
|
+
function validateViewCells({ view, dataColumns, keys, fail }) {
|
|
434
484
|
const expected = /* @__PURE__ */ new Map();
|
|
435
485
|
for (const column of dataColumns.values()) {
|
|
436
|
-
if (column.name
|
|
486
|
+
if (keys.has(column.name)) continue;
|
|
437
487
|
for (const part of RESOLVED_VIEW_CELL_PARTS) {
|
|
438
488
|
expected.set(cellColumnName(column.name, part), { part, columnName: cellColumnName(column.columnName, part) });
|
|
439
489
|
}
|
|
@@ -1452,8 +1502,13 @@ var resolvedSourceIrSchema = z.object({
|
|
|
1452
1502
|
}).optional()
|
|
1453
1503
|
});
|
|
1454
1504
|
var resolvedMetaIrSchema = z.object({
|
|
1455
|
-
/**
|
|
1456
|
-
|
|
1505
|
+
/**
|
|
1506
|
+
* Logical pk column of the resolved view. Absent for a composite key, which
|
|
1507
|
+
* only a read-only `existsIn` table may declare: it has no writes, prefetch
|
|
1508
|
+
* or materialization (the paths that address one key column), and its reads
|
|
1509
|
+
* use the view's `primaryKey` like any keyed view.
|
|
1510
|
+
*/
|
|
1511
|
+
pk: z.string().optional(),
|
|
1457
1512
|
/** Source name of the manual source. */
|
|
1458
1513
|
manual: z.string(),
|
|
1459
1514
|
sources: z.array(resolvedSourceIrSchema),
|