@prisma-next/target-postgres 0.5.0-dev.8 → 0.5.0-dev.81

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.
Files changed (180) hide show
  1. package/dist/{codec-ids-CojIXVf9.mjs → codec-ids-C5qzBqus.mjs} +4 -4
  2. package/dist/{codec-ids-CojIXVf9.mjs.map → codec-ids-C5qzBqus.mjs.map} +1 -1
  3. package/dist/codec-ids-CplrEfmx.d.mts +29 -0
  4. package/dist/codec-ids-CplrEfmx.d.mts.map +1 -0
  5. package/dist/codec-ids.d.mts +2 -28
  6. package/dist/codec-ids.mjs +2 -3
  7. package/dist/codec-types-lrsb3N07.d.mts +79 -0
  8. package/dist/codec-types-lrsb3N07.d.mts.map +1 -0
  9. package/dist/codec-types.d.mts +2 -42
  10. package/dist/codec-types.mjs +1 -4
  11. package/dist/codecs-Cue97Xqf.d.mts +558 -0
  12. package/dist/codecs-Cue97Xqf.d.mts.map +1 -0
  13. package/dist/codecs.d.mts +13 -2
  14. package/dist/codecs.d.mts.map +1 -0
  15. package/dist/codecs.mjs +738 -3
  16. package/dist/codecs.mjs.map +1 -0
  17. package/dist/control.d.mts +1 -1
  18. package/dist/control.d.mts.map +1 -1
  19. package/dist/control.mjs +131 -94
  20. package/dist/control.mjs.map +1 -1
  21. package/dist/{data-transform-VfEGzXWt.mjs → data-transform-DKWXdHuZ.mjs} +25 -7
  22. package/dist/data-transform-DKWXdHuZ.mjs.map +1 -0
  23. package/dist/data-transform-bIeAcZIJ.d.mts +38 -0
  24. package/dist/data-transform-bIeAcZIJ.d.mts.map +1 -0
  25. package/dist/data-transform.d.mts +1 -1
  26. package/dist/data-transform.mjs +2 -3
  27. package/dist/{default-normalizer-DNOpRoOF.mjs → default-normalizer-C8XyZj85.mjs} +2 -2
  28. package/dist/{default-normalizer-DNOpRoOF.mjs.map → default-normalizer-C8XyZj85.mjs.map} +1 -1
  29. package/dist/default-normalizer.d.mts +0 -1
  30. package/dist/default-normalizer.d.mts.map +1 -1
  31. package/dist/default-normalizer.mjs +2 -3
  32. package/dist/descriptor-meta-Dde_BS3K.mjs +99 -0
  33. package/dist/descriptor-meta-Dde_BS3K.mjs.map +1 -0
  34. package/dist/{errors-AFvEPZ1R.mjs → errors-Chm2bKcS.mjs} +2 -3
  35. package/dist/{errors-AFvEPZ1R.mjs.map → errors-Chm2bKcS.mjs.map} +1 -1
  36. package/dist/errors.d.mts +0 -1
  37. package/dist/errors.d.mts.map +1 -1
  38. package/dist/errors.mjs +2 -3
  39. package/dist/{issue-planner-CFjB0_oO.mjs → issue-planner-B10B70JF.mjs} +9 -13
  40. package/dist/issue-planner-B10B70JF.mjs.map +1 -0
  41. package/dist/issue-planner.d.mts +2 -4
  42. package/dist/issue-planner.d.mts.map +1 -1
  43. package/dist/issue-planner.mjs +2 -3
  44. package/dist/migration.d.mts +3 -3
  45. package/dist/migration.d.mts.map +1 -1
  46. package/dist/migration.mjs +4 -5
  47. package/dist/migration.mjs.map +1 -1
  48. package/dist/{native-type-normalizer-CInai_oY.mjs → native-type-normalizer-Cry4QoLf.mjs} +2 -2
  49. package/dist/native-type-normalizer-Cry4QoLf.mjs.map +1 -0
  50. package/dist/native-type-normalizer.d.mts.map +1 -1
  51. package/dist/native-type-normalizer.mjs +2 -3
  52. package/dist/{op-factory-call-C3bWXKSP.d.mts → op-factory-call-CW8pzxmB.d.mts} +3 -4
  53. package/dist/op-factory-call-CW8pzxmB.d.mts.map +1 -0
  54. package/dist/{op-factory-call-BKlruaiC.mjs → op-factory-call-Cq8s4Fz1.mjs} +3 -4
  55. package/dist/{op-factory-call-BKlruaiC.mjs.map → op-factory-call-Cq8s4Fz1.mjs.map} +1 -1
  56. package/dist/op-factory-call.d.mts +1 -2
  57. package/dist/op-factory-call.mjs +2 -3
  58. package/dist/pack.d.mts +28 -9
  59. package/dist/pack.d.mts.map +1 -1
  60. package/dist/pack.mjs +2 -3
  61. package/dist/{planner-CLUvVhUN.mjs → planner-BvKUuqG-.mjs} +22 -16
  62. package/dist/planner-BvKUuqG-.mjs.map +1 -0
  63. package/dist/{planner-ddl-builders-Dxvw1LHw.mjs → planner-ddl-builders-CLB7Umhh.mjs} +4 -5
  64. package/dist/planner-ddl-builders-CLB7Umhh.mjs.map +1 -0
  65. package/dist/planner-ddl-builders.d.mts +1 -1
  66. package/dist/planner-ddl-builders.d.mts.map +1 -1
  67. package/dist/planner-ddl-builders.mjs +2 -3
  68. package/dist/{planner-identity-values-Dju-o5GF.mjs → planner-identity-values-DTx0gePL.mjs} +2 -3
  69. package/dist/{planner-identity-values-Dju-o5GF.mjs.map → planner-identity-values-DTx0gePL.mjs.map} +1 -1
  70. package/dist/planner-identity-values.d.mts +0 -1
  71. package/dist/planner-identity-values.d.mts.map +1 -1
  72. package/dist/planner-identity-values.mjs +2 -3
  73. package/dist/{planner-produced-postgres-migration-CRRTno6Z.d.mts → planner-produced-postgres-migration-CjxWIVgh.d.mts} +11 -7
  74. package/dist/planner-produced-postgres-migration-CjxWIVgh.d.mts.map +1 -0
  75. package/dist/{planner-produced-postgres-migration-DSSPq8QS.mjs → planner-produced-postgres-migration-DphktB2N.mjs} +16 -8
  76. package/dist/planner-produced-postgres-migration-DphktB2N.mjs.map +1 -0
  77. package/dist/planner-produced-postgres-migration.d.mts +1 -4
  78. package/dist/planner-produced-postgres-migration.mjs +2 -3
  79. package/dist/{planner-schema-lookup-B7lkypwn.mjs → planner-schema-lookup-B1ags8ys.mjs} +2 -2
  80. package/dist/{planner-schema-lookup-B7lkypwn.mjs.map → planner-schema-lookup-B1ags8ys.mjs.map} +1 -1
  81. package/dist/planner-schema-lookup.d.mts +0 -1
  82. package/dist/planner-schema-lookup.d.mts.map +1 -1
  83. package/dist/planner-schema-lookup.mjs +2 -3
  84. package/dist/{planner-sql-checks-7jkgm9TX.mjs → planner-sql-checks-DwZvGlV4.mjs} +3 -5
  85. package/dist/planner-sql-checks-DwZvGlV4.mjs.map +1 -0
  86. package/dist/planner-sql-checks.d.mts.map +1 -1
  87. package/dist/planner-sql-checks.mjs +2 -3
  88. package/dist/{planner-target-details-DH-azLu-.d.mts → planner-target-details-bVVcanWh.d.mts} +1 -1
  89. package/dist/planner-target-details-bVVcanWh.d.mts.map +1 -0
  90. package/dist/planner-target-details.d.mts +1 -1
  91. package/dist/planner-target-details.mjs +1 -1
  92. package/dist/planner.d.mts +21 -12
  93. package/dist/planner.d.mts.map +1 -1
  94. package/dist/planner.mjs +2 -4
  95. package/dist/{postgres-migration-qtmtbONe.mjs → postgres-migration-Bkv140RW.mjs} +4 -5
  96. package/dist/postgres-migration-Bkv140RW.mjs.map +1 -0
  97. package/dist/{postgres-migration-BjA3Zmts.d.mts → postgres-migration-UkcHfZAA.d.mts} +6 -6
  98. package/dist/postgres-migration-UkcHfZAA.d.mts.map +1 -0
  99. package/dist/render-ops--1nnfNus.mjs +23 -0
  100. package/dist/render-ops--1nnfNus.mjs.map +1 -0
  101. package/dist/render-ops.d.mts +3 -4
  102. package/dist/render-ops.d.mts.map +1 -1
  103. package/dist/render-ops.mjs +2 -3
  104. package/dist/{render-typescript-1rF_SB4g.mjs → render-typescript-D3doH-vX.mjs} +2 -14
  105. package/dist/render-typescript-D3doH-vX.mjs.map +1 -0
  106. package/dist/render-typescript.d.mts +3 -6
  107. package/dist/render-typescript.d.mts.map +1 -1
  108. package/dist/render-typescript.mjs +2 -3
  109. package/dist/runtime.d.mts +5 -9
  110. package/dist/runtime.d.mts.map +1 -1
  111. package/dist/runtime.mjs +7 -14
  112. package/dist/runtime.mjs.map +1 -1
  113. package/dist/{shared-Bxkt8pNO.d.mts → shared-MpwjwAjM.d.mts} +2 -2
  114. package/dist/shared-MpwjwAjM.d.mts.map +1 -0
  115. package/dist/{sql-utils-r-Lw535w.mjs → sql-utils-CggjWNij.mjs} +4 -2
  116. package/dist/sql-utils-CggjWNij.mjs.map +1 -0
  117. package/dist/sql-utils.d.mts.map +1 -1
  118. package/dist/sql-utils.mjs +2 -3
  119. package/dist/{statement-builders-BPnmt6wx.mjs → statement-builders-BT889jV0.mjs} +28 -13
  120. package/dist/statement-builders-BT889jV0.mjs.map +1 -0
  121. package/dist/statement-builders.d.mts +31 -3
  122. package/dist/statement-builders.d.mts.map +1 -1
  123. package/dist/statement-builders.mjs +2 -3
  124. package/dist/{tables-BmdW_FWO.mjs → tables-Ej122-iI.mjs} +4 -11
  125. package/dist/tables-Ej122-iI.mjs.map +1 -0
  126. package/dist/{types-ClK03Ojd.d.mts → types-CTqpysRY.d.mts} +1 -1
  127. package/dist/types-CTqpysRY.d.mts.map +1 -0
  128. package/dist/types.d.mts +1 -1
  129. package/dist/types.mjs +1 -1
  130. package/package.json +21 -19
  131. package/src/core/authoring.ts +5 -11
  132. package/src/core/codec-helpers.ts +135 -0
  133. package/src/core/codec-ids.ts +1 -0
  134. package/src/core/codec-type-map.ts +81 -0
  135. package/src/core/codecs.ts +941 -547
  136. package/src/core/descriptor-meta.ts +1 -1
  137. package/src/core/migrations/operations/data-transform.ts +86 -21
  138. package/src/core/migrations/planner-produced-postgres-migration.ts +17 -5
  139. package/src/core/migrations/planner.ts +62 -20
  140. package/src/core/migrations/postgres-migration.ts +3 -6
  141. package/src/core/migrations/render-ops.ts +26 -3
  142. package/src/core/migrations/render-typescript.ts +5 -9
  143. package/src/core/migrations/runner.ts +172 -151
  144. package/src/core/migrations/statement-builders.ts +49 -10
  145. package/src/core/registry.ts +11 -0
  146. package/src/exports/codec-types.ts +4 -13
  147. package/src/exports/codecs.ts +49 -2
  148. package/src/exports/runtime.ts +6 -11
  149. package/src/exports/statement-builders.ts +2 -1
  150. package/dist/codec-ids.d.mts.map +0 -1
  151. package/dist/codec-types.d.mts.map +0 -1
  152. package/dist/codecs-BQEm9_oo.d.mts +0 -319
  153. package/dist/codecs-BQEm9_oo.d.mts.map +0 -1
  154. package/dist/codecs-BoahtY_Q.mjs +0 -385
  155. package/dist/codecs-BoahtY_Q.mjs.map +0 -1
  156. package/dist/data-transform-CxFRBIUp.d.mts +0 -32
  157. package/dist/data-transform-CxFRBIUp.d.mts.map +0 -1
  158. package/dist/data-transform-VfEGzXWt.mjs.map +0 -1
  159. package/dist/descriptor-meta-BVoVtyp-.mjs +0 -120
  160. package/dist/descriptor-meta-BVoVtyp-.mjs.map +0 -1
  161. package/dist/issue-planner-CFjB0_oO.mjs.map +0 -1
  162. package/dist/native-type-normalizer-CInai_oY.mjs.map +0 -1
  163. package/dist/op-factory-call-C3bWXKSP.d.mts.map +0 -1
  164. package/dist/planner-CLUvVhUN.mjs.map +0 -1
  165. package/dist/planner-ddl-builders-Dxvw1LHw.mjs.map +0 -1
  166. package/dist/planner-produced-postgres-migration-CRRTno6Z.d.mts.map +0 -1
  167. package/dist/planner-produced-postgres-migration-DSSPq8QS.mjs.map +0 -1
  168. package/dist/planner-sql-checks-7jkgm9TX.mjs.map +0 -1
  169. package/dist/planner-target-details-DH-azLu-.d.mts.map +0 -1
  170. package/dist/postgres-migration-BjA3Zmts.d.mts.map +0 -1
  171. package/dist/postgres-migration-qtmtbONe.mjs.map +0 -1
  172. package/dist/render-ops-D6_DHdOK.mjs +0 -8
  173. package/dist/render-ops-D6_DHdOK.mjs.map +0 -1
  174. package/dist/render-typescript-1rF_SB4g.mjs.map +0 -1
  175. package/dist/shared-Bxkt8pNO.d.mts.map +0 -1
  176. package/dist/sql-utils-r-Lw535w.mjs.map +0 -1
  177. package/dist/statement-builders-BPnmt6wx.mjs.map +0 -1
  178. package/dist/tables-BmdW_FWO.mjs.map +0 -1
  179. package/dist/types-ClK03Ojd.d.mts.map +0 -1
  180. package/src/core/json-schema-type-expression.ts +0 -131
@@ -1,24 +1,63 @@
1
1
  /**
2
- * Unified codec definitions for Postgres adapter.
2
+ * Native Postgres target codecs (TML-2357). Mirrors the SQL base codec form in `packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs.ts`.
3
3
  *
4
- * This file contains a single source of truth for all codec information:
5
- * - Scalar names
6
- * - Type IDs
7
- * - Codec implementations (runtime)
8
- * - Type information (compile-time)
4
+ * Each codec ships as three artifacts:
9
5
  *
10
- * This structure is used both at runtime (to populate the registry) and
11
- * at compile time (to derive CodecTypes).
6
+ * 1. A `PgXCodec` class extending {@link CodecImpl} that wraps the module-level encode/decode/encodeJson/decodeJson constants exported from `codec-helpers.ts` (the single source of truth for non-trivial runtime conversions; trivial identity passthroughs are inlined). 2. A `PgXDescriptor` class extending {@link CodecDescriptorImpl} declaring the codec id, traits, target types, params schema, meta, and (where applicable)
7
+ * the emit-path `renderOutputType`. 3. A per-codec column helper (`pgXColumn`) that calls `descriptor.factory(...)` directly and packages the result into a {@link ColumnSpec} via the framework {@link column} packager. The helper is tied to its descriptor with `satisfies ColumnHelperFor` (and `ColumnHelperForStrict` where the resolved codec type is well-defined).
8
+ *
9
+ * After TML-2357 this is the canonical source of Postgres codec metadata and runtime behaviour — the legacy `mkCodec` / `defineCodec` carriers (and the parallel `byScalar`/`codecDescriptorDefinitions`/ `codecDescriptorList` collection exports) retired with the deletion sweep.
10
+ *
11
+ * Audit (parameterized codecs): every parameterized codec in this file is **parameter-stateless** — the params (`length`, `precision`, `precision`+`scale`, `values`) only inform the emit-path `renderOutputType` renderer or stay as JSON metadata. None of the runtime encode/decode/encodeJson/decodeJson conversions thread params into their behavior, so each `factory(_params)` returns a fresh codec constructed solely from
12
+ * `this` (the descriptor).
12
13
  */
13
14
 
14
15
  import type { JsonValue } from '@prisma-next/contract/types';
15
- import type { Codec, CodecMeta, CodecTrait } from '@prisma-next/sql-relational-core/ast';
16
- import { codec, defineCodecs, sqlCodecDefinitions } from '@prisma-next/sql-relational-core/ast';
17
- import { ifDefined } from '@prisma-next/utils/defined';
16
+ import {
17
+ type AnyCodecDescriptor,
18
+ type CodecCallContext,
19
+ CodecDescriptorImpl,
20
+ CodecImpl,
21
+ type CodecInstanceContext,
22
+ type ColumnHelperFor,
23
+ type ColumnHelperForStrict,
24
+ column,
25
+ voidParamsSchema,
26
+ } from '@prisma-next/framework-components/codec';
27
+ import {
28
+ SqlCharCodec,
29
+ SqlFloatCodec,
30
+ SqlIntCodec,
31
+ SqlVarcharCodec,
32
+ sqlCharDescriptor,
33
+ sqlFloatDescriptor,
34
+ sqlIntDescriptor,
35
+ sqlTextDescriptor,
36
+ sqlTimestampDescriptor,
37
+ sqlVarcharDescriptor,
38
+ } from '@prisma-next/sql-relational-core/ast';
39
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
18
40
  import { type as arktype } from 'arktype';
41
+ import {
42
+ pgEnumRenderOutputType,
43
+ pgIntervalDecode,
44
+ pgJsonbDecode,
45
+ pgJsonbEncode,
46
+ pgJsonDecode,
47
+ pgJsonEncode,
48
+ pgNumericDecode,
49
+ pgNumericRenderOutputType,
50
+ pgTimestampDecodeJson,
51
+ pgTimestampEncodeJson,
52
+ pgTimestamptzDecodeJson,
53
+ pgTimestamptzEncodeJson,
54
+ renderLength,
55
+ renderPrecision,
56
+ } from './codec-helpers';
19
57
  import {
20
58
  PG_BIT_CODEC_ID,
21
59
  PG_BOOL_CODEC_ID,
60
+ PG_BYTEA_CODEC_ID,
22
61
  PG_CHAR_CODEC_ID,
23
62
  PG_ENUM_CODEC_ID,
24
63
  PG_FLOAT_CODEC_ID,
@@ -40,606 +79,961 @@ import {
40
79
  PG_VARBIT_CODEC_ID,
41
80
  PG_VARCHAR_CODEC_ID,
42
81
  } from './codec-ids';
43
- import { renderTypeScriptTypeFromJsonSchema } from './json-schema-type-expression';
82
+
83
+ type LengthParams = { readonly length?: number };
84
+ type PrecisionParams = { readonly precision?: number };
85
+ type NumericParams = { readonly precision: number; readonly scale?: number };
86
+ type EnumParams = { readonly values?: readonly string[] };
44
87
 
45
88
  const lengthParamsSchema = arktype({
46
- length: 'number.integer > 0',
47
- });
89
+ 'length?': 'number.integer > 0',
90
+ }) satisfies StandardSchemaV1<LengthParams>;
48
91
 
49
92
  const numericParamsSchema = arktype({
50
93
  precision: 'number.integer > 0 & number.integer <= 1000',
51
94
  'scale?': 'number.integer >= 0',
52
- });
95
+ }) satisfies StandardSchemaV1<NumericParams>;
53
96
 
54
97
  const precisionParamsSchema = arktype({
55
98
  'precision?': 'number.integer >= 0 & number.integer <= 6',
56
- });
99
+ }) satisfies StandardSchemaV1<PrecisionParams>;
100
+
101
+ const PG_TEXT_META = { db: { sql: { postgres: { nativeType: 'text' } } } } as const;
102
+ const PG_INT4_META = { db: { sql: { postgres: { nativeType: 'integer' } } } } as const;
103
+ const PG_INT2_META = { db: { sql: { postgres: { nativeType: 'smallint' } } } } as const;
104
+ const PG_INT8_META = { db: { sql: { postgres: { nativeType: 'bigint' } } } } as const;
105
+ const PG_FLOAT4_META = { db: { sql: { postgres: { nativeType: 'real' } } } } as const;
106
+ const PG_FLOAT8_META = { db: { sql: { postgres: { nativeType: 'double precision' } } } } as const;
107
+ const PG_NUMERIC_META = { db: { sql: { postgres: { nativeType: 'numeric' } } } } as const;
108
+ const PG_TIMESTAMP_META = {
109
+ db: { sql: { postgres: { nativeType: 'timestamp without time zone' } } },
110
+ } as const;
111
+ const PG_TIMESTAMPTZ_META = {
112
+ db: { sql: { postgres: { nativeType: 'timestamp with time zone' } } },
113
+ } as const;
114
+ const PG_TIME_META = { db: { sql: { postgres: { nativeType: 'time' } } } } as const;
115
+ const PG_TIMETZ_META = { db: { sql: { postgres: { nativeType: 'timetz' } } } } as const;
116
+ const PG_BOOL_META = { db: { sql: { postgres: { nativeType: 'boolean' } } } } as const;
117
+ const PG_BIT_META = { db: { sql: { postgres: { nativeType: 'bit' } } } } as const;
118
+ const PG_VARBIT_META = { db: { sql: { postgres: { nativeType: 'bit varying' } } } } as const;
119
+ const PG_BYTEA_META = { db: { sql: { postgres: { nativeType: 'bytea' } } } } as const;
120
+ const PG_INTERVAL_META = { db: { sql: { postgres: { nativeType: 'interval' } } } } as const;
121
+ const PG_JSON_META = { db: { sql: { postgres: { nativeType: 'json' } } } } as const;
122
+ const PG_JSONB_META = { db: { sql: { postgres: { nativeType: 'jsonb' } } } } as const;
57
123
 
58
- function renderLength(typeName: string, typeParams: Record<string, unknown>): string | undefined {
59
- const length = typeParams['length'];
60
- if (length === undefined) {
61
- return undefined;
124
+ export class PgTextCodec extends CodecImpl<
125
+ typeof PG_TEXT_CODEC_ID,
126
+ readonly ['equality', 'order', 'textual'],
127
+ string,
128
+ string
129
+ > {
130
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
131
+ return value;
132
+ }
133
+ async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
134
+ return wire;
135
+ }
136
+ encodeJson(value: string): JsonValue {
137
+ return value;
62
138
  }
63
- if (typeof length !== 'number' || !Number.isFinite(length) || !Number.isInteger(length)) {
64
- throw new Error(
65
- `renderOutputType: expected integer "length" in typeParams for ${typeName}, got ${String(length)}`,
66
- );
139
+ decodeJson(json: JsonValue): string {
140
+ return json as string;
67
141
  }
68
- return `${typeName}<${length}>`;
69
142
  }
70
143
 
71
- function renderPrecision(typeName: string, typeParams: Record<string, unknown>): string {
72
- const precision = typeParams['precision'];
73
- if (precision === undefined) {
74
- return typeName;
144
+ export class PgTextDescriptor extends CodecDescriptorImpl<void> {
145
+ override readonly codecId = PG_TEXT_CODEC_ID;
146
+ override readonly traits = ['equality', 'order', 'textual'] as const;
147
+ override readonly targetTypes = ['text'] as const;
148
+ override readonly meta = PG_TEXT_META;
149
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
150
+ override factory(): (ctx: CodecInstanceContext) => PgTextCodec {
151
+ return () => new PgTextCodec(this);
75
152
  }
76
- if (
77
- typeof precision !== 'number' ||
78
- !Number.isFinite(precision) ||
79
- !Number.isInteger(precision)
80
- ) {
81
- throw new Error(
82
- `renderOutputType: expected integer "precision" in typeParams for ${typeName}, got ${String(precision)}`,
83
- );
153
+ }
154
+
155
+ export const pgTextDescriptor = new PgTextDescriptor();
156
+
157
+ export const pgTextColumn = () =>
158
+ column(pgTextDescriptor.factory(), pgTextDescriptor.codecId, undefined, 'text');
159
+
160
+ pgTextColumn satisfies ColumnHelperFor<PgTextDescriptor>;
161
+ pgTextColumn satisfies ColumnHelperForStrict<PgTextDescriptor>;
162
+
163
+ export class PgInt4Codec extends CodecImpl<
164
+ typeof PG_INT4_CODEC_ID,
165
+ readonly ['equality', 'order', 'numeric'],
166
+ number,
167
+ number
168
+ > {
169
+ async encode(value: number, _ctx: CodecCallContext): Promise<number> {
170
+ return value;
171
+ }
172
+ async decode(wire: number, _ctx: CodecCallContext): Promise<number> {
173
+ return wire;
174
+ }
175
+ encodeJson(value: number): JsonValue {
176
+ return value;
177
+ }
178
+ decodeJson(json: JsonValue): number {
179
+ return json as number;
84
180
  }
85
- return `${typeName}<${precision}>`;
86
181
  }
87
182
 
88
- function renderJsonOutputType(typeParams: Record<string, unknown>): string {
89
- const typeName = typeParams['type'];
90
- if (typeof typeName === 'string' && typeName.trim().length > 0) {
91
- return typeName.trim();
183
+ export class PgInt4Descriptor extends CodecDescriptorImpl<void> {
184
+ override readonly codecId = PG_INT4_CODEC_ID;
185
+ override readonly traits = ['equality', 'order', 'numeric'] as const;
186
+ override readonly targetTypes = ['int4'] as const;
187
+ override readonly meta = PG_INT4_META;
188
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
189
+ override factory(): (ctx: CodecInstanceContext) => PgInt4Codec {
190
+ return () => new PgInt4Codec(this);
92
191
  }
93
- const schema = typeParams['schemaJson'];
94
- if (schema && typeof schema === 'object') {
95
- return renderTypeScriptTypeFromJsonSchema(schema);
192
+ }
193
+
194
+ export const pgInt4Descriptor = new PgInt4Descriptor();
195
+
196
+ export const pgInt4Column = () =>
197
+ column(pgInt4Descriptor.factory(), pgInt4Descriptor.codecId, undefined, 'int4');
198
+
199
+ pgInt4Column satisfies ColumnHelperFor<PgInt4Descriptor>;
200
+ pgInt4Column satisfies ColumnHelperForStrict<PgInt4Descriptor>;
201
+
202
+ export class PgInt2Codec extends CodecImpl<
203
+ typeof PG_INT2_CODEC_ID,
204
+ readonly ['equality', 'order', 'numeric'],
205
+ number,
206
+ number
207
+ > {
208
+ async encode(value: number, _ctx: CodecCallContext): Promise<number> {
209
+ return value;
210
+ }
211
+ async decode(wire: number, _ctx: CodecCallContext): Promise<number> {
212
+ return wire;
213
+ }
214
+ encodeJson(value: number): JsonValue {
215
+ return value;
216
+ }
217
+ decodeJson(json: JsonValue): number {
218
+ return json as number;
96
219
  }
97
- throw new Error(
98
- `renderOutputType: JSON codec typeParams must contain "type" (string) or "schemaJson" (object), got keys: ${Object.keys(typeParams).join(', ')}`,
99
- );
100
220
  }
101
221
 
102
- function aliasCodec<
103
- Id extends string,
104
- TTraits extends readonly CodecTrait[],
105
- TWire,
106
- TJs,
107
- TParams,
108
- THelper,
109
- >(
110
- base: Codec<string, TTraits, TWire, TJs, TParams, THelper>,
111
- options: {
112
- readonly typeId: Id;
113
- readonly targetTypes: readonly string[];
114
- readonly meta?: CodecMeta;
115
- },
116
- ): Codec<Id, TTraits, TWire, TJs, TParams, THelper> {
117
- return {
118
- id: options.typeId,
119
- targetTypes: options.targetTypes,
120
- ...ifDefined('meta', options.meta),
121
- ...ifDefined('paramsSchema', base.paramsSchema),
122
- ...ifDefined('init', base.init),
123
- ...ifDefined('encode', base.encode),
124
- ...ifDefined('traits', base.traits),
125
- ...ifDefined('renderOutputType', base.renderOutputType),
126
- decode: base.decode,
127
- encodeJson: base.encodeJson,
128
- decodeJson: base.decodeJson,
129
- } as Codec<Id, TTraits, TWire, TJs, TParams, THelper>;
130
- }
131
-
132
- const sqlCharCodec = sqlCodecDefinitions.char.codec;
133
- const sqlVarcharCodec = sqlCodecDefinitions.varchar.codec;
134
- const sqlIntCodec = sqlCodecDefinitions.int.codec;
135
- const sqlFloatCodec = sqlCodecDefinitions.float.codec;
136
- const sqlTextCodec = sqlCodecDefinitions.text.codec;
137
- const sqlTimestampCodec = sqlCodecDefinitions.timestamp.codec;
138
-
139
- // Create individual codec instances
140
- const pgTextCodec = codec({
141
- typeId: PG_TEXT_CODEC_ID,
142
- targetTypes: ['text'],
143
- traits: ['equality', 'order', 'textual'],
144
- encode: (value: string): string => value,
145
- decode: (wire: string): string => wire,
146
- meta: {
147
- db: {
148
- sql: {
149
- postgres: {
150
- nativeType: 'text',
151
- },
152
- },
153
- },
154
- },
155
- });
222
+ export class PgInt2Descriptor extends CodecDescriptorImpl<void> {
223
+ override readonly codecId = PG_INT2_CODEC_ID;
224
+ override readonly traits = ['equality', 'order', 'numeric'] as const;
225
+ override readonly targetTypes = ['int2'] as const;
226
+ override readonly meta = PG_INT2_META;
227
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
228
+ override factory(): (ctx: CodecInstanceContext) => PgInt2Codec {
229
+ return () => new PgInt2Codec(this);
230
+ }
231
+ }
156
232
 
157
- const pgCharCodec = aliasCodec(sqlCharCodec, {
158
- typeId: PG_CHAR_CODEC_ID,
159
- targetTypes: ['character'],
160
- meta: {
161
- db: {
162
- sql: {
163
- postgres: {
164
- nativeType: 'character',
165
- },
166
- },
167
- },
168
- },
169
- });
233
+ export const pgInt2Descriptor = new PgInt2Descriptor();
170
234
 
171
- const pgVarcharCodec = aliasCodec(sqlVarcharCodec, {
172
- typeId: PG_VARCHAR_CODEC_ID,
173
- targetTypes: ['character varying'],
174
- meta: {
175
- db: {
176
- sql: {
177
- postgres: {
178
- nativeType: 'character varying',
179
- },
180
- },
181
- },
182
- },
183
- });
235
+ export const pgInt2Column = () =>
236
+ column(pgInt2Descriptor.factory(), pgInt2Descriptor.codecId, undefined, 'int2');
184
237
 
185
- const pgIntCodec = aliasCodec(sqlIntCodec, {
186
- typeId: PG_INT_CODEC_ID,
187
- targetTypes: ['int4'],
188
- meta: {
189
- db: {
190
- sql: {
191
- postgres: {
192
- nativeType: 'integer',
193
- },
194
- },
195
- },
196
- },
197
- });
238
+ pgInt2Column satisfies ColumnHelperFor<PgInt2Descriptor>;
239
+ pgInt2Column satisfies ColumnHelperForStrict<PgInt2Descriptor>;
198
240
 
199
- const pgFloatCodec = aliasCodec(sqlFloatCodec, {
200
- typeId: PG_FLOAT_CODEC_ID,
201
- targetTypes: ['float8'],
202
- meta: {
203
- db: {
204
- sql: {
205
- postgres: {
206
- nativeType: 'double precision',
207
- },
208
- },
209
- },
210
- },
211
- });
241
+ export class PgInt8Codec extends CodecImpl<
242
+ typeof PG_INT8_CODEC_ID,
243
+ readonly ['equality', 'order', 'numeric'],
244
+ number,
245
+ number
246
+ > {
247
+ async encode(value: number, _ctx: CodecCallContext): Promise<number> {
248
+ return value;
249
+ }
250
+ async decode(wire: number, _ctx: CodecCallContext): Promise<number> {
251
+ return wire;
252
+ }
253
+ encodeJson(value: number): JsonValue {
254
+ return value;
255
+ }
256
+ decodeJson(json: JsonValue): number {
257
+ return json as number;
258
+ }
259
+ }
212
260
 
213
- const pgInt4Codec = codec({
214
- typeId: PG_INT4_CODEC_ID,
215
- targetTypes: ['int4'],
216
- traits: ['equality', 'order', 'numeric'],
217
- encode: (value: number): number => value,
218
- decode: (wire: number): number => wire,
219
- meta: {
220
- db: {
221
- sql: {
222
- postgres: {
223
- nativeType: 'integer',
224
- },
225
- },
226
- },
227
- },
228
- });
261
+ export class PgInt8Descriptor extends CodecDescriptorImpl<void> {
262
+ override readonly codecId = PG_INT8_CODEC_ID;
263
+ override readonly traits = ['equality', 'order', 'numeric'] as const;
264
+ override readonly targetTypes = ['int8'] as const;
265
+ override readonly meta = PG_INT8_META;
266
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
267
+ override factory(): (ctx: CodecInstanceContext) => PgInt8Codec {
268
+ return () => new PgInt8Codec(this);
269
+ }
270
+ }
271
+
272
+ export const pgInt8Descriptor = new PgInt8Descriptor();
273
+
274
+ export const pgInt8Column = () =>
275
+ column(pgInt8Descriptor.factory(), pgInt8Descriptor.codecId, undefined, 'int8');
276
+
277
+ pgInt8Column satisfies ColumnHelperFor<PgInt8Descriptor>;
278
+ pgInt8Column satisfies ColumnHelperForStrict<PgInt8Descriptor>;
279
+
280
+ export class PgFloat4Codec extends CodecImpl<
281
+ typeof PG_FLOAT4_CODEC_ID,
282
+ readonly ['equality', 'order', 'numeric'],
283
+ number,
284
+ number
285
+ > {
286
+ async encode(value: number, _ctx: CodecCallContext): Promise<number> {
287
+ return value;
288
+ }
289
+ async decode(wire: number, _ctx: CodecCallContext): Promise<number> {
290
+ return wire;
291
+ }
292
+ encodeJson(value: number): JsonValue {
293
+ return value;
294
+ }
295
+ decodeJson(json: JsonValue): number {
296
+ return json as number;
297
+ }
298
+ }
299
+
300
+ export class PgFloat4Descriptor extends CodecDescriptorImpl<void> {
301
+ override readonly codecId = PG_FLOAT4_CODEC_ID;
302
+ override readonly traits = ['equality', 'order', 'numeric'] as const;
303
+ override readonly targetTypes = ['float4'] as const;
304
+ override readonly meta = PG_FLOAT4_META;
305
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
306
+ override factory(): (ctx: CodecInstanceContext) => PgFloat4Codec {
307
+ return () => new PgFloat4Codec(this);
308
+ }
309
+ }
310
+
311
+ export const pgFloat4Descriptor = new PgFloat4Descriptor();
229
312
 
230
- const pgNumericCodec = codec<
313
+ export const pgFloat4Column = () =>
314
+ column(pgFloat4Descriptor.factory(), pgFloat4Descriptor.codecId, undefined, 'float4');
315
+
316
+ pgFloat4Column satisfies ColumnHelperFor<PgFloat4Descriptor>;
317
+ pgFloat4Column satisfies ColumnHelperForStrict<PgFloat4Descriptor>;
318
+
319
+ export class PgFloat8Codec extends CodecImpl<
320
+ typeof PG_FLOAT8_CODEC_ID,
321
+ readonly ['equality', 'order', 'numeric'],
322
+ number,
323
+ number
324
+ > {
325
+ async encode(value: number, _ctx: CodecCallContext): Promise<number> {
326
+ return value;
327
+ }
328
+ async decode(wire: number, _ctx: CodecCallContext): Promise<number> {
329
+ return wire;
330
+ }
331
+ encodeJson(value: number): JsonValue {
332
+ return value;
333
+ }
334
+ decodeJson(json: JsonValue): number {
335
+ return json as number;
336
+ }
337
+ }
338
+
339
+ export class PgFloat8Descriptor extends CodecDescriptorImpl<void> {
340
+ override readonly codecId = PG_FLOAT8_CODEC_ID;
341
+ override readonly traits = ['equality', 'order', 'numeric'] as const;
342
+ override readonly targetTypes = ['float8'] as const;
343
+ override readonly meta = PG_FLOAT8_META;
344
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
345
+ override factory(): (ctx: CodecInstanceContext) => PgFloat8Codec {
346
+ return () => new PgFloat8Codec(this);
347
+ }
348
+ }
349
+
350
+ export const pgFloat8Descriptor = new PgFloat8Descriptor();
351
+
352
+ export const pgFloat8Column = () =>
353
+ column(pgFloat8Descriptor.factory(), pgFloat8Descriptor.codecId, undefined, 'float8');
354
+
355
+ pgFloat8Column satisfies ColumnHelperFor<PgFloat8Descriptor>;
356
+ pgFloat8Column satisfies ColumnHelperForStrict<PgFloat8Descriptor>;
357
+
358
+ export class PgBoolCodec extends CodecImpl<
359
+ typeof PG_BOOL_CODEC_ID,
360
+ readonly ['equality', 'boolean'],
361
+ boolean,
362
+ boolean
363
+ > {
364
+ async encode(value: boolean, _ctx: CodecCallContext): Promise<boolean> {
365
+ return value;
366
+ }
367
+ async decode(wire: boolean, _ctx: CodecCallContext): Promise<boolean> {
368
+ return wire;
369
+ }
370
+ encodeJson(value: boolean): JsonValue {
371
+ return value;
372
+ }
373
+ decodeJson(json: JsonValue): boolean {
374
+ return json as boolean;
375
+ }
376
+ }
377
+
378
+ export class PgBoolDescriptor extends CodecDescriptorImpl<void> {
379
+ override readonly codecId = PG_BOOL_CODEC_ID;
380
+ override readonly traits = ['equality', 'boolean'] as const;
381
+ override readonly targetTypes = ['bool'] as const;
382
+ override readonly meta = PG_BOOL_META;
383
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
384
+ override factory(): (ctx: CodecInstanceContext) => PgBoolCodec {
385
+ return () => new PgBoolCodec(this);
386
+ }
387
+ }
388
+
389
+ export const pgBoolDescriptor = new PgBoolDescriptor();
390
+
391
+ export const pgBoolColumn = () =>
392
+ column(pgBoolDescriptor.factory(), pgBoolDescriptor.codecId, undefined, 'bool');
393
+
394
+ pgBoolColumn satisfies ColumnHelperFor<PgBoolDescriptor>;
395
+ pgBoolColumn satisfies ColumnHelperForStrict<PgBoolDescriptor>;
396
+
397
+ export class PgNumericCodec extends CodecImpl<
231
398
  typeof PG_NUMERIC_CODEC_ID,
232
399
  readonly ['equality', 'order', 'numeric'],
233
- string,
400
+ string | number,
234
401
  string
235
- >({
236
- typeId: PG_NUMERIC_CODEC_ID,
237
- targetTypes: ['numeric', 'decimal'],
238
- traits: ['equality', 'order', 'numeric'],
239
- encode: (value: string): string => value,
240
- decode: (wire: string | number): string => {
241
- if (typeof wire === 'number') return String(wire);
242
- return wire;
243
- },
244
- paramsSchema: numericParamsSchema,
245
- renderOutputType: (typeParams) => {
246
- const precision = typeParams['precision'];
247
- if (precision === undefined) return undefined;
248
- if (
249
- typeof precision !== 'number' ||
250
- !Number.isFinite(precision) ||
251
- !Number.isInteger(precision)
252
- ) {
253
- throw new Error(
254
- `renderOutputType: expected integer "precision" in typeParams for Numeric, got ${String(precision)}`,
255
- );
256
- }
257
- const scale = typeParams['scale'];
258
- return typeof scale === 'number' ? `Numeric<${precision}, ${scale}>` : `Numeric<${precision}>`;
259
- },
260
- meta: {
261
- db: {
262
- sql: {
263
- postgres: {
264
- nativeType: 'numeric',
265
- },
266
- },
267
- },
268
- },
269
- });
402
+ > {
403
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
404
+ return value;
405
+ }
406
+ async decode(wire: string | number, _ctx: CodecCallContext): Promise<string> {
407
+ return pgNumericDecode(wire);
408
+ }
409
+ encodeJson(value: string): JsonValue {
410
+ return value;
411
+ }
412
+ decodeJson(json: JsonValue): string {
413
+ return json as string;
414
+ }
415
+ }
270
416
 
271
- const pgInt2Codec = codec({
272
- typeId: PG_INT2_CODEC_ID,
273
- targetTypes: ['int2'],
274
- traits: ['equality', 'order', 'numeric'],
275
- encode: (value: number): number => value,
276
- decode: (wire: number): number => wire,
277
- meta: {
278
- db: {
279
- sql: {
280
- postgres: {
281
- nativeType: 'smallint',
282
- },
283
- },
284
- },
285
- },
286
- });
417
+ export class PgNumericDescriptor extends CodecDescriptorImpl<NumericParams> {
418
+ override readonly codecId = PG_NUMERIC_CODEC_ID;
419
+ override readonly traits = ['equality', 'order', 'numeric'] as const;
420
+ override readonly targetTypes = ['numeric', 'decimal'] as const;
421
+ override readonly meta = PG_NUMERIC_META;
422
+ override readonly paramsSchema = numericParamsSchema satisfies StandardSchemaV1<NumericParams>;
423
+ override renderOutputType(params: NumericParams): string | undefined {
424
+ return pgNumericRenderOutputType(params);
425
+ }
426
+ override factory(_params: NumericParams): (ctx: CodecInstanceContext) => PgNumericCodec {
427
+ return () => new PgNumericCodec(this);
428
+ }
429
+ }
287
430
 
288
- const pgInt8Codec = codec({
289
- typeId: PG_INT8_CODEC_ID,
290
- targetTypes: ['int8'],
291
- traits: ['equality', 'order', 'numeric'],
292
- encode: (value: number): number => value,
293
- decode: (wire: number): number => wire,
294
- meta: {
295
- db: {
296
- sql: {
297
- postgres: {
298
- nativeType: 'bigint',
299
- },
300
- },
301
- },
302
- },
303
- });
431
+ export const pgNumericDescriptor = new PgNumericDescriptor();
304
432
 
305
- const pgFloat4Codec = codec({
306
- typeId: PG_FLOAT4_CODEC_ID,
307
- targetTypes: ['float4'],
308
- traits: ['equality', 'order', 'numeric'],
309
- encode: (value: number): number => value,
310
- decode: (wire: number): number => wire,
311
- meta: {
312
- db: {
313
- sql: {
314
- postgres: {
315
- nativeType: 'real',
316
- },
317
- },
318
- },
319
- },
320
- });
433
+ export const pgNumericColumn = (params: NumericParams) =>
434
+ column(pgNumericDescriptor.factory(params), pgNumericDescriptor.codecId, params, 'numeric');
321
435
 
322
- const pgFloat8Codec = codec({
323
- typeId: PG_FLOAT8_CODEC_ID,
324
- targetTypes: ['float8'],
325
- traits: ['equality', 'order', 'numeric'],
326
- encode: (value: number): number => value,
327
- decode: (wire: number): number => wire,
328
- meta: {
329
- db: {
330
- sql: {
331
- postgres: {
332
- nativeType: 'double precision',
333
- },
334
- },
335
- },
336
- },
337
- });
436
+ pgNumericColumn satisfies ColumnHelperFor<PgNumericDescriptor>;
437
+ pgNumericColumn satisfies ColumnHelperForStrict<PgNumericDescriptor>;
338
438
 
339
- const pgTimestampCodec = codec<
439
+ export class PgTimestampCodec extends CodecImpl<
340
440
  typeof PG_TIMESTAMP_CODEC_ID,
341
441
  readonly ['equality', 'order'],
342
- string | Date,
343
- string | Date
344
- >({
345
- typeId: PG_TIMESTAMP_CODEC_ID,
346
- targetTypes: ['timestamp'],
347
- traits: ['equality', 'order'],
348
- encode: (value: string | Date): string => {
349
- if (value instanceof Date) return value.toISOString();
350
- if (typeof value === 'string') return value;
351
- return String(value);
352
- },
353
- decode: (wire: string | Date): string => {
354
- if (wire instanceof Date) return wire.toISOString();
442
+ Date,
443
+ Date
444
+ > {
445
+ async encode(value: Date, _ctx: CodecCallContext): Promise<Date> {
446
+ return value;
447
+ }
448
+ async decode(wire: Date, _ctx: CodecCallContext): Promise<Date> {
355
449
  return wire;
356
- },
357
- encodeJson: (value: string | Date) => (value instanceof Date ? value.toISOString() : value),
358
- decodeJson: (json) => {
359
- if (typeof json !== 'string') {
360
- throw new Error(`Expected ISO date string for pg/timestamp@1, got ${typeof json}`);
361
- }
362
- const date = new Date(json);
363
- if (Number.isNaN(date.getTime())) {
364
- throw new Error(`Invalid ISO date string for pg/timestamp@1: ${json}`);
365
- }
366
- return date;
367
- },
368
- paramsSchema: precisionParamsSchema,
369
- renderOutputType: (typeParams) => renderPrecision('Timestamp', typeParams),
370
- meta: {
371
- db: {
372
- sql: {
373
- postgres: {
374
- nativeType: 'timestamp without time zone',
375
- },
376
- },
377
- },
378
- },
379
- });
450
+ }
451
+ encodeJson(value: Date): JsonValue {
452
+ return pgTimestampEncodeJson(value);
453
+ }
454
+ decodeJson(json: JsonValue): Date {
455
+ return pgTimestampDecodeJson(json);
456
+ }
457
+ }
380
458
 
381
- const pgTimestamptzCodec = codec<
459
+ export class PgTimestampDescriptor extends CodecDescriptorImpl<PrecisionParams> {
460
+ override readonly codecId = PG_TIMESTAMP_CODEC_ID;
461
+ override readonly traits = ['equality', 'order'] as const;
462
+ override readonly targetTypes = ['timestamp'] as const;
463
+ override readonly meta = PG_TIMESTAMP_META;
464
+ override readonly paramsSchema =
465
+ precisionParamsSchema satisfies StandardSchemaV1<PrecisionParams>;
466
+ override renderOutputType(params: PrecisionParams): string | undefined {
467
+ return renderPrecision('Timestamp', params as Record<string, unknown>);
468
+ }
469
+ override factory(_params: PrecisionParams): (ctx: CodecInstanceContext) => PgTimestampCodec {
470
+ return () => new PgTimestampCodec(this);
471
+ }
472
+ }
473
+
474
+ export const pgTimestampDescriptor = new PgTimestampDescriptor();
475
+
476
+ export const pgTimestampColumn = (params: PrecisionParams = {}) =>
477
+ column(pgTimestampDescriptor.factory(params), pgTimestampDescriptor.codecId, params, 'timestamp');
478
+
479
+ pgTimestampColumn satisfies ColumnHelperFor<PgTimestampDescriptor>;
480
+ pgTimestampColumn satisfies ColumnHelperForStrict<PgTimestampDescriptor>;
481
+
482
+ export class PgTimestamptzCodec extends CodecImpl<
382
483
  typeof PG_TIMESTAMPTZ_CODEC_ID,
383
484
  readonly ['equality', 'order'],
384
- string | Date,
385
- string | Date
386
- >({
387
- typeId: PG_TIMESTAMPTZ_CODEC_ID,
388
- targetTypes: ['timestamptz'],
389
- traits: ['equality', 'order'],
390
- encode: (value: string | Date): string => {
391
- if (value instanceof Date) return value.toISOString();
392
- if (typeof value === 'string') return value;
393
- return String(value);
394
- },
395
- decode: (wire: string | Date): string => {
396
- if (wire instanceof Date) return wire.toISOString();
485
+ Date,
486
+ Date
487
+ > {
488
+ async encode(value: Date, _ctx: CodecCallContext): Promise<Date> {
489
+ return value;
490
+ }
491
+ async decode(wire: Date, _ctx: CodecCallContext): Promise<Date> {
397
492
  return wire;
398
- },
399
- encodeJson: (value: string | Date) => (value instanceof Date ? value.toISOString() : value),
400
- decodeJson: (json) => {
401
- if (typeof json !== 'string') {
402
- throw new Error(`Expected ISO date string for pg/timestamptz@1, got ${typeof json}`);
403
- }
404
- const date = new Date(json);
405
- if (Number.isNaN(date.getTime())) {
406
- throw new Error(`Invalid ISO date string for pg/timestamptz@1: ${json}`);
407
- }
408
- return date;
409
- },
410
- paramsSchema: precisionParamsSchema,
411
- renderOutputType: (typeParams) => renderPrecision('Timestamptz', typeParams),
412
- meta: {
413
- db: {
414
- sql: {
415
- postgres: {
416
- nativeType: 'timestamp with time zone',
417
- },
418
- },
419
- },
420
- },
421
- });
493
+ }
494
+ encodeJson(value: Date): JsonValue {
495
+ return pgTimestamptzEncodeJson(value);
496
+ }
497
+ decodeJson(json: JsonValue): Date {
498
+ return pgTimestamptzDecodeJson(json);
499
+ }
500
+ }
422
501
 
423
- const pgTimeCodec = codec<typeof PG_TIME_CODEC_ID, readonly ['equality', 'order'], string, string>({
424
- typeId: PG_TIME_CODEC_ID,
425
- targetTypes: ['time'],
426
- traits: ['equality', 'order'],
427
- encode: (value: string): string => value,
428
- decode: (wire: string): string => wire,
429
- paramsSchema: precisionParamsSchema,
430
- renderOutputType: (typeParams) => renderPrecision('Time', typeParams),
431
- meta: {
432
- db: {
433
- sql: {
434
- postgres: {
435
- nativeType: 'time',
436
- },
437
- },
438
- },
439
- },
440
- });
502
+ export class PgTimestamptzDescriptor extends CodecDescriptorImpl<PrecisionParams> {
503
+ override readonly codecId = PG_TIMESTAMPTZ_CODEC_ID;
504
+ override readonly traits = ['equality', 'order'] as const;
505
+ override readonly targetTypes = ['timestamptz'] as const;
506
+ override readonly meta = PG_TIMESTAMPTZ_META;
507
+ override readonly paramsSchema =
508
+ precisionParamsSchema satisfies StandardSchemaV1<PrecisionParams>;
509
+ override renderOutputType(params: PrecisionParams): string | undefined {
510
+ return renderPrecision('Timestamptz', params as Record<string, unknown>);
511
+ }
512
+ override factory(_params: PrecisionParams): (ctx: CodecInstanceContext) => PgTimestamptzCodec {
513
+ return () => new PgTimestamptzCodec(this);
514
+ }
515
+ }
516
+
517
+ export const pgTimestamptzDescriptor = new PgTimestamptzDescriptor();
518
+
519
+ export const pgTimestamptzColumn = (params: PrecisionParams = {}) =>
520
+ column(
521
+ pgTimestamptzDescriptor.factory(params),
522
+ pgTimestamptzDescriptor.codecId,
523
+ params,
524
+ 'timestamptz',
525
+ );
526
+
527
+ pgTimestamptzColumn satisfies ColumnHelperFor<PgTimestamptzDescriptor>;
528
+ pgTimestamptzColumn satisfies ColumnHelperForStrict<PgTimestamptzDescriptor>;
529
+
530
+ export class PgTimeCodec extends CodecImpl<
531
+ typeof PG_TIME_CODEC_ID,
532
+ readonly ['equality', 'order'],
533
+ string,
534
+ string
535
+ > {
536
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
537
+ return value;
538
+ }
539
+ async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
540
+ return wire;
541
+ }
542
+ encodeJson(value: string): JsonValue {
543
+ return value;
544
+ }
545
+ decodeJson(json: JsonValue): string {
546
+ return json as string;
547
+ }
548
+ }
549
+
550
+ export class PgTimeDescriptor extends CodecDescriptorImpl<PrecisionParams> {
551
+ override readonly codecId = PG_TIME_CODEC_ID;
552
+ override readonly traits = ['equality', 'order'] as const;
553
+ override readonly targetTypes = ['time'] as const;
554
+ override readonly meta = PG_TIME_META;
555
+ override readonly paramsSchema =
556
+ precisionParamsSchema satisfies StandardSchemaV1<PrecisionParams>;
557
+ override renderOutputType(params: PrecisionParams): string | undefined {
558
+ return renderPrecision('Time', params as Record<string, unknown>);
559
+ }
560
+ override factory(_params: PrecisionParams): (ctx: CodecInstanceContext) => PgTimeCodec {
561
+ return () => new PgTimeCodec(this);
562
+ }
563
+ }
564
+
565
+ export const pgTimeDescriptor = new PgTimeDescriptor();
566
+
567
+ export const pgTimeColumn = (params: PrecisionParams = {}) =>
568
+ column(pgTimeDescriptor.factory(params), pgTimeDescriptor.codecId, params, 'time');
569
+
570
+ pgTimeColumn satisfies ColumnHelperFor<PgTimeDescriptor>;
571
+ pgTimeColumn satisfies ColumnHelperForStrict<PgTimeDescriptor>;
441
572
 
442
- const pgTimetzCodec = codec<
573
+ export class PgTimetzCodec extends CodecImpl<
443
574
  typeof PG_TIMETZ_CODEC_ID,
444
575
  readonly ['equality', 'order'],
445
576
  string,
446
577
  string
447
- >({
448
- typeId: PG_TIMETZ_CODEC_ID,
449
- targetTypes: ['timetz'],
450
- traits: ['equality', 'order'],
451
- encode: (value: string): string => value,
452
- decode: (wire: string): string => wire,
453
- paramsSchema: precisionParamsSchema,
454
- renderOutputType: (typeParams) => renderPrecision('Timetz', typeParams),
455
- meta: {
456
- db: {
457
- sql: {
458
- postgres: {
459
- nativeType: 'timetz',
460
- },
461
- },
462
- },
463
- },
464
- });
578
+ > {
579
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
580
+ return value;
581
+ }
582
+ async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
583
+ return wire;
584
+ }
585
+ encodeJson(value: string): JsonValue {
586
+ return value;
587
+ }
588
+ decodeJson(json: JsonValue): string {
589
+ return json as string;
590
+ }
591
+ }
465
592
 
466
- const pgBoolCodec = codec({
467
- typeId: PG_BOOL_CODEC_ID,
468
- targetTypes: ['bool'],
469
- traits: ['equality', 'boolean'],
470
- encode: (value: boolean): boolean => value,
471
- decode: (wire: boolean): boolean => wire,
472
- meta: {
473
- db: {
474
- sql: {
475
- postgres: {
476
- nativeType: 'boolean',
477
- },
478
- },
479
- },
480
- },
481
- });
593
+ export class PgTimetzDescriptor extends CodecDescriptorImpl<PrecisionParams> {
594
+ override readonly codecId = PG_TIMETZ_CODEC_ID;
595
+ override readonly traits = ['equality', 'order'] as const;
596
+ override readonly targetTypes = ['timetz'] as const;
597
+ override readonly meta = PG_TIMETZ_META;
598
+ override readonly paramsSchema =
599
+ precisionParamsSchema satisfies StandardSchemaV1<PrecisionParams>;
600
+ override renderOutputType(params: PrecisionParams): string | undefined {
601
+ return renderPrecision('Timetz', params as Record<string, unknown>);
602
+ }
603
+ override factory(_params: PrecisionParams): (ctx: CodecInstanceContext) => PgTimetzCodec {
604
+ return () => new PgTimetzCodec(this);
605
+ }
606
+ }
482
607
 
483
- const pgBitCodec = codec<typeof PG_BIT_CODEC_ID, readonly ['equality', 'order'], string, string>({
484
- typeId: PG_BIT_CODEC_ID,
485
- targetTypes: ['bit'],
486
- traits: ['equality', 'order'],
487
- encode: (value: string): string => value,
488
- decode: (wire: string): string => wire,
489
- paramsSchema: lengthParamsSchema,
490
- renderOutputType: (typeParams) => renderLength('Bit', typeParams),
491
- meta: {
492
- db: {
493
- sql: {
494
- postgres: {
495
- nativeType: 'bit',
496
- },
497
- },
498
- },
499
- },
500
- });
608
+ export const pgTimetzDescriptor = new PgTimetzDescriptor();
609
+
610
+ export const pgTimetzColumn = (params: PrecisionParams = {}) =>
611
+ column(pgTimetzDescriptor.factory(params), pgTimetzDescriptor.codecId, params, 'timetz');
612
+
613
+ pgTimetzColumn satisfies ColumnHelperFor<PgTimetzDescriptor>;
614
+ pgTimetzColumn satisfies ColumnHelperForStrict<PgTimetzDescriptor>;
615
+
616
+ export class PgBitCodec extends CodecImpl<
617
+ typeof PG_BIT_CODEC_ID,
618
+ readonly ['equality', 'order'],
619
+ string,
620
+ string
621
+ > {
622
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
623
+ return value;
624
+ }
625
+ async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
626
+ return wire;
627
+ }
628
+ encodeJson(value: string): JsonValue {
629
+ return value;
630
+ }
631
+ decodeJson(json: JsonValue): string {
632
+ return json as string;
633
+ }
634
+ }
635
+
636
+ export class PgBitDescriptor extends CodecDescriptorImpl<LengthParams> {
637
+ override readonly codecId = PG_BIT_CODEC_ID;
638
+ override readonly traits = ['equality', 'order'] as const;
639
+ override readonly targetTypes = ['bit'] as const;
640
+ override readonly meta = PG_BIT_META;
641
+ override readonly paramsSchema = lengthParamsSchema satisfies StandardSchemaV1<LengthParams>;
642
+ override renderOutputType(params: LengthParams): string | undefined {
643
+ return renderLength('Bit', params as Record<string, unknown>);
644
+ }
645
+ override factory(_params: LengthParams): (ctx: CodecInstanceContext) => PgBitCodec {
646
+ return () => new PgBitCodec(this);
647
+ }
648
+ }
649
+
650
+ export const pgBitDescriptor = new PgBitDescriptor();
501
651
 
502
- const pgVarbitCodec = codec<
652
+ export const pgBitColumn = (params: LengthParams = {}) =>
653
+ column(pgBitDescriptor.factory(params), pgBitDescriptor.codecId, params, 'bit');
654
+
655
+ pgBitColumn satisfies ColumnHelperFor<PgBitDescriptor>;
656
+ pgBitColumn satisfies ColumnHelperForStrict<PgBitDescriptor>;
657
+
658
+ export class PgVarbitCodec extends CodecImpl<
503
659
  typeof PG_VARBIT_CODEC_ID,
504
660
  readonly ['equality', 'order'],
505
661
  string,
506
662
  string
507
- >({
508
- typeId: PG_VARBIT_CODEC_ID,
509
- targetTypes: ['bit varying'],
510
- traits: ['equality', 'order'],
511
- encode: (value: string): string => value,
512
- decode: (wire: string): string => wire,
513
- paramsSchema: lengthParamsSchema,
514
- renderOutputType: (typeParams) => renderLength('VarBit', typeParams),
515
- meta: {
516
- db: {
517
- sql: {
518
- postgres: {
519
- nativeType: 'bit varying',
520
- },
521
- },
522
- },
523
- },
524
- });
663
+ > {
664
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
665
+ return value;
666
+ }
667
+ async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
668
+ return wire;
669
+ }
670
+ encodeJson(value: string): JsonValue {
671
+ return value;
672
+ }
673
+ decodeJson(json: JsonValue): string {
674
+ return json as string;
675
+ }
676
+ }
525
677
 
526
- const pgEnumCodec = codec({
527
- typeId: PG_ENUM_CODEC_ID,
528
- targetTypes: ['enum'],
529
- traits: ['equality', 'order'],
530
- encode: (value: string): string => value,
531
- decode: (wire: string): string => wire,
532
- renderOutputType: (typeParams) => {
533
- const values = typeParams['values'];
534
- if (!Array.isArray(values)) {
535
- throw new Error(
536
- `renderOutputType: expected array "values" in typeParams for enum, got ${typeof values}`,
537
- );
678
+ export class PgVarbitDescriptor extends CodecDescriptorImpl<LengthParams> {
679
+ override readonly codecId = PG_VARBIT_CODEC_ID;
680
+ override readonly traits = ['equality', 'order'] as const;
681
+ override readonly targetTypes = ['bit varying'] as const;
682
+ override readonly meta = PG_VARBIT_META;
683
+ override readonly paramsSchema = lengthParamsSchema satisfies StandardSchemaV1<LengthParams>;
684
+ override renderOutputType(params: LengthParams): string | undefined {
685
+ return renderLength('VarBit', params as Record<string, unknown>);
686
+ }
687
+ override factory(_params: LengthParams): (ctx: CodecInstanceContext) => PgVarbitCodec {
688
+ return () => new PgVarbitCodec(this);
689
+ }
690
+ }
691
+
692
+ export const pgVarbitDescriptor = new PgVarbitDescriptor();
693
+
694
+ export const pgVarbitColumn = (params: LengthParams = {}) =>
695
+ column(pgVarbitDescriptor.factory(params), pgVarbitDescriptor.codecId, params, 'bit varying');
696
+
697
+ pgVarbitColumn satisfies ColumnHelperFor<PgVarbitDescriptor>;
698
+ pgVarbitColumn satisfies ColumnHelperForStrict<PgVarbitDescriptor>;
699
+
700
+ export class PgByteaCodec extends CodecImpl<
701
+ typeof PG_BYTEA_CODEC_ID,
702
+ readonly ['equality'],
703
+ Uint8Array,
704
+ Uint8Array
705
+ > {
706
+ async encode(value: Uint8Array, _ctx: CodecCallContext): Promise<Uint8Array> {
707
+ return value;
708
+ }
709
+ async decode(wire: Uint8Array, _ctx: CodecCallContext): Promise<Uint8Array> {
710
+ // Postgres node drivers commonly return Buffer instances (which extend Uint8Array) — normalize to a plain Uint8Array view so engine-agnostic consumers don't accidentally observe Buffer-specific APIs.
711
+ return wire instanceof Uint8Array && wire.constructor === Uint8Array
712
+ ? wire
713
+ : new Uint8Array(wire.buffer, wire.byteOffset, wire.byteLength);
714
+ }
715
+ encodeJson(value: Uint8Array): JsonValue {
716
+ return Buffer.from(value).toString('base64');
717
+ }
718
+ decodeJson(json: JsonValue): Uint8Array {
719
+ if (typeof json !== 'string') {
720
+ throw new Error(`Expected base64 string for pg/bytea@1, got ${typeof json}`);
538
721
  }
539
- return values
540
- .map((value) => `'${String(value).replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`)
541
- .join(' | ');
542
- },
543
- });
722
+ const decoded = Buffer.from(json, 'base64');
723
+ if (decoded.toString('base64') !== json) {
724
+ throw new Error(`Invalid base64 string for pg/bytea@1 (length: ${json.length})`);
725
+ }
726
+ return new Uint8Array(decoded);
727
+ }
728
+ }
729
+
730
+ export class PgByteaDescriptor extends CodecDescriptorImpl<void> {
731
+ override readonly codecId = PG_BYTEA_CODEC_ID;
732
+ override readonly traits = ['equality'] as const;
733
+ override readonly targetTypes = ['bytea'] as const;
734
+ override readonly meta = PG_BYTEA_META;
735
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
736
+ override factory(): (ctx: CodecInstanceContext) => PgByteaCodec {
737
+ return () => new PgByteaCodec(this);
738
+ }
739
+ }
740
+
741
+ export const pgByteaDescriptor = new PgByteaDescriptor();
742
+
743
+ export const pgByteaColumn = () =>
744
+ column(pgByteaDescriptor.factory(), pgByteaDescriptor.codecId, undefined, 'bytea');
544
745
 
545
- const pgIntervalCodec = codec<
746
+ pgByteaColumn satisfies ColumnHelperFor<PgByteaDescriptor>;
747
+ pgByteaColumn satisfies ColumnHelperForStrict<PgByteaDescriptor>;
748
+
749
+ export class PgIntervalCodec extends CodecImpl<
546
750
  typeof PG_INTERVAL_CODEC_ID,
547
751
  readonly ['equality', 'order'],
548
752
  string | Record<string, unknown>,
549
753
  string
550
- >({
551
- typeId: PG_INTERVAL_CODEC_ID,
552
- targetTypes: ['interval'],
553
- traits: ['equality', 'order'],
554
- encode: (value: string): string => value,
555
- decode: (wire: string | Record<string, unknown>): string => {
556
- if (typeof wire === 'string') return wire;
557
- return JSON.stringify(wire);
558
- },
559
- paramsSchema: precisionParamsSchema,
560
- renderOutputType: (typeParams) => renderPrecision('Interval', typeParams),
561
- meta: {
562
- db: {
563
- sql: {
564
- postgres: {
565
- nativeType: 'interval',
566
- },
567
- },
568
- },
569
- },
570
- });
754
+ > {
755
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
756
+ return value;
757
+ }
758
+ async decode(wire: string | Record<string, unknown>, _ctx: CodecCallContext): Promise<string> {
759
+ return pgIntervalDecode(wire);
760
+ }
761
+ encodeJson(value: string): JsonValue {
762
+ return value;
763
+ }
764
+ decodeJson(json: JsonValue): string {
765
+ return json as string;
766
+ }
767
+ }
571
768
 
572
- const pgJsonCodec = codec({
573
- typeId: PG_JSON_CODEC_ID,
574
- targetTypes: ['json'],
575
- traits: [],
576
- encode: (value: string | JsonValue): string => JSON.stringify(value),
577
- decode: (wire: string | JsonValue): JsonValue =>
578
- typeof wire === 'string' ? JSON.parse(wire) : wire,
579
- renderOutputType: renderJsonOutputType,
580
- meta: {
581
- db: {
582
- sql: {
583
- postgres: {
584
- nativeType: 'json',
585
- },
586
- },
587
- },
588
- },
589
- });
769
+ export class PgIntervalDescriptor extends CodecDescriptorImpl<PrecisionParams> {
770
+ override readonly codecId = PG_INTERVAL_CODEC_ID;
771
+ override readonly traits = ['equality', 'order'] as const;
772
+ override readonly targetTypes = ['interval'] as const;
773
+ override readonly meta = PG_INTERVAL_META;
774
+ override readonly paramsSchema =
775
+ precisionParamsSchema satisfies StandardSchemaV1<PrecisionParams>;
776
+ override renderOutputType(params: PrecisionParams): string | undefined {
777
+ return renderPrecision('Interval', params as Record<string, unknown>);
778
+ }
779
+ override factory(_params: PrecisionParams): (ctx: CodecInstanceContext) => PgIntervalCodec {
780
+ return () => new PgIntervalCodec(this);
781
+ }
782
+ }
783
+
784
+ export const pgIntervalDescriptor = new PgIntervalDescriptor();
785
+
786
+ export const pgIntervalColumn = (params: PrecisionParams = {}) =>
787
+ column(pgIntervalDescriptor.factory(params), pgIntervalDescriptor.codecId, params, 'interval');
788
+
789
+ pgIntervalColumn satisfies ColumnHelperFor<PgIntervalDescriptor>;
790
+ pgIntervalColumn satisfies ColumnHelperForStrict<PgIntervalDescriptor>;
590
791
 
591
- const pgJsonbCodec = codec({
592
- typeId: PG_JSONB_CODEC_ID,
593
- targetTypes: ['jsonb'],
594
- traits: ['equality'],
595
- encode: (value: string | JsonValue): string => JSON.stringify(value),
596
- decode: (wire: string | JsonValue): JsonValue =>
597
- typeof wire === 'string' ? JSON.parse(wire) : wire,
598
- renderOutputType: renderJsonOutputType,
599
- meta: {
600
- db: {
601
- sql: {
602
- postgres: {
603
- nativeType: 'jsonb',
604
- },
605
- },
606
- },
607
- },
792
+ const enumParamsSchema = arktype({
793
+ 'values?': 'string[]',
608
794
  });
609
795
 
610
- // Build codec definitions using the builder DSL
611
- const codecs = defineCodecs()
612
- .add('char', sqlCharCodec)
613
- .add('varchar', sqlVarcharCodec)
614
- .add('int', sqlIntCodec)
615
- .add('float', sqlFloatCodec)
616
- .add('sql-text', sqlTextCodec)
617
- .add('sql-timestamp', sqlTimestampCodec)
618
- .add('text', pgTextCodec)
619
- .add('character', pgCharCodec)
620
- .add('character varying', pgVarcharCodec)
621
- .add('integer', pgIntCodec)
622
- .add('double precision', pgFloatCodec)
623
- .add('int4', pgInt4Codec)
624
- .add('int2', pgInt2Codec)
625
- .add('int8', pgInt8Codec)
626
- .add('float4', pgFloat4Codec)
627
- .add('float8', pgFloat8Codec)
628
- .add('numeric', pgNumericCodec)
629
- .add('timestamp', pgTimestampCodec)
630
- .add('timestamptz', pgTimestamptzCodec)
631
- .add('time', pgTimeCodec)
632
- .add('timetz', pgTimetzCodec)
633
- .add('bool', pgBoolCodec)
634
- .add('bit', pgBitCodec)
635
- .add('bit varying', pgVarbitCodec)
636
- .add('interval', pgIntervalCodec)
637
- .add('enum', pgEnumCodec)
638
- .add('json', pgJsonCodec)
639
- .add('jsonb', pgJsonbCodec);
640
-
641
- // Export derived structures directly from codecs builder
642
- export const codecDefinitions = codecs.codecDefinitions;
643
- export const dataTypes = codecs.dataTypes;
644
-
645
- export type CodecTypes = typeof codecs.CodecTypes;
796
+ export class PgEnumCodec extends CodecImpl<
797
+ typeof PG_ENUM_CODEC_ID,
798
+ readonly ['equality', 'order'],
799
+ string,
800
+ string
801
+ > {
802
+ async encode(value: string, _ctx: CodecCallContext): Promise<string> {
803
+ return value;
804
+ }
805
+ async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
806
+ return wire;
807
+ }
808
+ encodeJson(value: string): JsonValue {
809
+ return value;
810
+ }
811
+ decodeJson(json: JsonValue): string {
812
+ return json as string;
813
+ }
814
+ }
815
+
816
+ export class PgEnumDescriptor extends CodecDescriptorImpl<EnumParams> {
817
+ override readonly codecId = PG_ENUM_CODEC_ID;
818
+ override readonly traits = ['equality', 'order'] as const;
819
+ override readonly targetTypes = ['enum'] as const;
820
+ override readonly paramsSchema = enumParamsSchema satisfies StandardSchemaV1<EnumParams>;
821
+ override renderOutputType(params: EnumParams): string | undefined {
822
+ return pgEnumRenderOutputType(params);
823
+ }
824
+ override factory(_params: EnumParams): (ctx: CodecInstanceContext) => PgEnumCodec {
825
+ return () => new PgEnumCodec(this);
826
+ }
827
+ }
828
+
829
+ export const pgEnumDescriptor = new PgEnumDescriptor();
830
+
831
+ export const pgEnumColumn = (params: EnumParams = {}) =>
832
+ column(pgEnumDescriptor.factory(params), pgEnumDescriptor.codecId, params, 'enum');
833
+
834
+ pgEnumColumn satisfies ColumnHelperFor<PgEnumDescriptor>;
835
+ pgEnumColumn satisfies ColumnHelperForStrict<PgEnumDescriptor>;
836
+
837
+ export class PgJsonCodec extends CodecImpl<
838
+ typeof PG_JSON_CODEC_ID,
839
+ readonly [],
840
+ string | JsonValue,
841
+ JsonValue
842
+ > {
843
+ async encode(value: JsonValue, _ctx: CodecCallContext): Promise<string> {
844
+ return pgJsonEncode(value);
845
+ }
846
+ async decode(wire: string | JsonValue, _ctx: CodecCallContext): Promise<JsonValue> {
847
+ return pgJsonDecode(wire);
848
+ }
849
+ encodeJson(value: JsonValue): JsonValue {
850
+ return value;
851
+ }
852
+ decodeJson(json: JsonValue): JsonValue {
853
+ return json;
854
+ }
855
+ }
856
+
857
+ export class PgJsonDescriptor extends CodecDescriptorImpl<void> {
858
+ override readonly codecId = PG_JSON_CODEC_ID;
859
+ override readonly traits = [] as const;
860
+ override readonly targetTypes = ['json'] as const;
861
+ override readonly meta = PG_JSON_META;
862
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
863
+ override factory(): (ctx: CodecInstanceContext) => PgJsonCodec {
864
+ return () => new PgJsonCodec(this);
865
+ }
866
+ }
867
+
868
+ export const pgJsonDescriptor = new PgJsonDescriptor();
869
+
870
+ export const pgJsonColumn = () =>
871
+ column(pgJsonDescriptor.factory(), pgJsonDescriptor.codecId, undefined, 'json');
872
+
873
+ pgJsonColumn satisfies ColumnHelperFor<PgJsonDescriptor>;
874
+ pgJsonColumn satisfies ColumnHelperForStrict<PgJsonDescriptor>;
875
+
876
+ export class PgJsonbCodec extends CodecImpl<
877
+ typeof PG_JSONB_CODEC_ID,
878
+ readonly ['equality'],
879
+ string | JsonValue,
880
+ JsonValue
881
+ > {
882
+ async encode(value: JsonValue, _ctx: CodecCallContext): Promise<string> {
883
+ return pgJsonbEncode(value);
884
+ }
885
+ async decode(wire: string | JsonValue, _ctx: CodecCallContext): Promise<JsonValue> {
886
+ return pgJsonbDecode(wire);
887
+ }
888
+ encodeJson(value: JsonValue): JsonValue {
889
+ return value;
890
+ }
891
+ decodeJson(json: JsonValue): JsonValue {
892
+ return json;
893
+ }
894
+ }
895
+
896
+ export class PgJsonbDescriptor extends CodecDescriptorImpl<void> {
897
+ override readonly codecId = PG_JSONB_CODEC_ID;
898
+ override readonly traits = ['equality'] as const;
899
+ override readonly targetTypes = ['jsonb'] as const;
900
+ override readonly meta = PG_JSONB_META;
901
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
902
+ override factory(): (ctx: CodecInstanceContext) => PgJsonbCodec {
903
+ return () => new PgJsonbCodec(this);
904
+ }
905
+ }
906
+
907
+ export const pgJsonbDescriptor = new PgJsonbDescriptor();
908
+
909
+ export const pgJsonbColumn = () =>
910
+ column(pgJsonbDescriptor.factory(), pgJsonbDescriptor.codecId, undefined, 'jsonb');
911
+
912
+ pgJsonbColumn satisfies ColumnHelperFor<PgJsonbDescriptor>;
913
+ pgJsonbColumn satisfies ColumnHelperForStrict<PgJsonbDescriptor>;
914
+
915
+ // `meta`. The factories instantiate the SQL-base codec class (`SqlCharCodec` etc.) passing `this` (the pg-alias descriptor) so `codec.id` resolves to the pg-alias codec id via `CodecImpl`'s `descriptor.codecId` proxy. ---------------------------------------------------------------------------
916
+
917
+ const PG_CHAR_META = { db: { sql: { postgres: { nativeType: 'character' } } } } as const;
918
+ const PG_VARCHAR_META = {
919
+ db: { sql: { postgres: { nativeType: 'character varying' } } },
920
+ } as const;
921
+ const PG_INT_META = { db: { sql: { postgres: { nativeType: 'integer' } } } } as const;
922
+ const PG_FLOAT_META = { db: { sql: { postgres: { nativeType: 'double precision' } } } } as const;
923
+
924
+ export class PgCharDescriptor extends CodecDescriptorImpl<LengthParams> {
925
+ override readonly codecId = PG_CHAR_CODEC_ID;
926
+ override readonly targetTypes = ['character'] as const;
927
+ override readonly meta = PG_CHAR_META;
928
+ override readonly traits = sqlCharDescriptor.traits;
929
+ override readonly paramsSchema = sqlCharDescriptor.paramsSchema;
930
+ override renderOutputType(params: LengthParams): string | undefined {
931
+ return sqlCharDescriptor.renderOutputType(params);
932
+ }
933
+ override factory(_params: LengthParams): (ctx: CodecInstanceContext) => SqlCharCodec {
934
+ return () => new SqlCharCodec(this);
935
+ }
936
+ }
937
+
938
+ export const pgCharDescriptor = new PgCharDescriptor();
939
+
940
+ export const pgCharColumn = (params: LengthParams = {}) =>
941
+ column(pgCharDescriptor.factory(params), pgCharDescriptor.codecId, params, 'character');
942
+
943
+ pgCharColumn satisfies ColumnHelperFor<PgCharDescriptor>;
944
+
945
+ export class PgVarcharDescriptor extends CodecDescriptorImpl<LengthParams> {
946
+ override readonly codecId = PG_VARCHAR_CODEC_ID;
947
+ override readonly targetTypes = ['character varying'] as const;
948
+ override readonly meta = PG_VARCHAR_META;
949
+ override readonly traits = sqlVarcharDescriptor.traits;
950
+ override readonly paramsSchema = sqlVarcharDescriptor.paramsSchema;
951
+ override renderOutputType(params: LengthParams): string | undefined {
952
+ return sqlVarcharDescriptor.renderOutputType(params);
953
+ }
954
+ override factory(_params: LengthParams): (ctx: CodecInstanceContext) => SqlVarcharCodec {
955
+ return () => new SqlVarcharCodec(this);
956
+ }
957
+ }
958
+
959
+ export const pgVarcharDescriptor = new PgVarcharDescriptor();
960
+
961
+ export const pgVarcharColumn = (params: LengthParams = {}) =>
962
+ column(
963
+ pgVarcharDescriptor.factory(params),
964
+ pgVarcharDescriptor.codecId,
965
+ params,
966
+ 'character varying',
967
+ );
968
+
969
+ pgVarcharColumn satisfies ColumnHelperFor<PgVarcharDescriptor>;
970
+
971
+ export class PgIntDescriptor extends CodecDescriptorImpl<void> {
972
+ override readonly codecId = PG_INT_CODEC_ID;
973
+ override readonly targetTypes = ['int4'] as const;
974
+ override readonly meta = PG_INT_META;
975
+ override readonly traits = sqlIntDescriptor.traits;
976
+ override readonly paramsSchema = sqlIntDescriptor.paramsSchema;
977
+ override factory(): (ctx: CodecInstanceContext) => SqlIntCodec {
978
+ return () => new SqlIntCodec(this);
979
+ }
980
+ }
981
+
982
+ export const pgIntDescriptor = new PgIntDescriptor();
983
+
984
+ export const pgIntColumn = () =>
985
+ column(pgIntDescriptor.factory(), pgIntDescriptor.codecId, undefined, 'int4');
986
+
987
+ pgIntColumn satisfies ColumnHelperFor<PgIntDescriptor>;
988
+
989
+ export class PgFloatDescriptor extends CodecDescriptorImpl<void> {
990
+ override readonly codecId = PG_FLOAT_CODEC_ID;
991
+ override readonly targetTypes = ['float8'] as const;
992
+ override readonly meta = PG_FLOAT_META;
993
+ override readonly traits = sqlFloatDescriptor.traits;
994
+ override readonly paramsSchema = sqlFloatDescriptor.paramsSchema;
995
+ override factory(): (ctx: CodecInstanceContext) => SqlFloatCodec {
996
+ return () => new SqlFloatCodec(this);
997
+ }
998
+ }
999
+
1000
+ export const pgFloatDescriptor = new PgFloatDescriptor();
1001
+
1002
+ export const pgFloatColumn = () =>
1003
+ column(pgFloatDescriptor.factory(), pgFloatDescriptor.codecId, undefined, 'float8');
1004
+
1005
+ pgFloatColumn satisfies ColumnHelperFor<PgFloatDescriptor>;
1006
+
1007
+ // `ExtractCodecTypes` to derive `CodecTypes`. ---------------------------------------------------------------------------
1008
+
1009
+ export const codecDescriptors: readonly AnyCodecDescriptor[] = [
1010
+ sqlCharDescriptor,
1011
+ sqlVarcharDescriptor,
1012
+ sqlIntDescriptor,
1013
+ sqlFloatDescriptor,
1014
+ sqlTextDescriptor,
1015
+ sqlTimestampDescriptor,
1016
+ pgTextDescriptor,
1017
+ pgCharDescriptor,
1018
+ pgVarcharDescriptor,
1019
+ pgIntDescriptor,
1020
+ pgFloatDescriptor,
1021
+ pgInt4Descriptor,
1022
+ pgInt2Descriptor,
1023
+ pgInt8Descriptor,
1024
+ pgFloat4Descriptor,
1025
+ pgFloat8Descriptor,
1026
+ pgNumericDescriptor,
1027
+ pgTimestampDescriptor,
1028
+ pgTimestamptzDescriptor,
1029
+ pgTimeDescriptor,
1030
+ pgTimetzDescriptor,
1031
+ pgBoolDescriptor,
1032
+ pgBitDescriptor,
1033
+ pgVarbitDescriptor,
1034
+ pgByteaDescriptor,
1035
+ pgIntervalDescriptor,
1036
+ pgEnumDescriptor,
1037
+ pgJsonDescriptor,
1038
+ pgJsonbDescriptor,
1039
+ ];