true-pg 0.5.1 → 0.6.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/index.d.ts +9 -8
- package/lib/extractor/index.js +10 -12
- 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 +2 -2
- package/lib/index.js +7 -6
- package/lib/kysely/index.js +14 -9
- package/lib/types.d.ts +3 -3
- package/lib/types.js +2 -11
- package/lib/zod/index.js +15 -11
- package/package.json +1 -1
package/lib/extractor/index.d.ts
CHANGED
@@ -9,6 +9,7 @@ import { type FunctionDetails } from "./kinds/function.ts";
|
|
9
9
|
import { type DomainDetails } from "./kinds/domain.ts";
|
10
10
|
import { type RangeDetails } from "./kinds/range.ts";
|
11
11
|
import type { PgType } from "./pgtype.ts";
|
12
|
+
export { pgTypeKinds, type PgType, type Kind } from "./pgtype.ts";
|
12
13
|
import { Canonical } from "./canonicalise.ts";
|
13
14
|
export { Canonical };
|
14
15
|
export type { TableDetails, ViewDetails, MaterializedViewDetails, EnumDetails, CompositeTypeDetails, FunctionDetails, DomainDetails, RangeDetails, };
|
@@ -23,14 +24,14 @@ export { FunctionReturnTypeKind } from "./kinds/function.ts";
|
|
23
24
|
*/
|
24
25
|
export type Schema = {
|
25
26
|
name: string;
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
table: TableDetails[];
|
28
|
+
view: ViewDetails[];
|
29
|
+
materializedView: MaterializedViewDetails[];
|
30
|
+
enum: EnumDetails[];
|
31
|
+
composite: CompositeTypeDetails[];
|
32
|
+
function: FunctionDetails[];
|
33
|
+
domain: DomainDetails[];
|
34
|
+
range: RangeDetails[];
|
34
35
|
};
|
35
36
|
export type SchemaType = TableDetails | ViewDetails | MaterializedViewDetails | EnumDetails | CompositeTypeDetails | FunctionDetails | DomainDetails | RangeDetails;
|
36
37
|
/**
|
package/lib/extractor/index.js
CHANGED
@@ -10,18 +10,19 @@ import extractFunction, {} from "./kinds/function.js";
|
|
10
10
|
import extractDomain, {} from "./kinds/domain.js";
|
11
11
|
import extractRange, {} from "./kinds/range.js";
|
12
12
|
import fetchTypes from "./fetchTypes.js";
|
13
|
+
export { pgTypeKinds } from "./pgtype.js";
|
13
14
|
import { canonicalise, Canonical } from "./canonicalise.js";
|
14
15
|
export { Canonical };
|
15
16
|
export { FunctionReturnTypeKind } from "./kinds/function.js";
|
16
17
|
const emptySchema = {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
table: [],
|
19
|
+
view: [],
|
20
|
+
materializedView: [],
|
21
|
+
enum: [],
|
22
|
+
composite: [],
|
23
|
+
function: [],
|
24
|
+
domain: [],
|
25
|
+
range: [],
|
25
26
|
};
|
26
27
|
const populatorMap = {
|
27
28
|
table: extractTable,
|
@@ -133,10 +134,7 @@ export class Extractor {
|
|
133
134
|
...emptySchema,
|
134
135
|
};
|
135
136
|
}
|
136
|
-
schemas[p.schemaName][
|
137
|
-
...schemas[p.schemaName][`${p.kind}s`],
|
138
|
-
p,
|
139
|
-
];
|
137
|
+
schemas[p.schemaName][p.kind] = [...schemas[p.schemaName][p.kind], p];
|
140
138
|
}
|
141
139
|
const result =
|
142
140
|
// options?.resolveViews
|
@@ -1,9 +1,9 @@
|
|
1
1
|
export declare const typeKindMap: {
|
2
|
-
readonly d: "domain";
|
3
2
|
readonly e: "enum";
|
3
|
+
readonly d: "domain";
|
4
4
|
readonly r: "range";
|
5
5
|
};
|
6
|
-
type TypeKind = (typeof typeKindMap)[keyof typeof typeKindMap];
|
6
|
+
export type TypeKind = (typeof typeKindMap)[keyof typeof typeKindMap];
|
7
7
|
export declare const classKindMap: {
|
8
8
|
readonly r: "table";
|
9
9
|
readonly p: "table";
|
@@ -11,12 +11,13 @@ export declare const classKindMap: {
|
|
11
11
|
readonly m: "materializedView";
|
12
12
|
readonly c: "composite";
|
13
13
|
};
|
14
|
-
type ClassKind = (typeof classKindMap)[keyof typeof classKindMap];
|
14
|
+
export type ClassKind = (typeof classKindMap)[keyof typeof classKindMap];
|
15
15
|
export declare const routineKindMap: {
|
16
16
|
readonly f: "function";
|
17
17
|
};
|
18
|
-
type RoutineKind = (typeof routineKindMap)[keyof typeof routineKindMap];
|
19
|
-
export
|
18
|
+
export type RoutineKind = (typeof routineKindMap)[keyof typeof routineKindMap];
|
19
|
+
export declare const pgTypeKinds: ("function" | "enum" | "domain" | "range" | "table" | "view" | "materializedView" | "composite")[];
|
20
|
+
export type Kind = (typeof pgTypeKinds)[number];
|
20
21
|
/**
|
21
22
|
* Base type for Postgres objects.
|
22
23
|
*/
|
@@ -38,4 +39,3 @@ export type PgType<K extends Kind = Kind> = {
|
|
38
39
|
*/
|
39
40
|
comment: string | null;
|
40
41
|
};
|
41
|
-
export {};
|
package/lib/extractor/pgtype.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
export const typeKindMap = {
|
2
|
-
d: "domain",
|
3
2
|
e: "enum",
|
3
|
+
d: "domain",
|
4
4
|
r: "range",
|
5
5
|
// Not supported (yet):
|
6
6
|
// m: 'multiRange',
|
@@ -28,3 +28,9 @@ export const routineKindMap = {
|
|
28
28
|
// a: 'aggregate',
|
29
29
|
// w: 'windowFunction',
|
30
30
|
};
|
31
|
+
const unique = (arr) => [...new Set(arr)];
|
32
|
+
export const pgTypeKinds = unique([
|
33
|
+
...Object.values(classKindMap),
|
34
|
+
...Object.values(typeKindMap),
|
35
|
+
...Object.values(routineKindMap),
|
36
|
+
]);
|
package/lib/imports.d.ts
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
import type { Canonical } from "./extractor/index.ts";
|
2
2
|
import type { FunctionReturnType } from "./extractor/index.ts";
|
3
|
-
import type { FolderStructure } from "./types.ts";
|
3
|
+
import type { allowed_kind_names, FolderStructure } from "./types.ts";
|
4
4
|
export interface ImportIdentifier {
|
5
5
|
name: string;
|
6
6
|
alias?: string;
|
7
7
|
typeOnly?: boolean;
|
8
8
|
}
|
9
|
+
type Supported<T> = {
|
10
|
+
[key in allowed_kind_names]: T extends {
|
11
|
+
kind: key;
|
12
|
+
} ? T : never;
|
13
|
+
}[allowed_kind_names];
|
9
14
|
export declare class Import {
|
10
15
|
from: string | ((files: FolderStructure) => string);
|
11
16
|
namedImports?: (string | ImportIdentifier)[];
|
@@ -21,7 +26,7 @@ export declare class Import {
|
|
21
26
|
});
|
22
27
|
static fromInternal(opts: {
|
23
28
|
source: string;
|
24
|
-
type: Canonical | FunctionReturnType.ExistingTable
|
29
|
+
type: Supported<Canonical | FunctionReturnType.ExistingTable>;
|
25
30
|
withName?: string;
|
26
31
|
typeOnly?: boolean;
|
27
32
|
}): Import;
|
@@ -33,3 +38,4 @@ export declare class ImportList {
|
|
33
38
|
add(item: Import): void;
|
34
39
|
stringify(files: FolderStructure): string;
|
35
40
|
}
|
41
|
+
export {};
|
package/lib/imports.js
CHANGED
@@ -18,9 +18,9 @@ export class Import {
|
|
18
18
|
return new Import({
|
19
19
|
from: files => {
|
20
20
|
const schema = files.children[t.schema];
|
21
|
-
const kind = schema.children[
|
21
|
+
const kind = schema.children[t.kind];
|
22
22
|
const type = kind.children[t.name];
|
23
|
-
const path = `${files.name}/${schema.name}/${kind.kind}/${type.name}.ts`;
|
23
|
+
const path = `${files.name}/${schema.name}/${kind.kind}s/${type.name}.ts`;
|
24
24
|
return relative(dirname(opts.source), path);
|
25
25
|
},
|
26
26
|
namedImports: [opts.withName ?? t.name],
|
package/lib/index.js
CHANGED
@@ -115,9 +115,9 @@ const multifile = async (generators, schemas, opts) => {
|
|
115
115
|
for (const schema of Object.values(schemas)) {
|
116
116
|
console.log("Selected schema '%s':\n", schema.name);
|
117
117
|
const schemaDir = joinpath(out, schema.name);
|
118
|
-
const [unique_functions, overloaded_functions] = filter_overloaded_functions(schema.
|
118
|
+
const [unique_functions, overloaded_functions] = filter_overloaded_functions(schema.function);
|
119
119
|
const [supported_functions, unsupported_functions] = filter_unsupported_functions(unique_functions);
|
120
|
-
schema.
|
120
|
+
schema.function = supported_functions;
|
121
121
|
{
|
122
122
|
const skipped = unsupported_functions.map(f => ` - ${f.name}`);
|
123
123
|
if (skipped.length) {
|
@@ -136,11 +136,12 @@ const multifile = async (generators, schemas, opts) => {
|
|
136
136
|
if (schema[kind].length < 1)
|
137
137
|
continue;
|
138
138
|
createIndex = true;
|
139
|
-
|
140
|
-
|
139
|
+
const kindDir = joinpath(schemaDir, kind + "s");
|
140
|
+
await mkdir(kindDir, { recursive: true });
|
141
|
+
console.log(" Creating %s:\n", kind + "s");
|
141
142
|
for (const [i, item] of schema[kind].entries()) {
|
142
143
|
const index = "[" + (i + 1 + "]").padEnd(3, " ");
|
143
|
-
const filename = joinpath(
|
144
|
+
const filename = joinpath(kindDir, def_gen.formatSchemaMemberName(item) + ".ts");
|
144
145
|
const exists = await existsSync(filename);
|
145
146
|
if (exists) {
|
146
147
|
warnings.add(`Skipping ${item.kind} "${item.name}": formatted name clashes. Wanted to create ${filename}`);
|
@@ -159,7 +160,7 @@ const multifile = async (generators, schemas, opts) => {
|
|
159
160
|
{
|
160
161
|
const start = performance.now();
|
161
162
|
const imports = new ImportList();
|
162
|
-
const fileName = joinpath(
|
163
|
+
const fileName = joinpath(kindDir, "index.ts");
|
163
164
|
const kindIndex = join(gens.map(gen => gen.schemaKindIndex({ source: fileName, imports }, schema, kind, def_gen)));
|
164
165
|
const file = join([imports.stringify(files), kindIndex]);
|
165
166
|
await write(fileName, file);
|
package/lib/kysely/index.js
CHANGED
@@ -33,7 +33,6 @@ export const Kysely = createGenerator(opts => {
|
|
33
33
|
}
|
34
34
|
let out = col.comment ? `/** ${col.comment} */\n\t` : "";
|
35
35
|
out += quoteI(col.name);
|
36
|
-
// TODO: update imports for non-primitive types
|
37
36
|
out += `: ${qualified}`;
|
38
37
|
return `\t${out};\n`;
|
39
38
|
};
|
@@ -56,21 +55,27 @@ export const Kysely = createGenerator(opts => {
|
|
56
55
|
let base;
|
57
56
|
if (type.kind === FunctionReturnTypeKind.ExistingTable) {
|
58
57
|
base = toPascalCase(type.name);
|
58
|
+
ctx.imports.add(Import.fromInternal({
|
59
|
+
source: ctx.source,
|
60
|
+
type,
|
61
|
+
withName: base,
|
62
|
+
typeOnly: true,
|
63
|
+
}));
|
59
64
|
}
|
60
|
-
else if (type.schema === "pg_catalog"
|
65
|
+
else if (type.schema === "pg_catalog" ||
|
66
|
+
type.kind === Canonical.Kind.Base ||
|
67
|
+
type.kind === Canonical.Kind.Pseudo) {
|
61
68
|
const name = type.canonical_name;
|
62
69
|
const format = builtins[name];
|
63
70
|
if (format)
|
64
71
|
base = format;
|
65
72
|
else {
|
66
|
-
opts?.warnings?.add(`(kysely) Unknown
|
73
|
+
opts?.warnings?.add(`(kysely) Unknown base type: ${name}. Pass 'kysely.builtinMap' to map this type. Defaulting to "unknown".`);
|
67
74
|
base = "unknown";
|
68
75
|
}
|
69
76
|
}
|
70
|
-
else
|
77
|
+
else {
|
71
78
|
base = toPascalCase(type.name);
|
72
|
-
if (type.schema !== "pg_catalog") {
|
73
|
-
// before adding modifiers, add the import
|
74
79
|
ctx.imports.add(Import.fromInternal({
|
75
80
|
source: ctx.source,
|
76
81
|
type,
|
@@ -222,14 +227,14 @@ export const Kysely = createGenerator(opts => {
|
|
222
227
|
schemaIndex(ctx, schema) {
|
223
228
|
const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
|
224
229
|
// 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");
|
230
|
+
let out = actual_kinds.map(kind => `import type * as ${kind}s from "./${kind}s/index.ts";`).join("\n");
|
226
231
|
out += "\n\n";
|
227
232
|
out += `export interface ${this.formatSchemaName(schema.name)} {\n`;
|
228
233
|
for (const kind of actual_kinds) {
|
229
234
|
const items = schema[kind];
|
230
235
|
if (items.length === 0)
|
231
236
|
continue;
|
232
|
-
out += `\t${kind}: {\n`;
|
237
|
+
out += `\t${kind}s: {\n`;
|
233
238
|
const formatted = items
|
234
239
|
.map(each => {
|
235
240
|
const formatted = generator.formatSchemaMemberName(each);
|
@@ -257,7 +262,7 @@ export const Kysely = createGenerator(opts => {
|
|
257
262
|
iface += schemas
|
258
263
|
.map(schema => {
|
259
264
|
// only tables, views, and materialized views are queryable
|
260
|
-
const tables = [...schema.
|
265
|
+
const tables = [...schema.table, ...schema.view, ...schema.materializedView];
|
261
266
|
let out = "";
|
262
267
|
const seen = new Set();
|
263
268
|
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" | "enum" | "domain" | "range" | "table" | "view" | "materializedView" | "composite")[];
|
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/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";
|
@@ -45,27 +45,31 @@ export const Zod = createGenerator(opts => {
|
|
45
45
|
let base;
|
46
46
|
if (type.kind === FunctionReturnTypeKind.ExistingTable) {
|
47
47
|
base = to_snake_case(type.name);
|
48
|
+
ctx.imports.add(Import.fromInternal({
|
49
|
+
source: ctx.source,
|
50
|
+
type,
|
51
|
+
withName: base,
|
52
|
+
typeOnly: false,
|
53
|
+
}));
|
48
54
|
}
|
49
|
-
else if (type.schema === "pg_catalog"
|
55
|
+
else if (type.schema === "pg_catalog" ||
|
56
|
+
type.kind === Canonical.Kind.Base ||
|
57
|
+
type.kind === Canonical.Kind.Pseudo) {
|
50
58
|
const name = type.canonical_name;
|
51
59
|
const format = builtins[name];
|
52
60
|
if (format)
|
53
61
|
base = format;
|
54
62
|
else {
|
55
|
-
opts?.warnings?.add(`(zod) Unknown
|
63
|
+
opts?.warnings?.add(`(zod) Unknown base type: ${name}. Pass 'zod.builtinMap' to map this type. Defaulting to "z.unknown()".`);
|
56
64
|
base = "z.unknown()";
|
57
65
|
}
|
58
|
-
}
|
59
|
-
else
|
60
|
-
base = to_snake_case(type.name);
|
61
|
-
if (type.schema === "pg_catalog") {
|
62
66
|
ctx.imports.add(new Import({
|
63
67
|
from: "zod",
|
64
68
|
namedImports: ["z"],
|
65
69
|
}));
|
66
70
|
}
|
67
71
|
else {
|
68
|
-
|
72
|
+
base = to_snake_case(type.name);
|
69
73
|
ctx.imports.add(Import.fromInternal({
|
70
74
|
source: ctx.source,
|
71
75
|
type,
|
@@ -217,14 +221,14 @@ export const Zod = createGenerator(opts => {
|
|
217
221
|
schemaIndex(ctx, schema, main_generator) {
|
218
222
|
const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
|
219
223
|
// 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");
|
224
|
+
let out = actual_kinds.map(kind => `import * as zod_${kind}s from "./${kind}s/index.ts";`).join("\n");
|
221
225
|
out += "\n\n";
|
222
226
|
out += `export const ${this.formatSchemaName(schema.name)} = {\n`;
|
223
227
|
for (const kind of actual_kinds) {
|
224
228
|
const items = schema[kind];
|
225
229
|
if (items.length === 0)
|
226
230
|
continue;
|
227
|
-
out += `\t${kind}: {\n`;
|
231
|
+
out += `\t${kind}s: {\n`;
|
228
232
|
const formatted = items
|
229
233
|
.map(each => {
|
230
234
|
const formatted = this.formatSchemaMemberName(each);
|
@@ -267,7 +271,7 @@ export const Zod = createGenerator(opts => {
|
|
267
271
|
if (!formatted.length)
|
268
272
|
return "";
|
269
273
|
let out = "";
|
270
|
-
out += "\t// " + kind + "\n";
|
274
|
+
out += "\t// " + kind + "s\n";
|
271
275
|
out += join(formatted.map(t => {
|
272
276
|
const isDefault = defaultSchema === schema.name;
|
273
277
|
let qualified = "";
|