@next-core/build-next-bricks 1.7.2 → 1.9.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/bin/build-next-bricks.js +4 -0
- package/package.json +3 -3
- package/src/EmitBricksJsonPlugin.js +7 -0
- package/src/build.js +3 -0
- package/src/makeBrickManifest.js +22 -1
- package/src/scanBricks.js +213 -4
- package/src/utils.js +227 -0
package/bin/build-next-bricks.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@next-core/build-next-bricks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "Build next bricks",
|
|
5
5
|
"homepage": "https://github.com/easyops-cn/next-core/tree/v3/packages/build-next-bricks",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"webpack": "^5.84.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@next-core/brick-manifest": "^0.
|
|
52
|
+
"@next-core/brick-manifest": "^0.2.0"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "618559c95f5a1ef0eaf4d2792b530deaf933d45d"
|
|
55
55
|
}
|
|
@@ -17,6 +17,7 @@ export default class EmitBricksJsonPlugin {
|
|
|
17
17
|
this.processors = options.processors;
|
|
18
18
|
this.dependencies = options.dependencies;
|
|
19
19
|
this.manifest = options.manifest;
|
|
20
|
+
this.types = options.types;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -71,6 +72,12 @@ export default class EmitBricksJsonPlugin {
|
|
|
71
72
|
new webpack.sources.RawSource(manifestJson, false)
|
|
72
73
|
);
|
|
73
74
|
|
|
75
|
+
const typesJson = JSON.stringify(this.types, null, 2);
|
|
76
|
+
compilation.emitAsset(
|
|
77
|
+
"types.json",
|
|
78
|
+
new webpack.sources.RawSource(typesJson, false)
|
|
79
|
+
);
|
|
80
|
+
|
|
74
81
|
console.log("Defined bricks:", this.bricks);
|
|
75
82
|
console.log("Defined elements:", this.elements);
|
|
76
83
|
console.log("Defined processors:", this.processors);
|
package/src/build.js
CHANGED
|
@@ -81,6 +81,8 @@ async function getWebpackConfig(config) {
|
|
|
81
81
|
"js-yaml",
|
|
82
82
|
"i18next-browser-languagedetector",
|
|
83
83
|
"react-i18next",
|
|
84
|
+
"@easyops-cn/brick-next-pipes",
|
|
85
|
+
"@next-core/pipes",
|
|
84
86
|
"@next-core/runtime",
|
|
85
87
|
"@next-core/easyops-runtime",
|
|
86
88
|
"@next-core/http",
|
|
@@ -366,6 +368,7 @@ async function getWebpackConfig(config) {
|
|
|
366
368
|
processors,
|
|
367
369
|
dependencies: config.dependencies,
|
|
368
370
|
manifest: config.manifest,
|
|
371
|
+
types: config.types,
|
|
369
372
|
}),
|
|
370
373
|
]
|
|
371
374
|
: []),
|
package/src/makeBrickManifest.js
CHANGED
|
@@ -5,6 +5,7 @@ import { parse } from "doctrine";
|
|
|
5
5
|
* @typedef {import("@next-core/brick-manifest").PropertyManifest} PropertyManifest
|
|
6
6
|
* @typedef {import("@next-core/brick-manifest").EventManifest} EventManifest
|
|
7
7
|
* @typedef {import("@next-core/brick-manifest").MethodManifest} MethodManifest
|
|
8
|
+
* @typedef {import("@next-core/brick-manifest").ProviderManifest} ProviderManifest
|
|
8
9
|
* @typedef {import("@babel/types").Node} Node
|
|
9
10
|
* @typedef {import("@babel/traverse").NodePath} NodePath
|
|
10
11
|
* @typedef {import("@babel/types").ClassDeclaration} ClassDeclaration
|
|
@@ -32,6 +33,7 @@ export default function makeBrickManifest(name, nodePath, source) {
|
|
|
32
33
|
const docComment = findDocComment(nodePath, source);
|
|
33
34
|
if (docComment) {
|
|
34
35
|
manifest.description = docComment.description;
|
|
36
|
+
manifest.deprecated = getDeprecatedInfo(docComment.tags);
|
|
35
37
|
for (const tag of docComment.tags) {
|
|
36
38
|
if (tag.title === "slot") {
|
|
37
39
|
const match = tag.description.match(/^(?:([-\w]+)\s+-\s+)?(.*)$/);
|
|
@@ -53,6 +55,25 @@ export default function makeBrickManifest(name, nodePath, source) {
|
|
|
53
55
|
return manifest;
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @param {string} name
|
|
60
|
+
* @param {NodePath} nodePath
|
|
61
|
+
* @param {string} source
|
|
62
|
+
* @returns {ProviderManifest}
|
|
63
|
+
*/
|
|
64
|
+
export function makeProviderManifest(name, nodePath, source) {
|
|
65
|
+
/** @type {ProviderManifest} */
|
|
66
|
+
const manifest = {
|
|
67
|
+
name,
|
|
68
|
+
};
|
|
69
|
+
const docComment = findDocComment(nodePath, source);
|
|
70
|
+
if (docComment) {
|
|
71
|
+
manifest.description = docComment.description;
|
|
72
|
+
manifest.deprecated = getDeprecatedInfo(docComment.tags);
|
|
73
|
+
}
|
|
74
|
+
return manifest;
|
|
75
|
+
}
|
|
76
|
+
|
|
56
77
|
/**
|
|
57
78
|
* @param {NodePath} nodePath
|
|
58
79
|
* @param {string} source
|
|
@@ -235,7 +256,7 @@ function scanFields(manifest, nodes, source) {
|
|
|
235
256
|
* @param {Node[]} nodes
|
|
236
257
|
* @param {string} source
|
|
237
258
|
*/
|
|
238
|
-
function parseDocComment(node, source) {
|
|
259
|
+
export function parseDocComment(node, source) {
|
|
239
260
|
if (node.leadingComments) {
|
|
240
261
|
const docComment = node.leadingComments.find(
|
|
241
262
|
(comment) => comment.type === "CommentBlock"
|
package/src/scanBricks.js
CHANGED
|
@@ -5,7 +5,15 @@ import { parse } from "@babel/parser";
|
|
|
5
5
|
import babelTraverse from "@babel/traverse";
|
|
6
6
|
import _ from "lodash";
|
|
7
7
|
import getCamelPackageName from "./getCamelPackageName.js";
|
|
8
|
-
import makeBrickManifest
|
|
8
|
+
import makeBrickManifest, {
|
|
9
|
+
makeProviderManifest,
|
|
10
|
+
} from "./makeBrickManifest.js";
|
|
11
|
+
import { BASE_TYPE, TS_KEYWORD_LIST, getTypeAnnotation } from "./utils.js";
|
|
12
|
+
import {
|
|
13
|
+
isImportDefaultSpecifier,
|
|
14
|
+
isImportDeclaration,
|
|
15
|
+
isImportSpecifier,
|
|
16
|
+
} from "@babel/types";
|
|
9
17
|
|
|
10
18
|
/**
|
|
11
19
|
* @typedef {import("@next-core/brick-manifest").PackageManifest} PackageManifest
|
|
@@ -26,7 +34,7 @@ const validExposeName = /^[-\w]+$/;
|
|
|
26
34
|
* Scan defined bricks by AST.
|
|
27
35
|
*
|
|
28
36
|
* @param {string} packageDir
|
|
29
|
-
* @returns {Promise<{exposes: Exposes; dependencies: Record<string, string[]>; manifest: PackageManifest}>}
|
|
37
|
+
* @returns {Promise<{exposes: Exposes; dependencies: Record<string, string[]>; manifest: PackageManifest; types: Record<string, unknown>}>}
|
|
30
38
|
*/
|
|
31
39
|
export default async function scanBricks(packageDir) {
|
|
32
40
|
/** @type {Map<string, Expose>} */
|
|
@@ -51,6 +59,7 @@ export default async function scanBricks(packageDir) {
|
|
|
51
59
|
package: packageJson.name,
|
|
52
60
|
name: packageName,
|
|
53
61
|
bricks: [],
|
|
62
|
+
providers: [],
|
|
54
63
|
};
|
|
55
64
|
|
|
56
65
|
/** @type {Map<string, Set<string>} */
|
|
@@ -62,6 +71,10 @@ export default async function scanBricks(packageDir) {
|
|
|
62
71
|
/** @type {Map<string, Set<string>} */
|
|
63
72
|
const importsMap = new Map();
|
|
64
73
|
|
|
74
|
+
const typescriptList = [];
|
|
75
|
+
|
|
76
|
+
const bricksImportsInfo = {};
|
|
77
|
+
|
|
65
78
|
/**
|
|
66
79
|
*
|
|
67
80
|
* @param {string} filePath
|
|
@@ -80,6 +93,9 @@ export default async function scanBricks(packageDir) {
|
|
|
80
93
|
const extname = path.extname(filePath);
|
|
81
94
|
const content = await readFile(filePath, "utf-8");
|
|
82
95
|
|
|
96
|
+
/** @type {Record<string, string[]>} */
|
|
97
|
+
/** @type {string} */
|
|
98
|
+
let brickFullName;
|
|
83
99
|
/** @type {ReturnType<typeof import("@babel/parser").parse>} */
|
|
84
100
|
let ast;
|
|
85
101
|
try {
|
|
@@ -203,7 +219,10 @@ export default async function scanBricks(packageDir) {
|
|
|
203
219
|
}
|
|
204
220
|
|
|
205
221
|
traverse(ast, {
|
|
206
|
-
CallExpression(
|
|
222
|
+
CallExpression(nodePath) {
|
|
223
|
+
const {
|
|
224
|
+
node: { callee, arguments: args },
|
|
225
|
+
} = nodePath;
|
|
207
226
|
// Match `customProcessors.define(...)`
|
|
208
227
|
// Match `customElements.define(...)`
|
|
209
228
|
if (
|
|
@@ -252,6 +271,9 @@ export default async function scanBricks(packageDir) {
|
|
|
252
271
|
const { type, value: fullName } = args[0];
|
|
253
272
|
if (type === "StringLiteral") {
|
|
254
273
|
collectBrick(fullName);
|
|
274
|
+
manifest.providers.push(
|
|
275
|
+
makeProviderManifest(fullName, nodePath, content)
|
|
276
|
+
);
|
|
255
277
|
} else {
|
|
256
278
|
throw new Error(
|
|
257
279
|
"Please call `customElements.define()` only with literal string"
|
|
@@ -388,6 +410,8 @@ export default async function scanBricks(packageDir) {
|
|
|
388
410
|
specifiedDeps[fullName] = deps;
|
|
389
411
|
}
|
|
390
412
|
|
|
413
|
+
brickFullName = fullName;
|
|
414
|
+
|
|
391
415
|
brickSourceFiles.set(fullName, filePath);
|
|
392
416
|
|
|
393
417
|
manifest.bricks.push(makeBrickManifest(fullName, nodePath, content));
|
|
@@ -401,7 +425,7 @@ export default async function scanBricks(packageDir) {
|
|
|
401
425
|
});
|
|
402
426
|
}
|
|
403
427
|
},
|
|
404
|
-
ImportDeclaration({ node: { source, importKind
|
|
428
|
+
ImportDeclaration({ node: { source, importKind } }) {
|
|
405
429
|
// Match `import "..."`
|
|
406
430
|
if (
|
|
407
431
|
source.type === "StringLiteral" &&
|
|
@@ -433,6 +457,25 @@ export default async function scanBricks(packageDir) {
|
|
|
433
457
|
}
|
|
434
458
|
}
|
|
435
459
|
},
|
|
460
|
+
TSInterfaceDeclaration({ node }) {
|
|
461
|
+
if (!node.id) return;
|
|
462
|
+
typescriptList.push({
|
|
463
|
+
...(getTypeAnnotation(node, content) || {}),
|
|
464
|
+
filePath,
|
|
465
|
+
});
|
|
466
|
+
},
|
|
467
|
+
TSTypeAliasDeclaration({ node }) {
|
|
468
|
+
typescriptList.push({
|
|
469
|
+
...(getTypeAnnotation(node, content) || {}),
|
|
470
|
+
filePath,
|
|
471
|
+
});
|
|
472
|
+
},
|
|
473
|
+
TSEnumDeclaration: ({ node }) => {
|
|
474
|
+
typescriptList.push({
|
|
475
|
+
...(getTypeAnnotation(node, content) || {}),
|
|
476
|
+
filePath,
|
|
477
|
+
});
|
|
478
|
+
},
|
|
436
479
|
});
|
|
437
480
|
|
|
438
481
|
await Promise.all(
|
|
@@ -440,6 +483,43 @@ export default async function scanBricks(packageDir) {
|
|
|
440
483
|
scanByImport(item, filePath, nextOverrideImport)
|
|
441
484
|
)
|
|
442
485
|
);
|
|
486
|
+
|
|
487
|
+
if (brickFullName) {
|
|
488
|
+
const imports = ast.program.body
|
|
489
|
+
.map((item) => {
|
|
490
|
+
if (isImportDeclaration(item)) {
|
|
491
|
+
const { source, specifiers } = item;
|
|
492
|
+
if (
|
|
493
|
+
source.type === "StringLiteral" &&
|
|
494
|
+
(source.value.startsWith("./") ||
|
|
495
|
+
source.value.startsWith("../")) &&
|
|
496
|
+
!source.value.endsWith(".css")
|
|
497
|
+
) {
|
|
498
|
+
const importPath = path.resolve(dirname, source.value);
|
|
499
|
+
const importKeys = [];
|
|
500
|
+
for (let i = 0; i < specifiers.length; i++) {
|
|
501
|
+
const importItem = specifiers[i];
|
|
502
|
+
if (isImportSpecifier(importItem)) {
|
|
503
|
+
importKeys.push(importItem.imported.name);
|
|
504
|
+
} else if (isImportDefaultSpecifier(importItem)) {
|
|
505
|
+
importKeys.push(importItem.local.name);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
keys: importKeys,
|
|
510
|
+
path: importPath,
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return false;
|
|
515
|
+
})
|
|
516
|
+
.filter(Boolean);
|
|
517
|
+
|
|
518
|
+
bricksImportsInfo[brickFullName] = {
|
|
519
|
+
imports,
|
|
520
|
+
filePath,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
443
523
|
}
|
|
444
524
|
|
|
445
525
|
/**
|
|
@@ -483,6 +563,45 @@ export default async function scanBricks(packageDir) {
|
|
|
483
563
|
|
|
484
564
|
await scanByFile(bootstrapTsPath);
|
|
485
565
|
|
|
566
|
+
async function checkMissLoadFile() {
|
|
567
|
+
const processedFilesList = [...processedFiles];
|
|
568
|
+
const files = Object.values(bricksImportsInfo)
|
|
569
|
+
.map(({ imports }) => {
|
|
570
|
+
return imports.map(
|
|
571
|
+
(item) =>
|
|
572
|
+
!processedFilesList.find((path) => isMatch(path, item.path)) &&
|
|
573
|
+
item.path
|
|
574
|
+
);
|
|
575
|
+
})
|
|
576
|
+
.flat(1)
|
|
577
|
+
.filter(Boolean);
|
|
578
|
+
|
|
579
|
+
if (files.length) {
|
|
580
|
+
await Promise.all(
|
|
581
|
+
[...new Set(files)].map((file) => {
|
|
582
|
+
const fileName = path.dirname(file);
|
|
583
|
+
const lastName = path.basename(file);
|
|
584
|
+
const matchExtension = /\.[tj]sx?$/.test(lastName);
|
|
585
|
+
const noExtension = !lastName.includes(".");
|
|
586
|
+
let fileInfo;
|
|
587
|
+
|
|
588
|
+
if (matchExtension || noExtension) {
|
|
589
|
+
fileInfo = [fileName, lastName.replace(/\.[^.]+$/, "")];
|
|
590
|
+
}
|
|
591
|
+
if (noExtension && existsSync(file) && statSync(file).isDirectory()) {
|
|
592
|
+
fileInfo = [fileName, "index"];
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (fileInfo) {
|
|
596
|
+
return scanByImport(fileInfo, "", "");
|
|
597
|
+
}
|
|
598
|
+
})
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
await checkMissLoadFile();
|
|
604
|
+
|
|
486
605
|
// console.log("usingWrappedBricks:", usingWrappedBricks);
|
|
487
606
|
// console.log("brickSourceFiles:", brickSourceFiles);
|
|
488
607
|
// console.log("importsMap:", importsMap);
|
|
@@ -519,6 +638,91 @@ export default async function scanBricks(packageDir) {
|
|
|
519
638
|
}
|
|
520
639
|
}
|
|
521
640
|
|
|
641
|
+
function ingoreField(obj) {
|
|
642
|
+
return _.omit(obj, ["filePath", "reference"]);
|
|
643
|
+
}
|
|
644
|
+
function isMatch(importPath, filePath) {
|
|
645
|
+
return (
|
|
646
|
+
importPath.replace(/\.[^.]+$/, "") === filePath.replace(/\.[^.]+$/, "")
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
*
|
|
652
|
+
* @param {string} type
|
|
653
|
+
* @param {Record<string, unknown} importInfo
|
|
654
|
+
* @param {Set<string>} importKeysSet
|
|
655
|
+
* @param {string} realFilePath
|
|
656
|
+
* @returns void
|
|
657
|
+
*/
|
|
658
|
+
function findType(name, importInfo, importKeysSet, realFilePath = "") {
|
|
659
|
+
if (importKeysSet.has(name)) return;
|
|
660
|
+
importKeysSet.add(name);
|
|
661
|
+
|
|
662
|
+
const { imports, filePath } = importInfo;
|
|
663
|
+
const importItem = imports.find((item) => item.keys.includes(name));
|
|
664
|
+
const importPath = realFilePath
|
|
665
|
+
? realFilePath
|
|
666
|
+
: importItem
|
|
667
|
+
? importItem.path
|
|
668
|
+
: filePath;
|
|
669
|
+
|
|
670
|
+
const interfaceItem = typescriptList.find(
|
|
671
|
+
(item) => isMatch(item.filePath, importPath) && item.name === name
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
if (interfaceItem) {
|
|
675
|
+
importInfo.types = (importInfo.types || []).concat(
|
|
676
|
+
ingoreField(interfaceItem)
|
|
677
|
+
);
|
|
678
|
+
findRefrenceItem(
|
|
679
|
+
interfaceItem.extends,
|
|
680
|
+
importInfo,
|
|
681
|
+
importKeysSet,
|
|
682
|
+
importPath
|
|
683
|
+
);
|
|
684
|
+
findRefrenceItem(
|
|
685
|
+
interfaceItem.reference,
|
|
686
|
+
importInfo,
|
|
687
|
+
importKeysSet,
|
|
688
|
+
importPath
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function findRefrenceItem(list, importInfo, importKeySet, realFilePath = "") {
|
|
694
|
+
if (Array.isArray(list) && list.length) {
|
|
695
|
+
list.forEach((item) =>
|
|
696
|
+
findType(item, importInfo, importKeySet, realFilePath)
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
if (manifest && manifest.bricks.length) {
|
|
702
|
+
manifest.bricks.forEach((brickDoc) => {
|
|
703
|
+
const { name, properties } = brickDoc;
|
|
704
|
+
const importInfo = bricksImportsInfo[name];
|
|
705
|
+
const fieldTypes = properties
|
|
706
|
+
.map(
|
|
707
|
+
({ type }) =>
|
|
708
|
+
type &&
|
|
709
|
+
type
|
|
710
|
+
.match(/\w+/g)
|
|
711
|
+
.filter(
|
|
712
|
+
(item) => !(BASE_TYPE[item] || TS_KEYWORD_LIST.includes(item))
|
|
713
|
+
)
|
|
714
|
+
)
|
|
715
|
+
.flat(1);
|
|
716
|
+
|
|
717
|
+
const importKeysSet = new Set();
|
|
718
|
+
if (Array.isArray(fieldTypes) && fieldTypes.length) {
|
|
719
|
+
[...new Set(fieldTypes)].forEach((type) =>
|
|
720
|
+
findType(type, importInfo, importKeysSet)
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
522
726
|
// console.log("exposes:", exposes);
|
|
523
727
|
|
|
524
728
|
return {
|
|
@@ -528,5 +732,10 @@ export default async function scanBricks(packageDir) {
|
|
|
528
732
|
...specifiedDeps,
|
|
529
733
|
},
|
|
530
734
|
manifest,
|
|
735
|
+
types: Object.fromEntries(
|
|
736
|
+
Object.entries(bricksImportsInfo).map(([k, v]) => {
|
|
737
|
+
return [k, v.types];
|
|
738
|
+
})
|
|
739
|
+
),
|
|
531
740
|
};
|
|
532
741
|
}
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isIdentifier,
|
|
3
|
+
isStringLiteral,
|
|
4
|
+
isTSArrayType,
|
|
5
|
+
isTSEnumDeclaration,
|
|
6
|
+
isTSEnumMember,
|
|
7
|
+
isTSIndexSignature,
|
|
8
|
+
isTSIndexedAccessType,
|
|
9
|
+
isTSInterfaceDeclaration,
|
|
10
|
+
isTSIntersectionType,
|
|
11
|
+
isTSLiteralType,
|
|
12
|
+
isTSPropertySignature,
|
|
13
|
+
isTSQualifiedName,
|
|
14
|
+
isTSTupleType,
|
|
15
|
+
isTSTypeAliasDeclaration,
|
|
16
|
+
isTSTypeAnnotation,
|
|
17
|
+
isTSTypeLiteral,
|
|
18
|
+
isTSTypeParameter,
|
|
19
|
+
isTSTypeParameterDeclaration,
|
|
20
|
+
isTSTypeReference,
|
|
21
|
+
isTSUnionType,
|
|
22
|
+
} from "@babel/types";
|
|
23
|
+
import _ from "lodash";
|
|
24
|
+
import { parseDocComment } from "./makeBrickManifest.js";
|
|
25
|
+
|
|
26
|
+
export const BASE_TYPE = {
|
|
27
|
+
any: "any",
|
|
28
|
+
boolean: "boolean",
|
|
29
|
+
undefined: "undefined",
|
|
30
|
+
bigint: "bigint",
|
|
31
|
+
null: "null",
|
|
32
|
+
number: "number",
|
|
33
|
+
object: "object",
|
|
34
|
+
string: "string",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const TS_KEYWORD_LIST = ["Record", "Array", "unknow", "void"];
|
|
38
|
+
const TS_BASIC_TYPE = {
|
|
39
|
+
TSAnyKeyword: BASE_TYPE.any,
|
|
40
|
+
TSBooleanKeyword: BASE_TYPE.boolean,
|
|
41
|
+
TSBigIntKeyword: BASE_TYPE.bigint,
|
|
42
|
+
TSNullKeyword: BASE_TYPE.null,
|
|
43
|
+
TSNumberKeyword: BASE_TYPE.number,
|
|
44
|
+
TSObjectKeyword: BASE_TYPE.object,
|
|
45
|
+
TSStringKeyword: BASE_TYPE.string,
|
|
46
|
+
TSUndefinedKeyword: BASE_TYPE.undefined,
|
|
47
|
+
TSUnknownKeyword: BASE_TYPE.any,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
function getTSBasicType(annotation) {
|
|
51
|
+
return annotation && TS_BASIC_TYPE[annotation.type];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const getDocComment = (typeAnnotation, source) => {
|
|
55
|
+
return parseDocComment(typeAnnotation, source) || {};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* @param {import("@babel/types").typeAnnotation} typeAnnotation
|
|
61
|
+
* @param {string} source
|
|
62
|
+
* @param {Set<string>} reference
|
|
63
|
+
* @returns
|
|
64
|
+
*/
|
|
65
|
+
export const getTypeAnnotation = (
|
|
66
|
+
typeAnnotation,
|
|
67
|
+
source,
|
|
68
|
+
reference = new Set()
|
|
69
|
+
) => {
|
|
70
|
+
const makeResultWithDocComment = (result) => {
|
|
71
|
+
return {
|
|
72
|
+
...result,
|
|
73
|
+
...getDocComment(typeAnnotation, source),
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* @param {import("@babel/types").typeAnnotation} typeAnnotation
|
|
78
|
+
*/
|
|
79
|
+
const walkTypeAnnotation = (typeAnnotation) => {
|
|
80
|
+
if (isTSInterfaceDeclaration(typeAnnotation)) {
|
|
81
|
+
const {
|
|
82
|
+
id,
|
|
83
|
+
body,
|
|
84
|
+
extends: extendsItems,
|
|
85
|
+
typeParameters,
|
|
86
|
+
} = typeAnnotation;
|
|
87
|
+
if (!id) return;
|
|
88
|
+
return makeResultWithDocComment({
|
|
89
|
+
name: id.name,
|
|
90
|
+
type: "interface",
|
|
91
|
+
typeParameters: typeParameters && walkTypeAnnotation(typeParameters),
|
|
92
|
+
annotation: body.body.map(walkTypeAnnotation),
|
|
93
|
+
extends: extendsItems?.map((item) => item.expression.name),
|
|
94
|
+
reference: [...reference],
|
|
95
|
+
});
|
|
96
|
+
} else if (isTSTypeAliasDeclaration(typeAnnotation)) {
|
|
97
|
+
const { id, typeParameters } = typeAnnotation;
|
|
98
|
+
return makeResultWithDocComment({
|
|
99
|
+
name: id.name,
|
|
100
|
+
type: "typeAlias",
|
|
101
|
+
typeParameters: typeParameters && walkTypeAnnotation(typeParameters),
|
|
102
|
+
annotation: walkTypeAnnotation(typeAnnotation.typeAnnotation),
|
|
103
|
+
reference: [...reference],
|
|
104
|
+
});
|
|
105
|
+
} else if (isTSEnumDeclaration(typeAnnotation)) {
|
|
106
|
+
const { id, members } = typeAnnotation;
|
|
107
|
+
return makeResultWithDocComment({
|
|
108
|
+
name: id.name,
|
|
109
|
+
type: "enums",
|
|
110
|
+
members: members?.map(walkTypeAnnotation),
|
|
111
|
+
reference: [...reference],
|
|
112
|
+
});
|
|
113
|
+
} else if (isTSEnumMember(typeAnnotation)) {
|
|
114
|
+
return {
|
|
115
|
+
name: walkTypeAnnotation(typeAnnotation.id),
|
|
116
|
+
value: walkTypeAnnotation(typeAnnotation.initializer),
|
|
117
|
+
};
|
|
118
|
+
} else if (isTSTypeAnnotation(typeAnnotation)) {
|
|
119
|
+
return walkTypeAnnotation(typeAnnotation.typeAnnotation);
|
|
120
|
+
} else if (isTSTypeReference(typeAnnotation)) {
|
|
121
|
+
const { typeName, typeParameters } = typeAnnotation;
|
|
122
|
+
const qualified = isTSQualifiedName(typeName)
|
|
123
|
+
? walkTypeAnnotation(typeName)
|
|
124
|
+
: undefined;
|
|
125
|
+
const name = typeName.name;
|
|
126
|
+
reference.add(name);
|
|
127
|
+
const params =
|
|
128
|
+
typeParameters?.params && typeParameters.params.map(walkTypeAnnotation);
|
|
129
|
+
return makeResultWithDocComment({
|
|
130
|
+
type: "reference",
|
|
131
|
+
typeName: name,
|
|
132
|
+
typeParameters: params,
|
|
133
|
+
qualified,
|
|
134
|
+
});
|
|
135
|
+
} else if (isTSQualifiedName(typeAnnotation)) {
|
|
136
|
+
const left = walkTypeAnnotation(typeAnnotation.left);
|
|
137
|
+
if (typeof left === "string") {
|
|
138
|
+
reference.add(left);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
type: "qualifiedName",
|
|
142
|
+
left: left,
|
|
143
|
+
right: walkTypeAnnotation(typeAnnotation.right),
|
|
144
|
+
};
|
|
145
|
+
} else if (isTSUnionType(typeAnnotation)) {
|
|
146
|
+
return makeResultWithDocComment({
|
|
147
|
+
type: "union",
|
|
148
|
+
types: typeAnnotation.types.map(walkTypeAnnotation),
|
|
149
|
+
});
|
|
150
|
+
} else if (isTSArrayType(typeAnnotation)) {
|
|
151
|
+
return makeResultWithDocComment({
|
|
152
|
+
type: "array",
|
|
153
|
+
elementType: walkTypeAnnotation(typeAnnotation.elementType),
|
|
154
|
+
});
|
|
155
|
+
} else if (isTSTupleType(typeAnnotation)) {
|
|
156
|
+
return makeResultWithDocComment({
|
|
157
|
+
type: "tuple",
|
|
158
|
+
elementTypes: typeAnnotation.elementTypes.map(walkTypeAnnotation),
|
|
159
|
+
});
|
|
160
|
+
} else if (isTSIntersectionType(typeAnnotation)) {
|
|
161
|
+
return makeResultWithDocComment({
|
|
162
|
+
type: "intersection",
|
|
163
|
+
types: typeAnnotation.types.map(walkTypeAnnotation),
|
|
164
|
+
});
|
|
165
|
+
} else if (isTSTypeLiteral(typeAnnotation)) {
|
|
166
|
+
return makeResultWithDocComment({
|
|
167
|
+
type: "typeLiteral",
|
|
168
|
+
members: typeAnnotation.members.map(walkTypeAnnotation),
|
|
169
|
+
});
|
|
170
|
+
} else if (isTSPropertySignature(typeAnnotation)) {
|
|
171
|
+
return makeResultWithDocComment({
|
|
172
|
+
type: "propertySignature",
|
|
173
|
+
name: typeAnnotation.key.name,
|
|
174
|
+
property: walkTypeAnnotation(typeAnnotation.typeAnnotation),
|
|
175
|
+
});
|
|
176
|
+
} else if (isTSIndexSignature(typeAnnotation)) {
|
|
177
|
+
return makeResultWithDocComment({
|
|
178
|
+
type: "indexSignature",
|
|
179
|
+
parameters: {
|
|
180
|
+
name: typeAnnotation.parameters[0].name,
|
|
181
|
+
...walkTypeAnnotation(typeAnnotation.parameters[0].typeAnnotation),
|
|
182
|
+
},
|
|
183
|
+
property: walkTypeAnnotation(typeAnnotation.typeAnnotation),
|
|
184
|
+
});
|
|
185
|
+
} else if (isTSIndexedAccessType(typeAnnotation)) {
|
|
186
|
+
return makeResultWithDocComment({
|
|
187
|
+
type: "indexedAccess",
|
|
188
|
+
objectType: walkTypeAnnotation(typeAnnotation.objectType),
|
|
189
|
+
indexType: walkTypeAnnotation(typeAnnotation.indexType),
|
|
190
|
+
});
|
|
191
|
+
} else if (isTSTypeParameterDeclaration(typeAnnotation)) {
|
|
192
|
+
return makeResultWithDocComment({
|
|
193
|
+
type: "typeParameterDeclaration",
|
|
194
|
+
params: typeAnnotation.params.map(walkTypeAnnotation),
|
|
195
|
+
});
|
|
196
|
+
} else if (isTSTypeParameter(typeAnnotation)) {
|
|
197
|
+
return makeResultWithDocComment({
|
|
198
|
+
type: "typeParameter",
|
|
199
|
+
value: typeAnnotation.name,
|
|
200
|
+
default:
|
|
201
|
+
typeAnnotation.default && walkTypeAnnotation(typeAnnotation.default),
|
|
202
|
+
});
|
|
203
|
+
} else if (isTSLiteralType(typeAnnotation)) {
|
|
204
|
+
return makeResultWithDocComment({
|
|
205
|
+
type: "literal",
|
|
206
|
+
value: typeAnnotation.literal.value,
|
|
207
|
+
});
|
|
208
|
+
} else if (isIdentifier(typeAnnotation)) {
|
|
209
|
+
return {
|
|
210
|
+
type: "identifier",
|
|
211
|
+
value: typeAnnotation.name,
|
|
212
|
+
};
|
|
213
|
+
} else if (isStringLiteral(typeAnnotation)) {
|
|
214
|
+
return {
|
|
215
|
+
type: "stringLiteral",
|
|
216
|
+
value: typeAnnotation.value,
|
|
217
|
+
};
|
|
218
|
+
} else if (getTSBasicType(typeAnnotation)) {
|
|
219
|
+
return makeResultWithDocComment({
|
|
220
|
+
type: "keyword",
|
|
221
|
+
value: getTSBasicType(typeAnnotation),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
return walkTypeAnnotation(typeAnnotation);
|
|
227
|
+
};
|