@prisma-next/sql-runtime 0.5.0-dev.30 → 0.5.0-dev.31

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.
@@ -2,6 +2,7 @@ import { AsyncIterableResult, RuntimeCore, checkAborted, checkMiddlewareCompatib
2
2
  import { type } from "arktype";
3
3
  import { collectOrderedParamRefs, createCodecRegistry, isQueryAst } from "@prisma-next/sql-relational-core/ast";
4
4
  import { ifDefined } from "@prisma-next/utils/defined";
5
+ import { synthesizeNonParameterizedDescriptor } from "@prisma-next/framework-components/codec";
5
6
  import { checkContractComponentRequirements } from "@prisma-next/framework-components/components";
6
7
  import { createExecutionStack } from "@prisma-next/framework-components/execution";
7
8
  import { createSqlOperationRegistry } from "@prisma-next/sql-operations";
@@ -25,10 +26,17 @@ function extractCodecIdsFromColumns(contract) {
25
26
  }
26
27
  return codecIds;
27
28
  }
29
+ function adaptDescriptorRegistry(registry) {
30
+ return { has: (id) => registry.descriptorFor(id) !== void 0 };
31
+ }
32
+ function isDescriptorRegistry(registry) {
33
+ return "descriptorFor" in registry;
34
+ }
28
35
  function validateContractCodecMappings(registry, contract) {
36
+ const lookup = isDescriptorRegistry(registry) ? adaptDescriptorRegistry(registry) : registry;
29
37
  const codecIds = extractCodecIdsFromColumns(contract);
30
38
  const invalidCodecs = [];
31
- for (const [key, codecId] of codecIds.entries()) if (!registry.has(codecId)) {
39
+ for (const [key, codecId] of codecIds.entries()) if (!lookup.has(codecId)) {
32
40
  const parts = key.split(".");
33
41
  const table = parts[0] ?? "";
34
42
  const column = parts[1] ?? "";
@@ -437,16 +445,21 @@ function assertExecutionStackContractRequirements(contract, stack) {
437
445
  }
438
446
  }
439
447
  function validateTypeParams(typeParams, codecDescriptor, context) {
440
- const result = codecDescriptor.paramsSchema(typeParams);
441
- if (result instanceof type.errors) {
442
- const messages = result.map((p) => p.message).join("; ");
448
+ const result = codecDescriptor.paramsSchema["~standard"].validate(typeParams);
449
+ if (result instanceof Promise) throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `paramsSchema for codec '${codecDescriptor.codecId}' returned a Promise; runtime validation requires a synchronous Standard Schema validator.`, {
450
+ ...context,
451
+ codecId: codecDescriptor.codecId,
452
+ typeParams
453
+ });
454
+ if (result.issues) {
455
+ const messages = result.issues.map((issue) => issue.message).join("; ");
443
456
  throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `Invalid typeParams for ${context.typeName ? `type '${context.typeName}'` : `column '${context.tableName}.${context.columnName}'`} (codecId: ${codecDescriptor.codecId}): ${messages}`, {
444
457
  ...context,
445
458
  codecId: codecDescriptor.codecId,
446
459
  typeParams
447
460
  });
448
461
  }
449
- return result;
462
+ return result.value;
450
463
  }
451
464
  function collectParameterizedCodecDescriptors(contributors) {
452
465
  const descriptors = /* @__PURE__ */ new Map();
@@ -456,16 +469,76 @@ function collectParameterizedCodecDescriptors(contributors) {
456
469
  }
457
470
  return descriptors;
458
471
  }
459
- function initializeTypeHelpers(storageTypes, codecDescriptors) {
472
+ /**
473
+ * Build the unified descriptor map. Combines parameterized descriptors
474
+ * (which already ship as `CodecDescriptor`s) with synthesized descriptors
475
+ * for non-parameterized codecs registered through the legacy `codecs:`
476
+ * slot. Codec ids that ship a parameterized descriptor take precedence —
477
+ * even when the legacy registry registers a representative codec under
478
+ * the same id, the parameterized descriptor is the authoritative source.
479
+ *
480
+ * Codec-registry-unification spec § Decision: every codec resolves
481
+ * through one descriptor map; reads are non-branching.
482
+ */
483
+ function buildCodecDescriptorRegistry(codecRegistry, parameterizedDescriptors) {
484
+ const byId = /* @__PURE__ */ new Map();
485
+ const byTargetType = /* @__PURE__ */ new Map();
486
+ function registerInIndices(descriptor) {
487
+ byId.set(descriptor.codecId, descriptor);
488
+ for (const targetType of descriptor.targetTypes) {
489
+ const list = byTargetType.get(targetType);
490
+ if (list) list.push(descriptor);
491
+ else byTargetType.set(targetType, [descriptor]);
492
+ }
493
+ }
494
+ for (const descriptor of parameterizedDescriptors.values()) registerInIndices(descriptor);
495
+ for (const codec$1 of codecRegistry.values()) {
496
+ if (byId.has(codec$1.id)) continue;
497
+ registerInIndices(synthesizeNonParameterizedDescriptor(codec$1));
498
+ }
499
+ return {
500
+ descriptorFor(codecId) {
501
+ return byId.get(codecId);
502
+ },
503
+ *values() {
504
+ yield* byId.values();
505
+ },
506
+ byTargetType(targetType) {
507
+ return byTargetType.get(targetType) ?? Object.freeze([]);
508
+ }
509
+ };
510
+ }
511
+ function collectTypeRefSites(storage) {
512
+ const sites = /* @__PURE__ */ new Map();
513
+ for (const [tableName, table] of Object.entries(storage.tables)) for (const [columnName, column] of Object.entries(table.columns)) {
514
+ if (typeof column.typeRef !== "string") continue;
515
+ const list = sites.get(column.typeRef);
516
+ const entry = {
517
+ table: tableName,
518
+ column: columnName
519
+ };
520
+ if (list) list.push(entry);
521
+ else sites.set(column.typeRef, [entry]);
522
+ }
523
+ return sites;
524
+ }
525
+ function initializeTypeHelpers(storage, codecDescriptors) {
460
526
  const helpers = {};
527
+ const storageTypes = storage.types;
461
528
  if (!storageTypes) return helpers;
529
+ const typeRefSites = collectTypeRefSites(storage);
462
530
  for (const [typeName, typeInstance] of Object.entries(storageTypes)) {
463
531
  const descriptor = codecDescriptors.get(typeInstance.codecId);
464
- if (descriptor) {
465
- const validatedParams = validateTypeParams(typeInstance.typeParams, descriptor, { typeName });
466
- if (descriptor.init) helpers[typeName] = descriptor.init(validatedParams);
467
- else helpers[typeName] = typeInstance;
468
- } else helpers[typeName] = typeInstance;
532
+ if (!descriptor) {
533
+ helpers[typeName] = typeInstance;
534
+ continue;
535
+ }
536
+ const validatedParams = validateTypeParams(typeInstance.typeParams, descriptor, { typeName });
537
+ const ctx = {
538
+ name: typeName,
539
+ usedAt: typeRefSites.get(typeName) ?? []
540
+ };
541
+ helpers[typeName] = descriptor.factory(validatedParams)(ctx);
469
542
  }
470
543
  return helpers;
471
544
  }
@@ -478,39 +551,115 @@ function validateColumnTypeParams(storage, codecDescriptors) {
478
551
  });
479
552
  }
480
553
  }
554
+ function hasJsonValidatorTrait(candidate) {
555
+ if (candidate === null || typeof candidate !== "object") return false;
556
+ const traits = candidate.traits;
557
+ if (!Array.isArray(traits)) return false;
558
+ if (!traits.includes("json-validator")) return false;
559
+ return typeof candidate.validate === "function";
560
+ }
561
+ function extractValidator(candidate) {
562
+ return hasJsonValidatorTrait(candidate) ? candidate.validate : void 0;
563
+ }
564
+ function isResolvedCodec(candidate) {
565
+ return candidate !== null && typeof candidate === "object" && "id" in candidate && "decode" in candidate;
566
+ }
481
567
  /**
482
- * Builds a registry of compiled JSON Schema validators by scanning the contract
483
- * for columns whose codec descriptor provides an `init` hook returning `{ validate }`.
568
+ * Walk the contract's `storage.tables[].columns[]` and resolve each
569
+ * column to a `Codec` through the unified descriptor map. Per-instance
570
+ * behavior:
484
571
  *
485
- * Handles both:
486
- * - Inline `typeParams.schema` on columns
487
- * - `typeRef` `storage.types[ref]` with init hook results already in `types` registry
572
+ * - **typeRef columns**: reuse the resolved codec materialized once by
573
+ * `initializeTypeHelpers` for the `storage.types` entry. Multiple
574
+ * columns sharing one typeRef share one codec instance.
575
+ * - **inline-typeParams columns**: call `descriptor.factory(typeParams)
576
+ * (ctx)` once per column (per-column anonymous instance).
577
+ * - **non-parameterized columns**: call `descriptor.factory()(ctx)`
578
+ * once. The synthesized descriptor's factory is constant — every call
579
+ * returns the same shared codec instance — so columns sharing a non-
580
+ * parameterized codec id share one resolved codec without explicit
581
+ * caching.
582
+ *
583
+ * Combines what `initializeTypeHelpers` (named-instance walk) and the
584
+ * old `buildJsonSchemaValidatorRegistry` (per-column walk) used to do
585
+ * separately: one walk over all columns, one resolved codec per column,
586
+ * one trait-gated validator extraction per column. The result drives
587
+ * both the dispatch registry (`ContractCodecRegistry.forColumn`) and the
588
+ * validator registry.
589
+ *
590
+ * Codec-registry-unification spec § AC-4: every column resolves through
591
+ * one descriptor map without branching on parameterization.
488
592
  */
489
- function buildJsonSchemaValidatorRegistry(contract, types, codecDescriptors) {
593
+ function buildContractCodecRegistry(contract, codecDescriptors, legacyCodecRegistry, types, parameterizedDescriptors) {
594
+ const byColumn = /* @__PURE__ */ new Map();
595
+ const byCodecId = /* @__PURE__ */ new Map();
596
+ const ambiguousCodecIds = /* @__PURE__ */ new Set();
490
597
  const validators = /* @__PURE__ */ new Map();
491
- const codecIdsWithInit = /* @__PURE__ */ new Set();
492
- for (const [codecId, descriptor] of codecDescriptors) if (descriptor.init) codecIdsWithInit.add(codecId);
493
- if (codecIdsWithInit.size === 0) return;
494
598
  for (const [tableName, table] of Object.entries(contract.storage.tables)) for (const [columnName, column] of Object.entries(table.columns)) {
495
- if (!codecIdsWithInit.has(column.codecId)) continue;
496
- const key = `${tableName}.${columnName}`;
497
- if (column.typeRef) {
498
- const helper = types[column.typeRef];
499
- if (helper?.validate) validators.set(key, helper.validate);
500
- continue;
501
- }
502
- if (column.typeParams) {
503
- const descriptor = codecDescriptors.get(column.codecId);
504
- if (descriptor?.init) {
505
- const helper = descriptor.init(column.typeParams);
506
- if (helper?.validate) validators.set(key, helper.validate);
599
+ const columnKey = `${tableName}.${columnName}`;
600
+ const descriptor = codecDescriptors.descriptorFor(column.codecId);
601
+ let resolvedCodec;
602
+ if (descriptor) {
603
+ const isParameterized = parameterizedDescriptors.has(column.codecId);
604
+ if (column.typeRef) {
605
+ const helper = types[column.typeRef];
606
+ if (isResolvedCodec(helper)) resolvedCodec = helper;
607
+ } else if (column.typeParams && isParameterized) {
608
+ const parameterizedDescriptor = parameterizedDescriptors.get(column.codecId);
609
+ if (parameterizedDescriptor) {
610
+ const validatedParams = validateTypeParams(column.typeParams, parameterizedDescriptor, {
611
+ tableName,
612
+ columnName
613
+ });
614
+ const ctx = {
615
+ name: `<anon:${tableName}.${columnName}>`,
616
+ usedAt: [{
617
+ table: tableName,
618
+ column: columnName
619
+ }]
620
+ };
621
+ resolvedCodec = parameterizedDescriptor.factory(validatedParams)(ctx);
622
+ }
623
+ } else if (!isParameterized) {
624
+ let cached = byCodecId.get(column.codecId);
625
+ if (!cached) {
626
+ const ctx = {
627
+ name: `<shared:${column.codecId}>`,
628
+ usedAt: [{
629
+ table: tableName,
630
+ column: columnName
631
+ }]
632
+ };
633
+ const voidFactory = descriptor.factory;
634
+ cached = voidFactory(void 0)(ctx);
635
+ byCodecId.set(column.codecId, cached);
636
+ }
637
+ resolvedCodec = cached;
507
638
  }
508
639
  }
640
+ if (resolvedCodec) {
641
+ byColumn.set(columnKey, resolvedCodec);
642
+ const validate = extractValidator(resolvedCodec);
643
+ if (validate) validators.set(columnKey, validate);
644
+ const existing = byCodecId.get(column.codecId);
645
+ if (existing === void 0) byCodecId.set(column.codecId, resolvedCodec);
646
+ else if (existing !== resolvedCodec && parameterizedDescriptors.has(column.codecId)) ambiguousCodecIds.add(column.codecId);
647
+ }
509
648
  }
510
- if (validators.size === 0) return void 0;
511
649
  return {
512
- get: (key) => validators.get(key),
513
- size: validators.size
650
+ registry: {
651
+ forColumn(table, column) {
652
+ return byColumn.get(`${table}.${column}`);
653
+ },
654
+ forCodecId(codecId) {
655
+ if (ambiguousCodecIds.has(codecId)) throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `Codec '${codecId}' resolves to multiple parameterized instances; column-aware dispatch is required.`, { codecId });
656
+ return byCodecId.get(codecId) ?? legacyCodecRegistry.get(codecId);
657
+ }
658
+ },
659
+ jsonValidators: validators.size > 0 ? {
660
+ get: (key) => validators.get(key),
661
+ size: validators.size
662
+ } : void 0
514
663
  };
515
664
  }
516
665
  function collectMutationDefaultGenerators(contributors) {
@@ -572,13 +721,16 @@ function createExecutionContext(options) {
572
721
  const queryOperationRegistry = createSqlOperationRegistry();
573
722
  for (const contributor of contributors) for (const op of contributor.queryOperations?.() ?? []) queryOperationRegistry.register(op);
574
723
  const parameterizedCodecDescriptors = collectParameterizedCodecDescriptors(contributors);
724
+ const codecDescriptors = buildCodecDescriptorRegistry(codecRegistry, parameterizedCodecDescriptors);
575
725
  const mutationDefaultGeneratorRegistry = collectMutationDefaultGenerators(contributors);
576
726
  if (parameterizedCodecDescriptors.size > 0) validateColumnTypeParams(contract.storage, parameterizedCodecDescriptors);
577
- const types = initializeTypeHelpers(contract.storage.types, parameterizedCodecDescriptors);
578
- const jsonSchemaValidators = buildJsonSchemaValidatorRegistry(contract, types, parameterizedCodecDescriptors);
727
+ const types = initializeTypeHelpers(contract.storage, parameterizedCodecDescriptors);
728
+ const { registry: contractCodecs, jsonValidators: jsonSchemaValidators } = buildContractCodecRegistry(contract, codecDescriptors, codecRegistry, types, parameterizedCodecDescriptors);
579
729
  return {
580
730
  contract,
581
731
  codecs: codecRegistry,
732
+ contractCodecs,
733
+ codecDescriptors,
582
734
  queryOperations: queryOperationRegistry,
583
735
  types,
584
736
  ...jsonSchemaValidators ? { jsonSchemaValidators } : {},
@@ -740,7 +892,35 @@ function projectionListFromAst(ast) {
740
892
  if (ast.kind === "select") return ast.projection;
741
893
  return ast.returning;
742
894
  }
743
- function buildDecodeContext(plan, registry) {
895
+ /**
896
+ * Resolve the per-cell codec for a projection item.
897
+ *
898
+ * Phase B: when a `(table, column)` ref is available for the projection,
899
+ * prefer `contractCodecs.forColumn(table, column)` — that's the per-
900
+ * instance resolved codec materialized from the codec descriptor's
901
+ * factory at context-construction time (carries any per-instance state
902
+ * such as the compiled JSON-Schema validator). When the projection
903
+ * resolves to a non-`column-ref` expression (computed projections, raw
904
+ * SQL aliases) but still carries a codec id (ADR 205 stamps every
905
+ * `ProjectionItem` with the producer's codec id), fall back to the
906
+ * codec-id-keyed `forCodecId(codecId)` lookup, which itself falls back
907
+ * to the legacy `CodecRegistry` for codec ids the contract walk
908
+ * couldn't resolve.
909
+ *
910
+ * Codec-registry-unification spec § AC-4.
911
+ */
912
+ function resolveProjectionCodec(item, registry, contractCodecs) {
913
+ if (item.expr.kind === "column-ref" && contractCodecs) {
914
+ const byColumn = contractCodecs.forColumn(item.expr.table, item.expr.column);
915
+ if (byColumn) return byColumn;
916
+ }
917
+ if (item.codecId) {
918
+ const fromContract = contractCodecs?.forCodecId(item.codecId);
919
+ if (fromContract) return fromContract;
920
+ return registry.get(item.codecId);
921
+ }
922
+ }
923
+ function buildDecodeContext(plan, registry, contractCodecs) {
744
924
  if (!isAstBackedPlan(plan)) return {
745
925
  aliases: void 0,
746
926
  codecs: /* @__PURE__ */ new Map(),
@@ -760,10 +940,8 @@ function buildDecodeContext(plan, registry) {
760
940
  const includeAliases = /* @__PURE__ */ new Set();
761
941
  for (const item of projection) {
762
942
  aliases.push(item.alias);
763
- if (item.codecId) {
764
- const codec$1 = registry.get(item.codecId);
765
- if (codec$1) codecs.set(item.alias, codec$1);
766
- }
943
+ const codec$1 = resolveProjectionCodec(item, registry, contractCodecs);
944
+ if (codec$1) codecs.set(item.alias, codec$1);
767
945
  if (item.expr.kind === "column-ref") columnRefs.set(item.alias, {
768
946
  table: item.expr.table,
769
947
  column: item.expr.column
@@ -882,10 +1060,10 @@ async function decodeField(alias, wireValue, decodeCtx, jsonValidators, rowCtx)
882
1060
  * - Existing `RUNTIME.DECODE_FAILED` envelopes from codec bodies pass
883
1061
  * through unchanged (no double wrap).
884
1062
  */
885
- async function decodeRow(row, plan, registry, jsonValidators, rowCtx) {
1063
+ async function decodeRow(row, plan, registry, jsonValidators, rowCtx, contractCodecs) {
886
1064
  checkAborted(rowCtx, "decode");
887
1065
  const signal = rowCtx.signal;
888
- const decodeCtx = buildDecodeContext(plan, registry);
1066
+ const decodeCtx = buildDecodeContext(plan, registry, contractCodecs);
889
1067
  const aliases = decodeCtx.aliases ?? Object.keys(row);
890
1068
  if (decodeCtx.aliases !== void 0) {
891
1069
  for (const alias of decodeCtx.aliases) if (!Object.hasOwn(row, alias)) throw runtimeError("RUNTIME.DECODE_FAILED", `Row missing projection alias "${alias}"`, {
@@ -923,6 +1101,34 @@ const NO_METADATA = Object.freeze({
923
1101
  codecId: void 0,
924
1102
  name: void 0
925
1103
  });
1104
+ /**
1105
+ * Resolve the codec for an outgoing param.
1106
+ *
1107
+ * Phase B (and AC-5-deferred carve-out): `ParamRef` does not carry a
1108
+ * `(table, column)` ref today — every `ParamRef` carries `codecId` but
1109
+ * not the column it relates to. Encode-side dispatch therefore consults
1110
+ * `contractCodecs.forCodecId(codecId)` (which itself prefers the
1111
+ * contract-walk-derived shared codec, falling back to the legacy
1112
+ * `CodecRegistry.get` for parameterized codec ids whose contracts don't
1113
+ * have a column the walk could resolve through).
1114
+ *
1115
+ * For the parameterized codecs shipped at Phase B (pgvector, postgres
1116
+ * json/jsonb), encode is per-instance-stateless w.r.t. params:
1117
+ * - pgvector formats `[v1,v2,...]` regardless of declared length;
1118
+ * - postgres json/jsonb encode is `JSON.stringify` regardless of schema.
1119
+ *
1120
+ * So the codec-id-keyed lookup yields a structurally equivalent encoder
1121
+ * even when the resolved per-instance codec carries extra state (e.g. a
1122
+ * compiled JSON-Schema validator used only by `decode`). TML-2357 retires
1123
+ * the fallback by threading `ParamRef.refs` through column-bound
1124
+ * construction sites.
1125
+ */
1126
+ function resolveParamCodec(metadata, registry, contractCodecs) {
1127
+ if (!metadata.codecId) return void 0;
1128
+ const fromContract = contractCodecs?.forCodecId(metadata.codecId);
1129
+ if (fromContract) return fromContract;
1130
+ return registry.get(metadata.codecId);
1131
+ }
926
1132
  function paramLabel(metadata, paramIndex) {
927
1133
  return metadata.name ?? `param[${paramIndex}]`;
928
1134
  }
@@ -936,10 +1142,9 @@ function wrapEncodeFailure(error, metadata, paramIndex, codecId) {
936
1142
  wrapped.cause = error;
937
1143
  throw wrapped;
938
1144
  }
939
- async function encodeParamValue(value, metadata, paramIndex, registry, ctx) {
1145
+ async function encodeParamValue(value, metadata, paramIndex, registry, ctx, contractCodecs) {
940
1146
  if (value === null || value === void 0) return null;
941
- if (!metadata.codecId) return value;
942
- const codec$1 = registry.get(metadata.codecId);
1147
+ const codec$1 = resolveParamCodec(metadata, registry, contractCodecs);
943
1148
  if (!codec$1) return value;
944
1149
  try {
945
1150
  return await codec$1.encode(value, ctx);
@@ -966,7 +1171,7 @@ async function encodeParamValue(value, metadata, paramIndex, registry, ctx) {
966
1171
  * body before the runtime observes the abort pass through unchanged
967
1172
  * (no double wrap).
968
1173
  */
969
- async function encodeParams(plan, registry, ctx) {
1174
+ async function encodeParams(plan, registry, ctx, contractCodecs) {
970
1175
  checkAborted(ctx, "encode");
971
1176
  const signal = ctx.signal;
972
1177
  if (plan.params.length === 0) return plan.params;
@@ -983,7 +1188,7 @@ async function encodeParams(plan, registry, ctx) {
983
1188
  }
984
1189
  }
985
1190
  const tasks = new Array(paramCount);
986
- for (let i = 0; i < paramCount; i++) tasks[i] = encodeParamValue(plan.params[i], metadata[i] ?? NO_METADATA, i, registry, ctx);
1191
+ for (let i = 0; i < paramCount; i++) tasks[i] = encodeParamValue(plan.params[i], metadata[i] ?? NO_METADATA, i, registry, ctx, contractCodecs);
987
1192
  const settled = await raceAgainstAbort(Promise.all(tasks), signal, "encode");
988
1193
  return Object.freeze(settled);
989
1194
  }
@@ -1057,6 +1262,8 @@ var SqlRuntimeImpl = class extends RuntimeCore {
1057
1262
  driver;
1058
1263
  familyAdapter;
1059
1264
  codecRegistry;
1265
+ contractCodecs;
1266
+ codecDescriptors;
1060
1267
  jsonSchemaValidators;
1061
1268
  sqlCtx;
1062
1269
  verify;
@@ -1086,6 +1293,8 @@ var SqlRuntimeImpl = class extends RuntimeCore {
1086
1293
  this.driver = driver;
1087
1294
  this.familyAdapter = new SqlFamilyAdapter(context.contract, adapter.profile);
1088
1295
  this.codecRegistry = context.codecs;
1296
+ this.contractCodecs = context.contractCodecs;
1297
+ this.codecDescriptors = context.codecDescriptors;
1089
1298
  this.jsonSchemaValidators = context.jsonSchemaValidators;
1090
1299
  this.sqlCtx = sqlCtx;
1091
1300
  this.verify = verify;
@@ -1094,7 +1303,7 @@ var SqlRuntimeImpl = class extends RuntimeCore {
1094
1303
  this.startupVerified = false;
1095
1304
  this._telemetry = null;
1096
1305
  if (verify.mode === "startup") {
1097
- validateCodecRegistryCompleteness(this.codecRegistry, context.contract);
1306
+ validateCodecRegistryCompleteness(this.codecDescriptors, context.contract);
1098
1307
  this.codecRegistryValidated = true;
1099
1308
  }
1100
1309
  }
@@ -1113,7 +1322,7 @@ var SqlRuntimeImpl = class extends RuntimeCore {
1113
1322
  const lowered = lowerSqlPlan(this.adapter, this.contract, plan);
1114
1323
  return Object.freeze({
1115
1324
  ...lowered,
1116
- params: await encodeParams(lowered, this.codecRegistry, ctx)
1325
+ params: await encodeParams(lowered, this.codecRegistry, ctx, this.contractCodecs)
1117
1326
  });
1118
1327
  }
1119
1328
  /**
@@ -1160,7 +1369,7 @@ var SqlRuntimeImpl = class extends RuntimeCore {
1160
1369
  checkAborted(codecCtx, "stream");
1161
1370
  const exec = isExecutionPlan(plan) ? Object.freeze({
1162
1371
  ...plan,
1163
- params: await encodeParams(plan, self.codecRegistry, codecCtx)
1372
+ params: await encodeParams(plan, self.codecRegistry, codecCtx, self.contractCodecs)
1164
1373
  }) : await self.lower(await self.runBeforeCompile(plan), codecCtx);
1165
1374
  self.familyAdapter.validatePlan(exec, self.contract);
1166
1375
  self._telemetry = null;
@@ -1179,7 +1388,7 @@ var SqlRuntimeImpl = class extends RuntimeCore {
1179
1388
  checkAborted(codecCtx, "stream");
1180
1389
  const next = await iterator.next();
1181
1390
  if (next.done) break;
1182
- yield await decodeRow(next.value, exec, self.codecRegistry, self.jsonSchemaValidators, codecCtx);
1391
+ yield await decodeRow(next.value, exec, self.codecRegistry, self.jsonSchemaValidators, codecCtx, self.contractCodecs);
1183
1392
  }
1184
1393
  } finally {
1185
1394
  await iterator.return?.();
@@ -1235,7 +1444,7 @@ var SqlRuntimeImpl = class extends RuntimeCore {
1235
1444
  }
1236
1445
  ensureCodecRegistryValidated() {
1237
1446
  if (!this.codecRegistryValidated) {
1238
- validateCodecRegistryCompleteness(this.codecRegistry, this.contract);
1447
+ validateCodecRegistryCompleteness(this.codecDescriptors, this.contract);
1239
1448
  this.codecRegistryValidated = true;
1240
1449
  }
1241
1450
  }
@@ -1352,4 +1561,4 @@ function createRuntime(options) {
1352
1561
 
1353
1562
  //#endregion
1354
1563
  export { readContractMarker as a, createSqlExecutionStack as c, parseContractMarkerRow as d, lowerSqlPlan as f, validateContractCodecMappings as h, ensureTableStatement as i, lints as l, validateCodecRegistryCompleteness as m, withTransaction as n, writeContractMarker as o, extractCodecIds as p, ensureSchemaStatement as r, createExecutionContext as s, createRuntime as t, budgets as u };
1355
- //# sourceMappingURL=exports-Cq_9ZrU4.mjs.map
1564
+ //# sourceMappingURL=exports-CrHMfIKo.mjs.map