@technicity/data-service-generator 0.14.1 → 0.14.3
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 +2 -0
- package/dist/generation/generate.d.ts +1 -0
- package/dist/generation/generate.js +916 -309
- package/dist/runtime/Cache.js +6 -3
- package/dist/runtime/IRuntime.d.ts +46 -17
- package/dist/runtime/RuntimeMSSQL.d.ts +7 -1
- package/dist/runtime/RuntimeMSSQL.js +4 -4
- package/dist/runtime/RuntimeMySQL.d.ts +3 -1
- package/dist/runtime/RuntimeMySQL.js +33 -7
- package/dist/runtime/RuntimeSQLite.d.ts +38 -0
- package/dist/runtime/RuntimeSQLite.js +135 -0
- package/dist/runtime/lib/MSSQL.d.ts +2 -1
- package/dist/runtime/lib/MSSQL.js +36 -8
- package/dist/runtime/lib/MySQL.d.ts +1 -1
- package/dist/runtime/lib/MySQL.js +15 -2
- package/dist/runtime/lib/addNullFallbacks.test.d.ts +1 -0
- package/dist/runtime/lib/addNullFallbacks.test.js +206 -0
- package/dist/runtime/lib/getSqlAst.js +158 -121
- package/dist/runtime/lib/shared.d.ts +1 -2
- package/dist/runtime/lib/shared.js +180 -71
- package/dist/runtime/lib/stringifyWhere.js +39 -12
- package/dist/runtime/lib/stringifyWhere.test.d.ts +1 -0
- package/dist/runtime/lib/stringifyWhere.test.js +236 -0
- package/dist/runtime/lib/typeCastMSSQL.js +24 -1
- package/dist/traverseFieldArgs.d.ts +2 -2
- package/dist/traverseFieldArgs.js +8 -3
- package/dist/traverseFieldArgs.test.d.ts +1 -0
- package/dist/traverseFieldArgs.test.js +56 -0
- package/package.json +3 -6
- package/dist/ksql.d.ts +0 -15
- package/dist/ksql.js +0 -55
- package/dist/runtime/RuntimeKSQL.d.ts +0 -19
- package/dist/runtime/RuntimeKSQL.js +0 -446
- package/dist/runtime/lib/runTransforms.d.ts +0 -2
- package/dist/runtime/lib/runTransforms.js +0 -36
|
@@ -1,18 +1,44 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
2
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
29
|
exports.generate = void 0;
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const fs = require("fs");
|
|
6
|
-
const os = require("os");
|
|
7
|
-
const child_process = require("child_process");
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const mssql = require("mssql");
|
|
30
|
+
const path = __importStar(require("node:path"));
|
|
31
|
+
const fs = __importStar(require("node:fs"));
|
|
32
|
+
const os = __importStar(require("node:os"));
|
|
33
|
+
const child_process = __importStar(require("node:child_process"));
|
|
34
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
35
|
+
const prettier = __importStar(require("prettier"));
|
|
36
|
+
const changeCase = __importStar(require("change-case"));
|
|
37
|
+
const fse = __importStar(require("fs-extra"));
|
|
38
|
+
const _ = __importStar(require("lodash/fp"));
|
|
39
|
+
const mssql = __importStar(require("mssql"));
|
|
14
40
|
// @ts-ignore
|
|
15
|
-
const TSqlString = require("tsqlstring");
|
|
41
|
+
const TSqlString = __importStar(require("tsqlstring"));
|
|
16
42
|
const json_schema_to_typescript_1 = require("json-schema-to-typescript");
|
|
17
43
|
const getDuplicates_1 = require("../lib/getDuplicates");
|
|
18
44
|
const isNotNullOrUndefined_1 = require("../lib/isNotNullOrUndefined");
|
|
@@ -25,8 +51,9 @@ const MySQL_1 = require("../runtime/lib/MySQL");
|
|
|
25
51
|
let query = undefined;
|
|
26
52
|
let dialect = "mysql";
|
|
27
53
|
const json2TsOpts = {
|
|
28
|
-
bannerComment: ""
|
|
54
|
+
bannerComment: ""
|
|
29
55
|
};
|
|
56
|
+
const keyFields = "$fields";
|
|
30
57
|
async function generate(input) {
|
|
31
58
|
if (input.tables != null && input.excludeTables != null) {
|
|
32
59
|
throw new Error("Must specify either `tables` or `excludeTables`, not both");
|
|
@@ -57,22 +84,26 @@ async function generate(input) {
|
|
|
57
84
|
getPatchOneData(x, specialCaseUuidColumn, includeMappedFields),
|
|
58
85
|
getPatchListData(x),
|
|
59
86
|
getDeleteOneData(x),
|
|
60
|
-
getDeleteListData(x)
|
|
87
|
+
getDeleteListData(x)
|
|
61
88
|
]));
|
|
62
|
-
const
|
|
63
|
-
const
|
|
89
|
+
const artifacts = await getArtifacts(tables, includeMappedFields, specialCaseUuidColumn);
|
|
90
|
+
const artifactsSource = getArtifactsSource(artifacts);
|
|
91
|
+
const sdkSource = await getSDKSource(data, specialCaseUuidColumn, supplementClientOpts, artifacts);
|
|
64
92
|
const sdkFilename = "index.ts";
|
|
93
|
+
const sourceIRuntimeFilePath = fs.existsSync(path.join(__dirname, "../runtime", "IRuntime.ts"))
|
|
94
|
+
? path.join(__dirname, "../runtime", "IRuntime.ts")
|
|
95
|
+
: path.join(__dirname, "../runtime", "IRuntime.js");
|
|
96
|
+
const IRuntimeFilename = path.basename(sourceIRuntimeFilePath);
|
|
65
97
|
const artifactsFilename = "artifacts.ts";
|
|
66
|
-
const IRuntimeFilename = "IRuntime.d.ts";
|
|
67
98
|
const tsConfigJSON = {
|
|
68
99
|
compilerOptions: {
|
|
69
100
|
module: "commonjs",
|
|
70
101
|
moduleResolution: "node",
|
|
71
102
|
target: "es2020",
|
|
72
103
|
declaration: true,
|
|
73
|
-
outDir: "./sdk-ts"
|
|
104
|
+
outDir: "./sdk-ts"
|
|
74
105
|
},
|
|
75
|
-
include: [sdkFilename, artifactsFilename, IRuntimeFilename]
|
|
106
|
+
include: [sdkFilename, artifactsFilename, IRuntimeFilename]
|
|
76
107
|
};
|
|
77
108
|
const packageJSON = {
|
|
78
109
|
name: "temp",
|
|
@@ -81,14 +112,15 @@ async function generate(input) {
|
|
|
81
112
|
dependencies: require("../../package.json").dependencies,
|
|
82
113
|
devDependencies: {
|
|
83
114
|
"@types/node": require("../../package.json").devDependencies["@types/node"],
|
|
84
|
-
typescript: require("../../package.json").devDependencies.typescript
|
|
85
|
-
}
|
|
115
|
+
typescript: require("../../package.json").devDependencies.typescript
|
|
116
|
+
}
|
|
86
117
|
};
|
|
87
|
-
const tmpDirPath = path.join(os.tmpdir(),
|
|
118
|
+
const tmpDirPath = path.join(os.tmpdir(),
|
|
119
|
+
// _ because - in filename is not supported by mysql2sqlite
|
|
120
|
+
`dsg_${node_crypto_1.default.randomUUID()}`.replace(/-/g, "_"));
|
|
88
121
|
fse.mkdirpSync(tmpDirPath);
|
|
89
122
|
fs.writeFileSync(path.join(tmpDirPath, sdkFilename), sdkSource);
|
|
90
123
|
fs.writeFileSync(path.join(tmpDirPath, artifactsFilename), artifactsSource);
|
|
91
|
-
const sourceIRuntimeFilePath = path.join(__dirname, "../runtime", IRuntimeFilename);
|
|
92
124
|
fse.copyFileSync(sourceIRuntimeFilePath, path.join(tmpDirPath, IRuntimeFilename));
|
|
93
125
|
const typesDirPath = path.join(tmpDirPath, "types");
|
|
94
126
|
fse.mkdirpSync(typesDirPath);
|
|
@@ -128,7 +160,40 @@ async function generate(input) {
|
|
|
128
160
|
.join("\n"));
|
|
129
161
|
// TODO: workaround for IRuntime.d.ts not being included
|
|
130
162
|
// copyFileSync hangs for some reason, so use writeFileSync + readFileSync instead
|
|
131
|
-
fs.writeFileSync(path.join(tmpBuildOutputPath,
|
|
163
|
+
fs.writeFileSync(path.join(tmpBuildOutputPath, "IRuntime.d.ts"), fs.existsSync(path.join(__dirname, "../runtime", "IRuntime.d.ts"))
|
|
164
|
+
? fs.readFileSync(path.join(__dirname, "../runtime", "IRuntime.d.ts"))
|
|
165
|
+
: fs.readFileSync(sourceIRuntimeFilePath));
|
|
166
|
+
if (dialect === "mysql" && input.outputSqliteSchema) {
|
|
167
|
+
// Since mysql2sqlite outputs a malformed string if a column
|
|
168
|
+
// has the name `enum`, temporarily change the name to something else,
|
|
169
|
+
// then change it back.
|
|
170
|
+
const enumMarker = "`" + node_crypto_1.default.randomUUID() + "`";
|
|
171
|
+
const schemaMySql = Object.values(artifacts)
|
|
172
|
+
.reduce((acc, x) => {
|
|
173
|
+
let d = x.dump?.schema;
|
|
174
|
+
if (!d) {
|
|
175
|
+
return acc;
|
|
176
|
+
}
|
|
177
|
+
d = d.replace(/`enum`/g, enumMarker);
|
|
178
|
+
d += ";";
|
|
179
|
+
acc.push(d);
|
|
180
|
+
return acc;
|
|
181
|
+
}, [])
|
|
182
|
+
.join("\n\n");
|
|
183
|
+
const mysql2SqliteSrc = getMysql2sqliteSrc();
|
|
184
|
+
const mysql2SqlitePath = path.join(tmpDirPath, "mysql2sqlite");
|
|
185
|
+
fs.writeFileSync(mysql2SqlitePath, mysql2SqliteSrc);
|
|
186
|
+
fs.chmodSync(mysql2SqlitePath, 0o755);
|
|
187
|
+
const tmpMySqlSchemaFilename = "tmp.sql";
|
|
188
|
+
const tmpMySqlSchemaPath = path.join(tmpDirPath, tmpMySqlSchemaFilename);
|
|
189
|
+
fs.writeFileSync(tmpMySqlSchemaPath, schemaMySql);
|
|
190
|
+
let schemaSqlite = child_process
|
|
191
|
+
.execFileSync(mysql2SqlitePath, [tmpMySqlSchemaFilename], { cwd: tmpDirPath })
|
|
192
|
+
.toString();
|
|
193
|
+
schemaSqlite = schemaSqlite.replace(new RegExp(enumMarker, "g"), "`enum`");
|
|
194
|
+
const src = prettier.format(`module.exports = { schema: \`${schemaSqlite.replace(/`/g, "\\`")}\` }`, { parser: "babel" });
|
|
195
|
+
fs.writeFileSync(path.join(tmpBuildOutputPath, "artifacts.sqlite.js"), src);
|
|
196
|
+
}
|
|
132
197
|
if (!fs.existsSync(outdir)) {
|
|
133
198
|
fse.mkdirpSync(outdir);
|
|
134
199
|
}
|
|
@@ -145,17 +210,17 @@ function init(input) {
|
|
|
145
210
|
password,
|
|
146
211
|
host,
|
|
147
212
|
port,
|
|
148
|
-
database
|
|
213
|
+
database
|
|
149
214
|
});
|
|
150
215
|
query = mysql.query.bind(mysql);
|
|
151
216
|
}
|
|
152
|
-
if (dialect === "mssql"
|
|
217
|
+
if (dialect === "mssql") {
|
|
153
218
|
const pool = new mssql.ConnectionPool({
|
|
154
219
|
server: server ?? "localhost",
|
|
155
220
|
user,
|
|
156
221
|
password,
|
|
157
222
|
port,
|
|
158
|
-
database
|
|
223
|
+
database
|
|
159
224
|
});
|
|
160
225
|
const poolConnect = pool.connect();
|
|
161
226
|
async function runMSSQLQuery(...input) {
|
|
@@ -170,7 +235,7 @@ function init(input) {
|
|
|
170
235
|
}
|
|
171
236
|
// It's a bit awkward to put __whereNeedsProcessing, __prepareWhere on the class,
|
|
172
237
|
// but it allows us to share the same database pool, clientOpts, etc.
|
|
173
|
-
async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts) {
|
|
238
|
+
async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts, artifacts) {
|
|
174
239
|
function getTypeImports() {
|
|
175
240
|
let set = new Set();
|
|
176
241
|
for (let d of input) {
|
|
@@ -179,7 +244,7 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
|
|
|
179
244
|
"typeReturnBaseName",
|
|
180
245
|
"typeWhereName",
|
|
181
246
|
"typeOrderByName",
|
|
182
|
-
"typeDataName"
|
|
247
|
+
"typeDataName"
|
|
183
248
|
]) {
|
|
184
249
|
const str = d[k];
|
|
185
250
|
if (str) {
|
|
@@ -204,10 +269,13 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
|
|
|
204
269
|
clientOpts: { [k: string]: any; },
|
|
205
270
|
otherOpts?: { [k: string]: any; }
|
|
206
271
|
}) {
|
|
207
|
-
|
|
272
|
+
let otherOpts = opts.otherOpts ?? {};
|
|
273
|
+
if (opts.clientOpts.filename === ":memory:") {
|
|
274
|
+
otherOpts = { ...otherOpts, createTablesString: require("./artifacts.sqlite").schema }
|
|
275
|
+
}
|
|
208
276
|
this.runtime = new opts.runtime(opts.clientOpts, ${supplementClientOpts === true
|
|
209
|
-
? "{ supplementClientOpts: true, ...
|
|
210
|
-
: "
|
|
277
|
+
? "{ supplementClientOpts: true, ...otherOpts }"
|
|
278
|
+
: "otherOpts"}, artifacts);
|
|
211
279
|
}
|
|
212
280
|
|
|
213
281
|
$use(middleware: TMiddleware) {
|
|
@@ -233,159 +301,362 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
|
|
|
233
301
|
return this.runtime.$shutdown();
|
|
234
302
|
}
|
|
235
303
|
|
|
304
|
+
async $startTransaction(input?: {
|
|
305
|
+
isolationLevel?:
|
|
306
|
+
| "READ UNCOMMITTED"
|
|
307
|
+
| "READ COMMITTED"
|
|
308
|
+
| "REPEATABLE READ"
|
|
309
|
+
| "SERIALIZABLE"
|
|
310
|
+
}) {
|
|
311
|
+
const { dbCall, commit, rollback } = await this.runtime.$startTransaction(input);
|
|
312
|
+
const runtime = this.runtime;
|
|
313
|
+
return {
|
|
314
|
+
$commit: commit,
|
|
315
|
+
$rollback: rollback,
|
|
316
|
+
${(await Promise.all(input.flatMap(async (x) => {
|
|
317
|
+
if (x.kind === "getOne") {
|
|
318
|
+
const findOnes = await getFindOnes(x, specialCaseUuidColumn);
|
|
319
|
+
return getMethodSourceGetOne(x, findOnes, true);
|
|
320
|
+
}
|
|
321
|
+
if (x.kind === "getList") {
|
|
322
|
+
return getMethodSourceGetList(x, true);
|
|
323
|
+
}
|
|
324
|
+
if (x.kind === "getListPaginated") {
|
|
325
|
+
return getMethodSourceGetListPaginated(x, true);
|
|
326
|
+
}
|
|
327
|
+
if (x.kind === "postOne") {
|
|
328
|
+
return getMethodSourcePostOne(x, specialCaseUuidColumn, true);
|
|
329
|
+
}
|
|
330
|
+
if (x.kind === "patchOne") {
|
|
331
|
+
const findOnes = await getFindOnes(x, specialCaseUuidColumn);
|
|
332
|
+
return getMethodSourcePatchOne(x, findOnes, true);
|
|
333
|
+
}
|
|
334
|
+
if (x.kind === "patchList") {
|
|
335
|
+
return getMethodSourcePatchList(x, true);
|
|
336
|
+
}
|
|
337
|
+
if (x.kind === "deleteOne") {
|
|
338
|
+
const findOnes = await getFindOnes(x, specialCaseUuidColumn);
|
|
339
|
+
return getMethodSourceDeleteOne(x, findOnes, true);
|
|
340
|
+
}
|
|
341
|
+
if (x.kind === "deleteList") {
|
|
342
|
+
return getMethodSourceDeleteList(x, true);
|
|
343
|
+
}
|
|
344
|
+
}))).join(",\n")}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
236
348
|
${(await Promise.all(input.flatMap(async (x) => {
|
|
237
|
-
let findOnes = [];
|
|
238
|
-
const primaryColumn = await getPrimaryColumn(x.table);
|
|
239
|
-
const uniqueColumns = await getUniqueColumns(x.table, specialCaseUuidColumn);
|
|
240
|
-
findOnes = findOnes
|
|
241
|
-
.concat([primaryColumn])
|
|
242
|
-
.concat(uniqueColumns)
|
|
243
|
-
.map((x) => ({
|
|
244
|
-
...x,
|
|
245
|
-
type: x.type === "integer" ? "number" : x.type,
|
|
246
|
-
}));
|
|
247
349
|
if (x.kind === "getOne") {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
.map((findOne) => `{ ${findOne.name}: ${findOne.type}${findOne.nullable ? " | null" : ""} }`)
|
|
251
|
-
.join(" | ")},
|
|
252
|
-
param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }
|
|
253
|
-
): Promise<${x.typeReturnBaseName}> {
|
|
254
|
-
return this.runtime.resolve(
|
|
255
|
-
{
|
|
256
|
-
resource: "${x.table}",
|
|
257
|
-
action: "findUnique",
|
|
258
|
-
args: { $where: param1 },
|
|
259
|
-
fields: param2?.fields,
|
|
260
|
-
artifacts,
|
|
261
|
-
context: param2?.context,
|
|
262
|
-
skipCache: param2?.skipCache
|
|
263
|
-
}
|
|
264
|
-
);
|
|
265
|
-
}`;
|
|
350
|
+
const findOnes = await getFindOnes(x, specialCaseUuidColumn);
|
|
351
|
+
return getMethodSourceGetOne(x, findOnes, false);
|
|
266
352
|
}
|
|
267
353
|
if (x.kind === "getList") {
|
|
268
|
-
return
|
|
269
|
-
param1: { $where?: ${x.typeWhereName}, $orderBy?: ${x.typeOrderByName}, $limit?: number },
|
|
270
|
-
param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }
|
|
271
|
-
): Promise<Array<${x.typeReturnBaseName}>> {
|
|
272
|
-
return this.runtime.resolve(
|
|
273
|
-
{
|
|
274
|
-
resource: "${x.table}",
|
|
275
|
-
action: "findMany",
|
|
276
|
-
args: param1,
|
|
277
|
-
fields: param2?.fields,
|
|
278
|
-
artifacts,
|
|
279
|
-
context: param2?.context,
|
|
280
|
-
skipCache: param2?.skipCache
|
|
281
|
-
}
|
|
282
|
-
);
|
|
283
|
-
}`;
|
|
354
|
+
return getMethodSourceGetList(x, false);
|
|
284
355
|
}
|
|
285
356
|
if (x.kind === "getListPaginated") {
|
|
286
|
-
return
|
|
287
|
-
param1: { $where?: ${x.typeWhereName}, $orderBy?: ${x.typeOrderByName}, $paginate: Paginate },
|
|
288
|
-
param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }
|
|
289
|
-
): Promise<ListPaginated<${x.typeReturnBaseName}>> {
|
|
290
|
-
return this.runtime.resolve(
|
|
291
|
-
{
|
|
292
|
-
resource: "${x.table}",
|
|
293
|
-
action: "findManyPaginated",
|
|
294
|
-
args: param1,
|
|
295
|
-
fields: param2?.fields,
|
|
296
|
-
artifacts,
|
|
297
|
-
context: param2?.context,
|
|
298
|
-
skipCache: param2?.skipCache
|
|
299
|
-
}
|
|
300
|
-
);
|
|
301
|
-
}`;
|
|
357
|
+
return getMethodSourceGetListPaginated(x, false);
|
|
302
358
|
}
|
|
303
359
|
if (x.kind === "postOne") {
|
|
304
|
-
return
|
|
305
|
-
data: ${x.typeDataName},
|
|
306
|
-
param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }
|
|
307
|
-
): Promise<${x.typeReturnBaseName}> {
|
|
308
|
-
return this.runtime.resolve({
|
|
309
|
-
resource: "${x.table}",
|
|
310
|
-
action: "create",
|
|
311
|
-
data,
|
|
312
|
-
artifacts,
|
|
313
|
-
fields: param2?.fields,
|
|
314
|
-
context: {...param2?.context, specialCaseUuidColumn: ${JSON.stringify(specialCaseUuidColumn)}}
|
|
315
|
-
});
|
|
316
|
-
}`;
|
|
360
|
+
return getMethodSourcePostOne(x, specialCaseUuidColumn, false);
|
|
317
361
|
}
|
|
318
362
|
if (x.kind === "patchOne") {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
.map((findOne) => `{ ${findOne.name}: ${findOne.type}${findOne.nullable ? " | null" : ""} }`)
|
|
322
|
-
.join(" | ")},
|
|
323
|
-
data: ${x.typeDataName},
|
|
324
|
-
param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }
|
|
325
|
-
): Promise<${x.typeReturnBaseName}> {
|
|
326
|
-
return this.runtime.resolve({
|
|
327
|
-
resource: "${x.table}",
|
|
328
|
-
action: "update",
|
|
329
|
-
args: { $where: param1 },
|
|
330
|
-
data,
|
|
331
|
-
artifacts,
|
|
332
|
-
fields: param2?.fields,
|
|
333
|
-
context: param2?.context
|
|
334
|
-
});
|
|
335
|
-
}`;
|
|
363
|
+
const findOnes = await getFindOnes(x, specialCaseUuidColumn);
|
|
364
|
+
return getMethodSourcePatchOne(x, findOnes, false);
|
|
336
365
|
}
|
|
337
366
|
if (x.kind === "patchList") {
|
|
338
|
-
return
|
|
339
|
-
param1: { $where?: ${x.typeWhereName} },
|
|
340
|
-
data: ${x.typeDataName},
|
|
341
|
-
param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }
|
|
342
|
-
): Promise<Array<${x.typeReturnBaseName}>> {
|
|
343
|
-
return this.runtime.resolve({
|
|
344
|
-
resource: "${x.table}",
|
|
345
|
-
action: "updateMany",
|
|
346
|
-
args: param1,
|
|
347
|
-
data,
|
|
348
|
-
artifacts,
|
|
349
|
-
fields: param2?.fields,
|
|
350
|
-
context: param2?.context
|
|
351
|
-
});
|
|
352
|
-
}`;
|
|
367
|
+
return getMethodSourcePatchList(x, false);
|
|
353
368
|
}
|
|
354
369
|
if (x.kind === "deleteOne") {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
.map((findOne) => `{ ${findOne.name}: ${findOne.type}${findOne.nullable ? " | null" : ""} }`)
|
|
358
|
-
.join(" | ")},
|
|
359
|
-
param2?: { correlationId?: string, context?: TContext }
|
|
360
|
-
): Promise<void> {
|
|
361
|
-
await this.runtime.resolve({
|
|
362
|
-
resource: "${x.table}",
|
|
363
|
-
action: "delete",
|
|
364
|
-
args: { $where: param1 },
|
|
365
|
-
artifacts,
|
|
366
|
-
context: param2?.context
|
|
367
|
-
});
|
|
368
|
-
}`;
|
|
370
|
+
const findOnes = await getFindOnes(x, specialCaseUuidColumn);
|
|
371
|
+
return getMethodSourceDeleteOne(x, findOnes, false);
|
|
369
372
|
}
|
|
370
373
|
if (x.kind === "deleteList") {
|
|
371
|
-
return
|
|
372
|
-
param1: { $where?: ${x.typeWhereName} },
|
|
373
|
-
param2?: { correlationId?: string, context?: TContext }
|
|
374
|
-
): Promise<void> {
|
|
375
|
-
await this.runtime.resolve({
|
|
376
|
-
resource: "${x.table}",
|
|
377
|
-
action: "deleteMany",
|
|
378
|
-
args: param1,
|
|
379
|
-
artifacts,
|
|
380
|
-
context: param2?.context
|
|
381
|
-
});
|
|
382
|
-
}`;
|
|
374
|
+
return getMethodSourceDeleteList(x, false);
|
|
383
375
|
}
|
|
384
376
|
}))).join("\n\n")}
|
|
385
377
|
}
|
|
378
|
+
|
|
379
|
+
${await Promise.all(Object.entries(artifacts).map(async ([table, tableArtifacts]) => {
|
|
380
|
+
const jsonSchema = {
|
|
381
|
+
type: "object",
|
|
382
|
+
properties: tableArtifacts.fields.reduce((acc, x) => {
|
|
383
|
+
if (x.kind === "object") {
|
|
384
|
+
return acc;
|
|
385
|
+
}
|
|
386
|
+
if (x.kind === "scalar" && x.mapped) {
|
|
387
|
+
return acc;
|
|
388
|
+
}
|
|
389
|
+
acc[x.name] =
|
|
390
|
+
x.kind === "enum"
|
|
391
|
+
? { enum: x.values }
|
|
392
|
+
: { type: getJSONTypes(x.type, x.nullable) };
|
|
393
|
+
return acc;
|
|
394
|
+
}, {}),
|
|
395
|
+
required: tableArtifacts.fields
|
|
396
|
+
.filter((x) => x.kind === "scalar" || x.kind === "enum")
|
|
397
|
+
.map((x) => x.name),
|
|
398
|
+
additionalProperties: false
|
|
399
|
+
};
|
|
400
|
+
return (0, json_schema_to_typescript_1.compile)(jsonSchema, getTypeReturnName(table), json2TsOpts);
|
|
401
|
+
})).then((xs) => xs.join(";\n\n"))}
|
|
402
|
+
|
|
403
|
+
${Object.entries(artifacts)
|
|
404
|
+
.map(([table, tableArtifacts]) => {
|
|
405
|
+
// https://pkerschbaum.com/blog/how-prisma-adapts-result-types-based-on-the-actual-arguments-given
|
|
406
|
+
// https://github.com/pkerschbaum/how-prisma-adapts-result-types-based-on-the-actual-arguments-given_example/blob/main/prisma/lib/prisma-client/index.d.ts
|
|
407
|
+
return `export type ${getTypeGetPayloadName(table)}<S extends { ${keyFields}?: ${getTypeFieldsName(table)} } | boolean, U = keyof S> = S extends true ? ${getTypeReturnName(table)} : S extends { ${keyFields}?: ${getTypeFieldsName(table)}, [k: string]: any } ? "${keyFields}" extends U ? S["${keyFields}"] extends undefined ? ${getTypeReturnName(table)} : { [P in TrueKeys<S["${keyFields}"]>]: ${tableArtifacts.fields
|
|
408
|
+
.reduce((acc, x) => {
|
|
409
|
+
if (x.kind !== "object") {
|
|
410
|
+
return acc;
|
|
411
|
+
}
|
|
412
|
+
let str = `P extends "${x.name}" ? ${getTypeGetPayloadName(x.type)}<S["${keyFields}"][P]>`;
|
|
413
|
+
if (x.isList) {
|
|
414
|
+
str += "[]";
|
|
415
|
+
}
|
|
416
|
+
if (x.nullable) {
|
|
417
|
+
str += " | null";
|
|
418
|
+
}
|
|
419
|
+
str += " : ";
|
|
420
|
+
acc.push(str);
|
|
421
|
+
return acc;
|
|
422
|
+
}, [])
|
|
423
|
+
.join("")} ${tableArtifacts.fields
|
|
424
|
+
.reduce((acc, x) => {
|
|
425
|
+
if (x.kind === "scalar" && x.mapped) {
|
|
426
|
+
let type = x.type;
|
|
427
|
+
if (x.nullable) {
|
|
428
|
+
type += " | null";
|
|
429
|
+
}
|
|
430
|
+
const str = `P extends "${x.name}" ? ${type} : `;
|
|
431
|
+
acc.push(str);
|
|
432
|
+
}
|
|
433
|
+
return acc;
|
|
434
|
+
}, [])
|
|
435
|
+
.join("")} P extends keyof ${getTypeReturnName(table)} ? ${getTypeReturnName(table)}[P] : never } : ${getTypeReturnName(table)} : ${getTypeReturnName(table)}`;
|
|
436
|
+
})
|
|
437
|
+
.join(";\n\n")}
|
|
438
|
+
|
|
439
|
+
// Utils
|
|
440
|
+
|
|
441
|
+
type Pick2<T, K extends keyof T> = { [P in K]: T[P]; };
|
|
442
|
+
|
|
443
|
+
type RequiredKeys<T> = {
|
|
444
|
+
[K in keyof T]-?: {} extends Pick2<T, K> ? never : K;
|
|
445
|
+
}[keyof T];
|
|
446
|
+
|
|
447
|
+
type TruthyKeys<T> = {
|
|
448
|
+
[key in keyof T]: T[key] extends false | undefined | null ? never : key;
|
|
449
|
+
}[keyof T];
|
|
450
|
+
|
|
451
|
+
type TrueKeys<T> = TruthyKeys<Pick2<T, RequiredKeys<T>>>;
|
|
452
|
+
|
|
453
|
+
type SelectSubset<T, U> = {
|
|
454
|
+
[key in keyof T]: key extends keyof U ? T[key] : never;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
type HasSelect = { ${keyFields}: any; };
|
|
458
|
+
|
|
459
|
+
type CheckSelect<T, S, U> = T extends HasSelect ? U : S;
|
|
386
460
|
`;
|
|
387
461
|
return prettier.format(src, { parser: "typescript" });
|
|
388
462
|
}
|
|
463
|
+
async function getFindOnes(x, specialCaseUuidColumn) {
|
|
464
|
+
let findOnes = [];
|
|
465
|
+
const primaryColumn = await getPrimaryColumn(x.table);
|
|
466
|
+
const uniqueColumns = await getUniqueColumns(x.table, specialCaseUuidColumn);
|
|
467
|
+
findOnes = findOnes
|
|
468
|
+
.concat([primaryColumn])
|
|
469
|
+
.concat(uniqueColumns)
|
|
470
|
+
.map((x) => ({
|
|
471
|
+
...x,
|
|
472
|
+
type: x.type === "integer" ? "number" : x.type
|
|
473
|
+
}));
|
|
474
|
+
return findOnes;
|
|
475
|
+
}
|
|
476
|
+
function getMethodSourceGetOne(x, findOnes, isTransaction) {
|
|
477
|
+
const param2 = `{ ${keyFields}?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }`;
|
|
478
|
+
return `async ${x.methodName}<T extends ${param2}>(
|
|
479
|
+
param1: ${findOnes
|
|
480
|
+
.map((findOne) => `{ ${findOne.name}: ${findOne.type}${findOne.nullable ? " | null" : ""} }`)
|
|
481
|
+
.join(" | ")},
|
|
482
|
+
param2?: SelectSubset<T, ${param2}>
|
|
483
|
+
): Promise<CheckSelect<T, ${getTypeReturnName(x.table)}, ${getTypeGetPayloadName(x.table)}<T>>> {
|
|
484
|
+
return ${isTransaction ? "runtime" : "this.runtime"}.resolve(
|
|
485
|
+
{
|
|
486
|
+
resource: "${x.table}",
|
|
487
|
+
action: "${mapKindToAction(x.kind)}",
|
|
488
|
+
args: { $where: param1 },
|
|
489
|
+
fields: param2?.$fields as any,
|
|
490
|
+
artifacts,
|
|
491
|
+
context: param2?.context,
|
|
492
|
+
skipCache: param2?.skipCache,
|
|
493
|
+
${isTransaction ? "dbCall" : ""}
|
|
494
|
+
}
|
|
495
|
+
);
|
|
496
|
+
}`;
|
|
497
|
+
}
|
|
498
|
+
function getMethodSourceGetList(x, isTransaction) {
|
|
499
|
+
const param2 = `{ ${keyFields}?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }`;
|
|
500
|
+
return `async ${x.methodName}<T extends ${param2}>(
|
|
501
|
+
param1: { $where?: ${x.typeWhereName}, $orderBy?: ${x.typeOrderByName}, $limit?: number },
|
|
502
|
+
param2?: SelectSubset<T, ${param2}>
|
|
503
|
+
): Promise<Array<CheckSelect<T, ${getTypeReturnName(x.table)}, ${getTypeGetPayloadName(x.table)}<T>>>> {
|
|
504
|
+
return ${isTransaction ? "runtime" : "this.runtime"}.resolve(
|
|
505
|
+
{
|
|
506
|
+
resource: "${x.table}",
|
|
507
|
+
action: "${mapKindToAction(x.kind)}",
|
|
508
|
+
args: param1,
|
|
509
|
+
fields: param2?.$fields as any,
|
|
510
|
+
artifacts,
|
|
511
|
+
context: param2?.context,
|
|
512
|
+
skipCache: param2?.skipCache,
|
|
513
|
+
${isTransaction ? "dbCall" : ""}
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
}`;
|
|
517
|
+
}
|
|
518
|
+
function getMethodSourceGetListPaginated(x, isTransaction) {
|
|
519
|
+
const param2 = `{ ${keyFields}?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }`;
|
|
520
|
+
return `async ${x.methodName}<T extends ${param2}>(
|
|
521
|
+
param1: { $where?: ${x.typeWhereName}, $orderBy?: ${x.typeOrderByName}, $paginate: Paginate },
|
|
522
|
+
param2?: SelectSubset<T, ${param2}>
|
|
523
|
+
): Promise<ListPaginated<CheckSelect<T, ${getTypeReturnName(x.table)}, ${getTypeGetPayloadName(x.table)}<T>>>> {
|
|
524
|
+
return ${isTransaction ? "runtime" : "this.runtime"}.resolve(
|
|
525
|
+
{
|
|
526
|
+
resource: "${x.table}",
|
|
527
|
+
action: "${mapKindToAction(x.kind)}",
|
|
528
|
+
args: param1,
|
|
529
|
+
fields: param2?.$fields as any,
|
|
530
|
+
artifacts,
|
|
531
|
+
context: param2?.context,
|
|
532
|
+
skipCache: param2?.skipCache,
|
|
533
|
+
${isTransaction ? "dbCall" : ""}
|
|
534
|
+
}
|
|
535
|
+
);
|
|
536
|
+
}`;
|
|
537
|
+
}
|
|
538
|
+
function getMethodSourcePostOne(x, specialCaseUuidColumn, isTransaction) {
|
|
539
|
+
const param2 = `{ ${keyFields}?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }`;
|
|
540
|
+
return `async ${x.methodName}<T extends ${param2}>(
|
|
541
|
+
data: ${x.typeDataName},
|
|
542
|
+
param2?: SelectSubset<T, ${param2}>
|
|
543
|
+
): Promise<CheckSelect<T, ${getTypeReturnName(x.table)}, ${getTypeGetPayloadName(x.table)}<T>>> {
|
|
544
|
+
return ${isTransaction ? "runtime" : "this.runtime"}.resolve({
|
|
545
|
+
resource: "${x.table}",
|
|
546
|
+
action: "${mapKindToAction(x.kind)}",
|
|
547
|
+
data,
|
|
548
|
+
artifacts,
|
|
549
|
+
fields: param2?.$fields as any,
|
|
550
|
+
context: {...param2?.context, specialCaseUuidColumn: ${JSON.stringify(specialCaseUuidColumn)}},
|
|
551
|
+
${isTransaction ? "dbCall" : ""}
|
|
552
|
+
});
|
|
553
|
+
}`;
|
|
554
|
+
}
|
|
555
|
+
function getMethodSourcePatchOne(x, findOnes, isTransaction) {
|
|
556
|
+
const param2 = `{ ${keyFields}?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }`;
|
|
557
|
+
return `async ${x.methodName}<T extends ${param2}>(
|
|
558
|
+
param1: ${findOnes
|
|
559
|
+
.map((findOne) => `{ ${findOne.name}: ${findOne.type}${findOne.nullable ? " | null" : ""} }`)
|
|
560
|
+
.join(" | ")},
|
|
561
|
+
data: ${x.typeDataName},
|
|
562
|
+
param2?: SelectSubset<T, ${param2}>
|
|
563
|
+
): Promise<CheckSelect<T, ${getTypeReturnName(x.table)}, ${getTypeGetPayloadName(x.table)}<T>>> {
|
|
564
|
+
return ${isTransaction ? "runtime" : "this.runtime"}.resolve({
|
|
565
|
+
resource: "${x.table}",
|
|
566
|
+
action: "${mapKindToAction(x.kind)}",
|
|
567
|
+
args: { $where: param1 },
|
|
568
|
+
data,
|
|
569
|
+
artifacts,
|
|
570
|
+
fields: param2?.$fields as any,
|
|
571
|
+
context: param2?.context,
|
|
572
|
+
${isTransaction ? "dbCall" : ""}
|
|
573
|
+
});
|
|
574
|
+
}`;
|
|
575
|
+
}
|
|
576
|
+
function getMethodSourcePatchList(x, isTransaction) {
|
|
577
|
+
const param2 = `{ ${keyFields}?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }`;
|
|
578
|
+
return `async ${x.methodName}<T extends ${param2}>(
|
|
579
|
+
param1: { $where?: ${x.typeWhereName}, $orderBy?: ${x.typeOrderByName} },
|
|
580
|
+
data: ${x.typeDataName},
|
|
581
|
+
param2?: SelectSubset<T, ${param2}>
|
|
582
|
+
): Promise<Array<CheckSelect<T, ${getTypeReturnName(x.table)}, ${getTypeGetPayloadName(x.table)}<T>>>> {
|
|
583
|
+
return ${isTransaction ? "runtime" : "this.runtime"}.resolve({
|
|
584
|
+
resource: "${x.table}",
|
|
585
|
+
action: "${mapKindToAction(x.kind)}",
|
|
586
|
+
args: param1,
|
|
587
|
+
data,
|
|
588
|
+
artifacts,
|
|
589
|
+
fields: param2?.$fields as any,
|
|
590
|
+
context: param2?.context,
|
|
591
|
+
${isTransaction ? "dbCall" : ""}
|
|
592
|
+
});
|
|
593
|
+
}`;
|
|
594
|
+
}
|
|
595
|
+
function getMethodSourceDeleteOne(x, findOnes, isTransaction) {
|
|
596
|
+
return `async ${x.methodName}(
|
|
597
|
+
param1: ${findOnes
|
|
598
|
+
.map((findOne) => `{ ${findOne.name}: ${findOne.type}${findOne.nullable ? " | null" : ""} }`)
|
|
599
|
+
.join(" | ")},
|
|
600
|
+
param2?: { correlationId?: string, context?: TContext }
|
|
601
|
+
): Promise<void> {
|
|
602
|
+
await ${isTransaction ? "runtime" : "this.runtime"}.resolve({
|
|
603
|
+
resource: "${x.table}",
|
|
604
|
+
action: "${mapKindToAction(x.kind)}",
|
|
605
|
+
args: { $where: param1 },
|
|
606
|
+
artifacts,
|
|
607
|
+
context: param2?.context,
|
|
608
|
+
${isTransaction ? "dbCall" : ""}
|
|
609
|
+
});
|
|
610
|
+
}`;
|
|
611
|
+
}
|
|
612
|
+
function getMethodSourceDeleteList(x, isTransaction) {
|
|
613
|
+
return `async ${x.methodName}(
|
|
614
|
+
param1: { $where?: ${x.typeWhereName} },
|
|
615
|
+
param2?: { correlationId?: string, context?: TContext }
|
|
616
|
+
): Promise<void> {
|
|
617
|
+
await ${isTransaction ? "runtime" : "this.runtime"}.resolve({
|
|
618
|
+
resource: "${x.table}",
|
|
619
|
+
action: "${mapKindToAction(x.kind)}",
|
|
620
|
+
args: param1,
|
|
621
|
+
artifacts,
|
|
622
|
+
context: param2?.context,
|
|
623
|
+
${isTransaction ? "dbCall" : ""}
|
|
624
|
+
});
|
|
625
|
+
}`;
|
|
626
|
+
}
|
|
627
|
+
function mapKindToAction(kind) {
|
|
628
|
+
if (kind === "getOne") {
|
|
629
|
+
return "findUnique";
|
|
630
|
+
}
|
|
631
|
+
if (kind === "getList") {
|
|
632
|
+
return "findMany";
|
|
633
|
+
}
|
|
634
|
+
if (kind === "getListPaginated") {
|
|
635
|
+
return "findManyPaginated";
|
|
636
|
+
}
|
|
637
|
+
if (kind === "postOne") {
|
|
638
|
+
return "create";
|
|
639
|
+
}
|
|
640
|
+
if (kind === "patchOne") {
|
|
641
|
+
return "update";
|
|
642
|
+
}
|
|
643
|
+
if (kind === "patchList") {
|
|
644
|
+
return "updateMany";
|
|
645
|
+
}
|
|
646
|
+
if (kind === "deleteOne") {
|
|
647
|
+
return "delete";
|
|
648
|
+
}
|
|
649
|
+
if (kind === "deleteList") {
|
|
650
|
+
return "deleteMany";
|
|
651
|
+
}
|
|
652
|
+
throw new Error(`Unhandled kind: ${kind}`);
|
|
653
|
+
}
|
|
654
|
+
function getTypeGetPayloadName(table) {
|
|
655
|
+
return "GetPayload" + changeCase.pascalCase(table);
|
|
656
|
+
}
|
|
657
|
+
function getTypeReturnName(table) {
|
|
658
|
+
return changeCase.pascalCase(table);
|
|
659
|
+
}
|
|
389
660
|
function getTypeReturnBaseName(table) {
|
|
390
661
|
return "ReturnBase" + changeCase.pascalCase(table);
|
|
391
662
|
}
|
|
@@ -411,7 +682,7 @@ async function getGetOneData(table, includeMappedFields) {
|
|
|
411
682
|
typeFields: await getTypeFields(table, typeFieldsName, includeMappedFields),
|
|
412
683
|
typeFieldsName,
|
|
413
684
|
typeReturnBase: await getTypeReturnBase(table, typeReturnBaseName, includeMappedFields),
|
|
414
|
-
typeReturnBaseName
|
|
685
|
+
typeReturnBaseName
|
|
415
686
|
};
|
|
416
687
|
}
|
|
417
688
|
async function getGetListData(table) {
|
|
@@ -430,7 +701,7 @@ async function getGetListData(table) {
|
|
|
430
701
|
typeWhere,
|
|
431
702
|
typeWhereName,
|
|
432
703
|
typeOrderBy,
|
|
433
|
-
typeOrderByName
|
|
704
|
+
typeOrderByName
|
|
434
705
|
};
|
|
435
706
|
}
|
|
436
707
|
async function getGetListPaginatedData(table) {
|
|
@@ -445,7 +716,7 @@ async function getGetListPaginatedData(table) {
|
|
|
445
716
|
typeFieldsName,
|
|
446
717
|
typeReturnBaseName,
|
|
447
718
|
typeWhereName,
|
|
448
|
-
typeOrderByName
|
|
719
|
+
typeOrderByName
|
|
449
720
|
};
|
|
450
721
|
}
|
|
451
722
|
async function getPostOneData(table, specialCaseUuidColumn, includeMappedFields) {
|
|
@@ -459,7 +730,7 @@ async function getPostOneData(table, specialCaseUuidColumn, includeMappedFields)
|
|
|
459
730
|
typeFieldsName,
|
|
460
731
|
typeReturnBaseName,
|
|
461
732
|
typeData: await getTypeDataPost(table, typeDataName, specialCaseUuidColumn, includeMappedFields),
|
|
462
|
-
typeDataName
|
|
733
|
+
typeDataName
|
|
463
734
|
};
|
|
464
735
|
}
|
|
465
736
|
async function getPatchOneData(table, specialCaseUuidColumn, includeMappedFields) {
|
|
@@ -473,7 +744,7 @@ async function getPatchOneData(table, specialCaseUuidColumn, includeMappedFields
|
|
|
473
744
|
typeFieldsName,
|
|
474
745
|
typeReturnBaseName,
|
|
475
746
|
typeData: await getTypeDataPatch(table, typeDataName, specialCaseUuidColumn, includeMappedFields),
|
|
476
|
-
typeDataName
|
|
747
|
+
typeDataName
|
|
477
748
|
};
|
|
478
749
|
}
|
|
479
750
|
async function getPatchListData(table) {
|
|
@@ -481,6 +752,7 @@ async function getPatchListData(table) {
|
|
|
481
752
|
const typeReturnBaseName = getTypeReturnBaseName(table);
|
|
482
753
|
const typeWhereName = getTypeWhereName(table);
|
|
483
754
|
const typeDataName = "DataPatch" + changeCase.pascalCase(table);
|
|
755
|
+
const typeOrderByName = getTypeOrderByName(table);
|
|
484
756
|
return {
|
|
485
757
|
kind: "patchList",
|
|
486
758
|
table,
|
|
@@ -489,13 +761,14 @@ async function getPatchListData(table) {
|
|
|
489
761
|
typeReturnBaseName,
|
|
490
762
|
typeWhereName,
|
|
491
763
|
typeDataName,
|
|
764
|
+
typeOrderByName
|
|
492
765
|
};
|
|
493
766
|
}
|
|
494
767
|
function getDeleteOneData(table) {
|
|
495
768
|
return {
|
|
496
769
|
kind: "deleteOne",
|
|
497
770
|
table,
|
|
498
|
-
methodName: "delete" + changeCase.pascalCase(table)
|
|
771
|
+
methodName: "delete" + changeCase.pascalCase(table)
|
|
499
772
|
};
|
|
500
773
|
}
|
|
501
774
|
function getDeleteListData(table) {
|
|
@@ -504,7 +777,7 @@ function getDeleteListData(table) {
|
|
|
504
777
|
kind: "deleteList",
|
|
505
778
|
table,
|
|
506
779
|
methodName: "delete" + changeCase.pascalCase(table) + "List",
|
|
507
|
-
typeWhereName
|
|
780
|
+
typeWhereName
|
|
508
781
|
};
|
|
509
782
|
}
|
|
510
783
|
async function getTypeWhere(table, name) {
|
|
@@ -516,11 +789,11 @@ async function getTypeDataPost(table, name, specialCaseUuidColumn, includeMapped
|
|
|
516
789
|
const tableMeta = (await getTableMeta(table)).filter((x) => x.Field !== primaryColumn.name);
|
|
517
790
|
const nullable = tableMeta.reduce((acc, m) => ({
|
|
518
791
|
...acc,
|
|
519
|
-
[m.Field]: m.Null === "YES" ? true : false
|
|
792
|
+
[m.Field]: m.Null === "YES" ? true : false
|
|
520
793
|
}), {});
|
|
521
794
|
const hasDefault = tableMeta.reduce((acc, m) => ({
|
|
522
795
|
...acc,
|
|
523
|
-
[m.Field]: m.Default == null ? false : true
|
|
796
|
+
[m.Field]: m.Default == null ? false : true
|
|
524
797
|
}), {});
|
|
525
798
|
let properties = getJSONSchemaObjProperties(tableMeta);
|
|
526
799
|
let notRequiredList = [];
|
|
@@ -533,7 +806,7 @@ async function getTypeDataPost(table, name, specialCaseUuidColumn, includeMapped
|
|
|
533
806
|
...mappedFields.reduce((acc, v) => {
|
|
534
807
|
acc[v.as] = { type: getJSONTypes(v.type, v.nullable) };
|
|
535
808
|
return acc;
|
|
536
|
-
}, {})
|
|
809
|
+
}, {})
|
|
537
810
|
};
|
|
538
811
|
notRequiredList = mappedFields.flatMap((x) => [x.as, x.foreignKey]);
|
|
539
812
|
for (let r of oneToManyRelations) {
|
|
@@ -548,9 +821,7 @@ async function getTypeDataPost(table, name, specialCaseUuidColumn, includeMapped
|
|
|
548
821
|
...oneToManyRelations.reduce((acc, v) => {
|
|
549
822
|
let tsType = getTypeDataPostName(v.table);
|
|
550
823
|
const mappedFields = mappedFieldsMap.get(v.table);
|
|
551
|
-
if (includeMappedFields &&
|
|
552
|
-
mappedFields != null &&
|
|
553
|
-
mappedFields.length > 0) {
|
|
824
|
+
if (includeMappedFields && mappedFields != null && mappedFields.length > 0) {
|
|
554
825
|
tsType = `Omit<${tsType}, ${mappedFields
|
|
555
826
|
.map((x) => JSON.stringify(x.as))
|
|
556
827
|
.join(" | ")}>`;
|
|
@@ -558,21 +829,19 @@ async function getTypeDataPost(table, name, specialCaseUuidColumn, includeMapped
|
|
|
558
829
|
tsType = `{$create: ${tsType}[]}`;
|
|
559
830
|
acc[v.name] = { tsType };
|
|
560
831
|
return acc;
|
|
561
|
-
}, {})
|
|
832
|
+
}, {})
|
|
562
833
|
},
|
|
563
834
|
additionalProperties: false,
|
|
564
835
|
required: Object.keys(properties)
|
|
565
836
|
.filter(
|
|
566
837
|
// `uuid` should not be required
|
|
567
|
-
(x) => !specialCaseUuidColumn || uuidColumn == null
|
|
568
|
-
? true
|
|
569
|
-
: x !== uuidColumn.name)
|
|
838
|
+
(x) => !specialCaseUuidColumn || uuidColumn == null ? true : x !== uuidColumn.name)
|
|
570
839
|
.filter(
|
|
571
840
|
// Required if column is non-nullable and has no default.
|
|
572
841
|
(x) => !nullable[x] && !hasDefault[x])
|
|
573
842
|
// Instead of doing a union with all possible permutations of UUID and IDs,
|
|
574
843
|
// for simplicity, just make both not required for now.
|
|
575
|
-
.filter((x) => !notRequiredList.includes(x))
|
|
844
|
+
.filter((x) => !notRequiredList.includes(x))
|
|
576
845
|
};
|
|
577
846
|
let type = await (0, json_schema_to_typescript_1.compile)(jsonSchema, name, json2TsOpts);
|
|
578
847
|
const imports = _.uniq(oneToManyRelations
|
|
@@ -601,13 +870,13 @@ async function getTypeDataPatch(table, name, specialCaseUuidColumn, includeMappe
|
|
|
601
870
|
const type = unwrapJSONType(properties[key].type);
|
|
602
871
|
if (type === "string") {
|
|
603
872
|
properties[key] = {
|
|
604
|
-
oneOf: [properties[key], { tsType: "TUpdateOperationsString" }]
|
|
873
|
+
oneOf: [properties[key], { tsType: "TUpdateOperationsString" }]
|
|
605
874
|
};
|
|
606
875
|
mustImportTUpdateOperationsString = true;
|
|
607
876
|
}
|
|
608
877
|
else if (type === "number" || type === "integer") {
|
|
609
878
|
properties[key] = {
|
|
610
|
-
oneOf: [properties[key], { tsType: "TUpdateOperationsNumber" }]
|
|
879
|
+
oneOf: [properties[key], { tsType: "TUpdateOperationsNumber" }]
|
|
611
880
|
};
|
|
612
881
|
mustImportTUpdateOperationsNumber = true;
|
|
613
882
|
}
|
|
@@ -619,14 +888,14 @@ async function getTypeDataPatch(table, name, specialCaseUuidColumn, includeMappe
|
|
|
619
888
|
...mappedFields.reduce((acc, v) => {
|
|
620
889
|
acc[v.as] = { type: getJSONTypes(v.type, v.nullable) };
|
|
621
890
|
return acc;
|
|
622
|
-
}, {})
|
|
891
|
+
}, {})
|
|
623
892
|
};
|
|
624
893
|
}
|
|
625
894
|
const jsonSchema = {
|
|
626
895
|
type: "object",
|
|
627
896
|
properties,
|
|
628
897
|
additionalProperties: false,
|
|
629
|
-
required: []
|
|
898
|
+
required: []
|
|
630
899
|
};
|
|
631
900
|
let type = await (0, json_schema_to_typescript_1.compile)(jsonSchema, name, json2TsOpts);
|
|
632
901
|
if (mustImportTUpdateOperationsString || mustImportTUpdateOperationsNumber) {
|
|
@@ -669,7 +938,7 @@ async function getMappedFields(table) {
|
|
|
669
938
|
name: "uuid",
|
|
670
939
|
// Replace `Id` with `Uuid`
|
|
671
940
|
as: x.foreignKey.slice(0, -2) + "Uuid",
|
|
672
|
-
type: getBaseJSONType(uuidColumn.Type)
|
|
941
|
+
type: getBaseJSONType(uuidColumn.Type)
|
|
673
942
|
});
|
|
674
943
|
}
|
|
675
944
|
return out;
|
|
@@ -688,52 +957,52 @@ async function getJSONSchemaWhere(table) {
|
|
|
688
957
|
{
|
|
689
958
|
type: "object",
|
|
690
959
|
properties: { $eq: v },
|
|
691
|
-
additionalProperties: false
|
|
960
|
+
additionalProperties: false
|
|
692
961
|
},
|
|
693
962
|
{
|
|
694
963
|
type: "object",
|
|
695
964
|
properties: { $neq: v },
|
|
696
|
-
additionalProperties: false
|
|
965
|
+
additionalProperties: false
|
|
697
966
|
},
|
|
698
967
|
{
|
|
699
968
|
type: "object",
|
|
700
969
|
properties: { $gt: v },
|
|
701
|
-
additionalProperties: false
|
|
970
|
+
additionalProperties: false
|
|
702
971
|
},
|
|
703
972
|
{
|
|
704
973
|
type: "object",
|
|
705
974
|
properties: { $gte: v },
|
|
706
|
-
additionalProperties: false
|
|
975
|
+
additionalProperties: false
|
|
707
976
|
},
|
|
708
977
|
{
|
|
709
978
|
type: "object",
|
|
710
979
|
properties: { $lt: v },
|
|
711
|
-
additionalProperties: false
|
|
980
|
+
additionalProperties: false
|
|
712
981
|
},
|
|
713
982
|
{
|
|
714
983
|
type: "object",
|
|
715
984
|
properties: { $lte: v },
|
|
716
|
-
additionalProperties: false
|
|
985
|
+
additionalProperties: false
|
|
717
986
|
},
|
|
718
987
|
{
|
|
719
988
|
type: "object",
|
|
720
989
|
properties: { $like: { type: "string", minLength: 1 } },
|
|
721
|
-
additionalProperties: false
|
|
990
|
+
additionalProperties: false
|
|
722
991
|
},
|
|
723
992
|
{
|
|
724
993
|
type: "object",
|
|
725
994
|
properties: { $nlike: { type: "string", minLength: 1 } },
|
|
726
|
-
additionalProperties: false
|
|
995
|
+
additionalProperties: false
|
|
727
996
|
},
|
|
728
997
|
{
|
|
729
998
|
type: "object",
|
|
730
999
|
properties: { $in: { type: "array", items: v } },
|
|
731
|
-
additionalProperties: false
|
|
1000
|
+
additionalProperties: false
|
|
732
1001
|
},
|
|
733
1002
|
{
|
|
734
1003
|
type: "object",
|
|
735
1004
|
properties: { $nin: { type: "array", items: v } },
|
|
736
|
-
additionalProperties: false
|
|
1005
|
+
additionalProperties: false
|
|
737
1006
|
},
|
|
738
1007
|
{
|
|
739
1008
|
type: "object",
|
|
@@ -743,10 +1012,10 @@ async function getJSONSchemaWhere(table) {
|
|
|
743
1012
|
items: v,
|
|
744
1013
|
minItems: 2,
|
|
745
1014
|
maxItems: 2,
|
|
746
|
-
uniqueItems: true
|
|
747
|
-
}
|
|
1015
|
+
uniqueItems: true
|
|
1016
|
+
}
|
|
748
1017
|
},
|
|
749
|
-
additionalProperties: false
|
|
1018
|
+
additionalProperties: false
|
|
750
1019
|
},
|
|
751
1020
|
{
|
|
752
1021
|
type: "object",
|
|
@@ -756,15 +1025,15 @@ async function getJSONSchemaWhere(table) {
|
|
|
756
1025
|
items: v,
|
|
757
1026
|
minItems: 2,
|
|
758
1027
|
maxItems: 2,
|
|
759
|
-
uniqueItems: true
|
|
760
|
-
}
|
|
1028
|
+
uniqueItems: true
|
|
1029
|
+
}
|
|
761
1030
|
},
|
|
762
|
-
additionalProperties: false
|
|
763
|
-
}
|
|
764
|
-
]
|
|
765
|
-
}
|
|
1031
|
+
additionalProperties: false
|
|
1032
|
+
}
|
|
1033
|
+
]
|
|
1034
|
+
}
|
|
766
1035
|
}), {}),
|
|
767
|
-
additionalProperties: false
|
|
1036
|
+
additionalProperties: false
|
|
768
1037
|
},
|
|
769
1038
|
{
|
|
770
1039
|
type: "object",
|
|
@@ -772,17 +1041,17 @@ async function getJSONSchemaWhere(table) {
|
|
|
772
1041
|
$and: {
|
|
773
1042
|
type: "array",
|
|
774
1043
|
items: {
|
|
775
|
-
$ref: `#/definitions/${whereSchemaName}
|
|
1044
|
+
$ref: `#/definitions/${whereSchemaName}`
|
|
776
1045
|
},
|
|
777
1046
|
// While it makes sense conceptually for $and to have
|
|
778
1047
|
// at least 2 items, in practice, $and could be
|
|
779
1048
|
// generated dynamically and could end up having
|
|
780
1049
|
// less than 2 items, so don't enforce minItems.
|
|
781
1050
|
// minItems: 2,
|
|
782
|
-
additionalProperties: false
|
|
783
|
-
}
|
|
1051
|
+
additionalProperties: false
|
|
1052
|
+
}
|
|
784
1053
|
},
|
|
785
|
-
additionalProperties: false
|
|
1054
|
+
additionalProperties: false
|
|
786
1055
|
},
|
|
787
1056
|
{
|
|
788
1057
|
type: "object",
|
|
@@ -790,19 +1059,19 @@ async function getJSONSchemaWhere(table) {
|
|
|
790
1059
|
$or: {
|
|
791
1060
|
type: "array",
|
|
792
1061
|
items: {
|
|
793
|
-
$ref: `#/definitions/${whereSchemaName}
|
|
1062
|
+
$ref: `#/definitions/${whereSchemaName}`
|
|
794
1063
|
},
|
|
795
1064
|
// While it makes sense conceptually for $and to have
|
|
796
1065
|
// at least 2 items, in practice, $and could be
|
|
797
1066
|
// generated dynamically and could end up having
|
|
798
1067
|
// less than 2 items, so don't enforce minItems.
|
|
799
1068
|
// minItems: 2,
|
|
800
|
-
additionalProperties: false
|
|
801
|
-
}
|
|
1069
|
+
additionalProperties: false
|
|
1070
|
+
}
|
|
802
1071
|
},
|
|
803
|
-
additionalProperties: false
|
|
804
|
-
}
|
|
805
|
-
]
|
|
1072
|
+
additionalProperties: false
|
|
1073
|
+
}
|
|
1074
|
+
]
|
|
806
1075
|
};
|
|
807
1076
|
return {
|
|
808
1077
|
definitions: { [whereSchemaName]: defWhere },
|
|
@@ -819,12 +1088,12 @@ async function getJSONSchemaWhere(table) {
|
|
|
819
1088
|
// generated dynamically and could end up having
|
|
820
1089
|
// less than 2 items, so don't enforce minItems.
|
|
821
1090
|
// minItems: 2,
|
|
822
|
-
additionalProperties: false
|
|
823
|
-
}
|
|
1091
|
+
additionalProperties: false
|
|
1092
|
+
}
|
|
824
1093
|
},
|
|
825
|
-
additionalProperties: false
|
|
826
|
-
}))
|
|
827
|
-
]
|
|
1094
|
+
additionalProperties: false
|
|
1095
|
+
}))
|
|
1096
|
+
]
|
|
828
1097
|
};
|
|
829
1098
|
}
|
|
830
1099
|
async function getTypeOrderBy(table, name) {
|
|
@@ -837,14 +1106,14 @@ async function getJSONSchemaOrderBy(table, name) {
|
|
|
837
1106
|
type: "object",
|
|
838
1107
|
properties: { [k]: { enum: ["asc", "desc"] } },
|
|
839
1108
|
required: [k],
|
|
840
|
-
additionalProperties: false
|
|
841
|
-
}))
|
|
1109
|
+
additionalProperties: false
|
|
1110
|
+
}))
|
|
842
1111
|
};
|
|
843
1112
|
const defName = `_${name}`;
|
|
844
1113
|
const _schema = { $ref: `#/definitions/${defName}` };
|
|
845
1114
|
return {
|
|
846
1115
|
definitions: { [defName]: def },
|
|
847
|
-
oneOf: [_schema, { type: "array", items: _schema }]
|
|
1116
|
+
oneOf: [_schema, { type: "array", items: _schema }]
|
|
848
1117
|
};
|
|
849
1118
|
}
|
|
850
1119
|
function getTypeTypesIndex(data) {
|
|
@@ -858,7 +1127,7 @@ function getTypeTypesIndex(data) {
|
|
|
858
1127
|
"typeReturnBaseName",
|
|
859
1128
|
"typeWhereName",
|
|
860
1129
|
"typeOrderByName",
|
|
861
|
-
"typeDataName"
|
|
1130
|
+
"typeDataName"
|
|
862
1131
|
]) {
|
|
863
1132
|
const str = d[k];
|
|
864
1133
|
if (str) {
|
|
@@ -870,7 +1139,7 @@ function getTypeTypesIndex(data) {
|
|
|
870
1139
|
"Paginate",
|
|
871
1140
|
"ListPaginated",
|
|
872
1141
|
"TUpdateOperationsString",
|
|
873
|
-
"TUpdateOperationsNumber"
|
|
1142
|
+
"TUpdateOperationsNumber"
|
|
874
1143
|
].join(",")} } from "./_shared";\n\n`;
|
|
875
1144
|
let arr = Array.from(set).sort();
|
|
876
1145
|
for (let x of arr) {
|
|
@@ -896,8 +1165,8 @@ export type ListPaginated<T> = {
|
|
|
896
1165
|
paginationInfo: {
|
|
897
1166
|
hasPreviousPage?: boolean,
|
|
898
1167
|
hasNextPage?: boolean,
|
|
899
|
-
startCursor?: string
|
|
900
|
-
endCursor?: string
|
|
1168
|
+
startCursor?: string,
|
|
1169
|
+
endCursor?: string,
|
|
901
1170
|
totalCount: number,
|
|
902
1171
|
},
|
|
903
1172
|
results: Array<T>,
|
|
@@ -915,58 +1184,49 @@ async function getTypeFields(table, name, includeMappedFields) {
|
|
|
915
1184
|
const mappedFields = includeMappedFields ? await getMappedFields(table) : [];
|
|
916
1185
|
const keyWhere = "$where";
|
|
917
1186
|
const keyOrderBy = "$orderBy";
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
},
|
|
935
|
-
},
|
|
936
|
-
additionalProperties: false,
|
|
937
|
-
},
|
|
1187
|
+
let properties = {};
|
|
1188
|
+
for (let x of scalarKeys) {
|
|
1189
|
+
properties[x] = { type: "boolean" };
|
|
1190
|
+
}
|
|
1191
|
+
for (let x of mappedFields) {
|
|
1192
|
+
properties[x.as] = { type: "boolean" };
|
|
1193
|
+
}
|
|
1194
|
+
for (let x of relations) {
|
|
1195
|
+
const argsProperties = x.type === "many-to-many"
|
|
1196
|
+
? {
|
|
1197
|
+
[keyWhere]: {
|
|
1198
|
+
type: "object",
|
|
1199
|
+
properties: {
|
|
1200
|
+
[x.table]: { tsType: getTypeWhereName(x.table) },
|
|
1201
|
+
[x.junctionTable]: {
|
|
1202
|
+
tsType: getTypeWhereName(x.junctionTable)
|
|
938
1203
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}),
|
|
963
|
-
],
|
|
964
|
-
},
|
|
1204
|
+
},
|
|
1205
|
+
additionalProperties: false
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
: { [keyWhere]: { tsType: getTypeWhereName(x.table) } };
|
|
1209
|
+
// $orderBy only makes sense for a list
|
|
1210
|
+
if (x.grabMany) {
|
|
1211
|
+
argsProperties[keyOrderBy] = {
|
|
1212
|
+
tsType: getTypeOrderByName(x.table)
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
argsProperties[keyFields] = { tsType: getTypeFieldsName(x.table) };
|
|
1216
|
+
const jsonSchemaArgs = {
|
|
1217
|
+
type: "object",
|
|
1218
|
+
properties: argsProperties,
|
|
1219
|
+
additionalProperties: false
|
|
1220
|
+
};
|
|
1221
|
+
properties[x.name] = { enum: [{ type: "boolean" }, jsonSchemaArgs] };
|
|
1222
|
+
}
|
|
1223
|
+
const jsonSchemaFields = {
|
|
1224
|
+
type: "object",
|
|
1225
|
+
additionalProperties: false,
|
|
1226
|
+
properties
|
|
965
1227
|
};
|
|
966
1228
|
let type = await (0, json_schema_to_typescript_1.compile)(jsonSchemaFields, name, json2TsOpts);
|
|
967
|
-
const fieldImports = _.uniq(relations
|
|
968
|
-
.filter((x) => x.table !== table)
|
|
969
|
-
.map((x) => getTypeFieldsName(x.table)));
|
|
1229
|
+
const fieldImports = _.uniq(relations.filter((x) => x.table !== table).map((x) => getTypeFieldsName(x.table)));
|
|
970
1230
|
const whereImports = _.uniq(relations.flatMap((x) => x.type === "many-to-many"
|
|
971
1231
|
? [getTypeWhereName(x.table), getTypeWhereName(x.junctionTable)]
|
|
972
1232
|
: getTypeWhereName(x.table)));
|
|
@@ -1006,10 +1266,10 @@ async function getTypeReturnBase(table, name, includeMappedFields) {
|
|
|
1006
1266
|
acc[key] = { tsType };
|
|
1007
1267
|
}
|
|
1008
1268
|
return acc;
|
|
1009
|
-
}, {})
|
|
1269
|
+
}, {})
|
|
1010
1270
|
},
|
|
1011
1271
|
// Because of aliases
|
|
1012
|
-
additionalProperties: true
|
|
1272
|
+
additionalProperties: true
|
|
1013
1273
|
};
|
|
1014
1274
|
let type = await (0, json_schema_to_typescript_1.compile)(jsonSchemaReturn, name, json2TsOpts);
|
|
1015
1275
|
const imports = _.uniq(relations.map((x) => getTypeReturnBaseName(x.table)))
|
|
@@ -1025,10 +1285,21 @@ function getMaybeNullableTsType(type, nullable) {
|
|
|
1025
1285
|
}
|
|
1026
1286
|
return type;
|
|
1027
1287
|
}
|
|
1028
|
-
|
|
1288
|
+
function getArtifactsSource(artifacts) {
|
|
1289
|
+
const src = `
|
|
1290
|
+
import type {IArtifacts} from "./IRuntime";
|
|
1291
|
+
|
|
1292
|
+
export const artifacts: IArtifacts = ${JSON.stringify(artifacts)};
|
|
1293
|
+
`;
|
|
1294
|
+
return prettier.format(src, { parser: "typescript" });
|
|
1295
|
+
}
|
|
1296
|
+
async function getArtifacts(tables, includeMappedFields, specialCaseUuidColumn) {
|
|
1029
1297
|
const tableMetaList = await Promise.all(tables.map(async (table) => {
|
|
1030
|
-
const tableMeta = await
|
|
1031
|
-
|
|
1298
|
+
const [tableMeta, primaryKey, dumpSchema] = await Promise.all([
|
|
1299
|
+
getTableMeta(table),
|
|
1300
|
+
getPrimaryColumn(table).then((x) => x.name),
|
|
1301
|
+
getShowCreateTable(table)
|
|
1302
|
+
]);
|
|
1032
1303
|
const scalarFields = tableMeta.map((x) => x.Field);
|
|
1033
1304
|
const relationInfo = await getRelationInfo(table);
|
|
1034
1305
|
const relationFields = relationInfo.reduce((acc, x) => {
|
|
@@ -1040,7 +1311,7 @@ async function getArtifactsSource(tables, includeMappedFields, specialCaseUuidCo
|
|
|
1040
1311
|
table: x.table,
|
|
1041
1312
|
grabMany: x.grabMany,
|
|
1042
1313
|
nullable: x.nullable,
|
|
1043
|
-
relation: x.relation
|
|
1314
|
+
relation: x.relation
|
|
1044
1315
|
};
|
|
1045
1316
|
}
|
|
1046
1317
|
else {
|
|
@@ -1050,14 +1321,12 @@ async function getArtifactsSource(tables, includeMappedFields, specialCaseUuidCo
|
|
|
1050
1321
|
table: x.table,
|
|
1051
1322
|
junctionTable: x.junctionTable,
|
|
1052
1323
|
grabMany: x.grabMany,
|
|
1053
|
-
relations: x.relations
|
|
1324
|
+
relations: x.relations
|
|
1054
1325
|
};
|
|
1055
1326
|
}
|
|
1056
1327
|
return acc;
|
|
1057
1328
|
}, {});
|
|
1058
|
-
const _mappedFields = includeMappedFields
|
|
1059
|
-
? await getMappedFields(table)
|
|
1060
|
-
: [];
|
|
1329
|
+
const _mappedFields = includeMappedFields ? await getMappedFields(table) : [];
|
|
1061
1330
|
const mappedFields = _mappedFields.length === 0
|
|
1062
1331
|
? null
|
|
1063
1332
|
: _mappedFields.reduce((acc, v) => {
|
|
@@ -1073,6 +1342,49 @@ async function getArtifactsSource(tables, includeMappedFields, specialCaseUuidCo
|
|
|
1073
1342
|
return acc;
|
|
1074
1343
|
}, {});
|
|
1075
1344
|
const uniqueFields = await getUniqueColumns(table, specialCaseUuidColumn);
|
|
1345
|
+
let fields = tableMeta.map((t) => {
|
|
1346
|
+
const nullable = t.Null === "YES";
|
|
1347
|
+
const isEnum = t.Type.startsWith("enum");
|
|
1348
|
+
if (isEnum) {
|
|
1349
|
+
const values = getPropertyEnum(t.Type);
|
|
1350
|
+
if (values && nullable) {
|
|
1351
|
+
values.push(null);
|
|
1352
|
+
}
|
|
1353
|
+
return {
|
|
1354
|
+
kind: "enum",
|
|
1355
|
+
values,
|
|
1356
|
+
name: t.Field,
|
|
1357
|
+
nullable
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
return {
|
|
1361
|
+
kind: "scalar",
|
|
1362
|
+
type: getBaseJSONType(t.Type),
|
|
1363
|
+
name: t.Field,
|
|
1364
|
+
nullable,
|
|
1365
|
+
hasDefaultValue: !!t.Default
|
|
1366
|
+
};
|
|
1367
|
+
});
|
|
1368
|
+
for (let x of _mappedFields) {
|
|
1369
|
+
fields.push({
|
|
1370
|
+
kind: "scalar",
|
|
1371
|
+
type: x.type,
|
|
1372
|
+
name: x.as,
|
|
1373
|
+
nullable: x.nullable,
|
|
1374
|
+
// TODO
|
|
1375
|
+
hasDefaultValue: false,
|
|
1376
|
+
mapped: true
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
for (let x of relationInfo) {
|
|
1380
|
+
fields.push({
|
|
1381
|
+
kind: "object",
|
|
1382
|
+
type: x.table,
|
|
1383
|
+
name: x.name,
|
|
1384
|
+
isList: x.grabMany,
|
|
1385
|
+
nullable: x.type === "one-to-many__many-to-one" ? x.nullable : false
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1076
1388
|
return {
|
|
1077
1389
|
table,
|
|
1078
1390
|
primaryKey,
|
|
@@ -1082,18 +1394,15 @@ async function getArtifactsSource(tables, includeMappedFields, specialCaseUuidCo
|
|
|
1082
1394
|
uniqueFields,
|
|
1083
1395
|
dateTimeFields,
|
|
1084
1396
|
dateTimeFieldsCount: Object.keys(dateTimeFields).length,
|
|
1397
|
+
fields,
|
|
1398
|
+
dump: dumpSchema == null ? null : { schema: dumpSchema }
|
|
1085
1399
|
};
|
|
1086
1400
|
}));
|
|
1087
1401
|
const artifacts = tableMetaList.reduce((acc, x) => {
|
|
1088
1402
|
acc[x.table] = x;
|
|
1089
1403
|
return acc;
|
|
1090
1404
|
}, {});
|
|
1091
|
-
|
|
1092
|
-
import type {IArtifacts} from "./IRuntime";
|
|
1093
|
-
|
|
1094
|
-
export const artifacts: IArtifacts = ${JSON.stringify(artifacts)};
|
|
1095
|
-
`;
|
|
1096
|
-
return prettier.format(src, { parser: "typescript" });
|
|
1405
|
+
return artifacts;
|
|
1097
1406
|
}
|
|
1098
1407
|
const getRelationInfo = _.memoize(async function getRelationInfo(table) {
|
|
1099
1408
|
const relationsManyToOne = await getRelationsManyToOne(table);
|
|
@@ -1108,7 +1417,7 @@ const getRelationInfo = _.memoize(async function getRelationInfo(table) {
|
|
|
1108
1417
|
table: x.referencedTable,
|
|
1109
1418
|
name,
|
|
1110
1419
|
relation: x,
|
|
1111
|
-
nullable: x.nullable
|
|
1420
|
+
nullable: x.nullable
|
|
1112
1421
|
};
|
|
1113
1422
|
}));
|
|
1114
1423
|
const relationsOneToManyDuplicates = (0, getDuplicates_1.getDuplicates)(relationsOneToMany.map((x) => x.referencedTable));
|
|
@@ -1131,7 +1440,7 @@ const getRelationInfo = _.memoize(async function getRelationInfo(table) {
|
|
|
1131
1440
|
table: x.referencedTable,
|
|
1132
1441
|
name,
|
|
1133
1442
|
relation: x,
|
|
1134
|
-
nullable: x.nullable
|
|
1443
|
+
nullable: x.nullable
|
|
1135
1444
|
};
|
|
1136
1445
|
}));
|
|
1137
1446
|
const relationsManyToMany = (await getJunctionTables()).reduce((acc, x) => {
|
|
@@ -1150,7 +1459,7 @@ const getRelationInfo = _.memoize(async function getRelationInfo(table) {
|
|
|
1150
1459
|
name: changeCase.camelCase(dataForChildTable.referencedTable) + "List",
|
|
1151
1460
|
// Ensure parent comes before child
|
|
1152
1461
|
relations: [dataForParentTable, dataForChildTable],
|
|
1153
|
-
grabMany: true
|
|
1462
|
+
grabMany: true
|
|
1154
1463
|
});
|
|
1155
1464
|
return acc;
|
|
1156
1465
|
}, []);
|
|
@@ -1171,7 +1480,7 @@ async function getJunctionTables() {
|
|
|
1171
1480
|
// e.g. junction of Foo, Bar must be FooBar or BarFoo
|
|
1172
1481
|
[
|
|
1173
1482
|
relations[0].referencedTable + relations[1].referencedTable,
|
|
1174
|
-
relations[1].referencedTable + relations[0].referencedTable
|
|
1483
|
+
relations[1].referencedTable + relations[0].referencedTable
|
|
1175
1484
|
].includes(table)) {
|
|
1176
1485
|
return { table, relations };
|
|
1177
1486
|
}
|
|
@@ -1227,7 +1536,7 @@ const getRelationsManyToOne = _.memoize(async function getRelationsManyToOne(tab
|
|
|
1227
1536
|
foreignKey: v.t1Field,
|
|
1228
1537
|
referencedTable: v.t2,
|
|
1229
1538
|
referencedKey: v.t2Field,
|
|
1230
|
-
nullable: tableMeta.find((m) => m.Field === v.t1Field)?.Null === "YES"
|
|
1539
|
+
nullable: tableMeta.find((m) => m.Field === v.t1Field)?.Null === "YES"
|
|
1231
1540
|
};
|
|
1232
1541
|
})));
|
|
1233
1542
|
return _.sortBy((x) => x.referencedTable, xs);
|
|
@@ -1276,7 +1585,7 @@ const getRelationsOneToMany = _.memoize(async function getRelationsOneToMany(tab
|
|
|
1276
1585
|
referencedTable: v.t1,
|
|
1277
1586
|
referencedKey: v.t1Field,
|
|
1278
1587
|
// TODO? I think this is right, since it's one-to-many, so a list
|
|
1279
|
-
nullable: false
|
|
1588
|
+
nullable: false
|
|
1280
1589
|
};
|
|
1281
1590
|
})));
|
|
1282
1591
|
return _.sortBy((x) => x.referencedKey, _.sortBy((x) => x.referencedTable, xs));
|
|
@@ -1291,7 +1600,7 @@ async function getPrimaryColumn(table) {
|
|
|
1291
1600
|
return {
|
|
1292
1601
|
name: column.Field,
|
|
1293
1602
|
type: getBaseJSONType(column.Type),
|
|
1294
|
-
nullable: column.Null === "YES"
|
|
1603
|
+
nullable: column.Null === "YES"
|
|
1295
1604
|
};
|
|
1296
1605
|
}
|
|
1297
1606
|
async function getUniqueColumns(table, specialCaseUuidColumn) {
|
|
@@ -1303,7 +1612,7 @@ async function getUniqueColumns(table, specialCaseUuidColumn) {
|
|
|
1303
1612
|
.map((x) => ({
|
|
1304
1613
|
name: x.Field,
|
|
1305
1614
|
type: getBaseJSONType(x.Type),
|
|
1306
|
-
nullable: x.Null === "YES"
|
|
1615
|
+
nullable: x.Null === "YES"
|
|
1307
1616
|
}));
|
|
1308
1617
|
}
|
|
1309
1618
|
async function getUuidColumn(table) {
|
|
@@ -1315,14 +1624,14 @@ async function getUuidColumn(table) {
|
|
|
1315
1624
|
return {
|
|
1316
1625
|
name: column.Field,
|
|
1317
1626
|
type: column.Type,
|
|
1318
|
-
nullable: column.Null === "YES"
|
|
1627
|
+
nullable: column.Null === "YES"
|
|
1319
1628
|
};
|
|
1320
1629
|
}
|
|
1321
1630
|
const getTableMeta = _.memoize(async function getTableMeta(table) {
|
|
1322
1631
|
if (dialect === "mysql") {
|
|
1323
1632
|
return query("DESCRIBE ??", [table]).then((xs) => _.sortBy((x) => x.Field, xs));
|
|
1324
1633
|
}
|
|
1325
|
-
if (dialect === "mssql"
|
|
1634
|
+
if (dialect === "mssql") {
|
|
1326
1635
|
const primaryColumn = await query(`SELECT columns.name as COLUMN_NAME
|
|
1327
1636
|
FROM sys.tables tables
|
|
1328
1637
|
JOIN sys.columns columns
|
|
@@ -1359,12 +1668,20 @@ const getTableMeta = _.memoize(async function getTableMeta(table) {
|
|
|
1359
1668
|
? "UNI"
|
|
1360
1669
|
: "",
|
|
1361
1670
|
Null: x["IS_NULLABLE"],
|
|
1362
|
-
Default: x["COLUMN_DEFAULT"]
|
|
1671
|
+
Default: x["COLUMN_DEFAULT"]
|
|
1363
1672
|
};
|
|
1364
1673
|
})));
|
|
1365
1674
|
}
|
|
1366
1675
|
throw new Error("Unsupported dialect: " + dialect);
|
|
1367
1676
|
});
|
|
1677
|
+
function getShowCreateTable(table) {
|
|
1678
|
+
if (dialect === "mysql") {
|
|
1679
|
+
return query("SHOW CREATE TABLE ??", [table]).then((xs) => xs[0]["Create Table"]
|
|
1680
|
+
// https://github.com/bradzacher/mysqldump/blob/66839a57e572a07c046b0ba98753f30a7026cbd8/src/getSchemaDump.ts#L65
|
|
1681
|
+
.replace(/AUTO_INCREMENT\s*=\s*\d+ /g, ""));
|
|
1682
|
+
}
|
|
1683
|
+
return Promise.resolve(null);
|
|
1684
|
+
}
|
|
1368
1685
|
function getJSONSchemaObjProperties(tableMeta) {
|
|
1369
1686
|
return tableMeta.reduce((acc, m) => {
|
|
1370
1687
|
const baseType = getBaseJSONType(m.Type);
|
|
@@ -1378,7 +1695,7 @@ function getJSONSchemaObjProperties(tableMeta) {
|
|
|
1378
1695
|
_enum.push(null);
|
|
1379
1696
|
}
|
|
1380
1697
|
acc[m.Field] = {
|
|
1381
|
-
type: getJSONTypes(baseType, nullable)
|
|
1698
|
+
type: getJSONTypes(baseType, nullable)
|
|
1382
1699
|
// maxLength:
|
|
1383
1700
|
// baseType === "string" && format == null && isEnum == null
|
|
1384
1701
|
// ? getPropertyMaxLength(m.Type)
|
|
@@ -1488,9 +1805,7 @@ function getPropertyEnum(sqlType) {
|
|
|
1488
1805
|
return c;
|
|
1489
1806
|
}
|
|
1490
1807
|
function getPropertyFormat(sqlType) {
|
|
1491
|
-
if (sqlType === "datetime" ||
|
|
1492
|
-
sqlType === "datetime2" ||
|
|
1493
|
-
sqlType === "timestamp") {
|
|
1808
|
+
if (sqlType === "datetime" || sqlType === "datetime2" || sqlType === "timestamp") {
|
|
1494
1809
|
// TODO: not sure this is correct for `timestamp`
|
|
1495
1810
|
return "date-time";
|
|
1496
1811
|
}
|
|
@@ -1514,13 +1829,13 @@ const mssqlTableExcludes = new Set([
|
|
|
1514
1829
|
"ddl_history",
|
|
1515
1830
|
"index_columns",
|
|
1516
1831
|
"lsn_time_mapping",
|
|
1517
|
-
"systranschemas"
|
|
1832
|
+
"systranschemas"
|
|
1518
1833
|
]);
|
|
1519
1834
|
async function getTableNames() {
|
|
1520
1835
|
if (dialect === "mysql") {
|
|
1521
1836
|
return query("SHOW TABLES").then((xs) => xs.flatMap((x) => Object.values(x)).sort());
|
|
1522
1837
|
}
|
|
1523
|
-
if (dialect === "mssql"
|
|
1838
|
+
if (dialect === "mssql") {
|
|
1524
1839
|
return query("SELECT * FROM INFORMATION_SCHEMA.TABLES").then((xs) => xs
|
|
1525
1840
|
.map((x) => x["TABLE_NAME"])
|
|
1526
1841
|
.filter((x) => !x.startsWith("dbo_") && !mssqlTableExcludes.has(x))
|
|
@@ -1528,3 +1843,295 @@ async function getTableNames() {
|
|
|
1528
1843
|
}
|
|
1529
1844
|
throw new Error("Unsupported dialect: " + dialect);
|
|
1530
1845
|
}
|
|
1846
|
+
function getMysql2sqliteSrc() {
|
|
1847
|
+
return `#!/usr/bin/awk -f
|
|
1848
|
+
|
|
1849
|
+
# Authors: @esperlu, @artemyk, @gkuenning, @dumblob
|
|
1850
|
+
|
|
1851
|
+
# FIXME detect empty input file and issue a warning
|
|
1852
|
+
|
|
1853
|
+
function printerr( s ){ print s | "cat >&2" }
|
|
1854
|
+
|
|
1855
|
+
BEGIN {
|
|
1856
|
+
if( ARGC != 2 ){
|
|
1857
|
+
printerr( \\
|
|
1858
|
+
"USAGE:\\n"\\
|
|
1859
|
+
" mysql2sqlite dump_mysql.sql > dump_sqlite3.sql\\n" \\
|
|
1860
|
+
" OR\\n" \\
|
|
1861
|
+
" mysql2sqlite dump_mysql.sql | sqlite3 sqlite.db\\n" \\
|
|
1862
|
+
"\\n" \\
|
|
1863
|
+
"NOTES:\\n" \\
|
|
1864
|
+
" Dash in filename is not supported, because dash (-) means stdin." )
|
|
1865
|
+
no_END = 1
|
|
1866
|
+
exit 1
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
# Find INT_MAX supported by both this AWK (usually an ISO C signed int)
|
|
1870
|
+
# and SQlite.
|
|
1871
|
+
# On non-8bit-based architectures, the additional bits are safely ignored.
|
|
1872
|
+
|
|
1873
|
+
# 8bit (lower precision should not exist)
|
|
1874
|
+
s="127"
|
|
1875
|
+
# "63" + 0 avoids potential parser misbehavior
|
|
1876
|
+
if( (s + 0) "" == s ){ INT_MAX_HALF = "63" + 0 }
|
|
1877
|
+
# 16bit
|
|
1878
|
+
s="32767"
|
|
1879
|
+
if( (s + 0) "" == s ){ INT_MAX_HALF = "16383" + 0 }
|
|
1880
|
+
# 32bit
|
|
1881
|
+
s="2147483647"
|
|
1882
|
+
if( (s + 0) "" == s ){ INT_MAX_HALF = "1073741823" + 0 }
|
|
1883
|
+
# 64bit (as INTEGER in SQlite3)
|
|
1884
|
+
s="9223372036854775807"
|
|
1885
|
+
if( (s + 0) "" == s ){ INT_MAX_HALF = "4611686018427387904" + 0 }
|
|
1886
|
+
# # 128bit
|
|
1887
|
+
# s="170141183460469231731687303715884105728"
|
|
1888
|
+
# if( (s + 0) "" == s ){ INT_MAX_HALF = "85070591730234615865843651857942052864" + 0 }
|
|
1889
|
+
# # 256bit
|
|
1890
|
+
# s="57896044618658097711785492504343953926634992332820282019728792003956564819968"
|
|
1891
|
+
# if( (s + 0) "" == s ){ INT_MAX_HALF = "28948022309329048855892746252171976963317496166410141009864396001978282409984" + 0 }
|
|
1892
|
+
# # 512bit
|
|
1893
|
+
# s="6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048"
|
|
1894
|
+
# if( (s + 0) "" == s ){ INT_MAX_HALF = "3351951982485649274893506249551461531869841455148098344430890360930441007518386744200468574541725856922507964546621512713438470702986642486608412251521024" + 0 }
|
|
1895
|
+
# # 1024bit
|
|
1896
|
+
# s="89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678164812112068608"
|
|
1897
|
+
# if( (s + 0) "" == s ){ INT_MAX_HALF = "44942328371557897693232629769725618340449424473557664318357520289433168951375240783177119330601884005280028469967848339414697442203604155623211857659868531094441973356216371319075554900311523529863270738021251442209537670585615720368478277635206809290837627671146574559986811484619929076208839082406056034304" + 0 }
|
|
1898
|
+
# # higher precision probably not needed
|
|
1899
|
+
|
|
1900
|
+
FS=",$"
|
|
1901
|
+
print "PRAGMA synchronous = OFF;"
|
|
1902
|
+
print "PRAGMA journal_mode = MEMORY;"
|
|
1903
|
+
print "BEGIN TRANSACTION;"
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
# historically 3 spaces separate non-argument local variables
|
|
1907
|
+
function bit_to_int( str_bit, powtwo, i, res, bit, overflow ){
|
|
1908
|
+
powtwo = 1
|
|
1909
|
+
overflow = 0
|
|
1910
|
+
# 011101 = 1*2^0 + 0*2^1 + 1*2^2 ...
|
|
1911
|
+
for( i = length( str_bit ); i > 0; --i ){
|
|
1912
|
+
bit = substr( str_bit, i, 1 )
|
|
1913
|
+
if( overflow || ( bit == 1 && res > INT_MAX_HALF ) ){
|
|
1914
|
+
printerr( \\
|
|
1915
|
+
NR ": WARN Bit field overflow, number truncated (LSBs saved, MSBs ignored)." )
|
|
1916
|
+
break
|
|
1917
|
+
}
|
|
1918
|
+
res = res + bit * powtwo
|
|
1919
|
+
# no warning here as it might be the last iteration
|
|
1920
|
+
if( powtwo > INT_MAX_HALF ){ overflow = 1; continue }
|
|
1921
|
+
powtwo = powtwo * 2
|
|
1922
|
+
}
|
|
1923
|
+
return res
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
# CREATE TRIGGER statements have funny commenting. Remember we are in trigger.
|
|
1927
|
+
/^\\/\\*.*(CREATE.*TRIGGER|create.*trigger)/ {
|
|
1928
|
+
gsub( /^.*(TRIGGER|trigger)/, "CREATE TRIGGER" )
|
|
1929
|
+
print
|
|
1930
|
+
inTrigger = 1
|
|
1931
|
+
next
|
|
1932
|
+
}
|
|
1933
|
+
# The end of CREATE TRIGGER has a stray comment terminator
|
|
1934
|
+
/(END|end) \\*\\/;;/ { gsub( /\\*\\//, "" ); print; inTrigger = 0; next }
|
|
1935
|
+
# The rest of triggers just get passed through
|
|
1936
|
+
inTrigger != 0 { print; next }
|
|
1937
|
+
|
|
1938
|
+
# CREATE VIEW looks like a TABLE in comments
|
|
1939
|
+
/^\\/\\*.*(CREATE.*TABLE|create.*table)/ {
|
|
1940
|
+
inView = 1
|
|
1941
|
+
next
|
|
1942
|
+
}
|
|
1943
|
+
# end of CREATE VIEW
|
|
1944
|
+
/^(\\).*(ENGINE|engine).*\\*\\/;)/ {
|
|
1945
|
+
inView = 0
|
|
1946
|
+
next
|
|
1947
|
+
}
|
|
1948
|
+
# content of CREATE VIEW
|
|
1949
|
+
inView != 0 { next }
|
|
1950
|
+
|
|
1951
|
+
# skip comments
|
|
1952
|
+
/^\\/\\*/ { next }
|
|
1953
|
+
|
|
1954
|
+
# skip PARTITION statements
|
|
1955
|
+
/^ *[(]?(PARTITION|partition) +[^ ]+/ { next }
|
|
1956
|
+
|
|
1957
|
+
# print all INSERT lines
|
|
1958
|
+
( /^ *\\(/ && /\\) *[,;] *$/ ) || /^(INSERT|insert|REPLACE|replace)/ {
|
|
1959
|
+
prev = ""
|
|
1960
|
+
|
|
1961
|
+
# first replace \\\\ by \\_ that mysqldump never generates to deal with
|
|
1962
|
+
# sequnces like \\\\n that should be translated into \\n, not \\<LF>.
|
|
1963
|
+
# After we convert all escapes we replace \\_ by backslashes.
|
|
1964
|
+
gsub( /\\\\\\\\/, "\\\\_" )
|
|
1965
|
+
|
|
1966
|
+
# single quotes are escaped by another single quote
|
|
1967
|
+
gsub( /\\\\'/, "''" )
|
|
1968
|
+
gsub( /\\\\n/, "\\n" )
|
|
1969
|
+
gsub( /\\\\r/, "\\r" )
|
|
1970
|
+
gsub( /\\\\"/, "\\"" )
|
|
1971
|
+
gsub( /\\\\\\032/, "\\032" ) # substitute char
|
|
1972
|
+
|
|
1973
|
+
gsub( /\\\\_/, "\\\\" )
|
|
1974
|
+
|
|
1975
|
+
# sqlite3 is limited to 16 significant digits of precision
|
|
1976
|
+
while( match( $0, /0x[0-9a-fA-F]{17}/ ) ){
|
|
1977
|
+
hexIssue = 1
|
|
1978
|
+
sub( /0x[0-9a-fA-F]+/, substr( $0, RSTART, RLENGTH-1 ), $0 )
|
|
1979
|
+
}
|
|
1980
|
+
if( hexIssue ){
|
|
1981
|
+
printerr( \\
|
|
1982
|
+
NR ": WARN Hex number trimmed (length longer than 16 chars)." )
|
|
1983
|
+
hexIssue = 0
|
|
1984
|
+
}
|
|
1985
|
+
print
|
|
1986
|
+
next
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
# CREATE DATABASE is not supported
|
|
1990
|
+
/^(CREATE DATABASE|create database)/ { next }
|
|
1991
|
+
|
|
1992
|
+
# print the CREATE line as is and capture the table name
|
|
1993
|
+
/^(CREATE|create)/ {
|
|
1994
|
+
if( $0 ~ /IF NOT EXISTS|if not exists/ || $0 ~ /TEMPORARY|temporary/ ){
|
|
1995
|
+
caseIssue = 1
|
|
1996
|
+
printerr( \\
|
|
1997
|
+
NR ": WARN Potential case sensitivity issues with table/column naming\\n" \\
|
|
1998
|
+
" (see INFO at the end)." )
|
|
1999
|
+
}
|
|
2000
|
+
if( match( $0, /\`[^\`]+/ ) ){
|
|
2001
|
+
tableName = substr( $0, RSTART+1, RLENGTH-1 )
|
|
2002
|
+
}
|
|
2003
|
+
aInc = 0
|
|
2004
|
+
prev = ""
|
|
2005
|
+
firstInTable = 1
|
|
2006
|
+
print
|
|
2007
|
+
next
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
# Replace \`FULLTEXT KEY\` (probably other \`XXXXX KEY\`)
|
|
2011
|
+
/^ (FULLTEXT KEY|fulltext key)/ { gsub( /[A-Za-z ]+(KEY|key)/, " KEY" ) }
|
|
2012
|
+
|
|
2013
|
+
# Get rid of field lengths in KEY lines
|
|
2014
|
+
/ (PRIMARY |primary )?(KEY|key)/ { gsub( /\\([0-9]+\\)/, "" ) }
|
|
2015
|
+
|
|
2016
|
+
aInc == 1 && /PRIMARY KEY|primary key/ { next }
|
|
2017
|
+
|
|
2018
|
+
# Replace COLLATE xxx_xxxx_xx statements with COLLATE BINARY
|
|
2019
|
+
/ (COLLATE|collate) [a-z0-9_]*/ { gsub( /(COLLATE|collate) [a-z0-9_]*/, "COLLATE BINARY" ) }
|
|
2020
|
+
|
|
2021
|
+
# Print all fields definition lines except the \`KEY\` lines.
|
|
2022
|
+
/^ / && !/^( (KEY|key)|\\);)/ {
|
|
2023
|
+
if( match( $0, /[^"\`]AUTO_INCREMENT|auto_increment[^"\`]/) ){
|
|
2024
|
+
aInc = 1
|
|
2025
|
+
gsub( /AUTO_INCREMENT|auto_increment/, "PRIMARY KEY AUTOINCREMENT" )
|
|
2026
|
+
}
|
|
2027
|
+
gsub( /(UNIQUE KEY|unique key) (\`.*\`|".*") /, "UNIQUE " )
|
|
2028
|
+
gsub( /(CHARACTER SET|character set) [^ ]+[ ,]/, "" )
|
|
2029
|
+
# FIXME
|
|
2030
|
+
# CREATE TRIGGER [UpdateLastTime]
|
|
2031
|
+
# AFTER UPDATE
|
|
2032
|
+
# ON Package
|
|
2033
|
+
# FOR EACH ROW
|
|
2034
|
+
# BEGIN
|
|
2035
|
+
# UPDATE Package SET LastUpdate = CURRENT_TIMESTAMP WHERE ActionId = old.ActionId;
|
|
2036
|
+
# END
|
|
2037
|
+
gsub( /(ON|on) (UPDATE|update) (CURRENT_TIMESTAMP|current_timestamp)(\\(\\))?/, "" )
|
|
2038
|
+
gsub( /(DEFAULT|default) (CURRENT_TIMESTAMP|current_timestamp)(\\(\\))?/, "DEFAULT current_timestamp")
|
|
2039
|
+
gsub( /(COLLATE|collate) [^ ]+ /, "" )
|
|
2040
|
+
gsub( /(ENUM|enum)[^)]+\\)/, "text " )
|
|
2041
|
+
gsub( /(SET|set)\\([^)]+\\)/, "text " )
|
|
2042
|
+
gsub( /UNSIGNED|unsigned/, "" )
|
|
2043
|
+
gsub( /_utf8mb3/, "" )
|
|
2044
|
+
gsub( /\` [^ ]*(INT|int|BIT|bit)[^ ]*/, "\` integer" )
|
|
2045
|
+
gsub( /" [^ ]*(INT|int|BIT|bit)[^ ]*/, "\\" integer" )
|
|
2046
|
+
ere_bit_field = "[bB]'[10]+'"
|
|
2047
|
+
if( match($0, ere_bit_field) ){
|
|
2048
|
+
sub( ere_bit_field, bit_to_int( substr( $0, RSTART +2, RLENGTH -2 -1 ) ) )
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
# remove USING BTREE and other suffixes for USING, for example: "UNIQUE KEY
|
|
2052
|
+
# \`hostname_domain\` (\`hostname\`,\`domain\`) USING BTREE,"
|
|
2053
|
+
gsub( / USING [^, ]+/, "" )
|
|
2054
|
+
|
|
2055
|
+
# field comments are not supported
|
|
2056
|
+
gsub( / (COMMENT|comment).+$/, "" )
|
|
2057
|
+
# Get commas off end of line
|
|
2058
|
+
gsub( /,.?$/, "" )
|
|
2059
|
+
if( prev ){
|
|
2060
|
+
if( firstInTable ){
|
|
2061
|
+
print prev
|
|
2062
|
+
firstInTable = 0
|
|
2063
|
+
}
|
|
2064
|
+
else {
|
|
2065
|
+
print "," prev
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
else {
|
|
2069
|
+
# FIXME check if this is correct in all cases
|
|
2070
|
+
if( match( $1,
|
|
2071
|
+
/(CONSTRAINT|constraint) ["].*["] (FOREIGN KEY|foreign key)/ ) ){
|
|
2072
|
+
print ","
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
prev = $1
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
/ ENGINE| engine/ {
|
|
2079
|
+
if( prev ){
|
|
2080
|
+
if( firstInTable ){
|
|
2081
|
+
print prev
|
|
2082
|
+
firstInTable = 0
|
|
2083
|
+
}
|
|
2084
|
+
else {
|
|
2085
|
+
print "," prev
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
prev=""
|
|
2089
|
+
print ");"
|
|
2090
|
+
next
|
|
2091
|
+
}
|
|
2092
|
+
# \`KEY\` lines are extracted from the \`CREATE\` block and stored in array for later print
|
|
2093
|
+
# in a separate \`CREATE KEY\` command. The index name is prefixed by the table name to
|
|
2094
|
+
# avoid a sqlite error for duplicate index name.
|
|
2095
|
+
/^( (KEY|key)|\\);)/ {
|
|
2096
|
+
if( prev ){
|
|
2097
|
+
if( firstInTable ){
|
|
2098
|
+
print prev
|
|
2099
|
+
firstInTable = 0
|
|
2100
|
+
}
|
|
2101
|
+
else {
|
|
2102
|
+
print "," prev
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
prev = ""
|
|
2106
|
+
if( $0 == ");" ){
|
|
2107
|
+
print
|
|
2108
|
+
}
|
|
2109
|
+
else {
|
|
2110
|
+
if( match( $0, /\`[^\`]+/ ) ){
|
|
2111
|
+
indexName = substr( $0, RSTART+1, RLENGTH-1 )
|
|
2112
|
+
}
|
|
2113
|
+
if( match( $0, /\\([^()]+/ ) ){
|
|
2114
|
+
indexKey = substr( $0, RSTART+1, RLENGTH-1 )
|
|
2115
|
+
}
|
|
2116
|
+
# idx_ prefix to avoid name clashes (they really happen!)
|
|
2117
|
+
key[tableName] = key[tableName] "CREATE INDEX \\"idx_" \\
|
|
2118
|
+
tableName "_" indexName "\\" ON \\"" tableName "\\" (" indexKey ");\\n"
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
END {
|
|
2123
|
+
if( no_END ){ exit 1}
|
|
2124
|
+
# print all KEY creation lines.
|
|
2125
|
+
for( table in key ){ printf key[table] }
|
|
2126
|
+
|
|
2127
|
+
print "END TRANSACTION;"
|
|
2128
|
+
|
|
2129
|
+
if( caseIssue ){
|
|
2130
|
+
printerr( \\
|
|
2131
|
+
"INFO Pure sqlite identifiers are case insensitive (even if quoted\\n" \\
|
|
2132
|
+
" or if ASCII) and doesnt cross-check TABLE and TEMPORARY TABLE\\n" \\
|
|
2133
|
+
" identifiers. Thus expect errors like \\"table T has no column named F\\".")
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
`;
|
|
2137
|
+
}
|