true-pg 0.5.0 → 0.5.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 +17 -17
- package/lib/bin.js +16 -16
- package/lib/config.d.ts +6 -6
- package/lib/config.js +8 -8
- package/lib/imports.d.ts +35 -0
- package/lib/imports.js +102 -0
- package/lib/index.js +70 -59
- package/lib/kysely/index.js +77 -90
- package/lib/types.d.ts +29 -74
- package/lib/types.js +0 -165
- package/lib/util.d.ts +2 -0
- package/lib/util.js +13 -0
- package/lib/zod/index.js +91 -93
- package/package.json +3 -2
package/lib/kysely/index.js
CHANGED
@@ -1,149 +1,148 @@
|
|
1
1
|
import { Canonical, FunctionReturnTypeKind, } from "../extractor/index.js";
|
2
|
-
import { allowed_kind_names, createGenerator
|
2
|
+
import { allowed_kind_names, createGenerator } from "../types.js";
|
3
|
+
import { Import } from "../imports.js";
|
3
4
|
import { builtins } from "./builtins.js";
|
4
5
|
import { toPascalCase, join, quote, quoteI } from "../util.js";
|
5
6
|
export const Kysely = createGenerator(opts => {
|
6
7
|
const defaultSchema = opts?.defaultSchema ?? "public";
|
7
|
-
const ky = (
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
star: false,
|
12
|
-
}));
|
13
|
-
const add = (imports, type) => {
|
14
|
-
if (type.schema === "pg_catalog")
|
15
|
-
return;
|
16
|
-
imports.add(new Nodes.InternalImport({
|
17
|
-
name: generator.formatType(type),
|
18
|
-
canonical_type: type,
|
8
|
+
const ky = (ctx, name) => {
|
9
|
+
ctx.imports.add(new Import({
|
10
|
+
from: "kysely",
|
11
|
+
namedImports: [name],
|
19
12
|
typeOnly: true,
|
20
|
-
star: false,
|
21
13
|
}));
|
22
14
|
};
|
23
15
|
const column = (
|
24
16
|
/** "this" */
|
25
|
-
generator,
|
26
|
-
/** @out Append used types to this array */
|
27
|
-
imports,
|
17
|
+
generator, ctx,
|
28
18
|
/** Information about the column */
|
29
19
|
col) => {
|
30
|
-
let base = generator.formatType(col.type);
|
31
|
-
if (col.type.dimensions > 0)
|
32
|
-
base += "[]".repeat(col.type.dimensions);
|
33
|
-
if (col.isNullable)
|
34
|
-
base += " | null";
|
20
|
+
let base = generator.formatType(ctx, col.type, { nullable: col.isNullable });
|
35
21
|
let qualified = base;
|
36
22
|
if (col.generated === "ALWAYS") {
|
37
23
|
qualified = `GeneratedAlways<${qualified}>`;
|
38
|
-
ky(
|
24
|
+
ky(ctx, "GeneratedAlways");
|
39
25
|
}
|
40
26
|
else if (col.generated === "BY DEFAULT") {
|
41
27
|
qualified = `Generated<${qualified}>`;
|
42
|
-
ky(
|
28
|
+
ky(ctx, "Generated");
|
43
29
|
}
|
44
30
|
else if (col.defaultValue) {
|
45
31
|
qualified = `Generated<${qualified}>`;
|
46
|
-
ky(
|
32
|
+
ky(ctx, "Generated");
|
47
33
|
}
|
48
34
|
let out = col.comment ? `/** ${col.comment} */\n\t` : "";
|
49
35
|
out += quoteI(col.name);
|
50
36
|
// TODO: update imports for non-primitive types
|
51
37
|
out += `: ${qualified}`;
|
52
|
-
add(imports, col.type);
|
53
38
|
return `\t${out};\n`;
|
54
39
|
};
|
55
|
-
const composite_attribute = (
|
40
|
+
const composite_attribute = (ctx, generator, attr) => {
|
56
41
|
let out = quoteI(attr.name);
|
57
42
|
if (attr.isNullable)
|
58
43
|
out += "?";
|
59
|
-
out +=
|
60
|
-
|
61
|
-
if (attr.type.dimensions > 0)
|
62
|
-
out += "[]".repeat(attr.type.dimensions);
|
63
|
-
if (attr.isNullable)
|
64
|
-
out += " | null";
|
44
|
+
out += ": ";
|
45
|
+
out += generator.formatType(ctx, attr.type, { nullable: attr.isNullable });
|
65
46
|
return out;
|
66
47
|
};
|
67
48
|
const generator = {
|
68
|
-
|
49
|
+
formatSchemaName(name) {
|
69
50
|
return toPascalCase(name) + "Schema";
|
70
51
|
},
|
71
|
-
|
52
|
+
formatSchemaMemberName(type) {
|
72
53
|
return toPascalCase(type.name);
|
73
54
|
},
|
74
|
-
formatType(type) {
|
55
|
+
formatType(ctx, type, attr) {
|
56
|
+
let base;
|
75
57
|
if (type.kind === FunctionReturnTypeKind.ExistingTable) {
|
76
|
-
|
58
|
+
base = toPascalCase(type.name);
|
77
59
|
}
|
78
60
|
else if (type.schema === "pg_catalog") {
|
79
61
|
const name = type.canonical_name;
|
80
62
|
const format = builtins[name];
|
81
63
|
if (format)
|
82
|
-
|
83
|
-
|
84
|
-
|
64
|
+
base = format;
|
65
|
+
else {
|
66
|
+
opts?.warnings?.add(`(kysely) Unknown builtin type: ${name}. Pass 'kysely.builtinMap' to map this type. Defaulting to "unknown".`);
|
67
|
+
base = "unknown";
|
68
|
+
}
|
85
69
|
}
|
86
|
-
|
70
|
+
else
|
71
|
+
base = toPascalCase(type.name);
|
72
|
+
if (type.schema !== "pg_catalog") {
|
73
|
+
// before adding modifiers, add the import
|
74
|
+
ctx.imports.add(Import.fromInternal({
|
75
|
+
source: ctx.source,
|
76
|
+
type,
|
77
|
+
withName: base,
|
78
|
+
typeOnly: true,
|
79
|
+
}));
|
80
|
+
}
|
81
|
+
if ("dimensions" in type)
|
82
|
+
base += "[]".repeat(type.dimensions);
|
83
|
+
if (attr?.nullable)
|
84
|
+
base += " | null";
|
85
|
+
return base;
|
87
86
|
},
|
88
|
-
table(
|
87
|
+
table(ctx, table) {
|
89
88
|
let out = "";
|
90
89
|
if (table.comment)
|
91
90
|
out += `/** ${table.comment} */\n`;
|
92
|
-
out += `export interface ${this.
|
91
|
+
out += `export interface ${this.formatSchemaMemberName(table)} {\n`;
|
93
92
|
for (const col of table.columns)
|
94
|
-
out += column(this,
|
93
|
+
out += column(this, ctx, col);
|
95
94
|
out += "}";
|
96
95
|
return out;
|
97
96
|
},
|
98
|
-
view(
|
97
|
+
view(ctx, view) {
|
99
98
|
let out = "";
|
100
99
|
if (view.comment)
|
101
100
|
out += `/** ${view.comment} */\n`;
|
102
|
-
out += `export interface ${this.
|
101
|
+
out += `export interface ${this.formatSchemaMemberName(view)} {\n`;
|
103
102
|
for (const col of view.columns)
|
104
|
-
out += column(this,
|
103
|
+
out += column(this, ctx, col);
|
105
104
|
out += "}";
|
106
105
|
return out;
|
107
106
|
},
|
108
|
-
materializedView(
|
107
|
+
materializedView(ctx, materializedView) {
|
109
108
|
let out = "";
|
110
109
|
if (materializedView.comment)
|
111
110
|
out += `/** ${materializedView.comment} */\n`;
|
112
|
-
out += `export interface ${this.
|
111
|
+
out += `export interface ${this.formatSchemaMemberName(materializedView)} {\n`;
|
113
112
|
for (const col of materializedView.columns)
|
114
|
-
out += column(this,
|
113
|
+
out += column(this, ctx, col);
|
115
114
|
out += "}";
|
116
115
|
return out;
|
117
116
|
},
|
118
|
-
enum(
|
117
|
+
enum(ctx, en) {
|
119
118
|
let out = "";
|
120
119
|
if (en.comment)
|
121
120
|
out += `/** ${en.comment} */\n`;
|
122
|
-
out += `export type ${this.
|
121
|
+
out += `export type ${this.formatSchemaMemberName(en)} = ${en.values.map(v => `"${v}"`).join(" | ")};`;
|
123
122
|
return out;
|
124
123
|
},
|
125
|
-
composite(
|
124
|
+
composite(ctx, type) {
|
126
125
|
let out = "";
|
127
126
|
if (type.comment)
|
128
127
|
out += `/** ${type.comment} */\n`;
|
129
|
-
out += `export interface ${this.
|
130
|
-
const props = type.canonical.attributes.map(c => composite_attribute(
|
128
|
+
out += `export interface ${this.formatSchemaMemberName(type)} {\n`;
|
129
|
+
const props = type.canonical.attributes.map(c => composite_attribute(ctx, this, c)).map(t => `\t${t};`);
|
131
130
|
out += props.join("\n");
|
132
131
|
out += "\n}";
|
133
132
|
return out;
|
134
133
|
},
|
135
|
-
domain(
|
134
|
+
domain(ctx, type) {
|
136
135
|
let out = "";
|
137
|
-
out += `export type ${this.
|
136
|
+
out += `export type ${this.formatSchemaMemberName(type)} = ${this.formatType(ctx, type.canonical.domain_base_type)};`;
|
138
137
|
return out;
|
139
138
|
},
|
140
|
-
range(
|
139
|
+
range(ctx, type) {
|
141
140
|
let out = "";
|
142
141
|
// force this to be string because range has to be passed as a string to Kysely
|
143
|
-
out += `export type ${this.
|
142
|
+
out += `export type ${this.formatSchemaMemberName(type)} = string;`;
|
144
143
|
return out;
|
145
144
|
},
|
146
|
-
function(
|
145
|
+
function(ctx, type) {
|
147
146
|
let out = "";
|
148
147
|
out += "/**\n";
|
149
148
|
if (type.comment)
|
@@ -152,7 +151,7 @@ export const Kysely = createGenerator(opts => {
|
|
152
151
|
out += ` * @parallelSafety ${type.parallelSafety}\n`;
|
153
152
|
out += ` * @isStrict ${type.isStrict}\n`;
|
154
153
|
out += " */\n";
|
155
|
-
out += `export interface ${this.
|
154
|
+
out += `export interface ${this.formatSchemaMemberName(type)} {\n\t`;
|
156
155
|
// Get the input parameters (those that appear in function signature)
|
157
156
|
const inputParams = type.parameters.filter(p => p.mode === "IN" || p.mode === "INOUT" || p.mode === "VARIADIC");
|
158
157
|
if (inputParams.length === 0) {
|
@@ -162,10 +161,7 @@ export const Kysely = createGenerator(opts => {
|
|
162
161
|
out += "(";
|
163
162
|
out += inputParams[0].name;
|
164
163
|
out += ": ";
|
165
|
-
out += this.formatType(inputParams[0].type);
|
166
|
-
add(imports, inputParams[0].type);
|
167
|
-
if (inputParams[0].type.dimensions > 0)
|
168
|
-
out += "[]".repeat(inputParams[0].type.dimensions);
|
164
|
+
out += this.formatType(ctx, inputParams[0].type);
|
169
165
|
out += "): ";
|
170
166
|
}
|
171
167
|
else if (inputParams.length > 0) {
|
@@ -177,10 +173,7 @@ export const Kysely = createGenerator(opts => {
|
|
177
173
|
out += `\t\t${paramName}`;
|
178
174
|
if (param.hasDefault && !isVariadic)
|
179
175
|
out += "?";
|
180
|
-
out += `: ${this.formatType(param.type)}`;
|
181
|
-
add(imports, param.type);
|
182
|
-
if (param.type.dimensions > 0)
|
183
|
-
out += "[]".repeat(param.type.dimensions);
|
176
|
+
out += `: ${this.formatType(ctx, param.type)}`;
|
184
177
|
if (!isVariadic)
|
185
178
|
out += ",";
|
186
179
|
out += "\n";
|
@@ -194,24 +187,17 @@ export const Kysely = createGenerator(opts => {
|
|
194
187
|
out += "{\n";
|
195
188
|
for (const col of type.returnType.columns) {
|
196
189
|
out += `\t\t"${col.name}": `;
|
197
|
-
out += this.formatType(col.type);
|
198
|
-
add(imports, col.type);
|
199
|
-
if (col.type.dimensions > 0)
|
200
|
-
out += "[]".repeat(col.type.dimensions);
|
190
|
+
out += this.formatType(ctx, col.type);
|
201
191
|
out += `;\n`;
|
202
192
|
}
|
203
193
|
out += "\t}";
|
204
194
|
}
|
205
195
|
}
|
206
196
|
else if (type.returnType.kind === FunctionReturnTypeKind.ExistingTable) {
|
207
|
-
out += this.formatType(type.returnType);
|
208
|
-
add(imports, type.returnType);
|
197
|
+
out += this.formatType(ctx, type.returnType);
|
209
198
|
}
|
210
199
|
else {
|
211
|
-
out += this.formatType(type.returnType.type);
|
212
|
-
add(imports, type.returnType.type);
|
213
|
-
if (type.returnType.type.dimensions > 0)
|
214
|
-
out += "[]".repeat(type.returnType.type.dimensions);
|
200
|
+
out += this.formatType(ctx, type.returnType.type);
|
215
201
|
}
|
216
202
|
// Add additional array brackets if it returns a set
|
217
203
|
if (type.returnType.isSet) {
|
@@ -220,24 +206,25 @@ export const Kysely = createGenerator(opts => {
|
|
220
206
|
out += ";\n}";
|
221
207
|
return out;
|
222
208
|
},
|
223
|
-
schemaKindIndex(schema, kind, main_generator) {
|
209
|
+
schemaKindIndex(ctx, schema, kind, main_generator) {
|
224
210
|
const generator = main_generator ?? this;
|
225
211
|
const imports = schema[kind];
|
226
212
|
if (imports.length === 0)
|
227
213
|
return "";
|
228
214
|
return imports
|
229
215
|
.map(each => {
|
230
|
-
const name =
|
231
|
-
const file = generator.
|
216
|
+
const name = generator.formatSchemaMemberName(each);
|
217
|
+
const file = generator.formatSchemaMemberName(each);
|
232
218
|
return `export type { ${name} } from "./${file}.ts";`;
|
233
219
|
})
|
234
220
|
.join("\n");
|
235
221
|
},
|
236
|
-
schemaIndex(schema) {
|
222
|
+
schemaIndex(ctx, schema) {
|
237
223
|
const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
|
224
|
+
// we could in theory use the imports from GeneratorContext here, but this works fine
|
238
225
|
let out = actual_kinds.map(kind => `import type * as ${kind} from "./${kind}/index.ts";`).join("\n");
|
239
226
|
out += "\n\n";
|
240
|
-
out += `export interface ${this.
|
227
|
+
out += `export interface ${this.formatSchemaName(schema.name)} {\n`;
|
241
228
|
for (const kind of actual_kinds) {
|
242
229
|
const items = schema[kind];
|
243
230
|
if (items.length === 0)
|
@@ -245,7 +232,7 @@ export const Kysely = createGenerator(opts => {
|
|
245
232
|
out += `\t${kind}: {\n`;
|
246
233
|
const formatted = items
|
247
234
|
.map(each => {
|
248
|
-
const formatted =
|
235
|
+
const formatted = generator.formatSchemaMemberName(each);
|
249
236
|
return { ...each, formatted };
|
250
237
|
})
|
251
238
|
.filter(x => x !== undefined);
|
@@ -260,10 +247,10 @@ export const Kysely = createGenerator(opts => {
|
|
260
247
|
out += "}";
|
261
248
|
return out;
|
262
249
|
},
|
263
|
-
fullIndex(schemas) {
|
250
|
+
fullIndex(ctx, schemas) {
|
264
251
|
const parts = [];
|
265
252
|
parts.push(schemas
|
266
|
-
.map(s => `import type { ${
|
253
|
+
.map(s => `import type { ${generator.formatSchemaName(s.name)} } from "./${s.name}/index.ts";`)
|
267
254
|
.join("\n"));
|
268
255
|
{
|
269
256
|
let iface = `export interface Database {\n`;
|
@@ -275,7 +262,7 @@ export const Kysely = createGenerator(opts => {
|
|
275
262
|
const seen = new Set();
|
276
263
|
const formatted = tables
|
277
264
|
.map(each => {
|
278
|
-
const formatted =
|
265
|
+
const formatted = generator.formatSchemaMemberName(each);
|
279
266
|
// skip clashing names
|
280
267
|
if (seen.has(formatted))
|
281
268
|
return;
|
@@ -294,7 +281,7 @@ export const Kysely = createGenerator(opts => {
|
|
294
281
|
else
|
295
282
|
qualified = t.name;
|
296
283
|
qualified = quoteI(qualified);
|
297
|
-
return `\t${qualified}: ${
|
284
|
+
return `\t${qualified}: ${generator.formatSchemaName(schema.name)}[${quote(t.kind + "s")}][${quote(t.name)}];`;
|
298
285
|
})
|
299
286
|
.join("\n");
|
300
287
|
return out;
|
@@ -303,7 +290,7 @@ export const Kysely = createGenerator(opts => {
|
|
303
290
|
iface += "\n}";
|
304
291
|
parts.push(iface);
|
305
292
|
}
|
306
|
-
parts.push(schemas.map(s => `export type { ${
|
293
|
+
parts.push(schemas.map(s => `export type { ${generator.formatSchemaName(s.name)} };`).join("\n"));
|
307
294
|
return join(parts);
|
308
295
|
},
|
309
296
|
};
|
package/lib/types.d.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
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
|
+
import type { ImportList } from "./imports.ts";
|
2
3
|
export declare const allowed_kind_names: readonly ["tables", "views", "materializedViews", "enums", "composites", "functions", "domains", "ranges"];
|
3
4
|
export type allowed_kind_names = (typeof allowed_kind_names)[number];
|
4
5
|
export interface FolderStructure {
|
@@ -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,6 +1,4 @@
|
|
1
1
|
import { Canonical, } from "./extractor/index.js";
|
2
|
-
import { dirname, relative } from "node:path/posix";
|
3
|
-
import { join } from "./util.js";
|
4
2
|
// To be updated when we add support for other kinds
|
5
3
|
export const allowed_kind_names = [
|
6
4
|
"tables",
|
@@ -12,168 +10,5 @@ export const allowed_kind_names = [
|
|
12
10
|
"domains",
|
13
11
|
"ranges",
|
14
12
|
];
|
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 = {}));
|
178
13
|
/* convenience function to create a generator with type inference */
|
179
14
|
export const createGenerator = (generatorCreator) => generatorCreator;
|