true-pg 0.5.1 → 0.7.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/extractor/adapter.d.ts +6 -1
- package/lib/extractor/adapter.js +15 -1
- package/lib/extractor/canonicalise.d.ts +56 -10
- package/lib/extractor/canonicalise.js +341 -202
- package/lib/extractor/index.d.ts +11 -10
- package/lib/extractor/index.js +11 -16
- package/lib/extractor/kinds/composite.d.ts +1 -1
- package/lib/extractor/kinds/composite.js +1 -2
- package/lib/extractor/kinds/domain.d.ts +1 -1
- package/lib/extractor/kinds/domain.js +1 -2
- package/lib/extractor/kinds/function.d.ts +1 -1
- package/lib/extractor/kinds/function.js +5 -6
- package/lib/extractor/kinds/materialized-view.d.ts +1 -1
- package/lib/extractor/kinds/materialized-view.js +1 -2
- package/lib/extractor/kinds/range.d.ts +1 -1
- package/lib/extractor/kinds/range.js +1 -2
- package/lib/extractor/kinds/table.d.ts +1 -1
- package/lib/extractor/kinds/table.js +1 -2
- package/lib/extractor/kinds/view.d.ts +1 -1
- package/lib/extractor/kinds/view.js +1 -2
- package/lib/extractor/pgtype.d.ts +6 -6
- package/lib/extractor/pgtype.js +7 -1
- package/lib/imports.d.ts +8 -2
- package/lib/imports.js +7 -4
- package/lib/imports.test.d.ts +1 -0
- package/lib/imports.test.js +188 -0
- package/lib/index.js +24 -7
- package/lib/kysely/index.js +16 -9
- package/lib/types.d.ts +3 -3
- package/lib/types.js +2 -11
- package/lib/util.d.ts +7 -0
- package/lib/util.js +14 -0
- package/lib/zod/index.js +17 -21
- package/package.json +1 -1
package/lib/kysely/index.js
CHANGED
@@ -31,9 +31,10 @@ export const Kysely = createGenerator(opts => {
|
|
31
31
|
qualified = `Generated<${qualified}>`;
|
32
32
|
ky(ctx, "Generated");
|
33
33
|
}
|
34
|
+
// TODO: Use ColumnType for appropriate cases:
|
35
|
+
// composite, jsonb, json, date types, etc
|
34
36
|
let out = col.comment ? `/** ${col.comment} */\n\t` : "";
|
35
37
|
out += quoteI(col.name);
|
36
|
-
// TODO: update imports for non-primitive types
|
37
38
|
out += `: ${qualified}`;
|
38
39
|
return `\t${out};\n`;
|
39
40
|
};
|
@@ -56,21 +57,27 @@ export const Kysely = createGenerator(opts => {
|
|
56
57
|
let base;
|
57
58
|
if (type.kind === FunctionReturnTypeKind.ExistingTable) {
|
58
59
|
base = toPascalCase(type.name);
|
60
|
+
ctx.imports.add(Import.fromInternal({
|
61
|
+
source: ctx.source,
|
62
|
+
type,
|
63
|
+
withName: base,
|
64
|
+
typeOnly: true,
|
65
|
+
}));
|
59
66
|
}
|
60
|
-
else if (type.schema === "pg_catalog"
|
67
|
+
else if (type.schema === "pg_catalog" ||
|
68
|
+
type.kind === Canonical.Kind.Base ||
|
69
|
+
type.kind === Canonical.Kind.Pseudo) {
|
61
70
|
const name = type.canonical_name;
|
62
71
|
const format = builtins[name];
|
63
72
|
if (format)
|
64
73
|
base = format;
|
65
74
|
else {
|
66
|
-
opts?.warnings?.add(`(kysely) Unknown
|
75
|
+
opts?.warnings?.add(`(kysely) Unknown base type: ${name}. Pass 'kysely.builtinMap' to map this type. Defaulting to "unknown".`);
|
67
76
|
base = "unknown";
|
68
77
|
}
|
69
78
|
}
|
70
|
-
else
|
79
|
+
else {
|
71
80
|
base = toPascalCase(type.name);
|
72
|
-
if (type.schema !== "pg_catalog") {
|
73
|
-
// before adding modifiers, add the import
|
74
81
|
ctx.imports.add(Import.fromInternal({
|
75
82
|
source: ctx.source,
|
76
83
|
type,
|
@@ -222,14 +229,14 @@ export const Kysely = createGenerator(opts => {
|
|
222
229
|
schemaIndex(ctx, schema) {
|
223
230
|
const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
|
224
231
|
// we could in theory use the imports from GeneratorContext here, but this works fine
|
225
|
-
let out = actual_kinds.map(kind => `import type * as ${kind} from "./${kind}/index.ts";`).join("\n");
|
232
|
+
let out = actual_kinds.map(kind => `import type * as ${kind}s from "./${kind}s/index.ts";`).join("\n");
|
226
233
|
out += "\n\n";
|
227
234
|
out += `export interface ${this.formatSchemaName(schema.name)} {\n`;
|
228
235
|
for (const kind of actual_kinds) {
|
229
236
|
const items = schema[kind];
|
230
237
|
if (items.length === 0)
|
231
238
|
continue;
|
232
|
-
out += `\t${kind}: {\n`;
|
239
|
+
out += `\t${kind}s: {\n`;
|
233
240
|
const formatted = items
|
234
241
|
.map(each => {
|
235
242
|
const formatted = generator.formatSchemaMemberName(each);
|
@@ -257,7 +264,7 @@ export const Kysely = createGenerator(opts => {
|
|
257
264
|
iface += schemas
|
258
265
|
.map(schema => {
|
259
266
|
// only tables, views, and materialized views are queryable
|
260
|
-
const tables = [...schema.
|
267
|
+
const tables = [...schema.table, ...schema.view, ...schema.materializedView];
|
261
268
|
let out = "";
|
262
269
|
const seen = new Set();
|
263
270
|
const formatted = tables
|
package/lib/types.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Canonical, type TableDetails, type ViewDetails, type MaterializedViewDetails, type EnumDetails, type CompositeTypeDetails, type DomainDetails, type RangeDetails, type FunctionDetails, type SchemaType, type Schema, type FunctionReturnType } from "./extractor/index.ts";
|
2
2
|
import type { ImportList } from "./imports.ts";
|
3
|
-
export declare const allowed_kind_names:
|
3
|
+
export declare const allowed_kind_names: ("function" | "composite" | "domain" | "enum" | "range" | "table" | "view" | "materializedView")[];
|
4
4
|
export type allowed_kind_names = (typeof allowed_kind_names)[number];
|
5
5
|
export interface FolderStructure {
|
6
6
|
name: string;
|
@@ -10,8 +10,8 @@ export interface FolderStructure {
|
|
10
10
|
name: string;
|
11
11
|
type: "schema";
|
12
12
|
children: {
|
13
|
-
[kind
|
14
|
-
kind:
|
13
|
+
[kind in allowed_kind_names]: {
|
14
|
+
kind: kind;
|
15
15
|
type: "kind";
|
16
16
|
children: {
|
17
17
|
[realname: string]: {
|
package/lib/types.js
CHANGED
@@ -1,14 +1,5 @@
|
|
1
|
-
import { Canonical, } from "./extractor/index.js";
|
1
|
+
import { Canonical, pgTypeKinds, } from "./extractor/index.js";
|
2
2
|
// To be updated when we add support for other kinds
|
3
|
-
export const allowed_kind_names =
|
4
|
-
"tables",
|
5
|
-
"views",
|
6
|
-
"materializedViews",
|
7
|
-
"enums",
|
8
|
-
"composites",
|
9
|
-
"functions",
|
10
|
-
"domains",
|
11
|
-
"ranges",
|
12
|
-
];
|
3
|
+
export const allowed_kind_names = pgTypeKinds;
|
13
4
|
/* convenience function to create a generator with type inference */
|
14
5
|
export const createGenerator = (generatorCreator) => generatorCreator;
|
package/lib/util.d.ts
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
export declare const unreachable: (value: never) => never;
|
2
|
+
export declare class Deferred<T> {
|
3
|
+
resolve: (value: T) => void;
|
4
|
+
reject: (reason?: any) => void;
|
5
|
+
promise: Promise<T>;
|
6
|
+
constructor();
|
7
|
+
}
|
1
8
|
export declare const eq: <T>(a: T, b: T) => boolean;
|
2
9
|
export declare const toPascalCase: (str: string) => string;
|
3
10
|
export declare const to_snake_case: (str: string) => string;
|
package/lib/util.js
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
export const unreachable = (value) => {
|
2
|
+
throw new Error(`Fatal: Reached unreachable code: ${value}`);
|
3
|
+
};
|
4
|
+
export class Deferred {
|
5
|
+
resolve;
|
6
|
+
reject;
|
7
|
+
promise;
|
8
|
+
constructor() {
|
9
|
+
this.promise = new Promise((resolve, reject) => {
|
10
|
+
this.resolve = resolve;
|
11
|
+
this.reject = reject;
|
12
|
+
});
|
13
|
+
}
|
14
|
+
}
|
1
15
|
export const eq = (a, b) => {
|
2
16
|
if (a === b)
|
3
17
|
return true;
|
package/lib/zod/index.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { FunctionReturnTypeKind, } from "../extractor/index.js";
|
1
|
+
import { Canonical, FunctionReturnTypeKind, } from "../extractor/index.js";
|
2
2
|
import { allowed_kind_names, createGenerator } from "../types.js";
|
3
3
|
import { Import } from "../imports.js";
|
4
4
|
import { builtins } from "./builtins.js";
|
@@ -22,16 +22,12 @@ export const Zod = createGenerator(opts => {
|
|
22
22
|
out += quoteI(col.name);
|
23
23
|
const nullable = col.isNullable || col.generated === "BY DEFAULT" || col.defaultValue;
|
24
24
|
let type = generator.formatType(ctx, col.type, { nullable });
|
25
|
-
if (nullable)
|
26
|
-
type += `.optional()`;
|
27
25
|
out += `: ${type}`;
|
28
26
|
return `\t${out},\n`;
|
29
27
|
};
|
30
28
|
const composite_attribute = (ctx, attr) => {
|
31
29
|
let out = quoteI(attr.name);
|
32
30
|
out += `: ${generator.formatType(ctx, attr.type, { nullable: attr.isNullable })}`;
|
33
|
-
if (attr.isNullable)
|
34
|
-
out += ".optional()";
|
35
31
|
return out;
|
36
32
|
};
|
37
33
|
const generator = {
|
@@ -45,27 +41,31 @@ export const Zod = createGenerator(opts => {
|
|
45
41
|
let base;
|
46
42
|
if (type.kind === FunctionReturnTypeKind.ExistingTable) {
|
47
43
|
base = to_snake_case(type.name);
|
44
|
+
ctx.imports.add(Import.fromInternal({
|
45
|
+
source: ctx.source,
|
46
|
+
type,
|
47
|
+
withName: base,
|
48
|
+
typeOnly: false,
|
49
|
+
}));
|
48
50
|
}
|
49
|
-
else if (type.schema === "pg_catalog"
|
51
|
+
else if (type.schema === "pg_catalog" ||
|
52
|
+
type.kind === Canonical.Kind.Base ||
|
53
|
+
type.kind === Canonical.Kind.Pseudo) {
|
50
54
|
const name = type.canonical_name;
|
51
55
|
const format = builtins[name];
|
52
56
|
if (format)
|
53
57
|
base = format;
|
54
58
|
else {
|
55
|
-
opts?.warnings?.add(`(zod) Unknown
|
59
|
+
opts?.warnings?.add(`(zod) Unknown base type: ${name}. Pass 'zod.builtinMap' to map this type. Defaulting to "z.unknown()".`);
|
56
60
|
base = "z.unknown()";
|
57
61
|
}
|
58
|
-
}
|
59
|
-
else
|
60
|
-
base = to_snake_case(type.name);
|
61
|
-
if (type.schema === "pg_catalog") {
|
62
62
|
ctx.imports.add(new Import({
|
63
63
|
from: "zod",
|
64
64
|
namedImports: ["z"],
|
65
65
|
}));
|
66
66
|
}
|
67
67
|
else {
|
68
|
-
|
68
|
+
base = to_snake_case(type.name);
|
69
69
|
ctx.imports.add(Import.fromInternal({
|
70
70
|
source: ctx.source,
|
71
71
|
type,
|
@@ -76,7 +76,7 @@ export const Zod = createGenerator(opts => {
|
|
76
76
|
if ("dimensions" in type)
|
77
77
|
base += ".array()".repeat(type.dimensions);
|
78
78
|
if (attr?.nullable)
|
79
|
-
base += ".
|
79
|
+
base += ".optional()";
|
80
80
|
return base;
|
81
81
|
},
|
82
82
|
table(ctx, table) {
|
@@ -159,8 +159,6 @@ export const Zod = createGenerator(opts => {
|
|
159
159
|
for (const param of inputParams) {
|
160
160
|
// TODO: update imports for non-primitive types based on typeInfo.kind
|
161
161
|
out += "\t\t" + this.formatType(ctx, param.type, { nullable: param.hasDefault });
|
162
|
-
if (param.hasDefault)
|
163
|
-
out += ".optional()";
|
164
162
|
out += `, // ${param.name}\n`;
|
165
163
|
}
|
166
164
|
out += "\t])";
|
@@ -217,14 +215,14 @@ export const Zod = createGenerator(opts => {
|
|
217
215
|
schemaIndex(ctx, schema, main_generator) {
|
218
216
|
const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
|
219
217
|
// we could in theory use the imports from GeneratorContext here, but this works fine
|
220
|
-
let out = actual_kinds.map(kind => `import * as zod_${kind} from "./${kind}/index.ts";`).join("\n");
|
218
|
+
let out = actual_kinds.map(kind => `import * as zod_${kind}s from "./${kind}s/index.ts";`).join("\n");
|
221
219
|
out += "\n\n";
|
222
220
|
out += `export const ${this.formatSchemaName(schema.name)} = {\n`;
|
223
221
|
for (const kind of actual_kinds) {
|
224
222
|
const items = schema[kind];
|
225
223
|
if (items.length === 0)
|
226
224
|
continue;
|
227
|
-
out += `\t${kind}: {\n`;
|
225
|
+
out += `\t${kind}s: {\n`;
|
228
226
|
const formatted = items
|
229
227
|
.map(each => {
|
230
228
|
const formatted = this.formatSchemaMemberName(each);
|
@@ -245,9 +243,7 @@ export const Zod = createGenerator(opts => {
|
|
245
243
|
fullIndex(ctx, schemas, main_generator) {
|
246
244
|
const generator = main_generator ?? this;
|
247
245
|
const parts = [];
|
248
|
-
parts.push(schemas
|
249
|
-
.map(s => `import { ${generator.formatSchemaName(s.name)} } from "./${s.name}/index.ts";`)
|
250
|
-
.join("\n"));
|
246
|
+
parts.push(schemas.map(s => `import { ${generator.formatSchemaName(s.name)} } from "./${s.name}/index.ts";`).join("\n"));
|
251
247
|
{
|
252
248
|
let validator = `export const Validators = {\n`;
|
253
249
|
validator += join(schemas.map(schema => {
|
@@ -267,7 +263,7 @@ export const Zod = createGenerator(opts => {
|
|
267
263
|
if (!formatted.length)
|
268
264
|
return "";
|
269
265
|
let out = "";
|
270
|
-
out += "\t// " + kind + "\n";
|
266
|
+
out += "\t// " + kind + "s\n";
|
271
267
|
out += join(formatted.map(t => {
|
272
268
|
const isDefault = defaultSchema === schema.name;
|
273
269
|
let qualified = "";
|