@morriconeluca/eslint-plugin-faf 0.1.1 → 0.2.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/README.md +6 -6
- package/dist/main.cjs +96 -39
- package/dist/main.cjs.map +1 -1
- package/dist/main.js +96 -39
- package/dist/main.js.map +1 -1
- package/package.json +7 -2
package/dist/main.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@morriconeluca/eslint-plugin-faf",
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "0.2.0",
|
|
5
5
|
description: "An ESLint plugin for FAF projects.",
|
|
6
|
+
repository: {
|
|
7
|
+
type: "git",
|
|
8
|
+
url: "git+https://github.com/morriconeluca/eslint-plugin-faf.git"
|
|
9
|
+
},
|
|
6
10
|
main: "./dist/main.cjs",
|
|
7
11
|
module: "./dist/main.js",
|
|
8
12
|
types: "./dist/main.d.ts",
|
|
@@ -14,7 +18,8 @@ var package_default = {
|
|
|
14
18
|
}
|
|
15
19
|
},
|
|
16
20
|
publishConfig: {
|
|
17
|
-
access: "public"
|
|
21
|
+
access: "public",
|
|
22
|
+
provenance: true
|
|
18
23
|
},
|
|
19
24
|
imports: {
|
|
20
25
|
"#_rules@shared/*": "./src/_rules/_rules@shared/*",
|
|
@@ -315,6 +320,9 @@ var rule = {
|
|
|
315
320
|
if (catConfig) {
|
|
316
321
|
const ext = path5.extname(fileName);
|
|
317
322
|
const isAllowedAsset = catConfig.allowedExtensions?.includes(ext) ?? false;
|
|
323
|
+
if (!isAllowedAsset && catConfig.allowedExtensions && catConfig.allowedExtensions.length > 0) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
318
326
|
if (!catConfig.allowSingleFiles && !isAllowedAsset) {
|
|
319
327
|
context.report({
|
|
320
328
|
message: `Category "${folderName}" cannot contain file nodes directly. File "${fileName}" must be encapsulated inside a Fragment.`,
|
|
@@ -902,43 +910,56 @@ var rule4 = {
|
|
|
902
910
|
var no_direct_fragment_import_rule_default = rule4;
|
|
903
911
|
|
|
904
912
|
// src/_rules/no-fractal-branch-leak/no-fractal-branch-leak.rule.ts
|
|
905
|
-
import
|
|
913
|
+
import path12 from "path";
|
|
906
914
|
|
|
907
|
-
// src/_rules/_rules@shared/_utils/
|
|
915
|
+
// src/_rules/_rules@shared/_utils/_primitives/get-fractal-branch-owner/get-fractal-branch-owner.util.ts
|
|
908
916
|
import path10 from "path";
|
|
909
|
-
function
|
|
917
|
+
function getFractalBranchOwner(relPath) {
|
|
910
918
|
let current = relPath;
|
|
911
919
|
while (current && current !== "." && current !== "/") {
|
|
920
|
+
const folderName = path10.basename(current);
|
|
921
|
+
if (folderName.startsWith("_") && folderName.includes("@shared")) {
|
|
922
|
+
return path10.dirname(current).replace(/\\/g, "/");
|
|
923
|
+
}
|
|
912
924
|
const parent = path10.dirname(current).replace(/\\/g, "/");
|
|
913
925
|
if (parent === current) {
|
|
914
926
|
break;
|
|
915
927
|
}
|
|
916
|
-
const currentType = classifyFolder(current, config);
|
|
917
|
-
const parentType = classifyFolder(parent, config);
|
|
918
|
-
if (currentType === "category" && (parentType === "fragment" || parentType === "root-fragment")) {
|
|
919
|
-
return parent;
|
|
920
|
-
}
|
|
921
928
|
current = parent;
|
|
922
929
|
}
|
|
923
930
|
return null;
|
|
924
931
|
}
|
|
925
932
|
|
|
926
|
-
// src/_rules/
|
|
927
|
-
function
|
|
933
|
+
// src/_rules/_rules@shared/_utils/_primitives/get-immediate-sub-domain/get-immediate-sub-domain.util.ts
|
|
934
|
+
function getImmediateSubDomain(relPath, privateCategoryPath) {
|
|
935
|
+
if (relPath !== privateCategoryPath && !relPath.startsWith(privateCategoryPath + "/")) {
|
|
936
|
+
return "";
|
|
937
|
+
}
|
|
938
|
+
const relative = relPath.substring(privateCategoryPath.length + 1);
|
|
939
|
+
const firstSegment = relative.split("/")[0];
|
|
940
|
+
return firstSegment ? privateCategoryPath + "/" + firstSegment : privateCategoryPath;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
// src/_rules/_rules@shared/_utils/_systems/get-private-category-info/get-private-category-info.util.ts
|
|
944
|
+
import path11 from "path";
|
|
945
|
+
function getPrivateCategoryInfo(relPath, config) {
|
|
928
946
|
let current = relPath;
|
|
929
947
|
while (current && current !== "." && current !== "/") {
|
|
930
|
-
const folderName = path11.basename(current);
|
|
931
|
-
if (folderName.startsWith("_") && folderName.includes("@shared")) {
|
|
932
|
-
return path11.dirname(current).replace(/\\/g, "/");
|
|
933
|
-
}
|
|
934
948
|
const parent = path11.dirname(current).replace(/\\/g, "/");
|
|
935
949
|
if (parent === current) {
|
|
936
950
|
break;
|
|
937
951
|
}
|
|
952
|
+
const currentType = classifyFolder(current, config);
|
|
953
|
+
const parentType = classifyFolder(parent, config);
|
|
954
|
+
if (currentType === "category" && (parentType === "fragment" || parentType === "root-fragment")) {
|
|
955
|
+
return { owner: parent, privateCategoryPath: current };
|
|
956
|
+
}
|
|
938
957
|
current = parent;
|
|
939
958
|
}
|
|
940
959
|
return null;
|
|
941
960
|
}
|
|
961
|
+
|
|
962
|
+
// src/_rules/no-fractal-branch-leak/no-fractal-branch-leak.rule.ts
|
|
942
963
|
var rule5 = {
|
|
943
964
|
create(context) {
|
|
944
965
|
const absPath = context.filename;
|
|
@@ -960,7 +981,7 @@ var rule5 = {
|
|
|
960
981
|
if (!resolvedRelPath) {
|
|
961
982
|
return;
|
|
962
983
|
}
|
|
963
|
-
const importedDir =
|
|
984
|
+
const importedDir = path12.dirname(resolvedRelPath);
|
|
964
985
|
const owner = getFractalBranchOwner(importedDir);
|
|
965
986
|
if (owner) {
|
|
966
987
|
const isDescendant = relPath === owner || relPath.startsWith(owner + "/");
|
|
@@ -970,12 +991,30 @@ var rule5 = {
|
|
|
970
991
|
node
|
|
971
992
|
});
|
|
972
993
|
} else {
|
|
973
|
-
const
|
|
974
|
-
if (
|
|
975
|
-
const
|
|
976
|
-
|
|
994
|
+
const info = getPrivateCategoryInfo(importedDir, config);
|
|
995
|
+
if (info) {
|
|
996
|
+
const { owner: owner2, privateCategoryPath } = info;
|
|
997
|
+
const isPrivateDirectChild = path12.dirname(relPath) === owner2;
|
|
998
|
+
const importerSubDomain = getImmediateSubDomain(
|
|
999
|
+
relPath,
|
|
1000
|
+
privateCategoryPath
|
|
1001
|
+
);
|
|
1002
|
+
const importedSubDomain = getImmediateSubDomain(
|
|
1003
|
+
resolvedRelPath,
|
|
1004
|
+
privateCategoryPath
|
|
1005
|
+
);
|
|
1006
|
+
const isInsideSameSubDomain = importerSubDomain !== "" && importerSubDomain === importedSubDomain;
|
|
1007
|
+
let isFractalBranchAllowed = false;
|
|
1008
|
+
const fbOwner = getFractalBranchOwner(importedDir);
|
|
1009
|
+
if (fbOwner) {
|
|
1010
|
+
const isFbInsidePrivateCategory = fbOwner === privateCategoryPath || fbOwner.startsWith(privateCategoryPath + "/");
|
|
1011
|
+
if (isFbInsidePrivateCategory) {
|
|
1012
|
+
isFractalBranchAllowed = relPath === fbOwner || relPath.startsWith(fbOwner + "/");
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
if (!isPrivateDirectChild && !isInsideSameSubDomain && !isFractalBranchAllowed) {
|
|
977
1016
|
context.report({
|
|
978
|
-
message: `Importing from Private Category is forbidden. The imported resource is private to "${
|
|
1017
|
+
message: `Importing from Private Category is forbidden. The imported resource is private to "${owner2}".`,
|
|
979
1018
|
node
|
|
980
1019
|
});
|
|
981
1020
|
}
|
|
@@ -1008,7 +1047,7 @@ var rule5 = {
|
|
|
1008
1047
|
var no_fractal_branch_leak_rule_default = rule5;
|
|
1009
1048
|
|
|
1010
1049
|
// src/_rules/no-peer-dependency/no-peer-dependency.rule.ts
|
|
1011
|
-
import
|
|
1050
|
+
import path13 from "path";
|
|
1012
1051
|
|
|
1013
1052
|
// src/_rules/_rules@shared/_utils/_primitives/find-tree-config-including-excluded/find-tree-config-including-excluded.util.ts
|
|
1014
1053
|
function findTreeConfigIncludingExcluded(relPath, settings) {
|
|
@@ -1086,7 +1125,7 @@ function resolveHorizontalHierarchy(lcaPath, subA, subB, config) {
|
|
|
1086
1125
|
|
|
1087
1126
|
// src/_rules/no-peer-dependency/no-peer-dependency.rule.ts
|
|
1088
1127
|
function getDirectoryRole(dirPath, config) {
|
|
1089
|
-
const folderName =
|
|
1128
|
+
const folderName = path13.basename(dirPath);
|
|
1090
1129
|
if (folderName.startsWith("_")) {
|
|
1091
1130
|
return getRoleFromFolderName(folderName, config);
|
|
1092
1131
|
}
|
|
@@ -1104,7 +1143,7 @@ function getRoleFromFolderName(name, config) {
|
|
|
1104
1143
|
return catConfig ? catConfig.role ?? null : null;
|
|
1105
1144
|
}
|
|
1106
1145
|
function getRootNodeIndex(relPath, rfConfig, lcaPath) {
|
|
1107
|
-
const relToLca =
|
|
1146
|
+
const relToLca = path13.relative(lcaPath, relPath).replace(/\\/g, "/");
|
|
1108
1147
|
for (let i = 0; i < rfConfig.rootNodes.length; i++) {
|
|
1109
1148
|
const group = rfConfig.rootNodes[i];
|
|
1110
1149
|
if (group && group.includes(relToLca)) {
|
|
@@ -1116,7 +1155,7 @@ function getRootNodeIndex(relPath, rfConfig, lcaPath) {
|
|
|
1116
1155
|
function isInsidePrivateCategoryOfLca(relPathB, lcaPath, config) {
|
|
1117
1156
|
let current = relPathB;
|
|
1118
1157
|
while (current && current !== "." && current !== "/" && current !== lcaPath) {
|
|
1119
|
-
const parent =
|
|
1158
|
+
const parent = path13.dirname(current).replace(/\\/g, "/");
|
|
1120
1159
|
if (parent === current) {
|
|
1121
1160
|
break;
|
|
1122
1161
|
}
|
|
@@ -1141,7 +1180,7 @@ var rule6 = {
|
|
|
1141
1180
|
if (!config) {
|
|
1142
1181
|
return {};
|
|
1143
1182
|
}
|
|
1144
|
-
const currentDir =
|
|
1183
|
+
const currentDir = path13.dirname(relPath);
|
|
1145
1184
|
const isCurrentFileExcluded = config.excludes?.some(
|
|
1146
1185
|
(exc) => relPath === exc || relPath.startsWith(exc + "/")
|
|
1147
1186
|
) ?? false;
|
|
@@ -1174,10 +1213,10 @@ var rule6 = {
|
|
|
1174
1213
|
if (isCurrentFileExcluded || isImportedFileExcluded) {
|
|
1175
1214
|
return;
|
|
1176
1215
|
}
|
|
1177
|
-
const importedDir =
|
|
1216
|
+
const importedDir = path13.dirname(resolvedRelPath);
|
|
1178
1217
|
if (currentDir === importedDir) {
|
|
1179
|
-
const fileA =
|
|
1180
|
-
const fileB =
|
|
1218
|
+
const fileA = path13.basename(relPath);
|
|
1219
|
+
const fileB = path13.basename(resolvedRelPath);
|
|
1181
1220
|
const roleA = getFileRole(fileA, config);
|
|
1182
1221
|
const roleB = getFileRole(fileB, config);
|
|
1183
1222
|
if (roleA && roleB) {
|
|
@@ -1215,7 +1254,7 @@ var rule6 = {
|
|
|
1215
1254
|
if (idxRootA !== -1 && idxRootB !== -1) {
|
|
1216
1255
|
if (idxRootB >= idxRootA) {
|
|
1217
1256
|
context.report({
|
|
1218
|
-
message: `Root Node import violation: "${
|
|
1257
|
+
message: `Root Node import violation: "${path13.basename(relPath)}" cannot import from "${path13.basename(resolvedRelPath)}" under Root Fragment "${lca}".`,
|
|
1219
1258
|
node
|
|
1220
1259
|
});
|
|
1221
1260
|
}
|
|
@@ -1231,8 +1270,8 @@ var rule6 = {
|
|
|
1231
1270
|
});
|
|
1232
1271
|
}
|
|
1233
1272
|
} else {
|
|
1234
|
-
const roleA = getDirectoryRole(
|
|
1235
|
-
const roleB = getDirectoryRole(
|
|
1273
|
+
const roleA = getDirectoryRole(path13.posix.join(lca, subA), config);
|
|
1274
|
+
const roleB = getDirectoryRole(path13.posix.join(lca, subB), config);
|
|
1236
1275
|
const idxA = roleA ? getRoleHierarchyIndex(roleA, config) : -1;
|
|
1237
1276
|
const idxB = roleB ? getRoleHierarchyIndex(roleB, config) : -1;
|
|
1238
1277
|
if (idxA !== -1 && idxB !== -1) {
|
|
@@ -1275,7 +1314,7 @@ var rule6 = {
|
|
|
1275
1314
|
var no_peer_dependency_rule_default = rule6;
|
|
1276
1315
|
|
|
1277
1316
|
// src/_rules/no-private-category-leak/no-private-category-leak.rule.ts
|
|
1278
|
-
import
|
|
1317
|
+
import path14 from "path";
|
|
1279
1318
|
var rule7 = {
|
|
1280
1319
|
create(context) {
|
|
1281
1320
|
const absPath = context.filename;
|
|
@@ -1297,11 +1336,29 @@ var rule7 = {
|
|
|
1297
1336
|
if (!resolvedRelPath) {
|
|
1298
1337
|
return;
|
|
1299
1338
|
}
|
|
1300
|
-
const importedDir =
|
|
1301
|
-
const
|
|
1302
|
-
if (
|
|
1303
|
-
const
|
|
1304
|
-
|
|
1339
|
+
const importedDir = path14.dirname(resolvedRelPath);
|
|
1340
|
+
const info = getPrivateCategoryInfo(importedDir, config);
|
|
1341
|
+
if (info) {
|
|
1342
|
+
const { owner, privateCategoryPath } = info;
|
|
1343
|
+
const isDirectChild = path14.dirname(relPath) === owner;
|
|
1344
|
+
const importerSubDomain = getImmediateSubDomain(
|
|
1345
|
+
relPath,
|
|
1346
|
+
privateCategoryPath
|
|
1347
|
+
);
|
|
1348
|
+
const importedSubDomain = getImmediateSubDomain(
|
|
1349
|
+
resolvedRelPath,
|
|
1350
|
+
privateCategoryPath
|
|
1351
|
+
);
|
|
1352
|
+
const isInsideSameSubDomain = importerSubDomain !== "" && importerSubDomain === importedSubDomain;
|
|
1353
|
+
let isFractalBranchAllowed = false;
|
|
1354
|
+
const fbOwner = getFractalBranchOwner(importedDir);
|
|
1355
|
+
if (fbOwner) {
|
|
1356
|
+
const isFbInsidePrivateCategory = fbOwner === privateCategoryPath || fbOwner.startsWith(privateCategoryPath + "/");
|
|
1357
|
+
if (isFbInsidePrivateCategory) {
|
|
1358
|
+
isFractalBranchAllowed = relPath === fbOwner || relPath.startsWith(fbOwner + "/");
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
if (!isDirectChild && !isInsideSameSubDomain && !isFractalBranchAllowed) {
|
|
1305
1362
|
context.report({
|
|
1306
1363
|
message: `Importing from Private Category is forbidden. The imported resource is private to "${owner}".`,
|
|
1307
1364
|
node
|