vue-component-meta 0.39.4 → 0.40.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/out/index.d.ts CHANGED
@@ -1,6 +1,12 @@
1
+ import * as ts from 'typescript/lib/tsserverlibrary';
1
2
  import type { MetaCheckerOptions, ComponentMeta, EventMeta, ExposeMeta, MetaCheckerSchemaOptions, PropertyMeta, PropertyMetaSchema, SlotMeta } from './types';
2
3
  export type { MetaCheckerOptions, ComponentMeta, EventMeta, ExposeMeta, MetaCheckerSchemaOptions, PropertyMeta, PropertyMetaSchema, SlotMeta };
3
4
  export declare function createComponentMetaChecker(tsconfigPath: string, checkerOptions?: MetaCheckerOptions): {
4
5
  getExportNames: (componentPath: string) => string[];
5
6
  getComponentMeta: (componentPath: string, exportName?: string) => ComponentMeta;
7
+ __internal__: {
8
+ program: ts.Program;
9
+ tsLs: ts.LanguageService;
10
+ typeChecker: ts.TypeChecker;
11
+ };
6
12
  };
package/out/index.js CHANGED
@@ -1,10 +1,10 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, "__esModule", { value: true });
3
2
  exports.createComponentMetaChecker = void 0;
4
3
  const vue = require("@volar/vue-language-core");
4
+ const vue_language_core_1 = require("@volar/vue-language-core");
5
5
  const ts = require("typescript/lib/tsserverlibrary");
6
6
  function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
7
- const parsedCommandLine = vue.tsShared.createParsedCommandLine(ts, {
7
+ const parsedCommandLine = vue.createParsedCommandLine(ts, {
8
8
  useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
9
9
  readDirectory: (path, extensions, exclude, include, depth) => {
10
10
  return ts.sys.readDirectory(path, [...extensions, '.vue'], exclude, include, depth);
@@ -70,6 +70,11 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
70
70
  return {
71
71
  getExportNames,
72
72
  getComponentMeta,
73
+ __internal__: {
74
+ program,
75
+ tsLs,
76
+ typeChecker,
77
+ },
73
78
  };
74
79
  function getMetaFileName(fileName) {
75
80
  return (fileName.endsWith('.vue') ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + '.meta.ts';
@@ -77,7 +82,7 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
77
82
  function getMetaScriptContent(fileName) {
78
83
  return `
79
84
  import * as Components from '${fileName.substring(0, fileName.length - '.meta.ts'.length)}';
80
- export default {} as { [K in keyof typeof Components]: InstanceType<typeof Components[K]>; };;
85
+ export default {} as { [K in keyof typeof Components]: InstanceType<typeof Components[K]>; };
81
86
  `;
82
87
  }
83
88
  function getExportNames(componentPath) {
@@ -92,7 +97,6 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
92
97
  }
93
98
  const componentType = typeChecker.getTypeOfSymbolAtLocation(_export, symbolNode);
94
99
  const symbolProperties = (_a = componentType.getProperties()) !== null && _a !== void 0 ? _a : [];
95
- const { resolveNestedProperties, resolveEventSignature, resolveExposedProperties, resolveSlotProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions.schema);
96
100
  return {
97
101
  props: getProps(),
98
102
  events: getEvents(),
@@ -105,9 +109,12 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
105
109
  let result = [];
106
110
  if ($props) {
107
111
  const type = typeChecker.getTypeOfSymbolAtLocation($props, symbolNode);
108
- const properties = type.getApparentProperties();
112
+ const properties = type.getProperties();
109
113
  result = properties
110
- .map(resolveNestedProperties)
114
+ .map((prop) => {
115
+ const { resolveNestedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
116
+ return resolveNestedProperties(prop);
117
+ })
111
118
  .filter((prop) => !prop.name.match(propEventRegex));
112
119
  }
113
120
  // fill global
@@ -115,15 +122,23 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
115
122
  prop.global = globalPropNames.includes(prop.name);
116
123
  }
117
124
  // fill defaults
118
- const printer = ts.createPrinter(checkerOptions.printer);
125
+ const printer = checkerOptions.printer ? ts.createPrinter(checkerOptions.printer) : undefined;
119
126
  const snapshot = host.getScriptSnapshot(componentPath);
120
- const vueDefaults = componentPath.endsWith('.vue') && exportName === 'default' ? readVueComponentDefaultProps(snapshot.getText(0, snapshot.getLength()), printer) : {};
127
+ const vueDefaults = componentPath.endsWith('.vue') && exportName === 'default'
128
+ ? readVueComponentDefaultProps(core, snapshot.getText(0, snapshot.getLength()), printer)
129
+ : {};
121
130
  const tsDefaults = !componentPath.endsWith('.vue') ? readTsComponentDefaultProps(componentPath.substring(componentPath.lastIndexOf('.') + 1), // ts | js | tsx | jsx
122
131
  snapshot.getText(0, snapshot.getLength()), exportName, printer) : {};
123
132
  for (const [propName, defaultExp] of Object.entries(Object.assign(Object.assign({}, vueDefaults), tsDefaults))) {
124
133
  const prop = result.find(p => p.name === propName);
125
134
  if (prop) {
126
- prop.default = defaultExp;
135
+ prop.default = defaultExp.default;
136
+ if (defaultExp.required !== undefined) {
137
+ prop.required = defaultExp.required;
138
+ }
139
+ if (prop.default !== undefined) {
140
+ prop.required = false; // props with default are always optional
141
+ }
127
142
  }
128
143
  }
129
144
  return result;
@@ -133,7 +148,10 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
133
148
  if ($emit) {
134
149
  const type = typeChecker.getTypeOfSymbolAtLocation($emit, symbolNode);
135
150
  const calls = type.getCallSignatures();
136
- return calls.map(resolveEventSignature).filter(event => event.name);
151
+ return calls.map((call) => {
152
+ const { resolveEventSignature, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
153
+ return resolveEventSignature(call);
154
+ }).filter(event => event.name);
137
155
  }
138
156
  return [];
139
157
  }
@@ -144,7 +162,10 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
144
162
  if ($slots) {
145
163
  const type = typeChecker.getTypeOfSymbolAtLocation($slots, symbolNode);
146
164
  const properties = type.getProperties();
147
- return properties.map(resolveSlotProperties);
165
+ return properties.map((prop) => {
166
+ const { resolveSlotProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
167
+ return resolveSlotProperties(prop);
168
+ });
148
169
  }
149
170
  return [];
150
171
  }
@@ -153,7 +174,10 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
153
174
  // only exposed props will have a syntheticOrigin
154
175
  Boolean(prop.syntheticOrigin));
155
176
  if (exposed.length) {
156
- return exposed.map(resolveExposedProperties);
177
+ return exposed.map((prop) => {
178
+ const { resolveExposedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
179
+ return resolveExposedProperties(prop);
180
+ });
157
181
  }
158
182
  return [];
159
183
  }
@@ -188,10 +212,10 @@ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
188
212
  }
189
213
  }
190
214
  exports.createComponentMetaChecker = createComponentMetaChecker;
191
- function createSchemaResolvers(typeChecker, symbolNode, options = false) {
215
+ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: options }) {
192
216
  var _a;
193
217
  const enabled = !!options;
194
- const ignore = typeof options === 'object' ? (_a = options.ignore) !== null && _a !== void 0 ? _a : [] : [];
218
+ const ignore = typeof options === 'object' ? [...(_a = options === null || options === void 0 ? void 0 : options.ignore) !== null && _a !== void 0 ? _a : []] : [];
195
219
  function shouldIgnore(subtype) {
196
220
  const type = typeChecker.typeToString(subtype);
197
221
  if (type === 'any') {
@@ -202,6 +226,10 @@ function createSchemaResolvers(typeChecker, symbolNode, options = false) {
202
226
  }
203
227
  return ignore.includes(type);
204
228
  }
229
+ function setVisited(subtype) {
230
+ const type = typeChecker.typeToString(subtype);
231
+ ignore.push(type);
232
+ }
205
233
  function reducer(acc, cur) {
206
234
  acc[cur.name] = cur;
207
235
  return acc;
@@ -223,6 +251,7 @@ function createSchemaResolvers(typeChecker, symbolNode, options = false) {
223
251
  }),
224
252
  required: !Boolean((_c = (_b = (_a = prop.declarations) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.questionToken) !== null && _c !== void 0 ? _c : false),
225
253
  type: typeChecker.typeToString(subtype),
254
+ rawType: rawType ? subtype : undefined,
226
255
  schema,
227
256
  };
228
257
  }
@@ -232,6 +261,7 @@ function createSchemaResolvers(typeChecker, symbolNode, options = false) {
232
261
  return {
233
262
  name: prop.getName(),
234
263
  type: typeChecker.typeToString(subtype),
264
+ rawType: rawType ? subtype : undefined,
235
265
  description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
236
266
  schema,
237
267
  };
@@ -242,6 +272,7 @@ function createSchemaResolvers(typeChecker, symbolNode, options = false) {
242
272
  return {
243
273
  name: expose.getName(),
244
274
  type: typeChecker.typeToString(subtype),
275
+ rawType: rawType ? subtype : undefined,
245
276
  description: ts.displayPartsToString(expose.getDocumentationComment(typeChecker)),
246
277
  schema,
247
278
  };
@@ -254,6 +285,7 @@ function createSchemaResolvers(typeChecker, symbolNode, options = false) {
254
285
  return {
255
286
  name: typeChecker.getTypeOfSymbolAtLocation(call.parameters[0], symbolNode).value,
256
287
  type: typeChecker.typeToString(subtype),
288
+ rawType: rawType ? subtype : undefined,
257
289
  signature: typeChecker.signatureToString(call),
258
290
  schema,
259
291
  };
@@ -270,69 +302,60 @@ function createSchemaResolvers(typeChecker, symbolNode, options = false) {
270
302
  schema,
271
303
  };
272
304
  }
273
- function resolveEventSchema(subtype) {
274
- return (subtype.getCallSignatures().length === 1)
275
- ? resolveCallbackSchema(subtype.getCallSignatures()[0])
276
- : typeChecker.typeToString(subtype);
277
- }
278
- function resolveNestedSchema(subtype) {
279
- if (subtype.getCallSignatures().length === 0 &&
280
- (subtype.isClassOrInterface() || subtype.isIntersection() || subtype.objectFlags & ts.ObjectFlags.Anonymous)) {
281
- if (shouldIgnore(subtype)) {
282
- return typeChecker.typeToString(subtype);
283
- }
284
- return {
285
- kind: 'object',
286
- type: typeChecker.typeToString(subtype),
287
- schema: subtype.getProperties().map(resolveNestedProperties).reduce(reducer, {})
305
+ function resolveSchema(subtype) {
306
+ const type = typeChecker.typeToString(subtype);
307
+ let schema = type;
308
+ if (shouldIgnore(subtype)) {
309
+ return type;
310
+ }
311
+ setVisited(subtype);
312
+ if (subtype.isUnion()) {
313
+ schema = {
314
+ kind: 'enum',
315
+ type,
316
+ schema: subtype.types.map(resolveSchema)
288
317
  };
289
318
  }
290
- return resolveEventSchema(subtype);
291
- }
292
- function resolveArraySchema(subtype) {
293
319
  // @ts-ignore - typescript internal, isArrayLikeType exists
294
- if (typeChecker.isArrayLikeType(subtype)) {
295
- if (shouldIgnore(subtype)) {
296
- return typeChecker.typeToString(subtype);
297
- }
298
- return {
320
+ else if (typeChecker.isArrayLikeType(subtype)) {
321
+ schema = {
299
322
  kind: 'array',
300
- type: typeChecker.typeToString(subtype),
323
+ type,
301
324
  schema: typeChecker.getTypeArguments(subtype).map(resolveSchema)
302
325
  };
303
326
  }
304
- return resolveNestedSchema(subtype);
305
- }
306
- function resolveSchema(subtype) {
307
- return subtype.isUnion()
308
- ? {
309
- kind: 'enum',
310
- type: typeChecker.typeToString(subtype),
311
- schema: subtype.types.map(resolveArraySchema)
312
- }
313
- : resolveArraySchema(subtype);
327
+ else if (subtype.getCallSignatures().length === 0 &&
328
+ (subtype.isClassOrInterface() || subtype.isIntersection() || subtype.objectFlags & ts.ObjectFlags.Anonymous)) {
329
+ // setVisited(subtype);
330
+ schema = {
331
+ kind: 'object',
332
+ type,
333
+ schema: subtype.getProperties().map(resolveNestedProperties).reduce(reducer, {})
334
+ };
335
+ }
336
+ else if (subtype.getCallSignatures().length === 1) {
337
+ schema = resolveCallbackSchema(subtype.getCallSignatures()[0]);
338
+ }
339
+ return schema;
314
340
  }
315
341
  return {
316
342
  resolveNestedProperties,
317
343
  resolveSlotProperties,
318
344
  resolveEventSignature,
319
345
  resolveExposedProperties,
320
- resolveCallbackSchema,
321
- resolveEventSchema,
322
- resolveNestedSchema,
323
- resolveArraySchema,
324
346
  resolveSchema,
325
347
  };
326
348
  }
327
- function readVueComponentDefaultProps(vueFileText, printer) {
328
- const result = {};
349
+ function readVueComponentDefaultProps(core, vueFileText, printer) {
350
+ let result = {};
329
351
  scriptSetupWorker();
330
- sciptWorker();
352
+ scriptWorker();
331
353
  return result;
332
354
  function scriptSetupWorker() {
333
- const vueSourceFile = vue.createSourceFile('/tmp.vue', vueFileText, {}, {}, ts);
334
- const descriptor = vueSourceFile.getDescriptor();
335
- const scriptSetupRanges = vueSourceFile.getScriptSetupRanges();
355
+ var _a;
356
+ const vueSourceFile = vue.createSourceFile('/tmp.vue', vueFileText, {}, ts, core.plugins);
357
+ const descriptor = vueSourceFile.sfc;
358
+ const scriptSetupRanges = descriptor.scriptSetupAst ? (0, vue_language_core_1.parseScriptSetupRanges)(ts, descriptor.scriptSetupAst) : undefined;
336
359
  if (descriptor.scriptSetup && (scriptSetupRanges === null || scriptSetupRanges === void 0 ? void 0 : scriptSetupRanges.withDefaultsArg)) {
337
360
  const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.withDefaultsArg.start, scriptSetupRanges.withDefaultsArg.end);
338
361
  const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
@@ -341,29 +364,39 @@ function readVueComponentDefaultProps(vueFileText, printer) {
341
364
  for (const prop of obj.properties) {
342
365
  if (ts.isPropertyAssignment(prop)) {
343
366
  const name = prop.name.getText(ast);
344
- const exp = printer.printNode(ts.EmitHint.Expression, resolveDefaultOptionExpression(prop.initializer), ast);
345
- ;
346
- result[name] = exp;
367
+ const expNode = resolveDefaultOptionExpression(prop.initializer);
368
+ const expText = (_a = printer === null || printer === void 0 ? void 0 : printer.printNode(ts.EmitHint.Expression, expNode, ast)) !== null && _a !== void 0 ? _a : expNode.getText(ast);
369
+ result[name] = {
370
+ default: expText,
371
+ };
347
372
  }
348
373
  }
349
374
  }
350
- function findObjectLiteralExpression(node) {
351
- if (ts.isObjectLiteralExpression(node)) {
352
- return node;
353
- }
354
- let result;
355
- node.forEachChild(child => {
356
- if (!result) {
357
- result = findObjectLiteralExpression(child);
358
- }
359
- });
360
- return result;
375
+ }
376
+ else if (descriptor.scriptSetup && (scriptSetupRanges === null || scriptSetupRanges === void 0 ? void 0 : scriptSetupRanges.propsRuntimeArg)) {
377
+ const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.propsRuntimeArg.start, scriptSetupRanges.propsRuntimeArg.end);
378
+ const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
379
+ const obj = findObjectLiteralExpression(ast);
380
+ if (obj) {
381
+ result = Object.assign(Object.assign({}, result), resolvePropsOption(ast, obj, printer));
361
382
  }
362
383
  }
384
+ function findObjectLiteralExpression(node) {
385
+ if (ts.isObjectLiteralExpression(node)) {
386
+ return node;
387
+ }
388
+ let result;
389
+ node.forEachChild(child => {
390
+ if (!result) {
391
+ result = findObjectLiteralExpression(child);
392
+ }
393
+ });
394
+ return result;
395
+ }
363
396
  }
364
- function sciptWorker() {
365
- const vueSourceFile = vue.createSourceFile('/tmp.vue', vueFileText, {}, {}, ts);
366
- const descriptor = vueSourceFile.getDescriptor();
397
+ function scriptWorker() {
398
+ const vueSourceFile = vue.createSourceFile('/tmp.vue', vueFileText, {}, ts, core.plugins);
399
+ const descriptor = vueSourceFile.sfc;
367
400
  if (descriptor.script) {
368
401
  const scriptResult = readTsComponentDefaultProps(descriptor.script.lang, descriptor.script.content, 'default', printer);
369
402
  for (const [key, value] of Object.entries(scriptResult)) {
@@ -373,28 +406,12 @@ function readVueComponentDefaultProps(vueFileText, printer) {
373
406
  }
374
407
  }
375
408
  function readTsComponentDefaultProps(lang, tsFileText, exportName, printer) {
376
- var _a, _b;
377
- const result = {};
378
409
  const ast = ts.createSourceFile('/tmp.' + lang, tsFileText, ts.ScriptTarget.Latest);
379
410
  const props = getPropsNode();
380
411
  if (props) {
381
- for (const prop of props.properties) {
382
- if (ts.isPropertyAssignment(prop)) {
383
- const name = (_a = prop.name) === null || _a === void 0 ? void 0 : _a.getText(ast);
384
- if (ts.isObjectLiteralExpression(prop.initializer)) {
385
- for (const propOption of prop.initializer.properties) {
386
- if (ts.isPropertyAssignment(propOption)) {
387
- if (((_b = propOption.name) === null || _b === void 0 ? void 0 : _b.getText(ast)) === 'default') {
388
- const _default = propOption.initializer;
389
- result[name] = printer.printNode(ts.EmitHint.Expression, resolveDefaultOptionExpression(_default), ast);
390
- }
391
- }
392
- }
393
- }
394
- }
395
- }
412
+ return resolvePropsOption(ast, props, printer);
396
413
  }
397
- return result;
414
+ return {};
398
415
  function getComponentNode() {
399
416
  let result;
400
417
  if (exportName === 'default') {
@@ -448,6 +465,30 @@ function readTsComponentDefaultProps(lang, tsFileText, exportName, printer) {
448
465
  }
449
466
  }
450
467
  }
468
+ function resolvePropsOption(ast, props, printer) {
469
+ var _a, _b;
470
+ const result = {};
471
+ for (const prop of props.properties) {
472
+ if (ts.isPropertyAssignment(prop)) {
473
+ const name = (_a = prop.name) === null || _a === void 0 ? void 0 : _a.getText(ast);
474
+ if (ts.isObjectLiteralExpression(prop.initializer)) {
475
+ const defaultProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'default');
476
+ const requiredProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'required');
477
+ result[name] = {};
478
+ if (requiredProp) {
479
+ const exp = requiredProp.initializer.getText(ast);
480
+ result[name].required = exp === 'true';
481
+ }
482
+ if (defaultProp) {
483
+ const expNode = resolveDefaultOptionExpression(defaultProp.initializer);
484
+ const expText = (_b = printer === null || printer === void 0 ? void 0 : printer.printNode(ts.EmitHint.Expression, expNode, ast)) !== null && _b !== void 0 ? _b : expNode.getText(ast);
485
+ result[name].default = expText;
486
+ }
487
+ }
488
+ }
489
+ }
490
+ return result;
491
+ }
451
492
  function resolveDefaultOptionExpression(_default) {
452
493
  if (ts.isArrowFunction(_default)) {
453
494
  if (ts.isBlock(_default.body)) {
package/out/types.d.ts CHANGED
@@ -11,6 +11,7 @@ export interface PropertyMeta {
11
11
  global: boolean;
12
12
  required: boolean;
13
13
  type: string;
14
+ rawType?: ts.Type;
14
15
  tags: {
15
16
  name: string;
16
17
  text?: string;
@@ -20,12 +21,14 @@ export interface PropertyMeta {
20
21
  export interface EventMeta {
21
22
  name: string;
22
23
  type: string;
24
+ rawType?: ts.Type;
23
25
  signature: string;
24
26
  schema?: PropertyMetaSchema[];
25
27
  }
26
28
  export interface SlotMeta {
27
29
  name: string;
28
30
  type: string;
31
+ rawType?: ts.Type;
29
32
  description: string;
30
33
  schema?: PropertyMetaSchema;
31
34
  }
@@ -33,6 +36,7 @@ export interface ExposeMeta {
33
36
  name: string;
34
37
  description: string;
35
38
  type: string;
39
+ rawType?: ts.Type;
36
40
  schema?: PropertyMetaSchema;
37
41
  }
38
42
  export declare type PropertyMetaSchema = string | {
@@ -59,4 +63,5 @@ export interface MetaCheckerOptions {
59
63
  schema?: MetaCheckerSchemaOptions;
60
64
  forceUseTs?: boolean;
61
65
  printer?: import('typescript').PrinterOptions;
66
+ rawType?: boolean;
62
67
  }
package/out/types.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, "__esModule", { value: true });
3
2
  ;
4
3
  //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-component-meta",
3
- "version": "0.39.4",
3
+ "version": "0.40.1",
4
4
  "main": "out/index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -13,10 +13,10 @@
13
13
  "directory": "packages/vue-component-meta"
14
14
  },
15
15
  "dependencies": {
16
- "@volar/vue-language-core": "0.39.4"
16
+ "@volar/vue-language-core": "0.40.1"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "typescript": "*"
20
20
  },
21
- "gitHead": "e3f6327b11a0a41c1b448c2ecc25ba85b9986dee"
21
+ "gitHead": "4f92ef83a905c6d46cc92653ad87e0aec10f4e53"
22
22
  }