true-pg 0.2.2 → 0.3.0
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/lib/bin.js +4 -9
- package/lib/extractor/adapter.d.ts +15 -0
- package/lib/extractor/adapter.js +53 -0
- package/lib/extractor/canonicalise.d.ts +64 -0
- package/lib/extractor/canonicalise.js +245 -0
- package/lib/extractor/fetchExtensionItemIds.d.ts +12 -0
- package/lib/extractor/fetchExtensionItemIds.js +43 -0
- package/lib/extractor/fetchTypes.d.ts +4 -0
- package/lib/extractor/fetchTypes.js +65 -0
- package/lib/extractor/index.d.ts +95 -0
- package/lib/extractor/index.js +140 -0
- package/lib/extractor/kinds/composite.d.ts +15 -0
- package/lib/extractor/kinds/composite.js +13 -0
- package/lib/extractor/kinds/domain.d.ts +15 -0
- package/lib/extractor/kinds/domain.js +13 -0
- package/lib/extractor/kinds/enum.d.ts +9 -0
- package/lib/extractor/kinds/enum.js +20 -0
- package/lib/extractor/kinds/function.d.ts +73 -0
- package/lib/extractor/kinds/function.js +179 -0
- package/lib/extractor/kinds/materialized-view.d.ts +17 -0
- package/lib/extractor/kinds/materialized-view.js +64 -0
- package/lib/extractor/kinds/parts/commentMapQueryPart.d.ts +2 -0
- package/lib/extractor/kinds/parts/commentMapQueryPart.js +14 -0
- package/lib/extractor/kinds/parts/indexMapQueryPart.d.ts +2 -0
- package/lib/extractor/kinds/parts/indexMapQueryPart.js +27 -0
- package/lib/extractor/kinds/range.d.ts +15 -0
- package/lib/extractor/kinds/range.js +13 -0
- package/lib/extractor/kinds/table.d.ts +212 -0
- package/lib/extractor/kinds/table.js +217 -0
- package/lib/extractor/kinds/util/parseInlineTable.d.ts +9 -0
- package/lib/extractor/kinds/util/parseInlineTable.js +135 -0
- package/lib/extractor/kinds/util/parseInlineTable.test.d.ts +1 -0
- package/lib/extractor/kinds/util/parseInlineTable.test.js +26 -0
- package/lib/extractor/kinds/view.d.ts +17 -0
- package/lib/extractor/kinds/view.js +63 -0
- package/lib/extractor/pgtype.d.ts +41 -0
- package/lib/extractor/pgtype.js +30 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +38 -28
- package/lib/kysely/builtins.js +6 -4
- package/lib/kysely/index.js +103 -59
- package/lib/types.d.ts +38 -10
- package/lib/types.js +14 -3
- package/lib/util.d.ts +11 -0
- package/lib/util.js +6 -0
- package/lib/zod/builtins.js +11 -9
- package/lib/zod/index.js +107 -60
- package/package.json +3 -4
package/lib/zod/builtins.js
CHANGED
@@ -4,12 +4,11 @@ export const builtins = {
|
|
4
4
|
"pg_catalog.int4": "z.number()",
|
5
5
|
// JS numbers are always floating point, so there is only 53 bits of precision
|
6
6
|
// for the integer part. Thus, storing a 64-bit integer in a JS number will
|
7
|
-
// result in potential data loss.
|
8
|
-
|
9
|
-
"pg_catalog.
|
7
|
+
// result in potential data loss.
|
8
|
+
"pg_catalog.int8": "z.bigint()",
|
9
|
+
"pg_catalog.numeric": "z.bigint()",
|
10
10
|
"pg_catalog.float4": "z.number()",
|
11
11
|
"pg_catalog.float8": "z.number()",
|
12
|
-
"pg_catalog.numeric": "z.string()",
|
13
12
|
"pg_catalog.bool": "z.boolean()",
|
14
13
|
"pg_catalog.json": "z.unknown()",
|
15
14
|
"pg_catalog.jsonb": "z.unknown()",
|
@@ -19,11 +18,11 @@ export const builtins = {
|
|
19
18
|
"pg_catalog.text": "z.string()",
|
20
19
|
"pg_catalog.uuid": "z.string()",
|
21
20
|
"pg_catalog.inet": "z.string()",
|
22
|
-
"pg_catalog.date": "z.date()",
|
23
|
-
"pg_catalog.time": "z.date()",
|
24
|
-
"pg_catalog.timetz": "z.date()",
|
25
|
-
"pg_catalog.timestamp": "z.date()",
|
26
|
-
"pg_catalog.timestamptz": "z.date()",
|
21
|
+
"pg_catalog.date": "z.coerce.date()",
|
22
|
+
"pg_catalog.time": "z.coerce.date()",
|
23
|
+
"pg_catalog.timetz": "z.coerce.date()",
|
24
|
+
"pg_catalog.timestamp": "z.coerce.date()",
|
25
|
+
"pg_catalog.timestamptz": "z.coerce.date()",
|
27
26
|
"pg_catalog.int4range": "z.string()",
|
28
27
|
"pg_catalog.int8range": "z.string()",
|
29
28
|
"pg_catalog.numrange": "z.string()",
|
@@ -32,4 +31,7 @@ export const builtins = {
|
|
32
31
|
"pg_catalog.daterange": "z.string()",
|
33
32
|
"pg_catalog.record": "z.record(z.string(), z.unknown())",
|
34
33
|
"pg_catalog.void": "z.void()",
|
34
|
+
"pg_catalog.bytea": "z.string()",
|
35
|
+
"pg_catalog.vector": "z.number().array()",
|
36
|
+
"pg_catalog.tsvector": "z.string().array()",
|
35
37
|
};
|
package/lib/zod/index.js
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
+
import { FunctionReturnTypeKind, } from "../extractor/index.js";
|
1
2
|
import { allowed_kind_names, createGenerator, Nodes } from "../types.js";
|
2
3
|
import { builtins } from "./builtins.js";
|
3
|
-
import { join } from "../util.js";
|
4
|
-
const isIdentifierInvalid = (str) => {
|
5
|
-
const invalid = str.match(/[^a-zA-Z0-9_]/);
|
6
|
-
return invalid !== null;
|
7
|
-
};
|
4
|
+
import { join, quote, quoteI } from "../util.js";
|
8
5
|
const to_snake_case = (str) => str
|
9
6
|
.replace(/^[^a-zA-Z]+/, "") // remove leading non-alphabetic characters
|
10
7
|
.replace(/[^a-zA-Z0-9]+/g, "_") // replace non-alphanumeric characters with underscores
|
@@ -37,7 +34,7 @@ export const Zod = createGenerator(opts => {
|
|
37
34
|
if (col.generated === "ALWAYS")
|
38
35
|
return "";
|
39
36
|
let out = col.comment ? `/** ${col.comment} */\n\t` : "";
|
40
|
-
out += col.name;
|
37
|
+
out += quoteI(col.name);
|
41
38
|
let type = generator.formatType(col.type);
|
42
39
|
add(imports, col.type);
|
43
40
|
if (col.type.dimensions > 0)
|
@@ -48,7 +45,7 @@ export const Zod = createGenerator(opts => {
|
|
48
45
|
return `\t${out},\n`;
|
49
46
|
};
|
50
47
|
const composite_attribute = (imports, attr) => {
|
51
|
-
let out = attr.name;
|
48
|
+
let out = quoteI(attr.name);
|
52
49
|
out += `: ${generator.formatType(attr.type)}`;
|
53
50
|
add(imports, attr.type);
|
54
51
|
if (attr.type.dimensions > 0)
|
@@ -65,12 +62,15 @@ export const Zod = createGenerator(opts => {
|
|
65
62
|
return to_snake_case(type.name);
|
66
63
|
},
|
67
64
|
formatType(type) {
|
68
|
-
if (type.
|
65
|
+
if (type.kind === FunctionReturnTypeKind.ExistingTable) {
|
66
|
+
return to_snake_case(type.name);
|
67
|
+
}
|
68
|
+
else if (type.schema === "pg_catalog") {
|
69
69
|
const name = type.canonical_name;
|
70
70
|
const format = builtins[name];
|
71
71
|
if (format)
|
72
72
|
return format;
|
73
|
-
opts?.warnings?.push(`Unknown builtin type: ${name}
|
73
|
+
opts?.warnings?.push(`(zod) Unknown builtin type: ${name}. Pass customBuiltinMap to map this type. Defaulting to "z.unknown()".`);
|
74
74
|
return "z.unknown()";
|
75
75
|
}
|
76
76
|
return to_snake_case(type.name);
|
@@ -86,6 +86,28 @@ export const Zod = createGenerator(opts => {
|
|
86
86
|
out += "});";
|
87
87
|
return out;
|
88
88
|
},
|
89
|
+
view(imports, view) {
|
90
|
+
let out = "";
|
91
|
+
if (view.comment)
|
92
|
+
out += `/** ${view.comment} */\n`;
|
93
|
+
zod(imports, "z");
|
94
|
+
out += `export const ${this.formatSchemaType(view)} = z.object({\n`;
|
95
|
+
for (const col of view.columns)
|
96
|
+
out += column(imports, col);
|
97
|
+
out += "});";
|
98
|
+
return out;
|
99
|
+
},
|
100
|
+
materializedView(imports, materializedView) {
|
101
|
+
let out = "";
|
102
|
+
if (materializedView.comment)
|
103
|
+
out += `/** ${materializedView.comment} */\n`;
|
104
|
+
zod(imports, "z");
|
105
|
+
out += `export const ${this.formatSchemaType(materializedView)} = z.object({\n`;
|
106
|
+
for (const col of materializedView.columns)
|
107
|
+
out += column(imports, col);
|
108
|
+
out += "});";
|
109
|
+
return out;
|
110
|
+
},
|
89
111
|
enum(imports, en) {
|
90
112
|
let out = "";
|
91
113
|
if (en.comment)
|
@@ -106,6 +128,18 @@ export const Zod = createGenerator(opts => {
|
|
106
128
|
out += "\n});";
|
107
129
|
return out;
|
108
130
|
},
|
131
|
+
domain(imports, type) {
|
132
|
+
let out = "";
|
133
|
+
out += `export const ${this.formatSchemaType(type)} = ${this.formatType(type.canonical.domain_base_type)};`;
|
134
|
+
zod(imports, "z");
|
135
|
+
return out;
|
136
|
+
},
|
137
|
+
range(imports, type) {
|
138
|
+
let out = "";
|
139
|
+
out += `export const ${this.formatSchemaType(type)} = z.string();`;
|
140
|
+
zod(imports, "z");
|
141
|
+
return out;
|
142
|
+
},
|
109
143
|
function(imports, type) {
|
110
144
|
let out = "export const ";
|
111
145
|
out += this.formatSchemaType(type);
|
@@ -142,17 +176,25 @@ export const Zod = createGenerator(opts => {
|
|
142
176
|
else
|
143
177
|
out += ",\n";
|
144
178
|
out += "\treturnType: ";
|
145
|
-
if (type.returnType.kind ===
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
out +=
|
150
|
-
|
151
|
-
|
152
|
-
out +=
|
153
|
-
|
179
|
+
if (type.returnType.kind === FunctionReturnTypeKind.InlineTable) {
|
180
|
+
if (type.returnType.columns.length === 0)
|
181
|
+
out += "z.void()/* RETURNS TABLE with no columns */";
|
182
|
+
else {
|
183
|
+
out += "z.object({\n";
|
184
|
+
for (const col of type.returnType.columns) {
|
185
|
+
out += `\t\t"${col.name}": `;
|
186
|
+
out += this.formatType(col.type);
|
187
|
+
add(imports, col.type);
|
188
|
+
if (col.type.dimensions > 0)
|
189
|
+
out += ".array()".repeat(col.type.dimensions);
|
190
|
+
out += `,\n`;
|
191
|
+
}
|
192
|
+
out += "\t})";
|
154
193
|
}
|
155
|
-
|
194
|
+
}
|
195
|
+
else if (type.returnType.kind === FunctionReturnTypeKind.ExistingTable) {
|
196
|
+
out += this.formatType(type.returnType);
|
197
|
+
add(imports, type.returnType);
|
156
198
|
}
|
157
199
|
else {
|
158
200
|
out += this.formatType(type.returnType.type);
|
@@ -164,6 +206,7 @@ export const Zod = createGenerator(opts => {
|
|
164
206
|
if (type.returnType.isSet)
|
165
207
|
out += ".array()";
|
166
208
|
out += ",\n};";
|
209
|
+
zod(imports, "z");
|
167
210
|
return out;
|
168
211
|
},
|
169
212
|
schemaKindIndex(schema, kind, main_generator) {
|
@@ -180,10 +223,11 @@ export const Zod = createGenerator(opts => {
|
|
180
223
|
.join("\n");
|
181
224
|
},
|
182
225
|
schemaIndex(schema, main_generator) {
|
183
|
-
|
226
|
+
const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
|
227
|
+
let out = actual_kinds.map(kind => `import * as zod_${kind} from "./${kind}/index.ts";`).join("\n");
|
184
228
|
out += "\n\n";
|
185
229
|
out += `export const ${this.formatSchema(schema.name)} = {\n`;
|
186
|
-
for (const kind of
|
230
|
+
for (const kind of actual_kinds) {
|
187
231
|
const items = schema[kind];
|
188
232
|
if (items.length === 0)
|
189
233
|
continue;
|
@@ -196,9 +240,7 @@ export const Zod = createGenerator(opts => {
|
|
196
240
|
.filter(x => x !== undefined);
|
197
241
|
out += formatted
|
198
242
|
.map(t => {
|
199
|
-
let name = t.name;
|
200
|
-
if (isIdentifierInvalid(name))
|
201
|
-
name = `"${name}"`;
|
243
|
+
let name = quoteI(t.name);
|
202
244
|
return `\t\t${name}: zod_${t.kind}s.${t.formatted},`;
|
203
245
|
})
|
204
246
|
.join("\n");
|
@@ -209,44 +251,49 @@ export const Zod = createGenerator(opts => {
|
|
209
251
|
},
|
210
252
|
fullIndex(schemas, main_generator) {
|
211
253
|
const generator = main_generator ?? this;
|
212
|
-
|
213
|
-
|
254
|
+
const parts = [];
|
255
|
+
parts.push(schemas
|
214
256
|
.map(s => `import { ${generator.formatSchema(s.name)} } from "./${s.name}/index.ts";`)
|
215
|
-
.join("\n");
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
257
|
+
.join("\n"));
|
258
|
+
{
|
259
|
+
let validator = `export const Validators = {\n`;
|
260
|
+
validator += join(schemas.map(schema => {
|
261
|
+
const schema_validators = join(allowed_kind_names.map(kind => {
|
262
|
+
const current = schema[kind];
|
263
|
+
const seen = new Set();
|
264
|
+
const formatted = current
|
265
|
+
.map(each => {
|
266
|
+
const formatted = generator.formatSchemaType(each);
|
267
|
+
// skip clashing names
|
268
|
+
if (seen.has(formatted))
|
269
|
+
return;
|
270
|
+
seen.add(formatted);
|
271
|
+
return { ...each, formatted };
|
272
|
+
})
|
273
|
+
.filter(x => x !== undefined);
|
274
|
+
if (!formatted.length)
|
275
|
+
return "";
|
276
|
+
let out = "";
|
277
|
+
out += "\t// " + kind + "\n";
|
278
|
+
out += join(formatted.map(t => {
|
279
|
+
const isDefault = defaultSchema === schema.name;
|
280
|
+
let qualified = "";
|
281
|
+
if (!isDefault)
|
282
|
+
qualified = schema.name + "." + t.name;
|
283
|
+
else
|
284
|
+
qualified = t.name;
|
285
|
+
qualified = quoteI(qualified);
|
286
|
+
return `\t${qualified}: ${this.formatSchema(schema.name)}[${quote(t.kind + "s")}][${quote(t.name)}],`;
|
287
|
+
}), "\n");
|
288
|
+
return out;
|
289
|
+
}));
|
290
|
+
return `\t/* -- ${schema.name} --*/\n\n` + schema_validators || "\t-- no validators\n\n";
|
244
291
|
}));
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
return
|
292
|
+
validator += "\n};";
|
293
|
+
parts.push(validator);
|
294
|
+
}
|
295
|
+
parts.push(schemas.map(s => `export type { ${this.formatSchema(s.name)} };`).join("\n"));
|
296
|
+
return join(parts);
|
250
297
|
},
|
251
298
|
};
|
252
299
|
return generator;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "true-pg",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.3.0",
|
4
4
|
"type": "module",
|
5
5
|
"module": "lib/index.js",
|
6
6
|
"main": "lib/index.js",
|
@@ -17,7 +17,7 @@
|
|
17
17
|
},
|
18
18
|
"scripts": {
|
19
19
|
"check": "tsc --noEmit",
|
20
|
-
"build": "tsc",
|
20
|
+
"build": "rm -rf lib && tsc",
|
21
21
|
"prepare": "bun run build"
|
22
22
|
},
|
23
23
|
"devDependencies": {
|
@@ -30,7 +30,6 @@
|
|
30
30
|
},
|
31
31
|
"dependencies": {
|
32
32
|
"cosmiconfig": "^9.0.0",
|
33
|
-
"mri": "^1.2.0"
|
34
|
-
"pg-extract": "^0.0.3"
|
33
|
+
"mri": "^1.2.0"
|
35
34
|
}
|
36
35
|
}
|