sasat 0.22.0 → 0.22.2

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/dist/index.mjs CHANGED
@@ -1,3930 +1,6 @@
1
- import fs, { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import * as path$1 from "node:path";
3
- import path, { join } from "node:path";
4
- import { mkdir, readdir, rm, writeFile } from "node:fs/promises";
5
- import yaml from "js-yaml";
6
- import "pluralize";
7
- import typescript from "typescript";
8
- import chalk from "chalk";
1
+ import { D as setConfig, a as getDbClient, b as unique, c as formatQuery, d as SasatError, j as assignDeep, m as Conditions, o as MySqlTransaction, s as DBClient, t as migrate, u as SqlString, v as nonNullable, y as pick } from "./migrate-Cbj2OVbY.mjs";
9
2
  import * as SqlString$1 from "sqlstring";
10
- import pkg from "sqlstring";
11
- import { createConnection, createPool } from "mysql2/promise";
12
- import { build } from "esbuild";
13
- //#region src/util/assignDeep.ts
14
- const assignDeep = (base, ...objects) => {
15
- const assign = (target, key, value) => {
16
- if (key === "__proto__" || key === "constructor") return;
17
- if (Array.isArray(target[key]) && Array.isArray(value)) target[key] = [...target[key], ...value];
18
- else if (typeof target[key] === "object" && typeof value === "object") assignDeep(target[key], value);
19
- else target[key] = value;
20
- };
21
- objects.forEach((obj) => {
22
- if (typeof obj === "object") Object.entries(obj).forEach(([key, value]) => {
23
- assign(base, key, value);
24
- });
25
- });
26
- return base;
27
- };
28
- //#endregion
29
- //#region src/util/fsUtil.ts
30
- const readYmlFile = (filepath) => yaml.load(readFileSync(filepath, "utf8"));
31
- const mkDirIfNotExist = (path) => {
32
- if (!existsSync(path)) mkdirSync(path);
33
- };
34
- const writeFileIfNotExist = (path, data) => {
35
- if (existsSync(path)) return Promise.resolve();
36
- return writeFile(path, data);
37
- };
38
- const writeYmlFile = (path, fileName, obj) => {
39
- mkDirIfNotExist(path);
40
- writeFileSync(join(path, fileName), yaml.dump(obj, {
41
- skipInvalid: true,
42
- noRefs: true,
43
- sortKeys: (a, b) => {
44
- if (b === "tableName") return 1;
45
- if (a === "tableName") return -1;
46
- if (a > b) return 1;
47
- if (a < b) return -1;
48
- return 0;
49
- }
50
- }));
51
- };
52
- const readInitialSchema = () => {
53
- return readYmlFile(join(config().migration.dir, "initialSchema.yml"));
54
- };
55
- const writeCurrentSchema = (schema) => {
56
- writeYmlFile(config().migration.dir, "currentSchema.yml", schema);
57
- };
58
- //#endregion
59
- //#region src/config/loader.ts
60
- var SasatConfigLoader = class SasatConfigLoader {
61
- static loadConfig() {
62
- const filepath = path.join(process.cwd(), "sasat.yml");
63
- if (!existsSync(filepath)) return defaultConf;
64
- return readYmlFile(filepath);
65
- }
66
- constructor() {
67
- const conf = this.readValue({
68
- ...defaultConf,
69
- ...SasatConfigLoader.loadConfig()
70
- });
71
- this.conf = { ...conf };
72
- }
73
- getConfig() {
74
- return this.conf;
75
- }
76
- readValue(value) {
77
- if (!value) return value;
78
- if (Array.isArray(value)) return value.map((it) => this.readValue(it));
79
- if (typeof value === "string" && value.startsWith("$")) return process.env[value.slice(1)];
80
- if (typeof value === "object") {
81
- for (const key in value) if (Object.hasOwn(value, key)) value[key] = this.readValue(value[key]);
82
- return value;
83
- }
84
- return value;
85
- }
86
- };
87
- const defaultConf = {
88
- db: {
89
- host: "127.0.0.1",
90
- port: 3306,
91
- user: "root",
92
- database: "sasat",
93
- password: ""
94
- },
95
- migration: {
96
- table: "__migrate__",
97
- dir: "migrations",
98
- out: "sasat"
99
- },
100
- generator: {
101
- addJsExtToImportStatement: false,
102
- gql: { subscription: true }
103
- }
104
- };
105
- let conf;
106
- const config = () => {
107
- if (conf === void 0) conf = new SasatConfigLoader().getConfig();
108
- return conf;
109
- };
110
- function setConfig(update) {
111
- conf = assignDeep(config(), update);
112
- return conf;
113
- }
114
- //#endregion
115
- //#region src/generatorv2/fs/emptyDir.ts
116
- async function emptyDir(dir) {
117
- let items;
118
- try {
119
- items = await readdir(dir);
120
- } catch {
121
- return mkdir(dir, { mode: 511 });
122
- }
123
- return Promise.all(items.map((item) => rm(path.join(dir, item), {
124
- recursive: true,
125
- force: true
126
- })));
127
- }
128
- //#endregion
129
- //#region src/generatorv2/codegen/ts/tsFileNames.ts
130
- const tsFileNames = {
131
- encoder: "idEncoder",
132
- conditions: "conditions",
133
- middleware: "middlewares"
134
- };
135
- //#endregion
136
- //#region src/migration/column/columnTypes.ts
137
- const columnTypeToTsType = (type) => {
138
- switch (type) {
139
- case "tinyint":
140
- case "smallint":
141
- case "mediumint":
142
- case "int":
143
- case "bigint":
144
- case "float":
145
- case "double":
146
- case "decimal":
147
- case "year": return "number";
148
- case "char":
149
- case "varchar":
150
- case "text":
151
- case "time":
152
- case "date":
153
- case "datetime":
154
- case "timestamp": return "string";
155
- case "boolean": return "boolean";
156
- }
157
- };
158
- //#endregion
159
- //#region src/tsg/importDeclaration.ts
160
- var ImportDeclaration = class {
161
- constructor(types, module) {
162
- this.types = types;
163
- this.module = module;
164
- }
165
- toString() {
166
- const addJsExt = config().generator.addJsExtToImportStatement && this.module.startsWith(".");
167
- return `import {${this.types.join(",")}} from "${addJsExt ? this.module + ".js" : this.module}";`;
168
- }
169
- };
170
- //#endregion
171
- //#region src/tsg/abstruct/tsCode.ts
172
- var TsCode = class {
173
- constructor() {
174
- this.importDeclarations = [];
175
- }
176
- addImport(types, module) {
177
- this.importDeclarations.push(new ImportDeclaration(types, module));
178
- return this;
179
- }
180
- toString() {
181
- return this.codePrefix() + this.toTsString();
182
- }
183
- codePrefix() {
184
- return "";
185
- }
186
- mergeImport(...code) {
187
- code.forEach((it) => {
188
- if (it) this.importDeclarations.push(...it.importDeclarations);
189
- });
190
- }
191
- };
192
- //#endregion
193
- //#region src/tsg/abstruct/statement.ts
194
- var TsStatement = class extends TsCode {
195
- constructor(..._args) {
196
- super(..._args);
197
- this.codeType = "statement";
198
- }
199
- };
200
- //#endregion
201
- //#region src/tsg/node/block.ts
202
- const notNull = (v) => {
203
- return v !== null;
204
- };
205
- var Block = class extends TsStatement {
206
- constructor(...statements) {
207
- super();
208
- const sts = statements.filter(notNull);
209
- this.mergeImport(...sts);
210
- this.statements = sts;
211
- }
212
- toTsString() {
213
- return `{${this.statements.map((it) => it.toString()).join("\n")}}`;
214
- }
215
- };
216
- //#endregion
217
- //#region src/tsg/abstruct/exportableDeclaration.ts
218
- var ExportableDeclaration = class extends TsStatement {
219
- constructor(..._args) {
220
- super(..._args);
221
- this.isExported = false;
222
- }
223
- codePrefix() {
224
- return this.isExported ? "export " : "";
225
- }
226
- export() {
227
- this.isExported = true;
228
- return this;
229
- }
230
- };
231
- //#endregion
232
- //#region src/tsg/node/class.ts
233
- var Class = class extends ExportableDeclaration {
234
- constructor(name) {
235
- super();
236
- this.name = name;
237
- this.properties = [];
238
- this.methods = [];
239
- this.isAbstract = false;
240
- }
241
- abstract() {
242
- this.isAbstract = true;
243
- return this;
244
- }
245
- extends(value) {
246
- this._extends = value;
247
- this.mergeImport(value);
248
- return this;
249
- }
250
- implements(value) {
251
- this._implements = value;
252
- this.mergeImport(value);
253
- return this;
254
- }
255
- addProperty(...properties) {
256
- this.properties.push(...properties);
257
- this.mergeImport(...properties);
258
- return this;
259
- }
260
- addMethod(...methods) {
261
- this.methods.push(...methods);
262
- this.mergeImport(...methods);
263
- return this;
264
- }
265
- toTsString() {
266
- const properties = this.properties.map((it) => it.toString()).join("");
267
- const methods = this.methods.map((it) => it.toString()).join("");
268
- const implement = this._implements ? this._implements.toString() + " " : "";
269
- const extend = this._extends ? this._extends.toString() + "" : "";
270
- return (this.isAbstract ? "abstract " : "") + `class ${this.name} ${implement}${extend}{${properties}${methods}}`;
271
- }
272
- };
273
- //#endregion
274
- //#region src/tsg/node/enumDeclaration.ts
275
- var EnumDeclaration = class extends ExportableDeclaration {
276
- constructor(identifier, members) {
277
- super();
278
- this.identifier = identifier;
279
- this.members = members;
280
- this.mergeImport(identifier, ...members);
281
- }
282
- addMembers(...members) {
283
- this.members.push(...members);
284
- this.mergeImport(...members);
285
- return this;
286
- }
287
- toTsString() {
288
- return `enum ${this.identifier}{${this.members.map((it) => it.toString() + ",").join("")}}`;
289
- }
290
- };
291
- //#endregion
292
- //#region src/tsg/node/enumMember.ts
293
- var EnumMember = class extends TsCode {
294
- constructor(identifier, value) {
295
- super();
296
- this.identifier = identifier;
297
- this.value = value;
298
- this.mergeImport(identifier);
299
- if (value) this.mergeImport(value);
300
- }
301
- toTsString() {
302
- if (!this.value) return this.identifier.toString();
303
- return this.identifier + "=" + this.value;
304
- }
305
- };
306
- //#endregion
307
- //#region src/tsg/node/expressionStatement.ts
308
- var ExpressionStatement = class extends TsStatement {
309
- constructor(expression) {
310
- super();
311
- this.expression = expression;
312
- this.mergeImport(expression);
313
- }
314
- toTsString() {
315
- return this.expression.toString() + ";";
316
- }
317
- };
318
- //#endregion
319
- //#region src/tsg/tsValueString.ts
320
- const tsValueString = (value) => {
321
- if (value === null) return "null";
322
- if (value === void 0) return "undefined";
323
- if (typeof value === "number") return "" + value;
324
- if (typeof value === "boolean") return "" + value;
325
- if (typeof value === "string") return `'${value.replaceAll("'", "\\'")}'`;
326
- if (typeof value === "bigint") return "" + value;
327
- if (typeof value === "function") return value.toString();
328
- if (Array.isArray(value)) return `[${value.map(tsValueString).join(",")}]`;
329
- if (typeof value === "object") return `{${Object.entries(value).map(([key, value]) => [key, tsValueString(value)]).map(([key, value]) => `${key}: ${value}`).join(",")}}`;
330
- throw new TypeError(`tsValueString::unsupported data type ${typeof value}`);
331
- };
332
- //#endregion
333
- //#region src/tsg/node/parameter.ts
334
- var Parameter = class extends TsCode {
335
- constructor(paramName, type) {
336
- super();
337
- this.paramName = paramName;
338
- this.type = type;
339
- this.mergeImport(type);
340
- }
341
- toTsString() {
342
- if (!this.type) return this.paramName;
343
- return `${this.paramName}: ${this.type.toString()}`;
344
- }
345
- static arrayToString(params) {
346
- return params.map((it) => it.toString()).join(",");
347
- }
348
- };
349
- //#endregion
350
- //#region src/tsg/node/expressions.ts
351
- var TsExpression = class extends TsCode {
352
- constructor(..._args) {
353
- super(..._args);
354
- this._codeType = "expression";
355
- }
356
- toStatement() {
357
- return new ExpressionStatement(this);
358
- }
359
- call(...args) {
360
- return new CallExpression(this, ...args);
361
- }
362
- nonNull() {
363
- return new NonNullExpression(this);
364
- }
365
- property(propertyName) {
366
- return new PropertyAccessExpression(this, propertyName);
367
- }
368
- as(type) {
369
- return new AsExpression(this, type);
370
- }
371
- };
372
- var CallExpression = class extends TsExpression {
373
- constructor(identifier, ...args) {
374
- super();
375
- this.identifier = identifier;
376
- this._typeArgs = [];
377
- this.mergeImport(identifier, ...args);
378
- this.args = args;
379
- }
380
- typeArgs(...typeArgs) {
381
- this._typeArgs = typeArgs;
382
- this.mergeImport(...typeArgs);
383
- return this;
384
- }
385
- toTsString() {
386
- return this.identifier.toString() + (this._typeArgs.length !== 0 ? `<${this._typeArgs.map((it) => it.toString()).join(",")}>` : "") + `(${this.args.map((it) => it.toString()).join(",")})`;
387
- }
388
- };
389
- var Literal = class extends TsExpression {};
390
- var StringLiteral = class extends Literal {
391
- constructor(value) {
392
- super();
393
- this.value = value;
394
- }
395
- toTsString() {
396
- return tsValueString(this.value);
397
- }
398
- };
399
- var NumericLiteral = class extends Literal {
400
- constructor(value) {
401
- super();
402
- this.value = value;
403
- }
404
- toTsString() {
405
- return this.value.toString();
406
- }
407
- };
408
- var Boolean = class extends Literal {
409
- constructor(value) {
410
- super();
411
- this.value = value;
412
- }
413
- toTsString() {
414
- return this.value.toString();
415
- }
416
- };
417
- var ArrayLiteral = class extends Literal {
418
- constructor(literals) {
419
- super();
420
- this.literals = literals;
421
- this.mergeImport(...literals);
422
- }
423
- toTsString() {
424
- return `[${this.literals.map((it) => it.toString()).join(",")}]`;
425
- }
426
- };
427
- var ObjectLiteral = class extends Literal {
428
- constructor(...properties) {
429
- super();
430
- this.properties = [];
431
- this.addProperties(...properties);
432
- }
433
- addProperties(...properties) {
434
- this.properties.push(...properties);
435
- this.mergeImport(...properties);
436
- return this;
437
- }
438
- toTsString() {
439
- return `{${this.properties.map((it) => it.toString()).join(",")}}`;
440
- }
441
- };
442
- var ArrowFunction = class extends Literal {
443
- constructor(params, returnType, body) {
444
- super();
445
- this.params = params;
446
- this.returnType = returnType;
447
- this.body = body;
448
- this.mergeImport(...params, body, returnType);
449
- }
450
- toTsString() {
451
- const returnType = this.returnType ? `: ${this.returnType}` : "";
452
- return `(${Parameter.arrayToString(this.params)})${returnType} => ${this.body.toString()}`;
453
- }
454
- toAsync() {
455
- return new AsyncExpression(this);
456
- }
457
- };
458
- var AsyncExpression = class extends TsExpression {
459
- constructor(expression) {
460
- super();
461
- this.expression = expression;
462
- this.mergeImport(expression);
463
- }
464
- toTsString() {
465
- return "async " + this.expression.toString();
466
- }
467
- };
468
- var AwaitExpression = class extends TsExpression {
469
- constructor(expression) {
470
- super();
471
- this.expression = expression;
472
- this.mergeImport(expression);
473
- }
474
- toTsString() {
475
- return "await " + this.expression.toString();
476
- }
477
- };
478
- var BinaryExpression = class extends TsExpression {
479
- constructor(left, operator, right) {
480
- super();
481
- this.left = left;
482
- this.operator = operator;
483
- this.right = right;
484
- this.mergeImport(left, right);
485
- }
486
- toTsString() {
487
- return this.left + this.operator + this.right;
488
- }
489
- };
490
- var Identifier = class extends TsExpression {
491
- constructor(name) {
492
- super();
493
- this.name = name;
494
- }
495
- toTsString() {
496
- return this.name;
497
- }
498
- importFrom(path) {
499
- this.addImport([this.name], path);
500
- return this;
501
- }
502
- };
503
- var NewExpression = class extends CallExpression {
504
- toTsString() {
505
- return "new " + super.toTsString();
506
- }
507
- };
508
- var ParenthesizedExpression = class extends TsExpression {
509
- constructor(expression) {
510
- super();
511
- this.expression = expression;
512
- this.mergeImport(expression);
513
- }
514
- toTsString() {
515
- return `(${this.expression})`;
516
- }
517
- };
518
- var NonNullExpression = class extends TsExpression {
519
- constructor(expression) {
520
- super();
521
- this.expression = expression;
522
- this.mergeImport(expression);
523
- }
524
- toTsString() {
525
- return `${this.expression}!`;
526
- }
527
- };
528
- var PropertyAccessExpression = class extends TsExpression {
529
- constructor(expression, propertyName) {
530
- super();
531
- this.expression = expression;
532
- this.propertyName = propertyName;
533
- this.mergeImport(expression);
534
- }
535
- toTsString() {
536
- return `${this.expression.toString()}.${this.propertyName}`;
537
- }
538
- };
539
- var AsExpression = class extends TsExpression {
540
- constructor(expression, asType) {
541
- super();
542
- this.expression = expression;
543
- this.asType = asType;
544
- this.mergeImport(expression, asType);
545
- }
546
- toTsString() {
547
- return this.expression.toString() + " as " + this.asType.toString();
548
- }
549
- };
550
- var TernaryExpression = class extends TsExpression {
551
- constructor(condition, left, right) {
552
- super();
553
- this.condition = condition;
554
- this.left = left;
555
- this.right = right;
556
- this.mergeImport(condition, left, right);
557
- }
558
- toTsString() {
559
- return `(${this.condition})?${this.left}:${this.right}`;
560
- }
561
- };
562
- var SpreadElement = class extends TsExpression {
563
- constructor(expression) {
564
- super();
565
- this.expression = expression;
566
- this.mergeImport(expression);
567
- }
568
- toTsString() {
569
- return `...${this.expression}`;
570
- }
571
- };
572
- //#endregion
573
- //#region src/tsg/node/extendsClause.ts
574
- var ExtendsClause = class extends TsCode {
575
- constructor(type) {
576
- super();
577
- this.type = type;
578
- this.mergeImport(type);
579
- }
580
- toTsString() {
581
- return `extends ${this.type}`;
582
- }
583
- };
584
- //#endregion
585
- //#region src/tsg/node/ifStatement.ts
586
- var IfStatement = class extends TsStatement {
587
- constructor(condition, statement) {
588
- super();
589
- this.condition = condition;
590
- this.statement = statement;
591
- this.mergeImport(condition, statement);
592
- }
593
- toTsString() {
594
- return `if(${this.condition})${this.statement}`;
595
- }
596
- };
597
- //#endregion
598
- //#region src/tsg/node/implementsClause.ts
599
- var ImplementsClause = class extends TsCode {
600
- constructor(...types) {
601
- super();
602
- this.types = types;
603
- this.mergeImport(...types);
604
- }
605
- toTsString() {
606
- return `implements ${this.types.join(",")}`;
607
- }
608
- };
609
- //#endregion
610
- //#region src/tsg/tsUtil.ts
611
- const TsUtil = {
612
- readonly: (isReadonly) => isReadonly ? "readonly " : "",
613
- questionToken: (isOptional) => isOptional ? "?" : ""
614
- };
615
- //#endregion
616
- //#region src/tsg/node/propertySignature.ts
617
- var PropertySignature = class extends TsCode {
618
- constructor(propertyName, type, isOptional = false, isReadOnly = false) {
619
- super();
620
- this.propertyName = propertyName;
621
- this.type = type;
622
- this.isOptional = isOptional;
623
- this.isReadOnly = isReadOnly;
624
- this.mergeImport(type);
625
- }
626
- codePrefix() {
627
- return TsUtil.readonly(this.isReadOnly);
628
- }
629
- toTsString() {
630
- return `${this.propertyName}${TsUtil.questionToken(this.isOptional)}: ${this.type}`;
631
- }
632
- };
633
- //#endregion
634
- //#region src/tsg/node/interface.ts
635
- var TsInterface = class extends ExportableDeclaration {
636
- constructor(name) {
637
- super();
638
- this.name = name;
639
- this.properties = [];
640
- }
641
- addProperty(propertyName, type, isOptional = false, isReadOnly = false) {
642
- this.properties.push(new PropertySignature(propertyName, type, isOptional, isReadOnly));
643
- return this;
644
- }
645
- addProperties(properties) {
646
- this.properties.push(...properties);
647
- this.mergeImport(...properties);
648
- return this;
649
- }
650
- extends(value) {
651
- this._extends = value;
652
- this.mergeImport(value);
653
- return this;
654
- }
655
- toTsString() {
656
- const extend = this._extends ? this._extends.toString() + " " : "";
657
- return `interface ${this.name} ${extend}{${this.properties.map((it) => it.toString()).join(";")}}`;
658
- }
659
- };
660
- //#endregion
661
- //#region src/tsg/node/modifier/modifiers.ts
662
- var Modifiers = class extends TsCode {
663
- constructor(..._args) {
664
- super(..._args);
665
- this._accessor = "";
666
- this.isReadOnly = false;
667
- this.isStatic = false;
668
- this.isAbstract = false;
669
- this.isAsync = false;
670
- }
671
- accessor(accessor) {
672
- this._accessor = accessor;
673
- return this;
674
- }
675
- private() {
676
- return this.accessor("private");
677
- }
678
- protected() {
679
- return this.accessor("protected ");
680
- }
681
- abstract() {
682
- this.isAbstract = true;
683
- return this;
684
- }
685
- readonly() {
686
- this.isReadOnly = true;
687
- return this;
688
- }
689
- static() {
690
- this.isStatic = true;
691
- return this;
692
- }
693
- async() {
694
- this.isAsync = true;
695
- return this;
696
- }
697
- toTsString() {
698
- const optional = (bool, string) => bool ? string : "";
699
- return this._accessor + " " + optional(this.isAbstract, "abstract ") + optional(this.isStatic, "static ") + optional(this.isReadOnly, "readonly ") + optional(this.isAsync, "async ");
700
- }
701
- };
702
- //#endregion
703
- //#region src/tsg/node/modifier/methodModifiers.ts
704
- var MethodModifiers = class extends Modifiers {
705
- private() {
706
- return super.private();
707
- }
708
- protected() {
709
- return super.protected();
710
- }
711
- abstract() {
712
- return super.abstract();
713
- }
714
- static() {
715
- return super.static();
716
- }
717
- async() {
718
- return super.async();
719
- }
720
- };
721
- //#endregion
722
- //#region src/tsg/node/type/type.ts
723
- const isCode = (t) => t instanceof TsCode;
724
- const pickCode = (types) => types.filter((it) => it instanceof TsCode);
725
- //#endregion
726
- //#region src/tsg/node/methodDeclaration.ts
727
- var MethodDeclaration = class extends TsCode {
728
- constructor(methodName, params, returnType, body) {
729
- super();
730
- this.methodName = methodName;
731
- this.params = params;
732
- this.returnType = returnType;
733
- this.body = body;
734
- this._modifiers = new MethodModifiers();
735
- this.mergeImport(...params, ...body);
736
- if (isCode(returnType)) this.mergeImport(returnType);
737
- }
738
- modifiers(modifiers) {
739
- this._modifiers = modifiers;
740
- return this;
741
- }
742
- importFrom(from) {
743
- this.addImport([this.methodName], from);
744
- return this;
745
- }
746
- toTsString() {
747
- const params = this.params.map((it) => it.toString()).join(",");
748
- return this._modifiers.toString() + `${this.methodName}(${params}): ${this.returnType}{${this.body.map((it) => it.toString()).join("")}}\n`;
749
- }
750
- };
751
- //#endregion
752
- //#region src/tsg/node/modifier/propertyModifiers.ts
753
- var PropertyModifiers = class extends Modifiers {
754
- accessor(accessor) {
755
- return super.accessor(accessor);
756
- }
757
- private() {
758
- return super.private();
759
- }
760
- protected() {
761
- return super.protected();
762
- }
763
- abstract() {
764
- return super.abstract();
765
- }
766
- readonly() {
767
- return super.readonly();
768
- }
769
- static() {
770
- return super.static();
771
- }
772
- };
773
- //#endregion
774
- //#region src/tsg/node/propertyAssignment.ts
775
- var PropertyAssignment = class extends TsCode {
776
- constructor(key, value) {
777
- super();
778
- this.key = key;
779
- this.value = value;
780
- this.mergeImport(value);
781
- }
782
- toTsString() {
783
- if (!this.value) return this.key;
784
- return `${this.key}: ${this.value.toString()}`;
785
- }
786
- };
787
- //#endregion
788
- //#region src/tsg/node/propertyDeclaration.ts
789
- var PropertyDeclaration = class extends TsCode {
790
- constructor(propertyName, type, optional = false) {
791
- super();
792
- this.propertyName = propertyName;
793
- this.type = type;
794
- this.optional = optional;
795
- this._modifiers = new PropertyModifiers();
796
- this._initializer = void 0;
797
- if (isCode(type)) this.mergeImport(type);
798
- }
799
- modifiers(modifiers) {
800
- this._modifiers = modifiers;
801
- return this;
802
- }
803
- initializer(initializer) {
804
- this._initializer = initializer;
805
- this.mergeImport(initializer);
806
- return this;
807
- }
808
- toTsString() {
809
- const initializer = this._initializer ? ` = ${this._initializer.toString()}` : "";
810
- return this._modifiers.toString() + `${this.propertyName}${TsUtil.questionToken(this.optional)}: ${this.type}` + initializer + ";";
811
- }
812
- };
813
- //#endregion
814
- //#region src/tsg/node/returnStatement.ts
815
- var ReturnStatement = class extends TsStatement {
816
- constructor(expression) {
817
- super();
818
- this.expression = expression;
819
- this.mergeImport(expression);
820
- }
821
- toTsString() {
822
- return `return ${this.expression.toString()};`;
823
- }
824
- };
825
- //#endregion
826
- //#region src/tsg/node/spreadAssignment.ts
827
- var SpreadAssignment = class extends TsCode {
828
- constructor(identifier) {
829
- super();
830
- this.identifier = identifier;
831
- this.mergeImport(identifier);
832
- }
833
- toTsString() {
834
- return `...${this.identifier.toString()}`;
835
- }
836
- };
837
- //#endregion
838
- //#region src/tsg/node/throwStatement.ts
839
- var ThrowStatement = class extends TsStatement {
840
- constructor(expression) {
841
- super();
842
- this.expression = expression;
843
- this.mergeImport(expression);
844
- }
845
- toTsString() {
846
- return "throw " + this.expression.toString() + ";";
847
- }
848
- };
849
- //#endregion
850
- //#region src/tsg/node/type/arrayType.ts
851
- var ArrayType = class extends TsCode {
852
- constructor(type) {
853
- super();
854
- this.type = type;
855
- if (isCode(type)) this.mergeImport(type);
856
- }
857
- toTsString() {
858
- return `Array<${this.type.toString()}>`;
859
- }
860
- };
861
- //#endregion
862
- //#region src/tsg/node/type/intersectionType.ts
863
- var IntersectionType = class extends TsCode {
864
- constructor(...types) {
865
- super();
866
- this.types = types;
867
- this.mergeImport(...types);
868
- }
869
- toTsString() {
870
- return this.types.map((it) => it.toString()).join(" & ");
871
- }
872
- };
873
- //#endregion
874
- //#region src/tsg/node/type/typeAliasDeclaration.ts
875
- var TypeAliasDeclaration = class extends ExportableDeclaration {
876
- constructor(alias, type) {
877
- super();
878
- this.alias = alias;
879
- this.type = type;
880
- if (isCode(type)) this.mergeImport(type);
881
- }
882
- toTsString() {
883
- return `type ${this.alias} = ${this.type.toString()}`;
884
- }
885
- };
886
- //#endregion
887
- //#region src/tsg/node/type/typeLiteral.ts
888
- var TypeLiteral = class extends TsCode {
889
- constructor(properties = []) {
890
- super();
891
- this.properties = properties;
892
- this.mergeImport(...properties);
893
- }
894
- addProperty(propertyName, type, isOptional = false, isReadOnly = false) {
895
- this.properties.push(new PropertySignature(propertyName, type, isOptional, isReadOnly));
896
- return this;
897
- }
898
- toTsString() {
899
- return `{${this.properties.map((it) => it.toString()).join(";")}}`;
900
- }
901
- };
902
- //#endregion
903
- //#region src/tsg/node/type/typeReference.ts
904
- var TypeReference = class TypeReference extends TsCode {
905
- constructor(typeName, typeArguments = []) {
906
- super();
907
- this.typeName = typeName;
908
- this.typeArguments = typeArguments;
909
- this.mergeImport(...pickCode(typeArguments));
910
- }
911
- importFrom(path) {
912
- this.addImport([this.typeName], path);
913
- return this;
914
- }
915
- partial() {
916
- return new TypeReference("Partial", [this]);
917
- }
918
- pick(...properties) {
919
- return new TypeReference("Pick", [this, new Identifier(properties.map((it) => `'${it}'`).join("|"))]);
920
- }
921
- toTsString() {
922
- const typeArgs = this.typeArguments.length === 0 ? "" : `<${this.typeArguments.join(",")}>`;
923
- return `${this.typeName}${typeArgs}`;
924
- }
925
- };
926
- //#endregion
927
- //#region src/tsg/node/type/unionType.ts
928
- var UnionType = class extends TsCode {
929
- constructor(...types) {
930
- super();
931
- this.types = types;
932
- const codeTypes = types.filter((it) => isCode(it));
933
- this.mergeImport(...codeTypes);
934
- }
935
- toTsString() {
936
- return this.types.map((it) => it.toString()).join(" | ");
937
- }
938
- };
939
- //#endregion
940
- //#region src/tsg/node/variableDeclaration.ts
941
- var VariableDeclaration = class extends ExportableDeclaration {
942
- constructor(flag, variableName, expression, type) {
943
- super();
944
- this.flag = flag;
945
- this.expression = expression;
946
- this.type = type;
947
- this.variableName = typeof variableName === "string" ? new Identifier(variableName) : variableName;
948
- this.mergeImport(expression, this.variableName, type);
949
- }
950
- toTsString() {
951
- const type = this.type ? ": " + this.type.toString() : "";
952
- return `${this.flag} ${this.variableName}${type} = ${this.expression.toString()};`;
953
- }
954
- };
955
- //#endregion
956
- //#region src/tsg/factory.ts
957
- const createFactory = (Constructor) => {
958
- return (...args) => new Constructor(...args);
959
- };
960
- const expressions = {
961
- arrowFunc: createFactory(ArrowFunction),
962
- async: createFactory(AsyncExpression),
963
- await: createFactory(AwaitExpression),
964
- binary: createFactory(BinaryExpression),
965
- call: createFactory(CallExpression),
966
- identifier: createFactory(Identifier),
967
- new: createFactory(NewExpression),
968
- nonNull: createFactory(NonNullExpression),
969
- parenthesis: createFactory(ParenthesizedExpression),
970
- propertyAccess: createFactory(PropertyAccessExpression),
971
- string: createFactory(StringLiteral),
972
- number: createFactory(NumericLiteral),
973
- boolean: createFactory(Boolean),
974
- array: createFactory(ArrayLiteral),
975
- object: createFactory(ObjectLiteral),
976
- as: createFactory(AsExpression),
977
- ternary: createFactory(TernaryExpression)
978
- };
979
- const types = {
980
- arrayType: createFactory(ArrayType),
981
- intersectionType: createFactory(IntersectionType),
982
- unionType: createFactory(UnionType),
983
- typeAlias: createFactory(TypeAliasDeclaration),
984
- typeLiteral: createFactory(TypeLiteral),
985
- typeRef: createFactory(TypeReference)
986
- };
987
- const others = {
988
- block: createFactory(Block),
989
- class: createFactory(Class),
990
- enum: createFactory(EnumDeclaration),
991
- enumMember: createFactory(EnumMember),
992
- ExpStatement: createFactory(ExpressionStatement),
993
- extends: createFactory(ExtendsClause),
994
- if: createFactory(IfStatement),
995
- implements: createFactory(ImplementsClause),
996
- interface: createFactory(TsInterface),
997
- method: createFactory(MethodDeclaration),
998
- parameter: createFactory(Parameter),
999
- propertyAssign: createFactory(PropertyAssignment),
1000
- propertyDeclaration: createFactory(PropertyDeclaration),
1001
- propertySignature: createFactory(PropertySignature),
1002
- return: createFactory(ReturnStatement),
1003
- spreadAssign: createFactory(SpreadAssignment),
1004
- variable: createFactory(VariableDeclaration),
1005
- methodModifiers: createFactory(MethodModifiers),
1006
- propertyModifiers: createFactory(PropertyModifiers),
1007
- throw: createFactory(ThrowStatement),
1008
- spread: createFactory(SpreadElement)
1009
- };
1010
- const tsg = {
1011
- ...expressions,
1012
- ...types,
1013
- ...others
1014
- };
1015
- //#endregion
1016
- //#region src/tsg/file.ts
1017
- var TsFile = class extends TsCode {
1018
- constructor(...statements) {
1019
- super();
1020
- this.esLintDisabled = false;
1021
- this.mergeImport(...statements);
1022
- this.statements = statements;
1023
- }
1024
- toTsString() {
1025
- const string = [...this.resolveImport(this.importDeclarations), ...this.statements].map((it) => it.toString()).join("\n");
1026
- return (this.esLintDisabled ? "/* eslint-disable */\n" : "") + string;
1027
- }
1028
- resolveImport(imports) {
1029
- const map = {};
1030
- imports.forEach((it) => {
1031
- if (!map[it.module]) map[it.module] = it.types;
1032
- else map[it.module] = [...map[it.module], ...it.types];
1033
- });
1034
- return Object.entries(map).map(([module, types]) => new ImportDeclaration([...new Set(types)], module));
1035
- }
1036
- disableEsLint() {
1037
- this.esLintDisabled = true;
1038
- return this;
1039
- }
1040
- enableEsLint() {
1041
- this.esLintDisabled = false;
1042
- return this;
1043
- }
1044
- async generate() {
1045
- return this.toString();
1046
- }
1047
- };
1048
- //#endregion
1049
- //#region src/tsg/node/type/typeKeyword.ts
1050
- const KeywordTypeNode = {
1051
- any: new TypeReference("any"),
1052
- unknown: new TypeReference("unknown"),
1053
- number: new TypeReference("number"),
1054
- bigInt: new TypeReference("BigInt"),
1055
- boolean: new TypeReference("boolean"),
1056
- string: new TypeReference("string"),
1057
- symbol: new TypeReference("Symbol"),
1058
- this: new TypeReference("this"),
1059
- void: new TypeReference("void"),
1060
- undefined: new TypeReference("undefined"),
1061
- null: new TypeReference("null"),
1062
- never: new TypeReference("never")
1063
- };
1064
- //#endregion
1065
- //#region src/generatorv2/directory.ts
1066
- const GeneratedDirName = "__generated__";
1067
- const EntityDirName = "entities";
1068
- const DataSourceDirName = "dataSources";
1069
- const relative = (from, to) => {
1070
- const result = path$1.posix.relative(from, to);
1071
- if (result.startsWith("../")) return result;
1072
- return "./" + result;
1073
- };
1074
- const GENERATED_PATH = `/${GeneratedDirName}/`;
1075
- const paths = {
1076
- BASE: "/",
1077
- GENERATED: GENERATED_PATH,
1078
- ENTITIES: `${GENERATED_PATH}${EntityDirName}/`,
1079
- DATA_SOURCES: `/${DataSourceDirName}/db/`,
1080
- GENERATED_DS: `${GENERATED_PATH}${DataSourceDirName}/db/`
1081
- };
1082
- const resolve = (from, source, fileName) => {
1083
- return relative(paths[from], paths[source] + fileName);
1084
- };
1085
- const Directory = {
1086
- paths,
1087
- resolve
1088
- };
1089
- //#endregion
1090
- //#region src/generatorv2/codegen/ts/scripts/getEntityTypeRefs.ts
1091
- const typeRefs = {
1092
- entity: {
1093
- name: (entity) => entity.name,
1094
- dir: "ENTITIES",
1095
- file: (entity) => entity.name
1096
- },
1097
- creatable: {
1098
- name: (entity) => entity.creatableInterface(),
1099
- dir: "ENTITIES",
1100
- file: (entity) => entity.name
1101
- },
1102
- updatable: {
1103
- name: (entity) => entity.updatable(),
1104
- dir: "ENTITIES",
1105
- file: (entity) => entity.name
1106
- },
1107
- identifiable: {
1108
- name: (entity) => entity.identifiableInterfaceName(),
1109
- dir: "ENTITIES",
1110
- file: (entity) => entity.name
1111
- },
1112
- fields: {
1113
- name: (entity) => entity.fieldsTypeName(),
1114
- dir: "GENERATED",
1115
- file: () => "fields"
1116
- },
1117
- withRelation: {
1118
- name: (entity) => entity.entityWithRelationTypeName(),
1119
- dir: "GENERATED",
1120
- file: () => "relationMap"
1121
- },
1122
- result: {
1123
- name: (entity) => entity.resultType(),
1124
- dir: "GENERATED",
1125
- file: () => "relationMap"
1126
- }
1127
- };
1128
- const makeTypeRef = (entity, type, importFrom) => {
1129
- const info = typeRefs[type];
1130
- return tsg.typeRef(info.name(entity)).importFrom(Directory.resolve(importFrom, info.dir, info.file(entity)));
1131
- };
1132
- const makeContextTypeRef = (importFrom) => {
1133
- return tsg.typeRef("GQLContext").importFrom(Directory.resolve(importFrom, "BASE", "context"));
1134
- };
1135
- //#endregion
1136
- //#region src/generatorv2/codegen/ts/scripts/sqlValueToTsExpression.ts
1137
- const sqlValueToTsExpression = (value) => {
1138
- if (typeof value === "string") return tsg.string(value);
1139
- if (typeof value === "number") return tsg.number(value);
1140
- return tsg.identifier("null");
1141
- };
1142
- //#endregion
1143
- //#region src/generatorv2/codegen/ts/generateAutoGeneratedDatasource.ts
1144
- const DIR$2 = "GENERATED_DS";
1145
- const generateAutoGeneratedDatasource = (node) => {
1146
- return new TsFile(tsg.typeAlias("QueryResult", tsg.intersectionType(makeTypeRef(node.name, "withRelation", DIR$2).partial(), makeTypeRef(node.name, "identifiable", DIR$2))), tsg.class(node.name.generatedDataSourceName()).export().abstract().extends(tsg.extends(tsg.typeRef("BaseDBDataSource", [
1147
- makeTypeRef(node.name, "entity", DIR$2),
1148
- makeTypeRef(node.name, "identifiable", DIR$2),
1149
- makeTypeRef(node.name, "creatable", DIR$2),
1150
- makeTypeRef(node.name, "updatable", DIR$2),
1151
- makeTypeRef(node.name, "fields", DIR$2),
1152
- tsg.typeRef("QueryResult")
1153
- ])).addImport(["BaseDBDataSource"], Directory.resolve(DIR$2, "BASE", "baseDBDataSource"))).addProperty(...makeClassProperties(node)).addMethod(makeDefaultValueMethod(node), ...makeFindMethods(node))).disableEsLint();
1154
- };
1155
- const makeClassProperties = (node) => {
1156
- const ai = node.fields.find((it) => it.isAutoIncrement);
1157
- return [
1158
- tsg.propertyDeclaration("tableName", KeywordTypeNode.string, false).modifiers(tsg.propertyModifiers().readonly()).initializer(tsg.string(node.tableName)),
1159
- tsg.propertyDeclaration("fields", tsg.arrayType(KeywordTypeNode.string), false).modifiers(tsg.propertyModifiers().readonly()).initializer(tsg.array(node.fields.map((it) => tsg.string(it.fieldName)))),
1160
- tsg.propertyDeclaration("primaryKeys", tsg.arrayType(KeywordTypeNode.string), false).modifiers(tsg.propertyModifiers().readonly().protected()).initializer(tsg.array(node.identifyKeys.map((it) => tsg.string(it)))),
1161
- tsg.propertyDeclaration("identifyFields", tsg.arrayType(KeywordTypeNode.string), false).modifiers(tsg.propertyModifiers().readonly().protected()).initializer(tsg.array(node.identifyKeys.map((it) => node.fields.find((f) => it === f.columnName).fieldName).map(tsg.string))),
1162
- tsg.propertyDeclaration("autoIncrementColumn", tsg.unionType(KeywordTypeNode.string, KeywordTypeNode.undefined), true).modifiers(tsg.propertyModifiers().readonly().protected()).initializer(ai ? tsg.string(ai.fieldName) : tsg.identifier("undefined"))
1163
- ];
1164
- };
1165
- const fieldToExpression = (node) => {
1166
- if (node.column.defaultCurrentTimeStamp) return tsg.identifier("getCurrentDateTimeString").addImport(["getCurrentDateTimeString"], "sasat").call();
1167
- return sqlValueToTsExpression(node.column.default);
1168
- };
1169
- const makeDefaultValueMethod = (node) => {
1170
- const columns = node.fields.filter((it) => it.column.defaultCurrentTimeStamp || it.column.default !== void 0);
1171
- const properties = columns.map((it) => {
1172
- return tsg.propertyAssign(it.fieldName, fieldToExpression(it));
1173
- });
1174
- const body = tsg.return(tsg.object(...properties));
1175
- return tsg.method("getDefaultValueString", [], columns.length !== 0 ? tsg.typeRef(node.name.name).pick(...columns.map((it) => it.fieldName)) : tsg.typeRef(node.name.name).partial(), [body]).modifiers(tsg.methodModifiers().protected());
1176
- };
1177
- const makeFindMethods = (node) => {
1178
- const qExpr = tsg.identifier("qe").importFrom("sasat");
1179
- return node.findMethods.map((it) => {
1180
- const bve = it.params.flatMap((it) => {
1181
- if (!it.entity) return qExpr.property("eq").call(qExpr.property("field").call(tsg.identifier("tableName"), tsg.string(it.columnName.toString())), qExpr.property("value").call(tsg.identifier(it.fieldName.toString())));
1182
- return it.fields.map((field) => {
1183
- return qExpr.property("eq").call(qExpr.property("field").call(tsg.identifier("tableName"), tsg.string(field.columnName)), qExpr.property("value").call(tsg.identifier(it.name).property(field.fieldName)));
1184
- });
1185
- });
1186
- const body = [tsg.variable("const", "tableName", tsg.identifier("fields?.tableAlias || \"t0\"")), tsg.return(tsg.identifier(it.isArray ? "this.find" : "this.first").call(tsg.identifier("fields"), tsg.object().addProperties(tsg.spreadAssign(tsg.identifier("options")), tsg.propertyAssign("where", qExpr.property("and").call(...bve, tsg.identifier("options?").property("where")))), tsg.identifier("context")))];
1187
- const returnType = tsg.typeRef("QueryResult");
1188
- return tsg.method(it.name, [
1189
- ...it.params.map((it) => tsg.parameter(it.entity ? it.name.toString() : it.fieldName, it.entity ? makeTypeRef(it.entityName, "identifiable", "GENERATED_DS") : tsg.typeRef(columnTypeToTsType(it.dbtype)))),
1190
- tsg.parameter(`fields?`, makeTypeRef(node.name, "fields", DIR$2)),
1191
- tsg.parameter("options?", it.isArray ? tsg.typeRef("QueryOptions").importFrom("sasat") : tsg.typeRef("Omit", [tsg.typeRef("QueryOptions").importFrom("sasat"), tsg.typeRef("\"offset\" | \"limit\" | \"sort\"")])),
1192
- tsg.parameter("context?", makeContextTypeRef(DIR$2))
1193
- ], tsg.typeRef("Promise", [it.isArray ? tsg.arrayType(returnType) : tsg.unionType(returnType, tsg.typeRef("null"))]), body);
1194
- });
1195
- };
1196
- //#endregion
1197
- //#region src/generatorv2/codegen/ts/generateContext.ts
1198
- const generateContext = (root) => {
1199
- return new TsFile(tsg.interface("BaseGQLContext").addProperties(root.contexts.map((it) => tsg.propertySignature(it.name, tsg.typeRef(columnTypeToTsType(it.dbtype))))).export()).disableEsLint();
1200
- };
1201
- //#endregion
1202
- //#region src/generatorv2/codegen/ts/generateDatasource.ts
1203
- const generateDatasource = (node) => {
1204
- return new TsFile(tsg.class(node.name.dataSourceName()).extends(tsg.extends(tsg.typeRef(node.name.generatedDataSourceName()).importFrom(Directory.resolve("DATA_SOURCES", "GENERATED_DS", node.name.name)))).export());
1205
- };
1206
- //#endregion
1207
- //#region src/generatorv2/codegen/ts/scripts/fieldToProperty.ts
1208
- const fieldToPropertySignature = (field) => {
1209
- const type = tsg.typeRef(columnTypeToTsType(field.dbType));
1210
- return tsg.propertySignature(field.fieldName, field.isNullable ? tsg.unionType(type, KeywordTypeNode.null) : type, field.isNullable, true);
1211
- };
1212
- //#endregion
1213
- //#region src/generatorv2/codegen/ts/generateEntity.ts
1214
- const generateEntityFile = (node) => {
1215
- return new TsFile(generateEntity(node), generateCreatable(node), generateUpdatable(node), generateIdentifiable(node)).disableEsLint();
1216
- };
1217
- const generateEntity = (node) => {
1218
- return tsg.typeAlias(node.name.name, tsg.typeLiteral(node.fields.map(fieldToPropertySignature))).export();
1219
- };
1220
- const generateCreatable = (node) => {
1221
- return tsg.typeAlias(node.name.creatableInterface(), node.creatable.fields.length === 0 ? tsg.typeRef("Record<string, never>") : tsg.typeLiteral(node.creatable.fields.map(fieldToPropertySignature))).export();
1222
- };
1223
- const generateUpdatable = (node) => {
1224
- return tsg.typeAlias(node.name.updatable(), node.updateInput.fields.length === 0 ? tsg.typeRef("Record<string, never>") : tsg.typeLiteral(node.updateInput.fields.map(fieldToPropertySignature))).export();
1225
- };
1226
- const generateIdentifiable = (node) => {
1227
- return tsg.typeAlias(node.name.identifiableInterfaceName(), tsg.typeLiteral(node.fields.filter((it) => it.isPrimary).map(fieldToPropertySignature))).export();
1228
- };
1229
- //#endregion
1230
- //#region src/util/stringUtil.ts
1231
- const capitalizeFirstLetter = (str) => str.slice(0, 1).toUpperCase() + str.slice(1);
1232
- const lowercaseFirstLetter = (str) => str.slice(0, 1).toLowerCase() + str.slice(1);
1233
- const camelize = (str) => str.replace(/(?:^\w|[A-Z]|_\w|\b\w)/g, (word, index) => index === 0 ? word.toLowerCase() : word.toUpperCase()).replace(/\s|_|-+/g, "");
1234
- //#endregion
1235
- //#region src/generatorv2/nodes/entityName.ts
1236
- var EntityName = class EntityName {
1237
- static fromTableName(tableName) {
1238
- return new EntityName(capitalizeFirstLetter(camelize(tableName)));
1239
- }
1240
- constructor(name) {
1241
- this.name = name;
1242
- }
1243
- toString() {
1244
- return this.name;
1245
- }
1246
- creatableInterface() {
1247
- return `${this.name}Creatable`;
1248
- }
1249
- updatable() {
1250
- return `${this.name}Updatable`;
1251
- }
1252
- identifiableInterfaceName() {
1253
- return `${this.name}Identifiable`;
1254
- }
1255
- relationTypeName() {
1256
- return this.name + "Relations";
1257
- }
1258
- entityWithRelationTypeName() {
1259
- return this.name + "WithRelations";
1260
- }
1261
- resultType() {
1262
- return this.name + "Result";
1263
- }
1264
- fieldsTypeName() {
1265
- return this.name + "Fields";
1266
- }
1267
- dataSourceName() {
1268
- return `${this.name}DBDataSource`;
1269
- }
1270
- generatedDataSourceName() {
1271
- return `Generated${this.name}DBDataSource`;
1272
- }
1273
- lowerCase() {
1274
- return lowercaseFirstLetter(this.name);
1275
- }
1276
- createInputName() {
1277
- return this.name + "CreateInput";
1278
- }
1279
- updateInputName() {
1280
- return this.name + "UpdateInput";
1281
- }
1282
- identifyInputName() {
1283
- return `${this.name}IdentifyInput`;
1284
- }
1285
- IDEncoderName() {
1286
- return `${this.name}HashId`;
1287
- }
1288
- };
1289
- //#endregion
1290
- //#region src/generatorv2/codegen/ts/generateFields.ts
1291
- const generateFields = (root) => {
1292
- return new TsFile(...root.entities.map((it) => tsg.typeAlias(it.name.fieldsTypeName(), tsg.typeRef("Fields", [makeTypeRef(it.name, "entity", "GENERATED"), makeTypeLiteral(it)]).importFrom("sasat")).export())).disableEsLint();
1293
- };
1294
- const makeTypeLiteral = (entity) => {
1295
- return tsg.typeLiteral([...entity.references.map((it) => tsg.propertySignature(`${it.fieldName}?`, tsg.typeRef(EntityName.fromTableName(it.parentTableName).fieldsTypeName()))), ...entity.referencedBy.map((it) => tsg.propertySignature(`${it.fieldName}?`, tsg.typeRef(EntityName.fromTableName(it.childTable).fieldsTypeName())))]);
1296
- };
1297
- //#endregion
1298
- //#region src/runtime/util.ts
1299
- const pick = (target, keys) => Object.fromEntries(keys.map((key) => [key, target[key]]));
1300
- const unique = (array) => {
1301
- const result = [];
1302
- for (let i = 0, l = array.length; i < l; i += 1) if (!result.includes(array[i])) result.push(array[i]);
1303
- return result;
1304
- };
1305
- const nonNullable = (value) => value != null;
1306
- //#endregion
1307
- //#region src/generatorv2/codegen/ts/scripts/ast/getExportedVariables.ts
1308
- const { SyntaxKind: SyntaxKind$1 } = typescript;
1309
- const getExportedVariables = (sourceFile) => {
1310
- return sourceFile.statements.filter((it) => it.kind === SyntaxKind$1.VariableStatement && it.modifiers?.some((it) => it.kind === SyntaxKind$1.ExportKeyword));
1311
- };
1312
- //#endregion
1313
- //#region src/generatorv2/codegen/ts/scripts/ast/isImported.ts
1314
- const { SyntaxKind } = typescript;
1315
- const isImported = (sourceFile, type, paths) => {
1316
- return sourceFile.statements.filter((it) => it.kind === SyntaxKind.ImportDeclaration).some((it) => {
1317
- if (!paths.some((path) => {
1318
- const text = it.moduleSpecifier.getText(sourceFile);
1319
- return `'${path}'` === text || `"${path}"` === text;
1320
- })) return false;
1321
- const binding = it.importClause?.namedBindings;
1322
- if (it.importClause?.name?.getText(sourceFile) === type) return true;
1323
- if (binding?.kind !== SyntaxKind.NamedImports) return false;
1324
- return binding.elements.some((it) => {
1325
- return it.name.text.trim() === type;
1326
- });
1327
- });
1328
- };
1329
- //#endregion
1330
- //#region src/generatorv2/codegen/ts/generateIDEncoder.ts
1331
- const { createSourceFile: createSourceFile$2, ScriptTarget: ScriptTarget$2 } = typescript;
1332
- const hashIds = "HashIds";
1333
- const generateIDEncoder = (root, content) => {
1334
- const fields = root.entities.map((it) => it.fields.find((it) => it.column.option.autoIncrementHashId)).filter(nonNullable);
1335
- if (fields.length === 0) return null;
1336
- const sourceFile = createSourceFile$2(tsFileNames.encoder + ".ts", content, ScriptTarget$2.ESNext);
1337
- sourceFile.getChildren().map((it) => it);
1338
- const exportedVariables = getExportedVariables(sourceFile);
1339
- const hashIdImported = isImported(sourceFile, hashIds, ["hashids"]);
1340
- const statements = [];
1341
- fields.forEach((field) => {
1342
- const name = field.entity.name.IDEncoderName();
1343
- if (exportedVariables.some((it) => {
1344
- return it.declarationList.declarations[0].name.getText(sourceFile) === name;
1345
- })) return;
1346
- statements.push(tsg.variable("const", name, tsg.identifier("makeNumberIdEncoder").call(tsg.new(tsg.identifier(hashIds), tsg.string(field.column.option.hashSalt || field.entity.name.name)))).export());
1347
- });
1348
- const imports = hashIdImported ? "" : "import HashIds from \"hashids\";\n";
1349
- const makeEncoder = isImported(sourceFile, "makeNumberIdEncoder", ["sasat"]) ? "" : new ImportDeclaration(["makeNumberIdEncoder"], "sasat").toString();
1350
- const addition = statements.length === 0 ? "" : "\n" + new TsFile(...statements).toString();
1351
- return imports + makeEncoder + content + addition;
1352
- };
1353
- //#endregion
1354
- //#region src/generatorv2/codegen/ts/generateMiddlewares.ts
1355
- const { createSourceFile: createSourceFile$1, ScriptTarget: ScriptTarget$1 } = typescript;
1356
- const generateMiddlewares = (root, content) => {
1357
- const middlewares = unique(root.entities.flatMap((it) => [...it.queries.flatMap((it) => it.middlewares), ...it.mutations.flatMap((it) => it.middlewares)]));
1358
- if (middlewares.length === 0) return null;
1359
- const sourceFile = createSourceFile$1(tsFileNames.middleware + ".ts", content, ScriptTarget$1.ESNext);
1360
- const exportedVariables = getExportedVariables(sourceFile);
1361
- const statements = [];
1362
- middlewares.forEach((middleware) => {
1363
- if (exportedVariables.some((it) => {
1364
- return it.declarationList.declarations[0].name.getText(sourceFile) === middleware;
1365
- })) return;
1366
- statements.push(tsg.variable("const", middleware, tsg.arrowFunc([tsg.parameter("args")], void 0, tsg.block(tsg.throw(tsg.new(tsg.identifier("Error"), tsg.string("TODO: Not implemented"))), tsg.return(tsg.identifier("args")))), tsg.typeRef("ResolverMiddleware", [tsg.typeRef("GQLContext")])).export());
1367
- });
1368
- const contextImported = isImported(sourceFile, "GQLContext", ["./context", "./context.js"]);
1369
- const resolverMiddlewareImported = isImported(sourceFile, "ResolverMiddleware", ["sasat"]);
1370
- const imports = [contextImported ? "" : new ImportDeclaration(["GQLContext"], "./context").toString() + "\n", resolverMiddlewareImported ? "" : new ImportDeclaration(["ResolverMiddleware"], "sasat").toString() + "\n"].join("");
1371
- const addition = statements.length === 0 ? "" : "\n" + new TsFile(...statements).toString();
1372
- return imports + content + addition;
1373
- };
1374
- //#endregion
1375
- //#region src/generatorv2/codegen/names.ts
1376
- const map = {
1377
- create: "Created",
1378
- update: "Updated",
1379
- delete: "Deleted"
1380
- };
1381
- const publishFunctionName = (entityName, type) => {
1382
- return `publish${entityName}${map[type]}`;
1383
- };
1384
- const makeFindQueryName = (keys) => "findBy" + keys.map(capitalizeFirstLetter).join("And");
1385
- //#endregion
1386
- //#region src/generatorv2/codegen/ts/mutation/makeMutationInputDecoder.ts
1387
- const DIR$1 = "GENERATED";
1388
- const makeMutationMiddlewareAndTypes = (entity) => {
1389
- return entity.mutations.map((node) => makeMutationResolverMiddleware(entity, node));
1390
- };
1391
- const makeParamType = (node) => {
1392
- if (node.mutationType === "create") return makeTypeRef(node.entityName, "creatable", "GENERATED");
1393
- if (node.mutationType === "update") return tsg.intersectionType(makeTypeRef(node.entityName, "identifiable", "GENERATED"), makeTypeRef(node.entityName, "updatable", "GENERATED"));
1394
- return makeTypeRef(node.entityName, "identifiable", "GENERATED");
1395
- };
1396
- const makeEncoder = (name) => tsg.identifier(name).importFrom(Directory.resolve(DIR$1, "BASE", tsFileNames.encoder));
1397
- const makeIdDecodeMiddleware = (fields, node) => {
1398
- const params = tsg.identifier("args[1]");
1399
- const entityName = node.entity.name.lowerCase();
1400
- return tsg.arrowFunc([tsg.parameter("args")], void 0, tsg.block(tsg.binary(params, "=", tsg.object(tsg.spreadAssign(params), tsg.propertyAssign(entityName, tsg.object(tsg.spreadAssign(params.property(entityName)), ...fields.filter((it) => it.hashId).map((it) => tsg.propertyAssign(it.fieldName, makeEncoder(it.hashId.encoder).property("decode").call(params.property(entityName).property(it.fieldName).as(tsg.typeRef("string"))))))))).toStatement(), tsg.return(tsg.identifier("args"))));
1401
- };
1402
- const makeResolverMiddleware = (typeName, entity, fields, node) => {
1403
- const sig = fields.map((it) => tsg.propertySignature(it.fieldName, tsg.typeRef(it.hashId ? "string" : columnTypeToTsType(it.dbType))));
1404
- const requiredType = tsg.typeAlias(typeName, tsg.typeLiteral([tsg.propertySignature(entity.name.lowerCase(), makeParamType(node))]));
1405
- const middlewareName = node.mutationName + "Middleware";
1406
- if (!node.requireIdDecodeMiddleware) return [requiredType, tsg.variable("const", middlewareName, tsg.array(node.middlewares.map((it) => tsg.identifier(it).importFrom("../" + tsFileNames.middleware))), tsg.arrayType(tsg.typeRef("ResolverMiddleware", [makeContextTypeRef(DIR$1), tsg.identifier(typeName)]).importFrom("sasat")))];
1407
- return [
1408
- tsg.typeAlias("GQL" + typeName, tsg.typeLiteral([tsg.propertySignature(entity.name.lowerCase(), tsg.typeLiteral(sig))])),
1409
- requiredType,
1410
- tsg.variable("const", node.mutationName + "Middleware", tsg.array([makeIdDecodeMiddleware(fields, node), ...node.middlewares.map((it) => tsg.identifier(it).importFrom("../" + tsFileNames.middleware))]), tsg.arrayType(tsg.typeRef("ResolverMiddleware", [
1411
- makeContextTypeRef(DIR$1),
1412
- tsg.identifier(typeName),
1413
- tsg.identifier("GQL" + typeName)
1414
- ]).importFrom("sasat")))
1415
- ];
1416
- };
1417
- const makeMutationResolverMiddleware = (entity, node) => {
1418
- switch (node.mutationType) {
1419
- case "create": return makeResolverMiddleware(entity.name.createInputName(), entity, entity.creatable.fields, node);
1420
- case "update": return makeResolverMiddleware(entity.name.updateInputName(), entity, entity.updateInput.fields, node);
1421
- case "delete": return makeResolverMiddleware(entity.name.identifyInputName(), entity, entity.identifyFields(), node);
1422
- }
1423
- };
1424
- //#endregion
1425
- //#region src/generatorv2/codegen/ts/scripts/makeDatasource.ts
1426
- const makeDatasource = (entity, importFrom, args) => {
1427
- return tsg.new(tsg.identifier(entity.dataSourceName()).importFrom(Directory.resolve(importFrom, "DATA_SOURCES", entity.name)), ...args || []);
1428
- };
1429
- //#endregion
1430
- //#region src/generatorv2/codegen/ts/generateMutationResolver.ts
1431
- const generateMutationResolver = (root) => {
1432
- return new TsFile(...root.entities.flatMap(makeMutationMiddlewareAndTypes).flat(), tsg.variable("const", "mutation", tsg.object(...root.entities.flatMap((it) => it.mutations).map(makeMutation$1))).export()).disableEsLint();
1433
- };
1434
- const result = tsg.identifier("result");
1435
- const refetched = tsg.identifier("fetched");
1436
- const ds = tsg.identifier("ds");
1437
- const ident$1 = tsg.identifier("identifiable");
1438
- const makeMutation$1 = (node) => {
1439
- return tsg.propertyAssign(node.mutationName, makeResolver$2.call(tsg.arrowFunc(makeResolverArgs(node), void 0, makeMutationBody(node)).toAsync(), tsg.identifier(node.mutationName + "Middleware")).typeArgs(...[
1440
- context,
1441
- tsg.typeRef(node.inputName),
1442
- node.requireIdDecodeMiddleware ? tsg.typeRef("GQL" + node.inputName) : null
1443
- ].filter(nonNullable)));
1444
- };
1445
- const makeMutationBody = (node) => {
1446
- if (node.mutationType === "create") return makeCreateMutationBody(node);
1447
- if (node.mutationType === "update") return makeUpdateMutationBody(node);
1448
- return makeDeleteMutationBody(node);
1449
- };
1450
- const makeResolver$2 = tsg.identifier("makeResolver").importFrom("sasat");
1451
- const context = tsg.typeRef("GQLContext").importFrom(Directory.resolve("GENERATED", "BASE", "context"));
1452
- const makeResolverArgs = (node) => [
1453
- tsg.parameter("_"),
1454
- tsg.parameter(`{${node.entityName.lowerCase()}}`),
1455
- node.contextFields.length === 0 ? null : tsg.parameter("context")
1456
- ].filter(nonNullable);
1457
- const makeCreateMutationBody = (node) => {
1458
- const entity = tsg.identifier(node.entityName.lowerCase());
1459
- const dsVariable = tsg.variable("const", ds, makeDatasource(node.entityName, "GENERATED"));
1460
- const createCall = ds.property("create").call(entity);
1461
- if (!node.subscription && !node.refetch) return tsg.block(dsVariable, tsg.return(createCall));
1462
- if (!node.refetch) return tsg.block(dsVariable, tsg.variable("const", result, tsg.await(createCall)), node.subscription ? makePublishCall(node, result) : null, tsg.return(result));
1463
- return tsg.block(dsVariable, tsg.variable("const", result, tsg.await(createCall)), ...makeRefetched(node), node.subscription ? makePublishCall(node, refetched) : null, tsg.return(refetched));
1464
- };
1465
- const makeRefetched = (node) => {
1466
- return [tsg.variable("const", ident$1, tsg.identifier("pick").importFrom("sasat").call(node.mutationType === "create" ? result : tsg.identifier(node.entityName.lowerCase()), tsg.array(node.identifyFields.map(tsg.string))).as(tsg.typeRef("unknown")).as(makeTypeRef(node.entityName, "identifiable", "GENERATED"))), tsg.variable("const", refetched, tsg.await(ds.property(makeFindQueryName(node.identifyFields)).call(...node.identifyFields.map((it) => ident$1.property(it)))))];
1467
- };
1468
- const makePublishCall = (node, identifier) => {
1469
- return tsg.await(tsg.identifier(publishFunctionName(node.entityName, node.mutationType)).importFrom("./subscription").call(identifier.as(makeTypeRef(node.entityName, "entity", "GENERATED")))).toStatement();
1470
- };
1471
- const makeDatasourceParam = (entity, contextParams) => {
1472
- if (contextParams.length === 0) return entity;
1473
- return tsg.object(tsg.spreadAssign(entity), ...contextParams.map((it) => tsg.propertyAssign(it.fieldName, tsg.identifier(`context.${it.contextName}`))));
1474
- };
1475
- const makeUpdateMutationBody = (node) => {
1476
- const entity = tsg.identifier(node.entityName.lowerCase());
1477
- const statements = [tsg.variable("const", ds, makeDatasource(node.entityName, "GENERATED")), tsg.variable("const", result, tsg.await(ds.property("update").call(makeDatasourceParam(entity, node.contextFields)).property("then").call(tsg.arrowFunc([tsg.parameter("it", tsg.typeRef("CommandResponse").importFrom("sasat"))], KeywordTypeNode.boolean, tsg.binary(tsg.identifier("it.changedRows"), "===", tsg.number(1))))))];
1478
- if (!node.refetch && !node.subscription) return tsg.block(...statements, tsg.return(result));
1479
- return tsg.block(...statements, ...makeRefetched(node), node.subscription ? makePublishCall(node, refetched) : null, tsg.return(node.refetch ? refetched : result));
1480
- };
1481
- const makeDeleteMutationBody = (node) => {
1482
- const entity = tsg.identifier(node.entityName.lowerCase());
1483
- const dsV = tsg.variable("const", ds, makeDatasource(node.entityName, "GENERATED"));
1484
- const deleteCall = ds.property("delete").call(entity).property("then").call(tsg.arrowFunc([tsg.parameter("it", tsg.typeRef("CommandResponse").importFrom("sasat"))], KeywordTypeNode.boolean, tsg.binary(tsg.identifier("it.affectedRows"), "===", new NumericLiteral(1))));
1485
- return tsg.block(dsV, tsg.variable("const", result, tsg.await(deleteCall)), node.subscription ? tsg.if(result, tsg.block(makePublishCall(node, entity))) : null, tsg.return(result));
1486
- };
1487
- //#endregion
1488
- //#region src/cli/console.ts
1489
- const Console = {
1490
- success: (msg) => {
1491
- console.log(chalk.green(msg));
1492
- },
1493
- error: (msg) => {
1494
- console.error(chalk.bold.red(msg));
1495
- },
1496
- log: (msg) => {
1497
- console.log(msg);
1498
- },
1499
- debug: (msg) => {
1500
- console.debug("debug:: " + msg);
1501
- }
1502
- };
1503
- //#endregion
1504
- //#region src/migration/data/GQLOption.ts
1505
- const defaultGQLOption = () => ({
1506
- enabled: false,
1507
- queries: [],
1508
- mutations: []
1509
- });
1510
- const getArgs = (query, entity) => {
1511
- if (query.type === "primary") return entity.fields.filter((it) => it.isPrimary).map((it) => ({
1512
- kind: "arg",
1513
- name: it.fieldName,
1514
- type: it.gqlType
1515
- }));
1516
- const r = [];
1517
- if (query.type === "list-paging") r.push({
1518
- kind: "arg",
1519
- name: "option",
1520
- type: "PagingOption"
1521
- });
1522
- query.conditions.forEach((it) => {
1523
- if (it.left.kind === "arg") r.push(it.left);
1524
- if (it.kind === "between") {
1525
- if (it.begin.kind === "arg") r.push(it.begin);
1526
- if (it.end.kind === "arg") r.push(it.end);
1527
- } else if (it.right.kind === "arg") r.push(it.right);
1528
- });
1529
- return r;
1530
- };
1531
- //#endregion
1532
- //#region src/tsg/node/rawCodeStatement.ts
1533
- var RawCodeStatement = class extends TsStatement {
1534
- constructor(code) {
1535
- super();
1536
- this.code = code;
1537
- }
1538
- toTsString() {
1539
- return this.code;
1540
- }
1541
- };
1542
- //#endregion
1543
- //#region src/generatorv2/scripts/gqlTypes.ts
1544
- const toTsType = (type) => {
1545
- switch (type) {
1546
- case "Int":
1547
- case "Float": return "number";
1548
- case "ID":
1549
- case "String": return "string";
1550
- case "Boolean": return "boolean";
1551
- default: return type;
1552
- }
1553
- };
1554
- //#endregion
1555
- //#region src/generatorv2/codegen/ts/scripts/makeConditonValueExpr.ts
1556
- const qExpr$3 = tsg.identifier("qe").importFrom("sasat");
1557
- const makeConditionValueRaw = (cv) => {
1558
- const context = tsg.identifier("arg").property("context?");
1559
- switch (cv.kind) {
1560
- case "context": {
1561
- const value = context.property(cv.field);
1562
- if (cv.onNotDefined.action !== "defaultValue") return value;
1563
- return tsg.binary(context.property(cv.field), "||", typeof cv.onNotDefined.value === "string" ? tsg.string(cv.onNotDefined.value) : tsg.number(cv.onNotDefined.value));
1564
- }
1565
- case "fixed": return typeof cv.value === "string" ? tsg.string(cv.value) : tsg.number(cv.value);
1566
- case "today": return tsg.identifier(cv.type === "datetime" ? "getTodayDateTimeString" : "getTodayDateString").importFrom("sasat").call();
1567
- case "now": return tsg.identifier("dateString").importFrom("sasat").call(tsg.new(tsg.identifier("Date")));
1568
- default: throw Error(`not implemented: makeConditionValue.${cv.kind}`);
1569
- }
1570
- };
1571
- const makeConditionValueQExpr = (cv) => {
1572
- const context = tsg.identifier("arg").property("context?");
1573
- switch (cv.kind) {
1574
- case "context": {
1575
- const value = context.property(cv.field);
1576
- if (cv.onNotDefined.action !== "defaultValue") return qExpr$3.property("value").call(value);
1577
- return qExpr$3.property("value").call(tsg.binary(context.property(cv.field), "||", typeof cv.onNotDefined.value === "string" ? tsg.string(cv.onNotDefined.value) : tsg.number(cv.onNotDefined.value)));
1578
- }
1579
- case "fixed": return qExpr$3.property("value").call(typeof cv.value === "string" ? tsg.string(cv.value) : tsg.number(cv.value));
1580
- case "today": return qExpr$3.property("value").call(tsg.identifier(cv.type === "datetime" ? "getTodayDateTimeString" : "getTodayDateString").importFrom("sasat").call());
1581
- case "now": return qExpr$3.property("value").call(tsg.identifier("dateString").importFrom("sasat").call(tsg.new(tsg.identifier("Date"))));
1582
- case "arg": return qExpr$3.property("value").call(tsg.identifier(cv.name));
1583
- case "field": return qExpr$3.property("field").call(tsg.string("t0"), tsg.string(cv.column));
1584
- }
1585
- };
1586
- //#endregion
1587
- //#region src/generatorv2/codegen/ts/scripts/makeQueryConditionExpr.ts
1588
- const qExpr$2 = tsg.identifier("qe").importFrom("sasat");
1589
- const makeQueryConditionExpr = (condition) => {
1590
- if (condition.kind === "between") return qExpr$2.property("between").call(makeConditionValueQExpr(condition.left), makeConditionValueQExpr(condition.begin), makeConditionValueQExpr(condition.end));
1591
- return qExpr$2.property("comparison").call(makeConditionValueQExpr(condition.left), tsg.string(condition.operator), makeConditionValueQExpr(condition.right));
1592
- };
1593
- //#endregion
1594
- //#region src/generatorv2/codegen/ts/generateQueryResolver.ts
1595
- const DIR = "GENERATED";
1596
- const generateQueryResolver = (root) => {
1597
- return new TsFile(tsg.variable("const", "query", tsg.object(...root.entities.flatMap((entity) => entity.queries.map((query) => makeGQLQuery(entity, query))).filter(nonNullable))).export()).disableEsLint();
1598
- };
1599
- const makeResolver$1 = () => tsg.identifier("makeResolver").importFrom("sasat");
1600
- const makeGQLQuery = (entity, query) => {
1601
- if (!entity.gqlEnabled) {
1602
- Console.log(`Query.${query.name || entity.name.lowerCase()} generation skipped. Reason: Entity:${entity.name.name} is not Open to GQL.`);
1603
- return null;
1604
- }
1605
- const args = getArgs(query, entity);
1606
- return tsg.propertyAssign(query.type === "primary" ? entity.name.lowerCase() : query.name, makeResolver$1().call(...[tsg.arrowFunc([
1607
- tsg.parameter("_"),
1608
- tsg.parameter(`{${args.map((it) => it.name).join(",")}}`),
1609
- tsg.parameter("context"),
1610
- tsg.parameter("info")
1611
- ], void 0, makeGQLQueryBody(entity, query)).toAsync(), makeMiddlewares(entity, query)].filter(nonNullable)).typeArgs(...makeTypeArgs(args)));
1612
- };
1613
- const getHashIdArgs = (entity, query) => {
1614
- if (query.type === "primary") {
1615
- const hashIDs = entity.identifyFields().filter((it) => it.option.autoIncrementHashId);
1616
- if (hashIDs.length === 0) return null;
1617
- return hashIDs.map((it) => ({
1618
- encoder: it.hashId.encoder,
1619
- name: it.fieldName
1620
- }));
1621
- }
1622
- const getHashIdArg = (arg, field) => {
1623
- const columnName = field.column;
1624
- const hashIdOpt = entity.fields.find((e) => e.columnName === columnName)?.hashId;
1625
- if (!hashIdOpt) return null;
1626
- return {
1627
- name: arg.name,
1628
- encoder: hashIdOpt.encoder
1629
- };
1630
- };
1631
- return query.conditions.map((it) => {
1632
- if (it.kind === "comparison") {
1633
- if (it.left.kind === "arg") {
1634
- if (it.right.kind === "field") return getHashIdArg(it.left, it.right);
1635
- }
1636
- if (it.right.kind === "arg") {
1637
- if (it.left.kind === "field") return getHashIdArg(it.right, it.left);
1638
- }
1639
- }
1640
- return null;
1641
- }).filter(nonNullable);
1642
- };
1643
- const makeHashIdMiddleware = (entity, query) => {
1644
- const args = getHashIdArgs(entity, query);
1645
- if (!args || args?.length === 0) return null;
1646
- return tsg.arrowFunc([tsg.parameter("args")], void 0, tsg.block(new RawCodeStatement(`args[1] = {...args[1], ${args.map((it) => `${it.name}: ${it.encoder}.decode(args[1].${it.name} as string),`).join("")}};`).addImport(args.map((it) => it.encoder), Directory.resolve(DIR, "BASE", tsFileNames.encoder)), tsg.return(tsg.identifier("args"))));
1647
- };
1648
- const makeMiddlewares = (entity, query) => {
1649
- const hashId = makeHashIdMiddleware(entity, query);
1650
- if (!hashId && query.middlewares.length === 0) return null;
1651
- if (query.middlewares.length === 0) return tsg.array([hashId]);
1652
- const middlewares = query.middlewares.map((it) => tsg.identifier(it).importFrom("../" + tsFileNames.middleware));
1653
- if (!hashId) return tsg.array(middlewares);
1654
- return tsg.array([hashId, ...middlewares]);
1655
- };
1656
- const makeTypeArgs = (args) => {
1657
- let hashIds = false;
1658
- const getType = (arg, checkHashId) => {
1659
- if (arg.type === "PagingOption") return tsg.typeRef(arg.type).importFrom("sasat");
1660
- if (checkHashId && arg.type === "ID") {
1661
- hashIds = true;
1662
- return tsg.typeRef("number");
1663
- }
1664
- return tsg.typeRef(toTsType(arg.type));
1665
- };
1666
- const params = tsg.typeLiteral(args.map((it) => tsg.propertySignature(it.name, getType(it, true))));
1667
- if (!hashIds) return [makeContextTypeRef("GENERATED"), params];
1668
- return [
1669
- makeContextTypeRef("GENERATED"),
1670
- params,
1671
- tsg.typeLiteral(args.map((it) => tsg.propertySignature(it.name, getType(it, false))))
1672
- ];
1673
- };
1674
- const qExpr$1 = tsg.identifier("qe").importFrom("sasat");
1675
- const makeGQLQueryBody = (entity, query) => {
1676
- const fields = tsg.variable("const", "fields", tsg.identifier("gqlResolveInfoToField").importFrom("sasat").call(tsg.identifier("info")).as(makeTypeRef(entity.name, "fields", "GENERATED")));
1677
- const where = query.conditions && query.conditions.length !== 0 ? tsg.variable("const", "where", qExpr$1.property("and").call(...(query.conditions || []).map(makeQueryConditionExpr))) : null;
1678
- const method = {
1679
- single: "first",
1680
- primary: entity.primaryQueryName(),
1681
- "list-all": "find",
1682
- "list-paging": "findPageable"
1683
- };
1684
- const queryArgs = getArgs(query, entity);
1685
- const args = [
1686
- ...query.type === "primary" ? queryArgs.map((it) => tsg.identifier(it.name)) : [],
1687
- query.type === "list-paging" ? tsg.identifier("pagingOption").importFrom("sasat").call(tsg.identifier("option")) : null,
1688
- tsg.identifier("fields"),
1689
- tsg.identifier(where ? "{ where }" : "undefined"),
1690
- tsg.identifier("context")
1691
- ].filter(nonNullable);
1692
- const result = makeDatasource(entity.name, DIR).property(method[query.type]).call(...args);
1693
- return tsg.block(fields, where, tsg.return(result));
1694
- };
1695
- //#endregion
1696
- //#region src/generatorv2/codegen/ts/generateResolver.ts
1697
- const generateResolver = (root) => {
1698
- const hasSubscription = root.subscriptions.some((it) => it.gqlEnabled);
1699
- const properties = [tsg.propertyAssign("Query", tsg.identifier("query").importFrom("./query")), tsg.propertyAssign("Mutation", tsg.identifier("mutation").importFrom("./mutation"))];
1700
- if (hasSubscription) properties.push(tsg.propertyAssign("Subscription", tsg.identifier("subscription").importFrom("./subscription")));
1701
- return new TsFile(tsg.variable("const", tsg.identifier("resolvers"), tsg.object(...properties, tsg.spreadAssign(tsg.object(...root.entities.filter((it) => it.gqlEnabled).map(makeEntityResolver))))).export()).disableEsLint();
1702
- };
1703
- const makeEntityResolver = (node) => {
1704
- return tsg.propertyAssign(node.name.name, tsg.object(...node.fields.filter((it) => it.hashId).map(makeHashIdProperty).filter(nonNullable), ...node.references.filter((it) => it.isGQLOpen).map((ref) => makeRelationProperty(ref)), ...node.referencedBy.filter((it) => it.isGQLOpen).map((ref) => makeReferencedByProperty(ref))));
1705
- };
1706
- const makeHashIdProperty = (field) => {
1707
- if (!field.hashId) return null;
1708
- const paramName = field.entity.name.lowerCase();
1709
- return tsg.propertyAssign(field.fieldName, tsg.arrowFunc([tsg.parameter(paramName, makeTypeRef(field.entity.name, "result", "GENERATED"))], void 0, tsg.binary(tsg.identifier(paramName).property(field.fieldName), "&&", tsg.identifier(field.hashId.encoder).importFrom(Directory.resolve("GENERATED", "BASE", tsFileNames.encoder)).property("encode").call(tsg.identifier(paramName).property(field.fieldName)))));
1710
- };
1711
- const makeRelationProperty = (ref) => {
1712
- const paramName = ref.entity.name.lowerCase();
1713
- return tsg.propertyAssign(ref.fieldName, tsg.arrowFunc([tsg.parameter(paramName, makeTypeRef(ref.entity.name, "result", "GENERATED")), tsg.parameter("context", makeContextTypeRef("GENERATED"))], void 0, tsg.block(tsg.if(tsg.binary(tsg.identifier(paramName).property(ref.fieldName), "!==", tsg.identifier("undefined")), tsg.return(tsg.identifier(paramName).property(ref.fieldName))), tsg.variable("const", "ds", makeDatasource(EntityName.fromTableName(ref.parentTableName), "GENERATED")), tsg.variable("const", "where", tsg.identifier("ds").property("getRelationMap").call().property(ref.fieldName).property("condition").call(tsg.object(tsg.propertyAssign("parent", tsg.identifier(paramName)), tsg.propertyAssign("childTableAlias", tsg.string("t0")), tsg.propertyAssign("context")))), tsg.return(tsg.identifier("ds").property("first").call(tsg.identifier("undefined"), tsg.object(tsg.propertyAssign("where")))))));
1714
- };
1715
- const makeReferencedByProperty = (ref) => {
1716
- const paramName = ref.entity.name.lowerCase();
1717
- const propertyName = ref.fieldName;
1718
- return tsg.propertyAssign(propertyName, tsg.arrowFunc([tsg.parameter(paramName, makeTypeRef(ref.entity.name, "result", "GENERATED")), tsg.parameter("context", makeContextTypeRef("GENERATED"))], void 0, tsg.block(tsg.if(tsg.binary(tsg.identifier(paramName).property(propertyName), "!==", tsg.identifier("undefined")), tsg.return(tsg.identifier(paramName).property(propertyName))), tsg.variable("const", "ds", makeDatasource(EntityName.fromTableName(ref.childTable), "GENERATED")), tsg.variable("const", "where", tsg.identifier("ds").property("getRelationMap").call().property(propertyName).property("condition").call(tsg.object(tsg.propertyAssign("parent", tsg.identifier(paramName)), tsg.propertyAssign("childTableAlias", tsg.string("t0")), tsg.propertyAssign("context")))), tsg.return(tsg.identifier("ds").property(ref.isArray ? "find" : "first").call(tsg.identifier("undefined"), tsg.object(tsg.propertyAssign("where")))))));
1719
- };
1720
- //#endregion
1721
- //#region src/generatorv2/codegen/ts/generateSubscription.ts
1722
- const generateSubscription = (root) => {
1723
- const subscriptionEnum = tsg.enum(tsg.identifier("SubscriptionName"), []).export();
1724
- const subscriptions = tsg.object();
1725
- const publishFunctions = [];
1726
- root.subscriptions.forEach((it) => {
1727
- subscriptionEnum.addMembers(tsg.enumMember(tsg.identifier(it.subscriptionName), tsg.string(it.subscriptionName)));
1728
- if (it.gqlEnabled) {
1729
- const fn = it.filters.length === 0 ? makeAsyncIteratorCall(it.subscriptionName) : makeWithFilter(it.subscriptionName, it.filters);
1730
- subscriptions.addProperties(tsg.propertyAssign(it.subscriptionName, tsg.object(tsg.propertyAssign("subscribe", fn))));
1731
- }
1732
- publishFunctions.push(tsg.variable("const", tsg.identifier(it.publishFunctionName), tsg.arrowFunc([tsg.parameter("entity", makeTypeRef(it.entity, it.mutationType === "delete" ? "identifiable" : "entity", "GENERATED"))], tsg.typeRef("Promise", [KeywordTypeNode.void]), tsg.identifier("pubsub.publish").call(tsg.identifier(`SubscriptionName.${it.subscriptionName}`), tsg.object(tsg.propertyAssign(it.subscriptionName, tsg.identifier("entity")))))).export());
1733
- });
1734
- return new TsFile(subscriptionEnum, tsg.variable("const", tsg.identifier("subscription"), subscriptions).export(), ...publishFunctions).disableEsLint();
1735
- };
1736
- const makeAsyncIteratorCall = (event) => {
1737
- return tsg.arrowFunc([], void 0, tsg.identifier("pubsub").importFrom("../pubsub").property("asyncIterator").call(tsg.array([tsg.identifier(`SubscriptionName.${event}`)])));
1738
- };
1739
- const makeWithFilter = (event, filters) => {
1740
- const binaryExpressions = filters.map((it) => tsg.binary(tsg.identifier(`result.${it.field}`), "===", tsg.identifier(`variables.${it.field}`))).reduce((previousValue, currentValue) => tsg.binary(previousValue, "&&", currentValue));
1741
- return tsg.identifier("withFilter").importFrom("graphql-subscriptions").call(makeAsyncIteratorCall(event), tsg.arrowFunc([tsg.parameter("payload", KeywordTypeNode.any), tsg.parameter("variables", KeywordTypeNode.any)], tsg.typeRef("Promise", [KeywordTypeNode.boolean]), tsg.block(tsg.variable("const", tsg.identifier("result"), tsg.await(tsg.identifier(`payload.${event}`))), tsg.return(binaryExpressions))).toAsync());
1742
- };
1743
- //#endregion
1744
- //#region src/generatorv2/codegen/ts/scripts/gqlString.ts
1745
- const GQLString = {
1746
- args: (args) => {
1747
- if (args.length === 0) return "";
1748
- return `(${args.map((arg) => `${arg.name}: ${GQLString.type(arg.type)}`).join(",")})`;
1749
- },
1750
- field: (field) => {
1751
- return `${field.fieldName}: ${fieldGqlType(field)}`;
1752
- },
1753
- referenceField: (ref) => {
1754
- return `${ref.fieldName}: ${makeGQLType(EntityName.fromTableName(ref.parentTableName).name, ref.isNullable, ref.isArray)}`;
1755
- },
1756
- referencedField: (ref) => {
1757
- return `${ref.fieldName}: ${makeGQLType(EntityName.fromTableName(ref.childTable).name, ref.isNullable, ref.isArray)}`;
1758
- },
1759
- query: (node) => {
1760
- return `${node.queryName}${GQLString.args(node.args)}: ${GQLString.type(node.returnType)}`;
1761
- },
1762
- mutation: (node) => {
1763
- return `${node.mutationName}${GQLString.args(node.args)}: ${GQLString.type(node.returnType)}`;
1764
- },
1765
- subscription: (node) => {
1766
- return `${node.subscriptionName}${GQLString.args(node.args)}: ${GQLString.type(node.returnType)}`;
1767
- },
1768
- type: (node) => {
1769
- const type = node.nullable ? node.typeName : node.typeName + "!";
1770
- if (node.array) return `[${type}]!`;
1771
- return type;
1772
- }
1773
- };
1774
- const fieldGqlType = (field) => {
1775
- return makeGQLType(field.gqlType, field.isNullable, field.isArray);
1776
- };
1777
- const makeGQLType = (typeName, isNullable, isArray) => {
1778
- const type = isNullable ? typeName : typeName + "!";
1779
- if (isArray) return `[${type}]!`;
1780
- return type;
1781
- };
1782
- //#endregion
1783
- //#region src/generatorv2/codegen/ts/scripts/typeDefinition.ts
1784
- const typeFieldDefinitionToTsg = (def) => {
1785
- const properties = [tsg.propertyAssign("return", tsg.string(def.return)), def.args ? tsg.propertyAssign("args", tsg.array(def.args.map((it) => {
1786
- return tsg.object(tsg.propertyAssign("name", tsg.string(it.name)), tsg.propertyAssign("type", tsg.string(it.type)));
1787
- }))) : null];
1788
- return tsg.object(...properties.filter(nonNullable));
1789
- };
1790
- //#endregion
1791
- //#region src/generatorv2/codegen/ts/generateTypeDefs.ts
1792
- const generateTypeDefs = (root) => {
1793
- const types = [
1794
- ...root.entities.map(makeEntityType),
1795
- makeQuery(root),
1796
- makeMutation(root.entities.flatMap((it) => it.mutations)),
1797
- makeSubscription(root.subscriptions.filter((it) => it.gqlEnabled))
1798
- ].filter(nonNullable);
1799
- const inputs = [
1800
- tsg.propertyAssign("PagingOption", tsg.object(tsg.propertyAssign("numberOfItem", typeFieldDefinitionToTsg({ return: "Int!" })), tsg.propertyAssign("offset", typeFieldDefinitionToTsg({ return: "Int" })), tsg.propertyAssign("order", typeFieldDefinitionToTsg({ return: "String" })), tsg.propertyAssign("asc", typeFieldDefinitionToTsg({ return: "Boolean" })))),
1801
- ...root.entities.map(makeCreateInput),
1802
- ...root.entities.map(makeUpdateInput),
1803
- ...root.entities.map(makeIdentifyInput)
1804
- ].filter(nonNullable);
1805
- return new TsFile(tsg.variable("const", tsg.identifier("typeDefs"), tsg.object(...types)).export(), tsg.variable("const", tsg.identifier("inputs"), tsg.object(...inputs)).export()).disableEsLint();
1806
- };
1807
- const makeEntityType = (node) => {
1808
- if (!node.gqlEnabled) return null;
1809
- return tsg.propertyAssign(node.name.name, tsg.object(...node.fields.filter((it) => it.isGQLOpen).map((it) => {
1810
- return tsg.propertyAssign(it.fieldName, typeFieldDefinitionToTsg({ return: makeGQLType(it.gqlType, it.isNullable, it.isArray) }));
1811
- }), ...node.references.filter((it) => it.isGQLOpen).map((it) => {
1812
- return tsg.propertyAssign(it.fieldName, typeFieldDefinitionToTsg({ return: makeGQLType(EntityName.fromTableName(it.parentTableName).name, it.isNullable, it.isArray) }));
1813
- }), ...node.referencedBy.filter((it) => it.isGQLOpen).map((it) => {
1814
- return tsg.propertyAssign(it.fieldName, typeFieldDefinitionToTsg({ return: makeGQLType(EntityName.fromTableName(it.childTable).name, it.isNullable, it.isArray) }));
1815
- })));
1816
- };
1817
- const makeInput = (inputName, fields) => {
1818
- return tsg.propertyAssign(inputName, tsg.object(...fields.filter((it) => it.isGQLOpen).map((it) => tsg.propertyAssign(it.fieldName, typeFieldDefinitionToTsg({ return: makeGQLType(it.gqlType, it.isNullable, it.isArray) })))));
1819
- };
1820
- const makeCreateInput = (node) => {
1821
- if (!node.gqlEnabled || !node.creatable.gqlEnabled) return null;
1822
- return makeInput(node.name.createInputName(), node.creatable.fields);
1823
- };
1824
- const makeUpdateInput = (node) => {
1825
- if (!node.gqlEnabled || !node.updateInput.gqlEnabled) return null;
1826
- return makeInput(node.name.updateInputName(), node.updateInput.fields);
1827
- };
1828
- const makeIdentifyInput = (node) => {
1829
- if (!node.gqlEnabled || !node.mutations.find((it) => it.mutationType === "delete")) return null;
1830
- return makeInput(node.name.identifyInputName(), node.fields.filter((it) => it.isPrimary));
1831
- };
1832
- const makeQueryTypeDef = (entity, query) => {
1833
- const args = getArgs(query, entity);
1834
- return tsg.propertyAssign(query.type === "primary" ? entity.name.lowerCase() : query.name, typeFieldDefinitionToTsg({
1835
- return: GQLString.type({
1836
- typeName: entity.name.name,
1837
- entity: true,
1838
- array: query.type === "list-paging" || query.type === "list-all",
1839
- nullable: query.type !== "list-paging" && query.type !== "list-all"
1840
- }),
1841
- args: args.map((it) => ({
1842
- name: it.name,
1843
- type: it.type + "!"
1844
- }))
1845
- }));
1846
- };
1847
- const makeQueryProperties = (root) => {
1848
- return root.entities.filter((it) => it.gqlEnabled).flatMap((entity) => entity.queries.map((it) => makeQueryTypeDef(entity, it)));
1849
- };
1850
- const makeQuery = (root) => {
1851
- const properties = makeQueryProperties(root);
1852
- if (properties.length === 0) return null;
1853
- return tsg.propertyAssign("Query", tsg.object(...properties));
1854
- };
1855
- const makeMutation = (mutations) => {
1856
- if (mutations.length === 0) return null;
1857
- return tsg.propertyAssign("Mutation", tsg.object(...mutations.map((mutation) => {
1858
- return tsg.propertyAssign(mutation.mutationName, typeFieldDefinitionToTsg({
1859
- return: GQLString.type(mutation.returnType),
1860
- args: mutation.args.map((arg) => ({
1861
- name: arg.name,
1862
- type: GQLString.type(arg.type)
1863
- }))
1864
- }));
1865
- })));
1866
- };
1867
- const makeSubscription = (subscriptions) => {
1868
- if (subscriptions.length === 0) return null;
1869
- return tsg.propertyAssign("Subscription", tsg.object(...subscriptions.map((subscription) => {
1870
- return tsg.propertyAssign(subscription.subscriptionName, typeFieldDefinitionToTsg({
1871
- return: GQLString.type(subscription.returnType),
1872
- args: subscription.args.map((arg) => ({
1873
- name: arg.name,
1874
- type: GQLString.type(arg.type)
1875
- }))
1876
- }));
1877
- })));
1878
- };
1879
- //#endregion
1880
- //#region src/generatorv2/codegen/ts/generateUserDefinedCondition.ts
1881
- const { createSourceFile, ScriptTarget } = typescript;
1882
- const generateUserDefinedCondition = (root, content) => {
1883
- const customConditionNames = unique(root.entities.flatMap((it) => [...it.references.flatMap((it) => it.joinCondition.filter((it) => it.kind === "custom").map((it) => it.conditionName)), ...it.referencedBy.flatMap((it) => it.joinCondition.filter((it) => it.kind === "custom").map((it) => it.conditionName))]));
1884
- if (customConditionNames.length === 0) return null;
1885
- const sourceFile = createSourceFile(tsFileNames.conditions + ".ts", content, ScriptTarget.ESNext);
1886
- const exportedVariables = getExportedVariables(sourceFile);
1887
- const contextImported = isImported(sourceFile, "GQLContext", ["./context", "./context.js"]);
1888
- const customConditionImported = isImported(sourceFile, "CustomCondition", ["sasat"]);
1889
- const statements = [];
1890
- customConditionNames.forEach((conditionName) => {
1891
- if (!exportedVariables.some((it) => {
1892
- return it.declarationList.declarations[0].name.getText(sourceFile) === conditionName;
1893
- })) statements.push(tsg.variable("const", conditionName, tsg.arrowFunc([], void 0, tsg.block(tsg.throw(tsg.new(tsg.identifier("Error"), tsg.string("TODO: Not Implemented"))))), tsg.typeRef("CustomCondition", [tsg.typeRef("GQLContext")])).export());
1894
- });
1895
- const context = contextImported ? "" : new ImportDeclaration(["GQLContext"], "./context").toString() + "\n";
1896
- const condition = customConditionImported ? "" : new ImportDeclaration(["CustomCondition"], "sasat").toString() + "\n";
1897
- const addition = statements.length === 0 ? "" : "\n" + new TsFile(...statements).toString();
1898
- return context + condition + content + addition;
1899
- };
1900
- //#endregion
1901
- //#region src/generatorv2/codegen/ts/relationMap/getRequiredColumnNames.ts
1902
- const getChildConditionValue = (cv) => {
1903
- if (cv.kind === "child") return cv.field;
1904
- return null;
1905
- };
1906
- const getConditionChildColumnNames = (getConditionValue) => (c) => {
1907
- if (c.kind === "custom") return c.childRequiredFields || [];
1908
- if (c.kind === "isNull") return [];
1909
- const result = [getConditionValue(c.left)];
1910
- if (c.operator === "IN") {
1911
- result.push(getConditionValue(c.left));
1912
- c.right.forEach((it) => {
1913
- result.push(getConditionValue(it));
1914
- });
1915
- }
1916
- if (c.operator !== "BETWEEN") result.push(getConditionValue(c.right));
1917
- else if (c.right.kind === "range") result.push(getConditionValue(c.right.begin), getConditionValue(c.right.end));
1918
- return result;
1919
- };
1920
- const getChildRequiredNames = (ref) => {
1921
- const getNames = getConditionChildColumnNames(getChildConditionValue);
1922
- return ref.joinCondition.flatMap(getNames).filter(nonNullable);
1923
- };
1924
- //#endregion
1925
- //#region src/generatorv2/codegen/ts/relationMap/makeNoContexError.ts
1926
- const makeJoinRangeConditionThrowExpressions = (cv) => {
1927
- if (cv.kind === "range") {
1928
- const result = [];
1929
- if (cv.begin.kind === "context") result.push(makeJoinConditionThrowExpressions(cv.begin));
1930
- if (cv.end.kind === "context") result.push(makeJoinConditionThrowExpressions(cv.end));
1931
- return result;
1932
- }
1933
- return [];
1934
- };
1935
- const makeJoinConditionThrowExpressions = (cv) => {
1936
- if (cv.kind !== "context") return null;
1937
- if (cv.onNotDefined.action !== "error") return null;
1938
- return tsg.if(tsg.binary(tsg.identifier("!arg.context"), "||", tsg.binary(tsg.identifier("arg.context").property(cv.field), "===", tsg.identifier("undefined"))), tsg.throw(tsg.new(tsg.identifier("Error"), tsg.string(cv.onNotDefined.message))));
1939
- };
1940
- const makeThrowExpressions = (condition) => {
1941
- if (condition.kind === "custom") return [];
1942
- if (condition.kind === "isNull") return [makeJoinConditionThrowExpressions(condition.value)];
1943
- if (condition.operator === "BETWEEN") return [makeJoinConditionThrowExpressions(condition.left), ...condition.right.kind === "range" ? makeJoinRangeConditionThrowExpressions(condition.right) : []];
1944
- if (condition.operator === "IN") return [makeJoinConditionThrowExpressions(condition.left), ...condition.right.map(makeJoinConditionThrowExpressions)];
1945
- return [makeJoinConditionThrowExpressions(condition.left), makeJoinConditionThrowExpressions(condition.right)];
1946
- };
1947
- //#endregion
1948
- //#region src/generatorv2/codegen/ts/relationMap/makeJoinConditionValue.ts
1949
- const qExpr = tsg.identifier("qe").importFrom("sasat");
1950
- const parentTableAlias = "parentTableAlias";
1951
- const childTableAlias = "childTableAlias";
1952
- const makeJoinConditionValueQExpr = (node, cv) => {
1953
- const arg = tsg.identifier("arg");
1954
- switch (cv.kind) {
1955
- case "parent": {
1956
- const columnName = node.fields.find((it) => it.fieldName === cv.field)?.columnName || cv.field;
1957
- return qExpr.property("field").call(arg.property(childTableAlias), tsg.string(columnName));
1958
- }
1959
- case "child": {
1960
- const columnName = node.fields.find((it) => it.fieldName === cv.field)?.columnName || cv.field;
1961
- return tsg.ternary(arg.property(parentTableAlias), qExpr.property("field").call(arg.property(parentTableAlias), tsg.string(columnName)), qExpr.property("value").call(arg.property("parent?").property(cv.field)));
1962
- }
1963
- default: return makeConditionValueQExpr(cv);
1964
- }
1965
- };
1966
- const makeRangeCondition = (entity, range) => {
1967
- if (range.kind === "range") return [makeJoinConditionValueQExpr(entity, range.begin), makeJoinConditionValueQExpr(entity, range.end)];
1968
- return [tsg.spread(tsg.identifier("getDayRangeQExpr").importFrom("sasat").call(tsg.new(tsg.identifier("Date")), range.thresholdHour ? tsg.number(range.thresholdHour) : tsg.identifier("undefined")))];
1969
- };
1970
- const makeConditionExpr = (entity, condition) => {
1971
- if (condition.kind === "custom") return tsg.identifier(condition.conditionName).importFrom("../conditions").call(tsg.identifier("arg"));
1972
- if (condition.kind === "isNull") return qExpr.property(condition.not ? "isNotNull" : "isNull").call(makeJoinConditionValueQExpr(entity, condition.value));
1973
- if (condition.operator === "BETWEEN") return qExpr.property("between").call(makeJoinConditionValueQExpr(entity, condition.left), ...makeRangeCondition(entity, condition.right));
1974
- if (condition.operator === "IN") return qExpr.property("in").call(makeJoinConditionValueQExpr(entity, condition.left), tsg.array(condition.right.map((it) => makeConditionValueRaw(it))));
1975
- return qExpr.property("comparison").call(makeJoinConditionValueQExpr(entity, condition.left), tsg.string(condition.operator), makeJoinConditionValueQExpr(entity, condition.right));
1976
- };
1977
- const makeJoinConditionValue = (node, ref) => {
1978
- const arg = tsg.identifier("arg");
1979
- return tsg.propertyAssign("condition", tsg.arrowFunc([tsg.parameter(arg.toString())], tsg.typeRef("BooleanValueExpression").importFrom("sasat"), tsg.block(...ref.joinCondition.flatMap((it) => makeThrowExpressions(it)).filter(nonNullable), tsg.return(qExpr.property("and").call(...ref.joinCondition.map((it) => makeConditionExpr(node, it)))))));
1980
- };
1981
- //#endregion
1982
- //#region src/generatorv2/codegen/ts/relationMap/index.ts
1983
- const generateRelationMap = (root) => {
1984
- return new TsFile(makeRelationMap(root), makeTableInfo(root), ...root.entities.flatMap(entityRelationType)).disableEsLint();
1985
- };
1986
- const makeRelationMap = (root) => {
1987
- return tsg.variable("const", tsg.identifier("relationMap"), tsg.object(...root.entities.map((it) => makeEntityRelationMap(it))), tsg.typeRef("RelationMap", [makeContextTypeRef("GENERATED")]).importFrom("sasat")).export();
1988
- };
1989
- const fieldNameToColumnNameAndFilterPrimary = (node) => (field) => {
1990
- const column = node.fields.find((it) => it.fieldName === field || it.columnName === field);
1991
- if (!column) throw new Error(`${node.name.name}.${field} Not Found`);
1992
- if (column.isPrimary) return null;
1993
- return column.columnName;
1994
- };
1995
- const makeEntityRelationMap = (node) => {
1996
- return tsg.propertyAssign(node.tableName, tsg.object(...node.references.map((ref) => {
1997
- const toColumnName = fieldNameToColumnNameAndFilterPrimary(ref.entity);
1998
- return tsg.propertyAssign(ref.fieldName, tsg.object(tsg.propertyAssign("table", tsg.string(ref.parentTableName)), makeJoinConditionValue(node, ref), tsg.propertyAssign("array", tsg.boolean(ref.isArray)), tsg.propertyAssign("nullable", tsg.boolean(ref.isNullable)), tsg.propertyAssign("requiredColumns", tsg.array(getChildRequiredNames(ref).map(toColumnName).filter(nonNullable).map(tsg.string)))));
1999
- }), ...node.referencedBy.map((rel) => {
2000
- const toColumnName = fieldNameToColumnNameAndFilterPrimary(rel.entity);
2001
- return tsg.propertyAssign(rel.fieldName, tsg.object(tsg.propertyAssign("table", tsg.string(rel.childTable)), makeJoinConditionValue(node, rel), tsg.propertyAssign("array", tsg.boolean(rel.isArray)), tsg.propertyAssign("nullable", tsg.boolean(rel.isNullable)), tsg.propertyAssign("requiredColumns", tsg.array(getChildRequiredNames(rel).map(toColumnName).filter(nonNullable).map(tsg.string)))));
2002
- })));
2003
- };
2004
- const makeTableInfo = (root) => {
2005
- const columnMap = (entity) => tsg.propertyAssign("columnMap", tsg.object(...entity.fields.map((field) => tsg.propertyAssign(field.fieldName, tsg.string(field.columnName)))));
2006
- return tsg.variable("const", "tableInfo", tsg.object(...root.entities.map((entity) => tsg.propertyAssign(entity.tableName, tsg.object(tsg.propertyAssign("identifiableKeys", tsg.array(entity.identifyKeys.map(tsg.string))), tsg.propertyAssign("identifiableFields", tsg.array(entity.fields.filter((it) => it.isPrimary).map((it) => it.fieldName).map(tsg.string))), columnMap(entity))))), tsg.typeRef("TableInfo").importFrom("sasat")).export();
2007
- };
2008
- const referenceRelationType = (ref) => {
2009
- const parentEntityName = EntityName.fromTableName(ref.parentTableName);
2010
- const type = tsg.typeRef("EntityResult", [tsg.typeRef(parentEntityName.entityWithRelationTypeName()), tsg.typeRef(parentEntityName.relationTypeName())]).importFrom("sasat");
2011
- return tsg.propertySignature(ref.fieldName, ref.isArray ? tsg.arrayType(type) : type);
2012
- };
2013
- const referencedRelationType = (node) => {
2014
- const child = EntityName.fromTableName(node.childTable);
2015
- const type = tsg.typeRef("EntityResult", [tsg.typeRef(child.entityWithRelationTypeName()), makeTypeRef(child, "identifiable", "GENERATED")]).importFrom("sasat");
2016
- return tsg.propertySignature(node.fieldName, node.isArray ? tsg.arrayType(type) : type);
2017
- };
2018
- const entityRelationType = (node) => {
2019
- const typeProperties = [...node.references.map(referenceRelationType), ...node.referencedBy.map(referencedRelationType)];
2020
- return [
2021
- tsg.typeAlias(node.name.relationTypeName(), typeProperties.length !== 0 ? tsg.typeLiteral(typeProperties) : tsg.typeRef("Record<never, never>")).export(),
2022
- tsg.typeAlias(node.name.entityWithRelationTypeName(), tsg.intersectionType(makeTypeRef(node.name, "entity", "GENERATED"), tsg.typeRef(node.name.relationTypeName()))).export(),
2023
- tsg.typeAlias(node.name.resultType(), tsg.typeRef("EntityResult", [tsg.typeRef(node.name.entityWithRelationTypeName()), makeTypeRef(node.name, "identifiable", "GENERATED")]).importFrom("sasat")).export()
2024
- ];
2025
- };
2026
- //#endregion
2027
- //#region src/generatorv2/codegen/ts/staticFiles.ts
2028
- const contextFile = `\
2029
- ${new ImportDeclaration(["BaseGQLContext"], "./__generated__/context").toString()}
2030
- export type GQLContext = BaseGQLContext & Record<string, never>;
2031
- `;
2032
- const pubsubFile = `\
2033
- ${new ImportDeclaration(["PubSub", "PubSubEngine"], "graphql-subscriptions").toString()}
2034
-
2035
- export const pubsub: PubSubEngine = new PubSub();
2036
- `;
2037
- const schemaFile = `\
2038
- ${new ImportDeclaration(["assignDeep", "createTypeDef"], "sasat").toString()}
2039
- ${new ImportDeclaration(["typeDefs", "inputs"], "./__generated__/typeDefs").toString()}
2040
- ${new ImportDeclaration(["resolvers"], "./__generated__/resolver").toString()}
2041
-
2042
- export const schema = {
2043
- typeDefs: createTypeDef(
2044
- assignDeep(typeDefs, {}),
2045
- assignDeep(inputs, {}),
2046
- ),
2047
- resolvers: assignDeep(resolvers, {}),
2048
- };
2049
- `;
2050
- const baseDBDataSourceFile = `\
2051
- ${new ImportDeclaration([
2052
- "Fields",
2053
- "SasatDBDatasource",
2054
- "EntityType"
2055
- ], "sasat").toString()}
2056
- ${new ImportDeclaration(["relationMap", "tableInfo"], "./__generated__/relationMap").toString()}
2057
-
2058
- export abstract class BaseDBDataSource<
2059
- Entity extends EntityType,
2060
- Identifiable extends object,
2061
- Creatable extends EntityType,
2062
- Updatable extends Identifiable,
2063
- EntityFields extends Fields<Entity>,
2064
- QueryResult extends Partial<Entity> & Identifiable,
2065
- > extends SasatDBDatasource<Entity, Identifiable, Creatable, Updatable, EntityFields, QueryResult> {
2066
- protected relationMap = relationMap;
2067
- protected tableInfo = tableInfo;
2068
- }
2069
- `;
2070
- const staticFiles = [
2071
- {
2072
- name: "context",
2073
- body: contextFile
2074
- },
2075
- {
2076
- name: "pubsub",
2077
- body: pubsubFile
2078
- },
2079
- {
2080
- name: "schema",
2081
- body: schemaFile
2082
- },
2083
- {
2084
- name: "baseDBDataSource",
2085
- body: baseDBDataSourceFile
2086
- }
2087
- ];
2088
- //#endregion
2089
- //#region src/generatorv2/codegen/tscodegen_v2.ts
2090
- var TsCodegen_v2 = class {
2091
- constructor() {
2092
- this.fileExtension = "ts";
2093
- this.generateEntity = (node) => generateEntityFile(node).generate();
2094
- this.generateDatasource = (node) => generateDatasource(node).generate();
2095
- this.generateGeneratedDatasource = (node) => generateAutoGeneratedDatasource(node).generate();
2096
- this.generateGqlTypeDefs = (root) => generateTypeDefs(root).generate();
2097
- this.generateGqlResolver = (root) => generateResolver(root).generate();
2098
- this.generateGqlQuery = (root) => generateQueryResolver(root).generate();
2099
- this.generateGqlMutation = (root) => generateMutationResolver(root).generate();
2100
- this.generateGqlSubscription = (root) => generateSubscription(root).generate();
2101
- this.generateGQLContext = (root) => generateContext(root).generate();
2102
- this.generateFiles = async (root) => {
2103
- return [{
2104
- name: "relationMap",
2105
- body: await generateRelationMap(root).generate()
2106
- }, {
2107
- name: "fields",
2108
- body: await generateFields(root).generate()
2109
- }];
2110
- };
2111
- this.generateOnceFiles = () => {
2112
- return staticFiles;
2113
- };
2114
- this.generateConditions = (root, currentFile) => {
2115
- return generateUserDefinedCondition(root, currentFile);
2116
- };
2117
- this.generateIDEncoders = (root, currentFile) => {
2118
- return generateIDEncoder(root, currentFile);
2119
- };
2120
- this.generateMiddlewares = (root, currentFile) => {
2121
- return generateMiddlewares(root, currentFile);
2122
- };
2123
- }
2124
- };
2125
- //#endregion
2126
- //#region src/generatorv2/parser/makeContextNodes.ts
2127
- const makeContextNodes = (store) => {
2128
- return store.tables.flatMap((table) => {
2129
- return table.gqlOption.mutations.flatMap((mutation) => mutation.contextFields.map((it) => ({
2130
- name: it.contextName || it.column,
2131
- dbtype: table.column(it.column).dataType()
2132
- })));
2133
- });
2134
- };
2135
- //#endregion
2136
- //#region src/generatorv2/parser/makeMutationNodes.ts
2137
- const makeEntityMutationNodes = (table, entity) => {
2138
- if (!table.gqlOption.enabled) return [];
2139
- return table.gqlOption.mutations.map((mutation) => {
2140
- switch (mutation.type) {
2141
- case "create": return makeCreateMutationNode(table, entity, mutation);
2142
- case "update": return makeUpdateMutationNode(table, entity, mutation);
2143
- case "delete": return makeDeleteMutationNode(table, entity, mutation);
2144
- default: throw new Error(`invalid mutation type: ${mutation.type}`);
2145
- }
2146
- });
2147
- };
2148
- const makeContextField = (params) => ({
2149
- fieldName: params.column,
2150
- contextName: params.contextName || params.column
2151
- });
2152
- const makeCreateMutationNode = (table, entity, mutation) => {
2153
- return {
2154
- entity,
2155
- contextFields: mutation.contextFields.map(makeContextField),
2156
- entityName: table.getEntityName(),
2157
- identifyFields: table.getPrimaryKeyColumns().map((it) => it.fieldName()),
2158
- mutationName: `create${table.getEntityName().name}`,
2159
- inputName: entity.name.createInputName(),
2160
- refetch: !mutation.noReFetch,
2161
- returnType: {
2162
- typeName: table.getEntityName().name,
2163
- nullable: false,
2164
- array: false,
2165
- entity: true
2166
- },
2167
- args: [{
2168
- name: table.getEntityName().lowerCase(),
2169
- type: {
2170
- typeName: table.getEntityName().createInputName(),
2171
- nullable: false,
2172
- array: false,
2173
- entity: true
2174
- }
2175
- }],
2176
- mutationType: "create",
2177
- subscription: mutation.subscription.enabled,
2178
- requireIdDecodeMiddleware: entity.creatable.fields.some((it) => it.hashId),
2179
- middlewares: mutation.middlewares
2180
- };
2181
- };
2182
- const makeUpdateMutationNode = (table, entity, mutation) => {
2183
- return {
2184
- entity,
2185
- contextFields: mutation.contextFields.map(makeContextField),
2186
- entityName: table.getEntityName(),
2187
- identifyFields: table.getPrimaryKeyColumns().map((it) => it.fieldName()),
2188
- mutationName: `update${table.getEntityName().name}`,
2189
- inputName: entity.name.updateInputName(),
2190
- refetch: !mutation.noReFetch,
2191
- returnType: {
2192
- typeName: mutation.noReFetch ? "Boolean" : table.getEntityName().name,
2193
- dbType: mutation.noReFetch ? "boolean" : void 0,
2194
- nullable: false,
2195
- array: false,
2196
- entity: !mutation.noReFetch
2197
- },
2198
- args: [{
2199
- name: table.getEntityName().lowerCase(),
2200
- type: {
2201
- typeName: table.getEntityName().updateInputName(),
2202
- nullable: false,
2203
- array: false,
2204
- entity: true
2205
- }
2206
- }],
2207
- mutationType: "update",
2208
- subscription: mutation.subscription.enabled,
2209
- requireIdDecodeMiddleware: entity.updateInput.fields.some((it) => it.hashId),
2210
- middlewares: mutation.middlewares
2211
- };
2212
- };
2213
- const makeDeleteMutationNode = (table, entity, mutation) => {
2214
- return {
2215
- entity,
2216
- mutationName: `delete${table.getEntityName().name}`,
2217
- inputName: entity.name.identifyInputName(),
2218
- contextFields: mutation.contextFields.map(makeContextField),
2219
- entityName: table.getEntityName(),
2220
- identifyFields: table.getPrimaryKeyColumns().map((it) => it.fieldName()),
2221
- refetch: false,
2222
- returnType: {
2223
- typeName: "Boolean",
2224
- dbType: "boolean",
2225
- nullable: false,
2226
- array: false,
2227
- entity: false
2228
- },
2229
- args: [{
2230
- name: table.getEntityName().lowerCase(),
2231
- type: {
2232
- typeName: table.getEntityName().identifyInputName(),
2233
- nullable: false,
2234
- array: false,
2235
- entity: true
2236
- }
2237
- }],
2238
- mutationType: "delete",
2239
- subscription: mutation.subscription.enabled,
2240
- requireIdDecodeMiddleware: entity.identifyFields().some((it) => it.hashId),
2241
- middlewares: mutation.middlewares
2242
- };
2243
- };
2244
- //#endregion
2245
- //#region src/generatorv2/scripts/columnToGqlType.ts
2246
- const columnTypeToGqlPrimitive = (type) => {
2247
- switch (type) {
2248
- case "tinyint":
2249
- case "smallint":
2250
- case "mediumint":
2251
- case "int":
2252
- case "bigint":
2253
- case "decimal":
2254
- case "year": return "Int";
2255
- case "float":
2256
- case "double": return "Float";
2257
- case "char":
2258
- case "varchar":
2259
- case "text":
2260
- case "time":
2261
- case "date":
2262
- case "datetime":
2263
- case "timestamp": return "String";
2264
- case "boolean": return "Boolean";
2265
- }
2266
- };
2267
- //#endregion
2268
- //#region src/generatorv2/nodes/FieldNode.ts
2269
- const getHashId = (store, entity, column) => {
2270
- if (!column.isReference()) {
2271
- if (column.data.option.autoIncrementHashId) return { encoder: entity.IDEncoderName() };
2272
- return;
2273
- }
2274
- const ref = column.data.reference;
2275
- const parent = store.table(ref.parentTable);
2276
- if (!parent.column(ref.parentColumn).data.option.autoIncrementHashId) return void 0;
2277
- return { encoder: parent.getEntityName().IDEncoderName() };
2278
- };
2279
- const makeFieldNode = (store, entity, column) => {
2280
- const hashId = getHashId(store, entity.name, column);
2281
- return {
2282
- entity,
2283
- fieldName: column.fieldName(),
2284
- columnName: column.columnName(),
2285
- gqlType: hashId ? "ID" : column.gqlType(),
2286
- dbType: column.dataType(),
2287
- isAutoIncrement: column.data.autoIncrement,
2288
- isArray: false,
2289
- isPrimary: column.isPrimary(),
2290
- isNullable: column.isNullable(),
2291
- isUpdatable: !(column.data.onUpdateCurrentTimeStamp || column.isPrimary()) && column.data.option.updatable,
2292
- isGQLOpen: true,
2293
- column: column.data,
2294
- option: column.data.option,
2295
- hashId
2296
- };
2297
- };
2298
- const makeCreatableFieldNode = (store, entity, column) => {
2299
- if (column.data.autoIncrement || column.data.defaultCurrentTimeStamp) return null;
2300
- const hashId = getHashId(store, entity.name, column);
2301
- return {
2302
- entity,
2303
- fieldName: column.fieldName(),
2304
- columnName: column.columnName(),
2305
- gqlType: hashId ? "ID" : column.gqlType(),
2306
- dbType: column.dataType(),
2307
- isAutoIncrement: column.data.autoIncrement,
2308
- isArray: false,
2309
- isPrimary: column.isPrimary(),
2310
- isNullable: column.isNullableOnCreate(),
2311
- isUpdatable: column.isUpdatable(),
2312
- isGQLOpen: !(column.table.gqlOption.mutations.find((it) => it.type === "create")?.contextFields || []).some((it) => it.column === column.columnName()),
2313
- column: column.data,
2314
- option: column.data.option,
2315
- hashId: getHashId(store, entity.name, column)
2316
- };
2317
- };
2318
- const makeUpdatableFieldNode = (store, entity, column) => {
2319
- if (!column.isUpdatable() || !column.data.option.updatable) return null;
2320
- const hashId = getHashId(store, entity.name, column);
2321
- return {
2322
- entity,
2323
- fieldName: column.fieldName(),
2324
- columnName: column.columnName(),
2325
- gqlType: hashId ? "ID" : column.gqlType(),
2326
- dbType: column.dataType(),
2327
- isAutoIncrement: column.data.autoIncrement,
2328
- isArray: false,
2329
- isNullable: true,
2330
- isPrimary: false,
2331
- isUpdatable: true,
2332
- isGQLOpen: !(column.table.gqlOption.mutations.find((it) => it.type === "update")?.contextFields || []).some((it) => it.column === column.columnName()),
2333
- column: column.data,
2334
- option: column.data.option,
2335
- hashId: getHashId(store, entity.name, column)
2336
- };
2337
- };
2338
- //#endregion
2339
- //#region src/migration/makeCondition.ts
2340
- const parent = (field) => ({
2341
- kind: "parent",
2342
- field
2343
- });
2344
- const child = (field) => ({
2345
- kind: "child",
2346
- field
2347
- });
2348
- const contextOrError = (field, errorMessage) => ({
2349
- kind: "context",
2350
- field,
2351
- onNotDefined: {
2352
- action: "error",
2353
- message: errorMessage
2354
- }
2355
- });
2356
- const contextOrDefault = (field, defaultValue) => ({
2357
- kind: "context",
2358
- field,
2359
- onNotDefined: {
2360
- action: "defaultValue",
2361
- value: defaultValue
2362
- }
2363
- });
2364
- const fixed = (value) => ({
2365
- kind: "fixed",
2366
- value
2367
- });
2368
- const today = (thresholdHour, date) => ({
2369
- kind: "today",
2370
- type: date ? "date" : "datetime",
2371
- thresholdHour
2372
- });
2373
- const now = () => ({ kind: "now" });
2374
- const values = (begin, end) => ({
2375
- kind: "range",
2376
- begin,
2377
- end
2378
- });
2379
- const betweenToday = (thresholdHour) => ({
2380
- kind: "date-range",
2381
- range: "today",
2382
- thresholdHour
2383
- });
2384
- const custom = (conditionName, parentRequiredFields, childRequiredFields) => ({
2385
- kind: "custom",
2386
- conditionName,
2387
- parentRequiredFields,
2388
- childRequiredFields
2389
- });
2390
- const field$1 = (column) => ({
2391
- kind: "field",
2392
- column
2393
- });
2394
- const arg = (name, type) => ({
2395
- kind: "arg",
2396
- name,
2397
- type
2398
- });
2399
- const betweenRel = (left, range) => ({
2400
- kind: "comparison",
2401
- left,
2402
- operator: "BETWEEN",
2403
- right: range
2404
- });
2405
- const betweenQuery = (left, begin, end) => ({
2406
- kind: "between",
2407
- operator: "BETWEEN",
2408
- left,
2409
- begin,
2410
- end
2411
- });
2412
- const comparisonRel = (left, operator, right) => ({
2413
- kind: "comparison",
2414
- left,
2415
- right,
2416
- operator
2417
- });
2418
- const inRel = (left, right) => ({
2419
- kind: "comparison",
2420
- left,
2421
- right,
2422
- operator: "IN"
2423
- });
2424
- const isNullRel = (value) => ({
2425
- kind: "isNull",
2426
- value,
2427
- not: false
2428
- });
2429
- const isNotNullRel = (value) => ({
2430
- kind: "isNull",
2431
- value,
2432
- not: true
2433
- });
2434
- const comparisonQuery = (left, operator, right) => ({
2435
- kind: "comparison",
2436
- left,
2437
- right,
2438
- operator
2439
- });
2440
- const Conditions = {
2441
- betweenRel,
2442
- betweenQuery,
2443
- custom,
2444
- rel: {
2445
- between: betweenRel,
2446
- comparison: comparisonRel,
2447
- in: inRel,
2448
- isNull: isNullRel,
2449
- isNotNull: isNotNullRel
2450
- },
2451
- query: {
2452
- between: betweenQuery,
2453
- comparison: comparisonQuery
2454
- },
2455
- value: {
2456
- parent,
2457
- child,
2458
- contextOrError,
2459
- contextOrDefault,
2460
- fixed,
2461
- today,
2462
- now,
2463
- field: field$1,
2464
- arg
2465
- },
2466
- range: {
2467
- values,
2468
- today: betweenToday
2469
- }
2470
- };
2471
- //#endregion
2472
- //#region src/generatorv2/nodes/ReferencedNode.ts
2473
- var ReferenceNode = class ReferenceNode {
2474
- static fromReference(entity, column, parentTable) {
2475
- const ref = column.data.reference;
2476
- if (!ref.fieldName) return null;
2477
- return new ReferenceNode(entity, ref.fieldName, column.table.tableName, ref.parentTable, makeJoinCondition(ref.parentColumn, column.columnName()), false, column.isNullable(), column.isPrimary(), column.table.gqlOption.enabled && parentTable.gqlOption.enabled);
2478
- }
2479
- static formVirtualRelation(ds, entity, rel) {
2480
- if (!rel.childFieldName) return null;
2481
- return new ReferenceNode(entity, rel.childFieldName, rel.childTable, rel.parentTable, rel.conditions, rel.childType === void 0 || rel.childType === "array", rel.childType === "nullable", false, ds.table(rel.parentTable).gqlOption.enabled && ds.table(rel.childTable).gqlOption.enabled);
2482
- }
2483
- constructor(entity, fieldName, tableName, parentTableName, joinCondition, isArray, isNullable, isPrimary, isGQLOpen) {
2484
- this.entity = entity;
2485
- this.fieldName = fieldName;
2486
- this.tableName = tableName;
2487
- this.parentTableName = parentTableName;
2488
- this.joinCondition = joinCondition;
2489
- this.isArray = isArray;
2490
- this.isNullable = isNullable;
2491
- this.isPrimary = isPrimary;
2492
- this.isGQLOpen = isGQLOpen;
2493
- }
2494
- };
2495
- var ReferencedNode = class ReferencedNode {
2496
- static fromReference(entity, parentTable, column) {
2497
- const ref = column.data.reference;
2498
- if (!ref.parentFieldName) return null;
2499
- return new ReferencedNode(entity, ref.parentFieldName, column.table.tableName, makeJoinCondition(column.columnName(), ref.parentColumn), ref.relation === "Many", ref.relation === "OneOrZero", column.isPrimary(), parentTable.gqlOption.enabled && column.table.gqlOption.enabled);
2500
- }
2501
- static fromVirtualRelation(ds, entity, rel) {
2502
- if (!rel.parentFieldName) return null;
2503
- return new ReferencedNode(entity, rel.parentFieldName, rel.childTable, rel.conditions.map(reverseConditionNode), rel.parentType === void 0 || rel.parentType === "array", rel.parentType === "nullable", false, ds.table(rel.parentTable).gqlOption.enabled && ds.table(rel.childTable).gqlOption.enabled);
2504
- }
2505
- constructor(entity, fieldName, childTable, joinCondition, isArray, isNullable, isPrimary, isGQLOpen) {
2506
- this.entity = entity;
2507
- this.fieldName = fieldName;
2508
- this.childTable = childTable;
2509
- this.joinCondition = joinCondition;
2510
- this.isArray = isArray;
2511
- this.isNullable = isNullable;
2512
- this.isPrimary = isPrimary;
2513
- this.isGQLOpen = isGQLOpen;
2514
- }
2515
- };
2516
- const reverseConditionValue = (cv) => {
2517
- if (cv.kind === "parent") return {
2518
- ...cv,
2519
- kind: "child"
2520
- };
2521
- else if (cv.kind === "child") return {
2522
- ...cv,
2523
- kind: "parent"
2524
- };
2525
- return cv;
2526
- };
2527
- const reverseRangeCondition = (condition) => {
2528
- if (condition.kind === "range") return {
2529
- kind: condition.kind,
2530
- begin: reverseConditionValue(condition.begin),
2531
- end: reverseConditionValue(condition.end)
2532
- };
2533
- return condition;
2534
- };
2535
- const reverseConditionNode = (condition) => {
2536
- if (condition.kind === "custom") return {
2537
- ...condition,
2538
- parentRequiredFields: condition.childRequiredFields,
2539
- childRequiredFields: condition.parentRequiredFields
2540
- };
2541
- if (condition.kind === "isNull") {
2542
- if (condition.not) return Conditions.rel.isNotNull(reverseConditionValue(condition.value));
2543
- return Conditions.rel.isNull(reverseConditionValue(condition.value));
2544
- }
2545
- if (condition.operator === "BETWEEN") return Conditions.rel.between(reverseConditionValue(condition.left), reverseRangeCondition(condition.right));
2546
- if (condition.operator === "IN") return Conditions.rel.in(reverseConditionValue(condition.left), condition.right.map(reverseConditionValue));
2547
- return Conditions.rel.comparison(reverseConditionValue(condition.right), condition.operator, reverseConditionValue(condition.left));
2548
- };
2549
- const makeJoinCondition = (parentColumn, childColumn) => {
2550
- return [Conditions.rel.comparison(Conditions.value.parent(parentColumn), "=", Conditions.value.child(childColumn))];
2551
- };
2552
- //#endregion
2553
- //#region src/generatorv2/nodes/entityNode.ts
2554
- var EntityNode = class {
2555
- constructor(store, table) {
2556
- this.name = EntityName.fromTableName(table.tableName);
2557
- this.fields = table.columns.map((it) => makeFieldNode(store, this, it));
2558
- this.tableName = table.tableName;
2559
- this.gqlEnabled = table.gqlOption.enabled;
2560
- this.identifyKeys = table.primaryKey;
2561
- this.queries = table.gqlOption.queries;
2562
- this.creatable = {
2563
- gqlEnabled: table.gqlOption.enabled && table.gqlOption.mutations.find((it) => it.type === "create") !== void 0,
2564
- fields: table.columns.map((it) => makeCreatableFieldNode(store, this, it)).filter(nonNullable)
2565
- };
2566
- this.updateInput = {
2567
- gqlEnabled: table.gqlOption.enabled && table.gqlOption.mutations.find((it) => it.type === "update") !== void 0,
2568
- fields: [...this.fields.filter((it) => it.isPrimary), ...table.columns.map((it) => makeUpdatableFieldNode(store, this, it)).filter(nonNullable)]
2569
- };
2570
- this.references = table.getReferenceColumns().map((column) => ReferenceNode.fromReference(this, column, store.table(column.data.reference.parentTable))).concat(table.virtualRelations.map((it) => ReferenceNode.formVirtualRelation(store, this, it))).filter(nonNullable);
2571
- this.referencedBy = store.referencedBy(table.tableName).map((column) => ReferencedNode.fromReference(this, table, column)).concat(store.virtualReferencedBy(table.tableName).map((rel) => ReferencedNode.fromVirtualRelation(store, this, rel))).filter(nonNullable);
2572
- const makeFindMethodNode = (columns, isArray) => {
2573
- const fields = columns.map((column) => this.fields.find((it) => it.columnName === column));
2574
- return {
2575
- name: makeFindQueryName(fields.map((it) => it.fieldName)),
2576
- params: fields.map((it) => makePrimitiveParameterNode(it.fieldName, it.columnName, it.dbType)),
2577
- isArray
2578
- };
2579
- };
2580
- this.findMethods = [makeFindMethodNode(table.primaryKey, false)];
2581
- this.mutations = makeEntityMutationNodes(table, this);
2582
- }
2583
- identifyFields() {
2584
- return this.fields.filter((it) => it.isPrimary);
2585
- }
2586
- primaryQueryName() {
2587
- return makeFindQueryName(this.identifyFields().map((it) => it.fieldName));
2588
- }
2589
- };
2590
- const makePrimitiveParameterNode = (fieldName, columnName, dbtype) => ({
2591
- entity: false,
2592
- fieldName,
2593
- columnName,
2594
- dbtype,
2595
- gqltype: columnTypeToGqlPrimitive(dbtype)
2596
- });
2597
- //#endregion
2598
- //#region src/generatorv2/parser/makeEntityNodes.ts
2599
- const makeEntityNodes = (store) => {
2600
- const make = makeEntityNode(store);
2601
- return store.tables.map(make);
2602
- };
2603
- const makeEntityNode = (store) => (table) => {
2604
- return new EntityNode(store, table);
2605
- };
2606
- //#endregion
2607
- //#region src/generatorv2/parser/makeSubscriptionNode.ts
2608
- const makeSubscriptionNodes = (store) => {
2609
- return store.tables.flatMap((table) => {
2610
- return table.gqlOption.mutations.map((it) => {
2611
- return makeSubscriptionNode(table, it);
2612
- });
2613
- }).filter(nonNullable);
2614
- };
2615
- const subscriptionNamePostfix = {
2616
- create: "Created",
2617
- update: "Updated",
2618
- delete: "Deleted"
2619
- };
2620
- const makeSubscriptionNode = (table, mutation) => {
2621
- if (!mutation.subscription.enabled) return null;
2622
- const subscriptionName = table.getEntityName().name + subscriptionNamePostfix[mutation.type];
2623
- return {
2624
- subscriptionName,
2625
- entity: table.getEntityName(),
2626
- publishFunctionName: "publish" + subscriptionName,
2627
- returnType: {
2628
- typeName: table.getEntityName().name,
2629
- nullable: false,
2630
- array: false,
2631
- entity: true
2632
- },
2633
- args: mutation.subscription.subscriptionFilter.map((it) => {
2634
- const column = table.column(it);
2635
- return {
2636
- name: it,
2637
- type: {
2638
- typeName: column.gqlType(),
2639
- dbType: column.dataType(),
2640
- nullable: false,
2641
- array: false,
2642
- entity: false
2643
- }
2644
- };
2645
- }),
2646
- filters: (mutation.subscription?.subscriptionFilter || []).map((it) => {
2647
- const column = table.column(it);
2648
- return {
2649
- field: column.fieldName(),
2650
- gqlType: column.gqlType()
2651
- };
2652
- }),
2653
- mutationType: mutation.type,
2654
- gqlEnabled: table.gqlOption.enabled && mutation.subscription.enabled
2655
- };
2656
- };
2657
- //#endregion
2658
- //#region src/generatorv2/parse.ts
2659
- const parse = (store) => {
2660
- store.tables.forEach((it) => {
2661
- if (it.primaryKey.length === 0) throw new Error(`Table: ${it.tableName} has no primary key.`);
2662
- });
2663
- return {
2664
- entities: makeEntityNodes(store),
2665
- subscriptions: makeSubscriptionNodes(store),
2666
- contexts: makeContextNodes(store)
2667
- };
2668
- };
2669
- //#endregion
2670
- //#region src/generatorv2/codegen_v2.ts
2671
- var CodeGen_v2 = class {
2672
- constructor(store) {
2673
- this.codeGen = new TsCodegen_v2();
2674
- this.outDir = config().migration.out;
2675
- this.dbDataSourceDir = path$1.join(this.outDir, Directory.paths.DATA_SOURCES);
2676
- this.generateDir = path$1.join(this.outDir, Directory.paths.GENERATED);
2677
- this.generateEntityDir = path$1.join(this.outDir, Directory.paths.ENTITIES);
2678
- this.generateDbDataSourceDir = path$1.join(this.outDir, Directory.paths.GENERATED_DS);
2679
- this.root = parse(store);
2680
- }
2681
- async generate() {
2682
- await this.prepareDirs();
2683
- await Promise.all([
2684
- ...this.root.entities.map((it) => this.generateEntity(it)),
2685
- ...this.root.entities.map((it) => this.generateDatasource(it)),
2686
- ...this.root.entities.map((it) => this.generateGeneratedDatasource(it)),
2687
- this.generateGql(this.root),
2688
- this.generateFiles(this.root),
2689
- ...this.generateOnceFiles(),
2690
- this.generateCondition(this.root),
2691
- this.generateIDEncoders(this.root),
2692
- this.generateMiddleware(this.root)
2693
- ]);
2694
- }
2695
- async prepareDirs() {
2696
- mkDirIfNotExist(this.generateDir);
2697
- await emptyDir(this.generateDir);
2698
- mkDirIfNotExist(this.generateEntityDir);
2699
- mkDirIfNotExist(this.generateDbDataSourceDir);
2700
- mkDirIfNotExist(this.dbDataSourceDir);
2701
- }
2702
- getFullPath(basePath, entityName) {
2703
- return path$1.join(basePath, `${entityName}.${this.codeGen.fileExtension}`);
2704
- }
2705
- async generateEntity(node) {
2706
- return writeFile(this.getFullPath(this.generateEntityDir, node.name.name), await this.codeGen.generateEntity(node));
2707
- }
2708
- async generateDatasource(node) {
2709
- return writeFileIfNotExist(this.getFullPath(this.dbDataSourceDir, node.name.name), await this.codeGen.generateDatasource(node));
2710
- }
2711
- async generateGeneratedDatasource(node) {
2712
- return writeFile(this.getFullPath(this.generateDbDataSourceDir, node.name.name), await this.codeGen.generateGeneratedDatasource(node));
2713
- }
2714
- async generateGql(rootNode) {
2715
- return Promise.all([
2716
- writeFile(this.getFullPath(this.generateDir, "typeDefs"), await this.codeGen.generateGqlTypeDefs(rootNode)),
2717
- writeFile(this.getFullPath(this.generateDir, "resolver"), await this.codeGen.generateGqlResolver(rootNode)),
2718
- writeFile(this.getFullPath(this.generateDir, "query"), await this.codeGen.generateGqlQuery(rootNode)),
2719
- writeFile(this.getFullPath(this.generateDir, "mutation"), await this.codeGen.generateGqlMutation(rootNode)),
2720
- writeFile(this.getFullPath(this.generateDir, "subscription"), await this.codeGen.generateGqlSubscription(rootNode)),
2721
- writeFile(this.getFullPath(this.generateDir, "context"), await this.codeGen.generateGQLContext(rootNode))
2722
- ]);
2723
- }
2724
- async generateFiles(rootNode) {
2725
- const files = await this.codeGen.generateFiles(rootNode);
2726
- return Promise.all(files.map((it) => writeFileIfNotExist(this.getFullPath(this.generateDir, it.name), it.body)));
2727
- }
2728
- generateOnceFiles() {
2729
- return this.codeGen.generateOnceFiles().map((it) => writeFileIfNotExist(this.getFullPath(this.outDir, it.name), it.body));
2730
- }
2731
- async generateCondition(rootNode) {
2732
- const filePath = this.getFullPath(this.outDir, tsFileNames.conditions);
2733
- const content = existsSync(filePath) ? readFileSync(filePath).toString() : "";
2734
- const nextContent = this.codeGen.generateConditions(rootNode, content);
2735
- if (nextContent) writeFileSync(filePath, nextContent);
2736
- }
2737
- async generateIDEncoders(rootNode) {
2738
- const filePath = this.getFullPath(this.outDir, tsFileNames.encoder);
2739
- const content = existsSync(filePath) ? readFileSync(filePath).toString() : "";
2740
- const nextContent = this.codeGen.generateIDEncoders(rootNode, content);
2741
- if (nextContent) writeFileSync(filePath, nextContent);
2742
- }
2743
- async generateMiddleware(rootNode) {
2744
- const filePath = this.getFullPath(this.outDir, tsFileNames.middleware);
2745
- const content = existsSync(filePath) ? readFileSync(filePath).toString() : "";
2746
- const nextContent = this.codeGen.generateMiddlewares(rootNode, content);
2747
- if (nextContent) writeFileSync(filePath, nextContent);
2748
- }
2749
- };
2750
- //#endregion
2751
- //#region src/migration/exec/getMigrationFiles.ts
2752
- const getMigrationFileDir = () => {
2753
- return path.join(process.cwd(), config().migration.dir);
2754
- };
2755
- const getMigrationFileNames = () => {
2756
- return fs.readdirSync(getMigrationFileDir()).filter((it) => it.split(".").pop() === "ts");
2757
- };
2758
- //#endregion
2759
- //#region src/error.ts
2760
- var SasatError = class extends Error {
2761
- constructor(message) {
2762
- super(message);
2763
- Object.setPrototypeOf(this, new.target.prototype);
2764
- this.name = "SasatError";
2765
- }
2766
- };
2767
- //#endregion
2768
- //#region src/runtime/sql/sqlString.ts
2769
- const { escape, escapeId: escapeId$1 } = pkg;
2770
- const SqlString = {
2771
- escape: (value) => escape(value, true),
2772
- escapeId: (name) => escapeId$1(name)
2773
- };
2774
- //#endregion
2775
- //#region src/db/sql/columnToSql.ts
2776
- const columnToSql = (column) => {
2777
- const words = [SqlString.escapeId(column.columnName), column.type];
2778
- if (column.length) words.push(`(${[column.length, column.scale].filter((it) => it !== void 0).join(",")})`);
2779
- if (column.signed === true) words.push("SIGNED");
2780
- else if (column.signed === false) words.push("UNSIGNED");
2781
- if (column.zerofill) words.push("ZEROFILL");
2782
- if (column.autoIncrement) words.push("AUTO_INCREMENT");
2783
- if (column.notNull) words.push("NOT NULL");
2784
- else if (!column.notNull) words.push("NULL");
2785
- if ((column.type === "timestamp" || column.type === "datetime") && column.default === "CURRENT_TIMESTAMP") words.push("DEFAULT CURRENT_TIMESTAMP");
2786
- else if (column.default !== void 0) words.push("DEFAULT " + SqlString.escape(column.default));
2787
- if (column.onUpdateCurrentTimeStamp) words.push("ON UPDATE CURRENT_TIMESTAMP");
2788
- return words.join(" ");
2789
- };
2790
- //#endregion
2791
- //#region src/migration/serializable/column.ts
2792
- var BaseColumn = class {
2793
- constructor(data, table) {
2794
- this.data = data;
2795
- this.table = table;
2796
- }
2797
- fieldName() {
2798
- return this.data.fieldName;
2799
- }
2800
- columnName() {
2801
- return this.data.columnName;
2802
- }
2803
- dataType() {
2804
- return this.data.type;
2805
- }
2806
- tsType() {
2807
- return columnTypeToTsType(this.dataType());
2808
- }
2809
- gqlType() {
2810
- return columnTypeToGqlPrimitive(this.dataType());
2811
- }
2812
- isNullable() {
2813
- return !this.data.notNull;
2814
- }
2815
- isNullableOnCreate() {
2816
- return !this.data.notNull || this.data.default !== void 0 || this.data.autoIncrement;
2817
- }
2818
- isReference() {
2819
- return this.data.hasReference;
2820
- }
2821
- serialize() {
2822
- return JSON.parse(JSON.stringify(this.data));
2823
- }
2824
- toSql() {
2825
- return columnToSql(this.data);
2826
- }
2827
- isPrimary() {
2828
- return this.table.primaryKey.includes(this.columnName());
2829
- }
2830
- isUpdatable() {
2831
- return !(this.isPrimary() || this.data.onUpdateCurrentTimeStamp);
2832
- }
2833
- };
2834
- var NormalColumn = class extends BaseColumn {
2835
- constructor(data, table) {
2836
- super(data, table);
2837
- this.data = data;
2838
- }
2839
- addReference(reference) {
2840
- return new ReferenceColumn({
2841
- ...this.data,
2842
- hasReference: true,
2843
- reference
2844
- }, this.table);
2845
- }
2846
- };
2847
- var ReferenceColumn = class extends BaseColumn {
2848
- constructor(data, table) {
2849
- super(data, table);
2850
- this.data = data;
2851
- }
2852
- getConstraintName() {
2853
- return `ref_${this.table.tableName}_${this.fieldName()}__${this.data.reference.parentTable}_${this.data.reference.parentColumn}`;
2854
- }
2855
- };
2856
- //#endregion
2857
- //#region src/migration/data/index.ts
2858
- var DBIndex = class {
2859
- constructor(tableName, columns) {
2860
- this.tableName = tableName;
2861
- this.columns = columns;
2862
- this.constraintName = this.toConstraintName(columns);
2863
- }
2864
- toConstraintName(columns) {
2865
- return `index_${this.tableName}__${columns.join("_")}`;
2866
- }
2867
- addSql() {
2868
- return `ALTER TABLE ${this.tableName} ADD INDEX ${this.constraintName}(${this.columns.join(",")})`;
2869
- }
2870
- dropSql() {
2871
- return `DROP INDEX ${this.constraintName} ON ${this.tableName}`;
2872
- }
2873
- serialize() {
2874
- return {
2875
- constraintName: this.constraintName,
2876
- columns: this.columns
2877
- };
2878
- }
2879
- };
2880
- //#endregion
2881
- //#region src/migration/functions/assembleColumn.ts
2882
- const assembleColumn = (data, table) => {
2883
- if (data.hasReference) return new ReferenceColumn(data, table);
2884
- return new NormalColumn(data, table);
2885
- };
2886
- //#endregion
2887
- //#region src/migration/serialized/serializedColumn.ts
2888
- const defaultColumnOption = {
2889
- updatable: true,
2890
- autoIncrementHashId: false
2891
- };
2892
- const referenceToSql = (constraintName, ref) => {
2893
- const onUpdate = ref.onUpdate ? ` ON UPDATE ${ref.onUpdate}` : "";
2894
- const onDelete = ref.onDelete ? ` ON DELETE ${ref.onDelete}` : "";
2895
- return `CONSTRAINT ${constraintName} FOREIGN KEY(${ref.columnName}) REFERENCES ${SqlString.escapeId(ref.parentTable)}(${SqlString.escapeId(ref.parentColumn)})` + onUpdate + onDelete;
2896
- };
2897
- //#endregion
2898
- //#region src/migration/serializable/table.ts
2899
- var TableHandler = class {
2900
- get index() {
2901
- return this.indexes;
2902
- }
2903
- get columns() {
2904
- return this._columns;
2905
- }
2906
- get virtualRelations() {
2907
- return this._virtualRelations;
2908
- }
2909
- addVirtualRelation(relation) {
2910
- this._virtualRelations.push({
2911
- ...relation,
2912
- childTable: this.tableName
2913
- });
2914
- }
2915
- get gqlOption() {
2916
- return this._gqlOption;
2917
- }
2918
- constructor(table, store) {
2919
- this.store = store;
2920
- this._gqlOption = defaultGQLOption();
2921
- this.tableName = table.tableName;
2922
- this.primaryKey = table.primaryKey || [];
2923
- this.uniqueKeys = table.uniqueKeys || [];
2924
- this.indexes = table.indexes?.map((it) => new DBIndex(this.tableName, it.columns)) || [];
2925
- this._gqlOption = table.gqlOption || defaultGQLOption();
2926
- this._columns = (table.columns || []).map((it) => assembleColumn(it, this));
2927
- this._virtualRelations = table.virtualRelations || [];
2928
- }
2929
- column(columnName) {
2930
- const column = this.columns.find((it) => it.columnName() === columnName);
2931
- if (!column) throw new Error(`${this.tableName}.${columnName} is Not Found`);
2932
- return column;
2933
- }
2934
- addColumn(column, isPrimary = false, isUnique = false) {
2935
- this.columns.push(column);
2936
- if (isPrimary) this.setPrimaryKey(column.columnName());
2937
- if (isUnique) this.addUniqueKey(column.columnName());
2938
- }
2939
- dropColumn(columnName) {
2940
- this._columns = this._columns.filter((it) => it.fieldName() !== columnName);
2941
- }
2942
- serialize() {
2943
- return {
2944
- columns: this.columns.map((it) => it.serialize()),
2945
- primaryKey: this.primaryKey,
2946
- uniqueKeys: this.uniqueKeys,
2947
- indexes: this.indexes,
2948
- tableName: this.tableName,
2949
- gqlOption: JSON.parse(JSON.stringify(this.gqlOption)),
2950
- virtualRelations: this._virtualRelations
2951
- };
2952
- }
2953
- addReferences(ref, fieldName, notNull = true) {
2954
- const data = {
2955
- ...this.store.table(ref.parentTable).column(ref.parentColumn).serialize(),
2956
- hasReference: true,
2957
- fieldName: fieldName || ref.columnName,
2958
- columnName: ref.columnName,
2959
- notNull,
2960
- default: void 0,
2961
- zerofill: false,
2962
- autoIncrement: false,
2963
- defaultCurrentTimeStamp: false,
2964
- onUpdateCurrentTimeStamp: false,
2965
- reference: ref
2966
- };
2967
- this.columns.push(new ReferenceColumn(data, this));
2968
- return this;
2969
- }
2970
- getIndexConstraintName(columns) {
2971
- return `index_${this.tableName}__${columns.join("_")}`;
2972
- }
2973
- addIndex(...columns) {
2974
- this.indexes.push(new DBIndex(this.tableName, columns));
2975
- return this;
2976
- }
2977
- removeIndex(...columns) {
2978
- const constraint = this.getIndexConstraintName(columns);
2979
- this.indexes = this.indexes.filter((it) => it.constraintName !== constraint);
2980
- return this;
2981
- }
2982
- addUniqueKey(...columnNames) {
2983
- if (columnNames.length === 0) throw new SasatError("No column name specified");
2984
- this.uniqueKeys.push(columnNames);
2985
- return this;
2986
- }
2987
- setPrimaryKey(...columnNames) {
2988
- if (columnNames.length === 0) throw new Error("Primary key is required");
2989
- this.primaryKey = columnNames;
2990
- return this;
2991
- }
2992
- showCreateTable() {
2993
- const rows = [...this.columns.map((it) => it.toSql())];
2994
- if (this.primaryKey.length !== 0) rows.push(`PRIMARY KEY (${this.primaryKey.map(SqlString.escapeId).join(",")})`);
2995
- this.uniqueKeys.forEach((it) => {
2996
- if (this.uniqueKeys.length !== 0) rows.push(`UNIQUE KEY (${it.join(",")})`);
2997
- });
2998
- rows.push(...this._columns.filter((it) => it.isReference() && !it.data.reference.noFKey).map((it) => {
2999
- const ref = it;
3000
- return referenceToSql(ref.getConstraintName(), ref.data.reference);
3001
- }));
3002
- return `CREATE TABLE ${SqlString.escapeId(this.tableName)}
3003
- (
3004
- ${rows.join(", ")}
3005
- )`;
3006
- }
3007
- hasColumn(columnName) {
3008
- return !!this.columns.find((it) => it.columnName() === columnName);
3009
- }
3010
- isColumnPrimary(columnName) {
3011
- return this.primaryKey.includes(columnName);
3012
- }
3013
- getEntityName() {
3014
- return EntityName.fromTableName(this.tableName);
3015
- }
3016
- setGQLOption(option) {
3017
- this._gqlOption = {
3018
- ...this.gqlOption,
3019
- ...option
3020
- };
3021
- }
3022
- getReferenceColumns() {
3023
- return this.columns.filter((it) => it.isReference());
3024
- }
3025
- addForeignKey(reference) {
3026
- const columnName = reference.columnName;
3027
- const column1 = this.column(columnName);
3028
- if (!column1) throw new Error("Column: `" + columnName + "` Not Found");
3029
- if (column1.isReference()) throw new Error("Column: `" + columnName + "`already has reference, multiple reference is not supported");
3030
- const ref = column1.addReference(reference);
3031
- this._columns = this.columns.map((it) => it.columnName() === columnName ? ref : it);
3032
- }
3033
- changeType(columnName, type) {
3034
- this.updateColumn(columnName, { type });
3035
- }
3036
- setDefault(columnName, value) {
3037
- this.updateColumn(columnName, { default: value });
3038
- }
3039
- updateColumn(columnName, diff) {
3040
- const update = (column) => {
3041
- if (column.isReference()) return new ReferenceColumn({
3042
- ...column.serialize(),
3043
- ...diff
3044
- }, this);
3045
- return new NormalColumn({
3046
- ...column.serialize(),
3047
- ...diff
3048
- }, this);
3049
- };
3050
- if (!this.column(columnName)) throw new Error(this.tableName + "." + columnName + " Not Found");
3051
- this._columns = this.columns.map((it) => it.columnName() === columnName ? update(it) : it);
3052
- }
3053
- getPrimaryKeyColumns() {
3054
- return this.columns.filter((it) => this.primaryKey.includes(it.columnName()));
3055
- }
3056
- };
3057
- //#endregion
3058
- //#region src/migration/creators/columnBuilder.ts
3059
- var ColumnBuilderBase = class {
3060
- constructor(columnName) {
3061
- this.columnName = columnName;
3062
- this._primary = false;
3063
- this._notNull = true;
3064
- this._unique = false;
3065
- this._option = defaultColumnOption;
3066
- this._fieldName = columnName;
3067
- }
3068
- fieldName(fieldName) {
3069
- this._fieldName = fieldName;
3070
- return this;
3071
- }
3072
- notNull() {
3073
- this._notNull = true;
3074
- return this;
3075
- }
3076
- nullable() {
3077
- this._notNull = false;
3078
- return this;
3079
- }
3080
- primary() {
3081
- this._primary = true;
3082
- return this;
3083
- }
3084
- unique() {
3085
- this._unique = true;
3086
- return this;
3087
- }
3088
- updatable(updatable) {
3089
- this._option = {
3090
- ...this._option,
3091
- updatable
3092
- };
3093
- return this;
3094
- }
3095
- };
3096
- var ColumnBuilder = class extends ColumnBuilderBase {
3097
- constructor(name, type, length, scale) {
3098
- super(name);
3099
- this.type = type;
3100
- this.length = length;
3101
- this.scale = scale;
3102
- this._zerofill = false;
3103
- this._autoIncrement = false;
3104
- this._defaultCurrentTimeStamp = false;
3105
- this._onUpdateCurrentTimeStamp = false;
3106
- this._fieldName = name;
3107
- }
3108
- default(value) {
3109
- this._default = value;
3110
- return this;
3111
- }
3112
- build() {
3113
- return {
3114
- data: {
3115
- hasReference: false,
3116
- columnName: this.columnName,
3117
- fieldName: this._fieldName,
3118
- type: this.type,
3119
- length: this.length,
3120
- scale: this.scale,
3121
- notNull: this._notNull,
3122
- zerofill: this._zerofill,
3123
- signed: this._signed,
3124
- autoIncrement: this._autoIncrement,
3125
- default: this._default,
3126
- defaultCurrentTimeStamp: this._defaultCurrentTimeStamp,
3127
- onUpdateCurrentTimeStamp: this._onUpdateCurrentTimeStamp,
3128
- option: this._option
3129
- },
3130
- isPrimary: this._primary,
3131
- isUnique: this._unique
3132
- };
3133
- }
3134
- };
3135
- var StringColumnBuilder = class extends ColumnBuilder {
3136
- constructor(name, type, length) {
3137
- super(name, type);
3138
- this.name = name;
3139
- this.type = type;
3140
- this.length = length;
3141
- }
3142
- default(value) {
3143
- this._default = value;
3144
- return this;
3145
- }
3146
- };
3147
- var TextColumnBuilder = class extends ColumnBuilder {
3148
- constructor(name, type) {
3149
- super(name, type);
3150
- this.name = name;
3151
- this.type = type;
3152
- }
3153
- default(value) {
3154
- this._default = value;
3155
- return this;
3156
- }
3157
- };
3158
- var NumberColumnBuilder = class extends ColumnBuilder {
3159
- signed() {
3160
- this._signed = true;
3161
- return this;
3162
- }
3163
- unsigned() {
3164
- this._signed = false;
3165
- return this;
3166
- }
3167
- zerofill() {
3168
- this._zerofill = true;
3169
- return this;
3170
- }
3171
- default(value) {
3172
- this._default = value;
3173
- return this;
3174
- }
3175
- };
3176
- var IntegerColumnBuilder = class extends NumberColumnBuilder {
3177
- constructor(name, type, length) {
3178
- super(name, type, length);
3179
- this.name = name;
3180
- this.type = type;
3181
- this.length = length;
3182
- }
3183
- autoIncrement() {
3184
- this._autoIncrement = true;
3185
- return this;
3186
- }
3187
- };
3188
- var FloatColumnBuilder = class extends NumberColumnBuilder {
3189
- constructor(name, type, length, scale) {
3190
- super(name, type, length, scale);
3191
- this.name = name;
3192
- this.type = type;
3193
- this.length = length;
3194
- this.scale = scale;
3195
- }
3196
- autoIncrement() {
3197
- this._autoIncrement = true;
3198
- return this;
3199
- }
3200
- };
3201
- var DecimalColumnBuilder = class extends NumberColumnBuilder {
3202
- constructor(name, type, length, scale) {
3203
- super(name, type, length, scale);
3204
- this.name = name;
3205
- this.type = type;
3206
- this.length = length;
3207
- this.scale = scale;
3208
- }
3209
- };
3210
- var DateColumnBuilder = class extends ColumnBuilder {
3211
- constructor(name, type) {
3212
- super(name, type);
3213
- this.name = name;
3214
- this.type = type;
3215
- }
3216
- default(value) {
3217
- this._default = value;
3218
- return this;
3219
- }
3220
- };
3221
- var TimeStampColumnBuilder = class extends ColumnBuilder {
3222
- constructor(name, type) {
3223
- super(name, type);
3224
- this.name = name;
3225
- this.type = type;
3226
- }
3227
- default(value) {
3228
- this._default = value;
3229
- return this;
3230
- }
3231
- defaultCurrentTimeStamp() {
3232
- this._defaultCurrentTimeStamp = true;
3233
- return this.default("CURRENT_TIMESTAMP");
3234
- }
3235
- onUpdateCurrentTimeStamp() {
3236
- this._onUpdateCurrentTimeStamp = true;
3237
- return this;
3238
- }
3239
- };
3240
- var ReferenceColumnBuilder = class extends ColumnBuilderBase {
3241
- constructor(ref, parent) {
3242
- super(ref.columnName);
3243
- this.ref = ref;
3244
- this.parent = parent;
3245
- this._option = {
3246
- ...this._option,
3247
- updatable: false
3248
- };
3249
- }
3250
- notNull() {
3251
- this._notNull = true;
3252
- return this;
3253
- }
3254
- nullable() {
3255
- this._notNull = false;
3256
- return this;
3257
- }
3258
- primary() {
3259
- this._primary = true;
3260
- return this;
3261
- }
3262
- unique() {
3263
- this._unique = true;
3264
- return this;
3265
- }
3266
- build() {
3267
- return {
3268
- data: {
3269
- ...this.parent.serialize(),
3270
- hasReference: true,
3271
- fieldName: this._fieldName,
3272
- columnName: this.columnName,
3273
- notNull: this._notNull,
3274
- default: void 0,
3275
- autoIncrement: false,
3276
- defaultCurrentTimeStamp: false,
3277
- onUpdateCurrentTimeStamp: false,
3278
- reference: this.ref,
3279
- option: this._option
3280
- },
3281
- isPrimary: this._primary,
3282
- isUnique: this._unique
3283
- };
3284
- }
3285
- };
3286
- var AutoIncrementIDColumnBuilder = class extends ColumnBuilderBase {
3287
- constructor(columnName, option) {
3288
- super(columnName);
3289
- this.option = option;
3290
- this._option = {
3291
- ...this._option,
3292
- updatable: false,
3293
- autoIncrementHashId: true,
3294
- hashSalt: option?.salt
3295
- };
3296
- }
3297
- build() {
3298
- return {
3299
- data: {
3300
- hasReference: false,
3301
- fieldName: this._fieldName,
3302
- columnName: this.columnName,
3303
- type: this.option?.bigint ? "bigint" : "int",
3304
- notNull: true,
3305
- default: void 0,
3306
- zerofill: false,
3307
- signed: false,
3308
- autoIncrement: true,
3309
- length: void 0,
3310
- scale: void 0,
3311
- defaultCurrentTimeStamp: false,
3312
- onUpdateCurrentTimeStamp: false,
3313
- option: this._option
3314
- },
3315
- isPrimary: true,
3316
- isUnique: false
3317
- };
3318
- }
3319
- };
3320
- //#endregion
3321
- //#region src/migration/creators/columnCreator.ts
3322
- var ColumnCreator = class {
3323
- constructor(table, name) {
3324
- this.table = table;
3325
- this.name = name;
3326
- this.char = (length) => this.create(new StringColumnBuilder(this.name, "char", length));
3327
- this.varchar = (length) => this.create(new StringColumnBuilder(this.name, "varchar", length));
3328
- this.text = () => this.create(new TextColumnBuilder(this.name, "text"));
3329
- this.tinyInt = (length) => this.create(new IntegerColumnBuilder(this.name, "tinyint", length));
3330
- this.smallInt = (length) => this.create(new IntegerColumnBuilder(this.name, "smallint", length));
3331
- this.mediumInt = (length) => this.create(new IntegerColumnBuilder(this.name, "mediumint", length));
3332
- this.int = (length) => this.create(new IntegerColumnBuilder(this.name, "int", length));
3333
- this.bigInt = (length) => this.create(new IntegerColumnBuilder(this.name, "bigint", length));
3334
- this.float = (length, scale) => this.create(new FloatColumnBuilder(this.name, "float", length, scale));
3335
- this.double = (length, scale) => this.create(new FloatColumnBuilder(this.name, "double", length, scale));
3336
- this.decimal = (length, scale) => this.create(new DecimalColumnBuilder(this.name, "decimal", length, scale));
3337
- this.year = () => this.create(new DateColumnBuilder(this.name, "year"));
3338
- this.date = () => this.create(new DateColumnBuilder(this.name, "date"));
3339
- this.time = () => this.create(new DateColumnBuilder(this.name, "time"));
3340
- this.dateTime = () => this.create(new TimeStampColumnBuilder(this.name, "datetime"));
3341
- this.timestamp = () => this.create(new TimeStampColumnBuilder(this.name, "timestamp"));
3342
- }
3343
- create(column) {
3344
- this.table.addColumn(column);
3345
- return column;
3346
- }
3347
- };
3348
- //#endregion
3349
- //#region src/migration/creators/tableCreator.ts
3350
- var TableCreator = class {
3351
- constructor(tableName, store) {
3352
- this.tableName = tableName;
3353
- this.store = store;
3354
- this.columns = [];
3355
- this.table = new TableHandler({ tableName }, store);
3356
- }
3357
- autoIncrementHashId(columnName, option) {
3358
- this.addColumn(new AutoIncrementIDColumnBuilder(columnName, option));
3359
- return this;
3360
- }
3361
- column(name) {
3362
- return new ColumnCreator(this, name);
3363
- }
3364
- addVirtualRelation(relation) {
3365
- this.table.addVirtualRelation(relation);
3366
- return this;
3367
- }
3368
- addColumn(column) {
3369
- if (this.table.hasColumn(column.columnName)) throw new Error(`${this.tableName}.${column.columnName} already exists`);
3370
- this.columns.push(column);
3371
- }
3372
- addUniqueKey(...columnNames) {
3373
- this.table.addUniqueKey(...columnNames);
3374
- return this;
3375
- }
3376
- references(ref) {
3377
- const column = new ReferenceColumnBuilder(ref, this.store.table(ref.parentTable).column(ref.parentColumn));
3378
- this.addColumn(column);
3379
- return column;
3380
- }
3381
- setPrimaryKey(...columnNames) {
3382
- this.table.setPrimaryKey(...columnNames);
3383
- return this;
3384
- }
3385
- create() {
3386
- this.columns.forEach((column) => {
3387
- const { data, isPrimary, isUnique } = column.build();
3388
- this.table.addColumn(data.hasReference ? new ReferenceColumn(data, this.table) : new NormalColumn(data, this.table), isPrimary, isUnique);
3389
- });
3390
- return this.table;
3391
- }
3392
- createdAt() {
3393
- this.column("createdAt").timestamp().defaultCurrentTimeStamp().notNull().updatable(false);
3394
- return this;
3395
- }
3396
- updatedAt() {
3397
- this.column("updatedAt").timestamp().defaultCurrentTimeStamp().onUpdateCurrentTimeStamp().notNull().updatable(false);
3398
- return this;
3399
- }
3400
- addIndex(...columns) {
3401
- this.table.addIndex(`index_${this.tableName}__${columns.join("_")}`, ...columns);
3402
- return this;
3403
- }
3404
- enableGQL() {
3405
- this.table.setGQLOption({
3406
- ...this.table.gqlOption,
3407
- enabled: true
3408
- });
3409
- return this;
3410
- }
3411
- setGQLOption(option) {
3412
- this.table.setGQLOption(option);
3413
- return this;
3414
- }
3415
- addGQLQuery(...query) {
3416
- this.table.setGQLOption({ queries: [...this.table.gqlOption.queries, ...query] });
3417
- return this;
3418
- }
3419
- addGQLMutation(...mutation) {
3420
- this.table.setGQLOption({ mutations: [...this.table.gqlOption.mutations, ...mutation] });
3421
- return this;
3422
- }
3423
- };
3424
- //#endregion
3425
- //#region src/db/sql/sqlCreater.ts
3426
- const SqlCreator = {
3427
- addColumn: (tableName, column) => `ALTER TABLE ${tableName} ADD COLUMN ${columnToSql(column)}`,
3428
- dropColumn: (tableName, columnName) => `ALTER TABLE ${tableName} DROP COLUMN ${columnName}`,
3429
- addUniqueKey: (tableName, columns) => `ALTER TABLE ${tableName} ADD UNIQUE ${columns.join("__")}(${columns.join(",")})`,
3430
- addPrimaryKey: (tableName, columns) => `ALTER TABLE ${tableName} ADD PRIMARY KEY ${columns.join("__")}(${columns.join(",")})`,
3431
- addForeignKey: (tableName, constraintName, reference) => {
3432
- const onUpdate = reference.onUpdate ? " ON UPDATE " + reference.onUpdate : "";
3433
- const onDelete = reference.onDelete ? " ON DELETE " + reference.onDelete : "";
3434
- return `ALTER TABLE ${tableName} ADD CONSTRAINT '${constraintName}' FOREIGN KEY (${reference.columnName}) REFERENCES ${reference.parentTable}(${reference.parentColumn})${onUpdate}${onDelete}`;
3435
- }
3436
- };
3437
- //#endregion
3438
- //#region src/migration/creators/createColumn.ts
3439
- const createColumn = (name) => ({
3440
- char: (length) => new StringColumnBuilder(name, "char", length),
3441
- varchar: (length) => new StringColumnBuilder(name, "varchar", length),
3442
- text: () => new TextColumnBuilder(name, "text"),
3443
- tinyInt: (length) => new IntegerColumnBuilder(name, "tinyint", length),
3444
- smallInt: (length) => new IntegerColumnBuilder(name, "smallint", length),
3445
- mediumInt: (length) => new IntegerColumnBuilder(name, "mediumint", length),
3446
- int: (length) => new IntegerColumnBuilder(name, "int", length),
3447
- bigInt: (length) => new IntegerColumnBuilder(name, "bigint", length),
3448
- float: (length, scale) => new FloatColumnBuilder(name, "float", length, scale),
3449
- double: (length, scale) => new FloatColumnBuilder(name, "double", length, scale),
3450
- decimal: (length, scale) => new DecimalColumnBuilder(name, "decimal", length, scale),
3451
- year: () => new DateColumnBuilder(name, "year"),
3452
- date: () => new DateColumnBuilder(name, "date"),
3453
- time: () => new DateColumnBuilder(name, "time"),
3454
- dateTime: () => new TimeStampColumnBuilder(name, "datetime"),
3455
- timestamp: () => new TimeStampColumnBuilder(name, "timestamp")
3456
- });
3457
- //#endregion
3458
- //#region src/migration/front/tableMigrator.ts
3459
- var TableMigrator = class TableMigrator {
3460
- constructor(table, store) {
3461
- this.table = table;
3462
- this.store = store;
3463
- }
3464
- get primaryKey() {
3465
- return this.table.primaryKey;
3466
- }
3467
- static deserialize(data, store) {
3468
- return new TableMigrator(new TableHandler(data, store), store);
3469
- }
3470
- get tableName() {
3471
- return this.table.tableName;
3472
- }
3473
- column(columnName) {
3474
- return this.table.column(columnName);
3475
- }
3476
- showCreateTable() {
3477
- return this.table.showCreateTable();
3478
- }
3479
- getIndexes() {
3480
- return this.table.index;
3481
- }
3482
- serialize() {
3483
- return this.table.serialize();
3484
- }
3485
- addIndex(...columns) {
3486
- this.table.addIndex(...columns);
3487
- const index = new DBIndex(this.tableName, columns);
3488
- this.store.addQuery(index.addSql());
3489
- return this;
3490
- }
3491
- removeIndex(...columns) {
3492
- this.table.removeIndex(...columns);
3493
- this.store.addQuery(new DBIndex(this.tableName, columns).dropSql());
3494
- return this;
3495
- }
3496
- _addColumn(column) {
3497
- this.table.addColumn(new NormalColumn(column, this.table));
3498
- this.store.addQuery(SqlCreator.addColumn(this.tableName, column));
3499
- return this;
3500
- }
3501
- addColumn(name, create) {
3502
- const column = create(createColumn(name)).build();
3503
- return this._addColumn(column.data);
3504
- }
3505
- dropColumn(columnName) {
3506
- this.table.dropColumn(columnName);
3507
- this.store.addQuery(SqlCreator.dropColumn(this.tableName, columnName));
3508
- return this;
3509
- }
3510
- enableGQL() {
3511
- this.table.setGQLOption({
3512
- ...this.table.gqlOption,
3513
- enabled: true
3514
- });
3515
- return this;
3516
- }
3517
- setGQLOption(option) {
3518
- this.table.setGQLOption(option);
3519
- return this;
3520
- }
3521
- addForeignKey(reference) {
3522
- this.tableExists(reference.parentTable);
3523
- this.table.addForeignKey(reference);
3524
- const column = this.table.column(reference.columnName);
3525
- const targetColumn = this.store.table(reference.parentTable).column(reference.parentColumn);
3526
- if (!targetColumn) throw new Error("Column: " + reference.parentTable + "." + reference.parentColumn + " Not Exists");
3527
- if (column.dataType() !== targetColumn.dataType()) throw new Error(`${this.tableName}.${reference.columnName} AND ${reference.parentTable}.${reference.parentColumn} is different Type( ${column.dataType()} != ${targetColumn.dataType()} )`);
3528
- this.store.addQuery(SqlCreator.addForeignKey(this.tableName, column.getConstraintName(), reference));
3529
- return this;
3530
- }
3531
- changeColumnType(columnName, type) {
3532
- this.table.changeType(columnName, type);
3533
- this.store.addQuery(`ALTER TABLE ${this.tableName} MODIFY ${columnName} ${type}`);
3534
- return this;
3535
- }
3536
- tableExists(tableName) {
3537
- if (!this.store.table(tableName)) throw new Error("QueryTable: " + tableName + " Not Exists");
3538
- return true;
3539
- }
3540
- setDefault(columnName, value) {
3541
- this.table.setDefault(columnName, value);
3542
- this.store.addQuery(`ALTER TABLE ${this.tableName} ALTER ${columnName} SET DEFAULT ${SqlString.escape(value)}`);
3543
- return this;
3544
- }
3545
- get gqlOption() {
3546
- return this.table.gqlOption;
3547
- }
3548
- addGQLQuery(...queries) {
3549
- this.table.setGQLOption({
3550
- ...this.table.gqlOption,
3551
- queries: [...this.table.gqlOption.queries, ...queries]
3552
- });
3553
- return this;
3554
- }
3555
- addGQLMutation(...mutations) {
3556
- this.table.setGQLOption({
3557
- ...this.table.gqlOption,
3558
- mutations: [...this.table.gqlOption.mutations, ...mutations]
3559
- });
3560
- return this;
3561
- }
3562
- };
3563
- //#endregion
3564
- //#region src/migration/front/storeMigrator.ts
3565
- var StoreMigrator = class StoreMigrator {
3566
- constructor() {
3567
- this.tables = [];
3568
- this.migrationQueue = [];
3569
- }
3570
- static new() {
3571
- if (fs.existsSync(path.join(config().migration.dir, "initialSchema.yml"))) return StoreMigrator.deserialize(readInitialSchema());
3572
- return new StoreMigrator();
3573
- }
3574
- static deserialize(data) {
3575
- const store = new StoreMigrator();
3576
- store.tables = data.tables.map((it) => TableMigrator.deserialize(it, store));
3577
- store.resetQueue();
3578
- return store;
3579
- }
3580
- table(tableName) {
3581
- const table = this.tables.find((it) => it.tableName === tableName);
3582
- if (!table) throw new Error("QueryTable: " + tableName + " Not Found");
3583
- return table;
3584
- }
3585
- addQuery(...query) {
3586
- this.migrationQueue.push(...query);
3587
- }
3588
- createTable(tableName, tableCreator) {
3589
- if (this.tables.find((it) => it.tableName === tableName)) throw new SasatError(`${tableName} is already exist`);
3590
- const creator = new TableCreator(tableName, this);
3591
- tableCreator(creator);
3592
- const table = new TableMigrator(creator.create(), this);
3593
- this.tables.push(table);
3594
- this.addQuery(table.showCreateTable());
3595
- this.addQuery(...table.getIndexes().map((it) => it.addSql()));
3596
- return this;
3597
- }
3598
- dropTable(tableName) {
3599
- this.addQuery(`DROP TABLE ${tableName}`);
3600
- this.tables = this.tables.filter((it) => it.tableName !== tableName);
3601
- return this;
3602
- }
3603
- sql(...sql) {
3604
- this.addQuery(...sql);
3605
- return this;
3606
- }
3607
- getSql() {
3608
- return this.migrationQueue;
3609
- }
3610
- resetQueue() {
3611
- this.migrationQueue = [];
3612
- }
3613
- serialize() {
3614
- return { tables: this.tables.map((it) => it.serialize()) };
3615
- }
3616
- setConfig(conf) {
3617
- this.conf = conf;
3618
- return this;
3619
- }
3620
- getUpdateConfig() {
3621
- return this.conf;
3622
- }
3623
- };
3624
- //#endregion
3625
- //#region src/db/formatQuery.ts
3626
- const formatQuery = (str, ...params) => {
3627
- let ret = str[0];
3628
- for (let i = 0; i < params.length; i++) {
3629
- if (typeof params[i] === "function") ret += params[i]();
3630
- else if (Array.isArray(params[i])) ret += params[i].map((it) => SqlString.escape(it)).join(", ");
3631
- else ret += SqlString.escape(params[i]);
3632
- ret += str[i + 1];
3633
- }
3634
- return ret;
3635
- };
3636
- //#endregion
3637
- //#region src/db/connectors/dbClient.ts
3638
- const noop = () => {};
3639
- var SQLClient = class {
3640
- constructor() {
3641
- this.logger = noop;
3642
- }
3643
- rawQuery(sql) {
3644
- this.logger(sql);
3645
- return this.execSql(sql);
3646
- }
3647
- rawCommand(sql) {
3648
- this.logger(sql);
3649
- return this.execSql(sql);
3650
- }
3651
- query(templateString, ...params) {
3652
- return this.rawQuery(formatQuery(templateString, ...params));
3653
- }
3654
- command(templateString, ...params) {
3655
- return this.rawCommand(formatQuery(templateString, ...params));
3656
- }
3657
- };
3658
- var SQLTransaction = class extends SQLClient {};
3659
- var DBClient = class extends SQLClient {
3660
- constructor(logger = noop) {
3661
- super();
3662
- this._released = false;
3663
- this.logger = logger;
3664
- }
3665
- isReleased() {
3666
- return this._released;
3667
- }
3668
- };
3669
- //#endregion
3670
- //#region src/db/connectors/mysql/transaction.ts
3671
- var MySqlTransaction = class extends SQLTransaction {
3672
- constructor(connection) {
3673
- super();
3674
- this.connection = connection;
3675
- }
3676
- async commit() {
3677
- const result = await this.connection.commit();
3678
- await this.connection.end();
3679
- return result;
3680
- }
3681
- async rollback() {
3682
- await this.connection.rollback();
3683
- await this.connection.end();
3684
- }
3685
- async execSql(sql) {
3686
- return (await this.connection.query(sql))[0];
3687
- }
3688
- };
3689
- //#endregion
3690
- //#region src/db/connectors/mysql/poolClient.ts
3691
- var MysqlPoolClient = class extends DBClient {
3692
- constructor(poolOption, logger) {
3693
- super(logger);
3694
- this.poolOption = poolOption;
3695
- this.pool = createPool({
3696
- dateStrings: true,
3697
- ...poolOption
3698
- });
3699
- this.release = this.release.bind(this);
3700
- }
3701
- async transaction() {
3702
- const connection = await createConnection({
3703
- ...config().db,
3704
- dateStrings: true,
3705
- ...this.poolOption
3706
- });
3707
- await connection.beginTransaction();
3708
- return new MySqlTransaction(connection);
3709
- }
3710
- async release() {
3711
- await this.pool.end();
3712
- this._released = true;
3713
- }
3714
- async execSql(sql) {
3715
- return (await this.pool.query(sql))[0];
3716
- }
3717
- };
3718
- //#endregion
3719
- //#region src/db/getDbClient.ts
3720
- let client;
3721
- const getDbClient = (option, logger) => {
3722
- if (client && !client.isReleased()) return client;
3723
- client = new MysqlPoolClient({
3724
- ...config().db,
3725
- ...option
3726
- }, logger);
3727
- return client;
3728
- };
3729
- //#endregion
3730
- //#region src/migration/exec/getCurrentMigration.ts
3731
- const calcRunMigrationFileNames = (records) => {
3732
- const result = [];
3733
- records.forEach((it) => {
3734
- if (it.direction === "down") {
3735
- if (result[result.length] !== it.name) throw new Error("Invalid migration history: `down` migration must be the same migration as the last `up` migration ");
3736
- result.pop();
3737
- return;
3738
- }
3739
- result.push(it.name);
3740
- });
3741
- return result;
3742
- };
3743
- const getCurrentMigration = async (options) => {
3744
- const migrationTable = SqlString.escapeId(config().migration.table);
3745
- const files = getMigrationFileNames();
3746
- const client = getDbClient();
3747
- const query = `CREATE TABLE IF NOT EXISTS ${migrationTable} (id int auto_increment primary key , name varchar(100) not null,direction enum('up', 'down') not null, migrated_at timestamp default current_timestamp)`;
3748
- if (!options.silent) {
3749
- Console.log(`creating migration table: ${migrationTable} :: ${Buffer.from(migrationTable).toString("base64")}`);
3750
- Console.log(query);
3751
- }
3752
- await client.rawQuery(query);
3753
- const q = `SELECT name, direction FROM ${migrationTable} ORDER BY id ASC`;
3754
- if (!options.silent) Console.debug(q);
3755
- const result = await client.rawQuery(q);
3756
- console.debug(result);
3757
- if (!result.length) return;
3758
- const runs = calcRunMigrationFileNames(result);
3759
- if (runs.length === 0) return;
3760
- runs.forEach((run, i) => {
3761
- if (files[i] !== run) throw new Error(`\
3762
- Invalid migration order: Migration must be performed in the same order
3763
- Found : ${files[i]}
3764
- in migration history: ${run}`);
3765
- });
3766
- return runs[runs.length - 1];
3767
- };
3768
- //#endregion
3769
- //#region src/migration/exec/migrationFileCompiler.ts
3770
- const changeExtTsToJs = (fileName) => fileName.slice(0, -3) + ".mjs";
3771
- const compileMigrationFiles = () => {
3772
- const compiles = getMigrationFileNames().map(async (fileName) => {
3773
- const filePath = path.join(getMigrationFileDir(), fileName);
3774
- const r = await build({
3775
- entryPoints: [filePath],
3776
- bundle: true,
3777
- outfile: changeExtTsToJs(filePath),
3778
- platform: "node",
3779
- format: "esm",
3780
- outExtension: { ".js": ".mjs" },
3781
- banner: { js: `import { createRequire as topLevelCreateRequire } from 'module';
3782
- const require = topLevelCreateRequire(import.meta.url);
3783
- import { fileURLToPath as __topLevelFileURLToPath } from 'url';
3784
- import { dirname as __topLevelDirname } from 'path';
3785
- const __filename = __topLevelFileURLToPath(import.meta.url);
3786
- const __dirname = __topLevelDirname(__filename);
3787
- ` }
3788
- });
3789
- if (r.errors.length !== 0) throw r.errors;
3790
- return fileName;
3791
- });
3792
- return Promise.all(compiles);
3793
- };
3794
- //#endregion
3795
- //#region src/migration/exec/readMigrationFile.ts
3796
- const readMigration = async (store, tsFileName, direction) => {
3797
- const instance = new (await (import(path.join(process.cwd(), config().migration.dir, changeExtTsToJs(tsFileName))))).default();
3798
- if (direction === "up") {
3799
- if (instance.beforeUp) await instance.beforeUp();
3800
- await instance.up(store);
3801
- if (instance.afterUp) await instance.afterUp();
3802
- } else {
3803
- if (instance.beforeDown) await instance.beforeDown();
3804
- await instance.down(store);
3805
- if (instance.afterDown) await instance.afterDown();
3806
- }
3807
- return store;
3808
- };
3809
- //#endregion
3810
- //#region src/migration/exec/createCurrentMigrationDataStore.ts
3811
- const createCurrentMigrationDataStore = async (targetMigrationName) => {
3812
- const allFiles = getMigrationFileNames();
3813
- let store = StoreMigrator.new();
3814
- if (!targetMigrationName) return store;
3815
- const files = allFiles.slice(0, allFiles.indexOf(targetMigrationName) + 1);
3816
- for (const tsFileName of files) store = await readMigration(store, tsFileName, "up");
3817
- store.resetQueue();
3818
- return store;
3819
- };
3820
- //#endregion
3821
- //#region src/migration/exec/getMigrationTarget.ts
3822
- const getMigrationTargets = (files, current) => {
3823
- const currentIndex = current ? files.indexOf(current) + 1 : 0;
3824
- const targetIndex = files.indexOf(config().migration.target || files[files.length - 1]) + 1;
3825
- if (currentIndex === -1 || targetIndex === -1) throw new Error("migration target not found");
3826
- if (targetIndex >= currentIndex) return {
3827
- direction: "up",
3828
- files: files.slice(currentIndex, targetIndex)
3829
- };
3830
- return {
3831
- direction: "down",
3832
- files: files.slice(targetIndex, currentIndex).reverse()
3833
- };
3834
- };
3835
- //#endregion
3836
- //#region src/migration/exec/runMigration.ts
3837
- const runMigration = async (client, store, migrationName, direction, options) => {
3838
- const sqls = store.getSql();
3839
- const conf = store.getUpdateConfig();
3840
- if (conf) setConfig(conf);
3841
- store.resetQueue();
3842
- if (!options.silent) sqls.forEach(Console.log);
3843
- if (options.dry) return;
3844
- const transaction = await client.transaction();
3845
- try {
3846
- for (const sql of sqls) await transaction.rawQuery(sql).catch((e) => {
3847
- Console.error(`ERROR ON ${migrationName}`);
3848
- Console.error(`SQL: ${sql}`);
3849
- Console.error(`MESSAGE: ${e.message}`);
3850
- process.exit(1);
3851
- });
3852
- await transaction.query`insert into ${() => config().migration.table} (name, direction) values (${[migrationName, direction]})`;
3853
- return await transaction.commit();
3854
- } catch (e) {
3855
- await transaction.rollback();
3856
- throw e;
3857
- }
3858
- };
3859
- //#endregion
3860
- //#region src/migration/controller.ts
3861
- var MigrationController = class {
3862
- async migrate(client, options) {
3863
- const fileNames = getMigrationFileNames();
3864
- console.log(4, options);
3865
- const currentMigration = await getCurrentMigration(options);
3866
- if (!options.silent) Console.log("--current migration--: " + currentMigration);
3867
- console.log(2);
3868
- let store = await createCurrentMigrationDataStore(currentMigration);
3869
- if (store.getUpdateConfig()) setConfig(store.getUpdateConfig());
3870
- console.log(1);
3871
- const target = getMigrationTargets(fileNames, currentMigration);
3872
- console.log(2);
3873
- for (const tsFileName of target.files) {
3874
- if (!options.silent) Console.log("---------\n" + tsFileName);
3875
- console.log(3, tsFileName);
3876
- store = await readMigration(store, tsFileName, target.direction);
3877
- console.log(4);
3878
- await runMigration(client, store, tsFileName, target.direction, options);
3879
- store.resetQueue();
3880
- }
3881
- return {
3882
- store: store.serialize(),
3883
- currentMigration: config().migration.target || fileNames[fileNames.length - 1]
3884
- };
3885
- }
3886
- };
3887
- //#endregion
3888
- //#region src/migration/dataStore.ts
3889
- var DataStoreHandler = class {
3890
- constructor(store) {
3891
- this.tables = store.tables.map((it) => new TableHandler(it, this));
3892
- }
3893
- table(tableName) {
3894
- const table = this.tables.find((it) => it.tableName === tableName);
3895
- if (!table) throw new Error(`Table: ${tableName} is Not Found`);
3896
- return table;
3897
- }
3898
- referencedBy(tableName) {
3899
- return this.tables.flatMap((it) => it.columns.filter((it) => it.isReference() && it.data.reference.parentTable === tableName));
3900
- }
3901
- virtualReferencedBy(tableName) {
3902
- return this.tables.flatMap((it) => it.virtualRelations.filter((it) => it.parentTable === tableName));
3903
- }
3904
- };
3905
- //#endregion
3906
- //#region src/cli/commands/migrate.ts
3907
- const migrate = async (client, options) => {
3908
- let current;
3909
- if (!options.silent) Console.log("--migration started--");
3910
- try {
3911
- if (!options.skipBuild) await compileMigrationFiles();
3912
- const conf = config();
3913
- if (conf.migration.db) setConfig({ db: conf.migration.db });
3914
- const result = await new MigrationController().migrate(client, options);
3915
- current = result.currentMigration;
3916
- if (options.generateFiles) {
3917
- const storeHandler = new DataStoreHandler(result.store);
3918
- writeCurrentSchema(result.store);
3919
- await new CodeGen_v2(storeHandler).generate();
3920
- }
3921
- if (!options.silent) Console.success(`current migration is ${current}`);
3922
- } catch (e) {
3923
- Console.error(e.message);
3924
- throw e;
3925
- }
3926
- };
3927
- //#endregion
3
+ import { createConnection } from "mysql2/promise";
3928
4
  //#region src/db/connectors/mysql/client.ts
3929
5
  var MysqlClient = class extends DBClient {
3930
6
  async release() {}
@@ -4356,7 +432,7 @@ const subQueryTable = (query, joins, alias) => ({
4356
432
  alias,
4357
433
  joins
4358
434
  });
4359
- const join$1 = (table, conditions, type) => ({
435
+ const join = (table, conditions, type) => ({
4360
436
  kind: 3,
4361
437
  type,
4362
438
  table,
@@ -4385,7 +461,7 @@ const QExpr = {
4385
461
  paren,
4386
462
  table,
4387
463
  subQueryTable,
4388
- join: join$1,
464
+ join,
4389
465
  value: literal,
4390
466
  sort,
4391
467
  order: sort,