@atscript/typescript 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/cli.cjs +3 -0
- package/dist/cli.cjs +726 -0
- package/dist/index.cjs +1019 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.mjs +990 -0
- package/package.json +61 -0
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,726 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//#region rolldown:runtime
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") 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) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
const moost = __toESM(require("moost"));
|
|
26
|
+
const __moostjs_event_cli = __toESM(require("@moostjs/event-cli"));
|
|
27
|
+
const path = __toESM(require("path"));
|
|
28
|
+
const __atscript_core = __toESM(require("@atscript/core"));
|
|
29
|
+
const fs = __toESM(require("fs"));
|
|
30
|
+
|
|
31
|
+
//#region packages/typescript/src/codegen/code-printer.ts
|
|
32
|
+
function _define_property$3(obj, key, value) {
|
|
33
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
34
|
+
value,
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true
|
|
38
|
+
});
|
|
39
|
+
else obj[key] = value;
|
|
40
|
+
return obj;
|
|
41
|
+
}
|
|
42
|
+
var CodePrinter = class {
|
|
43
|
+
/**
|
|
44
|
+
* Write text with NO automatic newline.
|
|
45
|
+
* If current line is empty, we prepend indentation.
|
|
46
|
+
*/ write(...text) {
|
|
47
|
+
if (!this.currentLine) this.currentLine = this.indentString();
|
|
48
|
+
this.currentLine += text.join("");
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Write text and then finalize this line with a newline.
|
|
53
|
+
* Implemented by calling `write(...)` + push line + reset `currentLine`.
|
|
54
|
+
*/ writeln(...text) {
|
|
55
|
+
this.write(...text);
|
|
56
|
+
this.lines.push(this.currentLine);
|
|
57
|
+
this.currentLine = "";
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Open a block with an opening/closing pair, e.g. "{}" or "()".
|
|
62
|
+
* By default, places the opening delimiter on the current line (no extra newline).
|
|
63
|
+
*/ block(pair) {
|
|
64
|
+
return this.doBlock(pair, false);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Same as `block()`, but adds a newline after writing the opening delimiter.
|
|
68
|
+
*/ blockln(pair) {
|
|
69
|
+
return this.doBlock(pair, true);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Close the most recent block. By default, closing delimiter goes on the current line.
|
|
73
|
+
*/ pop() {
|
|
74
|
+
return this.doPop(false);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Same as `pop()`, but puts the closing delimiter on a new line.
|
|
78
|
+
*/ popln() {
|
|
79
|
+
return this.doPop(true);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Increase indentation by one level.
|
|
83
|
+
*/ indent() {
|
|
84
|
+
this.indentLevel++;
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Decrease indentation by one level (never below 0).
|
|
89
|
+
*/ unindent() {
|
|
90
|
+
this.indentLevel = Math.max(0, this.indentLevel - 1);
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
render() {
|
|
94
|
+
return this.toString();
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Return the entire code as a string. Removes any half-finished current line if empty.
|
|
98
|
+
*/ toString() {
|
|
99
|
+
if (this.currentLine.trim() !== "") this.lines.push(this.currentLine);
|
|
100
|
+
else if (this.currentLine.length > 0) this.lines.push(this.currentLine);
|
|
101
|
+
return this.lines.join("\n");
|
|
102
|
+
}
|
|
103
|
+
doBlock(pair, withNewLine) {
|
|
104
|
+
if (pair.length < 2) throw new Error(`Block pair must have at least 2 chars, e.g. "{}" or "()". Got "${pair}"`);
|
|
105
|
+
const opening = pair[0];
|
|
106
|
+
const closing = pair[pair.length - 1];
|
|
107
|
+
this.write(opening);
|
|
108
|
+
this.blockStack.push(closing);
|
|
109
|
+
if (withNewLine) this.writeln();
|
|
110
|
+
this.indent();
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
doPop(withNewLine) {
|
|
114
|
+
if (!this.blockStack.length) throw new Error("No block to pop (stack is empty).");
|
|
115
|
+
const closing = this.blockStack.pop();
|
|
116
|
+
this.unindent();
|
|
117
|
+
if (withNewLine) this.writeln(closing);
|
|
118
|
+
else this.write(closing);
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
indentString() {
|
|
122
|
+
return " ".repeat(this.indentLevel * this.indentSize);
|
|
123
|
+
}
|
|
124
|
+
constructor() {
|
|
125
|
+
_define_property$3(this, "lines", []);
|
|
126
|
+
_define_property$3(this, "currentLine", "");
|
|
127
|
+
_define_property$3(this, "indentLevel", 0);
|
|
128
|
+
_define_property$3(this, "indentSize", 2);
|
|
129
|
+
_define_property$3(this, "blockStack", []);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region packages/typescript/src/codegen/base-renderer.ts
|
|
135
|
+
function _define_property$2(obj, key, value) {
|
|
136
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
137
|
+
value,
|
|
138
|
+
enumerable: true,
|
|
139
|
+
configurable: true,
|
|
140
|
+
writable: true
|
|
141
|
+
});
|
|
142
|
+
else obj[key] = value;
|
|
143
|
+
return obj;
|
|
144
|
+
}
|
|
145
|
+
var BaseRenderer = class extends CodePrinter {
|
|
146
|
+
pre() {}
|
|
147
|
+
post() {}
|
|
148
|
+
render() {
|
|
149
|
+
this.pre();
|
|
150
|
+
for (const node of this.doc.nodes) this.renderNode(node);
|
|
151
|
+
this.post();
|
|
152
|
+
return this.toString();
|
|
153
|
+
}
|
|
154
|
+
renderInterface(node) {}
|
|
155
|
+
renderType(node) {}
|
|
156
|
+
transformFromPath(path$3) {
|
|
157
|
+
return path$3 + ".as";
|
|
158
|
+
}
|
|
159
|
+
renderImport(node) {
|
|
160
|
+
const def = node.getDefinition();
|
|
161
|
+
const refs = [];
|
|
162
|
+
const from = this.transformFromPath(node.token("path").text);
|
|
163
|
+
let isUnusedImport = true;
|
|
164
|
+
if ((0, __atscript_core.isGroup)(def)) {
|
|
165
|
+
for (const child of def.unwrap()) if ((0, __atscript_core.isRef)(child) && !this.unused.has(child.id)) {
|
|
166
|
+
const node$1 = child;
|
|
167
|
+
refs.push(node$1.id);
|
|
168
|
+
isUnusedImport = false;
|
|
169
|
+
}
|
|
170
|
+
} else if ((0, __atscript_core.isRef)(def) && !this.unused.has(def.id)) {
|
|
171
|
+
refs.push(def.id);
|
|
172
|
+
isUnusedImport = false;
|
|
173
|
+
}
|
|
174
|
+
if (!isUnusedImport) this.writeln(`import { ${refs.join(", ")} } from "${from}"`);
|
|
175
|
+
}
|
|
176
|
+
renderNode(node) {
|
|
177
|
+
switch (node.entity) {
|
|
178
|
+
case "interface": {
|
|
179
|
+
this.renderInterface(node);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case "type": {
|
|
183
|
+
this.renderType(node);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case "import": {
|
|
187
|
+
this.renderImport(node);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
default: break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
constructor(doc) {
|
|
194
|
+
super(), _define_property$2(this, "doc", void 0), _define_property$2(this, "unused", void 0), this.doc = doc;
|
|
195
|
+
this.unused = new Set(this.doc.getUnusedTokens().map((t) => t.text));
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region packages/typescript/src/codegen/utils.ts
|
|
201
|
+
function wrapProp(name) {
|
|
202
|
+
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
203
|
+
if (!validIdentifier.test(name)) return `"${escapeQuotes(name)}"`;
|
|
204
|
+
return name;
|
|
205
|
+
}
|
|
206
|
+
function escapeQuotes(str) {
|
|
207
|
+
return str.replace(/"/g, "\\\"");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region packages/typescript/src/codegen/type-renderer.ts
|
|
212
|
+
var TypeRenderer = class extends BaseRenderer {
|
|
213
|
+
pre() {
|
|
214
|
+
this.writeln("// prettier-ignore-start");
|
|
215
|
+
this.writeln("/* eslint-disable */");
|
|
216
|
+
this.writeln(`/// <reference path="./${this.doc.name}" />`);
|
|
217
|
+
this.writeln("/**");
|
|
218
|
+
this.writeln(" * 🪄 This file was generated by Atscript");
|
|
219
|
+
this.writeln(" * Do not edit this file!");
|
|
220
|
+
this.writeln(" */");
|
|
221
|
+
this.writeln();
|
|
222
|
+
this.writeln("import type { TAtscriptTypeObject, TAtscriptTypeComplex, TAtscriptTypeFinal, TAtscriptTypeArray, TMetadataMap, Validator } from \"@atscript/typescript\"");
|
|
223
|
+
}
|
|
224
|
+
post() {
|
|
225
|
+
this.writeln("// prettier-ignore-end");
|
|
226
|
+
}
|
|
227
|
+
renderTypeDef(def) {
|
|
228
|
+
if (!def) {
|
|
229
|
+
this.write("unknown");
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if ((0, __atscript_core.isStructure)(def)) return this.renderStructure(def);
|
|
233
|
+
if ((0, __atscript_core.isGroup)(def)) {
|
|
234
|
+
const tuple = def.entity === "tuple";
|
|
235
|
+
const operator = tuple ? ", " : ` ${def.op} `;
|
|
236
|
+
const children = def.unwrap();
|
|
237
|
+
const hasSubgroup = !tuple && children.some((c) => c.entity === "group");
|
|
238
|
+
this.write(tuple ? "[" : hasSubgroup ? "(" : "");
|
|
239
|
+
this.renderTypeDef(def.first);
|
|
240
|
+
for (const child of children.slice(1)) {
|
|
241
|
+
this.write(operator);
|
|
242
|
+
this.renderTypeDef(child);
|
|
243
|
+
}
|
|
244
|
+
return this.write(tuple ? "]" : hasSubgroup ? ")" : "");
|
|
245
|
+
}
|
|
246
|
+
if ((0, __atscript_core.isConst)(def)) {
|
|
247
|
+
const name = def.token("identifier")?.type === "number" ? def.id : `"${escapeQuotes(def.id)}"`;
|
|
248
|
+
return this.write(name);
|
|
249
|
+
}
|
|
250
|
+
if ((0, __atscript_core.isRef)(def)) {
|
|
251
|
+
const node = def;
|
|
252
|
+
const unwound = this.doc.unwindType(node.id, node.chain);
|
|
253
|
+
if ((0, __atscript_core.isPrimitive)(unwound?.def)) {
|
|
254
|
+
this.write(renderPrimitiveTypeDef(unwound.def.config.type));
|
|
255
|
+
if (node.hasChain) this.write(` /* ${node.chain.map((c) => c.text).join(".")} */`);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
let name = node.id;
|
|
259
|
+
for (const c of node.chain) name += `["${escapeQuotes(c.text)}"]`;
|
|
260
|
+
return this.write(name);
|
|
261
|
+
}
|
|
262
|
+
if ((0, __atscript_core.isArray)(def)) {
|
|
263
|
+
const node = def;
|
|
264
|
+
const def2 = node.getDefinition();
|
|
265
|
+
const isGrp = def2?.entity === "group";
|
|
266
|
+
if (isGrp) this.write("(");
|
|
267
|
+
this.renderTypeDef(def2);
|
|
268
|
+
if (isGrp) this.write(")");
|
|
269
|
+
return this.write("[]");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
renderStructure(struct, asClass) {
|
|
273
|
+
this.blockln("{}");
|
|
274
|
+
for (const prop of Array.from(struct.props.values())) {
|
|
275
|
+
const optional = !!prop.token("optional");
|
|
276
|
+
this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
|
|
277
|
+
this.renderTypeDef(prop.getDefinition());
|
|
278
|
+
this.writeln();
|
|
279
|
+
}
|
|
280
|
+
if (asClass) {
|
|
281
|
+
this.writeln("static __is_anscript_annotated_type: true");
|
|
282
|
+
this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
|
|
283
|
+
this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
|
|
284
|
+
this.writeln(`static validator: () => Validator`);
|
|
285
|
+
}
|
|
286
|
+
this.pop();
|
|
287
|
+
}
|
|
288
|
+
renderInterface(node) {
|
|
289
|
+
this.writeln();
|
|
290
|
+
const exported = node.token("export")?.text === "export";
|
|
291
|
+
this.renderJsDoc(node);
|
|
292
|
+
this.write(exported ? "export declare " : "declare ");
|
|
293
|
+
this.write(`class ${node.id} `);
|
|
294
|
+
const struct = node.getDefinition();
|
|
295
|
+
if (struct?.entity === "structure") this.renderStructure(struct, node.id);
|
|
296
|
+
else this.writeln("{}");
|
|
297
|
+
this.writeln();
|
|
298
|
+
}
|
|
299
|
+
renderType(node) {
|
|
300
|
+
this.writeln();
|
|
301
|
+
const exported = node.token("export")?.text === "export";
|
|
302
|
+
this.renderJsDoc(node);
|
|
303
|
+
this.write(exported ? "export " : "declare ");
|
|
304
|
+
this.write(`type ${node.id} = `);
|
|
305
|
+
this.renderTypeDef(node.getDefinition());
|
|
306
|
+
this.writeln();
|
|
307
|
+
this.renderTypeNamespace(node);
|
|
308
|
+
}
|
|
309
|
+
renderTypeNamespace(node) {
|
|
310
|
+
this.write(`declare namespace ${node.id} `);
|
|
311
|
+
this.blockln("{}");
|
|
312
|
+
const def = node.getDefinition();
|
|
313
|
+
let typeDef = "TAtscriptTypeDef";
|
|
314
|
+
if (def) {
|
|
315
|
+
let realDef = def;
|
|
316
|
+
if ((0, __atscript_core.isRef)(def)) realDef = this.doc.unwindType(def.id, def.chain)?.def || realDef;
|
|
317
|
+
realDef = this.doc.mergeIntersection(realDef);
|
|
318
|
+
if ((0, __atscript_core.isStructure)(realDef) || (0, __atscript_core.isInterface)(realDef)) typeDef = `TAtscriptTypeObject<keyof ${node.id}}>`;
|
|
319
|
+
else if ((0, __atscript_core.isGroup)(realDef)) typeDef = "TAtscriptTypeComplex";
|
|
320
|
+
else if ((0, __atscript_core.isArray)(realDef)) typeDef = "TAtscriptTypeArray";
|
|
321
|
+
else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFinal";
|
|
322
|
+
}
|
|
323
|
+
this.writeln(`const __is_anscript_annotated_type: true`);
|
|
324
|
+
this.writeln(`const type: ${typeDef}`);
|
|
325
|
+
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
326
|
+
this.writeln(`const validator: () => Validator`);
|
|
327
|
+
this.popln();
|
|
328
|
+
}
|
|
329
|
+
renderJsDoc(node) {
|
|
330
|
+
const range = node.token("identifier")?.range;
|
|
331
|
+
const rangeStr = range ? `:${range.start.line + 1}:${range.start.character + 1}` : "";
|
|
332
|
+
this.writeln(`/**`);
|
|
333
|
+
this.writeln(` * Atscript ${node.entity} **${node.id}**`);
|
|
334
|
+
this.writeln(` * @see {@link ./${this.doc.name}${rangeStr}}`);
|
|
335
|
+
this.writeln(` */`);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
function renderPrimitiveTypeDef(def) {
|
|
339
|
+
if (!def) return "unknown";
|
|
340
|
+
if (typeof def === "string") return def === "void" ? "undefined" : def;
|
|
341
|
+
switch (def.kind) {
|
|
342
|
+
case "final": return def.value === "void" ? "undefined" : def.value;
|
|
343
|
+
case "union": return def.items.map(renderPrimitiveTypeDef).join(" | ");
|
|
344
|
+
case "intersection": return def.items.map(renderPrimitiveTypeDef).join(" & ");
|
|
345
|
+
case "tuple": return `[${def.items.map(renderPrimitiveTypeDef).join(", ")}]`;
|
|
346
|
+
case "array": return `${renderPrimitiveTypeDef(def.of)}[]`;
|
|
347
|
+
case "object": {
|
|
348
|
+
const props = Object.entries(def.props).map(([key, val]) => `${wrapProp(key)}${typeof val === "object" && val.optional ? "?" : ""}: ${renderPrimitiveTypeDef(val)}`).join("; ");
|
|
349
|
+
return `{ ${props} }`;
|
|
350
|
+
}
|
|
351
|
+
default: return "unknown";
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
//#endregion
|
|
356
|
+
//#region packages/typescript/src/codegen/js-renderer.ts
|
|
357
|
+
function _define_property$1(obj, key, value) {
|
|
358
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
359
|
+
value,
|
|
360
|
+
enumerable: true,
|
|
361
|
+
configurable: true,
|
|
362
|
+
writable: true
|
|
363
|
+
});
|
|
364
|
+
else obj[key] = value;
|
|
365
|
+
return obj;
|
|
366
|
+
}
|
|
367
|
+
var JsRenderer = class extends BaseRenderer {
|
|
368
|
+
pre() {
|
|
369
|
+
this.writeln("import { defineAnnotatedType as $ } from \"@atscript/typescript\"");
|
|
370
|
+
}
|
|
371
|
+
post() {
|
|
372
|
+
for (const node of this.postAnnotate) {
|
|
373
|
+
this.annotateType(node.getDefinition(), node.id);
|
|
374
|
+
this.indent().defineMetadata(node).unindent();
|
|
375
|
+
this.writeln();
|
|
376
|
+
}
|
|
377
|
+
super.post();
|
|
378
|
+
}
|
|
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_anscript_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();
|
|
391
|
+
}
|
|
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_anscript_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();
|
|
404
|
+
}
|
|
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 ((0, __atscript_core.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
|
+
}
|
|
451
|
+
}
|
|
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;
|
|
459
|
+
}
|
|
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;
|
|
464
|
+
}
|
|
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
|
+
this.unindent();
|
|
512
|
+
return;
|
|
513
|
+
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
defineObject(node) {
|
|
517
|
+
const props = Array.from(node.props.values());
|
|
518
|
+
for (const prop of props) {
|
|
519
|
+
const optional = !!prop.token("optional");
|
|
520
|
+
this.writeln(`.prop(`);
|
|
521
|
+
this.indent();
|
|
522
|
+
this.writeln(`"${escapeQuotes(prop.id)}",`);
|
|
523
|
+
this.annotateType(prop.getDefinition());
|
|
524
|
+
this.indent().defineMetadata(prop).unindent();
|
|
525
|
+
if (optional) this.writeln(" .optional()");
|
|
526
|
+
this.writeln(" .$type");
|
|
527
|
+
this.unindent();
|
|
528
|
+
this.write(`)`);
|
|
529
|
+
}
|
|
530
|
+
this.writeln();
|
|
531
|
+
return this;
|
|
532
|
+
}
|
|
533
|
+
defineGroup(node) {
|
|
534
|
+
const items = node.unwrap();
|
|
535
|
+
for (const item of items) this.write(".item(").indent().annotateType(item).write(" .$type").writeln(`)`).unindent();
|
|
536
|
+
return this;
|
|
537
|
+
}
|
|
538
|
+
defineArray(node) {
|
|
539
|
+
this.write(".of(").indent().annotateType(node.getDefinition()).write(" .$type").writeln(`)`).unindent();
|
|
540
|
+
return this;
|
|
541
|
+
}
|
|
542
|
+
defineMetadata(node) {
|
|
543
|
+
const annotations = this.doc.evalAnnotationsForNode(node);
|
|
544
|
+
annotations?.forEach((an) => {
|
|
545
|
+
this.resolveAnnotationValue(node, an);
|
|
546
|
+
});
|
|
547
|
+
return this;
|
|
548
|
+
}
|
|
549
|
+
resolveAnnotationValue(node, an) {
|
|
550
|
+
const spec = this.doc.resolveAnnotation(an.name);
|
|
551
|
+
let targetValue = "true";
|
|
552
|
+
let multiple = false;
|
|
553
|
+
if (spec) {
|
|
554
|
+
multiple = spec.config.multiple;
|
|
555
|
+
const length = spec.arguments.length;
|
|
556
|
+
if (length !== 0) if (Array.isArray(spec.config.argument)) {
|
|
557
|
+
targetValue = "{ ";
|
|
558
|
+
let i = 0;
|
|
559
|
+
for (const aSpec of spec.arguments) {
|
|
560
|
+
if (an.args[i]) targetValue += `${wrapProp(aSpec.name)}: ${aSpec.type === "string" ? `"${escapeQuotes(an.args[i]?.text)}"` : an.args[i]?.text}${i === length - 1 ? "" : ", "} `;
|
|
561
|
+
else {}
|
|
562
|
+
i++;
|
|
563
|
+
}
|
|
564
|
+
targetValue += "}";
|
|
565
|
+
} else {
|
|
566
|
+
const aSpec = spec.arguments[0];
|
|
567
|
+
if (an.args[0]) targetValue = aSpec.type === "string" ? `"${escapeQuotes(an.args[0]?.text)}"` : an.args[0]?.text;
|
|
568
|
+
else targetValue = "true";
|
|
569
|
+
}
|
|
570
|
+
} else {
|
|
571
|
+
multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
|
|
572
|
+
if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
|
|
573
|
+
}
|
|
574
|
+
if (multiple) this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue}, true)`);
|
|
575
|
+
else this.writeln(`.annotate("${escapeQuotes(an.name)}", ${targetValue})`);
|
|
576
|
+
}
|
|
577
|
+
constructor(...args) {
|
|
578
|
+
super(...args), _define_property$1(this, "postAnnotate", []);
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
//#endregion
|
|
583
|
+
//#region packages/typescript/src/plugin.ts
|
|
584
|
+
const tsPlugin = () => {
|
|
585
|
+
return {
|
|
586
|
+
name: "typesccript",
|
|
587
|
+
render(doc, format) {
|
|
588
|
+
if (format === "dts") return [{
|
|
589
|
+
fileName: `${doc.name}.d.ts`,
|
|
590
|
+
content: new TypeRenderer(doc).render()
|
|
591
|
+
}];
|
|
592
|
+
if (format === "js") return [{
|
|
593
|
+
fileName: `${doc.name}.js`,
|
|
594
|
+
content: new JsRenderer(doc).render()
|
|
595
|
+
}];
|
|
596
|
+
},
|
|
597
|
+
async buildEnd(output, format, repo) {
|
|
598
|
+
if (format === "dts") {
|
|
599
|
+
const annotations = await repo.getUsedAnnotations();
|
|
600
|
+
const tags = await repo.getPrimitivesTags() || new Set();
|
|
601
|
+
let rendered = [];
|
|
602
|
+
for (const [key, val] of Object.entries(annotations)) {
|
|
603
|
+
const multiple = val.multiple;
|
|
604
|
+
let typeLine = Array.from(val.types).map((t) => {
|
|
605
|
+
if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
606
|
+
else return t.optional ? `${t.type} | true` : t.type;
|
|
607
|
+
}).join(" | ");
|
|
608
|
+
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
609
|
+
}
|
|
610
|
+
let renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
|
|
611
|
+
output.push({
|
|
612
|
+
content: "/**\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",
|
|
613
|
+
fileName: "atscript.d.ts",
|
|
614
|
+
source: "",
|
|
615
|
+
target: path.default.join(repo.root, "atscript.d.ts")
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
//#endregion
|
|
623
|
+
//#region packages/typescript/src/cli/commands.controller.ts
|
|
624
|
+
function _define_property(obj, key, value) {
|
|
625
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
626
|
+
value,
|
|
627
|
+
enumerable: true,
|
|
628
|
+
configurable: true,
|
|
629
|
+
writable: true
|
|
630
|
+
});
|
|
631
|
+
else obj[key] = value;
|
|
632
|
+
return obj;
|
|
633
|
+
}
|
|
634
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
635
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
636
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
637
|
+
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;
|
|
638
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
639
|
+
}
|
|
640
|
+
function _ts_metadata(k, v) {
|
|
641
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
642
|
+
}
|
|
643
|
+
function _ts_param(paramIndex, decorator) {
|
|
644
|
+
return function(target, key) {
|
|
645
|
+
decorator(target, key, paramIndex);
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
var Commands = class {
|
|
649
|
+
async default(configFile, format) {
|
|
650
|
+
const config = await this.getConfig(configFile);
|
|
651
|
+
if (format) config.format = format;
|
|
652
|
+
this.logger.log(`Format: ${"\x1B[36m"}${config.format}${"\x1B[39m"}`);
|
|
653
|
+
const builder = await (0, __atscript_core.build)(config);
|
|
654
|
+
const out = await builder.write(config);
|
|
655
|
+
for (const { target } of out) this.logger.log(`✅ created ${"\x1B[32m"}${target}${"\x1B[39m"}`);
|
|
656
|
+
}
|
|
657
|
+
async getConfig(configFile) {
|
|
658
|
+
const root = process.cwd();
|
|
659
|
+
if (configFile) {
|
|
660
|
+
const c = path.default.join(root, configFile);
|
|
661
|
+
if (!(0, fs.existsSync)(c)) {
|
|
662
|
+
this.logger.error(`Config file ${"\x1B[4m"}${configFile}${"\x1B[24m"} not found`);
|
|
663
|
+
process.exit(1);
|
|
664
|
+
}
|
|
665
|
+
this.logger.log(`Using config file ${"\x1B[36m"}${configFile}${"\x1B[39m"}`);
|
|
666
|
+
return (0, __atscript_core.loadConfig)(c);
|
|
667
|
+
} else {
|
|
668
|
+
const resolved = await (0, __atscript_core.resolveConfigFile)(root);
|
|
669
|
+
if (resolved) {
|
|
670
|
+
this.logger.log(`Using config file ${"\x1B[36m"}${resolved}${"\x1B[39m"}`);
|
|
671
|
+
return (0, __atscript_core.loadConfig)(resolved);
|
|
672
|
+
}
|
|
673
|
+
this.logger.log(`No atscript config file found`);
|
|
674
|
+
return {
|
|
675
|
+
format: "dts",
|
|
676
|
+
plugins: [tsPlugin()]
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
constructor(logger) {
|
|
681
|
+
_define_property(this, "logger", void 0);
|
|
682
|
+
this.logger = logger;
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
_ts_decorate([
|
|
686
|
+
(0, __moostjs_event_cli.Cli)(""),
|
|
687
|
+
(0, moost.Description)("Builds .as files using --config and --format"),
|
|
688
|
+
(0, __moostjs_event_cli.CliExample)("-c atscript.config.js", "Build .as files using atscript.config.js"),
|
|
689
|
+
(0, __moostjs_event_cli.CliExample)("-f dts", "Build \"d.ts\" files for \".as\" files"),
|
|
690
|
+
_ts_param(0, (0, __moostjs_event_cli.CliOption)("c", "config")),
|
|
691
|
+
_ts_param(0, (0, moost.Optional)()),
|
|
692
|
+
_ts_param(0, (0, moost.Description)("Path to config file")),
|
|
693
|
+
_ts_param(1, (0, __moostjs_event_cli.CliOption)("f", "format")),
|
|
694
|
+
_ts_param(1, (0, moost.Optional)()),
|
|
695
|
+
_ts_param(1, (0, moost.Description)("Output format (js|dts), default: \"dts\"")),
|
|
696
|
+
_ts_metadata("design:type", Function),
|
|
697
|
+
_ts_metadata("design:paramtypes", [String, String]),
|
|
698
|
+
_ts_metadata("design:returntype", Promise)
|
|
699
|
+
], Commands.prototype, "default", null);
|
|
700
|
+
Commands = _ts_decorate([
|
|
701
|
+
(0, moost.Controller)(),
|
|
702
|
+
_ts_param(0, (0, moost.InjectMoostLogger)("asc")),
|
|
703
|
+
_ts_metadata("design:type", Function),
|
|
704
|
+
_ts_metadata("design:paramtypes", [typeof moost.TConsoleBase === "undefined" ? Object : moost.TConsoleBase])
|
|
705
|
+
], Commands);
|
|
706
|
+
|
|
707
|
+
//#endregion
|
|
708
|
+
//#region packages/typescript/src/cli/cli.ts
|
|
709
|
+
const app = new moost.Moost();
|
|
710
|
+
const cli = new __moostjs_event_cli.MoostCli({
|
|
711
|
+
debug: false,
|
|
712
|
+
wooksCli: { cliHelp: { name: "asc" } },
|
|
713
|
+
globalCliOptions: [{
|
|
714
|
+
keys: ["help"],
|
|
715
|
+
description: "Display instructions for the command."
|
|
716
|
+
}]
|
|
717
|
+
});
|
|
718
|
+
app.adapter(cli);
|
|
719
|
+
app.registerControllers(Commands);
|
|
720
|
+
app.applyGlobalInterceptors((0, __moostjs_event_cli.cliHelpInterceptor)({
|
|
721
|
+
colors: true,
|
|
722
|
+
lookupLevel: 3
|
|
723
|
+
}));
|
|
724
|
+
app.init();
|
|
725
|
+
|
|
726
|
+
//#endregion
|