@sequenceholdings/orm 2.8.3 → 2.8.5
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 +154 -45
- package/dist/authoring.cjs.map +1 -1
- package/dist/authoring.d.cts +12 -2
- package/dist/authoring.d.ts +12 -2
- package/dist/authoring.js +154 -45
- package/dist/authoring.js.map +1 -1
- package/dist/canonical.cjs +64 -14
- package/dist/canonical.cjs.map +1 -1
- package/dist/canonical.d.cts +12 -7
- package/dist/canonical.d.ts +12 -7
- package/dist/canonical.js +64 -14
- package/dist/canonical.js.map +1 -1
- package/dist/cli.cjs +78 -20
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +78 -20
- package/dist/cli.js.map +1 -1
- package/dist/compiler.cjs +77 -20
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +4 -4
- package/dist/compiler.d.ts +4 -4
- package/dist/compiler.js +77 -20
- package/dist/compiler.js.map +1 -1
- package/dist/index.cjs +161 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +161 -47
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +71 -16
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +9 -9
- package/dist/ir.d.ts +9 -9
- package/dist/ir.js +71 -16
- package/dist/ir.js.map +1 -1
- package/dist/{naming-CU9ThP_E.d.cts → naming-BMZKFO0W.d.cts} +1 -2
- package/dist/{naming-CPfx7EfF.d.ts → naming-DUk7AcXs.d.ts} +1 -2
- package/dist/predicate-v2.cjs +71 -16
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +3 -3
- package/dist/predicate-v2.d.ts +3 -3
- package/dist/predicate-v2.js +71 -16
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +71 -16
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +2 -2
- package/dist/sdl.d.ts +2 -2
- package/dist/sdl.js +71 -16
- package/dist/sdl.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen-gql/apollo-hooks.cjs +1 -1
- package/src/codegen-gql/server-fns.cjs +1 -1
- package/templates/orm-namespace/graphql/example/queries.ts +1 -1
package/dist/ir.cjs
CHANGED
|
@@ -239,6 +239,48 @@ var policyExpressionSchema = zod.z.union([
|
|
|
239
239
|
variants: zod.z.array(policyVariantSchema).max(10).default([])
|
|
240
240
|
})
|
|
241
241
|
]);
|
|
242
|
+
|
|
243
|
+
// src/canonical/resolved-rows.ts
|
|
244
|
+
function logicalKey(table) {
|
|
245
|
+
return (table.primaryKey ?? []).map((columnName) => table.columns.find((c) => c.columnName === columnName)?.name ?? columnName);
|
|
246
|
+
}
|
|
247
|
+
function sameKey(key, expected) {
|
|
248
|
+
return key.length === expected.length && key.every((name) => expected.includes(name));
|
|
249
|
+
}
|
|
250
|
+
function validateRowIdentity(input) {
|
|
251
|
+
validateExistsIn(input);
|
|
252
|
+
if (input.keys.length > 1) validateCompositeKey(input);
|
|
253
|
+
}
|
|
254
|
+
function validateExistsIn({ resolved, sourceByName, fail }) {
|
|
255
|
+
const name = resolved.existsIn?.[0];
|
|
256
|
+
if (name === void 0) return;
|
|
257
|
+
if (sourceByName.get(name)?.kind !== "etl") fail(`existsIn '${name}' must be an etl source`);
|
|
258
|
+
if (resolved.policies.insert !== void 0 || resolved.policies.write !== void 0) {
|
|
259
|
+
fail("existsIn allows only an update policy: rows come from the etl source");
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function validateCompositeKey({ resolved, keys, tableByName, fail }) {
|
|
263
|
+
const keyList = `(${keys.join(", ")})`;
|
|
264
|
+
if (resolved.existsIn === void 0) {
|
|
265
|
+
fail(`requires exactly one primary-key column: composite key ${keyList} requires existsIn`);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const writes = ["insert", "update", "write"].filter((kind) => resolved.policies[kind] !== void 0);
|
|
269
|
+
if (writes.length > 0) fail(`composite key ${keyList} requires a read-only table: remove the ${writes.join("/")} policy`);
|
|
270
|
+
if (resolved.materialized) fail(`composite key ${keyList} cannot be materialized`);
|
|
271
|
+
for (const source of resolved.sources) {
|
|
272
|
+
if (source.kind === "prefetch") {
|
|
273
|
+
fail(`composite key ${keyList} cannot have prefetch source '${source.name}'`);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const table = tableByName.get(source.table);
|
|
277
|
+
if (table && !sameKey(logicalKey(table), keys)) {
|
|
278
|
+
fail(`composite key ${keyList} requires ${source.kind} source '${source.name}' to be keyed by it; table '${source.table}' is keyed by (${logicalKey(table).join(", ")})`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/canonical/resolved.ts
|
|
242
284
|
var identifier = zod.z.string().min(1).max(63).regex(/^[a-z][a-z0-9_]*$/);
|
|
243
285
|
var durationMs = zod.z.number().int().positive().max(24 * 60 * 60 * 1e3);
|
|
244
286
|
var RESOLVED_VIEW_SYSTEM_COLUMNS = {
|
|
@@ -307,6 +349,13 @@ var canonicalResolvedSchema = zod.z.object({
|
|
|
307
349
|
resolve: zod.z.array(canonicalResolveRuleSchema).max(500),
|
|
308
350
|
/** Sources whose tombstone hides the resolved row (v1: the manual source only). */
|
|
309
351
|
deletedBy: zod.z.array(identifier).max(1).default([]),
|
|
352
|
+
/**
|
|
353
|
+
* `rows.existsIn`: the one etl source whose rows are the table's rows (read
|
|
354
|
+
* directly as the row source). Only an update policy may write. It is also
|
|
355
|
+
* what admits a composite primary key: a read-only table keyed exactly like
|
|
356
|
+
* that source.
|
|
357
|
+
*/
|
|
358
|
+
existsIn: zod.z.array(identifier).length(1).optional(),
|
|
310
359
|
/**
|
|
311
360
|
* Materialized: the view reads an indexed internal table (`table`) that the
|
|
312
361
|
* data plane keeps in step with `compute`, the internal view holding the
|
|
@@ -325,8 +374,8 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
325
374
|
if (!resolved) return [];
|
|
326
375
|
const errors = [];
|
|
327
376
|
const fail = (message) => errors.push(`resolved table '${view.view}': ${message}`);
|
|
328
|
-
const
|
|
329
|
-
if (
|
|
377
|
+
const keyColumns = (view.primaryKey ?? []).map((columnName) => view.columns.find((c) => c.columnName === columnName)).filter((column) => column !== void 0);
|
|
378
|
+
if (keyColumns.length === 0 || keyColumns.length !== view.primaryKey?.length) {
|
|
330
379
|
fail("requires exactly one primary-key column");
|
|
331
380
|
return errors;
|
|
332
381
|
}
|
|
@@ -334,7 +383,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
334
383
|
const scope = {
|
|
335
384
|
view,
|
|
336
385
|
resolved,
|
|
337
|
-
|
|
386
|
+
keys: new Map(keyColumns.map((column) => [column.name, column])),
|
|
338
387
|
dataColumns: new Map(view.columns.filter((c) => !systemNames.has(c.name) && c.cell === void 0).map((c) => [c.name, c])),
|
|
339
388
|
sourceByName: /* @__PURE__ */ new Map(),
|
|
340
389
|
fail
|
|
@@ -348,6 +397,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
348
397
|
if (!table) fail(`source '${source.name}' references unknown table '${source.table}'`);
|
|
349
398
|
else validateSource({ scope, source, table });
|
|
350
399
|
}
|
|
400
|
+
validateRowIdentity({ resolved, keys: [...scope.keys.keys()], sourceByName: scope.sourceByName, tableByName, fail });
|
|
351
401
|
validateRules(scope);
|
|
352
402
|
validateViewCells(scope);
|
|
353
403
|
if (resolved.materialized) validateMaterialized({ scope, tableByName, views });
|
|
@@ -377,7 +427,7 @@ function validateSource({ scope, source, table }) {
|
|
|
377
427
|
validatePrefetchFields({ scope, source });
|
|
378
428
|
}
|
|
379
429
|
function validatePrefetchFields({ scope, source }) {
|
|
380
|
-
const { fail,
|
|
430
|
+
const { fail, keys } = scope;
|
|
381
431
|
if (source.kind !== "prefetch") {
|
|
382
432
|
if (source.key || source.fetch || source.function || source.prefetchDefaults || source.writeback) {
|
|
383
433
|
fail(`only prefetch sources may declare key/fetch/function/prefetchDefaults/writeback ('${source.name}')`);
|
|
@@ -386,7 +436,7 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
386
436
|
}
|
|
387
437
|
if (!source.key || !source.fetch || !source.function || !source.prefetchDefaults) {
|
|
388
438
|
fail(`prefetch source '${source.name}' requires key, fetch, function and prefetchDefaults`);
|
|
389
|
-
} else if (source.key
|
|
439
|
+
} else if (!keys.has(source.key) && !source.columns.includes(source.key)) {
|
|
390
440
|
fail(`prefetch source '${source.name}' key '${source.key}' must be the primary key or one of its columns`);
|
|
391
441
|
}
|
|
392
442
|
for (const column of source.writeback?.columns ?? []) {
|
|
@@ -394,19 +444,19 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
394
444
|
}
|
|
395
445
|
}
|
|
396
446
|
function validateSourceColumns({ scope, source, byName }) {
|
|
397
|
-
const { fail,
|
|
398
|
-
for (const column of [
|
|
399
|
-
const own = column
|
|
447
|
+
const { fail, keys, dataColumns } = scope;
|
|
448
|
+
for (const column of [...keys.keys(), ...source.columns]) {
|
|
449
|
+
const own = keys.get(column) ?? dataColumns.get(column);
|
|
400
450
|
const theirs = byName.get(column);
|
|
401
451
|
if (!own) fail(`source '${source.name}' supplies unknown column '${column}'`);
|
|
402
452
|
else if (!theirs) fail(`source '${source.name}' table '${source.table}' has no column '${column}'`);
|
|
403
453
|
else if (JSON.stringify(theirs.type) !== JSON.stringify(own.type)) fail(`column '${column}' has a different type on source '${source.name}'`);
|
|
404
454
|
}
|
|
405
455
|
}
|
|
406
|
-
function validateRules({ resolved,
|
|
456
|
+
function validateRules({ resolved, keys, dataColumns, sourceByName, fail }) {
|
|
407
457
|
const ruled = /* @__PURE__ */ new Set();
|
|
408
458
|
for (const rule of resolved.resolve) {
|
|
409
|
-
if (!dataColumns.has(rule.column) || rule.column
|
|
459
|
+
if (!dataColumns.has(rule.column) || keys.has(rule.column)) {
|
|
410
460
|
fail(`resolve rule targets unknown column '${rule.column}'`);
|
|
411
461
|
continue;
|
|
412
462
|
}
|
|
@@ -423,7 +473,7 @@ function validateRules({ resolved, pkColumn, dataColumns, sourceByName, fail })
|
|
|
423
473
|
}
|
|
424
474
|
}
|
|
425
475
|
for (const column of dataColumns.keys()) {
|
|
426
|
-
if (column
|
|
476
|
+
if (!keys.has(column) && !ruled.has(column)) fail(`column '${column}' has no resolve rule`);
|
|
427
477
|
}
|
|
428
478
|
}
|
|
429
479
|
var VIEW_CELL_TYPES = {
|
|
@@ -432,10 +482,10 @@ var VIEW_CELL_TYPES = {
|
|
|
432
482
|
by: "text",
|
|
433
483
|
conflicts: "jsonb"
|
|
434
484
|
};
|
|
435
|
-
function validateViewCells({ view, dataColumns,
|
|
485
|
+
function validateViewCells({ view, dataColumns, keys, fail }) {
|
|
436
486
|
const expected = /* @__PURE__ */ new Map();
|
|
437
487
|
for (const column of dataColumns.values()) {
|
|
438
|
-
if (column.name
|
|
488
|
+
if (keys.has(column.name)) continue;
|
|
439
489
|
for (const part of RESOLVED_VIEW_CELL_PARTS) {
|
|
440
490
|
expected.set(cellColumnName(column.name, part), { part, columnName: cellColumnName(column.columnName, part) });
|
|
441
491
|
}
|
|
@@ -646,7 +696,7 @@ var canonicalTableSchema = zod.z.object({
|
|
|
646
696
|
table: identifier2,
|
|
647
697
|
displayName: zod.z.string().trim().min(1).max(120).optional(),
|
|
648
698
|
description: zod.z.string().max(2e3).optional(),
|
|
649
|
-
/** Table-level rename hint
|
|
699
|
+
/** Table-level rename hint. */
|
|
650
700
|
renamedFrom: identifier2.optional(),
|
|
651
701
|
/** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
|
|
652
702
|
source: zod.z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
|
|
@@ -1454,8 +1504,13 @@ var resolvedSourceIrSchema = zod.z.object({
|
|
|
1454
1504
|
}).optional()
|
|
1455
1505
|
});
|
|
1456
1506
|
var resolvedMetaIrSchema = zod.z.object({
|
|
1457
|
-
/**
|
|
1458
|
-
|
|
1507
|
+
/**
|
|
1508
|
+
* Logical pk column of the resolved view. Absent for a composite key, which
|
|
1509
|
+
* only a read-only `existsIn` table may declare: it has no writes, prefetch
|
|
1510
|
+
* or materialization (the paths that address one key column), and its reads
|
|
1511
|
+
* use the view's `primaryKey` like any keyed view.
|
|
1512
|
+
*/
|
|
1513
|
+
pk: zod.z.string().optional(),
|
|
1459
1514
|
/** Source name of the manual source. */
|
|
1460
1515
|
manual: zod.z.string(),
|
|
1461
1516
|
sources: zod.z.array(resolvedSourceIrSchema),
|