eslint-plugin-traceability 1.11.0 → 1.11.2

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 (84) hide show
  1. package/CHANGELOG.md +3 -4
  2. package/README.md +1 -1
  3. package/lib/src/index.d.ts +12 -1
  4. package/lib/src/index.js +43 -6
  5. package/lib/src/maintenance/commands.js +2 -3
  6. package/lib/src/maintenance/flags.js +111 -25
  7. package/lib/src/maintenance/update.js +1 -14
  8. package/lib/src/rules/helpers/require-story-core.d.ts +67 -0
  9. package/lib/src/rules/helpers/require-story-core.js +142 -23
  10. package/lib/src/rules/helpers/require-story-helpers.d.ts +9 -88
  11. package/lib/src/rules/helpers/require-story-helpers.js +118 -166
  12. package/lib/src/rules/helpers/require-story-io.js +51 -31
  13. package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +12 -13
  14. package/lib/src/rules/helpers/valid-annotation-format-internal.js +21 -16
  15. package/lib/src/rules/helpers/valid-annotation-format-validators.d.ts +29 -3
  16. package/lib/src/rules/helpers/valid-annotation-format-validators.js +29 -3
  17. package/lib/src/rules/helpers/valid-annotation-options.d.ts +3 -0
  18. package/lib/src/rules/helpers/valid-annotation-options.js +64 -21
  19. package/lib/src/rules/helpers/valid-annotation-utils.d.ts +3 -3
  20. package/lib/src/rules/helpers/valid-annotation-utils.js +10 -10
  21. package/lib/src/rules/helpers/valid-req-reference-helpers.d.ts +11 -0
  22. package/lib/src/rules/helpers/valid-req-reference-helpers.js +362 -0
  23. package/lib/src/rules/prefer-implements-annotation.js +7 -7
  24. package/lib/src/rules/require-story-annotation.d.ts +2 -0
  25. package/lib/src/rules/require-story-annotation.js +1 -1
  26. package/lib/src/rules/valid-req-reference.d.ts +4 -0
  27. package/lib/src/rules/valid-req-reference.js +5 -349
  28. package/lib/src/rules/valid-story-reference.d.ts +1 -1
  29. package/lib/src/rules/valid-story-reference.js +17 -10
  30. package/lib/src/utils/annotation-checker.js +31 -7
  31. package/lib/src/utils/branch-annotation-helpers.d.ts +2 -2
  32. package/lib/src/utils/branch-annotation-helpers.js +4 -4
  33. package/lib/src/utils/reqAnnotationDetection.js +36 -22
  34. package/lib/tests/cli-error-handling.test.js +2 -1
  35. package/lib/tests/config/eslint-config-validation.test.d.ts +8 -0
  36. package/lib/tests/config/eslint-config-validation.test.js +81 -0
  37. package/lib/tests/config/flat-config-presets-integration.test.js +1 -3
  38. package/lib/tests/config/require-story-annotation-config.test.d.ts +9 -0
  39. package/lib/tests/config/require-story-annotation-config.test.js +9 -0
  40. package/lib/tests/fixtures/stale/example.js +1 -1
  41. package/lib/tests/fixtures/update/example.js +1 -1
  42. package/lib/tests/integration/cli-integration.test.js +9 -1
  43. package/lib/tests/integration/dogfooding-validation.test.d.ts +1 -0
  44. package/lib/tests/integration/dogfooding-validation.test.js +94 -0
  45. package/lib/tests/maintenance/batch.test.js +1 -0
  46. package/lib/tests/maintenance/cli.test.js +38 -0
  47. package/lib/tests/maintenance/detect-isolated.test.js +6 -5
  48. package/lib/tests/maintenance/detect.test.js +1 -0
  49. package/lib/tests/maintenance/index.test.js +1 -0
  50. package/lib/tests/maintenance/report.test.js +1 -0
  51. package/lib/tests/maintenance/update-isolated.test.js +1 -0
  52. package/lib/tests/maintenance/update.test.js +1 -0
  53. package/lib/tests/perf/maintenance-cli-large-workspace.test.js +18 -0
  54. package/lib/tests/perf/require-branch-annotation-large-file.test.d.ts +1 -0
  55. package/lib/tests/perf/require-branch-annotation-large-file.test.js +67 -0
  56. package/lib/tests/plugin-default-export-and-configs.test.js +2 -0
  57. package/lib/tests/plugin-setup-error.test.d.ts +1 -0
  58. package/lib/tests/plugin-setup-error.test.js +1 -0
  59. package/lib/tests/plugin-setup.test.js +12 -1
  60. package/lib/tests/rules/auto-fix-behavior-008.test.js +16 -0
  61. package/lib/tests/rules/error-reporting.test.js +1 -0
  62. package/lib/tests/rules/prefer-implements-annotation.test.js +8 -0
  63. package/lib/tests/rules/require-branch-annotation.test.js +34 -0
  64. package/lib/tests/rules/require-story-core-edgecases.test.js +1 -0
  65. package/lib/tests/rules/require-story-core.autofix.test.js +1 -0
  66. package/lib/tests/rules/require-story-core.test.js +1 -0
  67. package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +1 -0
  68. package/lib/tests/rules/require-story-helpers-edgecases.test.js +1 -0
  69. package/lib/tests/rules/require-story-helpers.test.js +4 -3
  70. package/lib/tests/rules/require-story-io-behavior.test.d.ts +1 -0
  71. package/lib/tests/rules/require-story-io-behavior.test.js +1 -0
  72. package/lib/tests/rules/require-story-io.edgecases.test.d.ts +1 -0
  73. package/lib/tests/rules/require-story-io.edgecases.test.js +1 -0
  74. package/lib/tests/rules/require-story-visitors-edgecases.test.d.ts +1 -0
  75. package/lib/tests/rules/require-story-visitors-edgecases.test.js +1 -0
  76. package/lib/tests/rules/valid-annotation-format-internal.test.d.ts +8 -0
  77. package/lib/tests/rules/valid-annotation-format-internal.test.js +47 -0
  78. package/lib/tests/rules/valid-story-reference.test.js +2 -0
  79. package/lib/tests/utils/annotation-checker.test.js +2 -1
  80. package/lib/tests/utils/branch-annotation-helpers.test.js +2 -1
  81. package/package.json +2 -2
  82. package/user-docs/api-reference.md +115 -8
  83. package/user-docs/examples.md +1 -1
  84. package/user-docs/migration-guide.md +35 -2
package/CHANGELOG.md CHANGED
@@ -1,10 +1,9 @@
1
- # [1.11.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.10.1...v1.11.0) (2025-12-05)
1
+ ## [1.11.2](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.11.1...v1.11.2) (2025-12-06)
2
2
 
3
3
 
4
- ### Features
4
+ ### Bug Fixes
5
5
 
6
- * add configurable auto-fix templates and toggles ([5e0e6e7](https://github.com/voder-ai/eslint-plugin-traceability/commit/5e0e6e782812aebb128c4922931bb9703265bfb1))
7
- * add configurable auto-fix templates and toggles ([21c3a79](https://github.com/voder-ai/eslint-plugin-traceability/commit/21c3a79ce2e2e7fd95a422a963735d67940c8bd8))
6
+ * ignore inline-code annotation references in comment normalization ([118d743](https://github.com/voder-ai/eslint-plugin-traceability/commit/118d743ff8c8bf1dcb0854b898480c641cc727c8))
8
7
 
9
8
  # Changelog
10
9
 
package/README.md CHANGED
@@ -83,7 +83,7 @@ export default [
83
83
 
84
84
  ```js
85
85
  /**
86
- * @story stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
86
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
87
87
  * // Point this to your own project's story/requirements file, not to this plugin's internal docs.
88
88
  * @req REQ-ANNOTATION-REQUIRED
89
89
  */
@@ -11,16 +11,27 @@ import type { Rule } from "eslint";
11
11
  */
12
12
  import { detectStaleAnnotations, updateAnnotationReferences, batchUpdateAnnotations, verifyAnnotations, generateMaintenanceReport } from "./maintenance";
13
13
  /**
14
- * @story docs/stories/002.0-DYNAMIC-RULE-LOADING.story.md
14
+ * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
15
15
  * @req REQ-RULE-LIST - Enumerate supported rule file names for plugin discovery
16
16
  */
17
17
  declare const RULE_NAMES: readonly ["require-story-annotation", "require-req-annotation", "require-branch-annotation", "valid-annotation-format", "valid-story-reference", "valid-req-reference", "prefer-implements-annotation", "require-test-traceability"];
18
18
  type RuleName = (typeof RULE_NAMES)[number];
19
19
  declare const rules: Record<RuleName, Rule.RuleModule>;
20
+ /**
21
+ * Plugin metadata used by ESLint for debugging and caching.
22
+ *
23
+ * @supports docs/stories/001.0-DEV-PLUGIN-SETUP.story.md REQ-PLUGIN-STRUCTURE REQ-NPM-PACKAGE
24
+ */
25
+ declare const pluginMeta: {
26
+ readonly name: string;
27
+ readonly version: string;
28
+ readonly namespace: "traceability";
29
+ };
20
30
  declare const plugin: {
21
31
  rules: typeof rules;
22
32
  configs?: unknown;
23
33
  maintenance?: unknown;
34
+ meta?: typeof pluginMeta;
24
35
  };
25
36
  /**
26
37
  * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
package/lib/src/index.js CHANGED
@@ -7,7 +7,7 @@ exports.maintenance = exports.configs = exports.rules = void 0;
7
7
  */
8
8
  const maintenance_1 = require("./maintenance");
9
9
  /**
10
- * @story docs/stories/002.0-DYNAMIC-RULE-LOADING.story.md
10
+ * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
11
11
  * @req REQ-RULE-LIST - Enumerate supported rule file names for plugin discovery
12
12
  */
13
13
  const RULE_NAMES = [
@@ -24,18 +24,18 @@ const rules = {};
24
24
  exports.rules = rules;
25
25
  RULE_NAMES.forEach(
26
26
  /**
27
- * @story docs/stories/002.0-DYNAMIC-RULE-LOADING.story.md
27
+ * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
28
28
  * @req REQ-DYNAMIC-LOADING - Support dynamic rule loading by name at runtime
29
29
  * @param {RuleName} name - Rule file base name used to discover and load rule module
30
30
  */
31
31
  (name) => {
32
32
  /**
33
- * @story docs/stories/002.0-DYNAMIC-RULE-LOADING.story.md
33
+ * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
34
34
  * @req REQ-DYNAMIC-LOADING - Support dynamic rule loading by name at runtime
35
35
  */
36
36
  try {
37
37
  /**
38
- * @story docs/stories/002.0-DYNAMIC-RULE-LOADING.story.md
38
+ * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
39
39
  * @req REQ-DYNAMIC-LOADING - Support dynamic rule loading by name at runtime
40
40
  */
41
41
  // Dynamically require rule module
@@ -45,11 +45,11 @@ RULE_NAMES.forEach(
45
45
  }
46
46
  catch (error) {
47
47
  /**
48
- * @story docs/stories/003.0-RULE-LOAD-ERROR-HANDLING.story.md
48
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
49
49
  * @req REQ-ERROR-HANDLING - Provide fallback rule module and surface errors when rule loading fails
50
50
  */
51
51
  /**
52
- * @story docs/stories/003.0-RULE-LOAD-ERROR-HANDLING.story.md
52
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
53
53
  * @req REQ-ERROR-HANDLING - Provide fallback rule module and surface errors when rule loading fails
54
54
  */
55
55
  console.error(`[eslint-plugin-traceability] Failed to load rule "${name}": ${error.message}`);
@@ -74,8 +74,45 @@ RULE_NAMES.forEach(
74
74
  };
75
75
  }
76
76
  });
77
+ /**
78
+ * Plugin metadata used by ESLint for debugging and caching.
79
+ *
80
+ * @supports docs/stories/001.0-DEV-PLUGIN-SETUP.story.md REQ-PLUGIN-STRUCTURE REQ-NPM-PACKAGE
81
+ */
82
+ const pluginMeta = (() => {
83
+ let pkg = {};
84
+ try {
85
+ // When running from built output (lib/src/index.js)
86
+ // this resolves to the package.json at the project root.
87
+ // @supports docs/stories/001.0-DEV-PLUGIN-SETUP.story.md REQ-NPM-PACKAGE
88
+ pkg = require("../../package.json");
89
+ }
90
+ catch {
91
+ try {
92
+ // When running via the TypeScript sources (src/index.ts) in this repo,
93
+ // fall back to resolving package.json one level up from src/.
94
+ // @supports docs/stories/001.0-DEV-PLUGIN-SETUP.story.md REQ-NPM-PACKAGE
95
+ pkg = require("../package.json");
96
+ }
97
+ catch {
98
+ // As a last resort (tests, unusual environments), provide sensible
99
+ // defaults so that plugin loading never fails just for metadata.
100
+ // @supports docs/stories/001.0-DEV-PLUGIN-SETUP.story.md REQ-PLUGIN-STRUCTURE
101
+ pkg = {
102
+ name: "eslint-plugin-traceability",
103
+ version: "0.0.0-development",
104
+ };
105
+ }
106
+ }
107
+ return {
108
+ name: pkg.name ?? "eslint-plugin-traceability",
109
+ version: pkg.version ?? "0.0.0-development",
110
+ namespace: "traceability",
111
+ };
112
+ })();
77
113
  const plugin = {
78
114
  rules,
115
+ meta: pluginMeta,
79
116
  };
80
117
  /**
81
118
  * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
@@ -9,7 +9,7 @@ exports.handleUpdate = handleUpdate;
9
9
  * Subcommand handlers for the traceability-maint CLI.
10
10
  *
11
11
  * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
12
- * @req REQ-MAINT-DETECT - CLI support for detection of stale annotations
12
+ * @req REQ-MAINT-DETECT - CLI support for detection of stale annotations.
13
13
  * @req REQ-MAINT-VERIFY - CLI support for verification of annotations
14
14
  * @req REQ-MAINT-REPORT - CLI support for human-readable reports
15
15
  * @req REQ-MAINT-UPDATE - CLI support for updating annotation references
@@ -34,8 +34,7 @@ function handleDetect(normalized) {
34
34
  const root = flags.root;
35
35
  const stale = (0, detect_1.detectStaleAnnotations)(root);
36
36
  if (flags.json) {
37
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
38
- // @req REQ-MAINT-REPORT - JSON-friendly output for tooling integration
37
+ // Emit JSON output to support consumption by external tools and scripts.
39
38
  console.log(JSON.stringify({ root, stale }));
40
39
  }
41
40
  else if (stale.length === 0) {
@@ -60,43 +60,129 @@ function createDefaultFlags() {
60
60
  };
61
61
  }
62
62
  /**
63
- * Handle a single CLI argument and update the flags accordingly.
63
+ * Safely check if the next argument value exists and is a string.
64
64
  *
65
65
  * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
66
66
  * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
67
67
  */
68
- function applyFlag(flags, args, index) {
69
- const arg = args[index];
70
- if (arg === "--root" && typeof args[index + 1] === "string") {
71
- flags.root = path_1.default.resolve(args[index + 1]);
72
- return index + 1;
68
+ function isNextValueString(args, index) {
69
+ return typeof args[index + 1] === "string";
70
+ }
71
+ /**
72
+ * Handle the --root flag, updating the root path if present.
73
+ *
74
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
75
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
76
+ */
77
+ function handleRootFlag(flags, args, index) {
78
+ if (args[index] !== "--root" || !isNextValueString(args, index)) {
79
+ return index;
80
+ }
81
+ flags.root = path_1.default.resolve(args[index + 1]);
82
+ return index + 1;
83
+ }
84
+ /**
85
+ * Handle the --json flag, toggling JSON output when present.
86
+ *
87
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
88
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
89
+ */
90
+ function handleJsonFlag(flags, args, index) {
91
+ if (args[index] !== "--json") {
92
+ return index;
73
93
  }
74
- if (arg === "--json") {
75
- flags.json = true;
94
+ flags.json = true;
95
+ return index;
96
+ }
97
+ /**
98
+ * Handle the --format flag, validating and setting the output format.
99
+ *
100
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
101
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
102
+ */
103
+ function handleFormatFlag(flags, args, index) {
104
+ if (args[index] !== "--format" || !isNextValueString(args, index)) {
76
105
  return index;
77
106
  }
78
- if (arg === "--format" && typeof args[index + 1] === "string") {
79
- const value = args[index + 1];
80
- if (value === "text" || value === "json") {
81
- flags.format = value;
82
- }
83
- else {
84
- throw new Error(`Invalid format: ${value}. Expected 'text' or 'json'.`);
85
- }
86
- return index + 1;
107
+ const value = args[index + 1];
108
+ if (value === "text" || value === "json") {
109
+ flags.format = value;
110
+ }
111
+ else {
112
+ throw new Error(`Invalid format: ${value}. Expected 'text' or 'json'.`);
87
113
  }
88
- if (arg === "--from" && typeof args[index + 1] === "string") {
89
- flags.from = args[index + 1];
90
- return index + 1;
114
+ return index + 1;
115
+ }
116
+ /**
117
+ * Handle the --from flag, capturing the starting reference if present.
118
+ *
119
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
120
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
121
+ */
122
+ function handleFromFlag(flags, args, index) {
123
+ if (args[index] !== "--from" || !isNextValueString(args, index)) {
124
+ return index;
91
125
  }
92
- if (arg === "--to" && typeof args[index + 1] === "string") {
93
- flags.to = args[index + 1];
94
- return index + 1;
126
+ flags.from = args[index + 1];
127
+ return index + 1;
128
+ }
129
+ /**
130
+ * Handle the --to flag, capturing the ending reference if present.
131
+ *
132
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
133
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
134
+ */
135
+ function handleToFlag(flags, args, index) {
136
+ if (args[index] !== "--to" || !isNextValueString(args, index)) {
137
+ return index;
95
138
  }
96
- if (arg === "--dry-run") {
97
- flags.dryRun = true;
139
+ flags.to = args[index + 1];
140
+ return index + 1;
141
+ }
142
+ /**
143
+ * Handle the --dry-run flag, enabling dry-run mode when present.
144
+ *
145
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
146
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
147
+ */
148
+ function handleDryRunFlag(flags, args, index) {
149
+ if (args[index] !== "--dry-run") {
98
150
  return index;
99
151
  }
152
+ flags.dryRun = true;
153
+ return index;
154
+ }
155
+ /**
156
+ * Handle a single CLI argument and update the flags accordingly.
157
+ *
158
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
159
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
160
+ */
161
+ function applyFlag(flags, args, index) {
162
+ const afterRoot = handleRootFlag(flags, args, index);
163
+ if (afterRoot !== index) {
164
+ return afterRoot;
165
+ }
166
+ const afterJson = handleJsonFlag(flags, args, index);
167
+ if (afterJson !== index) {
168
+ return afterJson;
169
+ }
170
+ const afterFormat = handleFormatFlag(flags, args, index);
171
+ if (afterFormat !== index) {
172
+ return afterFormat;
173
+ }
174
+ const afterFrom = handleFromFlag(flags, args, index);
175
+ if (afterFrom !== index) {
176
+ return afterFrom;
177
+ }
178
+ const afterTo = handleToFlag(flags, args, index);
179
+ if (afterTo !== index) {
180
+ return afterTo;
181
+ }
182
+ const afterDryRun = handleDryRunFlag(flags, args, index);
183
+ if (afterDryRun !== index) {
184
+ return afterDryRun;
185
+ }
100
186
  return index;
101
187
  }
102
188
  /**
@@ -42,20 +42,7 @@ const utils_1 = require("./utils");
42
42
  * @req REQ-MAINT-UPDATE
43
43
  */
44
44
  function processFileForAnnotationUpdates(fullPath, regex, newPath, replacementCountRef) {
45
- const stat = fs.statSync(fullPath);
46
- /**
47
- * Skip non-files in iteration
48
- * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
49
- * @req REQ-MAINT-UPDATE
50
- */
51
- /**
52
- * Skip entries that are not regular files (e.g., directories)
53
- * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
54
- * @req REQ-MAINT-UPDATE
55
- */
56
- if (!stat.isFile())
57
- return;
58
- const content = fs.readFileSync(fullPath, "utf8");
45
+ const content = fs.readFileSync(fullPath, "utf8"); // getAllFiles already returns regular files
59
46
  const newContent = content.replace(regex,
60
47
  /**
61
48
  * Replacement callback to update annotation references
@@ -1,22 +1,89 @@
1
1
  /**
2
2
  * Create a fixer function that inserts a @story annotation before the target node.
3
+ * This fixer is responsible for placing the annotation immediately before the
4
+ * resolved target node in the source code.
3
5
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
6
  * @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
5
7
  */
6
8
  export declare function createAddStoryFix(target: any, annotationTemplate: string): (fixer: any) => any;
7
9
  /**
8
10
  * Create a fixer function for class method annotations.
11
+ * This helper ensures that the @story annotation is inserted with appropriate
12
+ * indentation and placement before a class method declaration.
9
13
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
10
14
  * @req REQ-AUTOFIX - Provide automatic fix for class method annotations
11
15
  */
12
16
  export declare function createMethodFix(node: any, annotationTemplate: string): (fixer: any) => any;
13
17
  /**
14
18
  * Default set of node types to check for missing @story annotations.
19
+ * This default scope covers common function-like declarations used in typical
20
+ * TypeScript and JavaScript codebases.
15
21
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
16
22
  * @req REQ-ANNOTATION-REQUIRED - Provide sensible default scope for rule checks
17
23
  */
18
24
  export declare const DEFAULT_SCOPE: string[];
25
+ /**
26
+ * Path to the story file for function-annotation helpers.
27
+ * This constant centralizes the reference to the canonical documentation story
28
+ * used by these helpers.
29
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
30
+ * @req REQ-ANNOTATION-REQUIRED - Provide a single source of truth for the canonical story path used by helper modules
31
+ */
32
+ export declare const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
19
33
  /**
20
34
  * Allowed values for export priority option.
21
35
  */
22
36
  export declare const EXPORT_PRIORITY_VALUES: string[];
37
+ import type { Rule } from "eslint";
38
+ type CoreReportOptions = {
39
+ annotationTemplateOverride?: string;
40
+ autoFixToggle?: boolean;
41
+ };
42
+ type ReportDeps = {
43
+ hasStoryAnnotation: (_sourceCode: any, _node: any) => boolean;
44
+ getReportedFunctionName: (_node: any) => string;
45
+ resolveAnnotationTargetNode: (_sourceCode: any, _node: any, _passedTarget: any) => any;
46
+ getNameNodeForReport: (_node: any) => any;
47
+ buildTemplateConfig: (_options?: CoreReportOptions) => {
48
+ effectiveTemplate: string;
49
+ allowFix: boolean;
50
+ };
51
+ extractName: (_node: any) => string;
52
+ getAnnotationTemplate: (_override?: string) => string;
53
+ shouldApplyAutoFix: (_autoFix: boolean | undefined) => boolean;
54
+ createAddStoryFix: (_target: any, _annotationTemplate: string) => any;
55
+ createMethodFix: (_node: any, _annotationTemplate: string) => any;
56
+ };
57
+ /**
58
+ * Core helper to report a missing @story annotation for a function-like node.
59
+ * This reporting utility delegates behavior to injected dependencies so that
60
+ * higher-level helpers can stay small while sharing error-reporting logic.
61
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
62
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
63
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
64
+ * @req REQ-ANNOTATION-REQUIRED
65
+ * @req REQ-AUTOFIX-MISSING
66
+ * @req REQ-ERROR-SPECIFIC
67
+ */
68
+ export declare function coreReportMissing(deps: ReportDeps, context: Rule.RuleContext, sourceCode: any, config: {
69
+ node: any;
70
+ target?: any;
71
+ options?: CoreReportOptions;
72
+ }): void;
73
+ /**
74
+ * Core helper to report a missing @story annotation for a method-like node.
75
+ * This method-focused reporting utility uses injected dependencies while
76
+ * keeping this module centered on core error-reporting behavior.
77
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
78
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
79
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
80
+ * @req REQ-ANNOTATION-REQUIRED
81
+ * @req REQ-AUTOFIX-MISSING
82
+ * @req REQ-ERROR-SPECIFIC
83
+ */
84
+ export declare function coreReportMethod(deps: ReportDeps, context: Rule.RuleContext, sourceCode: any, config: {
85
+ node: any;
86
+ target?: any;
87
+ options?: CoreReportOptions;
88
+ }): void;
89
+ export {};
@@ -1,64 +1,81 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EXPORT_PRIORITY_VALUES = exports.DEFAULT_SCOPE = void 0;
3
+ exports.EXPORT_PRIORITY_VALUES = exports.STORY_PATH = exports.DEFAULT_SCOPE = void 0;
4
4
  exports.createAddStoryFix = createAddStoryFix;
5
5
  exports.createMethodFix = createMethodFix;
6
+ exports.coreReportMissing = coreReportMissing;
7
+ exports.coreReportMethod = coreReportMethod;
8
+ /**
9
+ * Compute the insertion start offset for inserting annotations before a node.
10
+ * This helper ensures we insert before any export wrapper when present, while
11
+ * remaining resilient to malformed or unexpected AST structures.
12
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
13
+ * @req REQ-AUTOFIX
14
+ * @req REQ-AUTOFIX-SAFE
15
+ */
16
+ function getInsertionStart(candidate) {
17
+ if (!candidate || typeof candidate !== "object") {
18
+ return 0;
19
+ }
20
+ const parent = candidate.parent;
21
+ if (parent &&
22
+ (parent.type === "ExportNamedDeclaration" ||
23
+ parent.type === "ExportDefaultDeclaration") &&
24
+ Array.isArray(parent.range) &&
25
+ typeof parent.range[0] === "number") {
26
+ return parent.range[0];
27
+ }
28
+ if (Array.isArray(candidate.range) &&
29
+ typeof candidate.range[0] === "number") {
30
+ return candidate.range[0];
31
+ }
32
+ return 0;
33
+ }
6
34
  /**
7
35
  * Create a fixer function that inserts a @story annotation before the target node.
36
+ * This fixer is responsible for placing the annotation immediately before the
37
+ * resolved target node in the source code.
8
38
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
9
39
  * @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
10
40
  */
11
41
  function createAddStoryFix(target, annotationTemplate) {
12
42
  /**
13
43
  * Fixer that inserts a @story annotation before the target node.
44
+ * This inner fixer is used by ESLint to apply the actual code modification.
14
45
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
15
46
  * @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
16
47
  */
17
48
  function addStoryFixer(fixer) {
18
- const start = target && typeof target === "object"
19
- ? target.parent &&
20
- (target.parent.type === "ExportNamedDeclaration" ||
21
- target.parent.type === "ExportDefaultDeclaration") &&
22
- Array.isArray(target.parent.range) &&
23
- typeof target.parent.range[0] === "number"
24
- ? target.parent.range[0]
25
- : Array.isArray(target.range) && typeof target.range[0] === "number"
26
- ? target.range[0]
27
- : 0
28
- : 0;
49
+ const start = getInsertionStart(target);
29
50
  return fixer.insertTextBeforeRange([start, start], `${annotationTemplate}\n`);
30
51
  }
31
52
  return addStoryFixer;
32
53
  }
33
54
  /**
34
55
  * Create a fixer function for class method annotations.
56
+ * This helper ensures that the @story annotation is inserted with appropriate
57
+ * indentation and placement before a class method declaration.
35
58
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
36
59
  * @req REQ-AUTOFIX - Provide automatic fix for class method annotations
37
60
  */
38
61
  function createMethodFix(node, annotationTemplate) {
39
62
  /**
40
63
  * Fixer that inserts a @story annotation before a method node.
64
+ * This inner fixer handles inserting the annotation with method-friendly
65
+ * formatting and spacing.
41
66
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
42
67
  * @req REQ-AUTOFIX - Provide automatic fix for class method annotations
43
68
  */
44
69
  function methodFixer(fixer) {
45
- const start = node && typeof node === "object"
46
- ? node.parent &&
47
- (node.parent.type === "ExportNamedDeclaration" ||
48
- node.parent.type === "ExportDefaultDeclaration") &&
49
- Array.isArray(node.parent.range) &&
50
- typeof node.parent.range[0] === "number"
51
- ? node.parent.range[0]
52
- : Array.isArray(node.range) && typeof node.range[0] === "number"
53
- ? node.range[0]
54
- : 0
55
- : 0;
70
+ const start = getInsertionStart(node);
56
71
  return fixer.insertTextBeforeRange([start, start], `${annotationTemplate}\n `);
57
72
  }
58
73
  return methodFixer;
59
74
  }
60
75
  /**
61
76
  * Default set of node types to check for missing @story annotations.
77
+ * This default scope covers common function-like declarations used in typical
78
+ * TypeScript and JavaScript codebases.
62
79
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
63
80
  * @req REQ-ANNOTATION-REQUIRED - Provide sensible default scope for rule checks
64
81
  */
@@ -69,7 +86,109 @@ exports.DEFAULT_SCOPE = [
69
86
  "TSMethodSignature",
70
87
  "TSDeclareFunction",
71
88
  ];
89
+ /**
90
+ * Path to the story file for function-annotation helpers.
91
+ * This constant centralizes the reference to the canonical documentation story
92
+ * used by these helpers.
93
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
94
+ * @req REQ-ANNOTATION-REQUIRED - Provide a single source of truth for the canonical story path used by helper modules
95
+ */
96
+ exports.STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
72
97
  /**
73
98
  * Allowed values for export priority option.
74
99
  */
75
100
  exports.EXPORT_PRIORITY_VALUES = ["all", "exported", "non-exported"];
101
+ /**
102
+ * Core helper to report a missing @story annotation for a function-like node.
103
+ * This reporting utility delegates behavior to injected dependencies so that
104
+ * higher-level helpers can stay small while sharing error-reporting logic.
105
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
106
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
107
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
108
+ * @req REQ-ANNOTATION-REQUIRED
109
+ * @req REQ-AUTOFIX-MISSING
110
+ * @req REQ-ERROR-SPECIFIC
111
+ */
112
+ function coreReportMissing(deps, context, sourceCode, config) {
113
+ const { node, target: passedTarget, options = {} } = config;
114
+ try {
115
+ if (deps.hasStoryAnnotation(sourceCode, node)) {
116
+ return;
117
+ }
118
+ const functionName = deps.getReportedFunctionName(node);
119
+ const resolvedTarget = deps.resolveAnnotationTargetNode(sourceCode, node, passedTarget);
120
+ const nameNode = deps.getNameNodeForReport(node);
121
+ const { effectiveTemplate, allowFix } = deps.buildTemplateConfig(options);
122
+ const name = functionName;
123
+ context.report({
124
+ node: nameNode,
125
+ messageId: "missingStory",
126
+ data: { name, functionName: name },
127
+ fix: allowFix
128
+ ? deps.createAddStoryFix(resolvedTarget, effectiveTemplate)
129
+ : undefined,
130
+ suggest: [
131
+ {
132
+ desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
133
+ fix: deps.createAddStoryFix(resolvedTarget, effectiveTemplate),
134
+ },
135
+ ],
136
+ });
137
+ }
138
+ catch (error) {
139
+ // Intentionally swallow unexpected helper errors so traceability checks never
140
+ // break lint runs. When TRACEABILITY_DEBUG=1 is set, log a debug message to
141
+ // help diagnose misbehaving helpers in local development without affecting
142
+ // normal CI or production usage.
143
+ if (process.env.TRACEABILITY_DEBUG === "1") {
144
+ console.error("[traceability] coreReportMissing failed for node", error?.message ?? error);
145
+ }
146
+ }
147
+ }
148
+ /**
149
+ * Core helper to report a missing @story annotation for a method-like node.
150
+ * This method-focused reporting utility uses injected dependencies while
151
+ * keeping this module centered on core error-reporting behavior.
152
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
153
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
154
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
155
+ * @req REQ-ANNOTATION-REQUIRED
156
+ * @req REQ-AUTOFIX-MISSING
157
+ * @req REQ-ERROR-SPECIFIC
158
+ */
159
+ function coreReportMethod(deps, context, sourceCode, config) {
160
+ const { node, target: passedTarget, options = {} } = config;
161
+ try {
162
+ if (deps.hasStoryAnnotation(sourceCode, node)) {
163
+ return;
164
+ }
165
+ const resolvedTarget = passedTarget ?? deps.resolveAnnotationTargetNode(sourceCode, node, null);
166
+ const name = deps.extractName(node);
167
+ const nameNode = (node.key && node.key.type === "Identifier" && node.key) || node;
168
+ const effectiveTemplate = deps.getAnnotationTemplate(options.annotationTemplateOverride);
169
+ const allowFix = deps.shouldApplyAutoFix(options.autoFixToggle);
170
+ context.report({
171
+ node: nameNode,
172
+ messageId: "missingStory",
173
+ data: { name, functionName: name },
174
+ fix: allowFix
175
+ ? deps.createMethodFix(resolvedTarget, effectiveTemplate)
176
+ : undefined,
177
+ suggest: [
178
+ {
179
+ desc: `Add JSDoc @story annotation for function '${name}', e.g., ${effectiveTemplate}`,
180
+ fix: deps.createMethodFix(resolvedTarget, effectiveTemplate),
181
+ },
182
+ ],
183
+ });
184
+ }
185
+ catch (error) {
186
+ // Intentionally swallow unexpected helper errors so traceability checks never
187
+ // break lint runs. When TRACEABILITY_DEBUG=1 is set, log a debug message to
188
+ // help diagnose misbehaving helpers in local development without affecting
189
+ // normal CI or production usage.
190
+ if (process.env.TRACEABILITY_DEBUG === "1") {
191
+ console.error("[traceability] coreReportMethod failed for node", error?.message ?? error);
192
+ }
193
+ }
194
+ }