eslint-plugin-traceability 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +6 -0
- package/.github/workflows/ci-cd.yml +56 -0
- package/.husky/pre-commit +1 -0
- package/.husky/pre-push +1 -0
- package/.prettierignore +23 -0
- package/.prettierrc +4 -0
- package/.voder/history.md +164 -0
- package/.voder/implementation-progress.md +145 -0
- package/.voder/last-action.md +106 -0
- package/.voder/plan.md +15 -0
- package/.voder/progress-chart.png +0 -0
- package/.voder/progress-log-areas.csv +34 -0
- package/.voder/progress-log.csv +33 -0
- package/.voder/traceability/docs-stories-001.0-DEV-PLUGIN-SETUP.story.xml +17 -0
- package/.voder/traceability/docs-stories-002.0-DEV-ESLINT-CONFIG.story.xml +13 -0
- package/.voder/traceability/docs-stories-003.0-DEV-FUNCTION-ANNOTATIONS.story.xml +9 -0
- package/.voder/traceability/docs-stories-004.0-DEV-BRANCH-ANNOTATIONS.story.xml +9 -0
- package/.voder/traceability/docs-stories-005.0-DEV-ANNOTATION-VALIDATION.story.xml +9 -0
- package/.voder/traceability/docs-stories-006.0-DEV-FILE-VALIDATION.story.xml +9 -0
- package/.voder/traceability/docs-stories-007.0-DEV-ERROR-REPORTING.story.xml +9 -0
- package/.voder/traceability/docs-stories-008.0-DEV-AUTO-FIX.story.xml +9 -0
- package/.voder/traceability/docs-stories-009.0-DEV-MAINTENANCE-TOOLS.story.xml +16 -0
- package/.voder/traceability/docs-stories-010.0-DEV-DEEP-VALIDATION.story.xml +11 -0
- package/CHANGELOG.md +31 -0
- package/CONTRIBUTING.md +97 -0
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/cli-integration.js +157 -0
- package/docs/cli-integration.md +103 -0
- package/docs/config-presets.md +38 -0
- package/docs/decisions/001-typescript-for-eslint-plugin.accepted.md +111 -0
- package/docs/decisions/002-jest-for-eslint-testing.accepted.md +137 -0
- package/docs/decisions/003-code-quality-ratcheting-plan.md +48 -0
- package/docs/eslint-9-setup-guide.md +517 -0
- package/docs/eslint-plugin-development-guide.md +483 -0
- package/docs/jest-testing-guide.md +100 -0
- package/docs/rules/require-branch-annotation.md +34 -0
- package/docs/rules/require-req-annotation.md +39 -0
- package/docs/rules/require-story-annotation.md +36 -0
- package/docs/rules/valid-annotation-format.md +52 -0
- package/docs/rules/valid-req-reference.md +58 -0
- package/docs/rules/valid-story-reference.md +47 -0
- package/docs/security-incidents/unresolved-vulnerabilities.md +11 -0
- package/docs/stories/001.0-DEV-PLUGIN-SETUP.story.md +82 -0
- package/docs/stories/002.0-DEV-ESLINT-CONFIG.story.md +82 -0
- package/docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md +85 -0
- package/docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md +107 -0
- package/docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md +119 -0
- package/docs/stories/006.0-DEV-FILE-VALIDATION.story.md +127 -0
- package/docs/stories/007.0-DEV-ERROR-REPORTING.story.md +89 -0
- package/docs/stories/008.0-DEV-AUTO-FIX.story.md +104 -0
- package/docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md +104 -0
- package/docs/stories/010.0-DEV-DEEP-VALIDATION.story.md +110 -0
- package/docs/stories/developer-story.map.md +118 -0
- package/eslint.config.js +146 -0
- package/jest.config.js +21 -0
- package/lib/index.d.ts +26 -0
- package/lib/index.js +11 -0
- package/lib/src/index.d.ts +80 -0
- package/lib/src/index.js +58 -0
- package/lib/src/maintenance/batch.d.ts +16 -0
- package/lib/src/maintenance/batch.js +28 -0
- package/lib/src/maintenance/detect.d.ts +6 -0
- package/lib/src/maintenance/detect.js +69 -0
- package/lib/src/maintenance/index.d.ts +14 -0
- package/lib/src/maintenance/index.js +22 -0
- package/lib/src/maintenance/report.d.ts +7 -0
- package/lib/src/maintenance/report.js +17 -0
- package/lib/src/maintenance/update.d.ts +6 -0
- package/lib/src/maintenance/update.js +67 -0
- package/lib/src/maintenance/utils.d.ts +6 -0
- package/lib/src/maintenance/utils.js +64 -0
- package/lib/src/rules/require-branch-annotation.d.ts +7 -0
- package/lib/src/rules/require-branch-annotation.js +111 -0
- package/lib/src/rules/require-req-annotation.d.ts +7 -0
- package/lib/src/rules/require-req-annotation.js +38 -0
- package/lib/src/rules/require-story-annotation.d.ts +7 -0
- package/lib/src/rules/require-story-annotation.js +50 -0
- package/lib/src/rules/valid-annotation-format.d.ts +10 -0
- package/lib/src/rules/valid-annotation-format.js +60 -0
- package/lib/src/rules/valid-req-reference.d.ts +3 -0
- package/lib/src/rules/valid-req-reference.js +104 -0
- package/lib/src/rules/valid-story-reference.d.ts +3 -0
- package/lib/src/rules/valid-story-reference.js +168 -0
- package/lib/tests/basic.test.d.ts +1 -0
- package/lib/tests/basic.test.js +51 -0
- package/lib/tests/fixtures/stale/example.d.ts +0 -0
- package/lib/tests/fixtures/stale/example.js +3 -0
- package/lib/tests/fixtures/update/example.d.ts +0 -0
- package/lib/tests/fixtures/update/example.js +3 -0
- package/lib/tests/fixtures/valid-annotations/example.d.ts +0 -0
- package/lib/tests/fixtures/valid-annotations/example.js +3 -0
- package/lib/tests/index.test.d.ts +1 -0
- package/lib/tests/index.test.js +68 -0
- package/lib/tests/integration/file-validation.test.d.ts +1 -0
- package/lib/tests/integration/file-validation.test.js +60 -0
- package/lib/tests/integration/plugin-validation.test.d.ts +1 -0
- package/lib/tests/integration/plugin-validation.test.js +77 -0
- package/lib/tests/maintenance/batch.test.d.ts +1 -0
- package/lib/tests/maintenance/batch.test.js +79 -0
- package/lib/tests/maintenance/detect-isolated.test.d.ts +1 -0
- package/lib/tests/maintenance/detect-isolated.test.js +90 -0
- package/lib/tests/maintenance/detect.test.d.ts +1 -0
- package/lib/tests/maintenance/detect.test.js +23 -0
- package/lib/tests/maintenance/report.test.d.ts +1 -0
- package/lib/tests/maintenance/report.test.js +67 -0
- package/lib/tests/maintenance/update-isolated.test.d.ts +1 -0
- package/lib/tests/maintenance/update-isolated.test.js +66 -0
- package/lib/tests/maintenance/update.test.d.ts +1 -0
- package/lib/tests/maintenance/update.test.js +26 -0
- package/lib/tests/rules/require-branch-annotation.test.d.ts +1 -0
- package/lib/tests/rules/require-branch-annotation.test.js +251 -0
- package/lib/tests/rules/require-req-annotation.test.d.ts +1 -0
- package/lib/tests/rules/require-req-annotation.test.js +41 -0
- package/lib/tests/rules/require-story-annotation.test.d.ts +1 -0
- package/lib/tests/rules/require-story-annotation.test.js +35 -0
- package/lib/tests/rules/valid-annotation-format.test.d.ts +1 -0
- package/lib/tests/rules/valid-annotation-format.test.js +58 -0
- package/lib/tests/rules/valid-req-reference.test.d.ts +1 -0
- package/lib/tests/rules/valid-req-reference.test.js +87 -0
- package/lib/tests/rules/valid-story-reference.test.d.ts +1 -0
- package/lib/tests/rules/valid-story-reference.test.js +69 -0
- package/package.json +67 -0
- package/src/index.ts +56 -0
- package/src/maintenance/batch.ts +29 -0
- package/src/maintenance/detect.ts +42 -0
- package/src/maintenance/index.ts +14 -0
- package/src/maintenance/report.ts +15 -0
- package/src/maintenance/update.ts +40 -0
- package/src/maintenance/utils.ts +28 -0
- package/src/rules/require-branch-annotation.ts +114 -0
- package/src/rules/require-req-annotation.ts +36 -0
- package/src/rules/require-story-annotation.ts +52 -0
- package/src/rules/valid-annotation-format.ts +62 -0
- package/src/rules/valid-req-reference.ts +114 -0
- package/src/rules/valid-story-reference.ts +213 -0
- package/tests/basic.test.ts +17 -0
- package/tests/fixtures/stale/example.ts +2 -0
- package/tests/fixtures/story_bullet.md +6 -0
- package/tests/fixtures/update/example.ts +2 -0
- package/tests/fixtures/valid-annotations/example.ts +2 -0
- package/tests/index.test.ts +46 -0
- package/tests/integration/file-validation.test.ts +67 -0
- package/tests/integration/plugin-validation.test.ts +79 -0
- package/tests/maintenance/batch.test.ts +55 -0
- package/tests/maintenance/detect-isolated.test.ts +61 -0
- package/tests/maintenance/detect.test.ts +19 -0
- package/tests/maintenance/report.test.ts +37 -0
- package/tests/maintenance/update-isolated.test.ts +39 -0
- package/tests/maintenance/update.test.ts +21 -0
- package/tests/rules/require-branch-annotation.test.ts +248 -0
- package/tests/rules/require-req-annotation.test.ts +38 -0
- package/tests/rules/require-story-annotation.test.ts +32 -0
- package/tests/rules/valid-annotation-format.test.ts +55 -0
- package/tests/rules/valid-req-reference.test.ts +85 -0
- package/tests/rules/valid-story-reference.test.ts +66 -0
- package/tsconfig.json +15 -0
- package/user-docs/api-reference.md +135 -0
- package/user-docs/examples.md +73 -0
package/eslint.config.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint flat config for Traceability Plugin
|
|
3
|
+
* @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
|
|
4
|
+
* @req REQ-FLAT-CONFIG - Setup ESLint v9 flat config for plugin usage
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const typescriptParser = require("@typescript-eslint/parser");
|
|
8
|
+
const js = require("@eslint/js");
|
|
9
|
+
|
|
10
|
+
// Try to load the plugin, but handle case where it doesn't exist yet
|
|
11
|
+
let plugin;
|
|
12
|
+
try {
|
|
13
|
+
plugin = require("./lib/index.js");
|
|
14
|
+
} catch {
|
|
15
|
+
console.warn("Plugin not built yet, skipping traceability rules");
|
|
16
|
+
plugin = {};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = [
|
|
20
|
+
js.configs.recommended,
|
|
21
|
+
{
|
|
22
|
+
// Node.js config files
|
|
23
|
+
files: ["*.config.js", "*.config.mjs", "jest.config.js"],
|
|
24
|
+
languageOptions: {
|
|
25
|
+
ecmaVersion: 2022,
|
|
26
|
+
sourceType: "commonjs",
|
|
27
|
+
globals: {
|
|
28
|
+
require: "readonly",
|
|
29
|
+
module: "readonly",
|
|
30
|
+
exports: "readonly",
|
|
31
|
+
__dirname: "readonly",
|
|
32
|
+
__filename: "readonly",
|
|
33
|
+
console: "readonly",
|
|
34
|
+
process: "readonly",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
files: ["cli-integration.js"],
|
|
40
|
+
languageOptions: {
|
|
41
|
+
ecmaVersion: 2022,
|
|
42
|
+
sourceType: "script",
|
|
43
|
+
globals: {
|
|
44
|
+
require: "readonly",
|
|
45
|
+
module: "readonly",
|
|
46
|
+
exports: "readonly",
|
|
47
|
+
__dirname: "readonly",
|
|
48
|
+
__filename: "readonly",
|
|
49
|
+
console: "readonly",
|
|
50
|
+
process: "readonly",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
plugins: { ...(plugin.rules ? { traceability: plugin } : {}) },
|
|
54
|
+
rules: { complexity: "error" },
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
files: ["**/*.ts", "**/*.tsx"],
|
|
58
|
+
languageOptions: {
|
|
59
|
+
parser: typescriptParser,
|
|
60
|
+
parserOptions: {
|
|
61
|
+
project: "./tsconfig.json",
|
|
62
|
+
tsconfigRootDir: __dirname,
|
|
63
|
+
ecmaVersion: 2022,
|
|
64
|
+
sourceType: "module",
|
|
65
|
+
},
|
|
66
|
+
globals: {
|
|
67
|
+
process: "readonly",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
plugins: {
|
|
71
|
+
...(plugin.rules ? { traceability: plugin } : {}),
|
|
72
|
+
},
|
|
73
|
+
rules: {
|
|
74
|
+
complexity: "error",
|
|
75
|
+
// Enforce maximum lines per function for maintainability
|
|
76
|
+
"max-lines-per-function": ["error", { max: 90, skipBlankLines: true, skipComments: true }],
|
|
77
|
+
// Enforce maximum lines per file for maintainability
|
|
78
|
+
"max-lines": ["error", { max: 400, skipBlankLines: true, skipComments: true }],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
files: ["**/*.js", "**/*.jsx"],
|
|
83
|
+
languageOptions: {
|
|
84
|
+
ecmaVersion: 2022,
|
|
85
|
+
sourceType: "module",
|
|
86
|
+
},
|
|
87
|
+
plugins: {
|
|
88
|
+
...(plugin.rules ? { traceability: plugin } : {}),
|
|
89
|
+
},
|
|
90
|
+
rules: {
|
|
91
|
+
complexity: "error",
|
|
92
|
+
// Enforce maximum lines per function for maintainability
|
|
93
|
+
"max-lines-per-function": ["error", { max: 90, skipBlankLines: true, skipComments: true }],
|
|
94
|
+
// Enforce maximum lines per file for maintainability
|
|
95
|
+
"max-lines": ["error", { max: 400, skipBlankLines: true, skipComments: true }],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
files: ["src/rules/**/*.ts"],
|
|
100
|
+
languageOptions: {
|
|
101
|
+
globals: {
|
|
102
|
+
process: "readonly",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
// Test files
|
|
108
|
+
files: [
|
|
109
|
+
"**/*.test.{js,ts,tsx}",
|
|
110
|
+
"**/__tests__/**/*.{js,ts,tsx}",
|
|
111
|
+
"**/tests/**/*.{js,ts,tsx}",
|
|
112
|
+
],
|
|
113
|
+
languageOptions: {
|
|
114
|
+
globals: {
|
|
115
|
+
describe: "readonly",
|
|
116
|
+
it: "readonly",
|
|
117
|
+
test: "readonly",
|
|
118
|
+
expect: "readonly",
|
|
119
|
+
beforeEach: "readonly",
|
|
120
|
+
afterEach: "readonly",
|
|
121
|
+
beforeAll: "readonly",
|
|
122
|
+
afterAll: "readonly",
|
|
123
|
+
jest: "readonly",
|
|
124
|
+
require: "readonly",
|
|
125
|
+
__dirname: "readonly",
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
rules: {
|
|
129
|
+
"max-lines-per-function": "off",
|
|
130
|
+
"max-lines": "off",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
// Ignore build output and node_modules
|
|
135
|
+
ignores: [
|
|
136
|
+
"lib/**",
|
|
137
|
+
"node_modules/**",
|
|
138
|
+
"coverage/**",
|
|
139
|
+
".cursor/**",
|
|
140
|
+
"**/.cursor/**",
|
|
141
|
+
".voder/**",
|
|
142
|
+
"docs/**",
|
|
143
|
+
"*.md",
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
];
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/****
|
|
2
|
+
* Jest configuration for ESLint Traceability Plugin tests
|
|
3
|
+
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
|
+
* @req REQ-TEST-SETUP - Provide testing infrastructure for plugin
|
|
5
|
+
*/
|
|
6
|
+
module.exports = {
|
|
7
|
+
preset: "ts-jest",
|
|
8
|
+
testEnvironment: "node",
|
|
9
|
+
testPathIgnorePatterns: ["<rootDir>/lib/"],
|
|
10
|
+
testMatch: ["<rootDir>/tests/**/*.test.ts"],
|
|
11
|
+
coveragePathIgnorePatterns: ["<rootDir>/lib/"],
|
|
12
|
+
coverageThreshold: {
|
|
13
|
+
global: {
|
|
14
|
+
branches: 47,
|
|
15
|
+
functions: 42,
|
|
16
|
+
lines: 59,
|
|
17
|
+
statements: 57,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
moduleFileExtensions: ["ts", "js"],
|
|
21
|
+
};
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint Traceability Plugin
|
|
3
|
+
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
4
|
+
* @req REQ-PLUGIN-STRUCTURE - Provide foundational plugin export and registration
|
|
5
|
+
*/
|
|
6
|
+
export declare const rules: Record<string, unknown>;
|
|
7
|
+
export declare const configs: {
|
|
8
|
+
recommended: {
|
|
9
|
+
rules: {};
|
|
10
|
+
}[];
|
|
11
|
+
strict: {
|
|
12
|
+
rules: {};
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
declare const _default: {
|
|
16
|
+
rules: Record<string, unknown>;
|
|
17
|
+
configs: {
|
|
18
|
+
recommended: {
|
|
19
|
+
rules: {};
|
|
20
|
+
}[];
|
|
21
|
+
strict: {
|
|
22
|
+
rules: {};
|
|
23
|
+
}[];
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export default _default;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ESLint Traceability Plugin
|
|
4
|
+
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
5
|
+
* @req REQ-PLUGIN-STRUCTURE - Provide foundational plugin export and registration
|
|
6
|
+
*/
|
|
7
|
+
const plugin = require("./src/index.js");
|
|
8
|
+
|
|
9
|
+
module.exports = plugin;
|
|
10
|
+
module.exports.rules = plugin.rules;
|
|
11
|
+
module.exports.configs = plugin.configs;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint Traceability Plugin
|
|
3
|
+
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
4
|
+
* @req REQ-PLUGIN-STRUCTURE - Provide foundational plugin export and registration
|
|
5
|
+
*/
|
|
6
|
+
export declare const rules: {
|
|
7
|
+
"require-story-annotation": any;
|
|
8
|
+
"require-req-annotation": any;
|
|
9
|
+
"require-branch-annotation": any;
|
|
10
|
+
"valid-annotation-format": any;
|
|
11
|
+
"valid-story-reference": import("eslint").Rule.RuleModule;
|
|
12
|
+
"valid-req-reference": import("eslint").Rule.RuleModule;
|
|
13
|
+
};
|
|
14
|
+
export declare const configs: {
|
|
15
|
+
recommended: {
|
|
16
|
+
plugins: {
|
|
17
|
+
traceability: {};
|
|
18
|
+
};
|
|
19
|
+
rules: {
|
|
20
|
+
"traceability/require-story-annotation": string;
|
|
21
|
+
"traceability/require-req-annotation": string;
|
|
22
|
+
"traceability/require-branch-annotation": string;
|
|
23
|
+
"traceability/valid-annotation-format": string;
|
|
24
|
+
"traceability/valid-story-reference": string;
|
|
25
|
+
"traceability/valid-req-reference": string;
|
|
26
|
+
};
|
|
27
|
+
}[];
|
|
28
|
+
strict: {
|
|
29
|
+
plugins: {
|
|
30
|
+
traceability: {};
|
|
31
|
+
};
|
|
32
|
+
rules: {
|
|
33
|
+
"traceability/require-story-annotation": string;
|
|
34
|
+
"traceability/require-req-annotation": string;
|
|
35
|
+
"traceability/require-branch-annotation": string;
|
|
36
|
+
"traceability/valid-annotation-format": string;
|
|
37
|
+
"traceability/valid-story-reference": string;
|
|
38
|
+
"traceability/valid-req-reference": string;
|
|
39
|
+
};
|
|
40
|
+
}[];
|
|
41
|
+
};
|
|
42
|
+
declare const _default: {
|
|
43
|
+
rules: {
|
|
44
|
+
"require-story-annotation": any;
|
|
45
|
+
"require-req-annotation": any;
|
|
46
|
+
"require-branch-annotation": any;
|
|
47
|
+
"valid-annotation-format": any;
|
|
48
|
+
"valid-story-reference": import("eslint").Rule.RuleModule;
|
|
49
|
+
"valid-req-reference": import("eslint").Rule.RuleModule;
|
|
50
|
+
};
|
|
51
|
+
configs: {
|
|
52
|
+
recommended: {
|
|
53
|
+
plugins: {
|
|
54
|
+
traceability: {};
|
|
55
|
+
};
|
|
56
|
+
rules: {
|
|
57
|
+
"traceability/require-story-annotation": string;
|
|
58
|
+
"traceability/require-req-annotation": string;
|
|
59
|
+
"traceability/require-branch-annotation": string;
|
|
60
|
+
"traceability/valid-annotation-format": string;
|
|
61
|
+
"traceability/valid-story-reference": string;
|
|
62
|
+
"traceability/valid-req-reference": string;
|
|
63
|
+
};
|
|
64
|
+
}[];
|
|
65
|
+
strict: {
|
|
66
|
+
plugins: {
|
|
67
|
+
traceability: {};
|
|
68
|
+
};
|
|
69
|
+
rules: {
|
|
70
|
+
"traceability/require-story-annotation": string;
|
|
71
|
+
"traceability/require-req-annotation": string;
|
|
72
|
+
"traceability/require-branch-annotation": string;
|
|
73
|
+
"traceability/valid-annotation-format": string;
|
|
74
|
+
"traceability/valid-story-reference": string;
|
|
75
|
+
"traceability/valid-req-reference": string;
|
|
76
|
+
};
|
|
77
|
+
}[];
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
export default _default;
|
package/lib/src/index.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ESLint Traceability Plugin
|
|
4
|
+
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
5
|
+
* @req REQ-PLUGIN-STRUCTURE - Provide foundational plugin export and registration
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.configs = exports.rules = void 0;
|
|
12
|
+
const require_story_annotation_1 = __importDefault(require("./rules/require-story-annotation"));
|
|
13
|
+
const require_req_annotation_1 = __importDefault(require("./rules/require-req-annotation"));
|
|
14
|
+
const require_branch_annotation_1 = __importDefault(require("./rules/require-branch-annotation"));
|
|
15
|
+
const valid_annotation_format_1 = __importDefault(require("./rules/valid-annotation-format"));
|
|
16
|
+
const valid_story_reference_1 = __importDefault(require("./rules/valid-story-reference"));
|
|
17
|
+
const valid_req_reference_1 = __importDefault(require("./rules/valid-req-reference"));
|
|
18
|
+
exports.rules = {
|
|
19
|
+
"require-story-annotation": require_story_annotation_1.default,
|
|
20
|
+
"require-req-annotation": require_req_annotation_1.default,
|
|
21
|
+
"require-branch-annotation": require_branch_annotation_1.default,
|
|
22
|
+
"valid-annotation-format": valid_annotation_format_1.default,
|
|
23
|
+
"valid-story-reference": valid_story_reference_1.default,
|
|
24
|
+
"valid-req-reference": valid_req_reference_1.default,
|
|
25
|
+
};
|
|
26
|
+
exports.configs = {
|
|
27
|
+
recommended: [
|
|
28
|
+
{
|
|
29
|
+
plugins: {
|
|
30
|
+
traceability: {},
|
|
31
|
+
},
|
|
32
|
+
rules: {
|
|
33
|
+
"traceability/require-story-annotation": "error",
|
|
34
|
+
"traceability/require-req-annotation": "error",
|
|
35
|
+
"traceability/require-branch-annotation": "error",
|
|
36
|
+
"traceability/valid-annotation-format": "error",
|
|
37
|
+
"traceability/valid-story-reference": "error",
|
|
38
|
+
"traceability/valid-req-reference": "error",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
strict: [
|
|
43
|
+
{
|
|
44
|
+
plugins: {
|
|
45
|
+
traceability: {},
|
|
46
|
+
},
|
|
47
|
+
rules: {
|
|
48
|
+
"traceability/require-story-annotation": "error",
|
|
49
|
+
"traceability/require-req-annotation": "error",
|
|
50
|
+
"traceability/require-branch-annotation": "error",
|
|
51
|
+
"traceability/valid-annotation-format": "error",
|
|
52
|
+
"traceability/valid-story-reference": "error",
|
|
53
|
+
"traceability/valid-req-reference": "error",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
exports.default = { rules: exports.rules, configs: exports.configs };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch update annotations and verify references
|
|
3
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
4
|
+
* @req REQ-MAINT-BATCH - Perform batch updates
|
|
5
|
+
* @req REQ-MAINT-VERIFY - Verify annotation references
|
|
6
|
+
*/
|
|
7
|
+
export declare function batchUpdateAnnotations(codebasePath: string, mappings: {
|
|
8
|
+
oldPath: string;
|
|
9
|
+
newPath: string;
|
|
10
|
+
}[]): number;
|
|
11
|
+
/**
|
|
12
|
+
* Verify annotation references in codebase after maintenance operations
|
|
13
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
14
|
+
* @req REQ-MAINT-VERIFY - Verify annotation references
|
|
15
|
+
*/
|
|
16
|
+
export declare function verifyAnnotations(codebasePath: string): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.batchUpdateAnnotations = batchUpdateAnnotations;
|
|
4
|
+
exports.verifyAnnotations = verifyAnnotations;
|
|
5
|
+
const update_1 = require("./update");
|
|
6
|
+
const detect_1 = require("./detect");
|
|
7
|
+
/**
|
|
8
|
+
* Batch update annotations and verify references
|
|
9
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
10
|
+
* @req REQ-MAINT-BATCH - Perform batch updates
|
|
11
|
+
* @req REQ-MAINT-VERIFY - Verify annotation references
|
|
12
|
+
*/
|
|
13
|
+
function batchUpdateAnnotations(codebasePath, mappings) {
|
|
14
|
+
let totalUpdated = 0;
|
|
15
|
+
for (const { oldPath, newPath } of mappings) {
|
|
16
|
+
totalUpdated += (0, update_1.updateAnnotationReferences)(codebasePath, oldPath, newPath);
|
|
17
|
+
}
|
|
18
|
+
return totalUpdated;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Verify annotation references in codebase after maintenance operations
|
|
22
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
23
|
+
* @req REQ-MAINT-VERIFY - Verify annotation references
|
|
24
|
+
*/
|
|
25
|
+
function verifyAnnotations(codebasePath) {
|
|
26
|
+
const staleAnnotations = (0, detect_1.detectStaleAnnotations)(codebasePath);
|
|
27
|
+
return staleAnnotations.length === 0;
|
|
28
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect stale annotation references that point to moved or deleted story files
|
|
3
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
4
|
+
* @req REQ-MAINT-DETECT - Detect stale annotation references
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectStaleAnnotations(codebasePath: string): string[];
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.detectStaleAnnotations = detectStaleAnnotations;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const utils_1 = require("./utils");
|
|
40
|
+
/**
|
|
41
|
+
* Detect stale annotation references that point to moved or deleted story files
|
|
42
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
43
|
+
* @req REQ-MAINT-DETECT - Detect stale annotation references
|
|
44
|
+
*/
|
|
45
|
+
function detectStaleAnnotations(codebasePath) {
|
|
46
|
+
if (!fs.existsSync(codebasePath) ||
|
|
47
|
+
!fs.statSync(codebasePath).isDirectory()) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
const baseDir = path.resolve(cwd, codebasePath);
|
|
52
|
+
const stale = new Set();
|
|
53
|
+
const files = (0, utils_1.getAllFiles)(codebasePath);
|
|
54
|
+
for (const file of files) {
|
|
55
|
+
const content = fs.readFileSync(file, "utf8");
|
|
56
|
+
const regex = /@story\s+([^\s]+)/g;
|
|
57
|
+
let match;
|
|
58
|
+
while ((match = regex.exec(content)) !== null) {
|
|
59
|
+
const storyPath = match[1];
|
|
60
|
+
const storyProjectPath = path.resolve(cwd, storyPath);
|
|
61
|
+
const storyCodebasePath = path.resolve(baseDir, storyPath);
|
|
62
|
+
if (!fs.existsSync(storyProjectPath) &&
|
|
63
|
+
!fs.existsSync(storyCodebasePath)) {
|
|
64
|
+
stale.add(storyPath);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return Array.from(stale);
|
|
69
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maintenance Tools Module
|
|
3
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
4
|
+
* @req REQ-MAINT-DETECT
|
|
5
|
+
* @req REQ-MAINT-UPDATE
|
|
6
|
+
* @req REQ-MAINT-BATCH
|
|
7
|
+
* @req REQ-MAINT-VERIFY
|
|
8
|
+
* @req REQ-MAINT-REPORT
|
|
9
|
+
* @req REQ-MAINT-SAFE
|
|
10
|
+
*/
|
|
11
|
+
export { detectStaleAnnotations } from "./detect";
|
|
12
|
+
export { updateAnnotationReferences } from "./update";
|
|
13
|
+
export { batchUpdateAnnotations, verifyAnnotations } from "./batch";
|
|
14
|
+
export { generateMaintenanceReport } from "./report";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMaintenanceReport = exports.verifyAnnotations = exports.batchUpdateAnnotations = exports.updateAnnotationReferences = exports.detectStaleAnnotations = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Maintenance Tools Module
|
|
6
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
7
|
+
* @req REQ-MAINT-DETECT
|
|
8
|
+
* @req REQ-MAINT-UPDATE
|
|
9
|
+
* @req REQ-MAINT-BATCH
|
|
10
|
+
* @req REQ-MAINT-VERIFY
|
|
11
|
+
* @req REQ-MAINT-REPORT
|
|
12
|
+
* @req REQ-MAINT-SAFE
|
|
13
|
+
*/
|
|
14
|
+
var detect_1 = require("./detect");
|
|
15
|
+
Object.defineProperty(exports, "detectStaleAnnotations", { enumerable: true, get: function () { return detect_1.detectStaleAnnotations; } });
|
|
16
|
+
var update_1 = require("./update");
|
|
17
|
+
Object.defineProperty(exports, "updateAnnotationReferences", { enumerable: true, get: function () { return update_1.updateAnnotationReferences; } });
|
|
18
|
+
var batch_1 = require("./batch");
|
|
19
|
+
Object.defineProperty(exports, "batchUpdateAnnotations", { enumerable: true, get: function () { return batch_1.batchUpdateAnnotations; } });
|
|
20
|
+
Object.defineProperty(exports, "verifyAnnotations", { enumerable: true, get: function () { return batch_1.verifyAnnotations; } });
|
|
21
|
+
var report_1 = require("./report");
|
|
22
|
+
Object.defineProperty(exports, "generateMaintenanceReport", { enumerable: true, get: function () { return report_1.generateMaintenanceReport; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a report of maintenance operations performed
|
|
3
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
4
|
+
* @req REQ-MAINT-REPORT - Generate maintenance report
|
|
5
|
+
* @req REQ-MAINT-SAFE - Ensure operations are safe and reversible
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateMaintenanceReport(codebasePath: string): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMaintenanceReport = generateMaintenanceReport;
|
|
4
|
+
const detect_1 = require("./detect");
|
|
5
|
+
/**
|
|
6
|
+
* Generate a report of maintenance operations performed
|
|
7
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
8
|
+
* @req REQ-MAINT-REPORT - Generate maintenance report
|
|
9
|
+
* @req REQ-MAINT-SAFE - Ensure operations are safe and reversible
|
|
10
|
+
*/
|
|
11
|
+
function generateMaintenanceReport(codebasePath) {
|
|
12
|
+
const staleAnnotations = (0, detect_1.detectStaleAnnotations)(codebasePath);
|
|
13
|
+
if (staleAnnotations.length === 0) {
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
return staleAnnotations.join("\n");
|
|
17
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update annotation references when story files are moved or renamed
|
|
3
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
4
|
+
* @req REQ-MAINT-UPDATE - Update annotation references
|
|
5
|
+
*/
|
|
6
|
+
export declare function updateAnnotationReferences(codebasePath: string, oldPath: string, newPath: string): number;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.updateAnnotationReferences = updateAnnotationReferences;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const utils_1 = require("./utils");
|
|
39
|
+
/**
|
|
40
|
+
* Update annotation references when story files are moved or renamed
|
|
41
|
+
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
42
|
+
* @req REQ-MAINT-UPDATE - Update annotation references
|
|
43
|
+
*/
|
|
44
|
+
function updateAnnotationReferences(codebasePath, oldPath, newPath) {
|
|
45
|
+
if (!fs.existsSync(codebasePath) ||
|
|
46
|
+
!fs.statSync(codebasePath).isDirectory()) {
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
let replacementCount = 0;
|
|
50
|
+
const escapedOldPath = oldPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
51
|
+
const regex = new RegExp(`(@story\\s*)${escapedOldPath}`, "g");
|
|
52
|
+
const files = (0, utils_1.getAllFiles)(codebasePath);
|
|
53
|
+
for (const fullPath of files) {
|
|
54
|
+
const stat = fs.statSync(fullPath);
|
|
55
|
+
if (!stat.isFile())
|
|
56
|
+
continue;
|
|
57
|
+
const content = fs.readFileSync(fullPath, "utf8");
|
|
58
|
+
const newContent = content.replace(regex, (match, p1) => {
|
|
59
|
+
replacementCount++;
|
|
60
|
+
return `${p1}${newPath}`;
|
|
61
|
+
});
|
|
62
|
+
if (newContent !== content) {
|
|
63
|
+
fs.writeFileSync(fullPath, newContent, "utf8");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return replacementCount;
|
|
67
|
+
}
|