true-pg 0.5.0 → 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/README.md +17 -17
- package/lib/bin.js +16 -16
- package/lib/config.d.ts +6 -6
- package/lib/config.js +8 -8
- 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 +41 -0
- package/lib/imports.js +102 -0
- package/lib/index.js +75 -63
- package/lib/kysely/index.js +87 -95
- package/lib/types.d.ts +32 -77
- package/lib/types.js +2 -176
- package/lib/util.d.ts +2 -0
- package/lib/util.js +13 -0
- package/lib/zod/index.js +100 -98
- package/package.json +3 -2
package/lib/types.d.ts
CHANGED
@@ -1,5 +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: ("function" | "enum" | "domain" | "range" | "table" | "view" | "materializedView" | "composite")[];
|
3
4
|
export type allowed_kind_names = (typeof allowed_kind_names)[number];
|
4
5
|
export interface FolderStructure {
|
5
6
|
name: string;
|
@@ -9,8 +10,8 @@ export interface FolderStructure {
|
|
9
10
|
name: string;
|
10
11
|
type: "schema";
|
11
12
|
children: {
|
12
|
-
[kind
|
13
|
-
kind:
|
13
|
+
[kind in allowed_kind_names]: {
|
14
|
+
kind: kind;
|
14
15
|
type: "kind";
|
15
16
|
children: {
|
16
17
|
[realname: string]: {
|
@@ -23,118 +24,72 @@ export interface FolderStructure {
|
|
23
24
|
};
|
24
25
|
};
|
25
26
|
}
|
26
|
-
export declare namespace Nodes {
|
27
|
-
class ExternalImport {
|
28
|
-
name: string;
|
29
|
-
typeOnly: boolean;
|
30
|
-
star: boolean;
|
31
|
-
external: true;
|
32
|
-
module: string;
|
33
|
-
constructor(args: {
|
34
|
-
name: string;
|
35
|
-
module: string;
|
36
|
-
typeOnly: boolean;
|
37
|
-
star: boolean;
|
38
|
-
});
|
39
|
-
}
|
40
|
-
class InternalImport {
|
41
|
-
name: string;
|
42
|
-
canonical_type: Canonical | FunctionReturnType.ExistingTable;
|
43
|
-
typeOnly: boolean;
|
44
|
-
star: boolean;
|
45
|
-
external: false;
|
46
|
-
constructor(args: {
|
47
|
-
name: string;
|
48
|
-
canonical_type: Canonical | FunctionReturnType.ExistingTable;
|
49
|
-
typeOnly: boolean;
|
50
|
-
star: boolean;
|
51
|
-
});
|
52
|
-
}
|
53
|
-
class ImportList {
|
54
|
-
imports: (ExternalImport | InternalImport)[];
|
55
|
-
constructor(imports: (ExternalImport | InternalImport)[]);
|
56
|
-
static merge(lists: ImportList[]): ImportList;
|
57
|
-
add(item: ExternalImport | InternalImport): void;
|
58
|
-
stringify(context_file: string, files: FolderStructure): string;
|
59
|
-
}
|
60
|
-
interface Export {
|
61
|
-
name: string;
|
62
|
-
kind: SchemaType["kind"];
|
63
|
-
schema: string;
|
64
|
-
star: boolean;
|
65
|
-
}
|
66
|
-
}
|
67
27
|
export interface CreateGeneratorOpts {
|
68
28
|
defaultSchema?: string;
|
69
|
-
warnings: string
|
29
|
+
warnings: Set<string>;
|
70
30
|
}
|
71
31
|
export interface createGenerator {
|
72
32
|
(opts?: CreateGeneratorOpts): SchemaGenerator;
|
73
33
|
}
|
74
34
|
export declare const createGenerator: (generatorCreator: createGenerator) => createGenerator;
|
35
|
+
export interface GeneratorContext {
|
36
|
+
/** The source file path */
|
37
|
+
source: string;
|
38
|
+
/** Append types to import */
|
39
|
+
imports: ImportList;
|
40
|
+
}
|
41
|
+
export interface FormatTypeAttributes {
|
42
|
+
nullable?: boolean;
|
43
|
+
generated?: boolean;
|
44
|
+
identity?: boolean;
|
45
|
+
}
|
75
46
|
export interface SchemaGenerator {
|
76
47
|
/**
|
77
48
|
* Use this function to define a name mapping for schema names.
|
78
49
|
* This is useful if you want to use a different name for a schema in the generated code.
|
79
50
|
* Example: "public" -> "PublicSchema"
|
80
51
|
*/
|
81
|
-
|
52
|
+
formatSchemaName(name: string): string;
|
82
53
|
/**
|
83
|
-
* Use this function to define a name mapping for schema
|
84
|
-
* This is useful if you want to use a different name for a
|
54
|
+
* Use this function to define a name mapping for schema members.
|
55
|
+
* This is useful if you want to use a different name for a member in the generated code.
|
85
56
|
* Example: "users" -> "UsersTable"
|
86
57
|
*/
|
87
|
-
|
58
|
+
formatSchemaMemberName(type: SchemaType): string;
|
88
59
|
/**
|
89
60
|
* Use this function to define a name mapping for type names.
|
90
61
|
* This is useful if you want to use a different name for a type in the generated code.
|
91
62
|
* Example: "users" -> "UsersTable"
|
92
63
|
*/
|
93
|
-
formatType(type: Canonical | FunctionReturnType.ExistingTable): string;
|
94
|
-
table(
|
95
|
-
/** @out Append used types to this array */
|
96
|
-
imports: Nodes.ImportList,
|
64
|
+
formatType(ctx: GeneratorContext, type: Canonical | FunctionReturnType.ExistingTable, attr?: FormatTypeAttributes): string;
|
65
|
+
table(ctx: GeneratorContext,
|
97
66
|
/** Information about the table */
|
98
67
|
table: TableDetails): string;
|
99
|
-
view(
|
100
|
-
/** @out Append used types to this array */
|
101
|
-
imports: Nodes.ImportList,
|
68
|
+
view(ctx: GeneratorContext,
|
102
69
|
/** Information about the view */
|
103
70
|
view: ViewDetails): string;
|
104
|
-
materializedView(
|
105
|
-
/** @out Append used types to this array */
|
106
|
-
imports: Nodes.ImportList,
|
71
|
+
materializedView(ctx: GeneratorContext,
|
107
72
|
/** Information about the materialized view */
|
108
73
|
materializedView: MaterializedViewDetails): string;
|
109
|
-
enum(
|
110
|
-
/** @out Append used types to this array */
|
111
|
-
imports: Nodes.ImportList,
|
74
|
+
enum(ctx: GeneratorContext,
|
112
75
|
/** Information about the enum */
|
113
76
|
en: EnumDetails): string;
|
114
|
-
composite(
|
115
|
-
/** @out Append used types to this array */
|
116
|
-
imports: Nodes.ImportList,
|
77
|
+
composite(ctx: GeneratorContext,
|
117
78
|
/** Information about the composite type */
|
118
79
|
type: CompositeTypeDetails): string;
|
119
|
-
domain(
|
120
|
-
/** @out Append used types to this array */
|
121
|
-
imports: Nodes.ImportList,
|
80
|
+
domain(ctx: GeneratorContext,
|
122
81
|
/** Information about the domain */
|
123
82
|
type: DomainDetails): string;
|
124
|
-
range(
|
125
|
-
/** @out Append used types to this array */
|
126
|
-
imports: Nodes.ImportList,
|
83
|
+
range(ctx: GeneratorContext,
|
127
84
|
/** Information about the range */
|
128
85
|
type: RangeDetails): string;
|
129
|
-
function(
|
130
|
-
/** @out Append used types to this array */
|
131
|
-
imports: Nodes.ImportList,
|
86
|
+
function(ctx: GeneratorContext,
|
132
87
|
/** Information about the function */
|
133
88
|
type: FunctionDetails): string;
|
134
89
|
/** create the file `$out/$schema.name/$kind/index.ts` */
|
135
|
-
schemaKindIndex(schema: Schema, kind: Exclude<keyof Schema, "name">, main_generator?: SchemaGenerator): string;
|
90
|
+
schemaKindIndex(ctx: GeneratorContext, schema: Schema, kind: Exclude<keyof Schema, "name">, main_generator?: SchemaGenerator): string;
|
136
91
|
/** create the file `$out/$schema.name/index.ts` */
|
137
|
-
schemaIndex(schema: Schema, main_generator?: SchemaGenerator): string;
|
92
|
+
schemaIndex(ctx: GeneratorContext, schema: Schema, main_generator?: SchemaGenerator): string;
|
138
93
|
/** create the file `$out/index.ts` */
|
139
|
-
fullIndex(schemas: Schema[], main_generator?: SchemaGenerator): string;
|
94
|
+
fullIndex(ctx: GeneratorContext, schemas: Schema[], main_generator?: SchemaGenerator): string;
|
140
95
|
}
|
package/lib/types.js
CHANGED
@@ -1,179 +1,5 @@
|
|
1
|
-
import { Canonical, } from "./extractor/index.js";
|
2
|
-
import { dirname, relative } from "node:path/posix";
|
3
|
-
import { join } from "./util.js";
|
1
|
+
import { Canonical, pgTypeKinds, } from "./extractor/index.js";
|
4
2
|
// To be updated when we add support for other kinds
|
5
|
-
export const allowed_kind_names =
|
6
|
-
"tables",
|
7
|
-
"views",
|
8
|
-
"materializedViews",
|
9
|
-
"enums",
|
10
|
-
"composites",
|
11
|
-
"functions",
|
12
|
-
"domains",
|
13
|
-
"ranges",
|
14
|
-
];
|
15
|
-
export var Nodes;
|
16
|
-
(function (Nodes) {
|
17
|
-
class ExternalImport {
|
18
|
-
// what to import
|
19
|
-
name;
|
20
|
-
// use `type` syntax?
|
21
|
-
typeOnly;
|
22
|
-
// use `* as` syntax?
|
23
|
-
star;
|
24
|
-
// this is an external import
|
25
|
-
external;
|
26
|
-
// what module to import from
|
27
|
-
module;
|
28
|
-
constructor(args) {
|
29
|
-
this.name = args.name;
|
30
|
-
this.typeOnly = args.typeOnly;
|
31
|
-
this.star = args.star;
|
32
|
-
this.external = true;
|
33
|
-
this.module = args.module;
|
34
|
-
}
|
35
|
-
}
|
36
|
-
Nodes.ExternalImport = ExternalImport;
|
37
|
-
class InternalImport {
|
38
|
-
// what to import
|
39
|
-
name;
|
40
|
-
// underlying type that is being imported
|
41
|
-
canonical_type;
|
42
|
-
// use `type` syntax?
|
43
|
-
typeOnly;
|
44
|
-
// use `* as` syntax?
|
45
|
-
star;
|
46
|
-
// this is an internal import
|
47
|
-
external;
|
48
|
-
constructor(args) {
|
49
|
-
this.name = args.name;
|
50
|
-
this.canonical_type = args.canonical_type;
|
51
|
-
this.star = args.star;
|
52
|
-
this.typeOnly = args.typeOnly;
|
53
|
-
this.external = false;
|
54
|
-
}
|
55
|
-
}
|
56
|
-
Nodes.InternalImport = InternalImport;
|
57
|
-
class ImportList {
|
58
|
-
imports;
|
59
|
-
constructor(imports) {
|
60
|
-
this.imports = imports;
|
61
|
-
}
|
62
|
-
static merge(lists) {
|
63
|
-
return new ImportList(lists.flatMap(l => l.imports));
|
64
|
-
}
|
65
|
-
add(item) {
|
66
|
-
this.imports.push(item);
|
67
|
-
}
|
68
|
-
stringify(context_file, files) {
|
69
|
-
const externals = this.imports.filter(i => i.external);
|
70
|
-
const internals = this.imports.filter(i => !i.external);
|
71
|
-
const modulegroups = {};
|
72
|
-
for (const item of externals) {
|
73
|
-
const group = modulegroups[item.module];
|
74
|
-
if (group)
|
75
|
-
group.push(item);
|
76
|
-
else
|
77
|
-
modulegroups[item.module] = [item];
|
78
|
-
}
|
79
|
-
const out = [];
|
80
|
-
// TODO: normalise external and internal imports and handle the stringification of the imports in a single place
|
81
|
-
{
|
82
|
-
// EXTERNAL IMPORTS
|
83
|
-
const imports = [];
|
84
|
-
for (const module in modulegroups) {
|
85
|
-
const items = modulegroups[module];
|
86
|
-
const star = items.find(i => i.star);
|
87
|
-
const unique = items.filter((i, index, arr) => {
|
88
|
-
if (i.star)
|
89
|
-
return false;
|
90
|
-
if (arr.findIndex(i2 => i2.name === i.name) !== index)
|
91
|
-
return false;
|
92
|
-
return true;
|
93
|
-
});
|
94
|
-
const bits = [];
|
95
|
-
const typeOnlys = unique.filter(i => i.typeOnly);
|
96
|
-
const values = unique.filter(i => !i.typeOnly);
|
97
|
-
// if no values to import, use `import type { ... }` instead of `import { type ... }`
|
98
|
-
const typeInline = values.length !== 0;
|
99
|
-
let import_line = `import `;
|
100
|
-
for (const type of typeOnlys)
|
101
|
-
bits.push(typeInline ? "type " : "" + type.name);
|
102
|
-
for (const type of values)
|
103
|
-
bits.push(type.name);
|
104
|
-
if (bits.length)
|
105
|
-
import_line += (typeInline ? "" : "type ") + "{ " + bits.join(", ") + " }";
|
106
|
-
if (bits.length && star)
|
107
|
-
import_line += `, `;
|
108
|
-
if (star)
|
109
|
-
import_line += `* as ${star.name}`;
|
110
|
-
if (bits.length || star)
|
111
|
-
import_line += ` from `;
|
112
|
-
import_line += `"${module}";`;
|
113
|
-
imports.push(import_line);
|
114
|
-
}
|
115
|
-
out.push(join(imports, "\n"));
|
116
|
-
}
|
117
|
-
{
|
118
|
-
// INTERNAL IMPORTS
|
119
|
-
const imports = [];
|
120
|
-
const unique_types = internals
|
121
|
-
.filter(({ name: name1, canonical_type: int }, index, arr) => {
|
122
|
-
return (arr.findIndex(({ name: name2, canonical_type: int2 }) => {
|
123
|
-
return (
|
124
|
-
// adapter-assigned name
|
125
|
-
name2 === name1 &&
|
126
|
-
// canonical type details
|
127
|
-
int2.name === int.name &&
|
128
|
-
int2.schema === int.schema &&
|
129
|
-
int2.kind === int.kind);
|
130
|
-
}) === index);
|
131
|
-
})
|
132
|
-
.filter(imp => imp.canonical_type.kind === Canonical.Kind.Base ||
|
133
|
-
allowed_kind_names.includes(`${imp.canonical_type.kind}s`))
|
134
|
-
.map(imp => {
|
135
|
-
const t = imp.canonical_type;
|
136
|
-
const schema = files.children[t.schema];
|
137
|
-
const kind = schema.children[`${t.kind}s`];
|
138
|
-
const type = kind.children[t.name];
|
139
|
-
const located_file = `${files.name}/${schema.name}/${kind.kind}/${type.name}.ts`;
|
140
|
-
return { ...imp, located_file };
|
141
|
-
});
|
142
|
-
const group_by_file = {};
|
143
|
-
for (const type of unique_types) {
|
144
|
-
const file = group_by_file[type.located_file] || [];
|
145
|
-
file.push(type);
|
146
|
-
group_by_file[type.located_file] = file;
|
147
|
-
}
|
148
|
-
for (const group in group_by_file) {
|
149
|
-
let relative_path = relative(dirname(context_file), group);
|
150
|
-
if (/^[^\.+\/]/.test(relative_path))
|
151
|
-
relative_path = "./" + relative_path;
|
152
|
-
const items = group_by_file[group];
|
153
|
-
const typeOnlys = items.filter(i => i.typeOnly);
|
154
|
-
const values = items.filter(i => !i.typeOnly);
|
155
|
-
const star = values.find(i => i.star);
|
156
|
-
let import_line = "import ";
|
157
|
-
const bits = [];
|
158
|
-
// if no values to import, use `import type { ... }` instead of `import { type ... }`
|
159
|
-
const typeInline = values.length !== 0;
|
160
|
-
for (const type of typeOnlys)
|
161
|
-
bits.push((typeInline ? "type " : "") + type.name);
|
162
|
-
for (const type of values)
|
163
|
-
bits.push(type.name);
|
164
|
-
if (bits.length)
|
165
|
-
import_line += (typeInline ? "" : "type ") + "{ " + bits.join(", ") + " }";
|
166
|
-
if (star)
|
167
|
-
import_line += `* as ${star.name}`;
|
168
|
-
import_line += ` from "${relative_path}";`;
|
169
|
-
imports.push(import_line);
|
170
|
-
}
|
171
|
-
out.push(join(imports, "\n"));
|
172
|
-
}
|
173
|
-
return join(out);
|
174
|
-
}
|
175
|
-
}
|
176
|
-
Nodes.ImportList = ImportList;
|
177
|
-
})(Nodes || (Nodes = {}));
|
3
|
+
export const allowed_kind_names = pgTypeKinds;
|
178
4
|
/* convenience function to create a generator with type inference */
|
179
5
|
export const createGenerator = (generatorCreator) => generatorCreator;
|
package/lib/util.d.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
export declare const eq: <T>(a: T, b: T) => boolean;
|
1
2
|
export declare const toPascalCase: (str: string) => string;
|
2
3
|
export declare const to_snake_case: (str: string) => string;
|
3
4
|
export declare const join: (parts: Iterable<string>, joiner?: string) => string;
|
@@ -9,6 +10,7 @@ export type Deunionise<B extends object | undefined, T = B> = Simplify<T extends
|
|
9
10
|
export type Simplify<T> = {
|
10
11
|
[KeyType in keyof T]: T[KeyType];
|
11
12
|
} & {};
|
13
|
+
export declare const parens: (str: string, type?: string) => string;
|
12
14
|
export declare const quote: (str: string, using?: string) => string;
|
13
15
|
export declare const quoteI: (str: string, using?: string) => string;
|
14
16
|
export {};
|
package/lib/util.js
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
export const eq = (a, b) => {
|
2
|
+
if (a === b)
|
3
|
+
return true;
|
4
|
+
if (a == null || b == null)
|
5
|
+
return false;
|
6
|
+
if (typeof a !== "object" || typeof b !== "object")
|
7
|
+
return false;
|
8
|
+
for (const key in a)
|
9
|
+
if (!eq(a[key], b[key]))
|
10
|
+
return false;
|
11
|
+
return true;
|
12
|
+
};
|
1
13
|
export const toPascalCase = (str) => {
|
2
14
|
let result = "";
|
3
15
|
let index = 0;
|
@@ -113,5 +125,6 @@ const isIdentifierInvalid = (str) => {
|
|
113
125
|
const invalid = str.match(/[^a-zA-Z0-9_]/);
|
114
126
|
return invalid !== null;
|
115
127
|
};
|
128
|
+
export const parens = (str, type = "()") => `${type[0]}${str}${type[1]}`;
|
116
129
|
export const quote = (str, using = '"') => `${using}${str.replaceAll(using, "\\" + using)}${using}`;
|
117
130
|
export const quoteI = (str, using = '"') => (isIdentifierInvalid(str) ? quote(str, using) : str);
|