vue-component-meta 1.8.21 → 1.9.0-alpha.0
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/out/base.d.ts +34 -0
- package/out/base.js +680 -0
- package/out/index.d.ts +7 -17
- package/out/index.js +9 -659
- package/out/types.d.ts +1 -0
- package/package.json +10 -6
package/out/index.js
CHANGED
|
@@ -14,666 +14,16 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const vue_component_type_helpers_1 = require("vue-component-type-helpers");
|
|
21
|
-
const typescript_1 = require("@volar/typescript");
|
|
17
|
+
exports.createChecker = exports.createCheckerByJson = void 0;
|
|
18
|
+
const ts = require("typescript");
|
|
19
|
+
const base_1 = require("./base");
|
|
22
20
|
__exportStar(require("./types"), exports);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const rootPath = root.replace(windowsPathReg, '/');
|
|
26
|
-
return createComponentMetaCheckerWorker(() => vue.createParsedCommandLineByJson(ts, ts.sys, root, json), checkerOptions, rootPath, path.join(rootPath, 'jsconfig.json.global.vue'), ts);
|
|
21
|
+
function createCheckerByJson(rootPath, json, checkerOptions = {}) {
|
|
22
|
+
return (0, base_1.createCheckerByJsonBase)(ts, rootPath, json, checkerOptions);
|
|
27
23
|
}
|
|
28
|
-
exports.
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
return createComponentMetaCheckerWorker(() => vue.createParsedCommandLine(ts, ts.sys, tsconfigPath), checkerOptions, path.dirname(tsconfig), tsconfig + '.global.vue', ts);
|
|
32
|
-
}
|
|
33
|
-
exports.createComponentMetaChecker = createComponentMetaChecker;
|
|
34
|
-
function createComponentMetaCheckerWorker(loadParsedCommandLine, checkerOptions, rootPath, globalComponentName, ts) {
|
|
35
|
-
/**
|
|
36
|
-
* Original Host
|
|
37
|
-
*/
|
|
38
|
-
let parsedCommandLine = loadParsedCommandLine();
|
|
39
|
-
let fileNames = parsedCommandLine.fileNames.map(path => path.replace(windowsPathReg, '/'));
|
|
40
|
-
let projectVersion = 0;
|
|
41
|
-
const scriptSnapshots = new Map();
|
|
42
|
-
const _host = {
|
|
43
|
-
workspacePath: rootPath,
|
|
44
|
-
rootPath: rootPath,
|
|
45
|
-
getProjectVersion: () => projectVersion.toString(),
|
|
46
|
-
getCompilationSettings: () => parsedCommandLine.options,
|
|
47
|
-
getScriptFileNames: () => fileNames,
|
|
48
|
-
getProjectReferences: () => parsedCommandLine.projectReferences,
|
|
49
|
-
getScriptSnapshot: (fileName) => {
|
|
50
|
-
if (!scriptSnapshots.has(fileName)) {
|
|
51
|
-
const fileText = ts.sys.readFile(fileName);
|
|
52
|
-
if (fileText !== undefined) {
|
|
53
|
-
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(fileText));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return scriptSnapshots.get(fileName);
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
return {
|
|
60
|
-
...baseCreate(_host, vue.resolveVueCompilerOptions(parsedCommandLine.vueOptions), checkerOptions, globalComponentName, ts),
|
|
61
|
-
updateFile(fileName, text) {
|
|
62
|
-
fileName = fileName.replace(windowsPathReg, '/');
|
|
63
|
-
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(text));
|
|
64
|
-
projectVersion++;
|
|
65
|
-
},
|
|
66
|
-
deleteFile(fileName) {
|
|
67
|
-
fileName = fileName.replace(windowsPathReg, '/');
|
|
68
|
-
fileNames = fileNames.filter(f => f !== fileName);
|
|
69
|
-
projectVersion++;
|
|
70
|
-
},
|
|
71
|
-
reload() {
|
|
72
|
-
parsedCommandLine = loadParsedCommandLine();
|
|
73
|
-
fileNames = parsedCommandLine.fileNames.map(path => path.replace(windowsPathReg, '/'));
|
|
74
|
-
this.clearCache();
|
|
75
|
-
},
|
|
76
|
-
clearCache() {
|
|
77
|
-
scriptSnapshots.clear();
|
|
78
|
-
projectVersion++;
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
function baseCreate(_host, vueCompilerOptions, checkerOptions, globalComponentName, ts) {
|
|
83
|
-
const globalComponentSnapshot = ts.ScriptSnapshot.fromString('<script setup lang="ts"></script>');
|
|
84
|
-
const metaSnapshots = {};
|
|
85
|
-
const host = new Proxy({
|
|
86
|
-
getScriptFileNames: () => {
|
|
87
|
-
const names = _host.getScriptFileNames();
|
|
88
|
-
return [
|
|
89
|
-
...names,
|
|
90
|
-
...names.map(getMetaFileName),
|
|
91
|
-
globalComponentName,
|
|
92
|
-
getMetaFileName(globalComponentName),
|
|
93
|
-
];
|
|
94
|
-
},
|
|
95
|
-
getScriptSnapshot: fileName => {
|
|
96
|
-
if (isMetaFileName(fileName)) {
|
|
97
|
-
if (!metaSnapshots[fileName]) {
|
|
98
|
-
metaSnapshots[fileName] = ts.ScriptSnapshot.fromString(getMetaScriptContent(fileName));
|
|
99
|
-
}
|
|
100
|
-
return metaSnapshots[fileName];
|
|
101
|
-
}
|
|
102
|
-
else if (fileName === globalComponentName) {
|
|
103
|
-
return globalComponentSnapshot;
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
return _host.getScriptSnapshot(fileName);
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
}, {
|
|
110
|
-
get(target, prop) {
|
|
111
|
-
if (prop in target) {
|
|
112
|
-
return target[prop];
|
|
113
|
-
}
|
|
114
|
-
return _host[prop];
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
const vueLanguages = ts ? vue.createLanguages(host.getCompilationSettings(), vueCompilerOptions, ts) : [];
|
|
118
|
-
const core = vue.createLanguageContext(host, vueLanguages);
|
|
119
|
-
const tsLsHost = (0, typescript_1.createLanguageServiceHost)(core, ts, ts.sys, undefined);
|
|
120
|
-
const tsLs = ts.createLanguageService(tsLsHost);
|
|
121
|
-
(0, typescript_1.decorateLanguageService)(core.virtualFiles, tsLs, false);
|
|
122
|
-
if (checkerOptions.forceUseTs) {
|
|
123
|
-
const getScriptKind = tsLsHost.getScriptKind;
|
|
124
|
-
tsLsHost.getScriptKind = (fileName) => {
|
|
125
|
-
if (fileName.endsWith('.vue.js')) {
|
|
126
|
-
return ts.ScriptKind.TS;
|
|
127
|
-
}
|
|
128
|
-
if (fileName.endsWith('.vue.jsx')) {
|
|
129
|
-
return ts.ScriptKind.TSX;
|
|
130
|
-
}
|
|
131
|
-
return getScriptKind(fileName);
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
let globalPropNames;
|
|
135
|
-
return {
|
|
136
|
-
getExportNames,
|
|
137
|
-
getComponentMeta,
|
|
138
|
-
__internal__: {
|
|
139
|
-
tsLs,
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
function isMetaFileName(fileName) {
|
|
143
|
-
return fileName.endsWith('.meta.ts');
|
|
144
|
-
}
|
|
145
|
-
function getMetaFileName(fileName) {
|
|
146
|
-
return (fileName.endsWith('.vue') ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + '.meta.ts';
|
|
147
|
-
}
|
|
148
|
-
function getMetaScriptContent(fileName) {
|
|
149
|
-
let code = `
|
|
150
|
-
import * as Components from '${fileName.substring(0, fileName.length - '.meta.ts'.length)}';
|
|
151
|
-
export default {} as { [K in keyof typeof Components]: ComponentMeta<typeof Components[K]>; };
|
|
152
|
-
|
|
153
|
-
interface ComponentMeta<T> {
|
|
154
|
-
type: ComponentType<T>;
|
|
155
|
-
props: ComponentProps<T>;
|
|
156
|
-
emit: ComponentEmit<T>;
|
|
157
|
-
slots: ${vueCompilerOptions.target < 3 ? 'Vue2ComponentSlots' : 'ComponentSlots'}<T>;
|
|
158
|
-
exposed: ComponentExposed<T>;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
${vue_component_type_helpers_1.code}
|
|
162
|
-
`.trim();
|
|
163
|
-
return code;
|
|
164
|
-
}
|
|
165
|
-
function getExportNames(componentPath) {
|
|
166
|
-
const program = tsLs.getProgram();
|
|
167
|
-
const typeChecker = program.getTypeChecker();
|
|
168
|
-
return _getExports(program, typeChecker, componentPath).exports.map(e => e.getName());
|
|
169
|
-
}
|
|
170
|
-
function getComponentMeta(componentPath, exportName = 'default') {
|
|
171
|
-
const program = tsLs.getProgram();
|
|
172
|
-
const typeChecker = program.getTypeChecker();
|
|
173
|
-
const { symbolNode, exports } = _getExports(program, typeChecker, componentPath);
|
|
174
|
-
const _export = exports.find((property) => property.getName() === exportName);
|
|
175
|
-
if (!_export) {
|
|
176
|
-
throw `Could not find export ${exportName}`;
|
|
177
|
-
}
|
|
178
|
-
const componentType = typeChecker.getTypeOfSymbolAtLocation(_export, symbolNode);
|
|
179
|
-
const symbolProperties = componentType.getProperties() ?? [];
|
|
180
|
-
let _type;
|
|
181
|
-
let _props;
|
|
182
|
-
let _events;
|
|
183
|
-
let _slots;
|
|
184
|
-
let _exposed;
|
|
185
|
-
return {
|
|
186
|
-
get type() {
|
|
187
|
-
return _type ?? (_type = getType());
|
|
188
|
-
},
|
|
189
|
-
get props() {
|
|
190
|
-
return _props ?? (_props = getProps());
|
|
191
|
-
},
|
|
192
|
-
get events() {
|
|
193
|
-
return _events ?? (_events = getEvents());
|
|
194
|
-
},
|
|
195
|
-
get slots() {
|
|
196
|
-
return _slots ?? (_slots = getSlots());
|
|
197
|
-
},
|
|
198
|
-
get exposed() {
|
|
199
|
-
return _exposed ?? (_exposed = getExposed());
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
function getType() {
|
|
203
|
-
const $type = symbolProperties.find(prop => prop.escapedName === 'type');
|
|
204
|
-
if ($type) {
|
|
205
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($type, symbolNode);
|
|
206
|
-
return Number(typeChecker.typeToString(type));
|
|
207
|
-
}
|
|
208
|
-
return 0;
|
|
209
|
-
}
|
|
210
|
-
function getProps() {
|
|
211
|
-
const $props = symbolProperties.find(prop => prop.escapedName === 'props');
|
|
212
|
-
const propEventRegex = /^(on[A-Z])/;
|
|
213
|
-
let result = [];
|
|
214
|
-
if ($props) {
|
|
215
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($props, symbolNode);
|
|
216
|
-
const properties = type.getProperties();
|
|
217
|
-
result = properties
|
|
218
|
-
.map((prop) => {
|
|
219
|
-
const { resolveNestedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, core);
|
|
220
|
-
return resolveNestedProperties(prop);
|
|
221
|
-
})
|
|
222
|
-
.filter((prop) => !prop.name.match(propEventRegex));
|
|
223
|
-
}
|
|
224
|
-
// fill global
|
|
225
|
-
if (componentPath !== globalComponentName) {
|
|
226
|
-
globalPropNames ??= getComponentMeta(globalComponentName).props.map(prop => prop.name);
|
|
227
|
-
for (const prop of result) {
|
|
228
|
-
prop.global = globalPropNames.includes(prop.name);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
// fill defaults
|
|
232
|
-
const printer = ts.createPrinter(checkerOptions.printer);
|
|
233
|
-
const snapshot = host.getScriptSnapshot(componentPath);
|
|
234
|
-
const vueSourceFile = core.virtualFiles.getSource(componentPath)?.root;
|
|
235
|
-
const vueDefaults = vueSourceFile && exportName === 'default'
|
|
236
|
-
? (vueSourceFile instanceof vue.VueFile ? readVueComponentDefaultProps(vueSourceFile, printer, ts, vueCompilerOptions) : {})
|
|
237
|
-
: {};
|
|
238
|
-
const tsDefaults = !vueSourceFile ? readTsComponentDefaultProps(componentPath.substring(componentPath.lastIndexOf('.') + 1), // ts | js | tsx | jsx
|
|
239
|
-
snapshot.getText(0, snapshot.getLength()), exportName, printer, ts) : {};
|
|
240
|
-
for (const [propName, defaultExp] of Object.entries({
|
|
241
|
-
...vueDefaults,
|
|
242
|
-
...tsDefaults,
|
|
243
|
-
})) {
|
|
244
|
-
const prop = result.find(p => p.name === propName);
|
|
245
|
-
if (prop) {
|
|
246
|
-
prop.default = defaultExp.default;
|
|
247
|
-
if (defaultExp.required !== undefined) {
|
|
248
|
-
prop.required = defaultExp.required;
|
|
249
|
-
}
|
|
250
|
-
if (prop.default !== undefined) {
|
|
251
|
-
prop.required = false; // props with default are always optional
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
return result;
|
|
256
|
-
}
|
|
257
|
-
function getEvents() {
|
|
258
|
-
const $emit = symbolProperties.find(prop => prop.escapedName === 'emit');
|
|
259
|
-
if ($emit) {
|
|
260
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($emit, symbolNode);
|
|
261
|
-
const calls = type.getCallSignatures();
|
|
262
|
-
return calls.map((call) => {
|
|
263
|
-
const { resolveEventSignature, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, core);
|
|
264
|
-
return resolveEventSignature(call);
|
|
265
|
-
}).filter(event => event.name);
|
|
266
|
-
}
|
|
267
|
-
return [];
|
|
268
|
-
}
|
|
269
|
-
function getSlots() {
|
|
270
|
-
const $slots = symbolProperties.find(prop => prop.escapedName === 'slots');
|
|
271
|
-
if ($slots) {
|
|
272
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($slots, symbolNode);
|
|
273
|
-
const properties = type.getProperties();
|
|
274
|
-
return properties.map((prop) => {
|
|
275
|
-
const { resolveSlotProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, core);
|
|
276
|
-
return resolveSlotProperties(prop);
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
return [];
|
|
280
|
-
}
|
|
281
|
-
function getExposed() {
|
|
282
|
-
const $exposed = symbolProperties.find(prop => prop.escapedName === 'exposed');
|
|
283
|
-
if ($exposed) {
|
|
284
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($exposed, symbolNode);
|
|
285
|
-
const properties = type.getProperties().filter(prop =>
|
|
286
|
-
// only exposed props will not have a valueDeclaration
|
|
287
|
-
!prop.valueDeclaration);
|
|
288
|
-
return properties.map((prop) => {
|
|
289
|
-
const { resolveExposedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, core);
|
|
290
|
-
return resolveExposedProperties(prop);
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
return [];
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
function _getExports(program, typeChecker, componentPath) {
|
|
297
|
-
const sourceFile = program?.getSourceFile(getMetaFileName(componentPath));
|
|
298
|
-
if (!sourceFile) {
|
|
299
|
-
throw 'Could not find main source file';
|
|
300
|
-
}
|
|
301
|
-
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
302
|
-
if (!moduleSymbol) {
|
|
303
|
-
throw 'Could not find module symbol';
|
|
304
|
-
}
|
|
305
|
-
const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol);
|
|
306
|
-
let symbolNode;
|
|
307
|
-
for (const symbol of exportedSymbols) {
|
|
308
|
-
const [declaration] = symbol.getDeclarations() ?? [];
|
|
309
|
-
if (ts.isExportAssignment(declaration)) {
|
|
310
|
-
symbolNode = declaration.expression;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
if (!symbolNode) {
|
|
314
|
-
throw 'Could not find symbol node';
|
|
315
|
-
}
|
|
316
|
-
const exportDefaultType = typeChecker.getTypeAtLocation(symbolNode);
|
|
317
|
-
const exports = exportDefaultType.getProperties();
|
|
318
|
-
return {
|
|
319
|
-
symbolNode,
|
|
320
|
-
exports,
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
exports.baseCreate = baseCreate;
|
|
325
|
-
function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: options, noDeclarations }, ts, core) {
|
|
326
|
-
const visited = new Set();
|
|
327
|
-
function shouldIgnore(subtype) {
|
|
328
|
-
const name = typeChecker.typeToString(subtype);
|
|
329
|
-
if (name === 'any') {
|
|
330
|
-
return true;
|
|
331
|
-
}
|
|
332
|
-
if (visited.has(subtype)) {
|
|
333
|
-
return true;
|
|
334
|
-
}
|
|
335
|
-
if (typeof options === 'object') {
|
|
336
|
-
for (const item of options.ignore ?? []) {
|
|
337
|
-
if (typeof item === 'function') {
|
|
338
|
-
const result = item(name, subtype, typeChecker);
|
|
339
|
-
if (typeof result === 'boolean')
|
|
340
|
-
return result;
|
|
341
|
-
}
|
|
342
|
-
else if (name === item) {
|
|
343
|
-
return true;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return false;
|
|
348
|
-
}
|
|
349
|
-
function reducer(acc, cur) {
|
|
350
|
-
acc[cur.name] = cur;
|
|
351
|
-
return acc;
|
|
352
|
-
}
|
|
353
|
-
function resolveNestedProperties(prop) {
|
|
354
|
-
const subtype = typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode);
|
|
355
|
-
let schema;
|
|
356
|
-
let declarations;
|
|
357
|
-
return {
|
|
358
|
-
name: prop.getEscapedName().toString(),
|
|
359
|
-
global: false,
|
|
360
|
-
description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
|
|
361
|
-
tags: prop.getJsDocTags(typeChecker).map(tag => ({
|
|
362
|
-
name: tag.name,
|
|
363
|
-
text: tag.text !== undefined ? ts.displayPartsToString(tag.text) : undefined,
|
|
364
|
-
})),
|
|
365
|
-
required: !(prop.flags & ts.SymbolFlags.Optional),
|
|
366
|
-
type: typeChecker.typeToString(subtype),
|
|
367
|
-
rawType: rawType ? subtype : undefined,
|
|
368
|
-
get declarations() {
|
|
369
|
-
return declarations ??= getDeclarations(prop.declarations ?? []);
|
|
370
|
-
},
|
|
371
|
-
get schema() {
|
|
372
|
-
return schema ??= resolveSchema(subtype);
|
|
373
|
-
},
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
function resolveSlotProperties(prop) {
|
|
377
|
-
const propType = typeChecker.getNonNullableType(typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode));
|
|
378
|
-
const signatures = propType.getCallSignatures();
|
|
379
|
-
const paramType = signatures[0].parameters[0];
|
|
380
|
-
const subtype = typeChecker.getTypeOfSymbolAtLocation(paramType, symbolNode);
|
|
381
|
-
let schema;
|
|
382
|
-
let declarations;
|
|
383
|
-
return {
|
|
384
|
-
name: prop.getName(),
|
|
385
|
-
type: typeChecker.typeToString(subtype),
|
|
386
|
-
rawType: rawType ? subtype : undefined,
|
|
387
|
-
description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
|
|
388
|
-
get declarations() {
|
|
389
|
-
return declarations ??= getDeclarations(prop.declarations ?? []);
|
|
390
|
-
},
|
|
391
|
-
get schema() {
|
|
392
|
-
return schema ??= resolveSchema(subtype);
|
|
393
|
-
},
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
function resolveExposedProperties(expose) {
|
|
397
|
-
const subtype = typeChecker.getTypeOfSymbolAtLocation(expose, symbolNode);
|
|
398
|
-
let schema;
|
|
399
|
-
let declarations;
|
|
400
|
-
return {
|
|
401
|
-
name: expose.getName(),
|
|
402
|
-
type: typeChecker.typeToString(subtype),
|
|
403
|
-
rawType: rawType ? subtype : undefined,
|
|
404
|
-
description: ts.displayPartsToString(expose.getDocumentationComment(typeChecker)),
|
|
405
|
-
get declarations() {
|
|
406
|
-
return declarations ??= getDeclarations(expose.declarations ?? []);
|
|
407
|
-
},
|
|
408
|
-
get schema() {
|
|
409
|
-
return schema ??= resolveSchema(subtype);
|
|
410
|
-
},
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
function resolveEventSignature(call) {
|
|
414
|
-
const subtype = typeChecker.getTypeOfSymbolAtLocation(call.parameters[1], symbolNode);
|
|
415
|
-
let schema;
|
|
416
|
-
let declarations;
|
|
417
|
-
return {
|
|
418
|
-
name: typeChecker.getTypeOfSymbolAtLocation(call.parameters[0], symbolNode).value,
|
|
419
|
-
type: typeChecker.typeToString(subtype),
|
|
420
|
-
rawType: rawType ? subtype : undefined,
|
|
421
|
-
signature: typeChecker.signatureToString(call),
|
|
422
|
-
get declarations() {
|
|
423
|
-
return declarations ??= call.declaration ? getDeclarations([call.declaration]) : [];
|
|
424
|
-
},
|
|
425
|
-
get schema() {
|
|
426
|
-
return schema ??= typeChecker.getTypeArguments(subtype).map(resolveSchema);
|
|
427
|
-
},
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
function resolveCallbackSchema(signature) {
|
|
431
|
-
let schema;
|
|
432
|
-
return {
|
|
433
|
-
kind: 'event',
|
|
434
|
-
type: typeChecker.signatureToString(signature),
|
|
435
|
-
get schema() {
|
|
436
|
-
return schema ??= signature.parameters.length > 0
|
|
437
|
-
? typeChecker
|
|
438
|
-
.getTypeArguments(typeChecker.getTypeOfSymbolAtLocation(signature.parameters[0], symbolNode))
|
|
439
|
-
.map(resolveSchema)
|
|
440
|
-
: undefined;
|
|
441
|
-
},
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
function resolveSchema(subtype) {
|
|
445
|
-
const type = typeChecker.typeToString(subtype);
|
|
446
|
-
if (shouldIgnore(subtype)) {
|
|
447
|
-
return type;
|
|
448
|
-
}
|
|
449
|
-
visited.add(subtype);
|
|
450
|
-
if (subtype.isUnion()) {
|
|
451
|
-
let schema;
|
|
452
|
-
return {
|
|
453
|
-
kind: 'enum',
|
|
454
|
-
type,
|
|
455
|
-
get schema() {
|
|
456
|
-
return schema ??= subtype.types.map(resolveSchema);
|
|
457
|
-
},
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
// @ts-ignore - typescript internal, isArrayLikeType exists
|
|
461
|
-
else if (typeChecker.isArrayLikeType(subtype)) {
|
|
462
|
-
let schema;
|
|
463
|
-
return {
|
|
464
|
-
kind: 'array',
|
|
465
|
-
type,
|
|
466
|
-
get schema() {
|
|
467
|
-
return schema ??= typeChecker.getTypeArguments(subtype).map(resolveSchema);
|
|
468
|
-
},
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
else if (subtype.getCallSignatures().length === 0 &&
|
|
472
|
-
(subtype.isClassOrInterface() || subtype.isIntersection() || subtype.objectFlags & ts.ObjectFlags.Anonymous)) {
|
|
473
|
-
let schema;
|
|
474
|
-
return {
|
|
475
|
-
kind: 'object',
|
|
476
|
-
type,
|
|
477
|
-
get schema() {
|
|
478
|
-
return schema ??= subtype.getProperties().map(resolveNestedProperties).reduce(reducer, {});
|
|
479
|
-
},
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
else if (subtype.getCallSignatures().length === 1) {
|
|
483
|
-
return resolveCallbackSchema(subtype.getCallSignatures()[0]);
|
|
484
|
-
}
|
|
485
|
-
return type;
|
|
486
|
-
}
|
|
487
|
-
function getDeclarations(declaration) {
|
|
488
|
-
if (noDeclarations) {
|
|
489
|
-
return [];
|
|
490
|
-
}
|
|
491
|
-
return declaration.map(getDeclaration).filter(d => !!d);
|
|
492
|
-
}
|
|
493
|
-
function getDeclaration(declaration) {
|
|
494
|
-
const fileName = declaration.getSourceFile().fileName;
|
|
495
|
-
const [virtualFile] = core.virtualFiles.getVirtualFile(fileName);
|
|
496
|
-
if (virtualFile) {
|
|
497
|
-
const maps = core.virtualFiles.getMaps(virtualFile);
|
|
498
|
-
for (const [source, [_, map]] of maps) {
|
|
499
|
-
const start = map.toSourceOffset(declaration.getStart());
|
|
500
|
-
const end = map.toSourceOffset(declaration.getEnd());
|
|
501
|
-
if (start && end) {
|
|
502
|
-
return {
|
|
503
|
-
file: source,
|
|
504
|
-
range: [start[0], end[0]],
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
;
|
|
508
|
-
}
|
|
509
|
-
return undefined;
|
|
510
|
-
}
|
|
511
|
-
return {
|
|
512
|
-
file: declaration.getSourceFile().fileName,
|
|
513
|
-
range: [declaration.getStart(), declaration.getEnd()],
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
return {
|
|
517
|
-
resolveNestedProperties,
|
|
518
|
-
resolveSlotProperties,
|
|
519
|
-
resolveEventSignature,
|
|
520
|
-
resolveExposedProperties,
|
|
521
|
-
resolveSchema,
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
function readVueComponentDefaultProps(vueSourceFile, printer, ts, vueCompilerOptions) {
|
|
525
|
-
let result = {};
|
|
526
|
-
scriptSetupWorker();
|
|
527
|
-
scriptWorker();
|
|
528
|
-
return result;
|
|
529
|
-
function scriptSetupWorker() {
|
|
530
|
-
const descriptor = vueSourceFile.sfc;
|
|
531
|
-
const scriptSetupRanges = descriptor.scriptSetup ? vue.parseScriptSetupRanges(ts, descriptor.scriptSetup.ast, vueCompilerOptions) : undefined;
|
|
532
|
-
if (descriptor.scriptSetup && scriptSetupRanges?.props.withDefaults?.arg) {
|
|
533
|
-
const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.props.withDefaults.arg.start, scriptSetupRanges.props.withDefaults.arg.end);
|
|
534
|
-
const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
|
|
535
|
-
const obj = findObjectLiteralExpression(ast);
|
|
536
|
-
if (obj) {
|
|
537
|
-
for (const prop of obj.properties) {
|
|
538
|
-
if (ts.isPropertyAssignment(prop)) {
|
|
539
|
-
const name = prop.name.getText(ast);
|
|
540
|
-
const expNode = resolveDefaultOptionExpression(prop.initializer, ts);
|
|
541
|
-
const expText = printer?.printNode(ts.EmitHint.Expression, expNode, ast) ?? expNode.getText(ast);
|
|
542
|
-
result[name] = {
|
|
543
|
-
default: expText,
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
else if (descriptor.scriptSetup && scriptSetupRanges?.props.define?.arg) {
|
|
550
|
-
const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end);
|
|
551
|
-
const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
|
|
552
|
-
const obj = findObjectLiteralExpression(ast);
|
|
553
|
-
if (obj) {
|
|
554
|
-
result = {
|
|
555
|
-
...result,
|
|
556
|
-
...resolvePropsOption(ast, obj, printer, ts),
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
function findObjectLiteralExpression(node) {
|
|
561
|
-
if (ts.isObjectLiteralExpression(node)) {
|
|
562
|
-
return node;
|
|
563
|
-
}
|
|
564
|
-
let result;
|
|
565
|
-
node.forEachChild(child => {
|
|
566
|
-
if (!result) {
|
|
567
|
-
result = findObjectLiteralExpression(child);
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
return result;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
function scriptWorker() {
|
|
574
|
-
const descriptor = vueSourceFile.sfc;
|
|
575
|
-
if (descriptor.script) {
|
|
576
|
-
const scriptResult = readTsComponentDefaultProps(descriptor.script.lang, descriptor.script.content, 'default', printer, ts);
|
|
577
|
-
for (const [key, value] of Object.entries(scriptResult)) {
|
|
578
|
-
result[key] = value;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
function readTsComponentDefaultProps(lang, tsFileText, exportName, printer, ts) {
|
|
584
|
-
const ast = ts.createSourceFile('/tmp.' + lang, tsFileText, ts.ScriptTarget.Latest);
|
|
585
|
-
const props = getPropsNode();
|
|
586
|
-
if (props) {
|
|
587
|
-
return resolvePropsOption(ast, props, printer, ts);
|
|
588
|
-
}
|
|
589
|
-
return {};
|
|
590
|
-
function getComponentNode() {
|
|
591
|
-
let result;
|
|
592
|
-
if (exportName === 'default') {
|
|
593
|
-
ast.forEachChild(child => {
|
|
594
|
-
if (ts.isExportAssignment(child)) {
|
|
595
|
-
result = child.expression;
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
ast.forEachChild(child => {
|
|
601
|
-
if (ts.isVariableStatement(child)
|
|
602
|
-
&& child.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
603
|
-
for (const dec of child.declarationList.declarations) {
|
|
604
|
-
if (dec.name.getText(ast) === exportName) {
|
|
605
|
-
result = dec.initializer;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
});
|
|
610
|
-
}
|
|
611
|
-
return result;
|
|
612
|
-
}
|
|
613
|
-
function getComponentOptionsNode() {
|
|
614
|
-
const component = getComponentNode();
|
|
615
|
-
if (component) {
|
|
616
|
-
// export default { ... }
|
|
617
|
-
if (ts.isObjectLiteralExpression(component)) {
|
|
618
|
-
return component;
|
|
619
|
-
}
|
|
620
|
-
// export default defineComponent({ ... })
|
|
621
|
-
// export default Vue.extend({ ... })
|
|
622
|
-
else if (ts.isCallExpression(component)) {
|
|
623
|
-
if (component.arguments.length) {
|
|
624
|
-
const arg = component.arguments[0];
|
|
625
|
-
if (ts.isObjectLiteralExpression(arg)) {
|
|
626
|
-
return arg;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
function getPropsNode() {
|
|
633
|
-
const options = getComponentOptionsNode();
|
|
634
|
-
const props = options?.properties.find(prop => prop.name?.getText(ast) === 'props');
|
|
635
|
-
if (props && ts.isPropertyAssignment(props)) {
|
|
636
|
-
if (ts.isObjectLiteralExpression(props.initializer)) {
|
|
637
|
-
return props.initializer;
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
function resolvePropsOption(ast, props, printer, ts) {
|
|
643
|
-
const result = {};
|
|
644
|
-
for (const prop of props.properties) {
|
|
645
|
-
if (ts.isPropertyAssignment(prop)) {
|
|
646
|
-
const name = prop.name?.getText(ast);
|
|
647
|
-
if (ts.isObjectLiteralExpression(prop.initializer)) {
|
|
648
|
-
const defaultProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'default');
|
|
649
|
-
const requiredProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'required');
|
|
650
|
-
result[name] = {};
|
|
651
|
-
if (requiredProp) {
|
|
652
|
-
const exp = requiredProp.initializer.getText(ast);
|
|
653
|
-
result[name].required = exp === 'true';
|
|
654
|
-
}
|
|
655
|
-
if (defaultProp) {
|
|
656
|
-
const expNode = resolveDefaultOptionExpression(defaultProp.initializer, ts);
|
|
657
|
-
const expText = printer?.printNode(ts.EmitHint.Expression, expNode, ast) ?? expNode.getText(ast);
|
|
658
|
-
result[name].default = expText;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
return result;
|
|
664
|
-
}
|
|
665
|
-
function resolveDefaultOptionExpression(_default, ts) {
|
|
666
|
-
if (ts.isArrowFunction(_default)) {
|
|
667
|
-
if (ts.isBlock(_default.body)) {
|
|
668
|
-
return _default; // TODO
|
|
669
|
-
}
|
|
670
|
-
else if (ts.isParenthesizedExpression(_default.body)) {
|
|
671
|
-
return _default.body.expression;
|
|
672
|
-
}
|
|
673
|
-
else {
|
|
674
|
-
return _default.body;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
return _default;
|
|
24
|
+
exports.createCheckerByJson = createCheckerByJson;
|
|
25
|
+
function createChecker(tsconfig, checkerOptions = {}) {
|
|
26
|
+
return (0, base_1.createCheckerBase)(ts, tsconfig, checkerOptions);
|
|
678
27
|
}
|
|
28
|
+
exports.createChecker = createChecker;
|
|
679
29
|
//# sourceMappingURL=index.js.map
|