@atscript/typescript 0.0.27 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { isArray, isConst, isGroup, isInterface, isPrimitive, isRef, isStructure
2
2
  import path from "path";
3
3
 
4
4
  //#region packages/typescript/src/codegen/code-printer.ts
5
- function _define_property$3(obj, key, value) {
5
+ function _define_property$4(obj, key, value) {
6
6
  if (key in obj) Object.defineProperty(obj, key, {
7
7
  value,
8
8
  enumerable: true,
@@ -95,17 +95,17 @@ else this.write(closing);
95
95
  return " ".repeat(this.indentLevel * this.indentSize);
96
96
  }
97
97
  constructor() {
98
- _define_property$3(this, "lines", []);
99
- _define_property$3(this, "currentLine", "");
100
- _define_property$3(this, "indentLevel", 0);
101
- _define_property$3(this, "indentSize", 2);
102
- _define_property$3(this, "blockStack", []);
98
+ _define_property$4(this, "lines", []);
99
+ _define_property$4(this, "currentLine", "");
100
+ _define_property$4(this, "indentLevel", 0);
101
+ _define_property$4(this, "indentSize", 2);
102
+ _define_property$4(this, "blockStack", []);
103
103
  }
104
104
  };
105
105
 
106
106
  //#endregion
107
107
  //#region packages/typescript/src/codegen/base-renderer.ts
108
- function _define_property$2(obj, key, value) {
108
+ function _define_property$3(obj, key, value) {
109
109
  if (key in obj) Object.defineProperty(obj, key, {
110
110
  value,
111
111
  enumerable: true,
@@ -127,7 +127,7 @@ var BaseRenderer = class extends CodePrinter {
127
127
  renderInterface(node) {}
128
128
  renderType(node) {}
129
129
  transformFromPath(path$1) {
130
- return path$1 + ".as";
130
+ return `${path$1}.as`;
131
131
  }
132
132
  renderImport(node) {
133
133
  const def = node.getDefinition();
@@ -164,7 +164,7 @@ var BaseRenderer = class extends CodePrinter {
164
164
  }
165
165
  }
166
166
  constructor(doc) {
167
- super(), _define_property$2(this, "doc", void 0), _define_property$2(this, "unused", void 0), this.doc = doc;
167
+ super(), _define_property$3(this, "doc", void 0), _define_property$3(this, "unused", void 0), this.doc = doc;
168
168
  this.unused = new Set(this.doc.getUnusedTokens().map((t) => t.text));
169
169
  }
170
170
  };
@@ -182,7 +182,17 @@ function escapeQuotes(str) {
182
182
 
183
183
  //#endregion
184
184
  //#region packages/typescript/src/codegen/type-renderer.ts
185
- var TypeRenderer = class extends BaseRenderer {
185
+ function _define_property$2(obj, key, value) {
186
+ if (key in obj) Object.defineProperty(obj, key, {
187
+ value,
188
+ enumerable: true,
189
+ configurable: true,
190
+ writable: true
191
+ });
192
+ else obj[key] = value;
193
+ return obj;
194
+ }
195
+ var TypeRenderer = class TypeRenderer extends BaseRenderer {
186
196
  pre() {
187
197
  this.writeln("// prettier-ignore-start");
188
198
  this.writeln("/* eslint-disable */");
@@ -197,6 +207,11 @@ var TypeRenderer = class extends BaseRenderer {
197
207
  post() {
198
208
  this.writeln("// prettier-ignore-end");
199
209
  }
210
+ renderTypeDefString(def) {
211
+ const newThis = new TypeRenderer(this.doc, this.opts);
212
+ newThis.renderTypeDef(def);
213
+ return newThis.toString();
214
+ }
200
215
  renderTypeDef(def) {
201
216
  if (!def) {
202
217
  this.write("unknown");
@@ -245,33 +260,33 @@ var TypeRenderer = class extends BaseRenderer {
245
260
  renderStructure(struct, asClass) {
246
261
  this.blockln("{}");
247
262
  const patterns = [];
248
- let hasProp = false;
263
+ const propsDefs = new Set();
249
264
  for (const prop of Array.from(struct.props.values())) {
250
265
  if (prop.token("identifier")?.pattern) {
251
266
  patterns.push(prop);
252
267
  continue;
253
268
  }
254
- hasProp = true;
255
269
  const optional = !!prop.token("optional");
256
270
  this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
257
- this.renderTypeDef(prop.getDefinition());
258
- this.writeln();
271
+ const renderedDef = this.renderTypeDefString(prop.getDefinition());
272
+ propsDefs.add(renderedDef);
273
+ renderedDef.split("\n").forEach((l) => this.writeln(l));
259
274
  }
260
275
  if (patterns.length) {
261
276
  this.write(`[key: string]: `);
262
- if (hasProp) this.writeln("any");
263
- else if (patterns.length === 1) {
264
- this.renderTypeDef(patterns[0].getDefinition());
265
- this.writeln();
266
- } else {
267
- this.indent();
268
- for (const prop of patterns) {
277
+ if (patterns.length > 0) {
278
+ for (const prop of patterns) propsDefs.add(this.renderTypeDefString(prop.getDefinition()));
279
+ const defs = Array.from(propsDefs);
280
+ if (defs.length > 1) {
281
+ this.indent();
282
+ for (const def of defs) {
283
+ this.writeln();
284
+ this.write("| ");
285
+ def.split("\n").forEach((l) => this.write(l.trim()));
286
+ }
287
+ this.unindent();
269
288
  this.writeln();
270
- this.write("| ");
271
- this.renderTypeDef(prop.getDefinition());
272
- }
273
- this.unindent();
274
- this.writeln();
289
+ } else defs[0].split("\n").forEach((l) => this.writeln(l));
275
290
  }
276
291
  }
277
292
  if (asClass) {
@@ -279,6 +294,7 @@ else if (patterns.length === 1) {
279
294
  this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
280
295
  this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
281
296
  this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
297
+ this.writeln("static toJsonSchema: () => any");
282
298
  }
283
299
  this.pop();
284
300
  }
@@ -321,6 +337,7 @@ else if (isPrimitive(realDef)) typeDef = "TAtscriptTypeFinal";
321
337
  this.writeln(`const type: ${typeDef}`);
322
338
  this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
323
339
  this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
340
+ this.writeln("const toJsonSchema: () => any");
324
341
  this.popln();
325
342
  }
326
343
  renderJsDoc(node) {
@@ -331,6 +348,9 @@ else if (isPrimitive(realDef)) typeDef = "TAtscriptTypeFinal";
331
348
  this.writeln(` * @see {@link ./${this.doc.name}${rangeStr}}`);
332
349
  this.writeln(` */`);
333
350
  }
351
+ constructor(doc, opts) {
352
+ super(doc), _define_property$2(this, "opts", void 0), this.opts = opts;
353
+ }
334
354
  };
335
355
  function renderPrimitiveTypeDef(def) {
336
356
  if (!def) return "unknown";
@@ -350,7 +370,7 @@ function renderPrimitiveTypeDef(def) {
350
370
  }
351
371
 
352
372
  //#endregion
353
- //#region packages/typescript/src/codegen/js-renderer.ts
373
+ //#region packages/typescript/src/validator.ts
354
374
  function _define_property$1(obj, key, value) {
355
375
  if (key in obj) Object.defineProperty(obj, key, {
356
376
  value,
@@ -361,352 +381,64 @@ function _define_property$1(obj, key, value) {
361
381
  else obj[key] = value;
362
382
  return obj;
363
383
  }
364
- var JsRenderer = class extends BaseRenderer {
365
- pre() {
366
- this.writeln("// prettier-ignore-start");
367
- this.writeln("/* eslint-disable */");
368
- this.writeln("import { defineAnnotatedType as $ } from \"@atscript/typescript\"");
369
- }
370
- post() {
371
- for (const node of this.postAnnotate) {
372
- this.annotateType(node.getDefinition(), node.id);
373
- this.indent().defineMetadata(node).unindent();
374
- this.writeln();
375
- }
376
- this.writeln("// prettier-ignore-end");
377
- super.post();
384
+ const regexCache = new Map();
385
+ var Validator = class {
386
+ isLimitExceeded() {
387
+ if (this.stackErrors.length > 0) return this.stackErrors[this.stackErrors.length - 1].length >= this.opts.errorLimit;
388
+ return this.errors.length >= this.opts.errorLimit;
378
389
  }
379
- renderInterface(node) {
380
- this.writeln();
381
- const exported = node.token("export")?.text === "export";
382
- this.write(exported ? "export " : "");
383
- this.write(`class ${node.id} `);
384
- this.blockln("{}");
385
- this.writeln("static __is_atscript_annotated_type = true");
386
- this.writeln("static type = {}");
387
- this.writeln("static metadata = new Map()");
388
- this.popln();
389
- this.postAnnotate.push(node);
390
- this.writeln();
390
+ push(name) {
391
+ this.stackPath.push(name);
392
+ this.stackErrors.push([]);
391
393
  }
392
- renderType(node) {
393
- this.writeln();
394
- const exported = node.token("export")?.text === "export";
395
- this.write(exported ? "export " : "");
396
- this.write(`class ${node.id} `);
397
- this.blockln("{}");
398
- this.writeln("static __is_atscript_annotated_type = true");
399
- this.writeln("static type = {}");
400
- this.writeln("static metadata = new Map()");
401
- this.popln();
402
- this.postAnnotate.push(node);
403
- this.writeln();
394
+ pop(saveErrors) {
395
+ this.stackPath.pop();
396
+ const popped = this.stackErrors.pop();
397
+ if (saveErrors && popped?.length) popped.forEach((error) => {
398
+ this.error(error.message, error.path, error.details);
399
+ });
400
+ return popped;
404
401
  }
405
- annotateType(_node, name) {
406
- if (!_node) return this;
407
- const node = this.doc.mergeIntersection(_node);
408
- let kind = node.entity;
409
- switch (node.entity) {
410
- case "ref": {
411
- const ref = node;
412
- const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
413
- if (isPrimitive(decl)) {
414
- this.annotateType(decl, name);
415
- return this;
416
- }
417
- const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
418
- this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`).unindent();
419
- return this;
420
- }
421
- case "primitive": {
422
- this.definePrimitive(node, name);
423
- return this;
424
- }
425
- case "const": {
426
- this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().defineConst(node).unindent();
427
- return this;
428
- }
429
- case "structure": {
430
- this.writeln(`$("object"${name ? `, ${name}` : ""})`).indent().defineObject(node).unindent();
431
- return this;
432
- }
433
- case "group": {
434
- kind = node.op === "|" ? "union" : "intersection";
435
- this.writeln(`$("${kind}"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
436
- return this;
437
- }
438
- case "tuple": {
439
- this.writeln(`$("tuple"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
440
- return this;
441
- }
442
- case "array": {
443
- this.writeln(`$("array"${name ? `, ${name}` : ""})`).indent().defineArray(node).unindent();
444
- return this;
445
- }
446
- default: {
447
- console.log("!!!!!!! UNKNOWN ", node.entity);
448
- return this;
449
- }
450
- }
402
+ clear() {
403
+ this.stackErrors[this.stackErrors.length - 1] = [];
451
404
  }
452
- defineConst(node) {
453
- const t = node.token("identifier")?.type;
454
- const designType = t === "text" ? "string" : t === "number" ? "number" : "unknown";
455
- const type = t === "text" ? "String" : t === "number" ? "Number" : "undefined";
456
- this.writeln(`.designType("${escapeQuotes(designType)}")`);
457
- this.writeln(`.value(${t === "text" ? `"${escapeQuotes(node.id)}"` : node.id})`);
458
- return this;
405
+ error(message, path$1, details) {
406
+ const errors = this.stackErrors[this.stackErrors.length - 1] || this.errors;
407
+ const error = {
408
+ path: path$1 || this.path,
409
+ message
410
+ };
411
+ if (details?.length) error.details = details;
412
+ errors.push(error);
459
413
  }
460
- definePrimitive(node, name) {
461
- this.renderPrimitiveDef(node.id === "never" ? "never" : node.config.type, name);
462
- this.writeln(` .tags(${Array.from(node.tags).map((f) => `"${escapeQuotes(f)}"`).join(", ")})`);
463
- return this;
414
+ throw() {
415
+ throw new ValidatorError(this.errors);
464
416
  }
465
- renderPrimitiveDef(def, name) {
466
- const d = (t) => [`"${t || ""}"`, name].filter(Boolean).join(", ").replace(/^""$/, "");
467
- if (!def) return this.writeln(`$(${d()}).designType("any")`);
468
- if (typeof def === "string") return this.writeln(`$(${d()}).designType("${def === "void" ? "undefined" : def}")`);
469
- switch (def.kind) {
470
- case "final": return this.writeln(`$(${d()}).designType("${def.value === "void" ? "undefined" : def.value}")`);
471
- case "union":
472
- case "intersection":
473
- case "tuple":
474
- this.writeln(`$(${d(def.kind)})`);
475
- this.indent();
476
- for (const itemDef of def.items) {
477
- this.write(`.item(`);
478
- this.indent();
479
- this.renderPrimitiveDef(itemDef);
480
- this.writeln(".$type");
481
- this.unindent();
482
- this.write(`)`);
483
- }
484
- this.unindent();
485
- return;
486
- case "array":
487
- this.writeln(`$(${d("array")})`);
488
- this.indent();
489
- this.write(".of(");
490
- this.indent();
491
- this.renderPrimitiveDef(def.of);
492
- this.writeln(`.$type`);
493
- this.unindent();
494
- this.writeln(`)`);
495
- this.unindent();
496
- return;
497
- case "object":
498
- this.writeln(`$(${d("object")})`);
499
- this.indent();
500
- for (const [key, propDef] of Object.entries(def.props)) {
501
- const optional = typeof propDef === "object" && propDef.optional;
502
- this.writeln(`.prop(`);
503
- this.indent();
504
- this.writeln(`"${escapeQuotes(key)}",`);
505
- this.renderPrimitiveDef(propDef);
506
- if (optional) this.writeln(".optional()");
507
- this.writeln(".$type");
508
- this.unindent();
509
- this.write(`)`);
510
- }
511
- for (const [key, propDef] of Object.entries(def.propsPatterns)) {
512
- const optional = typeof propDef === "object" && propDef.optional;
513
- this.writeln(`.propPattern(`);
514
- this.indent();
515
- this.writeln(`${key},`);
516
- this.renderPrimitiveDef(propDef);
517
- if (optional) this.writeln(".optional()");
518
- this.writeln(".$type");
519
- this.unindent();
520
- this.write(`)`);
521
- }
522
- this.unindent();
523
- return;
524
- default: return this.writeln(`$(${d()}).designType("any")`);
417
+ validate(value, safe) {
418
+ this.push("");
419
+ this.errors = [];
420
+ this.stackErrors = [];
421
+ const passed = this.validateSafe(this.def, value);
422
+ this.pop(!passed);
423
+ if (!passed) {
424
+ if (safe) return false;
425
+ this.throw();
525
426
  }
427
+ return true;
526
428
  }
527
- defineObject(node) {
528
- const props = Array.from(node.props.values());
529
- for (const prop of props) {
530
- const pattern = prop.token("identifier")?.pattern;
531
- const optional = !!prop.token("optional");
532
- if (pattern) {
533
- this.writeln(`.propPattern(`);
534
- this.indent();
535
- this.writeln(`/${pattern.source}/${pattern.flags},`);
536
- } else {
537
- this.writeln(`.prop(`);
538
- this.indent();
539
- this.writeln(`"${escapeQuotes(prop.id)}",`);
540
- }
541
- this.annotateType(prop.getDefinition());
542
- this.indent().defineMetadata(prop).unindent();
543
- if (optional) this.writeln(" .optional()");
544
- this.writeln(" .$type");
545
- this.unindent();
546
- this.write(`)`);
429
+ validateSafe(def, value) {
430
+ if (this.isLimitExceeded()) return false;
431
+ if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
432
+ if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.path);
433
+ if (def.optional && value === undefined) return true;
434
+ for (const plugin of this.opts.plugins) {
435
+ const result = plugin(this, def, value);
436
+ if (result === false || result === true) return result;
547
437
  }
548
- this.writeln();
549
- return this;
550
- }
551
- defineGroup(node) {
552
- const items = node.unwrap();
553
- for (const item of items) this.write(".item(").indent().annotateType(item).write(" .$type").writeln(`)`).unindent();
554
- return this;
438
+ return this.validateAnnotatedType(def, value);
555
439
  }
556
- defineArray(node) {
557
- this.write(".of(").indent().annotateType(node.getDefinition()).write(" .$type").writeln(`)`).unindent();
558
- return this;
559
- }
560
- defineMetadata(node) {
561
- const annotations = this.doc.evalAnnotationsForNode(node);
562
- annotations?.forEach((an) => {
563
- this.resolveAnnotationValue(node, an);
564
- });
565
- return this;
566
- }
567
- resolveAnnotationValue(node, an) {
568
- const spec = this.doc.resolveAnnotation(an.name);
569
- let targetValue = "true";
570
- let multiple = false;
571
- if (spec) {
572
- multiple = spec.config.multiple;
573
- const length = spec.arguments.length;
574
- if (length !== 0) if (Array.isArray(spec.config.argument)) {
575
- targetValue = "{ ";
576
- let i = 0;
577
- for (const aSpec of spec.arguments) {
578
- if (an.args[i]) targetValue += `${wrapProp(aSpec.name)}: ${aSpec.type === "string" ? `"${escapeQuotes(an.args[i]?.text)}"` : an.args[i]?.text}${i === length - 1 ? "" : ", "} `;
579
- else {}
580
- i++;
581
- }
582
- targetValue += "}";
583
- } else {
584
- const aSpec = spec.arguments[0];
585
- if (an.args[0]) targetValue = aSpec.type === "string" ? `"${escapeQuotes(an.args[0]?.text)}"` : an.args[0]?.text;
586
- else targetValue = "true";
587
- }
588
- } else {
589
- multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
590
- if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
591
- }
592
- if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue}, true)`);
593
- else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue})`);
594
- }
595
- constructor(...args) {
596
- super(...args), _define_property$1(this, "postAnnotate", []);
597
- }
598
- };
599
-
600
- //#endregion
601
- //#region packages/typescript/src/plugin.ts
602
- const tsPlugin = () => {
603
- return {
604
- name: "typesccript",
605
- render(doc, format) {
606
- if (format === "dts") return [{
607
- fileName: `${doc.name}.d.ts`,
608
- content: new TypeRenderer(doc).render()
609
- }];
610
- if (format === "js") return [{
611
- fileName: `${doc.name}.js`,
612
- content: new JsRenderer(doc).render()
613
- }];
614
- },
615
- async buildEnd(output, format, repo) {
616
- if (format === "dts") {
617
- const annotations = await repo.getUsedAnnotations();
618
- const tags = await repo.getPrimitivesTags() || new Set();
619
- let rendered = [];
620
- for (const [key, val] of Object.entries(annotations)) {
621
- const multiple = val.multiple;
622
- let typeLine = Array.from(val.types).map((t) => {
623
- if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
624
- else return t.optional ? `${t.type} | true` : t.type;
625
- }).join(" | ");
626
- rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
627
- }
628
- let renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
629
- output.push({
630
- 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",
631
- fileName: "atscript.d.ts",
632
- source: "",
633
- target: path.join(repo.root, "atscript.d.ts")
634
- });
635
- }
636
- }
637
- };
638
- };
639
-
640
- //#endregion
641
- //#region packages/typescript/src/validator.ts
642
- function _define_property(obj, key, value) {
643
- if (key in obj) Object.defineProperty(obj, key, {
644
- value,
645
- enumerable: true,
646
- configurable: true,
647
- writable: true
648
- });
649
- else obj[key] = value;
650
- return obj;
651
- }
652
- const regexCache = new Map();
653
- var Validator = class {
654
- isLimitExceeded() {
655
- if (this.stackErrors.length > 0) return this.stackErrors[this.stackErrors.length - 1].length >= this.opts.errorLimit;
656
- return this.errors.length >= this.opts.errorLimit;
657
- }
658
- push(name) {
659
- this.stackPath.push(name);
660
- this.stackErrors.push([]);
661
- }
662
- pop(saveErrors) {
663
- this.stackPath.pop();
664
- const popped = this.stackErrors.pop();
665
- if (saveErrors && popped?.length) popped.forEach((error) => {
666
- this.error(error.message, error.path, error.details);
667
- });
668
- return popped;
669
- }
670
- clear() {
671
- this.stackErrors[this.stackErrors.length - 1] = [];
672
- }
673
- error(message, path$1, details) {
674
- const errors = this.stackErrors[this.stackErrors.length - 1] || this.errors;
675
- const error = {
676
- path: path$1 || this.path,
677
- message
678
- };
679
- if (details?.length) error.details = details;
680
- errors.push(error);
681
- }
682
- throw() {
683
- throw new ValidatorError(this.errors);
684
- }
685
- validate(value, safe) {
686
- this.push("");
687
- this.errors = [];
688
- this.stackErrors = [];
689
- const passed = this.validateSafe(this.def, value);
690
- this.pop(!passed);
691
- if (!passed) {
692
- if (safe) return false;
693
- this.throw();
694
- }
695
- return true;
696
- }
697
- validateSafe(def, value) {
698
- if (this.isLimitExceeded()) return false;
699
- if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
700
- if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.path);
701
- if (def.optional && value === undefined) return true;
702
- for (const plugin of this.opts.plugins) {
703
- const result = plugin(this, def, value);
704
- if (result === false || result === true) return result;
705
- }
706
- return this.validateAnnotatedType(def, value);
707
- }
708
- get path() {
709
- return this.stackPath.slice(1).join(".");
440
+ get path() {
441
+ return this.stackPath.slice(1).join(".");
710
442
  }
711
443
  validateAnnotatedType(def, value) {
712
444
  switch (def.type.kind) {
@@ -947,11 +679,11 @@ else {
947
679
  return true;
948
680
  }
949
681
  constructor(def, opts) {
950
- _define_property(this, "def", void 0);
951
- _define_property(this, "opts", void 0);
952
- _define_property(this, "errors", void 0);
953
- _define_property(this, "stackErrors", void 0);
954
- _define_property(this, "stackPath", void 0);
682
+ _define_property$1(this, "def", void 0);
683
+ _define_property$1(this, "opts", void 0);
684
+ _define_property$1(this, "errors", void 0);
685
+ _define_property$1(this, "stackErrors", void 0);
686
+ _define_property$1(this, "stackPath", void 0);
955
687
  this.def = def;
956
688
  this.errors = [];
957
689
  this.stackErrors = [];
@@ -967,7 +699,7 @@ else {
967
699
  };
968
700
  var ValidatorError = class extends Error {
969
701
  constructor(errors) {
970
- 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";
702
+ 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";
971
703
  }
972
704
  };
973
705
 
@@ -1100,9 +832,506 @@ function isAnnotatedTypeOfPrimitive(t) {
1100
832
  return false;
1101
833
  }
1102
834
 
835
+ //#endregion
836
+ //#region packages/typescript/src/json-schema.ts
837
+ function buildJsonSchema(type) {
838
+ const build = (def) => {
839
+ const t = def.type;
840
+ const meta = def.metadata;
841
+ switch (t.kind) {
842
+ case "object": {
843
+ const obj = t;
844
+ const properties = {};
845
+ const required = [];
846
+ for (const [key, val] of obj.props.entries()) {
847
+ properties[key] = build(val);
848
+ if (!val.optional) required.push(key);
849
+ }
850
+ const schema = {
851
+ type: "object",
852
+ properties
853
+ };
854
+ if (required.length) schema.required = required;
855
+ return schema;
856
+ }
857
+ case "array": {
858
+ const arr = t;
859
+ const schema = {
860
+ type: "array",
861
+ items: build(arr.of)
862
+ };
863
+ const minLength = meta.get("expect.minLength");
864
+ if (typeof minLength === "number") schema.minItems = minLength;
865
+ const maxLength = meta.get("expect.maxLength");
866
+ if (typeof maxLength === "number") schema.maxItems = maxLength;
867
+ return schema;
868
+ }
869
+ case "union": {
870
+ const grp = t;
871
+ return { anyOf: grp.items.map(build) };
872
+ }
873
+ case "intersection": {
874
+ const grp = t;
875
+ return { allOf: grp.items.map(build) };
876
+ }
877
+ case "tuple": {
878
+ const grp = t;
879
+ return {
880
+ type: "array",
881
+ items: grp.items.map(build),
882
+ additionalItems: false
883
+ };
884
+ }
885
+ case "": {
886
+ const fin = t;
887
+ const schema = {};
888
+ if (fin.value !== undefined) schema.const = fin.value;
889
+ if (fin.designType && fin.designType !== "any") {
890
+ schema.type = fin.designType === "undefined" ? "null" : fin.designType;
891
+ if (schema.type === "number" && meta.get("expect.int")) schema.type = "integer";
892
+ }
893
+ if (schema.type === "string") {
894
+ const minLength = meta.get("expect.minLength");
895
+ if (typeof minLength === "number") schema.minLength = minLength;
896
+ const maxLength = meta.get("expect.maxLength");
897
+ if (typeof maxLength === "number") schema.maxLength = maxLength;
898
+ const patterns = meta.get("expect.pattern");
899
+ if (patterns?.length) if (patterns.length === 1) schema.pattern = patterns[0].pattern;
900
+ else schema.allOf = (schema.allOf || []).concat(patterns.map((p) => ({ pattern: p.pattern })));
901
+ }
902
+ if (schema.type === "number" || schema.type === "integer") {
903
+ const min = meta.get("expect.min");
904
+ if (typeof min === "number") schema.minimum = min;
905
+ const max = meta.get("expect.max");
906
+ if (typeof max === "number") schema.maximum = max;
907
+ }
908
+ return schema;
909
+ }
910
+ default: return {};
911
+ }
912
+ };
913
+ return build(type);
914
+ }
915
+
916
+ //#endregion
917
+ //#region packages/typescript/src/codegen/js-renderer.ts
918
+ function _define_property(obj, key, value) {
919
+ if (key in obj) Object.defineProperty(obj, key, {
920
+ value,
921
+ enumerable: true,
922
+ configurable: true,
923
+ writable: true
924
+ });
925
+ else obj[key] = value;
926
+ return obj;
927
+ }
928
+ var JsRenderer = class extends BaseRenderer {
929
+ pre() {
930
+ this.writeln("// prettier-ignore-start");
931
+ this.writeln("/* eslint-disable */");
932
+ const imports = ["defineAnnotatedType as $"];
933
+ if (!this.opts?.preRenderJsonSchema) imports.push("buildJsonSchema as $$");
934
+ this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript"`);
935
+ }
936
+ post() {
937
+ for (const node of this.postAnnotate) {
938
+ this.annotateType(node.getDefinition(), node.id);
939
+ this.indent().defineMetadata(node).unindent();
940
+ this.writeln();
941
+ }
942
+ this.writeln("// prettier-ignore-end");
943
+ super.post();
944
+ }
945
+ renderInterface(node) {
946
+ this.writeln();
947
+ const exported = node.token("export")?.text === "export";
948
+ this.write(exported ? "export " : "");
949
+ this.write(`class ${node.id} `);
950
+ this.blockln("{}");
951
+ this.writeln("static __is_atscript_annotated_type = true");
952
+ this.writeln("static type = {}");
953
+ this.writeln("static metadata = new Map()");
954
+ if (this.opts?.preRenderJsonSchema) {
955
+ const schema = JSON.stringify(buildJsonSchema(this.toAnnotatedType(node)));
956
+ this.writeln(`static _jsonSchema = ${schema}`);
957
+ this.writeln("static toJsonSchema() {");
958
+ this.indent().writeln("return this._jsonSchema").unindent();
959
+ this.writeln("}");
960
+ } else {
961
+ this.writeln("static _jsonSchema");
962
+ this.writeln("static toJsonSchema() {");
963
+ this.indent().writeln("return this._jsonSchema ?? (this._jsonSchema = $$(this))").unindent();
964
+ this.writeln("}");
965
+ }
966
+ this.popln();
967
+ this.postAnnotate.push(node);
968
+ this.writeln();
969
+ }
970
+ renderType(node) {
971
+ this.writeln();
972
+ const exported = node.token("export")?.text === "export";
973
+ this.write(exported ? "export " : "");
974
+ this.write(`class ${node.id} `);
975
+ this.blockln("{}");
976
+ this.writeln("static __is_atscript_annotated_type = true");
977
+ this.writeln("static type = {}");
978
+ this.writeln("static metadata = new Map()");
979
+ if (this.opts?.jsonSchema) if (typeof this.opts.jsonSchema === "object" && this.opts.jsonSchema.preRender) {
980
+ const schema = JSON.stringify(buildJsonSchema(this.toAnnotatedType(node)));
981
+ this.writeln(`static _jsonSchema = ${schema}`);
982
+ this.writeln("static toJsonSchema() {");
983
+ this.indent().writeln("return this._jsonSchema").unindent();
984
+ this.writeln("}");
985
+ } else {
986
+ this.writeln("static _jsonSchema");
987
+ this.writeln("static toJsonSchema() {");
988
+ this.indent().writeln("return this._jsonSchema ?? (this._jsonSchema = $$(this))").unindent();
989
+ this.writeln("}");
990
+ }
991
+ this.popln();
992
+ this.postAnnotate.push(node);
993
+ this.writeln();
994
+ }
995
+ toAnnotatedType(node) {
996
+ return this.toAnnotatedHandle(node).$type;
997
+ }
998
+ toAnnotatedHandle(node, skipAnnotations = false) {
999
+ if (!node) return defineAnnotatedType();
1000
+ switch (node.entity) {
1001
+ case "interface":
1002
+ case "type": {
1003
+ const def = node.getDefinition();
1004
+ const handle = this.toAnnotatedHandle(def, true);
1005
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1006
+ }
1007
+ case "prop": {
1008
+ const prop = node;
1009
+ const def = prop.getDefinition();
1010
+ const handle = this.toAnnotatedHandle(def, true);
1011
+ if (!skipAnnotations) {
1012
+ this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(prop));
1013
+ if (prop.token("optional")) handle.optional();
1014
+ }
1015
+ return handle;
1016
+ }
1017
+ case "ref": {
1018
+ const ref = node;
1019
+ const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
1020
+ const handle = this.toAnnotatedHandle(decl, true);
1021
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1022
+ }
1023
+ case "primitive": {
1024
+ const prim = node;
1025
+ const handle = defineAnnotatedType();
1026
+ handle.designType(prim.id === "never" ? "never" : prim.config.type);
1027
+ if (!skipAnnotations) this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1028
+ return handle;
1029
+ }
1030
+ case "const": {
1031
+ const c = node;
1032
+ const handle = defineAnnotatedType();
1033
+ const t = c.token("identifier")?.type;
1034
+ handle.designType(t === "number" ? "number" : "string");
1035
+ handle.value(t === "number" ? Number(c.id) : c.id);
1036
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1037
+ }
1038
+ case "structure": {
1039
+ const struct = node;
1040
+ const handle = defineAnnotatedType("object");
1041
+ for (const prop of Array.from(struct.props.values())) {
1042
+ const propHandle = this.toAnnotatedHandle(prop);
1043
+ const pattern = prop.token("identifier")?.pattern;
1044
+ if (pattern) handle.propPattern(pattern, propHandle.$type);
1045
+ else handle.prop(prop.id, propHandle.$type);
1046
+ }
1047
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1048
+ }
1049
+ case "group": {
1050
+ const group = node;
1051
+ const kind = group.op === "|" ? "union" : "intersection";
1052
+ const handle = defineAnnotatedType(kind);
1053
+ for (const item of group.unwrap()) handle.item(this.toAnnotatedHandle(item).$type);
1054
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1055
+ }
1056
+ case "tuple": {
1057
+ const group = node;
1058
+ const handle = defineAnnotatedType("tuple");
1059
+ for (const item of group.unwrap()) handle.item(this.toAnnotatedHandle(item).$type);
1060
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1061
+ }
1062
+ case "array": {
1063
+ const arr = node;
1064
+ const handle = defineAnnotatedType("array");
1065
+ handle.of(this.toAnnotatedHandle(arr.getDefinition()).$type);
1066
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1067
+ }
1068
+ default: {
1069
+ const handle = defineAnnotatedType();
1070
+ return skipAnnotations ? handle : this.applyExpectAnnotations(handle, this.doc.evalAnnotationsForNode(node));
1071
+ }
1072
+ }
1073
+ }
1074
+ applyExpectAnnotations(handle, annotations) {
1075
+ annotations?.forEach((a) => {
1076
+ switch (a.name) {
1077
+ case "expect.minLength":
1078
+ case "expect.maxLength":
1079
+ case "expect.min":
1080
+ case "expect.max":
1081
+ if (a.args[0]) handle.annotate(a.name, Number(a.args[0].text));
1082
+ break;
1083
+ case "expect.pattern":
1084
+ handle.annotate(a.name, {
1085
+ pattern: a.args[0]?.text || "",
1086
+ flags: a.args[1]?.text,
1087
+ message: a.args[2]?.text
1088
+ }, true);
1089
+ break;
1090
+ case "expect.int":
1091
+ handle.annotate(a.name, true);
1092
+ break;
1093
+ default:
1094
+ }
1095
+ });
1096
+ return handle;
1097
+ }
1098
+ annotateType(_node, name) {
1099
+ if (!_node) return this;
1100
+ const node = this.doc.mergeIntersection(_node);
1101
+ let kind = node.entity;
1102
+ switch (node.entity) {
1103
+ case "ref": {
1104
+ const ref = node;
1105
+ const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
1106
+ if (isPrimitive(decl)) {
1107
+ this.annotateType(decl, name);
1108
+ return this;
1109
+ }
1110
+ const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
1111
+ this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`).unindent();
1112
+ return this;
1113
+ }
1114
+ case "primitive": {
1115
+ this.definePrimitive(node, name);
1116
+ return this;
1117
+ }
1118
+ case "const": {
1119
+ this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().defineConst(node).unindent();
1120
+ return this;
1121
+ }
1122
+ case "structure": {
1123
+ this.writeln(`$("object"${name ? `, ${name}` : ""})`).indent().defineObject(node).unindent();
1124
+ return this;
1125
+ }
1126
+ case "group": {
1127
+ kind = node.op === "|" ? "union" : "intersection";
1128
+ this.writeln(`$("${kind}"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
1129
+ return this;
1130
+ }
1131
+ case "tuple": {
1132
+ this.writeln(`$("tuple"${name ? `, ${name}` : ""})`).indent().defineGroup(node).unindent();
1133
+ return this;
1134
+ }
1135
+ case "array": {
1136
+ this.writeln(`$("array"${name ? `, ${name}` : ""})`).indent().defineArray(node).unindent();
1137
+ return this;
1138
+ }
1139
+ default: {
1140
+ console.log("!!!!!!! UNKNOWN ", node.entity);
1141
+ return this;
1142
+ }
1143
+ }
1144
+ }
1145
+ defineConst(node) {
1146
+ const t = node.token("identifier")?.type;
1147
+ const designType = t === "text" ? "string" : t === "number" ? "number" : "unknown";
1148
+ this.writeln(`.designType("${escapeQuotes(designType)}")`);
1149
+ this.writeln(`.value(${t === "text" ? `"${escapeQuotes(node.id)}"` : node.id})`);
1150
+ return this;
1151
+ }
1152
+ definePrimitive(node, name) {
1153
+ this.renderPrimitiveDef(node.id === "never" ? "never" : node.config.type, name);
1154
+ this.writeln(` .tags(${Array.from(node.tags).map((f) => `"${escapeQuotes(f)}"`).join(", ")})`);
1155
+ return this;
1156
+ }
1157
+ renderPrimitiveDef(def, name) {
1158
+ const d = (t) => [`"${t || ""}"`, name].filter(Boolean).join(", ").replace(/^""$/, "");
1159
+ if (!def) return this.writeln(`$(${d()}).designType("any")`);
1160
+ if (typeof def === "string") return this.writeln(`$(${d()}).designType("${def === "void" ? "undefined" : def}")`);
1161
+ switch (def.kind) {
1162
+ case "final": return this.writeln(`$(${d()}).designType("${def.value === "void" ? "undefined" : def.value}")`);
1163
+ case "union":
1164
+ case "intersection":
1165
+ case "tuple":
1166
+ this.writeln(`$(${d(def.kind)})`);
1167
+ this.indent();
1168
+ for (const itemDef of def.items) {
1169
+ this.write(`.item(`);
1170
+ this.indent();
1171
+ this.renderPrimitiveDef(itemDef);
1172
+ this.writeln(".$type");
1173
+ this.unindent();
1174
+ this.write(`)`);
1175
+ }
1176
+ this.unindent();
1177
+ return;
1178
+ case "array":
1179
+ this.writeln(`$(${d("array")})`);
1180
+ this.indent();
1181
+ this.write(".of(");
1182
+ this.indent();
1183
+ this.renderPrimitiveDef(def.of);
1184
+ this.writeln(`.$type`);
1185
+ this.unindent();
1186
+ this.writeln(`)`);
1187
+ this.unindent();
1188
+ return;
1189
+ case "object":
1190
+ this.writeln(`$(${d("object")})`);
1191
+ this.indent();
1192
+ for (const [key, propDef] of Object.entries(def.props)) {
1193
+ const optional = typeof propDef === "object" && propDef.optional;
1194
+ this.writeln(`.prop(`);
1195
+ this.indent();
1196
+ this.writeln(`"${escapeQuotes(key)}",`);
1197
+ this.renderPrimitiveDef(propDef);
1198
+ if (optional) this.writeln(".optional()");
1199
+ this.writeln(".$type");
1200
+ this.unindent();
1201
+ this.write(`)`);
1202
+ }
1203
+ for (const [key, propDef] of Object.entries(def.propsPatterns)) {
1204
+ const optional = typeof propDef === "object" && propDef.optional;
1205
+ this.writeln(`.propPattern(`);
1206
+ this.indent();
1207
+ this.writeln(`${key},`);
1208
+ this.renderPrimitiveDef(propDef);
1209
+ if (optional) this.writeln(".optional()");
1210
+ this.writeln(".$type");
1211
+ this.unindent();
1212
+ this.write(`)`);
1213
+ }
1214
+ this.unindent();
1215
+ return;
1216
+ default: return this.writeln(`$(${d()}).designType("any")`);
1217
+ }
1218
+ }
1219
+ defineObject(node) {
1220
+ const props = Array.from(node.props.values());
1221
+ for (const prop of props) {
1222
+ const pattern = prop.token("identifier")?.pattern;
1223
+ const optional = !!prop.token("optional");
1224
+ if (pattern) {
1225
+ this.writeln(`.propPattern(`);
1226
+ this.indent();
1227
+ this.writeln(`/${pattern.source}/${pattern.flags},`);
1228
+ } else {
1229
+ this.writeln(`.prop(`);
1230
+ this.indent();
1231
+ this.writeln(`"${escapeQuotes(prop.id)}",`);
1232
+ }
1233
+ this.annotateType(prop.getDefinition());
1234
+ this.indent().defineMetadata(prop).unindent();
1235
+ if (optional) this.writeln(" .optional()");
1236
+ this.writeln(" .$type");
1237
+ this.unindent();
1238
+ this.write(`)`);
1239
+ }
1240
+ this.writeln();
1241
+ return this;
1242
+ }
1243
+ defineGroup(node) {
1244
+ const items = node.unwrap();
1245
+ for (const item of items) this.write(".item(").indent().annotateType(item).write(" .$type").writeln(`)`).unindent();
1246
+ return this;
1247
+ }
1248
+ defineArray(node) {
1249
+ this.write(".of(").indent().annotateType(node.getDefinition()).write(" .$type").writeln(`)`).unindent();
1250
+ return this;
1251
+ }
1252
+ defineMetadata(node) {
1253
+ const annotations = this.doc.evalAnnotationsForNode(node);
1254
+ annotations?.forEach((an) => {
1255
+ this.resolveAnnotationValue(node, an);
1256
+ });
1257
+ return this;
1258
+ }
1259
+ resolveAnnotationValue(node, an) {
1260
+ const spec = this.doc.resolveAnnotation(an.name);
1261
+ let targetValue = "true";
1262
+ let multiple = false;
1263
+ if (spec) {
1264
+ multiple = spec.config.multiple;
1265
+ const length = spec.arguments.length;
1266
+ if (length !== 0) if (Array.isArray(spec.config.argument)) {
1267
+ targetValue = "{ ";
1268
+ let i = 0;
1269
+ for (const aSpec of spec.arguments) {
1270
+ if (an.args[i]) targetValue += `${wrapProp(aSpec.name)}: ${aSpec.type === "string" ? `"${escapeQuotes(an.args[i]?.text)}"` : an.args[i]?.text}${i === length - 1 ? "" : ", "} `;
1271
+ else {}
1272
+ i++;
1273
+ }
1274
+ targetValue += "}";
1275
+ } else {
1276
+ const aSpec = spec.arguments[0];
1277
+ if (an.args[0]) targetValue = aSpec.type === "string" ? `"${escapeQuotes(an.args[0]?.text)}"` : an.args[0]?.text;
1278
+ else targetValue = "true";
1279
+ }
1280
+ } else {
1281
+ multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
1282
+ if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
1283
+ }
1284
+ if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue}, true)`);
1285
+ else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue})`);
1286
+ }
1287
+ constructor(doc, opts) {
1288
+ super(doc), _define_property(this, "opts", void 0), _define_property(this, "postAnnotate", void 0), this.opts = opts, this.postAnnotate = [];
1289
+ }
1290
+ };
1291
+
1292
+ //#endregion
1293
+ //#region packages/typescript/src/plugin.ts
1294
+ const tsPlugin = (opts) => {
1295
+ return {
1296
+ name: "typesccript",
1297
+ render(doc, format) {
1298
+ if (format === "dts") return [{
1299
+ fileName: `${doc.name}.d.ts`,
1300
+ content: new TypeRenderer(doc, opts).render()
1301
+ }];
1302
+ if (format === "js") return [{
1303
+ fileName: `${doc.name}.js`,
1304
+ content: new JsRenderer(doc, opts).render()
1305
+ }];
1306
+ },
1307
+ async buildEnd(output, format, repo) {
1308
+ if (format === "dts") {
1309
+ const annotations = await repo.getUsedAnnotations();
1310
+ const tags = await repo.getPrimitivesTags() || new Set();
1311
+ let rendered = [];
1312
+ for (const [key, val] of Object.entries(annotations)) {
1313
+ const multiple = val.multiple;
1314
+ let typeLine = Array.from(val.types).map((t) => {
1315
+ if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
1316
+ else return t.optional ? `${t.type} | true` : t.type;
1317
+ }).join(" | ");
1318
+ rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
1319
+ }
1320
+ let renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
1321
+ output.push({
1322
+ 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",
1323
+ fileName: "atscript.d.ts",
1324
+ source: "",
1325
+ target: path.join(repo.root, "atscript.d.ts")
1326
+ });
1327
+ }
1328
+ }
1329
+ };
1330
+ };
1331
+
1103
1332
  //#endregion
1104
1333
  //#region packages/typescript/src/index.ts
1105
1334
  var src_default = tsPlugin;
1106
1335
 
1107
1336
  //#endregion
1108
- export { Validator, ValidatorError, src_default as default, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
1337
+ export { Validator, ValidatorError, buildJsonSchema, src_default as default, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };