@next-core/build-next-bricks 1.10.0 → 1.11.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/package.json +3 -3
- package/src/getTypeDeclaration.js +400 -0
- package/src/makeBrickManifest.js +259 -46
- package/src/scanBricks.js +136 -110
- package/src/utils.js +0 -227
package/src/makeBrickManifest.js
CHANGED
|
@@ -1,35 +1,67 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import { parse } from "doctrine";
|
|
2
|
-
import { getTypeAnnotation } from "./
|
|
3
|
+
import { getTypeAnnotation } from "./getTypeDeclaration.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* @typedef {import("@next-core/brick-manifest").BrickManifest} BrickManifest
|
|
6
7
|
* @typedef {import("@next-core/brick-manifest").PropertyManifest} PropertyManifest
|
|
7
8
|
* @typedef {import("@next-core/brick-manifest").EventManifest} EventManifest
|
|
8
9
|
* @typedef {import("@next-core/brick-manifest").MethodManifest} MethodManifest
|
|
10
|
+
* @typedef {import("@next-core/brick-manifest").MethodParamManifest} MethodParamManifest
|
|
9
11
|
* @typedef {import("@next-core/brick-manifest").ProviderManifest} ProviderManifest
|
|
12
|
+
* @typedef {import("@next-core/brick-manifest").Annotation} Annotation
|
|
10
13
|
* @typedef {import("@babel/types").Node} Node
|
|
11
14
|
* @typedef {import("@babel/traverse").NodePath} NodePath
|
|
12
15
|
* @typedef {import("@babel/types").ClassDeclaration} ClassDeclaration
|
|
16
|
+
* @typedef {import("@babel/types").Identifier} Identifier
|
|
13
17
|
* @typedef {import("doctrine").Tag} Tag
|
|
18
|
+
* @typedef {BrickManifest & { types: BrickTypes; }} BrickManifestAndTypes
|
|
19
|
+
* @typedef {{ name: string; annotation?: Annotation }} BrickPropertyWithAnnotation
|
|
20
|
+
* @typedef {{ name: string; detail: { annotation: Annotation } }} BrickEventWithAnnotation
|
|
21
|
+
* @typedef {{ name: string; params: BrickMethodParamWithAnnotation[]; returns: { annotation?: Annotation } }} BrickMethodWithAnnotation
|
|
22
|
+
* @typedef {{ name: string; annotation?: Annotation }} BrickMethodParamWithAnnotation
|
|
23
|
+
* @typedef {{
|
|
24
|
+
* properties: BrickPropertyWithAnnotation[];
|
|
25
|
+
* events: BrickEventWithAnnotation[];
|
|
26
|
+
* methods: BrickMethodWithAnnotation[];
|
|
27
|
+
* usedReferences?: Set<string>;
|
|
28
|
+
* }} BrickTypes
|
|
29
|
+
* @typedef {ProviderManifest & {
|
|
30
|
+
* params: (MethodParamManifest & {
|
|
31
|
+
* annotation?: Annotation;
|
|
32
|
+
* })[];
|
|
33
|
+
* returns?: {
|
|
34
|
+
* description?: string;
|
|
35
|
+
* annotation?: Annotation;
|
|
36
|
+
* };
|
|
37
|
+
* typeParameters?: Annotation;
|
|
38
|
+
* usedReferences?: Set<string>;
|
|
39
|
+
* }} ProviderManifestAndTypes
|
|
14
40
|
*/
|
|
15
41
|
|
|
16
42
|
/**
|
|
17
43
|
* @param {string} name
|
|
18
44
|
* @param {NodePath} nodePath
|
|
19
|
-
* @param {string} source
|
|
20
|
-
* @
|
|
21
|
-
* @returns {BrickManifest}
|
|
45
|
+
* @param {string} source
|
|
46
|
+
* @returns {BrickManifestAndTypes}
|
|
22
47
|
*/
|
|
23
48
|
export default function makeBrickManifest(name, nodePath, source) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
49
|
+
const classPath =
|
|
50
|
+
/** @type {import("@babel/traverse").NodePath<ClassDeclaration>} */ (
|
|
51
|
+
nodePath.parentPath
|
|
52
|
+
);
|
|
53
|
+
/** @type {BrickManifestAndTypes} */
|
|
27
54
|
const manifest = {
|
|
28
55
|
name,
|
|
29
56
|
properties: [],
|
|
30
57
|
events: [],
|
|
31
58
|
slots: [],
|
|
32
59
|
methods: [],
|
|
60
|
+
types: {
|
|
61
|
+
properties: [],
|
|
62
|
+
events: [],
|
|
63
|
+
methods: [],
|
|
64
|
+
},
|
|
33
65
|
};
|
|
34
66
|
|
|
35
67
|
const docComment = findDocComment(nodePath, source);
|
|
@@ -52,7 +84,11 @@ export default function makeBrickManifest(name, nodePath, source) {
|
|
|
52
84
|
}
|
|
53
85
|
}
|
|
54
86
|
|
|
55
|
-
|
|
87
|
+
manifest.types.usedReferences = scanFields(
|
|
88
|
+
manifest,
|
|
89
|
+
classPath.node.body.body,
|
|
90
|
+
source
|
|
91
|
+
);
|
|
56
92
|
|
|
57
93
|
return manifest;
|
|
58
94
|
}
|
|
@@ -61,18 +97,74 @@ export default function makeBrickManifest(name, nodePath, source) {
|
|
|
61
97
|
* @param {string} name
|
|
62
98
|
* @param {NodePath} nodePath
|
|
63
99
|
* @param {string} source
|
|
64
|
-
* @returns {
|
|
100
|
+
* @returns {ProviderManifestAndTypes}
|
|
65
101
|
*/
|
|
66
102
|
export function makeProviderManifest(name, nodePath, source) {
|
|
67
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* @type {ProviderManifestAndTypes}
|
|
105
|
+
*/
|
|
68
106
|
const manifest = {
|
|
69
107
|
name,
|
|
108
|
+
type: "provider",
|
|
109
|
+
params: [],
|
|
110
|
+
usedReferences: new Set(),
|
|
70
111
|
};
|
|
112
|
+
|
|
71
113
|
const docComment = findDocComment(nodePath, source);
|
|
72
114
|
if (docComment) {
|
|
73
115
|
manifest.description = docComment.description;
|
|
74
116
|
manifest.deprecated = getDeprecatedInfo(docComment.tags);
|
|
75
117
|
}
|
|
118
|
+
|
|
119
|
+
const fn = /** @type {import("@babel/types").FunctionDeclaration} */ (
|
|
120
|
+
nodePath.node
|
|
121
|
+
);
|
|
122
|
+
let index = 0;
|
|
123
|
+
for (const param of fn.params) {
|
|
124
|
+
const annotation = getTypeAnnotation(
|
|
125
|
+
param.typeAnnotation,
|
|
126
|
+
source,
|
|
127
|
+
manifest.usedReferences
|
|
128
|
+
);
|
|
129
|
+
if (param.type === "Identifier") {
|
|
130
|
+
manifest.params.push({
|
|
131
|
+
name: param.name,
|
|
132
|
+
description: docComment?.tags.find(
|
|
133
|
+
(tag) => tag.title === "param" && tag.name === param.name
|
|
134
|
+
)?.description,
|
|
135
|
+
annotation,
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
const paramTag = docComment?.tags.filter(
|
|
139
|
+
(tag) => tag.title === "param"
|
|
140
|
+
)?.[index];
|
|
141
|
+
manifest.params.push({
|
|
142
|
+
name: paramTag?.name ?? `param_${index + 1}`,
|
|
143
|
+
description: paramTag?.description,
|
|
144
|
+
isRestElement: param.type === "RestElement",
|
|
145
|
+
annotation,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
index++;
|
|
149
|
+
}
|
|
150
|
+
const returnAnnotation = getTypeAnnotation(
|
|
151
|
+
fn.returnType,
|
|
152
|
+
source,
|
|
153
|
+
manifest.usedReferences
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
manifest.returns = {
|
|
157
|
+
description: docComment?.tags.find((tag) => tag.title === "returns")
|
|
158
|
+
?.description,
|
|
159
|
+
annotation: returnAnnotation,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
manifest.typeParameters = getTypeAnnotation(
|
|
163
|
+
fn.typeParameters,
|
|
164
|
+
source,
|
|
165
|
+
manifest.usedReferences
|
|
166
|
+
);
|
|
167
|
+
|
|
76
168
|
return manifest;
|
|
77
169
|
}
|
|
78
170
|
|
|
@@ -93,12 +185,14 @@ function findDocComment({ node, parentPath }, source) {
|
|
|
93
185
|
}
|
|
94
186
|
|
|
95
187
|
/**
|
|
96
|
-
* @param {
|
|
188
|
+
* @param {BrickManifestAndTypes} manifest
|
|
97
189
|
* @param {Node[]} nodes
|
|
98
190
|
* @param {string} source
|
|
99
|
-
* @
|
|
191
|
+
* @returns {Set<string>}
|
|
100
192
|
*/
|
|
101
|
-
function scanFields(manifest, nodes, source
|
|
193
|
+
function scanFields(manifest, nodes, source) {
|
|
194
|
+
/** @type {Set<string>} */
|
|
195
|
+
const usedReferences = new Set();
|
|
102
196
|
for (const node of nodes) {
|
|
103
197
|
if (node.type === "ClassAccessorProperty" && node.decorators?.length) {
|
|
104
198
|
for (const { expression } of node.decorators) {
|
|
@@ -110,7 +204,7 @@ function scanFields(manifest, nodes, source, referenceSet = new Set()) {
|
|
|
110
204
|
case "property": {
|
|
111
205
|
/** @type {PropertyManifest} */
|
|
112
206
|
const prop = {
|
|
113
|
-
name: node.key.name,
|
|
207
|
+
name: /** @type {Identifier} */ (node.key).name,
|
|
114
208
|
};
|
|
115
209
|
const docComment = parseDocComment(node, source);
|
|
116
210
|
if (docComment) {
|
|
@@ -148,12 +242,41 @@ function scanFields(manifest, nodes, source, referenceSet = new Set()) {
|
|
|
148
242
|
) {
|
|
149
243
|
const { typeAnnotation } = node.typeAnnotation;
|
|
150
244
|
prop.type = getTypeWithoutUndefined(typeAnnotation, source);
|
|
151
|
-
|
|
152
|
-
|
|
245
|
+
|
|
246
|
+
const annotation = getTypeAnnotation(
|
|
247
|
+
getNodeWithoutUndefined(typeAnnotation),
|
|
153
248
|
source,
|
|
154
|
-
|
|
249
|
+
usedReferences
|
|
155
250
|
);
|
|
156
|
-
|
|
251
|
+
if (annotation) {
|
|
252
|
+
manifest.types.properties.push({
|
|
253
|
+
name: prop.name,
|
|
254
|
+
annotation,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
} else if (node.value) {
|
|
258
|
+
// Infer type annotation from the default value.
|
|
259
|
+
let inferType;
|
|
260
|
+
switch (node.value.type) {
|
|
261
|
+
case "BooleanLiteral":
|
|
262
|
+
inferType = "boolean";
|
|
263
|
+
break;
|
|
264
|
+
case "StringLiteral":
|
|
265
|
+
inferType = "string";
|
|
266
|
+
break;
|
|
267
|
+
case "NumericLiteral":
|
|
268
|
+
inferType = "number";
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
if (inferType) {
|
|
272
|
+
manifest.types.properties.push({
|
|
273
|
+
name: prop.name,
|
|
274
|
+
annotation: {
|
|
275
|
+
type: "keyword",
|
|
276
|
+
value: inferType,
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
}
|
|
157
280
|
}
|
|
158
281
|
if (node.value && !prop.default) {
|
|
159
282
|
prop.default = source.substring(
|
|
@@ -167,7 +290,7 @@ function scanFields(manifest, nodes, source, referenceSet = new Set()) {
|
|
|
167
290
|
|
|
168
291
|
case "event": {
|
|
169
292
|
/** @type {EventManifest} */
|
|
170
|
-
const event = {};
|
|
293
|
+
const event = { name: undefined };
|
|
171
294
|
|
|
172
295
|
// Find out the `type` option for the event.
|
|
173
296
|
if (expression.arguments.length > 0) {
|
|
@@ -190,7 +313,9 @@ function scanFields(manifest, nodes, source, referenceSet = new Set()) {
|
|
|
190
313
|
}
|
|
191
314
|
if (event.name === undefined) {
|
|
192
315
|
throw new Error(
|
|
193
|
-
`Invalid @event() call: no literal type option in event '${
|
|
316
|
+
`Invalid @event() call: no literal type option in event '${
|
|
317
|
+
/** @type {Identifier} */ (node.key).name
|
|
318
|
+
}'`
|
|
194
319
|
);
|
|
195
320
|
}
|
|
196
321
|
const docComment = parseDocComment(node, source);
|
|
@@ -218,12 +343,21 @@ function scanFields(manifest, nodes, source, referenceSet = new Set()) {
|
|
|
218
343
|
const param = typeAnnotation.typeParameters.params[0];
|
|
219
344
|
event.detail ??= {};
|
|
220
345
|
event.detail.type = source.substring(param.start, param.end);
|
|
221
|
-
|
|
346
|
+
|
|
347
|
+
const annotation = getTypeAnnotation(
|
|
222
348
|
param,
|
|
223
349
|
source,
|
|
224
|
-
|
|
350
|
+
usedReferences
|
|
225
351
|
);
|
|
226
|
-
|
|
352
|
+
|
|
353
|
+
if (annotation) {
|
|
354
|
+
manifest.types.events.push({
|
|
355
|
+
name: event.name,
|
|
356
|
+
detail: {
|
|
357
|
+
annotation,
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
}
|
|
227
361
|
}
|
|
228
362
|
}
|
|
229
363
|
manifest.events.push(event);
|
|
@@ -241,40 +375,99 @@ function scanFields(manifest, nodes, source, referenceSet = new Set()) {
|
|
|
241
375
|
) {
|
|
242
376
|
/** @type {MethodManifest} */
|
|
243
377
|
const method = {
|
|
244
|
-
name: node.key.name,
|
|
378
|
+
name: /** @type {Identifier} */ (node.key).name,
|
|
245
379
|
params: [],
|
|
246
380
|
};
|
|
247
381
|
const docComment = parseDocComment(node, source);
|
|
248
382
|
if (docComment) {
|
|
249
383
|
method.description = docComment.description;
|
|
250
384
|
method.deprecated = getDeprecatedInfo(docComment.tags);
|
|
385
|
+
method.returns = {
|
|
386
|
+
description: docComment.tags.find(
|
|
387
|
+
(tag) => tag.title === "returns"
|
|
388
|
+
)?.description,
|
|
389
|
+
};
|
|
251
390
|
}
|
|
391
|
+
|
|
392
|
+
let index = 0;
|
|
393
|
+
/** @type {BrickMethodParamWithAnnotation[]} */
|
|
394
|
+
const typedParams = [];
|
|
252
395
|
for (const param of node.params) {
|
|
253
|
-
|
|
396
|
+
const typeAnnotation =
|
|
397
|
+
/** @type {Identifier} */
|
|
398
|
+
(param).typeAnnotation;
|
|
399
|
+
const annotation = getTypeAnnotation(
|
|
400
|
+
typeAnnotation,
|
|
401
|
+
source,
|
|
402
|
+
usedReferences
|
|
403
|
+
);
|
|
404
|
+
const paramType =
|
|
405
|
+
typeAnnotation.type === "TSTypeAnnotation"
|
|
406
|
+
? source.substring(
|
|
407
|
+
typeAnnotation.typeAnnotation.start,
|
|
408
|
+
typeAnnotation.typeAnnotation.end
|
|
409
|
+
)
|
|
410
|
+
: undefined;
|
|
411
|
+
/** @type {string} */
|
|
412
|
+
let paramName;
|
|
413
|
+
if (param.type === "Identifier") {
|
|
414
|
+
paramName = param.name;
|
|
415
|
+
method.params.push({
|
|
416
|
+
name: paramName,
|
|
417
|
+
description: docComment?.tags.find(
|
|
418
|
+
(tag) => tag.title === "param" && tag.name === param.name
|
|
419
|
+
)?.description,
|
|
420
|
+
type: paramType,
|
|
421
|
+
});
|
|
422
|
+
} else {
|
|
423
|
+
const paramTag = docComment?.tags.filter(
|
|
424
|
+
(tag) => tag.title === "param"
|
|
425
|
+
)?.[index];
|
|
426
|
+
paramName = paramTag?.name ?? `param_${index + 1}`;
|
|
427
|
+
method.params.push({
|
|
428
|
+
name: paramName,
|
|
429
|
+
description: paramTag?.description,
|
|
430
|
+
type: paramType,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
typedParams.push({
|
|
434
|
+
name: paramName,
|
|
435
|
+
annotation,
|
|
436
|
+
});
|
|
437
|
+
index++;
|
|
254
438
|
}
|
|
439
|
+
|
|
440
|
+
/** @type {{ annotation?: Annotation }} */
|
|
441
|
+
const typedReturns = {};
|
|
255
442
|
if (node.returnType && node.returnType.type === "TSTypeAnnotation") {
|
|
256
443
|
const { typeAnnotation } = node.returnType;
|
|
257
|
-
method.
|
|
258
|
-
|
|
259
|
-
typeAnnotation.start,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
444
|
+
method.returns = {
|
|
445
|
+
...method.returns,
|
|
446
|
+
type: source.substring(typeAnnotation.start, typeAnnotation.end),
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
typedReturns.annotation = getTypeAnnotation(
|
|
263
450
|
typeAnnotation,
|
|
264
451
|
source,
|
|
265
|
-
|
|
452
|
+
usedReferences
|
|
266
453
|
);
|
|
267
|
-
method.return.reference = [...referenceSet];
|
|
268
454
|
}
|
|
455
|
+
manifest.types.methods.push({
|
|
456
|
+
name: method.name,
|
|
457
|
+
params: typedParams,
|
|
458
|
+
returns: typedReturns,
|
|
459
|
+
});
|
|
269
460
|
manifest.methods.push(method);
|
|
270
461
|
}
|
|
271
462
|
}
|
|
272
463
|
}
|
|
273
464
|
}
|
|
465
|
+
|
|
466
|
+
return usedReferences;
|
|
274
467
|
}
|
|
275
468
|
|
|
276
469
|
/**
|
|
277
|
-
* @param {Node
|
|
470
|
+
* @param {Node} node
|
|
278
471
|
* @param {string} source
|
|
279
472
|
*/
|
|
280
473
|
export function parseDocComment(node, source) {
|
|
@@ -290,6 +483,21 @@ export function parseDocComment(node, source) {
|
|
|
290
483
|
}
|
|
291
484
|
}
|
|
292
485
|
|
|
486
|
+
/**
|
|
487
|
+
* @param {Node} node
|
|
488
|
+
* @param {string} source
|
|
489
|
+
* @returns {undefined | { description?: string; deprecated?: boolean | string; }}
|
|
490
|
+
*/
|
|
491
|
+
export function parseTypeComment(node, source) {
|
|
492
|
+
const docComment = parseDocComment(node, source);
|
|
493
|
+
if (docComment) {
|
|
494
|
+
return {
|
|
495
|
+
description: docComment.description,
|
|
496
|
+
deprecated: getDeprecatedInfo(docComment.tags),
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
293
501
|
/**
|
|
294
502
|
* @param {Node} node
|
|
295
503
|
* @param {string} source
|
|
@@ -309,20 +517,25 @@ function getTypeWithoutUndefined(node, source) {
|
|
|
309
517
|
}
|
|
310
518
|
|
|
311
519
|
/**
|
|
312
|
-
* @param {
|
|
313
|
-
* @
|
|
314
|
-
* @param {Set<string} set
|
|
520
|
+
* @param {Node} node
|
|
521
|
+
* @returns {Node}
|
|
315
522
|
*/
|
|
316
|
-
function
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
type
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
523
|
+
function getNodeWithoutUndefined(node) {
|
|
524
|
+
if (node.type === "TSUnionType") {
|
|
525
|
+
const filteredTypes = node.types.filter(
|
|
526
|
+
(type) => type.type !== "TSUndefinedKeyword"
|
|
527
|
+
);
|
|
528
|
+
if (filteredTypes.length < node.types.length) {
|
|
529
|
+
if (filteredTypes.length === 1) {
|
|
530
|
+
return filteredTypes[0];
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
...node,
|
|
534
|
+
types: filteredTypes,
|
|
535
|
+
};
|
|
536
|
+
}
|
|
324
537
|
}
|
|
325
|
-
return
|
|
538
|
+
return node;
|
|
326
539
|
}
|
|
327
540
|
|
|
328
541
|
/**
|