@sequenceholdings/orm 2.8.1 → 2.8.3

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/cli.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  var promises = require('fs/promises');
4
4
  var module$1 = require('module');
5
5
  var path = require('path');
6
+ var consumers = require('stream/consumers');
6
7
  var url = require('url');
7
8
  var jiti = require('jiti');
8
9
  var crypto = require('crypto');
@@ -5464,8 +5465,8 @@ var SqlEmitter = class {
5464
5465
  }
5465
5466
  const result = node.op === "SETOP_UNION" ? this.union(node, scope) : this.projection(node, scope);
5466
5467
  const { columns } = result;
5467
- let text4 = `${ctes.length ? `WITH ${ctes.join(", ")} ` : ""}${result.text}`;
5468
- if (list(node.sortClause).length) text4 += ` ORDER BY ${list(node.sortClause).map((n) => {
5468
+ let text5 = `${ctes.length ? `WITH ${ctes.join(", ")} ` : ""}${result.text}`;
5469
+ if (list(node.sortClause).length) text5 += ` ORDER BY ${list(node.sortClause).map((n) => {
5469
5470
  const sort = obj(obj(n).SortBy);
5470
5471
  only(sort, ["node", "sortby_dir", "sortby_nulls", "location"]);
5471
5472
  const direction = sort.sortby_dir === "SORTBY_DESC" ? "DESC" : sort.sortby_dir === "SORTBY_ASC" || sort.sortby_dir === "SORTBY_DEFAULT" ? "ASC" : fail3("unsupported SQL sort");
@@ -5476,10 +5477,10 @@ var SqlEmitter = class {
5476
5477
  return `${projected.length === 1 ? quoteIdentifier(projected[0].name) : this.expr(value, scope).text} ${direction}${nulls}`;
5477
5478
  }).join(", ")}`;
5478
5479
  for (const [key, keyword] of [["limitCount", "LIMIT"], ["limitOffset", "OFFSET"]]) {
5479
- if (node[key]) text4 += ` ${keyword} ${this.expr(obj(node[key]), scope).text}`;
5480
+ if (node[key]) text5 += ` ${keyword} ${this.expr(obj(node[key]), scope).text}`;
5480
5481
  }
5481
5482
  this.depth--;
5482
- return { text: text4, columns: resolveUnknown ? columns.map((c) => c.type === "unknown" ? { ...c, type: "text" } : c) : columns };
5483
+ return { text: text5, columns: resolveUnknown ? columns.map((c) => c.type === "unknown" ? { ...c, type: "text" } : c) : columns };
5483
5484
  }
5484
5485
  union(node, scope) {
5485
5486
  for (const key of ["targetList", "fromClause", "whereClause", "groupClause", "havingClause"]) {
@@ -5520,11 +5521,11 @@ var SqlEmitter = class {
5520
5521
  }
5521
5522
  }
5522
5523
  if (!targets.length || targets.length > 256) fail3("invalid SQL projection");
5523
- let text4 = `SELECT ${targets.join(", ")}${from ? ` FROM ${from}` : ""}`;
5524
- if (node.whereClause) text4 += ` WHERE ${this.expr(obj(node.whereClause), scope).text}`;
5525
- if (list(node.groupClause).length) text4 += ` GROUP BY ${list(node.groupClause).map((n) => this.expr(obj(n), scope).text).join(", ")}`;
5526
- if (node.havingClause) text4 += ` HAVING ${this.expr(obj(node.havingClause), scope).text}`;
5527
- return { text: text4, columns };
5524
+ let text5 = `SELECT ${targets.join(", ")}${from ? ` FROM ${from}` : ""}`;
5525
+ if (node.whereClause) text5 += ` WHERE ${this.expr(obj(node.whereClause), scope).text}`;
5526
+ if (list(node.groupClause).length) text5 += ` GROUP BY ${list(node.groupClause).map((n) => this.expr(obj(n), scope).text).join(", ")}`;
5527
+ if (node.havingClause) text5 += ` HAVING ${this.expr(obj(node.havingClause), scope).text}`;
5528
+ return { text: text5, columns };
5528
5529
  }
5529
5530
  from(node, scope) {
5530
5531
  this.budget();
@@ -6007,7 +6008,7 @@ function generateSqlOperations({ artifact }) {
6007
6008
  lines.push(
6008
6009
  `export type ${prefix}Variables = SqlQueryVariables`,
6009
6010
  `export type ${prefix}Result = SqlQueryResult`,
6010
- `export const ${prefix}: OperationReference<${prefix}Variables, ${prefix}Result> = ${JSON.stringify({ namespace: artifact.namespace, hash: operation.opHash })}`,
6011
+ `export const ${prefix}: OperationReference<${prefix}Variables, ${prefix}Result> = ${JSON.stringify({ namespace: artifact.namespace, name: operation.name, kind: operation.kind })}`,
6011
6012
  ""
6012
6013
  );
6013
6014
  continue;
@@ -6022,7 +6023,7 @@ function generateSqlOperations({ artifact }) {
6022
6023
  ${variables}
6023
6024
  }`,
6024
6025
  `export type ${prefix}Result = { columns: Array<{ name: string; type: string; nullable: boolean }>; rows: Array<[${row}]>; truncated: boolean }`,
6025
- `export const ${prefix}: OperationReference<${prefix}Variables, ${prefix}Result> = ${JSON.stringify({ namespace: artifact.namespace, hash: operation.opHash })}`,
6026
+ `export const ${prefix}: OperationReference<${prefix}Variables, ${prefix}Result> = ${JSON.stringify({ namespace: artifact.namespace, name: operation.name, kind: operation.kind })}`,
6026
6027
  ""
6027
6028
  );
6028
6029
  }
@@ -6812,29 +6813,23 @@ var CodegenGqlError = class extends Error {
6812
6813
  this.name = "CodegenGqlError";
6813
6814
  }
6814
6815
  };
6815
- var MANIFEST_VERSION = 1;
6816
- var OP_HASH_RE = /^sha256:[0-9a-f]{64}$/;
6816
+ var MANIFEST_VERSION = 2;
6817
6817
  var GRAPHQL_NAME_RE = /^[_A-Za-z][_0-9A-Za-z]*$/;
6818
6818
  var manifestRequiresSchema = zod.z.object({
6819
6819
  capability: zod.z.string().min(1).optional(),
6820
6820
  role: zod.z.string().min(1).optional()
6821
6821
  }).nullable();
6822
6822
  var manifestOperationSchema = zod.z.object({
6823
- hash: zod.z.string().regex(OP_HASH_RE),
6824
6823
  kind: zod.z.enum(["query", "mutation"]),
6825
6824
  requires: manifestRequiresSchema
6826
6825
  });
6827
6826
  var operationsManifestSchema = zod.z.object({
6828
- manifestVersion: zod.z.literal(MANIFEST_VERSION),
6829
- schemaHash: zod.z.string().min(1),
6830
- opsHash: zod.z.string().regex(OP_HASH_RE),
6827
+ manifestVersion: zod.z.union([zod.z.literal(1), zod.z.literal(MANIFEST_VERSION)]),
6831
6828
  operations: zod.z.record(zod.z.string().regex(GRAPHQL_NAME_RE), manifestOperationSchema)
6832
6829
  });
6833
6830
  function buildOperationsManifest({
6834
- schemaHash,
6835
6831
  operations
6836
6832
  }) {
6837
- if (schemaHash.length === 0) throw new CodegenGqlError("schemaHash must be a non-empty string.");
6838
6833
  const sorted = [...operations].sort((a, b) => a.name.localeCompare(b.name));
6839
6834
  const seen = /* @__PURE__ */ new Set();
6840
6835
  const entries = sorted.map((op) => {
@@ -6845,20 +6840,14 @@ function buildOperationsManifest({
6845
6840
  throw new CodegenGqlError(`Duplicate operation name "${op.name}" \u2014 operation names must be unique per namespace.`);
6846
6841
  }
6847
6842
  seen.add(op.name);
6848
- if (!OP_HASH_RE.test(op.hash)) {
6849
- throw new CodegenGqlError(`Operation "${op.name}" has malformed hash "${op.hash}" (expected sha256:<64 hex>).`);
6850
- }
6851
- return { name: op.name, hash: op.hash, kind: op.kind, requires: normalizeRequires(op.requires) };
6843
+ return { name: op.name, kind: op.kind, requires: normalizeRequires(op.requires) };
6852
6844
  });
6853
- const opsHash = `sha256:${crypto.createHash("sha256").update(stableJson(entries)).digest("hex")}`;
6854
6845
  const operationsRecord = {};
6855
6846
  for (const entry of entries) {
6856
- operationsRecord[entry.name] = { hash: entry.hash, kind: entry.kind, requires: entry.requires };
6847
+ operationsRecord[entry.name] = { kind: entry.kind, requires: entry.requires };
6857
6848
  }
6858
6849
  return {
6859
6850
  manifestVersion: MANIFEST_VERSION,
6860
- schemaHash,
6861
- opsHash,
6862
6851
  operations: operationsRecord
6863
6852
  };
6864
6853
  }
@@ -7133,8 +7122,8 @@ function renderEnum(name2, values) {
7133
7122
  ${values.map((value) => ` ${value}`).join("\n")}
7134
7123
  }`;
7135
7124
  }
7136
- function descriptionLines(text4, indent) {
7137
- const escaped = text4.replace(/"""/g, '\\"""');
7125
+ function descriptionLines(text5, indent) {
7126
+ const escaped = text5.replace(/"""/g, '\\"""');
7138
7127
  return [`${indent}"""`, ...escaped.split("\n").map((line) => `${indent}${line}`), `${indent}"""`];
7139
7128
  }
7140
7129
  var PATTERN_COMPARISON_TYPES = /* @__PURE__ */ new Set(["String", "Int", "bigint", "uuid"]);
@@ -10305,7 +10294,7 @@ async function readMigrationSql(dir, entry) {
10305
10294
  throw new OrmDefinitionError("missing migration file", path$1);
10306
10295
  });
10307
10296
  }
10308
- var checksumOf = (text4) => crypto.createHash("sha256").update(text4).digest("hex");
10297
+ var checksumOf = (text5) => crypto.createHash("sha256").update(text5).digest("hex");
10309
10298
  var migrationName = (ordinal, contentHash) => `${pad(ordinal)}_${contentHash.slice(0, 12)}`;
10310
10299
  function renderMigrationSql({
10311
10300
  name: name2,
@@ -10674,10 +10663,10 @@ function createOrmMigrationExport({ schemaHash, payload }) {
10674
10663
  return { ...contents, checksum: checksum(contents) };
10675
10664
  }
10676
10665
  function renderOrmMigrationExport(exported) {
10677
- const text4 = `${JSON.stringify(exported, null, 2)}
10666
+ const text5 = `${JSON.stringify(exported, null, 2)}
10678
10667
  `;
10679
- if (Buffer.byteLength(text4, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
10680
- return text4;
10668
+ if (Buffer.byteLength(text5, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
10669
+ return text5;
10681
10670
  }
10682
10671
 
10683
10672
  // src/compiler-gql/role-warnings.ts
@@ -10897,7 +10886,7 @@ function renderImportScript({
10897
10886
  const procedure = renderProcedure({ targetSql, sourceSql, mapped, keys, onConflict, batchSize });
10898
10887
  const call = `CALL pg_temp.seq_orm_import(${resume.join(", ")});`;
10899
10888
  const omittedLine = omitted.length > 0 ? `-- Omitted columns keep their database default or NULL: ${omitted.join(", ")}` : "-- Every column is mapped.";
10900
- const text4 = [
10889
+ const text5 = [
10901
10890
  "-- Sequence ORM data import",
10902
10891
  `-- namespace: ${namespace}`,
10903
10892
  `-- target: ${schemaName}.${table.table}`,
@@ -10921,7 +10910,7 @@ function renderImportScript({
10921
10910
  call,
10922
10911
  ""
10923
10912
  ].join("\n");
10924
- return { probeSql, text: text4 };
10913
+ return { probeSql, text: text5 };
10925
10914
  }
10926
10915
  function renderProbe({
10927
10916
  sourceSql,
@@ -11294,10 +11283,10 @@ async function readSpec(flags) {
11294
11283
  if (flags["--table"] || flags["--from"] || flags["--map"]) {
11295
11284
  return { error: "--spec replaces --table, --from, and --map" };
11296
11285
  }
11297
- const text4 = await promises.readFile(path.resolve(flags["--spec"]), "utf8");
11286
+ const text5 = await promises.readFile(path.resolve(flags["--spec"]), "utf8");
11298
11287
  let parsed;
11299
11288
  try {
11300
- parsed = JSON.parse(text4);
11289
+ parsed = JSON.parse(text5);
11301
11290
  } catch {
11302
11291
  return { error: `--spec ${flags["--spec"]} is not valid JSON` };
11303
11292
  }
@@ -11377,6 +11366,7 @@ var USAGE = `usage:
11377
11366
  --no-wait returns once the apply is queued
11378
11367
  seq-studio orm execute <operation> [dir] --variables-file <file> -e <env>
11379
11368
  execute one named persisted operation from this checkout's manifest as the signed-in caller
11369
+ variables-file accepts - or /dev/stdin to read JSON from stdin until EOF
11380
11370
  seq-studio orm execute <namespace> <operation> -e <env> [--variables-file <file>] [--var <name>=<value>]...
11381
11371
  execute the deployed version's operation by name (no checkout; seq-studio only)
11382
11372
  seq-studio orm diff [dir] write/verify the committed migration standalone (--check is the offline CI gate; --allow-destructive consents; --rebase records a v1 -> v2 conversion as a verified no-op)
@@ -11657,21 +11647,21 @@ async function generateCommand(rest) {
11657
11647
  schema_snapshot: workspace.tipSnapshot,
11658
11648
  ...migration ? { migration } : {}
11659
11649
  } });
11660
- const text4 = renderOrmMigrationExport(exported);
11650
+ const text5 = renderOrmMigrationExport(exported);
11661
11651
  const path$1 = path.join(dir, ORM_MIGRATION_EXPORT_FILE);
11662
11652
  if (check) {
11663
11653
  const committed = await promises.readFile(path$1, "utf8").catch((error) => {
11664
11654
  if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
11665
11655
  throw error;
11666
11656
  });
11667
- if (committed !== text4) {
11657
+ if (committed !== text5) {
11668
11658
  console.error(`${ORM_MIGRATION_EXPORT_FILE} is missing or stale; run seq-studio orm generate ${dir} --migration-export and commit it`);
11669
11659
  return 1;
11670
11660
  }
11671
11661
  console.log(`${ORM_MIGRATION_EXPORT_FILE} matches the current definitions, operations, and committed migration`);
11672
11662
  return 0;
11673
11663
  }
11674
- await promises.writeFile(path$1, text4);
11664
+ await promises.writeFile(path$1, text5);
11675
11665
  console.log(`wrote ${ORM_MIGRATION_EXPORT_FILE} (${exported.checksum.slice(0, 12)})`);
11676
11666
  }
11677
11667
  await writeGenerateOutputs(dir, compiled.project);
@@ -11688,11 +11678,10 @@ async function writeGenerateOutputs(dir, project) {
11688
11678
  `);
11689
11679
  const operations = Object.entries(manifest.operations).map(([name2, op]) => ({
11690
11680
  name: name2,
11691
- hash: op.opHash,
11692
11681
  kind: op.kind,
11693
11682
  requires: op.requires
11694
11683
  }));
11695
- const manifestFile = buildOperationsManifest({ schemaHash: manifest.schemaHash, operations });
11684
+ const manifestFile = buildOperationsManifest({ operations });
11696
11685
  await promises.writeFile(path.join(dir, OPERATIONS_MANIFEST_FILE), `${JSON.stringify(manifestFile, null, 2)}
11697
11686
  `);
11698
11687
  await promises.writeFile(path.join(dir, TYPE_POLICIES_FILE), generateTypePolicies(loaded.canonical));
@@ -11763,7 +11752,8 @@ function parseExecuteArgs(rest) {
11763
11752
  async function readExecuteVariables(variablesFile) {
11764
11753
  let parsed;
11765
11754
  try {
11766
- parsed = JSON.parse(await promises.readFile(path.resolve(variablesFile), "utf8"));
11755
+ const contents = variablesFile === "-" || variablesFile === "/dev/stdin" ? await consumers.text(process.stdin) : await promises.readFile(path.resolve(variablesFile), "utf8");
11756
+ parsed = JSON.parse(contents);
11767
11757
  } catch (error) {
11768
11758
  throw new OrmDefinitionError(
11769
11759
  `could not read JSON variables from ${variablesFile}: ${error instanceof Error ? error.message : String(error)}`
@@ -11805,13 +11795,12 @@ async function executeV2Command(rest) {
11805
11795
  const namespace = loaded.canonical.namespace;
11806
11796
  let response;
11807
11797
  try {
11808
- response = await apiRequestStrict("POST", `${DATA_ENDPOINT_PREFIX}/${namespace}`, { op: selected.hash, variables });
11798
+ response = await apiRequestStrict("POST", `${DATA_ENDPOINT_PREFIX}/${namespace}`, { op: `${selected.kind}:${operation}`, expectedKind: selected.kind, variables });
11809
11799
  } catch (error) {
11810
11800
  if (!(error instanceof AtlasRequestError) || error.status !== 404) throw error;
11811
11801
  const diagnosis = await diagnoseUnknownOperation({
11812
11802
  namespace,
11813
11803
  operation,
11814
- localHash: selected.hash,
11815
11804
  retry: `seq-studio orm execute ${namespace} ${operation}${env ? ` -e ${env}` : ""} --variables-file ${variablesFile}`
11816
11805
  }).catch(() => null);
11817
11806
  throw diagnosis ? new OrmDefinitionError(diagnosis) : error;
@@ -11819,7 +11808,7 @@ async function executeV2Command(rest) {
11819
11808
  console.log(JSON.stringify(response, null, 2));
11820
11809
  return 0;
11821
11810
  }
11822
- async function diagnoseUnknownOperation({ namespace, operation, localHash, retry }) {
11811
+ async function diagnoseUnknownOperation({ namespace, operation, retry }) {
11823
11812
  const encoded = encodeURIComponent(namespace);
11824
11813
  const listing = await apiRequest(
11825
11814
  "GET",
@@ -11842,15 +11831,10 @@ async function diagnoseUnknownOperation({ namespace, operation, localHash, retry
11842
11831
  if (!deployed) {
11843
11832
  return `operation ${operation} is not in ${namespace}'s deployed version ${listing.schema_version_id}. Apply this checkout to deploy it (seq-studio orm apply), or list the deployed operations: seq-studio orm describe ${namespace} --operations`;
11844
11833
  }
11845
- if (deployed.op_hash === localHash) return null;
11846
11834
  return [
11847
- `operation ${operation}: this checkout's ${OPERATIONS_MANIFEST_FILE} does not match ${namespace}'s deployed version.`,
11848
- ` local hash: ${localHash}`,
11849
- ` deployed hash: ${deployed.op_hash}`,
11850
- ` deployed version: ${listing.schema_version_id}`,
11851
- "Run the deployed operation by name (no checkout needed):",
11852
- ` ${retry}`,
11853
- "Or bring the checkout up to date (git pull, then seq-studio orm generate) and retry."
11835
+ `operation ${operation} exists in ${namespace}'s deployed version ${listing.schema_version_id}, but its guarded name was refused.`,
11836
+ "Update Atlas to a runtime that supports guarded operation names, or retry if the operation set changed during lookup.",
11837
+ ` ${retry}`
11854
11838
  ].join("\n");
11855
11839
  }
11856
11840
  async function validateV2Command(dir) {