@prisma-next/sql-relational-core 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -1
- package/dist/codec-types-DJEaWT36.d.mts +313 -0
- package/dist/codec-types-DJEaWT36.d.mts.map +1 -0
- package/dist/{errors-ChY_dHam.d.mts → errors-BRt5yHo9.d.mts} +2 -2
- package/dist/errors-BRt5yHo9.d.mts.map +1 -0
- package/dist/{errors-D3xmG4h-.mjs → errors-D6kqqjHM.mjs} +1 -1
- package/dist/{errors-D3xmG4h-.mjs.map → errors-D6kqqjHM.mjs.map} +1 -1
- package/dist/exports/ast.d.mts +37 -20
- package/dist/exports/ast.d.mts.map +1 -1
- package/dist/exports/ast.mjs +63 -1089
- package/dist/exports/ast.mjs.map +1 -1
- package/dist/exports/errors.d.mts +4 -4
- package/dist/exports/errors.mjs +1 -1
- package/dist/exports/expression.d.mts +79 -0
- package/dist/exports/expression.d.mts.map +1 -0
- package/dist/exports/expression.mjs +41 -0
- package/dist/exports/expression.mjs.map +1 -0
- package/dist/exports/plan.d.mts +3 -2
- package/dist/exports/plan.mjs +1 -17
- package/dist/exports/query-lane-context.d.mts +3 -3
- package/dist/exports/types.d.mts +5 -4
- package/dist/index.d.mts +11 -9
- package/dist/index.mjs +6 -4
- package/dist/plan-C7SiEWkN.d.mts +25 -0
- package/dist/plan-C7SiEWkN.d.mts.map +1 -0
- package/dist/{query-lane-context-UlR8vOkd.d.mts → query-lane-context-BF-wuc0r.d.mts} +53 -3
- package/dist/query-lane-context-BF-wuc0r.d.mts.map +1 -0
- package/dist/sql-execution-plan-Dgx7BGin.d.mts +33 -0
- package/dist/sql-execution-plan-Dgx7BGin.d.mts.map +1 -0
- package/dist/{types-C3Hg-CVz.d.mts → types-B4dL4lc3.d.mts} +17 -22
- package/dist/types-B4dL4lc3.d.mts.map +1 -0
- package/dist/types-BUlUvdIU.d.mts +24 -0
- package/dist/types-BUlUvdIU.d.mts.map +1 -0
- package/dist/{types-k9pir8XY.d.mts → types-BWOCTYd8.d.mts} +12 -19
- package/dist/types-BWOCTYd8.d.mts.map +1 -0
- package/dist/types-DUL-3vy6.mjs +1064 -0
- package/dist/types-DUL-3vy6.mjs.map +1 -0
- package/package.json +9 -8
- package/src/ast/adapter-types.ts +20 -10
- package/src/ast/codec-types.ts +251 -45
- package/src/ast/sql-codecs.ts +20 -3
- package/src/ast/types.ts +142 -172
- package/src/ast/util.ts +23 -0
- package/src/exports/expression.ts +1 -0
- package/src/exports/plan.ts +1 -0
- package/src/exports/types.ts +1 -0
- package/src/expression.ts +117 -0
- package/src/index.ts +1 -0
- package/src/plan.ts +11 -30
- package/src/query-lane-context.ts +52 -1
- package/src/runtime-scope.ts +20 -0
- package/src/sql-execution-plan.ts +28 -0
- package/src/types.ts +9 -22
- package/dist/codec-types-DcEITed4.d.mts +0 -144
- package/dist/codec-types-DcEITed4.d.mts.map +0 -1
- package/dist/errors-ChY_dHam.d.mts.map +0 -1
- package/dist/exports/plan.mjs.map +0 -1
- package/dist/plan-Cs65hb-E.d.mts +0 -28
- package/dist/plan-Cs65hb-E.d.mts.map +0 -1
- package/dist/query-lane-context-UlR8vOkd.d.mts.map +0 -1
- package/dist/types-C3Hg-CVz.d.mts.map +0 -1
- package/dist/types-k9pir8XY.d.mts.map +0 -1
package/src/ast/codec-types.ts
CHANGED
|
@@ -1,14 +1,88 @@
|
|
|
1
1
|
import type { JsonValue } from '@prisma-next/contract/types';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
Codec as BaseCodec,
|
|
4
|
+
CodecCallContext,
|
|
5
|
+
CodecInstanceContext,
|
|
6
|
+
CodecTrait,
|
|
7
|
+
} from '@prisma-next/framework-components/codec';
|
|
3
8
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
4
9
|
import type { Type } from 'arktype';
|
|
5
10
|
import type { O } from 'ts-toolbelt';
|
|
6
11
|
|
|
7
|
-
export type { CodecTrait } from '@prisma-next/framework-components/codec';
|
|
12
|
+
export type { CodecCallContext, CodecTrait } from '@prisma-next/framework-components/codec';
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
15
|
+
* SQL-family addressing of a single column. The decode site populates a
|
|
16
|
+
* `SqlColumnRef` whenever it can resolve the cell to a single underlying
|
|
17
|
+
* `(table, column)` (the typical case for projected columns from a
|
|
18
|
+
* single-table source); cells the runtime cannot resolve (aggregate
|
|
19
|
+
* aliases, include aggregate fields, computed projections without a
|
|
20
|
+
* simple ref) get `column = undefined`.
|
|
21
|
+
*
|
|
22
|
+
* The shape is a structural projection of the runtime's `ColumnRef` so
|
|
23
|
+
* the SQL decode site can reuse the resolution it already performs for
|
|
24
|
+
* `RUNTIME.DECODE_FAILED` envelope construction without allocating
|
|
25
|
+
* twice per cell.
|
|
26
|
+
*/
|
|
27
|
+
export interface SqlColumnRef {
|
|
28
|
+
readonly table: string;
|
|
29
|
+
readonly name: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* SQL-family per-call context. Extends the framework {@link CodecCallContext}
|
|
34
|
+
* (which carries `signal` only) with `column?: SqlColumnRef`, populated
|
|
35
|
+
* on **decode** call sites that can resolve a single underlying column
|
|
36
|
+
* ref. Encode call sites currently leave `column` undefined (encode-time
|
|
37
|
+
* column context is the middleware's domain).
|
|
38
|
+
*
|
|
39
|
+
* SQL codec authors writing a `(value, ctx)` author function for the SQL
|
|
40
|
+
* `codec()` factory observe this type. The framework codec dispatch
|
|
41
|
+
* surface (and Mongo) sees only the base `CodecCallContext`.
|
|
42
|
+
*/
|
|
43
|
+
export interface SqlCodecCallContext extends CodecCallContext {
|
|
44
|
+
readonly column?: SqlColumnRef;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* SQL-family per-instance context. Extends the framework
|
|
49
|
+
* {@link CodecInstanceContext} (`name` only) with `usedAt`, the set of
|
|
50
|
+
* `(table, column)` pairs the resolved codec serves.
|
|
51
|
+
*
|
|
52
|
+
* - For `typeRef` columns sharing one named `storage.types` instance, the
|
|
53
|
+
* array lists every referencing column — a column-scoped stateful codec
|
|
54
|
+
* (e.g. encryption) can derive aggregated per-instance state across all
|
|
55
|
+
* the columns sharing the named instance.
|
|
56
|
+
* - For inline-`typeParams` columns, the array has exactly one entry —
|
|
57
|
+
* the column that owns the inline params.
|
|
58
|
+
* - For shared non-parameterized codecs, the array carries one
|
|
59
|
+
* representative entry (the column that triggered materialization);
|
|
60
|
+
* the codec is shared across every column with that codec id, so the
|
|
61
|
+
* `usedAt` is informational only.
|
|
62
|
+
*
|
|
63
|
+
* SQL extensions consuming `usedAt` (e.g. column-scoped state derivation)
|
|
64
|
+
* type their factory parameter as `SqlCodecInstanceContext`. Extensions
|
|
65
|
+
* that don't read `usedAt` type their factory parameter as the
|
|
66
|
+
* family-agnostic {@link CodecInstanceContext} — a `SqlCodecInstanceContext`
|
|
67
|
+
* is structurally assignable to the base.
|
|
68
|
+
*/
|
|
69
|
+
export interface SqlCodecInstanceContext extends CodecInstanceContext {
|
|
70
|
+
readonly usedAt: ReadonlyArray<{ readonly table: string; readonly column: string }>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Legacy adapter-level descriptor for parameterized codecs that require
|
|
75
|
+
* type-parameter validation at compile time. The runtime descriptor
|
|
76
|
+
* (`RuntimeParameterizedCodecDescriptor` in `@prisma-next/sql-runtime`)
|
|
77
|
+
* has migrated to the unified `CodecDescriptor<P>` shape with
|
|
78
|
+
* `factory: (P) => (CodecInstanceContext) => Codec`; this descriptor stays only because
|
|
79
|
+
* the SQL `Adapter.parameterizedCodecs()` surface still returns
|
|
80
|
+
* `CodecParamsDescriptor[]` (compile-time typeParams validation only,
|
|
81
|
+
* not runtime materialization).
|
|
82
|
+
*
|
|
83
|
+
* Retirement is tracked under TML-2357 T3.5.4 (single registration slot)
|
|
84
|
+
* — the adapter-level `parameterizedCodecs()` collapses into the unified
|
|
85
|
+
* runtime descriptor map once contributors migrate fully.
|
|
12
86
|
*
|
|
13
87
|
* @template TParams - The shape of the type parameters (e.g., `{ length: number }`)
|
|
14
88
|
* @template THelper - The type returned by the optional `init` hook
|
|
@@ -27,6 +101,14 @@ export interface CodecParamsDescriptor<TParams = Record<string, unknown>, THelpe
|
|
|
27
101
|
* Optional init hook called during runtime context creation.
|
|
28
102
|
* Receives validated params and returns a helper object to be stored in context.types.
|
|
29
103
|
* If not provided, the validated params are stored directly.
|
|
104
|
+
*
|
|
105
|
+
* Predecessor pattern. The runtime descriptor's curried
|
|
106
|
+
* `factory: (P) => (CodecInstanceContext) => Codec` subsumes this hook — per-instance
|
|
107
|
+
* state lives on the resolved codec rather than in a parallel
|
|
108
|
+
* `TypeHelperRegistry` entry. Retirement tracked under TML-2357 T3.5.2
|
|
109
|
+
* (narrow runtime `Codec` interface) and T3.5.4 (single registration
|
|
110
|
+
* slot). Adapter-level callers reading codec-self-carried `init` should
|
|
111
|
+
* migrate to the runtime descriptor map's factory instead.
|
|
30
112
|
*/
|
|
31
113
|
readonly init?: (params: TParams) => THelper;
|
|
32
114
|
}
|
|
@@ -46,25 +128,97 @@ export interface CodecMeta {
|
|
|
46
128
|
}
|
|
47
129
|
|
|
48
130
|
/**
|
|
49
|
-
* SQL codec
|
|
131
|
+
* SQL codec — extends the framework codec base with SQL-specific metadata:
|
|
132
|
+
* driver-native type info (`meta.db.sql.<dialect>.nativeType`) and an
|
|
133
|
+
* optional parameterized-codec descriptor (`paramsSchema` + `init`) for
|
|
134
|
+
* codecs that require type-parameter validation (e.g. `pg/vector@1`).
|
|
50
135
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
136
|
+
* `encode` and `decode` are redeclared here to narrow the per-call
|
|
137
|
+
* context to the SQL-family {@link SqlCodecCallContext} (adds
|
|
138
|
+
* `column?: SqlColumnRef`). TypeScript treats method-syntax declarations
|
|
139
|
+
* bivariantly, so the SQL narrowing is structurally compatible with the
|
|
140
|
+
* framework {@link BaseCodec} super-interface.
|
|
141
|
+
*
|
|
142
|
+
* Note: `paramsSchema` and `init` here are the legacy adapter-level slots
|
|
143
|
+
* mirrored from {@link CodecParamsDescriptor}. The runtime materialization
|
|
144
|
+
* path uses `RuntimeParameterizedCodecDescriptor` (in
|
|
145
|
+
* `@prisma-next/sql-runtime`) via the unified `CodecDescriptor<P>` shape;
|
|
146
|
+
* codec-self-carried `paramsSchema`/`init` retire under TML-2357 (T3.5.2
|
|
147
|
+
* narrows the runtime `Codec` interface; T3.5.4 collapses the parallel
|
|
148
|
+
* registration slots).
|
|
149
|
+
*
|
|
150
|
+
* See `Codec` in `@prisma-next/framework-components/codec` for the codec
|
|
151
|
+
* contract that this interface extends.
|
|
54
152
|
*/
|
|
55
153
|
export interface Codec<
|
|
56
154
|
Id extends string = string,
|
|
57
155
|
TTraits extends readonly CodecTrait[] = readonly CodecTrait[],
|
|
58
156
|
TWire = unknown,
|
|
59
|
-
|
|
157
|
+
TInput = unknown,
|
|
60
158
|
TParams = Record<string, unknown>,
|
|
61
159
|
THelper = unknown,
|
|
62
|
-
> extends BaseCodec<Id, TTraits, TWire,
|
|
160
|
+
> extends BaseCodec<Id, TTraits, TWire, TInput> {
|
|
161
|
+
encode(value: TInput, ctx: SqlCodecCallContext): Promise<TWire>;
|
|
162
|
+
decode(wire: TWire, ctx: SqlCodecCallContext): Promise<TInput>;
|
|
63
163
|
readonly meta?: CodecMeta;
|
|
64
164
|
readonly paramsSchema?: Type<TParams>;
|
|
165
|
+
/**
|
|
166
|
+
* Predecessor init hook. Retirement tracked under TML-2357 (T3.5.2 /
|
|
167
|
+
* T3.5.4); the unified runtime descriptor's
|
|
168
|
+
* `factory: (P) => (CodecInstanceContext) => Codec` is the replacement.
|
|
169
|
+
*/
|
|
65
170
|
readonly init?: (params: TParams) => THelper;
|
|
66
171
|
}
|
|
67
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Contract-bound codec registry.
|
|
175
|
+
*
|
|
176
|
+
* The dispatch interface for encode/decode at runtime: built once at
|
|
177
|
+
* `ExecutionContext` construction time by walking the contract's
|
|
178
|
+
* `storage.tables[].columns[]` and resolving each column to either a per-
|
|
179
|
+
* instance parameterized codec (via `descriptor.factory(typeParams)(ctx)`)
|
|
180
|
+
* or the shared codec instance from the legacy `CodecRegistry` (for non-
|
|
181
|
+
* parameterized codecs). The dispatch path calls
|
|
182
|
+
* `forColumn(table, column).encode/decode(...)` and doesn't know whether
|
|
183
|
+
* the codec is parameterized.
|
|
184
|
+
*
|
|
185
|
+
* `forCodecId(codecId)` is a fallback for sites that don't carry the
|
|
186
|
+
* `(table, column)` ref through to the encode/decode call site —
|
|
187
|
+
* primarily the param-encoding path, where `ParamRef.refs` is not
|
|
188
|
+
* populated by the SQL builder today (every `ParamRef` carries `codecId`
|
|
189
|
+
* but not the column it relates to). For the parameterized codecs shipped
|
|
190
|
+
* at Phase B, encode is per-instance-stateless (pgvector formats
|
|
191
|
+
* `[v1,v2,v3]` regardless of length; JSON's `encode` is `JSON.stringify`
|
|
192
|
+
* regardless of schema), so a codec-id-keyed lookup yields a structurally
|
|
193
|
+
* equivalent encoder; the fallback is the bridge that lets the legacy
|
|
194
|
+
* `codecs:` registration retire from the dispatch path while staying as
|
|
195
|
+
* the codec-id-only source for now.
|
|
196
|
+
*
|
|
197
|
+
* The encode-side fallback is the AC-5-deferred carve-out documented in
|
|
198
|
+
* the codec-registry-unification spec § Non-functional constraints.
|
|
199
|
+
* TML-2357 retires the fallback by threading `ParamRef.refs` through
|
|
200
|
+
* column-bound construction sites.
|
|
201
|
+
*/
|
|
202
|
+
export interface ContractCodecRegistry {
|
|
203
|
+
/**
|
|
204
|
+
* Resolve the codec for `(table, column)`. Returns the per-instance
|
|
205
|
+
* parameterized codec for parameterized columns, the shared codec for
|
|
206
|
+
* non-parameterized columns, or `undefined` if the column is unknown
|
|
207
|
+
* or the codec isn't registered.
|
|
208
|
+
*/
|
|
209
|
+
forColumn(table: string, column: string): Codec | undefined;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Resolve a codec by id. Returns the same codec instance the legacy
|
|
213
|
+
* `CodecRegistry.get(codecId)` would return — for non-parameterized
|
|
214
|
+
* codecs that's the shared instance; for parameterized codecs that's
|
|
215
|
+
* a representative resolved instance. Used by sites that don't carry
|
|
216
|
+
* `(table, column)` through to the encode/decode call site (the AC-5
|
|
217
|
+
* carve-out path).
|
|
218
|
+
*/
|
|
219
|
+
forCodecId(codecId: string): Codec | undefined;
|
|
220
|
+
}
|
|
221
|
+
|
|
68
222
|
/**
|
|
69
223
|
* Registry interface for codecs organized by ID and by contract scalar type.
|
|
70
224
|
*
|
|
@@ -180,30 +334,72 @@ class CodecRegistryImpl implements CodecRegistry {
|
|
|
180
334
|
}
|
|
181
335
|
|
|
182
336
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
337
|
+
* Conditional bundle for `encodeJson`/`decodeJson`: when `TInput` is
|
|
338
|
+
* structurally assignable to `JsonValue` the identity defaults are
|
|
339
|
+
* sound and both fields are optional; otherwise both fields are
|
|
340
|
+
* required so an author cannot silently produce a non-JSON-safe
|
|
341
|
+
* contract artifact.
|
|
342
|
+
*/
|
|
343
|
+
type JsonRoundTripConfig<TInput> = [TInput] extends [JsonValue]
|
|
344
|
+
? {
|
|
345
|
+
encodeJson?: (value: TInput) => JsonValue;
|
|
346
|
+
decodeJson?: (json: JsonValue) => TInput;
|
|
347
|
+
}
|
|
348
|
+
: {
|
|
349
|
+
encodeJson: (value: TInput) => JsonValue;
|
|
350
|
+
decodeJson: (json: JsonValue) => TInput;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Construct a SQL codec from author functions and optional metadata.
|
|
355
|
+
*
|
|
356
|
+
* Author `encode` and `decode` as sync or async functions; the factory
|
|
357
|
+
* produces a {@link Codec} whose query-time methods follow the boundary
|
|
358
|
+
* contract documented on `Codec`. Authors receive a second `ctx` options
|
|
359
|
+
* argument carrying the SQL-family per-call context; ignore it if you
|
|
360
|
+
* don't need it.
|
|
361
|
+
*
|
|
362
|
+
* Both `encode` and `decode` are required so `TInput` and `TWire` are
|
|
363
|
+
* always covered by an explicit author function — the factory installs
|
|
364
|
+
* no identity fallback. `encodeJson` and `decodeJson` default to identity
|
|
365
|
+
* **only when `TInput` is assignable to `JsonValue`**; otherwise both are
|
|
366
|
+
* required so the contract artifact stays JSON-safe.
|
|
185
367
|
*/
|
|
186
368
|
export function codec<
|
|
187
369
|
Id extends string,
|
|
188
|
-
const TTraits extends readonly CodecTrait[],
|
|
189
|
-
TWire,
|
|
190
|
-
|
|
370
|
+
const TTraits extends readonly CodecTrait[] = readonly [],
|
|
371
|
+
TWire = unknown,
|
|
372
|
+
TInput = unknown,
|
|
191
373
|
TParams = Record<string, unknown>,
|
|
192
374
|
THelper = unknown,
|
|
193
|
-
>(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
375
|
+
>(
|
|
376
|
+
config: {
|
|
377
|
+
typeId: Id;
|
|
378
|
+
targetTypes: readonly string[];
|
|
379
|
+
encode: (value: TInput, ctx: SqlCodecCallContext) => TWire | Promise<TWire>;
|
|
380
|
+
decode: (wire: TWire, ctx: SqlCodecCallContext) => TInput | Promise<TInput>;
|
|
381
|
+
meta?: CodecMeta;
|
|
382
|
+
paramsSchema?: Type<TParams>;
|
|
383
|
+
init?: (params: TParams) => THelper;
|
|
384
|
+
traits?: TTraits;
|
|
385
|
+
renderOutputType?: (typeParams: Record<string, unknown>) => string | undefined;
|
|
386
|
+
} & JsonRoundTripConfig<TInput>,
|
|
387
|
+
): Codec<Id, TTraits, TWire, TInput, TParams, THelper> {
|
|
206
388
|
const identity = (v: unknown) => v;
|
|
389
|
+
// The runtime allocates one `SqlCodecCallContext` per `runtime.execute()`
|
|
390
|
+
// call (no caller-supplied `signal` produces `{}` instead of `undefined`)
|
|
391
|
+
// and threads it as a non-optional reference to every codec call. The
|
|
392
|
+
// author surface keeps the second parameter optional so single-arg
|
|
393
|
+
// `(value) => …` authors continue to satisfy the signature via
|
|
394
|
+
// TypeScript's bivariance for trailing parameters.
|
|
395
|
+
const userEncode = config.encode;
|
|
396
|
+
const userDecode = config.decode;
|
|
397
|
+
// The conditional JsonRoundTripConfig narrows TInput|JsonValue at the
|
|
398
|
+
// boundary; widen back to the generic shape inside the factory body.
|
|
399
|
+
const widenedConfig = config as {
|
|
400
|
+
encodeJson?: (value: TInput) => JsonValue;
|
|
401
|
+
decodeJson?: (json: JsonValue) => TInput;
|
|
402
|
+
};
|
|
207
403
|
return {
|
|
208
404
|
id: config.typeId,
|
|
209
405
|
targetTypes: config.targetTypes,
|
|
@@ -215,10 +411,22 @@ export function codec<
|
|
|
215
411
|
config.traits ? (Object.freeze([...config.traits]) as TTraits) : undefined,
|
|
216
412
|
),
|
|
217
413
|
...ifDefined('renderOutputType', config.renderOutputType),
|
|
218
|
-
encode:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
414
|
+
encode: (value, ctx) => {
|
|
415
|
+
try {
|
|
416
|
+
return Promise.resolve(userEncode(value, ctx));
|
|
417
|
+
} catch (error) {
|
|
418
|
+
return Promise.reject(error);
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
decode: (wire, ctx) => {
|
|
422
|
+
try {
|
|
423
|
+
return Promise.resolve(userDecode(wire, ctx));
|
|
424
|
+
} catch (error) {
|
|
425
|
+
return Promise.reject(error);
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
encodeJson: (widenedConfig.encodeJson ?? identity) as (value: TInput) => JsonValue,
|
|
429
|
+
decodeJson: (widenedConfig.decodeJson ?? identity) as (json: JsonValue) => TInput,
|
|
222
430
|
};
|
|
223
431
|
}
|
|
224
432
|
|
|
@@ -228,9 +436,7 @@ export function codec<
|
|
|
228
436
|
export type CodecId<T> =
|
|
229
437
|
T extends Codec<infer Id> ? Id : T extends { readonly id: infer Id } ? Id : never;
|
|
230
438
|
export type CodecInput<T> =
|
|
231
|
-
T extends Codec<string, readonly CodecTrait[], unknown, infer
|
|
232
|
-
export type CodecOutput<T> =
|
|
233
|
-
T extends Codec<string, readonly CodecTrait[], unknown, infer JsT> ? JsT : never;
|
|
439
|
+
T extends Codec<string, readonly CodecTrait[], unknown, infer In> ? In : never;
|
|
234
440
|
export type CodecTraits<T> =
|
|
235
441
|
T extends Codec<string, infer TTraits> ? TTraits[number] & CodecTrait : never;
|
|
236
442
|
|
|
@@ -242,7 +448,7 @@ export type ExtractCodecTypes<
|
|
|
242
448
|
> = {
|
|
243
449
|
readonly [K in keyof ScalarNames as ScalarNames[K] extends Codec<infer Id> ? Id : never]: {
|
|
244
450
|
readonly input: CodecInput<ScalarNames[K]>;
|
|
245
|
-
readonly output:
|
|
451
|
+
readonly output: CodecInput<ScalarNames[K]>;
|
|
246
452
|
readonly traits: CodecTraits<ScalarNames[K]>;
|
|
247
453
|
};
|
|
248
454
|
};
|
|
@@ -283,8 +489,8 @@ export interface CodecDefBuilder<
|
|
|
283
489
|
readonly scalar: K;
|
|
284
490
|
readonly codec: ScalarNames[K];
|
|
285
491
|
readonly input: CodecInput<ScalarNames[K]>;
|
|
286
|
-
readonly output:
|
|
287
|
-
readonly jsType:
|
|
492
|
+
readonly output: CodecInput<ScalarNames[K]>;
|
|
493
|
+
readonly jsType: CodecInput<ScalarNames[K]>;
|
|
288
494
|
};
|
|
289
495
|
};
|
|
290
496
|
|
|
@@ -323,7 +529,7 @@ class CodecDefBuilderImpl<
|
|
|
323
529
|
const codecImplTyped = codecImpl as Codec<string>;
|
|
324
530
|
codecTypes[codecImplTyped.id] = {
|
|
325
531
|
input: undefined as unknown as CodecInput<typeof codecImplTyped>,
|
|
326
|
-
output: undefined as unknown as
|
|
532
|
+
output: undefined as unknown as CodecInput<typeof codecImplTyped>,
|
|
327
533
|
traits: undefined as unknown as CodecTraits<typeof codecImplTyped>,
|
|
328
534
|
};
|
|
329
535
|
}
|
|
@@ -368,8 +574,8 @@ class CodecDefBuilderImpl<
|
|
|
368
574
|
readonly scalar: K;
|
|
369
575
|
readonly codec: ScalarNames[K];
|
|
370
576
|
readonly input: CodecInput<ScalarNames[K]>;
|
|
371
|
-
readonly output:
|
|
372
|
-
readonly jsType:
|
|
577
|
+
readonly output: CodecInput<ScalarNames[K]>;
|
|
578
|
+
readonly jsType: CodecInput<ScalarNames[K]>;
|
|
373
579
|
};
|
|
374
580
|
} {
|
|
375
581
|
const result: Record<
|
|
@@ -391,8 +597,8 @@ class CodecDefBuilderImpl<
|
|
|
391
597
|
scalar: scalarName,
|
|
392
598
|
codec: codec,
|
|
393
599
|
input: undefined as unknown as CodecInput<typeof codec>,
|
|
394
|
-
output: undefined as unknown as
|
|
395
|
-
jsType: undefined as unknown as
|
|
600
|
+
output: undefined as unknown as CodecInput<typeof codec>,
|
|
601
|
+
jsType: undefined as unknown as CodecInput<typeof codec>,
|
|
396
602
|
};
|
|
397
603
|
}
|
|
398
604
|
|
|
@@ -402,8 +608,8 @@ class CodecDefBuilderImpl<
|
|
|
402
608
|
readonly scalar: K;
|
|
403
609
|
readonly codec: ScalarNames[K];
|
|
404
610
|
readonly input: CodecInput<ScalarNames[K]>;
|
|
405
|
-
readonly output:
|
|
406
|
-
readonly jsType:
|
|
611
|
+
readonly output: CodecInput<ScalarNames[K]>;
|
|
612
|
+
readonly jsType: CodecInput<ScalarNames[K]>;
|
|
407
613
|
};
|
|
408
614
|
};
|
|
409
615
|
}
|
package/src/ast/sql-codecs.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { JsonValue } from '@prisma-next/contract/types';
|
|
1
2
|
import { type as arktype } from 'arktype';
|
|
2
3
|
import { codec, defineCodecs } from './codec-types';
|
|
3
4
|
|
|
@@ -104,12 +105,28 @@ const sqlTextCodec = codec({
|
|
|
104
105
|
decode: (wire: string): string => wire,
|
|
105
106
|
});
|
|
106
107
|
|
|
107
|
-
const sqlTimestampCodec = codec
|
|
108
|
+
const sqlTimestampCodec = codec<
|
|
109
|
+
typeof SQL_TIMESTAMP_CODEC_ID,
|
|
110
|
+
readonly ['equality', 'order'],
|
|
111
|
+
Date,
|
|
112
|
+
Date
|
|
113
|
+
>({
|
|
108
114
|
typeId: SQL_TIMESTAMP_CODEC_ID,
|
|
109
115
|
targetTypes: ['timestamp'],
|
|
110
116
|
traits: ['equality', 'order'],
|
|
111
|
-
encode: (value:
|
|
112
|
-
decode: (wire:
|
|
117
|
+
encode: (value: Date): Date => value,
|
|
118
|
+
decode: (wire: Date): Date => wire,
|
|
119
|
+
encodeJson: (value: Date): JsonValue => value.toISOString(),
|
|
120
|
+
decodeJson: (json: JsonValue): Date => {
|
|
121
|
+
if (typeof json !== 'string') {
|
|
122
|
+
throw new Error(`Expected ISO date string for sql/timestamp@1, got ${typeof json}`);
|
|
123
|
+
}
|
|
124
|
+
const date = new Date(json);
|
|
125
|
+
if (Number.isNaN(date.getTime())) {
|
|
126
|
+
throw new Error(`Invalid ISO date string for sql/timestamp@1: ${json}`);
|
|
127
|
+
}
|
|
128
|
+
return date;
|
|
129
|
+
},
|
|
113
130
|
paramsSchema: precisionParamsSchema,
|
|
114
131
|
renderOutputType: (typeParams) => {
|
|
115
132
|
const precision = typeParams['precision'];
|