@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.
Files changed (107) hide show
  1. package/.husky/pre-commit +27 -0
  2. package/LICENSE +21 -0
  3. package/README.md +646 -0
  4. package/config/angular.config.ts +223 -0
  5. package/config/guidelines.config.ts +229 -0
  6. package/config/nextjs.config.ts +160 -0
  7. package/config/react.config.ts +330 -0
  8. package/dist/config/angular.config.d.ts +15 -0
  9. package/dist/config/angular.config.d.ts.map +1 -0
  10. package/dist/config/angular.config.js +187 -0
  11. package/dist/config/angular.config.js.map +1 -0
  12. package/dist/config/guidelines.config.d.ts +63 -0
  13. package/dist/config/guidelines.config.d.ts.map +1 -0
  14. package/dist/config/guidelines.config.js +167 -0
  15. package/dist/config/guidelines.config.js.map +1 -0
  16. package/dist/config/nextjs.config.d.ts +18 -0
  17. package/dist/config/nextjs.config.d.ts.map +1 -0
  18. package/dist/config/nextjs.config.js +133 -0
  19. package/dist/config/nextjs.config.js.map +1 -0
  20. package/dist/config/react.config.d.ts +15 -0
  21. package/dist/config/react.config.d.ts.map +1 -0
  22. package/dist/config/react.config.js +287 -0
  23. package/dist/config/react.config.js.map +1 -0
  24. package/dist/scripts/auto-fix.d.ts +16 -0
  25. package/dist/scripts/auto-fix.d.ts.map +1 -0
  26. package/dist/scripts/auto-fix.js +130 -0
  27. package/dist/scripts/auto-fix.js.map +1 -0
  28. package/dist/scripts/cli.d.ts +17 -0
  29. package/dist/scripts/cli.d.ts.map +1 -0
  30. package/dist/scripts/cli.js +255 -0
  31. package/dist/scripts/cli.js.map +1 -0
  32. package/dist/scripts/delete-bypass-logs.d.ts +17 -0
  33. package/dist/scripts/delete-bypass-logs.d.ts.map +1 -0
  34. package/dist/scripts/delete-bypass-logs.js +242 -0
  35. package/dist/scripts/delete-bypass-logs.js.map +1 -0
  36. package/dist/scripts/generate-doc.d.ts +18 -0
  37. package/dist/scripts/generate-doc.d.ts.map +1 -0
  38. package/dist/scripts/generate-doc.js +300 -0
  39. package/dist/scripts/generate-doc.js.map +1 -0
  40. package/dist/scripts/generate-pr-checklist.d.ts +20 -0
  41. package/dist/scripts/generate-pr-checklist.d.ts.map +1 -0
  42. package/dist/scripts/generate-pr-checklist.js +276 -0
  43. package/dist/scripts/generate-pr-checklist.js.map +1 -0
  44. package/dist/scripts/precommit-check.d.ts +23 -0
  45. package/dist/scripts/precommit-check.d.ts.map +1 -0
  46. package/dist/scripts/precommit-check.js +331 -0
  47. package/dist/scripts/precommit-check.js.map +1 -0
  48. package/dist/scripts/set-admin-password.d.ts +14 -0
  49. package/dist/scripts/set-admin-password.d.ts.map +1 -0
  50. package/dist/scripts/set-admin-password.js +116 -0
  51. package/dist/scripts/set-admin-password.js.map +1 -0
  52. package/dist/scripts/set-bypass-password.d.ts +11 -0
  53. package/dist/scripts/set-bypass-password.d.ts.map +1 -0
  54. package/dist/scripts/set-bypass-password.js +106 -0
  55. package/dist/scripts/set-bypass-password.js.map +1 -0
  56. package/dist/scripts/utils/auto-fixer.d.ts +28 -0
  57. package/dist/scripts/utils/auto-fixer.d.ts.map +1 -0
  58. package/dist/scripts/utils/auto-fixer.js +177 -0
  59. package/dist/scripts/utils/auto-fixer.js.map +1 -0
  60. package/dist/scripts/utils/bypass-manager.d.ts +101 -0
  61. package/dist/scripts/utils/bypass-manager.d.ts.map +1 -0
  62. package/dist/scripts/utils/bypass-manager.js +496 -0
  63. package/dist/scripts/utils/bypass-manager.js.map +1 -0
  64. package/dist/scripts/utils/code-analyzer.d.ts +34 -0
  65. package/dist/scripts/utils/code-analyzer.d.ts.map +1 -0
  66. package/dist/scripts/utils/code-analyzer.js +323 -0
  67. package/dist/scripts/utils/code-analyzer.js.map +1 -0
  68. package/dist/scripts/utils/file-checker.d.ts +93 -0
  69. package/dist/scripts/utils/file-checker.d.ts.map +1 -0
  70. package/dist/scripts/utils/file-checker.js +248 -0
  71. package/dist/scripts/utils/file-checker.js.map +1 -0
  72. package/dist/scripts/utils/logger.d.ts +26 -0
  73. package/dist/scripts/utils/logger.d.ts.map +1 -0
  74. package/dist/scripts/utils/logger.js +86 -0
  75. package/dist/scripts/utils/logger.js.map +1 -0
  76. package/dist/scripts/utils/project-detector.d.ts +34 -0
  77. package/dist/scripts/utils/project-detector.d.ts.map +1 -0
  78. package/dist/scripts/utils/project-detector.js +124 -0
  79. package/dist/scripts/utils/project-detector.js.map +1 -0
  80. package/dist/scripts/utils/rule-engine.d.ts +57 -0
  81. package/dist/scripts/utils/rule-engine.d.ts.map +1 -0
  82. package/dist/scripts/utils/rule-engine.js +158 -0
  83. package/dist/scripts/utils/rule-engine.js.map +1 -0
  84. package/dist/scripts/view-bypass-log.d.ts +13 -0
  85. package/dist/scripts/view-bypass-log.d.ts.map +1 -0
  86. package/dist/scripts/view-bypass-log.js +117 -0
  87. package/dist/scripts/view-bypass-log.js.map +1 -0
  88. package/package.json +74 -0
  89. package/scripts/auto-fix.ts +115 -0
  90. package/scripts/cli.ts +246 -0
  91. package/scripts/delete-bypass-logs.ts +253 -0
  92. package/scripts/generate-doc.ts +317 -0
  93. package/scripts/generate-pr-checklist.ts +285 -0
  94. package/scripts/precommit-check.ts +349 -0
  95. package/scripts/set-admin-password.ts +90 -0
  96. package/scripts/set-bypass-password.ts +80 -0
  97. package/scripts/utils/auto-fixer.ts +181 -0
  98. package/scripts/utils/bypass-manager.ts +566 -0
  99. package/scripts/utils/code-analyzer.ts +341 -0
  100. package/scripts/utils/file-checker.ts +253 -0
  101. package/scripts/utils/logger.ts +88 -0
  102. package/scripts/utils/project-detector.ts +115 -0
  103. package/scripts/utils/rule-engine.ts +186 -0
  104. package/scripts/view-bypass-log.ts +92 -0
  105. package/templates/feature-doc-api.md +101 -0
  106. package/templates/feature-doc-service.md +113 -0
  107. 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