@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/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.1.1",
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 path11 from "path";
913
+ import path12 from "path";
906
914
 
907
- // src/_rules/_rules@shared/_utils/_systems/get-private-category-owner/get-private-category-owner.util.ts
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 getPrivateCategoryOwner(relPath, config) {
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/no-fractal-branch-leak/no-fractal-branch-leak.rule.ts
927
- function getFractalBranchOwner(relPath) {
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 = path11.dirname(resolvedRelPath);
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 privateOwner = getPrivateCategoryOwner(importedDir, config);
974
- if (privateOwner) {
975
- const isPrivateDescendant = relPath === privateOwner || relPath.startsWith(privateOwner + "/");
976
- if (!isPrivateDescendant) {
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 "${privateOwner}".`,
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 path12 from "path";
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 = path12.basename(dirPath);
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 = path12.relative(lcaPath, relPath).replace(/\\/g, "/");
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 = path12.dirname(current).replace(/\\/g, "/");
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 = path12.dirname(relPath);
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 = path12.dirname(resolvedRelPath);
1216
+ const importedDir = path13.dirname(resolvedRelPath);
1178
1217
  if (currentDir === importedDir) {
1179
- const fileA = path12.basename(relPath);
1180
- const fileB = path12.basename(resolvedRelPath);
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: "${path12.basename(relPath)}" cannot import from "${path12.basename(resolvedRelPath)}" under Root Fragment "${lca}".`,
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(path12.posix.join(lca, subA), config);
1235
- const roleB = getDirectoryRole(path12.posix.join(lca, subB), config);
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 path13 from "path";
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 = path13.dirname(resolvedRelPath);
1301
- const owner = getPrivateCategoryOwner(importedDir, config);
1302
- if (owner) {
1303
- const isDescendant = relPath === owner || relPath.startsWith(owner + "/");
1304
- if (!isDescendant) {
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