@sequenceholdings/orm 2.9.0 → 2.10.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/compiler.cjs CHANGED
@@ -1665,19 +1665,20 @@ var variableIrSchema = zod.z.object({
1665
1665
  defaultValue: variableDefaultIrSchema.optional()
1666
1666
  });
1667
1667
  var sqlColumnSchema = zod.z.object({ name: zod.z.string(), type: zod.z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz", "jsonb"]), nullable: zod.z.boolean() });
1668
+ var sqlObjectIrSchema = zod.z.object({
1669
+ ref: zod.z.string(),
1670
+ table: zod.z.string(),
1671
+ columns: zod.z.array(sqlColumnSchema.extend({ type: zod.z.string() })).min(1),
1672
+ scan: zod.z.string().min(1),
1673
+ read: zod.z.array(zod.z.string()).min(1)
1674
+ }).strict();
1668
1675
  var compiledOperationSchema = zod.z.object({
1669
1676
  language: zod.z.literal("sql").optional(),
1670
1677
  /** Server-compiled object catalog and permission ceiling, never caller SQL. */
1671
1678
  sqlQuery: zod.z.object({
1672
1679
  catalog: zod.z.object({
1673
1680
  identity: zod.z.string(),
1674
- objects: zod.z.array(zod.z.object({
1675
- ref: zod.z.string(),
1676
- table: zod.z.string(),
1677
- columns: zod.z.array(sqlColumnSchema.extend({ type: zod.z.string() })).min(1),
1678
- scan: zod.z.string().min(1),
1679
- read: zod.z.array(zod.z.string()).min(1)
1680
- }).strict()).min(1).max(256)
1681
+ objects: zod.z.array(sqlObjectIrSchema).min(1).max(256)
1681
1682
  }).strict(),
1682
1683
  read: zod.z.array(zod.z.string()).min(1).max(256),
1683
1684
  maxRows: zod.z.number().int().min(1).max(1e4)
@@ -2337,6 +2338,7 @@ var FLIPPED = {
2337
2338
  ">=": "<="
2338
2339
  };
2339
2340
  function resolveTable(resolver, table) {
2341
+ resolver.onTable?.(table);
2340
2342
  const info = resolver.tables[table];
2341
2343
  if (!info) {
2342
2344
  throw new PolicyCompileError(`unknown table '${table}'`, "unknown-table", Object.keys(resolver.tables));
@@ -3560,12 +3562,12 @@ function computeOpHash({
3560
3562
  definition,
3561
3563
  schemaHash
3562
3564
  }) {
3563
- const digest = crypto.createHash("sha256").update(OP_HASH_DOMAIN).update(`${COMPILER_MAJOR}\0${schemaHash}\0`).update(canonicalOperationText(definition)).digest("hex");
3564
- return `sha256:${digest}`;
3565
+ const digest2 = crypto.createHash("sha256").update(OP_HASH_DOMAIN).update(`${COMPILER_MAJOR}\0${schemaHash}\0`).update(canonicalOperationText(definition)).digest("hex");
3566
+ return `sha256:${digest2}`;
3565
3567
  }
3566
3568
  function computeOpsHash(opHashes) {
3567
- const digest = crypto.createHash("sha256").update(OPS_HASH_DOMAIN).update([...opHashes].sort().join("\n")).digest("hex");
3568
- return `sha256:${digest}`;
3569
+ const digest2 = crypto.createHash("sha256").update(OPS_HASH_DOMAIN).update([...opHashes].sort().join("\n")).digest("hex");
3570
+ return `sha256:${digest2}`;
3569
3571
  }
3570
3572
  var SOURCE_DIRECTIVES = /* @__PURE__ */ new Set(["prefetch", "writeback", "localOnly"]);
3571
3573
  var fail = (message, code) => {
@@ -5020,8 +5022,8 @@ function restrictOperation({
5020
5022
  // src/compiler-gql/artifact.ts
5021
5023
  var SCHEMA_HASH_DOMAIN = "sequence-orm-canonical-v2\0";
5022
5024
  function computeSchemaHash(canonical) {
5023
- const digest = crypto.createHash("sha256").update(SCHEMA_HASH_DOMAIN).update(stableJson(canonical)).digest("hex");
5024
- return `sha256:${digest}`;
5025
+ const digest2 = crypto.createHash("sha256").update(SCHEMA_HASH_DOMAIN).update(stableJson(canonical)).digest("hex");
5026
+ return `sha256:${digest2}`;
5025
5027
  }
5026
5028
  function compileNamespace({ canonical, sdl, documents }) {
5027
5029
  const { ctx, diagnostics } = buildCompileContext(canonical);
@@ -6475,10 +6477,13 @@ function sqlHash(value) {
6475
6477
  return `sha256:${crypto.createHash("sha256").update(value).digest("hex")}`;
6476
6478
  }
6477
6479
  function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
6478
- if (!publishedObjects.length || new Set(publishedObjects).size !== publishedObjects.length) throw new Error("SQL objects must be explicitly declared and unique");
6479
6480
  const { ctx, diagnostics } = buildCompileContext(canonical);
6480
6481
  if (diagnostics.some((d) => d.severity === "error")) throw new Error(diagnostics.map((d) => d.message).join("; "));
6481
- const identity = sqlHash(`ontology-sql-v1\0${computeSchemaHash(canonical)}\0${executionTarget}`);
6482
+ return createSqlCatalogFromContext({ canonical, publishedObjects, executionTarget, ctx });
6483
+ }
6484
+ function createSqlCatalogFromContext({ canonical, publishedObjects, executionTarget, ctx, identity: suppliedIdentity }) {
6485
+ if (!publishedObjects.length || new Set(publishedObjects).size !== publishedObjects.length) throw new Error("SQL objects must be explicitly declared and unique");
6486
+ const identity = suppliedIdentity ?? sqlHash(`ontology-sql-v1\0${computeSchemaHash(canonical)}\0${executionTarget}`);
6482
6487
  const logicalNames = new Map(Object.entries(ctx.tables).map(([key, meta]) => [meta, key]));
6483
6488
  const refOf = (meta) => `${meta.namespace ?? canonical.namespace}/${logicalNames.get(meta)}`;
6484
6489
  const definitions = [canonical, ...canonical.imports ?? []];
@@ -6615,9 +6620,10 @@ var SqlEmitter = class {
6615
6620
  only(cte, ["ctename", "ctequery", "ctematerialized", "location"]);
6616
6621
  const name2 = str(cte.ctename);
6617
6622
  if (scope.ctes.has(name2)) fail3("duplicate CTE");
6623
+ const materialization = cte.ctematerialized === "CTEMaterializeAlways" ? "MATERIALIZED " : cte.ctematerialized === "CTEMaterializeNever" ? "NOT MATERIALIZED " : cte.ctematerialized === "CTEMaterializeDefault" ? "" : fail3("unsupported CTE materialization");
6618
6624
  const result2 = this.select(obj(cte.ctequery), { ...parent, ctes: scope.ctes });
6619
6625
  scope.ctes.set(name2, result2);
6620
- ctes.push(`${quoteIdentifier(name2)} AS (${result2.text})`);
6626
+ ctes.push(`${quoteIdentifier(name2)} AS ${materialization}(${result2.text})`);
6621
6627
  }
6622
6628
  }
6623
6629
  const result = node.op === "SETOP_UNION" ? this.union(node, scope) : this.projection(node, scope);
@@ -7223,7 +7229,7 @@ function compileBuiltinSqlArtifact({ namespace, definitions, read, unbackedObjec
7223
7229
  if (owner !== namespace && selected.some((identity) => !definition.exports?.[identity.slice(owner.length + 1)]?.read)) {
7224
7230
  throw new Error("SQL object is not exported");
7225
7231
  }
7226
- objects.push(...createSqlCatalog({ canonical: definition, publishedObjects: selected, executionTarget }).objects);
7232
+ objects.push(...createSqlCatalogFromContext({ canonical: definition, publishedObjects: selected, executionTarget, ctx }).objects);
7227
7233
  }
7228
7234
  if (objects.length !== read.length) throw new Error("SQL object is unavailable");
7229
7235
  const actualRead = [...new Set(objects.flatMap((object) => object.read))].sort();
@@ -7261,6 +7267,177 @@ function compileBuiltinSqlArtifact({ namespace, definitions, read, unbackedObjec
7261
7267
  } }
7262
7268
  });
7263
7269
  }
7270
+ var OBJECT_METADATA_FORMAT = 1;
7271
+ var digest = zod.z.string().regex(/^sha256:[a-f0-9]{64}$/u);
7272
+ var objectSqlBundleSchema = zod.z.object({
7273
+ format: zod.z.literal(OBJECT_METADATA_FORMAT),
7274
+ dependencies: zod.z.record(zod.z.string(), digest),
7275
+ object: sqlObjectIrSchema,
7276
+ tables: zod.z.record(zod.z.string(), tableMetaIrSchema),
7277
+ readPolicies: zod.z.record(zod.z.string(), predIrSchema)
7278
+ }).strict();
7279
+ function contractHashes(canonical) {
7280
+ const hashes = /* @__PURE__ */ new Map();
7281
+ for (const owner of [canonical, ...canonical.imports ?? []]) {
7282
+ for (const relation of [...owner.tables, ...owner.views ?? []]) {
7283
+ const name2 = "table" in relation ? relation.table : relation.view;
7284
+ hashes.set(`${owner.namespace}/${name2}`, sqlHash(stableJson([
7285
+ "orm-object-contract-v1",
7286
+ owner.namespace,
7287
+ relation,
7288
+ owner.enums,
7289
+ owner.exports?.[name2]
7290
+ ])));
7291
+ }
7292
+ }
7293
+ return hashes;
7294
+ }
7295
+ function objectClosure({ roots, tables, policies, sourceDependencies }) {
7296
+ const required = /* @__PURE__ */ new Set(), links = /* @__PURE__ */ new Map();
7297
+ const walk = (pred, table) => {
7298
+ if (!pred) return;
7299
+ if (pred.kind === "and" || pred.kind === "or") for (const operand of pred.operands) walk(operand, table);
7300
+ else if (pred.kind === "not") walk(pred.operand, table);
7301
+ else if (pred.kind === "exists" || pred.kind === "aggPredicate") {
7302
+ const link = tables[table]?.links.find((candidate) => candidate.name === pred.link);
7303
+ if (!link) throw new Error("object policy dependency is unavailable");
7304
+ const used = links.get(table) ?? /* @__PURE__ */ new Set();
7305
+ used.add(link.name);
7306
+ links.set(table, used);
7307
+ visit2(link.target);
7308
+ walk(pred.where, link.target);
7309
+ }
7310
+ };
7311
+ const visit2 = (ref) => {
7312
+ if (required.has(ref)) return;
7313
+ const meta = tables[ref];
7314
+ if (!meta) throw new Error("object dependency is unavailable");
7315
+ required.add(ref);
7316
+ if (required.size > 1024) throw new Error("object dependency budget exceeded");
7317
+ walk(policies[ref], ref);
7318
+ for (const dependency of sourceDependencies.get(ref) ?? []) visit2(dependency);
7319
+ for (const backing of meta.dependencies ?? []) visit2(backing);
7320
+ };
7321
+ for (const root of roots) visit2(root);
7322
+ return { required: [...required].sort(), links };
7323
+ }
7324
+ async function compileObjectMetadata({ canonical: raw }) {
7325
+ const canonical = normalizeCanonical(canonicalDefinitionSchema.parse(raw));
7326
+ await validateManagedViewQueries({ canonical });
7327
+ const context = buildCompileContext(canonical);
7328
+ if (context.diagnostics.some((item) => item.severity === "error")) throw new Error("invalid object metadata definition");
7329
+ const { ctx } = context;
7330
+ const hashes = contractHashes(canonical);
7331
+ const ref = (key) => {
7332
+ const meta = ctx.tables[key];
7333
+ if (!meta) throw new Error("object dependency is unavailable");
7334
+ return `${meta.namespace ?? canonical.namespace}/${key}`;
7335
+ };
7336
+ const tables = {}, policies = {};
7337
+ const sourceDependencies = /* @__PURE__ */ new Map();
7338
+ const relations = [canonical, ...canonical.imports ?? []].flatMap(canonicalRelations);
7339
+ const expressions = new Map(relations.map((relation) => [relation.table, relation.policies.read]));
7340
+ for (const [key, meta] of Object.entries(ctx.tables)) {
7341
+ tables[ref(key)] = {
7342
+ ...meta,
7343
+ namespace: meta.namespace ?? canonical.namespace,
7344
+ links: meta.links.map((link) => ({ ...link, target: ref(link.target) })),
7345
+ ...meta.dependencies ? { dependencies: meta.dependencies.map(ref) } : {},
7346
+ ...meta.foreignReferences ? { foreignReferences: meta.foreignReferences.map((link) => ({ ...link, target: ref(link.target) })) } : {}
7347
+ };
7348
+ const policy = ctx.readPolicies.get(key);
7349
+ if (policy) policies[ref(key)] = policy;
7350
+ const expression = expressions.get(key);
7351
+ if (expression !== void 0) {
7352
+ const consulted = /* @__PURE__ */ new Set();
7353
+ compilePolicy({ expression, table: key, access: "read", resolver: {
7354
+ tables: ctx.tables,
7355
+ onTable: (table) => {
7356
+ consulted.add(ref(table));
7357
+ },
7358
+ readPolicy: (table) => expressions.get(table),
7359
+ policyNamespace: (table) => ctx.tables[table]?.namespace
7360
+ } });
7361
+ sourceDependencies.set(ref(key), [...consulted]);
7362
+ }
7363
+ }
7364
+ const objects = [];
7365
+ for (const relation of [...canonical.tables, ...canonical.views ?? []]) {
7366
+ const name2 = "table" in relation ? relation.table : relation.view;
7367
+ const identity = `${canonical.namespace}/${name2}`, contractHash = hashes.get(identity);
7368
+ let bundle = null;
7369
+ if (!relation.internal) {
7370
+ const object = createSqlCatalogFromContext({
7371
+ canonical,
7372
+ ctx,
7373
+ identity: contractHash,
7374
+ publishedObjects: [identity],
7375
+ executionTarget: "default"
7376
+ }).objects[0];
7377
+ const closure = objectClosure({ roots: object.read, tables, policies, sourceDependencies });
7378
+ bundle = objectSqlBundleSchema.parse({
7379
+ format: OBJECT_METADATA_FORMAT,
7380
+ object,
7381
+ // platformUsers is compiler-owned metadata, pinned by the format above.
7382
+ dependencies: Object.fromEntries(closure.required.filter((key) => hashes.has(key)).map((key) => [key, hashes.get(key)])),
7383
+ tables: Object.fromEntries(closure.required.map((key) => {
7384
+ const { foreignReferences: _writeReferences, ...meta } = tables[key];
7385
+ return [key, { ...meta, links: meta.links.filter((link) => closure.links.get(key)?.has(link.name)) }];
7386
+ })),
7387
+ readPolicies: Object.fromEntries(closure.required.filter((key) => policies[key]).map((key) => [key, policies[key]]))
7388
+ });
7389
+ }
7390
+ objects.push({ name: name2, contractHash, bundle });
7391
+ }
7392
+ return {
7393
+ format: OBJECT_METADATA_FORMAT,
7394
+ objects,
7395
+ relations: Object.values(ctx.tables).map(({ schema, table }) => ({ schema, table }))
7396
+ };
7397
+ }
7398
+ function composeObjectSqlArtifact({ namespace, bundles }) {
7399
+ const tables = {}, readPolicies = {};
7400
+ const pins = /* @__PURE__ */ new Map();
7401
+ const objects = bundles.map((bundle) => {
7402
+ if (!bundle.object.ref.startsWith(`${namespace}/`) && !bundle.tables[bundle.object.ref]?.exportRead) throw new Error("SQL object is not exported");
7403
+ for (const [ref, hash] of Object.entries(bundle.dependencies)) {
7404
+ if (pins.has(ref) && pins.get(ref) !== hash) throw new Error("inconsistent object contracts");
7405
+ pins.set(ref, hash);
7406
+ }
7407
+ for (const [ref, meta] of Object.entries(bundle.tables)) {
7408
+ const previous = tables[ref];
7409
+ const links = new Map([...previous?.links ?? [], ...meta.links].map((link) => [link.name, link]));
7410
+ tables[ref] = { ...meta, links: [...links.values()] };
7411
+ }
7412
+ Object.assign(readPolicies, bundle.readPolicies);
7413
+ return bundle.object;
7414
+ });
7415
+ const read = [...new Set(objects.flatMap((object) => object.read))].sort();
7416
+ const identity = sqlHash(stableJson(["orm-object-sql-v1", namespace, bundles]));
7417
+ return normalizeIr({
7418
+ irVersion: usesServicePrincipal(readPolicies) ? SERVICE_PRINCIPAL_IR_VERSION : RUNTIME_SQL_IR_VERSION,
7419
+ namespace,
7420
+ schemaHash: identity,
7421
+ opsHash: BUILTIN_SQL_READ_HASH,
7422
+ tables,
7423
+ readPolicies,
7424
+ operations: { BuiltinSqlRead: {
7425
+ irVersion: RUNTIME_SQL_IR_VERSION,
7426
+ name: "BuiltinSqlRead",
7427
+ opHash: BUILTIN_SQL_READ_HASH,
7428
+ language: "sql",
7429
+ kind: "query",
7430
+ requires: null,
7431
+ roots: [],
7432
+ tableSet: read,
7433
+ variables: [
7434
+ { name: "sql", type: { kind: "scalar", scalar: "text" }, nullable: false, list: false },
7435
+ { name: "parameters", type: { kind: "scalar", scalar: "jsonb" }, nullable: true, list: false }
7436
+ ],
7437
+ sqlQuery: { catalog: { identity, objects }, read, maxRows: 1e3 }
7438
+ } }
7439
+ });
7440
+ }
7264
7441
  var DATASET_PREVIEW_LIMIT = 100;
7265
7442
  function compileDatasetPreviews(input) {
7266
7443
  const canonical = normalizeCanonical(input);
@@ -7306,6 +7483,64 @@ function compileDatasetPreviews(input) {
7306
7483
  return operations;
7307
7484
  }
7308
7485
 
7486
+ // src/compiler-gql/operation-metadata.ts
7487
+ var OPERATION_METADATA_FORMAT = 1;
7488
+ function projectOperationMetadata({ artifact, operation }) {
7489
+ const required = /* @__PURE__ */ new Set(), dynamic = /* @__PURE__ */ new Set();
7490
+ const visit2 = (table) => {
7491
+ if (required.has(table)) return;
7492
+ const meta = artifact.tables[table];
7493
+ if (!meta) throw new Error(`operation metadata references missing table '${table}'`);
7494
+ required.add(table);
7495
+ walk(artifact.readPolicies?.[table], table);
7496
+ for (const dependency of meta.dependencies ?? []) visit2(dependency);
7497
+ };
7498
+ const walk = (value, table) => {
7499
+ if (Array.isArray(value)) {
7500
+ for (const child of value) walk(child, table);
7501
+ return;
7502
+ }
7503
+ if (!value || typeof value !== "object") return;
7504
+ const node = value;
7505
+ let scope = typeof node.table === "string" && artifact.tables[node.table] ? node.table : table;
7506
+ if (scope !== table) visit2(scope);
7507
+ if (typeof node.link === "string") {
7508
+ const link = artifact.tables[scope]?.links.find((candidate) => candidate.name === node.link);
7509
+ if (!link) throw new Error("operation metadata has an unresolved relationship");
7510
+ scope = link.target;
7511
+ visit2(scope);
7512
+ }
7513
+ for (const [key, child] of Object.entries(node)) {
7514
+ if (["value", "objects", "set", "inc", "append", "pk", "onConflict"].includes(key)) continue;
7515
+ walk(child, scope);
7516
+ }
7517
+ };
7518
+ const visitDynamic = (table) => {
7519
+ if (dynamic.has(table)) return;
7520
+ dynamic.add(table);
7521
+ visit2(table);
7522
+ for (const link of artifact.tables[table].links) visitDynamic(link.target);
7523
+ };
7524
+ for (const table of operation.tableSet) visit2(table);
7525
+ for (const root of operation.roots) {
7526
+ visit2(root.table);
7527
+ walk(root, root.table);
7528
+ if (root.kind === "mutation" && !["delete", "deleteByPk", "cowRevert"].includes(root.op)) {
7529
+ for (const reference of artifact.tables[root.table].foreignReferences ?? []) visit2(reference.target);
7530
+ }
7531
+ }
7532
+ for (const variable of operation.variables) if (variable.type.kind === "inputRef") {
7533
+ visit2(variable.type.table);
7534
+ if (["boolExp", "orderBy"].includes(variable.type.input)) visitDynamic(variable.type.table);
7535
+ }
7536
+ return normalizeIr({
7537
+ ...artifact,
7538
+ tables: Object.fromEntries([...required].sort().map((table) => [table, artifact.tables[table]])),
7539
+ readPolicies: Object.fromEntries([...required].filter((table) => artifact.readPolicies?.[table]).map((table) => [table, artifact.readPolicies[table]])),
7540
+ operations: { [operation.name]: operation }
7541
+ });
7542
+ }
7543
+
7309
7544
  exports.COMPILER_MAJOR = COMPILER_MAJOR;
7310
7545
  exports.CONST_TRUE = CONST_TRUE;
7311
7546
  exports.DATASET_PREVIEW_LIMIT = DATASET_PREVIEW_LIMIT;
@@ -7313,6 +7548,8 @@ exports.DEFAULT_LIMIT = DEFAULT_LIMIT;
7313
7548
  exports.DocumentCompileError = DocumentCompileError;
7314
7549
  exports.MAX_LIMIT = MAX_LIMIT;
7315
7550
  exports.NamespaceCompileError = NamespaceCompileError;
7551
+ exports.OBJECT_METADATA_FORMAT = OBJECT_METADATA_FORMAT;
7552
+ exports.OPERATION_METADATA_FORMAT = OPERATION_METADATA_FORMAT;
7316
7553
  exports.ORDER_BY_DIRECTIONS = ORDER_BY_DIRECTIONS;
7317
7554
  exports.OperationLowerer = OperationLowerer;
7318
7555
  exports.PLATFORM_USER_TABLE = PLATFORM_USER_TABLE;
@@ -7336,10 +7573,12 @@ exports.compileDatasetPreviews = compileDatasetPreviews;
7336
7573
  exports.compileDefaultOperations = compileDefaultOperations;
7337
7574
  exports.compileNamespace = compileNamespace;
7338
7575
  exports.compileNamespaceOrThrow = compileNamespaceOrThrow;
7576
+ exports.compileObjectMetadata = compileObjectMetadata;
7339
7577
  exports.compileOperationDocuments = compileOperationDocuments;
7340
7578
  exports.compilePolicy = compilePolicy;
7341
7579
  exports.compilePredicateV2 = compilePredicateV2;
7342
7580
  exports.compileRuntimeSql = compileRuntimeSql;
7581
+ exports.composeObjectSqlArtifact = composeObjectSqlArtifact;
7343
7582
  exports.computeOpHash = computeOpHash;
7344
7583
  exports.computeOpsHash = computeOpsHash;
7345
7584
  exports.computePinnedColumnsByTable = computePinnedColumnsByTable;
@@ -7353,6 +7592,7 @@ exports.inputTypeName = inputTypeName;
7353
7592
  exports.isSqlOperationDocument = isSqlOperationDocument;
7354
7593
  exports.lowerOperation = lowerOperation;
7355
7594
  exports.mutationRootNames = mutationRootNames;
7595
+ exports.objectSqlBundleSchema = objectSqlBundleSchema;
7356
7596
  exports.parseDocuments = parseDocuments;
7357
7597
  exports.parsePolicy = parsePolicy;
7358
7598
  exports.parseSdl = parseSdl;
@@ -7360,6 +7600,7 @@ exports.pascalCase = pascalCase;
7360
7600
  exports.platformUserMeta = platformUserMeta;
7361
7601
  exports.predContains = predContains;
7362
7602
  exports.predContainsExists = predContainsExists;
7603
+ exports.projectOperationMetadata = projectOperationMetadata;
7363
7604
  exports.queryRootNames = queryRootNames;
7364
7605
  exports.referencedSqlObjects = referencedSqlObjects;
7365
7606
  exports.restrictOperation = restrictOperation;