@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
|
@@ -3,8 +3,7 @@ import { ColumnType } from './canonical.cjs';
|
|
|
3
3
|
/**
|
|
4
4
|
* graphql-default (Hasura-style) camelCase naming for the v2 SDL generator.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* (~/test/apps/marketplace/src/graphql, 871 ops):
|
|
6
|
+
* Conventions:
|
|
8
7
|
* - input types are singular PascalCase + suffix (`VideoClipBoolExp`,
|
|
9
8
|
* `UserOrderBy`, `ProfileInsertInput`, `ThirdPartyIntegrationOnConflict`)
|
|
10
9
|
* - roots keep the table's plurality camelCased (`videoClips`, `profileByPk`,
|
|
@@ -3,8 +3,7 @@ import { ColumnType } from './canonical.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* graphql-default (Hasura-style) camelCase naming for the v2 SDL generator.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* (~/test/apps/marketplace/src/graphql, 871 ops):
|
|
6
|
+
* Conventions:
|
|
8
7
|
* - input types are singular PascalCase + suffix (`VideoClipBoolExp`,
|
|
9
8
|
* `UserOrderBy`, `ProfileInsertInput`, `ThirdPartyIntegrationOnConflict`)
|
|
10
9
|
* - roots keep the table's plurality camelCased (`videoClips`, `profileByPk`,
|
package/dist/predicate-v2.cjs
CHANGED
|
@@ -265,6 +265,48 @@ var policyExpressionSchema = zod.z.union([
|
|
|
265
265
|
variants: zod.z.array(policyVariantSchema).max(10).default([])
|
|
266
266
|
})
|
|
267
267
|
]);
|
|
268
|
+
|
|
269
|
+
// src/canonical/resolved-rows.ts
|
|
270
|
+
function logicalKey(table) {
|
|
271
|
+
return (table.primaryKey ?? []).map((columnName) => table.columns.find((c) => c.columnName === columnName)?.name ?? columnName);
|
|
272
|
+
}
|
|
273
|
+
function sameKey(key, expected) {
|
|
274
|
+
return key.length === expected.length && key.every((name) => expected.includes(name));
|
|
275
|
+
}
|
|
276
|
+
function validateRowIdentity(input) {
|
|
277
|
+
validateExistsIn(input);
|
|
278
|
+
if (input.keys.length > 1) validateCompositeKey(input);
|
|
279
|
+
}
|
|
280
|
+
function validateExistsIn({ resolved, sourceByName, fail }) {
|
|
281
|
+
const name = resolved.existsIn?.[0];
|
|
282
|
+
if (name === void 0) return;
|
|
283
|
+
if (sourceByName.get(name)?.kind !== "etl") fail(`existsIn '${name}' must be an etl source`);
|
|
284
|
+
if (resolved.policies.insert !== void 0 || resolved.policies.write !== void 0) {
|
|
285
|
+
fail("existsIn allows only an update policy: rows come from the etl source");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function validateCompositeKey({ resolved, keys, tableByName, fail }) {
|
|
289
|
+
const keyList = `(${keys.join(", ")})`;
|
|
290
|
+
if (resolved.existsIn === void 0) {
|
|
291
|
+
fail(`requires exactly one primary-key column: composite key ${keyList} requires existsIn`);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const writes = ["insert", "update", "write"].filter((kind) => resolved.policies[kind] !== void 0);
|
|
295
|
+
if (writes.length > 0) fail(`composite key ${keyList} requires a read-only table: remove the ${writes.join("/")} policy`);
|
|
296
|
+
if (resolved.materialized) fail(`composite key ${keyList} cannot be materialized`);
|
|
297
|
+
for (const source of resolved.sources) {
|
|
298
|
+
if (source.kind === "prefetch") {
|
|
299
|
+
fail(`composite key ${keyList} cannot have prefetch source '${source.name}'`);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const table = tableByName.get(source.table);
|
|
303
|
+
if (table && !sameKey(logicalKey(table), keys)) {
|
|
304
|
+
fail(`composite key ${keyList} requires ${source.kind} source '${source.name}' to be keyed by it; table '${source.table}' is keyed by (${logicalKey(table).join(", ")})`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// src/canonical/resolved.ts
|
|
268
310
|
var identifier = zod.z.string().min(1).max(63).regex(/^[a-z][a-z0-9_]*$/);
|
|
269
311
|
var durationMs = zod.z.number().int().positive().max(24 * 60 * 60 * 1e3);
|
|
270
312
|
var RESOLVED_VIEW_SYSTEM_COLUMNS = {
|
|
@@ -333,6 +375,13 @@ var canonicalResolvedSchema = zod.z.object({
|
|
|
333
375
|
resolve: zod.z.array(canonicalResolveRuleSchema).max(500),
|
|
334
376
|
/** Sources whose tombstone hides the resolved row (v1: the manual source only). */
|
|
335
377
|
deletedBy: zod.z.array(identifier).max(1).default([]),
|
|
378
|
+
/**
|
|
379
|
+
* `rows.existsIn`: the one etl source whose rows are the table's rows (read
|
|
380
|
+
* directly as the row source). Only an update policy may write. It is also
|
|
381
|
+
* what admits a composite primary key: a read-only table keyed exactly like
|
|
382
|
+
* that source.
|
|
383
|
+
*/
|
|
384
|
+
existsIn: zod.z.array(identifier).length(1).optional(),
|
|
336
385
|
/**
|
|
337
386
|
* Materialized: the view reads an indexed internal table (`table`) that the
|
|
338
387
|
* data plane keeps in step with `compute`, the internal view holding the
|
|
@@ -351,8 +400,8 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
351
400
|
if (!resolved) return [];
|
|
352
401
|
const errors = [];
|
|
353
402
|
const fail = (message) => errors.push(`resolved table '${view.view}': ${message}`);
|
|
354
|
-
const
|
|
355
|
-
if (
|
|
403
|
+
const keyColumns = (view.primaryKey ?? []).map((columnName) => view.columns.find((c) => c.columnName === columnName)).filter((column) => column !== void 0);
|
|
404
|
+
if (keyColumns.length === 0 || keyColumns.length !== view.primaryKey?.length) {
|
|
356
405
|
fail("requires exactly one primary-key column");
|
|
357
406
|
return errors;
|
|
358
407
|
}
|
|
@@ -360,7 +409,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
360
409
|
const scope = {
|
|
361
410
|
view,
|
|
362
411
|
resolved,
|
|
363
|
-
|
|
412
|
+
keys: new Map(keyColumns.map((column) => [column.name, column])),
|
|
364
413
|
dataColumns: new Map(view.columns.filter((c) => !systemNames.has(c.name) && c.cell === void 0).map((c) => [c.name, c])),
|
|
365
414
|
sourceByName: /* @__PURE__ */ new Map(),
|
|
366
415
|
fail
|
|
@@ -374,6 +423,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
374
423
|
if (!table) fail(`source '${source.name}' references unknown table '${source.table}'`);
|
|
375
424
|
else validateSource({ scope, source, table });
|
|
376
425
|
}
|
|
426
|
+
validateRowIdentity({ resolved, keys: [...scope.keys.keys()], sourceByName: scope.sourceByName, tableByName, fail });
|
|
377
427
|
validateRules(scope);
|
|
378
428
|
validateViewCells(scope);
|
|
379
429
|
if (resolved.materialized) validateMaterialized({ scope, tableByName, views });
|
|
@@ -403,7 +453,7 @@ function validateSource({ scope, source, table }) {
|
|
|
403
453
|
validatePrefetchFields({ scope, source });
|
|
404
454
|
}
|
|
405
455
|
function validatePrefetchFields({ scope, source }) {
|
|
406
|
-
const { fail,
|
|
456
|
+
const { fail, keys } = scope;
|
|
407
457
|
if (source.kind !== "prefetch") {
|
|
408
458
|
if (source.key || source.fetch || source.function || source.prefetchDefaults || source.writeback) {
|
|
409
459
|
fail(`only prefetch sources may declare key/fetch/function/prefetchDefaults/writeback ('${source.name}')`);
|
|
@@ -412,7 +462,7 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
412
462
|
}
|
|
413
463
|
if (!source.key || !source.fetch || !source.function || !source.prefetchDefaults) {
|
|
414
464
|
fail(`prefetch source '${source.name}' requires key, fetch, function and prefetchDefaults`);
|
|
415
|
-
} else if (source.key
|
|
465
|
+
} else if (!keys.has(source.key) && !source.columns.includes(source.key)) {
|
|
416
466
|
fail(`prefetch source '${source.name}' key '${source.key}' must be the primary key or one of its columns`);
|
|
417
467
|
}
|
|
418
468
|
for (const column of source.writeback?.columns ?? []) {
|
|
@@ -420,19 +470,19 @@ function validatePrefetchFields({ scope, source }) {
|
|
|
420
470
|
}
|
|
421
471
|
}
|
|
422
472
|
function validateSourceColumns({ scope, source, byName }) {
|
|
423
|
-
const { fail,
|
|
424
|
-
for (const column of [
|
|
425
|
-
const own = column
|
|
473
|
+
const { fail, keys, dataColumns } = scope;
|
|
474
|
+
for (const column of [...keys.keys(), ...source.columns]) {
|
|
475
|
+
const own = keys.get(column) ?? dataColumns.get(column);
|
|
426
476
|
const theirs = byName.get(column);
|
|
427
477
|
if (!own) fail(`source '${source.name}' supplies unknown column '${column}'`);
|
|
428
478
|
else if (!theirs) fail(`source '${source.name}' table '${source.table}' has no column '${column}'`);
|
|
429
479
|
else if (JSON.stringify(theirs.type) !== JSON.stringify(own.type)) fail(`column '${column}' has a different type on source '${source.name}'`);
|
|
430
480
|
}
|
|
431
481
|
}
|
|
432
|
-
function validateRules({ resolved,
|
|
482
|
+
function validateRules({ resolved, keys, dataColumns, sourceByName, fail }) {
|
|
433
483
|
const ruled = /* @__PURE__ */ new Set();
|
|
434
484
|
for (const rule of resolved.resolve) {
|
|
435
|
-
if (!dataColumns.has(rule.column) || rule.column
|
|
485
|
+
if (!dataColumns.has(rule.column) || keys.has(rule.column)) {
|
|
436
486
|
fail(`resolve rule targets unknown column '${rule.column}'`);
|
|
437
487
|
continue;
|
|
438
488
|
}
|
|
@@ -449,7 +499,7 @@ function validateRules({ resolved, pkColumn, dataColumns, sourceByName, fail })
|
|
|
449
499
|
}
|
|
450
500
|
}
|
|
451
501
|
for (const column of dataColumns.keys()) {
|
|
452
|
-
if (column
|
|
502
|
+
if (!keys.has(column) && !ruled.has(column)) fail(`column '${column}' has no resolve rule`);
|
|
453
503
|
}
|
|
454
504
|
}
|
|
455
505
|
var VIEW_CELL_TYPES = {
|
|
@@ -458,10 +508,10 @@ var VIEW_CELL_TYPES = {
|
|
|
458
508
|
by: "text",
|
|
459
509
|
conflicts: "jsonb"
|
|
460
510
|
};
|
|
461
|
-
function validateViewCells({ view, dataColumns,
|
|
511
|
+
function validateViewCells({ view, dataColumns, keys, fail }) {
|
|
462
512
|
const expected = /* @__PURE__ */ new Map();
|
|
463
513
|
for (const column of dataColumns.values()) {
|
|
464
|
-
if (column.name
|
|
514
|
+
if (keys.has(column.name)) continue;
|
|
465
515
|
for (const part of RESOLVED_VIEW_CELL_PARTS) {
|
|
466
516
|
expected.set(cellColumnName(column.name, part), { part, columnName: cellColumnName(column.columnName, part) });
|
|
467
517
|
}
|
|
@@ -672,7 +722,7 @@ var canonicalTableSchema = zod.z.object({
|
|
|
672
722
|
table: identifier2,
|
|
673
723
|
displayName: zod.z.string().trim().min(1).max(120).optional(),
|
|
674
724
|
description: zod.z.string().max(2e3).optional(),
|
|
675
|
-
/** Table-level rename hint
|
|
725
|
+
/** Table-level rename hint. */
|
|
676
726
|
renamedFrom: identifier2.optional(),
|
|
677
727
|
/** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
|
|
678
728
|
source: zod.z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
|
|
@@ -1471,8 +1521,13 @@ var resolvedSourceIrSchema = zod.z.object({
|
|
|
1471
1521
|
}).optional()
|
|
1472
1522
|
});
|
|
1473
1523
|
var resolvedMetaIrSchema = zod.z.object({
|
|
1474
|
-
/**
|
|
1475
|
-
|
|
1524
|
+
/**
|
|
1525
|
+
* Logical pk column of the resolved view. Absent for a composite key, which
|
|
1526
|
+
* only a read-only `existsIn` table may declare: it has no writes, prefetch
|
|
1527
|
+
* or materialization (the paths that address one key column), and its reads
|
|
1528
|
+
* use the view's `primaryKey` like any keyed view.
|
|
1529
|
+
*/
|
|
1530
|
+
pk: zod.z.string().optional(),
|
|
1476
1531
|
/** Source name of the manual source. */
|
|
1477
1532
|
manual: zod.z.string(),
|
|
1478
1533
|
sources: zod.z.array(resolvedSourceIrSchema),
|