@atscript/typescript 0.1.88 → 0.1.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +664 -434
- package/dist/index.cjs +4 -5
- package/dist/index.mjs +1 -2
- package/dist/{json-schema-3mti4G4J.cjs → json-schema-DXEiCfe1.cjs} +206 -97
- package/dist/{json-schema-B64qclVa.mjs → json-schema-DycaD0Rm.mjs} +207 -98
- package/dist/{plugin-CZ5g5D9I.cjs → plugin-Cs9mKJ8h.cjs} +180 -215
- package/dist/{plugin-CYzZm3rk.mjs → plugin-DHhdrTs8.mjs} +118 -157
- package/dist/test-utils.cjs +16 -9
- package/dist/test-utils.mjs +9 -3
- package/dist/utils.cjs +176 -106
- package/dist/utils.mjs +153 -83
- package/package.json +4 -4
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
//#region rolldown:runtime
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
5
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -7,12 +6,16 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
7
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
8
|
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
16
19
|
}
|
|
17
20
|
return to;
|
|
18
21
|
};
|
|
@@ -22,14 +25,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
25
|
}) : target, mod));
|
|
23
26
|
|
|
24
27
|
//#endregion
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
let _moostjs_event_cli = require("@moostjs/event-cli");
|
|
29
|
+
let _atscript_core = require("@atscript/core");
|
|
30
|
+
let moost = require("moost");
|
|
31
|
+
let fs = require("fs");
|
|
32
|
+
let path = require("path");
|
|
33
|
+
path = __toESM(path);
|
|
34
|
+
let node_module = require("node:module");
|
|
35
|
+
let node_readline = require("node:readline");
|
|
36
|
+
let node_url = require("node:url");
|
|
33
37
|
|
|
34
38
|
//#region packages/typescript/src/codegen/code-printer.ts
|
|
35
39
|
function _define_property$7(obj, key, value) {
|
|
@@ -39,7 +43,7 @@ function _define_property$7(obj, key, value) {
|
|
|
39
43
|
configurable: true,
|
|
40
44
|
writable: true
|
|
41
45
|
});
|
|
42
|
-
else obj[key] = value;
|
|
46
|
+
else obj[key] = value;
|
|
43
47
|
return obj;
|
|
44
48
|
}
|
|
45
49
|
var CodePrinter = class {
|
|
@@ -100,7 +104,7 @@ var CodePrinter = class {
|
|
|
100
104
|
* Return the entire code as a string. Removes any half-finished current line if empty.
|
|
101
105
|
*/ toString() {
|
|
102
106
|
if (this.currentLine.trim() !== "") this.lines.push(this.currentLine);
|
|
103
|
-
else if (this.currentLine.length > 0) this.lines.push(this.currentLine);
|
|
107
|
+
else if (this.currentLine.length > 0) this.lines.push(this.currentLine);
|
|
104
108
|
return this.lines.join("\n");
|
|
105
109
|
}
|
|
106
110
|
doBlock(pair, withNewLine) {
|
|
@@ -118,7 +122,7 @@ else if (this.currentLine.length > 0) this.lines.push(this.currentLine);
|
|
|
118
122
|
const closing = this.blockStack.pop();
|
|
119
123
|
this.unindent();
|
|
120
124
|
if (withNewLine) this.writeln(closing);
|
|
121
|
-
else this.write(closing);
|
|
125
|
+
else this.write(closing);
|
|
122
126
|
return this;
|
|
123
127
|
}
|
|
124
128
|
indentString() {
|
|
@@ -142,7 +146,7 @@ function _define_property$6(obj, key, value) {
|
|
|
142
146
|
configurable: true,
|
|
143
147
|
writable: true
|
|
144
148
|
});
|
|
145
|
-
else obj[key] = value;
|
|
149
|
+
else obj[key] = value;
|
|
146
150
|
return obj;
|
|
147
151
|
}
|
|
148
152
|
var BaseRenderer = class extends CodePrinter {
|
|
@@ -160,21 +164,21 @@ var BaseRenderer = class extends CodePrinter {
|
|
|
160
164
|
renderInterface(node) {}
|
|
161
165
|
renderType(node) {}
|
|
162
166
|
renderAnnotate(node) {}
|
|
163
|
-
transformFromPath(path
|
|
164
|
-
return `${path
|
|
167
|
+
transformFromPath(path) {
|
|
168
|
+
return `${path}.as`;
|
|
165
169
|
}
|
|
166
170
|
renderImport(node) {
|
|
167
171
|
const def = node.getDefinition();
|
|
168
172
|
const refs = [];
|
|
169
173
|
const from = this.transformFromPath(node.token("path").text);
|
|
170
174
|
let isUnusedImport = true;
|
|
171
|
-
if ((0,
|
|
172
|
-
for (const child of def.unwrap()) if ((0,
|
|
173
|
-
const node
|
|
174
|
-
refs.push(node
|
|
175
|
+
if ((0, _atscript_core.isGroup)(def)) {
|
|
176
|
+
for (const child of def.unwrap()) if ((0, _atscript_core.isRef)(child) && !this.unused.has(child.id)) {
|
|
177
|
+
const node = child;
|
|
178
|
+
refs.push(node.id);
|
|
175
179
|
isUnusedImport = false;
|
|
176
180
|
}
|
|
177
|
-
} else if ((0,
|
|
181
|
+
} else if ((0, _atscript_core.isRef)(def) && !this.unused.has(def.id)) {
|
|
178
182
|
refs.push(def.id);
|
|
179
183
|
isUnusedImport = false;
|
|
180
184
|
}
|
|
@@ -182,22 +186,18 @@ var BaseRenderer = class extends CodePrinter {
|
|
|
182
186
|
}
|
|
183
187
|
renderNode(node) {
|
|
184
188
|
switch (node.entity) {
|
|
185
|
-
case "interface":
|
|
189
|
+
case "interface":
|
|
186
190
|
this.renderInterface(node);
|
|
187
191
|
break;
|
|
188
|
-
|
|
189
|
-
case "type": {
|
|
192
|
+
case "type":
|
|
190
193
|
this.renderType(node);
|
|
191
194
|
break;
|
|
192
|
-
|
|
193
|
-
case "import": {
|
|
195
|
+
case "import":
|
|
194
196
|
this.renderImport(node);
|
|
195
197
|
break;
|
|
196
|
-
|
|
197
|
-
case "annotate": {
|
|
198
|
+
case "annotate":
|
|
198
199
|
this.renderAnnotate(node);
|
|
199
200
|
break;
|
|
200
|
-
}
|
|
201
201
|
default: break;
|
|
202
202
|
}
|
|
203
203
|
}
|
|
@@ -209,7 +209,13 @@ var BaseRenderer = class extends CodePrinter {
|
|
|
209
209
|
//#endregion
|
|
210
210
|
//#region packages/typescript/src/codegen/utils.ts
|
|
211
211
|
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
212
|
-
|
|
212
|
+
/**
|
|
213
|
+
* Wraps a property name in double quotes if it's not a valid identifier (contains special chars, etc.).
|
|
214
|
+
*
|
|
215
|
+
* Examples:
|
|
216
|
+
* - "validName" => "validName"
|
|
217
|
+
* - "some-prop" => "\"some-prop\""
|
|
218
|
+
*/ function wrapProp(name) {
|
|
213
219
|
if (!validIdentifier.test(name)) return `"${escapeQuotes(name)}"`;
|
|
214
220
|
return name;
|
|
215
221
|
}
|
|
@@ -226,7 +232,7 @@ function _define_property$5(obj, key, value) {
|
|
|
226
232
|
configurable: true,
|
|
227
233
|
writable: true
|
|
228
234
|
});
|
|
229
|
-
else obj[key] = value;
|
|
235
|
+
else obj[key] = value;
|
|
230
236
|
return obj;
|
|
231
237
|
}
|
|
232
238
|
var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
@@ -255,8 +261,8 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
255
261
|
this.write("unknown");
|
|
256
262
|
return;
|
|
257
263
|
}
|
|
258
|
-
if ((0,
|
|
259
|
-
if ((0,
|
|
264
|
+
if ((0, _atscript_core.isStructure)(def)) return this.renderStructure(def);
|
|
265
|
+
if ((0, _atscript_core.isGroup)(def)) {
|
|
260
266
|
const tuple = def.entity === "tuple";
|
|
261
267
|
const operator = tuple ? ", " : ` ${def.op} `;
|
|
262
268
|
const children = def.unwrap();
|
|
@@ -269,14 +275,14 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
269
275
|
}
|
|
270
276
|
return this.write(tuple ? "]" : hasSubgroup ? ")" : "");
|
|
271
277
|
}
|
|
272
|
-
if ((0,
|
|
278
|
+
if ((0, _atscript_core.isConst)(def)) {
|
|
273
279
|
const name = def.token("identifier")?.type === "number" ? def.id : `"${escapeQuotes(def.id)}"`;
|
|
274
280
|
return this.write(name);
|
|
275
281
|
}
|
|
276
|
-
if ((0,
|
|
282
|
+
if ((0, _atscript_core.isRef)(def)) {
|
|
277
283
|
const node = def;
|
|
278
284
|
const unwound = this.doc.unwindType(node.id, node.chain);
|
|
279
|
-
if ((0,
|
|
285
|
+
if ((0, _atscript_core.isPrimitive)(unwound?.def)) {
|
|
280
286
|
this.write(renderPrimitiveTypeDef(unwound.def.config.type));
|
|
281
287
|
if (node.hasChain) this.write(` /* ${node.chain.map((c) => c.text).join(".")} */`);
|
|
282
288
|
return;
|
|
@@ -285,21 +291,20 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
285
291
|
for (const c of node.chain) name += `["${escapeQuotes(c.text)}"]`;
|
|
286
292
|
return this.write(name);
|
|
287
293
|
}
|
|
288
|
-
if ((0,
|
|
289
|
-
const
|
|
290
|
-
const def2 = node.getDefinition();
|
|
294
|
+
if ((0, _atscript_core.isArray)(def)) {
|
|
295
|
+
const def2 = def.getDefinition();
|
|
291
296
|
const isGrp = def2?.entity === "group";
|
|
292
297
|
if (isGrp) this.write("(");
|
|
293
298
|
this.renderTypeDef(def2);
|
|
294
299
|
if (isGrp) this.write(")");
|
|
295
300
|
return this.write("[]");
|
|
296
301
|
}
|
|
297
|
-
if ((0,
|
|
302
|
+
if ((0, _atscript_core.isPrimitive)(def)) return this.write(renderPrimitiveTypeDef(def.config.type));
|
|
298
303
|
}
|
|
299
304
|
renderStructure(struct, asClass, interfaceNode, filterProps) {
|
|
300
305
|
this.blockln("{}");
|
|
301
306
|
const patterns = [];
|
|
302
|
-
const propsDefs = new Set();
|
|
307
|
+
const propsDefs = /* @__PURE__ */ new Set();
|
|
303
308
|
for (const prop of struct.props.values()) {
|
|
304
309
|
if (filterProps?.has(prop.id)) continue;
|
|
305
310
|
if (prop.token("identifier")?.pattern) {
|
|
@@ -366,14 +371,14 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
366
371
|
let firstParentProps;
|
|
367
372
|
if (firstParentUnwound?.def) {
|
|
368
373
|
let fpDef = firstParentUnwound.def;
|
|
369
|
-
if ((0,
|
|
374
|
+
if ((0, _atscript_core.isInterface)(fpDef)) {
|
|
370
375
|
if (fpDef.hasExtends) {
|
|
371
376
|
const fpResolved = firstParentUnwound.doc.resolveInterfaceExtends(fpDef);
|
|
372
|
-
if (fpResolved && (0,
|
|
377
|
+
if (fpResolved && (0, _atscript_core.isStructure)(fpResolved)) firstParentProps = fpResolved.props;
|
|
373
378
|
}
|
|
374
379
|
if (!firstParentProps) fpDef = fpDef.getDefinition() || fpDef;
|
|
375
380
|
}
|
|
376
|
-
if (!firstParentProps && (0,
|
|
381
|
+
if (!firstParentProps && (0, _atscript_core.isStructure)(fpDef)) firstParentProps = fpDef.props;
|
|
377
382
|
}
|
|
378
383
|
this.renderStructure(resolved, node.id, node, firstParentProps);
|
|
379
384
|
} else this.writeln("{}");
|
|
@@ -381,7 +386,7 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
381
386
|
this.write(`class ${node.id} `);
|
|
382
387
|
const struct = node.getDefinition();
|
|
383
388
|
if (struct?.entity === "structure") this.renderStructure(struct, node.id, node);
|
|
384
|
-
else this.writeln("{}");
|
|
389
|
+
else this.writeln("{}");
|
|
385
390
|
}
|
|
386
391
|
this.writeln();
|
|
387
392
|
}
|
|
@@ -421,12 +426,12 @@ else this.writeln("{}");
|
|
|
421
426
|
let typeDef = "TAtscriptTypeDef";
|
|
422
427
|
if (inputDef) {
|
|
423
428
|
let realDef = inputDef;
|
|
424
|
-
if ((0,
|
|
429
|
+
if ((0, _atscript_core.isRef)(inputDef)) realDef = this.doc.unwindType(inputDef.id, inputDef.chain)?.def || realDef;
|
|
425
430
|
realDef = this.doc.mergeIntersection(realDef);
|
|
426
|
-
if ((0,
|
|
427
|
-
else if ((0,
|
|
428
|
-
else if ((0,
|
|
429
|
-
else if ((0,
|
|
431
|
+
if ((0, _atscript_core.isStructure)(realDef) || (0, _atscript_core.isInterface)(realDef)) typeDef = `TAtscriptTypeObject<keyof ${name}, ${name}>`;
|
|
432
|
+
else if ((0, _atscript_core.isGroup)(realDef)) typeDef = `TAtscriptTypeComplex<${name}>`;
|
|
433
|
+
else if ((0, _atscript_core.isArray)(realDef)) typeDef = `TAtscriptTypeArray<${name}>`;
|
|
434
|
+
else if ((0, _atscript_core.isPrimitive)(realDef)) typeDef = `TAtscriptTypeFinal<${name}>`;
|
|
430
435
|
}
|
|
431
436
|
this.writeln(`const __is_atscript_annotated_type: true`);
|
|
432
437
|
this.writeln(`const type: ${typeDef}`);
|
|
@@ -462,12 +467,12 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = `TAtscriptTypeFina
|
|
|
462
467
|
* not individually queryable)
|
|
463
468
|
* - **Leaf fields** → their original TypeScript type
|
|
464
469
|
*/ renderFlat(node) {
|
|
465
|
-
this.renderFlatMap("__flat", (0,
|
|
470
|
+
this.renderFlatMap("__flat", (0, _atscript_core.flattenInterfaceNode)(this.doc, node));
|
|
466
471
|
}
|
|
467
472
|
/**
|
|
468
473
|
* Renders the `static __ownProps` property — table-owned fields only (no nav props).
|
|
469
474
|
*/ renderOwnProps(node) {
|
|
470
|
-
this.renderFlatMap("__ownProps", (0,
|
|
475
|
+
this.renderFlatMap("__ownProps", (0, _atscript_core.flattenInterfaceNode)(this.doc, node, { skipNavProps: true }), {
|
|
471
476
|
leadingNewline: true,
|
|
472
477
|
trailingNewline: true
|
|
473
478
|
});
|
|
@@ -484,21 +489,20 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = `TAtscriptTypeFina
|
|
|
484
489
|
if (opts?.leadingNewline) this.writeln();
|
|
485
490
|
this.write(`static ${propName}: `);
|
|
486
491
|
this.blockln("{}");
|
|
487
|
-
for (const [path
|
|
488
|
-
this.write(`"${escapeQuotes(path
|
|
492
|
+
for (const [path, descriptor] of flatMap) {
|
|
493
|
+
this.write(`"${escapeQuotes(path)}"`);
|
|
489
494
|
if (descriptor.optional) this.write("?");
|
|
490
495
|
this.write(": ");
|
|
491
496
|
if (descriptor.intermediate) this.writeln("never");
|
|
492
|
-
else if (descriptor.dbJson) this.writeln("string");
|
|
493
|
-
else {
|
|
497
|
+
else if (descriptor.dbJson) this.writeln("string");
|
|
498
|
+
else {
|
|
494
499
|
const originalDef = descriptor.propNode?.getDefinition();
|
|
495
|
-
const defToRender = originalDef && !((0,
|
|
496
|
-
|
|
497
|
-
renderedDef.split("\n").forEach((l) => this.writeln(l));
|
|
500
|
+
const defToRender = originalDef && !((0, _atscript_core.isGroup)(descriptor.def) && descriptor.def !== originalDef) ? originalDef : descriptor.def;
|
|
501
|
+
this.renderTypeDefString(defToRender).split("\n").forEach((l) => this.writeln(l));
|
|
498
502
|
}
|
|
499
503
|
}
|
|
500
504
|
if (opts?.trailingNewline) this.popln();
|
|
501
|
-
else this.pop();
|
|
505
|
+
else this.pop();
|
|
502
506
|
}
|
|
503
507
|
/**
|
|
504
508
|
* Renders the `static __navProps` property — a map of navigation property names
|
|
@@ -510,12 +514,12 @@ else this.pop();
|
|
|
510
514
|
let struct;
|
|
511
515
|
if (node.hasExtends) struct = this.doc.resolveInterfaceExtends(node);
|
|
512
516
|
if (!struct) struct = node.getDefinition();
|
|
513
|
-
if (!struct || !(0,
|
|
517
|
+
if (!struct || !(0, _atscript_core.isStructure)(struct)) return;
|
|
514
518
|
const structNode = struct;
|
|
515
519
|
const navProps = [];
|
|
516
520
|
for (const [name, prop] of structNode.props) {
|
|
517
521
|
if (prop.token("identifier")?.pattern) continue;
|
|
518
|
-
if ((0,
|
|
522
|
+
if ((0, _atscript_core.hasNavPropAnnotation)(prop)) navProps.push({
|
|
519
523
|
name,
|
|
520
524
|
prop
|
|
521
525
|
});
|
|
@@ -529,10 +533,8 @@ else this.pop();
|
|
|
529
533
|
if (prop.token("optional")) this.write("?");
|
|
530
534
|
this.write(": ");
|
|
531
535
|
const propDef = prop.getDefinition();
|
|
532
|
-
if (propDef)
|
|
533
|
-
|
|
534
|
-
renderedDef.split("\n").forEach((l) => this.writeln(l));
|
|
535
|
-
} else this.writeln("unknown");
|
|
536
|
+
if (propDef) this.renderTypeDefString(propDef).split("\n").forEach((l) => this.writeln(l));
|
|
537
|
+
else this.writeln("unknown");
|
|
536
538
|
}
|
|
537
539
|
this.popln();
|
|
538
540
|
}
|
|
@@ -541,10 +543,10 @@ else this.pop();
|
|
|
541
543
|
let struct;
|
|
542
544
|
if (node.hasExtends) struct = this.doc.resolveInterfaceExtends(node);
|
|
543
545
|
if (!struct) struct = node.getDefinition();
|
|
544
|
-
if (!struct || !(0,
|
|
546
|
+
if (!struct || !(0, _atscript_core.isStructure)(struct)) return;
|
|
545
547
|
const structNode = struct;
|
|
546
548
|
const pkProps = [];
|
|
547
|
-
const uniqueByIndex = new Map();
|
|
549
|
+
const uniqueByIndex = /* @__PURE__ */ new Map();
|
|
548
550
|
for (const [name, prop] of structNode.props) {
|
|
549
551
|
if (prop.token("identifier")?.pattern) continue;
|
|
550
552
|
if (isMongoCollection && name === "_id") continue;
|
|
@@ -578,7 +580,7 @@ else this.pop();
|
|
|
578
580
|
mongoIdType ?? (mongoIdType = "string");
|
|
579
581
|
}
|
|
580
582
|
const uniqueTypes = [];
|
|
581
|
-
const seenTypes = new Set();
|
|
583
|
+
const seenTypes = /* @__PURE__ */ new Set();
|
|
582
584
|
for (const { prop } of uniqueProps) {
|
|
583
585
|
const rendered = this.renderTypeDefString(prop.getDefinition()).trim();
|
|
584
586
|
if (!seenTypes.has(rendered)) {
|
|
@@ -589,8 +591,8 @@ else this.pop();
|
|
|
589
591
|
this.writeln();
|
|
590
592
|
const uniqueSuffix = uniqueTypes.length > 0 ? ` | ${uniqueTypes.join(" | ")}` : "";
|
|
591
593
|
if (pkProps.length === 0 && !isMongoCollection) this.writeln(`static __pk: ${uniqueTypes.join(" | ")}`);
|
|
592
|
-
else if (pkProps.length === 0) this.writeln(`static __pk: ${mongoIdType}${uniqueSuffix}`);
|
|
593
|
-
else if (pkProps.length === 1) {
|
|
594
|
+
else if (pkProps.length === 0) this.writeln(`static __pk: ${mongoIdType}${uniqueSuffix}`);
|
|
595
|
+
else if (pkProps.length === 1) {
|
|
594
596
|
this.write("static __pk: ");
|
|
595
597
|
if (isMongoCollection) this.write(`${mongoIdType} | `);
|
|
596
598
|
const renderedDef = this.renderTypeDefString(pkProps[0].prop.getDefinition()).trim();
|
|
@@ -601,8 +603,7 @@ else if (pkProps.length === 1) {
|
|
|
601
603
|
this.blockln("{}");
|
|
602
604
|
for (const { name, prop } of pkProps) {
|
|
603
605
|
this.write(wrapProp(name), ": ");
|
|
604
|
-
|
|
605
|
-
renderedDef.split("\n").forEach((l) => this.writeln(l));
|
|
606
|
+
this.renderTypeDefString(prop.getDefinition()).split("\n").forEach((l) => this.writeln(l));
|
|
606
607
|
}
|
|
607
608
|
this.pop();
|
|
608
609
|
this.writeln(uniqueSuffix);
|
|
@@ -612,7 +613,7 @@ else if (pkProps.length === 1) {
|
|
|
612
613
|
let struct;
|
|
613
614
|
if (node.hasExtends) struct = this.doc.resolveInterfaceExtends(node);
|
|
614
615
|
if (!struct) struct = node.getDefinition();
|
|
615
|
-
if (!struct || !(0,
|
|
616
|
+
if (!struct || !(0, _atscript_core.isStructure)(struct)) return;
|
|
616
617
|
const structNode = struct;
|
|
617
618
|
const dims = [];
|
|
618
619
|
const measures = [];
|
|
@@ -627,18 +628,16 @@ else if (pkProps.length === 1) {
|
|
|
627
628
|
if (measures.length > 0) this.writeln(`static __measure: ${measures.map((m) => `"${escapeQuotes(m)}"`).join(" | ")}`);
|
|
628
629
|
}
|
|
629
630
|
phantomPropType(def) {
|
|
630
|
-
if (!def) return
|
|
631
|
-
if ((0,
|
|
632
|
-
if ((0,
|
|
631
|
+
if (!def) return;
|
|
632
|
+
if ((0, _atscript_core.isPrimitive)(def) && def.config.type === "phantom") return def.id;
|
|
633
|
+
if ((0, _atscript_core.isRef)(def)) {
|
|
633
634
|
const ref = def;
|
|
634
635
|
const unwound = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
635
|
-
if ((0,
|
|
636
|
+
if ((0, _atscript_core.isPrimitive)(unwound) && unwound.config.type === "phantom") return ref.hasChain ? `${ref.id}.${ref.chain.map((c) => c.text).join(".")}` : ref.id;
|
|
636
637
|
}
|
|
637
|
-
return undefined;
|
|
638
638
|
}
|
|
639
639
|
isTypeTarget(name, doc) {
|
|
640
|
-
const
|
|
641
|
-
const decl = d.getDeclarationOwnerNode(name);
|
|
640
|
+
const decl = (doc || this.doc).getDeclarationOwnerNode(name);
|
|
642
641
|
if (!decl?.node) return false;
|
|
643
642
|
if (decl.node.entity === "type") return true;
|
|
644
643
|
if (decl.node.entity === "interface") return false;
|
|
@@ -666,10 +665,7 @@ function renderPrimitiveTypeDef(def) {
|
|
|
666
665
|
case "intersection": return def.items.map(renderPrimitiveTypeDef).join(" & ");
|
|
667
666
|
case "tuple": return `[${def.items.map(renderPrimitiveTypeDef).join(", ")}]`;
|
|
668
667
|
case "array": return `${renderPrimitiveTypeDef(def.of)}[]`;
|
|
669
|
-
case "object": {
|
|
670
|
-
const props = Object.entries(def.props).map(([key, val]) => `${wrapProp(key)}${typeof val === "object" && val.optional ? "?" : ""}: ${renderPrimitiveTypeDef(val)}`).join("; ");
|
|
671
|
-
return `{ ${props} }`;
|
|
672
|
-
}
|
|
668
|
+
case "object": return `{ ${Object.entries(def.props).map(([key, val]) => `${wrapProp(key)}${typeof val === "object" && val.optional ? "?" : ""}: ${renderPrimitiveTypeDef(val)}`).join("; ")} }`;
|
|
673
669
|
default: return "unknown";
|
|
674
670
|
}
|
|
675
671
|
}
|
|
@@ -683,16 +679,36 @@ function _define_property$4(obj, key, value) {
|
|
|
683
679
|
configurable: true,
|
|
684
680
|
writable: true
|
|
685
681
|
});
|
|
686
|
-
else obj[key] = value;
|
|
682
|
+
else obj[key] = value;
|
|
687
683
|
return obj;
|
|
688
684
|
}
|
|
689
|
-
const regexCache = new Map();
|
|
690
|
-
|
|
685
|
+
const regexCache = /* @__PURE__ */ new Map();
|
|
686
|
+
/**
|
|
687
|
+
* Validates values against an {@link TAtscriptAnnotatedType} definition.
|
|
688
|
+
*
|
|
689
|
+
* `DataType` is automatically inferred from the type definition's phantom generic,
|
|
690
|
+
* enabling the {@link validate} method to act as a type guard.
|
|
691
|
+
*
|
|
692
|
+
* @example
|
|
693
|
+
* ```ts
|
|
694
|
+
* // From a generated interface class:
|
|
695
|
+
* const validator = new Validator(MyInterface)
|
|
696
|
+
* if (validator.validate(data, true)) {
|
|
697
|
+
* data // narrowed to MyInterface
|
|
698
|
+
* }
|
|
699
|
+
*
|
|
700
|
+
* // Or use the built-in factory:
|
|
701
|
+
* MyInterface.validator().validate(data)
|
|
702
|
+
* ```
|
|
703
|
+
*
|
|
704
|
+
* @typeParam T - The annotated type definition.
|
|
705
|
+
* @typeParam DataType - The TypeScript type that `validate` narrows to (auto-inferred).
|
|
706
|
+
*/ var Validator = class {
|
|
691
707
|
buildPath() {
|
|
692
708
|
if (this.depth <= 0) return "";
|
|
693
|
-
let path
|
|
694
|
-
for (let i = 1; i < this.depth; i++) path
|
|
695
|
-
return path
|
|
709
|
+
let path = this.pathSegments[0];
|
|
710
|
+
for (let i = 1; i < this.depth; i++) path += `.${this.pathSegments[i]}`;
|
|
711
|
+
return path;
|
|
696
712
|
}
|
|
697
713
|
push(name) {
|
|
698
714
|
this.pathSegments[this.depth] = name;
|
|
@@ -702,21 +718,21 @@ var Validator = class {
|
|
|
702
718
|
pop(saveErrors) {
|
|
703
719
|
this.depth--;
|
|
704
720
|
const popped = this.stackErrors.pop();
|
|
705
|
-
if (saveErrors && popped !== null && popped !==
|
|
721
|
+
if (saveErrors && popped !== null && popped !== void 0 && popped.length > 0) for (const err of popped) this.error(err.message, err.path, err.details);
|
|
706
722
|
return popped;
|
|
707
723
|
}
|
|
708
724
|
clear() {
|
|
709
725
|
this.stackErrors[this.stackErrors.length - 1] = null;
|
|
710
726
|
if (this.limitExceeded) this.limitExceeded = false;
|
|
711
727
|
}
|
|
712
|
-
error(message, path
|
|
728
|
+
error(message, path, details) {
|
|
713
729
|
let errors = this.stackErrors[this.stackErrors.length - 1];
|
|
714
730
|
if (!errors) if (this.stackErrors.length > 0) {
|
|
715
731
|
errors = [];
|
|
716
732
|
this.stackErrors[this.stackErrors.length - 1] = errors;
|
|
717
733
|
} else errors = this.errors;
|
|
718
734
|
const error = {
|
|
719
|
-
path: path
|
|
735
|
+
path: path || this.buildPath(),
|
|
720
736
|
message
|
|
721
737
|
};
|
|
722
738
|
if (details?.length) error.details = details;
|
|
@@ -743,7 +759,7 @@ var Validator = class {
|
|
|
743
759
|
this.limitExceeded = false;
|
|
744
760
|
this.context = context;
|
|
745
761
|
const passed = this.validateSafe(this.def, value);
|
|
746
|
-
this.context =
|
|
762
|
+
this.context = void 0;
|
|
747
763
|
if (!passed) {
|
|
748
764
|
if (safe) return false;
|
|
749
765
|
this.throw();
|
|
@@ -754,13 +770,13 @@ var Validator = class {
|
|
|
754
770
|
if (this.limitExceeded) return false;
|
|
755
771
|
if (this.hasReplace) {
|
|
756
772
|
let replaced = this.replaceCache.get(def);
|
|
757
|
-
if (replaced ===
|
|
773
|
+
if (replaced === void 0) {
|
|
758
774
|
replaced = this.opts.replace(def, this.buildPath());
|
|
759
775
|
this.replaceCache.set(def, replaced);
|
|
760
776
|
}
|
|
761
777
|
def = replaced;
|
|
762
778
|
}
|
|
763
|
-
if (def.optional && (value ===
|
|
779
|
+
if (def.optional && (value === void 0 || value === null)) return true;
|
|
764
780
|
if (this.hasPlugins) for (const plugin of this.opts.plugins) {
|
|
765
781
|
const result = plugin(this, def, value);
|
|
766
782
|
if (result === false || result === true) return result;
|
|
@@ -772,10 +788,9 @@ var Validator = class {
|
|
|
772
788
|
}
|
|
773
789
|
validateAnnotatedType(def, value) {
|
|
774
790
|
switch (def.type.kind) {
|
|
775
|
-
case "":
|
|
791
|
+
case "":
|
|
776
792
|
if (def.type.designType === "phantom") return true;
|
|
777
793
|
return this.validatePrimitive(def, value);
|
|
778
|
-
}
|
|
779
794
|
case "object": return this.validateObject(def, value);
|
|
780
795
|
case "array": return this.validateArray(def, value);
|
|
781
796
|
case "union": return this.validateUnion(def, value);
|
|
@@ -796,10 +811,10 @@ var Validator = class {
|
|
|
796
811
|
const branchErrors = this.stackErrors.pop();
|
|
797
812
|
if (this.limitExceeded) this.limitExceeded = false;
|
|
798
813
|
if (branchErrors) if (details) for (const err of branchErrors) details.push(err);
|
|
799
|
-
else details = branchErrors;
|
|
814
|
+
else details = branchErrors;
|
|
800
815
|
}
|
|
801
816
|
const expected = items.map((item, i) => `[${item.type.kind || item.type.designType}(${i})]`).join(", ");
|
|
802
|
-
this.error(`Value does not match any of the allowed types: ${expected}`,
|
|
817
|
+
this.error(`Value does not match any of the allowed types: ${expected}`, void 0, details);
|
|
803
818
|
return false;
|
|
804
819
|
}
|
|
805
820
|
validateIntersection(def, value) {
|
|
@@ -849,8 +864,8 @@ else details = branchErrors;
|
|
|
849
864
|
const uniqueItems = def.metadata.get("expect.array.uniqueItems");
|
|
850
865
|
if (uniqueItems) {
|
|
851
866
|
const separator = "▼↩";
|
|
852
|
-
const seen = new Set();
|
|
853
|
-
const keyProps = new Set();
|
|
867
|
+
const seen = /* @__PURE__ */ new Set();
|
|
868
|
+
const keyProps = /* @__PURE__ */ new Set();
|
|
854
869
|
if (def.type.of.type.kind === "object") {
|
|
855
870
|
for (const [key, val] of def.type.of.type.props.entries()) if (val.metadata.get("expect.array.key")) keyProps.add(key);
|
|
856
871
|
}
|
|
@@ -892,10 +907,10 @@ else details = branchErrors;
|
|
|
892
907
|
let keysToStrip;
|
|
893
908
|
let skipList;
|
|
894
909
|
if (this.opts.skipList) {
|
|
895
|
-
const path
|
|
896
|
-
for (const item of this.opts.skipList) if (item.startsWith(path
|
|
897
|
-
const key = item.slice(path
|
|
898
|
-
if (!skipList) skipList = new Set();
|
|
910
|
+
const path = this.depth > 0 ? `${this.buildPath()}.` : "";
|
|
911
|
+
for (const item of this.opts.skipList) if (item.startsWith(path)) {
|
|
912
|
+
const key = item.slice(path.length);
|
|
913
|
+
if (!skipList) skipList = /* @__PURE__ */ new Set();
|
|
899
914
|
skipList.add(key);
|
|
900
915
|
}
|
|
901
916
|
}
|
|
@@ -903,12 +918,12 @@ else details = branchErrors;
|
|
|
903
918
|
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.buildPath());
|
|
904
919
|
for (const [key, item] of def.type.props.entries()) {
|
|
905
920
|
if (skipList && skipList.has(key) || isPhantomType(item)) continue;
|
|
906
|
-
if (value[key] ===
|
|
921
|
+
if (value[key] === void 0) {
|
|
907
922
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.depth === 0) continue;
|
|
908
923
|
}
|
|
909
924
|
this.push(key);
|
|
910
925
|
if (this.validateSafe(item, value[key])) this.pop(false);
|
|
911
|
-
else {
|
|
926
|
+
else {
|
|
912
927
|
passed = false;
|
|
913
928
|
this.pop(true);
|
|
914
929
|
if (this.limitExceeded) return false;
|
|
@@ -958,7 +973,7 @@ else {
|
|
|
958
973
|
return passed;
|
|
959
974
|
}
|
|
960
975
|
validatePrimitive(def, value) {
|
|
961
|
-
if (def.type.value !==
|
|
976
|
+
if (def.type.value !== void 0) {
|
|
962
977
|
if (value !== def.type.value) {
|
|
963
978
|
this.error(`Expected ${def.type.value}, got ${value}`);
|
|
964
979
|
return false;
|
|
@@ -967,47 +982,41 @@ else {
|
|
|
967
982
|
}
|
|
968
983
|
const typeOfValue = Array.isArray(value) ? "array" : typeof value;
|
|
969
984
|
switch (def.type.designType) {
|
|
970
|
-
case "never":
|
|
985
|
+
case "never":
|
|
971
986
|
this.error(`This type is impossible, must be an internal problem`);
|
|
972
987
|
return false;
|
|
973
|
-
}
|
|
974
988
|
case "any": return true;
|
|
975
|
-
case "string":
|
|
989
|
+
case "string":
|
|
976
990
|
if (typeOfValue !== def.type.designType) {
|
|
977
991
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
978
992
|
return false;
|
|
979
993
|
}
|
|
980
994
|
return this.validateString(def, value);
|
|
981
|
-
|
|
982
|
-
case "number": {
|
|
995
|
+
case "number":
|
|
983
996
|
if (typeOfValue !== def.type.designType) {
|
|
984
997
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
985
998
|
return false;
|
|
986
999
|
}
|
|
987
1000
|
return this.validateNumber(def, value);
|
|
988
|
-
|
|
989
|
-
case "boolean": {
|
|
1001
|
+
case "boolean":
|
|
990
1002
|
if (typeOfValue !== def.type.designType) {
|
|
991
1003
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
992
1004
|
return false;
|
|
993
1005
|
}
|
|
994
1006
|
return this.validateBoolean(def, value);
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
if (value !== undefined) {
|
|
1007
|
+
case "undefined":
|
|
1008
|
+
if (value !== void 0) {
|
|
998
1009
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
999
1010
|
return false;
|
|
1000
1011
|
}
|
|
1001
1012
|
return true;
|
|
1002
|
-
|
|
1003
|
-
case "null": {
|
|
1013
|
+
case "null":
|
|
1004
1014
|
if (value !== null) {
|
|
1005
1015
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
1006
1016
|
return false;
|
|
1007
1017
|
}
|
|
1008
1018
|
return true;
|
|
1009
|
-
|
|
1010
|
-
case "decimal": {
|
|
1019
|
+
case "decimal":
|
|
1011
1020
|
if (typeOfValue !== "string") {
|
|
1012
1021
|
this.error(`Expected string (decimal), got ${typeOfValue}`);
|
|
1013
1022
|
return false;
|
|
@@ -1017,7 +1026,6 @@ else {
|
|
|
1017
1026
|
return false;
|
|
1018
1027
|
}
|
|
1019
1028
|
return true;
|
|
1020
|
-
}
|
|
1021
1029
|
default: throw new Error(`Unknown type "${def.type.designType}"`);
|
|
1022
1030
|
}
|
|
1023
1031
|
}
|
|
@@ -1132,10 +1140,10 @@ else {
|
|
|
1132
1140
|
};
|
|
1133
1141
|
this.hasPlugins = this.opts.plugins.length > 0;
|
|
1134
1142
|
this.hasReplace = typeof this.opts.replace === "function";
|
|
1135
|
-
if (this.hasReplace) this.replaceCache = new WeakMap();
|
|
1143
|
+
if (this.hasReplace) this.replaceCache = /* @__PURE__ */ new WeakMap();
|
|
1136
1144
|
}
|
|
1137
1145
|
};
|
|
1138
|
-
var ValidatorError = class extends Error {
|
|
1146
|
+
/** Error thrown by {@link Validator.validate} when validation fails. Contains structured error details. */ var ValidatorError = class extends Error {
|
|
1139
1147
|
constructor(errors) {
|
|
1140
1148
|
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";
|
|
1141
1149
|
}
|
|
@@ -1151,7 +1159,10 @@ const COMPLEX_KINDS = new Set([
|
|
|
1151
1159
|
/** Shared validator method reused by all annotated type nodes. */ function validatorMethod(opts) {
|
|
1152
1160
|
return new Validator(this, opts);
|
|
1153
1161
|
}
|
|
1154
|
-
|
|
1162
|
+
/**
|
|
1163
|
+
* Creates a minimal annotated type node from a type def and metadata map.
|
|
1164
|
+
* Centralises the shape so callers never duplicate the boilerplate.
|
|
1165
|
+
*/ function createAnnotatedTypeNode(type, metadata, opts) {
|
|
1155
1166
|
return {
|
|
1156
1167
|
__is_atscript_annotated_type: true,
|
|
1157
1168
|
type,
|
|
@@ -1162,22 +1173,27 @@ function createAnnotatedTypeNode(type, metadata, opts) {
|
|
|
1162
1173
|
ref: opts?.ref
|
|
1163
1174
|
};
|
|
1164
1175
|
}
|
|
1165
|
-
|
|
1176
|
+
/**
|
|
1177
|
+
* Type Guard to check if a type is atscript-annotated
|
|
1178
|
+
*/ function isAnnotatedType(type) {
|
|
1166
1179
|
return type && type.__is_atscript_annotated_type;
|
|
1167
1180
|
}
|
|
1168
|
-
|
|
1181
|
+
/**
|
|
1182
|
+
* Standalone annotate function that handles both replace and append (array) strategies.
|
|
1183
|
+
* Used by the handle's .annotate() method and by generated mutation statements.
|
|
1184
|
+
*/ function annotate(metadata, key, value, asArray) {
|
|
1169
1185
|
if (!metadata) return;
|
|
1170
1186
|
if (asArray) if (metadata.has(key)) {
|
|
1171
1187
|
const a = metadata.get(key);
|
|
1172
1188
|
if (Array.isArray(a)) a.push(value);
|
|
1173
|
-
else metadata.set(key, [a, value]);
|
|
1189
|
+
else metadata.set(key, [a, value]);
|
|
1174
1190
|
} else metadata.set(key, [value]);
|
|
1175
|
-
else metadata.set(key, value);
|
|
1191
|
+
else metadata.set(key, value);
|
|
1176
1192
|
}
|
|
1177
1193
|
function cloneTypeDef(type) {
|
|
1178
1194
|
if (type.kind === "object") {
|
|
1179
1195
|
const obj = type;
|
|
1180
|
-
const props = new Map();
|
|
1196
|
+
const props = /* @__PURE__ */ new Map();
|
|
1181
1197
|
for (const [k, v] of obj.props) props.set(k, createAnnotatedTypeNode(v.type, new Map(v.metadata), {
|
|
1182
1198
|
id: v.id,
|
|
1183
1199
|
optional: v.optional
|
|
@@ -1210,18 +1226,36 @@ function cloneTypeDef(type) {
|
|
|
1210
1226
|
tags: new Set(type.tags)
|
|
1211
1227
|
};
|
|
1212
1228
|
}
|
|
1213
|
-
|
|
1229
|
+
/**
|
|
1230
|
+
* Creates a builder handle for constructing a {@link TAtscriptAnnotatedType} at runtime.
|
|
1231
|
+
*
|
|
1232
|
+
* This is primarily used by generated `.as.js` code. The returned handle provides
|
|
1233
|
+
* a fluent API for setting the type definition, metadata, and properties.
|
|
1234
|
+
*
|
|
1235
|
+
* @example
|
|
1236
|
+
* ```ts
|
|
1237
|
+
* const handle = defineAnnotatedType('object')
|
|
1238
|
+
* .prop('name', defineAnnotatedType().designType('string').$type)
|
|
1239
|
+
* .prop('age', defineAnnotatedType().designType('number').$type)
|
|
1240
|
+
*
|
|
1241
|
+
* handle.$type // the resulting TAtscriptAnnotatedType
|
|
1242
|
+
* ```
|
|
1243
|
+
*
|
|
1244
|
+
* @param _kind - The kind of type to create (e.g. `'object'`, `'array'`, `'union'`). Defaults to `''` (primitive/final).
|
|
1245
|
+
* @param base - Optional existing object to augment with annotated type fields.
|
|
1246
|
+
* @returns A builder handle for fluent type construction.
|
|
1247
|
+
*/ function defineAnnotatedType(_kind, base) {
|
|
1214
1248
|
const kind = _kind || "";
|
|
1215
|
-
const baseProvided = base !==
|
|
1249
|
+
const baseProvided = base !== void 0;
|
|
1216
1250
|
const type = base?.type || {};
|
|
1217
1251
|
type.kind = kind;
|
|
1218
1252
|
if (COMPLEX_KINDS.has(kind)) type.items = [];
|
|
1219
1253
|
if (kind === "object") {
|
|
1220
|
-
type.props = new Map();
|
|
1254
|
+
type.props = /* @__PURE__ */ new Map();
|
|
1221
1255
|
type.propsPatterns = [];
|
|
1222
1256
|
}
|
|
1223
|
-
type.tags = new Set();
|
|
1224
|
-
const metadata = base?.metadata || new Map();
|
|
1257
|
+
type.tags = /* @__PURE__ */ new Set();
|
|
1258
|
+
const metadata = base?.metadata || /* @__PURE__ */ new Map();
|
|
1225
1259
|
const payload = {
|
|
1226
1260
|
__is_atscript_annotated_type: true,
|
|
1227
1261
|
metadata,
|
|
@@ -1229,7 +1263,7 @@ function defineAnnotatedType(_kind, base) {
|
|
|
1229
1263
|
validator: validatorMethod
|
|
1230
1264
|
};
|
|
1231
1265
|
base = base ? Object.assign(base, payload) : payload;
|
|
1232
|
-
|
|
1266
|
+
return {
|
|
1233
1267
|
$type: base,
|
|
1234
1268
|
$def: type,
|
|
1235
1269
|
$metadata: metadata,
|
|
@@ -1272,15 +1306,15 @@ function defineAnnotatedType(_kind, base) {
|
|
|
1272
1306
|
for (const [key, value] of fromMetadata.entries()) if (!ignore || !ignore.has(key)) this.$metadata.set(key, value);
|
|
1273
1307
|
return this;
|
|
1274
1308
|
},
|
|
1275
|
-
refTo(type
|
|
1309
|
+
refTo(type, chain) {
|
|
1276
1310
|
const node = this.$type;
|
|
1277
|
-
if (isAnnotatedType(type
|
|
1278
|
-
let newBase = type
|
|
1279
|
-
const typeName = type
|
|
1311
|
+
if (isAnnotatedType(type)) {
|
|
1312
|
+
let newBase = type;
|
|
1313
|
+
const typeName = type.name || "Unknown";
|
|
1280
1314
|
if (chain) for (let i = 0; i < chain.length; i++) {
|
|
1281
1315
|
const c = chain[i];
|
|
1282
1316
|
if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
|
|
1283
|
-
else {
|
|
1317
|
+
else {
|
|
1284
1318
|
const keys = chain.slice(0, i + 1).map((k) => `["${k}"]`).join("");
|
|
1285
1319
|
throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
1286
1320
|
}
|
|
@@ -1288,11 +1322,11 @@ else {
|
|
|
1288
1322
|
node.type = baseProvided ? cloneTypeDef(newBase.type) : newBase.type;
|
|
1289
1323
|
node.id = node.id ?? newBase.id;
|
|
1290
1324
|
if (chain && chain.length > 0) node.ref = {
|
|
1291
|
-
type: () => type
|
|
1325
|
+
type: () => type,
|
|
1292
1326
|
field: chain.join(".")
|
|
1293
1327
|
};
|
|
1294
|
-
} else if (typeof type
|
|
1295
|
-
const lazyType = type
|
|
1328
|
+
} else if (typeof type === "function") {
|
|
1329
|
+
const lazyType = type;
|
|
1296
1330
|
const ownId = node.id;
|
|
1297
1331
|
node.ref = {
|
|
1298
1332
|
type: lazyType,
|
|
@@ -1312,7 +1346,7 @@ else {
|
|
|
1312
1346
|
}
|
|
1313
1347
|
let target = t;
|
|
1314
1348
|
if (chain) for (const c of chain) if (target.type.kind === "object" && target.type.props.has(c)) target = target.type.props.get(c);
|
|
1315
|
-
else return t.type;
|
|
1349
|
+
else return t.type;
|
|
1316
1350
|
node.id = ownId ?? target.id;
|
|
1317
1351
|
const resolved = baseProvided ? cloneTypeDef(target.type) : target.type;
|
|
1318
1352
|
Object.defineProperty(node, "type", {
|
|
@@ -1324,7 +1358,7 @@ else return t.type;
|
|
|
1324
1358
|
},
|
|
1325
1359
|
configurable: true
|
|
1326
1360
|
});
|
|
1327
|
-
} else throw new TypeError(`${type
|
|
1361
|
+
} else throw new TypeError(`${type} is not annotated type`);
|
|
1328
1362
|
return this;
|
|
1329
1363
|
},
|
|
1330
1364
|
annotate(key, value, asArray) {
|
|
@@ -1336,15 +1370,29 @@ else return t.type;
|
|
|
1336
1370
|
return this;
|
|
1337
1371
|
}
|
|
1338
1372
|
};
|
|
1339
|
-
return handle;
|
|
1340
1373
|
}
|
|
1341
|
-
|
|
1374
|
+
/**
|
|
1375
|
+
* Checks whether an annotated type is a phantom type.
|
|
1376
|
+
*
|
|
1377
|
+
* Phantom types do not affect the data type, validation, or schema,
|
|
1378
|
+
* but are discoverable via runtime type traversal.
|
|
1379
|
+
*/ function isPhantomType(def) {
|
|
1342
1380
|
return def.type.kind === "" && def.type.designType === "phantom";
|
|
1343
1381
|
}
|
|
1344
1382
|
|
|
1345
1383
|
//#endregion
|
|
1346
1384
|
//#region packages/typescript/src/runtime/traverse.ts
|
|
1347
|
-
|
|
1385
|
+
/**
|
|
1386
|
+
* Type-safe dispatch over `TAtscriptAnnotatedType` by its `type.kind`.
|
|
1387
|
+
*
|
|
1388
|
+
* Provides the common `switch (def.type.kind)` pattern used by
|
|
1389
|
+
* the validator, JSON-schema builder, and serializer.
|
|
1390
|
+
* Each caller supplies its own handlers that control recursion.
|
|
1391
|
+
*
|
|
1392
|
+
* When a `phantom` handler is provided, phantom types (`designType === 'phantom'`)
|
|
1393
|
+
* are dispatched to it instead of `final`. This allows consumers to skip or
|
|
1394
|
+
* handle phantom props without polluting their `final` handler.
|
|
1395
|
+
*/ function forAnnotatedType(def, handlers) {
|
|
1348
1396
|
switch (def.type.kind) {
|
|
1349
1397
|
case "": {
|
|
1350
1398
|
const typed = def;
|
|
@@ -1362,21 +1410,27 @@ function forAnnotatedType(def, handlers) {
|
|
|
1362
1410
|
|
|
1363
1411
|
//#endregion
|
|
1364
1412
|
//#region packages/typescript/src/runtime/json-schema.ts
|
|
1365
|
-
|
|
1413
|
+
/**
|
|
1414
|
+
* Detects a discriminator property across union items.
|
|
1415
|
+
*
|
|
1416
|
+
* Scans all items for object-typed members that share a common property
|
|
1417
|
+
* with distinct const/literal values. If exactly one such property exists,
|
|
1418
|
+
* it is returned as the discriminator. Returns `null` when no qualifying
|
|
1419
|
+
* property exists, or when more than one does (ambiguous).
|
|
1420
|
+
*/ function detectDiscriminator(items) {
|
|
1366
1421
|
if (items.length < 2) return null;
|
|
1367
1422
|
for (const item of items) if (item.type.kind !== "object") return null;
|
|
1368
1423
|
const firstObj = items[0].type;
|
|
1369
1424
|
const candidates = [];
|
|
1370
|
-
for (const [propName, propType] of firstObj.props.entries()) if (propType.type.kind === "" && propType.type.value !==
|
|
1425
|
+
for (const [propName, propType] of firstObj.props.entries()) if (propType.type.kind === "" && propType.type.value !== void 0) candidates.push(propName);
|
|
1371
1426
|
let result = null;
|
|
1372
1427
|
for (const candidate of candidates) {
|
|
1373
|
-
const values = new Set();
|
|
1428
|
+
const values = /* @__PURE__ */ new Set();
|
|
1374
1429
|
const indexMapping = {};
|
|
1375
1430
|
let valid = true;
|
|
1376
1431
|
for (let i = 0; i < items.length; i++) {
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
if (!prop || prop.type.kind !== "" || prop.type.value === undefined) {
|
|
1432
|
+
const prop = items[i].type.props.get(candidate);
|
|
1433
|
+
if (!prop || prop.type.kind !== "" || prop.type.value === void 0) {
|
|
1380
1434
|
valid = false;
|
|
1381
1435
|
break;
|
|
1382
1436
|
}
|
|
@@ -1398,7 +1452,23 @@ function detectDiscriminator(items) {
|
|
|
1398
1452
|
}
|
|
1399
1453
|
return result;
|
|
1400
1454
|
}
|
|
1401
|
-
|
|
1455
|
+
/**
|
|
1456
|
+
* Builds a JSON Schema from an {@link TAtscriptAnnotatedType}.
|
|
1457
|
+
*
|
|
1458
|
+
* Translates the atscript type structure and validation metadata
|
|
1459
|
+
* (min/max, patterns, integer constraints, etc.) into a standard JSON Schema.
|
|
1460
|
+
*
|
|
1461
|
+
* @example
|
|
1462
|
+
* ```ts
|
|
1463
|
+
* import { buildJsonSchema } from '@atscript/typescript'
|
|
1464
|
+
*
|
|
1465
|
+
* const schema = buildJsonSchema(MyInterface)
|
|
1466
|
+
* // { type: 'object', properties: { ... }, required: [...] }
|
|
1467
|
+
* ```
|
|
1468
|
+
*
|
|
1469
|
+
* @param type - The annotated type to convert.
|
|
1470
|
+
* @returns A JSON Schema object.
|
|
1471
|
+
*/ function buildJsonSchema(type) {
|
|
1402
1472
|
const defs = {};
|
|
1403
1473
|
let hasDefs = false;
|
|
1404
1474
|
const buildObject = (d) => {
|
|
@@ -1406,17 +1476,17 @@ function buildJsonSchema(type) {
|
|
|
1406
1476
|
const required = [];
|
|
1407
1477
|
for (const [key, val] of d.type.props.entries()) {
|
|
1408
1478
|
if (isPhantomType(val)) continue;
|
|
1409
|
-
properties[key] = build
|
|
1479
|
+
properties[key] = build(val);
|
|
1410
1480
|
if (!val.optional) required.push(key);
|
|
1411
1481
|
}
|
|
1412
|
-
const schema
|
|
1482
|
+
const schema = {
|
|
1413
1483
|
type: "object",
|
|
1414
1484
|
properties
|
|
1415
1485
|
};
|
|
1416
|
-
if (required.length > 0) schema
|
|
1417
|
-
return schema
|
|
1486
|
+
if (required.length > 0) schema.required = required;
|
|
1487
|
+
return schema;
|
|
1418
1488
|
};
|
|
1419
|
-
const build
|
|
1489
|
+
const build = (def) => {
|
|
1420
1490
|
if (def.id && def.type.kind === "object" && def !== type) {
|
|
1421
1491
|
const name = def.id;
|
|
1422
1492
|
if (!defs[name]) {
|
|
@@ -1435,20 +1505,20 @@ function buildJsonSchema(type) {
|
|
|
1435
1505
|
return buildObject(d);
|
|
1436
1506
|
},
|
|
1437
1507
|
array(d) {
|
|
1438
|
-
const schema
|
|
1508
|
+
const schema = {
|
|
1439
1509
|
type: "array",
|
|
1440
|
-
items: build
|
|
1510
|
+
items: build(d.type.of)
|
|
1441
1511
|
};
|
|
1442
1512
|
const minLength = meta.get("expect.minLength");
|
|
1443
|
-
if (minLength) schema
|
|
1513
|
+
if (minLength) schema.minItems = typeof minLength === "number" ? minLength : minLength.length;
|
|
1444
1514
|
const maxLength = meta.get("expect.maxLength");
|
|
1445
|
-
if (maxLength) schema
|
|
1446
|
-
return schema
|
|
1515
|
+
if (maxLength) schema.maxItems = typeof maxLength === "number" ? maxLength : maxLength.length;
|
|
1516
|
+
return schema;
|
|
1447
1517
|
},
|
|
1448
1518
|
union(d) {
|
|
1449
1519
|
const disc = detectDiscriminator(d.type.items);
|
|
1450
1520
|
if (disc) {
|
|
1451
|
-
const oneOf = d.type.items.map(build
|
|
1521
|
+
const oneOf = d.type.items.map(build);
|
|
1452
1522
|
const mapping = {};
|
|
1453
1523
|
for (const [val, idx] of Object.entries(disc.indexMapping)) {
|
|
1454
1524
|
const item = d.type.items[idx];
|
|
@@ -1462,47 +1532,47 @@ function buildJsonSchema(type) {
|
|
|
1462
1532
|
}
|
|
1463
1533
|
};
|
|
1464
1534
|
}
|
|
1465
|
-
return { anyOf: d.type.items.map(build
|
|
1535
|
+
return { anyOf: d.type.items.map(build) };
|
|
1466
1536
|
},
|
|
1467
1537
|
intersection(d) {
|
|
1468
|
-
return { allOf: d.type.items.map(build
|
|
1538
|
+
return { allOf: d.type.items.map(build) };
|
|
1469
1539
|
},
|
|
1470
1540
|
tuple(d) {
|
|
1471
1541
|
return {
|
|
1472
1542
|
type: "array",
|
|
1473
|
-
items: d.type.items.map(build
|
|
1543
|
+
items: d.type.items.map(build),
|
|
1474
1544
|
additionalItems: false
|
|
1475
1545
|
};
|
|
1476
1546
|
},
|
|
1477
1547
|
final(d) {
|
|
1478
|
-
const schema
|
|
1479
|
-
if (d.type.value !==
|
|
1548
|
+
const schema = {};
|
|
1549
|
+
if (d.type.value !== void 0) schema.const = d.type.value;
|
|
1480
1550
|
if (d.type.designType && d.type.designType !== "any") {
|
|
1481
1551
|
const dt = d.type.designType;
|
|
1482
|
-
schema
|
|
1483
|
-
if (schema
|
|
1552
|
+
schema.type = dt === "undefined" ? "null" : dt === "decimal" ? "string" : dt;
|
|
1553
|
+
if (schema.type === "number" && meta.get("expect.int")) schema.type = "integer";
|
|
1484
1554
|
}
|
|
1485
|
-
if (schema
|
|
1486
|
-
if (meta.get("meta.required")) schema
|
|
1555
|
+
if (schema.type === "string") {
|
|
1556
|
+
if (meta.get("meta.required")) schema.minLength = 1;
|
|
1487
1557
|
const minLength = meta.get("expect.minLength");
|
|
1488
|
-
if (minLength) schema
|
|
1558
|
+
if (minLength) schema.minLength = typeof minLength === "number" ? minLength : minLength.length;
|
|
1489
1559
|
const maxLength = meta.get("expect.maxLength");
|
|
1490
|
-
if (maxLength) schema
|
|
1560
|
+
if (maxLength) schema.maxLength = typeof maxLength === "number" ? maxLength : maxLength.length;
|
|
1491
1561
|
const patterns = meta.get("expect.pattern");
|
|
1492
|
-
if (patterns?.length) if (patterns.length === 1) schema
|
|
1493
|
-
else schema
|
|
1562
|
+
if (patterns?.length) if (patterns.length === 1) schema.pattern = patterns[0].pattern;
|
|
1563
|
+
else schema.allOf = (schema.allOf || []).concat(patterns.map((p) => ({ pattern: p.pattern })));
|
|
1494
1564
|
}
|
|
1495
|
-
if (schema
|
|
1565
|
+
if (schema.type === "number" || schema.type === "integer") {
|
|
1496
1566
|
const min = meta.get("expect.min");
|
|
1497
|
-
if (min) schema
|
|
1567
|
+
if (min) schema.minimum = typeof min === "number" ? min : min.minValue;
|
|
1498
1568
|
const max = meta.get("expect.max");
|
|
1499
|
-
if (max) schema
|
|
1569
|
+
if (max) schema.maximum = typeof max === "number" ? max : max.maxValue;
|
|
1500
1570
|
}
|
|
1501
|
-
return schema
|
|
1571
|
+
return schema;
|
|
1502
1572
|
}
|
|
1503
1573
|
});
|
|
1504
1574
|
};
|
|
1505
|
-
const schema = build
|
|
1575
|
+
const schema = build(type);
|
|
1506
1576
|
if (hasDefs) return {
|
|
1507
1577
|
...schema,
|
|
1508
1578
|
$defs: defs
|
|
@@ -1519,7 +1589,7 @@ function _define_property$3(obj, key, value) {
|
|
|
1519
1589
|
configurable: true,
|
|
1520
1590
|
writable: true
|
|
1521
1591
|
});
|
|
1522
|
-
else obj[key] = value;
|
|
1592
|
+
else obj[key] = value;
|
|
1523
1593
|
return obj;
|
|
1524
1594
|
}
|
|
1525
1595
|
const QUERY_OP_MAP = {
|
|
@@ -1548,31 +1618,31 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
1548
1618
|
}
|
|
1549
1619
|
getExtendsRefs() {
|
|
1550
1620
|
if (this._extendsRefs) return this._extendsRefs;
|
|
1551
|
-
const out = new Map();
|
|
1552
|
-
const visitedInterfaces = new Set();
|
|
1553
|
-
for (const node of this.doc.nodes) if ((0,
|
|
1621
|
+
const out = /* @__PURE__ */ new Map();
|
|
1622
|
+
const visitedInterfaces = /* @__PURE__ */ new Set();
|
|
1623
|
+
for (const node of this.doc.nodes) if ((0, _atscript_core.isInterface)(node) && node.hasExtends) this.walkExtendsParents(node, this.doc, out, visitedInterfaces);
|
|
1554
1624
|
return this._extendsRefs = out;
|
|
1555
1625
|
}
|
|
1556
1626
|
walkRefs(node, visited, visit) {
|
|
1557
1627
|
if (!node || visited.has(node)) return;
|
|
1558
1628
|
visited.add(node);
|
|
1559
|
-
if ((0,
|
|
1629
|
+
if ((0, _atscript_core.isRef)(node)) {
|
|
1560
1630
|
visit(node);
|
|
1561
1631
|
return;
|
|
1562
1632
|
}
|
|
1563
|
-
if ((0,
|
|
1633
|
+
if ((0, _atscript_core.isGroup)(node)) {
|
|
1564
1634
|
for (const item of node.unwrap()) this.walkRefs(item, visited, visit);
|
|
1565
1635
|
return;
|
|
1566
1636
|
}
|
|
1567
|
-
if ((0,
|
|
1637
|
+
if ((0, _atscript_core.isArray)(node) || (0, _atscript_core.isProp)(node)) this.walkRefs(node.getDefinition(), visited, visit);
|
|
1568
1638
|
}
|
|
1569
1639
|
walkExtendsParents(iface, doc, out, visited) {
|
|
1570
1640
|
if (visited.has(iface)) return;
|
|
1571
1641
|
visited.add(iface);
|
|
1572
|
-
const visitedNodes = new Set();
|
|
1642
|
+
const visitedNodes = /* @__PURE__ */ new Set();
|
|
1573
1643
|
for (const token of iface.extendsTokens) {
|
|
1574
1644
|
const unwound = doc.unwindType(token.text);
|
|
1575
|
-
if (!unwound?.def || !(0,
|
|
1645
|
+
if (!unwound?.def || !(0, _atscript_core.isInterface)(unwound.def)) continue;
|
|
1576
1646
|
const parentInterface = unwound.def;
|
|
1577
1647
|
const parentDoc = unwound.doc;
|
|
1578
1648
|
this.walkRefs(parentInterface.getDefinition(), visitedNodes, (ref) => {
|
|
@@ -1587,18 +1657,18 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
1587
1657
|
const refToOriginDoc = this.getExtendsRefs();
|
|
1588
1658
|
if (refToOriginDoc.size === 0) return;
|
|
1589
1659
|
const taken = new Set(this.doc.registry.definitions.keys());
|
|
1590
|
-
const allocated = new Map();
|
|
1591
|
-
const synthPathCache = new Map();
|
|
1660
|
+
const allocated = /* @__PURE__ */ new Map();
|
|
1661
|
+
const synthPathCache = /* @__PURE__ */ new Map();
|
|
1592
1662
|
for (const [refNode, originDoc] of refToOriginDoc) {
|
|
1593
1663
|
const refId = refNode.id;
|
|
1594
1664
|
if (!refId) continue;
|
|
1595
1665
|
const ownerInfo = this.resolveOwner(originDoc, refId);
|
|
1596
1666
|
if (!ownerInfo?.doc || ownerInfo.doc === this.doc) continue;
|
|
1597
|
-
if (ownerInfo.node && (0,
|
|
1667
|
+
if (ownerInfo.node && (0, _atscript_core.isPrimitive)(ownerInfo.node)) continue;
|
|
1598
1668
|
const ownerDoc = ownerInfo.doc;
|
|
1599
1669
|
let synthPath;
|
|
1600
1670
|
if (synthPathCache.has(ownerDoc)) synthPath = synthPathCache.get(ownerDoc);
|
|
1601
|
-
else {
|
|
1671
|
+
else {
|
|
1602
1672
|
synthPath = this.computeSynthPath(ownerDoc);
|
|
1603
1673
|
synthPathCache.set(ownerDoc, synthPath);
|
|
1604
1674
|
}
|
|
@@ -1615,7 +1685,7 @@ else {
|
|
|
1615
1685
|
resolveOwner(fromDoc, refId) {
|
|
1616
1686
|
const key = `${fromDoc.id}::${refId}`;
|
|
1617
1687
|
let v = this._ownerCache.get(key);
|
|
1618
|
-
if (v ===
|
|
1688
|
+
if (v === void 0 && !this._ownerCache.has(key)) {
|
|
1619
1689
|
v = fromDoc.getDeclarationOwnerNode(refId);
|
|
1620
1690
|
this._ownerCache.set(key, v);
|
|
1621
1691
|
}
|
|
@@ -1624,8 +1694,7 @@ else {
|
|
|
1624
1694
|
allocateSynthInfo(refId, synthPath, ownerInfo, taken) {
|
|
1625
1695
|
const ownerDoc = ownerInfo.doc;
|
|
1626
1696
|
const ownerNode = ownerInfo.node;
|
|
1627
|
-
|
|
1628
|
-
if (existing?.text === synthPath) return {
|
|
1697
|
+
if (this.doc.importedDefs.get(refId)?.text === synthPath) return {
|
|
1629
1698
|
alias: refId,
|
|
1630
1699
|
ownerDoc,
|
|
1631
1700
|
ownerNode
|
|
@@ -1658,26 +1727,26 @@ else {
|
|
|
1658
1727
|
return alias;
|
|
1659
1728
|
}
|
|
1660
1729
|
computeSynthPath(ownerDoc) {
|
|
1661
|
-
if ((0,
|
|
1662
|
-
if (!ownerDoc.id.startsWith("file://")) return
|
|
1663
|
-
return (0,
|
|
1730
|
+
if ((0, _atscript_core.isBareId)(ownerDoc.id)) return ownerDoc.id.slice(5, -3);
|
|
1731
|
+
if (!ownerDoc.id.startsWith("file://")) return;
|
|
1732
|
+
return (0, _atscript_core.getRelPath)(this.doc.id, ownerDoc.id);
|
|
1664
1733
|
}
|
|
1665
1734
|
pre() {
|
|
1666
1735
|
this.writeln("// prettier-ignore-start");
|
|
1667
1736
|
this.writeln("/* eslint-disable */");
|
|
1668
1737
|
this.writeln("/* oxlint-disable */");
|
|
1669
1738
|
let hasMutatingAnnotate = false;
|
|
1670
|
-
const nodesByName = new Map();
|
|
1739
|
+
const nodesByName = /* @__PURE__ */ new Map();
|
|
1671
1740
|
for (const node of this.doc.nodes) {
|
|
1672
1741
|
if (node.entity === "annotate" && node.isMutating) hasMutatingAnnotate = true;
|
|
1673
|
-
if (node.__typeId !== null && node.__typeId !==
|
|
1742
|
+
if (node.__typeId !== null && node.__typeId !== void 0 && node.id) {
|
|
1674
1743
|
const name = node.id;
|
|
1675
1744
|
if (!nodesByName.has(name)) nodesByName.set(name, []);
|
|
1676
1745
|
nodesByName.get(name).push(node);
|
|
1677
1746
|
}
|
|
1678
1747
|
}
|
|
1679
1748
|
for (const [name, nodes] of nodesByName) if (nodes.length === 1) this.typeIds.set(nodes[0], name);
|
|
1680
|
-
else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}__${i + 1}`);
|
|
1749
|
+
else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}__${i + 1}`);
|
|
1681
1750
|
const imports = ["defineAnnotatedType as $", "annotate as $a"];
|
|
1682
1751
|
if (hasMutatingAnnotate) imports.push("cloneRefProp as $c");
|
|
1683
1752
|
const jsonSchemaMode = resolveJsonSchemaMode(this.opts);
|
|
@@ -1692,14 +1761,14 @@ else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}_
|
|
|
1692
1761
|
}
|
|
1693
1762
|
}
|
|
1694
1763
|
buildAdHocMap(annotateNodes) {
|
|
1695
|
-
const map = new Map();
|
|
1764
|
+
const map = /* @__PURE__ */ new Map();
|
|
1696
1765
|
for (const annotateNode of annotateNodes) for (const entry of annotateNode.entries) {
|
|
1697
|
-
const path
|
|
1766
|
+
const path = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)].join(".") : entry.id;
|
|
1698
1767
|
const anns = entry.annotations || [];
|
|
1699
1768
|
if (anns.length > 0) {
|
|
1700
|
-
const existing = map.get(path
|
|
1769
|
+
const existing = map.get(path);
|
|
1701
1770
|
if (existing) existing.push(...anns);
|
|
1702
|
-
else map.set(path
|
|
1771
|
+
else map.set(path, [...anns]);
|
|
1703
1772
|
}
|
|
1704
1773
|
}
|
|
1705
1774
|
return map.size > 0 ? map : null;
|
|
@@ -1717,15 +1786,12 @@ else map.set(path$4, [...anns]);
|
|
|
1717
1786
|
for (const node of this.postAnnotate) if (node.entity === "annotate") {
|
|
1718
1787
|
const annotateNode = node;
|
|
1719
1788
|
if (annotateNode.isMutating) this.renderMutatingAnnotateNode(annotateNode);
|
|
1720
|
-
else {
|
|
1789
|
+
else {
|
|
1721
1790
|
const unwound = this.doc.unwindType(annotateNode.targetName);
|
|
1722
1791
|
if (unwound?.def) {
|
|
1723
1792
|
let def = this.doc.mergeIntersection(unwound.def);
|
|
1724
|
-
if ((0,
|
|
1725
|
-
|
|
1726
|
-
if (resolved) def = resolved;
|
|
1727
|
-
else def = def.getDefinition() || def;
|
|
1728
|
-
} else def = def.getDefinition() || def;
|
|
1793
|
+
if ((0, _atscript_core.isInterface)(def)) if (def.hasExtends) def = unwound.doc.resolveInterfaceExtends(def) || def.getDefinition() || def;
|
|
1794
|
+
else def = def.getDefinition() || def;
|
|
1729
1795
|
this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
|
|
1730
1796
|
this.annotateType(def, node.id);
|
|
1731
1797
|
this._adHocAnnotations = null;
|
|
@@ -1737,7 +1803,7 @@ else def = def.getDefinition() || def;
|
|
|
1737
1803
|
}
|
|
1738
1804
|
} else {
|
|
1739
1805
|
let def = node.getDefinition();
|
|
1740
|
-
if ((0,
|
|
1806
|
+
if ((0, _atscript_core.isInterface)(node) && node.hasExtends) {
|
|
1741
1807
|
const resolved = this.doc.resolveInterfaceExtends(node);
|
|
1742
1808
|
if (resolved) def = resolved;
|
|
1743
1809
|
}
|
|
@@ -1785,8 +1851,7 @@ else def = def.getDefinition() || def;
|
|
|
1785
1851
|
}
|
|
1786
1852
|
renderJsonSchemaMethod(node) {
|
|
1787
1853
|
const mode = resolveJsonSchemaMode(this.opts);
|
|
1788
|
-
|
|
1789
|
-
if (hasAnnotation || mode === "bundle") {
|
|
1854
|
+
if (node.countAnnotations("emit.jsonSchema") > 0 || mode === "bundle") {
|
|
1790
1855
|
const schema = JSON.stringify(buildJsonSchema(this.toAnnotatedType(node)));
|
|
1791
1856
|
this.writeln("static toJsonSchema() {");
|
|
1792
1857
|
this.indent().writeln(`return ${schema}`).unindent();
|
|
@@ -1809,13 +1874,13 @@ else def = def.getDefinition() || def;
|
|
|
1809
1874
|
}
|
|
1810
1875
|
}
|
|
1811
1876
|
renderDimMeasure(node) {
|
|
1812
|
-
if (!(0,
|
|
1877
|
+
if (!(0, _atscript_core.isInterface)(node)) return;
|
|
1813
1878
|
const interfaceNode = node;
|
|
1814
1879
|
if (!interfaceNode.annotations?.some((a) => a.name === "db.table" || a.name === "db.view" || a.name === "db.view.for")) return;
|
|
1815
1880
|
let struct;
|
|
1816
1881
|
if (interfaceNode.hasExtends) struct = this.doc.resolveInterfaceExtends(interfaceNode);
|
|
1817
1882
|
if (!struct) struct = interfaceNode.getDefinition();
|
|
1818
|
-
if (!struct || !(0,
|
|
1883
|
+
if (!struct || !(0, _atscript_core.isStructure)(struct)) return;
|
|
1819
1884
|
const structNode = struct;
|
|
1820
1885
|
const dims = [];
|
|
1821
1886
|
const measures = [];
|
|
@@ -1836,12 +1901,12 @@ else def = def.getDefinition() || def;
|
|
|
1836
1901
|
case "interface":
|
|
1837
1902
|
case "type": {
|
|
1838
1903
|
let def = node.getDefinition();
|
|
1839
|
-
if ((0,
|
|
1904
|
+
if ((0, _atscript_core.isInterface)(node) && node.hasExtends) {
|
|
1840
1905
|
const resolved = this.doc.resolveInterfaceExtends(node);
|
|
1841
1906
|
if (resolved) def = resolved;
|
|
1842
1907
|
}
|
|
1843
1908
|
const handle = this.toAnnotatedHandle(def, true);
|
|
1844
|
-
const typeId = this.typeIds.get(node) ?? (node.__typeId !== null && node.__typeId !==
|
|
1909
|
+
const typeId = this.typeIds.get(node) ?? (node.__typeId !== null && node.__typeId !== void 0 ? node.id : void 0);
|
|
1845
1910
|
if (typeId) handle.id(typeId);
|
|
1846
1911
|
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1847
1912
|
}
|
|
@@ -1883,14 +1948,13 @@ else def = def.getDefinition() || def;
|
|
|
1883
1948
|
const propHandle = this.toAnnotatedHandle(prop);
|
|
1884
1949
|
const pattern = prop.token("identifier")?.pattern;
|
|
1885
1950
|
if (pattern) handle.propPattern(pattern, propHandle.$type);
|
|
1886
|
-
else handle.prop(prop.id, propHandle.$type);
|
|
1951
|
+
else handle.prop(prop.id, propHandle.$type);
|
|
1887
1952
|
}
|
|
1888
1953
|
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1889
1954
|
}
|
|
1890
1955
|
case "group": {
|
|
1891
1956
|
const group = node;
|
|
1892
|
-
const
|
|
1893
|
-
const handle = defineAnnotatedType(kind);
|
|
1957
|
+
const handle = defineAnnotatedType(group.op === "|" ? "union" : "intersection");
|
|
1894
1958
|
for (const item of group.unwrap()) handle.item(this.toAnnotatedHandle(item).$type);
|
|
1895
1959
|
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1896
1960
|
}
|
|
@@ -1916,44 +1980,38 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1916
1980
|
annotations?.forEach((a) => {
|
|
1917
1981
|
switch (a.name) {
|
|
1918
1982
|
case "expect.minLength":
|
|
1919
|
-
case "expect.maxLength":
|
|
1983
|
+
case "expect.maxLength":
|
|
1920
1984
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1921
1985
|
length: Number(a.args[0].text),
|
|
1922
1986
|
message: a.args[1]?.text
|
|
1923
1987
|
});
|
|
1924
1988
|
break;
|
|
1925
|
-
|
|
1926
|
-
case "expect.min": {
|
|
1989
|
+
case "expect.min":
|
|
1927
1990
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1928
1991
|
minValue: Number(a.args[0].text),
|
|
1929
1992
|
message: a.args[1]?.text
|
|
1930
1993
|
});
|
|
1931
1994
|
break;
|
|
1932
|
-
|
|
1933
|
-
case "expect.max": {
|
|
1995
|
+
case "expect.max":
|
|
1934
1996
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1935
1997
|
maxValue: Number(a.args[0].text),
|
|
1936
1998
|
message: a.args[1]?.text
|
|
1937
1999
|
});
|
|
1938
2000
|
break;
|
|
1939
|
-
|
|
1940
|
-
case "expect.pattern": {
|
|
2001
|
+
case "expect.pattern":
|
|
1941
2002
|
handle.annotate(a.name, {
|
|
1942
2003
|
pattern: a.args[0]?.text || "",
|
|
1943
2004
|
flags: a.args[1]?.text,
|
|
1944
2005
|
message: a.args[2]?.text
|
|
1945
2006
|
}, true);
|
|
1946
2007
|
break;
|
|
1947
|
-
|
|
1948
|
-
case "expect.int": {
|
|
2008
|
+
case "expect.int":
|
|
1949
2009
|
handle.annotate(a.name, true);
|
|
1950
2010
|
break;
|
|
1951
|
-
}
|
|
1952
2011
|
case "expect.array.uniqueItems":
|
|
1953
|
-
case "expect.array.key":
|
|
2012
|
+
case "expect.array.key":
|
|
1954
2013
|
handle.annotate(a.name, { message: a.args[0]?.text });
|
|
1955
2014
|
break;
|
|
1956
|
-
}
|
|
1957
2015
|
default:
|
|
1958
2016
|
}
|
|
1959
2017
|
});
|
|
@@ -1967,16 +2025,16 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1967
2025
|
case "ref": {
|
|
1968
2026
|
const ref = node;
|
|
1969
2027
|
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
1970
|
-
if ((0,
|
|
1971
|
-
const ownerDecl
|
|
1972
|
-
if (!ownerDecl
|
|
2028
|
+
if ((0, _atscript_core.isPrimitive)(decl)) {
|
|
2029
|
+
const ownerDecl = this.resolveOwner(this.doc, ref.id);
|
|
2030
|
+
if (!ownerDecl?.node || ownerDecl.node.entity !== "type" && ownerDecl.node.entity !== "interface") {
|
|
1973
2031
|
this.annotateType(decl, name);
|
|
1974
2032
|
return this;
|
|
1975
2033
|
}
|
|
1976
2034
|
}
|
|
1977
2035
|
if (this._adHocAnnotations && this.hasAdHocAnnotationsThroughRef()) {
|
|
1978
|
-
let resolved = decl ? this.doc.mergeIntersection(decl) :
|
|
1979
|
-
if (resolved && (0,
|
|
2036
|
+
let resolved = decl ? this.doc.mergeIntersection(decl) : void 0;
|
|
2037
|
+
if (resolved && (0, _atscript_core.isInterface)(resolved)) resolved = resolved.getDefinition() || resolved;
|
|
1980
2038
|
if (resolved) {
|
|
1981
2039
|
this.annotateType(resolved, name);
|
|
1982
2040
|
return this;
|
|
@@ -1989,45 +2047,35 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1989
2047
|
node: synth.ownerNode
|
|
1990
2048
|
} : this.resolveOwner(this.doc, ref.id);
|
|
1991
2049
|
const refName = synth?.alias ?? ref.id;
|
|
1992
|
-
const
|
|
1993
|
-
const refExpr = isImported ? `() => ${refName}` : refName;
|
|
2050
|
+
const refExpr = !!synth || (ownerDecl ? ownerDecl.doc !== this.doc : false) ? `() => ${refName}` : refName;
|
|
1994
2051
|
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${refExpr}${chain})`);
|
|
1995
2052
|
if (!ref.hasChain) {
|
|
1996
|
-
if (ownerDecl?.node) {
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
this.resolveAnnotationValue(ownerDecl.node, an);
|
|
2000
|
-
});
|
|
2001
|
-
}
|
|
2053
|
+
if (ownerDecl?.node) ownerDecl.doc.filterPassedWhenReferred(ownerDecl.doc.evalAnnotationsForNode(ownerDecl.node))?.forEach((an) => {
|
|
2054
|
+
this.resolveAnnotationValue(ownerDecl.node, an);
|
|
2055
|
+
});
|
|
2002
2056
|
}
|
|
2003
2057
|
this.unindent();
|
|
2004
2058
|
return this;
|
|
2005
2059
|
}
|
|
2006
|
-
case "primitive":
|
|
2060
|
+
case "primitive":
|
|
2007
2061
|
this.definePrimitive(node, name);
|
|
2008
2062
|
return this;
|
|
2009
|
-
|
|
2010
|
-
case "const": {
|
|
2063
|
+
case "const":
|
|
2011
2064
|
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().defineConst(node).unindent();
|
|
2012
2065
|
return this;
|
|
2013
|
-
|
|
2014
|
-
case "structure": {
|
|
2066
|
+
case "structure":
|
|
2015
2067
|
this.writeln(`$("object"${name ? `, ${name}` : ""})`).indent().defineObject(node).unindent();
|
|
2016
2068
|
return this;
|
|
2017
|
-
|
|
2018
|
-
case "group": {
|
|
2069
|
+
case "group":
|
|
2019
2070
|
kind = node.op === "|" ? "union" : "intersection";
|
|
2020
2071
|
this.writeln(`$("${kind}"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
|
|
2021
2072
|
return this;
|
|
2022
|
-
|
|
2023
|
-
case "tuple": {
|
|
2073
|
+
case "tuple":
|
|
2024
2074
|
this.writeln(`$("tuple"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
|
|
2025
2075
|
return this;
|
|
2026
|
-
|
|
2027
|
-
case "array": {
|
|
2076
|
+
case "array":
|
|
2028
2077
|
this.writeln(`$("array"${name ? `, ${name}` : ""})`).indent().defineArray(node).unindent();
|
|
2029
2078
|
return this;
|
|
2030
|
-
}
|
|
2031
2079
|
default: return this;
|
|
2032
2080
|
}
|
|
2033
2081
|
}
|
|
@@ -2051,7 +2099,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
2051
2099
|
case "final": return this.writeln(`$(${d()}).designType("${def.value === "void" ? "undefined" : def.value}")`);
|
|
2052
2100
|
case "union":
|
|
2053
2101
|
case "intersection":
|
|
2054
|
-
case "tuple":
|
|
2102
|
+
case "tuple":
|
|
2055
2103
|
this.writeln(`$(${d(def.kind)})`);
|
|
2056
2104
|
this.indent();
|
|
2057
2105
|
for (const itemDef of def.items) {
|
|
@@ -2064,8 +2112,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
2064
2112
|
}
|
|
2065
2113
|
this.unindent();
|
|
2066
2114
|
return;
|
|
2067
|
-
|
|
2068
|
-
case "array": {
|
|
2115
|
+
case "array":
|
|
2069
2116
|
this.writeln(`$(${d("array")})`);
|
|
2070
2117
|
this.indent();
|
|
2071
2118
|
this.write(".of(");
|
|
@@ -2076,8 +2123,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
2076
2123
|
this.writeln(`)`);
|
|
2077
2124
|
this.unindent();
|
|
2078
2125
|
return;
|
|
2079
|
-
|
|
2080
|
-
case "object": {
|
|
2126
|
+
case "object":
|
|
2081
2127
|
this.writeln(`$(${d("object")})`);
|
|
2082
2128
|
this.indent();
|
|
2083
2129
|
for (const [key, propDef] of Object.entries(def.props)) {
|
|
@@ -2104,7 +2150,6 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
2104
2150
|
}
|
|
2105
2151
|
this.unindent();
|
|
2106
2152
|
return;
|
|
2107
|
-
}
|
|
2108
2153
|
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
2109
2154
|
}
|
|
2110
2155
|
}
|
|
@@ -2146,21 +2191,21 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
2146
2191
|
defineMetadata(node) {
|
|
2147
2192
|
let annotations;
|
|
2148
2193
|
const nodeDef = node.getDefinition?.();
|
|
2149
|
-
if (nodeDef && (0,
|
|
2194
|
+
if (nodeDef && (0, _atscript_core.isRef)(nodeDef)) {
|
|
2150
2195
|
const refNode = nodeDef;
|
|
2151
2196
|
if (!refNode.hasChain) {
|
|
2152
2197
|
const resolved = this.doc.unwindType(refNode.id, refNode.chain)?.def;
|
|
2153
|
-
if (resolved && !(0,
|
|
2154
|
-
else if (resolved && (0,
|
|
2198
|
+
if (resolved && !(0, _atscript_core.isPrimitive)(resolved)) annotations = node.annotations ?? [];
|
|
2199
|
+
else if (resolved && (0, _atscript_core.isPrimitive)(resolved)) {
|
|
2155
2200
|
const ownerDecl = this.doc.getDeclarationOwnerNode(refNode.id);
|
|
2156
2201
|
if (ownerDecl?.node && (ownerDecl.node.entity === "type" || ownerDecl.node.entity === "interface")) annotations = node.annotations ?? [];
|
|
2157
2202
|
}
|
|
2158
2203
|
}
|
|
2159
2204
|
}
|
|
2160
|
-
if (annotations ===
|
|
2205
|
+
if (annotations === void 0) annotations = this.doc.evalAnnotationsForNode(node);
|
|
2161
2206
|
if (this._adHocAnnotations && this._propPath.length > 0) {
|
|
2162
|
-
const path
|
|
2163
|
-
const adHoc = this._adHocAnnotations.get(path
|
|
2207
|
+
const path = this._propPath.join(".");
|
|
2208
|
+
const adHoc = this._adHocAnnotations.get(path);
|
|
2164
2209
|
if (adHoc) annotations = this.doc.mergeNodesAnnotations(annotations, adHoc);
|
|
2165
2210
|
}
|
|
2166
2211
|
annotations?.forEach((an) => {
|
|
@@ -2174,9 +2219,8 @@ else if (resolved && (0, __atscript_core.isPrimitive)(resolved)) {
|
|
|
2174
2219
|
*/ defineMetadataForAnnotateAlias(annotateNode) {
|
|
2175
2220
|
const annotateAnnotations = this.doc.evalAnnotationsForNode(annotateNode);
|
|
2176
2221
|
const targetDecl = this.doc.getDeclarationOwnerNode(annotateNode.targetName);
|
|
2177
|
-
const targetAnnotations = targetDecl?.node ? targetDecl.doc.evalAnnotationsForNode(targetDecl.node) :
|
|
2178
|
-
|
|
2179
|
-
merged.forEach((an) => {
|
|
2222
|
+
const targetAnnotations = targetDecl?.node ? targetDecl.doc.evalAnnotationsForNode(targetDecl.node) : void 0;
|
|
2223
|
+
this.doc.mergeNodesAnnotations(targetAnnotations, annotateAnnotations).forEach((an) => {
|
|
2180
2224
|
this.resolveAnnotationValue(annotateNode, an);
|
|
2181
2225
|
});
|
|
2182
2226
|
return this;
|
|
@@ -2184,14 +2228,12 @@ else if (resolved && (0, __atscript_core.isPrimitive)(resolved)) {
|
|
|
2184
2228
|
resolveAnnotationValue(node, an) {
|
|
2185
2229
|
const { value, multiple } = this.computeAnnotationValue(node, an);
|
|
2186
2230
|
if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value}, true)`);
|
|
2187
|
-
else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
2231
|
+
else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
2188
2232
|
}
|
|
2189
2233
|
emitRefValue(text) {
|
|
2190
2234
|
const dotIdx = text.indexOf(".");
|
|
2191
2235
|
if (dotIdx === -1) return `() => ${text}`;
|
|
2192
|
-
|
|
2193
|
-
const field = text.slice(dotIdx + 1);
|
|
2194
|
-
return `{ type: () => ${typeName}, field: "${escapeQuotes(field)}" }`;
|
|
2236
|
+
return `{ type: () => ${text.slice(0, dotIdx)}, field: "${escapeQuotes(text.slice(dotIdx + 1))}" }`;
|
|
2195
2237
|
}
|
|
2196
2238
|
emitArgValue(aSpec, argToken) {
|
|
2197
2239
|
if (aSpec.type === "ref") return this.emitRefValue(argToken.text);
|
|
@@ -2202,14 +2244,12 @@ else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
|
2202
2244
|
return this.emitQueryExpr(queryNode.expression);
|
|
2203
2245
|
}
|
|
2204
2246
|
emitQueryExpr(node) {
|
|
2205
|
-
if ((0,
|
|
2247
|
+
if ((0, _atscript_core.isQueryLogical)(node)) return this.emitQueryLogical(node);
|
|
2206
2248
|
return this.emitQueryComparison(node);
|
|
2207
2249
|
}
|
|
2208
2250
|
emitQueryLogical(node) {
|
|
2209
2251
|
if (node.operator === "not") return `{ "$not": ${this.emitQueryExpr(node.operands[0])} }`;
|
|
2210
|
-
|
|
2211
|
-
const items = node.operands.map((op) => this.emitQueryExpr(op)).join(", ");
|
|
2212
|
-
return `{ "${key}": [${items}] }`;
|
|
2252
|
+
return `{ "${node.operator === "and" ? "$and" : "$or"}": [${node.operands.map((op) => this.emitQueryExpr(op)).join(", ")}] }`;
|
|
2213
2253
|
}
|
|
2214
2254
|
emitQueryComparison(node) {
|
|
2215
2255
|
const left = this.emitQueryFieldRef(node.left);
|
|
@@ -2217,12 +2257,12 @@ else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${value})`);
|
|
|
2217
2257
|
const parts = [`left: ${left}`, `op: "${mappedOp}"`];
|
|
2218
2258
|
if (node.right) {
|
|
2219
2259
|
if ("fieldRef" in node.right && node.right.fieldRef) parts.push(`right: ${this.emitQueryFieldRef(node.right)}`);
|
|
2220
|
-
else if ("values" in node.right && node.right.values) {
|
|
2260
|
+
else if ("values" in node.right && node.right.values) {
|
|
2221
2261
|
const values = node.right.values.map((v) => this.emitQueryLiteral(v)).join(", ");
|
|
2222
2262
|
parts.push(`right: [${values}]`);
|
|
2223
2263
|
} else if ("valueToken" in node.right) parts.push(`right: ${this.emitQueryLiteral(node.right)}`);
|
|
2224
2264
|
} else if (node.operator === "exists") parts.push("right: true");
|
|
2225
|
-
else if (node.operator === "not exists") parts.push("right: false");
|
|
2265
|
+
else if (node.operator === "not exists") parts.push("right: false");
|
|
2226
2266
|
return `{ ${parts.join(", ")} }`;
|
|
2227
2267
|
}
|
|
2228
2268
|
emitQueryFieldRef(node) {
|
|
@@ -2240,11 +2280,10 @@ else if (node.operator === "not exists") parts.push("right: false");
|
|
|
2240
2280
|
const match = /^\/(.*)\/[a-z]*$/.exec(token.text);
|
|
2241
2281
|
return `"${escapeQuotes(match ? match[1] : token.text)}"`;
|
|
2242
2282
|
}
|
|
2243
|
-
case "identifier":
|
|
2283
|
+
case "identifier":
|
|
2244
2284
|
if (token.text === "true" || token.text === "false") return token.text;
|
|
2245
2285
|
if (token.text === "null" || token.text === "undefined") return "null";
|
|
2246
2286
|
return token.text;
|
|
2247
|
-
}
|
|
2248
2287
|
default: return token.text;
|
|
2249
2288
|
}
|
|
2250
2289
|
}
|
|
@@ -2265,8 +2304,7 @@ else if (node.operator === "not exists") parts.push("right: false");
|
|
|
2265
2304
|
targetValue += "}";
|
|
2266
2305
|
} else {
|
|
2267
2306
|
const aSpec = spec.arguments[0];
|
|
2268
|
-
|
|
2269
|
-
else targetValue = "true";
|
|
2307
|
+
targetValue = an.args[0] ? this.emitArgValue(aSpec, an.args[0]) : "true";
|
|
2270
2308
|
}
|
|
2271
2309
|
} else {
|
|
2272
2310
|
multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
|
|
@@ -2294,7 +2332,7 @@ else targetValue = "true";
|
|
|
2294
2332
|
accessors
|
|
2295
2333
|
});
|
|
2296
2334
|
}
|
|
2297
|
-
const cloneKeys = new Set();
|
|
2335
|
+
const cloneKeys = /* @__PURE__ */ new Set();
|
|
2298
2336
|
for (const clone of allClones) {
|
|
2299
2337
|
const key = `${clone.parentPath}|${clone.propName}`;
|
|
2300
2338
|
if (!cloneKeys.has(key)) {
|
|
@@ -2308,7 +2346,7 @@ else targetValue = "true";
|
|
|
2308
2346
|
this.writeln();
|
|
2309
2347
|
}
|
|
2310
2348
|
emitMutatingAnnotations(node, annotations, accessor) {
|
|
2311
|
-
const cleared = new Set();
|
|
2349
|
+
const cleared = /* @__PURE__ */ new Set();
|
|
2312
2350
|
for (const an of annotations) {
|
|
2313
2351
|
const { value, multiple } = this.computeAnnotationValue(node, an);
|
|
2314
2352
|
if (multiple) {
|
|
@@ -2323,9 +2361,9 @@ else targetValue = "true";
|
|
|
2323
2361
|
}
|
|
2324
2362
|
resolveTargetDef(targetName) {
|
|
2325
2363
|
const unwound = this.doc.unwindType(targetName);
|
|
2326
|
-
if (!unwound?.def) return
|
|
2364
|
+
if (!unwound?.def) return;
|
|
2327
2365
|
let def = unwound.def;
|
|
2328
|
-
if ((0,
|
|
2366
|
+
if ((0, _atscript_core.isInterface)(def)) def = def.getDefinition() || def;
|
|
2329
2367
|
return def;
|
|
2330
2368
|
}
|
|
2331
2369
|
/**
|
|
@@ -2344,7 +2382,7 @@ else targetValue = "true";
|
|
|
2344
2382
|
for (const { prefix, def } of accessors) {
|
|
2345
2383
|
const results = this.buildPropPaths(def, parts[i]);
|
|
2346
2384
|
if (results.length > 0) for (const result of results) if (i < parts.length - 1) {
|
|
2347
|
-
if (result.propDef && (0,
|
|
2385
|
+
if (result.propDef && (0, _atscript_core.isRef)(result.propDef)) clones.push({
|
|
2348
2386
|
parentPath: prefix,
|
|
2349
2387
|
propName: parts[i]
|
|
2350
2388
|
});
|
|
@@ -2356,11 +2394,11 @@ else targetValue = "true";
|
|
|
2356
2394
|
prefix: `${prefix}${result.path}?`,
|
|
2357
2395
|
def: result.propDef
|
|
2358
2396
|
});
|
|
2359
|
-
else {
|
|
2397
|
+
else {
|
|
2360
2398
|
const suffix = `.props.get("${escapeQuotes(parts[i])}")${i < parts.length - 1 ? "?.type" : "?"}`;
|
|
2361
2399
|
nextAccessors.push({
|
|
2362
2400
|
prefix: `${prefix}${suffix}`,
|
|
2363
|
-
def:
|
|
2401
|
+
def: void 0
|
|
2364
2402
|
});
|
|
2365
2403
|
}
|
|
2366
2404
|
}
|
|
@@ -2378,13 +2416,13 @@ else {
|
|
|
2378
2416
|
*/ buildPropPaths(def, propName) {
|
|
2379
2417
|
if (!def) return [];
|
|
2380
2418
|
def = this.doc.mergeIntersection(def);
|
|
2381
|
-
if ((0,
|
|
2419
|
+
if ((0, _atscript_core.isRef)(def)) {
|
|
2382
2420
|
const ref = def;
|
|
2383
2421
|
const unwound = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
2384
2422
|
return this.buildPropPaths(unwound, propName);
|
|
2385
2423
|
}
|
|
2386
|
-
if ((0,
|
|
2387
|
-
if ((0,
|
|
2424
|
+
if ((0, _atscript_core.isInterface)(def)) return this.buildPropPaths(def.getDefinition(), propName);
|
|
2425
|
+
if ((0, _atscript_core.isStructure)(def)) {
|
|
2388
2426
|
const prop = def.props.get(propName);
|
|
2389
2427
|
if (prop) return [{
|
|
2390
2428
|
path: `.props.get("${escapeQuotes(propName)}")`,
|
|
@@ -2392,9 +2430,8 @@ else {
|
|
|
2392
2430
|
}];
|
|
2393
2431
|
return [];
|
|
2394
2432
|
}
|
|
2395
|
-
if ((0,
|
|
2396
|
-
const
|
|
2397
|
-
const items = group.unwrap();
|
|
2433
|
+
if ((0, _atscript_core.isGroup)(def)) {
|
|
2434
|
+
const items = def.unwrap();
|
|
2398
2435
|
const results = [];
|
|
2399
2436
|
for (let i = 0; i < items.length; i++) for (const result of this.buildPropPaths(items[i], propName)) results.push({
|
|
2400
2437
|
path: `.items[${i}].type${result.path}`,
|
|
@@ -2405,21 +2442,23 @@ else {
|
|
|
2405
2442
|
return [];
|
|
2406
2443
|
}
|
|
2407
2444
|
constructor(doc, opts) {
|
|
2408
|
-
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), _define_property$3(this, "_unusedJs", void 0), _define_property$3(this, "_extendsRefs", void 0), _define_property$3(this, "_refSynthInfo", void 0), _define_property$3(this, "_synthImports", void 0), _define_property$3(this, "_synthComputed", void 0), _define_property$3(this, "_ownerCache", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map(), this._refSynthInfo = new Map(), this._synthImports = new Map(), this._synthComputed = false, this._ownerCache = new Map();
|
|
2445
|
+
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), _define_property$3(this, "_unusedJs", void 0), _define_property$3(this, "_extendsRefs", void 0), _define_property$3(this, "_refSynthInfo", void 0), _define_property$3(this, "_synthImports", void 0), _define_property$3(this, "_synthComputed", void 0), _define_property$3(this, "_ownerCache", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = /* @__PURE__ */ new Map(), this._refSynthInfo = /* @__PURE__ */ new Map(), this._synthImports = /* @__PURE__ */ new Map(), this._synthComputed = false, this._ownerCache = /* @__PURE__ */ new Map();
|
|
2409
2446
|
}
|
|
2410
2447
|
};
|
|
2411
2448
|
|
|
2412
2449
|
//#endregion
|
|
2413
2450
|
//#region packages/typescript/src/plugin.ts
|
|
2414
|
-
|
|
2415
|
-
|
|
2451
|
+
/**
|
|
2452
|
+
* Resolves the effective JSON schema mode from plugin options.
|
|
2453
|
+
*/ function resolveJsonSchemaMode(opts) {
|
|
2454
|
+
if (opts?.jsonSchema !== void 0) return opts.jsonSchema;
|
|
2416
2455
|
return false;
|
|
2417
2456
|
}
|
|
2418
2457
|
const tsPlugin = (opts) => {
|
|
2419
2458
|
return {
|
|
2420
2459
|
name: "typescript",
|
|
2421
2460
|
render(doc, format) {
|
|
2422
|
-
if (format === "dts" || format ===
|
|
2461
|
+
if (format === "dts" || format === _atscript_core.DEFAULT_FORMAT) return [{
|
|
2423
2462
|
fileName: `${doc.name}.d.ts`,
|
|
2424
2463
|
content: new TypeRenderer(doc, opts).render()
|
|
2425
2464
|
}];
|
|
@@ -2429,21 +2468,21 @@ const tsPlugin = (opts) => {
|
|
|
2429
2468
|
}];
|
|
2430
2469
|
},
|
|
2431
2470
|
async buildEnd(output, format, repo) {
|
|
2432
|
-
if (format === "dts" || format ===
|
|
2471
|
+
if (format === "dts" || format === _atscript_core.DEFAULT_FORMAT) {
|
|
2433
2472
|
const annotations = await repo.getUsedAnnotations();
|
|
2434
|
-
const tags = await repo.getPrimitivesTags() || new Set();
|
|
2473
|
+
const tags = await repo.getPrimitivesTags() || /* @__PURE__ */ new Set();
|
|
2435
2474
|
const rendered = [];
|
|
2436
2475
|
for (const [key, val] of Object.entries(annotations)) {
|
|
2437
2476
|
const multiple = val.multiple;
|
|
2438
2477
|
const typeLine = Array.from(val.types).map((t) => {
|
|
2439
2478
|
if (t.type === "object" && "props" in t) return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
2440
|
-
else return "optional" in t && t.optional ? `${t.type} | true` : t.type;
|
|
2479
|
+
else return "optional" in t && t.optional ? `${t.type} | true` : t.type;
|
|
2441
2480
|
}).join(" | ");
|
|
2442
2481
|
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
2443
2482
|
}
|
|
2444
2483
|
const renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
|
|
2445
2484
|
output.push({
|
|
2446
|
-
content: "// prettier-ignore-start\n/* eslint-disable */\n/* oxlint-disable */\n/**\n * 🪄 This file was generated by Atscript\n * It is generated based on annotations used in this project\n * Do not edit this file!\n *\n * Use `npx asc -f dts` command to re-generate this file\n */\nexport {}\n\ndeclare global {\n interface AtscriptMetadata {\n " + rendered.join("\n ") + "\n }\n
|
|
2485
|
+
content: "// prettier-ignore-start\n/* eslint-disable */\n/* oxlint-disable */\n/**\n * 🪄 This file was generated by Atscript\n * It is generated based on annotations used in this project\n * Do not edit this file!\n *\n * Use `npx asc -f dts` command to re-generate this file\n */\nexport {}\n\ndeclare global {\n interface AtscriptMetadata {\n " + rendered.join("\n ") + "\n }\n type AtscriptPrimitiveTags = " + renderedTags + "\n}\n// prettier-ignore-end",
|
|
2447
2486
|
fileName: "atscript.d.ts",
|
|
2448
2487
|
source: "",
|
|
2449
2488
|
target: path.default.join(repo.root, "atscript.d.ts")
|
|
@@ -2460,25 +2499,44 @@ async function getConfig(configFile, logger) {
|
|
|
2460
2499
|
if (configFile) {
|
|
2461
2500
|
const c = path.default.join(root, configFile);
|
|
2462
2501
|
if (!(0, fs.existsSync)(c)) {
|
|
2463
|
-
logger.error(`Config file
|
|
2502
|
+
logger.error(`Config file [4m${configFile}[24m not found`);
|
|
2464
2503
|
process.exit(1);
|
|
2465
2504
|
}
|
|
2466
|
-
logger.log(`Using config file
|
|
2467
|
-
return (0,
|
|
2505
|
+
logger.log(`Using config file [36m${configFile}[39m`);
|
|
2506
|
+
return (0, _atscript_core.loadConfig)(c);
|
|
2468
2507
|
} else {
|
|
2469
|
-
const resolved = await (0,
|
|
2508
|
+
const resolved = await (0, _atscript_core.resolveConfigFile)(root);
|
|
2470
2509
|
if (resolved) {
|
|
2471
|
-
logger.log(`Using config file
|
|
2472
|
-
return (0,
|
|
2510
|
+
logger.log(`Using config file [36m${resolved}[39m`);
|
|
2511
|
+
return (0, _atscript_core.loadConfig)(resolved);
|
|
2473
2512
|
}
|
|
2474
2513
|
logger.log(`No atscript config file found`);
|
|
2475
2514
|
return {
|
|
2476
|
-
format:
|
|
2515
|
+
format: _atscript_core.DEFAULT_FORMAT,
|
|
2477
2516
|
plugins: [tsPlugin()]
|
|
2478
2517
|
};
|
|
2479
2518
|
}
|
|
2480
2519
|
}
|
|
2481
2520
|
|
|
2521
|
+
//#endregion
|
|
2522
|
+
//#region packages/typescript/src/cli/emit-policy.ts
|
|
2523
|
+
/**
|
|
2524
|
+
* Printed when diagnostics found errors and the emit was suppressed, so the
|
|
2525
|
+
* user knows the previous outputs are still the last known-good ones.
|
|
2526
|
+
*/ const NOTHING_EMITTED_MESSAGE = "Nothing emitted — previous outputs were left untouched. Fix the errors above, or pass --skipDiag to emit anyway.";
|
|
2527
|
+
/**
|
|
2528
|
+
* Decides whether `asc` may write its outputs.
|
|
2529
|
+
*
|
|
2530
|
+
* A failing compile must never replace valid artifacts: half of the outputs
|
|
2531
|
+
* would be stale and aggregate manifests produced in `buildEnd` would be
|
|
2532
|
+
* regenerated from an incomplete document set. Errors therefore block the
|
|
2533
|
+
* write entirely — `--skipDiag` is the explicit opt-out.
|
|
2534
|
+
*/ function shouldEmit(input) {
|
|
2535
|
+
if (input.noEmit) return false;
|
|
2536
|
+
if (input.skipDiag) return true;
|
|
2537
|
+
return input.errorCount === 0;
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2482
2540
|
//#endregion
|
|
2483
2541
|
//#region packages/typescript/src/cli/commands.controller.ts
|
|
2484
2542
|
function _define_property$2(obj, key, value) {
|
|
@@ -2488,13 +2546,13 @@ function _define_property$2(obj, key, value) {
|
|
|
2488
2546
|
configurable: true,
|
|
2489
2547
|
writable: true
|
|
2490
2548
|
});
|
|
2491
|
-
else obj[key] = value;
|
|
2549
|
+
else obj[key] = value;
|
|
2492
2550
|
return obj;
|
|
2493
2551
|
}
|
|
2494
2552
|
function _ts_decorate$1(decorators, target, key, desc) {
|
|
2495
2553
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2496
2554
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2497
|
-
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;
|
|
2555
|
+
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;
|
|
2498
2556
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2499
2557
|
}
|
|
2500
2558
|
function _ts_metadata$1(k, v) {
|
|
@@ -2508,9 +2566,9 @@ function _ts_param$1(paramIndex, decorator) {
|
|
|
2508
2566
|
var Commands = class {
|
|
2509
2567
|
async default(configFile, format, noEmit, skipDiag) {
|
|
2510
2568
|
const config = await getConfig(configFile, this.logger);
|
|
2511
|
-
config.format = format ||
|
|
2512
|
-
this.logger.log(`Format:
|
|
2513
|
-
const builder = await (0,
|
|
2569
|
+
config.format = format || _atscript_core.DEFAULT_FORMAT;
|
|
2570
|
+
this.logger.log(`Format: [36m${config.format}[39m`);
|
|
2571
|
+
const builder = await (0, _atscript_core.build)(config);
|
|
2514
2572
|
let errorCount = 0;
|
|
2515
2573
|
let warningCount = 0;
|
|
2516
2574
|
if (!skipDiag) {
|
|
@@ -2519,22 +2577,30 @@ var Commands = class {
|
|
|
2519
2577
|
const doc = builder.getDoc(docId);
|
|
2520
2578
|
for (const m of messages) {
|
|
2521
2579
|
if (m.severity === 1) errorCount++;
|
|
2522
|
-
else if (m.severity === 2) warningCount++;
|
|
2580
|
+
else if (m.severity === 2) warningCount++;
|
|
2523
2581
|
if (doc) this.logger.log(doc.renderDiagMessage(m, true, true));
|
|
2524
2582
|
}
|
|
2525
2583
|
}
|
|
2526
2584
|
}
|
|
2527
|
-
|
|
2585
|
+
const emit = shouldEmit({
|
|
2586
|
+
noEmit,
|
|
2587
|
+
skipDiag,
|
|
2588
|
+
errorCount
|
|
2589
|
+
});
|
|
2590
|
+
if (emit) {
|
|
2528
2591
|
const out = await builder.write(config);
|
|
2529
|
-
for (const { target } of out) this.logger.log(`✅ created
|
|
2592
|
+
for (const { target } of out) this.logger.log(`✅ created [32m${target}[39m`);
|
|
2530
2593
|
}
|
|
2531
2594
|
if (errorCount > 0 || warningCount > 0) {
|
|
2532
2595
|
const parts = [];
|
|
2533
|
-
if (errorCount > 0) parts.push(
|
|
2534
|
-
if (warningCount > 0) parts.push(
|
|
2596
|
+
if (errorCount > 0) parts.push(`[31m${errorCount} error${errorCount > 1 ? "s" : ""}[39m`);
|
|
2597
|
+
if (warningCount > 0) parts.push(`[33m${warningCount} warning${warningCount > 1 ? "s" : ""}[39m`);
|
|
2535
2598
|
this.logger.log(`\nFound ${parts.join(" and ")}`);
|
|
2536
2599
|
}
|
|
2537
|
-
if (errorCount > 0)
|
|
2600
|
+
if (errorCount > 0) {
|
|
2601
|
+
if (!emit && !noEmit) this.logger.log(`[33m${NOTHING_EMITTED_MESSAGE}[39m`);
|
|
2602
|
+
process.exit(1);
|
|
2603
|
+
}
|
|
2538
2604
|
}
|
|
2539
2605
|
constructor(logger) {
|
|
2540
2606
|
_define_property$2(this, "logger", void 0);
|
|
@@ -2542,22 +2608,22 @@ else if (m.severity === 2) warningCount++;
|
|
|
2542
2608
|
}
|
|
2543
2609
|
};
|
|
2544
2610
|
_ts_decorate$1([
|
|
2545
|
-
(0,
|
|
2611
|
+
(0, _moostjs_event_cli.Cli)(""),
|
|
2546
2612
|
(0, moost.Description)("Builds .as files using --config and --format"),
|
|
2547
|
-
(0,
|
|
2548
|
-
(0,
|
|
2549
|
-
(0,
|
|
2550
|
-
(0,
|
|
2551
|
-
_ts_param$1(0, (0,
|
|
2613
|
+
(0, _moostjs_event_cli.CliExample)("-c atscript.config.js", "Build .as files using atscript.config.js"),
|
|
2614
|
+
(0, _moostjs_event_cli.CliExample)("-f dts", "Build \"d.ts\" files for \".as\" files"),
|
|
2615
|
+
(0, _moostjs_event_cli.CliExample)("--noEmit", "Only check for errors, do not emit files"),
|
|
2616
|
+
(0, _moostjs_event_cli.CliExample)("--skipDiag", "Emit files without running diagnostics"),
|
|
2617
|
+
_ts_param$1(0, (0, _moostjs_event_cli.CliOption)("c", "config")),
|
|
2552
2618
|
_ts_param$1(0, (0, moost.Optional)()),
|
|
2553
2619
|
_ts_param$1(0, (0, moost.Description)("Path to config file")),
|
|
2554
|
-
_ts_param$1(1, (0,
|
|
2620
|
+
_ts_param$1(1, (0, _moostjs_event_cli.CliOption)("f", "format")),
|
|
2555
2621
|
_ts_param$1(1, (0, moost.Optional)()),
|
|
2556
2622
|
_ts_param$1(1, (0, moost.Description)("Output format (e.g. js, dts). Omit to run all plugins with their default output.")),
|
|
2557
|
-
_ts_param$1(2, (0,
|
|
2623
|
+
_ts_param$1(2, (0, _moostjs_event_cli.CliOption)("noEmit")),
|
|
2558
2624
|
_ts_param$1(2, (0, moost.Optional)()),
|
|
2559
2625
|
_ts_param$1(2, (0, moost.Description)("Only run diagnostics without emitting files")),
|
|
2560
|
-
_ts_param$1(3, (0,
|
|
2626
|
+
_ts_param$1(3, (0, _moostjs_event_cli.CliOption)("skipDiag")),
|
|
2561
2627
|
_ts_param$1(3, (0, moost.Optional)()),
|
|
2562
2628
|
_ts_param$1(3, (0, moost.Description)("Skip diagnostics and always emit files")),
|
|
2563
2629
|
_ts_metadata$1("design:type", Function),
|
|
@@ -2576,6 +2642,188 @@ Commands = _ts_decorate$1([
|
|
|
2576
2642
|
_ts_metadata$1("design:paramtypes", [typeof TConsoleBase === "undefined" ? Object : TConsoleBase])
|
|
2577
2643
|
], Commands);
|
|
2578
2644
|
|
|
2645
|
+
//#endregion
|
|
2646
|
+
//#region packages/typescript/src/cli/db-sync-models.ts
|
|
2647
|
+
/** Depth cap for `config.models` — deep enough for nested arrays and namespaces. */ const MAX_MODELS_DEPTH = 6;
|
|
2648
|
+
/** Keeps two runs in the same process (and the same millisecond) apart. */ let runSeq = 0;
|
|
2649
|
+
/**
|
|
2650
|
+
* Compiles the project's `.as` files and loads every `@db.table` / `@db.view`
|
|
2651
|
+
* model, plus the models contributed by `config.models`.
|
|
2652
|
+
*
|
|
2653
|
+
* The result is only a complete inventory when `diagnostics.errors` is 0 and
|
|
2654
|
+
* both `failures` and `modelsError` are empty — a caller that plans a sync
|
|
2655
|
+
* from a partial inventory would propose dropping the tables it failed to see.
|
|
2656
|
+
*/ async function loadDbModels(options) {
|
|
2657
|
+
const { config, cwd = process.cwd(), logger } = options;
|
|
2658
|
+
const buildConfig = toBuildConfig(config);
|
|
2659
|
+
logger?.log(`Compiling .as files...`);
|
|
2660
|
+
const builder = await (0, _atscript_core.build)(buildConfig);
|
|
2661
|
+
const diagnostics = await collectDiagnostics(builder);
|
|
2662
|
+
if (diagnostics.errors > 0) return {
|
|
2663
|
+
types: [],
|
|
2664
|
+
failures: [],
|
|
2665
|
+
diagnostics,
|
|
2666
|
+
packaged: 0
|
|
2667
|
+
};
|
|
2668
|
+
const { types, failures } = await importGeneratedModules(await builder.generate(buildConfig), buildConfig.rootDir || cwd, cwd);
|
|
2669
|
+
const result = {
|
|
2670
|
+
types,
|
|
2671
|
+
failures,
|
|
2672
|
+
diagnostics,
|
|
2673
|
+
packaged: 0
|
|
2674
|
+
};
|
|
2675
|
+
if (failures.length > 0 || !config.models) return result;
|
|
2676
|
+
try {
|
|
2677
|
+
const seen = new Set(types);
|
|
2678
|
+
for (const model of flattenModels(await config.models())) if (!seen.has(model)) {
|
|
2679
|
+
seen.add(model);
|
|
2680
|
+
types.push(model);
|
|
2681
|
+
result.packaged++;
|
|
2682
|
+
}
|
|
2683
|
+
} catch (error) {
|
|
2684
|
+
result.modelsError = error;
|
|
2685
|
+
}
|
|
2686
|
+
return result;
|
|
2687
|
+
}
|
|
2688
|
+
/** Abort message printed when some generated modules could not be imported. */ function partialInventoryMessage(count) {
|
|
2689
|
+
return `Could not load ${count} compiled model module(s); aborting before planning — a partial inventory would propose dropping tables.`;
|
|
2690
|
+
}
|
|
2691
|
+
function errorMessage(error) {
|
|
2692
|
+
return error instanceof Error ? error.message : String(error);
|
|
2693
|
+
}
|
|
2694
|
+
/**
|
|
2695
|
+
* Collects every `@db.table` / `@db.view` model out of whatever `config.models`
|
|
2696
|
+
* returned — an annotated type, an array, a module namespace object, or any
|
|
2697
|
+
* nesting of those. Deduplicated by identity.
|
|
2698
|
+
*/ function flattenModels(value) {
|
|
2699
|
+
const out = [];
|
|
2700
|
+
walkModels(value, out, /* @__PURE__ */ new Set(), 0);
|
|
2701
|
+
return out;
|
|
2702
|
+
}
|
|
2703
|
+
/** Rewrites the emitted `.as` specifiers to the `.mjs` files we just wrote. */ function patchAsImports(content) {
|
|
2704
|
+
return content.replace(/(from\s+["'][^"']+)\.as(["'])/g, "$1.as.mjs$2");
|
|
2705
|
+
}
|
|
2706
|
+
function toBuildConfig(config) {
|
|
2707
|
+
const buildConfig = { ...config };
|
|
2708
|
+
if (typeof config.db === "object" && "adapter" in config.db) {
|
|
2709
|
+
const dbConfig = config.db;
|
|
2710
|
+
if (dbConfig.include) buildConfig.include = dbConfig.include;
|
|
2711
|
+
if (dbConfig.exclude) buildConfig.exclude = dbConfig.exclude;
|
|
2712
|
+
}
|
|
2713
|
+
buildConfig.format = "js";
|
|
2714
|
+
return buildConfig;
|
|
2715
|
+
}
|
|
2716
|
+
async function collectDiagnostics(builder) {
|
|
2717
|
+
const diagnostics = {
|
|
2718
|
+
errors: 0,
|
|
2719
|
+
warnings: 0,
|
|
2720
|
+
messages: []
|
|
2721
|
+
};
|
|
2722
|
+
const diagMap = await builder.diagnostics();
|
|
2723
|
+
for (const [docId, messages] of diagMap) {
|
|
2724
|
+
const doc = builder.getDoc(docId);
|
|
2725
|
+
for (const m of messages) {
|
|
2726
|
+
if (m.severity === 1) diagnostics.errors++;
|
|
2727
|
+
else if (m.severity === 2) diagnostics.warnings++;
|
|
2728
|
+
if (doc) diagnostics.messages.push(doc.renderDiagMessage(m, true, true));
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
return diagnostics;
|
|
2732
|
+
}
|
|
2733
|
+
async function importGeneratedModules(outputs, rootDir, cwd) {
|
|
2734
|
+
const jsOutputs = [];
|
|
2735
|
+
for (const o of outputs) if (o.fileName.endsWith(".js") && o.source) jsOutputs.push({
|
|
2736
|
+
fileName: o.fileName,
|
|
2737
|
+
content: o.content,
|
|
2738
|
+
source: o.source
|
|
2739
|
+
});
|
|
2740
|
+
const base = resolveLayoutBase(rootDir, jsOutputs.map((o) => path.default.dirname((0, _atscript_core.fileUriToPath)(o.source))));
|
|
2741
|
+
const tmpDir = path.default.join(cwd, `.atscript-db-sync-${process.pid}-${Date.now()}-${runSeq++}`);
|
|
2742
|
+
const cleanup = () => {
|
|
2743
|
+
try {
|
|
2744
|
+
(0, fs.rmSync)(tmpDir, {
|
|
2745
|
+
recursive: true,
|
|
2746
|
+
force: true
|
|
2747
|
+
});
|
|
2748
|
+
} catch {}
|
|
2749
|
+
};
|
|
2750
|
+
process.on("exit", cleanup);
|
|
2751
|
+
try {
|
|
2752
|
+
const files = [];
|
|
2753
|
+
for (const o of jsOutputs) {
|
|
2754
|
+
const srcDir = path.default.dirname((0, _atscript_core.fileUriToPath)(o.source));
|
|
2755
|
+
const rel = path.default.join(path.default.relative(base, srcDir), o.fileName.replace(/\.js$/, ".mjs"));
|
|
2756
|
+
const abs = path.default.join(tmpDir, rel);
|
|
2757
|
+
(0, fs.mkdirSync)(path.default.dirname(abs), { recursive: true });
|
|
2758
|
+
(0, fs.writeFileSync)(abs, patchAsImports(o.content));
|
|
2759
|
+
files.push({
|
|
2760
|
+
abs,
|
|
2761
|
+
rel
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2764
|
+
const types = [];
|
|
2765
|
+
const failures = [];
|
|
2766
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2767
|
+
for (const file of files) try {
|
|
2768
|
+
collectFromModule(await import(
|
|
2769
|
+
/* @vite-ignore */
|
|
2770
|
+
(0, node_url.pathToFileURL)(file.abs).href
|
|
2771
|
+
), types, seen);
|
|
2772
|
+
} catch (error) {
|
|
2773
|
+
failures.push({
|
|
2774
|
+
file: file.rel,
|
|
2775
|
+
error
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
return {
|
|
2779
|
+
types,
|
|
2780
|
+
failures
|
|
2781
|
+
};
|
|
2782
|
+
} finally {
|
|
2783
|
+
cleanup();
|
|
2784
|
+
process.off("exit", cleanup);
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
function collectFromModule(mod, types, seen) {
|
|
2788
|
+
for (const exp of Object.values(mod)) if (isDbModel(exp) && !seen.has(exp)) {
|
|
2789
|
+
seen.add(exp);
|
|
2790
|
+
types.push(exp);
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
/**
|
|
2794
|
+
* Directory the temp layout mirrors. Normally `rootDir`; when a source lives
|
|
2795
|
+
* outside it, the common ancestor of `rootDir` and every source, so that no
|
|
2796
|
+
* `..` segment ever escapes the temp directory.
|
|
2797
|
+
*/ function resolveLayoutBase(rootDir, sourceDirs) {
|
|
2798
|
+
const root = path.default.resolve(rootDir);
|
|
2799
|
+
return sourceDirs.some((dir) => {
|
|
2800
|
+
const rel = path.default.relative(root, path.default.resolve(dir));
|
|
2801
|
+
return rel === ".." || rel.startsWith(`..${path.default.sep}`);
|
|
2802
|
+
}) ? commonAncestor([root, ...sourceDirs]) : root;
|
|
2803
|
+
}
|
|
2804
|
+
function commonAncestor(dirs) {
|
|
2805
|
+
const parts = dirs.map((d) => path.default.resolve(d).split(path.default.sep));
|
|
2806
|
+
const first = parts[0];
|
|
2807
|
+
let i = 0;
|
|
2808
|
+
while (i < first.length && parts.every((p) => p[i] === first[i])) i++;
|
|
2809
|
+
return first.slice(0, i).join(path.default.sep) || path.default.sep;
|
|
2810
|
+
}
|
|
2811
|
+
function isDbModel(value) {
|
|
2812
|
+
return isAnnotatedType(value) && Boolean(value.metadata?.has("db.table") || value.metadata?.has("db.view"));
|
|
2813
|
+
}
|
|
2814
|
+
function walkModels(value, out, seen, depth) {
|
|
2815
|
+
if (!value || typeof value !== "object" && typeof value !== "function") return;
|
|
2816
|
+
if (seen.has(value)) return;
|
|
2817
|
+
seen.add(value);
|
|
2818
|
+
if (isAnnotatedType(value)) {
|
|
2819
|
+
if (isDbModel(value)) out.push(value);
|
|
2820
|
+
return;
|
|
2821
|
+
}
|
|
2822
|
+
if (depth >= MAX_MODELS_DEPTH) return;
|
|
2823
|
+
const items = Array.isArray(value) ? value : Object.values(value);
|
|
2824
|
+
for (const item of items) walkModels(item, out, seen, depth + 1);
|
|
2825
|
+
}
|
|
2826
|
+
|
|
2579
2827
|
//#endregion
|
|
2580
2828
|
//#region packages/typescript/src/cli/db-sync-printer.ts
|
|
2581
2829
|
function _define_property$1(obj, key, value) {
|
|
@@ -2585,17 +2833,17 @@ function _define_property$1(obj, key, value) {
|
|
|
2585
2833
|
configurable: true,
|
|
2586
2834
|
writable: true
|
|
2587
2835
|
});
|
|
2588
|
-
else obj[key] = value;
|
|
2836
|
+
else obj[key] = value;
|
|
2589
2837
|
return obj;
|
|
2590
2838
|
}
|
|
2591
2839
|
const DYE_COLORS = {
|
|
2592
|
-
green: (s) =>
|
|
2593
|
-
red: (s) =>
|
|
2594
|
-
cyan: (s) =>
|
|
2595
|
-
yellow: (s) =>
|
|
2596
|
-
bold: (s) =>
|
|
2597
|
-
dim: (s) =>
|
|
2598
|
-
underline: (s) =>
|
|
2840
|
+
green: (s) => `[32m${s}[39m`,
|
|
2841
|
+
red: (s) => `[31m${s}[39m`,
|
|
2842
|
+
cyan: (s) => `[36m${s}[39m`,
|
|
2843
|
+
yellow: (s) => `[33m${s}[39m`,
|
|
2844
|
+
bold: (s) => `[1m${s}[22m`,
|
|
2845
|
+
dim: (s) => `[2m${s}[22m`,
|
|
2846
|
+
underline: (s) => `[4m${s}[24m`
|
|
2599
2847
|
};
|
|
2600
2848
|
const BANNER = DYE_COLORS.cyan(`
|
|
2601
2849
|
|
|
@@ -2623,7 +2871,7 @@ const PLAN_HEADER = [
|
|
|
2623
2871
|
DYE_COLORS.bold("╚══════════════════════════════════════╝"),
|
|
2624
2872
|
""
|
|
2625
2873
|
];
|
|
2626
|
-
function planFlags(plan) {
|
|
2874
|
+
/** Plan-level aggregates over the per-entry SyncEntry getters. */ function planFlags(plan) {
|
|
2627
2875
|
return {
|
|
2628
2876
|
destructive: plan.entries.some((e) => e.destructive),
|
|
2629
2877
|
hasChanges: plan.entries.some((e) => e.hasChanges),
|
|
@@ -2690,7 +2938,7 @@ var DbSyncPrinter = class {
|
|
|
2690
2938
|
errors: e.errors
|
|
2691
2939
|
}))
|
|
2692
2940
|
};
|
|
2693
|
-
return `${JSON.stringify(doc,
|
|
2941
|
+
return `${JSON.stringify(doc, void 0, 2)}\n`;
|
|
2694
2942
|
}
|
|
2695
2943
|
/** Renders the plan as a Markdown document (e.g. for PR comments). */ renderMarkdown(plan) {
|
|
2696
2944
|
const { destructive } = planFlags(plan);
|
|
@@ -2739,13 +2987,13 @@ function _define_property(obj, key, value) {
|
|
|
2739
2987
|
configurable: true,
|
|
2740
2988
|
writable: true
|
|
2741
2989
|
});
|
|
2742
|
-
else obj[key] = value;
|
|
2990
|
+
else obj[key] = value;
|
|
2743
2991
|
return obj;
|
|
2744
2992
|
}
|
|
2745
2993
|
function _ts_decorate(decorators, target, key, desc) {
|
|
2746
2994
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2747
2995
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2748
|
-
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;
|
|
2996
|
+
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;
|
|
2749
2997
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2750
2998
|
}
|
|
2751
2999
|
function _ts_metadata(k, v) {
|
|
@@ -2762,24 +3010,24 @@ var DbSyncController = class {
|
|
|
2762
3010
|
}
|
|
2763
3011
|
async dbSync(configFile, dryRun, yes, force, safe, check, format, out) {
|
|
2764
3012
|
if (format && format !== "json" && format !== "markdown") {
|
|
2765
|
-
this.logger.error(
|
|
3013
|
+
this.logger.error(`[31mUnknown --format "${format}". Use "json" or "markdown".[39m`);
|
|
2766
3014
|
process.exit(1);
|
|
2767
3015
|
}
|
|
2768
3016
|
this.quiet = Boolean(format) && !out;
|
|
2769
3017
|
this.printer.muted = this.quiet;
|
|
2770
|
-
const
|
|
2771
|
-
const config = await getConfig(configFile, cfgLogger);
|
|
3018
|
+
const config = await getConfig(configFile, this.quiet ? Object.create(this.logger, { log: { value: () => {} } }) : this.logger);
|
|
2772
3019
|
if (!config.db) {
|
|
2773
|
-
this.logger.error(
|
|
3020
|
+
this.logger.error("\x1B[31mNo \"db\" field in atscript config. Add a db configuration to use schema sync.\x1B[39m");
|
|
2774
3021
|
process.exit(1);
|
|
2775
3022
|
}
|
|
2776
|
-
const
|
|
3023
|
+
const dbTypes = await this.loadTypes(config);
|
|
2777
3024
|
if (dbTypes.length === 0) {
|
|
2778
3025
|
this.info(`No types with @db.table or @db.view found. Nothing to sync.`);
|
|
2779
3026
|
return;
|
|
2780
3027
|
}
|
|
2781
3028
|
this.printer.typeCount(dbTypes.length);
|
|
2782
3029
|
this.printer.banner();
|
|
3030
|
+
const dbSpace = await this.resolveDbSpace(config.db);
|
|
2783
3031
|
const { SchemaSync } = await this.importFromCwd("@atscript/db/sync", true);
|
|
2784
3032
|
const sync = new SchemaSync(dbSpace);
|
|
2785
3033
|
const plan = await sync.plan(dbTypes, {
|
|
@@ -2795,7 +3043,7 @@ var DbSyncController = class {
|
|
|
2795
3043
|
} else process.stdout.write(doc);
|
|
2796
3044
|
}
|
|
2797
3045
|
if (plan.status === "up-to-date") this.printer.planUpToDate(plan);
|
|
2798
|
-
else {
|
|
3046
|
+
else {
|
|
2799
3047
|
this.printer.plan(plan);
|
|
2800
3048
|
if (hasErrors) {
|
|
2801
3049
|
this.logger.error(`Schema has errors. Fix the issues above before syncing.`);
|
|
@@ -2823,8 +3071,7 @@ else {
|
|
|
2823
3071
|
}
|
|
2824
3072
|
if (hasDestructive) {
|
|
2825
3073
|
if (!yes) {
|
|
2826
|
-
|
|
2827
|
-
if (!confirmed) {
|
|
3074
|
+
if (!await this.confirm("Apply these changes? (includes destructive operations)")) {
|
|
2828
3075
|
this.logger.log("Aborted.");
|
|
2829
3076
|
return;
|
|
2830
3077
|
}
|
|
@@ -2836,46 +3083,33 @@ else {
|
|
|
2836
3083
|
});
|
|
2837
3084
|
this.printer.result(result);
|
|
2838
3085
|
}
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
for (const o of jsOutputs) {
|
|
2854
|
-
const target = path.default.join(tmpDir, o.fileName.replace(/\.js$/, ".mjs"));
|
|
2855
|
-
(0, fs.mkdirSync)(path.default.dirname(target), { recursive: true });
|
|
2856
|
-
(0, fs.writeFileSync)(target, patchAsImports(o.content));
|
|
2857
|
-
writtenFiles.push(target);
|
|
3086
|
+
/**
|
|
3087
|
+
* Loads the full model inventory or aborts. Diagnostics run first, every
|
|
3088
|
+
* generated module is imported individually, and any failure exits 1 before
|
|
3089
|
+
* a plan is computed.
|
|
3090
|
+
*/ async loadTypes(config) {
|
|
3091
|
+
const result = await loadDbModels({
|
|
3092
|
+
config,
|
|
3093
|
+
cwd: process.cwd(),
|
|
3094
|
+
logger: { log: (message) => this.info(message) }
|
|
3095
|
+
});
|
|
3096
|
+
if (result.diagnostics.errors > 0) {
|
|
3097
|
+
for (const message of result.diagnostics.messages) this.logger.error(message);
|
|
3098
|
+
this.logger.error(`Fix the errors above before syncing.`);
|
|
3099
|
+
process.exit(1);
|
|
2858
3100
|
}
|
|
2859
|
-
const
|
|
2860
|
-
|
|
2861
|
-
for (const
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
)
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
} catch (error) {
|
|
2869
|
-
this.logger.warn?.(`Could not import compiled types: ${error}`);
|
|
2870
|
-
} finally {
|
|
2871
|
-
try {
|
|
2872
|
-
(0, fs.rmSync)(tmpDir, {
|
|
2873
|
-
recursive: true,
|
|
2874
|
-
force: true
|
|
2875
|
-
});
|
|
2876
|
-
} catch {}
|
|
3101
|
+
for (const message of result.diagnostics.messages) this.info(message);
|
|
3102
|
+
if (result.failures.length > 0) {
|
|
3103
|
+
for (const failure of result.failures) this.logger.error(`[31m✖ ${failure.file}: ${errorMessage(failure.error)}[39m`);
|
|
3104
|
+
this.logger.error(`[31m${partialInventoryMessage(result.failures.length)}[39m`);
|
|
3105
|
+
process.exit(1);
|
|
3106
|
+
}
|
|
3107
|
+
if (result.modelsError) {
|
|
3108
|
+
this.logger.error(`[31mconfig.models failed: ${errorMessage(result.modelsError)}[39m`);
|
|
3109
|
+
process.exit(1);
|
|
2877
3110
|
}
|
|
2878
|
-
|
|
3111
|
+
if (result.packaged > 0) this.info(`Loaded ${result.packaged} packaged model(s) from config.models`);
|
|
3112
|
+
return result.types;
|
|
2879
3113
|
}
|
|
2880
3114
|
async resolveDbSpace(dbConfig) {
|
|
2881
3115
|
if (typeof dbConfig === "function") {
|
|
@@ -2883,24 +3117,23 @@ else {
|
|
|
2883
3117
|
return await dbConfig();
|
|
2884
3118
|
}
|
|
2885
3119
|
const { adapter, connection, options } = dbConfig;
|
|
2886
|
-
this.info(`Using adapter:
|
|
3120
|
+
this.info(`Using adapter: [36m${adapter}[39m`);
|
|
2887
3121
|
let mod;
|
|
2888
3122
|
try {
|
|
2889
3123
|
mod = await this.importFromCwd(adapter);
|
|
2890
3124
|
} catch {
|
|
2891
|
-
this.logger.error(
|
|
3125
|
+
this.logger.error(`[31mCould not import adapter package "${adapter}". Is it installed?[39m`);
|
|
2892
3126
|
process.exit(1);
|
|
2893
3127
|
}
|
|
2894
3128
|
if (typeof mod.createAdapter !== "function") {
|
|
2895
|
-
this.logger.error(
|
|
3129
|
+
this.logger.error(`[31mAdapter package "${adapter}" does not export a createAdapter function.[39m`);
|
|
2896
3130
|
process.exit(1);
|
|
2897
3131
|
}
|
|
2898
3132
|
const resolvedConnection = typeof connection === "function" ? await connection() : connection;
|
|
2899
3133
|
return mod.createAdapter(resolvedConnection, options);
|
|
2900
3134
|
}
|
|
2901
3135
|
async importFromCwd(specifier, preferEsm = false) {
|
|
2902
|
-
|
|
2903
|
-
let resolved = require$1.resolve(specifier);
|
|
3136
|
+
let resolved = (0, node_module.createRequire)(path.default.join(process.cwd(), "__synthetic.cjs")).resolve(specifier);
|
|
2904
3137
|
if (preferEsm) {
|
|
2905
3138
|
const mjsPath = resolved.replace(/\.cjs$/, ".mjs");
|
|
2906
3139
|
if ((0, fs.existsSync)(mjsPath)) resolved = mjsPath;
|
|
@@ -2932,38 +3165,38 @@ else {
|
|
|
2932
3165
|
}
|
|
2933
3166
|
};
|
|
2934
3167
|
_ts_decorate([
|
|
2935
|
-
(0,
|
|
3168
|
+
(0, _moostjs_event_cli.Cli)("db sync"),
|
|
2936
3169
|
(0, moost.Description)("Synchronize database schema with .as type definitions"),
|
|
2937
|
-
(0,
|
|
2938
|
-
(0,
|
|
2939
|
-
(0,
|
|
2940
|
-
(0,
|
|
2941
|
-
(0,
|
|
2942
|
-
(0,
|
|
2943
|
-
(0,
|
|
2944
|
-
(0,
|
|
2945
|
-
_ts_param(0, (0,
|
|
3170
|
+
(0, _moostjs_event_cli.CliExample)("db sync", "Interactive sync — shows plan, prompts, then applies"),
|
|
3171
|
+
(0, _moostjs_event_cli.CliExample)("db sync --dry-run", "Show what would change without applying"),
|
|
3172
|
+
(0, _moostjs_event_cli.CliExample)("db sync --yes", "Skip confirmation prompt (CI mode)"),
|
|
3173
|
+
(0, _moostjs_event_cli.CliExample)("db sync --force", "Re-sync even if schema hash matches"),
|
|
3174
|
+
(0, _moostjs_event_cli.CliExample)("db sync --safe", "Skip destructive operations (column/table drops)"),
|
|
3175
|
+
(0, _moostjs_event_cli.CliExample)("db sync --check", "Exit 1 when changes are needed, 2 when destructive (CI gate)"),
|
|
3176
|
+
(0, _moostjs_event_cli.CliExample)("db sync --format json", "Emit the plan as JSON to stdout, do not apply"),
|
|
3177
|
+
(0, _moostjs_event_cli.CliExample)("db sync --format markdown --out plan.md", "Write the plan as Markdown to a file"),
|
|
3178
|
+
_ts_param(0, (0, _moostjs_event_cli.CliOption)("c", "config")),
|
|
2946
3179
|
_ts_param(0, (0, moost.Optional)()),
|
|
2947
3180
|
_ts_param(0, (0, moost.Description)("Path to config file")),
|
|
2948
|
-
_ts_param(1, (0,
|
|
3181
|
+
_ts_param(1, (0, _moostjs_event_cli.CliOption)("dry-run")),
|
|
2949
3182
|
_ts_param(1, (0, moost.Optional)()),
|
|
2950
3183
|
_ts_param(1, (0, moost.Description)("Show plan only, do not apply changes")),
|
|
2951
|
-
_ts_param(2, (0,
|
|
3184
|
+
_ts_param(2, (0, _moostjs_event_cli.CliOption)("yes")),
|
|
2952
3185
|
_ts_param(2, (0, moost.Optional)()),
|
|
2953
3186
|
_ts_param(2, (0, moost.Description)("Skip confirmation prompt (CI mode)")),
|
|
2954
|
-
_ts_param(3, (0,
|
|
3187
|
+
_ts_param(3, (0, _moostjs_event_cli.CliOption)("force")),
|
|
2955
3188
|
_ts_param(3, (0, moost.Optional)()),
|
|
2956
3189
|
_ts_param(3, (0, moost.Description)("Ignore schema hash, re-sync even if up-to-date")),
|
|
2957
|
-
_ts_param(4, (0,
|
|
3190
|
+
_ts_param(4, (0, _moostjs_event_cli.CliOption)("safe")),
|
|
2958
3191
|
_ts_param(4, (0, moost.Optional)()),
|
|
2959
3192
|
_ts_param(4, (0, moost.Description)("Skip destructive operations (column/table drops)")),
|
|
2960
|
-
_ts_param(5, (0,
|
|
3193
|
+
_ts_param(5, (0, _moostjs_event_cli.CliOption)("check")),
|
|
2961
3194
|
_ts_param(5, (0, moost.Optional)()),
|
|
2962
3195
|
_ts_param(5, (0, moost.Description)("Plan only; exit 1 when changes are needed, 2 when destructive changes are present")),
|
|
2963
|
-
_ts_param(6, (0,
|
|
3196
|
+
_ts_param(6, (0, _moostjs_event_cli.CliOption)("f", "format")),
|
|
2964
3197
|
_ts_param(6, (0, moost.Optional)()),
|
|
2965
3198
|
_ts_param(6, (0, moost.Description)("Emit the plan as \"json\" or \"markdown\" instead of applying (plan-only mode)")),
|
|
2966
|
-
_ts_param(7, (0,
|
|
3199
|
+
_ts_param(7, (0, _moostjs_event_cli.CliOption)("out")),
|
|
2967
3200
|
_ts_param(7, (0, moost.Optional)()),
|
|
2968
3201
|
_ts_param(7, (0, moost.Description)("Write --format output to a file instead of stdout")),
|
|
2969
3202
|
_ts_metadata("design:type", Function),
|
|
@@ -2985,13 +3218,10 @@ DbSyncController = _ts_decorate([
|
|
|
2985
3218
|
_ts_metadata("design:type", Function),
|
|
2986
3219
|
_ts_metadata("design:paramtypes", [typeof TConsoleBase === "undefined" ? Object : TConsoleBase])
|
|
2987
3220
|
], DbSyncController);
|
|
2988
|
-
function patchAsImports(content) {
|
|
2989
|
-
return content.replace(/(from\s+["'][^"']+)\.as(["'])/g, "$1.as.mjs$2");
|
|
2990
|
-
}
|
|
2991
3221
|
|
|
2992
3222
|
//#endregion
|
|
2993
3223
|
//#region packages/typescript/src/cli/cli.ts
|
|
2994
|
-
new
|
|
3224
|
+
new _moostjs_event_cli.CliApp().controllers(Commands, DbSyncController).useHelp({ name: "asc" }).useOptions([{
|
|
2995
3225
|
keys: ["help"],
|
|
2996
3226
|
description: "Display instructions for the command."
|
|
2997
3227
|
}]).start();
|