@hatem427/code-guard-ci 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/.husky/pre-commit +27 -0
- package/LICENSE +21 -0
- package/README.md +646 -0
- package/config/angular.config.ts +223 -0
- package/config/guidelines.config.ts +229 -0
- package/config/nextjs.config.ts +160 -0
- package/config/react.config.ts +330 -0
- package/dist/config/angular.config.d.ts +15 -0
- package/dist/config/angular.config.d.ts.map +1 -0
- package/dist/config/angular.config.js +187 -0
- package/dist/config/angular.config.js.map +1 -0
- package/dist/config/guidelines.config.d.ts +63 -0
- package/dist/config/guidelines.config.d.ts.map +1 -0
- package/dist/config/guidelines.config.js +167 -0
- package/dist/config/guidelines.config.js.map +1 -0
- package/dist/config/nextjs.config.d.ts +18 -0
- package/dist/config/nextjs.config.d.ts.map +1 -0
- package/dist/config/nextjs.config.js +133 -0
- package/dist/config/nextjs.config.js.map +1 -0
- package/dist/config/react.config.d.ts +15 -0
- package/dist/config/react.config.d.ts.map +1 -0
- package/dist/config/react.config.js +287 -0
- package/dist/config/react.config.js.map +1 -0
- package/dist/scripts/auto-fix.d.ts +16 -0
- package/dist/scripts/auto-fix.d.ts.map +1 -0
- package/dist/scripts/auto-fix.js +130 -0
- package/dist/scripts/auto-fix.js.map +1 -0
- package/dist/scripts/cli.d.ts +17 -0
- package/dist/scripts/cli.d.ts.map +1 -0
- package/dist/scripts/cli.js +255 -0
- package/dist/scripts/cli.js.map +1 -0
- package/dist/scripts/delete-bypass-logs.d.ts +17 -0
- package/dist/scripts/delete-bypass-logs.d.ts.map +1 -0
- package/dist/scripts/delete-bypass-logs.js +242 -0
- package/dist/scripts/delete-bypass-logs.js.map +1 -0
- package/dist/scripts/generate-doc.d.ts +18 -0
- package/dist/scripts/generate-doc.d.ts.map +1 -0
- package/dist/scripts/generate-doc.js +300 -0
- package/dist/scripts/generate-doc.js.map +1 -0
- package/dist/scripts/generate-pr-checklist.d.ts +20 -0
- package/dist/scripts/generate-pr-checklist.d.ts.map +1 -0
- package/dist/scripts/generate-pr-checklist.js +276 -0
- package/dist/scripts/generate-pr-checklist.js.map +1 -0
- package/dist/scripts/precommit-check.d.ts +23 -0
- package/dist/scripts/precommit-check.d.ts.map +1 -0
- package/dist/scripts/precommit-check.js +331 -0
- package/dist/scripts/precommit-check.js.map +1 -0
- package/dist/scripts/set-admin-password.d.ts +14 -0
- package/dist/scripts/set-admin-password.d.ts.map +1 -0
- package/dist/scripts/set-admin-password.js +116 -0
- package/dist/scripts/set-admin-password.js.map +1 -0
- package/dist/scripts/set-bypass-password.d.ts +11 -0
- package/dist/scripts/set-bypass-password.d.ts.map +1 -0
- package/dist/scripts/set-bypass-password.js +106 -0
- package/dist/scripts/set-bypass-password.js.map +1 -0
- package/dist/scripts/utils/auto-fixer.d.ts +28 -0
- package/dist/scripts/utils/auto-fixer.d.ts.map +1 -0
- package/dist/scripts/utils/auto-fixer.js +177 -0
- package/dist/scripts/utils/auto-fixer.js.map +1 -0
- package/dist/scripts/utils/bypass-manager.d.ts +101 -0
- package/dist/scripts/utils/bypass-manager.d.ts.map +1 -0
- package/dist/scripts/utils/bypass-manager.js +496 -0
- package/dist/scripts/utils/bypass-manager.js.map +1 -0
- package/dist/scripts/utils/code-analyzer.d.ts +34 -0
- package/dist/scripts/utils/code-analyzer.d.ts.map +1 -0
- package/dist/scripts/utils/code-analyzer.js +323 -0
- package/dist/scripts/utils/code-analyzer.js.map +1 -0
- package/dist/scripts/utils/file-checker.d.ts +93 -0
- package/dist/scripts/utils/file-checker.d.ts.map +1 -0
- package/dist/scripts/utils/file-checker.js +248 -0
- package/dist/scripts/utils/file-checker.js.map +1 -0
- package/dist/scripts/utils/logger.d.ts +26 -0
- package/dist/scripts/utils/logger.d.ts.map +1 -0
- package/dist/scripts/utils/logger.js +86 -0
- package/dist/scripts/utils/logger.js.map +1 -0
- package/dist/scripts/utils/project-detector.d.ts +34 -0
- package/dist/scripts/utils/project-detector.d.ts.map +1 -0
- package/dist/scripts/utils/project-detector.js +124 -0
- package/dist/scripts/utils/project-detector.js.map +1 -0
- package/dist/scripts/utils/rule-engine.d.ts +57 -0
- package/dist/scripts/utils/rule-engine.d.ts.map +1 -0
- package/dist/scripts/utils/rule-engine.js +158 -0
- package/dist/scripts/utils/rule-engine.js.map +1 -0
- package/dist/scripts/view-bypass-log.d.ts +13 -0
- package/dist/scripts/view-bypass-log.d.ts.map +1 -0
- package/dist/scripts/view-bypass-log.js +117 -0
- package/dist/scripts/view-bypass-log.js.map +1 -0
- package/package.json +74 -0
- package/scripts/auto-fix.ts +115 -0
- package/scripts/cli.ts +246 -0
- package/scripts/delete-bypass-logs.ts +253 -0
- package/scripts/generate-doc.ts +317 -0
- package/scripts/generate-pr-checklist.ts +285 -0
- package/scripts/precommit-check.ts +349 -0
- package/scripts/set-admin-password.ts +90 -0
- package/scripts/set-bypass-password.ts +80 -0
- package/scripts/utils/auto-fixer.ts +181 -0
- package/scripts/utils/bypass-manager.ts +566 -0
- package/scripts/utils/code-analyzer.ts +341 -0
- package/scripts/utils/file-checker.ts +253 -0
- package/scripts/utils/logger.ts +88 -0
- package/scripts/utils/project-detector.ts +115 -0
- package/scripts/utils/rule-engine.ts +186 -0
- package/scripts/view-bypass-log.ts +92 -0
- package/templates/feature-doc-api.md +101 -0
- package/templates/feature-doc-service.md +113 -0
- package/templates/feature-doc-ui.md +91 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* code-analyzer.ts — Automatic documentation from TypeScript/React code
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* Analyzes TypeScript/React components and extracts:
|
|
8
|
+
* - Component props and their types
|
|
9
|
+
* - JSDoc comments
|
|
10
|
+
* - Default values
|
|
11
|
+
* - Event handlers
|
|
12
|
+
*/
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
+
var ownKeys = function(o) {
|
|
31
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
+
var ar = [];
|
|
33
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
+
return ar;
|
|
35
|
+
};
|
|
36
|
+
return ownKeys(o);
|
|
37
|
+
};
|
|
38
|
+
return function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
})();
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.analyzeComponent = analyzeComponent;
|
|
48
|
+
exports.findComponentFile = findComponentFile;
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const ts_morph_1 = require("ts-morph");
|
|
52
|
+
/**
|
|
53
|
+
* Analyze a TypeScript/React component file
|
|
54
|
+
*/
|
|
55
|
+
function analyzeComponent(filePath) {
|
|
56
|
+
if (!fs.existsSync(filePath)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const project = new ts_morph_1.Project({
|
|
60
|
+
compilerOptions: {
|
|
61
|
+
jsx: 1, // React JSX
|
|
62
|
+
target: 99, // ESNext
|
|
63
|
+
module: 99, // ESNext
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
const sourceFile = project.addSourceFileAtPath(filePath);
|
|
67
|
+
const fileName = path.basename(filePath, path.extname(filePath));
|
|
68
|
+
// Try to find component name and props
|
|
69
|
+
const componentInfo = extractComponentInfo(sourceFile, fileName);
|
|
70
|
+
if (!componentInfo) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
name: componentInfo.name,
|
|
75
|
+
description: componentInfo.description,
|
|
76
|
+
props: componentInfo.props,
|
|
77
|
+
filePath,
|
|
78
|
+
isReactComponent: componentInfo.isReactComponent,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Extract component information from source file
|
|
83
|
+
*/
|
|
84
|
+
function extractComponentInfo(sourceFile, defaultName) {
|
|
85
|
+
let componentName = toPascalCase(defaultName);
|
|
86
|
+
let props = [];
|
|
87
|
+
let description;
|
|
88
|
+
let isReactComponent = false;
|
|
89
|
+
// Look for React component (function or arrow function)
|
|
90
|
+
const functionDeclarations = sourceFile.getFunctions();
|
|
91
|
+
const variableStatements = sourceFile.getVariableStatements();
|
|
92
|
+
// Check function declarations
|
|
93
|
+
for (const func of functionDeclarations) {
|
|
94
|
+
const name = func.getName();
|
|
95
|
+
if (name && /^[A-Z]/.test(name)) {
|
|
96
|
+
componentName = name;
|
|
97
|
+
isReactComponent = true;
|
|
98
|
+
description = extractJsDocComment(func);
|
|
99
|
+
// Extract props from parameters
|
|
100
|
+
const params = func.getParameters();
|
|
101
|
+
if (params.length > 0) {
|
|
102
|
+
const propsParam = params[0];
|
|
103
|
+
const typeNode = propsParam.getTypeNode();
|
|
104
|
+
if (typeNode) {
|
|
105
|
+
props = extractPropsFromType(sourceFile, typeNode.getText());
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Check variable declarations (arrow functions)
|
|
112
|
+
if (!isReactComponent) {
|
|
113
|
+
for (const statement of variableStatements) {
|
|
114
|
+
const declarations = statement.getDeclarations();
|
|
115
|
+
for (const decl of declarations) {
|
|
116
|
+
const name = decl.getName();
|
|
117
|
+
if (/^[A-Z]/.test(name)) {
|
|
118
|
+
const initializer = decl.getInitializer();
|
|
119
|
+
if (initializer && (initializer.getKindName() === 'ArrowFunction' || initializer.getKindName() === 'FunctionExpression')) {
|
|
120
|
+
componentName = name;
|
|
121
|
+
isReactComponent = true;
|
|
122
|
+
description = extractJsDocComment(decl);
|
|
123
|
+
// Extract props from arrow function parameters
|
|
124
|
+
const arrowFunc = initializer.asKind(218); // ArrowFunction kind
|
|
125
|
+
if (arrowFunc) {
|
|
126
|
+
const params = arrowFunc.getParameters();
|
|
127
|
+
if (params.length > 0) {
|
|
128
|
+
const propsParam = params[0];
|
|
129
|
+
const typeNode = propsParam.getTypeNode();
|
|
130
|
+
if (typeNode) {
|
|
131
|
+
props = extractPropsFromType(sourceFile, typeNode.getText());
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (isReactComponent)
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// If still not found, look for props interface/type
|
|
144
|
+
if (props.length === 0) {
|
|
145
|
+
props = findPropsInterface(sourceFile, componentName);
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
name: componentName,
|
|
149
|
+
description,
|
|
150
|
+
props,
|
|
151
|
+
isReactComponent,
|
|
152
|
+
filePath: sourceFile.getFilePath(),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Find props interface or type alias
|
|
157
|
+
*/
|
|
158
|
+
function findPropsInterface(sourceFile, componentName) {
|
|
159
|
+
const possibleNames = [
|
|
160
|
+
`${componentName}Props`,
|
|
161
|
+
`I${componentName}Props`,
|
|
162
|
+
`${componentName}Properties`,
|
|
163
|
+
];
|
|
164
|
+
// Check interfaces
|
|
165
|
+
for (const interfaceDecl of sourceFile.getInterfaces()) {
|
|
166
|
+
const name = interfaceDecl.getName();
|
|
167
|
+
if (possibleNames.includes(name) || name.toLowerCase().includes('props')) {
|
|
168
|
+
return extractPropsFromInterface(interfaceDecl);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Check type aliases
|
|
172
|
+
for (const typeAlias of sourceFile.getTypeAliases()) {
|
|
173
|
+
const name = typeAlias.getName();
|
|
174
|
+
if (possibleNames.includes(name) || name.toLowerCase().includes('props')) {
|
|
175
|
+
return extractPropsFromTypeAlias(typeAlias);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Extract props from interface declaration
|
|
182
|
+
*/
|
|
183
|
+
function extractPropsFromInterface(interfaceDecl) {
|
|
184
|
+
const props = [];
|
|
185
|
+
for (const prop of interfaceDecl.getProperties()) {
|
|
186
|
+
props.push(extractPropInfo(prop));
|
|
187
|
+
}
|
|
188
|
+
return props;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Extract props from type alias
|
|
192
|
+
*/
|
|
193
|
+
function extractPropsFromTypeAlias(typeAlias) {
|
|
194
|
+
const props = [];
|
|
195
|
+
const typeNode = typeAlias.getTypeNode();
|
|
196
|
+
if (typeNode && typeNode.getKindName() === 'TypeLiteral') {
|
|
197
|
+
const members = typeNode.getMembers();
|
|
198
|
+
for (const member of members) {
|
|
199
|
+
if (member.getKindName() === 'PropertySignature') {
|
|
200
|
+
props.push(extractPropInfo(member));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return props;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Extract props from type reference string
|
|
208
|
+
*/
|
|
209
|
+
function extractPropsFromType(sourceFile, typeName) {
|
|
210
|
+
// Remove generic brackets and get base type name
|
|
211
|
+
const baseType = typeName.replace(/<.*>/, '').trim();
|
|
212
|
+
// Find the interface or type
|
|
213
|
+
const interfaceDecl = sourceFile.getInterface(baseType);
|
|
214
|
+
if (interfaceDecl) {
|
|
215
|
+
return extractPropsFromInterface(interfaceDecl);
|
|
216
|
+
}
|
|
217
|
+
const typeAlias = sourceFile.getTypeAlias(baseType);
|
|
218
|
+
if (typeAlias) {
|
|
219
|
+
return extractPropsFromTypeAlias(typeAlias);
|
|
220
|
+
}
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Extract individual prop information
|
|
225
|
+
*/
|
|
226
|
+
function extractPropInfo(prop) {
|
|
227
|
+
const name = prop.getName();
|
|
228
|
+
const type = prop.getType().getText();
|
|
229
|
+
const required = !prop.hasQuestionToken();
|
|
230
|
+
const description = extractJsDocComment(prop);
|
|
231
|
+
// Try to get default value
|
|
232
|
+
let defaultValue;
|
|
233
|
+
const initializer = prop.getInitializer();
|
|
234
|
+
if (initializer) {
|
|
235
|
+
defaultValue = initializer.getText();
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
name,
|
|
239
|
+
type: simplifyType(type),
|
|
240
|
+
required,
|
|
241
|
+
defaultValue,
|
|
242
|
+
description,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Extract JSDoc comment
|
|
247
|
+
*/
|
|
248
|
+
function extractJsDocComment(node) {
|
|
249
|
+
try {
|
|
250
|
+
if (typeof node.getJsDocs !== 'function') {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
const jsDocs = node.getJsDocs();
|
|
254
|
+
if (jsDocs && jsDocs.length > 0) {
|
|
255
|
+
const comment = jsDocs[0].getDescription().trim();
|
|
256
|
+
return comment || undefined;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
// Silently fail
|
|
261
|
+
}
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Simplify complex type names for documentation
|
|
266
|
+
*/
|
|
267
|
+
function simplifyType(type) {
|
|
268
|
+
// Remove 'import("...")' wrapper
|
|
269
|
+
type = type.replace(/import\([^)]+\)\./g, '');
|
|
270
|
+
// Simplify React types
|
|
271
|
+
type = type.replace(/React\./g, '');
|
|
272
|
+
type = type.replace(/MouseEvent<.*?>/g, 'MouseEvent');
|
|
273
|
+
type = type.replace(/ChangeEvent<.*?>/g, 'ChangeEvent');
|
|
274
|
+
// Shorten long union types
|
|
275
|
+
if (type.length > 50 && type.includes('|')) {
|
|
276
|
+
const parts = type.split('|');
|
|
277
|
+
if (parts.length > 3) {
|
|
278
|
+
return `${parts.slice(0, 3).join(' | ')} | ...`;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return type;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Convert kebab-case or snake_case to PascalCase
|
|
285
|
+
*/
|
|
286
|
+
function toPascalCase(str) {
|
|
287
|
+
return str
|
|
288
|
+
.split(/[-_]/)
|
|
289
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
290
|
+
.join('');
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Search for component files in directory
|
|
294
|
+
*/
|
|
295
|
+
function findComponentFile(componentName, searchDir = process.cwd()) {
|
|
296
|
+
const possibleNames = [
|
|
297
|
+
componentName,
|
|
298
|
+
componentName.toLowerCase(),
|
|
299
|
+
componentName.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, ''),
|
|
300
|
+
];
|
|
301
|
+
const possibleExtensions = ['.tsx', '.ts', '.jsx', '.js'];
|
|
302
|
+
const possibleDirs = [
|
|
303
|
+
'src/components',
|
|
304
|
+
'components',
|
|
305
|
+
'src',
|
|
306
|
+
'.',
|
|
307
|
+
];
|
|
308
|
+
for (const dir of possibleDirs) {
|
|
309
|
+
const fullDir = path.join(searchDir, dir);
|
|
310
|
+
if (!fs.existsSync(fullDir))
|
|
311
|
+
continue;
|
|
312
|
+
for (const name of possibleNames) {
|
|
313
|
+
for (const ext of possibleExtensions) {
|
|
314
|
+
const filePath = path.join(fullDir, name + ext);
|
|
315
|
+
if (fs.existsSync(filePath)) {
|
|
316
|
+
return filePath;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=code-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-analyzer.js","sourceRoot":"","sources":["../../../scripts/utils/code-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* file-checker.ts — Low-level file analysis utilities
|
|
4
|
+
* ============================================================================
|
|
5
|
+
*
|
|
6
|
+
* Provides helpers for reading staged files, counting lines, extracting
|
|
7
|
+
* template content, and running regex-based checks against source code.
|
|
8
|
+
* Used by the rule engine to apply individual lint rules.
|
|
9
|
+
*/
|
|
10
|
+
export interface FileInfo {
|
|
11
|
+
/** Absolute path to the file */
|
|
12
|
+
absolutePath: string;
|
|
13
|
+
/** Path relative to repo root */
|
|
14
|
+
relativePath: string;
|
|
15
|
+
/** File extension without the leading dot (e.g. "ts", "tsx", "html") */
|
|
16
|
+
extension: string;
|
|
17
|
+
/** Full file content (UTF-8) */
|
|
18
|
+
content: string;
|
|
19
|
+
/** Individual lines (1-indexed access via lines[lineNumber - 1]) */
|
|
20
|
+
lines: string[];
|
|
21
|
+
/** Total line count */
|
|
22
|
+
lineCount: number;
|
|
23
|
+
}
|
|
24
|
+
export interface CheckMatch {
|
|
25
|
+
/** 1-based line number where the match was found */
|
|
26
|
+
line: number;
|
|
27
|
+
/** The content of the matched line (trimmed) */
|
|
28
|
+
text: string;
|
|
29
|
+
/** Column offset (0-based) within the line */
|
|
30
|
+
column: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns the list of staged files (relative paths) using `git diff --cached`.
|
|
34
|
+
* Filters out deleted files (status "D") so we only check files that exist.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getStagedFiles(): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Returns the current commit message from `.git/COMMIT_EDITMSG`.
|
|
39
|
+
* Falls back to empty string if unavailable.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getCommitMessage(): string;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the current branch name.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getCurrentBranch(): string;
|
|
46
|
+
/**
|
|
47
|
+
* Read a single file and return a structured `FileInfo` object.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readFileInfo(relativePath: string): FileInfo | null;
|
|
50
|
+
/**
|
|
51
|
+
* Read multiple staged files, filtering by allowed extensions.
|
|
52
|
+
*/
|
|
53
|
+
export declare function readStagedFiles(extensions?: string[]): FileInfo[];
|
|
54
|
+
/**
|
|
55
|
+
* Search a file's content for all matches of the given regex.
|
|
56
|
+
* Returns an array of matches with line numbers and text.
|
|
57
|
+
*/
|
|
58
|
+
export declare function findMatches(file: FileInfo, pattern: RegExp): CheckMatch[];
|
|
59
|
+
/**
|
|
60
|
+
* Check if a file exceeds the maximum allowed line count.
|
|
61
|
+
*/
|
|
62
|
+
export declare function exceedsMaxLines(file: FileInfo, maxLines: number): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Extract Angular inline template content from a component file.
|
|
65
|
+
* Looks for `template: \`...\`` blocks.
|
|
66
|
+
*/
|
|
67
|
+
export declare function extractInlineTemplate(file: FileInfo): {
|
|
68
|
+
content: string;
|
|
69
|
+
startLine: number;
|
|
70
|
+
} | null;
|
|
71
|
+
/**
|
|
72
|
+
* Extract content from Angular HTML template files.
|
|
73
|
+
* Returns the full file content for .html files associated with Angular components.
|
|
74
|
+
*/
|
|
75
|
+
export declare function extractExternalTemplate(file: FileInfo): string | null;
|
|
76
|
+
/**
|
|
77
|
+
* Check if a file has a specific inline suppression comment.
|
|
78
|
+
* Supports: // code-guardian-disable <rule-id>
|
|
79
|
+
*/
|
|
80
|
+
export declare function hasInlineSuppression(file: FileInfo, ruleId: string, lineNumber: number): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Detect whether a file contains JSX/TSX content (React templates).
|
|
83
|
+
*/
|
|
84
|
+
export declare function isJsxFile(file: FileInfo): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Detect whether a file is an Angular component.
|
|
87
|
+
*/
|
|
88
|
+
export declare function isAngularComponent(file: FileInfo): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Detect whether a file is a style file.
|
|
91
|
+
*/
|
|
92
|
+
export declare function isStyleFile(file: FileInfo): boolean;
|
|
93
|
+
//# sourceMappingURL=file-checker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-checker.d.ts","sourceRoot":"","sources":["../../../scripts/utils/file-checker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,WAAW,QAAQ;IACvB,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAWzC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAczC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAID;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAoBlE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAiBjE;AAID;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CA0BzE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAcnG;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAGrE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAkBhG;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEnD"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* file-checker.ts — Low-level file analysis utilities
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* Provides helpers for reading staged files, counting lines, extracting
|
|
8
|
+
* template content, and running regex-based checks against source code.
|
|
9
|
+
* Used by the rule engine to apply individual lint rules.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.getStagedFiles = getStagedFiles;
|
|
46
|
+
exports.getCommitMessage = getCommitMessage;
|
|
47
|
+
exports.getCurrentBranch = getCurrentBranch;
|
|
48
|
+
exports.readFileInfo = readFileInfo;
|
|
49
|
+
exports.readStagedFiles = readStagedFiles;
|
|
50
|
+
exports.findMatches = findMatches;
|
|
51
|
+
exports.exceedsMaxLines = exceedsMaxLines;
|
|
52
|
+
exports.extractInlineTemplate = extractInlineTemplate;
|
|
53
|
+
exports.extractExternalTemplate = extractExternalTemplate;
|
|
54
|
+
exports.hasInlineSuppression = hasInlineSuppression;
|
|
55
|
+
exports.isJsxFile = isJsxFile;
|
|
56
|
+
exports.isAngularComponent = isAngularComponent;
|
|
57
|
+
exports.isStyleFile = isStyleFile;
|
|
58
|
+
const fs = __importStar(require("fs"));
|
|
59
|
+
const path = __importStar(require("path"));
|
|
60
|
+
const child_process_1 = require("child_process");
|
|
61
|
+
// ── Git helpers ─────────────────────────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* Returns the list of staged files (relative paths) using `git diff --cached`.
|
|
64
|
+
* Filters out deleted files (status "D") so we only check files that exist.
|
|
65
|
+
*/
|
|
66
|
+
function getStagedFiles() {
|
|
67
|
+
try {
|
|
68
|
+
const output = (0, child_process_1.execSync)('git diff --cached --name-only --diff-filter=d', {
|
|
69
|
+
encoding: 'utf-8',
|
|
70
|
+
}).trim();
|
|
71
|
+
if (!output)
|
|
72
|
+
return [];
|
|
73
|
+
return output.split('\n').filter(Boolean);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns the current commit message from `.git/COMMIT_EDITMSG`.
|
|
81
|
+
* Falls back to empty string if unavailable.
|
|
82
|
+
*/
|
|
83
|
+
function getCommitMessage() {
|
|
84
|
+
try {
|
|
85
|
+
// During a pre-commit hook the message file may not exist yet.
|
|
86
|
+
// We also support reading from the HUSKY_GIT_PARAMS env.
|
|
87
|
+
const msgFile = path.join(process.cwd(), '.git', 'COMMIT_EDITMSG');
|
|
88
|
+
if (fs.existsSync(msgFile)) {
|
|
89
|
+
return fs.readFileSync(msgFile, 'utf-8').trim();
|
|
90
|
+
}
|
|
91
|
+
// Fallback: try getting the last commit message (for post-commit uses)
|
|
92
|
+
return (0, child_process_1.execSync)('git log -1 --pretty=%B 2>/dev/null', { encoding: 'utf-8' }).trim();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return '';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Returns the current branch name.
|
|
100
|
+
*/
|
|
101
|
+
function getCurrentBranch() {
|
|
102
|
+
try {
|
|
103
|
+
return (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim();
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return 'unknown';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// ── File reading ────────────────────────────────────────────────────────────
|
|
110
|
+
/**
|
|
111
|
+
* Read a single file and return a structured `FileInfo` object.
|
|
112
|
+
*/
|
|
113
|
+
function readFileInfo(relativePath) {
|
|
114
|
+
const absolutePath = path.resolve(process.cwd(), relativePath);
|
|
115
|
+
if (!fs.existsSync(absolutePath))
|
|
116
|
+
return null;
|
|
117
|
+
try {
|
|
118
|
+
const content = fs.readFileSync(absolutePath, 'utf-8');
|
|
119
|
+
const lines = content.split('\n');
|
|
120
|
+
return {
|
|
121
|
+
absolutePath,
|
|
122
|
+
relativePath,
|
|
123
|
+
extension: path.extname(relativePath).replace(/^\./, ''),
|
|
124
|
+
content,
|
|
125
|
+
lines,
|
|
126
|
+
lineCount: lines.length,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Read multiple staged files, filtering by allowed extensions.
|
|
135
|
+
*/
|
|
136
|
+
function readStagedFiles(extensions) {
|
|
137
|
+
const staged = getStagedFiles();
|
|
138
|
+
const files = [];
|
|
139
|
+
for (const rel of staged) {
|
|
140
|
+
const ext = path.extname(rel).replace(/^\./, '');
|
|
141
|
+
// Skip files that don't match the allowed extensions
|
|
142
|
+
if (extensions && extensions.length > 0 && !extensions.includes(ext)) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const info = readFileInfo(rel);
|
|
146
|
+
if (info)
|
|
147
|
+
files.push(info);
|
|
148
|
+
}
|
|
149
|
+
return files;
|
|
150
|
+
}
|
|
151
|
+
// ── Content checks ──────────────────────────────────────────────────────────
|
|
152
|
+
/**
|
|
153
|
+
* Search a file's content for all matches of the given regex.
|
|
154
|
+
* Returns an array of matches with line numbers and text.
|
|
155
|
+
*/
|
|
156
|
+
function findMatches(file, pattern) {
|
|
157
|
+
const matches = [];
|
|
158
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
159
|
+
const line = file.lines[i];
|
|
160
|
+
// Skip lines that are comments
|
|
161
|
+
const trimmed = line.trim();
|
|
162
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
// Reset lastIndex for global regexps
|
|
166
|
+
pattern.lastIndex = 0;
|
|
167
|
+
const match = pattern.exec(line);
|
|
168
|
+
if (match) {
|
|
169
|
+
matches.push({
|
|
170
|
+
line: i + 1, // 1-based
|
|
171
|
+
text: trimmed,
|
|
172
|
+
column: match.index,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return matches;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Check if a file exceeds the maximum allowed line count.
|
|
180
|
+
*/
|
|
181
|
+
function exceedsMaxLines(file, maxLines) {
|
|
182
|
+
return file.lineCount > maxLines;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Extract Angular inline template content from a component file.
|
|
186
|
+
* Looks for `template: \`...\`` blocks.
|
|
187
|
+
*/
|
|
188
|
+
function extractInlineTemplate(file) {
|
|
189
|
+
const templateRegex = /template\s*:\s*`([\s\S]*?)`/;
|
|
190
|
+
const match = templateRegex.exec(file.content);
|
|
191
|
+
if (!match)
|
|
192
|
+
return null;
|
|
193
|
+
// Find the line number where the template starts
|
|
194
|
+
const before = file.content.substring(0, match.index);
|
|
195
|
+
const startLine = before.split('\n').length;
|
|
196
|
+
return {
|
|
197
|
+
content: match[1],
|
|
198
|
+
startLine,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Extract content from Angular HTML template files.
|
|
203
|
+
* Returns the full file content for .html files associated with Angular components.
|
|
204
|
+
*/
|
|
205
|
+
function extractExternalTemplate(file) {
|
|
206
|
+
if (file.extension !== 'html')
|
|
207
|
+
return null;
|
|
208
|
+
return file.content;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Check if a file has a specific inline suppression comment.
|
|
212
|
+
* Supports: // code-guardian-disable <rule-id>
|
|
213
|
+
*/
|
|
214
|
+
function hasInlineSuppression(file, ruleId, lineNumber) {
|
|
215
|
+
// Check the line itself
|
|
216
|
+
if (file.lines[lineNumber - 1]?.includes(`code-guardian-disable ${ruleId}`)) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
// Check the line above
|
|
220
|
+
if (lineNumber > 1 && file.lines[lineNumber - 2]?.includes(`code-guardian-disable ${ruleId}`)) {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
// Check file-level suppression at the top of the file
|
|
224
|
+
const firstLines = file.lines.slice(0, 5).join('\n');
|
|
225
|
+
if (firstLines.includes(`code-guardian-disable-file ${ruleId}`)) {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Detect whether a file contains JSX/TSX content (React templates).
|
|
232
|
+
*/
|
|
233
|
+
function isJsxFile(file) {
|
|
234
|
+
return ['jsx', 'tsx'].includes(file.extension);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Detect whether a file is an Angular component.
|
|
238
|
+
*/
|
|
239
|
+
function isAngularComponent(file) {
|
|
240
|
+
return file.content.includes('@Component') && ['ts'].includes(file.extension);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Detect whether a file is a style file.
|
|
244
|
+
*/
|
|
245
|
+
function isStyleFile(file) {
|
|
246
|
+
return ['css', 'scss', 'sass', 'less'].includes(file.extension);
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=file-checker.js.map
|