@sequenceholdings/orm 2.5.0 → 2.6.1

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/README.md CHANGED
@@ -131,6 +131,29 @@ Execute uses the `/_data/v2` endpoint by default. Set
131
131
  `SEQUENCE_ORM_ATLAS_EXECUTE_V2=1` to opt into Atlas's `/api/data/v2` endpoint.
132
132
  This client rollout switch does not bypass server feature flags or authorization.
133
133
 
134
+ ## Default read-only SQL (planned 2.6.0)
135
+
136
+ With the matching SDK and Atlas rollout, every active v2 namespace supports
137
+ runtime-supplied SQL without an authored operation or Function:
138
+
139
+ ```ts
140
+ const orm = createArtifactOrmExecutor({ namespace: 'lending' })
141
+ const result = await orm.sql({
142
+ sql: `SELECT l.id, c.name FROM lending.loans l
143
+ JOIN party.customers c ON c.id = l."customerId"
144
+ WHERE c.type = :type`,
145
+ parameters: { type: { type: 'text', value: 'retail' } },
146
+ })
147
+ ```
148
+
149
+ Functions use `createFunctionOrmExecutor({ request, baseUrl, namespace })` and
150
+ the same `sql()` method. Namespace access, object policies, foreign exports,
151
+ delegated table scopes and optional consumer contracts still apply. Queries are
152
+ read-only, restricted to supported SELECT syntax, and capped at 1,000 rows / 8 MiB.
153
+ Separate protected execution targets cannot be joined. Existing registered
154
+ operations remain supported; supply a manifest when executing them by name.
155
+ Source versions alone do not prove package publication or server availability.
156
+
134
157
  ## Public exports
135
158
 
136
159
  - `@sequenceholdings/orm/authoring` — namespace, table, policy, and view DSL
package/dist/cli.cjs CHANGED
@@ -1458,6 +1458,9 @@ function normalizeCanonical(definition) {
1458
1458
  return normalized;
1459
1459
  }
1460
1460
 
1461
+ // src/client/sql.ts
1462
+ var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
1463
+
1461
1464
  // src/ir/index.ts
1462
1465
  var IR_VERSION = 5;
1463
1466
  var LEGACY_IR_VERSION = 1;
@@ -1791,7 +1794,8 @@ var compiledOperationSchema = zod.z.object({
1791
1794
  }).superRefine((operation, ctx) => {
1792
1795
  if (operation.language === "sql") {
1793
1796
  const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
1794
- if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !operation.requires?.capability) {
1797
+ const builtin = operation.name === "BuiltinSqlRead" && operation.opHash === BUILTIN_SQL_READ_HASH && operation.requires === null;
1798
+ if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !builtin && !operation.requires?.capability) {
1795
1799
  ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
1796
1800
  }
1797
1801
  } else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
@@ -5173,9 +5177,9 @@ function compilePredIrToSql(pred, options = {}) {
5173
5177
  case "cmp":
5174
5178
  return compileCmp(pred.op, pred.column, pred.value, options);
5175
5179
  case "capability":
5176
- return `(${capabilityExpression(pred.key, pred.namespace ?? options.namespace)})`;
5180
+ return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(pred.key, pred.namespace ?? options.namespace)})`;
5177
5181
  case "role":
5178
- return `(${roleExpression(pred.key, pred.namespace ?? options.namespace)})`;
5182
+ return `(${options.statementClaimChecks ? "SELECT " : ""}${roleExpression(pred.key, pred.namespace ?? options.namespace)})`;
5179
5183
  case "exists":
5180
5184
  if (options.exists) return options.exists(pred);
5181
5185
  throw new OrmDefinitionError("synced view read policy cannot use 'exists' without a relationship resolver");
@@ -5283,7 +5287,8 @@ function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
5283
5287
  const { ctx, diagnostics } = buildCompileContext(canonical);
5284
5288
  if (diagnostics.some((d) => d.severity === "error")) throw new Error(diagnostics.map((d) => d.message).join("; "));
5285
5289
  const identity = sqlHash(`ontology-sql-v1\0${computeSchemaHash(canonical)}\0${executionTarget}`);
5286
- const refOf = (meta) => `${meta.namespace ?? canonical.namespace}/${meta.table}`;
5290
+ const logicalNames = new Map(Object.entries(ctx.tables).map(([key, meta]) => [meta, key]));
5291
+ const refOf = (meta) => `${meta.namespace ?? canonical.namespace}/${logicalNames.get(meta)}`;
5287
5292
  const definitions = [canonical, ...canonical.imports ?? []];
5288
5293
  const internal = new Set(definitions.flatMap((owner) => [
5289
5294
  ...owner.tables.filter((t2) => t2.internal).map((t2) => `${owner.namespace}/${t2.table}`),
@@ -5359,15 +5364,22 @@ function only(node, keys) {
5359
5364
  var parser;
5360
5365
  var SQL_TYPES = ["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"];
5361
5366
  var pgType = (type) => type === "double" ? "double precision" : SQL_TYPES.some((t2) => t2 === type) ? type : fail3("unsupported SQL type");
5362
- async function compileOntologySql({ catalog, sql: sql4, parameterTypes = [], maxRows = 1e3 }) {
5363
- if (!Number.isInteger(maxRows) || maxRows < 1 || maxRows > 1e4 || Buffer.byteLength(sql4) > 65536) fail3("SQL limit exceeded");
5367
+ async function parseSelect(sql4) {
5368
+ if (Buffer.byteLength(sql4) > 65536) fail3("SQL limit exceeded");
5364
5369
  parser ??= new pgParser.PgParser({ version: 17 });
5365
5370
  const parsed = await parser.parse(sql4);
5366
5371
  if (parsed.error || !parsed.tree) fail3("invalid SQL");
5367
5372
  const statements = list(obj(parsed.tree).stmts);
5368
5373
  if (statements.length !== 1) fail3("one SQL SELECT is required");
5374
+ const statement = obj(obj(statements[0]).stmt);
5375
+ if (!statement.SelectStmt) fail3("one SQL SELECT is required");
5376
+ return statement;
5377
+ }
5378
+ async function compileOntologySql({ catalog, sql: sql4, parameterTypes = [], maxRows = 1e3 }) {
5379
+ if (!Number.isInteger(maxRows) || maxRows < 1 || maxRows > 1e4 || Buffer.byteLength(sql4) > 65536) fail3("SQL limit exceeded");
5380
+ const statement = await parseSelect(sql4);
5369
5381
  const emitter = new SqlEmitter({ catalog, parameterTypes });
5370
- const result = emitter.select(obj(obj(statements[0]).stmt), { relations: [], ctes: /* @__PURE__ */ new Map() });
5382
+ const result = emitter.select(statement, { relations: [], ctes: /* @__PURE__ */ new Map() });
5371
5383
  if (emitter.used.size !== parameterTypes.length) fail3("SQL parameters must be used exactly as declared");
5372
5384
  if (!emitter.read.size) fail3("SQL operation must read an ontology object");
5373
5385
  return {
@@ -7786,19 +7798,19 @@ function compileComparison(op, left, right, columnTypes) {
7786
7798
  }
7787
7799
  return `${compileOperand(left, right, columnTypes)} ${SQL_COMPARE_OPS[op]} ${compileOperand(right, left, columnTypes)}`;
7788
7800
  }
7789
- function compilePredicate(predicate, columnTypes) {
7801
+ function compilePredicate(predicate, columnTypes, options = {}) {
7790
7802
  switch (predicate.kind) {
7791
7803
  case "and":
7792
7804
  case "or": {
7793
- const joined = predicate.operands.map((operand) => compilePredicate(operand, columnTypes)).join(` ${predicate.kind.toUpperCase()} `);
7805
+ const joined = predicate.operands.map((operand) => compilePredicate(operand, columnTypes, options)).join(` ${predicate.kind.toUpperCase()} `);
7794
7806
  return `(${joined})`;
7795
7807
  }
7796
7808
  case "not":
7797
- return `(NOT ${compilePredicate(predicate.operand, columnTypes)})`;
7809
+ return `(NOT ${compilePredicate(predicate.operand, columnTypes, options)})`;
7798
7810
  case "compare":
7799
7811
  return `(${compileComparison(predicate.op, predicate.left, predicate.right, columnTypes)})`;
7800
7812
  case "capability":
7801
- return `(${capabilityExpression(predicate.key)})`;
7813
+ return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(predicate.key)})`;
7802
7814
  }
7803
7815
  }
7804
7816