@akanjs/cli 2.3.11-rc.8 → 2.3.11-rc.9
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.
|
@@ -15706,6 +15706,7 @@ class AkanQualityScanner {
|
|
|
15706
15706
|
const warnings = [
|
|
15707
15707
|
...this.#scanGlobalQuality(sourceFiles),
|
|
15708
15708
|
...sourceFiles.flatMap((sourceFile2) => this.#scanSingleFileQuality(sourceFile2)),
|
|
15709
|
+
...sourceFiles.flatMap((sourceFile2) => this.#scanComponentQuality(sourceFile2)),
|
|
15709
15710
|
...sourceFiles.flatMap((sourceFile2) => this.#scanConventionQuality(sourceFile2)),
|
|
15710
15711
|
...sourceFiles.flatMap((sourceFile2) => this.#scanLayoutQuality(sourceFile2))
|
|
15711
15712
|
];
|
|
@@ -15834,6 +15835,28 @@ class AkanQualityScanner {
|
|
|
15834
15835
|
}
|
|
15835
15836
|
return warnings;
|
|
15836
15837
|
}
|
|
15838
|
+
#scanComponentQuality(sourceFile2) {
|
|
15839
|
+
if (!isComponentDeclarationFile(sourceFile2.file))
|
|
15840
|
+
return [];
|
|
15841
|
+
const exportedNames = getExportedDeclarationNames(sourceFile2.sourceFile);
|
|
15842
|
+
const allowedInternalInterfaces = new Set([...exportedNames].map((name) => `${name}Props`));
|
|
15843
|
+
const warnings = [];
|
|
15844
|
+
for (const declaration of getInternalTypeOrFunctionDeclarations(sourceFile2.sourceFile)) {
|
|
15845
|
+
if (exportedNames.has(declaration.name))
|
|
15846
|
+
continue;
|
|
15847
|
+
if (declaration.kind === "interface" && allowedInternalInterfaces.has(declaration.name))
|
|
15848
|
+
continue;
|
|
15849
|
+
warnings.push({
|
|
15850
|
+
rule: "akan.file.component-internal-declaration",
|
|
15851
|
+
scope: "file",
|
|
15852
|
+
severity: "warning",
|
|
15853
|
+
file: sourceFile2.file,
|
|
15854
|
+
line: declaration.line,
|
|
15855
|
+
message: `Component file should not declare non-exported ${declaration.kind} "${declaration.name}". Only a "<Component>Props" interface may stay internal; move other types or helpers to a separate file in ui/, webkit/, or common/ by purpose.`
|
|
15856
|
+
});
|
|
15857
|
+
}
|
|
15858
|
+
return warnings;
|
|
15859
|
+
}
|
|
15837
15860
|
#scanConventionQuality(sourceFile2) {
|
|
15838
15861
|
const suffix = CONVENTION_SUFFIXES.find((candidate) => sourceFile2.file.endsWith(candidate));
|
|
15839
15862
|
if (!suffix)
|
|
@@ -15917,7 +15940,7 @@ function formatQualityLocation(file, line) {
|
|
|
15917
15940
|
}
|
|
15918
15941
|
function getExportedFunctionLikes(sourceFile2) {
|
|
15919
15942
|
const declarations = [];
|
|
15920
|
-
const
|
|
15943
|
+
const nameExempt = isPageRouteFile(sourceFile2.file) || isUiComponentFile(sourceFile2.file);
|
|
15921
15944
|
for (const statement of sourceFile2.sourceFile.statements) {
|
|
15922
15945
|
if (ts11.isFunctionDeclaration(statement) && statement.name && isExported(statement)) {
|
|
15923
15946
|
declarations.push({
|
|
@@ -15926,7 +15949,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
15926
15949
|
file: sourceFile2.file,
|
|
15927
15950
|
line: getLine(sourceFile2.sourceFile, statement),
|
|
15928
15951
|
bodyFingerprint: getBodyFingerprint(sourceFile2.sourceFile, statement.body),
|
|
15929
|
-
duplicateNameExempt:
|
|
15952
|
+
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, false)
|
|
15930
15953
|
});
|
|
15931
15954
|
}
|
|
15932
15955
|
if (ts11.isClassDeclaration(statement) && statement.name && isExported(statement)) {
|
|
@@ -15936,7 +15959,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
15936
15959
|
file: sourceFile2.file,
|
|
15937
15960
|
line: getLine(sourceFile2.sourceFile, statement),
|
|
15938
15961
|
bodyFingerprint: getBodyFingerprint(sourceFile2.sourceFile, statement),
|
|
15939
|
-
duplicateNameExempt:
|
|
15962
|
+
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, isEnumClassStatement(sourceFile2.sourceFile, statement))
|
|
15940
15963
|
});
|
|
15941
15964
|
}
|
|
15942
15965
|
if (ts11.isVariableStatement(statement) && isExported(statement)) {
|
|
@@ -15949,7 +15972,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
15949
15972
|
file: sourceFile2.file,
|
|
15950
15973
|
line: getLine(sourceFile2.sourceFile, declaration),
|
|
15951
15974
|
bodyFingerprint: getBodyFingerprint(sourceFile2.sourceFile, declaration.initializer),
|
|
15952
|
-
duplicateNameExempt:
|
|
15975
|
+
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, false)
|
|
15953
15976
|
});
|
|
15954
15977
|
}
|
|
15955
15978
|
}
|
|
@@ -15960,6 +15983,10 @@ function isPageRouteFile(file) {
|
|
|
15960
15983
|
const segments = file.split("/");
|
|
15961
15984
|
return (segments[0] === "apps" || segments[0] === "libs") && segments[2] === "page";
|
|
15962
15985
|
}
|
|
15986
|
+
function isUiComponentFile(file) {
|
|
15987
|
+
const segments = file.split("/");
|
|
15988
|
+
return (segments[0] === "apps" || segments[0] === "libs") && segments[2] === "ui";
|
|
15989
|
+
}
|
|
15963
15990
|
function isConventionDuplicateNameExempt(file, isEnumClass) {
|
|
15964
15991
|
if (!isInLibModule(file))
|
|
15965
15992
|
return false;
|
|
@@ -15985,6 +16012,72 @@ function isEnumClassStatement(sourceFile2, statement) {
|
|
|
15985
16012
|
function getExportedClassNames(sourceFile2) {
|
|
15986
16013
|
return sourceFile2.statements.filter((statement) => ts11.isClassDeclaration(statement) && !!statement.name).filter((statement) => isExported(statement)).map((statement) => statement.name.text);
|
|
15987
16014
|
}
|
|
16015
|
+
function isComponentDeclarationFile(file) {
|
|
16016
|
+
if (!file.endsWith(".tsx"))
|
|
16017
|
+
return false;
|
|
16018
|
+
const segments = file.split("/");
|
|
16019
|
+
const [root, , area] = segments;
|
|
16020
|
+
if (root !== "apps" && root !== "libs")
|
|
16021
|
+
return false;
|
|
16022
|
+
if (area === "lib" || area === "ui")
|
|
16023
|
+
return true;
|
|
16024
|
+
return root === "apps" && area === "page";
|
|
16025
|
+
}
|
|
16026
|
+
function getExportedDeclarationNames(sourceFile2) {
|
|
16027
|
+
const names = new Set;
|
|
16028
|
+
for (const statement of sourceFile2.statements) {
|
|
16029
|
+
if (ts11.isExportDeclaration(statement) && statement.exportClause && ts11.isNamedExports(statement.exportClause)) {
|
|
16030
|
+
for (const element of statement.exportClause.elements) {
|
|
16031
|
+
names.add(element.name.text);
|
|
16032
|
+
if (element.propertyName)
|
|
16033
|
+
names.add(element.propertyName.text);
|
|
16034
|
+
}
|
|
16035
|
+
continue;
|
|
16036
|
+
}
|
|
16037
|
+
if (!isExported(statement))
|
|
16038
|
+
continue;
|
|
16039
|
+
for (const name of getStatementDeclarationNames(statement))
|
|
16040
|
+
names.add(name);
|
|
16041
|
+
}
|
|
16042
|
+
return names;
|
|
16043
|
+
}
|
|
16044
|
+
function getStatementDeclarationNames(statement) {
|
|
16045
|
+
if (ts11.isFunctionDeclaration(statement) && statement.name)
|
|
16046
|
+
return [statement.name.text];
|
|
16047
|
+
if (ts11.isClassDeclaration(statement) && statement.name)
|
|
16048
|
+
return [statement.name.text];
|
|
16049
|
+
if (ts11.isInterfaceDeclaration(statement))
|
|
16050
|
+
return [statement.name.text];
|
|
16051
|
+
if (ts11.isTypeAliasDeclaration(statement))
|
|
16052
|
+
return [statement.name.text];
|
|
16053
|
+
if (ts11.isEnumDeclaration(statement))
|
|
16054
|
+
return [statement.name.text];
|
|
16055
|
+
if (ts11.isVariableStatement(statement)) {
|
|
16056
|
+
return statement.declarationList.declarations.filter((declaration) => ts11.isIdentifier(declaration.name)).map((declaration) => declaration.name.text);
|
|
16057
|
+
}
|
|
16058
|
+
return [];
|
|
16059
|
+
}
|
|
16060
|
+
function getInternalTypeOrFunctionDeclarations(sourceFile2) {
|
|
16061
|
+
const declarations = [];
|
|
16062
|
+
for (const statement of sourceFile2.statements) {
|
|
16063
|
+
if (isExported(statement))
|
|
16064
|
+
continue;
|
|
16065
|
+
if (ts11.isInterfaceDeclaration(statement)) {
|
|
16066
|
+
declarations.push({ name: statement.name.text, kind: "interface", line: getLine(sourceFile2, statement) });
|
|
16067
|
+
} else if (ts11.isTypeAliasDeclaration(statement)) {
|
|
16068
|
+
declarations.push({ name: statement.name.text, kind: "type", line: getLine(sourceFile2, statement) });
|
|
16069
|
+
} else if (ts11.isFunctionDeclaration(statement) && statement.name) {
|
|
16070
|
+
declarations.push({ name: statement.name.text, kind: "function", line: getLine(sourceFile2, statement) });
|
|
16071
|
+
} else if (ts11.isVariableStatement(statement)) {
|
|
16072
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
16073
|
+
if (!ts11.isIdentifier(declaration.name) || !isFunctionLikeInitializer(declaration.initializer))
|
|
16074
|
+
continue;
|
|
16075
|
+
declarations.push({ name: declaration.name.text, kind: "function", line: getLine(sourceFile2, declaration) });
|
|
16076
|
+
}
|
|
16077
|
+
}
|
|
16078
|
+
}
|
|
16079
|
+
return declarations;
|
|
16080
|
+
}
|
|
15988
16081
|
function getPlaceholderExportWarnings(sourceFile2) {
|
|
15989
16082
|
if (!sourceFile2.file.endsWith("/index.ts") && !sourceFile2.file.endsWith("/index.tsx"))
|
|
15990
16083
|
return [];
|
package/index.js
CHANGED
|
@@ -15704,6 +15704,7 @@ class AkanQualityScanner {
|
|
|
15704
15704
|
const warnings = [
|
|
15705
15705
|
...this.#scanGlobalQuality(sourceFiles),
|
|
15706
15706
|
...sourceFiles.flatMap((sourceFile2) => this.#scanSingleFileQuality(sourceFile2)),
|
|
15707
|
+
...sourceFiles.flatMap((sourceFile2) => this.#scanComponentQuality(sourceFile2)),
|
|
15707
15708
|
...sourceFiles.flatMap((sourceFile2) => this.#scanConventionQuality(sourceFile2)),
|
|
15708
15709
|
...sourceFiles.flatMap((sourceFile2) => this.#scanLayoutQuality(sourceFile2))
|
|
15709
15710
|
];
|
|
@@ -15832,6 +15833,28 @@ class AkanQualityScanner {
|
|
|
15832
15833
|
}
|
|
15833
15834
|
return warnings;
|
|
15834
15835
|
}
|
|
15836
|
+
#scanComponentQuality(sourceFile2) {
|
|
15837
|
+
if (!isComponentDeclarationFile(sourceFile2.file))
|
|
15838
|
+
return [];
|
|
15839
|
+
const exportedNames = getExportedDeclarationNames(sourceFile2.sourceFile);
|
|
15840
|
+
const allowedInternalInterfaces = new Set([...exportedNames].map((name) => `${name}Props`));
|
|
15841
|
+
const warnings = [];
|
|
15842
|
+
for (const declaration of getInternalTypeOrFunctionDeclarations(sourceFile2.sourceFile)) {
|
|
15843
|
+
if (exportedNames.has(declaration.name))
|
|
15844
|
+
continue;
|
|
15845
|
+
if (declaration.kind === "interface" && allowedInternalInterfaces.has(declaration.name))
|
|
15846
|
+
continue;
|
|
15847
|
+
warnings.push({
|
|
15848
|
+
rule: "akan.file.component-internal-declaration",
|
|
15849
|
+
scope: "file",
|
|
15850
|
+
severity: "warning",
|
|
15851
|
+
file: sourceFile2.file,
|
|
15852
|
+
line: declaration.line,
|
|
15853
|
+
message: `Component file should not declare non-exported ${declaration.kind} "${declaration.name}". Only a "<Component>Props" interface may stay internal; move other types or helpers to a separate file in ui/, webkit/, or common/ by purpose.`
|
|
15854
|
+
});
|
|
15855
|
+
}
|
|
15856
|
+
return warnings;
|
|
15857
|
+
}
|
|
15835
15858
|
#scanConventionQuality(sourceFile2) {
|
|
15836
15859
|
const suffix = CONVENTION_SUFFIXES.find((candidate) => sourceFile2.file.endsWith(candidate));
|
|
15837
15860
|
if (!suffix)
|
|
@@ -15915,7 +15938,7 @@ function formatQualityLocation(file, line) {
|
|
|
15915
15938
|
}
|
|
15916
15939
|
function getExportedFunctionLikes(sourceFile2) {
|
|
15917
15940
|
const declarations = [];
|
|
15918
|
-
const
|
|
15941
|
+
const nameExempt = isPageRouteFile(sourceFile2.file) || isUiComponentFile(sourceFile2.file);
|
|
15919
15942
|
for (const statement of sourceFile2.sourceFile.statements) {
|
|
15920
15943
|
if (ts11.isFunctionDeclaration(statement) && statement.name && isExported(statement)) {
|
|
15921
15944
|
declarations.push({
|
|
@@ -15924,7 +15947,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
15924
15947
|
file: sourceFile2.file,
|
|
15925
15948
|
line: getLine(sourceFile2.sourceFile, statement),
|
|
15926
15949
|
bodyFingerprint: getBodyFingerprint(sourceFile2.sourceFile, statement.body),
|
|
15927
|
-
duplicateNameExempt:
|
|
15950
|
+
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, false)
|
|
15928
15951
|
});
|
|
15929
15952
|
}
|
|
15930
15953
|
if (ts11.isClassDeclaration(statement) && statement.name && isExported(statement)) {
|
|
@@ -15934,7 +15957,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
15934
15957
|
file: sourceFile2.file,
|
|
15935
15958
|
line: getLine(sourceFile2.sourceFile, statement),
|
|
15936
15959
|
bodyFingerprint: getBodyFingerprint(sourceFile2.sourceFile, statement),
|
|
15937
|
-
duplicateNameExempt:
|
|
15960
|
+
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, isEnumClassStatement(sourceFile2.sourceFile, statement))
|
|
15938
15961
|
});
|
|
15939
15962
|
}
|
|
15940
15963
|
if (ts11.isVariableStatement(statement) && isExported(statement)) {
|
|
@@ -15947,7 +15970,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
15947
15970
|
file: sourceFile2.file,
|
|
15948
15971
|
line: getLine(sourceFile2.sourceFile, declaration),
|
|
15949
15972
|
bodyFingerprint: getBodyFingerprint(sourceFile2.sourceFile, declaration.initializer),
|
|
15950
|
-
duplicateNameExempt:
|
|
15973
|
+
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, false)
|
|
15951
15974
|
});
|
|
15952
15975
|
}
|
|
15953
15976
|
}
|
|
@@ -15958,6 +15981,10 @@ function isPageRouteFile(file) {
|
|
|
15958
15981
|
const segments = file.split("/");
|
|
15959
15982
|
return (segments[0] === "apps" || segments[0] === "libs") && segments[2] === "page";
|
|
15960
15983
|
}
|
|
15984
|
+
function isUiComponentFile(file) {
|
|
15985
|
+
const segments = file.split("/");
|
|
15986
|
+
return (segments[0] === "apps" || segments[0] === "libs") && segments[2] === "ui";
|
|
15987
|
+
}
|
|
15961
15988
|
function isConventionDuplicateNameExempt(file, isEnumClass) {
|
|
15962
15989
|
if (!isInLibModule(file))
|
|
15963
15990
|
return false;
|
|
@@ -15983,6 +16010,72 @@ function isEnumClassStatement(sourceFile2, statement) {
|
|
|
15983
16010
|
function getExportedClassNames(sourceFile2) {
|
|
15984
16011
|
return sourceFile2.statements.filter((statement) => ts11.isClassDeclaration(statement) && !!statement.name).filter((statement) => isExported(statement)).map((statement) => statement.name.text);
|
|
15985
16012
|
}
|
|
16013
|
+
function isComponentDeclarationFile(file) {
|
|
16014
|
+
if (!file.endsWith(".tsx"))
|
|
16015
|
+
return false;
|
|
16016
|
+
const segments = file.split("/");
|
|
16017
|
+
const [root, , area] = segments;
|
|
16018
|
+
if (root !== "apps" && root !== "libs")
|
|
16019
|
+
return false;
|
|
16020
|
+
if (area === "lib" || area === "ui")
|
|
16021
|
+
return true;
|
|
16022
|
+
return root === "apps" && area === "page";
|
|
16023
|
+
}
|
|
16024
|
+
function getExportedDeclarationNames(sourceFile2) {
|
|
16025
|
+
const names = new Set;
|
|
16026
|
+
for (const statement of sourceFile2.statements) {
|
|
16027
|
+
if (ts11.isExportDeclaration(statement) && statement.exportClause && ts11.isNamedExports(statement.exportClause)) {
|
|
16028
|
+
for (const element of statement.exportClause.elements) {
|
|
16029
|
+
names.add(element.name.text);
|
|
16030
|
+
if (element.propertyName)
|
|
16031
|
+
names.add(element.propertyName.text);
|
|
16032
|
+
}
|
|
16033
|
+
continue;
|
|
16034
|
+
}
|
|
16035
|
+
if (!isExported(statement))
|
|
16036
|
+
continue;
|
|
16037
|
+
for (const name of getStatementDeclarationNames(statement))
|
|
16038
|
+
names.add(name);
|
|
16039
|
+
}
|
|
16040
|
+
return names;
|
|
16041
|
+
}
|
|
16042
|
+
function getStatementDeclarationNames(statement) {
|
|
16043
|
+
if (ts11.isFunctionDeclaration(statement) && statement.name)
|
|
16044
|
+
return [statement.name.text];
|
|
16045
|
+
if (ts11.isClassDeclaration(statement) && statement.name)
|
|
16046
|
+
return [statement.name.text];
|
|
16047
|
+
if (ts11.isInterfaceDeclaration(statement))
|
|
16048
|
+
return [statement.name.text];
|
|
16049
|
+
if (ts11.isTypeAliasDeclaration(statement))
|
|
16050
|
+
return [statement.name.text];
|
|
16051
|
+
if (ts11.isEnumDeclaration(statement))
|
|
16052
|
+
return [statement.name.text];
|
|
16053
|
+
if (ts11.isVariableStatement(statement)) {
|
|
16054
|
+
return statement.declarationList.declarations.filter((declaration) => ts11.isIdentifier(declaration.name)).map((declaration) => declaration.name.text);
|
|
16055
|
+
}
|
|
16056
|
+
return [];
|
|
16057
|
+
}
|
|
16058
|
+
function getInternalTypeOrFunctionDeclarations(sourceFile2) {
|
|
16059
|
+
const declarations = [];
|
|
16060
|
+
for (const statement of sourceFile2.statements) {
|
|
16061
|
+
if (isExported(statement))
|
|
16062
|
+
continue;
|
|
16063
|
+
if (ts11.isInterfaceDeclaration(statement)) {
|
|
16064
|
+
declarations.push({ name: statement.name.text, kind: "interface", line: getLine(sourceFile2, statement) });
|
|
16065
|
+
} else if (ts11.isTypeAliasDeclaration(statement)) {
|
|
16066
|
+
declarations.push({ name: statement.name.text, kind: "type", line: getLine(sourceFile2, statement) });
|
|
16067
|
+
} else if (ts11.isFunctionDeclaration(statement) && statement.name) {
|
|
16068
|
+
declarations.push({ name: statement.name.text, kind: "function", line: getLine(sourceFile2, statement) });
|
|
16069
|
+
} else if (ts11.isVariableStatement(statement)) {
|
|
16070
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
16071
|
+
if (!ts11.isIdentifier(declaration.name) || !isFunctionLikeInitializer(declaration.initializer))
|
|
16072
|
+
continue;
|
|
16073
|
+
declarations.push({ name: declaration.name.text, kind: "function", line: getLine(sourceFile2, declaration) });
|
|
16074
|
+
}
|
|
16075
|
+
}
|
|
16076
|
+
}
|
|
16077
|
+
return declarations;
|
|
16078
|
+
}
|
|
15986
16079
|
function getPlaceholderExportWarnings(sourceFile2) {
|
|
15987
16080
|
if (!sourceFile2.file.endsWith("/index.ts") && !sourceFile2.file.endsWith("/index.tsx"))
|
|
15988
16081
|
return [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/cli",
|
|
3
|
-
"version": "2.3.11-rc.
|
|
3
|
+
"version": "2.3.11-rc.9",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@langchain/openai": "^1.4.6",
|
|
35
35
|
"@tailwindcss/node": "^4.3.0",
|
|
36
36
|
"@trapezedev/project": "^7.1.4",
|
|
37
|
-
"akanjs": "2.3.11-rc.
|
|
37
|
+
"akanjs": "2.3.11-rc.9",
|
|
38
38
|
"chalk": "^5.6.2",
|
|
39
39
|
"commander": "^14.0.3",
|
|
40
40
|
"daisyui": "5.5.23",
|
|
@@ -132,6 +132,20 @@
|
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
"overrides": [
|
|
135
|
+
{
|
|
136
|
+
"includes": [
|
|
137
|
+
"apps/**/*.ts",
|
|
138
|
+
"apps/**/*.tsx",
|
|
139
|
+
"libs/**/*.ts",
|
|
140
|
+
"libs/**/*.tsx",
|
|
141
|
+
"!**/*.test.ts",
|
|
142
|
+
"!**/*.test.tsx",
|
|
143
|
+
"!**/*.spec.ts",
|
|
144
|
+
"!**/*.spec.tsx",
|
|
145
|
+
"!**/common/**"
|
|
146
|
+
],
|
|
147
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-throw-raw-error.grit"]
|
|
148
|
+
},
|
|
135
149
|
{
|
|
136
150
|
"includes": ["**/page/**/*.ts", "**/page/**/*.tsx", "**/*.Unit.tsx", "**/*.View.tsx"],
|
|
137
151
|
"plugins": [
|