@sequenceholdings/orm 2.3.0 → 2.5.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.
Files changed (59) hide show
  1. package/dist/authoring.cjs +53 -7
  2. package/dist/authoring.cjs.map +1 -1
  3. package/dist/authoring.d.cts +11 -7
  4. package/dist/authoring.d.ts +11 -7
  5. package/dist/authoring.js +53 -7
  6. package/dist/authoring.js.map +1 -1
  7. package/dist/canonical.cjs +48 -2
  8. package/dist/canonical.cjs.map +1 -1
  9. package/dist/canonical.d.cts +72 -72
  10. package/dist/canonical.d.ts +72 -72
  11. package/dist/canonical.js +48 -2
  12. package/dist/canonical.js.map +1 -1
  13. package/dist/cli.cjs +337 -86
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/cli.js +337 -86
  16. package/dist/cli.js.map +1 -1
  17. package/dist/client.cjs +1 -1
  18. package/dist/client.cjs.map +1 -1
  19. package/dist/client.d.cts +1 -1
  20. package/dist/client.d.ts +1 -1
  21. package/dist/client.js +1 -1
  22. package/dist/client.js.map +1 -1
  23. package/dist/compiler.cjs +493 -52
  24. package/dist/compiler.cjs.map +1 -1
  25. package/dist/compiler.d.cts +22 -7
  26. package/dist/compiler.d.ts +22 -7
  27. package/dist/compiler.js +493 -53
  28. package/dist/compiler.js.map +1 -1
  29. package/dist/{constants-C6EG6Wq7.d.cts → constants-Dou1RkTo.d.cts} +7 -2
  30. package/dist/{constants-C6EG6Wq7.d.ts → constants-Dou1RkTo.d.ts} +7 -2
  31. package/dist/dynamic-input.d.cts +1 -1
  32. package/dist/dynamic-input.d.ts +1 -1
  33. package/dist/index.cjs +329 -130
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +66 -58
  36. package/dist/index.d.ts +66 -58
  37. package/dist/index.js +329 -131
  38. package/dist/index.js.map +1 -1
  39. package/dist/ir.cjs +50 -3
  40. package/dist/ir.cjs.map +1 -1
  41. package/dist/ir.d.cts +71 -71
  42. package/dist/ir.d.ts +71 -71
  43. package/dist/ir.js +50 -3
  44. package/dist/ir.js.map +1 -1
  45. package/dist/predicate-v2.cjs +145 -22
  46. package/dist/predicate-v2.cjs.map +1 -1
  47. package/dist/predicate-v2.d.cts +41 -4
  48. package/dist/predicate-v2.d.ts +41 -4
  49. package/dist/predicate-v2.js +145 -22
  50. package/dist/predicate-v2.js.map +1 -1
  51. package/dist/sdl.cjs +53 -3
  52. package/dist/sdl.cjs.map +1 -1
  53. package/dist/sdl.d.cts +3 -1
  54. package/dist/sdl.d.ts +3 -1
  55. package/dist/sdl.js +53 -3
  56. package/dist/sdl.js.map +1 -1
  57. package/package.json +1 -1
  58. package/dist/{definition-DjfC7Lll.d.cts → definition-B99BsOAO.d.cts} +4 -4
  59. package/dist/{definition-DjfC7Lll.d.ts → definition-B99BsOAO.d.ts} +4 -4
package/dist/compiler.cjs CHANGED
@@ -8,12 +8,17 @@ var pgParser = require('@supabase/pg-parser');
8
8
  // src/compiler-gql/artifact.ts
9
9
 
10
10
  // src/constants.ts
11
+ var NAMESPACE_PATTERN = /^(?!(?:events|native_sources)$)[a-z][a-z0-9_]{0,40}$/;
11
12
  var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
12
13
  var MAX_IDENTIFIER_LENGTH = 63;
13
14
  var CAPABILITY_KEY_PATTERN = /^(?:org\/|app\/[a-z][a-z0-9-]{0,63}\/)?[a-z0-9-]{1,64}$/;
15
+ var MAX_PERSISTED_READ_ROWS = 50001;
14
16
  var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
15
17
  var ORM_SCHEMA_PREFIX = "orm_";
16
- var ormSchemaName = (namespace) => `${ORM_SCHEMA_PREFIX}${namespace}`;
18
+ var ormSchemaName = (namespace) => {
19
+ if (!NAMESPACE_PATTERN.test(namespace)) throw new Error(`invalid or reserved ORM namespace '${namespace}'`);
20
+ return `${ORM_SCHEMA_PREFIX}${namespace}`;
21
+ };
17
22
  var CELL_PARTS = ["at", "by", "rev", "source", "conflicts"];
18
23
  var CELL_PART_SUFFIX = {
19
24
  at: "__at",
@@ -389,6 +394,7 @@ function validateResolvedView({ view, tables, views = [] }) {
389
394
  function validateSource({ scope, source, table }) {
390
395
  const { fail: fail4 } = scope;
391
396
  if (source.kind === "etl" && table.source === void 0) fail4(`etl source '${source.name}' must reference a synced table`);
397
+ if (source.kind === "etl" && table.primaryKey?.length === 0) fail4(`etl source '${source.name}' cannot use an unkeyed synced table for resolved row identity`);
392
398
  if (source.kind !== "etl" && (table.internal !== true || table.cellMetadata !== true)) {
393
399
  fail4(`${source.kind} source '${source.name}' must reference an internal table with cell metadata`);
394
400
  }
@@ -620,6 +626,163 @@ function isSingleViewQuerySql(value) {
620
626
  }
621
627
  return state === "normal" && !/\$[a-z_0-9]*\$/i.test(query);
622
628
  }
629
+ var VIEW_QUERY_FUNCTION_ALLOWLIST = [
630
+ "abs",
631
+ "age",
632
+ "array_agg",
633
+ "array_append",
634
+ "array_cat",
635
+ "array_dims",
636
+ "array_length",
637
+ "array_lower",
638
+ "array_ndims",
639
+ "array_position",
640
+ "array_positions",
641
+ "array_prepend",
642
+ "array_remove",
643
+ "array_replace",
644
+ "array_to_string",
645
+ "array_trim",
646
+ "array_upper",
647
+ "ascii",
648
+ "avg",
649
+ "bit_and",
650
+ "bit_or",
651
+ "bit_xor",
652
+ "bool_and",
653
+ "bool_or",
654
+ "btrim",
655
+ "cardinality",
656
+ "cbrt",
657
+ "ceil",
658
+ "ceiling",
659
+ "char_length",
660
+ "character_length",
661
+ "chr",
662
+ "concat",
663
+ "concat_ws",
664
+ "count",
665
+ "cume_dist",
666
+ "date_bin",
667
+ "date_part",
668
+ "date_trunc",
669
+ "decode",
670
+ "degrees",
671
+ "dense_rank",
672
+ "encode",
673
+ "enum_first",
674
+ "enum_last",
675
+ "enum_range",
676
+ "every",
677
+ "exp",
678
+ "first_value",
679
+ "floor",
680
+ "format",
681
+ "grouping",
682
+ "initcap",
683
+ "json_agg",
684
+ "json_array_length",
685
+ "json_build_array",
686
+ "json_build_object",
687
+ "json_extract_path",
688
+ "json_extract_path_text",
689
+ "json_object_agg",
690
+ "json_object_keys",
691
+ "json_strip_nulls",
692
+ "json_typeof",
693
+ "jsonb_agg",
694
+ "jsonb_array_length",
695
+ "jsonb_build_array",
696
+ "jsonb_build_object",
697
+ "jsonb_extract_path",
698
+ "jsonb_extract_path_text",
699
+ "jsonb_insert",
700
+ "jsonb_object_agg",
701
+ "jsonb_object_keys",
702
+ "jsonb_path_exists",
703
+ "jsonb_path_match",
704
+ "jsonb_path_query",
705
+ "jsonb_path_query_array",
706
+ "jsonb_path_query_first",
707
+ "jsonb_pretty",
708
+ "jsonb_set",
709
+ "jsonb_set_lax",
710
+ "jsonb_strip_nulls",
711
+ "jsonb_typeof",
712
+ "justify_days",
713
+ "justify_hours",
714
+ "justify_interval",
715
+ "lag",
716
+ "last_value",
717
+ "lead",
718
+ "left",
719
+ "length",
720
+ "ln",
721
+ "log",
722
+ "lower",
723
+ "lpad",
724
+ "ltrim",
725
+ "make_date",
726
+ "make_interval",
727
+ "make_time",
728
+ "make_timestamp",
729
+ "make_timestamptz",
730
+ "max",
731
+ "md5",
732
+ "min",
733
+ "mod",
734
+ "nth_value",
735
+ "ntile",
736
+ "octet_length",
737
+ "percent_rank",
738
+ "pi",
739
+ "power",
740
+ "quote_ident",
741
+ "quote_literal",
742
+ "quote_nullable",
743
+ "radians",
744
+ "rank",
745
+ "regexp_count",
746
+ "regexp_instr",
747
+ "regexp_like",
748
+ "regexp_match",
749
+ "regexp_matches",
750
+ "regexp_replace",
751
+ "regexp_split_to_array",
752
+ "regexp_split_to_table",
753
+ "repeat",
754
+ "replace",
755
+ "reverse",
756
+ "right",
757
+ "round",
758
+ "row_number",
759
+ "rpad",
760
+ "rtrim",
761
+ "sign",
762
+ "split_part",
763
+ "sqrt",
764
+ "starts_with",
765
+ "string_agg",
766
+ "string_to_array",
767
+ "strpos",
768
+ "substr",
769
+ "substring",
770
+ "sum",
771
+ "timezone",
772
+ "to_ascii",
773
+ "to_char",
774
+ "to_date",
775
+ "to_hex",
776
+ "to_json",
777
+ "to_jsonb",
778
+ "to_number",
779
+ "to_timestamp",
780
+ "translate",
781
+ "trunc",
782
+ "unnest",
783
+ "upper",
784
+ "width_bucket"
785
+ ];
623
786
  var canonicalActionSchema = zod.z.object({
624
787
  name: identifier2,
625
788
  requires: zod.z.string().max(1e3).optional(),
@@ -680,7 +843,7 @@ var canonicalTableSchema = zod.z.object({
680
843
  /** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
681
844
  source: zod.z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
682
845
  columns: zod.z.array(canonicalColumnSchema).default([]),
683
- primaryKey: zod.z.array(columnIdentifier).min(1).max(8).optional(),
846
+ primaryKey: zod.z.array(columnIdentifier).max(8).optional(),
684
847
  links: zod.z.array(canonicalLinkSchema).default([]),
685
848
  indexes: zod.z.array(canonicalIndexSchema).default([]),
686
849
  /** Omitted by old definitions, preserving their existing content hashes. */
@@ -716,6 +879,29 @@ var canonicalTableSchema = zod.z.object({
716
879
  * data plane. Omitted otherwise.
717
880
  */
718
881
  materializes: identifier2.optional()
882
+ }).superRefine((table, ctx) => {
883
+ if (table.primaryKey?.length !== 0) return;
884
+ const fail4 = (message, path = ["primaryKey"]) => ctx.addIssue({ code: "custom", path, message: `unkeyed table '${table.table}' ${message}` });
885
+ if (table.source === void 0 || table.columns.length === 0) {
886
+ fail4("requires a typed synced source");
887
+ }
888
+ if ([table.policies.write, table.policies.insert, table.policies.update].some((policy) => policy !== void 0)) {
889
+ fail4("is read-only and cannot declare write policies", ["policies"]);
890
+ }
891
+ const ownedCollections = [table.indexes, table.actions, table.checks, table.foreignKeys, table.cowMutations];
892
+ const ownedMetadata = [table.cellMetadata, table.internal, table.materializes, table.renamedFrom];
893
+ if (ownedCollections.some((items) => items !== void 0 && items.length > 0) || ownedMetadata.some((value) => value !== void 0)) {
894
+ fail4("cannot declare owned storage, constraints or identity operations");
895
+ }
896
+ for (const [index, column] of table.columns.entries()) {
897
+ const ownedColumnMetadata = [column.default, column.defaultFn, column.onUpdateFn, column.renamedFrom, column.cast, column.cell];
898
+ if (column.unique || ownedColumnMetadata.some((value) => value !== void 0)) {
899
+ fail4("cannot declare column uniqueness, mutation defaults or migration metadata", ["columns", index]);
900
+ }
901
+ }
902
+ for (const [index, link] of table.links.entries()) {
903
+ if (link.enforce || link.kind === "toMany") fail4("cannot provide an identity for this link", ["links", index]);
904
+ }
719
905
  });
720
906
  var MAX_VIEW_QUERY = 1e5;
721
907
  var MAX_RESOLVED_VIEW_QUERY = 5e6;
@@ -772,6 +958,26 @@ var canonicalViewSchema = zod.z.object({
772
958
  }
773
959
  }
774
960
  });
961
+ function validateUnkeyedLinkIdentities({ definition, ctx }) {
962
+ const tables = new Map(definition.tables.map((table) => [table.table, table]));
963
+ const relations = [
964
+ ...definition.tables.map((table, index) => ({ kind: "tables", index, links: table.links })),
965
+ ...(definition.views ?? []).map((view, index) => ({ kind: "views", index, links: view.links }))
966
+ ];
967
+ for (const relation of relations) {
968
+ for (const [linkIndex, link] of relation.links.entries()) {
969
+ if (link.kind !== "toOne" || link.namespace !== void 0 && link.namespace !== definition.namespace) continue;
970
+ const target = link.target === void 0 ? void 0 : tables.get(link.target);
971
+ if (target?.source !== void 0 && target.primaryKey?.length === 0) {
972
+ ctx.addIssue({
973
+ code: "custom",
974
+ path: [relation.kind, relation.index, "links", linkIndex],
975
+ message: `link '${link.name}' cannot use unkeyed table '${target.table}' as a to-one identity`
976
+ });
977
+ }
978
+ }
979
+ }
980
+ }
775
981
  var CELL_PART_TYPES = {
776
982
  at: "timestamptz",
777
983
  by: "text",
@@ -835,7 +1041,7 @@ var exportGateSchema = zod.z.union([zod.z.literal(true), zod.z.object({ capabili
835
1041
  var relationExportSchema = zod.z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
836
1042
  var localDefinitionSchema = zod.z.object({
837
1043
  definition_format: zod.z.literal(CANONICAL_FORMAT),
838
- namespace: identifier2.max(41),
1044
+ namespace: identifier2.max(41).regex(NAMESPACE_PATTERN, "invalid or reserved ORM namespace"),
839
1045
  description: zod.z.string().max(2e3).optional(),
840
1046
  enums: zod.z.array(canonicalEnumSchema).default([]),
841
1047
  tables: zod.z.array(canonicalTableSchema).min(0).max(500),
@@ -869,6 +1075,7 @@ var localDefinitionSchema = zod.z.object({
869
1075
  }
870
1076
  }
871
1077
  const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
1078
+ validateUnkeyedLinkIdentities({ definition, ctx });
872
1079
  const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
873
1080
  for (const name2 of Object.keys(definition.exports ?? {})) {
874
1081
  if (!relations.has(name2)) ctx.addIssue({ code: "custom", path: ["exports", name2], message: `export '${name2}' is not a local object` });
@@ -1191,7 +1398,7 @@ var limitIrSchema = zod.z.object({
1191
1398
  variable: zod.z.string().optional(),
1192
1399
  value: zod.z.number().int().positive().optional(),
1193
1400
  default: zod.z.number().int().positive(),
1194
- max: zod.z.number().int().positive()
1401
+ max: zod.z.number().int().positive().max(MAX_PERSISTED_READ_ROWS)
1195
1402
  });
1196
1403
  var selectionIrSchema = zod.z.lazy(
1197
1404
  () => zod.z.object({
@@ -1856,6 +2063,7 @@ var Parser2 = class {
1856
2063
  return node;
1857
2064
  }
1858
2065
  if (this.peekKeyword("exists")) return this.parseExists();
2066
+ if (this.peekKeyword("visible") && this.tokens[this.index + 1]?.kind === "lparen") return this.parseVisible();
1859
2067
  return this.parseComparison();
1860
2068
  }
1861
2069
  parseBooleanCall(fn) {
@@ -1875,6 +2083,13 @@ var Parser2 = class {
1875
2083
  this.expect("rparen", "')' closing exists(...)");
1876
2084
  return { kind: "exists", path, where };
1877
2085
  }
2086
+ parseVisible() {
2087
+ this.advance();
2088
+ this.expect("lparen", "'(' after visible");
2089
+ const path = this.parsePath("a link path in visible(...)");
2090
+ this.expect("rparen", "')' closing visible(...)");
2091
+ return { kind: "visible", path };
2092
+ }
1878
2093
  parseComparison() {
1879
2094
  const left = this.parseOperand();
1880
2095
  const operator = this.expect("operator", "a comparison operator");
@@ -1990,6 +2205,24 @@ function parsePolicy(source) {
1990
2205
 
1991
2206
  // src/predicate-v2/compile.ts
1992
2207
  var POLICY_MAX_LINK_DEPTH = 3;
2208
+ function scopeToNamespace(pred, namespace) {
2209
+ switch (pred.kind) {
2210
+ case "capability":
2211
+ case "role":
2212
+ return pred.namespace ? pred : { ...pred, namespace };
2213
+ case "and":
2214
+ case "or":
2215
+ return { ...pred, operands: pred.operands.map((operand) => scopeToNamespace(operand, namespace)) };
2216
+ case "not":
2217
+ return { ...pred, operand: scopeToNamespace(pred.operand, namespace) };
2218
+ case "exists":
2219
+ return { ...pred, where: scopeToNamespace(pred.where, namespace) };
2220
+ case "aggPredicate":
2221
+ return pred.where ? { ...pred, where: scopeToNamespace(pred.where, namespace) } : pred;
2222
+ default:
2223
+ return pred;
2224
+ }
2225
+ }
1993
2226
  var CMP_BY_OP = {
1994
2227
  "=": "eq",
1995
2228
  "!=": "neq",
@@ -2023,7 +2256,7 @@ function resolveLink(info, ref) {
2023
2256
  function columnCandidates(info) {
2024
2257
  return [...info.columns.map((c) => c.name), ...info.links.map((l) => l.name)];
2025
2258
  }
2026
- var PolicyCompiler = class {
2259
+ var PolicyCompiler = class _PolicyCompiler {
2027
2260
  constructor(ctx) {
2028
2261
  this.ctx = ctx;
2029
2262
  }
@@ -2036,13 +2269,15 @@ var PolicyCompiler = class {
2036
2269
  return { kind: node.kind, operands: node.operands.map((operand) => this.compile(operand, table, depth)) };
2037
2270
  case "not":
2038
2271
  assertNoNegatedExternalClaim(node.operand);
2039
- return { kind: "not", operand: this.compile(node.operand, table, depth) };
2272
+ return { kind: "not", operand: new _PolicyCompiler({ ...this.ctx, negated: true }).compile(node.operand, table, depth) };
2040
2273
  case "capability":
2041
2274
  return { kind: "capability", key: node.key };
2042
2275
  case "role":
2043
2276
  return { kind: "role", key: node.key };
2044
2277
  case "exists":
2045
2278
  return this.compileExists(node.path, node.where, table, depth);
2279
+ case "visible":
2280
+ return this.compileVisible(node.path, table, depth);
2046
2281
  case "compare":
2047
2282
  return this.compileCompare(node, table, depth);
2048
2283
  }
@@ -2056,6 +2291,36 @@ var PolicyCompiler = class {
2056
2291
  }
2057
2292
  return pred;
2058
2293
  }
2294
+ /** `visible(path)` → `exists(path, <final target's read policy>)`. */
2295
+ compileVisible(path, table, depth) {
2296
+ const { links, finalTable } = this.resolveLinkPath(path, table, depth, { toOneOnly: false });
2297
+ const readPolicy = this.ctx.resolver.readPolicy;
2298
+ if (!readPolicy) {
2299
+ throw new PolicyCompileError(
2300
+ `visible(${path.join(".")}) needs the target's read policy, which this compile context does not provide`,
2301
+ "visible-unresolvable"
2302
+ );
2303
+ }
2304
+ if (this.ctx.visiting.includes(finalTable)) {
2305
+ throw new PolicyCompileError(
2306
+ `visible(${path.join(".")}) on '${table}' reaches '${finalTable}' whose read policy is already being expanded (${[...this.ctx.visiting, finalTable].join(" \u2192 ")})`,
2307
+ "visible-cycle"
2308
+ );
2309
+ }
2310
+ const expression = readPolicy(finalTable);
2311
+ let pred = expression === void 0 ? { kind: "const", value: true } : compilePolicyAt({
2312
+ expression,
2313
+ table: finalTable,
2314
+ ctx: { ...this.ctx, visiting: [...this.ctx.visiting, finalTable] },
2315
+ depth: depth + links.length
2316
+ });
2317
+ const owner = this.ctx.resolver.policyNamespace?.(finalTable);
2318
+ if (owner) pred = scopeToNamespace(pred, owner);
2319
+ for (let i = links.length - 1; i >= 0; i -= 1) {
2320
+ pred = { kind: "exists", link: links[i].name, where: pred };
2321
+ }
2322
+ return pred;
2323
+ }
2059
2324
  resolveLinkPath(path, table, depth, { toOneOnly }) {
2060
2325
  const links = [];
2061
2326
  let current = table;
@@ -2116,6 +2381,7 @@ var PolicyCompiler = class {
2116
2381
  );
2117
2382
  }
2118
2383
  if (valueSide.kind === "claim" && isExternalPolicyClaimKey(valueSide.key)) {
2384
+ if (this.ctx.negated) throw negatedExternalClaim(valueSide.key);
2119
2385
  assertExternalClaimComparison({ op, key: valueSide.key, column: info.columns.find((c) => c.name === column) });
2120
2386
  }
2121
2387
  let cmp = this.buildCmp(op, column, valueSide);
@@ -2153,22 +2419,30 @@ function assertExternalClaimComparison({ op, key, column }) {
2153
2419
  );
2154
2420
  }
2155
2421
  }
2422
+ function negatedExternalClaim(key) {
2423
+ return new PolicyCompileError(
2424
+ `claim('${key}') cannot appear under not(): a negated borrower comparison admits other borrowers' rows`,
2425
+ "unsupported-comparison"
2426
+ );
2427
+ }
2156
2428
  function assertNoNegatedExternalClaim(operand) {
2157
2429
  walkPolicy(operand, (node) => {
2158
2430
  if (node.kind !== "compare") return;
2159
2431
  const claim = [node.left, node.right].find((side) => side.kind === "claim" && isExternalPolicyClaimKey(side.key));
2160
- if (claim?.kind === "claim") {
2161
- throw new PolicyCompileError(
2162
- `claim('${claim.key}') cannot appear under not(): a negated borrower comparison admits other borrowers' rows`,
2163
- "unsupported-comparison"
2164
- );
2165
- }
2432
+ if (claim?.kind === "claim") throw negatedExternalClaim(claim.key);
2166
2433
  });
2167
2434
  }
2168
2435
  function compilePredicateV2({ expression, table, resolver, maxLinkDepth }) {
2436
+ return compilePredicateAt({
2437
+ expression,
2438
+ table,
2439
+ depth: 0,
2440
+ ctx: { resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH, visiting: [table] }
2441
+ });
2442
+ }
2443
+ function compilePredicateAt({ expression, table, ctx, depth }) {
2169
2444
  const parsed = typeof expression === "string" ? parsePolicy(expression) : expression;
2170
- const compiler = new PolicyCompiler({ resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH });
2171
- return compiler.compile(parsed.ast, table, 0);
2445
+ return new PolicyCompiler(ctx).compile(parsed.ast, table, depth);
2172
2446
  }
2173
2447
  function assertClaimsOnlyWhen(parsed) {
2174
2448
  walkPolicy(parsed.ast, (node) => {
@@ -2185,25 +2459,34 @@ function assertClaimsOnlyWhen(parsed) {
2185
2459
  "when-not-claims-only"
2186
2460
  );
2187
2461
  }
2188
- if (node.kind === "exists") {
2462
+ if (node.kind === "exists" || node.kind === "visible") {
2189
2463
  throw new PolicyCompileError(
2190
- "variant 'when' guards are claims-only \u2014 exists() is not allowed",
2464
+ `variant 'when' guards are claims-only \u2014 ${node.kind}() is not allowed`,
2191
2465
  "when-not-claims-only"
2192
2466
  );
2193
2467
  }
2194
2468
  });
2195
2469
  }
2196
- function compilePolicy({ expression, table, resolver, maxLinkDepth }) {
2197
- if (typeof expression === "string") {
2198
- return compilePredicateV2({ expression, table, resolver, maxLinkDepth });
2199
- }
2200
- const defaultPred = compilePredicateV2({ expression: expression.default, table, resolver, maxLinkDepth });
2470
+ function initialVisiting({ table, access }) {
2471
+ return (access ?? "read") === "read" ? [table] : [];
2472
+ }
2473
+ function compilePolicy({ expression, table, resolver, maxLinkDepth, access }) {
2474
+ return compilePolicyAt({
2475
+ expression,
2476
+ table,
2477
+ depth: 0,
2478
+ ctx: { resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH, visiting: initialVisiting({ table, access }) }
2479
+ });
2480
+ }
2481
+ function compilePolicyAt({ expression, table, ctx, depth }) {
2482
+ if (typeof expression === "string") return compilePredicateAt({ expression, table, ctx, depth });
2483
+ const defaultPred = compilePredicateAt({ expression: expression.default, table, ctx, depth });
2201
2484
  if (expression.variants.length === 0) return defaultPred;
2202
2485
  const branches = expression.variants.map((variant) => {
2203
2486
  const parsedWhen = parsePolicy(variant.when);
2204
2487
  assertClaimsOnlyWhen(parsedWhen);
2205
- const when = compilePredicateV2({ expression: parsedWhen, table, resolver, maxLinkDepth });
2206
- const grant = variant.allow === true ? { kind: "const", value: true } : compilePredicateV2({ expression: variant.policy, table, resolver, maxLinkDepth });
2488
+ const when = compilePredicateAt({ expression: parsedWhen, table, ctx, depth });
2489
+ const grant = variant.allow === true ? { kind: "const", value: true } : compilePredicateAt({ expression: variant.policy, table, ctx, depth });
2207
2490
  return { kind: "and", operands: [when, grant] };
2208
2491
  });
2209
2492
  return { kind: "or", operands: [defaultPred, ...branches] };
@@ -2419,12 +2702,6 @@ var PolicyInjector = class {
2419
2702
  if (root.op === "resolvedWrite") return this.injectResolvedWrite(root, returning);
2420
2703
  if (root.op === "insert" || root.op === "insertOne") {
2421
2704
  const insertPolicy = this.insert(table);
2422
- if (predContainsExists(insertPolicy)) {
2423
- throw new DocumentCompileError(
2424
- `table '${table}' cannot be inserted into: v2.0 insert checks are claims + inserted-values only, but its insert policy traverses a link (exists)`,
2425
- "insert-check-unrepresentable"
2426
- );
2427
- }
2428
2705
  const pins = (this.ctx.pins.get(table) ?? []).map(
2429
2706
  (pin) => ({ column: pin.column, value: { kind: "claim", key: pin.claim } })
2430
2707
  );
@@ -2439,22 +2716,14 @@ var PolicyInjector = class {
2439
2716
  const updatePolicy = this.update(table);
2440
2717
  const where = andPred(updatePolicy, root.where ? this.injectDocPred(root.where, table) : void 0);
2441
2718
  if (root.op === "update" || root.op === "updateByPk") {
2442
- const check = predContainsExists(updatePolicy) && !this.ctx.composed ? {} : { insertCheck: updatePolicy };
2443
- return { ...root, where, ...check, returning };
2719
+ return { ...root, where, insertCheck: updatePolicy, returning };
2444
2720
  }
2445
2721
  if (root.op === "cowOverride") {
2446
2722
  const insertPolicy = this.insert(table);
2447
- if (predContainsExists(insertPolicy)) {
2448
- throw new DocumentCompileError(
2449
- `table '${table}' cannot be copy-on-write overridden: v2.0 insert checks are claims + inserted-values only, but its insert policy traverses a link (exists)`,
2450
- "insert-check-unrepresentable"
2451
- );
2452
- }
2453
2723
  const pins = (this.ctx.pins.get(table) ?? []).map(
2454
2724
  (pin) => ({ column: pin.column, value: { kind: "claim", key: pin.claim } })
2455
2725
  );
2456
- const check = predContainsExists(updatePolicy) && !this.ctx.composed ? {} : { insertCheck: updatePolicy };
2457
- return { ...root, pinnedColumns: pins, cowCopyCheck: insertPolicy, where, ...check, returning };
2726
+ return { ...root, pinnedColumns: pins, cowCopyCheck: insertPolicy, where, insertCheck: updatePolicy, returning };
2458
2727
  }
2459
2728
  return { ...root, where, returning };
2460
2729
  }
@@ -2676,7 +2945,7 @@ function scopePolicy(pred, namespace) {
2676
2945
  switch (pred.kind) {
2677
2946
  case "capability":
2678
2947
  case "role":
2679
- return { ...pred, namespace };
2948
+ return pred.namespace ? pred : { ...pred, namespace };
2680
2949
  case "and":
2681
2950
  case "or":
2682
2951
  return { ...pred, operands: pred.operands.map((p) => scopePolicy(p, namespace)) };
@@ -2766,6 +3035,7 @@ function buildCompileContext(rawCanonical) {
2766
3035
  const platformMeta = usesPlatformUsers ? platformUserMeta() : void 0;
2767
3036
  if (platformMeta) tables[PLATFORM_USER_TABLE] = platformMeta;
2768
3037
  const syncedTableNames = new Set(canonical.tables.filter((t) => t.source !== void 0).map((t) => t.table));
3038
+ const unkeyedSyncedTableNames = new Set(relations.filter((table) => table.source !== void 0 && table.primaryKey?.length === 0).map((table) => table.table));
2769
3039
  const viewDependencies = new Map((canonical.views ?? []).map((view) => [view.view, view.dependencies]));
2770
3040
  const claimsGatedMemo = /* @__PURE__ */ new Map();
2771
3041
  const relationIsClaimsGated = (name2) => {
@@ -2779,6 +3049,7 @@ function buildCompileContext(rawCanonical) {
2779
3049
  };
2780
3050
  for (const table of relations) {
2781
3051
  const isView = viewNames.has(table.table);
3052
+ const readOnly = isView || unkeyedSyncedTableNames.has(table.table);
2782
3053
  const owner = owners.get(table.table);
2783
3054
  const entries = resolveColumnEntries(table, enums, diagnostics);
2784
3055
  columnEntries.set(table.table, entries);
@@ -2826,13 +3097,13 @@ function buildCompileContext(rawCanonical) {
2826
3097
  // are claims-gated — see tableMetaIrSchema.claimsGated.
2827
3098
  claimsGated: relationIsClaimsGated(table.table),
2828
3099
  columns: entries.map(({ deprecated: _deprecated, onUpdateFn: _onUpdateFn, ...column }) => column),
2829
- primaryKey: isView ? primaryKey : primaryKey.length > 0 ? primaryKey : ["id"],
3100
+ primaryKey: isView || unkeyedSyncedTableNames.has(table.table) ? primaryKey : primaryKey.length > 0 ? primaryKey : ["id"],
2830
3101
  links: [],
2831
3102
  filterable: data.map((c) => c.name),
2832
3103
  orderable: data.filter((c) => c.type !== "jsonb").map((c) => c.name),
2833
- insertable: resolved ? resolvedWritable(data) : isView ? [] : active.map((c) => c.name),
2834
- settable: resolved ? resolvedWritable(data).filter((name2) => !primaryKey.includes(name2)) : isView ? [] : active.filter((c) => !c.onUpdateFn).map((c) => c.name),
2835
- appendable: isView ? [] : active.filter((c) => c.type === "jsonb").map((c) => c.name),
3104
+ insertable: resolved ? resolvedWritable(data) : readOnly ? [] : active.map((c) => c.name),
3105
+ settable: resolved ? resolvedWritable(data).filter((name2) => !primaryKey.includes(name2)) : readOnly ? [] : active.filter((c) => !c.onUpdateFn).map((c) => c.name),
3106
+ appendable: readOnly ? [] : active.filter((c) => c.type === "jsonb").map((c) => c.name),
2836
3107
  ...touchOnUpdate.length > 0 ? { touchOnUpdate } : {},
2837
3108
  ...cells ? { cells } : {},
2838
3109
  ...resolved ? { resolved: resolvedMeta({ resolved, pk: primaryKey[0] }) } : {},
@@ -2856,6 +3127,16 @@ function buildCompileContext(rawCanonical) {
2856
3127
  });
2857
3128
  continue;
2858
3129
  }
3130
+ const identityTable = link.kind === "toOne" ? targetName : link.kind === "toMany" ? table.table : void 0;
3131
+ if (identityTable !== void 0 && unkeyedSyncedTableNames.has(identityTable)) {
3132
+ diagnostics.push({
3133
+ severity: "error",
3134
+ code: "unkeyed-link-identity",
3135
+ table: table.table,
3136
+ message: `link '${link.name}' cannot use unkeyed table '${identityTable}' as a row identity`
3137
+ });
3138
+ continue;
3139
+ }
2859
3140
  const targetEntries = targetName === PLATFORM_USER_TABLE ? target.columns.map((c) => ({ ...c, deprecated: false, onUpdateFn: false })) : columnEntries.get(targetName);
2860
3141
  const onEntries = link.kind === "toMany" ? targetEntries : entries;
2861
3142
  const referencesEntries = link.kind === "toMany" ? entries : targetEntries;
@@ -2885,7 +3166,14 @@ function buildCompileContext(rawCanonical) {
2885
3166
  const updatePolicies = /* @__PURE__ */ new Map();
2886
3167
  const pins = /* @__PURE__ */ new Map();
2887
3168
  const splitWritePolicyTables = /* @__PURE__ */ new Set();
2888
- const resolver = { tables };
3169
+ const readPolicyExpressions = new Map(relations.map((relation) => [relation.table, relation.policies.read]));
3170
+ const resolver = {
3171
+ tables,
3172
+ readPolicy: (table) => readPolicyExpressions.get(table),
3173
+ // In a composed namespace, an imported table's read policy (inlined by
3174
+ // visible()) is checked against the namespace that owns it.
3175
+ ...normalized.imports?.length ? { policyNamespace: (table) => owners.get(table)?.namespace } : {}
3176
+ };
2889
3177
  for (const table of relations) {
2890
3178
  const isView = viewNames.has(table.table);
2891
3179
  const compilePolicyFor = (access, store) => {
@@ -2894,7 +3182,7 @@ function buildCompileContext(rawCanonical) {
2894
3182
  return;
2895
3183
  }
2896
3184
  try {
2897
- const pred = compilePolicy({ expression, table: table.table, resolver });
3185
+ const pred = compilePolicy({ expression, table: table.table, resolver, access });
2898
3186
  store.set(table.table, normalized.imports?.length ? scopePolicy(pred, owners.get(table.table).namespace) : pred);
2899
3187
  } catch (error) {
2900
3188
  if (error instanceof PolicyCompileError || error instanceof PolicyParseError) {
@@ -2914,7 +3202,7 @@ function buildCompileContext(rawCanonical) {
2914
3202
  compilePolicyFor("write", writePolicies);
2915
3203
  compilePolicyFor("insert", insertPolicies);
2916
3204
  compilePolicyFor("update", updatePolicies);
2917
- if (isView && table.resolved === void 0) {
3205
+ if (isView && table.resolved === void 0 || unkeyedSyncedTableNames.has(table.table)) {
2918
3206
  writePolicies.set(table.table, CONST_FALSE);
2919
3207
  insertPolicies.set(table.table, CONST_FALSE);
2920
3208
  updatePolicies.set(table.table, CONST_FALSE);
@@ -2989,7 +3277,7 @@ function buildCompileContext(rawCanonical) {
2989
3277
  const queryRoots = /* @__PURE__ */ new Map();
2990
3278
  const mutationRoots = /* @__PURE__ */ new Map();
2991
3279
  for (const table of relations) {
2992
- if (table.internal === true) continue;
3280
+ if (table.internal === true || unkeyedSyncedTableNames.has(table.table)) continue;
2993
3281
  const roots = queryRootNames(table.table);
2994
3282
  queryRoots.set(roots.select, { kind: "select", table: table.table });
2995
3283
  if ((tables[table.table]?.primaryKey.length ?? 0) > 0) {
@@ -3369,8 +3657,10 @@ var OperationLowerer = class {
3369
3657
  constructor(ctx, restricted) {
3370
3658
  this.ctx = ctx;
3371
3659
  this.variables = new Map(restricted.variables.map((v) => [v.name, v]));
3660
+ this.maxRows = restricted.readBudget ?? MAX_LIMIT;
3372
3661
  }
3373
3662
  variables;
3663
+ maxRows;
3374
3664
  meta(table) {
3375
3665
  return this.ctx.tables[table];
3376
3666
  }
@@ -3574,13 +3864,13 @@ var OperationLowerer = class {
3574
3864
  });
3575
3865
  }
3576
3866
  lowerLimit(node) {
3577
- const base2 = { default: DEFAULT_LIMIT, max: MAX_LIMIT };
3867
+ const base2 = { default: DEFAULT_LIMIT, max: this.maxRows };
3578
3868
  if (!node) return base2;
3579
3869
  if (node.kind === graphql.Kind.VARIABLE) return { ...base2, variable: node.name.value };
3580
3870
  if (node.kind === graphql.Kind.INT) {
3581
3871
  const value = Number(node.value);
3582
3872
  if (value < 1) fail2("limit must be a positive integer", "invalid-limit");
3583
- return { ...base2, value: Math.min(value, MAX_LIMIT) };
3873
+ return { ...base2, value: Math.min(value, this.maxRows) };
3584
3874
  }
3585
3875
  fail2("limit must be an integer literal or a variable", "invalid-limit");
3586
3876
  }
@@ -4379,7 +4669,13 @@ var OperationLowerer = class {
4379
4669
  };
4380
4670
  function lowerOperation({ restricted, ctx }) {
4381
4671
  const lowerer = new OperationLowerer(ctx, restricted);
4382
- return lowerer.lowerRoots(restricted.definition, restricted.kind);
4672
+ const roots = lowerer.lowerRoots(restricted.definition, restricted.kind);
4673
+ if (restricted.readBudget === void 0) return roots;
4674
+ const root = roots[0];
4675
+ if (restricted.kind !== "query" || restricted.definition.selectionSet.selections.length !== 1 || roots.length !== 1 || root?.kind !== "select" || root.selection.relations.length > 0 || root.selection.aggregates.length > 0 || root.selection.cells !== void 0 || root.prefetch?.length) {
4676
+ fail2("@readBudget requires one flat select root without related selections, aggregates, cells, or prefetch", "invalid-read-budget");
4677
+ }
4678
+ return roots;
4383
4679
  }
4384
4680
  function isCellColumn(meta, name2) {
4385
4681
  if (!meta.cells) return false;
@@ -4438,6 +4734,19 @@ function parseDocuments({
4438
4734
  }
4439
4735
  return { documents: parsed, diagnostics };
4440
4736
  }
4737
+ function parseReadBudget(operation) {
4738
+ const directives = operation.directives?.filter((directive) => directive.name.value === "readBudget") ?? [];
4739
+ if (directives.length === 0) return void 0;
4740
+ const value = directives[0]?.arguments?.find((argument) => argument.name.value === "maxRows")?.value;
4741
+ if (operation.operation !== "query" || directives.length !== 1 || value?.kind !== graphql.Kind.INT) {
4742
+ throw new DocumentCompileError("@readBudget requires a literal maxRows on a query", "invalid-read-budget");
4743
+ }
4744
+ const maxRows = Number(value.value);
4745
+ if (!Number.isSafeInteger(maxRows) || maxRows < 1 || maxRows > MAX_PERSISTED_READ_ROWS) {
4746
+ throw new DocumentCompileError(`@readBudget(maxRows:) must be between 1 and ${MAX_PERSISTED_READ_ROWS}`, "invalid-read-budget");
4747
+ }
4748
+ return maxRows;
4749
+ }
4441
4750
  function unwrapType(node, variable) {
4442
4751
  let nullable = true;
4443
4752
  let list2 = false;
@@ -4598,6 +4907,7 @@ function restrictOperation({
4598
4907
  name: name2,
4599
4908
  kind: operation.operation === "mutation" ? "mutation" : "query",
4600
4909
  requires: parseRequires(operation),
4910
+ readBudget: parseReadBudget(operation),
4601
4911
  variables,
4602
4912
  definition: operation
4603
4913
  };
@@ -5638,6 +5948,118 @@ function bindNamedParameters({ sql, names }) {
5638
5948
  }
5639
5949
  return result;
5640
5950
  }
5951
+ var parser2;
5952
+ var functions = new Set(VIEW_QUERY_FUNCTION_ALLOWLIST);
5953
+ var scalarTypes = /* @__PURE__ */ new Set([
5954
+ "bool",
5955
+ "boolean",
5956
+ "int2",
5957
+ "int4",
5958
+ "int8",
5959
+ "integer",
5960
+ "bigint",
5961
+ "smallint",
5962
+ "numeric",
5963
+ "decimal",
5964
+ "float4",
5965
+ "float8",
5966
+ "real",
5967
+ "text",
5968
+ "varchar",
5969
+ "bpchar",
5970
+ "uuid",
5971
+ "date",
5972
+ "timestamp",
5973
+ "timestamptz",
5974
+ "time",
5975
+ "timetz",
5976
+ "interval",
5977
+ "json",
5978
+ "jsonb",
5979
+ "bytea"
5980
+ ]);
5981
+ var sqlValues = /* @__PURE__ */ new Set([
5982
+ "SVFOP_CURRENT_DATE",
5983
+ "SVFOP_CURRENT_TIME",
5984
+ "SVFOP_CURRENT_TIME_N",
5985
+ "SVFOP_CURRENT_TIMESTAMP",
5986
+ "SVFOP_CURRENT_TIMESTAMP_N",
5987
+ "SVFOP_LOCALTIME",
5988
+ "SVFOP_LOCALTIME_N",
5989
+ "SVFOP_LOCALTIMESTAMP",
5990
+ "SVFOP_LOCALTIMESTAMP_N",
5991
+ "SVFOP_CURRENT_ROLE",
5992
+ "SVFOP_CURRENT_USER",
5993
+ "SVFOP_USER",
5994
+ "SVFOP_SESSION_USER",
5995
+ "SVFOP_CURRENT_CATALOG",
5996
+ "SVFOP_CURRENT_SCHEMA"
5997
+ ]);
5998
+ async function validateManagedViewQueries({ canonical }) {
5999
+ for (const definition of [canonical, ...canonical.imports ?? []]) {
6000
+ for (const view of definition.views ?? []) {
6001
+ const fail4 = (message) => {
6002
+ throw new OrmDefinitionError(`managed view '${definition.namespace}/${view.view}': ${message}`);
6003
+ };
6004
+ parser2 ??= new pgParser.PgParser({ version: 17 });
6005
+ const parsed = await parser2.parse(view.query);
6006
+ if (parsed.error || !parsed.tree) fail4("invalid SELECT query");
6007
+ const statements = list(obj(parsed.tree).stmts);
6008
+ if (statements.length !== 1 || !obj(obj(statements[0]).stmt).SelectStmt) fail4("one SELECT query is required");
6009
+ validateTree({ tree: parsed.tree, schema: ormSchemaName(definition.namespace), enums: definition.enums.map((entry) => entry.name), fail: fail4 });
6010
+ }
6011
+ }
6012
+ }
6013
+ function pgCatalogName(parts) {
6014
+ if (parts.length === 1) return parts[0];
6015
+ if (parts.length === 2 && parts[0] === "pg_catalog") return parts[1];
6016
+ return void 0;
6017
+ }
6018
+ function reviewedFunctionName({ parts, format }) {
6019
+ return format === "COERCE_SQL_SYNTAX" && parts.length === 2 && parts[0] === "pg_catalog" && parts[1] === "position" ? "strpos" : pgCatalogName(parts);
6020
+ }
6021
+ function validateTree({ tree, ...scope }) {
6022
+ const pending = [tree];
6023
+ while (pending.length) {
6024
+ const value = pending.pop();
6025
+ if (Array.isArray(value)) {
6026
+ pending.push(...value);
6027
+ continue;
6028
+ }
6029
+ if (!value || typeof value !== "object") continue;
6030
+ const node = obj(value);
6031
+ for (const [kind, child] of Object.entries(node)) {
6032
+ validateNode({ kind, child, scope });
6033
+ pending.push(child);
6034
+ }
6035
+ }
6036
+ }
6037
+ function validateNode({ kind, child, scope }) {
6038
+ const { fail: fail4 } = scope;
6039
+ if (kind.endsWith("Stmt") && kind !== "SelectStmt") fail4("only SELECT statements are permitted");
6040
+ if (kind === "FuncCall") {
6041
+ const call = obj(child);
6042
+ const parts = strings(call.funcname);
6043
+ const name2 = reviewedFunctionName({ parts, format: call.funcformat });
6044
+ if (!name2 || !functions.has(name2)) fail4(`only explicitly allowlisted pg_catalog functions are permitted (found '${parts.join(".")}')`);
6045
+ }
6046
+ if (kind === "typeName" || kind === "TypeName") validateType({ node: obj(child), ...scope });
6047
+ if (kind === "A_Expr" && pgCatalogName(strings(obj(child).name)) === void 0) fail4("only pg_catalog operators are permitted");
6048
+ if (kind === "SortBy" && list(obj(child).useOp).length && pgCatalogName(strings(obj(child).useOp)) === void 0) fail4("only pg_catalog sort operators are permitted");
6049
+ if (kind === "SQLValueFunction" && !sqlValues.has(String(obj(child).op))) fail4("unsupported SQL value expression");
6050
+ if (kind === "ParamRef") fail4("view queries cannot contain parameters");
6051
+ if (kind === "A_Indirection" && list(obj(child).indirection).some((entry) => !obj(entry).A_Indices)) {
6052
+ fail4("composite field notation is not permitted in managed views");
6053
+ }
6054
+ }
6055
+ function validateType({ node, schema, enums, fail: fail4 }) {
6056
+ const parts = strings(node.names);
6057
+ const builtin = pgCatalogName(parts);
6058
+ const managedEnum = parts.length === 1 && enums.includes(parts[0]) || parts.length === 2 && parts[0] === schema && enums.includes(parts[1]);
6059
+ if (node.setof || node.pct_type || !managedEnum && (!builtin || !scalarTypes.has(builtin))) {
6060
+ fail4(`casts may only use supported pg_catalog scalar types or declared enums (found '${parts.join(".")}')`);
6061
+ }
6062
+ }
5641
6063
 
5642
6064
  // src/sql/operations.ts
5643
6065
  function isSqlOperationDocument(path, contents) {
@@ -5653,7 +6075,13 @@ function isSqlOperationDocument(path, contents) {
5653
6075
  async function compileOperationDocuments(input) {
5654
6076
  const sqlDocuments = input.documents.filter((d) => isSqlOperationDocument(d.path, d.contents));
5655
6077
  const result = compileNamespace({ ...input, documents: input.documents.filter((d) => !isSqlOperationDocument(d.path, d.contents)) });
5656
- if (!result.ok || !sqlDocuments.length) return result;
6078
+ if (!result.ok) return result;
6079
+ const viewDiagnostics = await managedViewDiagnostics(input.canonical);
6080
+ if (viewDiagnostics.length) return { ok: false, diagnostics: [...result.diagnostics, ...viewDiagnostics] };
6081
+ if (!sqlDocuments.length) return result;
6082
+ return compileSqlDocuments({ input, result, sqlDocuments });
6083
+ }
6084
+ async function compileSqlDocuments({ input, result, sqlDocuments }) {
5657
6085
  for (const document of sqlDocuments) {
5658
6086
  try {
5659
6087
  const definition = defineOperation(JSON.parse(document.contents));
@@ -5747,6 +6175,18 @@ async function compileOperationDocuments(input) {
5747
6175
  result.manifest.opsHash = result.artifact.opsHash;
5748
6176
  return { ...result, artifact: normalizeIr(result.artifact) };
5749
6177
  }
6178
+ async function managedViewDiagnostics(canonical) {
6179
+ try {
6180
+ await validateManagedViewQueries({ canonical });
6181
+ return [];
6182
+ } catch (error) {
6183
+ return [{
6184
+ severity: "error",
6185
+ code: "invalid-view-query",
6186
+ message: error instanceof Error ? error.message : "invalid managed view query"
6187
+ }];
6188
+ }
6189
+ }
5750
6190
  var parameterName = zod.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(63).refine((value) => !["__proto__", "prototype", "constructor"].includes(value), "reserved parameter name");
5751
6191
  var parameter = zod.z.discriminatedUnion("type", [
5752
6192
  zod.z.object({ type: zod.z.literal("text"), value: zod.z.string().nullable() }).strict(),
@@ -5886,6 +6326,7 @@ exports.typeNameForTable = typeNameForTable;
5886
6326
  exports.validateAppendInput = validateAppendInput;
5887
6327
  exports.validateBoolExpInput = validateBoolExpInput;
5888
6328
  exports.validateInsertInput = validateInsertInput;
6329
+ exports.validateManagedViewQueries = validateManagedViewQueries;
5889
6330
  exports.validateOnConflictInput = validateOnConflictInput;
5890
6331
  exports.validateOrderByInput = validateOrderByInput;
5891
6332
  exports.validateSelectColumns = validateSelectColumns;