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/index.js
CHANGED
@@ -1,14 +1,30 @@
|
|
1
1
|
import { Extractor, FunctionReturnTypeKind } from "./extractor/index.js";
|
2
2
|
import { rm, mkdir, writeFile } from "node:fs/promises";
|
3
|
-
import {
|
3
|
+
import { allowed_kind_names } from "./types.js";
|
4
|
+
import { ImportList } from "./imports.js";
|
4
5
|
import { existsSync } from "node:fs";
|
5
|
-
import { join } from "./util.js";
|
6
|
+
import { join, parens } from "./util.js";
|
6
7
|
import { join as joinpath } from "node:path";
|
7
|
-
import { config,
|
8
|
+
import { config, generators as builtin_generators } from "./config.js";
|
8
9
|
export { config };
|
9
|
-
const
|
10
|
-
|
11
|
-
|
10
|
+
const NO_COLOR = Boolean(process.env.NO_COLOR || process.env.CI);
|
11
|
+
const red = (str) => (NO_COLOR ? str : `\x1b[31m${str}\x1b[0m`);
|
12
|
+
const green = (str) => (NO_COLOR ? str : `\x1b[32m${str}\x1b[0m`);
|
13
|
+
const yellow = (str) => (NO_COLOR ? str : `\x1b[33m${str}\x1b[0m`);
|
14
|
+
const blue = (str) => (NO_COLOR ? str : `\x1b[34m${str}\x1b[0m`);
|
15
|
+
const bold = (str) => (NO_COLOR ? str : `\x1b[1m${str}\x1b[0m`);
|
16
|
+
const underline = (str) => (NO_COLOR ? str : `\x1b[4m${str}\x1b[0m`);
|
17
|
+
const THRESHOLD1 = 800;
|
18
|
+
const THRESHOLD2 = 1500;
|
19
|
+
const time = (start, addParens = true) => {
|
20
|
+
const diff = performance.now() - start;
|
21
|
+
const diffstr = diff.toFixed(2) + "ms";
|
22
|
+
const str = addParens ? parens(diffstr) : diffstr;
|
23
|
+
if (diff < THRESHOLD1)
|
24
|
+
return green(str);
|
25
|
+
if (diff < THRESHOLD2)
|
26
|
+
return yellow(str);
|
27
|
+
return red(str);
|
12
28
|
};
|
13
29
|
const filter_overloaded_functions = (functions) => {
|
14
30
|
const counts = functions.reduce((acc, func) => {
|
@@ -61,11 +77,15 @@ const filter_unsupported_functions = (functions) => {
|
|
61
77
|
const unsupported = filtered.filter(func => !filtered.includes(func));
|
62
78
|
return [filtered, unsupported];
|
63
79
|
};
|
64
|
-
const write = (filename, file) => writeFile(filename, file + "\n");
|
65
80
|
const multifile = async (generators, schemas, opts) => {
|
66
|
-
const { out } = opts;
|
67
|
-
|
68
|
-
const
|
81
|
+
const { out, defaultSchema } = opts;
|
82
|
+
let count = 0;
|
83
|
+
const write = async (filename, file) => {
|
84
|
+
await writeFile(filename, file + "\n");
|
85
|
+
count++;
|
86
|
+
};
|
87
|
+
const warnings = new Set();
|
88
|
+
const gens = generators.map(g => g({ defaultSchema, warnings }));
|
69
89
|
const def_gen = gens[0];
|
70
90
|
const files = {
|
71
91
|
name: out,
|
@@ -83,7 +103,7 @@ const multifile = async (generators, schemas, opts) => {
|
|
83
103
|
children: Object.fromEntries(schema[kind].map(item => [
|
84
104
|
item.name,
|
85
105
|
{
|
86
|
-
name: def_gen.
|
106
|
+
name: def_gen.formatSchemaMemberName(item),
|
87
107
|
type: "type",
|
88
108
|
},
|
89
109
|
])),
|
@@ -95,20 +115,20 @@ const multifile = async (generators, schemas, opts) => {
|
|
95
115
|
for (const schema of Object.values(schemas)) {
|
96
116
|
console.log("Selected schema '%s':\n", schema.name);
|
97
117
|
const schemaDir = joinpath(out, schema.name);
|
98
|
-
const [unique_functions, overloaded_functions] = filter_overloaded_functions(schema.
|
118
|
+
const [unique_functions, overloaded_functions] = filter_overloaded_functions(schema.function);
|
99
119
|
const [supported_functions, unsupported_functions] = filter_unsupported_functions(unique_functions);
|
100
|
-
schema.
|
120
|
+
schema.function = supported_functions;
|
101
121
|
{
|
102
122
|
const skipped = unsupported_functions.map(f => ` - ${f.name}`);
|
103
123
|
if (skipped.length) {
|
104
|
-
warnings.
|
124
|
+
warnings.add(`Skipping ${skipped.length} functions not representable in JavaScript (safe to ignore):\n` +
|
105
125
|
skipped.join("\n"));
|
106
126
|
}
|
107
127
|
}
|
108
128
|
{
|
109
129
|
const skipped = overloaded_functions.map(f => ` - ${f}`);
|
110
130
|
if (skipped.length) {
|
111
|
-
warnings.
|
131
|
+
warnings.add(`Skipping ${skipped.length} overloaded functions (not supported):\n` + skipped.join("\n"));
|
112
132
|
}
|
113
133
|
}
|
114
134
|
let createIndex = false;
|
@@ -116,73 +136,65 @@ const multifile = async (generators, schemas, opts) => {
|
|
116
136
|
if (schema[kind].length < 1)
|
117
137
|
continue;
|
118
138
|
createIndex = true;
|
119
|
-
|
120
|
-
|
139
|
+
const kindDir = joinpath(schemaDir, kind + "s");
|
140
|
+
await mkdir(kindDir, { recursive: true });
|
141
|
+
console.log(" Creating %s:\n", kind + "s");
|
121
142
|
for (const [i, item] of schema[kind].entries()) {
|
122
143
|
const index = "[" + (i + 1 + "]").padEnd(3, " ");
|
123
|
-
const filename = joinpath(
|
144
|
+
const filename = joinpath(kindDir, def_gen.formatSchemaMemberName(item) + ".ts");
|
124
145
|
const exists = await existsSync(filename);
|
125
146
|
if (exists) {
|
126
|
-
warnings.
|
147
|
+
warnings.add(`Skipping ${item.kind} "${item.name}": formatted name clashes. Wanted to create ${filename}`);
|
127
148
|
continue;
|
128
149
|
}
|
129
150
|
const start = performance.now();
|
130
151
|
let file = "";
|
131
|
-
const imports = new
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
// prettier-ignore
|
137
|
-
if (item.kind === "materializedView")
|
138
|
-
file += join(gens.map(gen => gen.materializedView(imports, item)));
|
139
|
-
if (item.kind === "enum")
|
140
|
-
file += join(gens.map(gen => gen.enum(imports, item)));
|
141
|
-
if (item.kind === "composite")
|
142
|
-
file += join(gens.map(gen => gen.composite(imports, item)));
|
143
|
-
if (item.kind === "domain")
|
144
|
-
file += join(gens.map(gen => gen.domain(imports, item)));
|
145
|
-
if (item.kind === "range")
|
146
|
-
file += join(gens.map(gen => gen.range(imports, item)));
|
147
|
-
if (item.kind === "function")
|
148
|
-
file += join(gens.map(gen => gen.function(imports, item)));
|
149
|
-
const parts = [];
|
150
|
-
parts.push(imports.stringify(filename, files));
|
151
|
-
parts.push(file);
|
152
|
-
file = join(parts);
|
152
|
+
const imports = new ImportList();
|
153
|
+
file += join(gens.map(gen => gen[item.kind]({ source: filename, imports },
|
154
|
+
// @ts-expect-error TypeScript cannot fathom the fact that item is related to item.kind
|
155
|
+
item)));
|
156
|
+
file = join([imports.stringify(files), file]);
|
153
157
|
await write(filename, file);
|
154
|
-
console.log(" %s %s
|
158
|
+
console.log(" %s %s %s", index, filename, time(start));
|
155
159
|
}
|
156
160
|
{
|
157
161
|
const start = performance.now();
|
158
|
-
const
|
159
|
-
const
|
160
|
-
|
161
|
-
const
|
162
|
-
|
162
|
+
const imports = new ImportList();
|
163
|
+
const fileName = joinpath(kindDir, "index.ts");
|
164
|
+
const kindIndex = join(gens.map(gen => gen.schemaKindIndex({ source: fileName, imports }, schema, kind, def_gen)));
|
165
|
+
const file = join([imports.stringify(files), kindIndex]);
|
166
|
+
await write(fileName, file);
|
167
|
+
console.log(" ✅ Created %s index: %s %s\n", kind, fileName, time(start));
|
163
168
|
}
|
164
169
|
}
|
165
170
|
if (!createIndex)
|
166
171
|
continue;
|
167
172
|
{
|
168
173
|
const start = performance.now();
|
169
|
-
const
|
170
|
-
const
|
171
|
-
|
172
|
-
|
174
|
+
const imports = new ImportList();
|
175
|
+
const fileName = joinpath(schemaDir, "index.ts");
|
176
|
+
const index = join(gens.map(gen => gen.schemaIndex({ source: fileName, imports }, schema, def_gen)));
|
177
|
+
const file = join([imports.stringify(files), index]);
|
178
|
+
await write(fileName, file);
|
179
|
+
console.log(" Created schema index: %s %s\n", fileName, time(start));
|
173
180
|
}
|
174
181
|
}
|
175
182
|
{
|
176
183
|
const start = performance.now();
|
177
|
-
const
|
178
|
-
const
|
179
|
-
|
180
|
-
|
184
|
+
const imports = new ImportList();
|
185
|
+
const fileName = joinpath(out, "index.ts");
|
186
|
+
const fullIndex = join(gens.map(gen => gen.fullIndex({ source: fileName, imports }, Object.values(schemas))));
|
187
|
+
const file = join([imports.stringify(files), fullIndex]);
|
188
|
+
await write(fileName, file);
|
189
|
+
console.log("Created full index: %s %s", fileName, time(start));
|
181
190
|
}
|
182
|
-
if (warnings.
|
191
|
+
if (warnings.size > 0) {
|
183
192
|
console.log("\nWarnings generated:");
|
184
|
-
|
193
|
+
for (const warning of warnings) {
|
194
|
+
console.log("* " + warning);
|
195
|
+
}
|
185
196
|
}
|
197
|
+
return count;
|
186
198
|
};
|
187
199
|
export async function generate(opts, generators) {
|
188
200
|
const validated = config(opts);
|
@@ -190,13 +202,13 @@ export async function generate(opts, generators) {
|
|
190
202
|
const extractor = new Extractor(opts);
|
191
203
|
const start = performance.now();
|
192
204
|
const schemas = await extractor.extractSchemas();
|
193
|
-
|
194
|
-
console.
|
195
|
-
|
196
|
-
generators = validated.adapters.map(adapter => adapters[adapter]).concat(generators ?? []);
|
205
|
+
console.log("Extracted schemas %s\n", time(start));
|
206
|
+
console.info("Generators enabled: %s\n", validated.generators.join(", "));
|
207
|
+
generators = validated.generators.map(generator => builtin_generators[generator]).concat(generators ?? []);
|
197
208
|
console.log("Clearing directory and generating schemas at '%s'\n", out);
|
198
209
|
await rm(out, { recursive: true, force: true });
|
199
210
|
await mkdir(out, { recursive: true });
|
200
|
-
await multifile(generators, schemas, validated);
|
201
|
-
console.log("Completed in
|
211
|
+
const count = await multifile(generators, schemas, validated);
|
212
|
+
console.log("Completed in %s, %s generated.", time(start, false), bold(underline(blue(count + " files"))));
|
213
|
+
console.log();
|
202
214
|
}
|
package/lib/kysely/index.js
CHANGED
@@ -1,149 +1,153 @@
|
|
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
|
-
// TODO: update imports for non-primitive types
|
51
36
|
out += `: ${qualified}`;
|
52
|
-
add(imports, col.type);
|
53
37
|
return `\t${out};\n`;
|
54
38
|
};
|
55
|
-
const composite_attribute = (
|
39
|
+
const composite_attribute = (ctx, generator, attr) => {
|
56
40
|
let out = quoteI(attr.name);
|
57
41
|
if (attr.isNullable)
|
58
42
|
out += "?";
|
59
|
-
out +=
|
60
|
-
|
61
|
-
if (attr.type.dimensions > 0)
|
62
|
-
out += "[]".repeat(attr.type.dimensions);
|
63
|
-
if (attr.isNullable)
|
64
|
-
out += " | null";
|
43
|
+
out += ": ";
|
44
|
+
out += generator.formatType(ctx, attr.type, { nullable: attr.isNullable });
|
65
45
|
return out;
|
66
46
|
};
|
67
47
|
const generator = {
|
68
|
-
|
48
|
+
formatSchemaName(name) {
|
69
49
|
return toPascalCase(name) + "Schema";
|
70
50
|
},
|
71
|
-
|
51
|
+
formatSchemaMemberName(type) {
|
72
52
|
return toPascalCase(type.name);
|
73
53
|
},
|
74
|
-
formatType(type) {
|
54
|
+
formatType(ctx, type, attr) {
|
55
|
+
let base;
|
75
56
|
if (type.kind === FunctionReturnTypeKind.ExistingTable) {
|
76
|
-
|
57
|
+
base = toPascalCase(type.name);
|
58
|
+
ctx.imports.add(Import.fromInternal({
|
59
|
+
source: ctx.source,
|
60
|
+
type,
|
61
|
+
withName: base,
|
62
|
+
typeOnly: true,
|
63
|
+
}));
|
77
64
|
}
|
78
|
-
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) {
|
79
68
|
const name = type.canonical_name;
|
80
69
|
const format = builtins[name];
|
81
70
|
if (format)
|
82
|
-
|
83
|
-
|
84
|
-
|
71
|
+
base = format;
|
72
|
+
else {
|
73
|
+
opts?.warnings?.add(`(kysely) Unknown base type: ${name}. Pass 'kysely.builtinMap' to map this type. Defaulting to "unknown".`);
|
74
|
+
base = "unknown";
|
75
|
+
}
|
85
76
|
}
|
86
|
-
|
77
|
+
else {
|
78
|
+
base = toPascalCase(type.name);
|
79
|
+
ctx.imports.add(Import.fromInternal({
|
80
|
+
source: ctx.source,
|
81
|
+
type,
|
82
|
+
withName: base,
|
83
|
+
typeOnly: true,
|
84
|
+
}));
|
85
|
+
}
|
86
|
+
if ("dimensions" in type)
|
87
|
+
base += "[]".repeat(type.dimensions);
|
88
|
+
if (attr?.nullable)
|
89
|
+
base += " | null";
|
90
|
+
return base;
|
87
91
|
},
|
88
|
-
table(
|
92
|
+
table(ctx, table) {
|
89
93
|
let out = "";
|
90
94
|
if (table.comment)
|
91
95
|
out += `/** ${table.comment} */\n`;
|
92
|
-
out += `export interface ${this.
|
96
|
+
out += `export interface ${this.formatSchemaMemberName(table)} {\n`;
|
93
97
|
for (const col of table.columns)
|
94
|
-
out += column(this,
|
98
|
+
out += column(this, ctx, col);
|
95
99
|
out += "}";
|
96
100
|
return out;
|
97
101
|
},
|
98
|
-
view(
|
102
|
+
view(ctx, view) {
|
99
103
|
let out = "";
|
100
104
|
if (view.comment)
|
101
105
|
out += `/** ${view.comment} */\n`;
|
102
|
-
out += `export interface ${this.
|
106
|
+
out += `export interface ${this.formatSchemaMemberName(view)} {\n`;
|
103
107
|
for (const col of view.columns)
|
104
|
-
out += column(this,
|
108
|
+
out += column(this, ctx, col);
|
105
109
|
out += "}";
|
106
110
|
return out;
|
107
111
|
},
|
108
|
-
materializedView(
|
112
|
+
materializedView(ctx, materializedView) {
|
109
113
|
let out = "";
|
110
114
|
if (materializedView.comment)
|
111
115
|
out += `/** ${materializedView.comment} */\n`;
|
112
|
-
out += `export interface ${this.
|
116
|
+
out += `export interface ${this.formatSchemaMemberName(materializedView)} {\n`;
|
113
117
|
for (const col of materializedView.columns)
|
114
|
-
out += column(this,
|
118
|
+
out += column(this, ctx, col);
|
115
119
|
out += "}";
|
116
120
|
return out;
|
117
121
|
},
|
118
|
-
enum(
|
122
|
+
enum(ctx, en) {
|
119
123
|
let out = "";
|
120
124
|
if (en.comment)
|
121
125
|
out += `/** ${en.comment} */\n`;
|
122
|
-
out += `export type ${this.
|
126
|
+
out += `export type ${this.formatSchemaMemberName(en)} = ${en.values.map(v => `"${v}"`).join(" | ")};`;
|
123
127
|
return out;
|
124
128
|
},
|
125
|
-
composite(
|
129
|
+
composite(ctx, type) {
|
126
130
|
let out = "";
|
127
131
|
if (type.comment)
|
128
132
|
out += `/** ${type.comment} */\n`;
|
129
|
-
out += `export interface ${this.
|
130
|
-
const props = type.canonical.attributes.map(c => composite_attribute(
|
133
|
+
out += `export interface ${this.formatSchemaMemberName(type)} {\n`;
|
134
|
+
const props = type.canonical.attributes.map(c => composite_attribute(ctx, this, c)).map(t => `\t${t};`);
|
131
135
|
out += props.join("\n");
|
132
136
|
out += "\n}";
|
133
137
|
return out;
|
134
138
|
},
|
135
|
-
domain(
|
139
|
+
domain(ctx, type) {
|
136
140
|
let out = "";
|
137
|
-
out += `export type ${this.
|
141
|
+
out += `export type ${this.formatSchemaMemberName(type)} = ${this.formatType(ctx, type.canonical.domain_base_type)};`;
|
138
142
|
return out;
|
139
143
|
},
|
140
|
-
range(
|
144
|
+
range(ctx, type) {
|
141
145
|
let out = "";
|
142
146
|
// force this to be string because range has to be passed as a string to Kysely
|
143
|
-
out += `export type ${this.
|
147
|
+
out += `export type ${this.formatSchemaMemberName(type)} = string;`;
|
144
148
|
return out;
|
145
149
|
},
|
146
|
-
function(
|
150
|
+
function(ctx, type) {
|
147
151
|
let out = "";
|
148
152
|
out += "/**\n";
|
149
153
|
if (type.comment)
|
@@ -152,7 +156,7 @@ export const Kysely = createGenerator(opts => {
|
|
152
156
|
out += ` * @parallelSafety ${type.parallelSafety}\n`;
|
153
157
|
out += ` * @isStrict ${type.isStrict}\n`;
|
154
158
|
out += " */\n";
|
155
|
-
out += `export interface ${this.
|
159
|
+
out += `export interface ${this.formatSchemaMemberName(type)} {\n\t`;
|
156
160
|
// Get the input parameters (those that appear in function signature)
|
157
161
|
const inputParams = type.parameters.filter(p => p.mode === "IN" || p.mode === "INOUT" || p.mode === "VARIADIC");
|
158
162
|
if (inputParams.length === 0) {
|
@@ -162,10 +166,7 @@ export const Kysely = createGenerator(opts => {
|
|
162
166
|
out += "(";
|
163
167
|
out += inputParams[0].name;
|
164
168
|
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);
|
169
|
+
out += this.formatType(ctx, inputParams[0].type);
|
169
170
|
out += "): ";
|
170
171
|
}
|
171
172
|
else if (inputParams.length > 0) {
|
@@ -177,10 +178,7 @@ export const Kysely = createGenerator(opts => {
|
|
177
178
|
out += `\t\t${paramName}`;
|
178
179
|
if (param.hasDefault && !isVariadic)
|
179
180
|
out += "?";
|
180
|
-
out += `: ${this.formatType(param.type)}`;
|
181
|
-
add(imports, param.type);
|
182
|
-
if (param.type.dimensions > 0)
|
183
|
-
out += "[]".repeat(param.type.dimensions);
|
181
|
+
out += `: ${this.formatType(ctx, param.type)}`;
|
184
182
|
if (!isVariadic)
|
185
183
|
out += ",";
|
186
184
|
out += "\n";
|
@@ -194,24 +192,17 @@ export const Kysely = createGenerator(opts => {
|
|
194
192
|
out += "{\n";
|
195
193
|
for (const col of type.returnType.columns) {
|
196
194
|
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);
|
195
|
+
out += this.formatType(ctx, col.type);
|
201
196
|
out += `;\n`;
|
202
197
|
}
|
203
198
|
out += "\t}";
|
204
199
|
}
|
205
200
|
}
|
206
201
|
else if (type.returnType.kind === FunctionReturnTypeKind.ExistingTable) {
|
207
|
-
out += this.formatType(type.returnType);
|
208
|
-
add(imports, type.returnType);
|
202
|
+
out += this.formatType(ctx, type.returnType);
|
209
203
|
}
|
210
204
|
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);
|
205
|
+
out += this.formatType(ctx, type.returnType.type);
|
215
206
|
}
|
216
207
|
// Add additional array brackets if it returns a set
|
217
208
|
if (type.returnType.isSet) {
|
@@ -220,32 +211,33 @@ export const Kysely = createGenerator(opts => {
|
|
220
211
|
out += ";\n}";
|
221
212
|
return out;
|
222
213
|
},
|
223
|
-
schemaKindIndex(schema, kind, main_generator) {
|
214
|
+
schemaKindIndex(ctx, schema, kind, main_generator) {
|
224
215
|
const generator = main_generator ?? this;
|
225
216
|
const imports = schema[kind];
|
226
217
|
if (imports.length === 0)
|
227
218
|
return "";
|
228
219
|
return imports
|
229
220
|
.map(each => {
|
230
|
-
const name =
|
231
|
-
const file = generator.
|
221
|
+
const name = generator.formatSchemaMemberName(each);
|
222
|
+
const file = generator.formatSchemaMemberName(each);
|
232
223
|
return `export type { ${name} } from "./${file}.ts";`;
|
233
224
|
})
|
234
225
|
.join("\n");
|
235
226
|
},
|
236
|
-
schemaIndex(schema) {
|
227
|
+
schemaIndex(ctx, schema) {
|
237
228
|
const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
|
238
|
-
|
229
|
+
// we could in theory use the imports from GeneratorContext here, but this works fine
|
230
|
+
let out = actual_kinds.map(kind => `import type * as ${kind}s from "./${kind}s/index.ts";`).join("\n");
|
239
231
|
out += "\n\n";
|
240
|
-
out += `export interface ${this.
|
232
|
+
out += `export interface ${this.formatSchemaName(schema.name)} {\n`;
|
241
233
|
for (const kind of actual_kinds) {
|
242
234
|
const items = schema[kind];
|
243
235
|
if (items.length === 0)
|
244
236
|
continue;
|
245
|
-
out += `\t${kind}: {\n`;
|
237
|
+
out += `\t${kind}s: {\n`;
|
246
238
|
const formatted = items
|
247
239
|
.map(each => {
|
248
|
-
const formatted =
|
240
|
+
const formatted = generator.formatSchemaMemberName(each);
|
249
241
|
return { ...each, formatted };
|
250
242
|
})
|
251
243
|
.filter(x => x !== undefined);
|
@@ -260,22 +252,22 @@ export const Kysely = createGenerator(opts => {
|
|
260
252
|
out += "}";
|
261
253
|
return out;
|
262
254
|
},
|
263
|
-
fullIndex(schemas) {
|
255
|
+
fullIndex(ctx, schemas) {
|
264
256
|
const parts = [];
|
265
257
|
parts.push(schemas
|
266
|
-
.map(s => `import type { ${
|
258
|
+
.map(s => `import type { ${generator.formatSchemaName(s.name)} } from "./${s.name}/index.ts";`)
|
267
259
|
.join("\n"));
|
268
260
|
{
|
269
261
|
let iface = `export interface Database {\n`;
|
270
262
|
iface += schemas
|
271
263
|
.map(schema => {
|
272
264
|
// only tables, views, and materialized views are queryable
|
273
|
-
const tables = [...schema.
|
265
|
+
const tables = [...schema.table, ...schema.view, ...schema.materializedView];
|
274
266
|
let out = "";
|
275
267
|
const seen = new Set();
|
276
268
|
const formatted = tables
|
277
269
|
.map(each => {
|
278
|
-
const formatted =
|
270
|
+
const formatted = generator.formatSchemaMemberName(each);
|
279
271
|
// skip clashing names
|
280
272
|
if (seen.has(formatted))
|
281
273
|
return;
|
@@ -294,7 +286,7 @@ export const Kysely = createGenerator(opts => {
|
|
294
286
|
else
|
295
287
|
qualified = t.name;
|
296
288
|
qualified = quoteI(qualified);
|
297
|
-
return `\t${qualified}: ${
|
289
|
+
return `\t${qualified}: ${generator.formatSchemaName(schema.name)}[${quote(t.kind + "s")}][${quote(t.name)}];`;
|
298
290
|
})
|
299
291
|
.join("\n");
|
300
292
|
return out;
|
@@ -303,7 +295,7 @@ export const Kysely = createGenerator(opts => {
|
|
303
295
|
iface += "\n}";
|
304
296
|
parts.push(iface);
|
305
297
|
}
|
306
|
-
parts.push(schemas.map(s => `export type { ${
|
298
|
+
parts.push(schemas.map(s => `export type { ${generator.formatSchemaName(s.name)} };`).join("\n"));
|
307
299
|
return join(parts);
|
308
300
|
},
|
309
301
|
};
|