@codeperfect/eslint-plugin 2.3.0 → 2.5.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.
Files changed (151) hide show
  1. package/dist/application/index.d.ts +1 -1
  2. package/dist/application/index.d.ts.map +1 -1
  3. package/dist/application/index.js +2 -2
  4. package/dist/codeperfect-eslint-plugin-1.0.0.tgz +0 -0
  5. package/dist/domain/architecture/consistent-barrel-files/consistent-barrel-files-options.d.ts.map +1 -1
  6. package/dist/domain/architecture/consistent-barrel-files/consistent-barrel-files-options.js +4 -2
  7. package/dist/domain/architecture/consistent-barrel-files/exports-only-rule.d.ts.map +1 -1
  8. package/dist/domain/architecture/consistent-barrel-files/exports-only-rule.js +2 -4
  9. package/dist/domain/architecture/consistent-barrel-files/no-import-export-aliases-rule.d.ts.map +1 -1
  10. package/dist/domain/architecture/consistent-barrel-files/no-import-export-aliases-rule.js +4 -134
  11. package/dist/domain/architecture/consistent-barrel-files/no-import-export-aliases-utilities.d.ts +14 -0
  12. package/dist/domain/architecture/consistent-barrel-files/no-import-export-aliases-utilities.d.ts.map +1 -0
  13. package/dist/domain/architecture/consistent-barrel-files/no-import-export-aliases-utilities.js +154 -0
  14. package/dist/domain/architecture/consistent-barrel-files/no-import-export-extensions-rule.d.ts.map +1 -1
  15. package/dist/domain/architecture/consistent-barrel-files/no-import-export-extensions-rule.js +10 -12
  16. package/dist/domain/architecture/consistent-barrel-files/no-reexports-outside-barrels-rule.d.ts.map +1 -1
  17. package/dist/domain/architecture/consistent-barrel-files/no-reexports-outside-barrels-rule.js +4 -11
  18. package/dist/domain/architecture/no-unused-exports/no-unused-exports-declaration-utilities.d.ts +14 -0
  19. package/dist/domain/architecture/no-unused-exports/no-unused-exports-declaration-utilities.d.ts.map +1 -0
  20. package/dist/domain/architecture/no-unused-exports/no-unused-exports-declaration-utilities.js +187 -0
  21. package/dist/domain/architecture/no-unused-exports/no-unused-exports-identifier-utilities.d.ts +26 -0
  22. package/dist/domain/architecture/no-unused-exports/no-unused-exports-identifier-utilities.d.ts.map +1 -0
  23. package/dist/domain/architecture/no-unused-exports/no-unused-exports-identifier-utilities.js +95 -0
  24. package/dist/domain/architecture/no-unused-exports/no-unused-exports-pattern-utilities.d.ts +32 -0
  25. package/dist/domain/architecture/no-unused-exports/no-unused-exports-pattern-utilities.d.ts.map +1 -0
  26. package/dist/domain/architecture/no-unused-exports/no-unused-exports-pattern-utilities.js +78 -0
  27. package/dist/domain/architecture/no-unused-exports/no-unused-exports-public-api-usage-utilities.d.ts +18 -0
  28. package/dist/domain/architecture/no-unused-exports/no-unused-exports-public-api-usage-utilities.d.ts.map +1 -0
  29. package/dist/domain/architecture/no-unused-exports/no-unused-exports-public-api-usage-utilities.js +45 -0
  30. package/dist/domain/architecture/no-unused-exports/no-unused-exports-record-utilities.d.ts +34 -0
  31. package/dist/domain/architecture/no-unused-exports/no-unused-exports-record-utilities.d.ts.map +1 -0
  32. package/dist/domain/architecture/no-unused-exports/no-unused-exports-record-utilities.js +44 -0
  33. package/dist/domain/architecture/no-unused-exports/no-unused-exports-symbol-utilities.d.ts +59 -0
  34. package/dist/domain/architecture/no-unused-exports/no-unused-exports-symbol-utilities.d.ts.map +1 -0
  35. package/dist/domain/architecture/no-unused-exports/no-unused-exports-symbol-utilities.js +133 -0
  36. package/dist/domain/architecture/no-unused-exports/no-unused-exports-usage-utilities.d.ts +28 -0
  37. package/dist/domain/architecture/no-unused-exports/no-unused-exports-usage-utilities.d.ts.map +1 -0
  38. package/dist/domain/architecture/no-unused-exports/no-unused-exports-usage-utilities.js +106 -0
  39. package/dist/domain/architecture/no-unused-exports/no-unused-exports-utilities.d.ts +21 -21
  40. package/dist/domain/architecture/no-unused-exports/no-unused-exports-utilities.d.ts.map +1 -1
  41. package/dist/domain/architecture/no-unused-exports/no-unused-exports-utilities.js +24 -587
  42. package/dist/domain/architecture/no-unused-exports/rule.js +3 -3
  43. package/dist/domain/core/no-multiple-declarators/rule-utilities.d.ts +58 -0
  44. package/dist/domain/core/no-multiple-declarators/rule-utilities.d.ts.map +1 -0
  45. package/dist/domain/core/no-multiple-declarators/rule-utilities.js +204 -0
  46. package/dist/domain/core/no-multiple-declarators/rule.d.ts.map +1 -1
  47. package/dist/domain/core/no-multiple-declarators/rule.js +9 -211
  48. package/dist/domain/core/no-multiple-declarators/types.js +2 -2
  49. package/dist/domain/core/prefer-interface-types/rule-utilities.d.ts +57 -0
  50. package/dist/domain/core/prefer-interface-types/rule-utilities.d.ts.map +1 -0
  51. package/dist/domain/core/prefer-interface-types/rule-utilities.js +105 -0
  52. package/dist/domain/core/prefer-interface-types/rule.d.ts.map +1 -1
  53. package/dist/domain/core/prefer-interface-types/rule.js +2 -104
  54. package/dist/domain/docs/no-interface-member-docs/comment-removal-ranges.d.ts +25 -0
  55. package/dist/domain/docs/no-interface-member-docs/comment-removal-ranges.d.ts.map +1 -0
  56. package/dist/domain/docs/no-interface-member-docs/comment-removal-ranges.js +64 -0
  57. package/dist/domain/docs/no-interface-member-docs/comment-utilities.d.ts +2 -24
  58. package/dist/domain/docs/no-interface-member-docs/comment-utilities.d.ts.map +1 -1
  59. package/dist/domain/docs/no-interface-member-docs/comment-utilities.js +3 -65
  60. package/dist/domain/docs/no-interface-member-docs/parameter-tags.js +2 -2
  61. package/dist/domain/docs/no-interface-member-docs/parameter-utilities.js +2 -2
  62. package/dist/domain/docs/no-interface-member-docs/rule.d.ts.map +1 -1
  63. package/dist/domain/docs/no-interface-member-docs/rule.js +3 -2
  64. package/dist/domain/docs/require-example-language/examples-collect.d.ts +15 -0
  65. package/dist/domain/docs/require-example-language/examples-collect.d.ts.map +1 -0
  66. package/dist/domain/docs/require-example-language/examples-collect.js +113 -0
  67. package/dist/domain/docs/require-example-language/examples.d.ts +24 -13
  68. package/dist/domain/docs/require-example-language/examples.d.ts.map +1 -1
  69. package/dist/domain/docs/require-example-language/examples.js +2 -111
  70. package/dist/domain/docs/require-example-language/fixes.js +4 -4
  71. package/dist/domain/docs/require-example-language/rule.d.ts.map +1 -1
  72. package/dist/domain/docs/require-example-language/rule.js +9 -8
  73. package/dist/domain/docs/require-example-language/types.d.ts.map +1 -1
  74. package/dist/domain/docs/require-example-language/types.js +1 -1
  75. package/dist/domain/index.d.ts +1 -1
  76. package/dist/domain/index.d.ts.map +1 -1
  77. package/dist/domain/index.js +2 -2
  78. package/dist/domain/testing/aaa/analyzer.analysis.helpers.d.ts.map +1 -1
  79. package/dist/domain/testing/aaa/analyzer.analysis.helpers.js +8 -8
  80. package/dist/domain/testing/aaa/analyzer.assertions.helpers.d.ts.map +1 -1
  81. package/dist/domain/testing/aaa/analyzer.assertions.helpers.js +10 -9
  82. package/dist/domain/testing/aaa/analyzer.assertions.operands.d.ts.map +1 -1
  83. package/dist/domain/testing/aaa/analyzer.assertions.operands.js +2 -5
  84. package/dist/domain/testing/aaa/analyzer.classification.helpers.js +14 -16
  85. package/dist/domain/testing/aaa/analyzer.classification.traversal.js +6 -4
  86. package/dist/domain/testing/aaa/analyzer.super.d.ts.map +1 -1
  87. package/dist/domain/testing/aaa/analyzer.super.js +10 -8
  88. package/dist/domain/testing/assert-actual-expected-names/rule.d.ts.map +1 -1
  89. package/dist/domain/testing/assert-actual-expected-names/rule.js +21 -23
  90. package/dist/domain/testing/enforce-aaa-phase-purity/pattern-identifiers.d.ts.map +1 -1
  91. package/dist/domain/testing/enforce-aaa-phase-purity/pattern-identifiers.js +1 -1
  92. package/dist/domain/testing/enforce-aaa-phase-purity/phase-purity-reporting.d.ts.map +1 -1
  93. package/dist/domain/testing/enforce-aaa-phase-purity/phase-purity-reporting.js +2 -160
  94. package/dist/domain/testing/enforce-aaa-phase-purity/statement-purity-reporters.d.ts +41 -0
  95. package/dist/domain/testing/enforce-aaa-phase-purity/statement-purity-reporters.d.ts.map +1 -0
  96. package/dist/domain/testing/enforce-aaa-phase-purity/statement-purity-reporters.js +161 -0
  97. package/dist/domain/testing/enforce-aaa-structure/missing-section-fixes.d.ts.map +1 -1
  98. package/dist/domain/testing/enforce-aaa-structure/missing-section-fixes.js +2 -2
  99. package/dist/domain/testing/enforce-aaa-structure/rule-section-reporting.d.ts +81 -0
  100. package/dist/domain/testing/enforce-aaa-structure/rule-section-reporting.d.ts.map +1 -0
  101. package/dist/domain/testing/enforce-aaa-structure/rule-section-reporting.js +181 -0
  102. package/dist/domain/testing/enforce-aaa-structure/rule.d.ts.map +1 -1
  103. package/dist/domain/testing/enforce-aaa-structure/rule.js +28 -217
  104. package/dist/domain/testing/index.d.ts +1 -0
  105. package/dist/domain/testing/index.d.ts.map +1 -1
  106. package/dist/domain/testing/index.js +2 -1
  107. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/index.d.ts +2 -0
  108. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/index.d.ts.map +1 -0
  109. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/index.js +2 -0
  110. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-detection.d.ts +29 -0
  111. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-detection.d.ts.map +1 -0
  112. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-detection.js +200 -0
  113. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-names.d.ts +12 -0
  114. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-names.d.ts.map +1 -0
  115. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-names.js +151 -0
  116. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-reporting.d.ts +16 -0
  117. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-reporting.d.ts.map +1 -0
  118. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule-reporting.js +109 -0
  119. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule.d.ts +5 -0
  120. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule.d.ts.map +1 -0
  121. package/dist/domain/testing/no-unsafe-vitest-mock-factory-cast/rule.js +35 -0
  122. package/dist/domain/testing/prefer-vi-mocked-import/fix-import-updates.d.ts.map +1 -1
  123. package/dist/domain/testing/prefer-vi-mocked-import/fix-import-updates.js +7 -4
  124. package/dist/domain/testing/prefer-vi-mocked-import/fix-imports.d.ts.map +1 -1
  125. package/dist/domain/testing/prefer-vi-mocked-import/fix-imports.js +7 -4
  126. package/dist/domain/testing/prefer-vi-mocked-import/fix.js +2 -2
  127. package/dist/domain/testing/prefer-vi-mocked-import/match-collisions.d.ts +18 -0
  128. package/dist/domain/testing/prefer-vi-mocked-import/match-collisions.d.ts.map +1 -0
  129. package/dist/domain/testing/prefer-vi-mocked-import/match-collisions.js +162 -0
  130. package/dist/domain/testing/prefer-vi-mocked-import/match-rewrites.d.ts.map +1 -1
  131. package/dist/domain/testing/prefer-vi-mocked-import/match-rewrites.js +5 -4
  132. package/dist/domain/testing/prefer-vi-mocked-import/match-seeds.d.ts +29 -0
  133. package/dist/domain/testing/prefer-vi-mocked-import/match-seeds.d.ts.map +1 -0
  134. package/dist/domain/testing/prefer-vi-mocked-import/match-seeds.js +100 -0
  135. package/dist/domain/testing/prefer-vi-mocked-import/match.d.ts.map +1 -1
  136. package/dist/domain/testing/prefer-vi-mocked-import/match.js +5 -246
  137. package/dist/domain/testing/prefer-vi-mocked-import/rule.d.ts.map +1 -1
  138. package/dist/domain/testing/prefer-vi-mocked-import/rule.js +18 -20
  139. package/dist/domain/testing/require-act-result-capture/rule.d.ts.map +1 -1
  140. package/dist/domain/testing/require-act-result-capture/rule.js +47 -21
  141. package/dist/domain/testing/require-test-companion/rule.d.ts.map +1 -1
  142. package/dist/domain/testing/require-test-companion/rule.js +2 -4
  143. package/dist/domain/testing/single-act-statement/rule.d.ts.map +1 -1
  144. package/dist/domain/testing/single-act-statement/rule.js +20 -22
  145. package/dist/infrastructure/codeperfect-plugin.d.ts +2 -0
  146. package/dist/infrastructure/codeperfect-plugin.d.ts.map +1 -1
  147. package/dist/infrastructure/codeperfect-plugin.js +3 -2
  148. package/dist/infrastructure/presets.d.ts.map +1 -1
  149. package/dist/infrastructure/presets.js +3 -1
  150. package/package.json +58 -58
  151. package/dist/.tsbuildinfo +0 -1
@@ -0,0 +1,78 @@
1
+ import { asRecord, readArrayProperty, readStringProperty, } from "./no-unused-exports-record-utilities.js";
2
+ /**
3
+ * Collects identifier names from one variable pattern.
4
+ * @param node Variable pattern candidate.
5
+ * @returns Identifier names declared by the pattern.
6
+ * @example
7
+ * ```typescript
8
+ * const names = collectPatternIdentifierNames(pattern);
9
+ * ```
10
+ */
11
+ const collectPatternIdentifierNames = (node) => {
12
+ const pattern = asRecord(node);
13
+ if (pattern === void 0) {
14
+ return [];
15
+ }
16
+ const patternType = readStringProperty(pattern, "type");
17
+ if (patternType === "Identifier") {
18
+ const name = readStringProperty(pattern, "name");
19
+ return name === void 0 ? [] : [name];
20
+ }
21
+ if (patternType === "RestElement") {
22
+ return collectPatternIdentifierNames(pattern["argument"]);
23
+ }
24
+ if (patternType === "AssignmentPattern") {
25
+ return collectPatternIdentifierNames(pattern["left"]);
26
+ }
27
+ if (patternType === "ArrayPattern") {
28
+ const elements = readArrayProperty(pattern, "elements");
29
+ return elements === void 0
30
+ ? []
31
+ : elements.flatMap((element) => collectPatternIdentifierNames(element));
32
+ }
33
+ if (patternType === "ObjectPattern") {
34
+ const properties = readArrayProperty(pattern, "properties");
35
+ return properties === void 0
36
+ ? []
37
+ : properties.flatMap((property) => {
38
+ if (readStringProperty(property, "type") === "RestElement") {
39
+ return collectPatternIdentifierNames(asRecord(property)?.["argument"]);
40
+ }
41
+ return collectPatternIdentifierNames(asRecord(property)?.["value"]);
42
+ });
43
+ }
44
+ return [];
45
+ };
46
+ /**
47
+ * Reads one export specifier name.
48
+ * @param specifier Export specifier candidate.
49
+ * @returns Exported name when available.
50
+ * @example
51
+ * ```typescript
52
+ * const name = getExportSpecifierName(specifier);
53
+ * ```
54
+ */
55
+ const getExportSpecifierName = (specifier) => {
56
+ const candidate = asRecord(specifier);
57
+ const exportedName = readStringProperty(candidate?.["exported"], "name");
58
+ if (typeof exportedName === "string") {
59
+ return exportedName;
60
+ }
61
+ const localName = readStringProperty(candidate?.["local"], "name");
62
+ return typeof localName === "string" ? localName : void 0;
63
+ };
64
+ /**
65
+ * Reads one local export specifier name.
66
+ * @param specifier Export specifier candidate.
67
+ * @returns Local specifier name when available.
68
+ * @example
69
+ * ```typescript
70
+ * const name = getExportSpecifierLocalName(specifier);
71
+ * ```
72
+ */
73
+ const getExportSpecifierLocalName = (specifier) => {
74
+ const candidate = asRecord(specifier);
75
+ return readStringProperty(candidate?.["local"], "name");
76
+ };
77
+ export { collectPatternIdentifierNames, getExportSpecifierLocalName, getExportSpecifierName, };
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tdW51c2VkLWV4cG9ydHMtcGF0dGVybi11dGlsaXRpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZG9tYWluL2FyY2hpdGVjdHVyZS9uby11bnVzZWQtZXhwb3J0cy9uby11bnVzZWQtZXhwb3J0cy1wYXR0ZXJuLXV0aWxpdGllcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsUUFBUSxFQUNSLGlCQUFpQixFQUNqQixrQkFBa0IsR0FDbkIsTUFBTSxzQ0FBc0MsQ0FBQztBQUU5Qzs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sNkJBQTZCLEdBQUcsQ0FBQyxJQUFhLEVBQVksRUFBRTtJQUNoRSxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFL0IsSUFBSSxPQUFPLEtBQUssS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxNQUFNLFdBQVcsR0FBRyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFFeEQsSUFBSSxXQUFXLEtBQUssWUFBWSxFQUFFLENBQUM7UUFDakMsTUFBTSxJQUFJLEdBQUcsa0JBQWtCLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2pELE9BQU8sSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVELElBQUksV0FBVyxLQUFLLGFBQWEsRUFBRSxDQUFDO1FBQ2xDLE9BQU8sNkJBQTZCLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVELElBQUksV0FBVyxLQUFLLG1CQUFtQixFQUFFLENBQUM7UUFDeEMsT0FBTyw2QkFBNkIsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBRUQsSUFBSSxXQUFXLEtBQUssY0FBYyxFQUFFLENBQUM7UUFDbkMsTUFBTSxRQUFRLEdBQUcsaUJBQWlCLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRXhELE9BQU8sUUFBUSxLQUFLLEtBQUssQ0FBQztZQUN4QixDQUFDLENBQUMsRUFBRTtZQUNKLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyw2QkFBNkIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRCxJQUFJLFdBQVcsS0FBSyxlQUFlLEVBQUUsQ0FBQztRQUNwQyxNQUFNLFVBQVUsR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFNUQsT0FBTyxVQUFVLEtBQUssS0FBSyxDQUFDO1lBQzFCLENBQUMsQ0FBQyxFQUFFO1lBQ0osQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtnQkFDOUIsSUFBSSxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLEtBQUssYUFBYSxFQUFFLENBQUM7b0JBQzNELE9BQU8sNkJBQTZCLENBQ2xDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUNqQyxDQUFDO2dCQUNKLENBQUM7Z0JBRUQsT0FBTyw2QkFBNkIsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3RFLENBQUMsQ0FBQyxDQUFDO0lBQ1QsQ0FBQztJQUVELE9BQU8sRUFBRSxDQUFDO0FBQ1osQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLHNCQUFzQixHQUFHLENBQUMsU0FBa0IsRUFBc0IsRUFBRTtJQUN4RSxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdEMsTUFBTSxZQUFZLEdBQUcsa0JBQWtCLENBQUMsU0FBUyxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFFekUsSUFBSSxPQUFPLFlBQVksS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNyQyxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDO0lBRUQsTUFBTSxTQUFTLEdBQUcsa0JBQWtCLENBQUMsU0FBUyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFFbkUsT0FBTyxPQUFPLFNBQVMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDNUQsQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLDJCQUEyQixHQUFHLENBQ2xDLFNBQWtCLEVBQ0UsRUFBRTtJQUN0QixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFdEMsT0FBTyxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUMxRCxDQUFDLENBQUM7QUFFRixPQUFPLEVBQ0wsNkJBQTZCLEVBQzdCLDJCQUEyQixFQUMzQixzQkFBc0IsR0FDdkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIGFzUmVjb3JkLFxuICByZWFkQXJyYXlQcm9wZXJ0eSxcbiAgcmVhZFN0cmluZ1Byb3BlcnR5LFxufSBmcm9tIFwiLi9uby11bnVzZWQtZXhwb3J0cy1yZWNvcmQtdXRpbGl0aWVzXCI7XG5cbi8qKlxuICogQ29sbGVjdHMgaWRlbnRpZmllciBuYW1lcyBmcm9tIG9uZSB2YXJpYWJsZSBwYXR0ZXJuLlxuICogQHBhcmFtIG5vZGUgVmFyaWFibGUgcGF0dGVybiBjYW5kaWRhdGUuXG4gKiBAcmV0dXJucyBJZGVudGlmaWVyIG5hbWVzIGRlY2xhcmVkIGJ5IHRoZSBwYXR0ZXJuLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IG5hbWVzID0gY29sbGVjdFBhdHRlcm5JZGVudGlmaWVyTmFtZXMocGF0dGVybik7XG4gKiBgYGBcbiAqL1xuY29uc3QgY29sbGVjdFBhdHRlcm5JZGVudGlmaWVyTmFtZXMgPSAobm9kZTogdW5rbm93bik6IHN0cmluZ1tdID0+IHtcbiAgY29uc3QgcGF0dGVybiA9IGFzUmVjb3JkKG5vZGUpO1xuXG4gIGlmIChwYXR0ZXJuID09PSB2b2lkIDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwYXR0ZXJuVHlwZSA9IHJlYWRTdHJpbmdQcm9wZXJ0eShwYXR0ZXJuLCBcInR5cGVcIik7XG5cbiAgaWYgKHBhdHRlcm5UeXBlID09PSBcIklkZW50aWZpZXJcIikge1xuICAgIGNvbnN0IG5hbWUgPSByZWFkU3RyaW5nUHJvcGVydHkocGF0dGVybiwgXCJuYW1lXCIpO1xuICAgIHJldHVybiBuYW1lID09PSB2b2lkIDAgPyBbXSA6IFtuYW1lXTtcbiAgfVxuXG4gIGlmIChwYXR0ZXJuVHlwZSA9PT0gXCJSZXN0RWxlbWVudFwiKSB7XG4gICAgcmV0dXJuIGNvbGxlY3RQYXR0ZXJuSWRlbnRpZmllck5hbWVzKHBhdHRlcm5bXCJhcmd1bWVudFwiXSk7XG4gIH1cblxuICBpZiAocGF0dGVyblR5cGUgPT09IFwiQXNzaWdubWVudFBhdHRlcm5cIikge1xuICAgIHJldHVybiBjb2xsZWN0UGF0dGVybklkZW50aWZpZXJOYW1lcyhwYXR0ZXJuW1wibGVmdFwiXSk7XG4gIH1cblxuICBpZiAocGF0dGVyblR5cGUgPT09IFwiQXJyYXlQYXR0ZXJuXCIpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IHJlYWRBcnJheVByb3BlcnR5KHBhdHRlcm4sIFwiZWxlbWVudHNcIik7XG5cbiAgICByZXR1cm4gZWxlbWVudHMgPT09IHZvaWQgMFxuICAgICAgPyBbXVxuICAgICAgOiBlbGVtZW50cy5mbGF0TWFwKChlbGVtZW50KSA9PiBjb2xsZWN0UGF0dGVybklkZW50aWZpZXJOYW1lcyhlbGVtZW50KSk7XG4gIH1cblxuICBpZiAocGF0dGVyblR5cGUgPT09IFwiT2JqZWN0UGF0dGVyblwiKSB7XG4gICAgY29uc3QgcHJvcGVydGllcyA9IHJlYWRBcnJheVByb3BlcnR5KHBhdHRlcm4sIFwicHJvcGVydGllc1wiKTtcblxuICAgIHJldHVybiBwcm9wZXJ0aWVzID09PSB2b2lkIDBcbiAgICAgID8gW11cbiAgICAgIDogcHJvcGVydGllcy5mbGF0TWFwKChwcm9wZXJ0eSkgPT4ge1xuICAgICAgICAgIGlmIChyZWFkU3RyaW5nUHJvcGVydHkocHJvcGVydHksIFwidHlwZVwiKSA9PT0gXCJSZXN0RWxlbWVudFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gY29sbGVjdFBhdHRlcm5JZGVudGlmaWVyTmFtZXMoXG4gICAgICAgICAgICAgIGFzUmVjb3JkKHByb3BlcnR5KT8uW1wiYXJndW1lbnRcIl0sXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBjb2xsZWN0UGF0dGVybklkZW50aWZpZXJOYW1lcyhhc1JlY29yZChwcm9wZXJ0eSk/LltcInZhbHVlXCJdKTtcbiAgICAgICAgfSk7XG4gIH1cblxuICByZXR1cm4gW107XG59O1xuXG4vKipcbiAqIFJlYWRzIG9uZSBleHBvcnQgc3BlY2lmaWVyIG5hbWUuXG4gKiBAcGFyYW0gc3BlY2lmaWVyIEV4cG9ydCBzcGVjaWZpZXIgY2FuZGlkYXRlLlxuICogQHJldHVybnMgRXhwb3J0ZWQgbmFtZSB3aGVuIGF2YWlsYWJsZS5cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBuYW1lID0gZ2V0RXhwb3J0U3BlY2lmaWVyTmFtZShzcGVjaWZpZXIpO1xuICogYGBgXG4gKi9cbmNvbnN0IGdldEV4cG9ydFNwZWNpZmllck5hbWUgPSAoc3BlY2lmaWVyOiB1bmtub3duKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IHtcbiAgY29uc3QgY2FuZGlkYXRlID0gYXNSZWNvcmQoc3BlY2lmaWVyKTtcbiAgY29uc3QgZXhwb3J0ZWROYW1lID0gcmVhZFN0cmluZ1Byb3BlcnR5KGNhbmRpZGF0ZT8uW1wiZXhwb3J0ZWRcIl0sIFwibmFtZVwiKTtcblxuICBpZiAodHlwZW9mIGV4cG9ydGVkTmFtZSA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBleHBvcnRlZE5hbWU7XG4gIH1cblxuICBjb25zdCBsb2NhbE5hbWUgPSByZWFkU3RyaW5nUHJvcGVydHkoY2FuZGlkYXRlPy5bXCJsb2NhbFwiXSwgXCJuYW1lXCIpO1xuXG4gIHJldHVybiB0eXBlb2YgbG9jYWxOYW1lID09PSBcInN0cmluZ1wiID8gbG9jYWxOYW1lIDogdm9pZCAwO1xufTtcblxuLyoqXG4gKiBSZWFkcyBvbmUgbG9jYWwgZXhwb3J0IHNwZWNpZmllciBuYW1lLlxuICogQHBhcmFtIHNwZWNpZmllciBFeHBvcnQgc3BlY2lmaWVyIGNhbmRpZGF0ZS5cbiAqIEByZXR1cm5zIExvY2FsIHNwZWNpZmllciBuYW1lIHdoZW4gYXZhaWxhYmxlLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IG5hbWUgPSBnZXRFeHBvcnRTcGVjaWZpZXJMb2NhbE5hbWUoc3BlY2lmaWVyKTtcbiAqIGBgYFxuICovXG5jb25zdCBnZXRFeHBvcnRTcGVjaWZpZXJMb2NhbE5hbWUgPSAoXG4gIHNwZWNpZmllcjogdW5rbm93bixcbik6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IGNhbmRpZGF0ZSA9IGFzUmVjb3JkKHNwZWNpZmllcik7XG5cbiAgcmV0dXJuIHJlYWRTdHJpbmdQcm9wZXJ0eShjYW5kaWRhdGU/LltcImxvY2FsXCJdLCBcIm5hbWVcIik7XG59O1xuXG5leHBvcnQge1xuICBjb2xsZWN0UGF0dGVybklkZW50aWZpZXJOYW1lcyxcbiAgZ2V0RXhwb3J0U3BlY2lmaWVyTG9jYWxOYW1lLFxuICBnZXRFeHBvcnRTcGVjaWZpZXJOYW1lLFxufTtcbiJdfQ==
@@ -0,0 +1,18 @@
1
+ import * as ts from "typescript";
2
+ import type { ExportUsage, NoUnusedExportsState } from "./types.js";
3
+ /**
4
+ * Collects public API exposure usages for one exported symbol.
5
+ * @param program TypeScript program.
6
+ * @param sourceFilename Source filename where export is defined.
7
+ * @param state Normalized rule options.
8
+ * @param repoRoot Absolute repository root used for file classification.
9
+ * @param targetSymbol Export symbol being classified.
10
+ * @returns Public API exposure usages for the exported symbol.
11
+ * @example
12
+ * ```typescript
13
+ * const usages = collectPublicApiExposureUsages(program, sourceFilename, state, repoRoot, targetSymbol);
14
+ * ```
15
+ */
16
+ declare const collectPublicApiExposureUsages: (program: ts.Program, sourceFilename: string, state: NoUnusedExportsState, repoRoot: string, targetSymbol: ts.Symbol) => ExportUsage[];
17
+ export { collectPublicApiExposureUsages };
18
+ //# sourceMappingURL=no-unused-exports-public-api-usage-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unused-exports-public-api-usage-utilities.d.ts","sourceRoot":"","sources":["../../../../src/domain/architecture/no-unused-exports/no-unused-exports-public-api-usage-utilities.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAQjE;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,8BAA8B,GAClC,SAAS,EAAE,CAAC,OAAO,EACnB,gBAAgB,MAAM,EACtB,OAAO,oBAAoB,EAC3B,UAAU,MAAM,EAChB,cAAc,EAAE,CAAC,MAAM,KACtB,WAAW,EAiCb,CAAC;AAEF,OAAO,EAAE,8BAA8B,EAAE,CAAC"}
@@ -0,0 +1,45 @@
1
+ import path from "node:path";
2
+ import * as ts from "typescript";
3
+ import { isPublicApiFile, isTestFile } from "./no-unused-exports-options.js";
4
+ import { sourceFileExportsSymbol, toComparableAbsolutePath, } from "./no-unused-exports-symbol-utilities.js";
5
+ /**
6
+ * Collects public API exposure usages for one exported symbol.
7
+ * @param program TypeScript program.
8
+ * @param sourceFilename Source filename where export is defined.
9
+ * @param state Normalized rule options.
10
+ * @param repoRoot Absolute repository root used for file classification.
11
+ * @param targetSymbol Export symbol being classified.
12
+ * @returns Public API exposure usages for the exported symbol.
13
+ * @example
14
+ * ```typescript
15
+ * const usages = collectPublicApiExposureUsages(program, sourceFilename, state, repoRoot, targetSymbol);
16
+ * ```
17
+ */
18
+ const collectPublicApiExposureUsages = (program, sourceFilename, state, repoRoot, targetSymbol) => {
19
+ const checker = program.getTypeChecker();
20
+ const normalizedSourceFilename = toComparableAbsolutePath(sourceFilename);
21
+ const normalizedRepoRoot = path.resolve(repoRoot);
22
+ const usages = [];
23
+ for (const sourceFile of program.getSourceFiles()) {
24
+ if (sourceFile.isDeclarationFile) {
25
+ continue;
26
+ }
27
+ const publicApiFilename = path.resolve(sourceFile.fileName);
28
+ const normalizedPublicApiFilename = toComparableAbsolutePath(publicApiFilename);
29
+ if (normalizedPublicApiFilename === normalizedSourceFilename) {
30
+ continue;
31
+ }
32
+ if (!isPublicApiFile(publicApiFilename, state, normalizedRepoRoot)) {
33
+ continue;
34
+ }
35
+ if (!sourceFileExportsSymbol(sourceFile, checker, targetSymbol)) {
36
+ continue;
37
+ }
38
+ usages.push({
39
+ isTestFile: isTestFile(publicApiFilename, state, normalizedRepoRoot),
40
+ });
41
+ }
42
+ return usages;
43
+ };
44
+ export { collectPublicApiExposureUsages };
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tdW51c2VkLWV4cG9ydHMtcHVibGljLWFwaS11c2FnZS11dGlsaXRpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZG9tYWluL2FyY2hpdGVjdHVyZS9uby11bnVzZWQtZXhwb3J0cy9uby11bnVzZWQtZXhwb3J0cy1wdWJsaWMtYXBpLXVzYWdlLXV0aWxpdGllcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFDN0IsT0FBTyxLQUFLLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFJakMsT0FBTyxFQUFFLGVBQWUsRUFBRSxVQUFVLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMxRSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLHdCQUF3QixHQUN6QixNQUFNLHNDQUFzQyxDQUFDO0FBRTlDOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILE1BQU0sOEJBQThCLEdBQUcsQ0FDckMsT0FBbUIsRUFDbkIsY0FBc0IsRUFDdEIsS0FBMkIsRUFDM0IsUUFBZ0IsRUFDaEIsWUFBdUIsRUFDUixFQUFFO0lBQ2pCLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN6QyxNQUFNLHdCQUF3QixHQUFHLHdCQUF3QixDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzFFLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNsRCxNQUFNLE1BQU0sR0FBa0IsRUFBRSxDQUFDO0lBRWpDLEtBQUssTUFBTSxVQUFVLElBQUksT0FBTyxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUM7UUFDbEQsSUFBSSxVQUFVLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUNqQyxTQUFTO1FBQ1gsQ0FBQztRQUVELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDNUQsTUFBTSwyQkFBMkIsR0FDL0Isd0JBQXdCLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUU5QyxJQUFJLDJCQUEyQixLQUFLLHdCQUF3QixFQUFFLENBQUM7WUFDN0QsU0FBUztRQUNYLENBQUM7UUFFRCxJQUFJLENBQUMsZUFBZSxDQUFDLGlCQUFpQixFQUFFLEtBQUssRUFBRSxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7WUFDbkUsU0FBUztRQUNYLENBQUM7UUFFRCxJQUFJLENBQUMsdUJBQXVCLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQ2hFLFNBQVM7UUFDWCxDQUFDO1FBRUQsTUFBTSxDQUFDLElBQUksQ0FBQztZQUNWLFVBQVUsRUFBRSxVQUFVLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxFQUFFLGtCQUFrQixDQUFDO1NBQ3JFLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUM7QUFFRixPQUFPLEVBQUUsOEJBQThCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCAqIGFzIHRzIGZyb20gXCJ0eXBlc2NyaXB0XCI7XG5cbmltcG9ydCB0eXBlIHsgRXhwb3J0VXNhZ2UsIE5vVW51c2VkRXhwb3J0c1N0YXRlIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuaW1wb3J0IHsgaXNQdWJsaWNBcGlGaWxlLCBpc1Rlc3RGaWxlIH0gZnJvbSBcIi4vbm8tdW51c2VkLWV4cG9ydHMtb3B0aW9uc1wiO1xuaW1wb3J0IHtcbiAgc291cmNlRmlsZUV4cG9ydHNTeW1ib2wsXG4gIHRvQ29tcGFyYWJsZUFic29sdXRlUGF0aCxcbn0gZnJvbSBcIi4vbm8tdW51c2VkLWV4cG9ydHMtc3ltYm9sLXV0aWxpdGllc1wiO1xuXG4vKipcbiAqIENvbGxlY3RzIHB1YmxpYyBBUEkgZXhwb3N1cmUgdXNhZ2VzIGZvciBvbmUgZXhwb3J0ZWQgc3ltYm9sLlxuICogQHBhcmFtIHByb2dyYW0gVHlwZVNjcmlwdCBwcm9ncmFtLlxuICogQHBhcmFtIHNvdXJjZUZpbGVuYW1lIFNvdXJjZSBmaWxlbmFtZSB3aGVyZSBleHBvcnQgaXMgZGVmaW5lZC5cbiAqIEBwYXJhbSBzdGF0ZSBOb3JtYWxpemVkIHJ1bGUgb3B0aW9ucy5cbiAqIEBwYXJhbSByZXBvUm9vdCBBYnNvbHV0ZSByZXBvc2l0b3J5IHJvb3QgdXNlZCBmb3IgZmlsZSBjbGFzc2lmaWNhdGlvbi5cbiAqIEBwYXJhbSB0YXJnZXRTeW1ib2wgRXhwb3J0IHN5bWJvbCBiZWluZyBjbGFzc2lmaWVkLlxuICogQHJldHVybnMgUHVibGljIEFQSSBleHBvc3VyZSB1c2FnZXMgZm9yIHRoZSBleHBvcnRlZCBzeW1ib2wuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgdXNhZ2VzID0gY29sbGVjdFB1YmxpY0FwaUV4cG9zdXJlVXNhZ2VzKHByb2dyYW0sIHNvdXJjZUZpbGVuYW1lLCBzdGF0ZSwgcmVwb1Jvb3QsIHRhcmdldFN5bWJvbCk7XG4gKiBgYGBcbiAqL1xuY29uc3QgY29sbGVjdFB1YmxpY0FwaUV4cG9zdXJlVXNhZ2VzID0gKFxuICBwcm9ncmFtOiB0cy5Qcm9ncmFtLFxuICBzb3VyY2VGaWxlbmFtZTogc3RyaW5nLFxuICBzdGF0ZTogTm9VbnVzZWRFeHBvcnRzU3RhdGUsXG4gIHJlcG9Sb290OiBzdHJpbmcsXG4gIHRhcmdldFN5bWJvbDogdHMuU3ltYm9sLFxuKTogRXhwb3J0VXNhZ2VbXSA9PiB7XG4gIGNvbnN0IGNoZWNrZXIgPSBwcm9ncmFtLmdldFR5cGVDaGVja2VyKCk7XG4gIGNvbnN0IG5vcm1hbGl6ZWRTb3VyY2VGaWxlbmFtZSA9IHRvQ29tcGFyYWJsZUFic29sdXRlUGF0aChzb3VyY2VGaWxlbmFtZSk7XG4gIGNvbnN0IG5vcm1hbGl6ZWRSZXBvUm9vdCA9IHBhdGgucmVzb2x2ZShyZXBvUm9vdCk7XG4gIGNvbnN0IHVzYWdlczogRXhwb3J0VXNhZ2VbXSA9IFtdO1xuXG4gIGZvciAoY29uc3Qgc291cmNlRmlsZSBvZiBwcm9ncmFtLmdldFNvdXJjZUZpbGVzKCkpIHtcbiAgICBpZiAoc291cmNlRmlsZS5pc0RlY2xhcmF0aW9uRmlsZSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgcHVibGljQXBpRmlsZW5hbWUgPSBwYXRoLnJlc29sdmUoc291cmNlRmlsZS5maWxlTmFtZSk7XG4gICAgY29uc3Qgbm9ybWFsaXplZFB1YmxpY0FwaUZpbGVuYW1lID1cbiAgICAgIHRvQ29tcGFyYWJsZUFic29sdXRlUGF0aChwdWJsaWNBcGlGaWxlbmFtZSk7XG5cbiAgICBpZiAobm9ybWFsaXplZFB1YmxpY0FwaUZpbGVuYW1lID09PSBub3JtYWxpemVkU291cmNlRmlsZW5hbWUpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICghaXNQdWJsaWNBcGlGaWxlKHB1YmxpY0FwaUZpbGVuYW1lLCBzdGF0ZSwgbm9ybWFsaXplZFJlcG9Sb290KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKCFzb3VyY2VGaWxlRXhwb3J0c1N5bWJvbChzb3VyY2VGaWxlLCBjaGVja2VyLCB0YXJnZXRTeW1ib2wpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB1c2FnZXMucHVzaCh7XG4gICAgICBpc1Rlc3RGaWxlOiBpc1Rlc3RGaWxlKHB1YmxpY0FwaUZpbGVuYW1lLCBzdGF0ZSwgbm9ybWFsaXplZFJlcG9Sb290KSxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB1c2FnZXM7XG59O1xuXG5leHBvcnQgeyBjb2xsZWN0UHVibGljQXBpRXhwb3N1cmVVc2FnZXMgfTtcbiJdfQ==
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Converts one unknown value into an indexable record.
3
+ * @param value Candidate value.
4
+ * @returns Record view when the value is object-like.
5
+ * @example
6
+ * ```typescript
7
+ * const record = asRecord({ type: "Identifier" });
8
+ * ```
9
+ */
10
+ declare const asRecord: (value: unknown) => Record<string, unknown> | undefined;
11
+ /**
12
+ * Reads one array property from an object-like value.
13
+ * @param value Candidate object.
14
+ * @param key Lookup key used to read the property.
15
+ * @returns Array value when present.
16
+ * @example
17
+ * ```typescript
18
+ * const items = readArrayProperty({ elements: [1, 2] }, "elements");
19
+ * ```
20
+ */
21
+ declare const readArrayProperty: (value: unknown, key: string) => undefined | unknown[];
22
+ /**
23
+ * Reads one string property from an object-like value.
24
+ * @param value Candidate object.
25
+ * @param key Lookup key used to read the property.
26
+ * @returns String value when present.
27
+ * @example
28
+ * ```typescript
29
+ * const name = readStringProperty({ name: "feature" }, "name");
30
+ * ```
31
+ */
32
+ declare const readStringProperty: (value: unknown, key: string) => string | undefined;
33
+ export { asRecord, readArrayProperty, readStringProperty };
34
+ //# sourceMappingURL=no-unused-exports-record-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unused-exports-record-utilities.d.ts","sourceRoot":"","sources":["../../../../src/domain/architecture/no-unused-exports/no-unused-exports-record-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,QAAA,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAGjD,CAAC;AAEb;;;;;;;;;GASG;AACH,QAAA,MAAM,iBAAiB,GACrB,OAAO,OAAO,EACd,KAAK,MAAM,KACV,SAAS,GAAG,OAAO,EAIrB,CAAC;AAEF;;;;;;;;;GASG;AACH,QAAA,MAAM,kBAAkB,GACtB,OAAO,OAAO,EACd,KAAK,MAAM,KACV,MAAM,GAAG,SAIX,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Converts one unknown value into an indexable record.
3
+ * @param value Candidate value.
4
+ * @returns Record view when the value is object-like.
5
+ * @example
6
+ * ```typescript
7
+ * const record = asRecord({ type: "Identifier" });
8
+ * ```
9
+ */
10
+ const asRecord = (value) => value !== null && typeof value === "object"
11
+ ? value
12
+ : void 0;
13
+ /**
14
+ * Reads one array property from an object-like value.
15
+ * @param value Candidate object.
16
+ * @param key Lookup key used to read the property.
17
+ * @returns Array value when present.
18
+ * @example
19
+ * ```typescript
20
+ * const items = readArrayProperty({ elements: [1, 2] }, "elements");
21
+ * ```
22
+ */
23
+ const readArrayProperty = (value, key) => {
24
+ const record = asRecord(value);
25
+ const property = record?.[key];
26
+ return Array.isArray(property) ? property : void 0;
27
+ };
28
+ /**
29
+ * Reads one string property from an object-like value.
30
+ * @param value Candidate object.
31
+ * @param key Lookup key used to read the property.
32
+ * @returns String value when present.
33
+ * @example
34
+ * ```typescript
35
+ * const name = readStringProperty({ name: "feature" }, "name");
36
+ * ```
37
+ */
38
+ const readStringProperty = (value, key) => {
39
+ const record = asRecord(value);
40
+ const property = record?.[key];
41
+ return typeof property === "string" ? property : void 0;
42
+ };
43
+ export { asRecord, readArrayProperty, readStringProperty };
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tdW51c2VkLWV4cG9ydHMtcmVjb3JkLXV0aWxpdGllcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kb21haW4vYXJjaGl0ZWN0dXJlL25vLXVudXNlZC1leHBvcnRzL25vLXVudXNlZC1leHBvcnRzLXJlY29yZC11dGlsaXRpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFFBQVEsR0FBRyxDQUFDLEtBQWMsRUFBdUMsRUFBRSxDQUN2RSxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7SUFDekMsQ0FBQyxDQUFFLEtBQWlDO0lBQ3BDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUViOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0saUJBQWlCLEdBQUcsQ0FDeEIsS0FBYyxFQUNkLEdBQVcsRUFDWSxFQUFFO0lBQ3pCLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvQixNQUFNLFFBQVEsR0FBRyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvQixPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDckQsQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxrQkFBa0IsR0FBRyxDQUN6QixLQUFjLEVBQ2QsR0FBVyxFQUNTLEVBQUU7SUFDdEIsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9CLE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLE9BQU8sT0FBTyxRQUFRLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzFELENBQUMsQ0FBQztBQUVGLE9BQU8sRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29udmVydHMgb25lIHVua25vd24gdmFsdWUgaW50byBhbiBpbmRleGFibGUgcmVjb3JkLlxuICogQHBhcmFtIHZhbHVlIENhbmRpZGF0ZSB2YWx1ZS5cbiAqIEByZXR1cm5zIFJlY29yZCB2aWV3IHdoZW4gdGhlIHZhbHVlIGlzIG9iamVjdC1saWtlLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHJlY29yZCA9IGFzUmVjb3JkKHsgdHlwZTogXCJJZGVudGlmaWVyXCIgfSk7XG4gKiBgYGBcbiAqL1xuY29uc3QgYXNSZWNvcmQgPSAodmFsdWU6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZCA9PlxuICB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCJcbiAgICA/ICh2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilcbiAgICA6IHZvaWQgMDtcblxuLyoqXG4gKiBSZWFkcyBvbmUgYXJyYXkgcHJvcGVydHkgZnJvbSBhbiBvYmplY3QtbGlrZSB2YWx1ZS5cbiAqIEBwYXJhbSB2YWx1ZSBDYW5kaWRhdGUgb2JqZWN0LlxuICogQHBhcmFtIGtleSBMb29rdXAga2V5IHVzZWQgdG8gcmVhZCB0aGUgcHJvcGVydHkuXG4gKiBAcmV0dXJucyBBcnJheSB2YWx1ZSB3aGVuIHByZXNlbnQuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgaXRlbXMgPSByZWFkQXJyYXlQcm9wZXJ0eSh7IGVsZW1lbnRzOiBbMSwgMl0gfSwgXCJlbGVtZW50c1wiKTtcbiAqIGBgYFxuICovXG5jb25zdCByZWFkQXJyYXlQcm9wZXJ0eSA9IChcbiAgdmFsdWU6IHVua25vd24sXG4gIGtleTogc3RyaW5nLFxuKTogdW5kZWZpbmVkIHwgdW5rbm93bltdID0+IHtcbiAgY29uc3QgcmVjb3JkID0gYXNSZWNvcmQodmFsdWUpO1xuICBjb25zdCBwcm9wZXJ0eSA9IHJlY29yZD8uW2tleV07XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHByb3BlcnR5KSA/IHByb3BlcnR5IDogdm9pZCAwO1xufTtcblxuLyoqXG4gKiBSZWFkcyBvbmUgc3RyaW5nIHByb3BlcnR5IGZyb20gYW4gb2JqZWN0LWxpa2UgdmFsdWUuXG4gKiBAcGFyYW0gdmFsdWUgQ2FuZGlkYXRlIG9iamVjdC5cbiAqIEBwYXJhbSBrZXkgTG9va3VwIGtleSB1c2VkIHRvIHJlYWQgdGhlIHByb3BlcnR5LlxuICogQHJldHVybnMgU3RyaW5nIHZhbHVlIHdoZW4gcHJlc2VudC5cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBuYW1lID0gcmVhZFN0cmluZ1Byb3BlcnR5KHsgbmFtZTogXCJmZWF0dXJlXCIgfSwgXCJuYW1lXCIpO1xuICogYGBgXG4gKi9cbmNvbnN0IHJlYWRTdHJpbmdQcm9wZXJ0eSA9IChcbiAgdmFsdWU6IHVua25vd24sXG4gIGtleTogc3RyaW5nLFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IHtcbiAgY29uc3QgcmVjb3JkID0gYXNSZWNvcmQodmFsdWUpO1xuICBjb25zdCBwcm9wZXJ0eSA9IHJlY29yZD8uW2tleV07XG4gIHJldHVybiB0eXBlb2YgcHJvcGVydHkgPT09IFwic3RyaW5nXCIgPyBwcm9wZXJ0eSA6IHZvaWQgMDtcbn07XG5cbmV4cG9ydCB7IGFzUmVjb3JkLCByZWFkQXJyYXlQcm9wZXJ0eSwgcmVhZFN0cmluZ1Byb3BlcnR5IH07XG4iXX0=
@@ -0,0 +1,59 @@
1
+ import * as ts from "typescript";
2
+ /**
3
+ * Normalizes an absolute file path for safe equality checks.
4
+ * @param inputPath Candidate path.
5
+ * @returns Normalized absolute path suitable for cross-platform comparisons.
6
+ * @example
7
+ * ```typescript
8
+ * const comparable = toComparableAbsolutePath("/repo/src/feature.ts");
9
+ * ```
10
+ */
11
+ declare const toComparableAbsolutePath: (inputPath: string) => string;
12
+ /**
13
+ * Checks whether two symbols reference the same declaration site.
14
+ * @param left Left-hand symbol candidate.
15
+ * @param right Right-hand symbol candidate.
16
+ * @returns True when both symbols identify the same declaration.
17
+ * @example
18
+ * ```typescript
19
+ * const same = isSameSymbol(left, right);
20
+ * ```
21
+ */
22
+ declare const isSameSymbol: (left: ts.Symbol, right: ts.Symbol) => boolean;
23
+ /**
24
+ * Resolves one symbol to its canonical target.
25
+ * @param symbol Candidate symbol.
26
+ * @param checker TypeScript checker.
27
+ * @returns Resolved canonical symbol.
28
+ * @example
29
+ * ```typescript
30
+ * const resolved = resolveCanonicalSymbol(symbol, checker);
31
+ * ```
32
+ */
33
+ declare const resolveCanonicalSymbol: (symbol: ts.Symbol, checker: ts.TypeChecker) => ts.Symbol;
34
+ /**
35
+ * Resolves one exported symbol by name from a source file.
36
+ * @param program TypeScript program.
37
+ * @param sourceFilename Source file path.
38
+ * @param exportedName Public name exposed by the module export list.
39
+ * @returns Symbol when found.
40
+ * @example
41
+ * ```typescript
42
+ * const symbol = getExportedSymbol(program, sourceFilename, "feature");
43
+ * ```
44
+ */
45
+ declare const getExportedSymbol: (program: ts.Program, sourceFilename: string, exportedName: string) => ts.Symbol | undefined;
46
+ /**
47
+ * Checks whether one source file exports the target symbol.
48
+ * @param sourceFile Source file that may expose the symbol.
49
+ * @param checker TypeScript checker.
50
+ * @param targetSymbol Symbol being classified.
51
+ * @returns True when one module export resolves to the target symbol.
52
+ * @example
53
+ * ```typescript
54
+ * const exposed = sourceFileExportsSymbol(sourceFile, checker, targetSymbol);
55
+ * ```
56
+ */
57
+ declare const sourceFileExportsSymbol: (sourceFile: ts.SourceFile, checker: ts.TypeChecker, targetSymbol: ts.Symbol) => boolean;
58
+ export { getExportedSymbol, isSameSymbol, resolveCanonicalSymbol, sourceFileExportsSymbol, toComparableAbsolutePath, };
59
+ //# sourceMappingURL=no-unused-exports-symbol-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unused-exports-symbol-utilities.d.ts","sourceRoot":"","sources":["../../../../src/domain/architecture/no-unused-exports/no-unused-exports-symbol-utilities.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC;;;;;;;;GAQG;AACH,QAAA,MAAM,wBAAwB,GAAI,WAAW,MAAM,KAAG,MAIrD,CAAC;AAsBF;;;;;;;;;GASG;AACH,QAAA,MAAM,YAAY,GAAI,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,KAAG,OAezD,CAAC;AAEF;;;;;;;;;GASG;AACH,QAAA,MAAM,sBAAsB,GAC1B,QAAQ,EAAE,CAAC,MAAM,EACjB,SAAS,EAAE,CAAC,WAAW,KACtB,EAAE,CAAC,MAUL,CAAC;AAEF;;;;;;;;;;GAUG;AACH,QAAA,MAAM,iBAAiB,GACrB,SAAS,EAAE,CAAC,OAAO,EACnB,gBAAgB,MAAM,EACtB,cAAc,MAAM,KACnB,EAAE,CAAC,MAAM,GAAG,SA6Bd,CAAC;AAEF;;;;;;;;;;GAUG;AACH,QAAA,MAAM,uBAAuB,GAC3B,YAAY,EAAE,CAAC,UAAU,EACzB,SAAS,EAAE,CAAC,WAAW,EACvB,cAAc,EAAE,CAAC,MAAM,KACtB,OAgBF,CAAC;AAEF,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,GACzB,CAAC"}
@@ -0,0 +1,133 @@
1
+ import path from "node:path";
2
+ import * as ts from "typescript";
3
+ /**
4
+ * Normalizes an absolute file path for safe equality checks.
5
+ * @param inputPath Candidate path.
6
+ * @returns Normalized absolute path suitable for cross-platform comparisons.
7
+ * @example
8
+ * ```typescript
9
+ * const comparable = toComparableAbsolutePath("/repo/src/feature.ts");
10
+ * ```
11
+ */
12
+ const toComparableAbsolutePath = (inputPath) => {
13
+ const absolutePath = path.normalize(path.resolve(inputPath));
14
+ return absolutePath.toLowerCase();
15
+ };
16
+ /**
17
+ * Builds declaration-site keys for symbol identity matching.
18
+ * @param symbol Symbol being compared.
19
+ * @returns Declaration keys describing where this symbol is declared.
20
+ * @example
21
+ * ```typescript
22
+ * const keys = getDeclarationKeys(symbol);
23
+ * ```
24
+ */
25
+ const getDeclarationKeys = (symbol) => {
26
+ const declarations = symbol.declarations ?? [];
27
+ return new Set(declarations.map((declaration) => {
28
+ const sourceFilename = declaration.getSourceFile().fileName;
29
+ return `${sourceFilename}:${String(declaration.pos)}:${String(declaration.end)}`;
30
+ }));
31
+ };
32
+ /**
33
+ * Checks whether two symbols reference the same declaration site.
34
+ * @param left Left-hand symbol candidate.
35
+ * @param right Right-hand symbol candidate.
36
+ * @returns True when both symbols identify the same declaration.
37
+ * @example
38
+ * ```typescript
39
+ * const same = isSameSymbol(left, right);
40
+ * ```
41
+ */
42
+ const isSameSymbol = (left, right) => {
43
+ if (left === right) {
44
+ return true;
45
+ }
46
+ const leftKeys = getDeclarationKeys(left);
47
+ const rightKeys = getDeclarationKeys(right);
48
+ for (const key of leftKeys) {
49
+ if (rightKeys.has(key)) {
50
+ return true;
51
+ }
52
+ }
53
+ return false;
54
+ };
55
+ /**
56
+ * Resolves one symbol to its canonical target.
57
+ * @param symbol Candidate symbol.
58
+ * @param checker TypeScript checker.
59
+ * @returns Resolved canonical symbol.
60
+ * @example
61
+ * ```typescript
62
+ * const resolved = resolveCanonicalSymbol(symbol, checker);
63
+ * ```
64
+ */
65
+ const resolveCanonicalSymbol = (symbol, checker) => {
66
+ if ((symbol.flags & ts.SymbolFlags.Alias) === 0) {
67
+ return symbol;
68
+ }
69
+ try {
70
+ return checker.getAliasedSymbol(symbol);
71
+ }
72
+ catch {
73
+ return symbol;
74
+ }
75
+ };
76
+ /**
77
+ * Resolves one exported symbol by name from a source file.
78
+ * @param program TypeScript program.
79
+ * @param sourceFilename Source file path.
80
+ * @param exportedName Public name exposed by the module export list.
81
+ * @returns Symbol when found.
82
+ * @example
83
+ * ```typescript
84
+ * const symbol = getExportedSymbol(program, sourceFilename, "feature");
85
+ * ```
86
+ */
87
+ const getExportedSymbol = (program, sourceFilename, exportedName) => {
88
+ const checker = program.getTypeChecker();
89
+ const sourceFile = program
90
+ .getSourceFiles()
91
+ .find((file) => toComparableAbsolutePath(file.fileName) ===
92
+ toComparableAbsolutePath(sourceFilename));
93
+ if (sourceFile === void 0) {
94
+ return void 0;
95
+ }
96
+ const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
97
+ if (moduleSymbol === void 0) {
98
+ return void 0;
99
+ }
100
+ const exportedSymbol = checker
101
+ .getExportsOfModule(moduleSymbol)
102
+ .find((symbol) => symbol.getName() === exportedName);
103
+ if (exportedSymbol === void 0) {
104
+ return void 0;
105
+ }
106
+ return resolveCanonicalSymbol(exportedSymbol, checker);
107
+ };
108
+ /**
109
+ * Checks whether one source file exports the target symbol.
110
+ * @param sourceFile Source file that may expose the symbol.
111
+ * @param checker TypeScript checker.
112
+ * @param targetSymbol Symbol being classified.
113
+ * @returns True when one module export resolves to the target symbol.
114
+ * @example
115
+ * ```typescript
116
+ * const exposed = sourceFileExportsSymbol(sourceFile, checker, targetSymbol);
117
+ * ```
118
+ */
119
+ const sourceFileExportsSymbol = (sourceFile, checker, targetSymbol) => {
120
+ const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
121
+ if (moduleSymbol === void 0) {
122
+ return false;
123
+ }
124
+ for (const exportedSymbol of checker.getExportsOfModule(moduleSymbol)) {
125
+ const resolvedSymbol = resolveCanonicalSymbol(exportedSymbol, checker);
126
+ if (isSameSymbol(resolvedSymbol, targetSymbol)) {
127
+ return true;
128
+ }
129
+ }
130
+ return false;
131
+ };
132
+ export { getExportedSymbol, isSameSymbol, resolveCanonicalSymbol, sourceFileExportsSymbol, toComparableAbsolutePath, };
133
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tdW51c2VkLWV4cG9ydHMtc3ltYm9sLXV0aWxpdGllcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kb21haW4vYXJjaGl0ZWN0dXJlL25vLXVudXNlZC1leHBvcnRzL25vLXVudXNlZC1leHBvcnRzLXN5bWJvbC11dGlsaXRpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sS0FBSyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWpDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLFNBQWlCLEVBQVUsRUFBRTtJQUM3RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUU3RCxPQUFPLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztBQUNwQyxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxNQUFpQixFQUFlLEVBQUU7SUFDNUQsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFlBQVksSUFBSSxFQUFFLENBQUM7SUFFL0MsT0FBTyxJQUFJLEdBQUcsQ0FDWixZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUU7UUFDL0IsTUFBTSxjQUFjLEdBQUcsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDLFFBQVEsQ0FBQztRQUM1RCxPQUFPLEdBQUcsY0FBYyxJQUFJLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO0lBQ25GLENBQUMsQ0FBQyxDQUNILENBQUM7QUFDSixDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFlBQVksR0FBRyxDQUFDLElBQWUsRUFBRSxLQUFnQixF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Y0FBYyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDL0MsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyxDQUFDO0FBRUYsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixZQUFZLEVBQ1osc0JBQXNCLEVBQ3RCLHVCQUF1QixFQUN2Qix3QkFBd0IsR0FDekIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCAqIGFzIHRzIGZyb20gXCJ0eXBlc2NyaXB0XCI7XG5cbi8qKlxuICogTm9ybWFsaXplcyBhbiBhYnNvbHV0ZSBmaWxlIHBhdGggZm9yIHNhZmUgZXF1YWxpdHkgY2hlY2tzLlxuICogQHBhcmFtIGlucHV0UGF0aCBDYW5kaWRhdGUgcGF0aC5cbiAqIEByZXR1cm5zIE5vcm1hbGl6ZWQgYWJzb2x1dGUgcGF0aCBzdWl0YWJsZSBmb3IgY3Jvc3MtcGxhdGZvcm0gY29tcGFyaXNvbnMuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgY29tcGFyYWJsZSA9IHRvQ29tcGFyYWJsZUFic29sdXRlUGF0aChcIi9yZXBvL3NyYy9mZWF0dXJlLnRzXCIpO1xuICogYGBgXG4gKi9cbmNvbnN0IHRvQ29tcGFyYWJsZUFic29sdXRlUGF0aCA9IChpbnB1dFBhdGg6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGFic29sdXRlUGF0aCA9IHBhdGgubm9ybWFsaXplKHBhdGgucmVzb2x2ZShpbnB1dFBhdGgpKTtcblxuICByZXR1cm4gYWJzb2x1dGVQYXRoLnRvTG93ZXJDYXNlKCk7XG59O1xuXG4vKipcbiAqIEJ1aWxkcyBkZWNsYXJhdGlvbi1zaXRlIGtleXMgZm9yIHN5bWJvbCBpZGVudGl0eSBtYXRjaGluZy5cbiAqIEBwYXJhbSBzeW1ib2wgU3ltYm9sIGJlaW5nIGNvbXBhcmVkLlxuICogQHJldHVybnMgRGVjbGFyYXRpb24ga2V5cyBkZXNjcmliaW5nIHdoZXJlIHRoaXMgc3ltYm9sIGlzIGRlY2xhcmVkLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGtleXMgPSBnZXREZWNsYXJhdGlvbktleXMoc3ltYm9sKTtcbiAqIGBgYFxuICovXG5jb25zdCBnZXREZWNsYXJhdGlvbktleXMgPSAoc3ltYm9sOiB0cy5TeW1ib2wpOiBTZXQ8c3RyaW5nPiA9PiB7XG4gIGNvbnN0IGRlY2xhcmF0aW9ucyA9IHN5bWJvbC5kZWNsYXJhdGlvbnMgPz8gW107XG5cbiAgcmV0dXJuIG5ldyBTZXQoXG4gICAgZGVjbGFyYXRpb25zLm1hcCgoZGVjbGFyYXRpb24pID0+IHtcbiAgICAgIGNvbnN0IHNvdXJjZUZpbGVuYW1lID0gZGVjbGFyYXRpb24uZ2V0U291cmNlRmlsZSgpLmZpbGVOYW1lO1xuICAgICAgcmV0dXJuIGAke3NvdXJjZUZpbGVuYW1lfToke1N0cmluZyhkZWNsYXJhdGlvbi5wb3MpfToke1N0cmluZyhkZWNsYXJhdGlvbi5lbmQpfWA7XG4gICAgfSksXG4gICk7XG59O1xuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHR3byBzeW1ib2xzIHJlZmVyZW5jZSB0aGUgc2FtZSBkZWNsYXJhdGlvbiBzaXRlLlxuICogQHBhcmFtIGxlZnQgTGVmdC1oYW5kIHN5bWJvbCBjYW5kaWRhdGUuXG4gKiBAcGFyYW0gcmlnaHQgUmlnaHQtaGFuZCBzeW1ib2wgY2FuZGlkYXRlLlxuICogQHJldHVybnMgVHJ1ZSB3aGVuIGJvdGggc3ltYm9scyBpZGVudGlmeSB0aGUgc2FtZSBkZWNsYXJhdGlvbi5cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBzYW1lID0gaXNTYW1lU3ltYm9sKGxlZnQsIHJpZ2h0KTtcbiAqIGBgYFxuICovXG5jb25zdCBpc1NhbWVTeW1ib2wgPSAobGVmdDogdHMuU3ltYm9sLCByaWdodDogdHMuU3ltYm9sKTogYm9vbGVhbiA9PiB7XG4gIGlmIChsZWZ0ID09PSByaWdodCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgbGVmdEtleXMgPSBnZXREZWNsYXJhdGlvbktleXMobGVmdCk7XG4gIGNvbnN0IHJpZ2h0S2V5cyA9IGdldERlY2xhcmF0aW9uS2V5cyhyaWdodCk7XG5cbiAgZm9yIChjb25zdCBrZXkgb2YgbGVmdEtleXMpIHtcbiAgICBpZiAocmlnaHRLZXlzLmhhcyhrZXkpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIFJlc29sdmVzIG9uZSBzeW1ib2wgdG8gaXRzIGNhbm9uaWNhbCB0YXJnZXQuXG4gKiBAcGFyYW0gc3ltYm9sIENhbmRpZGF0ZSBzeW1ib2wuXG4gKiBAcGFyYW0gY2hlY2tlciBUeXBlU2NyaXB0IGNoZWNrZXIuXG4gKiBAcmV0dXJucyBSZXNvbHZlZCBjYW5vbmljYWwgc3ltYm9sLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZUNhbm9uaWNhbFN5bWJvbChzeW1ib2wsIGNoZWNrZXIpO1xuICogYGBgXG4gKi9cbmNvbnN0IHJlc29sdmVDYW5vbmljYWxTeW1ib2wgPSAoXG4gIHN5bWJvbDogdHMuU3ltYm9sLFxuICBjaGVja2VyOiB0cy5UeXBlQ2hlY2tlcixcbik6IHRzLlN5bWJvbCA9PiB7XG4gIGlmICgoc3ltYm9sLmZsYWdzICYgdHMuU3ltYm9sRmxhZ3MuQWxpYXMpID09PSAwKSB7XG4gICAgcmV0dXJuIHN5bWJvbDtcbiAgfVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGNoZWNrZXIuZ2V0QWxpYXNlZFN5bWJvbChzeW1ib2wpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gc3ltYm9sO1xuICB9XG59O1xuXG4vKipcbiAqIFJlc29sdmVzIG9uZSBleHBvcnRlZCBzeW1ib2wgYnkgbmFtZSBmcm9tIGEgc291cmNlIGZpbGUuXG4gKiBAcGFyYW0gcHJvZ3JhbSBUeXBlU2NyaXB0IHByb2dyYW0uXG4gKiBAcGFyYW0gc291cmNlRmlsZW5hbWUgU291cmNlIGZpbGUgcGF0aC5cbiAqIEBwYXJhbSBleHBvcnRlZE5hbWUgUHVibGljIG5hbWUgZXhwb3NlZCBieSB0aGUgbW9kdWxlIGV4cG9ydCBsaXN0LlxuICogQHJldHVybnMgU3ltYm9sIHdoZW4gZm91bmQuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3Qgc3ltYm9sID0gZ2V0RXhwb3J0ZWRTeW1ib2wocHJvZ3JhbSwgc291cmNlRmlsZW5hbWUsIFwiZmVhdHVyZVwiKTtcbiAqIGBgYFxuICovXG5jb25zdCBnZXRFeHBvcnRlZFN5bWJvbCA9IChcbiAgcHJvZ3JhbTogdHMuUHJvZ3JhbSxcbiAgc291cmNlRmlsZW5hbWU6IHN0cmluZyxcbiAgZXhwb3J0ZWROYW1lOiBzdHJpbmcsXG4pOiB0cy5TeW1ib2wgfCB1bmRlZmluZWQgPT4ge1xuICBjb25zdCBjaGVja2VyID0gcHJvZ3JhbS5nZXRUeXBlQ2hlY2tlcigpO1xuICBjb25zdCBzb3VyY2VGaWxlID0gcHJvZ3JhbVxuICAgIC5nZXRTb3VyY2VGaWxlcygpXG4gICAgLmZpbmQoXG4gICAgICAoZmlsZSkgPT5cbiAgICAgICAgdG9Db21wYXJhYmxlQWJzb2x1dGVQYXRoKGZpbGUuZmlsZU5hbWUpID09PVxuICAgICAgICB0b0NvbXBhcmFibGVBYnNvbHV0ZVBhdGgoc291cmNlRmlsZW5hbWUpLFxuICAgICk7XG5cbiAgaWYgKHNvdXJjZUZpbGUgPT09IHZvaWQgMCkge1xuICAgIHJldHVybiB2b2lkIDA7XG4gIH1cblxuICBjb25zdCBtb2R1bGVTeW1ib2wgPSBjaGVja2VyLmdldFN5bWJvbEF0TG9jYXRpb24oc291cmNlRmlsZSk7XG5cbiAgaWYgKG1vZHVsZVN5bWJvbCA9PT0gdm9pZCAwKSB7XG4gICAgcmV0dXJuIHZvaWQgMDtcbiAgfVxuXG4gIGNvbnN0IGV4cG9ydGVkU3ltYm9sID0gY2hlY2tlclxuICAgIC5nZXRFeHBvcnRzT2ZNb2R1bGUobW9kdWxlU3ltYm9sKVxuICAgIC5maW5kKChzeW1ib2wpID0+IHN5bWJvbC5nZXROYW1lKCkgPT09IGV4cG9ydGVkTmFtZSk7XG5cbiAgaWYgKGV4cG9ydGVkU3ltYm9sID09PSB2b2lkIDApIHtcbiAgICByZXR1cm4gdm9pZCAwO1xuICB9XG5cbiAgcmV0dXJuIHJlc29sdmVDYW5vbmljYWxTeW1ib2woZXhwb3J0ZWRTeW1ib2wsIGNoZWNrZXIpO1xufTtcblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBvbmUgc291cmNlIGZpbGUgZXhwb3J0cyB0aGUgdGFyZ2V0IHN5bWJvbC5cbiAqIEBwYXJhbSBzb3VyY2VGaWxlIFNvdXJjZSBmaWxlIHRoYXQgbWF5IGV4cG9zZSB0aGUgc3ltYm9sLlxuICogQHBhcmFtIGNoZWNrZXIgVHlwZVNjcmlwdCBjaGVja2VyLlxuICogQHBhcmFtIHRhcmdldFN5bWJvbCBTeW1ib2wgYmVpbmcgY2xhc3NpZmllZC5cbiAqIEByZXR1cm5zIFRydWUgd2hlbiBvbmUgbW9kdWxlIGV4cG9ydCByZXNvbHZlcyB0byB0aGUgdGFyZ2V0IHN5bWJvbC5cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBleHBvc2VkID0gc291cmNlRmlsZUV4cG9ydHNTeW1ib2woc291cmNlRmlsZSwgY2hlY2tlciwgdGFyZ2V0U3ltYm9sKTtcbiAqIGBgYFxuICovXG5jb25zdCBzb3VyY2VGaWxlRXhwb3J0c1N5bWJvbCA9IChcbiAgc291cmNlRmlsZTogdHMuU291cmNlRmlsZSxcbiAgY2hlY2tlcjogdHMuVHlwZUNoZWNrZXIsXG4gIHRhcmdldFN5bWJvbDogdHMuU3ltYm9sLFxuKTogYm9vbGVhbiA9PiB7XG4gIGNvbnN0IG1vZHVsZVN5bWJvbCA9IGNoZWNrZXIuZ2V0U3ltYm9sQXRMb2NhdGlvbihzb3VyY2VGaWxlKTtcblxuICBpZiAobW9kdWxlU3ltYm9sID09PSB2b2lkIDApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBmb3IgKGNvbnN0IGV4cG9ydGVkU3ltYm9sIG9mIGNoZWNrZXIuZ2V0RXhwb3J0c09mTW9kdWxlKG1vZHVsZVN5bWJvbCkpIHtcbiAgICBjb25zdCByZXNvbHZlZFN5bWJvbCA9IHJlc29sdmVDYW5vbmljYWxTeW1ib2woZXhwb3J0ZWRTeW1ib2wsIGNoZWNrZXIpO1xuXG4gICAgaWYgKGlzU2FtZVN5bWJvbChyZXNvbHZlZFN5bWJvbCwgdGFyZ2V0U3ltYm9sKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuZXhwb3J0IHtcbiAgZ2V0RXhwb3J0ZWRTeW1ib2wsXG4gIGlzU2FtZVN5bWJvbCxcbiAgcmVzb2x2ZUNhbm9uaWNhbFN5bWJvbCxcbiAgc291cmNlRmlsZUV4cG9ydHNTeW1ib2wsXG4gIHRvQ29tcGFyYWJsZUFic29sdXRlUGF0aCxcbn07XG4iXX0=
@@ -0,0 +1,28 @@
1
+ import * as ts from "typescript";
2
+ import type { ExportedElement, ExportUsage, NoUnusedExportsState } from "./types.js";
3
+ /**
4
+ * Collects concrete usages of one exported element across the program.
5
+ * @param program TypeScript program.
6
+ * @param sourceFilename Source filename where export is defined.
7
+ * @param state Normalized rule options.
8
+ * @param repoRoot Absolute repository root used for test-file classification.
9
+ * @param exportedElement Exported element to classify.
10
+ * @returns Concrete usages for the exported element.
11
+ * @example
12
+ * ```typescript
13
+ * const usages = collectCrossFileUsages(program, "/repo/src/feature.ts", state, "/repo", exportedElement);
14
+ * ```
15
+ */
16
+ declare const collectCrossFileUsages: (program: ts.Program, sourceFilename: string, state: NoUnusedExportsState, repoRoot: string, exportedElement: ExportedElement) => ExportUsage[];
17
+ /**
18
+ * Classifies one exported name based on cross-file usages.
19
+ * @param usages Collected usages.
20
+ * @returns Classification label.
21
+ * @example
22
+ * ```typescript
23
+ * const classification = classifyExportUsage("feature", usages);
24
+ * ```
25
+ */
26
+ declare const classifyExportUsage: (usages: ExportUsage[]) => "production" | "test-only" | "unused";
27
+ export { classifyExportUsage, collectCrossFileUsages };
28
+ //# sourceMappingURL=no-unused-exports-usage-utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unused-exports-usage-utilities.d.ts","sourceRoot":"","sources":["../../../../src/domain/architecture/no-unused-exports/no-unused-exports-usage-utilities.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAuEjB;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,sBAAsB,GAC1B,SAAS,EAAE,CAAC,OAAO,EACnB,gBAAgB,MAAM,EACtB,OAAO,oBAAoB,EAC3B,UAAU,MAAM,EAChB,iBAAiB,eAAe,KAC/B,WAAW,EAoDb,CAAC;AAEF;;;;;;;;GAQG;AACH,QAAA,MAAM,mBAAmB,GACvB,QAAQ,WAAW,EAAE,KACpB,YAAY,GAAG,WAAW,GAAG,QAY/B,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,106 @@
1
+ import path from "node:path";
2
+ import * as ts from "typescript";
3
+ import { isConcreteUsageIdentifier } from "./no-unused-exports-identifier-utilities.js";
4
+ import { isTestFile } from "./no-unused-exports-options.js";
5
+ import { collectPublicApiExposureUsages } from "./no-unused-exports-public-api-usage-utilities.js";
6
+ import { getExportedSymbol, isSameSymbol, resolveCanonicalSymbol, toComparableAbsolutePath, } from "./no-unused-exports-symbol-utilities.js";
7
+ /**
8
+ * Appends concrete usages from one source file into the accumulator.
9
+ * @param sourceFile Source file to scan.
10
+ * @param checker TypeScript checker.
11
+ * @param targetSymbol Export symbol being classified.
12
+ * @param exportedElement Export metadata.
13
+ * @param consumerIsTestFile Whether source file is a test file.
14
+ * @param usages Mutable usage accumulator.
15
+ * @example
16
+ * ```typescript
17
+ * collectConcreteUsagesFromSourceFile(sourceFile, checker, targetSymbolKey, exportedElement, false, usages);
18
+ * ```
19
+ */
20
+ const collectConcreteUsagesFromSourceFile = (sourceFile, checker, targetSymbol, exportedElement, consumerIsTestFile, usages) => {
21
+ const visitNode = (node) => {
22
+ if (!ts.isIdentifier(node)) {
23
+ ts.forEachChild(node, visitNode);
24
+ return;
25
+ }
26
+ if (!isConcreteUsageIdentifier(node, exportedElement.exportKind)) {
27
+ ts.forEachChild(node, visitNode);
28
+ return;
29
+ }
30
+ const isShorthandName = ts.isShorthandPropertyAssignment(node.parent) &&
31
+ node.parent.name === node;
32
+ const candidateSymbol = isShorthandName
33
+ ? checker.getShorthandAssignmentValueSymbol(node.parent)
34
+ : checker.getSymbolAtLocation(node);
35
+ if (candidateSymbol === void 0) {
36
+ ts.forEachChild(node, visitNode);
37
+ return;
38
+ }
39
+ const resolvedSymbol = resolveCanonicalSymbol(candidateSymbol, checker);
40
+ if (!isSameSymbol(resolvedSymbol, targetSymbol)) {
41
+ ts.forEachChild(node, visitNode);
42
+ return;
43
+ }
44
+ usages.push({ isTestFile: consumerIsTestFile });
45
+ ts.forEachChild(node, visitNode);
46
+ };
47
+ visitNode(sourceFile);
48
+ };
49
+ /**
50
+ * Collects concrete usages of one exported element across the program.
51
+ * @param program TypeScript program.
52
+ * @param sourceFilename Source filename where export is defined.
53
+ * @param state Normalized rule options.
54
+ * @param repoRoot Absolute repository root used for test-file classification.
55
+ * @param exportedElement Exported element to classify.
56
+ * @returns Concrete usages for the exported element.
57
+ * @example
58
+ * ```typescript
59
+ * const usages = collectCrossFileUsages(program, "/repo/src/feature.ts", state, "/repo", exportedElement);
60
+ * ```
61
+ */
62
+ const collectCrossFileUsages = (program, sourceFilename, state, repoRoot, exportedElement) => {
63
+ const checker = program.getTypeChecker();
64
+ const targetSymbol = getExportedSymbol(program, sourceFilename, exportedElement.exportedName);
65
+ if (targetSymbol === void 0) {
66
+ return [];
67
+ }
68
+ const normalizedSourceFilename = toComparableAbsolutePath(sourceFilename);
69
+ const normalizedRepoRoot = path.resolve(repoRoot);
70
+ const usages = collectPublicApiExposureUsages(program, sourceFilename, state, repoRoot, targetSymbol);
71
+ for (const sourceFile of program.getSourceFiles()) {
72
+ if (sourceFile.isDeclarationFile) {
73
+ continue;
74
+ }
75
+ const consumerFilename = path.resolve(sourceFile.fileName);
76
+ const normalizedConsumerFilename = toComparableAbsolutePath(consumerFilename);
77
+ if (normalizedConsumerFilename === normalizedSourceFilename) {
78
+ continue;
79
+ }
80
+ const isConsumerTestFile = isTestFile(consumerFilename, state, normalizedRepoRoot);
81
+ collectConcreteUsagesFromSourceFile(sourceFile, checker, targetSymbol, exportedElement, isConsumerTestFile, usages);
82
+ }
83
+ return usages;
84
+ };
85
+ /**
86
+ * Classifies one exported name based on cross-file usages.
87
+ * @param usages Collected usages.
88
+ * @returns Classification label.
89
+ * @example
90
+ * ```typescript
91
+ * const classification = classifyExportUsage("feature", usages);
92
+ * ```
93
+ */
94
+ const classifyExportUsage = (usages) => {
95
+ if (usages.length === 0) {
96
+ return "unused";
97
+ }
98
+ for (const usage of usages) {
99
+ if (!usage.isTestFile) {
100
+ return "production";
101
+ }
102
+ }
103
+ return "test-only";
104
+ };
105
+ export { classifyExportUsage, collectCrossFileUsages };
106
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tdW51c2VkLWV4cG9ydHMtdXNhZ2UtdXRpbGl0aWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2RvbWFpbi9hcmNoaXRlY3R1cmUvbm8tdW51c2VkLWV4cG9ydHMvbm8tdW51c2VkLWV4cG9ydHMtdXNhZ2UtdXRpbGl0aWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQztBQVFqQyxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUNyRixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDekQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sZ0RBQWdELENBQUM7QUFDaEcsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixZQUFZLEVBQ1osc0JBQXNCLEVBQ3RCLHdCQUF3QixHQUN6QixNQUFNLHNDQUFzQyxDQUFDO0FBRTlDOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILE1BQU0sbUNBQW1DLEdBQUcsQ0FDMUMsVUFBeUIsRUFDekIsT0FBdUIsRUFDdkIsWUFBdUIsRUFDdkIsZUFBZ0MsRUFDaEMsa0JBQTJCLEVBQzNCLE1BQXFCLEVBQ2YsRUFBRTtJQUNSLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBYSxFQUFRLEVBQUU7UUFDeEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUMzQixFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNqQyxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLEVBQUUsZUFBZSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDakUsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFD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a0IsRUFBRTtJQUN6QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDeEIsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUVELEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN0QixPQUFPLFlBQVksQ0FBQztRQUN0QixDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUMsQ0FBQztBQUVGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxzQkFBc0IsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0ICogYXMgdHMgZnJvbSBcInR5cGVzY3JpcHRcIjtcblxuaW1wb3J0IHR5cGUge1xuICBFeHBvcnRlZEVsZW1lbnQsXG4gIEV4cG9ydFVzYWdlLFxuICBOb1VudXNlZEV4cG9ydHNTdGF0ZSxcbn0gZnJvbSBcIi4vdHlwZXNcIjtcblxuaW1wb3J0IHsgaXNDb25jcmV0ZVVzYWdlSWRlbnRpZmllciB9IGZyb20gXCIuL25vLXVudXNlZC1leHBvcnRzLWlkZW50aWZpZXItdXRpbGl0aWVzXCI7XG5pbXBvcnQgeyBpc1Rlc3RGaWxlIH0gZnJvbSBcIi4vbm8tdW51c2VkLWV4cG9ydHMtb3B0aW9uc1wiO1xuaW1wb3J0IHsgY29sbGVjdFB1YmxpY0FwaUV4cG9zdXJlVXNhZ2VzIH0gZnJvbSBcIi4vbm8tdW51c2VkLWV4cG9ydHMtcHVibGljLWFwaS11c2FnZS11dGlsaXRpZXNcIjtcbmltcG9ydCB7XG4gIGdldEV4cG9ydGVkU3ltYm9sLFxuICBpc1NhbWVTeW1ib2wsXG4gIHJlc29sdmVDYW5vbmljYWxTeW1ib2wsXG4gIHRvQ29tcGFyYWJsZUFic29sdXRlUGF0aCxcbn0gZnJvbSBcIi4vbm8tdW51c2VkLWV4cG9ydHMtc3ltYm9sLXV0aWxpdGllc1wiO1xuXG4vKipcbiAqIEFwcGVuZHMgY29uY3JldGUgdXNhZ2VzIGZyb20gb25lIHNvdXJjZSBmaWxlIGludG8gdGhlIGFjY3VtdWxhdG9yLlxuICogQHBhcmFtIHNvdXJjZUZpbGUgU291cmNlIGZpbGUgdG8gc2Nhbi5cbiAqIEBwYXJhbSBjaGVja2VyIFR5cGVTY3JpcHQgY2hlY2tlci5cbiAqIEBwYXJhbSB0YXJnZXRTeW1ib2wgRXhwb3J0IHN5bWJvbCBiZWluZyBjbGFzc2lmaWVkLlxuICogQHBhcmFtIGV4cG9ydGVkRWxlbWVudCBFeHBvcnQgbWV0YWRhdGEuXG4gKiBAcGFyYW0gY29uc3VtZXJJc1Rlc3RGaWxlIFdoZXRoZXIgc291cmNlIGZpbGUgaXMgYSB0ZXN0IGZpbGUuXG4gKiBAcGFyYW0gdXNhZ2VzIE11dGFibGUgdXNhZ2UgYWNjdW11bGF0b3IuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29sbGVjdENvbmNyZXRlVXNhZ2VzRnJvbVNvdXJjZUZpbGUoc291cmNlRmlsZSwgY2hlY2tlciwgdGFyZ2V0U3ltYm9sS2V5LCBleHBvcnRlZEVsZW1lbnQsIGZhbHNlLCB1c2FnZXMpO1xuICogYGBgXG4gKi9cbmNvbnN0IGNvbGxlY3RDb25jcmV0ZVVzYWdlc0Zyb21Tb3VyY2VGaWxlID0gKFxuICBzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlLFxuICBjaGVja2VyOiB0cy5UeXBlQ2hlY2tlcixcbiAgdGFyZ2V0U3ltYm9sOiB0cy5TeW1ib2wsXG4gIGV4cG9ydGVkRWxlbWVudDogRXhwb3J0ZWRFbGVtZW50LFxuICBjb25zdW1lcklzVGVzdEZpbGU6IGJvb2xlYW4sXG4gIHVzYWdlczogRXhwb3J0VXNhZ2VbXSxcbik6IHZvaWQgPT4ge1xuICBjb25zdCB2aXNpdE5vZGUgPSAobm9kZTogdHMuTm9kZSk6IHZvaWQgPT4ge1xuICAgIGlmICghdHMuaXNJZGVudGlmaWVyKG5vZGUpKSB7XG4gICAgICB0cy5mb3JFYWNoQ2hpbGQobm9kZSwgdmlzaXROb2RlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlzQ29uY3JldGVVc2FnZUlkZW50aWZpZXIobm9kZSwgZXhwb3J0ZWRFbGVtZW50LmV4cG9ydEtpbmQpKSB7XG4gICAgICB0cy5mb3JFYWNoQ2hpbGQobm9kZSwgdmlzaXROb2RlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBpc1Nob3J0aGFuZE5hbWUgPVxuICAgICAgdHMuaXNTaG9ydGhhbmRQcm9wZXJ0eUFzc2lnbm1lbnQobm9kZS5wYXJlbnQpICYmXG4gICAgICBub2RlLnBhcmVudC5uYW1lID09PSBub2RlO1xuXG4gICAgY29uc3QgY2FuZGlkYXRlU3ltYm9sID0gaXNTaG9ydGhhbmROYW1lXG4gICAgICA/IGNoZWNrZXIuZ2V0U2hvcnRoYW5kQXNzaWdubWVudFZhbHVlU3ltYm9sKG5vZGUucGFyZW50KVxuICAgICAgOiBjaGVja2VyLmdldFN5bWJvbEF0TG9jYXRpb24obm9kZSk7XG5cbiAgICBpZiAoY2FuZGlkYXRlU3ltYm9sID09PSB2b2lkIDApIHtcbiAgICAgIHRzLmZvckVhY2hDaGlsZChub2RlLCB2aXNpdE5vZGUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc29sdmVkU3ltYm9sID0gcmVzb2x2ZUNhbm9uaWNhbFN5bWJvbChjYW5kaWRhdGVTeW1ib2wsIGNoZWNrZXIpO1xuXG4gICAgaWYgKCFpc1NhbWVTeW1ib2wocmVzb2x2ZWRTeW1ib2wsIHRhcmdldFN5bWJvbCkpIHtcbiAgICAgIHRzLmZvckVhY2hDaGlsZChub2RlLCB2aXNpdE5vZGUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHVzYWdlcy5wdXNoKHsgaXNUZXN0RmlsZTogY29uc3VtZXJJc1Rlc3RGaWxlIH0pO1xuICAgIHRzLmZvckVhY2hDaGlsZChub2RlLCB2aXNpdE5vZGUpO1xuICB9O1xuXG4gIHZpc2l0Tm9kZShzb3VyY2VGaWxlKTtcbn07XG5cbi8qKlxuICogQ29sbGVjdHMgY29uY3JldGUgdXNhZ2VzIG9mIG9uZSBleHBvcnRlZCBlbGVtZW50IGFjcm9zcyB0aGUgcHJvZ3JhbS5cbiAqIEBwYXJhbSBwcm9ncmFtIFR5cGVTY3JpcHQgcHJvZ3JhbS5cbiAqIEBwYXJhbSBzb3VyY2VGaWxlbmFtZSBTb3VyY2UgZmlsZW5hbWUgd2hlcmUgZXhwb3J0IGlzIGRlZmluZWQuXG4gKiBAcGFyYW0gc3RhdGUgTm9ybWFsaXplZCBydWxlIG9wdGlvbnMuXG4gKiBAcGFyYW0gcmVwb1Jvb3QgQWJzb2x1dGUgcmVwb3NpdG9yeSByb290IHVzZWQgZm9yIHRlc3QtZmlsZSBjbGFzc2lmaWNhdGlvbi5cbiAqIEBwYXJhbSBleHBvcnRlZEVsZW1lbnQgRXhwb3J0ZWQgZWxlbWVudCB0byBjbGFzc2lmeS5cbiAqIEByZXR1cm5zIENvbmNyZXRlIHVzYWdlcyBmb3IgdGhlIGV4cG9ydGVkIGVsZW1lbnQuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgdXNhZ2VzID0gY29sbGVjdENyb3NzRmlsZVVzYWdlcyhwcm9ncmFtLCBcIi9yZXBvL3NyYy9mZWF0dXJlLnRzXCIsIHN0YXRlLCBcIi9yZXBvXCIsIGV4cG9ydGVkRWxlbWVudCk7XG4gKiBgYGBcbiAqL1xuY29uc3QgY29sbGVjdENyb3NzRmlsZVVzYWdlcyA9IChcbiAgcHJvZ3JhbTogdHMuUHJvZ3JhbSxcbiAgc291cmNlRmlsZW5hbWU6IHN0cmluZyxcbiAgc3RhdGU6IE5vVW51c2VkRXhwb3J0c1N0YXRlLFxuICByZXBvUm9vdDogc3RyaW5nLFxuICBleHBvcnRlZEVsZW1lbnQ6IEV4cG9ydGVkRWxlbWVudCxcbik6IEV4cG9ydFVzYWdlW10gPT4ge1xuICBjb25zdCBjaGVja2VyID0gcHJvZ3JhbS5nZXRUeXBlQ2hlY2tlcigpO1xuICBjb25zdCB0YXJnZXRTeW1ib2wgPSBnZXRFeHBvcnRlZFN5bWJvbChcbiAgICBwcm9ncmFtLFxuICAgIHNvdXJjZUZpbGVuYW1lLFxuICAgIGV4cG9ydGVkRWxlbWVudC5leHBvcnRlZE5hbWUsXG4gICk7XG5cbiAgaWYgKHRhcmdldFN5bWJvbCA9PT0gdm9pZCAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3Qgbm9ybWFsaXplZFNvdXJjZUZpbGVuYW1lID0gdG9Db21wYXJhYmxlQWJzb2x1dGVQYXRoKHNvdXJjZUZpbGVuYW1lKTtcbiAgY29uc3Qgbm9ybWFsaXplZFJlcG9Sb290ID0gcGF0aC5yZXNvbHZlKHJlcG9Sb290KTtcbiAgY29uc3QgdXNhZ2VzOiBFeHBvcnRVc2FnZVtdID0gY29sbGVjdFB1YmxpY0FwaUV4cG9zdXJlVXNhZ2VzKFxuICAgIHByb2dyYW0sXG4gICAgc291cmNlRmlsZW5hbWUsXG4gICAgc3RhdGUsXG4gICAgcmVwb1Jvb3QsXG4gICAgdGFyZ2V0U3ltYm9sLFxuICApO1xuXG4gIGZvciAoY29uc3Qgc291cmNlRmlsZSBvZiBwcm9ncmFtLmdldFNvdXJjZUZpbGVzKCkpIHtcbiAgICBpZiAoc291cmNlRmlsZS5pc0RlY2xhcmF0aW9uRmlsZSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgY29uc3VtZXJGaWxlbmFtZSA9IHBhdGgucmVzb2x2ZShzb3VyY2VGaWxlLmZpbGVOYW1lKTtcbiAgICBjb25zdCBub3JtYWxpemVkQ29uc3VtZXJGaWxlbmFtZSA9XG4gICAgICB0b0NvbXBhcmFibGVBYnNvbHV0ZVBhdGgoY29uc3VtZXJGaWxlbmFtZSk7XG5cbiAgICBpZiAobm9ybWFsaXplZENvbnN1bWVyRmlsZW5hbWUgPT09IG5vcm1hbGl6ZWRTb3VyY2VGaWxlbmFtZSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgaXNDb25zdW1lclRlc3RGaWxlID0gaXNUZXN0RmlsZShcbiAgICAgIGNvbnN1bWVyRmlsZW5hbWUsXG4gICAgICBzdGF0ZSxcbiAgICAgIG5vcm1hbGl6ZWRSZXBvUm9vdCxcbiAgICApO1xuXG4gICAgY29sbGVjdENvbmNyZXRlVXNhZ2VzRnJvbVNvdXJjZUZpbGUoXG4gICAgICBzb3VyY2VGaWxlLFxuICAgICAgY2hlY2tlcixcbiAgICAgIHRhcmdldFN5bWJvbCxcbiAgICAgIGV4cG9ydGVkRWxlbWVudCxcbiAgICAgIGlzQ29uc3VtZXJUZXN0RmlsZSxcbiAgICAgIHVzYWdlcyxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHVzYWdlcztcbn07XG5cbi8qKlxuICogQ2xhc3NpZmllcyBvbmUgZXhwb3J0ZWQgbmFtZSBiYXNlZCBvbiBjcm9zcy1maWxlIHVzYWdlcy5cbiAqIEBwYXJhbSB1c2FnZXMgQ29sbGVjdGVkIHVzYWdlcy5cbiAqIEByZXR1cm5zIENsYXNzaWZpY2F0aW9uIGxhYmVsLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNsYXNzaWZpY2F0aW9uID0gY2xhc3NpZnlFeHBvcnRVc2FnZShcImZlYXR1cmVcIiwgdXNhZ2VzKTtcbiAqIGBgYFxuICovXG5jb25zdCBjbGFzc2lmeUV4cG9ydFVzYWdlID0gKFxuICB1c2FnZXM6IEV4cG9ydFVzYWdlW10sXG4pOiBcInByb2R1Y3Rpb25cIiB8IFwidGVzdC1vbmx5XCIgfCBcInVudXNlZFwiID0+IHtcbiAgaWYgKHVzYWdlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gXCJ1bnVzZWRcIjtcbiAgfVxuXG4gIGZvciAoY29uc3QgdXNhZ2Ugb2YgdXNhZ2VzKSB7XG4gICAgaWYgKCF1c2FnZS5pc1Rlc3RGaWxlKSB7XG4gICAgICByZXR1cm4gXCJwcm9kdWN0aW9uXCI7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFwidGVzdC1vbmx5XCI7XG59O1xuXG5leHBvcnQgeyBjbGFzc2lmeUV4cG9ydFVzYWdlLCBjb2xsZWN0Q3Jvc3NGaWxlVXNhZ2VzIH07XG4iXX0=