@atscript/typescript 0.1.34 → 0.1.36
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/LICENSE +1 -1
- package/dist/cli.cjs +552 -113
- package/dist/index.cjs +165 -814
- package/dist/index.mjs +157 -806
- package/dist/json-schema-0UUPoHud.mjs +952 -0
- package/dist/json-schema-S5-XAOrR.cjs +1030 -0
- package/dist/utils.cjs +46 -976
- package/dist/utils.d.ts +47 -3
- package/dist/utils.mjs +24 -954
- package/package.json +11 -6
package/dist/cli.cjs
CHANGED
|
@@ -23,13 +23,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
|
|
24
24
|
//#endregion
|
|
25
25
|
const __moostjs_event_cli = __toESM(require("@moostjs/event-cli"));
|
|
26
|
-
const fs = __toESM(require("fs"));
|
|
27
|
-
const path = __toESM(require("path"));
|
|
28
26
|
const __atscript_core = __toESM(require("@atscript/core"));
|
|
29
27
|
const moost = __toESM(require("moost"));
|
|
28
|
+
const fs = __toESM(require("fs"));
|
|
29
|
+
const path = __toESM(require("path"));
|
|
30
|
+
const node_module = __toESM(require("node:module"));
|
|
31
|
+
const node_readline = __toESM(require("node:readline"));
|
|
32
|
+
const node_url = __toESM(require("node:url"));
|
|
30
33
|
|
|
31
34
|
//#region packages/typescript/src/codegen/code-printer.ts
|
|
32
|
-
function _define_property$
|
|
35
|
+
function _define_property$7(obj, key, value) {
|
|
33
36
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
34
37
|
value,
|
|
35
38
|
enumerable: true,
|
|
@@ -122,17 +125,17 @@ else this.write(closing);
|
|
|
122
125
|
return " ".repeat(this.indentLevel * this.indentSize);
|
|
123
126
|
}
|
|
124
127
|
constructor() {
|
|
125
|
-
_define_property$
|
|
126
|
-
_define_property$
|
|
127
|
-
_define_property$
|
|
128
|
-
_define_property$
|
|
129
|
-
_define_property$
|
|
128
|
+
_define_property$7(this, "lines", []);
|
|
129
|
+
_define_property$7(this, "currentLine", "");
|
|
130
|
+
_define_property$7(this, "indentLevel", 0);
|
|
131
|
+
_define_property$7(this, "indentSize", 2);
|
|
132
|
+
_define_property$7(this, "blockStack", []);
|
|
130
133
|
}
|
|
131
134
|
};
|
|
132
135
|
|
|
133
136
|
//#endregion
|
|
134
137
|
//#region packages/typescript/src/codegen/base-renderer.ts
|
|
135
|
-
function _define_property$
|
|
138
|
+
function _define_property$6(obj, key, value) {
|
|
136
139
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
137
140
|
value,
|
|
138
141
|
enumerable: true,
|
|
@@ -157,8 +160,8 @@ var BaseRenderer = class extends CodePrinter {
|
|
|
157
160
|
renderInterface(node) {}
|
|
158
161
|
renderType(node) {}
|
|
159
162
|
renderAnnotate(node) {}
|
|
160
|
-
transformFromPath(path$
|
|
161
|
-
return `${path$
|
|
163
|
+
transformFromPath(path$4) {
|
|
164
|
+
return `${path$4}.as`;
|
|
162
165
|
}
|
|
163
166
|
renderImport(node) {
|
|
164
167
|
const def = node.getDefinition();
|
|
@@ -199,7 +202,7 @@ var BaseRenderer = class extends CodePrinter {
|
|
|
199
202
|
}
|
|
200
203
|
}
|
|
201
204
|
constructor(doc) {
|
|
202
|
-
super(), _define_property$
|
|
205
|
+
super(), _define_property$6(this, "doc", void 0), _define_property$6(this, "_unused", void 0), this.doc = doc;
|
|
203
206
|
}
|
|
204
207
|
};
|
|
205
208
|
|
|
@@ -216,7 +219,7 @@ function escapeQuotes(str) {
|
|
|
216
219
|
|
|
217
220
|
//#endregion
|
|
218
221
|
//#region packages/typescript/src/codegen/type-renderer.ts
|
|
219
|
-
function _define_property$
|
|
222
|
+
function _define_property$5(obj, key, value) {
|
|
220
223
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
221
224
|
value,
|
|
222
225
|
enumerable: true,
|
|
@@ -341,8 +344,10 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
341
344
|
this.writeln("static toJsonSchema: () => any");
|
|
342
345
|
if (!this.opts?.exampleData) this.writeln("/** @deprecated Example Data support is disabled. To enable, set `exampleData: true` in tsPlugin options. */");
|
|
343
346
|
this.writeln("static toExampleData?: () => any");
|
|
344
|
-
if (interfaceNode && this.
|
|
347
|
+
if (interfaceNode && this.hasDbEntity(interfaceNode)) {
|
|
345
348
|
this.renderFlat(interfaceNode);
|
|
349
|
+
this.renderOwnProps(interfaceNode);
|
|
350
|
+
this.renderNavProps(interfaceNode);
|
|
346
351
|
this.renderPk(interfaceNode);
|
|
347
352
|
}
|
|
348
353
|
}
|
|
@@ -433,14 +438,13 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = `TAtscriptTypeFina
|
|
|
433
438
|
this.popln();
|
|
434
439
|
}
|
|
435
440
|
/**
|
|
436
|
-
* Checks whether an interface
|
|
441
|
+
* Checks whether an interface is a DB entity (`@db.table` or `@db.view`).
|
|
437
442
|
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
return !!node.annotations?.some((a) => a.name === "db.table");
|
|
443
|
+
* Only DB entities get `__flat`, `__pk`, `__ownProps`, and `__navProps` static properties.
|
|
444
|
+
* These exist solely to improve type-safety for filter expressions, `$select`/`$sort`,
|
|
445
|
+
* and `$with` operations in the DB layer.
|
|
446
|
+
*/ hasDbEntity(node) {
|
|
447
|
+
return !!node.annotations?.some((a) => a.name === "db.table" || a.name === "db.view" || a.name === "db.view.for");
|
|
444
448
|
}
|
|
445
449
|
/**
|
|
446
450
|
* Renders the `static __flat` property — a map of all dot-notation paths
|
|
@@ -457,12 +461,30 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = `TAtscriptTypeFina
|
|
|
457
461
|
* not individually queryable)
|
|
458
462
|
* - **Leaf fields** → their original TypeScript type
|
|
459
463
|
*/ renderFlat(node) {
|
|
460
|
-
|
|
464
|
+
this.renderFlatMap("__flat", (0, __atscript_core.flattenInterfaceNode)(this.doc, node));
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Renders the `static __ownProps` property — table-owned fields only (no nav props).
|
|
468
|
+
*/ renderOwnProps(node) {
|
|
469
|
+
this.renderFlatMap("__ownProps", (0, __atscript_core.flattenInterfaceNode)(this.doc, node, { skipNavProps: true }), {
|
|
470
|
+
leadingNewline: true,
|
|
471
|
+
trailingNewline: true
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Shared renderer for flat-map static properties (`__flat`, `__ownProps`).
|
|
476
|
+
*
|
|
477
|
+
* Special rendering rules:
|
|
478
|
+
* - **Intermediate paths** (structures, arrays of structures) → `never`
|
|
479
|
+
* - **`@db.json` fields** → `string` (stored as serialized JSON in DB)
|
|
480
|
+
* - **Leaf fields** → their original TypeScript type
|
|
481
|
+
*/ renderFlatMap(propName, flatMap, opts) {
|
|
461
482
|
if (flatMap.size === 0) return;
|
|
462
|
-
this.
|
|
483
|
+
if (opts?.leadingNewline) this.writeln();
|
|
484
|
+
this.write(`static ${propName}: `);
|
|
463
485
|
this.blockln("{}");
|
|
464
|
-
for (const [path$
|
|
465
|
-
this.write(`"${escapeQuotes(path$
|
|
486
|
+
for (const [path$4, descriptor] of flatMap) {
|
|
487
|
+
this.write(`"${escapeQuotes(path$4)}"`);
|
|
466
488
|
if (descriptor.optional) this.write("?");
|
|
467
489
|
this.write(": ");
|
|
468
490
|
if (descriptor.intermediate) this.writeln("never");
|
|
@@ -474,19 +496,46 @@ else {
|
|
|
474
496
|
renderedDef.split("\n").forEach((l) => this.writeln(l));
|
|
475
497
|
}
|
|
476
498
|
}
|
|
477
|
-
this.
|
|
499
|
+
if (opts?.trailingNewline) this.popln();
|
|
500
|
+
else this.pop();
|
|
478
501
|
}
|
|
479
502
|
/**
|
|
480
|
-
* Renders the `static
|
|
481
|
-
*
|
|
503
|
+
* Renders the `static __navProps` property — a map of navigation property names
|
|
504
|
+
* to their declared TypeScript types.
|
|
482
505
|
*
|
|
483
|
-
* -
|
|
484
|
-
*
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
506
|
+
* This enables type-safe `$with` in queries: `name` is constrained to known
|
|
507
|
+
* navigation property keys, and nested filter/controls are typed to the target entity.
|
|
508
|
+
*/ renderNavProps(node) {
|
|
509
|
+
let struct;
|
|
510
|
+
if (node.hasExtends) struct = this.doc.resolveInterfaceExtends(node);
|
|
511
|
+
if (!struct) struct = node.getDefinition();
|
|
512
|
+
if (!struct || !(0, __atscript_core.isStructure)(struct)) return;
|
|
513
|
+
const structNode = struct;
|
|
514
|
+
const navProps = [];
|
|
515
|
+
for (const [name, prop] of structNode.props) {
|
|
516
|
+
if (prop.token("identifier")?.pattern) continue;
|
|
517
|
+
if ((0, __atscript_core.hasNavPropAnnotation)(prop)) navProps.push({
|
|
518
|
+
name,
|
|
519
|
+
prop
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
if (navProps.length === 0) return;
|
|
523
|
+
this.writeln();
|
|
524
|
+
this.write("static __navProps: ");
|
|
525
|
+
this.blockln("{}");
|
|
526
|
+
for (const { name, prop } of navProps) {
|
|
527
|
+
this.write(`"${escapeQuotes(name)}"`);
|
|
528
|
+
if (prop.token("optional")) this.write("?");
|
|
529
|
+
this.write(": ");
|
|
530
|
+
const propDef = prop.getDefinition();
|
|
531
|
+
if (propDef) {
|
|
532
|
+
const renderedDef = this.renderTypeDefString(propDef);
|
|
533
|
+
renderedDef.split("\n").forEach((l) => this.writeln(l));
|
|
534
|
+
} else this.writeln("unknown");
|
|
535
|
+
}
|
|
536
|
+
this.popln();
|
|
537
|
+
}
|
|
538
|
+
renderPk(node) {
|
|
490
539
|
const isMongoCollection = !!node.annotations?.some((a) => a.name === "db.mongo.collection");
|
|
491
540
|
let struct;
|
|
492
541
|
if (node.hasExtends) struct = this.doc.resolveInterfaceExtends(node);
|
|
@@ -586,7 +635,7 @@ else if (pkProps.length === 1) {
|
|
|
586
635
|
this.writeln(` */`);
|
|
587
636
|
}
|
|
588
637
|
constructor(doc, opts) {
|
|
589
|
-
super(doc), _define_property$
|
|
638
|
+
super(doc), _define_property$5(this, "opts", void 0), this.opts = opts;
|
|
590
639
|
}
|
|
591
640
|
};
|
|
592
641
|
function renderPrimitiveTypeDef(def) {
|
|
@@ -608,7 +657,7 @@ function renderPrimitiveTypeDef(def) {
|
|
|
608
657
|
|
|
609
658
|
//#endregion
|
|
610
659
|
//#region packages/typescript/src/validator.ts
|
|
611
|
-
function _define_property$
|
|
660
|
+
function _define_property$4(obj, key, value) {
|
|
612
661
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
613
662
|
value,
|
|
614
663
|
enumerable: true,
|
|
@@ -642,14 +691,14 @@ var Validator = class {
|
|
|
642
691
|
clear() {
|
|
643
692
|
this.stackErrors[this.stackErrors.length - 1] = null;
|
|
644
693
|
}
|
|
645
|
-
error(message, path$
|
|
694
|
+
error(message, path$4, details) {
|
|
646
695
|
let errors = this.stackErrors[this.stackErrors.length - 1];
|
|
647
696
|
if (!errors) if (this.stackErrors.length > 0) {
|
|
648
697
|
errors = [];
|
|
649
698
|
this.stackErrors[this.stackErrors.length - 1] = errors;
|
|
650
699
|
} else errors = this.errors;
|
|
651
700
|
const error = {
|
|
652
|
-
path: path$
|
|
701
|
+
path: path$4 || this.cachedPath,
|
|
653
702
|
message
|
|
654
703
|
};
|
|
655
704
|
if (details?.length) error.details = details;
|
|
@@ -687,7 +736,7 @@ var Validator = class {
|
|
|
687
736
|
if (this.isLimitExceeded()) return false;
|
|
688
737
|
if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
|
|
689
738
|
if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.cachedPath);
|
|
690
|
-
if (def.optional && value === undefined) return true;
|
|
739
|
+
if (def.optional && (value === undefined || value === null)) return true;
|
|
691
740
|
for (const plugin of this.opts.plugins) {
|
|
692
741
|
const result = plugin(this, def, value);
|
|
693
742
|
if (result === false || result === true) return result;
|
|
@@ -820,9 +869,9 @@ var Validator = class {
|
|
|
820
869
|
const typeKeys = new Set();
|
|
821
870
|
let skipList;
|
|
822
871
|
if (this.opts.skipList) {
|
|
823
|
-
const path$
|
|
824
|
-
for (const item of this.opts.skipList) if (item.startsWith(path$
|
|
825
|
-
const key = item.slice(path$
|
|
872
|
+
const path$4 = this.stackPath.length > 1 ? `${this.cachedPath}.` : "";
|
|
873
|
+
for (const item of this.opts.skipList) if (item.startsWith(path$4)) {
|
|
874
|
+
const key = item.slice(path$4.length);
|
|
826
875
|
if (!skipList) skipList = new Set();
|
|
827
876
|
skipList.add(key);
|
|
828
877
|
valueKeys.delete(key);
|
|
@@ -1014,13 +1063,13 @@ else {
|
|
|
1014
1063
|
return true;
|
|
1015
1064
|
}
|
|
1016
1065
|
constructor(def, opts) {
|
|
1017
|
-
_define_property$
|
|
1018
|
-
_define_property$
|
|
1019
|
-
/** Validation errors collected during the last {@link validate} call. */ _define_property$
|
|
1020
|
-
_define_property$
|
|
1021
|
-
_define_property$
|
|
1022
|
-
_define_property$
|
|
1023
|
-
_define_property$
|
|
1066
|
+
_define_property$4(this, "def", void 0);
|
|
1067
|
+
_define_property$4(this, "opts", void 0);
|
|
1068
|
+
/** Validation errors collected during the last {@link validate} call. */ _define_property$4(this, "errors", void 0);
|
|
1069
|
+
_define_property$4(this, "stackErrors", void 0);
|
|
1070
|
+
_define_property$4(this, "stackPath", void 0);
|
|
1071
|
+
_define_property$4(this, "cachedPath", void 0);
|
|
1072
|
+
_define_property$4(this, "context", void 0);
|
|
1024
1073
|
this.def = def;
|
|
1025
1074
|
this.errors = [];
|
|
1026
1075
|
this.stackErrors = [];
|
|
@@ -1037,7 +1086,7 @@ else {
|
|
|
1037
1086
|
};
|
|
1038
1087
|
var ValidatorError = class extends Error {
|
|
1039
1088
|
constructor(errors) {
|
|
1040
|
-
super(`${errors[0].path ? errors[0].path + ": " : ""}${errors[0].message}`), _define_property$
|
|
1089
|
+
super(`${errors[0].path ? errors[0].path + ": " : ""}${errors[0].message}`), _define_property$4(this, "errors", void 0), _define_property$4(this, "name", void 0), this.errors = errors, this.name = "Validation Error";
|
|
1041
1090
|
}
|
|
1042
1091
|
};
|
|
1043
1092
|
|
|
@@ -1176,7 +1225,7 @@ else {
|
|
|
1176
1225
|
let target = t;
|
|
1177
1226
|
if (chain) for (const c of chain) if (target.type.kind === "object" && target.type.props.has(c)) target = target.type.props.get(c);
|
|
1178
1227
|
else return t.type;
|
|
1179
|
-
node.id = target.id || t.id;
|
|
1228
|
+
node.id = chain ? target.id : target.id || t.id;
|
|
1180
1229
|
Object.defineProperty(node, "type", {
|
|
1181
1230
|
value: target.type,
|
|
1182
1231
|
writable: false,
|
|
@@ -1186,7 +1235,7 @@ else return t.type;
|
|
|
1186
1235
|
},
|
|
1187
1236
|
configurable: true
|
|
1188
1237
|
});
|
|
1189
|
-
} else throw new
|
|
1238
|
+
} else throw new TypeError(`${type$1} is not annotated type`);
|
|
1190
1239
|
return this;
|
|
1191
1240
|
},
|
|
1192
1241
|
annotate(key, value, asArray) {
|
|
@@ -1274,7 +1323,7 @@ function buildJsonSchema(type) {
|
|
|
1274
1323
|
const required = [];
|
|
1275
1324
|
for (const [key, val] of d.type.props.entries()) {
|
|
1276
1325
|
if (isPhantomType(val)) continue;
|
|
1277
|
-
properties[key] = build$
|
|
1326
|
+
properties[key] = build$2(val);
|
|
1278
1327
|
if (!val.optional) required.push(key);
|
|
1279
1328
|
}
|
|
1280
1329
|
const schema$1 = {
|
|
@@ -1284,7 +1333,7 @@ function buildJsonSchema(type) {
|
|
|
1284
1333
|
if (required.length > 0) schema$1.required = required;
|
|
1285
1334
|
return schema$1;
|
|
1286
1335
|
};
|
|
1287
|
-
const build$
|
|
1336
|
+
const build$2 = (def) => {
|
|
1288
1337
|
if (def.id && def.type.kind === "object" && def !== type) {
|
|
1289
1338
|
const name = def.id;
|
|
1290
1339
|
if (!defs[name]) {
|
|
@@ -1305,7 +1354,7 @@ function buildJsonSchema(type) {
|
|
|
1305
1354
|
array(d) {
|
|
1306
1355
|
const schema$1 = {
|
|
1307
1356
|
type: "array",
|
|
1308
|
-
items: build$
|
|
1357
|
+
items: build$2(d.type.of)
|
|
1309
1358
|
};
|
|
1310
1359
|
const minLength = meta.get("expect.minLength");
|
|
1311
1360
|
if (minLength) schema$1.minItems = typeof minLength === "number" ? minLength : minLength.length;
|
|
@@ -1316,7 +1365,7 @@ function buildJsonSchema(type) {
|
|
|
1316
1365
|
union(d) {
|
|
1317
1366
|
const disc = detectDiscriminator(d.type.items);
|
|
1318
1367
|
if (disc) {
|
|
1319
|
-
const oneOf = d.type.items.map(build$
|
|
1368
|
+
const oneOf = d.type.items.map(build$2);
|
|
1320
1369
|
const mapping = {};
|
|
1321
1370
|
for (const [val, idx] of Object.entries(disc.indexMapping)) {
|
|
1322
1371
|
const item = d.type.items[idx];
|
|
@@ -1330,15 +1379,15 @@ function buildJsonSchema(type) {
|
|
|
1330
1379
|
}
|
|
1331
1380
|
};
|
|
1332
1381
|
}
|
|
1333
|
-
return { anyOf: d.type.items.map(build$
|
|
1382
|
+
return { anyOf: d.type.items.map(build$2) };
|
|
1334
1383
|
},
|
|
1335
1384
|
intersection(d) {
|
|
1336
|
-
return { allOf: d.type.items.map(build$
|
|
1385
|
+
return { allOf: d.type.items.map(build$2) };
|
|
1337
1386
|
},
|
|
1338
1387
|
tuple(d) {
|
|
1339
1388
|
return {
|
|
1340
1389
|
type: "array",
|
|
1341
|
-
items: d.type.items.map(build$
|
|
1390
|
+
items: d.type.items.map(build$2),
|
|
1342
1391
|
additionalItems: false
|
|
1343
1392
|
};
|
|
1344
1393
|
},
|
|
@@ -1369,7 +1418,7 @@ else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ patte
|
|
|
1369
1418
|
}
|
|
1370
1419
|
});
|
|
1371
1420
|
};
|
|
1372
|
-
const schema = build$
|
|
1421
|
+
const schema = build$2(type);
|
|
1373
1422
|
if (hasDefs) return {
|
|
1374
1423
|
...schema,
|
|
1375
1424
|
$defs: defs
|
|
@@ -1379,7 +1428,7 @@ else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ patte
|
|
|
1379
1428
|
|
|
1380
1429
|
//#endregion
|
|
1381
1430
|
//#region packages/typescript/src/codegen/js-renderer.ts
|
|
1382
|
-
function _define_property$
|
|
1431
|
+
function _define_property$3(obj, key, value) {
|
|
1383
1432
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
1384
1433
|
value,
|
|
1385
1434
|
enumerable: true,
|
|
@@ -1389,6 +1438,19 @@ function _define_property$1(obj, key, value) {
|
|
|
1389
1438
|
else obj[key] = value;
|
|
1390
1439
|
return obj;
|
|
1391
1440
|
}
|
|
1441
|
+
const QUERY_OP_MAP = {
|
|
1442
|
+
"=": "$eq",
|
|
1443
|
+
"!=": "$ne",
|
|
1444
|
+
">": "$gt",
|
|
1445
|
+
">=": "$gte",
|
|
1446
|
+
"<": "$lt",
|
|
1447
|
+
"<=": "$lte",
|
|
1448
|
+
"in": "$in",
|
|
1449
|
+
"not in": "$nin",
|
|
1450
|
+
"matches": "$regex",
|
|
1451
|
+
"exists": "$exists",
|
|
1452
|
+
"not exists": "$exists"
|
|
1453
|
+
};
|
|
1392
1454
|
var JsRenderer = class extends BaseRenderer {
|
|
1393
1455
|
pre() {
|
|
1394
1456
|
this.writeln("// prettier-ignore-start");
|
|
@@ -1417,12 +1479,12 @@ else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}_
|
|
|
1417
1479
|
buildAdHocMap(annotateNodes) {
|
|
1418
1480
|
const map = new Map();
|
|
1419
1481
|
for (const annotateNode of annotateNodes) for (const entry of annotateNode.entries) {
|
|
1420
|
-
const path$
|
|
1482
|
+
const path$4 = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)].join(".") : entry.id;
|
|
1421
1483
|
const anns = entry.annotations || [];
|
|
1422
1484
|
if (anns.length > 0) {
|
|
1423
|
-
const existing = map.get(path$
|
|
1485
|
+
const existing = map.get(path$4);
|
|
1424
1486
|
if (existing) existing.push(...anns);
|
|
1425
|
-
else map.set(path$
|
|
1487
|
+
else map.set(path$4, [...anns]);
|
|
1426
1488
|
}
|
|
1427
1489
|
}
|
|
1428
1490
|
return map.size > 0 ? map : null;
|
|
@@ -1857,8 +1919,8 @@ else if (resolved && (0, __atscript_core.isPrimitive)(resolved)) {
|
|
|
1857
1919
|
}
|
|
1858
1920
|
if (annotations === undefined) annotations = this.doc.evalAnnotationsForNode(node);
|
|
1859
1921
|
if (this._adHocAnnotations && this._propPath.length > 0) {
|
|
1860
|
-
const path$
|
|
1861
|
-
const adHoc = this._adHocAnnotations.get(path$
|
|
1922
|
+
const path$4 = this._propPath.join(".");
|
|
1923
|
+
const adHoc = this._adHocAnnotations.get(path$4);
|
|
1862
1924
|
if (adHoc) annotations = this.doc.mergeNodesAnnotations(annotations, adHoc);
|
|
1863
1925
|
}
|
|
1864
1926
|
annotations?.forEach((an) => {
|
|
@@ -1884,6 +1946,68 @@ else if (resolved && (0, __atscript_core.isPrimitive)(resolved)) {
|
|
|
1884
1946
|
if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value}, true)`);
|
|
1885
1947
|
else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
1886
1948
|
}
|
|
1949
|
+
emitRefValue(text) {
|
|
1950
|
+
const dotIdx = text.indexOf(".");
|
|
1951
|
+
if (dotIdx === -1) return `() => ${text}`;
|
|
1952
|
+
const typeName = text.slice(0, dotIdx);
|
|
1953
|
+
const field = text.slice(dotIdx + 1);
|
|
1954
|
+
return `{ type: () => ${typeName}, field: "${escapeQuotes(field)}" }`;
|
|
1955
|
+
}
|
|
1956
|
+
emitArgValue(aSpec, argToken) {
|
|
1957
|
+
if (aSpec.type === "ref") return this.emitRefValue(argToken.text);
|
|
1958
|
+
if (aSpec.type === "query" && argToken.queryNode) return this.emitQueryTree(argToken.queryNode);
|
|
1959
|
+
return aSpec.type === "string" ? `"${escapeQuotes(argToken.text)}"` : argToken.text;
|
|
1960
|
+
}
|
|
1961
|
+
emitQueryTree(queryNode) {
|
|
1962
|
+
return this.emitQueryExpr(queryNode.expression);
|
|
1963
|
+
}
|
|
1964
|
+
emitQueryExpr(node) {
|
|
1965
|
+
if ((0, __atscript_core.isQueryLogical)(node)) return this.emitQueryLogical(node);
|
|
1966
|
+
return this.emitQueryComparison(node);
|
|
1967
|
+
}
|
|
1968
|
+
emitQueryLogical(node) {
|
|
1969
|
+
if (node.operator === "not") return `{ "$not": ${this.emitQueryExpr(node.operands[0])} }`;
|
|
1970
|
+
const key = node.operator === "and" ? "$and" : "$or";
|
|
1971
|
+
const items = node.operands.map((op) => this.emitQueryExpr(op)).join(", ");
|
|
1972
|
+
return `{ "${key}": [${items}] }`;
|
|
1973
|
+
}
|
|
1974
|
+
emitQueryComparison(node) {
|
|
1975
|
+
const left = this.emitQueryFieldRef(node.left);
|
|
1976
|
+
const mappedOp = QUERY_OP_MAP[node.operator] || node.operator;
|
|
1977
|
+
const parts = [`left: ${left}`, `op: "${mappedOp}"`];
|
|
1978
|
+
if (node.right) {
|
|
1979
|
+
if ("fieldRef" in node.right && node.right.fieldRef) parts.push(`right: ${this.emitQueryFieldRef(node.right)}`);
|
|
1980
|
+
else if ("values" in node.right && node.right.values) {
|
|
1981
|
+
const values = node.right.values.map((v) => this.emitQueryLiteral(v)).join(", ");
|
|
1982
|
+
parts.push(`right: [${values}]`);
|
|
1983
|
+
} else if ("valueToken" in node.right) parts.push(`right: ${this.emitQueryLiteral(node.right)}`);
|
|
1984
|
+
} else if (node.operator === "exists") parts.push("right: true");
|
|
1985
|
+
else if (node.operator === "not exists") parts.push("right: false");
|
|
1986
|
+
return `{ ${parts.join(", ")} }`;
|
|
1987
|
+
}
|
|
1988
|
+
emitQueryFieldRef(node) {
|
|
1989
|
+
const parts = [];
|
|
1990
|
+
if (node.typeRef) parts.push(`type: () => ${node.typeRef.text}`);
|
|
1991
|
+
parts.push(`field: "${escapeQuotes(node.fieldRef.text)}"`);
|
|
1992
|
+
return `{ ${parts.join(", ")} }`;
|
|
1993
|
+
}
|
|
1994
|
+
emitQueryLiteral(node) {
|
|
1995
|
+
const token = node.valueToken;
|
|
1996
|
+
switch (token.type) {
|
|
1997
|
+
case "text": return `"${escapeQuotes(token.text)}"`;
|
|
1998
|
+
case "number": return token.text;
|
|
1999
|
+
case "regexp": {
|
|
2000
|
+
const match = /^\/(.*)\/[a-z]*$/.exec(token.text);
|
|
2001
|
+
return `"${escapeQuotes(match ? match[1] : token.text)}"`;
|
|
2002
|
+
}
|
|
2003
|
+
case "identifier": {
|
|
2004
|
+
if (token.text === "true" || token.text === "false") return token.text;
|
|
2005
|
+
if (token.text === "null" || token.text === "undefined") return "null";
|
|
2006
|
+
return token.text;
|
|
2007
|
+
}
|
|
2008
|
+
default: return token.text;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
1887
2011
|
computeAnnotationValue(node, an) {
|
|
1888
2012
|
const spec = this.doc.resolveAnnotation(an.name);
|
|
1889
2013
|
let targetValue = "true";
|
|
@@ -1895,13 +2019,13 @@ else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
|
1895
2019
|
targetValue = "{ ";
|
|
1896
2020
|
let i = 0;
|
|
1897
2021
|
for (const aSpec of spec.arguments) {
|
|
1898
|
-
if (an.args[i]) targetValue += `${wrapProp(aSpec.name)}: ${aSpec
|
|
2022
|
+
if (an.args[i]) targetValue += `${wrapProp(aSpec.name)}: ${this.emitArgValue(aSpec, an.args[i])}${i === length - 1 ? "" : ", "} `;
|
|
1899
2023
|
i++;
|
|
1900
2024
|
}
|
|
1901
2025
|
targetValue += "}";
|
|
1902
2026
|
} else {
|
|
1903
2027
|
const aSpec = spec.arguments[0];
|
|
1904
|
-
if (an.args[0]) targetValue = aSpec
|
|
2028
|
+
if (an.args[0]) targetValue = this.emitArgValue(aSpec, an.args[0]);
|
|
1905
2029
|
else targetValue = "true";
|
|
1906
2030
|
}
|
|
1907
2031
|
} else {
|
|
@@ -2041,7 +2165,7 @@ else {
|
|
|
2041
2165
|
return [];
|
|
2042
2166
|
}
|
|
2043
2167
|
constructor(doc, opts) {
|
|
2044
|
-
super(doc), _define_property$
|
|
2168
|
+
super(doc), _define_property$3(this, "opts", void 0), _define_property$3(this, "postAnnotate", void 0), _define_property$3(this, "_adHocAnnotations", void 0), _define_property$3(this, "_propPath", void 0), _define_property$3(this, "typeIds", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map();
|
|
2045
2169
|
}
|
|
2046
2170
|
};
|
|
2047
2171
|
|
|
@@ -2072,8 +2196,8 @@ const tsPlugin = (opts) => {
|
|
|
2072
2196
|
for (const [key, val] of Object.entries(annotations)) {
|
|
2073
2197
|
const multiple = val.multiple;
|
|
2074
2198
|
const typeLine = Array.from(val.types).map((t) => {
|
|
2075
|
-
if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
2076
|
-
else return t.optional ? `${t.type} | true` : t.type;
|
|
2199
|
+
if (t.type === "object" && "props" in t) return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
2200
|
+
else return "optional" in t && t.optional ? `${t.type} | true` : t.type;
|
|
2077
2201
|
}).join(" | ");
|
|
2078
2202
|
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
2079
2203
|
}
|
|
@@ -2089,9 +2213,35 @@ else return t.optional ? `${t.type} | true` : t.type;
|
|
|
2089
2213
|
};
|
|
2090
2214
|
};
|
|
2091
2215
|
|
|
2216
|
+
//#endregion
|
|
2217
|
+
//#region packages/typescript/src/cli/config.ts
|
|
2218
|
+
async function getConfig(configFile, logger) {
|
|
2219
|
+
const root = process.cwd();
|
|
2220
|
+
if (configFile) {
|
|
2221
|
+
const c = path.default.join(root, configFile);
|
|
2222
|
+
if (!(0, fs.existsSync)(c)) {
|
|
2223
|
+
logger.error(`Config file ${"\x1B[4m"}${configFile}${"\x1B[24m"} not found`);
|
|
2224
|
+
process.exit(1);
|
|
2225
|
+
}
|
|
2226
|
+
logger.log(`Using config file ${"\x1B[36m"}${configFile}${"\x1B[39m"}`);
|
|
2227
|
+
return (0, __atscript_core.loadConfig)(c);
|
|
2228
|
+
} else {
|
|
2229
|
+
const resolved = await (0, __atscript_core.resolveConfigFile)(root);
|
|
2230
|
+
if (resolved) {
|
|
2231
|
+
logger.log(`Using config file ${"\x1B[36m"}${resolved}${"\x1B[39m"}`);
|
|
2232
|
+
return (0, __atscript_core.loadConfig)(resolved);
|
|
2233
|
+
}
|
|
2234
|
+
logger.log(`No atscript config file found`);
|
|
2235
|
+
return {
|
|
2236
|
+
format: __atscript_core.DEFAULT_FORMAT,
|
|
2237
|
+
plugins: [tsPlugin()]
|
|
2238
|
+
};
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2092
2242
|
//#endregion
|
|
2093
2243
|
//#region packages/typescript/src/cli/commands.controller.ts
|
|
2094
|
-
function _define_property(obj, key, value) {
|
|
2244
|
+
function _define_property$2(obj, key, value) {
|
|
2095
2245
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
2096
2246
|
value,
|
|
2097
2247
|
enumerable: true,
|
|
@@ -2101,23 +2251,23 @@ function _define_property(obj, key, value) {
|
|
|
2101
2251
|
else obj[key] = value;
|
|
2102
2252
|
return obj;
|
|
2103
2253
|
}
|
|
2104
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
2254
|
+
function _ts_decorate$1(decorators, target, key, desc) {
|
|
2105
2255
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2106
2256
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2107
2257
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2108
2258
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2109
2259
|
}
|
|
2110
|
-
function _ts_metadata(k, v) {
|
|
2260
|
+
function _ts_metadata$1(k, v) {
|
|
2111
2261
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2112
2262
|
}
|
|
2113
|
-
function _ts_param(paramIndex, decorator) {
|
|
2263
|
+
function _ts_param$1(paramIndex, decorator) {
|
|
2114
2264
|
return function(target, key) {
|
|
2115
2265
|
decorator(target, key, paramIndex);
|
|
2116
2266
|
};
|
|
2117
2267
|
}
|
|
2118
2268
|
var Commands = class {
|
|
2119
2269
|
async default(configFile, format, noEmit, skipDiag) {
|
|
2120
|
-
const config = await
|
|
2270
|
+
const config = await getConfig(configFile, this.logger);
|
|
2121
2271
|
config.format = format || __atscript_core.DEFAULT_FORMAT;
|
|
2122
2272
|
this.logger.log(`Format: ${"\x1B[36m"}${config.format}${"\x1B[39m"}`);
|
|
2123
2273
|
const builder = await (0, __atscript_core.build)(config);
|
|
@@ -2146,72 +2296,361 @@ else if (m.severity === 2) warningCount++;
|
|
|
2146
2296
|
}
|
|
2147
2297
|
if (errorCount > 0) process.exit(1);
|
|
2148
2298
|
}
|
|
2149
|
-
async getConfig(configFile) {
|
|
2150
|
-
const root = process.cwd();
|
|
2151
|
-
if (configFile) {
|
|
2152
|
-
const c = path.default.join(root, configFile);
|
|
2153
|
-
if (!(0, fs.existsSync)(c)) {
|
|
2154
|
-
this.logger.error(`Config file ${"\x1B[4m"}${configFile}${"\x1B[24m"} not found`);
|
|
2155
|
-
process.exit(1);
|
|
2156
|
-
}
|
|
2157
|
-
this.logger.log(`Using config file ${"\x1B[36m"}${configFile}${"\x1B[39m"}`);
|
|
2158
|
-
return (0, __atscript_core.loadConfig)(c);
|
|
2159
|
-
} else {
|
|
2160
|
-
const resolved = await (0, __atscript_core.resolveConfigFile)(root);
|
|
2161
|
-
if (resolved) {
|
|
2162
|
-
this.logger.log(`Using config file ${"\x1B[36m"}${resolved}${"\x1B[39m"}`);
|
|
2163
|
-
return (0, __atscript_core.loadConfig)(resolved);
|
|
2164
|
-
}
|
|
2165
|
-
this.logger.log(`No atscript config file found`);
|
|
2166
|
-
return {
|
|
2167
|
-
format: __atscript_core.DEFAULT_FORMAT,
|
|
2168
|
-
plugins: [tsPlugin()]
|
|
2169
|
-
};
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
2299
|
constructor(logger) {
|
|
2173
|
-
_define_property(this, "logger", void 0);
|
|
2300
|
+
_define_property$2(this, "logger", void 0);
|
|
2174
2301
|
this.logger = logger;
|
|
2175
2302
|
}
|
|
2176
2303
|
};
|
|
2177
|
-
_ts_decorate([
|
|
2304
|
+
_ts_decorate$1([
|
|
2178
2305
|
(0, __moostjs_event_cli.Cli)(""),
|
|
2179
2306
|
(0, moost.Description)("Builds .as files using --config and --format"),
|
|
2180
2307
|
(0, __moostjs_event_cli.CliExample)("-c atscript.config.js", "Build .as files using atscript.config.js"),
|
|
2181
2308
|
(0, __moostjs_event_cli.CliExample)("-f dts", "Build \"d.ts\" files for \".as\" files"),
|
|
2182
2309
|
(0, __moostjs_event_cli.CliExample)("--noEmit", "Only check for errors, do not emit files"),
|
|
2183
2310
|
(0, __moostjs_event_cli.CliExample)("--skipDiag", "Emit files without running diagnostics"),
|
|
2311
|
+
_ts_param$1(0, (0, __moostjs_event_cli.CliOption)("c", "config")),
|
|
2312
|
+
_ts_param$1(0, (0, moost.Optional)()),
|
|
2313
|
+
_ts_param$1(0, (0, moost.Description)("Path to config file")),
|
|
2314
|
+
_ts_param$1(1, (0, __moostjs_event_cli.CliOption)("f", "format")),
|
|
2315
|
+
_ts_param$1(1, (0, moost.Optional)()),
|
|
2316
|
+
_ts_param$1(1, (0, moost.Description)("Output format (e.g. js, dts). Omit to run all plugins with their default output.")),
|
|
2317
|
+
_ts_param$1(2, (0, __moostjs_event_cli.CliOption)("noEmit")),
|
|
2318
|
+
_ts_param$1(2, (0, moost.Optional)()),
|
|
2319
|
+
_ts_param$1(2, (0, moost.Description)("Only run diagnostics without emitting files")),
|
|
2320
|
+
_ts_param$1(3, (0, __moostjs_event_cli.CliOption)("skipDiag")),
|
|
2321
|
+
_ts_param$1(3, (0, moost.Optional)()),
|
|
2322
|
+
_ts_param$1(3, (0, moost.Description)("Skip diagnostics and always emit files")),
|
|
2323
|
+
_ts_metadata$1("design:type", Function),
|
|
2324
|
+
_ts_metadata$1("design:paramtypes", [
|
|
2325
|
+
String,
|
|
2326
|
+
String,
|
|
2327
|
+
Boolean,
|
|
2328
|
+
Boolean
|
|
2329
|
+
]),
|
|
2330
|
+
_ts_metadata$1("design:returntype", Promise)
|
|
2331
|
+
], Commands.prototype, "default", null);
|
|
2332
|
+
Commands = _ts_decorate$1([
|
|
2333
|
+
(0, moost.Controller)(),
|
|
2334
|
+
_ts_param$1(0, (0, moost.InjectMoostLogger)("asc")),
|
|
2335
|
+
_ts_metadata$1("design:type", Function),
|
|
2336
|
+
_ts_metadata$1("design:paramtypes", [typeof TConsoleBase === "undefined" ? Object : TConsoleBase])
|
|
2337
|
+
], Commands);
|
|
2338
|
+
|
|
2339
|
+
//#endregion
|
|
2340
|
+
//#region packages/typescript/src/cli/db-sync-printer.ts
|
|
2341
|
+
function _define_property$1(obj, key, value) {
|
|
2342
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
2343
|
+
value,
|
|
2344
|
+
enumerable: true,
|
|
2345
|
+
configurable: true,
|
|
2346
|
+
writable: true
|
|
2347
|
+
});
|
|
2348
|
+
else obj[key] = value;
|
|
2349
|
+
return obj;
|
|
2350
|
+
}
|
|
2351
|
+
const DYE_COLORS = {
|
|
2352
|
+
green: (s) => `${"\x1B[32m"}${s}${"\x1B[39m"}`,
|
|
2353
|
+
red: (s) => `${"\x1B[31m"}${s}${"\x1B[39m"}`,
|
|
2354
|
+
cyan: (s) => `${"\x1B[36m"}${s}${"\x1B[39m"}`,
|
|
2355
|
+
yellow: (s) => `${"\x1B[33m"}${s}${"\x1B[39m"}`,
|
|
2356
|
+
bold: (s) => `${"\x1B[1m"}${s}${"\x1B[22m"}`,
|
|
2357
|
+
dim: (s) => `${"\x1B[2m"}${s}${"\x1B[22m"}`,
|
|
2358
|
+
underline: (s) => `${"\x1B[4m"}${s}${"\x1B[24m"}`
|
|
2359
|
+
};
|
|
2360
|
+
const BANNER = DYE_COLORS.cyan(`
|
|
2361
|
+
|
|
2362
|
+
#############
|
|
2363
|
+
#################
|
|
2364
|
+
%# #####
|
|
2365
|
+
####
|
|
2366
|
+
########## #### #######
|
|
2367
|
+
############ #### ###########
|
|
2368
|
+
#### #### #### #### ###
|
|
2369
|
+
#### #### #### ######
|
|
2370
|
+
#### #### #### #########
|
|
2371
|
+
#### #### #### ######
|
|
2372
|
+
#### #### #### ### ####
|
|
2373
|
+
############ #### ###########
|
|
2374
|
+
############ #### #########
|
|
2375
|
+
#########
|
|
2376
|
+
#####
|
|
2377
|
+
|
|
2378
|
+
`);
|
|
2379
|
+
const PLAN_HEADER = [
|
|
2380
|
+
"",
|
|
2381
|
+
DYE_COLORS.bold("╔══════════════════════════════════════╗"),
|
|
2382
|
+
DYE_COLORS.bold("║ Schema Sync Plan ║"),
|
|
2383
|
+
DYE_COLORS.bold("╚══════════════════════════════════════╝"),
|
|
2384
|
+
""
|
|
2385
|
+
];
|
|
2386
|
+
var DbSyncPrinter = class {
|
|
2387
|
+
log(...args) {
|
|
2388
|
+
console.log(...args);
|
|
2389
|
+
}
|
|
2390
|
+
banner() {
|
|
2391
|
+
this.log(BANNER);
|
|
2392
|
+
}
|
|
2393
|
+
typeCount(count) {
|
|
2394
|
+
this.log(`Found ${this.colors.cyan(String(count))} type(s)`);
|
|
2395
|
+
}
|
|
2396
|
+
planUpToDate(plan) {
|
|
2397
|
+
this.log(`${this.colors.green(this.colors.bold("Schema is up to date."))}\n`);
|
|
2398
|
+
this.printGrouped(plan.entries, "plan");
|
|
2399
|
+
this.log("");
|
|
2400
|
+
}
|
|
2401
|
+
plan(plan) {
|
|
2402
|
+
for (const line of PLAN_HEADER) this.log(line);
|
|
2403
|
+
this.printGrouped(plan.entries, "plan");
|
|
2404
|
+
this.log("");
|
|
2405
|
+
}
|
|
2406
|
+
result(result) {
|
|
2407
|
+
this.log("");
|
|
2408
|
+
this.log(`${this.colors.green(this.colors.bold("Schema synced successfully."))} Hash: ${result.schemaHash}`);
|
|
2409
|
+
this.log("");
|
|
2410
|
+
this.printGrouped(result.entries, "result");
|
|
2411
|
+
this.log("");
|
|
2412
|
+
}
|
|
2413
|
+
printGrouped(entries, mode) {
|
|
2414
|
+
const tables = entries.filter((e) => !e.viewType);
|
|
2415
|
+
const views = entries.filter((e) => e.viewType);
|
|
2416
|
+
if (tables.length > 0) {
|
|
2417
|
+
this.log(this.colors.bold("Tables:"));
|
|
2418
|
+
for (const e of tables) for (const line of e.print(mode, this.colors)) this.log(line);
|
|
2419
|
+
}
|
|
2420
|
+
if (views.length > 0) {
|
|
2421
|
+
if (tables.length > 0) this.log("");
|
|
2422
|
+
this.log(this.colors.bold("Views:"));
|
|
2423
|
+
for (const e of views) for (const line of e.print(mode, this.colors)) this.log(line);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
constructor() {
|
|
2427
|
+
_define_property$1(this, "colors", DYE_COLORS);
|
|
2428
|
+
}
|
|
2429
|
+
};
|
|
2430
|
+
|
|
2431
|
+
//#endregion
|
|
2432
|
+
//#region packages/typescript/src/cli/db-sync.controller.ts
|
|
2433
|
+
function _define_property(obj, key, value) {
|
|
2434
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
2435
|
+
value,
|
|
2436
|
+
enumerable: true,
|
|
2437
|
+
configurable: true,
|
|
2438
|
+
writable: true
|
|
2439
|
+
});
|
|
2440
|
+
else obj[key] = value;
|
|
2441
|
+
return obj;
|
|
2442
|
+
}
|
|
2443
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2444
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2445
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2446
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2447
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2448
|
+
}
|
|
2449
|
+
function _ts_metadata(k, v) {
|
|
2450
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2451
|
+
}
|
|
2452
|
+
function _ts_param(paramIndex, decorator) {
|
|
2453
|
+
return function(target, key) {
|
|
2454
|
+
decorator(target, key, paramIndex);
|
|
2455
|
+
};
|
|
2456
|
+
}
|
|
2457
|
+
var DbSyncController = class {
|
|
2458
|
+
async dbSync(configFile, dryRun, yes, force, safe) {
|
|
2459
|
+
const config = await getConfig(configFile, this.logger);
|
|
2460
|
+
if (!config.db) {
|
|
2461
|
+
this.logger.error(`${"\x1B[31m"}No "db" field in atscript config. ` + `Add a db configuration to use schema sync.${"\x1B[39m"}`);
|
|
2462
|
+
process.exit(1);
|
|
2463
|
+
}
|
|
2464
|
+
const [dbSpace, dbTypes] = await Promise.all([this.resolveDbSpace(config.db), this.compileAndLoadTypes(config)]);
|
|
2465
|
+
if (dbTypes.length === 0) {
|
|
2466
|
+
this.logger.log(`No types with @db.table or @db.view found. Nothing to sync.`);
|
|
2467
|
+
return;
|
|
2468
|
+
}
|
|
2469
|
+
this.printer.typeCount(dbTypes.length);
|
|
2470
|
+
this.printer.banner();
|
|
2471
|
+
const { SchemaSync } = await this.importFromCwd("@atscript/utils-db/sync", true);
|
|
2472
|
+
const sync = new SchemaSync(dbSpace);
|
|
2473
|
+
const plan = await sync.plan(dbTypes, {
|
|
2474
|
+
force,
|
|
2475
|
+
safe
|
|
2476
|
+
});
|
|
2477
|
+
if (plan.status === "up-to-date") {
|
|
2478
|
+
this.printer.planUpToDate(plan);
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
const hasDestructive = plan.entries.some((e) => e.destructive);
|
|
2482
|
+
const hasChanges = plan.entries.some((e) => e.hasChanges);
|
|
2483
|
+
const hasErrors = plan.entries.some((e) => e.hasErrors);
|
|
2484
|
+
this.printer.plan(plan);
|
|
2485
|
+
if (hasErrors) {
|
|
2486
|
+
this.logger.error(`Schema has errors. Fix the issues above before syncing.`);
|
|
2487
|
+
process.exit(1);
|
|
2488
|
+
}
|
|
2489
|
+
if (!hasChanges) {
|
|
2490
|
+
if (!dryRun) await sync.run(dbTypes, {
|
|
2491
|
+
force: true,
|
|
2492
|
+
safe
|
|
2493
|
+
});
|
|
2494
|
+
return;
|
|
2495
|
+
}
|
|
2496
|
+
if (dryRun) {
|
|
2497
|
+
this.logger.log(`Dry run — no changes applied.`);
|
|
2498
|
+
return;
|
|
2499
|
+
}
|
|
2500
|
+
if (hasDestructive) {
|
|
2501
|
+
if (!yes) {
|
|
2502
|
+
const confirmed = await this.confirm("Apply these changes? (includes destructive operations)");
|
|
2503
|
+
if (!confirmed) {
|
|
2504
|
+
this.logger.log("Aborted.");
|
|
2505
|
+
return;
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
} else this.logger.log(`No destructive changes, proceeding to sync...`);
|
|
2509
|
+
const result = await sync.run(dbTypes, {
|
|
2510
|
+
force: true,
|
|
2511
|
+
safe
|
|
2512
|
+
});
|
|
2513
|
+
this.printer.result(result);
|
|
2514
|
+
}
|
|
2515
|
+
async compileAndLoadTypes(config) {
|
|
2516
|
+
const buildConfig = { ...config };
|
|
2517
|
+
if (typeof config.db === "object" && "adapter" in config.db) {
|
|
2518
|
+
const dbConfig = config.db;
|
|
2519
|
+
if (dbConfig.include) buildConfig.include = dbConfig.include;
|
|
2520
|
+
if (dbConfig.exclude) buildConfig.exclude = dbConfig.exclude;
|
|
2521
|
+
}
|
|
2522
|
+
buildConfig.format = "js";
|
|
2523
|
+
this.logger.log(`Compiling .as files...`);
|
|
2524
|
+
const builder = await (0, __atscript_core.build)(buildConfig);
|
|
2525
|
+
const outputs = await builder.generate(buildConfig);
|
|
2526
|
+
const jsOutputs = outputs.filter((o) => o.fileName.endsWith(".js"));
|
|
2527
|
+
const tmpDir = path.default.join(process.cwd(), `.atscript-db-sync-${Date.now()}`);
|
|
2528
|
+
const writtenFiles = [];
|
|
2529
|
+
for (const o of jsOutputs) {
|
|
2530
|
+
const target = path.default.join(tmpDir, o.fileName.replace(/\.js$/, ".mjs"));
|
|
2531
|
+
(0, fs.mkdirSync)(path.default.dirname(target), { recursive: true });
|
|
2532
|
+
(0, fs.writeFileSync)(target, patchAsImports(o.content));
|
|
2533
|
+
writtenFiles.push(target);
|
|
2534
|
+
}
|
|
2535
|
+
const dbTypes = [];
|
|
2536
|
+
try {
|
|
2537
|
+
for (const file of writtenFiles) {
|
|
2538
|
+
const mod = await import(
|
|
2539
|
+
/* @vite-ignore */
|
|
2540
|
+
(0, node_url.pathToFileURL)(file).href
|
|
2541
|
+
);
|
|
2542
|
+
for (const exp of Object.values(mod)) if (isAnnotatedType(exp) && (exp.metadata?.has("db.table") || exp.metadata?.has("db.view"))) dbTypes.push(exp);
|
|
2543
|
+
}
|
|
2544
|
+
} catch (error) {
|
|
2545
|
+
this.logger.warn?.(`Could not import compiled types: ${error}`);
|
|
2546
|
+
} finally {
|
|
2547
|
+
try {
|
|
2548
|
+
(0, fs.rmSync)(tmpDir, {
|
|
2549
|
+
recursive: true,
|
|
2550
|
+
force: true
|
|
2551
|
+
});
|
|
2552
|
+
} catch {}
|
|
2553
|
+
}
|
|
2554
|
+
return dbTypes;
|
|
2555
|
+
}
|
|
2556
|
+
async resolveDbSpace(dbConfig) {
|
|
2557
|
+
if (typeof dbConfig === "function") {
|
|
2558
|
+
this.logger.log(`Resolving database space from callback...`);
|
|
2559
|
+
return await dbConfig();
|
|
2560
|
+
}
|
|
2561
|
+
const { adapter, connection, options } = dbConfig;
|
|
2562
|
+
this.logger.log(`Using adapter: ${"\x1B[36m"}${adapter}${"\x1B[39m"}`);
|
|
2563
|
+
let mod;
|
|
2564
|
+
try {
|
|
2565
|
+
mod = await this.importFromCwd(adapter);
|
|
2566
|
+
} catch {
|
|
2567
|
+
this.logger.error(`${"\x1B[31m"}Could not import adapter package "${adapter}". Is it installed?${"\x1B[39m"}`);
|
|
2568
|
+
process.exit(1);
|
|
2569
|
+
}
|
|
2570
|
+
if (typeof mod.createAdapter !== "function") {
|
|
2571
|
+
this.logger.error(`${"\x1B[31m"}Adapter package "${adapter}" does not export a createAdapter function.${"\x1B[39m"}`);
|
|
2572
|
+
process.exit(1);
|
|
2573
|
+
}
|
|
2574
|
+
const resolvedConnection = typeof connection === "function" ? await connection() : connection;
|
|
2575
|
+
return mod.createAdapter(resolvedConnection, options);
|
|
2576
|
+
}
|
|
2577
|
+
async importFromCwd(specifier, preferEsm = false) {
|
|
2578
|
+
const require$1 = (0, node_module.createRequire)(path.default.join(process.cwd(), "__synthetic.cjs"));
|
|
2579
|
+
let resolved = require$1.resolve(specifier);
|
|
2580
|
+
if (preferEsm) {
|
|
2581
|
+
const mjsPath = resolved.replace(/\.cjs$/, ".mjs");
|
|
2582
|
+
if ((0, fs.existsSync)(mjsPath)) resolved = mjsPath;
|
|
2583
|
+
}
|
|
2584
|
+
return import(
|
|
2585
|
+
/* @vite-ignore */
|
|
2586
|
+
(0, node_url.pathToFileURL)(resolved).href
|
|
2587
|
+
);
|
|
2588
|
+
}
|
|
2589
|
+
async confirm(message) {
|
|
2590
|
+
const rl = (0, node_readline.createInterface)({
|
|
2591
|
+
input: process.stdin,
|
|
2592
|
+
output: process.stdout
|
|
2593
|
+
});
|
|
2594
|
+
return new Promise((resolve) => {
|
|
2595
|
+
rl.question(`${message} [y/N] `, (answer) => {
|
|
2596
|
+
rl.close();
|
|
2597
|
+
resolve(answer.trim().toLowerCase() === "y");
|
|
2598
|
+
});
|
|
2599
|
+
});
|
|
2600
|
+
}
|
|
2601
|
+
constructor(logger) {
|
|
2602
|
+
_define_property(this, "logger", void 0);
|
|
2603
|
+
_define_property(this, "printer", void 0);
|
|
2604
|
+
this.logger = logger;
|
|
2605
|
+
this.printer = new DbSyncPrinter();
|
|
2606
|
+
}
|
|
2607
|
+
};
|
|
2608
|
+
_ts_decorate([
|
|
2609
|
+
(0, __moostjs_event_cli.Cli)("db sync"),
|
|
2610
|
+
(0, moost.Description)("Synchronize database schema with .as type definitions"),
|
|
2611
|
+
(0, __moostjs_event_cli.CliExample)("db sync", "Interactive sync — shows plan, prompts, then applies"),
|
|
2612
|
+
(0, __moostjs_event_cli.CliExample)("db sync --dry-run", "Show what would change without applying"),
|
|
2613
|
+
(0, __moostjs_event_cli.CliExample)("db sync --yes", "Skip confirmation prompt (CI mode)"),
|
|
2614
|
+
(0, __moostjs_event_cli.CliExample)("db sync --force", "Re-sync even if schema hash matches"),
|
|
2615
|
+
(0, __moostjs_event_cli.CliExample)("db sync --safe", "Skip destructive operations (column/table drops)"),
|
|
2184
2616
|
_ts_param(0, (0, __moostjs_event_cli.CliOption)("c", "config")),
|
|
2185
2617
|
_ts_param(0, (0, moost.Optional)()),
|
|
2186
2618
|
_ts_param(0, (0, moost.Description)("Path to config file")),
|
|
2187
|
-
_ts_param(1, (0, __moostjs_event_cli.CliOption)("
|
|
2619
|
+
_ts_param(1, (0, __moostjs_event_cli.CliOption)("dry-run")),
|
|
2188
2620
|
_ts_param(1, (0, moost.Optional)()),
|
|
2189
|
-
_ts_param(1, (0, moost.Description)("
|
|
2190
|
-
_ts_param(2, (0, __moostjs_event_cli.CliOption)("
|
|
2621
|
+
_ts_param(1, (0, moost.Description)("Show plan only, do not apply changes")),
|
|
2622
|
+
_ts_param(2, (0, __moostjs_event_cli.CliOption)("yes")),
|
|
2191
2623
|
_ts_param(2, (0, moost.Optional)()),
|
|
2192
|
-
_ts_param(2, (0, moost.Description)("
|
|
2193
|
-
_ts_param(3, (0, __moostjs_event_cli.CliOption)("
|
|
2624
|
+
_ts_param(2, (0, moost.Description)("Skip confirmation prompt (CI mode)")),
|
|
2625
|
+
_ts_param(3, (0, __moostjs_event_cli.CliOption)("force")),
|
|
2194
2626
|
_ts_param(3, (0, moost.Optional)()),
|
|
2195
|
-
_ts_param(3, (0, moost.Description)("
|
|
2627
|
+
_ts_param(3, (0, moost.Description)("Ignore schema hash, re-sync even if up-to-date")),
|
|
2628
|
+
_ts_param(4, (0, __moostjs_event_cli.CliOption)("safe")),
|
|
2629
|
+
_ts_param(4, (0, moost.Optional)()),
|
|
2630
|
+
_ts_param(4, (0, moost.Description)("Skip destructive operations (column/table drops)")),
|
|
2196
2631
|
_ts_metadata("design:type", Function),
|
|
2197
2632
|
_ts_metadata("design:paramtypes", [
|
|
2198
2633
|
String,
|
|
2199
|
-
|
|
2634
|
+
Boolean,
|
|
2635
|
+
Boolean,
|
|
2200
2636
|
Boolean,
|
|
2201
2637
|
Boolean
|
|
2202
2638
|
]),
|
|
2203
2639
|
_ts_metadata("design:returntype", Promise)
|
|
2204
|
-
],
|
|
2205
|
-
|
|
2640
|
+
], DbSyncController.prototype, "dbSync", null);
|
|
2641
|
+
DbSyncController = _ts_decorate([
|
|
2206
2642
|
(0, moost.Controller)(),
|
|
2207
2643
|
_ts_param(0, (0, moost.InjectMoostLogger)("asc")),
|
|
2208
2644
|
_ts_metadata("design:type", Function),
|
|
2209
2645
|
_ts_metadata("design:paramtypes", [typeof TConsoleBase === "undefined" ? Object : TConsoleBase])
|
|
2210
|
-
],
|
|
2646
|
+
], DbSyncController);
|
|
2647
|
+
function patchAsImports(content) {
|
|
2648
|
+
return content.replace(/(from\s+["'][^"']+)\.as(["'])/g, "$1.as.mjs$2");
|
|
2649
|
+
}
|
|
2211
2650
|
|
|
2212
2651
|
//#endregion
|
|
2213
2652
|
//#region packages/typescript/src/cli/cli.ts
|
|
2214
|
-
new __moostjs_event_cli.CliApp().controllers(Commands).useHelp({ name: "asc" }).useOptions([{
|
|
2653
|
+
new __moostjs_event_cli.CliApp().controllers(Commands, DbSyncController).useHelp({ name: "asc" }).useOptions([{
|
|
2215
2654
|
keys: ["help"],
|
|
2216
2655
|
description: "Display instructions for the command."
|
|
2217
2656
|
}]).start();
|