@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/src/scanBricks.js CHANGED
@@ -8,17 +8,22 @@ import getCamelPackageName from "./getCamelPackageName.js";
8
8
  import makeBrickManifest, {
9
9
  makeProviderManifest,
10
10
  } from "./makeBrickManifest.js";
11
- import { BASE_TYPE, TS_KEYWORD_LIST, getTypeAnnotation } from "./utils.js";
12
11
  import {
13
12
  isImportDefaultSpecifier,
14
13
  isImportDeclaration,
15
14
  isImportSpecifier,
16
15
  } from "@babel/types";
16
+ import getTypeDeclaration from "./getTypeDeclaration.js";
17
17
 
18
18
  /**
19
+ *
20
+ * @typedef {import("@babel/traverse").NodePath} NodePath
19
21
  * @typedef {import("@next-core/brick-manifest").PackageManifest} PackageManifest
22
+ * @typedef {import("@next-core/brick-manifest").ProviderManifest} ProviderManifest
23
+ * @typedef {import("@next-core/brick-manifest").Declaration} Declaration
20
24
  * @typedef {{import: string; name: string; noNamespace?: boolean;}} Expose
21
25
  * @typedef {Record<string, Expose>} Exposes
26
+ * @typedef {import("./makeBrickManifest.js").BrickManifestAndTypes} BrickManifestAndTypes
22
27
  */
23
28
 
24
29
  const { default: traverse } = babelTraverse;
@@ -71,10 +76,14 @@ export default async function scanBricks(packageDir) {
71
76
  /** @type {Map<string, Set<string>} */
72
77
  const importsMap = new Map();
73
78
 
74
- const typescriptList = [];
79
+ /** @type {{ filePath: string; declaration: Declaration; usedReferences: Set<string> }[]} */
80
+ const typeDeclarations = [];
75
81
 
76
82
  const bricksImportsInfo = {};
77
83
 
84
+ /** @type {ProviderManifest[]} */
85
+ const providerTypes = [];
86
+
78
87
  /**
79
88
  *
80
89
  * @param {string} filePath
@@ -93,7 +102,12 @@ export default async function scanBricks(packageDir) {
93
102
  const extname = path.extname(filePath);
94
103
  const content = await readFile(filePath, "utf-8");
95
104
 
96
- /** @type {Record<string, string[]>} */
105
+ // Record top level functions for providers
106
+ /** @type {Map<string, NodePath} */
107
+ const topLevelFunctions = new Map();
108
+ /** @type {Map<string, string>} */
109
+ const providerMap = new Map();
110
+
97
111
  /** @type {string} */
98
112
  let brickFullName;
99
113
  /** @type {ReturnType<typeof import("@babel/parser").parse>} */
@@ -268,12 +282,20 @@ export default async function scanBricks(packageDir) {
268
282
  callee.property.name === "define" &&
269
283
  args.length === 2
270
284
  ) {
271
- const { type, value: fullName } = args[0];
285
+ const [{ type, value: fullName }, constructor] = args;
272
286
  if (type === "StringLiteral") {
273
287
  collectBrick(fullName);
274
- manifest.providers.push(
275
- makeProviderManifest(fullName, nodePath, content)
276
- );
288
+ if (
289
+ constructor.type === "CallExpression" &&
290
+ constructor.callee.type === "Identifier" &&
291
+ constructor.callee.name === "createProviderClass" &&
292
+ constructor.arguments.length > 0 &&
293
+ constructor.arguments[0].type === "Identifier"
294
+ ) {
295
+ providerMap.set(fullName, constructor.arguments[0].name);
296
+ } else {
297
+ manifest.providers.push({ name: fullName });
298
+ }
277
299
  } else {
278
300
  throw new Error(
279
301
  "Please call `customElements.define()` only with literal string"
@@ -425,6 +447,17 @@ export default async function scanBricks(packageDir) {
425
447
  });
426
448
  }
427
449
  },
450
+ FunctionDeclaration(nodePath) {
451
+ const { node, parent } = nodePath;
452
+ if (
453
+ node.id &&
454
+ (parent.type === "Program" ||
455
+ parent.type === "ExportNamedDeclaration" ||
456
+ parent.type === "ExportDefaultDeclaration")
457
+ ) {
458
+ topLevelFunctions.set(node.id.name, nodePath);
459
+ }
460
+ },
428
461
  ImportDeclaration({ node: { source, importKind } }) {
429
462
  // Match `import "..."`
430
463
  if (
@@ -458,22 +491,27 @@ export default async function scanBricks(packageDir) {
458
491
  }
459
492
  },
460
493
  TSInterfaceDeclaration({ node }) {
461
- if (!node.id) return;
462
- typescriptList.push({
463
- ...(getTypeAnnotation(node, content) || {}),
494
+ const usedReferences = new Set();
495
+ typeDeclarations.push({
464
496
  filePath,
497
+ declaration: getTypeDeclaration(node, content, usedReferences),
498
+ usedReferences,
465
499
  });
466
500
  },
467
501
  TSTypeAliasDeclaration({ node }) {
468
- typescriptList.push({
469
- ...(getTypeAnnotation(node, content) || {}),
502
+ const usedReferences = new Set();
503
+ typeDeclarations.push({
470
504
  filePath,
505
+ declaration: getTypeDeclaration(node, content, usedReferences),
506
+ usedReferences,
471
507
  });
472
508
  },
473
509
  TSEnumDeclaration: ({ node }) => {
474
- typescriptList.push({
475
- ...(getTypeAnnotation(node, content) || {}),
510
+ const usedReferences = new Set();
511
+ typeDeclarations.push({
476
512
  filePath,
513
+ declaration: getTypeDeclaration(node, content, usedReferences),
514
+ usedReferences,
477
515
  });
478
516
  },
479
517
  });
@@ -484,7 +522,7 @@ export default async function scanBricks(packageDir) {
484
522
  )
485
523
  );
486
524
 
487
- if (brickFullName) {
525
+ if (brickFullName || providerMap.size > 0) {
488
526
  const imports = ast.program.body
489
527
  .map((item) => {
490
528
  if (isImportDeclaration(item)) {
@@ -515,10 +553,36 @@ export default async function scanBricks(packageDir) {
515
553
  })
516
554
  .filter(Boolean);
517
555
 
518
- bricksImportsInfo[brickFullName] = {
519
- imports,
520
- filePath,
521
- };
556
+ if (brickFullName) {
557
+ bricksImportsInfo[brickFullName] = {
558
+ imports,
559
+ filePath,
560
+ };
561
+ }
562
+ for (const providerName of providerMap.keys()) {
563
+ bricksImportsInfo[providerName] = {
564
+ imports,
565
+ filePath,
566
+ };
567
+ }
568
+ }
569
+
570
+ if (providerMap.size > 0) {
571
+ for (const [providerName, providerConstructor] of providerMap) {
572
+ const nodePath = topLevelFunctions.get(providerConstructor);
573
+ if (nodePath) {
574
+ const { description, deprecated, ...restTypes } =
575
+ makeProviderManifest(providerName, nodePath, content);
576
+ providerTypes.push(restTypes);
577
+ manifest.providers.push({
578
+ name: providerName,
579
+ description,
580
+ deprecated,
581
+ });
582
+ } else {
583
+ manifest.providers.push({ name: providerName });
584
+ }
585
+ }
522
586
  }
523
587
  }
524
588
 
@@ -618,9 +682,6 @@ export default async function scanBricks(packageDir) {
618
682
  if (analyzedFiles.has(filePath)) {
619
683
  return;
620
684
  }
621
- if (brickName === "button-with-icon") {
622
- console.log("scan:", filePath);
623
- }
624
685
  analyzedFiles.add(filePath);
625
686
  for (const dep of usingWrappedBricks.get(filePath) ?? []) {
626
687
  // Do not dependent on itself
@@ -638,9 +699,6 @@ export default async function scanBricks(packageDir) {
638
699
  }
639
700
  }
640
701
 
641
- function ingoreField(obj) {
642
- return _.omit(obj, ["filePath", "reference"]);
643
- }
644
702
  function isMatch(importPath, filePath) {
645
703
  return (
646
704
  importPath.replace(/\.[^.]+$/, "") === filePath.replace(/\.[^.]+$/, "")
@@ -649,11 +707,11 @@ export default async function scanBricks(packageDir) {
649
707
 
650
708
  /**
651
709
  *
652
- * @param {string} type
710
+ * @param {string} name
653
711
  * @param {Record<string, unknown} importInfo
654
712
  * @param {Set<string>} importKeysSet
655
713
  * @param {string} realFilePath
656
- * @returns void
714
+ * @returns {void}
657
715
  */
658
716
  function findType(name, importInfo, importKeysSet, realFilePath = "") {
659
717
  if (importKeysSet.has(name)) return;
@@ -667,85 +725,43 @@ export default async function scanBricks(packageDir) {
667
725
  ? importItem.path
668
726
  : filePath;
669
727
 
670
- const interfaceItem = typescriptList.find(
671
- (item) => isMatch(item.filePath, importPath) && item.name === name
672
- );
728
+ const { declaration, usedReferences } =
729
+ typeDeclarations.find(
730
+ (item) =>
731
+ isMatch(item.filePath, importPath) && item.declaration.name === name
732
+ ) ?? {};
673
733
 
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
- );
734
+ if (declaration) {
735
+ importInfo.types = (importInfo.types || []).concat(declaration);
736
+ for (const ref of usedReferences) {
737
+ findType(ref, importInfo, importKeysSet, importPath);
738
+ }
690
739
  }
691
740
  }
692
741
 
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
- );
742
+ manifest.bricks.forEach((/** @type {BrickManifestAndTypes} */ brickDoc) => {
743
+ const {
744
+ name,
745
+ types: { usedReferences, ...types },
746
+ } = brickDoc;
747
+ const importInfo = bricksImportsInfo[name];
748
+ Object.assign(importInfo, types);
749
+
750
+ const importKeysSet = new Set();
751
+ for (const ref of usedReferences) {
752
+ findType(ref, importInfo, importKeysSet);
698
753
  }
699
- }
700
-
701
- if (manifest && manifest.bricks.length) {
702
- manifest.bricks.forEach((brickDoc) => {
703
- const { name, properties = [], events = [], methods = [] } = brickDoc;
704
- const importInfo = bricksImportsInfo[name];
705
- const fieldTypes = new Set();
706
-
707
- properties.forEach((item) => {
708
- importInfo.properties = (importInfo.properties || []).concat({
709
- name: item.name,
710
- types: item.types,
711
- });
712
- (item.reference || []).forEach((item) => fieldTypes.add(item));
713
-
714
- delete item.types;
715
- delete item.reference;
716
- });
717
-
718
- events.forEach((item) => {
719
- if (item.detail) {
720
- importInfo.events = (importInfo.events || []).concat({
721
- name: item.name,
722
- types: item.detail.types,
723
- });
724
- (item.detail.reference || []).forEach((item) => fieldTypes.add(item));
754
+ delete brickDoc.types;
755
+ });
725
756
 
726
- delete item.detail.types;
727
- delete item.detail.reference;
728
- }
729
- });
730
-
731
- methods.forEach((item) => {
732
- if (item.return) {
733
- importInfo.methods = (importInfo.methods || []).concat({
734
- name: item.name,
735
- types: item.return.types,
736
- });
737
- (item.return.reference || []).forEach((item) => fieldTypes.add(item));
738
-
739
- delete item.return.types;
740
- delete item.return.reference;
741
- }
742
- });
757
+ for (const providerDoc of providerTypes) {
758
+ const importInfo = bricksImportsInfo[providerDoc.name];
743
759
 
744
- const importKeysSet = new Set();
745
- [...fieldTypes].forEach((type) =>
746
- findType(type, importInfo, importKeysSet)
747
- );
748
- });
760
+ const importKeysSet = new Set();
761
+ for (const ref of providerDoc.usedReferences) {
762
+ findType(ref, importInfo, importKeysSet);
763
+ }
764
+ delete providerDoc.usedReferences;
749
765
  }
750
766
 
751
767
  // console.log("exposes:", exposes);
@@ -758,17 +774,27 @@ export default async function scanBricks(packageDir) {
758
774
  },
759
775
  manifest,
760
776
  types: Object.fromEntries(
761
- Object.entries(bricksImportsInfo).map(([k, v]) => {
762
- return [
763
- k,
764
- {
765
- properties: v.properties,
766
- events: v.events,
767
- methods: v.methods,
768
- types: v.types,
769
- },
770
- ];
771
- })
777
+ Object.entries(bricksImportsInfo)
778
+ .map(([k, v]) => {
779
+ return [
780
+ k,
781
+ {
782
+ properties: v.properties,
783
+ events: v.events,
784
+ methods: v.methods,
785
+ types: v.types,
786
+ },
787
+ ];
788
+ })
789
+ .concat(
790
+ providerTypes.map(({ name, ...types }) => [
791
+ name,
792
+ {
793
+ ...types,
794
+ types: bricksImportsInfo[name]?.types,
795
+ },
796
+ ])
797
+ )
772
798
  ),
773
799
  };
774
800
  }
package/src/utils.js DELETED
@@ -1,227 +0,0 @@
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
- };