@luna-park/plugin 1.3.1 → 1.4.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.
@@ -0,0 +1,611 @@
1
+ import { c as typeToSchema, d as objectMap, i as LogicType, l as cleanObject, r as EVarType, s as schemaLoop } from "./dist-hc-SHkAg.mjs";
2
+ import fs from "node:fs";
3
+ import * as ts$1 from "typescript";
4
+ import ts from "typescript";
5
+ import * as path from "path";
6
+ import * as fs$1 from "fs";
7
+ //#region src/extractor/code/lib.ts
8
+ function generateCode(schema, options = {}) {
9
+ if (typeof schema !== "object" || schema === null) return JSON.stringify(schema);
10
+ const properties = {};
11
+ for (const props of [
12
+ "default",
13
+ "description",
14
+ "name",
15
+ "target",
16
+ "promise",
17
+ "optional",
18
+ "example",
19
+ "enum"
20
+ ]) if (schema[props]) properties[props] = schema[props];
21
+ if (schema.type === EVarType.array) return buildFunctionCall(`LogicType.${schema.type}`, [generateCode(schema.items, options), getCodeFromObject(properties)]);
22
+ if (schema.type === EVarType.interface) return buildFunctionCall(`LogicType.${schema.type}`, [JSON.stringify(schema.className), getCodeFromObject(properties)]);
23
+ if (schema.type === EVarType.union) return buildFunctionCall(`LogicType.${schema.type}`, [`[${schema.elements.map((element) => generateCode(element, options)).join(", ")}]`, getCodeFromObject(properties)]);
24
+ if (schema.type === EVarType.function) return buildFunctionCall(`LogicType.${schema.type}`, [
25
+ generateCode(schema.inputs, options),
26
+ generateCode(schema.output, options),
27
+ getCodeFromObject(properties)
28
+ ]);
29
+ if (schema.type === EVarType.object) return buildFunctionCall(`LogicType.${schema.type}`, [getCodeFromObject(objectMap(schema.properties, ({ value }) => generateCode(value, options)), true), getCodeFromObject(properties)]);
30
+ if (schema.type === EVarType.type) {
31
+ const target = schema.target.at(-1);
32
+ const propertyCode = getCodeFromObject(properties);
33
+ if (propertyCode !== "{}") return target;
34
+ else return `{ ...${target}, ${propertyCode.slice(1, -1)} }`;
35
+ }
36
+ return buildFunctionCall(`LogicType.${schema.type}`, [getCodeFromObject(properties)]);
37
+ }
38
+ function buildFunctionCall(target, args) {
39
+ const lastArgIndex = args.findLastIndex((arg) => arg !== "{}");
40
+ return `${target}(${args.slice(0, lastArgIndex + 1).join(", ")})`;
41
+ }
42
+ function getCodeFromObject(object, raw) {
43
+ return `{${Object.entries(object).map(([key, value]) => `${getSafeKey(key)}: ${raw ? value : JSON.stringify(value)}`).join(", ")}}`;
44
+ }
45
+ function getSafeKey(key) {
46
+ return /^[a-zA-Z]+$/.test(key) ? key : JSON.stringify(key);
47
+ }
48
+ //#endregion
49
+ //#region src/extractor/code/component.ts
50
+ function getComponentCode(logicResult, file) {
51
+ const content = [];
52
+ const component = logicResult.components["default"];
53
+ const typeLib = Object.keys(logicResult.types);
54
+ for (const type of [
55
+ "properties",
56
+ "slots",
57
+ "models",
58
+ "emits"
59
+ ]) if (component[type] && Object.keys(component[type]).length) content.push({
60
+ key: type,
61
+ value: Object.entries(component[type]).map(([key, value]) => `${getSafeKey(key)}: ${generateCode(value, { lib: typeLib })}`).join(",\n ")
62
+ });
63
+ const typesDeclaration = Object.entries(logicResult.types).map(([key, value]) => `const ${key} = ${generateCode(value, { lib: typeLib })};`).join("\n\n");
64
+ return `import { LogicType, type TComponent } from "@luna-park/plugin";
65
+ import ${file.name} from "${file.path}";
66
+
67
+ ${typesDeclaration}
68
+
69
+ export const ${file.name.toLocaleLowerCase()}: TComponent = {
70
+ name: "${file.name}",
71
+ component: ${file.name},
72
+ ${content.map(({ key, value }) => `${key}: {\n ${value}\n }`).join(",\n ")}
73
+ }`;
74
+ }
75
+ //#endregion
76
+ //#region src/extractor/documentation.ts
77
+ function getDocumentationFromSymbol(symbol, checker) {
78
+ const documentation = { description: mergeSymbolDisplayParts(symbol.getDocumentationComment(checker)) || void 0 };
79
+ for (const tag of symbol.getJsDocTags()) {
80
+ if (tag.name === "param") {
81
+ if (!documentation.params) documentation.params = {};
82
+ let paramDescription = mergeSymbolDisplayParts(tag.text?.slice(1)).trim();
83
+ if (paramDescription.startsWith("- ")) paramDescription = paramDescription.slice(2);
84
+ const paramName = tag.text[0]?.text;
85
+ documentation.params[paramName] = paramDescription;
86
+ continue;
87
+ }
88
+ documentation[tag.name] = mergeSymbolDisplayParts(tag.text);
89
+ }
90
+ return cleanObject(documentation);
91
+ }
92
+ function mergeSymbolDisplayParts(symbolDisplayParts = []) {
93
+ return symbolDisplayParts.map((part) => part.text).join("");
94
+ }
95
+ //#endregion
96
+ //#region src/extractor/export/component.ts
97
+ function getSlots(type, typeExport) {
98
+ const properties = typeExport.checker.getPropertiesOfType(type);
99
+ const slots = {};
100
+ properties.forEach((slot) => {
101
+ const slotType = getDefinedType(typeExport.checker.getTypeOfSymbol(slot)).type;
102
+ const firstParameter = typeExport.checker.getSignaturesOfType(slotType, ts$1.SignatureKind.Call)[0]?.parameters?.[0];
103
+ if (firstParameter) {
104
+ const firstParameterType = typeExport.checker.getTypeOfSymbol(firstParameter);
105
+ slots[slot.name] = { type: typeExport.typeToString(firstParameterType) };
106
+ typeExport.extractType(firstParameterType);
107
+ } else slots[slot.name] = { type: "{}" };
108
+ });
109
+ return slots;
110
+ }
111
+ function getProps(type, typeExport) {
112
+ const properties = typeExport.checker.getPropertiesOfType(type);
113
+ const props = {};
114
+ const emits = {};
115
+ properties.forEach((prop) => {
116
+ if (["onVnode", "ref_"].some((name) => prop.name.startsWith(name)) || [
117
+ "ref",
118
+ "class",
119
+ "style",
120
+ "key"
121
+ ].includes(prop.name)) return;
122
+ const propType = typeExport.checker.getTypeOfSymbol(prop);
123
+ typeExport.extractType(propType);
124
+ if (isEmits(prop.name)) {
125
+ emits[emitName(prop.name)] = getExportType(propType, prop, typeExport);
126
+ return;
127
+ }
128
+ props[prop.name] = getExportType(propType, prop, typeExport);
129
+ });
130
+ return {
131
+ emits,
132
+ props
133
+ };
134
+ }
135
+ function computeModels(component) {
136
+ component.models = Object.keys(component.properties ?? {}).reduce((models, prop) => {
137
+ if (component.emits?.[`update:${prop}`]) {
138
+ models[prop] = component.properties[prop];
139
+ delete component.properties[prop];
140
+ delete component.emits[`update:${prop}`];
141
+ }
142
+ return models;
143
+ }, {});
144
+ return component;
145
+ }
146
+ function getDefinedType(type) {
147
+ if (type.isUnion()) {
148
+ const notUndefined = type.types.filter((type) => type.flags !== ts$1.TypeFlags.Undefined);
149
+ if (notUndefined.length === 1) return {
150
+ optional: true,
151
+ type: notUndefined[0]
152
+ };
153
+ }
154
+ return { type };
155
+ }
156
+ function getExportType(type, symbol, typeExport) {
157
+ const definedType = getDefinedType(type);
158
+ return cleanObject({
159
+ description: getDocumentationFromSymbol(symbol, typeExport.checker).description,
160
+ optional: definedType.optional,
161
+ type: typeExport.typeToString(definedType.type)
162
+ });
163
+ }
164
+ function isEmits(name) {
165
+ return /^on[A-Z]/.test(name);
166
+ }
167
+ function emitName(name) {
168
+ name = name.slice(2);
169
+ return name.charAt(0).toLowerCase() + name.slice(1);
170
+ }
171
+ //#endregion
172
+ //#region src/extractor/export/template.ts
173
+ function getTemplateTypeParameters(signature, typeExport) {
174
+ return Object.fromEntries((signature.getTypeParameters() ?? []).map((typeParameter) => {
175
+ let type = "unknown";
176
+ const defaultType = typeParameter.getDefault();
177
+ if (defaultType) type = typeExport.typeToString(defaultType);
178
+ const constraintType = typeParameter.getConstraint();
179
+ if (constraintType) type = typeExport.typeToString(constraintType);
180
+ return [typeParameter.symbol.name, type];
181
+ }));
182
+ }
183
+ //#endregion
184
+ //#region src/extractor/export/utils.ts
185
+ function getResolvedExports(checker, module) {
186
+ const resolvedExports = /* @__PURE__ */ new Map();
187
+ const exports = checker.getExportsOfModule(module);
188
+ for (const exp of exports) {
189
+ let resolvedSymbol = exp;
190
+ while (resolvedSymbol.flags & ts$1.SymbolFlags.Alias) resolvedSymbol = checker.getAliasedSymbol(resolvedSymbol);
191
+ resolvedExports.set(exp.name, resolvedSymbol);
192
+ }
193
+ return resolvedExports;
194
+ }
195
+ function getFullName(checker, symbol) {
196
+ let fullName = checker.getFullyQualifiedName(symbol);
197
+ if (fullName.includes("\".")) fullName = fullName.split("\".").pop();
198
+ if (fullName.includes(").")) fullName = fullName.split(").").pop();
199
+ return fullName;
200
+ }
201
+ function swapType(target, template) {
202
+ for (const [key, value] of Object.entries(template)) target = target.replace(new RegExp(`\\b${key}\\b`, "g"), value);
203
+ return target;
204
+ }
205
+ function extractEnumDefinition(enumDeclaration) {
206
+ const members = [];
207
+ enumDeclaration.members.forEach((member) => {
208
+ const memberName = member.name.getText();
209
+ if (member.initializer) {
210
+ let initializerText;
211
+ if (ts$1.isStringLiteral(member.initializer)) initializerText = `"${member.initializer.text}"`;
212
+ else if (ts$1.isNumericLiteral(member.initializer)) initializerText = member.initializer.text;
213
+ else initializerText = member.initializer.getText();
214
+ members.push(`${memberName} = ${initializerText}`);
215
+ } else members.push(memberName);
216
+ });
217
+ return `{ ${members.join(", ")} }`;
218
+ }
219
+ //#endregion
220
+ //#region src/extractor/lib.ts
221
+ function isUserType(type) {
222
+ if (type.getFlags() & (ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BooleanLike | ts.TypeFlags.ESSymbolLike | ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Null | ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) return false;
223
+ const symbol = type.getSymbol();
224
+ if (!symbol) return true;
225
+ const declaration = symbol.declarations?.[0];
226
+ if (!declaration) return true;
227
+ const srcFile = declaration.getSourceFile();
228
+ if (/lib\..*\.d\.ts$/.test(srcFile.fileName)) return false;
229
+ if (srcFile.fileName.startsWith("/@vue/")) return false;
230
+ return true;
231
+ }
232
+ //#endregion
233
+ //#region src/extractor/export/index.ts
234
+ const FLAGS = ts.TypeFormatFlags.WriteArrowStyleSignature | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseFullyQualifiedType;
235
+ var CTypeExport = class {
236
+ checker;
237
+ index;
238
+ cache = /* @__PURE__ */ new Set();
239
+ result;
240
+ constructor(program) {
241
+ this.program = program;
242
+ this.checker = program.getTypeChecker();
243
+ }
244
+ get(target) {
245
+ this.index = this.program.getSourceFile(target);
246
+ if (!this.index) throw new Error(`Cannot find file ${target}`);
247
+ const moduleSymbol = this.checker.getSymbolAtLocation(this.index);
248
+ if (!moduleSymbol) throw new Error(`Cannot find module ${target}`);
249
+ this.result = {
250
+ components: {},
251
+ functions: {},
252
+ types: {}
253
+ };
254
+ const exportAssignment = this.index.statements.find((statement) => ts.isExportAssignment(statement));
255
+ if (exportAssignment) {
256
+ const callSignature = this.checker.getTypeAtLocation(exportAssignment.expression).getCallSignatures()[0];
257
+ if (callSignature) this.exportFunction("default", callSignature);
258
+ }
259
+ this.exportModule(moduleSymbol);
260
+ return this.result;
261
+ }
262
+ exportModule(module) {
263
+ const resolvedExports = getResolvedExports(this.checker, module);
264
+ for (const [name, exportSymbol] of resolvedExports.entries()) {
265
+ let exportType = this.checker.getTypeOfSymbol(exportSymbol);
266
+ if (exportType.symbol && exportType.symbol.flags & ts.SymbolFlags.Module) {
267
+ const defaultExport = exportType.symbol.exports?.get("default");
268
+ if (defaultExport) exportType = this.checker.getTypeOfSymbol(defaultExport);
269
+ }
270
+ const symbol = exportType.symbol || exportType.aliasSymbol;
271
+ if (symbol?.flags & ts.SymbolFlags.Function) {
272
+ const functionType = this.checker.getTypeOfSymbol(symbol);
273
+ const callSignature = this.checker.getSignaturesOfType(functionType, ts.SignatureKind.Call)[0];
274
+ if (callSignature) {
275
+ const fullName = getFullName(this.checker, symbol);
276
+ this.exportFunction(fullName, callSignature);
277
+ }
278
+ } else if (this.typeToString(exportType).includes("DefineComponent<")) try {
279
+ this.exportComponent(name, exportType);
280
+ } catch (e) {
281
+ console.error(`Fail to export component ${name}`);
282
+ console.error(e);
283
+ }
284
+ }
285
+ }
286
+ exportComponent(name, type) {
287
+ const constructSignatures = type.getConstructSignatures()[0];
288
+ if (!constructSignatures) return;
289
+ const returnType = this.checker.getReturnTypeOfSignature(constructSignatures);
290
+ const component = {};
291
+ const propsSymbol = this.checker.getPropertyOfType(returnType, "$props");
292
+ if (propsSymbol) {
293
+ const props = getProps(this.checker.getTypeOfSymbol(propsSymbol), this);
294
+ component.properties = props.props;
295
+ component.emits = props.emits;
296
+ }
297
+ const slotsSymbol = this.checker.getPropertyOfType(returnType, "$slots");
298
+ if (slotsSymbol) component.slots = getSlots(this.checker.getTypeOfSymbol(slotsSymbol), this);
299
+ this.result.components[name] = computeModels(component);
300
+ }
301
+ exportFunction(name, signature) {
302
+ const documentation = getDocumentationFromSymbol(signature, this.checker);
303
+ const typeParameters = getTemplateTypeParameters(signature, this);
304
+ const parameters = signature.getParameters().map((symbol) => {
305
+ const pNode = symbol.valueDeclaration ?? this.index;
306
+ const pType = this.checker.getTypeOfSymbol(symbol);
307
+ this.extractType(pType, pNode);
308
+ const defaultValue = symbol.valueDeclaration?.initializer?.getText();
309
+ return cleanObject({
310
+ default: defaultValue,
311
+ description: documentation.params?.[symbol.name],
312
+ name: symbol.name,
313
+ optional: !!pNode.questionToken || defaultValue !== void 0 || void 0,
314
+ type: swapType(this.typeToString(pType), typeParameters)
315
+ });
316
+ });
317
+ if (parameters.some((parameter) => parameter.name?.startsWith("__VLS_"))) {
318
+ const component = {};
319
+ const propsIndex = parameters.findIndex((parameter) => parameter.name === "__VLS_props");
320
+ const propsSymbol = signature.getParameters()[propsIndex];
321
+ if (propsSymbol) {
322
+ const props = getProps(this.checker.getTypeOfSymbol(propsSymbol), this);
323
+ component.properties = props.props;
324
+ component.emits = props.emits;
325
+ Object.values(component.properties).forEach((prop) => {
326
+ prop.type = swapType(prop.type, typeParameters);
327
+ });
328
+ }
329
+ const slotsIndex = parameters.findIndex((parameter) => parameter.name === "__VLS_slots");
330
+ const slotsSymbol = signature.getParameters()[slotsIndex];
331
+ if (slotsSymbol) {
332
+ component.slots = getSlots(this.checker.getTypeOfSymbol(slotsSymbol), this);
333
+ Object.values(component.slots).forEach((slot) => {
334
+ slot.type = swapType(slot.type, typeParameters);
335
+ });
336
+ }
337
+ this.result.components[name] = computeModels(component);
338
+ return;
339
+ }
340
+ const returnType = this.checker.getReturnTypeOfSignature(signature);
341
+ this.extractType(returnType);
342
+ this.result.functions[name] = cleanObject({
343
+ description: documentation.description,
344
+ parameters,
345
+ return: {
346
+ description: documentation.returns,
347
+ type: swapType(this.typeToString(returnType), typeParameters)
348
+ }
349
+ });
350
+ }
351
+ extractType(type, ctxNode = this.index) {
352
+ if (this.cache.has(type)) return;
353
+ this.cache.add(type);
354
+ const symbol = type.symbol || type.aliasSymbol;
355
+ if ((type.isUnion() || type.isIntersection()) && !(symbol?.flags & ts.SymbolFlags.Enum)) type.types.forEach((childType) => {
356
+ this.extractType(childType, ctxNode);
357
+ });
358
+ if (symbol) {
359
+ if (this.checker.getFullyQualifiedName(symbol).includes("/@vue/")) return;
360
+ const fullName = getFullName(this.checker, symbol);
361
+ if (symbol.flags & ts.SymbolFlags.Enum) {
362
+ const enumDeclaration = symbol.valueDeclaration || symbol.declarations?.[0];
363
+ if (enumDeclaration && ts.isEnumDeclaration(enumDeclaration)) {
364
+ const fullName = getFullName(this.checker, symbol);
365
+ this.result.types[fullName] = cleanObject({
366
+ ...getDocumentationFromSymbol(symbol, this.checker),
367
+ type: extractEnumDefinition(enumDeclaration)
368
+ });
369
+ }
370
+ return;
371
+ }
372
+ if (symbol.flags & ts.SymbolFlags.Namespace) {
373
+ const namespaceSymbol = symbol;
374
+ this.exportModule(namespaceSymbol);
375
+ }
376
+ if (symbol.flags & ts.SymbolFlags.TypeAlias) {
377
+ const declaration = symbol.valueDeclaration || symbol.declarations?.[0];
378
+ if (!declaration) return;
379
+ const typeParameters = Object.fromEntries((declaration?.typeParameters ?? []).map((typeParameter) => {
380
+ let type = "unknown";
381
+ const defaultType = typeParameter.default;
382
+ if (defaultType) {
383
+ const defaultTypeObj = this.checker.getTypeFromTypeNode(defaultType);
384
+ type = this.typeToString(defaultTypeObj);
385
+ }
386
+ const constraintType = typeParameter.constraint;
387
+ if (constraintType) {
388
+ const constraintTypeObj = this.checker.getTypeFromTypeNode(constraintType);
389
+ type = this.typeToString(constraintTypeObj);
390
+ }
391
+ return [typeParameter.symbol.name, type];
392
+ }));
393
+ this.result.types[fullName] = {
394
+ ...getDocumentationFromSymbol(symbol, this.checker),
395
+ type: swapType(this.typeToString(type, FLAGS | ts.TypeFormatFlags.InTypeAlias), typeParameters)
396
+ };
397
+ }
398
+ if (symbol.flags & ts.SymbolFlags.Interface && isUserType(type)) {
399
+ const declaration = symbol.getDeclarations()[0];
400
+ if (declaration) {
401
+ const properties = this.checker.getPropertiesOfType(type);
402
+ const exportProperties = {};
403
+ properties.forEach((prop) => {
404
+ const propType = this.checker.getTypeOfSymbol(prop);
405
+ this.extractType(propType, declaration);
406
+ exportProperties[prop.name] = {
407
+ ...getDocumentationFromSymbol(prop, this.checker),
408
+ optional: !!(prop.flags & ts.SymbolFlags.Optional) || void 0,
409
+ type: this.typeToString(propType)
410
+ };
411
+ });
412
+ this.result.types[fullName] = {
413
+ ...getDocumentationFromSymbol(symbol, this.checker),
414
+ type: exportProperties
415
+ };
416
+ }
417
+ }
418
+ if (symbol.flags & ts.SymbolFlags.TypeLiteral) {
419
+ const fullName = getFullName(this.checker, type.aliasSymbol || type.symbol);
420
+ const properties = this.checker.getPropertiesOfType(type);
421
+ const exportProperties = {};
422
+ if ([
423
+ "Promise",
424
+ "Partial",
425
+ "Pick",
426
+ "Omit",
427
+ "Required"
428
+ ].includes(fullName)) {
429
+ this.cache.delete(type);
430
+ this.extractType(type.aliasTypeArguments[0]);
431
+ return;
432
+ }
433
+ if (type.aliasTypeArguments?.some((typeArgument) => !isUserType(typeArgument))) return;
434
+ properties.forEach((prop) => {
435
+ const propType = this.checker.getTypeOfSymbol(prop);
436
+ exportProperties[prop.name] = {
437
+ ...getDocumentationFromSymbol(prop, this.checker),
438
+ optional: !!(prop.flags & ts.SymbolFlags.Optional),
439
+ type: this.typeToString(propType)
440
+ };
441
+ });
442
+ if (fullName !== "__type") this.result.types[fullName] = {
443
+ ...getDocumentationFromSymbol(symbol, this.checker),
444
+ type: exportProperties
445
+ };
446
+ }
447
+ }
448
+ if (type.flags & ts.TypeFlags.Object) {
449
+ const object = type;
450
+ if (isUserType(type)) this.checker.getPropertiesOfType(type).forEach((prop) => {
451
+ const propType = this.checker.getTypeOfSymbol(prop);
452
+ this.extractType(propType, ctxNode);
453
+ });
454
+ if (object.objectFlags & ts.ObjectFlags.Reference) {
455
+ const reference = object;
456
+ this.checker.getTypeArguments(reference).forEach((typeArg) => {
457
+ this.extractType(typeArg, ctxNode);
458
+ });
459
+ }
460
+ }
461
+ }
462
+ typeToString(type, flags = FLAGS) {
463
+ return this.checker.typeToString(type, void 0, flags);
464
+ }
465
+ };
466
+ //#endregion
467
+ //#region src/extractor/generator.ts
468
+ function generateNodes(exportResult, packageName = "unknown") {
469
+ const nodeResult = {
470
+ components: {},
471
+ functions: {},
472
+ types: {}
473
+ };
474
+ for (const [name, type] of Object.entries(exportResult.types)) nodeResult.types[name] = getSchemaFromType(type, name);
475
+ for (const [name, type] of Object.entries(exportResult.functions)) nodeResult.functions[name] = getSchemaFromFunction(type, name);
476
+ for (const [name, type] of Object.entries(exportResult.components)) nodeResult.components[name] = getSchemaFromComponent(type, name);
477
+ return nodeResult;
478
+ function getSchemaFromType(type, name = "") {
479
+ if (typeof type.type === "string") {
480
+ if (type.type === "{}") return LogicType.void();
481
+ const schema = {
482
+ ...linkTypeReferences(typeToSchema(type.type)),
483
+ ...cleanObject({
484
+ description: type.description,
485
+ name: name?.split(".").pop() || void 0,
486
+ optional: type.optional
487
+ })
488
+ };
489
+ if (type.default) switch (schema.type) {
490
+ case EVarType.boolean:
491
+ schema.default = type.default === "true";
492
+ break;
493
+ case EVarType.number:
494
+ schema.default = Number(type.default);
495
+ break;
496
+ case EVarType.string:
497
+ schema.default = type.default;
498
+ break;
499
+ }
500
+ if (schema.type === EVarType.object && !Object.keys(schema.properties).length) schema.customizable = true;
501
+ return schema;
502
+ } else {
503
+ const schema = LogicType.object(objectMap(type.type, ({ key, value }) => getSchemaFromType(value, key)), cleanObject({
504
+ description: type.description,
505
+ name: name?.split(".").pop(),
506
+ optional: type.optional
507
+ }));
508
+ if (!Object.keys(schema.properties).length) schema.customizable = true;
509
+ return schema;
510
+ }
511
+ }
512
+ function getSchemaFromFunction(func, name = "") {
513
+ return {
514
+ ...cleanObject({
515
+ description: func.description,
516
+ name: name?.split(".").pop()
517
+ }),
518
+ parameters: (func.parameters ?? []).map((param) => getSchemaFromType(param, param.name)),
519
+ return: getSchemaFromType(func.return, "result")
520
+ };
521
+ }
522
+ function getSchemaFromComponent(component, name = "") {
523
+ return {
524
+ ...cleanObject({ name: name?.split(".").pop() }),
525
+ emits: objectMap(component.emits, ({ value }) => getSchemaFromType(value)),
526
+ models: objectMap(component.models, ({ value }) => getSchemaFromType(value)),
527
+ properties: objectMap(component.properties, ({ key, value }) => getSchemaFromType(value, key)),
528
+ slots: objectMap(component.slots, ({ value }) => getSchemaFromType(value))
529
+ };
530
+ }
531
+ function linkTypeReferences(schema, prefix = "") {
532
+ return schemaLoop(schema, ({ schema }) => {
533
+ if (schema.type === EVarType.interface) return {
534
+ ...getShadowedType(schema.className, prefix),
535
+ description: schema.description,
536
+ name: schema.name,
537
+ optional: schema.optional
538
+ };
539
+ });
540
+ function getShadowedType(key, prefix = "") {
541
+ let target = `${prefix}${key}`;
542
+ while (!exportResult.types[target] && target.indexOf(".") !== -1) target = target.substring(target.indexOf(".") + 1);
543
+ return exportResult.types[target] ? LogicType.type([
544
+ "packages",
545
+ packageName,
546
+ ...target.split(".")
547
+ ]) : LogicType.interface(key);
548
+ }
549
+ }
550
+ }
551
+ //#endregion
552
+ //#region src/extractor/config.ts
553
+ function findNearestTsConfig(configPath) {
554
+ while (true) {
555
+ const tsconfigPath = path.join(configPath, "tsconfig.json");
556
+ if (fs$1.existsSync(tsconfigPath)) return tsconfigPath;
557
+ const parentDir = path.dirname(configPath);
558
+ if (parentDir === configPath) return;
559
+ configPath = parentDir;
560
+ }
561
+ }
562
+ function getTsConfig(configPath) {
563
+ const configFile = ts$1.readConfigFile(configPath, ts$1.sys.readFile);
564
+ if (configFile.error) throw new Error(`Failed to read tsconfig.json: ${configFile.error.messageText}`);
565
+ return ts$1.parseJsonConfigFileContent(configFile.config, ts$1.sys, path.dirname(configPath));
566
+ }
567
+ //#endregion
568
+ //#region src/extractor/source.ts
569
+ function resolveModulePath(moduleName, compilerOptions) {
570
+ const tempFileName = path.join(process.cwd(), "__temp__.ts");
571
+ const tempHost = ts$1.createCompilerHost(compilerOptions);
572
+ const resolved = ts$1.resolveModuleName(moduleName, tempFileName, compilerOptions, tempHost);
573
+ if (resolved.resolvedModule) return resolved.resolvedModule.resolvedFileName;
574
+ }
575
+ function getSourceFile(moduleName) {
576
+ const tsconfigPath = findNearestTsConfig(moduleName);
577
+ if (!tsconfigPath) throw new Error(`Could not find tsconfig.json for: ${moduleName}`);
578
+ const compilerOptions = getTsConfig(tsconfigPath).options;
579
+ const resolvedPath = resolveModulePath(moduleName, compilerOptions);
580
+ if (!resolvedPath) throw new Error(`Could not resolve module: ${moduleName}`);
581
+ const host = ts$1.createCompilerHost(compilerOptions);
582
+ const program = ts$1.createProgram({
583
+ host,
584
+ options: compilerOptions,
585
+ rootNames: [resolvedPath]
586
+ });
587
+ const sourceFile = program.getSourceFile(resolvedPath);
588
+ if (!sourceFile) throw new Error(`Could not get source file for: ${resolvedPath}`);
589
+ return {
590
+ program,
591
+ sourceFile
592
+ };
593
+ }
594
+ //#endregion
595
+ //#region src/extractor/index.ts
596
+ const fsp = fs.promises;
597
+ async function extractFile(filePath, target) {
598
+ const fileName = filePath.split("/").pop().split(".")[0];
599
+ const { program, sourceFile } = getSourceFile(filePath);
600
+ const logicResult = generateNodes(new CTypeExport(program).get(sourceFile.fileName), fileName);
601
+ if (logicResult.components.default) {
602
+ const content = getComponentCode(logicResult, {
603
+ name: fileName,
604
+ path: filePath
605
+ });
606
+ await fsp.mkdir(target.split("/").slice(0, -1).join("/"), { recursive: true });
607
+ await fsp.writeFile(target, content);
608
+ }
609
+ }
610
+ //#endregion
611
+ export { CTypeExport, extractFile, generateNodes, getSourceFile };