@prisma-next/sql-runtime 0.12.0-dev.5 → 0.12.0-dev.50

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
@@ -23,7 +23,7 @@ Execute SQL query Plans with deterministic verification, guardrails, and feedbac
23
23
  - **Mutation Default Generator Composition**: Assemble execution default generators from composed target/adapter/extension contributors
24
24
  - **No Implicit Generator Baseline**: Runtime resolves generator ids only from composed contributors (no built-in runtime fallback table)
25
25
  - **SQL Context Creation**: Create runtime contexts with SQL contracts, adapters, and codecs
26
- - **SQL Marker Management**: Provide SQL statements for reading/writing contract markers
26
+ - **SQL Marker Bootstrap**: Provide test-utility helpers for bootstrapping the marker table; marker reads and writes both go through the control adapter SPI
27
27
  - **Codec Encoding/Decoding**: Encode parameters and decode rows using SQL codec registries
28
28
  - **Codec Validation**: Validate that codec registries contain all required codecs
29
29
  - **SQL Family Adapter**: Implement `RuntimeFamilyAdapter` for SQL contracts (defined in `runtime-spi.ts`)
@@ -124,12 +124,15 @@ const runtime = createRuntime({
124
124
  - `validateCodecRegistryCompleteness` - Codec validation
125
125
  - `extractCodecIds` - Extract codec IDs from a contract
126
126
  - `validateContractCodecMappings` - Validate contract codec mappings against registry
127
+ - `createAstCodecRegistry` - Contract-free codec registry that resolves codecs from AST-supplied `CodecRef`s
128
+ - `deriveParamMetadata` - Walk a control DML AST and collect per-value codec metadata for encoding
129
+ - `encodeParamsWithMetadata` - Encode lowered control DML parameters through their codecs
127
130
 
128
131
  ### SQL Marker
129
132
 
130
- - `readContractMarker`, `writeContractMarker` - SQL marker statements
131
- - `ensureSchemaStatement`, `ensureTableStatement` - DDL statements for marker table setup
132
- - `SqlStatement` - SQL statement type
133
+ - Test helpers in `./test/utils` bootstrap marker tables via contract-free DDL lowering
134
+
135
+ Marker reads and writes go through the control adapter SPI (`adapter.readMarker`, `adapter.initMarker`, `adapter.updateMarker`, `adapter.writeLedgerEntry`).
133
136
 
134
137
  ### Plan Lowering
135
138
 
@@ -1,23 +1,143 @@
1
1
  import { AsyncIterableResult, RuntimeCore, checkAborted, checkMiddlewareCompatibility, isRuntimeError, raceAgainstAbort, runBeforeExecuteChain, runWithMiddleware, runtimeError } from "@prisma-next/framework-components/runtime";
2
- import { type } from "arktype";
2
+ import { canonicalizeJson } from "@prisma-next/framework-components/utils";
3
3
  import { PreparedParamRef, collectOrderedParamRefs, isQueryAst } from "@prisma-next/sql-relational-core/ast";
4
4
  import { ifDefined } from "@prisma-next/utils/defined";
5
5
  import { checkContractComponentRequirements, mergeCapabilityMatrices } from "@prisma-next/framework-components/components";
6
6
  import { createExecutionStack } from "@prisma-next/framework-components/execution";
7
- import { canonicalizeJson } from "@prisma-next/framework-components/utils";
8
7
  import { isPostgresEnumStorageEntry } from "@prisma-next/sql-contract/types";
9
8
  import { blindCast } from "@prisma-next/utils/casts";
10
9
  import { createSqlOperationRegistry } from "@prisma-next/sql-operations";
11
10
  import { buildCodecDescriptorRegistry } from "@prisma-next/sql-relational-core/codec-descriptor-registry";
12
- import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
13
11
  import { createSqlParamRefMutator } from "@prisma-next/sql-relational-core/middleware";
14
12
  import { canonicalStringify } from "@prisma-next/utils/canonical-stringify";
15
13
  import { hashContent } from "@prisma-next/utils/hash-content";
16
14
  import { createHash } from "node:crypto";
15
+ //#region src/codecs/ast-codec-resolver.ts
16
+ /**
17
+ * Build an {@link AstCodecResolver} bound to a descriptor registry and a per-call instance-context factory.
18
+ *
19
+ * The instance-context factory lets callers control `name` / `usedAt` for refs the AST supplies (e.g. AST-embedded migration ops where the materialisation site is the AST node, not a contract column). The contract-walk pre-population path constructs its own contexts and invokes the resolver with those refs to seed the cache.
20
+ */
21
+ function createAstCodecResolver(descriptors, instanceContextFor) {
22
+ const cache = /* @__PURE__ */ new Map();
23
+ return { forCodecRef(ref) {
24
+ const key = `${ref.codecId}:${canonicalizeJson(ref.typeParams)}`;
25
+ const cached = cache.get(key);
26
+ if (cached) return cached;
27
+ const descriptor = descriptors.descriptorFor(ref.codecId);
28
+ if (!descriptor) throw runtimeError("RUNTIME.CODEC_DESCRIPTOR_MISSING", `No codec descriptor registered for codecId '${ref.codecId}'.`, { codecId: ref.codecId });
29
+ const validated = validateTypeParams$1(descriptor.paramsSchema, descriptor.isParameterized && ref.typeParams === void 0 ? {
30
+ ...ref,
31
+ typeParams: {}
32
+ } : ref);
33
+ const ctx = instanceContextFor(ref);
34
+ const codec = descriptor.factory(validated)(ctx);
35
+ cache.set(key, codec);
36
+ return codec;
37
+ } };
38
+ }
39
+ function validateTypeParams$1(paramsSchema, ref) {
40
+ const result = paramsSchema["~standard"].validate(ref.typeParams);
41
+ if (result instanceof Promise) throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `paramsSchema for codec '${ref.codecId}' returned a Promise; runtime validation requires a synchronous Standard Schema validator.`, {
42
+ codecId: ref.codecId,
43
+ typeParams: ref.typeParams
44
+ });
45
+ if ("issues" in result && result.issues) {
46
+ const messages = result.issues.map((issue) => issue.message).join("; ");
47
+ throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `Invalid typeParams for codec '${ref.codecId}': ${messages}`, {
48
+ codecId: ref.codecId,
49
+ typeParams: ref.typeParams
50
+ });
51
+ }
52
+ return result.value;
53
+ }
54
+ //#endregion
55
+ //#region src/codecs/ast-codec-registry.ts
56
+ /**
57
+ * Build a contract-free {@link ContractCodecRegistry} that resolves codecs
58
+ * purely from AST-supplied {@link import('@prisma-next/framework-components/codec').CodecRef}s
59
+ * against a target's descriptor registry.
60
+ *
61
+ * Dispatch is driven entirely by `CodecRef`s embedded in AST nodes; no
62
+ * contract walk is needed. `forColumn` always returns `undefined` — this
63
+ * registry carries no column-to-codec mappings.
64
+ */
65
+ function createAstCodecRegistry(descriptors) {
66
+ const resolver = createAstCodecResolver(descriptors, (ref) => ({
67
+ name: ref.codecId,
68
+ usedAt: []
69
+ }));
70
+ return {
71
+ forColumn: () => void 0,
72
+ forCodecRef: (ref) => resolver.forCodecRef(ref)
73
+ };
74
+ }
75
+ //#endregion
76
+ //#region src/codecs/encoding.ts
77
+ const NO_METADATA = Object.freeze({
78
+ codec: void 0,
79
+ name: void 0
80
+ });
81
+ function deriveParamMetadata(ast) {
82
+ return collectOrderedParamRefs(ast).map((ref) => {
83
+ return {
84
+ codec: ref.codec,
85
+ name: ref.name
86
+ };
87
+ });
88
+ }
89
+ function resolveParamCodec(metadata, contractCodecs) {
90
+ if (metadata.codec && contractCodecs) return contractCodecs.forCodecRef(metadata.codec);
91
+ }
92
+ function paramLabel(metadata, paramIndex) {
93
+ return metadata.name ?? `param[${paramIndex}]`;
94
+ }
95
+ function wrapEncodeFailure(error, metadata, paramIndex, codecId) {
96
+ const label = paramLabel(metadata, paramIndex);
97
+ const wrapped = runtimeError("RUNTIME.ENCODE_FAILED", `Failed to encode parameter ${label} with codec '${codecId}': ${error instanceof Error ? error.message : String(error)}`, {
98
+ label,
99
+ codec: codecId,
100
+ paramIndex
101
+ });
102
+ wrapped.cause = error;
103
+ throw wrapped;
104
+ }
105
+ async function encodeParamValue(value, metadata, paramIndex, ctx, contractCodecs) {
106
+ if (value === null || value === void 0) return null;
107
+ const codec = resolveParamCodec(metadata, contractCodecs);
108
+ if (!codec) return value;
109
+ try {
110
+ return await codec.encode(value, ctx);
111
+ } catch (error) {
112
+ if (isRuntimeError(error)) throw error;
113
+ wrapEncodeFailure(error, metadata, paramIndex, codec.id);
114
+ }
115
+ }
116
+ /**
117
+ * Encodes all parameters concurrently via `Promise.all`. Per parameter, sync-and async-authored codecs share the same path: `codec.encode → await → return`. Param-level failures are wrapped in `RUNTIME.ENCODE_FAILED`.
118
+ *
119
+ * When `ctx.signal` is provided:
120
+ *
121
+ * - **Already-aborted at entry** short-circuits with `RUNTIME.ABORTED` (`{ phase: 'encode' }`) before any `codec.encode` call is made — codecs can pin this with a per-call counter that stays at zero.
122
+ * - **Mid-flight abort** races the per-param `Promise.all` against `abortable(ctx.signal)`. The runtime returns `RUNTIME.ABORTED` promptly even if codec bodies ignore the signal; the in-flight bodies are abandoned and run to completion in the background (cooperative cancellation, see ADR 204).
123
+ * - Existing `RUNTIME.ENCODE_FAILED` envelopes that surface from a codec body before the runtime observes the abort pass through unchanged (no double wrap).
124
+ */
125
+ async function encodeParams(plan, ctx, contractCodecs) {
126
+ return encodeParamsWithMetadata(plan.params, deriveParamMetadata(plan.ast), ctx, contractCodecs);
127
+ }
128
+ async function encodeParamsWithMetadata(values, metadata, ctx, contractCodecs) {
129
+ checkAborted(ctx, "encode");
130
+ const signal = ctx.signal;
131
+ if (values.length === 0) return values;
132
+ const tasks = values.map((value, i) => encodeParamValue(value, metadata[i] ?? NO_METADATA, i, ctx, contractCodecs));
133
+ const settled = await raceAgainstAbort(Promise.all(tasks), signal, "encode");
134
+ return Object.freeze(settled);
135
+ }
136
+ //#endregion
17
137
  //#region src/codecs/validation.ts
18
138
  function extractCodecIds(contract) {
19
139
  const codecIds = /* @__PURE__ */ new Set();
20
- for (const ns of Object.values(contract.storage.namespaces)) for (const table of Object.values(ns.tables)) for (const column of Object.values(table.columns)) {
140
+ for (const ns of Object.values(contract.storage.namespaces)) for (const table of Object.values(ns.entries.table)) for (const column of Object.values(table.columns)) {
21
141
  const codecId = column.codecId;
22
142
  codecIds.add(codecId);
23
143
  }
@@ -25,7 +145,7 @@ function extractCodecIds(contract) {
25
145
  }
26
146
  function extractCodecIdsFromColumns(contract) {
27
147
  const codecIds = /* @__PURE__ */ new Map();
28
- for (const ns of Object.values(contract.storage.namespaces)) for (const [tableName, table] of Object.entries(ns.tables)) for (const [columnName, column] of Object.entries(table.columns)) {
148
+ for (const ns of Object.values(contract.storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table)) for (const [columnName, column] of Object.entries(table.columns)) {
29
149
  const codecId = column.codecId;
30
150
  const key = `${tableName}.${columnName}`;
31
151
  codecIds.set(key, codecId);
@@ -84,50 +204,6 @@ function lowerSqlPlan(adapter, contract, queryPlan) {
84
204
  });
85
205
  }
86
206
  //#endregion
87
- //#region src/marker.ts
88
- const MetaSchema = type({ "[string]": "unknown" });
89
- function parseMeta(meta) {
90
- if (meta === null || meta === void 0) return {};
91
- let parsed;
92
- if (typeof meta === "string") try {
93
- parsed = JSON.parse(meta);
94
- } catch {
95
- return {};
96
- }
97
- else parsed = meta;
98
- const result = MetaSchema(parsed);
99
- if (result instanceof type.errors) return {};
100
- return result;
101
- }
102
- const ContractMarkerRowSchema = type({
103
- core_hash: "string",
104
- profile_hash: "string",
105
- "contract_json?": "unknown | null",
106
- "canonical_version?": "number | null",
107
- "updated_at?": "Date | string",
108
- "app_tag?": "string | null",
109
- "meta?": "unknown | null",
110
- invariants: type("string").array()
111
- });
112
- function parseContractMarkerRow(row) {
113
- const result = ContractMarkerRowSchema(row);
114
- if (result instanceof type.errors) {
115
- const messages = result.map((p) => p.message).join("; ");
116
- throw new Error(`Invalid contract marker row: ${messages}`);
117
- }
118
- const updatedAt = result.updated_at ? result.updated_at instanceof Date ? result.updated_at : new Date(result.updated_at) : /* @__PURE__ */ new Date();
119
- return {
120
- storageHash: result.core_hash,
121
- profileHash: result.profile_hash,
122
- contractJson: result.contract_json ?? null,
123
- canonicalVersion: result.canonical_version ?? null,
124
- updatedAt,
125
- appTag: result.app_tag ?? null,
126
- meta: parseMeta(result.meta),
127
- invariants: result.invariants
128
- };
129
- }
130
- //#endregion
131
207
  //#region src/middleware/budgets.ts
132
208
  function hasAggregateWithoutGroupBy(ast) {
133
209
  if (ast.groupBy !== void 0) return false;
@@ -396,46 +472,6 @@ function lints(options) {
396
472
  });
397
473
  }
398
474
  //#endregion
399
- //#region src/codecs/ast-codec-resolver.ts
400
- /**
401
- * Build an {@link AstCodecResolver} bound to a descriptor registry and a per-call instance-context factory.
402
- *
403
- * The instance-context factory lets callers control `name` / `usedAt` for refs the AST supplies (e.g. AST-embedded migration ops where the materialisation site is the AST node, not a contract column). The contract-walk pre-population path constructs its own contexts and invokes the resolver with those refs to seed the cache.
404
- */
405
- function createAstCodecResolver(descriptors, instanceContextFor) {
406
- const cache = /* @__PURE__ */ new Map();
407
- return { forCodecRef(ref) {
408
- const key = `${ref.codecId}:${canonicalizeJson(ref.typeParams)}`;
409
- const cached = cache.get(key);
410
- if (cached) return cached;
411
- const descriptor = descriptors.descriptorFor(ref.codecId);
412
- if (!descriptor) throw runtimeError("RUNTIME.CODEC_DESCRIPTOR_MISSING", `No codec descriptor registered for codecId '${ref.codecId}'.`, { codecId: ref.codecId });
413
- const validated = validateTypeParams$1(descriptor.paramsSchema, descriptor.isParameterized && ref.typeParams === void 0 ? {
414
- ...ref,
415
- typeParams: {}
416
- } : ref);
417
- const ctx = instanceContextFor(ref);
418
- const codec = descriptor.factory(validated)(ctx);
419
- cache.set(key, codec);
420
- return codec;
421
- } };
422
- }
423
- function validateTypeParams$1(paramsSchema, ref) {
424
- const result = paramsSchema["~standard"].validate(ref.typeParams);
425
- if (result instanceof Promise) throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `paramsSchema for codec '${ref.codecId}' returned a Promise; runtime validation requires a synchronous Standard Schema validator.`, {
426
- codecId: ref.codecId,
427
- typeParams: ref.typeParams
428
- });
429
- if ("issues" in result && result.issues) {
430
- const messages = result.issues.map((issue) => issue.message).join("; ");
431
- throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `Invalid typeParams for codec '${ref.codecId}': ${messages}`, {
432
- codecId: ref.codecId,
433
- typeParams: ref.typeParams
434
- });
435
- }
436
- return result.value;
437
- }
438
- //#endregion
439
475
  //#region src/sql-context.ts
440
476
  function documentScopedCodecTypes(contract) {
441
477
  return blindCast(contract.storage.types);
@@ -531,7 +567,7 @@ function collectCodecDescriptors(contributors) {
531
567
  }
532
568
  function collectTypeRefSites(storage) {
533
569
  const sites = /* @__PURE__ */ new Map();
534
- for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.tables)) for (const [columnName, column] of Object.entries(table.columns)) {
570
+ for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table)) for (const [columnName, column] of Object.entries(table.columns)) {
535
571
  if (typeof column.typeRef !== "string") continue;
536
572
  const list = sites.get(column.typeRef);
537
573
  const entry = {
@@ -566,7 +602,7 @@ function initializeTypeHelpers(storage, documentTypes, codecDescriptors) {
566
602
  return helpers;
567
603
  }
568
604
  function validateColumnTypeParams(storage, codecDescriptors) {
569
- for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.tables)) for (const [columnName, column] of Object.entries(table.columns)) if (column.typeParams) {
605
+ for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table)) for (const [columnName, column] of Object.entries(table.columns)) if (column.typeParams) {
570
606
  const descriptor = codecDescriptors.get(column.codecId);
571
607
  if (descriptor) validateTypeParams(column.typeParams, descriptor, {
572
608
  tableName,
@@ -586,7 +622,7 @@ function validateColumnTypeParams(storage, codecDescriptors) {
586
622
  * Runs unconditionally from `createExecutionContext` so contract bugs fail fast at construction time instead of silently skipping affected columns in the codec registry's pre-population walk.
587
623
  */
588
624
  function assertColumnCodecIntegrity(storage, codecDescriptors) {
589
- for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.tables)) for (const columnName of Object.keys(table.columns)) {
625
+ for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table)) for (const columnName of Object.keys(table.columns)) {
590
626
  const ref = codecDescriptors.codecRefForColumn(tableName, columnName);
591
627
  if (!ref) continue;
592
628
  const descriptor = codecDescriptors.descriptorFor(ref.codecId);
@@ -660,7 +696,7 @@ function buildContractCodecRegistry(contract, codecDescriptors) {
660
696
  nameByKey.set(key, typeName);
661
697
  }
662
698
  }
663
- for (const ns of Object.values(contract.storage.namespaces)) for (const [tableName, table] of Object.entries(ns.tables)) for (const [columnName, column] of Object.entries(table.columns)) {
699
+ for (const ns of Object.values(contract.storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table)) for (const [columnName, column] of Object.entries(table.columns)) {
664
700
  if (column.typeRef !== void 0) continue;
665
701
  const ref = codecDescriptors.codecRefForColumn(tableName, columnName);
666
702
  if (!ref) continue;
@@ -684,7 +720,7 @@ function buildContractCodecRegistry(contract, codecDescriptors) {
684
720
  usedAt: usedAtByKey.get(key) ?? []
685
721
  };
686
722
  });
687
- for (const ns of Object.values(contract.storage.namespaces)) for (const [tableName, table] of Object.entries(ns.tables)) for (const columnName of Object.keys(table.columns)) {
723
+ for (const ns of Object.values(contract.storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table)) for (const columnName of Object.keys(table.columns)) {
688
724
  const ref = codecDescriptors.codecRefForColumn(tableName, columnName);
689
725
  if (!ref) continue;
690
726
  resolver.forCodecRef(ref);
@@ -817,125 +853,6 @@ function createExecutionContext(options) {
817
853
  };
818
854
  }
819
855
  //#endregion
820
- //#region src/sql-marker.ts
821
- const ensureSchemaStatement = {
822
- sql: "create schema if not exists prisma_contract",
823
- params: []
824
- };
825
- /**
826
- * Schema for `prisma_contract.marker`. The `space text` primary key
827
- * supports one row per loaded contract space (`'app'`,
828
- * `'<extension-id>'`, …); brand-new databases create this shape
829
- * directly. Pre-1.0 single-row markers (no `space` column) are not
830
- * auto-migrated — the target-specific migration runner detects the
831
- * legacy shape at boot and surfaces a structured `LEGACY_MARKER_SHAPE`
832
- * failure pointing the operator at re-running `dbInit`.
833
- *
834
- * @see specs/framework-mechanism.spec.md § 2.
835
- */
836
- const ensureTableStatement = {
837
- sql: `create table if not exists prisma_contract.marker (
838
- space text not null primary key default '${APP_SPACE_ID}',
839
- core_hash text not null,
840
- profile_hash text not null,
841
- contract_json jsonb,
842
- canonical_version int,
843
- updated_at timestamptz not null default now(),
844
- app_tag text,
845
- meta jsonb not null default '{}',
846
- invariants text[] not null default '{}'
847
- )`,
848
- params: []
849
- };
850
- function readContractMarker(space) {
851
- return {
852
- sql: `select
853
- core_hash,
854
- profile_hash,
855
- contract_json,
856
- canonical_version,
857
- updated_at,
858
- app_tag,
859
- meta,
860
- invariants
861
- from prisma_contract.marker
862
- where space = $1`,
863
- params: [space]
864
- };
865
- }
866
- /**
867
- * Variable columns that participate in INSERT/UPDATE alongside the
868
- * always-on `space = $1` and `updated_at = now()`. Each column declares
869
- * its name, optional cast type, and parameter value; the placeholder
870
- * (`$N`) is computed positionally below — adding or reordering a
871
- * column doesn't desync indices. `invariants` only appears when the
872
- * caller supplies it — see `WriteMarkerInput.invariants`.
873
- */
874
- function markerColumns(input) {
875
- return [
876
- {
877
- name: "core_hash",
878
- param: input.storageHash
879
- },
880
- {
881
- name: "profile_hash",
882
- param: input.profileHash
883
- },
884
- {
885
- name: "contract_json",
886
- type: "jsonb",
887
- param: input.contractJson ?? null
888
- },
889
- {
890
- name: "canonical_version",
891
- param: input.canonicalVersion ?? null
892
- },
893
- {
894
- name: "app_tag",
895
- param: input.appTag ?? null
896
- },
897
- {
898
- name: "meta",
899
- type: "jsonb",
900
- param: JSON.stringify(input.meta ?? {})
901
- },
902
- ...input.invariants !== void 0 ? [{
903
- name: "invariants",
904
- type: "text[]",
905
- param: input.invariants
906
- }] : []
907
- ];
908
- }
909
- function writeContractMarker(input) {
910
- const placed = markerColumns(input).map((c, i) => ({
911
- name: c.name,
912
- expr: c.type ? `$${i + 2}::${c.type}` : `$${i + 2}`,
913
- param: c.param
914
- }));
915
- const params = [input.space, ...placed.map((c) => c.param)];
916
- const insertColumns = [
917
- "space",
918
- ...placed.map((c) => c.name),
919
- "updated_at"
920
- ].join(", ");
921
- const insertValues = [
922
- "$1",
923
- ...placed.map((c) => c.expr),
924
- "now()"
925
- ].join(", ");
926
- const setClauses = [...placed.map((c) => `${c.name} = ${c.expr}`), "updated_at = now()"].join(", ");
927
- return {
928
- insert: {
929
- sql: `insert into prisma_contract.marker (${insertColumns}) values (${insertValues})`,
930
- params
931
- },
932
- update: {
933
- sql: `update prisma_contract.marker set ${setClauses} where space = $1`,
934
- params
935
- }
936
- };
937
- }
938
- //#endregion
939
856
  //#region src/codecs/decoding.ts
940
857
  const WIRE_PREVIEW_LIMIT = 100;
941
858
  const EMPTY_INCLUDE_ALIASES = /* @__PURE__ */ new Set();
@@ -1085,67 +1002,6 @@ async function decodeRow(row, decodeCtx, rowCtx) {
1085
1002
  return decoded;
1086
1003
  }
1087
1004
  //#endregion
1088
- //#region src/codecs/encoding.ts
1089
- const NO_METADATA = Object.freeze({
1090
- codec: void 0,
1091
- name: void 0
1092
- });
1093
- function deriveParamMetadata(ast) {
1094
- return collectOrderedParamRefs(ast).map((ref) => {
1095
- return {
1096
- codec: ref.codec,
1097
- name: ref.name
1098
- };
1099
- });
1100
- }
1101
- function resolveParamCodec(metadata, contractCodecs) {
1102
- if (metadata.codec && contractCodecs) return contractCodecs.forCodecRef(metadata.codec);
1103
- }
1104
- function paramLabel(metadata, paramIndex) {
1105
- return metadata.name ?? `param[${paramIndex}]`;
1106
- }
1107
- function wrapEncodeFailure(error, metadata, paramIndex, codecId) {
1108
- const label = paramLabel(metadata, paramIndex);
1109
- const wrapped = runtimeError("RUNTIME.ENCODE_FAILED", `Failed to encode parameter ${label} with codec '${codecId}': ${error instanceof Error ? error.message : String(error)}`, {
1110
- label,
1111
- codec: codecId,
1112
- paramIndex
1113
- });
1114
- wrapped.cause = error;
1115
- throw wrapped;
1116
- }
1117
- async function encodeParamValue(value, metadata, paramIndex, ctx, contractCodecs) {
1118
- if (value === null || value === void 0) return null;
1119
- const codec = resolveParamCodec(metadata, contractCodecs);
1120
- if (!codec) return value;
1121
- try {
1122
- return await codec.encode(value, ctx);
1123
- } catch (error) {
1124
- if (isRuntimeError(error)) throw error;
1125
- wrapEncodeFailure(error, metadata, paramIndex, codec.id);
1126
- }
1127
- }
1128
- /**
1129
- * Encodes all parameters concurrently via `Promise.all`. Per parameter, sync-and async-authored codecs share the same path: `codec.encode → await → return`. Param-level failures are wrapped in `RUNTIME.ENCODE_FAILED`.
1130
- *
1131
- * When `ctx.signal` is provided:
1132
- *
1133
- * - **Already-aborted at entry** short-circuits with `RUNTIME.ABORTED` (`{ phase: 'encode' }`) before any `codec.encode` call is made — codecs can pin this with a per-call counter that stays at zero.
1134
- * - **Mid-flight abort** races the per-param `Promise.all` against `abortable(ctx.signal)`. The runtime returns `RUNTIME.ABORTED` promptly even if codec bodies ignore the signal; the in-flight bodies are abandoned and run to completion in the background (cooperative cancellation, see ADR 204).
1135
- * - Existing `RUNTIME.ENCODE_FAILED` envelopes that surface from a codec body before the runtime observes the abort pass through unchanged (no double wrap).
1136
- */
1137
- async function encodeParams(plan, ctx, contractCodecs) {
1138
- return encodeParamsWithMetadata(plan.params, deriveParamMetadata(plan.ast), ctx, contractCodecs);
1139
- }
1140
- async function encodeParamsWithMetadata(values, metadata, ctx, contractCodecs) {
1141
- checkAborted(ctx, "encode");
1142
- const signal = ctx.signal;
1143
- if (values.length === 0) return values;
1144
- const tasks = values.map((value, i) => encodeParamValue(value, metadata[i] ?? NO_METADATA, i, ctx, contractCodecs));
1145
- const settled = await raceAgainstAbort(Promise.all(tasks), signal, "encode");
1146
- return Object.freeze(settled);
1147
- }
1148
- //#endregion
1149
1005
  //#region src/content-hash.ts
1150
1006
  /**
1151
1007
  * Computes a stable content hash for a lowered SQL execution plan.
@@ -1778,6 +1634,6 @@ function createRuntime(options) {
1778
1634
  });
1779
1635
  }
1780
1636
  //#endregion
1781
- export { ensureTableStatement as a, createExecutionContext as c, budgets as d, parseContractMarkerRow as f, validateContractCodecMappings as g, validateCodecRegistryCompleteness as h, ensureSchemaStatement as i, createSqlExecutionStack as l, extractCodecIds as m, withTransaction as n, readContractMarker as o, lowerSqlPlan as p, APP_SPACE_ID as r, writeContractMarker as s, createRuntime as t, lints as u };
1637
+ export { lints as a, extractCodecIds as c, deriveParamMetadata as d, encodeParamsWithMetadata as f, createSqlExecutionStack as i, validateCodecRegistryCompleteness as l, withTransaction as n, budgets as o, createAstCodecRegistry as p, createExecutionContext as r, lowerSqlPlan as s, createRuntime as t, validateContractCodecMappings as u };
1782
1638
 
1783
- //# sourceMappingURL=exports-CXYd2w6k.mjs.map
1639
+ //# sourceMappingURL=exports-tEA99Uhc.mjs.map