@prisma-next/adapter-postgres 0.3.0-pr.106.3 → 0.3.0-pr.110.1
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 +8 -0
- package/dist/{chunk-Y6L4BBLR.js → chunk-KJMTKEE7.js} +2 -2
- package/dist/{chunk-J3XSOAM2.js → chunk-VJEVMBDI.js} +20 -2
- package/dist/{chunk-J3XSOAM2.js.map → chunk-VJEVMBDI.js.map} +1 -1
- package/dist/{chunk-HD5YISNQ.js → chunk-VPNRPV63.js} +15 -3
- package/dist/chunk-VPNRPV63.js.map +1 -0
- package/dist/core/codecs.d.ts +11 -1
- package/dist/core/codecs.d.ts.map +1 -1
- package/dist/core/control-adapter.d.ts.map +1 -1
- package/dist/core/descriptor-meta.d.ts +19 -0
- package/dist/core/descriptor-meta.d.ts.map +1 -1
- package/dist/exports/adapter.js +2 -2
- package/dist/exports/codec-types.d.ts +1 -1
- package/dist/exports/codec-types.d.ts.map +1 -1
- package/dist/exports/codec-types.js +1 -1
- package/dist/exports/column-types.d.ts +20 -0
- package/dist/exports/column-types.d.ts.map +1 -1
- package/dist/exports/column-types.js +8 -0
- package/dist/exports/column-types.js.map +1 -1
- package/dist/exports/control.js +30 -1
- package/dist/exports/control.js.map +1 -1
- package/dist/exports/runtime.js +3 -3
- package/dist/types/codec-types.d.ts +35 -0
- package/dist/types/codec-types.d.ts.map +1 -0
- package/package.json +12 -12
- package/src/core/codecs.ts +28 -1
- package/src/core/control-adapter.ts +40 -0
- package/src/core/descriptor-meta.ts +21 -0
- package/src/exports/codec-types.ts +1 -1
- package/src/exports/column-types.ts +28 -0
- package/src/types/codec-types.ts +36 -0
- package/dist/chunk-HD5YISNQ.js.map +0 -1
- /package/dist/{chunk-Y6L4BBLR.js.map → chunk-KJMTKEE7.js.map} +0 -0
package/README.md
CHANGED
|
@@ -180,6 +180,7 @@ The adapter declares the following PostgreSQL capabilities:
|
|
|
180
180
|
- **`lateral: true`** - Supports LATERAL joins for `includeMany` nested array includes
|
|
181
181
|
- **`jsonAgg: true`** - Supports JSON aggregation functions (`json_agg`) for `includeMany`
|
|
182
182
|
- **`returning: true`** - Supports RETURNING clauses for DML operations (INSERT, UPDATE, DELETE)
|
|
183
|
+
- **`nativeEnums: true`** - Supports native PostgreSQL enums with `CREATE TYPE ... AS ENUM` and append-only `ALTER TYPE ... ADD VALUE`
|
|
183
184
|
|
|
184
185
|
**Important**: Capabilities must be declared in **both** places:
|
|
185
186
|
|
|
@@ -190,6 +191,13 @@ The capabilities on the descriptor must match the capabilities in code. If they
|
|
|
190
191
|
|
|
191
192
|
See `docs/reference/capabilities.md` and `docs/architecture docs/subsystems/5. Adapters & Targets.md` for details.
|
|
192
193
|
|
|
194
|
+
### Enum handling
|
|
195
|
+
|
|
196
|
+
- Enum identity is the column `nativeType` (e.g., `Role`).
|
|
197
|
+
- Migration planner emits `CREATE TYPE ... AS ENUM` before tables, appends new values with `ALTER TYPE ... ADD VALUE IF NOT EXISTS`, and (if unused) can drop extra enums.
|
|
198
|
+
- Non-append changes (reorder/remove) are surfaced as conflicts.
|
|
199
|
+
- For targets without native enums, the shared planner can fall back to CHECK constraints per column when `supportsNativeEnums` is disabled.
|
|
200
|
+
|
|
193
201
|
## includeMany Support
|
|
194
202
|
|
|
195
203
|
The adapter supports `includeMany` for nested array includes using PostgreSQL's `LATERAL` joins and `json_agg`:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
codecDefinitions
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VJEVMBDI.js";
|
|
4
4
|
|
|
5
5
|
// src/core/adapter.ts
|
|
6
6
|
import { createCodecRegistry, isOperationExpr } from "@prisma-next/sql-relational-core/ast";
|
|
@@ -306,4 +306,4 @@ function createPostgresAdapter(options) {
|
|
|
306
306
|
export {
|
|
307
307
|
createPostgresAdapter
|
|
308
308
|
};
|
|
309
|
-
//# sourceMappingURL=chunk-
|
|
309
|
+
//# sourceMappingURL=chunk-KJMTKEE7.js.map
|
|
@@ -151,7 +151,25 @@ var pgBoolCodec = codec({
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
});
|
|
154
|
-
var
|
|
154
|
+
var pgEnumCodec = codec({
|
|
155
|
+
typeId: "pg/enum@1",
|
|
156
|
+
targetTypes: [],
|
|
157
|
+
// Enum types are dynamically determined by nativeType
|
|
158
|
+
encode: (value) => value,
|
|
159
|
+
decode: (wire) => wire,
|
|
160
|
+
meta: {
|
|
161
|
+
db: {
|
|
162
|
+
sql: {
|
|
163
|
+
postgres: {
|
|
164
|
+
// The actual enum type name is specified per-column via nativeType.
|
|
165
|
+
// This placeholder indicates it's an enum without specifying which one.
|
|
166
|
+
nativeType: "enum"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
var codecs = defineCodecs().add("text", pgTextCodec).add("int4", pgInt4Codec).add("int2", pgInt2Codec).add("int8", pgInt8Codec).add("float4", pgFloat4Codec).add("float8", pgFloat8Codec).add("timestamp", pgTimestampCodec).add("timestamptz", pgTimestamptzCodec).add("bool", pgBoolCodec).add("enum", pgEnumCodec);
|
|
155
173
|
var codecDefinitions = codecs.codecDefinitions;
|
|
156
174
|
var dataTypes = codecs.dataTypes;
|
|
157
175
|
|
|
@@ -159,4 +177,4 @@ export {
|
|
|
159
177
|
codecDefinitions,
|
|
160
178
|
dataTypes
|
|
161
179
|
};
|
|
162
|
-
//# sourceMappingURL=chunk-
|
|
180
|
+
//# sourceMappingURL=chunk-VJEVMBDI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/codecs.ts"],"sourcesContent":["/**\n * Unified codec definitions for Postgres adapter.\n *\n * This file contains a single source of truth for all codec information:\n * - Scalar names\n * - Type IDs\n * - Codec implementations (runtime)\n * - Type information (compile-time)\n *\n * This structure is used both at runtime (to populate the registry) and\n * at compile time (to derive CodecTypes).\n */\n\nimport { codec, defineCodecs } from '@prisma-next/sql-relational-core/ast';\n\n// Create individual codec instances\nconst pgTextCodec = codec({\n typeId: 'pg/text@1',\n targetTypes: ['text'],\n encode: (value: string): string => value,\n decode: (wire: string): string => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'text',\n },\n },\n },\n },\n});\n\nconst pgInt4Codec = codec<'pg/int4@1', number, number>({\n typeId: 'pg/int4@1',\n targetTypes: ['int4'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'integer',\n },\n },\n },\n },\n});\n\nconst pgInt2Codec = codec<'pg/int2@1', number, number>({\n typeId: 'pg/int2@1',\n targetTypes: ['int2'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'smallint',\n },\n },\n },\n },\n});\n\nconst pgInt8Codec = codec<'pg/int8@1', number, number>({\n typeId: 'pg/int8@1',\n targetTypes: ['int8'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'bigint',\n },\n },\n },\n },\n});\n\nconst pgFloat4Codec = codec<'pg/float4@1', number, number>({\n typeId: 'pg/float4@1',\n targetTypes: ['float4'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'real',\n },\n },\n },\n },\n});\n\nconst pgFloat8Codec = codec<'pg/float8@1', number, number>({\n typeId: 'pg/float8@1',\n targetTypes: ['float8'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'double precision',\n },\n },\n },\n },\n});\n\nconst pgTimestampCodec = codec<'pg/timestamp@1', string | Date, string>({\n typeId: 'pg/timestamp@1',\n targetTypes: ['timestamp'],\n encode: (value: string | Date): string => {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string') return value;\n return String(value);\n },\n decode: (wire: string | Date): string => {\n if (typeof wire === 'string') return wire;\n if (wire instanceof Date) return wire.toISOString();\n return String(wire);\n },\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'timestamp without time zone',\n },\n },\n },\n },\n});\n\nconst pgTimestamptzCodec = codec<'pg/timestamptz@1', string | Date, string>({\n typeId: 'pg/timestamptz@1',\n targetTypes: ['timestamptz'],\n encode: (value: string | Date): string => {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string') return value;\n return String(value);\n },\n decode: (wire: string | Date): string => {\n if (typeof wire === 'string') return wire;\n if (wire instanceof Date) return wire.toISOString();\n return String(wire);\n },\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'timestamp with time zone',\n },\n },\n },\n },\n});\n\nconst pgBoolCodec = codec<'pg/bool@1', boolean, boolean>({\n typeId: 'pg/bool@1',\n targetTypes: ['bool'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'boolean',\n },\n },\n },\n },\n});\n\n// Build codec definitions using the builder DSL\nconst codecs = defineCodecs()\n .add('text', pgTextCodec)\n .add('int4', pgInt4Codec)\n .add('int2', pgInt2Codec)\n .add('int8', pgInt8Codec)\n .add('float4', pgFloat4Codec)\n .add('float8', pgFloat8Codec)\n .add('timestamp', pgTimestampCodec)\n .add('timestamptz', pgTimestamptzCodec)\n .add('bool', pgBoolCodec);\n\n// Export derived structures directly from codecs builder\nexport const codecDefinitions = codecs.codecDefinitions;\nexport const dataTypes = codecs.dataTypes;\n\n// Export types derived from codecs builder\nexport type CodecTypes = typeof codecs.CodecTypes;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/core/codecs.ts"],"sourcesContent":["/**\n * Unified codec definitions for Postgres adapter.\n *\n * This file contains a single source of truth for all codec information:\n * - Scalar names\n * - Type IDs\n * - Codec implementations (runtime)\n * - Type information (compile-time)\n *\n * This structure is used both at runtime (to populate the registry) and\n * at compile time (to derive CodecTypes).\n */\n\nimport { codec, defineCodecs } from '@prisma-next/sql-relational-core/ast';\n\n// Create individual codec instances\nconst pgTextCodec = codec({\n typeId: 'pg/text@1',\n targetTypes: ['text'],\n encode: (value: string): string => value,\n decode: (wire: string): string => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'text',\n },\n },\n },\n },\n});\n\nconst pgInt4Codec = codec<'pg/int4@1', number, number>({\n typeId: 'pg/int4@1',\n targetTypes: ['int4'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'integer',\n },\n },\n },\n },\n});\n\nconst pgInt2Codec = codec<'pg/int2@1', number, number>({\n typeId: 'pg/int2@1',\n targetTypes: ['int2'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'smallint',\n },\n },\n },\n },\n});\n\nconst pgInt8Codec = codec<'pg/int8@1', number, number>({\n typeId: 'pg/int8@1',\n targetTypes: ['int8'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'bigint',\n },\n },\n },\n },\n});\n\nconst pgFloat4Codec = codec<'pg/float4@1', number, number>({\n typeId: 'pg/float4@1',\n targetTypes: ['float4'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'real',\n },\n },\n },\n },\n});\n\nconst pgFloat8Codec = codec<'pg/float8@1', number, number>({\n typeId: 'pg/float8@1',\n targetTypes: ['float8'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'double precision',\n },\n },\n },\n },\n});\n\nconst pgTimestampCodec = codec<'pg/timestamp@1', string | Date, string>({\n typeId: 'pg/timestamp@1',\n targetTypes: ['timestamp'],\n encode: (value: string | Date): string => {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string') return value;\n return String(value);\n },\n decode: (wire: string | Date): string => {\n if (typeof wire === 'string') return wire;\n if (wire instanceof Date) return wire.toISOString();\n return String(wire);\n },\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'timestamp without time zone',\n },\n },\n },\n },\n});\n\nconst pgTimestamptzCodec = codec<'pg/timestamptz@1', string | Date, string>({\n typeId: 'pg/timestamptz@1',\n targetTypes: ['timestamptz'],\n encode: (value: string | Date): string => {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string') return value;\n return String(value);\n },\n decode: (wire: string | Date): string => {\n if (typeof wire === 'string') return wire;\n if (wire instanceof Date) return wire.toISOString();\n return String(wire);\n },\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'timestamp with time zone',\n },\n },\n },\n },\n});\n\nconst pgBoolCodec = codec<'pg/bool@1', boolean, boolean>({\n typeId: 'pg/bool@1',\n targetTypes: ['bool'],\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n nativeType: 'boolean',\n },\n },\n },\n },\n});\n\n/**\n * Generic codec for Postgres enum types.\n * Enums are wire-encoded as strings and JS-typed as strings.\n * The specific enum type name is provided via nativeType in the storage column.\n *\n * Type safety for enum values is provided at compile time via parameterizedOutput\n * which derives the union type from typeParams.values in the contract.\n */\nconst pgEnumCodec = codec<'pg/enum@1', string, string>({\n typeId: 'pg/enum@1',\n targetTypes: [], // Enum types are dynamically determined by nativeType\n encode: (value) => value,\n decode: (wire) => wire,\n meta: {\n db: {\n sql: {\n postgres: {\n // The actual enum type name is specified per-column via nativeType.\n // This placeholder indicates it's an enum without specifying which one.\n nativeType: 'enum',\n },\n },\n },\n },\n});\n\n// Build codec definitions using the builder DSL\nconst codecs = defineCodecs()\n .add('text', pgTextCodec)\n .add('int4', pgInt4Codec)\n .add('int2', pgInt2Codec)\n .add('int8', pgInt8Codec)\n .add('float4', pgFloat4Codec)\n .add('float8', pgFloat8Codec)\n .add('timestamp', pgTimestampCodec)\n .add('timestamptz', pgTimestamptzCodec)\n .add('bool', pgBoolCodec)\n .add('enum', pgEnumCodec);\n\n// Export derived structures directly from codecs builder\nexport const codecDefinitions = codecs.codecDefinitions;\nexport const dataTypes = codecs.dataTypes;\n\n// Export types derived from codecs builder\nexport type CodecTypes = typeof codecs.CodecTypes;\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
// src/core/descriptor-meta.ts
|
|
2
|
+
function renderEnumType(params) {
|
|
3
|
+
const values = params["values"];
|
|
4
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
5
|
+
return "string";
|
|
6
|
+
}
|
|
7
|
+
return values.map((v) => JSON.stringify(String(v))).join(" | ");
|
|
8
|
+
}
|
|
2
9
|
var postgresAdapterDescriptorMeta = {
|
|
3
10
|
kind: "adapter",
|
|
4
11
|
familyId: "sql",
|
|
@@ -11,7 +18,8 @@ var postgresAdapterDescriptorMeta = {
|
|
|
11
18
|
limit: true,
|
|
12
19
|
lateral: true,
|
|
13
20
|
jsonAgg: true,
|
|
14
|
-
returning: true
|
|
21
|
+
returning: true,
|
|
22
|
+
nativeEnums: true
|
|
15
23
|
}
|
|
16
24
|
},
|
|
17
25
|
types: {
|
|
@@ -20,6 +28,9 @@ var postgresAdapterDescriptorMeta = {
|
|
|
20
28
|
package: "@prisma-next/adapter-postgres/codec-types",
|
|
21
29
|
named: "CodecTypes",
|
|
22
30
|
alias: "PgTypes"
|
|
31
|
+
},
|
|
32
|
+
parameterized: {
|
|
33
|
+
"pg/enum@1": renderEnumType
|
|
23
34
|
}
|
|
24
35
|
},
|
|
25
36
|
storage: [
|
|
@@ -36,7 +47,8 @@ var postgresAdapterDescriptorMeta = {
|
|
|
36
47
|
targetId: "postgres",
|
|
37
48
|
nativeType: "timestamptz"
|
|
38
49
|
},
|
|
39
|
-
{ typeId: "pg/bool@1", familyId: "sql", targetId: "postgres", nativeType: "bool" }
|
|
50
|
+
{ typeId: "pg/bool@1", familyId: "sql", targetId: "postgres", nativeType: "bool" },
|
|
51
|
+
{ typeId: "pg/enum@1", familyId: "sql", targetId: "postgres", nativeType: "enum" }
|
|
40
52
|
]
|
|
41
53
|
}
|
|
42
54
|
};
|
|
@@ -44,4 +56,4 @@ var postgresAdapterDescriptorMeta = {
|
|
|
44
56
|
export {
|
|
45
57
|
postgresAdapterDescriptorMeta
|
|
46
58
|
};
|
|
47
|
-
//# sourceMappingURL=chunk-
|
|
59
|
+
//# sourceMappingURL=chunk-VPNRPV63.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/descriptor-meta.ts"],"sourcesContent":["/**\n * Parameterized renderer for enum types.\n * Converts typeParams.values array to a union type string.\n * e.g., { values: ['USER', 'ADMIN'] } -> '\"USER\" | \"ADMIN\"'\n *\n * Uses JSON.stringify to properly escape special characters in enum values\n * (e.g., quotes, backslashes) ensuring valid TypeScript string literals.\n */\nfunction renderEnumType(params: Record<string, unknown>): string {\n const values = params['values'];\n if (!Array.isArray(values) || values.length === 0) {\n return 'string';\n }\n return values.map((v) => JSON.stringify(String(v))).join(' | ');\n}\n\nexport const postgresAdapterDescriptorMeta = {\n kind: 'adapter',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n nativeEnums: true,\n },\n },\n types: {\n codecTypes: {\n import: {\n package: '@prisma-next/adapter-postgres/codec-types',\n named: 'CodecTypes',\n alias: 'PgTypes',\n },\n parameterized: {\n 'pg/enum@1': renderEnumType,\n },\n },\n storage: [\n { typeId: 'pg/text@1', familyId: 'sql', targetId: 'postgres', nativeType: 'text' },\n { typeId: 'pg/int4@1', familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: 'pg/int2@1', familyId: 'sql', targetId: 'postgres', nativeType: 'int2' },\n { typeId: 'pg/int8@1', familyId: 'sql', targetId: 'postgres', nativeType: 'int8' },\n { typeId: 'pg/float4@1', familyId: 'sql', targetId: 'postgres', nativeType: 'float4' },\n { typeId: 'pg/float8@1', familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: 'pg/timestamp@1', familyId: 'sql', targetId: 'postgres', nativeType: 'timestamp' },\n {\n typeId: 'pg/timestamptz@1',\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamptz',\n },\n { typeId: 'pg/bool@1', familyId: 'sql', targetId: 'postgres', nativeType: 'bool' },\n { typeId: 'pg/enum@1', familyId: 'sql', targetId: 'postgres', nativeType: 'enum' },\n ],\n },\n} as const;\n"],"mappings":";AAQA,SAAS,eAAe,QAAyC;AAC/D,QAAM,SAAS,OAAO,QAAQ;AAC9B,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,GAAG;AACjD,WAAO;AAAA,EACT;AACA,SAAO,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK;AAChE;AAEO,IAAM,gCAAgC;AAAA,EAC3C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,cAAc;AAAA,IACZ,UAAU;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,SAAS;AAAA,MACT,SAAS;AAAA,MACT,WAAW;AAAA,MACX,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,YAAY;AAAA,MACV,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,MACA,eAAe;AAAA,QACb,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,eAAe,UAAU,OAAO,UAAU,YAAY,YAAY,SAAS;AAAA,MACrF,EAAE,QAAQ,eAAe,UAAU,OAAO,UAAU,YAAY,YAAY,SAAS;AAAA,MACrF,EAAE,QAAQ,kBAAkB,UAAU,OAAO,UAAU,YAAY,YAAY,YAAY;AAAA,MAC3F;AAAA,QACE,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA,MACA,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,IACnF;AAAA,EACF;AACF;","names":[]}
|
package/dist/core/codecs.d.ts
CHANGED
|
@@ -19,7 +19,8 @@ declare const codecs: import("@prisma-next/sql-relational-core/ast").CodecDefBui
|
|
|
19
19
|
float8: import("@prisma-next/sql-relational-core/ast").Codec<"pg/float8@1", number, number>;
|
|
20
20
|
timestamp: import("@prisma-next/sql-relational-core/ast").Codec<"pg/timestamp@1", string | Date, string>;
|
|
21
21
|
timestamptz: import("@prisma-next/sql-relational-core/ast").Codec<"pg/timestamptz@1", string | Date, string>;
|
|
22
|
-
|
|
22
|
+
bool: import("@prisma-next/sql-relational-core/ast").Codec<"pg/bool@1", boolean, boolean>;
|
|
23
|
+
} & Record<"enum", import("@prisma-next/sql-relational-core/ast").Codec<"pg/enum@1", string, string>>>;
|
|
23
24
|
export declare const codecDefinitions: {
|
|
24
25
|
readonly text: {
|
|
25
26
|
readonly typeId: "pg/text@1";
|
|
@@ -93,6 +94,14 @@ export declare const codecDefinitions: {
|
|
|
93
94
|
readonly output: boolean;
|
|
94
95
|
readonly jsType: boolean;
|
|
95
96
|
};
|
|
97
|
+
readonly enum: {
|
|
98
|
+
readonly typeId: "pg/enum@1";
|
|
99
|
+
readonly scalar: "enum";
|
|
100
|
+
readonly codec: import("@prisma-next/sql-relational-core/ast").Codec<"pg/enum@1", string, string>;
|
|
101
|
+
readonly input: string;
|
|
102
|
+
readonly output: string;
|
|
103
|
+
readonly jsType: string;
|
|
104
|
+
};
|
|
96
105
|
};
|
|
97
106
|
export declare const dataTypes: {
|
|
98
107
|
readonly text: "pg/text@1";
|
|
@@ -104,6 +113,7 @@ export declare const dataTypes: {
|
|
|
104
113
|
readonly timestamp: "pg/timestamp@1";
|
|
105
114
|
readonly timestamptz: "pg/timestamptz@1";
|
|
106
115
|
readonly bool: "pg/bool@1";
|
|
116
|
+
readonly enum: "pg/enum@1";
|
|
107
117
|
};
|
|
108
118
|
export type CodecTypes = typeof codecs.CodecTypes;
|
|
109
119
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codecs.d.ts","sourceRoot":"","sources":["../../src/core/codecs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"codecs.d.ts","sourceRoot":"","sources":["../../src/core/codecs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgMH,QAAA,MAAM,MAAM;;;;;;;;;;sGAUe,CAAC;AAG5B,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAA0B,CAAC;AACxD,eAAO,MAAM,SAAS;;;;;;;;;;;CAAmB,CAAC;AAG1C,MAAM,MAAM,UAAU,GAAG,OAAO,MAAM,CAAC,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-adapter.d.ts","sourceRoot":"","sources":["../../src/core/control-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"control-adapter.d.ts","sourceRoot":"","sources":["../../src/core/control-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,KAAK,EAMV,WAAW,EAGZ,MAAM,kCAAkC,CAAC;AAE1C;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,iBAAiB,CAAC,UAAU,CAAC;IAC1E,QAAQ,CAAC,QAAQ,EAAG,KAAK,CAAU;IACnC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IACxC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAG,UAAU,CAAU;IAEtC;;;;;;;;;;;OAWG;IACG,UAAU,CACd,MAAM,EAAE,qBAAqB,CAAC,KAAK,EAAE,UAAU,CAAC,EAChD,WAAW,CAAC,EAAE,OAAO,EACrB,MAAM,SAAW,GAChB,OAAO,CAAC,WAAW,CAAC;IAyWvB;;OAEG;YACW,kBAAkB;CASjC"}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameterized renderer for enum types.
|
|
3
|
+
* Converts typeParams.values array to a union type string.
|
|
4
|
+
* e.g., { values: ['USER', 'ADMIN'] } -> '"USER" | "ADMIN"'
|
|
5
|
+
*
|
|
6
|
+
* Uses JSON.stringify to properly escape special characters in enum values
|
|
7
|
+
* (e.g., quotes, backslashes) ensuring valid TypeScript string literals.
|
|
8
|
+
*/
|
|
9
|
+
declare function renderEnumType(params: Record<string, unknown>): string;
|
|
1
10
|
export declare const postgresAdapterDescriptorMeta: {
|
|
2
11
|
readonly kind: "adapter";
|
|
3
12
|
readonly familyId: "sql";
|
|
@@ -11,6 +20,7 @@ export declare const postgresAdapterDescriptorMeta: {
|
|
|
11
20
|
readonly lateral: true;
|
|
12
21
|
readonly jsonAgg: true;
|
|
13
22
|
readonly returning: true;
|
|
23
|
+
readonly nativeEnums: true;
|
|
14
24
|
};
|
|
15
25
|
};
|
|
16
26
|
readonly types: {
|
|
@@ -20,6 +30,9 @@ export declare const postgresAdapterDescriptorMeta: {
|
|
|
20
30
|
readonly named: "CodecTypes";
|
|
21
31
|
readonly alias: "PgTypes";
|
|
22
32
|
};
|
|
33
|
+
readonly parameterized: {
|
|
34
|
+
readonly 'pg/enum@1': typeof renderEnumType;
|
|
35
|
+
};
|
|
23
36
|
};
|
|
24
37
|
readonly storage: readonly [{
|
|
25
38
|
readonly typeId: "pg/text@1";
|
|
@@ -66,7 +79,13 @@ export declare const postgresAdapterDescriptorMeta: {
|
|
|
66
79
|
readonly familyId: "sql";
|
|
67
80
|
readonly targetId: "postgres";
|
|
68
81
|
readonly nativeType: "bool";
|
|
82
|
+
}, {
|
|
83
|
+
readonly typeId: "pg/enum@1";
|
|
84
|
+
readonly familyId: "sql";
|
|
85
|
+
readonly targetId: "postgres";
|
|
86
|
+
readonly nativeType: "enum";
|
|
69
87
|
}];
|
|
70
88
|
};
|
|
71
89
|
};
|
|
90
|
+
export {};
|
|
72
91
|
//# sourceMappingURL=descriptor-meta.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"descriptor-meta.d.ts","sourceRoot":"","sources":["../../src/core/descriptor-meta.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B
|
|
1
|
+
{"version":3,"file":"descriptor-meta.d.ts","sourceRoot":"","sources":["../../src/core/descriptor-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,iBAAS,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAM/D;AAED,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6ChC,CAAC"}
|
package/dist/exports/adapter.js
CHANGED
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Runtime codec implementations are provided by the adapter's codec registry.
|
|
8
8
|
*/
|
|
9
|
-
export type { CodecTypes } from '../core/codecs';
|
|
10
9
|
export { dataTypes } from '../core/codecs';
|
|
10
|
+
export type { CodecTypes } from '../types/codec-types';
|
|
11
11
|
//# sourceMappingURL=codec-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec-types.d.ts","sourceRoot":"","sources":["../../src/exports/codec-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,
|
|
1
|
+
{"version":3,"file":"codec-types.d.ts","sourceRoot":"","sources":["../../src/exports/codec-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -14,4 +14,24 @@ export declare const float8Column: ColumnTypeDescriptor;
|
|
|
14
14
|
export declare const timestampColumn: ColumnTypeDescriptor;
|
|
15
15
|
export declare const timestamptzColumn: ColumnTypeDescriptor;
|
|
16
16
|
export declare const boolColumn: ColumnTypeDescriptor;
|
|
17
|
+
/**
|
|
18
|
+
* Factory for creating enum column descriptors.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* .column('role', { type: enumColumn('Role', ['USER', 'ADMIN', 'MODERATOR'] as const), nullable: false })
|
|
23
|
+
* // Produces: nativeType: 'Role', codecId: 'pg/enum@1', typeParams: { values: ['USER', 'ADMIN', 'MODERATOR'] }
|
|
24
|
+
* // TypeScript type: 'USER' | 'ADMIN' | 'MODERATOR'
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @param enumName - The name of the enum type in the database (e.g., 'Role', 'Status')
|
|
28
|
+
* @param values - The ordered list of valid enum values as a const tuple
|
|
29
|
+
* @returns A column type descriptor with `typeParams.values` for union type inference
|
|
30
|
+
*/
|
|
31
|
+
export declare function enumColumn<Name extends string, Values extends readonly string[]>(enumName: Name, values: Values): ColumnTypeDescriptor & {
|
|
32
|
+
readonly nativeType: Name;
|
|
33
|
+
readonly typeParams: {
|
|
34
|
+
readonly values: Values;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
17
37
|
//# sourceMappingURL=column-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-types.d.ts","sourceRoot":"","sources":["../../src/exports/column-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,YAAY,EAAE,oBAGjB,CAAC;AAEX,eAAO,MAAM,YAAY,EAAE,oBAGjB,CAAC;AAEX,eAAO,MAAM,eAAe,EAAE,oBAGpB,CAAC;AAEX,eAAO,MAAM,iBAAiB,EAAE,oBAGtB,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC"}
|
|
1
|
+
{"version":3,"file":"column-types.d.ts","sourceRoot":"","sources":["../../src/exports/column-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX,eAAO,MAAM,YAAY,EAAE,oBAGjB,CAAC;AAEX,eAAO,MAAM,YAAY,EAAE,oBAGjB,CAAC;AAEX,eAAO,MAAM,eAAe,EAAE,oBAGpB,CAAC;AAEX,eAAO,MAAM,iBAAiB,EAAE,oBAGtB,CAAC;AAEX,eAAO,MAAM,UAAU,EAAE,oBAGf,CAAC;AAEX;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,SAAS,SAAS,MAAM,EAAE,EAC9E,QAAQ,EAAE,IAAI,EACd,MAAM,EAAE,MAAM,GACb,oBAAoB,GAAG;IACxB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAClD,CAMA"}
|
|
@@ -35,8 +35,16 @@ var boolColumn = {
|
|
|
35
35
|
codecId: "pg/bool@1",
|
|
36
36
|
nativeType: "bool"
|
|
37
37
|
};
|
|
38
|
+
function enumColumn(enumName, values) {
|
|
39
|
+
return {
|
|
40
|
+
codecId: "pg/enum@1",
|
|
41
|
+
nativeType: enumName,
|
|
42
|
+
typeParams: { values }
|
|
43
|
+
};
|
|
44
|
+
}
|
|
38
45
|
export {
|
|
39
46
|
boolColumn,
|
|
47
|
+
enumColumn,
|
|
40
48
|
float4Column,
|
|
41
49
|
float8Column,
|
|
42
50
|
int2Column,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/column-types.ts"],"sourcesContent":["/**\n * Column type descriptors for Postgres adapter.\n *\n * These descriptors provide both codecId and nativeType for use in contract authoring.\n * They are derived from the same source of truth as codec definitions and manifests.\n */\n\nimport type { ColumnTypeDescriptor } from '@prisma-next/contract-authoring';\n\nexport const textColumn: ColumnTypeDescriptor = {\n codecId: 'pg/text@1',\n nativeType: 'text',\n} as const;\n\nexport const int4Column: ColumnTypeDescriptor = {\n codecId: 'pg/int4@1',\n nativeType: 'int4',\n} as const;\n\nexport const int2Column: ColumnTypeDescriptor = {\n codecId: 'pg/int2@1',\n nativeType: 'int2',\n} as const;\n\nexport const int8Column: ColumnTypeDescriptor = {\n codecId: 'pg/int8@1',\n nativeType: 'int8',\n} as const;\n\nexport const float4Column: ColumnTypeDescriptor = {\n codecId: 'pg/float4@1',\n nativeType: 'float4',\n} as const;\n\nexport const float8Column: ColumnTypeDescriptor = {\n codecId: 'pg/float8@1',\n nativeType: 'float8',\n} as const;\n\nexport const timestampColumn: ColumnTypeDescriptor = {\n codecId: 'pg/timestamp@1',\n nativeType: 'timestamp',\n} as const;\n\nexport const timestamptzColumn: ColumnTypeDescriptor = {\n codecId: 'pg/timestamptz@1',\n nativeType: 'timestamptz',\n} as const;\n\nexport const boolColumn: ColumnTypeDescriptor = {\n codecId: 'pg/bool@1',\n nativeType: 'bool',\n} as const;\n"],"mappings":";AASO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,eAAqC;AAAA,EAChD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,eAAqC;AAAA,EAChD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,kBAAwC;AAAA,EACnD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,oBAA0C;AAAA,EACrD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/exports/column-types.ts"],"sourcesContent":["/**\n * Column type descriptors for Postgres adapter.\n *\n * These descriptors provide both codecId and nativeType for use in contract authoring.\n * They are derived from the same source of truth as codec definitions and manifests.\n */\n\nimport type { ColumnTypeDescriptor } from '@prisma-next/contract-authoring';\n\nexport const textColumn: ColumnTypeDescriptor = {\n codecId: 'pg/text@1',\n nativeType: 'text',\n} as const;\n\nexport const int4Column: ColumnTypeDescriptor = {\n codecId: 'pg/int4@1',\n nativeType: 'int4',\n} as const;\n\nexport const int2Column: ColumnTypeDescriptor = {\n codecId: 'pg/int2@1',\n nativeType: 'int2',\n} as const;\n\nexport const int8Column: ColumnTypeDescriptor = {\n codecId: 'pg/int8@1',\n nativeType: 'int8',\n} as const;\n\nexport const float4Column: ColumnTypeDescriptor = {\n codecId: 'pg/float4@1',\n nativeType: 'float4',\n} as const;\n\nexport const float8Column: ColumnTypeDescriptor = {\n codecId: 'pg/float8@1',\n nativeType: 'float8',\n} as const;\n\nexport const timestampColumn: ColumnTypeDescriptor = {\n codecId: 'pg/timestamp@1',\n nativeType: 'timestamp',\n} as const;\n\nexport const timestamptzColumn: ColumnTypeDescriptor = {\n codecId: 'pg/timestamptz@1',\n nativeType: 'timestamptz',\n} as const;\n\nexport const boolColumn: ColumnTypeDescriptor = {\n codecId: 'pg/bool@1',\n nativeType: 'bool',\n} as const;\n\n/**\n * Factory for creating enum column descriptors.\n *\n * @example\n * ```typescript\n * .column('role', { type: enumColumn('Role', ['USER', 'ADMIN', 'MODERATOR'] as const), nullable: false })\n * // Produces: nativeType: 'Role', codecId: 'pg/enum@1', typeParams: { values: ['USER', 'ADMIN', 'MODERATOR'] }\n * // TypeScript type: 'USER' | 'ADMIN' | 'MODERATOR'\n * ```\n *\n * @param enumName - The name of the enum type in the database (e.g., 'Role', 'Status')\n * @param values - The ordered list of valid enum values as a const tuple\n * @returns A column type descriptor with `typeParams.values` for union type inference\n */\nexport function enumColumn<Name extends string, Values extends readonly string[]>(\n enumName: Name,\n values: Values,\n): ColumnTypeDescriptor & {\n readonly nativeType: Name;\n readonly typeParams: { readonly values: Values };\n} {\n return {\n codecId: 'pg/enum@1',\n nativeType: enumName,\n typeParams: { values },\n } as const;\n}\n"],"mappings":";AASO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,eAAqC;AAAA,EAChD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,eAAqC;AAAA,EAChD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,kBAAwC;AAAA,EACnD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,oBAA0C;AAAA,EACrD,SAAS;AAAA,EACT,YAAY;AACd;AAEO,IAAM,aAAmC;AAAA,EAC9C,SAAS;AAAA,EACT,YAAY;AACd;AAgBO,SAAS,WACd,UACA,QAIA;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,YAAY,EAAE,OAAO;AAAA,EACvB;AACF;","names":[]}
|
package/dist/exports/control.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
postgresAdapterDescriptorMeta
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-VPNRPV63.js";
|
|
4
4
|
|
|
5
5
|
// src/core/control-adapter.ts
|
|
6
6
|
var PostgresControlAdapter = class {
|
|
@@ -235,6 +235,34 @@ var PostgresControlAdapter = class {
|
|
|
235
235
|
indexes
|
|
236
236
|
};
|
|
237
237
|
}
|
|
238
|
+
const enumsResult = await driver.query(
|
|
239
|
+
`SELECT
|
|
240
|
+
t.typname AS enum_name,
|
|
241
|
+
e.enumlabel AS enum_value,
|
|
242
|
+
e.enumsortorder AS sort_order
|
|
243
|
+
FROM pg_type t
|
|
244
|
+
JOIN pg_enum e ON t.oid = e.enumtypid
|
|
245
|
+
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
246
|
+
WHERE n.nspname = $1
|
|
247
|
+
AND t.typtype = 'e'
|
|
248
|
+
ORDER BY t.typname, e.enumsortorder`,
|
|
249
|
+
[schema]
|
|
250
|
+
);
|
|
251
|
+
const enums = {};
|
|
252
|
+
for (const row of enumsResult.rows) {
|
|
253
|
+
const existing = enums[row.enum_name];
|
|
254
|
+
if (existing) {
|
|
255
|
+
existing.values.push(row.enum_value);
|
|
256
|
+
} else {
|
|
257
|
+
enums[row.enum_name] = {
|
|
258
|
+
name: row.enum_name,
|
|
259
|
+
values: [row.enum_value]
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (const enumIR of Object.values(enums)) {
|
|
264
|
+
enumIR.values = Object.freeze(enumIR.values);
|
|
265
|
+
}
|
|
238
266
|
const extensionsResult = await driver.query(
|
|
239
267
|
`SELECT extname
|
|
240
268
|
FROM pg_extension
|
|
@@ -250,6 +278,7 @@ var PostgresControlAdapter = class {
|
|
|
250
278
|
};
|
|
251
279
|
return {
|
|
252
280
|
tables,
|
|
281
|
+
...Object.keys(enums).length > 0 ? { enums } : {},
|
|
253
282
|
extensions,
|
|
254
283
|
annotations
|
|
255
284
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/control-adapter.ts","../../src/exports/control.ts"],"sourcesContent":["import type { ControlDriverInstance } from '@prisma-next/core-control-plane/types';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport type {\n PrimaryKey,\n SqlColumnIR,\n SqlForeignKeyIR,\n SqlIndexIR,\n SqlSchemaIR,\n SqlTableIR,\n SqlUniqueIR,\n} from '@prisma-next/sql-schema-ir/types';\n\n/**\n * Postgres control plane adapter for control-plane operations like introspection.\n * Provides target-specific implementations for control-plane domain actions.\n */\nexport class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n /**\n * @deprecated Use targetId instead\n */\n readonly target = 'postgres' as const;\n\n /**\n * Introspects a Postgres database schema and returns a raw SqlSchemaIR.\n *\n * This is a pure schema discovery operation that queries the Postgres catalog\n * and returns the schema structure without type mapping or contract enrichment.\n * Type mapping and enrichment are handled separately by enrichment helpers.\n *\n * @param driver - ControlDriverInstance<'sql', 'postgres'> instance for executing queries\n * @param contractIR - Optional contract IR for contract-guided introspection (filtering, optimization)\n * @param schema - Schema name to introspect (defaults to 'public')\n * @returns Promise resolving to SqlSchemaIR representing the live database schema\n */\n async introspect(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n _contractIR?: unknown,\n schema = 'public',\n ): Promise<SqlSchemaIR> {\n // Query tables\n const tablesResult = await driver.query<{\n table_name: string;\n }>(\n `SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = $1\n AND table_type = 'BASE TABLE'\n ORDER BY table_name`,\n [schema],\n );\n\n const tables: Record<string, SqlTableIR> = {};\n\n for (const tableRow of tablesResult.rows) {\n const tableName = tableRow.table_name;\n\n // Query columns for this table\n const columnsResult = await driver.query<{\n column_name: string;\n data_type: string;\n udt_name: string;\n is_nullable: string;\n character_maximum_length: number | null;\n numeric_precision: number | null;\n numeric_scale: number | null;\n }>(\n `SELECT\n column_name,\n data_type,\n udt_name,\n is_nullable,\n character_maximum_length,\n numeric_precision,\n numeric_scale\n FROM information_schema.columns\n WHERE table_schema = $1\n AND table_name = $2\n ORDER BY ordinal_position`,\n [schema, tableName],\n );\n\n const columns: Record<string, SqlColumnIR> = {};\n for (const colRow of columnsResult.rows) {\n // Build native type string from catalog data\n let nativeType = colRow.udt_name;\n if (colRow.data_type === 'character varying' || colRow.data_type === 'character') {\n if (colRow.character_maximum_length) {\n nativeType = `${colRow.data_type}(${colRow.character_maximum_length})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else if (colRow.data_type === 'numeric' || colRow.data_type === 'decimal') {\n if (colRow.numeric_precision && colRow.numeric_scale !== null) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision},${colRow.numeric_scale})`;\n } else if (colRow.numeric_precision) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else {\n nativeType = colRow.udt_name || colRow.data_type;\n }\n\n columns[colRow.column_name] = {\n name: colRow.column_name,\n nativeType,\n nullable: colRow.is_nullable === 'YES',\n };\n }\n\n // Query primary key\n const pkResult = await driver.query<{\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'PRIMARY KEY'\n ORDER BY kcu.ordinal_position`,\n [schema, tableName],\n );\n\n const primaryKeyColumns = pkResult.rows\n .sort((a, b) => a.ordinal_position - b.ordinal_position)\n .map((row) => row.column_name);\n const primaryKey: PrimaryKey | undefined =\n primaryKeyColumns.length > 0\n ? {\n columns: primaryKeyColumns,\n ...(pkResult.rows[0]?.constraint_name\n ? { name: pkResult.rows[0].constraint_name }\n : {}),\n }\n : undefined;\n\n // Query foreign keys\n const fkResult = await driver.query<{\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n referenced_table_schema: string;\n referenced_table_name: string;\n referenced_column_name: string;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position,\n ccu.table_schema AS referenced_table_schema,\n ccu.table_name AS referenced_table_name,\n ccu.column_name AS referenced_column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n JOIN information_schema.constraint_column_usage ccu\n ON ccu.constraint_name = tc.constraint_name\n AND ccu.table_schema = tc.table_schema\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'FOREIGN KEY'\n ORDER BY tc.constraint_name, kcu.ordinal_position`,\n [schema, tableName],\n );\n\n const foreignKeysMap = new Map<\n string,\n {\n columns: string[];\n referencedTable: string;\n referencedColumns: string[];\n name: string;\n }\n >();\n for (const fkRow of fkResult.rows) {\n const existing = foreignKeysMap.get(fkRow.constraint_name);\n if (existing) {\n // Multi-column FK - add column\n existing.columns.push(fkRow.column_name);\n existing.referencedColumns.push(fkRow.referenced_column_name);\n } else {\n foreignKeysMap.set(fkRow.constraint_name, {\n columns: [fkRow.column_name],\n referencedTable: fkRow.referenced_table_name,\n referencedColumns: [fkRow.referenced_column_name],\n name: fkRow.constraint_name,\n });\n }\n }\n const foreignKeys: readonly SqlForeignKeyIR[] = Array.from(foreignKeysMap.values()).map(\n (fk) => ({\n columns: Object.freeze([...fk.columns]) as readonly string[],\n referencedTable: fk.referencedTable,\n referencedColumns: Object.freeze([...fk.referencedColumns]) as readonly string[],\n name: fk.name,\n }),\n );\n\n // Query unique constraints (excluding PK)\n const uniqueResult = await driver.query<{\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'UNIQUE'\n AND tc.constraint_name NOT IN (\n SELECT constraint_name\n FROM information_schema.table_constraints\n WHERE table_schema = $1\n AND table_name = $2\n AND constraint_type = 'PRIMARY KEY'\n )\n ORDER BY tc.constraint_name, kcu.ordinal_position`,\n [schema, tableName],\n );\n\n const uniquesMap = new Map<\n string,\n {\n columns: string[];\n name: string;\n }\n >();\n for (const uniqueRow of uniqueResult.rows) {\n const existing = uniquesMap.get(uniqueRow.constraint_name);\n if (existing) {\n existing.columns.push(uniqueRow.column_name);\n } else {\n uniquesMap.set(uniqueRow.constraint_name, {\n columns: [uniqueRow.column_name],\n name: uniqueRow.constraint_name,\n });\n }\n }\n const uniques: readonly SqlUniqueIR[] = Array.from(uniquesMap.values()).map((uq) => ({\n columns: Object.freeze([...uq.columns]) as readonly string[],\n name: uq.name,\n }));\n\n // Query indexes (excluding PK and unique constraints)\n const indexResult = await driver.query<{\n indexname: string;\n indisunique: boolean;\n attname: string;\n attnum: number;\n }>(\n `SELECT\n i.indexname,\n ix.indisunique,\n a.attname,\n a.attnum\n FROM pg_indexes i\n JOIN pg_class ic ON ic.relname = i.indexname\n JOIN pg_namespace ins ON ins.oid = ic.relnamespace AND ins.nspname = $1\n JOIN pg_index ix ON ix.indexrelid = ic.oid\n JOIN pg_class t ON t.oid = ix.indrelid\n JOIN pg_namespace tn ON tn.oid = t.relnamespace AND tn.nspname = $1\n LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND a.attnum > 0\n WHERE i.schemaname = $1\n AND i.tablename = $2\n AND NOT EXISTS (\n SELECT 1\n FROM information_schema.table_constraints tc\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_name = i.indexname\n )\n ORDER BY i.indexname, a.attnum`,\n [schema, tableName],\n );\n\n const indexesMap = new Map<\n string,\n {\n columns: string[];\n name: string;\n unique: boolean;\n }\n >();\n for (const idxRow of indexResult.rows) {\n // Skip rows where attname is null (system columns or invalid attnum)\n if (!idxRow.attname) {\n continue;\n }\n const existing = indexesMap.get(idxRow.indexname);\n if (existing) {\n existing.columns.push(idxRow.attname);\n } else {\n indexesMap.set(idxRow.indexname, {\n columns: [idxRow.attname],\n name: idxRow.indexname,\n unique: idxRow.indisunique,\n });\n }\n }\n const indexes: readonly SqlIndexIR[] = Array.from(indexesMap.values()).map((idx) => ({\n columns: Object.freeze([...idx.columns]) as readonly string[],\n name: idx.name,\n unique: idx.unique,\n }));\n\n tables[tableName] = {\n name: tableName,\n columns,\n ...(primaryKey ? { primaryKey } : {}),\n foreignKeys,\n uniques,\n indexes,\n };\n }\n\n // Query extensions\n const extensionsResult = await driver.query<{\n extname: string;\n }>(\n `SELECT extname\n FROM pg_extension\n ORDER BY extname`,\n [],\n );\n\n const extensions = extensionsResult.rows.map((row) => row.extname);\n\n // Build annotations with Postgres-specific metadata\n const annotations = {\n pg: {\n schema,\n version: await this.getPostgresVersion(driver),\n },\n };\n\n return {\n tables,\n extensions,\n annotations,\n };\n }\n\n /**\n * Gets the Postgres version from the database.\n */\n private async getPostgresVersion(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n ): Promise<string> {\n const result = await driver.query<{ version: string }>('SELECT version() AS version', []);\n const versionString = result.rows[0]?.version ?? '';\n // Extract version number from \"PostgreSQL 15.1 ...\" format\n const match = versionString.match(/PostgreSQL (\\d+\\.\\d+)/);\n return match?.[1] ?? 'unknown';\n }\n}\n","import type { ControlAdapterDescriptor } from '@prisma-next/core-control-plane/types';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { PostgresControlAdapter } from '../core/control-adapter';\nimport { postgresAdapterDescriptorMeta } from '../core/descriptor-meta';\n\n/**\n * Postgres adapter descriptor for CLI config.\n */\nconst postgresAdapterDescriptor: ControlAdapterDescriptor<\n 'sql',\n 'postgres',\n SqlControlAdapter<'postgres'>\n> = {\n ...postgresAdapterDescriptorMeta,\n create(): SqlControlAdapter<'postgres'> {\n return new PostgresControlAdapter();\n },\n};\n\nexport default postgresAdapterDescriptor;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/control-adapter.ts","../../src/exports/control.ts"],"sourcesContent":["import type { ControlDriverInstance } from '@prisma-next/core-control-plane/types';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport type {\n PrimaryKey,\n SqlColumnIR,\n SqlEnumIR,\n SqlForeignKeyIR,\n SqlIndexIR,\n SqlSchemaIR,\n SqlTableIR,\n SqlUniqueIR,\n} from '@prisma-next/sql-schema-ir/types';\n\n/**\n * Postgres control plane adapter for control-plane operations like introspection.\n * Provides target-specific implementations for control-plane domain actions.\n */\nexport class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n /**\n * @deprecated Use targetId instead\n */\n readonly target = 'postgres' as const;\n\n /**\n * Introspects a Postgres database schema and returns a raw SqlSchemaIR.\n *\n * This is a pure schema discovery operation that queries the Postgres catalog\n * and returns the schema structure without type mapping or contract enrichment.\n * Type mapping and enrichment are handled separately by enrichment helpers.\n *\n * @param driver - ControlDriverInstance<'sql', 'postgres'> instance for executing queries\n * @param contractIR - Optional contract IR for contract-guided introspection (filtering, optimization)\n * @param schema - Schema name to introspect (defaults to 'public')\n * @returns Promise resolving to SqlSchemaIR representing the live database schema\n */\n async introspect(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n _contractIR?: unknown,\n schema = 'public',\n ): Promise<SqlSchemaIR> {\n // Query tables\n const tablesResult = await driver.query<{\n table_name: string;\n }>(\n `SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = $1\n AND table_type = 'BASE TABLE'\n ORDER BY table_name`,\n [schema],\n );\n\n const tables: Record<string, SqlTableIR> = {};\n\n for (const tableRow of tablesResult.rows) {\n const tableName = tableRow.table_name;\n\n // Query columns for this table\n const columnsResult = await driver.query<{\n column_name: string;\n data_type: string;\n udt_name: string;\n is_nullable: string;\n character_maximum_length: number | null;\n numeric_precision: number | null;\n numeric_scale: number | null;\n }>(\n `SELECT\n column_name,\n data_type,\n udt_name,\n is_nullable,\n character_maximum_length,\n numeric_precision,\n numeric_scale\n FROM information_schema.columns\n WHERE table_schema = $1\n AND table_name = $2\n ORDER BY ordinal_position`,\n [schema, tableName],\n );\n\n const columns: Record<string, SqlColumnIR> = {};\n for (const colRow of columnsResult.rows) {\n // Build native type string from catalog data\n let nativeType = colRow.udt_name;\n if (colRow.data_type === 'character varying' || colRow.data_type === 'character') {\n if (colRow.character_maximum_length) {\n nativeType = `${colRow.data_type}(${colRow.character_maximum_length})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else if (colRow.data_type === 'numeric' || colRow.data_type === 'decimal') {\n if (colRow.numeric_precision && colRow.numeric_scale !== null) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision},${colRow.numeric_scale})`;\n } else if (colRow.numeric_precision) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else {\n nativeType = colRow.udt_name || colRow.data_type;\n }\n\n columns[colRow.column_name] = {\n name: colRow.column_name,\n nativeType,\n nullable: colRow.is_nullable === 'YES',\n };\n }\n\n // Query primary key\n const pkResult = await driver.query<{\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'PRIMARY KEY'\n ORDER BY kcu.ordinal_position`,\n [schema, tableName],\n );\n\n const primaryKeyColumns = pkResult.rows\n .sort((a, b) => a.ordinal_position - b.ordinal_position)\n .map((row) => row.column_name);\n const primaryKey: PrimaryKey | undefined =\n primaryKeyColumns.length > 0\n ? {\n columns: primaryKeyColumns,\n ...(pkResult.rows[0]?.constraint_name\n ? { name: pkResult.rows[0].constraint_name }\n : {}),\n }\n : undefined;\n\n // Query foreign keys\n const fkResult = await driver.query<{\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n referenced_table_schema: string;\n referenced_table_name: string;\n referenced_column_name: string;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position,\n ccu.table_schema AS referenced_table_schema,\n ccu.table_name AS referenced_table_name,\n ccu.column_name AS referenced_column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n JOIN information_schema.constraint_column_usage ccu\n ON ccu.constraint_name = tc.constraint_name\n AND ccu.table_schema = tc.table_schema\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'FOREIGN KEY'\n ORDER BY tc.constraint_name, kcu.ordinal_position`,\n [schema, tableName],\n );\n\n const foreignKeysMap = new Map<\n string,\n {\n columns: string[];\n referencedTable: string;\n referencedColumns: string[];\n name: string;\n }\n >();\n for (const fkRow of fkResult.rows) {\n const existing = foreignKeysMap.get(fkRow.constraint_name);\n if (existing) {\n // Multi-column FK - add column\n existing.columns.push(fkRow.column_name);\n existing.referencedColumns.push(fkRow.referenced_column_name);\n } else {\n foreignKeysMap.set(fkRow.constraint_name, {\n columns: [fkRow.column_name],\n referencedTable: fkRow.referenced_table_name,\n referencedColumns: [fkRow.referenced_column_name],\n name: fkRow.constraint_name,\n });\n }\n }\n const foreignKeys: readonly SqlForeignKeyIR[] = Array.from(foreignKeysMap.values()).map(\n (fk) => ({\n columns: Object.freeze([...fk.columns]) as readonly string[],\n referencedTable: fk.referencedTable,\n referencedColumns: Object.freeze([...fk.referencedColumns]) as readonly string[],\n name: fk.name,\n }),\n );\n\n // Query unique constraints (excluding PK)\n const uniqueResult = await driver.query<{\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_type = 'UNIQUE'\n AND tc.constraint_name NOT IN (\n SELECT constraint_name\n FROM information_schema.table_constraints\n WHERE table_schema = $1\n AND table_name = $2\n AND constraint_type = 'PRIMARY KEY'\n )\n ORDER BY tc.constraint_name, kcu.ordinal_position`,\n [schema, tableName],\n );\n\n const uniquesMap = new Map<\n string,\n {\n columns: string[];\n name: string;\n }\n >();\n for (const uniqueRow of uniqueResult.rows) {\n const existing = uniquesMap.get(uniqueRow.constraint_name);\n if (existing) {\n existing.columns.push(uniqueRow.column_name);\n } else {\n uniquesMap.set(uniqueRow.constraint_name, {\n columns: [uniqueRow.column_name],\n name: uniqueRow.constraint_name,\n });\n }\n }\n const uniques: readonly SqlUniqueIR[] = Array.from(uniquesMap.values()).map((uq) => ({\n columns: Object.freeze([...uq.columns]) as readonly string[],\n name: uq.name,\n }));\n\n // Query indexes (excluding PK and unique constraints)\n const indexResult = await driver.query<{\n indexname: string;\n indisunique: boolean;\n attname: string;\n attnum: number;\n }>(\n `SELECT\n i.indexname,\n ix.indisunique,\n a.attname,\n a.attnum\n FROM pg_indexes i\n JOIN pg_class ic ON ic.relname = i.indexname\n JOIN pg_namespace ins ON ins.oid = ic.relnamespace AND ins.nspname = $1\n JOIN pg_index ix ON ix.indexrelid = ic.oid\n JOIN pg_class t ON t.oid = ix.indrelid\n JOIN pg_namespace tn ON tn.oid = t.relnamespace AND tn.nspname = $1\n LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND a.attnum > 0\n WHERE i.schemaname = $1\n AND i.tablename = $2\n AND NOT EXISTS (\n SELECT 1\n FROM information_schema.table_constraints tc\n WHERE tc.table_schema = $1\n AND tc.table_name = $2\n AND tc.constraint_name = i.indexname\n )\n ORDER BY i.indexname, a.attnum`,\n [schema, tableName],\n );\n\n const indexesMap = new Map<\n string,\n {\n columns: string[];\n name: string;\n unique: boolean;\n }\n >();\n for (const idxRow of indexResult.rows) {\n // Skip rows where attname is null (system columns or invalid attnum)\n if (!idxRow.attname) {\n continue;\n }\n const existing = indexesMap.get(idxRow.indexname);\n if (existing) {\n existing.columns.push(idxRow.attname);\n } else {\n indexesMap.set(idxRow.indexname, {\n columns: [idxRow.attname],\n name: idxRow.indexname,\n unique: idxRow.indisunique,\n });\n }\n }\n const indexes: readonly SqlIndexIR[] = Array.from(indexesMap.values()).map((idx) => ({\n columns: Object.freeze([...idx.columns]) as readonly string[],\n name: idx.name,\n unique: idx.unique,\n }));\n\n tables[tableName] = {\n name: tableName,\n columns,\n ...(primaryKey ? { primaryKey } : {}),\n foreignKeys,\n uniques,\n indexes,\n };\n }\n\n // Query enum types\n const enumsResult = await driver.query<{\n enum_name: string;\n enum_value: string;\n sort_order: number;\n }>(\n `SELECT\n t.typname AS enum_name,\n e.enumlabel AS enum_value,\n e.enumsortorder AS sort_order\n FROM pg_type t\n JOIN pg_enum e ON t.oid = e.enumtypid\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname = $1\n AND t.typtype = 'e'\n ORDER BY t.typname, e.enumsortorder`,\n [schema],\n );\n\n // Group enum values by enum name (rows already ordered by t.typname, e.enumsortorder)\n const enums: Record<string, SqlEnumIR> = {};\n for (const row of enumsResult.rows) {\n const existing = enums[row.enum_name];\n if (existing) {\n // Add value to existing enum (values are mutable during construction)\n (existing.values as string[]).push(row.enum_value);\n } else {\n enums[row.enum_name] = {\n name: row.enum_name,\n values: [row.enum_value],\n };\n }\n }\n // Freeze values arrays for immutability\n for (const enumIR of Object.values(enums)) {\n (enumIR as { values: readonly string[] }).values = Object.freeze(enumIR.values);\n }\n\n // Query extensions\n const extensionsResult = await driver.query<{\n extname: string;\n }>(\n `SELECT extname\n FROM pg_extension\n ORDER BY extname`,\n [],\n );\n\n const extensions = extensionsResult.rows.map((row) => row.extname);\n\n // Build annotations with Postgres-specific metadata\n const annotations = {\n pg: {\n schema,\n version: await this.getPostgresVersion(driver),\n },\n };\n\n return {\n tables,\n ...(Object.keys(enums).length > 0 ? { enums } : {}),\n extensions,\n annotations,\n };\n }\n\n /**\n * Gets the Postgres version from the database.\n */\n private async getPostgresVersion(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n ): Promise<string> {\n const result = await driver.query<{ version: string }>('SELECT version() AS version', []);\n const versionString = result.rows[0]?.version ?? '';\n // Extract version number from \"PostgreSQL 15.1 ...\" format\n const match = versionString.match(/PostgreSQL (\\d+\\.\\d+)/);\n return match?.[1] ?? 'unknown';\n }\n}\n","import type { ControlAdapterDescriptor } from '@prisma-next/core-control-plane/types';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { PostgresControlAdapter } from '../core/control-adapter';\nimport { postgresAdapterDescriptorMeta } from '../core/descriptor-meta';\n\n/**\n * Postgres adapter descriptor for CLI config.\n */\nconst postgresAdapterDescriptor: ControlAdapterDescriptor<\n 'sql',\n 'postgres',\n SqlControlAdapter<'postgres'>\n> = {\n ...postgresAdapterDescriptorMeta,\n create(): SqlControlAdapter<'postgres'> {\n return new PostgresControlAdapter();\n },\n};\n\nexport default postgresAdapterDescriptor;\n"],"mappings":"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","names":[]}
|
package/dist/exports/runtime.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createPostgresAdapter
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-KJMTKEE7.js";
|
|
4
|
+
import "../chunk-VJEVMBDI.js";
|
|
5
5
|
import {
|
|
6
6
|
postgresAdapterDescriptorMeta
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-VPNRPV63.js";
|
|
8
8
|
|
|
9
9
|
// src/exports/runtime.ts
|
|
10
10
|
var postgresRuntimeAdapterDescriptor = {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extended codec type definitions for Postgres adapter.
|
|
3
|
+
*
|
|
4
|
+
* This file exports type-only definitions for codec input/output types,
|
|
5
|
+
* including parameterized output types for enums.
|
|
6
|
+
*
|
|
7
|
+
* Runtime codec implementations are provided by the adapter's codec registry.
|
|
8
|
+
*/
|
|
9
|
+
import type { CodecTypes as CoreCodecTypes } from '../core/codecs';
|
|
10
|
+
/**
|
|
11
|
+
* Helper type that converts a readonly array of string literals to a union type.
|
|
12
|
+
* e.g., readonly ['USER', 'ADMIN'] -> 'USER' | 'ADMIN'
|
|
13
|
+
*/
|
|
14
|
+
type ArrayToUnion<T extends readonly string[]> = T[number];
|
|
15
|
+
/**
|
|
16
|
+
* Codec types for Postgres adapter with parameterized enum support.
|
|
17
|
+
*
|
|
18
|
+
* - Base scalar types use their standard output types.
|
|
19
|
+
* - `pg/enum@1` uses `parameterizedOutput` to compute the union type from `typeParams.values`.
|
|
20
|
+
*/
|
|
21
|
+
export type CodecTypes = CoreCodecTypes & {
|
|
22
|
+
readonly 'pg/enum@1': CoreCodecTypes['pg/enum@1'] & {
|
|
23
|
+
/**
|
|
24
|
+
* Computes the enum union type from typeParams.values.
|
|
25
|
+
* e.g., { values: readonly ['USER', 'ADMIN'] } -> 'USER' | 'ADMIN'
|
|
26
|
+
*/
|
|
27
|
+
readonly parameterizedOutput: <P extends {
|
|
28
|
+
readonly values: readonly string[];
|
|
29
|
+
}>(params: P) => P extends {
|
|
30
|
+
readonly values: infer V extends readonly string[];
|
|
31
|
+
} ? ArrayToUnion<V> : string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=codec-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec-types.d.ts","sourceRoot":"","sources":["../../src/types/codec-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEnE;;;GAGG;AACH,KAAK,YAAY,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC,WAAW,CAAC,GAAG;QAClD;;;WAGG;QACH,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,SAAS;YAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,EAC7E,MAAM,EAAE,CAAC,KACN,CAAC,SAAS;YAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,SAAS,MAAM,EAAE,CAAA;SAAE,GACjE,YAAY,CAAC,CAAC,CAAC,GACf,MAAM,CAAC;KACZ,CAAC;CACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/adapter-postgres",
|
|
3
|
-
"version": "0.3.0-pr.
|
|
3
|
+
"version": "0.3.0-pr.110.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"files": [
|
|
@@ -9,17 +9,17 @@
|
|
|
9
9
|
],
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"arktype": "^2.0.0",
|
|
12
|
-
"@prisma-next/cli": "0.3.0-pr.
|
|
13
|
-
"@prisma-next/contract": "0.3.0-pr.
|
|
14
|
-
"@prisma-next/contract-authoring": "0.3.0-pr.
|
|
15
|
-
"@prisma-next/core-control-plane": "0.3.0-pr.
|
|
16
|
-
"@prisma-next/core-execution-plane": "0.3.0-pr.
|
|
17
|
-
"@prisma-next/family-sql": "0.3.0-pr.
|
|
18
|
-
"@prisma-next/sql-contract": "0.3.0-pr.
|
|
19
|
-
"@prisma-next/sql-contract-ts": "0.3.0-pr.
|
|
20
|
-
"@prisma-next/sql-operations": "0.3.0-pr.
|
|
21
|
-
"@prisma-next/sql-relational-core": "0.3.0-pr.
|
|
22
|
-
"@prisma-next/sql-schema-ir": "0.3.0-pr.
|
|
12
|
+
"@prisma-next/cli": "0.3.0-pr.110.1",
|
|
13
|
+
"@prisma-next/contract": "0.3.0-pr.110.1",
|
|
14
|
+
"@prisma-next/contract-authoring": "0.3.0-pr.110.1",
|
|
15
|
+
"@prisma-next/core-control-plane": "0.3.0-pr.110.1",
|
|
16
|
+
"@prisma-next/core-execution-plane": "0.3.0-pr.110.1",
|
|
17
|
+
"@prisma-next/family-sql": "0.3.0-pr.110.1",
|
|
18
|
+
"@prisma-next/sql-contract": "0.3.0-pr.110.1",
|
|
19
|
+
"@prisma-next/sql-contract-ts": "0.3.0-pr.110.1",
|
|
20
|
+
"@prisma-next/sql-operations": "0.3.0-pr.110.1",
|
|
21
|
+
"@prisma-next/sql-relational-core": "0.3.0-pr.110.1",
|
|
22
|
+
"@prisma-next/sql-schema-ir": "0.3.0-pr.110.1"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"tsup": "8.5.1",
|
package/src/core/codecs.ts
CHANGED
|
@@ -174,6 +174,32 @@ const pgBoolCodec = codec<'pg/bool@1', boolean, boolean>({
|
|
|
174
174
|
},
|
|
175
175
|
});
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Generic codec for Postgres enum types.
|
|
179
|
+
* Enums are wire-encoded as strings and JS-typed as strings.
|
|
180
|
+
* The specific enum type name is provided via nativeType in the storage column.
|
|
181
|
+
*
|
|
182
|
+
* Type safety for enum values is provided at compile time via parameterizedOutput
|
|
183
|
+
* which derives the union type from typeParams.values in the contract.
|
|
184
|
+
*/
|
|
185
|
+
const pgEnumCodec = codec<'pg/enum@1', string, string>({
|
|
186
|
+
typeId: 'pg/enum@1',
|
|
187
|
+
targetTypes: [], // Enum types are dynamically determined by nativeType
|
|
188
|
+
encode: (value) => value,
|
|
189
|
+
decode: (wire) => wire,
|
|
190
|
+
meta: {
|
|
191
|
+
db: {
|
|
192
|
+
sql: {
|
|
193
|
+
postgres: {
|
|
194
|
+
// The actual enum type name is specified per-column via nativeType.
|
|
195
|
+
// This placeholder indicates it's an enum without specifying which one.
|
|
196
|
+
nativeType: 'enum',
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
177
203
|
// Build codec definitions using the builder DSL
|
|
178
204
|
const codecs = defineCodecs()
|
|
179
205
|
.add('text', pgTextCodec)
|
|
@@ -184,7 +210,8 @@ const codecs = defineCodecs()
|
|
|
184
210
|
.add('float8', pgFloat8Codec)
|
|
185
211
|
.add('timestamp', pgTimestampCodec)
|
|
186
212
|
.add('timestamptz', pgTimestamptzCodec)
|
|
187
|
-
.add('bool', pgBoolCodec)
|
|
213
|
+
.add('bool', pgBoolCodec)
|
|
214
|
+
.add('enum', pgEnumCodec);
|
|
188
215
|
|
|
189
216
|
// Export derived structures directly from codecs builder
|
|
190
217
|
export const codecDefinitions = codecs.codecDefinitions;
|
|
@@ -3,6 +3,7 @@ import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter'
|
|
|
3
3
|
import type {
|
|
4
4
|
PrimaryKey,
|
|
5
5
|
SqlColumnIR,
|
|
6
|
+
SqlEnumIR,
|
|
6
7
|
SqlForeignKeyIR,
|
|
7
8
|
SqlIndexIR,
|
|
8
9
|
SqlSchemaIR,
|
|
@@ -333,6 +334,44 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
|
|
|
333
334
|
};
|
|
334
335
|
}
|
|
335
336
|
|
|
337
|
+
// Query enum types
|
|
338
|
+
const enumsResult = await driver.query<{
|
|
339
|
+
enum_name: string;
|
|
340
|
+
enum_value: string;
|
|
341
|
+
sort_order: number;
|
|
342
|
+
}>(
|
|
343
|
+
`SELECT
|
|
344
|
+
t.typname AS enum_name,
|
|
345
|
+
e.enumlabel AS enum_value,
|
|
346
|
+
e.enumsortorder AS sort_order
|
|
347
|
+
FROM pg_type t
|
|
348
|
+
JOIN pg_enum e ON t.oid = e.enumtypid
|
|
349
|
+
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
350
|
+
WHERE n.nspname = $1
|
|
351
|
+
AND t.typtype = 'e'
|
|
352
|
+
ORDER BY t.typname, e.enumsortorder`,
|
|
353
|
+
[schema],
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// Group enum values by enum name (rows already ordered by t.typname, e.enumsortorder)
|
|
357
|
+
const enums: Record<string, SqlEnumIR> = {};
|
|
358
|
+
for (const row of enumsResult.rows) {
|
|
359
|
+
const existing = enums[row.enum_name];
|
|
360
|
+
if (existing) {
|
|
361
|
+
// Add value to existing enum (values are mutable during construction)
|
|
362
|
+
(existing.values as string[]).push(row.enum_value);
|
|
363
|
+
} else {
|
|
364
|
+
enums[row.enum_name] = {
|
|
365
|
+
name: row.enum_name,
|
|
366
|
+
values: [row.enum_value],
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// Freeze values arrays for immutability
|
|
371
|
+
for (const enumIR of Object.values(enums)) {
|
|
372
|
+
(enumIR as { values: readonly string[] }).values = Object.freeze(enumIR.values);
|
|
373
|
+
}
|
|
374
|
+
|
|
336
375
|
// Query extensions
|
|
337
376
|
const extensionsResult = await driver.query<{
|
|
338
377
|
extname: string;
|
|
@@ -355,6 +394,7 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
|
|
|
355
394
|
|
|
356
395
|
return {
|
|
357
396
|
tables,
|
|
397
|
+
...(Object.keys(enums).length > 0 ? { enums } : {}),
|
|
358
398
|
extensions,
|
|
359
399
|
annotations,
|
|
360
400
|
};
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameterized renderer for enum types.
|
|
3
|
+
* Converts typeParams.values array to a union type string.
|
|
4
|
+
* e.g., { values: ['USER', 'ADMIN'] } -> '"USER" | "ADMIN"'
|
|
5
|
+
*
|
|
6
|
+
* Uses JSON.stringify to properly escape special characters in enum values
|
|
7
|
+
* (e.g., quotes, backslashes) ensuring valid TypeScript string literals.
|
|
8
|
+
*/
|
|
9
|
+
function renderEnumType(params: Record<string, unknown>): string {
|
|
10
|
+
const values = params['values'];
|
|
11
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
12
|
+
return 'string';
|
|
13
|
+
}
|
|
14
|
+
return values.map((v) => JSON.stringify(String(v))).join(' | ');
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
export const postgresAdapterDescriptorMeta = {
|
|
2
18
|
kind: 'adapter',
|
|
3
19
|
familyId: 'sql',
|
|
@@ -11,6 +27,7 @@ export const postgresAdapterDescriptorMeta = {
|
|
|
11
27
|
lateral: true,
|
|
12
28
|
jsonAgg: true,
|
|
13
29
|
returning: true,
|
|
30
|
+
nativeEnums: true,
|
|
14
31
|
},
|
|
15
32
|
},
|
|
16
33
|
types: {
|
|
@@ -20,6 +37,9 @@ export const postgresAdapterDescriptorMeta = {
|
|
|
20
37
|
named: 'CodecTypes',
|
|
21
38
|
alias: 'PgTypes',
|
|
22
39
|
},
|
|
40
|
+
parameterized: {
|
|
41
|
+
'pg/enum@1': renderEnumType,
|
|
42
|
+
},
|
|
23
43
|
},
|
|
24
44
|
storage: [
|
|
25
45
|
{ typeId: 'pg/text@1', familyId: 'sql', targetId: 'postgres', nativeType: 'text' },
|
|
@@ -36,6 +56,7 @@ export const postgresAdapterDescriptorMeta = {
|
|
|
36
56
|
nativeType: 'timestamptz',
|
|
37
57
|
},
|
|
38
58
|
{ typeId: 'pg/bool@1', familyId: 'sql', targetId: 'postgres', nativeType: 'bool' },
|
|
59
|
+
{ typeId: 'pg/enum@1', familyId: 'sql', targetId: 'postgres', nativeType: 'enum' },
|
|
39
60
|
],
|
|
40
61
|
},
|
|
41
62
|
} as const;
|
|
@@ -51,3 +51,31 @@ export const boolColumn: ColumnTypeDescriptor = {
|
|
|
51
51
|
codecId: 'pg/bool@1',
|
|
52
52
|
nativeType: 'bool',
|
|
53
53
|
} as const;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Factory for creating enum column descriptors.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* .column('role', { type: enumColumn('Role', ['USER', 'ADMIN', 'MODERATOR'] as const), nullable: false })
|
|
61
|
+
* // Produces: nativeType: 'Role', codecId: 'pg/enum@1', typeParams: { values: ['USER', 'ADMIN', 'MODERATOR'] }
|
|
62
|
+
* // TypeScript type: 'USER' | 'ADMIN' | 'MODERATOR'
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @param enumName - The name of the enum type in the database (e.g., 'Role', 'Status')
|
|
66
|
+
* @param values - The ordered list of valid enum values as a const tuple
|
|
67
|
+
* @returns A column type descriptor with `typeParams.values` for union type inference
|
|
68
|
+
*/
|
|
69
|
+
export function enumColumn<Name extends string, Values extends readonly string[]>(
|
|
70
|
+
enumName: Name,
|
|
71
|
+
values: Values,
|
|
72
|
+
): ColumnTypeDescriptor & {
|
|
73
|
+
readonly nativeType: Name;
|
|
74
|
+
readonly typeParams: { readonly values: Values };
|
|
75
|
+
} {
|
|
76
|
+
return {
|
|
77
|
+
codecId: 'pg/enum@1',
|
|
78
|
+
nativeType: enumName,
|
|
79
|
+
typeParams: { values },
|
|
80
|
+
} as const;
|
|
81
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extended codec type definitions for Postgres adapter.
|
|
3
|
+
*
|
|
4
|
+
* This file exports type-only definitions for codec input/output types,
|
|
5
|
+
* including parameterized output types for enums.
|
|
6
|
+
*
|
|
7
|
+
* Runtime codec implementations are provided by the adapter's codec registry.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { CodecTypes as CoreCodecTypes } from '../core/codecs';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Helper type that converts a readonly array of string literals to a union type.
|
|
14
|
+
* e.g., readonly ['USER', 'ADMIN'] -> 'USER' | 'ADMIN'
|
|
15
|
+
*/
|
|
16
|
+
type ArrayToUnion<T extends readonly string[]> = T[number];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Codec types for Postgres adapter with parameterized enum support.
|
|
20
|
+
*
|
|
21
|
+
* - Base scalar types use their standard output types.
|
|
22
|
+
* - `pg/enum@1` uses `parameterizedOutput` to compute the union type from `typeParams.values`.
|
|
23
|
+
*/
|
|
24
|
+
export type CodecTypes = CoreCodecTypes & {
|
|
25
|
+
readonly 'pg/enum@1': CoreCodecTypes['pg/enum@1'] & {
|
|
26
|
+
/**
|
|
27
|
+
* Computes the enum union type from typeParams.values.
|
|
28
|
+
* e.g., { values: readonly ['USER', 'ADMIN'] } -> 'USER' | 'ADMIN'
|
|
29
|
+
*/
|
|
30
|
+
readonly parameterizedOutput: <P extends { readonly values: readonly string[] }>(
|
|
31
|
+
params: P,
|
|
32
|
+
) => P extends { readonly values: infer V extends readonly string[] }
|
|
33
|
+
? ArrayToUnion<V>
|
|
34
|
+
: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/descriptor-meta.ts"],"sourcesContent":["export const postgresAdapterDescriptorMeta = {\n kind: 'adapter',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n },\n },\n types: {\n codecTypes: {\n import: {\n package: '@prisma-next/adapter-postgres/codec-types',\n named: 'CodecTypes',\n alias: 'PgTypes',\n },\n },\n storage: [\n { typeId: 'pg/text@1', familyId: 'sql', targetId: 'postgres', nativeType: 'text' },\n { typeId: 'pg/int4@1', familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: 'pg/int2@1', familyId: 'sql', targetId: 'postgres', nativeType: 'int2' },\n { typeId: 'pg/int8@1', familyId: 'sql', targetId: 'postgres', nativeType: 'int8' },\n { typeId: 'pg/float4@1', familyId: 'sql', targetId: 'postgres', nativeType: 'float4' },\n { typeId: 'pg/float8@1', familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: 'pg/timestamp@1', familyId: 'sql', targetId: 'postgres', nativeType: 'timestamp' },\n {\n typeId: 'pg/timestamptz@1',\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamptz',\n },\n { typeId: 'pg/bool@1', familyId: 'sql', targetId: 'postgres', nativeType: 'bool' },\n ],\n },\n} as const;\n"],"mappings":";AAAO,IAAM,gCAAgC;AAAA,EAC3C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,cAAc;AAAA,IACZ,UAAU;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,SAAS;AAAA,MACT,SAAS;AAAA,MACT,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,YAAY;AAAA,MACV,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,MACjF,EAAE,QAAQ,eAAe,UAAU,OAAO,UAAU,YAAY,YAAY,SAAS;AAAA,MACrF,EAAE,QAAQ,eAAe,UAAU,OAAO,UAAU,YAAY,YAAY,SAAS;AAAA,MACrF,EAAE,QAAQ,kBAAkB,UAAU,OAAO,UAAU,YAAY,YAAY,YAAY;AAAA,MAC3F;AAAA,QACE,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA,MACA,EAAE,QAAQ,aAAa,UAAU,OAAO,UAAU,YAAY,YAAY,OAAO;AAAA,IACnF;AAAA,EACF;AACF;","names":[]}
|
|
File without changes
|