@morriconeluca/eslint-plugin-faf 0.6.0 → 0.6.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/dist/main.cjs CHANGED
@@ -37,7 +37,7 @@ module.exports = __toCommonJS(main_exports);
37
37
  // package.json
38
38
  var package_default = {
39
39
  name: "@morriconeluca/eslint-plugin-faf",
40
- version: "0.6.0",
40
+ version: "0.6.1",
41
41
  description: "An ESLint plugin for FAF projects.",
42
42
  repository: {
43
43
  type: "git",
@@ -115,12 +115,12 @@ var package_default = {
115
115
  "@stryker-mutator/core": "^10.1.1",
116
116
  "@stryker-mutator/vitest-runner": "^10.1.1",
117
117
  "@types/node": "^25.9.3",
118
- "@typescript-eslint/utils": "^8.24.1",
118
+ "@typescript-eslint/utils": "^8.72.2",
119
119
  "@vitest/coverage-v8": "^4.1.12",
120
120
  "dependency-cruiser": "^17.4.3",
121
121
  eslint: "^10.14.0",
122
122
  "eslint-import-resolver-typescript": "^4.4.5",
123
- "eslint-plugin-import-x": "^4.16.2",
123
+ "eslint-plugin-import-x": "^4.18.1",
124
124
  "eslint-plugin-jsdoc": "^65.4.2",
125
125
  "eslint-plugin-perfectionist": "^5.9.0",
126
126
  "eslint-plugin-sonarjs": "^4.2.2",
@@ -132,9 +132,14 @@ var package_default = {
132
132
  publint: "^0.3.25",
133
133
  tsup: "^8.3.6",
134
134
  typescript: "^6.0.3",
135
- "typescript-eslint": "^8.61.0",
135
+ "typescript-eslint": "^8.72.2",
136
136
  vitest: "^4.1.9"
137
137
  },
138
+ overrides: {
139
+ esbuild: "^0.28.2",
140
+ minimatch: "^11.0.5",
141
+ qs: "^6.17.1"
142
+ },
138
143
  "lint-staged": {
139
144
  "*": "prettier --write --ignore-unknown",
140
145
  "src/**/*.ts": "eslint --fix"
@@ -176,12 +181,15 @@ var REFERENCE_D_08 = "D-08";
176
181
  var REFERENCE_D_09 = "D-09";
177
182
  var REFERENCE_D_14 = "D-14";
178
183
  var REFERENCE_FAF_4 = "FAF \xA74";
184
+ var REFERENCE_FAF_4_6_3_1 = "FAF \xA74, \xA76.3.1";
179
185
  var REFERENCE_FAF_4_6_3_5_6_6 = "FAF \xA74, \xA76.3.5, \xA76.6";
180
186
  var REFERENCE_FAF_4_6_7 = "FAF \xA74, \xA76.7";
181
187
  var REFERENCE_FAF_5 = "FAF \xA75";
182
188
  var REFERENCE_FAF_6 = "FAF \xA76";
183
189
  var REFERENCE_FAF_6_1_1 = "FAF \xA76.1.1";
184
190
  var REFERENCE_FAF_6_1_3 = "FAF \xA76.1.3";
191
+ var REFERENCE_FAF_6_2 = "FAF \xA76.2";
192
+ var REFERENCE_FAF_6_2_1 = "FAF \xA76.2.1";
185
193
  var REFERENCE_FAF_6_2_2 = "FAF \xA76.2.2";
186
194
  var REFERENCE_FAF_6_3_1 = "FAF \xA76.3.1";
187
195
  var REFERENCE_FAF_6_3_2_MULTIPLE = "FAF \xA76.3.2, \xA76.4.1, \xA76.5.1, \xA76.6.1";
@@ -478,8 +486,8 @@ var OUTCOME_CATALOG = {
478
486
  "configuration/invalid-file-name": {
479
487
  family: "configuration",
480
488
  form: "element",
481
- normativeReference: REFERENCE_FAF_4,
482
- predicate: "must adhere to kebab-case grammar"
489
+ normativeReference: REFERENCE_D_05,
490
+ predicate: "must be a direct child file name without path separators"
483
491
  },
484
492
  "configuration/invalid-foreign-pattern": {
485
493
  family: "configuration",
@@ -490,8 +498,8 @@ var OUTCOME_CATALOG = {
490
498
  "configuration/invalid-implicit-extension": {
491
499
  family: "configuration",
492
500
  form: "element",
493
- normativeReference: REFERENCE_FAF_6_3_1,
494
- predicate: "must start with a dot and contain only lowercase letters"
501
+ normativeReference: REFERENCE_FAF_4_6_3_1,
502
+ predicate: "must be a dot-prefixed asset extension reserved to non-script files"
495
503
  },
496
504
  "configuration/invalid-literal-path": {
497
505
  family: "configuration",
@@ -568,7 +576,7 @@ var OUTCOME_CATALOG = {
568
576
  "configuration/nested-root-fragment-not-direct-child": {
569
577
  family: "configuration",
570
578
  form: "element",
571
- normativeReference: REFERENCE_FAF_6_2_2,
579
+ normativeReference: REFERENCE_FAF_6_2,
572
580
  predicate: "must be a direct child directory of the root fragment"
573
581
  },
574
582
  "configuration/non-existent-path": {
@@ -646,7 +654,7 @@ var OUTCOME_CATALOG = {
646
654
  "configuration/root-node-not-direct-child": {
647
655
  family: "configuration",
648
656
  form: "element",
649
- normativeReference: REFERENCE_FAF_6_2_2,
657
+ normativeReference: REFERENCE_FAF_6_2_1,
650
658
  predicate: "must be a direct child root node of the root fragment"
651
659
  },
652
660
  "configuration/scope-mismatch": {
@@ -682,13 +690,13 @@ var OUTCOME_CATALOG = {
682
690
  "configuration/undeclared-sub-root-fragment": {
683
691
  family: "configuration",
684
692
  form: "element",
685
- normativeReference: REFERENCE_FAF_6_2_2,
693
+ normativeReference: REFERENCE_FAF_6_2,
686
694
  predicate: "must be declared in subRootFragments"
687
695
  },
688
696
  "configuration/unenumerated-root-file": {
689
697
  family: "configuration",
690
698
  form: "element",
691
- normativeReference: REFERENCE_FAF_6_2_2,
699
+ normativeReference: REFERENCE_FAF_6_2_1,
692
700
  predicate: "must be either enumerated as a Root Node or designated as a Foreign Node"
693
701
  },
694
702
  "configuration/unknown-property": {
@@ -1649,7 +1657,7 @@ function resolveSpecifiers(baseDirectory, aliases) {
1649
1657
  const tsconfigCandidate = import_node_path10.default.join(resolvedBase, "tsconfig.json");
1650
1658
  const hasTsconfig = import_node_fs10.default.existsSync(tsconfigCandidate);
1651
1659
  const tsconfig = hasTsconfig ? { configFile: tsconfigCandidate, references: "auto" } : void 0;
1652
- const resolver = new import_oxc_resolver.ResolverFactory({
1660
+ const resolverOptions = {
1653
1661
  builtinModules: true,
1654
1662
  conditionNames: ["import", "require", "node", "types", "style", "default"],
1655
1663
  extensionAlias: {
@@ -1670,9 +1678,13 @@ function resolveSpecifiers(baseDirectory, aliases) {
1670
1678
  ".json",
1671
1679
  ".css"
1672
1680
  ],
1673
- importsFields: [["imports"]],
1681
+ importsFields: [["imports"]]
1682
+ };
1683
+ const resolver = new import_oxc_resolver.ResolverFactory({
1684
+ ...resolverOptions,
1674
1685
  tsconfig
1675
1686
  });
1687
+ const noTsconfigResolver = hasTsconfig ? new import_oxc_resolver.ResolverFactory(resolverOptions) : null;
1676
1688
  const resolutionCache = /* @__PURE__ */ new Map();
1677
1689
  const toCanonicalPath = (filePath) => {
1678
1690
  try {
@@ -1681,17 +1693,58 @@ function resolveSpecifiers(baseDirectory, aliases) {
1681
1693
  return filePath;
1682
1694
  }
1683
1695
  };
1696
+ const isCandidateForDiscordanceCheck = (cleanSpecifier, aliasUsed, hasUsedRelativeFallback, isBuiltin, resolvedPath) => {
1697
+ const isContextEligible = hasTsconfig && aliasUsed === null && !hasUsedRelativeFallback;
1698
+ const isBare = !cleanSpecifier.startsWith(".") && !cleanSpecifier.startsWith("/");
1699
+ const isLocal = !isBuiltin && resolvedPath !== void 0;
1700
+ const isOutsideNodeModules = resolvedPath !== void 0 && !toPosixPath(resolvedPath).includes(NODE_MODULES_MARKER);
1701
+ return isContextEligible && isBare && isLocal && isOutsideNodeModules;
1702
+ };
1703
+ const resolveWithoutTsconfig = (directory, specifier) => {
1704
+ if (noTsconfigResolver === null) {
1705
+ return null;
1706
+ }
1707
+ try {
1708
+ const result = noTsconfigResolver.sync(directory, specifier);
1709
+ if (result.path === void 0) {
1710
+ return null;
1711
+ }
1712
+ const cleanPath = result.path.split("?", 1)[0] ?? result.path;
1713
+ return toCanonicalPath(cleanPath);
1714
+ } catch {
1715
+ return null;
1716
+ }
1717
+ };
1718
+ const resolveWithFallback = (directory, specifier, canFallbackToBare) => {
1719
+ let result = resolver.sync(directory, specifier);
1720
+ if (canFallbackToBare && result.path === void 0 && specifier.startsWith("./")) {
1721
+ result = resolver.sync(directory, specifier.slice(2));
1722
+ return { hasUsedFallback: true, result };
1723
+ }
1724
+ return { hasUsedFallback: false, result };
1725
+ };
1726
+ const acquireCanonicalResult = (rawResult) => {
1727
+ if (rawResult.path === void 0) {
1728
+ return rawResult;
1729
+ }
1730
+ const cleanPath = rawResult.path.split("?", 1)[0] ?? rawResult.path;
1731
+ return {
1732
+ ...rawResult,
1733
+ path: toCanonicalPath(cleanPath)
1734
+ };
1735
+ };
1684
1736
  const resolveSingle = (directory, specifier, canFallbackToBare) => {
1685
1737
  const cleanSpecifier = specifier.split("?", 1)[0] ?? specifier;
1686
1738
  const matchedAlias = matchPathAlias(cleanSpecifier, aliases);
1687
1739
  const aliasUsed = matchedAlias?.alias.prefix ?? null;
1688
1740
  const aliasAlternatives = matchedAlias?.targets ?? [];
1689
- let resolveResult;
1741
+ let fallbackOutcome;
1690
1742
  try {
1691
- resolveResult = resolver.sync(directory, specifier);
1692
- if (canFallbackToBare && resolveResult.path === void 0 && specifier.startsWith("./")) {
1693
- resolveResult = resolver.sync(directory, specifier.slice(2));
1694
- }
1743
+ fallbackOutcome = resolveWithFallback(
1744
+ directory,
1745
+ specifier,
1746
+ canFallbackToBare
1747
+ );
1695
1748
  } catch (error) {
1696
1749
  assertInvariant(error instanceof Error, "Expected resolver error");
1697
1750
  return {
@@ -1703,13 +1756,28 @@ function resolveSpecifiers(baseDirectory, aliases) {
1703
1756
  }
1704
1757
  };
1705
1758
  }
1706
- let acquiredResolveResult = resolveResult;
1707
- if (resolveResult.path !== void 0) {
1708
- const cleanResolvedPath = resolveResult.path.split("?", 1)[0] ?? resolveResult.path;
1709
- acquiredResolveResult = {
1710
- ...resolveResult,
1711
- path: toCanonicalPath(cleanResolvedPath)
1712
- };
1759
+ const acquiredResolveResult = acquireCanonicalResult(
1760
+ fallbackOutcome.result
1761
+ );
1762
+ const isCandidate = isCandidateForDiscordanceCheck(
1763
+ cleanSpecifier,
1764
+ aliasUsed,
1765
+ fallbackOutcome.hasUsedFallback,
1766
+ acquiredResolveResult.builtin !== void 0,
1767
+ acquiredResolveResult.path
1768
+ );
1769
+ if (isCandidate) {
1770
+ const nonTsconfigPath = resolveWithoutTsconfig(directory, specifier);
1771
+ if (nonTsconfigPath === null || nonTsconfigPath !== acquiredResolveResult.path) {
1772
+ return {
1773
+ aliasAlternatives,
1774
+ aliasUsed,
1775
+ target: {
1776
+ reason: DISCORDANCE_REASON,
1777
+ type: "unresolved"
1778
+ }
1779
+ };
1780
+ }
1713
1781
  }
1714
1782
  const target = classifyResolutionTarget({
1715
1783
  aliasAlternatives,
@@ -2105,6 +2173,13 @@ function extractDefaultExport(statement, rootSymbols, importedBindings, locator)
2105
2173
  };
2106
2174
  }
2107
2175
 
2176
+ // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-module-exports/_utils/extract-named-specifiers-exports/_utils/extract-local-specifiers/_utils/is-local-type-export/is-local-type-export.util.ts
2177
+ function isLocalTypeExport(isExplicitlyTypeOnly, binding, localName, rootSymbols) {
2178
+ return isExplicitlyTypeOnly && binding !== void 0 && !binding.isTypeOnly && rootSymbols.some(
2179
+ (symbol) => symbol.name === localName && symbol.space === "type"
2180
+ );
2181
+ }
2182
+
2108
2183
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-module-exports/_utils/extract-named-specifiers-exports/_utils/extract-local-specifiers/extract-local-specifiers.util.ts
2109
2184
  function extractLocalSpecifiers(statement, rootSymbols, importedBindings, locator, exports2) {
2110
2185
  const isDeclarationTypeOnly = statement.exportKind === "type";
@@ -2113,8 +2188,9 @@ function extractLocalSpecifiers(statement, rootSymbols, importedBindings, locato
2113
2188
  const localName = getExportedName(specifier.local);
2114
2189
  const position = locator(specifier.start);
2115
2190
  const binding = importedBindings.get(localName);
2116
- if (binding === void 0) {
2117
- const isTypeOnly = isDeclarationTypeOnly || specifier.exportKind === "type" || isAllTypeSpace(localName, rootSymbols);
2191
+ const isExplicitlyTypeOnly = isDeclarationTypeOnly || specifier.exportKind === "type";
2192
+ if (binding === void 0 || isLocalTypeExport(isExplicitlyTypeOnly, binding, localName, rootSymbols)) {
2193
+ const isTypeOnly = isExplicitlyTypeOnly || isAllTypeSpace(localName, rootSymbols);
2118
2194
  exports2.push({
2119
2195
  exportedName,
2120
2196
  isTypeOnly,
@@ -2122,7 +2198,7 @@ function extractLocalSpecifiers(statement, rootSymbols, importedBindings, locato
2122
2198
  position
2123
2199
  });
2124
2200
  } else {
2125
- const isTypeOnly = isDeclarationTypeOnly || specifier.exportKind === "type" || binding.isTypeOnly;
2201
+ const isTypeOnly = isExplicitlyTypeOnly || binding.isTypeOnly;
2126
2202
  const origin = binding.isNamespace ? { specifier: binding.specifier, type: NAMESPACE_ORIGIN } : {
2127
2203
  importedName: binding.importedName,
2128
2204
  specifier: binding.specifier,
@@ -2621,64 +2697,67 @@ var BINDING_PATTERN_TYPES = /* @__PURE__ */ new Set([
2621
2697
  "ObjectPattern",
2622
2698
  "RestElement"
2623
2699
  ]);
2700
+ var EXPORTS_NAME = "exports";
2624
2701
  var FUNCTION_AST_TYPES = /* @__PURE__ */ new Set([
2625
2702
  "ArrowFunctionExpression",
2626
2703
  "FunctionDeclaration",
2627
2704
  "FunctionExpression"
2628
2705
  ]);
2706
+ var MODULE_NAME = "module";
2629
2707
  var REQUIRE_NAME = "require";
2708
+ var UNSUPPORTED_COMMONJS_MESSAGE = "CommonJS export assignment (module.exports / exports) is unsupported";
2630
2709
  var UNSUPPORTED_REQUIRE_MESSAGE = "Unsupported non-literal require call";
2631
2710
 
2632
2711
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/does-node-declare-require/_does-node-declare-require@shared/_utils/_primitives/does-pattern-bind-require/does-pattern-bind-require.util.ts
2633
- function doesPatternBindRequire(pattern) {
2712
+ function doesPatternBindRequire(pattern, name = REQUIRE_NAME) {
2634
2713
  let current = pattern;
2635
2714
  while (current.type === "AssignmentPattern" || current.type === "RestElement") {
2636
2715
  current = current.type === "AssignmentPattern" ? current.left : current.argument;
2637
2716
  }
2638
2717
  if (current.type === "Identifier") {
2639
- return current.name === REQUIRE_NAME;
2718
+ return current.name === name;
2640
2719
  }
2641
2720
  if (current.type === "ArrayPattern") {
2642
2721
  return current.elements.some(
2643
- (element) => element !== null && doesPatternBindRequire(element)
2722
+ (element) => element !== null && doesPatternBindRequire(element, name)
2644
2723
  );
2645
2724
  }
2646
2725
  return current.properties.some((property) => {
2647
2726
  const next = property.type === "Property" ? property.value : property.argument;
2648
- return doesPatternBindRequire(next);
2727
+ return doesPatternBindRequire(next, name);
2649
2728
  });
2650
2729
  }
2651
2730
 
2652
2731
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/does-node-declare-require/_does-node-declare-require@shared/_utils/_compounds/does-statement-declare-require/_utils/does-target-declare-require/does-target-declare-require.util.ts
2653
- function doesTargetDeclareRequire(statement) {
2732
+ function doesTargetDeclareRequire(statement, name = REQUIRE_NAME) {
2654
2733
  if (statement.type === "TSModuleDeclaration") {
2655
- return "name" in statement.id && statement.id.name === REQUIRE_NAME;
2734
+ return "name" in statement.id && statement.id.name === name;
2656
2735
  }
2657
2736
  if (statement.type === "ClassDeclaration" || statement.type === "FunctionDeclaration" || statement.type === "TSEnumDeclaration") {
2658
- return statement.id?.name === REQUIRE_NAME;
2737
+ return statement.id?.name === name;
2659
2738
  }
2660
2739
  return false;
2661
2740
  }
2662
2741
 
2663
2742
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/does-node-declare-require/_does-node-declare-require@shared/_utils/_compounds/does-statement-declare-require/does-statement-declare-require.util.ts
2664
- function doesStatementDeclareRequire(statement) {
2743
+ function doesStatementDeclareRequire(statement, name = REQUIRE_NAME) {
2665
2744
  if (statement.type === "ExportNamedDeclaration") {
2666
- return statement.declaration !== null && doesStatementDeclareRequire(statement.declaration);
2745
+ return statement.declaration !== null && doesStatementDeclareRequire(statement.declaration, name);
2667
2746
  }
2668
2747
  if (statement.type === "VariableDeclaration") {
2669
2748
  return statement.declarations.some(
2670
- (declarator) => doesPatternBindRequire(declarator.id)
2749
+ (declarator) => doesPatternBindRequire(declarator.id, name)
2671
2750
  );
2672
2751
  }
2673
2752
  if (statement.type === "ImportDeclaration") {
2674
2753
  return statement.specifiers.some(
2675
- (specifier) => specifier.local.name === REQUIRE_NAME
2754
+ (specifier) => specifier.local.name === name
2676
2755
  );
2677
2756
  }
2678
2757
  if (statement.type === "TSImportEqualsDeclaration") {
2679
- return statement.id.name === REQUIRE_NAME;
2758
+ return statement.id.name === name;
2680
2759
  }
2681
- return doesTargetDeclareRequire(statement);
2760
+ return doesTargetDeclareRequire(statement, name);
2682
2761
  }
2683
2762
 
2684
2763
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_traverse-ast@shared/_utils/is-ast-node/is-ast-node.util.ts
@@ -2698,14 +2777,14 @@ function isStatement(value) {
2698
2777
  }
2699
2778
 
2700
2779
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/does-node-declare-require/_utils/does-function-declare-require/does-function-declare-require.util.ts
2701
- function doesFunctionDeclareRequire(node) {
2780
+ function doesFunctionDeclareRequire(node, name = REQUIRE_NAME) {
2702
2781
  const id = node["id"];
2703
- if (isAstNode(id) && id["name"] === REQUIRE_NAME) {
2782
+ if (isAstNode(id) && id["name"] === name) {
2704
2783
  return true;
2705
2784
  }
2706
2785
  const parameters = node["params"];
2707
2786
  if (Array.isArray(parameters) && parameters.some(
2708
- (parameter) => isBindingPattern(parameter) && doesPatternBindRequire(parameter)
2787
+ (parameter) => isBindingPattern(parameter) && doesPatternBindRequire(parameter, name)
2709
2788
  )) {
2710
2789
  return true;
2711
2790
  }
@@ -2713,24 +2792,24 @@ function doesFunctionDeclareRequire(node) {
2713
2792
  if (isAstNode(body)) {
2714
2793
  const inner = body["body"];
2715
2794
  if (Array.isArray(inner)) {
2716
- return inner.filter(isStatement).some((statement) => doesStatementDeclareRequire(statement));
2795
+ return inner.filter(isStatement).some((statement) => doesStatementDeclareRequire(statement, name));
2717
2796
  }
2718
2797
  }
2719
2798
  return false;
2720
2799
  }
2721
2800
 
2722
2801
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/does-node-declare-require/does-node-declare-require.util.ts
2723
- function doesNodeDeclareRequire(node) {
2802
+ function doesNodeDeclareRequire(node, name = REQUIRE_NAME) {
2724
2803
  if (node.type === "Program" || node.type === "BlockStatement") {
2725
2804
  const body = node["body"];
2726
- return Array.isArray(body) && body.filter(isStatement).some((statement) => doesStatementDeclareRequire(statement));
2805
+ return Array.isArray(body) && body.filter(isStatement).some((statement) => doesStatementDeclareRequire(statement, name));
2727
2806
  }
2728
2807
  if (FUNCTION_AST_TYPES.has(node.type)) {
2729
- return doesFunctionDeclareRequire(node);
2808
+ return doesFunctionDeclareRequire(node, name);
2730
2809
  }
2731
2810
  if (node.type === "CatchClause") {
2732
2811
  const parameter = node["param"];
2733
- return isBindingPattern(parameter) && doesPatternBindRequire(parameter);
2812
+ return isBindingPattern(parameter) && doesPatternBindRequire(parameter, name);
2734
2813
  }
2735
2814
  return false;
2736
2815
  }
@@ -2827,20 +2906,69 @@ function handleTsImportType(importType, locator, inlineImports) {
2827
2906
  });
2828
2907
  }
2829
2908
 
2909
+ // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/handle-specific-node/_utils/handle-unsupported-syntax/_utils/is-commonjs-export-assignment/_utils/is-exports-property/is-exports-property.util.ts
2910
+ function isExportsProperty(node) {
2911
+ const property = node["property"];
2912
+ if (!isAstNode(property)) {
2913
+ return false;
2914
+ }
2915
+ if (node["computed"] === true) {
2916
+ return extractStaticSpecifier(property) === EXPORTS_NAME;
2917
+ }
2918
+ return property.type === "Identifier" && property["name"] === EXPORTS_NAME;
2919
+ }
2920
+
2921
+ // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/handle-specific-node/_utils/handle-unsupported-syntax/_utils/is-commonjs-export-assignment/is-commonjs-export-assignment.util.ts
2922
+ function isCommonJsExportAssignment(left, isModuleShadowed, isExportsShadowed) {
2923
+ if (left.type !== "MemberExpression") {
2924
+ return false;
2925
+ }
2926
+ let current = left;
2927
+ let innermostOnModule = null;
2928
+ while (current.type === "MemberExpression") {
2929
+ const object = current["object"];
2930
+ if (!isAstNode(object)) {
2931
+ return false;
2932
+ }
2933
+ if (object.type === "Identifier") {
2934
+ if (object["name"] === EXPORTS_NAME) {
2935
+ return !isExportsShadowed;
2936
+ }
2937
+ if (object["name"] === MODULE_NAME) {
2938
+ innermostOnModule = current;
2939
+ }
2940
+ }
2941
+ current = object;
2942
+ }
2943
+ return innermostOnModule !== null && !isModuleShadowed && isExportsProperty(innermostOnModule);
2944
+ }
2945
+
2830
2946
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/handle-specific-node/_utils/handle-unsupported-syntax/handle-unsupported-syntax.util.ts
2831
- function handleUnsupportedSyntax(node, locator, unsupportedSyntaxes) {
2832
- if (node.type !== "TSExportAssignment") {
2947
+ function handleUnsupportedSyntax(node, isModuleShadowed, isExportsShadowed, locator, unsupportedSyntaxes) {
2948
+ if (node.type === "TSExportAssignment") {
2949
+ const start2 = typeof node["start"] === "number" ? node["start"] : 0;
2950
+ unsupportedSyntaxes.push({
2951
+ description: "TypeScript export assignment (export =) is unsupported",
2952
+ position: locator(start2)
2953
+ });
2954
+ return;
2955
+ }
2956
+ if (node.type !== "AssignmentExpression") {
2957
+ return;
2958
+ }
2959
+ const left = node["left"];
2960
+ if (!isAstNode(left) || !isCommonJsExportAssignment(left, isModuleShadowed, isExportsShadowed)) {
2833
2961
  return;
2834
2962
  }
2835
2963
  const start = typeof node["start"] === "number" ? node["start"] : 0;
2836
2964
  unsupportedSyntaxes.push({
2837
- description: "TypeScript export assignment (export =) is unsupported",
2965
+ description: UNSUPPORTED_COMMONJS_MESSAGE,
2838
2966
  position: locator(start)
2839
2967
  });
2840
2968
  }
2841
2969
 
2842
2970
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/handle-specific-node/handle-specific-node.util.ts
2843
- function handleSpecificNode(node, isRequireShadowed, locator, inlineImports, unsupportedSyntaxes) {
2971
+ function handleSpecificNode(node, isRequireShadowed, isModuleShadowed, isExportsShadowed, locator, inlineImports, unsupportedSyntaxes) {
2844
2972
  if (node.type === "CallExpression") {
2845
2973
  const callee = node["callee"];
2846
2974
  if (!isRequireShadowed && isAstNode(callee) && callee.type === "Identifier" && callee["name"] === REQUIRE_NAME) {
@@ -2856,7 +2984,13 @@ function handleSpecificNode(node, isRequireShadowed, locator, inlineImports, uns
2856
2984
  handleTsImportType(node, locator, inlineImports);
2857
2985
  return;
2858
2986
  }
2859
- handleUnsupportedSyntax(node, locator, unsupportedSyntaxes);
2987
+ handleUnsupportedSyntax(
2988
+ node,
2989
+ isModuleShadowed,
2990
+ isExportsShadowed,
2991
+ locator,
2992
+ unsupportedSyntaxes
2993
+ );
2860
2994
  }
2861
2995
 
2862
2996
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/_utils/visit-children/visit-children.util.ts
@@ -2870,12 +3004,16 @@ function visitChildren(node, visitor) {
2870
3004
  }
2871
3005
 
2872
3006
  // src/_rules/conformity/_stores/session/_services/verify-project/_adapters/collect-modules/_utils/produce-module-record-by-extension/_utils/extract-script-module-record/_utils/extract-traversal-entries/_utils/traverse-ast/traverse-ast.util.ts
2873
- function traverseAst(node, isRequireShadowed, locator, inlineImports, unsupportedSyntaxes) {
3007
+ function traverseAst(node, isRequireShadowed, isModuleShadowed, isExportsShadowed, locator, inlineImports, unsupportedSyntaxes) {
2874
3008
  const astNode = { ...node, type: node.type };
2875
- const isNextShadowed = isRequireShadowed || doesNodeDeclareRequire(astNode);
3009
+ const isNextRequireShadowed = isRequireShadowed || doesNodeDeclareRequire(astNode, REQUIRE_NAME);
3010
+ const isNextModuleShadowed = isModuleShadowed || doesNodeDeclareRequire(astNode, MODULE_NAME);
3011
+ const isNextExportsShadowed = isExportsShadowed || doesNodeDeclareRequire(astNode, EXPORTS_NAME);
2876
3012
  handleSpecificNode(
2877
3013
  astNode,
2878
- isNextShadowed,
3014
+ isNextRequireShadowed,
3015
+ isNextModuleShadowed,
3016
+ isNextExportsShadowed,
2879
3017
  locator,
2880
3018
  inlineImports,
2881
3019
  unsupportedSyntaxes
@@ -2883,7 +3021,9 @@ function traverseAst(node, isRequireShadowed, locator, inlineImports, unsupporte
2883
3021
  visitChildren(astNode, (child) => {
2884
3022
  traverseAst(
2885
3023
  child,
2886
- isNextShadowed,
3024
+ isNextRequireShadowed,
3025
+ isNextModuleShadowed,
3026
+ isNextExportsShadowed,
2887
3027
  locator,
2888
3028
  inlineImports,
2889
3029
  unsupportedSyntaxes
@@ -2895,7 +3035,15 @@ function traverseAst(node, isRequireShadowed, locator, inlineImports, unsupporte
2895
3035
  function extractTraversalEntries(program, locator) {
2896
3036
  const inlineImports = [];
2897
3037
  const unsupportedSyntaxes = [];
2898
- traverseAst(program, false, locator, inlineImports, unsupportedSyntaxes);
3038
+ traverseAst(
3039
+ program,
3040
+ false,
3041
+ false,
3042
+ false,
3043
+ locator,
3044
+ inlineImports,
3045
+ unsupportedSyntaxes
3046
+ );
2899
3047
  return {
2900
3048
  inlineImports,
2901
3049
  unsupportedSyntaxes
@@ -6036,21 +6184,28 @@ function isViolatingDomainName(classification, inventory, trees) {
6036
6184
  // src/_rules/conformity/_stores/session/_services/verify-project/_norms/nomenclature/_utils/is-violating-unit-name/_utils/is-violating-path-fragment-name/is-violating-path-fragment-name.util.ts
6037
6185
  function isViolatingPathFragmentName(name, lookupPath, mimeticStructures) {
6038
6186
  const isKebab = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name);
6039
- const matched = mimeticStructures.find(
6040
- (structure) => structure.paths.some(
6187
+ const matchingCandidates = mimeticStructures.flatMap(
6188
+ (structure) => structure.paths.filter(
6041
6189
  (prefix) => lookupPath === prefix || lookupPath.startsWith(`${prefix}/`)
6042
- )
6190
+ ).map((prefix) => ({
6191
+ prefixLength: prefix.length,
6192
+ structure
6193
+ }))
6043
6194
  );
6195
+ matchingCandidates.sort(
6196
+ (left, right) => right.prefixLength - left.prefixLength
6197
+ );
6198
+ const matched = matchingCandidates[0]?.structure;
6044
6199
  const actions = matched?.actions ?? [];
6045
6200
  if (actions.length === 0) {
6046
6201
  return !isKebab;
6047
6202
  }
6048
6203
  const matchingActions = actions.filter(
6049
- (action) => name.startsWith(`${action}-`)
6204
+ (action) => name === action || name.startsWith(`${action}-`)
6050
6205
  );
6051
6206
  matchingActions.sort((left, right) => right.length - left.length);
6052
6207
  const longestAction = matchingActions[0];
6053
- if (longestAction === void 0) {
6208
+ if (longestAction === void 0 || name === longestAction) {
6054
6209
  return true;
6055
6210
  }
6056
6211
  const target = name.slice(longestAction.length + 1);
@@ -7368,42 +7523,105 @@ function readPackageJson(input) {
7368
7523
  // src/_rules/conformity/_stores/session/_services/verify-project/_services/prepare-project/_adapters/include-external-targets/include-external-targets.adapter.ts
7369
7524
  var import_node_fs12 = __toESM(require("fs"), 1);
7370
7525
  var import_node_path12 = __toESM(require("path"), 1);
7371
- function includeExternalTargets(inventory, config, baseDirectory) {
7526
+ function includeExternalTargets(inventory, config, baseDirectory, origins) {
7527
+ const skippedDirectoryNames = /* @__PURE__ */ new Set([
7528
+ "build",
7529
+ "coverage",
7530
+ "dist",
7531
+ "node_modules",
7532
+ "out",
7533
+ "reports",
7534
+ "tmp"
7535
+ ]);
7372
7536
  const items = [...inventory.items];
7373
7537
  const pathToId = new Map(inventory.pathToId);
7374
7538
  const realPathToId = new Map(inventory.realPathToId);
7539
+ const resolveTargetKind = (target) => {
7540
+ const normalized = toPosixPath(target);
7541
+ if (pathToId.has(normalized)) {
7542
+ return null;
7543
+ }
7544
+ const absolute = import_node_path12.default.resolve(baseDirectory, normalized);
7545
+ const stats = import_node_fs12.default.statSync(absolute, { throwIfNoEntry: false });
7546
+ if (stats?.isDirectory() === true) {
7547
+ return { absolute, kind: "directory", normalized };
7548
+ }
7549
+ if (stats?.isFile() === true) {
7550
+ return { absolute, kind: "file", normalized };
7551
+ }
7552
+ return null;
7553
+ };
7554
+ const declaredOriginList = origins ?? config.faf.locals.flatMap((local) => [
7555
+ ...local.rootLayers ?? [],
7556
+ ...local.rootFragments?.map((rootFragment) => rootFragment.path) ?? []
7557
+ ]);
7558
+ const declaredOrigins = new Set(
7559
+ declaredOriginList.map((origin) => toPosixPath(origin))
7560
+ );
7561
+ const collectExternalCandidates = () => {
7562
+ if (declaredOrigins.has(".") || !import_node_fs12.default.existsSync(baseDirectory)) {
7563
+ return [];
7564
+ }
7565
+ const readDirectory = (directory) => {
7566
+ try {
7567
+ return import_node_fs12.default.readdirSync(directory, {
7568
+ withFileTypes: true
7569
+ });
7570
+ } catch {
7571
+ return [];
7572
+ }
7573
+ };
7574
+ const candidates = [];
7575
+ const directoryQueue = [baseDirectory];
7576
+ const processDirent2 = (dirent, currentDirectory) => {
7577
+ if (dirent.name.startsWith(".") || dirent.isSymbolicLink()) {
7578
+ return;
7579
+ }
7580
+ const fullPath = import_node_path12.default.join(currentDirectory, dirent.name);
7581
+ const relativePath = toPosixPath(
7582
+ import_node_path12.default.relative(baseDirectory, fullPath)
7583
+ );
7584
+ if (dirent.isDirectory() && !skippedDirectoryNames.has(dirent.name) && !declaredOrigins.has(relativePath)) {
7585
+ directoryQueue.push(fullPath);
7586
+ }
7587
+ if (relativePath !== "fafconfig.ts" && dirent.isFile() && LINTABLE_EXTENSIONS.some((extension) => dirent.name.endsWith(extension))) {
7588
+ candidates.push(relativePath);
7589
+ }
7590
+ };
7591
+ for (const currentDirectory of directoryQueue) {
7592
+ for (const dirent of readDirectory(currentDirectory)) {
7593
+ processDirent2(dirent, currentDirectory);
7594
+ }
7595
+ }
7596
+ candidates.sort(compareOrdinal);
7597
+ return candidates;
7598
+ };
7375
7599
  const sections = [
7376
7600
  config.faf.common?.externalDependencies,
7377
7601
  ...config.faf.locals.map((local) => local.externalDependencies)
7378
7602
  ];
7379
- const targets = sections.flatMap((section) => section ?? []).flatMap((edge) => edge.to);
7380
- const dirents = import_node_fs12.default.existsSync(baseDirectory) ? import_node_fs12.default.readdirSync(baseDirectory, { withFileTypes: true }) : [];
7381
- for (const dirent of dirents) {
7382
- const isRootCandidate = dirent.isFile() && dirent.name !== "fafconfig.ts" && LINTABLE_EXTENSIONS.some((extension) => dirent.name.endsWith(extension));
7383
- if (isRootCandidate) {
7384
- targets.push(dirent.name);
7385
- }
7386
- }
7603
+ const targets = [
7604
+ ...sections.flatMap((section) => section ?? []).flatMap((edge) => edge.to),
7605
+ ...Object.values(config.faf.common?.aliases ?? {}),
7606
+ ...collectExternalCandidates()
7607
+ ];
7387
7608
  for (const target of targets) {
7388
- const normalized = toPosixPath(target);
7389
- const absolute = import_node_path12.default.resolve(baseDirectory, normalized);
7390
- const stats = import_node_fs12.default.statSync(absolute, { throwIfNoEntry: false });
7391
- const isRegularFile = stats?.isFile() === true;
7392
- if (!isRegularFile || pathToId.has(normalized)) {
7609
+ const resolved = resolveTargetKind(target);
7610
+ if (resolved === null) {
7393
7611
  continue;
7394
7612
  }
7395
7613
  const id = items.length;
7396
- const isSymlink = import_node_fs12.default.lstatSync(absolute).isSymbolicLink();
7614
+ const isSymlink = import_node_fs12.default.lstatSync(resolved.absolute).isSymbolicLink();
7397
7615
  const item = {
7398
7616
  depth: 0,
7399
7617
  id,
7400
7618
  isSymlink,
7401
- kind: "file",
7619
+ kind: resolved.kind,
7402
7620
  parentId: null,
7403
- path: normalized,
7621
+ path: resolved.normalized,
7404
7622
  preorderEnd: id,
7405
7623
  preorderStart: id,
7406
- realPath: import_node_fs12.default.realpathSync(absolute),
7624
+ realPath: import_node_fs12.default.realpathSync(resolved.absolute),
7407
7625
  treeOrigin: null
7408
7626
  };
7409
7627
  items.push(item);
@@ -8777,6 +8995,9 @@ function isLiteralConfigPath(path5) {
8777
8995
  if (path5 === ".") {
8778
8996
  return true;
8779
8997
  }
8998
+ if (path5.includes("\\")) {
8999
+ return false;
9000
+ }
8780
9001
  const segments = path5.split("/");
8781
9002
  return segments.every(
8782
9003
  (segment) => !INVALID_CONFIG_PATH_SEGMENTS.has(segment)
@@ -9260,7 +9481,7 @@ var aliasesSchema = import_zod6.z.record(
9260
9481
  path: [key]
9261
9482
  });
9262
9483
  }
9263
- if (value.length > 0 && !formFields.isLiteralPath(value)) {
9484
+ if (value.includes("*") || value.length > 0 && !formFields.isLiteralPath(value)) {
9264
9485
  context.addIssue({
9265
9486
  code: "custom",
9266
9487
  message: formFields.fixed(CONSTRAINT_INVALID_LITERAL_PATH),
@@ -10036,6 +10257,9 @@ var CONSTRAINT_INVALID_IMPLICIT_EXT = "configuration/invalid-implicit-extension"
10036
10257
  var FORBIDDEN_CODE_EXTENSIONS = /* @__PURE__ */ new Set([
10037
10258
  ".cjs",
10038
10259
  ".cts",
10260
+ ".d.cts",
10261
+ ".d.mts",
10262
+ ".d.ts",
10039
10263
  ".js",
10040
10264
  ".jsx",
10041
10265
  ".mjs",
@@ -10528,6 +10752,36 @@ var validateConfigFormat = /* @__PURE__ */ (() => {
10528
10752
  };
10529
10753
  })();
10530
10754
 
10755
+ // src/_rules/conformity/_stores/session/_services/verify-project/_services/prepare-project/_utils/validate-config-references/_utils/validate-alias-references/validate-alias-references.util.ts
10756
+ function validateAliasReferences(config, context) {
10757
+ const outcomes = [];
10758
+ const entries = Object.entries(config.faf.common?.aliases ?? {});
10759
+ for (const [key, basePath] of entries) {
10760
+ const id = context.inventory.pathToId.get(basePath);
10761
+ if (id === void 0) {
10762
+ outcomes.push(
10763
+ createOutcome("configuration/non-existent-path", {
10764
+ detail: `Alias base "${basePath}" does not exist under configuration base "${context.baseDirectory}".`,
10765
+ element: basePath,
10766
+ propertyPath: `faf.common.aliases.${key}`
10767
+ })
10768
+ );
10769
+ continue;
10770
+ }
10771
+ const item = context.inventory.items[id];
10772
+ if (item === void 0 || item.kind !== "directory") {
10773
+ outcomes.push(
10774
+ createOutcome("configuration/expected-directory", {
10775
+ detail: `Alias base "${basePath}" must be a directory.`,
10776
+ element: basePath,
10777
+ propertyPath: `faf.common.aliases.${key}`
10778
+ })
10779
+ );
10780
+ }
10781
+ }
10782
+ return outcomes;
10783
+ }
10784
+
10531
10785
  // src/_rules/conformity/_stores/session/_services/verify-project/_services/prepare-project/_utils/validate-config-references/_validate-config-references@shared/_utils/reject-directory-in-scope/_utils/reject-directory-scope/reject-directory-scope.util.ts
10532
10786
  function rejectDirectoryScope(check, item, _family) {
10533
10787
  if (item.treeOrigin === null) {
@@ -11561,7 +11815,8 @@ function validateConfigReferences(config, declarations, inventory) {
11561
11815
  ...validateRootReferences(config, context),
11562
11816
  ...validateForeignReferences(config, context),
11563
11817
  ...validateStructuralReferences(config, context),
11564
- ...validateFrontierReferences(config, context)
11818
+ ...validateFrontierReferences(config, context),
11819
+ ...validateAliasReferences(config, context)
11565
11820
  ]);
11566
11821
  }
11567
11822
 
@@ -11628,7 +11883,11 @@ function prepareProject(configPath) {
11628
11883
  declarations.outcomes
11629
11884
  );
11630
11885
  }
11631
- const origins = declarations.value.trees.map((tree) => tree.originPath);
11886
+ const effectiveDeclarations = {
11887
+ ...declarations.value,
11888
+ aliases: aliases.value
11889
+ };
11890
+ const origins = effectiveDeclarations.trees.map((tree) => tree.originPath);
11632
11891
  const entries = listEntries(loaded.value.configDirectory, origins);
11633
11892
  if (!entries.ok) {
11634
11893
  return blocked(
@@ -11642,11 +11901,12 @@ function prepareProject(configPath) {
11642
11901
  const inventory = includeExternalTargets(
11643
11902
  built.inventory,
11644
11903
  formatted.value,
11645
- loaded.value.configDirectory
11904
+ loaded.value.configDirectory,
11905
+ origins
11646
11906
  );
11647
11907
  const references = validateConfigReferences(
11648
11908
  formatted.value,
11649
- declarations.value,
11909
+ effectiveDeclarations,
11650
11910
  inventory
11651
11911
  );
11652
11912
  if (references.length > 0) {
@@ -11661,7 +11921,7 @@ function prepareProject(configPath) {
11661
11921
  aliases: aliases.value,
11662
11922
  baseDirectory: loaded.value.configDirectory,
11663
11923
  configPath: loaded.value.configPath,
11664
- declarations: declarations.value,
11924
+ declarations: effectiveDeclarations,
11665
11925
  inventory,
11666
11926
  inventoryOutcomes: built.outcomes,
11667
11927
  kind: "ready",