@sequenceholdings/orm 2.7.1 → 2.8.2

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/client.d.cts CHANGED
@@ -86,7 +86,10 @@ declare class TableQuery<Row extends Record<string, unknown>, Result = Row> {
86
86
  private filter;
87
87
  }
88
88
 
89
+ type OperationSelection = 'name';
90
+
89
91
  /** Runtime SQL inputs are values, never interpolated into the submitted SQL. */
92
+ declare const BUILTIN_SQL_READ_NAME = "BuiltinSqlRead";
90
93
  declare const BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
91
94
  type SqlQueryParameter = {
92
95
  type: 'text' | 'uuid' | 'date' | 'timestamptz' | 'numeric' | 'bigint';
@@ -115,9 +118,19 @@ interface SqlQueryResult {
115
118
  truncated: boolean;
116
119
  }
117
120
 
121
+ /**
122
+ * Persisted-operation client for the v2 data plane. The wire carries only
123
+ * `{ op: <name>, variables, idempotencyKey?, expectedSourceGeneration? }`. Runtime SQL contracts accept SQL in variables;
124
+ * GraphQL and fixed SQL operations keep their documents server-side. This runtime
125
+ * is deliberately free of node builtins and third-
126
+ * party deps (no @apollo/client import): Apollo integration happens through a
127
+ * fetch-compatible shim (`createOrmFetch`) handed to `HttpLink({ fetch })`.
128
+ */
129
+
118
130
  /** One entry of `operations.manifest.json` (generated by `orm generate`). */
119
131
  interface ManifestOperation {
120
- readonly hash: string;
132
+ /** Legacy manifests only; requests use the operation name. */
133
+ readonly hash?: string;
121
134
  readonly kind: 'query' | 'mutation';
122
135
  readonly requires: {
123
136
  readonly capability?: string;
@@ -125,7 +138,8 @@ interface ManifestOperation {
125
138
  } | null;
126
139
  }
127
140
  interface OperationsManifest {
128
- readonly schemaHash: string;
141
+ /** Legacy manifest metadata; absent from newly generated clients. */
142
+ readonly schemaHash?: string;
129
143
  readonly opsHash?: string;
130
144
  readonly operations: Readonly<Record<string, ManifestOperation>>;
131
145
  }
@@ -134,6 +148,8 @@ interface OperationExecutorConfig {
134
148
  baseUrl: string;
135
149
  namespace: string;
136
150
  manifest?: OperationsManifest;
151
+ /** Optional compatibility setting; only stable name selection is supported. */
152
+ operationSelection?: OperationSelection;
137
153
  /** App-user / session bearer → `Authorization: Bearer`. */
138
154
  getToken?: () => Promise<string | null> | string | null;
139
155
  /** Delegated, attenuated function token → the `ORM_DATA_TOKEN_HEADER`. */
@@ -147,7 +163,7 @@ interface OperationExecutionOptions {
147
163
  expectedSourceGeneration?: string;
148
164
  }
149
165
  interface OperationExecutor {
150
- /** Execute a manifest operation by name (or a raw `sha256:` hash). */
166
+ /** Execute a registered operation by its stable name. */
151
167
  execute<TData = Record<string, unknown>>(op: string, variables?: Record<string, unknown>, options?: OperationExecutionOptions): Promise<TData>;
152
168
  }
153
169
  /** Additive factory result; existing host wrappers implementing OperationExecutor remain valid. */
@@ -178,13 +194,19 @@ interface TypedReadReceiptOperationExecutor extends TypedOperationExecutor {
178
194
  }
179
195
  type TypedReadReceiptSqlOperationExecutor = TypedReadReceiptOperationExecutor & ReadReceiptSqlOperationExecutor;
180
196
  /** Generated handle identifies the registered contract; optional types are phantom. */
181
- interface OperationReference<TVariables extends Record<string, unknown>, TData> {
197
+ type OperationReference<TVariables extends Record<string, unknown>, TData> = {
182
198
  readonly namespace: string;
183
- readonly hash: string;
184
199
  readonly variables?: TVariables;
185
200
  readonly result?: TData;
186
- }
187
- declare function createOperationExecutor({ baseUrl, namespace, manifest, getToken, getDataToken, fetchImpl, }: OperationExecutorConfig): TypedReadReceiptSqlOperationExecutor;
201
+ readonly kind?: 'query' | 'mutation';
202
+ } & ({
203
+ readonly name: string;
204
+ readonly hash?: string;
205
+ } | {
206
+ readonly hash: string;
207
+ readonly name?: string;
208
+ });
209
+ declare function createOperationExecutor({ baseUrl, namespace, manifest, operationSelection, getToken, getDataToken, fetchImpl, }: OperationExecutorConfig): TypedReadReceiptSqlOperationExecutor;
188
210
  /**
189
211
  * Configure the process-wide executor the generated `db<Name>` server
190
212
  * functions call through. Call once at startup (server-side); browser apps
@@ -200,7 +222,7 @@ declare function executeOperation<TData = Record<string, unknown>>({ op, variabl
200
222
  /**
201
223
  * A fetch-compatible function for `new HttpLink({ uri: '/unused', fetch: createOrmFetch(...) })`.
202
224
  * Intercepts Apollo's GraphQL POST, swaps the body for the persisted-op
203
- * envelope (`{ op: <hash>, variables }`) resolved via the manifest's
225
+ * envelope (`{ op: <name>, variables }`) resolved via the manifest's
204
226
  * operationName, rewrites the URL to the data plane, and attaches auth.
205
227
  * The GraphQL-spec response body passes through untouched, so InMemoryCache
206
228
  * and error links behave exactly as they do against a GraphQL server.
@@ -213,6 +235,7 @@ interface OperationTransportRequest {
213
235
  variables: Record<string, unknown>;
214
236
  idempotencyKey?: string;
215
237
  expectedSourceGeneration?: string;
238
+ expectedKind?: 'query' | 'mutation';
216
239
  }
217
240
  interface OperationTransportResponse {
218
241
  ok: boolean;
@@ -225,11 +248,12 @@ type OperationTransport = (request: OperationTransportRequest) => Promise<Operat
225
248
  * No credential handling, retries, or global configuration. The manifest is
226
249
  * validated once and copied, so later caller mutation cannot alter the target.
227
250
  */
228
- declare function createOperationExecutorWithTransport({ namespace, manifest, transport }: {
251
+ declare function createOperationExecutorWithTransport({ namespace, manifest, transport, operationSelection }: {
229
252
  namespace: string;
230
- /** Accept generated JSON imports directly; validate them at construction. */
253
+ /** Accept generated JSON imports directly; validate them at construction. Optional under `operationSelection: 'name'`. */
231
254
  manifest?: unknown;
232
255
  transport: OperationTransport;
256
+ operationSelection?: OperationSelection;
233
257
  }): TypedReadReceiptSqlOperationExecutor;
234
258
 
235
259
  /** Bindable scalar for `query()` placeholders ($1, $2, …). */
@@ -329,4 +353,4 @@ declare function createServiceOrmClient<Tables extends Record<string, Record<str
329
353
  transport?: OrmTransport;
330
354
  }): OrmClient<Tables, Actions>;
331
355
 
332
- export { BUILTIN_SQL_READ_HASH, type FilterValue, type ManifestOperation, type OperationErrorEntry, type OperationExecutionOptions, type OperationExecutor, type OperationExecutorConfig, type OperationReadReceipt, type OperationReference, type OperationTransport, type OperationTransportRequest, type OperationTransportResponse, type OperationsManifest, type OrmActionShape, type OrmActions, type OrmClient, OrmClientError, OrmOperationError, type OrmTransport, type QueryParam, type ReadReceiptOperationExecutor, type ReadReceiptSqlOperationExecutor, type ReadResponse, type SqlOperationExecutor, type SqlQueryParameter, type SqlQueryResult, type SqlQueryVariables, TableQuery, type TypedOperationExecutor, type TypedReadReceiptOperationExecutor, type TypedReadReceiptSqlOperationExecutor, type TypedSqlOperationExecutor, configureOrmOperations, createFetchTransport, createOperationExecutor, createOperationExecutorWithTransport, createOrmClient, createOrmFetch, createServiceOrmClient, executeOperation };
356
+ export { BUILTIN_SQL_READ_HASH, BUILTIN_SQL_READ_NAME, type FilterValue, type ManifestOperation, type OperationErrorEntry, type OperationExecutionOptions, type OperationExecutor, type OperationExecutorConfig, type OperationReadReceipt, type OperationReference, type OperationSelection, type OperationTransport, type OperationTransportRequest, type OperationTransportResponse, type OperationsManifest, type OrmActionShape, type OrmActions, type OrmClient, OrmClientError, OrmOperationError, type OrmTransport, type QueryParam, type ReadReceiptOperationExecutor, type ReadReceiptSqlOperationExecutor, type ReadResponse, type SqlOperationExecutor, type SqlQueryParameter, type SqlQueryResult, type SqlQueryVariables, TableQuery, type TypedOperationExecutor, type TypedReadReceiptOperationExecutor, type TypedReadReceiptSqlOperationExecutor, type TypedSqlOperationExecutor, configureOrmOperations, createFetchTransport, createOperationExecutor, createOperationExecutorWithTransport, createOrmClient, createOrmFetch, createServiceOrmClient, executeOperation };
package/dist/client.d.ts CHANGED
@@ -86,7 +86,10 @@ declare class TableQuery<Row extends Record<string, unknown>, Result = Row> {
86
86
  private filter;
87
87
  }
88
88
 
89
+ type OperationSelection = 'name';
90
+
89
91
  /** Runtime SQL inputs are values, never interpolated into the submitted SQL. */
92
+ declare const BUILTIN_SQL_READ_NAME = "BuiltinSqlRead";
90
93
  declare const BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
91
94
  type SqlQueryParameter = {
92
95
  type: 'text' | 'uuid' | 'date' | 'timestamptz' | 'numeric' | 'bigint';
@@ -115,9 +118,19 @@ interface SqlQueryResult {
115
118
  truncated: boolean;
116
119
  }
117
120
 
121
+ /**
122
+ * Persisted-operation client for the v2 data plane. The wire carries only
123
+ * `{ op: <name>, variables, idempotencyKey?, expectedSourceGeneration? }`. Runtime SQL contracts accept SQL in variables;
124
+ * GraphQL and fixed SQL operations keep their documents server-side. This runtime
125
+ * is deliberately free of node builtins and third-
126
+ * party deps (no @apollo/client import): Apollo integration happens through a
127
+ * fetch-compatible shim (`createOrmFetch`) handed to `HttpLink({ fetch })`.
128
+ */
129
+
118
130
  /** One entry of `operations.manifest.json` (generated by `orm generate`). */
119
131
  interface ManifestOperation {
120
- readonly hash: string;
132
+ /** Legacy manifests only; requests use the operation name. */
133
+ readonly hash?: string;
121
134
  readonly kind: 'query' | 'mutation';
122
135
  readonly requires: {
123
136
  readonly capability?: string;
@@ -125,7 +138,8 @@ interface ManifestOperation {
125
138
  } | null;
126
139
  }
127
140
  interface OperationsManifest {
128
- readonly schemaHash: string;
141
+ /** Legacy manifest metadata; absent from newly generated clients. */
142
+ readonly schemaHash?: string;
129
143
  readonly opsHash?: string;
130
144
  readonly operations: Readonly<Record<string, ManifestOperation>>;
131
145
  }
@@ -134,6 +148,8 @@ interface OperationExecutorConfig {
134
148
  baseUrl: string;
135
149
  namespace: string;
136
150
  manifest?: OperationsManifest;
151
+ /** Optional compatibility setting; only stable name selection is supported. */
152
+ operationSelection?: OperationSelection;
137
153
  /** App-user / session bearer → `Authorization: Bearer`. */
138
154
  getToken?: () => Promise<string | null> | string | null;
139
155
  /** Delegated, attenuated function token → the `ORM_DATA_TOKEN_HEADER`. */
@@ -147,7 +163,7 @@ interface OperationExecutionOptions {
147
163
  expectedSourceGeneration?: string;
148
164
  }
149
165
  interface OperationExecutor {
150
- /** Execute a manifest operation by name (or a raw `sha256:` hash). */
166
+ /** Execute a registered operation by its stable name. */
151
167
  execute<TData = Record<string, unknown>>(op: string, variables?: Record<string, unknown>, options?: OperationExecutionOptions): Promise<TData>;
152
168
  }
153
169
  /** Additive factory result; existing host wrappers implementing OperationExecutor remain valid. */
@@ -178,13 +194,19 @@ interface TypedReadReceiptOperationExecutor extends TypedOperationExecutor {
178
194
  }
179
195
  type TypedReadReceiptSqlOperationExecutor = TypedReadReceiptOperationExecutor & ReadReceiptSqlOperationExecutor;
180
196
  /** Generated handle identifies the registered contract; optional types are phantom. */
181
- interface OperationReference<TVariables extends Record<string, unknown>, TData> {
197
+ type OperationReference<TVariables extends Record<string, unknown>, TData> = {
182
198
  readonly namespace: string;
183
- readonly hash: string;
184
199
  readonly variables?: TVariables;
185
200
  readonly result?: TData;
186
- }
187
- declare function createOperationExecutor({ baseUrl, namespace, manifest, getToken, getDataToken, fetchImpl, }: OperationExecutorConfig): TypedReadReceiptSqlOperationExecutor;
201
+ readonly kind?: 'query' | 'mutation';
202
+ } & ({
203
+ readonly name: string;
204
+ readonly hash?: string;
205
+ } | {
206
+ readonly hash: string;
207
+ readonly name?: string;
208
+ });
209
+ declare function createOperationExecutor({ baseUrl, namespace, manifest, operationSelection, getToken, getDataToken, fetchImpl, }: OperationExecutorConfig): TypedReadReceiptSqlOperationExecutor;
188
210
  /**
189
211
  * Configure the process-wide executor the generated `db<Name>` server
190
212
  * functions call through. Call once at startup (server-side); browser apps
@@ -200,7 +222,7 @@ declare function executeOperation<TData = Record<string, unknown>>({ op, variabl
200
222
  /**
201
223
  * A fetch-compatible function for `new HttpLink({ uri: '/unused', fetch: createOrmFetch(...) })`.
202
224
  * Intercepts Apollo's GraphQL POST, swaps the body for the persisted-op
203
- * envelope (`{ op: <hash>, variables }`) resolved via the manifest's
225
+ * envelope (`{ op: <name>, variables }`) resolved via the manifest's
204
226
  * operationName, rewrites the URL to the data plane, and attaches auth.
205
227
  * The GraphQL-spec response body passes through untouched, so InMemoryCache
206
228
  * and error links behave exactly as they do against a GraphQL server.
@@ -213,6 +235,7 @@ interface OperationTransportRequest {
213
235
  variables: Record<string, unknown>;
214
236
  idempotencyKey?: string;
215
237
  expectedSourceGeneration?: string;
238
+ expectedKind?: 'query' | 'mutation';
216
239
  }
217
240
  interface OperationTransportResponse {
218
241
  ok: boolean;
@@ -225,11 +248,12 @@ type OperationTransport = (request: OperationTransportRequest) => Promise<Operat
225
248
  * No credential handling, retries, or global configuration. The manifest is
226
249
  * validated once and copied, so later caller mutation cannot alter the target.
227
250
  */
228
- declare function createOperationExecutorWithTransport({ namespace, manifest, transport }: {
251
+ declare function createOperationExecutorWithTransport({ namespace, manifest, transport, operationSelection }: {
229
252
  namespace: string;
230
- /** Accept generated JSON imports directly; validate them at construction. */
253
+ /** Accept generated JSON imports directly; validate them at construction. Optional under `operationSelection: 'name'`. */
231
254
  manifest?: unknown;
232
255
  transport: OperationTransport;
256
+ operationSelection?: OperationSelection;
233
257
  }): TypedReadReceiptSqlOperationExecutor;
234
258
 
235
259
  /** Bindable scalar for `query()` placeholders ($1, $2, …). */
@@ -329,4 +353,4 @@ declare function createServiceOrmClient<Tables extends Record<string, Record<str
329
353
  transport?: OrmTransport;
330
354
  }): OrmClient<Tables, Actions>;
331
355
 
332
- export { BUILTIN_SQL_READ_HASH, type FilterValue, type ManifestOperation, type OperationErrorEntry, type OperationExecutionOptions, type OperationExecutor, type OperationExecutorConfig, type OperationReadReceipt, type OperationReference, type OperationTransport, type OperationTransportRequest, type OperationTransportResponse, type OperationsManifest, type OrmActionShape, type OrmActions, type OrmClient, OrmClientError, OrmOperationError, type OrmTransport, type QueryParam, type ReadReceiptOperationExecutor, type ReadReceiptSqlOperationExecutor, type ReadResponse, type SqlOperationExecutor, type SqlQueryParameter, type SqlQueryResult, type SqlQueryVariables, TableQuery, type TypedOperationExecutor, type TypedReadReceiptOperationExecutor, type TypedReadReceiptSqlOperationExecutor, type TypedSqlOperationExecutor, configureOrmOperations, createFetchTransport, createOperationExecutor, createOperationExecutorWithTransport, createOrmClient, createOrmFetch, createServiceOrmClient, executeOperation };
356
+ export { BUILTIN_SQL_READ_HASH, BUILTIN_SQL_READ_NAME, type FilterValue, type ManifestOperation, type OperationErrorEntry, type OperationExecutionOptions, type OperationExecutor, type OperationExecutorConfig, type OperationReadReceipt, type OperationReference, type OperationSelection, type OperationTransport, type OperationTransportRequest, type OperationTransportResponse, type OperationsManifest, type OrmActionShape, type OrmActions, type OrmClient, OrmClientError, OrmOperationError, type OrmTransport, type QueryParam, type ReadReceiptOperationExecutor, type ReadReceiptSqlOperationExecutor, type ReadResponse, type SqlOperationExecutor, type SqlQueryParameter, type SqlQueryResult, type SqlQueryVariables, TableQuery, type TypedOperationExecutor, type TypedReadReceiptOperationExecutor, type TypedReadReceiptSqlOperationExecutor, type TypedSqlOperationExecutor, configureOrmOperations, createFetchTransport, createOperationExecutor, createOperationExecutorWithTransport, createOrmClient, createOrmFetch, createServiceOrmClient, executeOperation };
package/dist/client.js CHANGED
@@ -159,6 +159,51 @@ var TableQuery = class _TableQuery {
159
159
  }
160
160
  };
161
161
 
162
+ // src/client/sql.ts
163
+ var BUILTIN_SQL_READ_NAME = "BuiltinSqlRead";
164
+ var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
165
+
166
+ // src/client/operation-selection.ts
167
+ var NAME = /^[_A-Za-z][_0-9A-Za-z]{0,254}$/;
168
+ function selectorForReference(op) {
169
+ if (typeof op === "string") return op;
170
+ if (op.name) return op.name;
171
+ if (op.hash?.startsWith("sha256:")) return op.hash;
172
+ throw new OrmClientError("unknown operation reference \u2014 regenerate the client");
173
+ }
174
+ function manifestEntry({ selector, operations }) {
175
+ if (selector.startsWith("sha256:")) return [...operations].find(([, entry2]) => entry2.hash === selector);
176
+ const entry = operations.get(selector);
177
+ return entry ? [selector, entry] : void 0;
178
+ }
179
+ function referenceKind(op) {
180
+ return typeof op === "string" ? void 0 : op.kind;
181
+ }
182
+ function assertKnownName({ name, known, operations, selector }) {
183
+ if (!NAME.test(name) || !known || ["__proto__", "constructor", "prototype"].includes(name)) {
184
+ throw new OrmClientError(`unknown operation "${selector}" \u2014 not in the manifest (${operations.size} known); regenerate the typed operation reference`);
185
+ }
186
+ }
187
+ function assertReferenceKind({ op, kind }) {
188
+ const declared = referenceKind(op);
189
+ if (declared && kind !== declared) throw new OrmClientError("operation kind differs from the typed reference");
190
+ }
191
+ function selectOperationTarget({ op, operations, selection = "name", readReceipt = false }) {
192
+ if (selection !== "name") throw new OrmClientError("ORM calls use operation names; hash selection is no longer supported");
193
+ const selector = selectorForReference(op);
194
+ if (selector === BUILTIN_SQL_READ_HASH || selector === BUILTIN_SQL_READ_NAME) {
195
+ return { op: `query:${BUILTIN_SQL_READ_NAME}`, expectedKind: "query" };
196
+ }
197
+ const match = manifestEntry({ selector, operations });
198
+ const name = match?.[0] ?? selector;
199
+ const kind = match?.[1].kind ?? referenceKind(op);
200
+ assertKnownName({ name, known: operations.size === 0 || match !== void 0, operations, selector });
201
+ assertReferenceKind({ op, kind });
202
+ if (readReceipt && kind !== "query") throw new OrmClientError("read receipts require a registered query or the built-in SQL read");
203
+ const guarded = kind ? `${kind}:${name}` : name;
204
+ return { op: guarded, ...kind ? { expectedKind: kind } : {} };
205
+ }
206
+
162
207
  // src/client/response.ts
163
208
  function isRecord(value) {
164
209
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -206,9 +251,6 @@ function readOperationResponseWithReceipt({
206
251
  return { data, sourceGeneration };
207
252
  }
208
253
 
209
- // src/client/sql.ts
210
- var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
211
-
212
254
  // src/client/operations.ts
213
255
  function validateIdempotencyKey(key) {
214
256
  if (key !== void 0 && !/^[A-Za-z0-9._:-]{1,128}$/.test(key)) {
@@ -221,38 +263,11 @@ function validateExpectedSourceGeneration(value) {
221
263
  }
222
264
  }
223
265
  var dataPlanePath = (namespace) => `/_data/v2/${namespace}`;
224
- function resolveOpHash(manifest, op) {
225
- if (op.startsWith("sha256:")) return op;
226
- const entry = manifest.operations[op];
227
- if (!entry) {
228
- const known = Object.keys(manifest.operations).sort();
229
- throw new OrmClientError(
230
- `unknown operation "${op}" \u2014 not in the manifest (${known.length} known). Re-run \`seq-studio orm generate\` after editing graphql documents.`
231
- );
232
- }
233
- return entry.hash;
234
- }
235
- function createReadReceiptOperationResolver({ operations }) {
236
- const hashesByName = /* @__PURE__ */ new Map();
237
- const readHashes = /* @__PURE__ */ new Set([BUILTIN_SQL_READ_HASH]);
238
- const mutationHashes = /* @__PURE__ */ new Set();
239
- for (const [name, entry] of operations) {
240
- hashesByName.set(name, entry.hash);
241
- if (entry.kind === "query" && /^sha256:[a-f0-9]{64}$/.test(entry.hash)) readHashes.add(entry.hash);
242
- if (entry.kind === "mutation") mutationHashes.add(entry.hash);
243
- }
244
- return ({ selector, hashOnly = false }) => {
245
- const hash = selector.startsWith("sha256:") ? selector : hashOnly ? void 0 : hashesByName.get(selector);
246
- if (!hash || !readHashes.has(hash) || mutationHashes.has(hash)) {
247
- throw new OrmClientError("read receipts require a registered query or the built-in SQL read");
248
- }
249
- return hash;
250
- };
251
- }
252
266
  function createOperationExecutor({
253
267
  baseUrl,
254
268
  namespace,
255
- manifest = { schemaHash: "builtin", operations: {} },
269
+ manifest = { operations: {} },
270
+ operationSelection = "name",
256
271
  getToken,
257
272
  getDataToken,
258
273
  fetchImpl = globalThis.fetch
@@ -262,12 +277,12 @@ function createOperationExecutor({
262
277
  throw new OrmClientError("provide exactly one of getToken (bearer) or getDataToken (delegated)");
263
278
  }
264
279
  const root = baseUrl.replace(/\/+$/, "");
265
- const resolveReceiptOperation = createReadReceiptOperationResolver({ operations: Object.entries(manifest.operations) });
280
+ const operations = new Map(Object.entries(manifest.operations).map(([name, entry]) => [name, { ...entry }]));
266
281
  async function request({ op, variables, options, requireReadReceipt = false }) {
267
282
  validateIdempotencyKey(options.idempotencyKey);
268
283
  validateExpectedSourceGeneration(options.expectedSourceGeneration);
269
284
  if (typeof op !== "string" && op.namespace !== namespace) throw new OrmClientError("operation belongs to a different namespace");
270
- const hash = requireReadReceipt ? resolveReceiptOperation({ selector: typeof op === "string" ? op : op.hash, hashOnly: typeof op !== "string" }) : typeof op === "string" ? resolveOpHash(manifest, op) : op.hash;
285
+ const target = selectOperationTarget({ op, operations, selection: operationSelection, readReceipt: requireReadReceipt });
271
286
  const token = await (getDataToken ?? getToken)();
272
287
  if (!token) throw new OrmClientError("not authenticated \u2014 no token available");
273
288
  const auth = getDataToken ? { [ORM_DATA_TOKEN_HEADER]: token } : { Authorization: `Bearer ${token}` };
@@ -275,7 +290,7 @@ function createOperationExecutor({
275
290
  method: "POST",
276
291
  headers: { ...auth, "Content-Type": "application/json" },
277
292
  body: JSON.stringify({
278
- op: hash,
293
+ ...target,
279
294
  variables,
280
295
  idempotencyKey: options.idempotencyKey,
281
296
  expectedSourceGeneration: options.expectedSourceGeneration
@@ -340,7 +355,7 @@ function createOrmFetch({
340
355
  "createOrmFetch requires named operations (Apollo sends operationName for named documents)"
341
356
  );
342
357
  }
343
- const hash = resolveOpHash(manifest, name);
358
+ const target = selectOperationTarget({ op: name, operations: new Map(Object.entries(manifest.operations)) });
344
359
  const idempotencyKey = new Headers(init?.headers).get("Idempotency-Key") ?? void 0;
345
360
  validateIdempotencyKey(idempotencyKey);
346
361
  const token = await (getDataToken ?? getToken)();
@@ -349,7 +364,7 @@ function createOrmFetch({
349
364
  return fetchImpl(url, {
350
365
  method: "POST",
351
366
  headers: { ...auth, "Content-Type": "application/json" },
352
- body: JSON.stringify({ op: hash, variables: parsed.variables ?? {}, idempotencyKey }),
367
+ body: JSON.stringify({ ...target, variables: parsed.variables ?? {}, idempotencyKey }),
353
368
  ...init?.signal ? { signal: init.signal } : {}
354
369
  });
355
370
  };
@@ -357,39 +372,37 @@ function createOrmFetch({
357
372
 
358
373
  // src/client/transport-executor.ts
359
374
  var operationHash = /^sha256:[a-f0-9]{64}$/;
360
- function readManifestHashes(manifest) {
361
- if (!isRecord(manifest) || typeof manifest.schemaHash !== "string" || !manifest.schemaHash || !isRecord(manifest.operations)) {
375
+ function readManifestOperations(manifest) {
376
+ if (!isRecord(manifest) || !isRecord(manifest.operations)) {
362
377
  throw new OrmClientError("invalid operations manifest \u2014 use operations.manifest.json from seq-studio orm generate");
363
378
  }
364
- const hashes = /* @__PURE__ */ new Map();
379
+ const operations = /* @__PURE__ */ new Map();
365
380
  for (const [name, entry] of Object.entries(manifest.operations)) {
366
- if (!/^[_A-Za-z][_0-9A-Za-z]*$/.test(name) || !isRecord(entry) || typeof entry.hash !== "string" || !operationHash.test(entry.hash) || entry.kind !== "query" && entry.kind !== "mutation") {
381
+ if (!/^[_A-Za-z][_0-9A-Za-z]*$/.test(name) || !isRecord(entry) || entry.hash !== void 0 && (typeof entry.hash !== "string" || !operationHash.test(entry.hash)) || entry.kind !== "query" && entry.kind !== "mutation") {
367
382
  throw new OrmClientError(`invalid operations manifest entry "${name}" \u2014 regenerate the manifest`);
368
383
  }
369
- hashes.set(name, { hash: entry.hash, kind: entry.kind });
384
+ operations.set(name, { ...typeof entry.hash === "string" ? { hash: entry.hash } : {}, kind: entry.kind });
370
385
  }
371
- return hashes;
386
+ return operations;
372
387
  }
373
- function createOperationExecutorWithTransport({ namespace, manifest, transport }) {
388
+ function createOperationExecutorWithTransport({ namespace, manifest, transport, operationSelection = "name" }) {
389
+ if (operationSelection !== "name") throw new OrmClientError("ORM calls use operation names; hash selection is no longer supported");
374
390
  if (typeof namespace !== "string" || !NAMESPACE_PATTERN.test(namespace)) throw new OrmClientError("invalid ORM namespace \u2014 expected a lowercase identifier of at most 41 characters");
375
- const hashes = manifest === void 0 ? /* @__PURE__ */ new Map() : readManifestHashes(manifest);
376
- const knownHashes = new Set([...hashes.values()].map((entry) => entry.hash));
377
- const resolveReceiptOperation = createReadReceiptOperationResolver({ operations: hashes });
391
+ const operations = manifest === void 0 ? /* @__PURE__ */ new Map() : readManifestOperations(manifest);
378
392
  async function request({ op, variables, options, requireReadReceipt = false }) {
379
393
  validateIdempotencyKey(options.idempotencyKey);
380
394
  validateExpectedSourceGeneration(options.expectedSourceGeneration);
381
395
  if (typeof op !== "string" && op.namespace !== namespace) throw new OrmClientError("operation belongs to a different namespace");
382
- const selector = typeof op === "string" ? op : op.hash;
383
- const hash = requireReadReceipt ? resolveReceiptOperation({ selector, hashOnly: typeof op !== "string" }) : selector === BUILTIN_SQL_READ_HASH ? selector : hashes.get(selector)?.hash ?? (knownHashes.has(selector) ? selector : void 0);
384
- if (!hash) throw new OrmClientError(`unknown operation "${op}" \u2014 not in the manifest (${hashes.size} known). Re-run seq-studio orm generate.`);
396
+ const target = selectOperationTarget({ op, operations, selection: operationSelection, readReceipt: requireReadReceipt });
385
397
  if (!isRecord(variables)) throw new OrmClientError("operation variables must be an object");
386
- const response = await transport({
398
+ const send = () => transport({
387
399
  namespace,
388
- op: hash,
400
+ ...target,
389
401
  variables,
390
402
  ...options.idempotencyKey === void 0 ? {} : { idempotencyKey: options.idempotencyKey },
391
403
  ...options.expectedSourceGeneration === void 0 ? {} : { expectedSourceGeneration: options.expectedSourceGeneration }
392
404
  });
405
+ const response = await send();
393
406
  if (!response || typeof response.ok !== "boolean" || !Number.isInteger(response.status) || response.status < 100 || response.status > 599 || response.ok !== (response.status >= 200 && response.status < 300)) {
394
407
  throw new OrmOperationError("malformed transport response", null, null);
395
408
  }
@@ -475,6 +488,6 @@ function requireOption(value, name) {
475
488
  return value;
476
489
  }
477
490
 
478
- export { BUILTIN_SQL_READ_HASH, NAMESPACE_PATTERN, ORM_DATA_TOKEN_HEADER, ORM_SERVICE_DATA_TOKEN_HEADER, OrmClientError, OrmOperationError, TableQuery, configureOrmOperations, createFetchTransport, createOperationExecutor, createOperationExecutorWithTransport, createOrmClient, createOrmFetch, createServiceOrmClient, executeOperation };
491
+ export { BUILTIN_SQL_READ_HASH, BUILTIN_SQL_READ_NAME, NAMESPACE_PATTERN, ORM_DATA_TOKEN_HEADER, ORM_SERVICE_DATA_TOKEN_HEADER, OrmClientError, OrmOperationError, TableQuery, configureOrmOperations, createFetchTransport, createOperationExecutor, createOperationExecutorWithTransport, createOrmClient, createOrmFetch, createServiceOrmClient, executeOperation };
479
492
  //# sourceMappingURL=client.js.map
480
493
  //# sourceMappingURL=client.js.map