@atscript/typescript 0.1.33 → 0.1.35
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 +607 -126
- package/dist/index.cjs +171 -778
- package/dist/index.mjs +163 -770
- package/dist/json-schema-0UUPoHud.mjs +952 -0
- package/dist/json-schema-S5-XAOrR.cjs +1030 -0
- package/dist/utils.cjs +80 -945
- package/dist/utils.d.ts +64 -6
- package/dist/utils.mjs +58 -923
- 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
|
|
|
@@ -1058,7 +1107,8 @@ function createAnnotatedTypeNode(type, metadata, opts) {
|
|
|
1058
1107
|
metadata,
|
|
1059
1108
|
validator: validatorMethod,
|
|
1060
1109
|
id: opts?.id,
|
|
1061
|
-
optional: opts?.optional
|
|
1110
|
+
optional: opts?.optional,
|
|
1111
|
+
ref: opts?.ref
|
|
1062
1112
|
};
|
|
1063
1113
|
}
|
|
1064
1114
|
function isAnnotatedType(type) {
|
|
@@ -1135,18 +1185,57 @@ function defineAnnotatedType(_kind, base) {
|
|
|
1135
1185
|
return this;
|
|
1136
1186
|
},
|
|
1137
1187
|
refTo(type$1, chain) {
|
|
1138
|
-
if (
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1188
|
+
if (isAnnotatedType(type$1)) {
|
|
1189
|
+
let newBase = type$1;
|
|
1190
|
+
const typeName = type$1.name || "Unknown";
|
|
1191
|
+
if (chain) for (let i = 0; i < chain.length; i++) {
|
|
1192
|
+
const c = chain[i];
|
|
1193
|
+
if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
|
|
1144
1194
|
else {
|
|
1145
|
-
|
|
1146
|
-
|
|
1195
|
+
const keys = chain.slice(0, i + 1).map((k) => `["${k}"]`).join("");
|
|
1196
|
+
throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
1197
|
+
}
|
|
1147
1198
|
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1199
|
+
this.$type = createAnnotatedTypeNode(newBase.type, metadata, {
|
|
1200
|
+
id: newBase.id,
|
|
1201
|
+
ref: chain && chain.length > 0 ? {
|
|
1202
|
+
type: () => type$1,
|
|
1203
|
+
field: chain.join(".")
|
|
1204
|
+
} : undefined
|
|
1205
|
+
});
|
|
1206
|
+
} else if (typeof type$1 === "function") {
|
|
1207
|
+
const lazyType = type$1;
|
|
1208
|
+
this.$type = createAnnotatedTypeNode({ kind: "" }, metadata, { ref: {
|
|
1209
|
+
type: lazyType,
|
|
1210
|
+
field: chain ? chain.join(".") : ""
|
|
1211
|
+
} });
|
|
1212
|
+
const node = this.$type;
|
|
1213
|
+
const placeholder = node.type;
|
|
1214
|
+
Object.defineProperty(node, "type", {
|
|
1215
|
+
get() {
|
|
1216
|
+
const t = lazyType();
|
|
1217
|
+
if (!isAnnotatedType(t)) {
|
|
1218
|
+
Object.defineProperty(node, "type", {
|
|
1219
|
+
value: placeholder,
|
|
1220
|
+
writable: false,
|
|
1221
|
+
configurable: true
|
|
1222
|
+
});
|
|
1223
|
+
return placeholder;
|
|
1224
|
+
}
|
|
1225
|
+
let target = t;
|
|
1226
|
+
if (chain) for (const c of chain) if (target.type.kind === "object" && target.type.props.has(c)) target = target.type.props.get(c);
|
|
1227
|
+
else return t.type;
|
|
1228
|
+
node.id = chain ? target.id : target.id || t.id;
|
|
1229
|
+
Object.defineProperty(node, "type", {
|
|
1230
|
+
value: target.type,
|
|
1231
|
+
writable: false,
|
|
1232
|
+
configurable: true
|
|
1233
|
+
});
|
|
1234
|
+
return target.type;
|
|
1235
|
+
},
|
|
1236
|
+
configurable: true
|
|
1237
|
+
});
|
|
1238
|
+
} else throw new TypeError(`${type$1} is not annotated type`);
|
|
1150
1239
|
return this;
|
|
1151
1240
|
},
|
|
1152
1241
|
annotate(key, value, asArray) {
|
|
@@ -1234,7 +1323,7 @@ function buildJsonSchema(type) {
|
|
|
1234
1323
|
const required = [];
|
|
1235
1324
|
for (const [key, val] of d.type.props.entries()) {
|
|
1236
1325
|
if (isPhantomType(val)) continue;
|
|
1237
|
-
properties[key] = build$
|
|
1326
|
+
properties[key] = build$2(val);
|
|
1238
1327
|
if (!val.optional) required.push(key);
|
|
1239
1328
|
}
|
|
1240
1329
|
const schema$1 = {
|
|
@@ -1244,7 +1333,7 @@ function buildJsonSchema(type) {
|
|
|
1244
1333
|
if (required.length > 0) schema$1.required = required;
|
|
1245
1334
|
return schema$1;
|
|
1246
1335
|
};
|
|
1247
|
-
const build$
|
|
1336
|
+
const build$2 = (def) => {
|
|
1248
1337
|
if (def.id && def.type.kind === "object" && def !== type) {
|
|
1249
1338
|
const name = def.id;
|
|
1250
1339
|
if (!defs[name]) {
|
|
@@ -1265,7 +1354,7 @@ function buildJsonSchema(type) {
|
|
|
1265
1354
|
array(d) {
|
|
1266
1355
|
const schema$1 = {
|
|
1267
1356
|
type: "array",
|
|
1268
|
-
items: build$
|
|
1357
|
+
items: build$2(d.type.of)
|
|
1269
1358
|
};
|
|
1270
1359
|
const minLength = meta.get("expect.minLength");
|
|
1271
1360
|
if (minLength) schema$1.minItems = typeof minLength === "number" ? minLength : minLength.length;
|
|
@@ -1276,7 +1365,7 @@ function buildJsonSchema(type) {
|
|
|
1276
1365
|
union(d) {
|
|
1277
1366
|
const disc = detectDiscriminator(d.type.items);
|
|
1278
1367
|
if (disc) {
|
|
1279
|
-
const oneOf = d.type.items.map(build$
|
|
1368
|
+
const oneOf = d.type.items.map(build$2);
|
|
1280
1369
|
const mapping = {};
|
|
1281
1370
|
for (const [val, idx] of Object.entries(disc.indexMapping)) {
|
|
1282
1371
|
const item = d.type.items[idx];
|
|
@@ -1290,15 +1379,15 @@ function buildJsonSchema(type) {
|
|
|
1290
1379
|
}
|
|
1291
1380
|
};
|
|
1292
1381
|
}
|
|
1293
|
-
return { anyOf: d.type.items.map(build$
|
|
1382
|
+
return { anyOf: d.type.items.map(build$2) };
|
|
1294
1383
|
},
|
|
1295
1384
|
intersection(d) {
|
|
1296
|
-
return { allOf: d.type.items.map(build$
|
|
1385
|
+
return { allOf: d.type.items.map(build$2) };
|
|
1297
1386
|
},
|
|
1298
1387
|
tuple(d) {
|
|
1299
1388
|
return {
|
|
1300
1389
|
type: "array",
|
|
1301
|
-
items: d.type.items.map(build$
|
|
1390
|
+
items: d.type.items.map(build$2),
|
|
1302
1391
|
additionalItems: false
|
|
1303
1392
|
};
|
|
1304
1393
|
},
|
|
@@ -1329,7 +1418,7 @@ else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ patte
|
|
|
1329
1418
|
}
|
|
1330
1419
|
});
|
|
1331
1420
|
};
|
|
1332
|
-
const schema = build$
|
|
1421
|
+
const schema = build$2(type);
|
|
1333
1422
|
if (hasDefs) return {
|
|
1334
1423
|
...schema,
|
|
1335
1424
|
$defs: defs
|
|
@@ -1339,7 +1428,7 @@ else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ patte
|
|
|
1339
1428
|
|
|
1340
1429
|
//#endregion
|
|
1341
1430
|
//#region packages/typescript/src/codegen/js-renderer.ts
|
|
1342
|
-
function _define_property$
|
|
1431
|
+
function _define_property$3(obj, key, value) {
|
|
1343
1432
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
1344
1433
|
value,
|
|
1345
1434
|
enumerable: true,
|
|
@@ -1349,6 +1438,19 @@ function _define_property$1(obj, key, value) {
|
|
|
1349
1438
|
else obj[key] = value;
|
|
1350
1439
|
return obj;
|
|
1351
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
|
+
};
|
|
1352
1454
|
var JsRenderer = class extends BaseRenderer {
|
|
1353
1455
|
pre() {
|
|
1354
1456
|
this.writeln("// prettier-ignore-start");
|
|
@@ -1377,12 +1479,12 @@ else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}_
|
|
|
1377
1479
|
buildAdHocMap(annotateNodes) {
|
|
1378
1480
|
const map = new Map();
|
|
1379
1481
|
for (const annotateNode of annotateNodes) for (const entry of annotateNode.entries) {
|
|
1380
|
-
const path$
|
|
1482
|
+
const path$4 = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)].join(".") : entry.id;
|
|
1381
1483
|
const anns = entry.annotations || [];
|
|
1382
1484
|
if (anns.length > 0) {
|
|
1383
|
-
const existing = map.get(path$
|
|
1485
|
+
const existing = map.get(path$4);
|
|
1384
1486
|
if (existing) existing.push(...anns);
|
|
1385
|
-
else map.set(path$
|
|
1487
|
+
else map.set(path$4, [...anns]);
|
|
1386
1488
|
}
|
|
1387
1489
|
}
|
|
1388
1490
|
return map.size > 0 ? map : null;
|
|
@@ -1631,8 +1733,8 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1631
1733
|
const ref = node;
|
|
1632
1734
|
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
1633
1735
|
if ((0, __atscript_core.isPrimitive)(decl)) {
|
|
1634
|
-
const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1635
|
-
if (!ownerDecl?.node || ownerDecl.node.entity !== "type" && ownerDecl.node.entity !== "interface") {
|
|
1736
|
+
const ownerDecl$1 = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1737
|
+
if (!ownerDecl$1?.node || ownerDecl$1.node.entity !== "type" && ownerDecl$1.node.entity !== "interface") {
|
|
1636
1738
|
this.annotateType(decl, name);
|
|
1637
1739
|
return this;
|
|
1638
1740
|
}
|
|
@@ -1646,9 +1748,11 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1646
1748
|
}
|
|
1647
1749
|
}
|
|
1648
1750
|
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
1649
|
-
|
|
1751
|
+
const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1752
|
+
const isImported = ownerDecl ? ownerDecl.doc !== this.doc : false;
|
|
1753
|
+
const refExpr = isImported ? `() => ${ref.id}` : ref.id;
|
|
1754
|
+
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${refExpr}${chain})`);
|
|
1650
1755
|
if (!ref.hasChain) {
|
|
1651
|
-
const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1652
1756
|
if (ownerDecl?.node) {
|
|
1653
1757
|
const typeAnnotations = ownerDecl.doc.evalAnnotationsForNode(ownerDecl.node);
|
|
1654
1758
|
typeAnnotations?.forEach((an) => {
|
|
@@ -1815,8 +1919,8 @@ else if (resolved && (0, __atscript_core.isPrimitive)(resolved)) {
|
|
|
1815
1919
|
}
|
|
1816
1920
|
if (annotations === undefined) annotations = this.doc.evalAnnotationsForNode(node);
|
|
1817
1921
|
if (this._adHocAnnotations && this._propPath.length > 0) {
|
|
1818
|
-
const path$
|
|
1819
|
-
const adHoc = this._adHocAnnotations.get(path$
|
|
1922
|
+
const path$4 = this._propPath.join(".");
|
|
1923
|
+
const adHoc = this._adHocAnnotations.get(path$4);
|
|
1820
1924
|
if (adHoc) annotations = this.doc.mergeNodesAnnotations(annotations, adHoc);
|
|
1821
1925
|
}
|
|
1822
1926
|
annotations?.forEach((an) => {
|
|
@@ -1842,6 +1946,68 @@ else if (resolved && (0, __atscript_core.isPrimitive)(resolved)) {
|
|
|
1842
1946
|
if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value}, true)`);
|
|
1843
1947
|
else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
1844
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
|
+
}
|
|
1845
2011
|
computeAnnotationValue(node, an) {
|
|
1846
2012
|
const spec = this.doc.resolveAnnotation(an.name);
|
|
1847
2013
|
let targetValue = "true";
|
|
@@ -1853,13 +2019,13 @@ else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
|
1853
2019
|
targetValue = "{ ";
|
|
1854
2020
|
let i = 0;
|
|
1855
2021
|
for (const aSpec of spec.arguments) {
|
|
1856
|
-
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 ? "" : ", "} `;
|
|
1857
2023
|
i++;
|
|
1858
2024
|
}
|
|
1859
2025
|
targetValue += "}";
|
|
1860
2026
|
} else {
|
|
1861
2027
|
const aSpec = spec.arguments[0];
|
|
1862
|
-
if (an.args[0]) targetValue = aSpec
|
|
2028
|
+
if (an.args[0]) targetValue = this.emitArgValue(aSpec, an.args[0]);
|
|
1863
2029
|
else targetValue = "true";
|
|
1864
2030
|
}
|
|
1865
2031
|
} else {
|
|
@@ -1999,7 +2165,7 @@ else {
|
|
|
1999
2165
|
return [];
|
|
2000
2166
|
}
|
|
2001
2167
|
constructor(doc, opts) {
|
|
2002
|
-
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();
|
|
2003
2169
|
}
|
|
2004
2170
|
};
|
|
2005
2171
|
|
|
@@ -2030,8 +2196,8 @@ const tsPlugin = (opts) => {
|
|
|
2030
2196
|
for (const [key, val] of Object.entries(annotations)) {
|
|
2031
2197
|
const multiple = val.multiple;
|
|
2032
2198
|
const typeLine = Array.from(val.types).map((t) => {
|
|
2033
|
-
if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
2034
|
-
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;
|
|
2035
2201
|
}).join(" | ");
|
|
2036
2202
|
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
2037
2203
|
}
|
|
@@ -2047,9 +2213,35 @@ else return t.optional ? `${t.type} | true` : t.type;
|
|
|
2047
2213
|
};
|
|
2048
2214
|
};
|
|
2049
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
|
+
|
|
2050
2242
|
//#endregion
|
|
2051
2243
|
//#region packages/typescript/src/cli/commands.controller.ts
|
|
2052
|
-
function _define_property(obj, key, value) {
|
|
2244
|
+
function _define_property$2(obj, key, value) {
|
|
2053
2245
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
2054
2246
|
value,
|
|
2055
2247
|
enumerable: true,
|
|
@@ -2059,23 +2251,23 @@ function _define_property(obj, key, value) {
|
|
|
2059
2251
|
else obj[key] = value;
|
|
2060
2252
|
return obj;
|
|
2061
2253
|
}
|
|
2062
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
2254
|
+
function _ts_decorate$1(decorators, target, key, desc) {
|
|
2063
2255
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2064
2256
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2065
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;
|
|
2066
2258
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2067
2259
|
}
|
|
2068
|
-
function _ts_metadata(k, v) {
|
|
2260
|
+
function _ts_metadata$1(k, v) {
|
|
2069
2261
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2070
2262
|
}
|
|
2071
|
-
function _ts_param(paramIndex, decorator) {
|
|
2263
|
+
function _ts_param$1(paramIndex, decorator) {
|
|
2072
2264
|
return function(target, key) {
|
|
2073
2265
|
decorator(target, key, paramIndex);
|
|
2074
2266
|
};
|
|
2075
2267
|
}
|
|
2076
2268
|
var Commands = class {
|
|
2077
2269
|
async default(configFile, format, noEmit, skipDiag) {
|
|
2078
|
-
const config = await
|
|
2270
|
+
const config = await getConfig(configFile, this.logger);
|
|
2079
2271
|
config.format = format || __atscript_core.DEFAULT_FORMAT;
|
|
2080
2272
|
this.logger.log(`Format: ${"\x1B[36m"}${config.format}${"\x1B[39m"}`);
|
|
2081
2273
|
const builder = await (0, __atscript_core.build)(config);
|
|
@@ -2104,72 +2296,361 @@ else if (m.severity === 2) warningCount++;
|
|
|
2104
2296
|
}
|
|
2105
2297
|
if (errorCount > 0) process.exit(1);
|
|
2106
2298
|
}
|
|
2107
|
-
async getConfig(configFile) {
|
|
2108
|
-
const root = process.cwd();
|
|
2109
|
-
if (configFile) {
|
|
2110
|
-
const c = path.default.join(root, configFile);
|
|
2111
|
-
if (!(0, fs.existsSync)(c)) {
|
|
2112
|
-
this.logger.error(`Config file ${"\x1B[4m"}${configFile}${"\x1B[24m"} not found`);
|
|
2113
|
-
process.exit(1);
|
|
2114
|
-
}
|
|
2115
|
-
this.logger.log(`Using config file ${"\x1B[36m"}${configFile}${"\x1B[39m"}`);
|
|
2116
|
-
return (0, __atscript_core.loadConfig)(c);
|
|
2117
|
-
} else {
|
|
2118
|
-
const resolved = await (0, __atscript_core.resolveConfigFile)(root);
|
|
2119
|
-
if (resolved) {
|
|
2120
|
-
this.logger.log(`Using config file ${"\x1B[36m"}${resolved}${"\x1B[39m"}`);
|
|
2121
|
-
return (0, __atscript_core.loadConfig)(resolved);
|
|
2122
|
-
}
|
|
2123
|
-
this.logger.log(`No atscript config file found`);
|
|
2124
|
-
return {
|
|
2125
|
-
format: __atscript_core.DEFAULT_FORMAT,
|
|
2126
|
-
plugins: [tsPlugin()]
|
|
2127
|
-
};
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
2299
|
constructor(logger) {
|
|
2131
|
-
_define_property(this, "logger", void 0);
|
|
2300
|
+
_define_property$2(this, "logger", void 0);
|
|
2132
2301
|
this.logger = logger;
|
|
2133
2302
|
}
|
|
2134
2303
|
};
|
|
2135
|
-
_ts_decorate([
|
|
2304
|
+
_ts_decorate$1([
|
|
2136
2305
|
(0, __moostjs_event_cli.Cli)(""),
|
|
2137
2306
|
(0, moost.Description)("Builds .as files using --config and --format"),
|
|
2138
2307
|
(0, __moostjs_event_cli.CliExample)("-c atscript.config.js", "Build .as files using atscript.config.js"),
|
|
2139
2308
|
(0, __moostjs_event_cli.CliExample)("-f dts", "Build \"d.ts\" files for \".as\" files"),
|
|
2140
2309
|
(0, __moostjs_event_cli.CliExample)("--noEmit", "Only check for errors, do not emit files"),
|
|
2141
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)"),
|
|
2142
2616
|
_ts_param(0, (0, __moostjs_event_cli.CliOption)("c", "config")),
|
|
2143
2617
|
_ts_param(0, (0, moost.Optional)()),
|
|
2144
2618
|
_ts_param(0, (0, moost.Description)("Path to config file")),
|
|
2145
|
-
_ts_param(1, (0, __moostjs_event_cli.CliOption)("
|
|
2619
|
+
_ts_param(1, (0, __moostjs_event_cli.CliOption)("dry-run")),
|
|
2146
2620
|
_ts_param(1, (0, moost.Optional)()),
|
|
2147
|
-
_ts_param(1, (0, moost.Description)("
|
|
2148
|
-
_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")),
|
|
2149
2623
|
_ts_param(2, (0, moost.Optional)()),
|
|
2150
|
-
_ts_param(2, (0, moost.Description)("
|
|
2151
|
-
_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")),
|
|
2152
2626
|
_ts_param(3, (0, moost.Optional)()),
|
|
2153
|
-
_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)")),
|
|
2154
2631
|
_ts_metadata("design:type", Function),
|
|
2155
2632
|
_ts_metadata("design:paramtypes", [
|
|
2156
2633
|
String,
|
|
2157
|
-
|
|
2634
|
+
Boolean,
|
|
2635
|
+
Boolean,
|
|
2158
2636
|
Boolean,
|
|
2159
2637
|
Boolean
|
|
2160
2638
|
]),
|
|
2161
2639
|
_ts_metadata("design:returntype", Promise)
|
|
2162
|
-
],
|
|
2163
|
-
|
|
2640
|
+
], DbSyncController.prototype, "dbSync", null);
|
|
2641
|
+
DbSyncController = _ts_decorate([
|
|
2164
2642
|
(0, moost.Controller)(),
|
|
2165
2643
|
_ts_param(0, (0, moost.InjectMoostLogger)("asc")),
|
|
2166
2644
|
_ts_metadata("design:type", Function),
|
|
2167
2645
|
_ts_metadata("design:paramtypes", [typeof TConsoleBase === "undefined" ? Object : TConsoleBase])
|
|
2168
|
-
],
|
|
2646
|
+
], DbSyncController);
|
|
2647
|
+
function patchAsImports(content) {
|
|
2648
|
+
return content.replace(/(from\s+["'][^"']+)\.as(["'])/g, "$1.as.mjs$2");
|
|
2649
|
+
}
|
|
2169
2650
|
|
|
2170
2651
|
//#endregion
|
|
2171
2652
|
//#region packages/typescript/src/cli/cli.ts
|
|
2172
|
-
new __moostjs_event_cli.CliApp().controllers(Commands).useHelp({ name: "asc" }).useOptions([{
|
|
2653
|
+
new __moostjs_event_cli.CliApp().controllers(Commands, DbSyncController).useHelp({ name: "asc" }).useOptions([{
|
|
2173
2654
|
keys: ["help"],
|
|
2174
2655
|
description: "Display instructions for the command."
|
|
2175
2656
|
}]).start();
|