@prisma-next/extension-arktype-json 0.6.0-dev.4 → 0.6.0-dev.6
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 +30 -4
- package/dist/{arktype-json-codec-VX9T28RG.d.mts → arktype-json-codec-BRSKEodM.d.mts} +12 -3
- package/dist/arktype-json-codec-BRSKEodM.d.mts.map +1 -0
- package/dist/{arktype-json-codec-DluUG3EZ.mjs → arktype-json-codec-BjUHsoD5.mjs} +36 -16
- package/dist/arktype-json-codec-BjUHsoD5.mjs.map +1 -0
- package/dist/codecs.d.mts +1 -1
- package/dist/codecs.mjs +2 -2
- package/dist/column-types.d.mts +1 -1
- package/dist/column-types.mjs +1 -1
- package/dist/control.mjs +2 -2
- package/dist/{pack-meta-TjNpp3sc.mjs → pack-meta-DA3cXkds.mjs} +3 -3
- package/dist/{pack-meta-TjNpp3sc.mjs.map → pack-meta-DA3cXkds.mjs.map} +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{registry-CfU1C3-F.mjs → registry-CkZprj2g.mjs} +2 -2
- package/dist/{registry-CfU1C3-F.mjs.map → registry-CkZprj2g.mjs.map} +1 -1
- package/dist/runtime.mjs +3 -2
- package/dist/runtime.mjs.map +1 -1
- package/package.json +11 -11
- package/src/core/arktype-json-codec.ts +69 -20
- package/src/exports/runtime.ts +5 -0
- package/dist/arktype-json-codec-DluUG3EZ.mjs.map +0 -1
- package/dist/arktype-json-codec-VX9T28RG.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -9,7 +9,8 @@ Given an arktype `Type`, `arktypeJson(schema)` produces a column descriptor that
|
|
|
9
9
|
- Stores values as `jsonb` on Postgres.
|
|
10
10
|
- Eagerly serializes `schema.expression` (TypeScript-source-like rendering) and `schema.json` (arktype's internal IR) into `typeParams`. The IR is the lossless rehydration source; the expression is the emit-path renderer's input.
|
|
11
11
|
- At runtime, the framework's unified codec descriptor map rehydrates the schema via `ark.schema(typeParams.jsonIr)` and returns a `Codec` whose `decode` validates wire payloads via the rehydrated schema. Validation failures throw `RUNTIME.JSON_SCHEMA_VALIDATION_FAILED`.
|
|
12
|
-
-
|
|
12
|
+
- `encode` is schema-independent and only checks JSON representability; validation runs on `decode` and `decodeJson`.
|
|
13
|
+
- The emitted `contract.d.ts` renders the column's TS type as the schema's `expression` (e.g. `{ name: string; price: number }`). No-emit contracts currently fall back to the base codec output type (`unknown`).
|
|
13
14
|
|
|
14
15
|
## Why a per-library extension
|
|
15
16
|
|
|
@@ -30,14 +31,13 @@ const contract = defineContract({ /* ... */ }, ({ field, model }) => ({
|
|
|
30
31
|
fields: {
|
|
31
32
|
id: field.id.uuidv4(),
|
|
32
33
|
spec: field.column(arktypeJson(ProductSchema)),
|
|
33
|
-
// ^? Type<{ name: string; price: number; description?: string }>
|
|
34
34
|
},
|
|
35
35
|
}).sql({ table: 'product' }),
|
|
36
36
|
},
|
|
37
37
|
}));
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
After emit, `Product.spec` in `contract.d.ts` resolves to `{ name: string; price: number; description?: string }` because the schema's expression renders directly into the field type. In the no-emit TypeScript path, the column still carries `typeParams` and runtime validation, but `FieldOutputType` currently falls back to `CodecTypes['arktype/json@1']['output']` (`unknown`), so use emitted contracts when user-facing field types must preserve the arktype schema shape.
|
|
41
41
|
|
|
42
42
|
## Pack registration
|
|
43
43
|
|
|
@@ -61,8 +61,34 @@ const stack = createSqlExecutionStack({
|
|
|
61
61
|
});
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
## Compatibility
|
|
65
|
+
|
|
66
|
+
Codec stability depends on a round-trip invariant: `ark.schema(typeParams.jsonIr).expression === typeParams.expression`. The emit-path renderer reads `expression` directly, so a contract emitted against arktype `X` and rehydrated against arktype `Y` produces correct types only as long as that invariant holds across `X→Y`.
|
|
67
|
+
|
|
68
|
+
The package's `arktype` dependency is pinned to a tilde range (`~2.1.29`) — patch upgrades are accepted, minor and major upgrades are not. Bumping the range without a coordinated re-emit of every contract using `arktype/json@1` risks emit-path output going stale relative to the rehydrated runtime schema. Consumers who upgrade `arktype` outside this range should re-run `pnpm emit` and verify `contract.d.ts` matches expectations.
|
|
69
|
+
|
|
70
|
+
The runtime enforces the invariant defensively: the codec's factory runs at execution-context construction time (typically when `runtime.connect()` is called), and throws `RUNTIME.TYPE_PARAMS_INVALID` if the rehydrated schema's `expression` doesn't match the serialized one. So a stale-but-shape-valid `contract.json` fails fast at startup rather than rendering wrong types in user code. The error message points at re-running `pnpm emit`.
|
|
71
|
+
|
|
64
72
|
## Notes
|
|
65
73
|
|
|
66
74
|
- The codec is library-bound (`arktype/json@1`), not target-bound. Other schema libraries ship as parallel extensions (`zod/json@1`, `valibot/json@1`) when their serialize/rehydrate stories materialize.
|
|
67
|
-
- `decode` validates internally and throws on rejection. JSON-Schema validation lives uniformly inside the resolved codec's `decode` body; the framework no longer maintains a parallel validator registry. Validation rejections surface as `RUNTIME.
|
|
75
|
+
- `decode` validates internally and throws on rejection. JSON-Schema validation lives uniformly inside the resolved codec's `decode` body; the framework no longer maintains a parallel validator registry. Validation rejections surface as `RUNTIME.JSON_SCHEMA_VALIDATION_FAILED`.
|
|
68
76
|
- For untyped raw JSON columns, use `jsonColumn` / `jsonbColumn` from `@prisma-next/adapter-postgres/column-types` instead.
|
|
77
|
+
|
|
78
|
+
## Data integrity: validate-on-decode, not on encode
|
|
79
|
+
|
|
80
|
+
Schema validation runs only on `decode` / `decodeJson`. `encode` checks JSON representability but does not invoke the schema. This is intentional — ADR 208 keeps `encode` parameter-independent so it can be dispatched by `codecId` without resolving per-column schemas — but it has a consequence callers must plan for: **a schema-invalid write commits the row to the database, and only then fails on the read-back through `RETURNING`**.
|
|
81
|
+
|
|
82
|
+
The TypeScript types prevent this at the call site, so well-typed callers are safe. The footgun is reachable only when types are bypassed (`as never`, `// @ts-ignore`, untyped data from a third-party feed, runtime drift between writers). In that case:
|
|
83
|
+
|
|
84
|
+
1. `ORM.create({ ... })` calls `codec.encode` — succeeds, because encode skips the schema.
|
|
85
|
+
2. `INSERT … RETURNING` runs in autocommit — the row commits to the database.
|
|
86
|
+
3. Decoding the `RETURNING` payload invokes `codec.decode` — throws `RUNTIME.JSON_SCHEMA_VALIDATION_FAILED`.
|
|
87
|
+
4. The caller sees an error from `create`, but the bad row is now in the table and every subsequent read of it will fail the same way.
|
|
88
|
+
|
|
89
|
+
If your inputs cross a type boundary you don't fully control, mitigate:
|
|
90
|
+
|
|
91
|
+
- **Wrap mutations in `withTransaction`** so a `RETURNING`-decode failure rolls back the `INSERT`.
|
|
92
|
+
- **Pre-validate** with `schema.allows(value)` (or `schema(value) instanceof ArkErrors`) before calling `create` / `update`.
|
|
93
|
+
|
|
94
|
+
In a fully-typed application path this never fires; the warning is for the boundary where ergonomics collide with foreign data.
|
|
@@ -24,11 +24,11 @@ type ArktypeJsonTypeParams = {
|
|
|
24
24
|
type ArktypeSchemaLike = ((value: unknown) => unknown) & {
|
|
25
25
|
readonly expression: string;
|
|
26
26
|
};
|
|
27
|
-
declare class ArktypeJsonCodecClass<TInferred> extends CodecImpl<typeof ARKTYPE_JSON_CODEC_ID, readonly ['equality'], string, TInferred> {
|
|
27
|
+
declare class ArktypeJsonCodecClass<TInferred> extends CodecImpl<typeof ARKTYPE_JSON_CODEC_ID, readonly ['equality'], string | JsonValue, TInferred> {
|
|
28
28
|
private readonly schema;
|
|
29
29
|
constructor(descriptor: ArktypeJsonDescriptor, schema: ArktypeSchemaLike);
|
|
30
30
|
encode(value: TInferred, _ctx: CodecCallContext): Promise<string>;
|
|
31
|
-
decode(wire: string, _ctx: CodecCallContext): Promise<TInferred>;
|
|
31
|
+
decode(wire: string | JsonValue, _ctx: CodecCallContext): Promise<TInferred>;
|
|
32
32
|
encodeJson(value: TInferred): JsonValue;
|
|
33
33
|
decodeJson(json: JsonValue): TInferred;
|
|
34
34
|
}
|
|
@@ -36,6 +36,15 @@ declare class ArktypeJsonDescriptor extends CodecDescriptorImpl<ArktypeJsonTypeP
|
|
|
36
36
|
readonly codecId: "arktype/json@1";
|
|
37
37
|
readonly traits: readonly ["equality"];
|
|
38
38
|
readonly targetTypes: readonly ["jsonb"];
|
|
39
|
+
readonly meta: {
|
|
40
|
+
readonly db: {
|
|
41
|
+
readonly sql: {
|
|
42
|
+
readonly postgres: {
|
|
43
|
+
readonly nativeType: "jsonb";
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
39
48
|
readonly paramsSchema: StandardSchemaV1<ArktypeJsonTypeParams>;
|
|
40
49
|
renderOutputType(params: ArktypeJsonTypeParams): string;
|
|
41
50
|
factory(params: ArktypeJsonTypeParams): (ctx: CodecInstanceContext) => ArktypeJsonCodecClass<unknown>;
|
|
@@ -54,4 +63,4 @@ declare function arktypeJsonColumn<S extends Type<unknown>>(schema: S): ColumnSp
|
|
|
54
63
|
type ArktypeJsonCodec<TInferred> = ArktypeJsonCodecClass<TInferred>;
|
|
55
64
|
//#endregion
|
|
56
65
|
export { ArktypeJsonTypeParams as a, ArktypeJsonDescriptor as i, ARKTYPE_JSON_NATIVE_TYPE as n, arktypeJsonColumn as o, ArktypeJsonCodec as r, ARKTYPE_JSON_CODEC_ID as t };
|
|
57
|
-
//# sourceMappingURL=arktype-json-codec-
|
|
66
|
+
//# sourceMappingURL=arktype-json-codec-BRSKEodM.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arktype-json-codec-BRSKEodM.d.mts","names":[],"sources":["../src/core/arktype-json-codec.ts"],"mappings":";;;;;;AAqCA;AAAA,cARa,qBAAA;;cAGA,wBAAA;;AAcX;;KATU,qBAAA;EAWe;;AA8G3B;EA9G2B,SAPhB,UAAA;EAqHuB;;;EAAA,SAjHvB,MAAA;AAAA;AAAA,KAGN,iBAAA,KAAsB,KAAA;EAAA,SAChB,UAAA;AAAA;AAAA,cA6GE,qBAAA,oBAAyC,SAAA,QAC7C,qBAAA,kCAEE,SAAA,EACT,SAAA;EAAA,iBAImB,MAAA;cADjB,UAAA,EAAY,qBAAA,EACK,MAAA,EAAQ,iBAAA;EAKrB,MAAA,CAAO,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAIlD,MAAA,CAAO,IAAA,WAAe,SAAA,EAAW,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,SAAA;EAIxE,UAAA,CAAW,KAAA,EAAO,SAAA,GAAY,SAAA;EAI9B,UAAA,CAAW,IAAA,EAAM,SAAA,GAAY,SAAA;AAAA;AAAA,cAYlB,qBAAA,SAA8B,mBAAA,CAAoB,qBAAA;EAAA,SAC3C,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,IAAA;IAAA;;;;;;;;WACA,YAAA,EAAc,gBAAA,CAAiB,qBAAA;EACxC,gBAAA,CAAiB,MAAA,EAAQ,qBAAA;EAGzB,OAAA,CACP,MAAA,EAAQ,qBAAA,IACN,GAAA,EAAK,oBAAA,KAAyB,qBAAA;AAAA;;;;;;;;iBA2BpB,iBAAA,WAA4B,IAAA,UAAA,CAC1C,MAAA,EAAQ,CAAA,GACP,UAAA,CAAW,qBAAA,CAAsB,CAAA,YAAa,qBAAA;;;;KA4BrC,gBAAA,cAA8B,qBAAA,CAAsB,SAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CodecDescriptorImpl, CodecImpl, column } from "@prisma-next/framework-components/codec";
|
|
2
|
-
import { runtimeError } from "@prisma-next/framework-components/runtime";
|
|
2
|
+
import { isRuntimeError, runtimeError } from "@prisma-next/framework-components/runtime";
|
|
3
3
|
import { ArkErrors, ark, type } from "arktype";
|
|
4
4
|
//#region src/core/arktype-json-codec.ts
|
|
5
5
|
/** Codec id for arktype-backed JSON columns. Library-bound, not target-bound. */
|
|
@@ -18,15 +18,31 @@ function validateSchema(schema, value) {
|
|
|
18
18
|
});
|
|
19
19
|
return result;
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function serializeWire(value) {
|
|
22
22
|
const wire = JSON.stringify(value);
|
|
23
|
-
if (typeof wire !== "string") throw
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
if (typeof wire !== "string") throw new Error(`arktype-json value is not representable as JSON (codecId: ${ARKTYPE_JSON_CODEC_ID})`);
|
|
24
|
+
return wire;
|
|
25
|
+
}
|
|
26
|
+
function serializeJson(value) {
|
|
27
|
+
return JSON.parse(serializeWire(value));
|
|
28
|
+
}
|
|
29
|
+
function parseJsonText(wire) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(wire);
|
|
32
|
+
} catch {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function decodeWireValue(schema, wire) {
|
|
37
|
+
if (typeof wire !== "string") return validateSchema(schema, wire);
|
|
38
|
+
try {
|
|
39
|
+
return validateSchema(schema, wire);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (!isRuntimeError(error) || error.code !== "RUNTIME.JSON_SCHEMA_VALIDATION_FAILED") throw error;
|
|
42
|
+
const parsed = parseJsonText(wire);
|
|
43
|
+
if (parsed === void 0) throw error;
|
|
44
|
+
return validateSchema(schema, parsed);
|
|
45
|
+
}
|
|
30
46
|
}
|
|
31
47
|
function rehydrateSchema(jsonIr) {
|
|
32
48
|
let rehydrated;
|
|
@@ -62,13 +78,13 @@ var ArktypeJsonCodecClass = class extends CodecImpl {
|
|
|
62
78
|
this.schema = schema;
|
|
63
79
|
}
|
|
64
80
|
async encode(value, _ctx) {
|
|
65
|
-
return
|
|
81
|
+
return serializeWire(value);
|
|
66
82
|
}
|
|
67
83
|
async decode(wire, _ctx) {
|
|
68
|
-
return
|
|
84
|
+
return decodeWireValue(this.schema, wire);
|
|
69
85
|
}
|
|
70
86
|
encodeJson(value) {
|
|
71
|
-
return
|
|
87
|
+
return serializeJson(value);
|
|
72
88
|
}
|
|
73
89
|
decodeJson(json) {
|
|
74
90
|
return validateSchema(this.schema, json);
|
|
@@ -78,20 +94,24 @@ const arktypeJsonParamsSchema = type({
|
|
|
78
94
|
expression: "string",
|
|
79
95
|
jsonIr: "object"
|
|
80
96
|
});
|
|
97
|
+
const ARKTYPE_JSON_META = { db: { sql: { postgres: { nativeType: "jsonb" } } } };
|
|
81
98
|
var ArktypeJsonDescriptor = class extends CodecDescriptorImpl {
|
|
82
99
|
codecId = ARKTYPE_JSON_CODEC_ID;
|
|
83
100
|
traits = ["equality"];
|
|
84
101
|
targetTypes = [ARKTYPE_JSON_NATIVE_TYPE];
|
|
102
|
+
meta = ARKTYPE_JSON_META;
|
|
85
103
|
paramsSchema = arktypeJsonParamsSchema;
|
|
86
104
|
renderOutputType(params) {
|
|
87
105
|
return renderArktypeJsonOutputType(params);
|
|
88
106
|
}
|
|
89
107
|
factory(params) {
|
|
90
108
|
const schema = rehydrateSchema(params.jsonIr);
|
|
91
|
-
/* c8 ignore start — defensive parity check; not exercised by typical contracts */
|
|
92
109
|
const rehydratedExpression = schema.expression;
|
|
93
|
-
if (typeof rehydratedExpression === "string" && rehydratedExpression !== params.expression)
|
|
94
|
-
|
|
110
|
+
if (typeof rehydratedExpression === "string" && rehydratedExpression !== params.expression) throw runtimeError("RUNTIME.TYPE_PARAMS_INVALID", `arktype-json: typeParams.expression (${params.expression}) does not match the rehydrated schema's expression (${rehydratedExpression}). The contract was likely emitted against a different arktype version or hand-edited; re-run \`pnpm emit\` to regenerate.`, {
|
|
111
|
+
codecId: ARKTYPE_JSON_CODEC_ID,
|
|
112
|
+
serializedExpression: params.expression,
|
|
113
|
+
rehydratedExpression
|
|
114
|
+
});
|
|
95
115
|
return () => new ArktypeJsonCodecClass(this, schema);
|
|
96
116
|
}
|
|
97
117
|
};
|
|
@@ -117,4 +137,4 @@ const codecDescriptors = [arktypeJsonDescriptor];
|
|
|
117
137
|
//#endregion
|
|
118
138
|
export { codecDescriptors as i, ARKTYPE_JSON_NATIVE_TYPE as n, arktypeJsonColumn as r, ARKTYPE_JSON_CODEC_ID as t };
|
|
119
139
|
|
|
120
|
-
//# sourceMappingURL=arktype-json-codec-
|
|
140
|
+
//# sourceMappingURL=arktype-json-codec-BjUHsoD5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arktype-json-codec-BjUHsoD5.mjs","names":[],"sources":["../src/core/arktype-json-codec.ts"],"sourcesContent":["/**\n * Arktype-json codec (TML-2357).\n *\n * Spec § Case 3: method-level generic over `S extends Type<unknown>`. The schema's TypeScript-level inferred type `S['infer']` is only available at the column-author site (where the user passes their typed schema), not at the descriptor's factory site (where only the serialized IR is available). This drives the shape:\n *\n * 1. {@link ArktypeJsonCodecClass} extends {@link CodecImpl} and is generic over `TInferred` — the application-level JS type the schema validates to. The constructor takes both the descriptor (for `id` proxy) and the rehydrated arktype `Type` (closure-captured so encode/decode/encodeJson/decodeJson can validate through it). 2. {@link ArktypeJsonDescriptor} extends {@link CodecDescriptorImpl} over {@link\n * ArktypeJsonTypeParams}. Factory rehydrates the schema from `params.jsonIr` and returns `(ctx) => new ArktypeJsonCodecClass<unknown>(this, schema)` — `S` is erased to `unknown` because the descriptor only sees IR. The runtime path through `descriptor.factory(params)` always exists (e.g. for `validateContract` re-materialization); it just loses the typed inferred shape. 3. {@link arktypeJsonColumn} is the column-author\n * surface with the method-level generic over `S extends Type<unknown>`. It bypasses `descriptor.factory` because `S` is only available here, instead constructing the typed codec directly so `S['infer']` flows through `codecFactory`'s return into the column site's resolved output type. Eager serialization at this call site captures `expression` (for the emit-path renderer) and `jsonIr` (for runtime rehydration).\n *\n * `satisfies ColumnHelperFor<ArktypeJsonDescriptor>` (coarse) is applied — the typeParams shape is verified. `ColumnHelperForStrict` is intentionally skipped: the descriptor's factory return is `ArktypeJsonCodecClass<unknown>` while the helper produces `ArktypeJsonCodecClass<S['infer']>`, and `Codec`'s `TInput` is invariant (used contravariantly in `encode`, covariantly in `decode`/`encodeJson`/`decodeJson`). Strict\n * assignment fails by design; the explicit `expectTypeOf` tests in `test/arktype-json-codec.types.test-d.ts` cover the literal-preservation property the strict variant would otherwise enforce.\n */\n\nimport type { JsonValue } from '@prisma-next/contract/types';\nimport {\n type AnyCodecDescriptor,\n type CodecCallContext,\n CodecDescriptorImpl,\n CodecImpl,\n type CodecInstanceContext,\n type ColumnHelperFor,\n type ColumnSpec,\n column,\n} from '@prisma-next/framework-components/codec';\nimport { isRuntimeError, runtimeError } from '@prisma-next/framework-components/runtime';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { ArkErrors, ark, type Type, type } from 'arktype';\n\n/** Codec id for arktype-backed JSON columns. Library-bound, not target-bound. */\nexport const ARKTYPE_JSON_CODEC_ID = 'arktype/json@1' as const;\n\n/** Native storage type backing the codec. JSONB on Postgres; binary, indexable. */\nexport const ARKTYPE_JSON_NATIVE_TYPE = 'jsonb' as const;\n\n/**\n * Eagerly serialized typeParams for the arktype-json column. Carried in the contract IR; the runtime descriptor's factory rehydrates `jsonIr` and the emitter consumes `expression`.\n */\nexport type ArktypeJsonTypeParams = {\n /**\n * Arktype's TypeScript-source-like rendering of the schema. Read by `renderOutputType` to emit the column's TS type into `contract.d.ts`. Stable across the serialize/rehydrate cycle: the rehydrated schema's `expression` matches the source schema's.\n */\n readonly expression: string;\n /**\n * Arktype's internal IR for the schema. Lossless; the rehydration source. Schema-shape — `ark.schema(jsonIr)` reconstructs a callable `Type`-like structurally identical to the original `type(definition)` output.\n */\n readonly jsonIr: object;\n};\n\ntype ArktypeSchemaLike = ((value: unknown) => unknown) & {\n readonly expression: string;\n};\n\nfunction isArktypeSchemaLike(value: unknown): value is ArktypeSchemaLike {\n if (typeof value !== 'function') return false;\n const expression = (value as { readonly expression?: unknown }).expression;\n return typeof expression === 'string';\n}\n\nfunction validateSchema<TInferred>(schema: ArktypeSchemaLike, value: unknown): TInferred {\n const result = schema(value);\n if (result instanceof ArkErrors) {\n throw runtimeError(\n 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',\n `arktype-json schema validation failed (decode): ${result.summary}`,\n { codecId: ARKTYPE_JSON_CODEC_ID, issues: result.summary },\n );\n }\n return result as TInferred;\n}\n\nfunction serializeWire<TInferred>(value: TInferred): string {\n const wire: string | undefined = JSON.stringify(value);\n if (typeof wire !== 'string') {\n throw new Error(\n `arktype-json value is not representable as JSON (codecId: ${ARKTYPE_JSON_CODEC_ID})`,\n );\n }\n return wire;\n}\n\nfunction serializeJson<TInferred>(value: TInferred): JsonValue {\n // The stringify → parse round-trip both validates JSON-representability\n // (matching `serializeWire`) and produces a deep-cloned `JsonValue` that\n // strips class prototypes / `toJSON` side effects, so callers reading\n // the in-memory `JsonValue` see exactly the shape that would round-trip\n // through the database.\n return JSON.parse(serializeWire(value)) as JsonValue;\n}\n\nfunction parseJsonText(wire: string): JsonValue | undefined {\n try {\n return JSON.parse(wire) as JsonValue;\n } catch {\n return undefined;\n }\n}\n\nfunction decodeWireValue<TInferred>(\n schema: ArktypeSchemaLike,\n wire: string | JsonValue,\n): TInferred {\n if (typeof wire !== 'string') return validateSchema<TInferred>(schema, wire);\n\n // Try the wire as the literal value first. Under `pg` + `jsonb` (the\n // documented native type), wire arrives already-parsed: a JSON object\n // surfaces as a JS object, a JSON string surfaces as a JS string. For\n // string columns that means the wire IS the user's value — including\n // strings whose literal characters happen to start and end with `\"`.\n // A `\"…\"`-shape unwrap heuristic would silently truncate them (the\n // 7-char `\"hello\"` would decode to the 5-char `hello`).\n //\n // Fall back to JSON.parse only when schema validation rejects the raw\n // wire: that path covers object/array shapes received as raw JSON\n // text (legacy `json` text-OID adapters, or any code path that hands\n // us un-pre-parsed JSON).\n try {\n return validateSchema<TInferred>(schema, wire);\n } catch (error) {\n if (!isRuntimeError(error) || error.code !== 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED') {\n throw error;\n }\n const parsed = parseJsonText(wire);\n if (parsed === undefined) {\n throw error;\n }\n return validateSchema<TInferred>(schema, parsed);\n }\n}\n\nfunction rehydrateSchema(jsonIr: object): ArktypeSchemaLike {\n let rehydrated: unknown;\n try {\n rehydrated = ark.schema(jsonIr);\n } catch (error) {\n throw runtimeError(\n 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',\n /* c8 ignore next — the `String(error)` fallback covers throws of non-Error values; arktype only throws Error subclasses, so this branch is defensive only. */\n `Failed to rehydrate arktype schema from contract IR: ${error instanceof Error ? error.message : String(error)}`,\n { codecId: ARKTYPE_JSON_CODEC_ID, jsonIr },\n );\n }\n /* c8 ignore start — defensive: ark.schema either throws (handled above) or returns a callable Type with `expression: string`. The structural guard is kept so a future ark internal change can't silently slip a non-callable past us. */\n if (!isArktypeSchemaLike(rehydrated)) {\n throw runtimeError(\n 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',\n `Rehydrated arktype schema does not have the expected callable + 'expression: string' shape (codecId: ${ARKTYPE_JSON_CODEC_ID})`,\n { codecId: ARKTYPE_JSON_CODEC_ID, jsonIr },\n );\n }\n /* c8 ignore stop */\n return rehydrated;\n}\n\nfunction renderArktypeJsonOutputType(params: ArktypeJsonTypeParams): string {\n const expression = params.expression.trim();\n return expression.length > 0 ? expression : 'unknown';\n}\n\nexport class ArktypeJsonCodecClass<TInferred> extends CodecImpl<\n typeof ARKTYPE_JSON_CODEC_ID,\n readonly ['equality'],\n string | JsonValue,\n TInferred\n> {\n constructor(\n descriptor: ArktypeJsonDescriptor,\n private readonly schema: ArktypeSchemaLike,\n ) {\n super(descriptor);\n }\n\n async encode(value: TInferred, _ctx: CodecCallContext): Promise<string> {\n return serializeWire(value);\n }\n\n async decode(wire: string | JsonValue, _ctx: CodecCallContext): Promise<TInferred> {\n return decodeWireValue<TInferred>(this.schema, wire);\n }\n\n encodeJson(value: TInferred): JsonValue {\n return serializeJson(value);\n }\n\n decodeJson(json: JsonValue): TInferred {\n return validateSchema<TInferred>(this.schema, json);\n }\n}\n\nconst arktypeJsonParamsSchema = type({\n expression: 'string',\n jsonIr: 'object',\n}) satisfies StandardSchemaV1<ArktypeJsonTypeParams>;\n\nconst ARKTYPE_JSON_META = { db: { sql: { postgres: { nativeType: 'jsonb' } } } } as const;\n\nexport class ArktypeJsonDescriptor extends CodecDescriptorImpl<ArktypeJsonTypeParams> {\n override readonly codecId = ARKTYPE_JSON_CODEC_ID;\n override readonly traits = ['equality'] as const;\n override readonly targetTypes = [ARKTYPE_JSON_NATIVE_TYPE] as const;\n override readonly meta = ARKTYPE_JSON_META;\n override readonly paramsSchema: StandardSchemaV1<ArktypeJsonTypeParams> = arktypeJsonParamsSchema;\n override renderOutputType(params: ArktypeJsonTypeParams): string {\n return renderArktypeJsonOutputType(params);\n }\n override factory(\n params: ArktypeJsonTypeParams,\n ): (ctx: CodecInstanceContext) => ArktypeJsonCodecClass<unknown> {\n const schema = rehydrateSchema(params.jsonIr);\n const rehydratedExpression = (schema as { readonly expression?: unknown }).expression;\n if (typeof rehydratedExpression === 'string' && rehydratedExpression !== params.expression) {\n throw runtimeError(\n 'RUNTIME.TYPE_PARAMS_INVALID',\n `arktype-json: typeParams.expression (${params.expression}) does not match the rehydrated schema's expression (${rehydratedExpression}). The contract was likely emitted against a different arktype version or hand-edited; re-run \\`pnpm emit\\` to regenerate.`,\n {\n codecId: ARKTYPE_JSON_CODEC_ID,\n serializedExpression: params.expression,\n rehydratedExpression,\n },\n );\n }\n return () => new ArktypeJsonCodecClass<unknown>(this, schema);\n }\n}\n\nexport const arktypeJsonDescriptor = new ArktypeJsonDescriptor();\n\n/**\n * Per-codec column helper for `arktype/json@1`. Method-level generic over `S extends Type<unknown>` so the column site preserves the schema's inferred TS type in the resolved codec (`ArktypeJsonCodecClass<S['infer']>`). Bypasses `descriptor.factory` because `S` is only available at the column-author site; constructs the typed codec directly with the closure-captured schema.\n *\n * Eager serialization at this call site captures `expression` (for the emit-path renderer) and `jsonIr` (for runtime rehydration via the descriptor's factory).\n *\n * @throws {Error} if the schema doesn't expose `expression` and `json` fields (i.e. is not an arktype `Type`). Validates the schema shape at the call site so configuration errors surface during contract authoring, not at runtime.\n */\nexport function arktypeJsonColumn<S extends Type<unknown>>(\n schema: S,\n): ColumnSpec<ArktypeJsonCodecClass<S['infer']>, ArktypeJsonTypeParams> {\n if (!isArktypeSchemaLike(schema)) {\n throw new Error(\n typeof schema !== 'function'\n ? 'arktypeJsonColumn(schema) expects a callable arktype Type.'\n : 'arktypeJsonColumn(schema) expects an arktype Type (missing `expression: string`).',\n );\n }\n const jsonIr: unknown = (schema as { readonly json?: unknown }).json;\n if (jsonIr === null || typeof jsonIr !== 'object') {\n throw new Error('arktypeJsonColumn(schema) expects an arktype Type (missing `json` IR).');\n }\n const params: ArktypeJsonTypeParams = { expression: schema.expression, jsonIr };\n return column(\n (_ctx: CodecInstanceContext) =>\n new ArktypeJsonCodecClass<S['infer']>(arktypeJsonDescriptor, schema),\n arktypeJsonDescriptor.codecId,\n params,\n ARKTYPE_JSON_NATIVE_TYPE,\n );\n}\n\narktypeJsonColumn satisfies ColumnHelperFor<ArktypeJsonDescriptor>;\n// Note: `ColumnHelperForStrict` is intentionally not applied — `Codec` is invariant in `TInput` (encode contravariant, decode covariant), so `ArktypeJsonCodecClass<S['infer']>` is not assignable to `ArktypeJsonCodecClass<unknown>` (the descriptor.factory return). `expectTypeOf` tests cover the literal-preservation property strict satisfies would otherwise enforce.\n\n/**\n * Codec instance returned by `arktypeJsonColumn(schema).codecFactory(ctx)` and by `arktypeJsonDescriptor.factory(typeParams)(ctx)`. The `TInferred` slot carries the arktype schema's inferred output type at the column-author site; descriptor-side factories erase to `unknown`.\n */\nexport type ArktypeJsonCodec<TInferred> = ArktypeJsonCodecClass<TInferred>;\n\nexport const codecDescriptors: readonly AnyCodecDescriptor[] = [arktypeJsonDescriptor];\n"],"mappings":";;;;;AA6BA,MAAa,wBAAwB;;AAGrC,MAAa,2BAA2B;AAoBxC,SAAS,oBAAoB,OAA4C;CACvE,IAAI,OAAO,UAAU,YAAY,OAAO;CAExC,OAAO,OADa,MAA4C,eACnC;;AAG/B,SAAS,eAA0B,QAA2B,OAA2B;CACvF,MAAM,SAAS,OAAO,MAAM;CAC5B,IAAI,kBAAkB,WACpB,MAAM,aACJ,yCACA,mDAAmD,OAAO,WAC1D;EAAE,SAAS;EAAuB,QAAQ,OAAO;EAAS,CAC3D;CAEH,OAAO;;AAGT,SAAS,cAAyB,OAA0B;CAC1D,MAAM,OAA2B,KAAK,UAAU,MAAM;CACtD,IAAI,OAAO,SAAS,UAClB,MAAM,IAAI,MACR,6DAA6D,sBAAsB,GACpF;CAEH,OAAO;;AAGT,SAAS,cAAyB,OAA6B;CAM7D,OAAO,KAAK,MAAM,cAAc,MAAM,CAAC;;AAGzC,SAAS,cAAc,MAAqC;CAC1D,IAAI;EACF,OAAO,KAAK,MAAM,KAAK;SACjB;EACN;;;AAIJ,SAAS,gBACP,QACA,MACW;CACX,IAAI,OAAO,SAAS,UAAU,OAAO,eAA0B,QAAQ,KAAK;CAc5E,IAAI;EACF,OAAO,eAA0B,QAAQ,KAAK;UACvC,OAAO;EACd,IAAI,CAAC,eAAe,MAAM,IAAI,MAAM,SAAS,yCAC3C,MAAM;EAER,MAAM,SAAS,cAAc,KAAK;EAClC,IAAI,WAAW,KAAA,GACb,MAAM;EAER,OAAO,eAA0B,QAAQ,OAAO;;;AAIpD,SAAS,gBAAgB,QAAmC;CAC1D,IAAI;CACJ,IAAI;EACF,aAAa,IAAI,OAAO,OAAO;UACxB,OAAO;EACd,MAAM;GACJ;;GAEA,wDAAwD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC9G;IAAE,SAAS;IAAuB;IAAQ;GAC3C;;;CAGH,IAAI,CAAC,oBAAoB,WAAW,EAClC,MAAM,aACJ,yCACA,wGAAwG,sBAAsB,IAC9H;EAAE,SAAS;EAAuB;EAAQ,CAC3C;;CAGH,OAAO;;AAGT,SAAS,4BAA4B,QAAuC;CAC1E,MAAM,aAAa,OAAO,WAAW,MAAM;CAC3C,OAAO,WAAW,SAAS,IAAI,aAAa;;AAG9C,IAAa,wBAAb,cAAsD,UAKpD;CAGmB;CAFnB,YACE,YACA,QACA;EACA,MAAM,WAAW;EAFA,KAAA,SAAA;;CAKnB,MAAM,OAAO,OAAkB,MAAyC;EACtE,OAAO,cAAc,MAAM;;CAG7B,MAAM,OAAO,MAA0B,MAA4C;EACjF,OAAO,gBAA2B,KAAK,QAAQ,KAAK;;CAGtD,WAAW,OAA6B;EACtC,OAAO,cAAc,MAAM;;CAG7B,WAAW,MAA4B;EACrC,OAAO,eAA0B,KAAK,QAAQ,KAAK;;;AAIvD,MAAM,0BAA0B,KAAK;CACnC,YAAY;CACZ,QAAQ;CACT,CAAC;AAEF,MAAM,oBAAoB,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,SAAS,EAAE,EAAE,EAAE;AAEhF,IAAa,wBAAb,cAA2C,oBAA2C;CACpF,UAA4B;CAC5B,SAA2B,CAAC,WAAW;CACvC,cAAgC,CAAC,yBAAyB;CAC1D,OAAyB;CACzB,eAA0E;CAC1E,iBAA0B,QAAuC;EAC/D,OAAO,4BAA4B,OAAO;;CAE5C,QACE,QAC+D;EAC/D,MAAM,SAAS,gBAAgB,OAAO,OAAO;EAC7C,MAAM,uBAAwB,OAA6C;EAC3E,IAAI,OAAO,yBAAyB,YAAY,yBAAyB,OAAO,YAC9E,MAAM,aACJ,+BACA,wCAAwC,OAAO,WAAW,uDAAuD,qBAAqB,6HACtI;GACE,SAAS;GACT,sBAAsB,OAAO;GAC7B;GACD,CACF;EAEH,aAAa,IAAI,sBAA+B,MAAM,OAAO;;;AAIjE,MAAa,wBAAwB,IAAI,uBAAuB;;;;;;;;AAShE,SAAgB,kBACd,QACsE;CACtE,IAAI,CAAC,oBAAoB,OAAO,EAC9B,MAAM,IAAI,MACR,OAAO,WAAW,aACd,+DACA,oFACL;CAEH,MAAM,SAAmB,OAAuC;CAChE,IAAI,WAAW,QAAQ,OAAO,WAAW,UACvC,MAAM,IAAI,MAAM,yEAAyE;CAE3F,MAAM,SAAgC;EAAE,YAAY,OAAO;EAAY;EAAQ;CAC/E,OAAO,QACJ,SACC,IAAI,sBAAkC,uBAAuB,OAAO,EACtE,sBAAsB,SACtB,QACA,yBACD;;AAWH,MAAa,mBAAkD,CAAC,sBAAsB"}
|
package/dist/codecs.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ArktypeJsonTypeParams, i as ArktypeJsonDescriptor, n as ARKTYPE_JSON_NATIVE_TYPE, o as arktypeJsonColumn, r as ArktypeJsonCodec, t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-
|
|
1
|
+
import { a as ArktypeJsonTypeParams, i as ArktypeJsonDescriptor, n as ARKTYPE_JSON_NATIVE_TYPE, o as arktypeJsonColumn, r as ArktypeJsonCodec, t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-BRSKEodM.mjs";
|
|
2
2
|
import { CodecDescriptorRegistry } from "@prisma-next/sql-relational-core/query-lane-context";
|
|
3
3
|
|
|
4
4
|
//#region src/core/registry.d.ts
|
package/dist/codecs.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as ARKTYPE_JSON_NATIVE_TYPE, r as arktypeJsonColumn, t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-
|
|
2
|
-
import { t as arktypeJsonCodecRegistry } from "./registry-
|
|
1
|
+
import { n as ARKTYPE_JSON_NATIVE_TYPE, r as arktypeJsonColumn, t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-BjUHsoD5.mjs";
|
|
2
|
+
import { t as arktypeJsonCodecRegistry } from "./registry-CkZprj2g.mjs";
|
|
3
3
|
export { ARKTYPE_JSON_CODEC_ID, ARKTYPE_JSON_NATIVE_TYPE, arktypeJsonCodecRegistry, arktypeJsonColumn };
|
package/dist/column-types.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ArktypeJsonTypeParams, o as arktypeJsonColumn, r as ArktypeJsonCodec } from "./arktype-json-codec-
|
|
1
|
+
import { a as ArktypeJsonTypeParams, o as arktypeJsonColumn, r as ArktypeJsonCodec } from "./arktype-json-codec-BRSKEodM.mjs";
|
|
2
2
|
export { type ArktypeJsonCodec, type ArktypeJsonTypeParams, arktypeJsonColumn as arktypeJson };
|
package/dist/column-types.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { r as arktypeJsonColumn } from "./arktype-json-codec-
|
|
1
|
+
import { r as arktypeJsonColumn } from "./arktype-json-codec-BjUHsoD5.mjs";
|
|
2
2
|
export { arktypeJsonColumn as arktypeJson };
|
package/dist/control.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-
|
|
2
|
-
import { t as arktypeJsonPackMeta } from "./pack-meta-
|
|
1
|
+
import { t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-BjUHsoD5.mjs";
|
|
2
|
+
import { t as arktypeJsonPackMeta } from "./pack-meta-DA3cXkds.mjs";
|
|
3
3
|
//#region src/exports/control.ts
|
|
4
4
|
const arktypeJsonControlPlaneHooks = { expandNativeType: ({ nativeType }) => nativeType };
|
|
5
5
|
const arktypeJsonExtensionDescriptor = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-
|
|
2
|
-
import { t as arktypeJsonCodecRegistry } from "./registry-
|
|
1
|
+
import { t as ARKTYPE_JSON_CODEC_ID } from "./arktype-json-codec-BjUHsoD5.mjs";
|
|
2
|
+
import { t as arktypeJsonCodecRegistry } from "./registry-CkZprj2g.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* Public pack metadata. The phantom `__codecTypes` field threads the codec-types map's literal type into the pack ref so contract-builder generics can pick it up; it is never accessed at runtime.
|
|
5
5
|
*/
|
|
@@ -30,4 +30,4 @@ const arktypeJsonPackMeta = {
|
|
|
30
30
|
//#endregion
|
|
31
31
|
export { arktypeJsonPackMeta as t };
|
|
32
32
|
|
|
33
|
-
//# sourceMappingURL=pack-meta-
|
|
33
|
+
//# sourceMappingURL=pack-meta-DA3cXkds.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack-meta-
|
|
1
|
+
{"version":3,"file":"pack-meta-DA3cXkds.mjs","names":[],"sources":["../src/core/pack-meta.ts"],"sourcesContent":["/**\n * arktype-json pack metadata.\n *\n * The pack metadata is the framework-composition entry point: control-stack assembly reads `types.codecTypes.import` to thread the type-side imports into emitted `contract.d.ts`, and `types.storage` declares the codec id's storage backing (`jsonb` on Postgres).\n *\n * Per TML-2357 runtime materialization flows through the unified descriptor map (`arktypeJsonDescriptor`) and the emit path consults `descriptorFor('arktype/json@1').renderOutputType` directly — no per-library \"emit-only Codec\" stub.\n */\n\nimport type { CodecTypes } from '../types/codec-types';\nimport { ARKTYPE_JSON_CODEC_ID } from './arktype-json-codec';\nimport { arktypeJsonCodecRegistry } from './registry';\n\nconst arktypeJsonPackMetaBase = {\n kind: 'extension',\n id: 'arktype-json',\n familyId: 'sql',\n targetId: 'postgres',\n version: '0.0.1',\n capabilities: {},\n types: {\n codecTypes: {\n codecDescriptors: Array.from(arktypeJsonCodecRegistry.values()),\n import: {\n package: '@prisma-next/extension-arktype-json/codec-types',\n named: 'CodecTypes',\n alias: 'ArktypeJsonTypes',\n },\n },\n storage: [\n {\n typeId: ARKTYPE_JSON_CODEC_ID,\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n nativeType: 'jsonb',\n },\n ],\n },\n} as const;\n\n/**\n * Public pack metadata. The phantom `__codecTypes` field threads the codec-types map's literal type into the pack ref so contract-builder generics can pick it up; it is never accessed at runtime.\n */\nexport const arktypeJsonPackMeta: typeof arktypeJsonPackMetaBase & {\n readonly __codecTypes?: CodecTypes;\n} = arktypeJsonPackMetaBase;\n"],"mappings":";;;;;AA0CA,MAAa,sBAET;CA/BF,MAAM;CACN,IAAI;CACJ,UAAU;CACV,UAAU;CACV,SAAS;CACT,cAAc,EAAE;CAChB,OAAO;EACL,YAAY;GACV,kBAAkB,MAAM,KAAK,yBAAyB,QAAQ,CAAC;GAC/D,QAAQ;IACN,SAAS;IACT,OAAO;IACP,OAAO;IACR;GACF;EACD,SAAS,CACP;GACE,QAAQ;GACR,UAAU;GACV,UAAU;GACV,YAAY;GACb,CACF;EACF;CAQC"}
|
package/dist/pack.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as arktypeJsonPackMeta } from "./pack-meta-
|
|
1
|
+
import { t as arktypeJsonPackMeta } from "./pack-meta-DA3cXkds.mjs";
|
|
2
2
|
export { arktypeJsonPackMeta, arktypeJsonPackMeta as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as codecDescriptors } from "./arktype-json-codec-
|
|
1
|
+
import { i as codecDescriptors } from "./arktype-json-codec-BjUHsoD5.mjs";
|
|
2
2
|
import { buildCodecDescriptorRegistry } from "@prisma-next/sql-relational-core/codec-descriptor-registry";
|
|
3
3
|
//#region src/core/registry.ts
|
|
4
4
|
/**
|
|
@@ -10,4 +10,4 @@ const arktypeJsonCodecRegistry = buildCodecDescriptorRegistry(codecDescriptors);
|
|
|
10
10
|
//#endregion
|
|
11
11
|
export { arktypeJsonCodecRegistry as t };
|
|
12
12
|
|
|
13
|
-
//# sourceMappingURL=registry-
|
|
13
|
+
//# sourceMappingURL=registry-CkZprj2g.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-
|
|
1
|
+
{"version":3,"file":"registry-CkZprj2g.mjs","names":[],"sources":["../src/core/registry.ts"],"sourcesContent":["import { buildCodecDescriptorRegistry } from '@prisma-next/sql-relational-core/codec-descriptor-registry';\nimport type { CodecDescriptorRegistry } from '@prisma-next/sql-relational-core/query-lane-context';\nimport { codecDescriptors } from './arktype-json-codec';\n\n/**\n * Registry of every codec descriptor shipped by `@prisma-next/extension-arktype-json`.\n *\n * Public consumer surface for the arktype-json codec set. Currently a single entry (`arktype/json@1`); the registry shape stays consistent with the other codec-shipping packages so consumers don't need to special-case extensions. See ADR 208.\n */\nexport const arktypeJsonCodecRegistry: CodecDescriptorRegistry =\n buildCodecDescriptorRegistry(codecDescriptors);\n"],"mappings":";;;;;;;;AASA,MAAa,2BACX,6BAA6B,iBAAiB"}
|
package/dist/runtime.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as arktypeJsonCodecRegistry } from "./registry-
|
|
2
|
-
import { t as arktypeJsonPackMeta } from "./pack-meta-
|
|
1
|
+
import { t as arktypeJsonCodecRegistry } from "./registry-CkZprj2g.mjs";
|
|
2
|
+
import { t as arktypeJsonPackMeta } from "./pack-meta-DA3cXkds.mjs";
|
|
3
3
|
//#region src/exports/runtime.ts
|
|
4
4
|
const arktypeJsonRuntimeDescriptor = {
|
|
5
5
|
kind: "extension",
|
|
@@ -7,6 +7,7 @@ const arktypeJsonRuntimeDescriptor = {
|
|
|
7
7
|
version: arktypeJsonPackMeta.version,
|
|
8
8
|
familyId: "sql",
|
|
9
9
|
targetId: "postgres",
|
|
10
|
+
types: { codecTypes: { codecDescriptors: Array.from(arktypeJsonCodecRegistry.values()) } },
|
|
10
11
|
codecs: () => Array.from(arktypeJsonCodecRegistry.values()),
|
|
11
12
|
create() {
|
|
12
13
|
return {
|
package/dist/runtime.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.mjs","names":[],"sources":["../src/exports/runtime.ts"],"sourcesContent":["/**\n * Runtime-plane extension descriptor for arktype-json.\n *\n * Registers `arktypeJsonCodec` (the unified `CodecDescriptor`) through the SQL runtime's `codecs:` slot. Per TML-2357 the dedicated parameterized-codec slot retired — the unified descriptor map dispatches every codec id, parameterized or not.\n *\n * Lives at the runtime-plane entrypoint so `src/core/**` stays free of runtime-plane imports (per `.cursor/rules/multi-plane-entrypoints.mdc`).\n */\n\nimport type { SqlRuntimeExtensionDescriptor } from '@prisma-next/sql-runtime';\nimport { arktypeJsonPackMeta } from '../core/pack-meta';\nimport { arktypeJsonCodecRegistry } from '../core/registry';\n\nexport const arktypeJsonRuntimeDescriptor: SqlRuntimeExtensionDescriptor<'postgres'> = {\n kind: 'extension' as const,\n id: arktypeJsonPackMeta.id,\n version: arktypeJsonPackMeta.version,\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n codecs: () => Array.from(arktypeJsonCodecRegistry.values()),\n create() {\n return {\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n };\n },\n};\n\nexport default arktypeJsonRuntimeDescriptor;\n"],"mappings":";;;AAYA,MAAa,+BAA0E;CACrF,MAAM;CACN,IAAI,oBAAoB;CACxB,SAAS,oBAAoB;CAC7B,UAAU;CACV,UAAU;CACV,cAAc,MAAM,KAAK,yBAAyB,QAAQ,CAAC;CAC3D,SAAS;EACP,OAAO;GACL,UAAU;GACV,UAAU;GACX;;CAEJ"}
|
|
1
|
+
{"version":3,"file":"runtime.mjs","names":[],"sources":["../src/exports/runtime.ts"],"sourcesContent":["/**\n * Runtime-plane extension descriptor for arktype-json.\n *\n * Registers `arktypeJsonCodec` (the unified `CodecDescriptor`) through the SQL runtime's `codecs:` slot. Per TML-2357 the dedicated parameterized-codec slot retired — the unified descriptor map dispatches every codec id, parameterized or not.\n *\n * Lives at the runtime-plane entrypoint so `src/core/**` stays free of runtime-plane imports (per `.cursor/rules/multi-plane-entrypoints.mdc`).\n */\n\nimport type { SqlRuntimeExtensionDescriptor } from '@prisma-next/sql-runtime';\nimport { arktypeJsonPackMeta } from '../core/pack-meta';\nimport { arktypeJsonCodecRegistry } from '../core/registry';\n\nexport const arktypeJsonRuntimeDescriptor: SqlRuntimeExtensionDescriptor<'postgres'> = {\n kind: 'extension' as const,\n id: arktypeJsonPackMeta.id,\n version: arktypeJsonPackMeta.version,\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n types: {\n codecTypes: {\n codecDescriptors: Array.from(arktypeJsonCodecRegistry.values()),\n },\n },\n codecs: () => Array.from(arktypeJsonCodecRegistry.values()),\n create() {\n return {\n familyId: 'sql' as const,\n targetId: 'postgres' as const,\n };\n },\n};\n\nexport default arktypeJsonRuntimeDescriptor;\n"],"mappings":";;;AAYA,MAAa,+BAA0E;CACrF,MAAM;CACN,IAAI,oBAAoB;CACxB,SAAS,oBAAoB;CAC7B,UAAU;CACV,UAAU;CACV,OAAO,EACL,YAAY,EACV,kBAAkB,MAAM,KAAK,yBAAyB,QAAQ,CAAC,EAChE,EACF;CACD,cAAc,MAAM,KAAK,yBAAyB,QAAQ,CAAC;CAC3D,SAAS;EACP,OAAO;GACL,UAAU;GACV,UAAU;GACX;;CAEJ"}
|
package/package.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/extension-arktype-json",
|
|
3
|
-
"version": "0.6.0-dev.
|
|
3
|
+
"version": "0.6.0-dev.6",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@standard-schema/spec": "^1.1.0",
|
|
9
|
-
"arktype": "
|
|
10
|
-
"@prisma-next/contract
|
|
11
|
-
"@prisma-next/family-sql": "0.6.0-dev.
|
|
12
|
-
"@prisma-next/contract": "0.6.0-dev.
|
|
13
|
-
"@prisma-next/sql-runtime": "0.6.0-dev.
|
|
14
|
-
"@prisma-next/framework-components": "0.6.0-dev.
|
|
15
|
-
"@prisma-next/sql-relational-core": "0.6.0-dev.
|
|
9
|
+
"arktype": "~2.1.29",
|
|
10
|
+
"@prisma-next/contract": "0.6.0-dev.6",
|
|
11
|
+
"@prisma-next/family-sql": "0.6.0-dev.6",
|
|
12
|
+
"@prisma-next/contract-authoring": "0.6.0-dev.6",
|
|
13
|
+
"@prisma-next/sql-runtime": "0.6.0-dev.6",
|
|
14
|
+
"@prisma-next/framework-components": "0.6.0-dev.6",
|
|
15
|
+
"@prisma-next/sql-relational-core": "0.6.0-dev.6"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"tsdown": "0.22.0",
|
|
19
19
|
"typescript": "5.9.3",
|
|
20
20
|
"vitest": "4.1.5",
|
|
21
|
+
"@prisma-next/sql-contract": "0.6.0-dev.6",
|
|
21
22
|
"@prisma-next/test-utils": "0.0.1",
|
|
22
|
-
"@prisma-next/
|
|
23
|
-
"@prisma-next/tsdown": "0.0.0"
|
|
24
|
-
"@prisma-next/tsconfig": "0.0.0"
|
|
23
|
+
"@prisma-next/tsconfig": "0.0.0",
|
|
24
|
+
"@prisma-next/tsdown": "0.0.0"
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"dist",
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
type ColumnSpec,
|
|
23
23
|
column,
|
|
24
24
|
} from '@prisma-next/framework-components/codec';
|
|
25
|
-
import { runtimeError } from '@prisma-next/framework-components/runtime';
|
|
25
|
+
import { isRuntimeError, runtimeError } from '@prisma-next/framework-components/runtime';
|
|
26
26
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
27
27
|
import { ArkErrors, ark, type Type, type } from 'arktype';
|
|
28
28
|
|
|
@@ -68,21 +68,63 @@ function validateSchema<TInferred>(schema: ArktypeSchemaLike, value: unknown): T
|
|
|
68
68
|
return result as TInferred;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
function
|
|
72
|
-
schema: ArktypeSchemaLike,
|
|
73
|
-
value: TInferred,
|
|
74
|
-
): { wire: string; json: JsonValue } {
|
|
71
|
+
function serializeWire<TInferred>(value: TInferred): string {
|
|
75
72
|
const wire: string | undefined = JSON.stringify(value);
|
|
76
73
|
if (typeof wire !== 'string') {
|
|
77
|
-
throw
|
|
78
|
-
'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',
|
|
74
|
+
throw new Error(
|
|
79
75
|
`arktype-json value is not representable as JSON (codecId: ${ARKTYPE_JSON_CODEC_ID})`,
|
|
80
|
-
{ codecId: ARKTYPE_JSON_CODEC_ID },
|
|
81
76
|
);
|
|
82
77
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
78
|
+
return wire;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function serializeJson<TInferred>(value: TInferred): JsonValue {
|
|
82
|
+
// The stringify → parse round-trip both validates JSON-representability
|
|
83
|
+
// (matching `serializeWire`) and produces a deep-cloned `JsonValue` that
|
|
84
|
+
// strips class prototypes / `toJSON` side effects, so callers reading
|
|
85
|
+
// the in-memory `JsonValue` see exactly the shape that would round-trip
|
|
86
|
+
// through the database.
|
|
87
|
+
return JSON.parse(serializeWire(value)) as JsonValue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function parseJsonText(wire: string): JsonValue | undefined {
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(wire) as JsonValue;
|
|
93
|
+
} catch {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function decodeWireValue<TInferred>(
|
|
99
|
+
schema: ArktypeSchemaLike,
|
|
100
|
+
wire: string | JsonValue,
|
|
101
|
+
): TInferred {
|
|
102
|
+
if (typeof wire !== 'string') return validateSchema<TInferred>(schema, wire);
|
|
103
|
+
|
|
104
|
+
// Try the wire as the literal value first. Under `pg` + `jsonb` (the
|
|
105
|
+
// documented native type), wire arrives already-parsed: a JSON object
|
|
106
|
+
// surfaces as a JS object, a JSON string surfaces as a JS string. For
|
|
107
|
+
// string columns that means the wire IS the user's value — including
|
|
108
|
+
// strings whose literal characters happen to start and end with `"`.
|
|
109
|
+
// A `"…"`-shape unwrap heuristic would silently truncate them (the
|
|
110
|
+
// 7-char `"hello"` would decode to the 5-char `hello`).
|
|
111
|
+
//
|
|
112
|
+
// Fall back to JSON.parse only when schema validation rejects the raw
|
|
113
|
+
// wire: that path covers object/array shapes received as raw JSON
|
|
114
|
+
// text (legacy `json` text-OID adapters, or any code path that hands
|
|
115
|
+
// us un-pre-parsed JSON).
|
|
116
|
+
try {
|
|
117
|
+
return validateSchema<TInferred>(schema, wire);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (!isRuntimeError(error) || error.code !== 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED') {
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
const parsed = parseJsonText(wire);
|
|
123
|
+
if (parsed === undefined) {
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
return validateSchema<TInferred>(schema, parsed);
|
|
127
|
+
}
|
|
86
128
|
}
|
|
87
129
|
|
|
88
130
|
function rehydrateSchema(jsonIr: object): ArktypeSchemaLike {
|
|
@@ -117,7 +159,7 @@ function renderArktypeJsonOutputType(params: ArktypeJsonTypeParams): string {
|
|
|
117
159
|
export class ArktypeJsonCodecClass<TInferred> extends CodecImpl<
|
|
118
160
|
typeof ARKTYPE_JSON_CODEC_ID,
|
|
119
161
|
readonly ['equality'],
|
|
120
|
-
string,
|
|
162
|
+
string | JsonValue,
|
|
121
163
|
TInferred
|
|
122
164
|
> {
|
|
123
165
|
constructor(
|
|
@@ -128,15 +170,15 @@ export class ArktypeJsonCodecClass<TInferred> extends CodecImpl<
|
|
|
128
170
|
}
|
|
129
171
|
|
|
130
172
|
async encode(value: TInferred, _ctx: CodecCallContext): Promise<string> {
|
|
131
|
-
return
|
|
173
|
+
return serializeWire(value);
|
|
132
174
|
}
|
|
133
175
|
|
|
134
|
-
async decode(wire: string, _ctx: CodecCallContext): Promise<TInferred> {
|
|
135
|
-
return
|
|
176
|
+
async decode(wire: string | JsonValue, _ctx: CodecCallContext): Promise<TInferred> {
|
|
177
|
+
return decodeWireValue<TInferred>(this.schema, wire);
|
|
136
178
|
}
|
|
137
179
|
|
|
138
180
|
encodeJson(value: TInferred): JsonValue {
|
|
139
|
-
return
|
|
181
|
+
return serializeJson(value);
|
|
140
182
|
}
|
|
141
183
|
|
|
142
184
|
decodeJson(json: JsonValue): TInferred {
|
|
@@ -149,10 +191,13 @@ const arktypeJsonParamsSchema = type({
|
|
|
149
191
|
jsonIr: 'object',
|
|
150
192
|
}) satisfies StandardSchemaV1<ArktypeJsonTypeParams>;
|
|
151
193
|
|
|
194
|
+
const ARKTYPE_JSON_META = { db: { sql: { postgres: { nativeType: 'jsonb' } } } } as const;
|
|
195
|
+
|
|
152
196
|
export class ArktypeJsonDescriptor extends CodecDescriptorImpl<ArktypeJsonTypeParams> {
|
|
153
197
|
override readonly codecId = ARKTYPE_JSON_CODEC_ID;
|
|
154
198
|
override readonly traits = ['equality'] as const;
|
|
155
199
|
override readonly targetTypes = [ARKTYPE_JSON_NATIVE_TYPE] as const;
|
|
200
|
+
override readonly meta = ARKTYPE_JSON_META;
|
|
156
201
|
override readonly paramsSchema: StandardSchemaV1<ArktypeJsonTypeParams> = arktypeJsonParamsSchema;
|
|
157
202
|
override renderOutputType(params: ArktypeJsonTypeParams): string {
|
|
158
203
|
return renderArktypeJsonOutputType(params);
|
|
@@ -161,14 +206,18 @@ export class ArktypeJsonDescriptor extends CodecDescriptorImpl<ArktypeJsonTypePa
|
|
|
161
206
|
params: ArktypeJsonTypeParams,
|
|
162
207
|
): (ctx: CodecInstanceContext) => ArktypeJsonCodecClass<unknown> {
|
|
163
208
|
const schema = rehydrateSchema(params.jsonIr);
|
|
164
|
-
/* c8 ignore start — defensive parity check; not exercised by typical contracts */
|
|
165
209
|
const rehydratedExpression = (schema as { readonly expression?: unknown }).expression;
|
|
166
210
|
if (typeof rehydratedExpression === 'string' && rehydratedExpression !== params.expression) {
|
|
167
|
-
|
|
168
|
-
|
|
211
|
+
throw runtimeError(
|
|
212
|
+
'RUNTIME.TYPE_PARAMS_INVALID',
|
|
213
|
+
`arktype-json: typeParams.expression (${params.expression}) does not match the rehydrated schema's expression (${rehydratedExpression}). The contract was likely emitted against a different arktype version or hand-edited; re-run \`pnpm emit\` to regenerate.`,
|
|
214
|
+
{
|
|
215
|
+
codecId: ARKTYPE_JSON_CODEC_ID,
|
|
216
|
+
serializedExpression: params.expression,
|
|
217
|
+
rehydratedExpression,
|
|
218
|
+
},
|
|
169
219
|
);
|
|
170
220
|
}
|
|
171
|
-
/* c8 ignore stop */
|
|
172
221
|
return () => new ArktypeJsonCodecClass<unknown>(this, schema);
|
|
173
222
|
}
|
|
174
223
|
}
|
package/src/exports/runtime.ts
CHANGED
|
@@ -16,6 +16,11 @@ export const arktypeJsonRuntimeDescriptor: SqlRuntimeExtensionDescriptor<'postgr
|
|
|
16
16
|
version: arktypeJsonPackMeta.version,
|
|
17
17
|
familyId: 'sql' as const,
|
|
18
18
|
targetId: 'postgres' as const,
|
|
19
|
+
types: {
|
|
20
|
+
codecTypes: {
|
|
21
|
+
codecDescriptors: Array.from(arktypeJsonCodecRegistry.values()),
|
|
22
|
+
},
|
|
23
|
+
},
|
|
19
24
|
codecs: () => Array.from(arktypeJsonCodecRegistry.values()),
|
|
20
25
|
create() {
|
|
21
26
|
return {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"arktype-json-codec-DluUG3EZ.mjs","names":[],"sources":["../src/core/arktype-json-codec.ts"],"sourcesContent":["/**\n * Arktype-json codec (TML-2357).\n *\n * Spec § Case 3: method-level generic over `S extends Type<unknown>`. The schema's TypeScript-level inferred type `S['infer']` is only available at the column-author site (where the user passes their typed schema), not at the descriptor's factory site (where only the serialized IR is available). This drives the shape:\n *\n * 1. {@link ArktypeJsonCodecClass} extends {@link CodecImpl} and is generic over `TInferred` — the application-level JS type the schema validates to. The constructor takes both the descriptor (for `id` proxy) and the rehydrated arktype `Type` (closure-captured so encode/decode/encodeJson/decodeJson can validate through it). 2. {@link ArktypeJsonDescriptor} extends {@link CodecDescriptorImpl} over {@link\n * ArktypeJsonTypeParams}. Factory rehydrates the schema from `params.jsonIr` and returns `(ctx) => new ArktypeJsonCodecClass<unknown>(this, schema)` — `S` is erased to `unknown` because the descriptor only sees IR. The runtime path through `descriptor.factory(params)` always exists (e.g. for `validateContract` re-materialization); it just loses the typed inferred shape. 3. {@link arktypeJsonColumn} is the column-author\n * surface with the method-level generic over `S extends Type<unknown>`. It bypasses `descriptor.factory` because `S` is only available here, instead constructing the typed codec directly so `S['infer']` flows through `codecFactory`'s return into the column site's resolved output type. Eager serialization at this call site captures `expression` (for the emit-path renderer) and `jsonIr` (for runtime rehydration).\n *\n * `satisfies ColumnHelperFor<ArktypeJsonDescriptor>` (coarse) is applied — the typeParams shape is verified. `ColumnHelperForStrict` is intentionally skipped: the descriptor's factory return is `ArktypeJsonCodecClass<unknown>` while the helper produces `ArktypeJsonCodecClass<S['infer']>`, and `Codec`'s `TInput` is invariant (used contravariantly in `encode`, covariantly in `decode`/`encodeJson`/`decodeJson`). Strict\n * assignment fails by design; the explicit `expectTypeOf` tests in `test/arktype-json-codec.types.test-d.ts` cover the literal-preservation property the strict variant would otherwise enforce.\n */\n\nimport type { JsonValue } from '@prisma-next/contract/types';\nimport {\n type AnyCodecDescriptor,\n type CodecCallContext,\n CodecDescriptorImpl,\n CodecImpl,\n type CodecInstanceContext,\n type ColumnHelperFor,\n type ColumnSpec,\n column,\n} from '@prisma-next/framework-components/codec';\nimport { runtimeError } from '@prisma-next/framework-components/runtime';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { ArkErrors, ark, type Type, type } from 'arktype';\n\n/** Codec id for arktype-backed JSON columns. Library-bound, not target-bound. */\nexport const ARKTYPE_JSON_CODEC_ID = 'arktype/json@1' as const;\n\n/** Native storage type backing the codec. JSONB on Postgres; binary, indexable. */\nexport const ARKTYPE_JSON_NATIVE_TYPE = 'jsonb' as const;\n\n/**\n * Eagerly serialized typeParams for the arktype-json column. Carried in the contract IR; the runtime descriptor's factory rehydrates `jsonIr` and the emitter consumes `expression`.\n */\nexport type ArktypeJsonTypeParams = {\n /**\n * Arktype's TypeScript-source-like rendering of the schema. Read by `renderOutputType` to emit the column's TS type into `contract.d.ts`. Stable across the serialize/rehydrate cycle: the rehydrated schema's `expression` matches the source schema's.\n */\n readonly expression: string;\n /**\n * Arktype's internal IR for the schema. Lossless; the rehydration source. Schema-shape — `ark.schema(jsonIr)` reconstructs a callable `Type`-like structurally identical to the original `type(definition)` output.\n */\n readonly jsonIr: object;\n};\n\ntype ArktypeSchemaLike = ((value: unknown) => unknown) & {\n readonly expression: string;\n};\n\nfunction isArktypeSchemaLike(value: unknown): value is ArktypeSchemaLike {\n if (typeof value !== 'function') return false;\n const expression = (value as { readonly expression?: unknown }).expression;\n return typeof expression === 'string';\n}\n\nfunction validateSchema<TInferred>(schema: ArktypeSchemaLike, value: unknown): TInferred {\n const result = schema(value);\n if (result instanceof ArkErrors) {\n throw runtimeError(\n 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',\n `arktype-json schema validation failed (decode): ${result.summary}`,\n { codecId: ARKTYPE_JSON_CODEC_ID, issues: result.summary },\n );\n }\n return result as TInferred;\n}\n\nfunction serializeToJsonSafe<TInferred>(\n schema: ArktypeSchemaLike,\n value: TInferred,\n): { wire: string; json: JsonValue } {\n const wire: string | undefined = JSON.stringify(value);\n if (typeof wire !== 'string') {\n throw runtimeError(\n 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',\n `arktype-json value is not representable as JSON (codecId: ${ARKTYPE_JSON_CODEC_ID})`,\n { codecId: ARKTYPE_JSON_CODEC_ID },\n );\n }\n const json = JSON.parse(wire) as JsonValue;\n validateSchema(schema, json);\n return { wire, json };\n}\n\nfunction rehydrateSchema(jsonIr: object): ArktypeSchemaLike {\n let rehydrated: unknown;\n try {\n rehydrated = ark.schema(jsonIr);\n } catch (error) {\n throw runtimeError(\n 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',\n /* c8 ignore next — the `String(error)` fallback covers throws of non-Error values; arktype only throws Error subclasses, so this branch is defensive only. */\n `Failed to rehydrate arktype schema from contract IR: ${error instanceof Error ? error.message : String(error)}`,\n { codecId: ARKTYPE_JSON_CODEC_ID, jsonIr },\n );\n }\n /* c8 ignore start — defensive: ark.schema either throws (handled above) or returns a callable Type with `expression: string`. The structural guard is kept so a future ark internal change can't silently slip a non-callable past us. */\n if (!isArktypeSchemaLike(rehydrated)) {\n throw runtimeError(\n 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',\n `Rehydrated arktype schema does not have the expected callable + 'expression: string' shape (codecId: ${ARKTYPE_JSON_CODEC_ID})`,\n { codecId: ARKTYPE_JSON_CODEC_ID, jsonIr },\n );\n }\n /* c8 ignore stop */\n return rehydrated;\n}\n\nfunction renderArktypeJsonOutputType(params: ArktypeJsonTypeParams): string {\n const expression = params.expression.trim();\n return expression.length > 0 ? expression : 'unknown';\n}\n\nexport class ArktypeJsonCodecClass<TInferred> extends CodecImpl<\n typeof ARKTYPE_JSON_CODEC_ID,\n readonly ['equality'],\n string,\n TInferred\n> {\n constructor(\n descriptor: ArktypeJsonDescriptor,\n private readonly schema: ArktypeSchemaLike,\n ) {\n super(descriptor);\n }\n\n async encode(value: TInferred, _ctx: CodecCallContext): Promise<string> {\n return serializeToJsonSafe(this.schema, value).wire;\n }\n\n async decode(wire: string, _ctx: CodecCallContext): Promise<TInferred> {\n return validateSchema<TInferred>(this.schema, JSON.parse(wire));\n }\n\n encodeJson(value: TInferred): JsonValue {\n return serializeToJsonSafe(this.schema, value).json;\n }\n\n decodeJson(json: JsonValue): TInferred {\n return validateSchema<TInferred>(this.schema, json);\n }\n}\n\nconst arktypeJsonParamsSchema = type({\n expression: 'string',\n jsonIr: 'object',\n}) satisfies StandardSchemaV1<ArktypeJsonTypeParams>;\n\nexport class ArktypeJsonDescriptor extends CodecDescriptorImpl<ArktypeJsonTypeParams> {\n override readonly codecId = ARKTYPE_JSON_CODEC_ID;\n override readonly traits = ['equality'] as const;\n override readonly targetTypes = [ARKTYPE_JSON_NATIVE_TYPE] as const;\n override readonly paramsSchema: StandardSchemaV1<ArktypeJsonTypeParams> = arktypeJsonParamsSchema;\n override renderOutputType(params: ArktypeJsonTypeParams): string {\n return renderArktypeJsonOutputType(params);\n }\n override factory(\n params: ArktypeJsonTypeParams,\n ): (ctx: CodecInstanceContext) => ArktypeJsonCodecClass<unknown> {\n const schema = rehydrateSchema(params.jsonIr);\n /* c8 ignore start — defensive parity check; not exercised by typical contracts */\n const rehydratedExpression = (schema as { readonly expression?: unknown }).expression;\n if (typeof rehydratedExpression === 'string' && rehydratedExpression !== params.expression) {\n console.warn(\n `[arktype-json] typeParams.expression (${params.expression}) does not match rehydrated schema expression (${rehydratedExpression}); contract.json may be stale relative to the runtime schema.`,\n );\n }\n /* c8 ignore stop */\n return () => new ArktypeJsonCodecClass<unknown>(this, schema);\n }\n}\n\nexport const arktypeJsonDescriptor = new ArktypeJsonDescriptor();\n\n/**\n * Per-codec column helper for `arktype/json@1`. Method-level generic over `S extends Type<unknown>` so the column site preserves the schema's inferred TS type in the resolved codec (`ArktypeJsonCodecClass<S['infer']>`). Bypasses `descriptor.factory` because `S` is only available at the column-author site; constructs the typed codec directly with the closure-captured schema.\n *\n * Eager serialization at this call site captures `expression` (for the emit-path renderer) and `jsonIr` (for runtime rehydration via the descriptor's factory).\n *\n * @throws {Error} if the schema doesn't expose `expression` and `json` fields (i.e. is not an arktype `Type`). Validates the schema shape at the call site so configuration errors surface during contract authoring, not at runtime.\n */\nexport function arktypeJsonColumn<S extends Type<unknown>>(\n schema: S,\n): ColumnSpec<ArktypeJsonCodecClass<S['infer']>, ArktypeJsonTypeParams> {\n if (!isArktypeSchemaLike(schema)) {\n throw new Error(\n typeof schema !== 'function'\n ? 'arktypeJsonColumn(schema) expects a callable arktype Type.'\n : 'arktypeJsonColumn(schema) expects an arktype Type (missing `expression: string`).',\n );\n }\n const jsonIr: unknown = (schema as { readonly json?: unknown }).json;\n if (jsonIr === null || typeof jsonIr !== 'object') {\n throw new Error('arktypeJsonColumn(schema) expects an arktype Type (missing `json` IR).');\n }\n const params: ArktypeJsonTypeParams = { expression: schema.expression, jsonIr };\n return column(\n (_ctx: CodecInstanceContext) =>\n new ArktypeJsonCodecClass<S['infer']>(arktypeJsonDescriptor, schema),\n arktypeJsonDescriptor.codecId,\n params,\n ARKTYPE_JSON_NATIVE_TYPE,\n );\n}\n\narktypeJsonColumn satisfies ColumnHelperFor<ArktypeJsonDescriptor>;\n// Note: `ColumnHelperForStrict` is intentionally not applied — `Codec` is invariant in `TInput` (encode contravariant, decode covariant), so `ArktypeJsonCodecClass<S['infer']>` is not assignable to `ArktypeJsonCodecClass<unknown>` (the descriptor.factory return). `expectTypeOf` tests cover the literal-preservation property strict satisfies would otherwise enforce.\n\n/**\n * Codec instance returned by `arktypeJsonColumn(schema).codecFactory(ctx)` and by `arktypeJsonDescriptor.factory(typeParams)(ctx)`. The `TInferred` slot carries the arktype schema's inferred output type at the column-author site; descriptor-side factories erase to `unknown`.\n */\nexport type ArktypeJsonCodec<TInferred> = ArktypeJsonCodecClass<TInferred>;\n\nexport const codecDescriptors: readonly AnyCodecDescriptor[] = [arktypeJsonDescriptor];\n"],"mappings":";;;;;AA6BA,MAAa,wBAAwB;;AAGrC,MAAa,2BAA2B;AAoBxC,SAAS,oBAAoB,OAA4C;CACvE,IAAI,OAAO,UAAU,YAAY,OAAO;CAExC,OAAO,OADa,MAA4C,eACnC;;AAG/B,SAAS,eAA0B,QAA2B,OAA2B;CACvF,MAAM,SAAS,OAAO,MAAM;CAC5B,IAAI,kBAAkB,WACpB,MAAM,aACJ,yCACA,mDAAmD,OAAO,WAC1D;EAAE,SAAS;EAAuB,QAAQ,OAAO;EAAS,CAC3D;CAEH,OAAO;;AAGT,SAAS,oBACP,QACA,OACmC;CACnC,MAAM,OAA2B,KAAK,UAAU,MAAM;CACtD,IAAI,OAAO,SAAS,UAClB,MAAM,aACJ,yCACA,6DAA6D,sBAAsB,IACnF,EAAE,SAAS,uBAAuB,CACnC;CAEH,MAAM,OAAO,KAAK,MAAM,KAAK;CAC7B,eAAe,QAAQ,KAAK;CAC5B,OAAO;EAAE;EAAM;EAAM;;AAGvB,SAAS,gBAAgB,QAAmC;CAC1D,IAAI;CACJ,IAAI;EACF,aAAa,IAAI,OAAO,OAAO;UACxB,OAAO;EACd,MAAM;GACJ;;GAEA,wDAAwD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC9G;IAAE,SAAS;IAAuB;IAAQ;GAC3C;;;CAGH,IAAI,CAAC,oBAAoB,WAAW,EAClC,MAAM,aACJ,yCACA,wGAAwG,sBAAsB,IAC9H;EAAE,SAAS;EAAuB;EAAQ,CAC3C;;CAGH,OAAO;;AAGT,SAAS,4BAA4B,QAAuC;CAC1E,MAAM,aAAa,OAAO,WAAW,MAAM;CAC3C,OAAO,WAAW,SAAS,IAAI,aAAa;;AAG9C,IAAa,wBAAb,cAAsD,UAKpD;CAGmB;CAFnB,YACE,YACA,QACA;EACA,MAAM,WAAW;EAFA,KAAA,SAAA;;CAKnB,MAAM,OAAO,OAAkB,MAAyC;EACtE,OAAO,oBAAoB,KAAK,QAAQ,MAAM,CAAC;;CAGjD,MAAM,OAAO,MAAc,MAA4C;EACrE,OAAO,eAA0B,KAAK,QAAQ,KAAK,MAAM,KAAK,CAAC;;CAGjE,WAAW,OAA6B;EACtC,OAAO,oBAAoB,KAAK,QAAQ,MAAM,CAAC;;CAGjD,WAAW,MAA4B;EACrC,OAAO,eAA0B,KAAK,QAAQ,KAAK;;;AAIvD,MAAM,0BAA0B,KAAK;CACnC,YAAY;CACZ,QAAQ;CACT,CAAC;AAEF,IAAa,wBAAb,cAA2C,oBAA2C;CACpF,UAA4B;CAC5B,SAA2B,CAAC,WAAW;CACvC,cAAgC,CAAC,yBAAyB;CAC1D,eAA0E;CAC1E,iBAA0B,QAAuC;EAC/D,OAAO,4BAA4B,OAAO;;CAE5C,QACE,QAC+D;EAC/D,MAAM,SAAS,gBAAgB,OAAO,OAAO;;EAE7C,MAAM,uBAAwB,OAA6C;EAC3E,IAAI,OAAO,yBAAyB,YAAY,yBAAyB,OAAO,YAC9E,QAAQ,KACN,yCAAyC,OAAO,WAAW,iDAAiD,qBAAqB,+DAClI;;EAGH,aAAa,IAAI,sBAA+B,MAAM,OAAO;;;AAIjE,MAAa,wBAAwB,IAAI,uBAAuB;;;;;;;;AAShE,SAAgB,kBACd,QACsE;CACtE,IAAI,CAAC,oBAAoB,OAAO,EAC9B,MAAM,IAAI,MACR,OAAO,WAAW,aACd,+DACA,oFACL;CAEH,MAAM,SAAmB,OAAuC;CAChE,IAAI,WAAW,QAAQ,OAAO,WAAW,UACvC,MAAM,IAAI,MAAM,yEAAyE;CAE3F,MAAM,SAAgC;EAAE,YAAY,OAAO;EAAY;EAAQ;CAC/E,OAAO,QACJ,SACC,IAAI,sBAAkC,uBAAuB,OAAO,EACtE,sBAAsB,SACtB,QACA,yBACD;;AAWH,MAAa,mBAAkD,CAAC,sBAAsB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"arktype-json-codec-VX9T28RG.d.mts","names":[],"sources":["../src/core/arktype-json-codec.ts"],"mappings":";;;;;;AAqCA;AAAA,cARa,qBAAA;;cAGA,wBAAA;;AAcX;;KATU,qBAAA;EAWe;;AAoE3B;EApE2B,SAPhB,UAAA;EA2EuB;;;EAAA,SAvEvB,MAAA;AAAA;AAAA,KAGN,iBAAA,KAAsB,KAAA;EAAA,SAChB,UAAA;AAAA;AAAA,cAmEE,qBAAA,oBAAyC,SAAA,QAC7C,qBAAA,iCAGP,SAAA;EAAA,iBAImB,MAAA;cADjB,UAAA,EAAY,qBAAA,EACK,MAAA,EAAQ,iBAAA;EAKrB,MAAA,CAAO,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,gBAAA,GAAmB,OAAA;EAIlD,MAAA,CAAO,IAAA,UAAc,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,SAAA;EAI5D,UAAA,CAAW,KAAA,EAAO,SAAA,GAAY,SAAA;EAI9B,UAAA,CAAW,IAAA,EAAM,SAAA,GAAY,SAAA;AAAA;AAAA,cAUlB,qBAAA,SAA8B,mBAAA,CAAoB,qBAAA;EAAA,SAC3C,OAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,YAAA,EAAc,gBAAA,CAAiB,qBAAA;EACxC,gBAAA,CAAiB,MAAA,EAAQ,qBAAA;EAGzB,OAAA,CACP,MAAA,EAAQ,qBAAA,IACN,GAAA,EAAK,oBAAA,KAAyB,qBAAA;AAAA;;;;;;;;iBAuBpB,iBAAA,WAA4B,IAAA,UAAA,CAC1C,MAAA,EAAQ,CAAA,GACP,UAAA,CAAW,qBAAA,CAAsB,CAAA,YAAa,qBAAA;;;;KA4BrC,gBAAA,cAA8B,qBAAA,CAAsB,SAAA"}
|