@atscript/typescript 0.0.26 → 0.0.28
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 +689 -15
- package/dist/index.cjs +586 -361
- package/dist/index.d.ts +11 -2
- package/dist/index.mjs +586 -362
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -27,7 +27,7 @@ const __atscript_core = __toESM(require("@atscript/core"));
|
|
|
27
27
|
const path = __toESM(require("path"));
|
|
28
28
|
|
|
29
29
|
//#region packages/typescript/src/codegen/code-printer.ts
|
|
30
|
-
function _define_property$
|
|
30
|
+
function _define_property$4(obj, key, value) {
|
|
31
31
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
32
32
|
value,
|
|
33
33
|
enumerable: true,
|
|
@@ -120,17 +120,17 @@ else this.write(closing);
|
|
|
120
120
|
return " ".repeat(this.indentLevel * this.indentSize);
|
|
121
121
|
}
|
|
122
122
|
constructor() {
|
|
123
|
-
_define_property$
|
|
124
|
-
_define_property$
|
|
125
|
-
_define_property$
|
|
126
|
-
_define_property$
|
|
127
|
-
_define_property$
|
|
123
|
+
_define_property$4(this, "lines", []);
|
|
124
|
+
_define_property$4(this, "currentLine", "");
|
|
125
|
+
_define_property$4(this, "indentLevel", 0);
|
|
126
|
+
_define_property$4(this, "indentSize", 2);
|
|
127
|
+
_define_property$4(this, "blockStack", []);
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
//#endregion
|
|
132
132
|
//#region packages/typescript/src/codegen/base-renderer.ts
|
|
133
|
-
function _define_property$
|
|
133
|
+
function _define_property$3(obj, key, value) {
|
|
134
134
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
135
135
|
value,
|
|
136
136
|
enumerable: true,
|
|
@@ -189,7 +189,7 @@ var BaseRenderer = class extends CodePrinter {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
constructor(doc) {
|
|
192
|
-
super(), _define_property$
|
|
192
|
+
super(), _define_property$3(this, "doc", void 0), _define_property$3(this, "unused", void 0), this.doc = doc;
|
|
193
193
|
this.unused = new Set(this.doc.getUnusedTokens().map((t) => t.text));
|
|
194
194
|
}
|
|
195
195
|
};
|
|
@@ -207,6 +207,16 @@ function escapeQuotes(str) {
|
|
|
207
207
|
|
|
208
208
|
//#endregion
|
|
209
209
|
//#region packages/typescript/src/codegen/type-renderer.ts
|
|
210
|
+
function _define_property$2(obj, key, value) {
|
|
211
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
212
|
+
value,
|
|
213
|
+
enumerable: true,
|
|
214
|
+
configurable: true,
|
|
215
|
+
writable: true
|
|
216
|
+
});
|
|
217
|
+
else obj[key] = value;
|
|
218
|
+
return obj;
|
|
219
|
+
}
|
|
210
220
|
var TypeRenderer = class extends BaseRenderer {
|
|
211
221
|
pre() {
|
|
212
222
|
this.writeln("// prettier-ignore-start");
|
|
@@ -304,6 +314,7 @@ else if (patterns.length === 1) {
|
|
|
304
314
|
this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
|
|
305
315
|
this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
|
|
306
316
|
this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
317
|
+
this.writeln("static toJsonSchema: () => any");
|
|
307
318
|
}
|
|
308
319
|
this.pop();
|
|
309
320
|
}
|
|
@@ -346,6 +357,7 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFina
|
|
|
346
357
|
this.writeln(`const type: ${typeDef}`);
|
|
347
358
|
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
348
359
|
this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
360
|
+
if (this.opts?.jsonSchema) this.writeln("const toJsonSchema: () => any");
|
|
349
361
|
this.popln();
|
|
350
362
|
}
|
|
351
363
|
renderJsDoc(node) {
|
|
@@ -356,6 +368,9 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFina
|
|
|
356
368
|
this.writeln(` * @see {@link ./${this.doc.name}${rangeStr}}`);
|
|
357
369
|
this.writeln(` */`);
|
|
358
370
|
}
|
|
371
|
+
constructor(doc, opts) {
|
|
372
|
+
super(doc), _define_property$2(this, "opts", void 0), this.opts = opts;
|
|
373
|
+
}
|
|
359
374
|
};
|
|
360
375
|
function renderPrimitiveTypeDef(def) {
|
|
361
376
|
if (!def) return "unknown";
|
|
@@ -375,7 +390,7 @@ function renderPrimitiveTypeDef(def) {
|
|
|
375
390
|
}
|
|
376
391
|
|
|
377
392
|
//#endregion
|
|
378
|
-
//#region packages/typescript/src/
|
|
393
|
+
//#region packages/typescript/src/validator.ts
|
|
379
394
|
function _define_property$1(obj, key, value) {
|
|
380
395
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
381
396
|
value,
|
|
@@ -386,363 +401,75 @@ function _define_property$1(obj, key, value) {
|
|
|
386
401
|
else obj[key] = value;
|
|
387
402
|
return obj;
|
|
388
403
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
this.
|
|
393
|
-
this.
|
|
394
|
-
}
|
|
395
|
-
post() {
|
|
396
|
-
for (const node of this.postAnnotate) {
|
|
397
|
-
this.annotateType(node.getDefinition(), node.id);
|
|
398
|
-
this.indent().defineMetadata(node).unindent();
|
|
399
|
-
this.writeln();
|
|
400
|
-
}
|
|
401
|
-
this.writeln("// prettier-ignore-end");
|
|
402
|
-
super.post();
|
|
404
|
+
const regexCache = new Map();
|
|
405
|
+
var Validator = class {
|
|
406
|
+
isLimitExceeded() {
|
|
407
|
+
if (this.stackErrors.length > 0) return this.stackErrors[this.stackErrors.length - 1].length >= this.opts.errorLimit;
|
|
408
|
+
return this.errors.length >= this.opts.errorLimit;
|
|
403
409
|
}
|
|
404
|
-
|
|
405
|
-
this.
|
|
406
|
-
|
|
407
|
-
this.write(exported ? "export " : "");
|
|
408
|
-
this.write(`class ${node.id} `);
|
|
409
|
-
this.blockln("{}");
|
|
410
|
-
this.writeln("static __is_atscript_annotated_type = true");
|
|
411
|
-
this.writeln("static type = {}");
|
|
412
|
-
this.writeln("static metadata = new Map()");
|
|
413
|
-
this.popln();
|
|
414
|
-
this.postAnnotate.push(node);
|
|
415
|
-
this.writeln();
|
|
410
|
+
push(name) {
|
|
411
|
+
this.stackPath.push(name);
|
|
412
|
+
this.stackErrors.push([]);
|
|
416
413
|
}
|
|
417
|
-
|
|
418
|
-
this.
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
this.writeln("static type = {}");
|
|
425
|
-
this.writeln("static metadata = new Map()");
|
|
426
|
-
this.popln();
|
|
427
|
-
this.postAnnotate.push(node);
|
|
428
|
-
this.writeln();
|
|
414
|
+
pop(saveErrors) {
|
|
415
|
+
this.stackPath.pop();
|
|
416
|
+
const popped = this.stackErrors.pop();
|
|
417
|
+
if (saveErrors && popped?.length) popped.forEach((error) => {
|
|
418
|
+
this.error(error.message, error.path, error.details);
|
|
419
|
+
});
|
|
420
|
+
return popped;
|
|
429
421
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
const node = this.doc.mergeIntersection(_node);
|
|
433
|
-
let kind = node.entity;
|
|
434
|
-
switch (node.entity) {
|
|
435
|
-
case "ref": {
|
|
436
|
-
const ref = node;
|
|
437
|
-
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
438
|
-
if ((0, __atscript_core.isPrimitive)(decl)) {
|
|
439
|
-
this.annotateType(decl, name);
|
|
440
|
-
return this;
|
|
441
|
-
}
|
|
442
|
-
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
443
|
-
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`).unindent();
|
|
444
|
-
return this;
|
|
445
|
-
}
|
|
446
|
-
case "primitive": {
|
|
447
|
-
this.definePrimitive(node, name);
|
|
448
|
-
return this;
|
|
449
|
-
}
|
|
450
|
-
case "const": {
|
|
451
|
-
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().defineConst(node).unindent();
|
|
452
|
-
return this;
|
|
453
|
-
}
|
|
454
|
-
case "structure": {
|
|
455
|
-
this.writeln(`$("object"${name ? `, ${name}` : ""})`).indent().defineObject(node).unindent();
|
|
456
|
-
return this;
|
|
457
|
-
}
|
|
458
|
-
case "group": {
|
|
459
|
-
kind = node.op === "|" ? "union" : "intersection";
|
|
460
|
-
this.writeln(`$("${kind}"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
|
|
461
|
-
return this;
|
|
462
|
-
}
|
|
463
|
-
case "tuple": {
|
|
464
|
-
this.writeln(`$("tuple"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
|
|
465
|
-
return this;
|
|
466
|
-
}
|
|
467
|
-
case "array": {
|
|
468
|
-
this.writeln(`$("array"${name ? `, ${name}` : ""})`).indent().defineArray(node).unindent();
|
|
469
|
-
return this;
|
|
470
|
-
}
|
|
471
|
-
default: {
|
|
472
|
-
console.log("!!!!!!! UNKNOWN ", node.entity);
|
|
473
|
-
return this;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
422
|
+
clear() {
|
|
423
|
+
this.stackErrors[this.stackErrors.length - 1] = [];
|
|
476
424
|
}
|
|
477
|
-
|
|
478
|
-
const
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
425
|
+
error(message, path$2, details) {
|
|
426
|
+
const errors = this.stackErrors[this.stackErrors.length - 1] || this.errors;
|
|
427
|
+
const error = {
|
|
428
|
+
path: path$2 || this.path,
|
|
429
|
+
message
|
|
430
|
+
};
|
|
431
|
+
if (details?.length) error.details = details;
|
|
432
|
+
errors.push(error);
|
|
484
433
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
this.writeln(` .tags(${Array.from(node.tags).map((f) => `"${escapeQuotes(f)}"`).join(", ")})`);
|
|
488
|
-
return this;
|
|
434
|
+
throw() {
|
|
435
|
+
throw new ValidatorError(this.errors);
|
|
489
436
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
this.writeln(`$(${d(def.kind)})`);
|
|
500
|
-
this.indent();
|
|
501
|
-
for (const itemDef of def.items) {
|
|
502
|
-
this.write(`.item(`);
|
|
503
|
-
this.indent();
|
|
504
|
-
this.renderPrimitiveDef(itemDef);
|
|
505
|
-
this.writeln(".$type");
|
|
506
|
-
this.unindent();
|
|
507
|
-
this.write(`)`);
|
|
508
|
-
}
|
|
509
|
-
this.unindent();
|
|
510
|
-
return;
|
|
511
|
-
case "array":
|
|
512
|
-
this.writeln(`$(${d("array")})`);
|
|
513
|
-
this.indent();
|
|
514
|
-
this.write(".of(");
|
|
515
|
-
this.indent();
|
|
516
|
-
this.renderPrimitiveDef(def.of);
|
|
517
|
-
this.writeln(`.$type`);
|
|
518
|
-
this.unindent();
|
|
519
|
-
this.writeln(`)`);
|
|
520
|
-
this.unindent();
|
|
521
|
-
return;
|
|
522
|
-
case "object":
|
|
523
|
-
this.writeln(`$(${d("object")})`);
|
|
524
|
-
this.indent();
|
|
525
|
-
for (const [key, propDef] of Object.entries(def.props)) {
|
|
526
|
-
const optional = typeof propDef === "object" && propDef.optional;
|
|
527
|
-
this.writeln(`.prop(`);
|
|
528
|
-
this.indent();
|
|
529
|
-
this.writeln(`"${escapeQuotes(key)}",`);
|
|
530
|
-
this.renderPrimitiveDef(propDef);
|
|
531
|
-
if (optional) this.writeln(".optional()");
|
|
532
|
-
this.writeln(".$type");
|
|
533
|
-
this.unindent();
|
|
534
|
-
this.write(`)`);
|
|
535
|
-
}
|
|
536
|
-
for (const [key, propDef] of Object.entries(def.propsPatterns)) {
|
|
537
|
-
const optional = typeof propDef === "object" && propDef.optional;
|
|
538
|
-
this.writeln(`.propPattern(`);
|
|
539
|
-
this.indent();
|
|
540
|
-
this.writeln(`${key},`);
|
|
541
|
-
this.renderPrimitiveDef(propDef);
|
|
542
|
-
if (optional) this.writeln(".optional()");
|
|
543
|
-
this.writeln(".$type");
|
|
544
|
-
this.unindent();
|
|
545
|
-
this.write(`)`);
|
|
546
|
-
}
|
|
547
|
-
this.unindent();
|
|
548
|
-
return;
|
|
549
|
-
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
437
|
+
validate(value, safe) {
|
|
438
|
+
this.push("");
|
|
439
|
+
this.errors = [];
|
|
440
|
+
this.stackErrors = [];
|
|
441
|
+
const passed = this.validateSafe(this.def, value);
|
|
442
|
+
this.pop(!passed);
|
|
443
|
+
if (!passed) {
|
|
444
|
+
if (safe) return false;
|
|
445
|
+
this.throw();
|
|
550
446
|
}
|
|
447
|
+
return true;
|
|
551
448
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
this.writeln(`/${pattern.source}/${pattern.flags},`);
|
|
561
|
-
} else {
|
|
562
|
-
this.writeln(`.prop(`);
|
|
563
|
-
this.indent();
|
|
564
|
-
this.writeln(`"${escapeQuotes(prop.id)}",`);
|
|
565
|
-
}
|
|
566
|
-
this.annotateType(prop.getDefinition());
|
|
567
|
-
this.indent().defineMetadata(prop).unindent();
|
|
568
|
-
if (optional) this.writeln(" .optional()");
|
|
569
|
-
this.writeln(" .$type");
|
|
570
|
-
this.unindent();
|
|
571
|
-
this.write(`)`);
|
|
449
|
+
validateSafe(def, value) {
|
|
450
|
+
if (this.isLimitExceeded()) return false;
|
|
451
|
+
if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
|
|
452
|
+
if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.path);
|
|
453
|
+
if (def.optional && value === undefined) return true;
|
|
454
|
+
for (const plugin of this.opts.plugins) {
|
|
455
|
+
const result = plugin(this, def, value);
|
|
456
|
+
if (result === false || result === true) return result;
|
|
572
457
|
}
|
|
573
|
-
this.
|
|
574
|
-
return this;
|
|
458
|
+
return this.validateAnnotatedType(def, value);
|
|
575
459
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
for (const item of items) this.write(".item(").indent().annotateType(item).write(" .$type").writeln(`)`).unindent();
|
|
579
|
-
return this;
|
|
460
|
+
get path() {
|
|
461
|
+
return this.stackPath.slice(1).join(".");
|
|
580
462
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
this.
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
}
|
|
592
|
-
resolveAnnotationValue(node, an) {
|
|
593
|
-
const spec = this.doc.resolveAnnotation(an.name);
|
|
594
|
-
let targetValue = "true";
|
|
595
|
-
let multiple = false;
|
|
596
|
-
if (spec) {
|
|
597
|
-
multiple = spec.config.multiple;
|
|
598
|
-
const length = spec.arguments.length;
|
|
599
|
-
if (length !== 0) if (Array.isArray(spec.config.argument)) {
|
|
600
|
-
targetValue = "{ ";
|
|
601
|
-
let i = 0;
|
|
602
|
-
for (const aSpec of spec.arguments) {
|
|
603
|
-
if (an.args[i]) targetValue += `${wrapProp(aSpec.name)}: ${aSpec.type === "string" ? `"${escapeQuotes(an.args[i]?.text)}"` : an.args[i]?.text}${i === length - 1 ? "" : ", "} `;
|
|
604
|
-
else {}
|
|
605
|
-
i++;
|
|
606
|
-
}
|
|
607
|
-
targetValue += "}";
|
|
608
|
-
} else {
|
|
609
|
-
const aSpec = spec.arguments[0];
|
|
610
|
-
if (an.args[0]) targetValue = aSpec.type === "string" ? `"${escapeQuotes(an.args[0]?.text)}"` : an.args[0]?.text;
|
|
611
|
-
else targetValue = "true";
|
|
612
|
-
}
|
|
613
|
-
} else {
|
|
614
|
-
multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
|
|
615
|
-
if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
|
|
616
|
-
}
|
|
617
|
-
if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue}, true)`);
|
|
618
|
-
else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue})`);
|
|
619
|
-
}
|
|
620
|
-
constructor(...args) {
|
|
621
|
-
super(...args), _define_property$1(this, "postAnnotate", []);
|
|
622
|
-
}
|
|
623
|
-
};
|
|
624
|
-
|
|
625
|
-
//#endregion
|
|
626
|
-
//#region packages/typescript/src/plugin.ts
|
|
627
|
-
const tsPlugin = () => {
|
|
628
|
-
return {
|
|
629
|
-
name: "typesccript",
|
|
630
|
-
render(doc, format) {
|
|
631
|
-
if (format === "dts") return [{
|
|
632
|
-
fileName: `${doc.name}.d.ts`,
|
|
633
|
-
content: new TypeRenderer(doc).render()
|
|
634
|
-
}];
|
|
635
|
-
if (format === "js") return [{
|
|
636
|
-
fileName: `${doc.name}.js`,
|
|
637
|
-
content: new JsRenderer(doc).render()
|
|
638
|
-
}];
|
|
639
|
-
},
|
|
640
|
-
async buildEnd(output, format, repo) {
|
|
641
|
-
if (format === "dts") {
|
|
642
|
-
const annotations = await repo.getUsedAnnotations();
|
|
643
|
-
const tags = await repo.getPrimitivesTags() || new Set();
|
|
644
|
-
let rendered = [];
|
|
645
|
-
for (const [key, val] of Object.entries(annotations)) {
|
|
646
|
-
const multiple = val.multiple;
|
|
647
|
-
let typeLine = Array.from(val.types).map((t) => {
|
|
648
|
-
if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
649
|
-
else return t.optional ? `${t.type} | true` : t.type;
|
|
650
|
-
}).join(" | ");
|
|
651
|
-
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
652
|
-
}
|
|
653
|
-
let renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
|
|
654
|
-
output.push({
|
|
655
|
-
content: "// prettier-ignore-start\n/* eslint-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",
|
|
656
|
-
fileName: "atscript.d.ts",
|
|
657
|
-
source: "",
|
|
658
|
-
target: path.default.join(repo.root, "atscript.d.ts")
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
};
|
|
664
|
-
|
|
665
|
-
//#endregion
|
|
666
|
-
//#region packages/typescript/src/validator.ts
|
|
667
|
-
function _define_property(obj, key, value) {
|
|
668
|
-
if (key in obj) Object.defineProperty(obj, key, {
|
|
669
|
-
value,
|
|
670
|
-
enumerable: true,
|
|
671
|
-
configurable: true,
|
|
672
|
-
writable: true
|
|
673
|
-
});
|
|
674
|
-
else obj[key] = value;
|
|
675
|
-
return obj;
|
|
676
|
-
}
|
|
677
|
-
const regexCache = new Map();
|
|
678
|
-
var Validator = class {
|
|
679
|
-
isLimitExceeded() {
|
|
680
|
-
if (this.stackErrors.length > 0) return this.stackErrors[this.stackErrors.length - 1].length >= this.opts.errorLimit;
|
|
681
|
-
return this.errors.length >= this.opts.errorLimit;
|
|
682
|
-
}
|
|
683
|
-
push(name) {
|
|
684
|
-
this.stackPath.push(name);
|
|
685
|
-
this.stackErrors.push([]);
|
|
686
|
-
}
|
|
687
|
-
pop(saveErrors) {
|
|
688
|
-
this.stackPath.pop();
|
|
689
|
-
const popped = this.stackErrors.pop();
|
|
690
|
-
if (saveErrors && popped?.length) popped.forEach((error) => {
|
|
691
|
-
this.error(error.message, error.path, error.details);
|
|
692
|
-
});
|
|
693
|
-
return popped;
|
|
694
|
-
}
|
|
695
|
-
clear() {
|
|
696
|
-
this.stackErrors[this.stackErrors.length - 1] = [];
|
|
697
|
-
}
|
|
698
|
-
error(message, path$2, details) {
|
|
699
|
-
const errors = this.stackErrors[this.stackErrors.length - 1] || this.errors;
|
|
700
|
-
const error = {
|
|
701
|
-
path: path$2 || this.path,
|
|
702
|
-
message
|
|
703
|
-
};
|
|
704
|
-
if (details?.length) error.details = details;
|
|
705
|
-
errors.push(error);
|
|
706
|
-
}
|
|
707
|
-
throw() {
|
|
708
|
-
throw new ValidatorError(this.errors);
|
|
709
|
-
}
|
|
710
|
-
validate(value, safe) {
|
|
711
|
-
this.push("");
|
|
712
|
-
this.errors = [];
|
|
713
|
-
this.stackErrors = [];
|
|
714
|
-
const passed = this.validateSafe(this.def, value);
|
|
715
|
-
this.pop(!passed);
|
|
716
|
-
if (!passed) {
|
|
717
|
-
if (safe) return false;
|
|
718
|
-
this.throw();
|
|
719
|
-
}
|
|
720
|
-
return true;
|
|
721
|
-
}
|
|
722
|
-
validateSafe(def, value) {
|
|
723
|
-
if (this.isLimitExceeded()) return false;
|
|
724
|
-
if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
|
|
725
|
-
if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.path);
|
|
726
|
-
if (def.optional && value === undefined) return true;
|
|
727
|
-
for (const plugin of this.opts.plugins) {
|
|
728
|
-
const result = plugin(this, def, value);
|
|
729
|
-
if (result === false || result === true) return result;
|
|
730
|
-
}
|
|
731
|
-
return this.validateAnnotatedType(def, value);
|
|
732
|
-
}
|
|
733
|
-
get path() {
|
|
734
|
-
return this.stackPath.slice(1).join(".");
|
|
735
|
-
}
|
|
736
|
-
validateAnnotatedType(def, value) {
|
|
737
|
-
switch (def.type.kind) {
|
|
738
|
-
case "object": return this.validateObject(def, value);
|
|
739
|
-
case "union": return this.validateUnion(def, value);
|
|
740
|
-
case "intersection": return this.validateIntersection(def, value);
|
|
741
|
-
case "tuple": return this.validateTuple(def, value);
|
|
742
|
-
case "array": return this.validateArray(def, value);
|
|
743
|
-
case "": return this.validatePrimitive(def, value);
|
|
744
|
-
default: throw new Error(`Unknown type "${def.type.kind}"`);
|
|
745
|
-
}
|
|
463
|
+
validateAnnotatedType(def, value) {
|
|
464
|
+
switch (def.type.kind) {
|
|
465
|
+
case "object": return this.validateObject(def, value);
|
|
466
|
+
case "union": return this.validateUnion(def, value);
|
|
467
|
+
case "intersection": return this.validateIntersection(def, value);
|
|
468
|
+
case "tuple": return this.validateTuple(def, value);
|
|
469
|
+
case "array": return this.validateArray(def, value);
|
|
470
|
+
case "": return this.validatePrimitive(def, value);
|
|
471
|
+
default: throw new Error(`Unknown type "${def.type.kind}"`);
|
|
472
|
+
}
|
|
746
473
|
}
|
|
747
474
|
validateUnion(def, value) {
|
|
748
475
|
let i = 0;
|
|
@@ -972,11 +699,11 @@ else {
|
|
|
972
699
|
return true;
|
|
973
700
|
}
|
|
974
701
|
constructor(def, opts) {
|
|
975
|
-
_define_property(this, "def", void 0);
|
|
976
|
-
_define_property(this, "opts", void 0);
|
|
977
|
-
_define_property(this, "errors", void 0);
|
|
978
|
-
_define_property(this, "stackErrors", void 0);
|
|
979
|
-
_define_property(this, "stackPath", void 0);
|
|
702
|
+
_define_property$1(this, "def", void 0);
|
|
703
|
+
_define_property$1(this, "opts", void 0);
|
|
704
|
+
_define_property$1(this, "errors", void 0);
|
|
705
|
+
_define_property$1(this, "stackErrors", void 0);
|
|
706
|
+
_define_property$1(this, "stackPath", void 0);
|
|
980
707
|
this.def = def;
|
|
981
708
|
this.errors = [];
|
|
982
709
|
this.stackErrors = [];
|
|
@@ -992,7 +719,7 @@ else {
|
|
|
992
719
|
};
|
|
993
720
|
var ValidatorError = class extends Error {
|
|
994
721
|
constructor(errors) {
|
|
995
|
-
super(`${errors[0].path ? errors[0].path + ": " : ""}${errors[0].message}`), _define_property(this, "errors", void 0), _define_property(this, "name", void 0), this.errors = errors, this.name = "Validation Error";
|
|
722
|
+
super(`${errors[0].path ? errors[0].path + ": " : ""}${errors[0].message}`), _define_property$1(this, "errors", void 0), _define_property$1(this, "name", void 0), this.errors = errors, this.name = "Validation Error";
|
|
996
723
|
}
|
|
997
724
|
};
|
|
998
725
|
|
|
@@ -1125,6 +852,503 @@ function isAnnotatedTypeOfPrimitive(t) {
|
|
|
1125
852
|
return false;
|
|
1126
853
|
}
|
|
1127
854
|
|
|
855
|
+
//#endregion
|
|
856
|
+
//#region packages/typescript/src/json-schema.ts
|
|
857
|
+
function buildJsonSchema(type) {
|
|
858
|
+
const build = (def) => {
|
|
859
|
+
const t = def.type;
|
|
860
|
+
const meta = def.metadata;
|
|
861
|
+
switch (t.kind) {
|
|
862
|
+
case "object": {
|
|
863
|
+
const obj = t;
|
|
864
|
+
const properties = {};
|
|
865
|
+
const required = [];
|
|
866
|
+
for (const [key, val] of obj.props.entries()) {
|
|
867
|
+
properties[key] = build(val);
|
|
868
|
+
if (!val.optional) required.push(key);
|
|
869
|
+
}
|
|
870
|
+
const schema = {
|
|
871
|
+
type: "object",
|
|
872
|
+
properties
|
|
873
|
+
};
|
|
874
|
+
if (required.length) schema.required = required;
|
|
875
|
+
return schema;
|
|
876
|
+
}
|
|
877
|
+
case "array": {
|
|
878
|
+
const arr = t;
|
|
879
|
+
const schema = {
|
|
880
|
+
type: "array",
|
|
881
|
+
items: build(arr.of)
|
|
882
|
+
};
|
|
883
|
+
const minLength = meta.get("expect.minLength");
|
|
884
|
+
if (typeof minLength === "number") schema.minItems = minLength;
|
|
885
|
+
const maxLength = meta.get("expect.maxLength");
|
|
886
|
+
if (typeof maxLength === "number") schema.maxItems = maxLength;
|
|
887
|
+
return schema;
|
|
888
|
+
}
|
|
889
|
+
case "union": {
|
|
890
|
+
const grp = t;
|
|
891
|
+
return { anyOf: grp.items.map(build) };
|
|
892
|
+
}
|
|
893
|
+
case "intersection": {
|
|
894
|
+
const grp = t;
|
|
895
|
+
return { allOf: grp.items.map(build) };
|
|
896
|
+
}
|
|
897
|
+
case "tuple": {
|
|
898
|
+
const grp = t;
|
|
899
|
+
return {
|
|
900
|
+
type: "array",
|
|
901
|
+
items: grp.items.map(build),
|
|
902
|
+
additionalItems: false
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
case "": {
|
|
906
|
+
const fin = t;
|
|
907
|
+
const schema = {};
|
|
908
|
+
if (fin.value !== undefined) schema.const = fin.value;
|
|
909
|
+
if (fin.designType && fin.designType !== "any") {
|
|
910
|
+
schema.type = fin.designType === "undefined" ? "null" : fin.designType;
|
|
911
|
+
if (schema.type === "number" && meta.get("expect.int")) schema.type = "integer";
|
|
912
|
+
}
|
|
913
|
+
if (schema.type === "string") {
|
|
914
|
+
const minLength = meta.get("expect.minLength");
|
|
915
|
+
if (typeof minLength === "number") schema.minLength = minLength;
|
|
916
|
+
const maxLength = meta.get("expect.maxLength");
|
|
917
|
+
if (typeof maxLength === "number") schema.maxLength = maxLength;
|
|
918
|
+
const patterns = meta.get("expect.pattern");
|
|
919
|
+
if (patterns?.length) if (patterns.length === 1) schema.pattern = patterns[0].pattern;
|
|
920
|
+
else schema.allOf = (schema.allOf || []).concat(patterns.map((p) => ({ pattern: p.pattern })));
|
|
921
|
+
}
|
|
922
|
+
if (schema.type === "number" || schema.type === "integer") {
|
|
923
|
+
const min = meta.get("expect.min");
|
|
924
|
+
if (typeof min === "number") schema.minimum = min;
|
|
925
|
+
const max = meta.get("expect.max");
|
|
926
|
+
if (typeof max === "number") schema.maximum = max;
|
|
927
|
+
}
|
|
928
|
+
return schema;
|
|
929
|
+
}
|
|
930
|
+
default: return {};
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
return build(type);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
//#endregion
|
|
937
|
+
//#region packages/typescript/src/codegen/js-renderer.ts
|
|
938
|
+
function _define_property(obj, key, value) {
|
|
939
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
940
|
+
value,
|
|
941
|
+
enumerable: true,
|
|
942
|
+
configurable: true,
|
|
943
|
+
writable: true
|
|
944
|
+
});
|
|
945
|
+
else obj[key] = value;
|
|
946
|
+
return obj;
|
|
947
|
+
}
|
|
948
|
+
var JsRenderer = class extends BaseRenderer {
|
|
949
|
+
pre() {
|
|
950
|
+
this.writeln("// prettier-ignore-start");
|
|
951
|
+
this.writeln("/* eslint-disable */");
|
|
952
|
+
const imports = ["defineAnnotatedType as $"];
|
|
953
|
+
if (!this.opts?.preRenderJsonSchema) imports.push("buildJsonSchema as $$");
|
|
954
|
+
this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript"`);
|
|
955
|
+
}
|
|
956
|
+
post() {
|
|
957
|
+
for (const node of this.postAnnotate) {
|
|
958
|
+
this.annotateType(node.getDefinition(), node.id);
|
|
959
|
+
this.indent().defineMetadata(node).unindent();
|
|
960
|
+
this.writeln();
|
|
961
|
+
}
|
|
962
|
+
this.writeln("// prettier-ignore-end");
|
|
963
|
+
super.post();
|
|
964
|
+
}
|
|
965
|
+
renderInterface(node) {
|
|
966
|
+
this.writeln();
|
|
967
|
+
const exported = node.token("export")?.text === "export";
|
|
968
|
+
this.write(exported ? "export " : "");
|
|
969
|
+
this.write(`class ${node.id} `);
|
|
970
|
+
this.blockln("{}");
|
|
971
|
+
this.writeln("static __is_atscript_annotated_type = true");
|
|
972
|
+
this.writeln("static type = {}");
|
|
973
|
+
this.writeln("static metadata = new Map()");
|
|
974
|
+
if (this.opts?.preRenderJsonSchema) {
|
|
975
|
+
const schema = JSON.stringify(buildJsonSchema(this.toAnnotatedType(node)));
|
|
976
|
+
this.writeln(`static _jsonSchema = ${schema}`);
|
|
977
|
+
this.writeln("static toJsonSchema() {");
|
|
978
|
+
this.indent().writeln("return this._jsonSchema").unindent();
|
|
979
|
+
this.writeln("}");
|
|
980
|
+
} else {
|
|
981
|
+
this.writeln("static _jsonSchema");
|
|
982
|
+
this.writeln("static toJsonSchema() {");
|
|
983
|
+
this.indent().writeln("return this._jsonSchema ?? (this._jsonSchema = $$(this))").unindent();
|
|
984
|
+
this.writeln("}");
|
|
985
|
+
}
|
|
986
|
+
this.popln();
|
|
987
|
+
this.postAnnotate.push(node);
|
|
988
|
+
this.writeln();
|
|
989
|
+
}
|
|
990
|
+
renderType(node) {
|
|
991
|
+
this.writeln();
|
|
992
|
+
const exported = node.token("export")?.text === "export";
|
|
993
|
+
this.write(exported ? "export " : "");
|
|
994
|
+
this.write(`class ${node.id} `);
|
|
995
|
+
this.blockln("{}");
|
|
996
|
+
this.writeln("static __is_atscript_annotated_type = true");
|
|
997
|
+
this.writeln("static type = {}");
|
|
998
|
+
this.writeln("static metadata = new Map()");
|
|
999
|
+
if (this.opts?.jsonSchema) if (typeof this.opts.jsonSchema === "object" && this.opts.jsonSchema.preRender) {
|
|
1000
|
+
const schema = JSON.stringify(buildJsonSchema(this.toAnnotatedType(node)));
|
|
1001
|
+
this.writeln(`static _jsonSchema = ${schema}`);
|
|
1002
|
+
this.writeln("static toJsonSchema() {");
|
|
1003
|
+
this.indent().writeln("return this._jsonSchema").unindent();
|
|
1004
|
+
this.writeln("}");
|
|
1005
|
+
} else {
|
|
1006
|
+
this.writeln("static _jsonSchema");
|
|
1007
|
+
this.writeln("static toJsonSchema() {");
|
|
1008
|
+
this.indent().writeln("return this._jsonSchema ?? (this._jsonSchema = $$(this))").unindent();
|
|
1009
|
+
this.writeln("}");
|
|
1010
|
+
}
|
|
1011
|
+
this.popln();
|
|
1012
|
+
this.postAnnotate.push(node);
|
|
1013
|
+
this.writeln();
|
|
1014
|
+
}
|
|
1015
|
+
toAnnotatedType(node) {
|
|
1016
|
+
return this.toAnnotatedHandle(node).$type;
|
|
1017
|
+
}
|
|
1018
|
+
toAnnotatedHandle(node, skipAnnotations = false) {
|
|
1019
|
+
if (!node) return defineAnnotatedType();
|
|
1020
|
+
switch (node.entity) {
|
|
1021
|
+
case "interface":
|
|
1022
|
+
case "type": {
|
|
1023
|
+
const def = node.getDefinition();
|
|
1024
|
+
const handle = this.toAnnotatedHandle(def, true);
|
|
1025
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1026
|
+
}
|
|
1027
|
+
case "prop": {
|
|
1028
|
+
const prop = node;
|
|
1029
|
+
const def = prop.getDefinition();
|
|
1030
|
+
const handle = this.toAnnotatedHandle(def, true);
|
|
1031
|
+
if (!skipAnnotations) {
|
|
1032
|
+
this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(prop));
|
|
1033
|
+
if (prop.token("optional")) handle.optional();
|
|
1034
|
+
}
|
|
1035
|
+
return handle;
|
|
1036
|
+
}
|
|
1037
|
+
case "ref": {
|
|
1038
|
+
const ref = node;
|
|
1039
|
+
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
1040
|
+
const handle = this.toAnnotatedHandle(decl, true);
|
|
1041
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1042
|
+
}
|
|
1043
|
+
case "primitive": {
|
|
1044
|
+
const prim = node;
|
|
1045
|
+
const handle = defineAnnotatedType();
|
|
1046
|
+
handle.designType(prim.id === "never" ? "never" : prim.config.type);
|
|
1047
|
+
if (!skipAnnotations) this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1048
|
+
return handle;
|
|
1049
|
+
}
|
|
1050
|
+
case "const": {
|
|
1051
|
+
const c = node;
|
|
1052
|
+
const handle = defineAnnotatedType();
|
|
1053
|
+
const t = c.token("identifier")?.type;
|
|
1054
|
+
handle.designType(t === "number" ? "number" : "string");
|
|
1055
|
+
handle.value(t === "number" ? Number(c.id) : c.id);
|
|
1056
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1057
|
+
}
|
|
1058
|
+
case "structure": {
|
|
1059
|
+
const struct = node;
|
|
1060
|
+
const handle = defineAnnotatedType("object");
|
|
1061
|
+
for (const prop of Array.from(struct.props.values())) {
|
|
1062
|
+
const propHandle = this.toAnnotatedHandle(prop);
|
|
1063
|
+
const pattern = prop.token("identifier")?.pattern;
|
|
1064
|
+
if (pattern) handle.propPattern(pattern, propHandle.$type);
|
|
1065
|
+
else handle.prop(prop.id, propHandle.$type);
|
|
1066
|
+
}
|
|
1067
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1068
|
+
}
|
|
1069
|
+
case "group": {
|
|
1070
|
+
const group = node;
|
|
1071
|
+
const kind = group.op === "|" ? "union" : "intersection";
|
|
1072
|
+
const handle = defineAnnotatedType(kind);
|
|
1073
|
+
for (const item of group.unwrap()) handle.item(this.toAnnotatedHandle(item).$type);
|
|
1074
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1075
|
+
}
|
|
1076
|
+
case "tuple": {
|
|
1077
|
+
const group = node;
|
|
1078
|
+
const handle = defineAnnotatedType("tuple");
|
|
1079
|
+
for (const item of group.unwrap()) handle.item(this.toAnnotatedHandle(item).$type);
|
|
1080
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1081
|
+
}
|
|
1082
|
+
case "array": {
|
|
1083
|
+
const arr = node;
|
|
1084
|
+
const handle = defineAnnotatedType("array");
|
|
1085
|
+
handle.of(this.toAnnotatedHandle(arr.getDefinition()).$type);
|
|
1086
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1087
|
+
}
|
|
1088
|
+
default: {
|
|
1089
|
+
const handle = defineAnnotatedType();
|
|
1090
|
+
return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
applyExpectAnnotations(handle, annotations) {
|
|
1095
|
+
annotations?.forEach((a) => {
|
|
1096
|
+
switch (a.name) {
|
|
1097
|
+
case "expect.minLength":
|
|
1098
|
+
case "expect.maxLength":
|
|
1099
|
+
case "expect.min":
|
|
1100
|
+
case "expect.max":
|
|
1101
|
+
if (a.args[0]) handle.annotate(a.name, Number(a.args[0].text));
|
|
1102
|
+
break;
|
|
1103
|
+
case "expect.pattern":
|
|
1104
|
+
handle.annotate(a.name, {
|
|
1105
|
+
pattern: a.args[0]?.text || "",
|
|
1106
|
+
flags: a.args[1]?.text,
|
|
1107
|
+
message: a.args[2]?.text
|
|
1108
|
+
}, true);
|
|
1109
|
+
break;
|
|
1110
|
+
case "expect.int":
|
|
1111
|
+
handle.annotate(a.name, true);
|
|
1112
|
+
break;
|
|
1113
|
+
default:
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
return handle;
|
|
1117
|
+
}
|
|
1118
|
+
annotateType(_node, name) {
|
|
1119
|
+
if (!_node) return this;
|
|
1120
|
+
const node = this.doc.mergeIntersection(_node);
|
|
1121
|
+
let kind = node.entity;
|
|
1122
|
+
switch (node.entity) {
|
|
1123
|
+
case "ref": {
|
|
1124
|
+
const ref = node;
|
|
1125
|
+
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
1126
|
+
if ((0, __atscript_core.isPrimitive)(decl)) {
|
|
1127
|
+
this.annotateType(decl, name);
|
|
1128
|
+
return this;
|
|
1129
|
+
}
|
|
1130
|
+
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
1131
|
+
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`).unindent();
|
|
1132
|
+
return this;
|
|
1133
|
+
}
|
|
1134
|
+
case "primitive": {
|
|
1135
|
+
this.definePrimitive(node, name);
|
|
1136
|
+
return this;
|
|
1137
|
+
}
|
|
1138
|
+
case "const": {
|
|
1139
|
+
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().defineConst(node).unindent();
|
|
1140
|
+
return this;
|
|
1141
|
+
}
|
|
1142
|
+
case "structure": {
|
|
1143
|
+
this.writeln(`$("object"${name ? `, ${name}` : ""})`).indent().defineObject(node).unindent();
|
|
1144
|
+
return this;
|
|
1145
|
+
}
|
|
1146
|
+
case "group": {
|
|
1147
|
+
kind = node.op === "|" ? "union" : "intersection";
|
|
1148
|
+
this.writeln(`$("${kind}"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
|
|
1149
|
+
return this;
|
|
1150
|
+
}
|
|
1151
|
+
case "tuple": {
|
|
1152
|
+
this.writeln(`$("tuple"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
|
|
1153
|
+
return this;
|
|
1154
|
+
}
|
|
1155
|
+
case "array": {
|
|
1156
|
+
this.writeln(`$("array"${name ? `, ${name}` : ""})`).indent().defineArray(node).unindent();
|
|
1157
|
+
return this;
|
|
1158
|
+
}
|
|
1159
|
+
default: {
|
|
1160
|
+
console.log("!!!!!!! UNKNOWN ", node.entity);
|
|
1161
|
+
return this;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
defineConst(node) {
|
|
1166
|
+
const t = node.token("identifier")?.type;
|
|
1167
|
+
const designType = t === "text" ? "string" : t === "number" ? "number" : "unknown";
|
|
1168
|
+
this.writeln(`.designType("${escapeQuotes(designType)}")`);
|
|
1169
|
+
this.writeln(`.value(${t === "text" ? `"${escapeQuotes(node.id)}"` : node.id})`);
|
|
1170
|
+
return this;
|
|
1171
|
+
}
|
|
1172
|
+
definePrimitive(node, name) {
|
|
1173
|
+
this.renderPrimitiveDef(node.id === "never" ? "never" : node.config.type, name);
|
|
1174
|
+
this.writeln(` .tags(${Array.from(node.tags).map((f) => `"${escapeQuotes(f)}"`).join(", ")})`);
|
|
1175
|
+
return this;
|
|
1176
|
+
}
|
|
1177
|
+
renderPrimitiveDef(def, name) {
|
|
1178
|
+
const d = (t) => [`"${t || ""}"`, name].filter(Boolean).join(", ").replace(/^""$/, "");
|
|
1179
|
+
if (!def) return this.writeln(`$(${d()}).designType("any")`);
|
|
1180
|
+
if (typeof def === "string") return this.writeln(`$(${d()}).designType("${def === "void" ? "undefined" : def}")`);
|
|
1181
|
+
switch (def.kind) {
|
|
1182
|
+
case "final": return this.writeln(`$(${d()}).designType("${def.value === "void" ? "undefined" : def.value}")`);
|
|
1183
|
+
case "union":
|
|
1184
|
+
case "intersection":
|
|
1185
|
+
case "tuple":
|
|
1186
|
+
this.writeln(`$(${d(def.kind)})`);
|
|
1187
|
+
this.indent();
|
|
1188
|
+
for (const itemDef of def.items) {
|
|
1189
|
+
this.write(`.item(`);
|
|
1190
|
+
this.indent();
|
|
1191
|
+
this.renderPrimitiveDef(itemDef);
|
|
1192
|
+
this.writeln(".$type");
|
|
1193
|
+
this.unindent();
|
|
1194
|
+
this.write(`)`);
|
|
1195
|
+
}
|
|
1196
|
+
this.unindent();
|
|
1197
|
+
return;
|
|
1198
|
+
case "array":
|
|
1199
|
+
this.writeln(`$(${d("array")})`);
|
|
1200
|
+
this.indent();
|
|
1201
|
+
this.write(".of(");
|
|
1202
|
+
this.indent();
|
|
1203
|
+
this.renderPrimitiveDef(def.of);
|
|
1204
|
+
this.writeln(`.$type`);
|
|
1205
|
+
this.unindent();
|
|
1206
|
+
this.writeln(`)`);
|
|
1207
|
+
this.unindent();
|
|
1208
|
+
return;
|
|
1209
|
+
case "object":
|
|
1210
|
+
this.writeln(`$(${d("object")})`);
|
|
1211
|
+
this.indent();
|
|
1212
|
+
for (const [key, propDef] of Object.entries(def.props)) {
|
|
1213
|
+
const optional = typeof propDef === "object" && propDef.optional;
|
|
1214
|
+
this.writeln(`.prop(`);
|
|
1215
|
+
this.indent();
|
|
1216
|
+
this.writeln(`"${escapeQuotes(key)}",`);
|
|
1217
|
+
this.renderPrimitiveDef(propDef);
|
|
1218
|
+
if (optional) this.writeln(".optional()");
|
|
1219
|
+
this.writeln(".$type");
|
|
1220
|
+
this.unindent();
|
|
1221
|
+
this.write(`)`);
|
|
1222
|
+
}
|
|
1223
|
+
for (const [key, propDef] of Object.entries(def.propsPatterns)) {
|
|
1224
|
+
const optional = typeof propDef === "object" && propDef.optional;
|
|
1225
|
+
this.writeln(`.propPattern(`);
|
|
1226
|
+
this.indent();
|
|
1227
|
+
this.writeln(`${key},`);
|
|
1228
|
+
this.renderPrimitiveDef(propDef);
|
|
1229
|
+
if (optional) this.writeln(".optional()");
|
|
1230
|
+
this.writeln(".$type");
|
|
1231
|
+
this.unindent();
|
|
1232
|
+
this.write(`)`);
|
|
1233
|
+
}
|
|
1234
|
+
this.unindent();
|
|
1235
|
+
return;
|
|
1236
|
+
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
defineObject(node) {
|
|
1240
|
+
const props = Array.from(node.props.values());
|
|
1241
|
+
for (const prop of props) {
|
|
1242
|
+
const pattern = prop.token("identifier")?.pattern;
|
|
1243
|
+
const optional = !!prop.token("optional");
|
|
1244
|
+
if (pattern) {
|
|
1245
|
+
this.writeln(`.propPattern(`);
|
|
1246
|
+
this.indent();
|
|
1247
|
+
this.writeln(`/${pattern.source}/${pattern.flags},`);
|
|
1248
|
+
} else {
|
|
1249
|
+
this.writeln(`.prop(`);
|
|
1250
|
+
this.indent();
|
|
1251
|
+
this.writeln(`"${escapeQuotes(prop.id)}",`);
|
|
1252
|
+
}
|
|
1253
|
+
this.annotateType(prop.getDefinition());
|
|
1254
|
+
this.indent().defineMetadata(prop).unindent();
|
|
1255
|
+
if (optional) this.writeln(" .optional()");
|
|
1256
|
+
this.writeln(" .$type");
|
|
1257
|
+
this.unindent();
|
|
1258
|
+
this.write(`)`);
|
|
1259
|
+
}
|
|
1260
|
+
this.writeln();
|
|
1261
|
+
return this;
|
|
1262
|
+
}
|
|
1263
|
+
defineGroup(node) {
|
|
1264
|
+
const items = node.unwrap();
|
|
1265
|
+
for (const item of items) this.write(".item(").indent().annotateType(item).write(" .$type").writeln(`)`).unindent();
|
|
1266
|
+
return this;
|
|
1267
|
+
}
|
|
1268
|
+
defineArray(node) {
|
|
1269
|
+
this.write(".of(").indent().annotateType(node.getDefinition()).write(" .$type").writeln(`)`).unindent();
|
|
1270
|
+
return this;
|
|
1271
|
+
}
|
|
1272
|
+
defineMetadata(node) {
|
|
1273
|
+
const annotations = this.doc.evalAnnotationsForNode(node);
|
|
1274
|
+
annotations?.forEach((an) => {
|
|
1275
|
+
this.resolveAnnotationValue(node, an);
|
|
1276
|
+
});
|
|
1277
|
+
return this;
|
|
1278
|
+
}
|
|
1279
|
+
resolveAnnotationValue(node, an) {
|
|
1280
|
+
const spec = this.doc.resolveAnnotation(an.name);
|
|
1281
|
+
let targetValue = "true";
|
|
1282
|
+
let multiple = false;
|
|
1283
|
+
if (spec) {
|
|
1284
|
+
multiple = spec.config.multiple;
|
|
1285
|
+
const length = spec.arguments.length;
|
|
1286
|
+
if (length !== 0) if (Array.isArray(spec.config.argument)) {
|
|
1287
|
+
targetValue = "{ ";
|
|
1288
|
+
let i = 0;
|
|
1289
|
+
for (const aSpec of spec.arguments) {
|
|
1290
|
+
if (an.args[i]) targetValue += `${wrapProp(aSpec.name)}: ${aSpec.type === "string" ? `"${escapeQuotes(an.args[i]?.text)}"` : an.args[i]?.text}${i === length - 1 ? "" : ", "} `;
|
|
1291
|
+
else {}
|
|
1292
|
+
i++;
|
|
1293
|
+
}
|
|
1294
|
+
targetValue += "}";
|
|
1295
|
+
} else {
|
|
1296
|
+
const aSpec = spec.arguments[0];
|
|
1297
|
+
if (an.args[0]) targetValue = aSpec.type === "string" ? `"${escapeQuotes(an.args[0]?.text)}"` : an.args[0]?.text;
|
|
1298
|
+
else targetValue = "true";
|
|
1299
|
+
}
|
|
1300
|
+
} else {
|
|
1301
|
+
multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
|
|
1302
|
+
if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
|
|
1303
|
+
}
|
|
1304
|
+
if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue}, true)`);
|
|
1305
|
+
else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue})`);
|
|
1306
|
+
}
|
|
1307
|
+
constructor(doc, opts) {
|
|
1308
|
+
super(doc), _define_property(this, "opts", void 0), _define_property(this, "postAnnotate", void 0), this.opts = opts, this.postAnnotate = [];
|
|
1309
|
+
}
|
|
1310
|
+
};
|
|
1311
|
+
|
|
1312
|
+
//#endregion
|
|
1313
|
+
//#region packages/typescript/src/plugin.ts
|
|
1314
|
+
const tsPlugin = (opts) => {
|
|
1315
|
+
return {
|
|
1316
|
+
name: "typesccript",
|
|
1317
|
+
render(doc, format) {
|
|
1318
|
+
if (format === "dts") return [{
|
|
1319
|
+
fileName: `${doc.name}.d.ts`,
|
|
1320
|
+
content: new TypeRenderer(doc, opts).render()
|
|
1321
|
+
}];
|
|
1322
|
+
if (format === "js") return [{
|
|
1323
|
+
fileName: `${doc.name}.js`,
|
|
1324
|
+
content: new JsRenderer(doc, opts).render()
|
|
1325
|
+
}];
|
|
1326
|
+
},
|
|
1327
|
+
async buildEnd(output, format, repo) {
|
|
1328
|
+
if (format === "dts") {
|
|
1329
|
+
const annotations = await repo.getUsedAnnotations();
|
|
1330
|
+
const tags = await repo.getPrimitivesTags() || new Set();
|
|
1331
|
+
let rendered = [];
|
|
1332
|
+
for (const [key, val] of Object.entries(annotations)) {
|
|
1333
|
+
const multiple = val.multiple;
|
|
1334
|
+
let typeLine = Array.from(val.types).map((t) => {
|
|
1335
|
+
if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
1336
|
+
else return t.optional ? `${t.type} | true` : t.type;
|
|
1337
|
+
}).join(" | ");
|
|
1338
|
+
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
1339
|
+
}
|
|
1340
|
+
let renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
|
|
1341
|
+
output.push({
|
|
1342
|
+
content: "// prettier-ignore-start\n/* eslint-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",
|
|
1343
|
+
fileName: "atscript.d.ts",
|
|
1344
|
+
source: "",
|
|
1345
|
+
target: path.default.join(repo.root, "atscript.d.ts")
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1128
1352
|
//#endregion
|
|
1129
1353
|
//#region packages/typescript/src/index.ts
|
|
1130
1354
|
var src_default = tsPlugin;
|
|
@@ -1132,6 +1356,7 @@ var src_default = tsPlugin;
|
|
|
1132
1356
|
//#endregion
|
|
1133
1357
|
exports.Validator = Validator
|
|
1134
1358
|
exports.ValidatorError = ValidatorError
|
|
1359
|
+
exports.buildJsonSchema = buildJsonSchema
|
|
1135
1360
|
exports.default = src_default
|
|
1136
1361
|
exports.defineAnnotatedType = defineAnnotatedType
|
|
1137
1362
|
exports.isAnnotatedType = isAnnotatedType
|