@prisma-next/sql-runtime 0.3.0-dev.33 → 0.3.0-dev.36
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 +115 -24
- package/dist/exports-C8hi0N-a.mjs +622 -0
- package/dist/exports-C8hi0N-a.mjs.map +1 -0
- package/dist/index-SlQIrV_t.d.mts +131 -0
- package/dist/index-SlQIrV_t.d.mts.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +3 -0
- package/dist/test/utils.d.mts +82 -0
- package/dist/test/utils.d.mts.map +1 -0
- package/dist/test/utils.mjs +212 -0
- package/dist/test/utils.mjs.map +1 -0
- package/package.json +26 -20
- package/src/codecs/decoding.ts +84 -3
- package/src/codecs/encoding.ts +15 -2
- package/src/codecs/json-schema-validation.ts +61 -0
- package/src/exports/index.ts +9 -4
- package/src/lower-sql-plan.ts +8 -8
- package/src/sql-context.ts +286 -245
- package/src/sql-family-adapter.ts +9 -5
- package/src/sql-marker.ts +2 -2
- package/src/sql-runtime.ts +89 -23
- package/test/async-iterable-result.test.ts +42 -34
- package/test/context.types.test-d.ts +12 -14
- package/test/execution-stack.test.ts +166 -0
- package/test/json-schema-validation.test.ts +653 -0
- package/test/parameterized-types.test.ts +182 -196
- package/test/sql-context.test.ts +292 -117
- package/test/sql-family-adapter.test.ts +7 -6
- package/test/sql-runtime.test.ts +117 -31
- package/test/utils.ts +76 -50
- package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js +0 -137863
- package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js.map +0 -1
- package/dist/amcheck-24VY6X5V.js +0 -13
- package/dist/amcheck-24VY6X5V.js.map +0 -1
- package/dist/bloom-VS74NLHT.js +0 -13
- package/dist/bloom-VS74NLHT.js.map +0 -1
- package/dist/btree_gin-WBC4EAAI.js +0 -13
- package/dist/btree_gin-WBC4EAAI.js.map +0 -1
- package/dist/btree_gist-UNC6QD3M.js +0 -13
- package/dist/btree_gist-UNC6QD3M.js.map +0 -1
- package/dist/chunk-3KTOEDFX.js +0 -49
- package/dist/chunk-3KTOEDFX.js.map +0 -1
- package/dist/chunk-47DZBRQC.js +0 -1280
- package/dist/chunk-47DZBRQC.js.map +0 -1
- package/dist/chunk-52N6AFZM.js +0 -133
- package/dist/chunk-52N6AFZM.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-7D4SUZUM.js.map +0 -1
- package/dist/chunk-APA6GHYY.js +0 -537
- package/dist/chunk-APA6GHYY.js.map +0 -1
- package/dist/chunk-ECWIHLAT.js +0 -37
- package/dist/chunk-ECWIHLAT.js.map +0 -1
- package/dist/chunk-EI626SDC.js +0 -105
- package/dist/chunk-EI626SDC.js.map +0 -1
- package/dist/chunk-UKKOYUGL.js +0 -578
- package/dist/chunk-UKKOYUGL.js.map +0 -1
- package/dist/chunk-XPLNMXQV.js +0 -1537
- package/dist/chunk-XPLNMXQV.js.map +0 -1
- package/dist/citext-T7MXGUY7.js +0 -13
- package/dist/citext-T7MXGUY7.js.map +0 -1
- package/dist/client-5FENX6AW.js +0 -299
- package/dist/client-5FENX6AW.js.map +0 -1
- package/dist/cube-TFDQBZCI.js +0 -13
- package/dist/cube-TFDQBZCI.js.map +0 -1
- package/dist/dict_int-AEUOPGWP.js +0 -13
- package/dist/dict_int-AEUOPGWP.js.map +0 -1
- package/dist/dict_xsyn-DAAYX3FL.js +0 -13
- package/dist/dict_xsyn-DAAYX3FL.js.map +0 -1
- package/dist/dist-AQ3LWXOX.js +0 -570
- package/dist/dist-AQ3LWXOX.js.map +0 -1
- package/dist/dist-LBVX6BJW.js +0 -189
- package/dist/dist-LBVX6BJW.js.map +0 -1
- package/dist/dist-WLKUVDN2.js +0 -5127
- package/dist/dist-WLKUVDN2.js.map +0 -1
- package/dist/earthdistance-KIGTF4LE.js +0 -13
- package/dist/earthdistance-KIGTF4LE.js.map +0 -1
- package/dist/file_fdw-5N55UP6I.js +0 -13
- package/dist/file_fdw-5N55UP6I.js.map +0 -1
- package/dist/fuzzystrmatch-KN3YWBFP.js +0 -13
- package/dist/fuzzystrmatch-KN3YWBFP.js.map +0 -1
- package/dist/hstore-YX726NKN.js +0 -13
- package/dist/hstore-YX726NKN.js.map +0 -1
- package/dist/http-exception-FZY2H4OF.js +0 -8
- package/dist/http-exception-FZY2H4OF.js.map +0 -1
- package/dist/index.js +0 -30
- package/dist/index.js.map +0 -1
- package/dist/intarray-NKVXNO2D.js +0 -13
- package/dist/intarray-NKVXNO2D.js.map +0 -1
- package/dist/isn-FTEMJGEV.js +0 -13
- package/dist/isn-FTEMJGEV.js.map +0 -1
- package/dist/lo-DB7L4NGI.js +0 -13
- package/dist/lo-DB7L4NGI.js.map +0 -1
- package/dist/logger-WQ7SHNDD.js +0 -68
- package/dist/logger-WQ7SHNDD.js.map +0 -1
- package/dist/ltree-Z32TZT6W.js +0 -13
- package/dist/ltree-Z32TZT6W.js.map +0 -1
- package/dist/nodefs-NM46ACH7.js +0 -31
- package/dist/nodefs-NM46ACH7.js.map +0 -1
- package/dist/opfs-ahp-NJO33LVZ.js +0 -332
- package/dist/opfs-ahp-NJO33LVZ.js.map +0 -1
- package/dist/pageinspect-YP3IZR4X.js +0 -13
- package/dist/pageinspect-YP3IZR4X.js.map +0 -1
- package/dist/pg_buffercache-7TD5J2FB.js +0 -13
- package/dist/pg_buffercache-7TD5J2FB.js.map +0 -1
- package/dist/pg_dump-SG4KYBUB.js +0 -2492
- package/dist/pg_dump-SG4KYBUB.js.map +0 -1
- package/dist/pg_freespacemap-DZDNCPZK.js +0 -13
- package/dist/pg_freespacemap-DZDNCPZK.js.map +0 -1
- package/dist/pg_surgery-J2MUEWEP.js +0 -13
- package/dist/pg_surgery-J2MUEWEP.js.map +0 -1
- package/dist/pg_trgm-7VNQOYS6.js +0 -13
- package/dist/pg_trgm-7VNQOYS6.js.map +0 -1
- package/dist/pg_visibility-TTSIPHFL.js +0 -13
- package/dist/pg_visibility-TTSIPHFL.js.map +0 -1
- package/dist/pg_walinspect-KPFHSHRJ.js +0 -13
- package/dist/pg_walinspect-KPFHSHRJ.js.map +0 -1
- package/dist/proxy-signals-GUDAMDHV.js +0 -39
- package/dist/proxy-signals-GUDAMDHV.js.map +0 -1
- package/dist/seg-IYVDLE4O.js +0 -13
- package/dist/seg-IYVDLE4O.js.map +0 -1
- package/dist/src/codecs/decoding.d.ts +0 -4
- package/dist/src/codecs/decoding.d.ts.map +0 -1
- package/dist/src/codecs/encoding.d.ts +0 -5
- package/dist/src/codecs/encoding.d.ts.map +0 -1
- package/dist/src/codecs/validation.d.ts +0 -6
- package/dist/src/codecs/validation.d.ts.map +0 -1
- package/dist/src/exports/index.d.ts +0 -11
- package/dist/src/exports/index.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/lower-sql-plan.d.ts +0 -15
- package/dist/src/lower-sql-plan.d.ts.map +0 -1
- package/dist/src/sql-context.d.ts +0 -130
- package/dist/src/sql-context.d.ts.map +0 -1
- package/dist/src/sql-family-adapter.d.ts +0 -10
- package/dist/src/sql-family-adapter.d.ts.map +0 -1
- package/dist/src/sql-marker.d.ts +0 -22
- package/dist/src/sql-marker.d.ts.map +0 -1
- package/dist/src/sql-runtime.d.ts +0 -25
- package/dist/src/sql-runtime.d.ts.map +0 -1
- package/dist/tablefunc-EF4RCS7S.js +0 -13
- package/dist/tablefunc-EF4RCS7S.js.map +0 -1
- package/dist/tcn-3VT5BQYW.js +0 -13
- package/dist/tcn-3VT5BQYW.js.map +0 -1
- package/dist/test/utils.d.ts +0 -60
- package/dist/test/utils.d.ts.map +0 -1
- package/dist/test/utils.js +0 -24635
- package/dist/test/utils.js.map +0 -1
- package/dist/tiny-CW6F4GX6.js +0 -10
- package/dist/tiny-CW6F4GX6.js.map +0 -1
- package/dist/tsm_system_rows-ES7KNUQH.js +0 -13
- package/dist/tsm_system_rows-ES7KNUQH.js.map +0 -1
- package/dist/tsm_system_time-76WEIMBG.js +0 -13
- package/dist/tsm_system_time-76WEIMBG.js.map +0 -1
- package/dist/unaccent-7RYF3R64.js +0 -13
- package/dist/unaccent-7RYF3R64.js.map +0 -1
- package/dist/utility-Q5A254LJ-J4HTKZPT.js +0 -347
- package/dist/utility-Q5A254LJ-J4HTKZPT.js.map +0 -1
- package/dist/uuid_ossp-4ETE4FPE.js +0 -13
- package/dist/uuid_ossp-4ETE4FPE.js.map +0 -1
- package/dist/vector-74GPNV7V.js +0 -13
- package/dist/vector-74GPNV7V.js.map +0 -1
- package/src/index.ts +0 -1
package/src/sql-context.ts
CHANGED
|
@@ -1,220 +1,197 @@
|
|
|
1
|
+
import { checkContractComponentRequirements } from '@prisma-next/contract/framework-components';
|
|
2
|
+
import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';
|
|
3
|
+
import { createExecutionStack, type ExecutionStack } from '@prisma-next/core-execution-plane/stack';
|
|
1
4
|
import type {
|
|
2
5
|
RuntimeAdapterDescriptor,
|
|
3
6
|
RuntimeAdapterInstance,
|
|
7
|
+
RuntimeDriverDescriptor,
|
|
8
|
+
RuntimeDriverInstance,
|
|
4
9
|
RuntimeExtensionDescriptor,
|
|
5
10
|
RuntimeExtensionInstance,
|
|
6
11
|
RuntimeTargetDescriptor,
|
|
12
|
+
RuntimeTargetInstance,
|
|
7
13
|
} from '@prisma-next/core-execution-plane/types';
|
|
14
|
+
import { generateId } from '@prisma-next/ids/runtime';
|
|
8
15
|
import { createOperationRegistry } from '@prisma-next/operations';
|
|
16
|
+
import { runtimeError } from '@prisma-next/runtime-executor';
|
|
9
17
|
import type { SqlContract, SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types';
|
|
10
18
|
import type { SqlOperationSignature } from '@prisma-next/sql-operations';
|
|
11
19
|
import type {
|
|
12
20
|
Adapter,
|
|
21
|
+
CodecParamsDescriptor,
|
|
13
22
|
CodecRegistry,
|
|
14
23
|
LoweredStatement,
|
|
15
24
|
QueryAst,
|
|
25
|
+
SqlDriver,
|
|
16
26
|
} from '@prisma-next/sql-relational-core/ast';
|
|
17
27
|
import { createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
|
|
18
28
|
import type {
|
|
19
|
-
|
|
29
|
+
AppliedMutationDefault,
|
|
30
|
+
ExecutionContext,
|
|
31
|
+
JsonSchemaValidateFn,
|
|
32
|
+
JsonSchemaValidatorRegistry,
|
|
33
|
+
MutationDefaultsOptions,
|
|
20
34
|
TypeHelperRegistry,
|
|
21
35
|
} from '@prisma-next/sql-relational-core/query-lane-context';
|
|
22
|
-
import type { Type } from 'arktype';
|
|
23
36
|
import { type as arktype } from 'arktype';
|
|
24
37
|
|
|
25
|
-
// ============================================================================
|
|
26
|
-
// Runtime Parameterized Codec Descriptor Types
|
|
27
|
-
// ============================================================================
|
|
28
|
-
|
|
29
38
|
/**
|
|
30
39
|
* Runtime parameterized codec descriptor.
|
|
31
40
|
* Provides validation schema and optional init hook for codecs that support type parameters.
|
|
32
41
|
* Used at runtime to validate typeParams and create type helpers.
|
|
42
|
+
*
|
|
43
|
+
* This is a type alias for `CodecParamsDescriptor` from the AST layer,
|
|
44
|
+
* which is the shared definition used by both adapter and runtime.
|
|
33
45
|
*/
|
|
34
|
-
export
|
|
46
|
+
export type RuntimeParameterizedCodecDescriptor<
|
|
35
47
|
TParams = Record<string, unknown>,
|
|
36
48
|
THelper = unknown,
|
|
37
|
-
>
|
|
38
|
-
/** The codec ID this descriptor applies to (e.g., 'pg/vector@1') */
|
|
39
|
-
readonly codecId: string;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Arktype schema for validating typeParams.
|
|
43
|
-
* The schema is used to validate both storage.types entries and inline column typeParams.
|
|
44
|
-
*/
|
|
45
|
-
readonly paramsSchema: Type<TParams>;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Optional init hook called during runtime context creation.
|
|
49
|
-
* Receives validated params and returns a helper object to be stored in context.types.
|
|
50
|
-
* If not provided, the validated params are stored directly.
|
|
51
|
-
*/
|
|
52
|
-
readonly init?: (params: TParams) => THelper;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ============================================================================
|
|
56
|
-
// SQL Runtime Extension Types
|
|
57
|
-
// ============================================================================
|
|
49
|
+
> = CodecParamsDescriptor<TParams, THelper>;
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
* for contributing codecs and operations to the runtime context.
|
|
63
|
-
*
|
|
64
|
-
* @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
|
|
65
|
-
*/
|
|
66
|
-
export interface SqlRuntimeExtensionInstance<TTargetId extends string>
|
|
67
|
-
extends RuntimeExtensionInstance<'sql', TTargetId> {
|
|
68
|
-
/** Returns codecs to register in the runtime context. */
|
|
69
|
-
codecs?(): CodecRegistry;
|
|
70
|
-
/** Returns operations to register in the runtime context. */
|
|
71
|
-
operations?(): ReadonlyArray<SqlOperationSignature>;
|
|
72
|
-
/**
|
|
73
|
-
* Returns parameterized codec descriptors for type validation and helper creation.
|
|
74
|
-
* Uses unknown for type parameters to allow any concrete descriptor types.
|
|
75
|
-
*/
|
|
51
|
+
export interface SqlStaticContributions {
|
|
52
|
+
readonly codecs: () => CodecRegistry;
|
|
53
|
+
readonly operationSignatures: () => ReadonlyArray<SqlOperationSignature>;
|
|
76
54
|
// biome-ignore lint/suspicious/noExplicitAny: needed for covariance with concrete descriptor types
|
|
77
|
-
parameterizedCodecs
|
|
55
|
+
readonly parameterizedCodecs: () => ReadonlyArray<RuntimeParameterizedCodecDescriptor<any, any>>;
|
|
78
56
|
}
|
|
79
57
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
58
|
+
export interface SqlRuntimeTargetDescriptor<
|
|
59
|
+
TTargetId extends string = string,
|
|
60
|
+
TTargetInstance extends RuntimeTargetInstance<'sql', TTargetId> = RuntimeTargetInstance<
|
|
61
|
+
'sql',
|
|
62
|
+
TTargetId
|
|
63
|
+
>,
|
|
64
|
+
> extends RuntimeTargetDescriptor<'sql', TTargetId, TTargetInstance>,
|
|
65
|
+
SqlStaticContributions {}
|
|
66
|
+
|
|
67
|
+
export interface SqlRuntimeAdapterDescriptor<
|
|
68
|
+
TTargetId extends string = string,
|
|
69
|
+
TAdapterInstance extends RuntimeAdapterInstance<
|
|
70
|
+
'sql',
|
|
71
|
+
TTargetId
|
|
72
|
+
> = SqlRuntimeAdapterInstance<TTargetId>,
|
|
73
|
+
> extends RuntimeAdapterDescriptor<'sql', TTargetId, TAdapterInstance>,
|
|
74
|
+
SqlStaticContributions {}
|
|
75
|
+
|
|
76
|
+
export interface SqlRuntimeExtensionDescriptor<TTargetId extends string = string>
|
|
77
|
+
extends RuntimeExtensionDescriptor<'sql', TTargetId, SqlRuntimeExtensionInstance<TTargetId>>,
|
|
78
|
+
SqlStaticContributions {
|
|
88
79
|
create(): SqlRuntimeExtensionInstance<TTargetId>;
|
|
89
80
|
}
|
|
90
81
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
82
|
+
export interface SqlExecutionStack<TTargetId extends string = string> {
|
|
83
|
+
readonly target: SqlRuntimeTargetDescriptor<TTargetId>;
|
|
84
|
+
readonly adapter: SqlRuntimeAdapterDescriptor<TTargetId>;
|
|
85
|
+
readonly extensionPacks: readonly SqlRuntimeExtensionDescriptor<TTargetId>[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type SqlExecutionStackWithDriver<TTargetId extends string = string> = Omit<
|
|
89
|
+
ExecutionStack<
|
|
90
|
+
'sql',
|
|
91
|
+
TTargetId,
|
|
92
|
+
SqlRuntimeAdapterInstance<TTargetId>,
|
|
93
|
+
SqlRuntimeDriverInstance<TTargetId>,
|
|
94
|
+
SqlRuntimeExtensionInstance<TTargetId>
|
|
95
|
+
>,
|
|
96
|
+
'target' | 'adapter' | 'driver' | 'extensionPacks'
|
|
97
|
+
> & {
|
|
98
|
+
readonly target: SqlRuntimeTargetDescriptor<TTargetId>;
|
|
99
|
+
readonly adapter: SqlRuntimeAdapterDescriptor<TTargetId, SqlRuntimeAdapterInstance<TTargetId>>;
|
|
100
|
+
readonly driver:
|
|
101
|
+
| RuntimeDriverDescriptor<'sql', TTargetId, unknown, SqlRuntimeDriverInstance<TTargetId>>
|
|
102
|
+
| undefined;
|
|
103
|
+
readonly extensionPacks: readonly SqlRuntimeExtensionDescriptor<TTargetId>[];
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export interface SqlRuntimeExtensionInstance<TTargetId extends string>
|
|
107
|
+
extends RuntimeExtensionInstance<'sql', TTargetId> {}
|
|
94
108
|
|
|
95
|
-
/**
|
|
96
|
-
* SQL runtime adapter instance interface.
|
|
97
|
-
* Combines RuntimeAdapterInstance identity with SQL Adapter behavior.
|
|
98
|
-
* The instance IS an Adapter (via intersection), not HAS an adapter property.
|
|
99
|
-
*
|
|
100
|
-
* @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
|
|
101
|
-
*/
|
|
102
109
|
export type SqlRuntimeAdapterInstance<TTargetId extends string = string> = RuntimeAdapterInstance<
|
|
103
110
|
'sql',
|
|
104
111
|
TTargetId
|
|
105
112
|
> &
|
|
106
113
|
Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
|
|
107
114
|
|
|
108
|
-
// ============================================================================
|
|
109
|
-
// SQL Runtime Context
|
|
110
|
-
// ============================================================================
|
|
111
|
-
|
|
112
|
-
export type { TypeHelperRegistry };
|
|
113
|
-
|
|
114
|
-
export interface RuntimeContext<TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>>
|
|
115
|
-
extends QueryLaneContext<TContract> {
|
|
116
|
-
readonly adapter:
|
|
117
|
-
| Adapter<QueryAst, TContract, LoweredStatement>
|
|
118
|
-
| Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Initialized type helpers from storage.types.
|
|
122
|
-
* Each entry corresponds to a named type instance in the contract's storage.types.
|
|
123
|
-
* The value is the result of calling the codec's init hook (if provided)
|
|
124
|
-
* or the validated typeParams (if no init hook).
|
|
125
|
-
*/
|
|
126
|
-
readonly types?: TypeHelperRegistry;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
115
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
|
|
116
|
+
* NOTE: Binding type is intentionally erased to unknown at this shared runtime layer.
|
|
117
|
+
* Target clients (for example `postgres()`) validate and construct the concrete binding
|
|
118
|
+
* before calling `driver.connect(binding)`, which keeps runtime behavior safe today.
|
|
119
|
+
* A future follow-up can preserve TBinding through stack/context generics end-to-end.
|
|
135
120
|
*/
|
|
136
|
-
export
|
|
137
|
-
|
|
138
|
-
TTargetId
|
|
139
|
-
>
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
121
|
+
export type SqlRuntimeDriverInstance<TTargetId extends string = string> = RuntimeDriverInstance<
|
|
122
|
+
'sql',
|
|
123
|
+
TTargetId
|
|
124
|
+
> &
|
|
125
|
+
SqlDriver<unknown>;
|
|
126
|
+
|
|
127
|
+
export function createSqlExecutionStack<TTargetId extends string>(options: {
|
|
128
|
+
readonly target: SqlRuntimeTargetDescriptor<TTargetId>;
|
|
129
|
+
readonly adapter: SqlRuntimeAdapterDescriptor<TTargetId>;
|
|
130
|
+
readonly driver?:
|
|
131
|
+
| RuntimeDriverDescriptor<'sql', TTargetId, unknown, SqlRuntimeDriverInstance<TTargetId>>
|
|
132
|
+
| undefined;
|
|
133
|
+
readonly extensionPacks?: readonly SqlRuntimeExtensionDescriptor<TTargetId>[] | undefined;
|
|
134
|
+
}): SqlExecutionStackWithDriver<TTargetId> {
|
|
135
|
+
return createExecutionStack({
|
|
136
|
+
target: options.target,
|
|
137
|
+
adapter: options.adapter,
|
|
138
|
+
driver: options.driver,
|
|
139
|
+
extensionPacks: options.extensionPacks,
|
|
140
|
+
});
|
|
148
141
|
}
|
|
149
142
|
|
|
150
|
-
|
|
151
|
-
// Runtime Error Types and Helpers
|
|
152
|
-
// ============================================================================
|
|
143
|
+
export type { ExecutionContext, JsonSchemaValidatorRegistry, TypeHelperRegistry };
|
|
153
144
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
* @example
|
|
164
|
-
* ```typescript
|
|
165
|
-
* try {
|
|
166
|
-
* createRuntimeContext({ ... });
|
|
167
|
-
* } catch (e) {
|
|
168
|
-
* if ((e as RuntimeError).code === 'RUNTIME.TYPE_PARAMS_INVALID') {
|
|
169
|
-
* console.error('Invalid type parameters:', (e as RuntimeError).details);
|
|
170
|
-
* }
|
|
171
|
-
* }
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
export interface RuntimeError extends Error {
|
|
175
|
-
/** Stable error code for programmatic handling (e.g., `RUNTIME.TYPE_PARAMS_INVALID`) */
|
|
176
|
-
readonly code: string;
|
|
177
|
-
/** Error source category */
|
|
178
|
-
readonly category: 'RUNTIME';
|
|
179
|
-
/** Error severity level */
|
|
180
|
-
readonly severity: 'error';
|
|
181
|
-
/** Optional structured details for debugging */
|
|
182
|
-
readonly details?: Record<string, unknown>;
|
|
183
|
-
}
|
|
145
|
+
export function assertExecutionStackContractRequirements(
|
|
146
|
+
contract: SqlContract<SqlStorage>,
|
|
147
|
+
stack: SqlExecutionStack,
|
|
148
|
+
): void {
|
|
149
|
+
const providedComponentIds = new Set<string>([
|
|
150
|
+
stack.target.id,
|
|
151
|
+
stack.adapter.id,
|
|
152
|
+
...stack.extensionPacks.map((pack) => pack.id),
|
|
153
|
+
]);
|
|
184
154
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
* Thrown when:
|
|
191
|
-
* - `storage.types` entries have typeParams that fail codec schema validation
|
|
192
|
-
* - Column inline typeParams fail codec schema validation
|
|
193
|
-
*
|
|
194
|
-
* @internal
|
|
195
|
-
*/
|
|
196
|
-
function runtimeTypeParamsInvalid(
|
|
197
|
-
message: string,
|
|
198
|
-
details?: Record<string, unknown>,
|
|
199
|
-
): RuntimeError {
|
|
200
|
-
const error = new Error(message) as RuntimeError;
|
|
201
|
-
Object.defineProperty(error, 'name', { value: 'RuntimeError', configurable: true });
|
|
202
|
-
return Object.assign(error, {
|
|
203
|
-
code: 'RUNTIME.TYPE_PARAMS_INVALID',
|
|
204
|
-
category: 'RUNTIME' as const,
|
|
205
|
-
severity: 'error' as const,
|
|
206
|
-
details,
|
|
155
|
+
const result = checkContractComponentRequirements({
|
|
156
|
+
contract,
|
|
157
|
+
expectedTargetFamily: 'sql',
|
|
158
|
+
expectedTargetId: stack.target.targetId,
|
|
159
|
+
providedComponentIds,
|
|
207
160
|
});
|
|
208
|
-
}
|
|
209
161
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
162
|
+
if (result.familyMismatch) {
|
|
163
|
+
throw runtimeError(
|
|
164
|
+
'RUNTIME.CONTRACT_FAMILY_MISMATCH',
|
|
165
|
+
`Contract target family '${result.familyMismatch.actual}' does not match runtime family '${result.familyMismatch.expected}'.`,
|
|
166
|
+
{
|
|
167
|
+
actual: result.familyMismatch.actual,
|
|
168
|
+
expected: result.familyMismatch.expected,
|
|
169
|
+
},
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (result.targetMismatch) {
|
|
174
|
+
throw runtimeError(
|
|
175
|
+
'RUNTIME.CONTRACT_TARGET_MISMATCH',
|
|
176
|
+
`Contract target '${result.targetMismatch.actual}' does not match runtime target descriptor '${result.targetMismatch.expected}'.`,
|
|
177
|
+
{
|
|
178
|
+
actual: result.targetMismatch.actual,
|
|
179
|
+
expected: result.targetMismatch.expected,
|
|
180
|
+
},
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (result.missingExtensionPackIds.length > 0) {
|
|
185
|
+
const packIds = result.missingExtensionPackIds;
|
|
186
|
+
const packList = packIds.map((id) => `'${id}'`).join(', ');
|
|
187
|
+
throw runtimeError(
|
|
188
|
+
'RUNTIME.MISSING_EXTENSION_PACK',
|
|
189
|
+
`Contract requires extension pack(s) ${packList}, but runtime descriptors do not provide matching component(s).`,
|
|
190
|
+
{ packIds },
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
213
194
|
|
|
214
|
-
/**
|
|
215
|
-
* Validates typeParams against the codec's paramsSchema.
|
|
216
|
-
* @throws RuntimeError with code RUNTIME.TYPE_PARAMS_INVALID if validation fails
|
|
217
|
-
*/
|
|
218
195
|
function validateTypeParams(
|
|
219
196
|
typeParams: Record<string, unknown>,
|
|
220
197
|
codecDescriptor: RuntimeParameterizedCodecDescriptor,
|
|
@@ -226,7 +203,8 @@ function validateTypeParams(
|
|
|
226
203
|
const locationInfo = context.typeName
|
|
227
204
|
? `type '${context.typeName}'`
|
|
228
205
|
: `column '${context.tableName}.${context.columnName}'`;
|
|
229
|
-
throw
|
|
206
|
+
throw runtimeError(
|
|
207
|
+
'RUNTIME.TYPE_PARAMS_INVALID',
|
|
230
208
|
`Invalid typeParams for ${locationInfo} (codecId: ${codecDescriptor.codecId}): ${messages}`,
|
|
231
209
|
{ ...context, codecId: codecDescriptor.codecId, typeParams },
|
|
232
210
|
);
|
|
@@ -234,43 +212,27 @@ function validateTypeParams(
|
|
|
234
212
|
return result as Record<string, unknown>;
|
|
235
213
|
}
|
|
236
214
|
|
|
237
|
-
/**
|
|
238
|
-
* Collects parameterized codec descriptors from extension instances.
|
|
239
|
-
* Returns a map of codecId → descriptor for quick lookup.
|
|
240
|
-
*/
|
|
241
215
|
function collectParameterizedCodecDescriptors(
|
|
242
|
-
|
|
216
|
+
contributors: ReadonlyArray<SqlStaticContributions>,
|
|
243
217
|
): Map<string, RuntimeParameterizedCodecDescriptor> {
|
|
244
218
|
const descriptors = new Map<string, RuntimeParameterizedCodecDescriptor>();
|
|
245
219
|
|
|
246
|
-
for (const
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
255
|
-
descriptors.set(descriptor.codecId, descriptor);
|
|
220
|
+
for (const contributor of contributors) {
|
|
221
|
+
for (const descriptor of contributor.parameterizedCodecs()) {
|
|
222
|
+
if (descriptors.has(descriptor.codecId)) {
|
|
223
|
+
throw runtimeError(
|
|
224
|
+
'RUNTIME.DUPLICATE_PARAMETERIZED_CODEC',
|
|
225
|
+
`Duplicate parameterized codec descriptor for codecId '${descriptor.codecId}'.`,
|
|
226
|
+
{ codecId: descriptor.codecId },
|
|
227
|
+
);
|
|
256
228
|
}
|
|
229
|
+
descriptors.set(descriptor.codecId, descriptor);
|
|
257
230
|
}
|
|
258
231
|
}
|
|
259
232
|
|
|
260
233
|
return descriptors;
|
|
261
234
|
}
|
|
262
235
|
|
|
263
|
-
/**
|
|
264
|
-
* Initializes type helpers from storage.types using codec descriptors.
|
|
265
|
-
*
|
|
266
|
-
* For each named type instance in `storage.types`:
|
|
267
|
-
* - If a codec descriptor exists with an `init` hook: calls the hook and stores the result
|
|
268
|
-
* - Otherwise: stores the full type instance metadata directly (codecId, nativeType, typeParams)
|
|
269
|
-
*
|
|
270
|
-
* This matches the typing in `ExtractSchemaTypes<Contract>` which extracts
|
|
271
|
-
* `Contract['storage']['types']` directly, ensuring runtime values match static types
|
|
272
|
-
* when no init hook transforms the value.
|
|
273
|
-
*/
|
|
274
236
|
function initializeTypeHelpers(
|
|
275
237
|
storageTypes: Record<string, StorageTypeInstance> | undefined,
|
|
276
238
|
codecDescriptors: Map<string, RuntimeParameterizedCodecDescriptor>,
|
|
@@ -285,20 +247,16 @@ function initializeTypeHelpers(
|
|
|
285
247
|
const descriptor = codecDescriptors.get(typeInstance.codecId);
|
|
286
248
|
|
|
287
249
|
if (descriptor) {
|
|
288
|
-
// Validate typeParams against the codec's schema
|
|
289
250
|
const validatedParams = validateTypeParams(typeInstance.typeParams, descriptor, {
|
|
290
251
|
typeName,
|
|
291
252
|
});
|
|
292
253
|
|
|
293
|
-
// Call init hook if provided, otherwise store full type instance
|
|
294
254
|
if (descriptor.init) {
|
|
295
255
|
helpers[typeName] = descriptor.init(validatedParams);
|
|
296
256
|
} else {
|
|
297
|
-
// No init hook: expose full type instance metadata (matches contract typing)
|
|
298
257
|
helpers[typeName] = typeInstance;
|
|
299
258
|
}
|
|
300
259
|
} else {
|
|
301
|
-
// No descriptor found: expose full type instance (no validation possible)
|
|
302
260
|
helpers[typeName] = typeInstance;
|
|
303
261
|
}
|
|
304
262
|
}
|
|
@@ -306,10 +264,6 @@ function initializeTypeHelpers(
|
|
|
306
264
|
return helpers;
|
|
307
265
|
}
|
|
308
266
|
|
|
309
|
-
/**
|
|
310
|
-
* Validates inline column typeParams across all tables.
|
|
311
|
-
* @throws RuntimeError with code RUNTIME.TYPE_PARAMS_INVALID if validation fails
|
|
312
|
-
*/
|
|
313
267
|
function validateColumnTypeParams(
|
|
314
268
|
storage: SqlStorage,
|
|
315
269
|
codecDescriptors: Map<string, RuntimeParameterizedCodecDescriptor>,
|
|
@@ -327,76 +281,163 @@ function validateColumnTypeParams(
|
|
|
327
281
|
}
|
|
328
282
|
|
|
329
283
|
/**
|
|
330
|
-
*
|
|
284
|
+
* Builds a registry of compiled JSON Schema validators by scanning the contract
|
|
285
|
+
* for columns whose codec descriptor provides an `init` hook returning `{ validate }`.
|
|
331
286
|
*
|
|
332
|
-
*
|
|
333
|
-
* -
|
|
334
|
-
* -
|
|
335
|
-
* - Codec registry (populated from adapter + extension instances)
|
|
336
|
-
* - Operation registry (populated from extension instances)
|
|
337
|
-
* - Types registry (initialized helpers from storage.types)
|
|
338
|
-
*
|
|
339
|
-
* @param options - Descriptor-first composition options
|
|
340
|
-
* @returns RuntimeContext with registries wired from all components
|
|
287
|
+
* Handles both:
|
|
288
|
+
* - Inline `typeParams.schema` on columns
|
|
289
|
+
* - `typeRef` → `storage.types[ref]` with init hook results already in `types` registry
|
|
341
290
|
*/
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
291
|
+
function buildJsonSchemaValidatorRegistry(
|
|
292
|
+
contract: SqlContract<SqlStorage>,
|
|
293
|
+
types: TypeHelperRegistry,
|
|
294
|
+
codecDescriptors: Map<string, RuntimeParameterizedCodecDescriptor>,
|
|
295
|
+
): JsonSchemaValidatorRegistry | undefined {
|
|
296
|
+
const validators = new Map<string, JsonSchemaValidateFn>();
|
|
297
|
+
|
|
298
|
+
// Collect codec IDs that have init hooks (these produce { validate } helpers)
|
|
299
|
+
const codecIdsWithInit = new Set<string>();
|
|
300
|
+
for (const [codecId, descriptor] of codecDescriptors) {
|
|
301
|
+
if (descriptor.init) {
|
|
302
|
+
codecIdsWithInit.add(codecId);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
347
305
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
306
|
+
if (codecIdsWithInit.size === 0) {
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
351
309
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
310
|
+
for (const [tableName, table] of Object.entries(contract.storage.tables)) {
|
|
311
|
+
for (const [columnName, column] of Object.entries(table.columns)) {
|
|
312
|
+
if (!codecIdsWithInit.has(column.codecId)) continue;
|
|
313
|
+
|
|
314
|
+
const key = `${tableName}.${columnName}`;
|
|
315
|
+
|
|
316
|
+
// Case 1: column references a named type → validator already compiled via init hook
|
|
317
|
+
if (column.typeRef) {
|
|
318
|
+
const helper = types[column.typeRef] as { validate?: JsonSchemaValidateFn } | undefined;
|
|
319
|
+
if (helper?.validate) {
|
|
320
|
+
validators.set(key, helper.validate);
|
|
321
|
+
}
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Case 2: inline typeParams with schema → compile via init hook
|
|
326
|
+
if (column.typeParams) {
|
|
327
|
+
const descriptor = codecDescriptors.get(column.codecId);
|
|
328
|
+
if (descriptor?.init) {
|
|
329
|
+
const helper = descriptor.init(column.typeParams) as
|
|
330
|
+
| { validate?: JsonSchemaValidateFn }
|
|
331
|
+
| undefined;
|
|
332
|
+
if (helper?.validate) {
|
|
333
|
+
validators.set(key, helper.validate);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (validators.size === 0) return undefined;
|
|
341
|
+
return {
|
|
342
|
+
get: (key: string) => validators.get(key),
|
|
343
|
+
size: validators.size,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
355
346
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
347
|
+
function computeExecutionDefaultValue(spec: ExecutionMutationDefaultValue): unknown {
|
|
348
|
+
switch (spec.kind) {
|
|
349
|
+
case 'generator':
|
|
350
|
+
return generateId(spec.params ? { id: spec.id, params: spec.params } : { id: spec.id });
|
|
360
351
|
}
|
|
352
|
+
}
|
|
361
353
|
|
|
362
|
-
|
|
363
|
-
|
|
354
|
+
function applyMutationDefaults(
|
|
355
|
+
contract: SqlContract<SqlStorage>,
|
|
356
|
+
options: MutationDefaultsOptions,
|
|
357
|
+
): ReadonlyArray<AppliedMutationDefault> {
|
|
358
|
+
const defaults = contract.execution?.mutations.defaults ?? [];
|
|
359
|
+
if (defaults.length === 0) {
|
|
360
|
+
return [];
|
|
361
|
+
}
|
|
364
362
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
extensionInstances.push(extInstance);
|
|
363
|
+
const applied: AppliedMutationDefault[] = [];
|
|
364
|
+
const appliedColumns = new Set<string>();
|
|
368
365
|
|
|
369
|
-
|
|
370
|
-
if (
|
|
371
|
-
|
|
372
|
-
codecRegistry.register(codec);
|
|
373
|
-
}
|
|
366
|
+
for (const mutationDefault of defaults) {
|
|
367
|
+
if (mutationDefault.ref.table !== options.table) {
|
|
368
|
+
continue;
|
|
374
369
|
}
|
|
375
370
|
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
371
|
+
const defaultSpec =
|
|
372
|
+
options.op === 'create' ? mutationDefault.onCreate : mutationDefault.onUpdate;
|
|
373
|
+
if (!defaultSpec) {
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const columnName = mutationDefault.ref.column;
|
|
378
|
+
if (Object.hasOwn(options.values, columnName) || appliedColumns.has(columnName)) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
applied.push({
|
|
383
|
+
column: columnName,
|
|
384
|
+
value: computeExecutionDefaultValue(defaultSpec),
|
|
385
|
+
});
|
|
386
|
+
appliedColumns.add(columnName);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return applied;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export function createExecutionContext<
|
|
393
|
+
TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
|
|
394
|
+
TTargetId extends string = string,
|
|
395
|
+
>(options: {
|
|
396
|
+
readonly contract: TContract;
|
|
397
|
+
readonly stack: SqlExecutionStack<TTargetId>;
|
|
398
|
+
}): ExecutionContext<TContract> {
|
|
399
|
+
const { contract, stack } = options;
|
|
400
|
+
|
|
401
|
+
assertExecutionStackContractRequirements(contract, stack);
|
|
402
|
+
|
|
403
|
+
const codecRegistry = createCodecRegistry();
|
|
404
|
+
const operationRegistry = createOperationRegistry();
|
|
405
|
+
|
|
406
|
+
const contributors: SqlStaticContributions[] = [
|
|
407
|
+
stack.target,
|
|
408
|
+
stack.adapter,
|
|
409
|
+
...stack.extensionPacks,
|
|
410
|
+
];
|
|
411
|
+
|
|
412
|
+
for (const contributor of contributors) {
|
|
413
|
+
for (const c of contributor.codecs().values()) {
|
|
414
|
+
codecRegistry.register(c);
|
|
415
|
+
}
|
|
416
|
+
for (const operation of contributor.operationSignatures()) {
|
|
417
|
+
operationRegistry.register(operation);
|
|
381
418
|
}
|
|
382
419
|
}
|
|
383
420
|
|
|
384
|
-
|
|
385
|
-
const parameterizedCodecDescriptors = collectParameterizedCodecDescriptors(extensionInstances);
|
|
421
|
+
const parameterizedCodecDescriptors = collectParameterizedCodecDescriptors(contributors);
|
|
386
422
|
|
|
387
|
-
// Validate column typeParams if any descriptors are registered
|
|
388
423
|
if (parameterizedCodecDescriptors.size > 0) {
|
|
389
424
|
validateColumnTypeParams(contract.storage, parameterizedCodecDescriptors);
|
|
390
425
|
}
|
|
391
426
|
|
|
392
|
-
// Initialize type helpers from storage.types
|
|
393
427
|
const types = initializeTypeHelpers(contract.storage.types, parameterizedCodecDescriptors);
|
|
394
428
|
|
|
429
|
+
const jsonSchemaValidators = buildJsonSchemaValidatorRegistry(
|
|
430
|
+
contract,
|
|
431
|
+
types,
|
|
432
|
+
parameterizedCodecDescriptors,
|
|
433
|
+
);
|
|
434
|
+
|
|
395
435
|
return {
|
|
396
436
|
contract,
|
|
397
|
-
adapter: adapterInstance,
|
|
398
437
|
operations: operationRegistry,
|
|
399
438
|
codecs: codecRegistry,
|
|
400
439
|
types,
|
|
440
|
+
...(jsonSchemaValidators ? { jsonSchemaValidators } : {}),
|
|
441
|
+
applyMutationDefaults: (options) => applyMutationDefaults(contract, options),
|
|
401
442
|
};
|
|
402
443
|
}
|