@hatem427/code-guard-ci 3.5.7 → 3.5.9
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/config/angular.config.ts +66 -22
- package/config/guidelines.config.ts +15 -2
- package/dist/config/angular.config.d.ts.map +1 -1
- package/dist/config/angular.config.js +97 -22
- package/dist/config/angular.config.js.map +1 -1
- package/dist/config/guidelines.config.d.ts.map +1 -1
- package/dist/config/guidelines.config.js +13 -2
- package/dist/config/guidelines.config.js.map +1 -1
- package/dist/scripts/cli.js +101 -0
- package/dist/scripts/cli.js.map +1 -1
- package/dist/scripts/config-generators/ai-config-generator.d.ts.map +1 -1
- package/dist/scripts/config-generators/ai-config-generator.js +108 -0
- package/dist/scripts/config-generators/ai-config-generator.js.map +1 -1
- package/dist/scripts/utils/report-generator.d.ts.map +1 -1
- package/dist/scripts/utils/report-generator.js +0 -4
- package/dist/scripts/utils/report-generator.js.map +1 -1
- package/package.json +1 -1
- package/scripts/cli.ts +121 -0
- package/scripts/config-generators/ai-config-generator.ts +133 -0
- package/scripts/utils/report-generator.ts +0 -5
package/config/angular.config.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - RxJS best practices (async pipe, takeUntilDestroyed, signals)
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import * as fs from 'fs';
|
|
13
14
|
import { registerRules, Rule } from './guidelines.config';
|
|
14
15
|
|
|
15
16
|
const angularRules: Rule[] = [
|
|
@@ -90,42 +91,85 @@ const angularRules: Rule[] = [
|
|
|
90
91
|
customCheck: (file) => {
|
|
91
92
|
const violations: Array<{ line: number | null; message: string }> = [];
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
94
|
+
// ── 1. Discover signals declared in the companion .ts component file ────
|
|
95
|
+
//
|
|
96
|
+
// Angular signals (signal, computed, toSignal, input, output, viewChild,
|
|
97
|
+
// contentChild, model) are read by calling them as functions — e.g.
|
|
98
|
+
// loading() — which looks identical to a regular method call in a template.
|
|
99
|
+
// We resolve the companion TypeScript file and extract every identifier
|
|
100
|
+
// that is assigned to a signal factory so we can whitelist those calls.
|
|
101
|
+
const signalNames = new Set<string>();
|
|
102
|
+
const tsFilePath = file.absolutePath.replace(/\.html$/, '.ts');
|
|
103
|
+
try {
|
|
104
|
+
if (fs.existsSync(tsFilePath)) {
|
|
105
|
+
const tsContent = fs.readFileSync(tsFilePath, 'utf-8');
|
|
106
|
+
// Matches class field assignments like:
|
|
107
|
+
// loading = signal(false)
|
|
108
|
+
// readonly isReady = computed(() => ...)
|
|
109
|
+
// data = toSignal(obs$)
|
|
110
|
+
// name = input('') / name = input.required<string>()
|
|
111
|
+
// clicked = output() / el = viewChild('ref') / val = model(0)
|
|
112
|
+
const signalDeclPattern =
|
|
113
|
+
/\b(\w+)\s*=\s*(?:signal|computed|toSignal|input(?:\.required)?|output(?:Required)?|viewChild(?:Required)?|viewChildren|contentChild(?:Required)?|contentChildren|model)\s*[(<]/g;
|
|
114
|
+
let m: RegExpExecArray | null;
|
|
115
|
+
while ((m = signalDeclPattern.exec(tsContent)) !== null) {
|
|
116
|
+
signalNames.add(m[1]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
// If the companion file cannot be read, fall back to no signal awareness.
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── 2. Helper: returns true when every function call in the expression
|
|
124
|
+
// is either a known signal read or an Angular built-in ($any, $event). ──
|
|
125
|
+
const ANGULAR_BUILTINS = new Set(['$any', '$event']);
|
|
126
|
+
const allCallsAreSafe = (expression: string): boolean => {
|
|
127
|
+
// Without signal metadata we cannot safely whitelist anything.
|
|
128
|
+
if (signalNames.size === 0) return false;
|
|
129
|
+
const callPattern = /\b(\w+)\s*\(/g;
|
|
130
|
+
let m: RegExpExecArray | null;
|
|
131
|
+
while ((m = callPattern.exec(expression)) !== null) {
|
|
132
|
+
if (!signalNames.has(m[1]) && !ANGULAR_BUILTINS.has(m[1])) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// ── 3. Scan each line ────────────────────────────────────────────────────
|
|
103
140
|
const interpolationRegex = /\{\{[^}]*\w+\s*\([^)]*\)[^}]*\}\}/g;
|
|
104
|
-
|
|
141
|
+
// Property binding regex — excludes event bindings such as (click), (submit) …
|
|
142
|
+
const propertyBindingRegex =
|
|
143
|
+
/\[(?!click|submit|keyup|keydown|change|input|focus|blur)\w+\]\s*=\s*"([^"]*)"/g;
|
|
105
144
|
|
|
106
145
|
for (let i = 0; i < file.lines.length; i++) {
|
|
107
146
|
const line = file.lines[i];
|
|
147
|
+
const trimmed = line.trim();
|
|
108
148
|
|
|
109
|
-
//
|
|
149
|
+
// ── Interpolation: {{ expr() }} ─────────────────────────────────────
|
|
110
150
|
interpolationRegex.lastIndex = 0;
|
|
111
151
|
if (interpolationRegex.test(line)) {
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
if (!trimmed.includes(' | ')) {
|
|
152
|
+
// Pipes like {{ value | date }} are always safe.
|
|
153
|
+
if (!trimmed.includes(' | ') && !allCallsAreSafe(trimmed)) {
|
|
115
154
|
violations.push({
|
|
116
155
|
line: i + 1,
|
|
117
|
-
message: `Function call in interpolation: "${trimmed}". Use a pipe or signal instead.`,
|
|
156
|
+
message: `Function call in interpolation: "${trimmed}". Use a pipe or computed signal instead.`,
|
|
118
157
|
});
|
|
119
158
|
}
|
|
120
159
|
}
|
|
121
160
|
|
|
122
|
-
//
|
|
161
|
+
// ── Property bindings: [prop]="expr()" ──────────────────────────────
|
|
123
162
|
propertyBindingRegex.lastIndex = 0;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
163
|
+
let match: RegExpExecArray | null;
|
|
164
|
+
while ((match = propertyBindingRegex.exec(line)) !== null) {
|
|
165
|
+
const expression = match[1]; // content between the quotes
|
|
166
|
+
if (/\w+\s*\(/.test(expression) && !allCallsAreSafe(expression)) {
|
|
167
|
+
violations.push({
|
|
168
|
+
line: i + 1,
|
|
169
|
+
message: `Function call in property binding: "${trimmed}". Use a signal or computed signal instead.`,
|
|
170
|
+
});
|
|
171
|
+
break; // one violation per line is enough
|
|
172
|
+
}
|
|
129
173
|
}
|
|
130
174
|
}
|
|
131
175
|
|
|
@@ -336,7 +336,18 @@ export const sharedRules: Rule[] = [
|
|
|
336
336
|
(/^\s*(export\s+)?(const|let|var)\s+\w+\s*=\s*(async\s+)?\(/.test(line) &&
|
|
337
337
|
(line.includes('=>') || /=\s*(async\s+)?\(\s*$/.test(line)));
|
|
338
338
|
|
|
339
|
-
|
|
339
|
+
// Detect class methods (Angular components, services, directives, etc.):
|
|
340
|
+
// foo() {, async foo() {, public/private/protected foo() {
|
|
341
|
+
// override foo() {, get foo() {, set foo() {
|
|
342
|
+
// Also handles method signatures spread across lines via trailing (
|
|
343
|
+
const isClassMethod =
|
|
344
|
+
/^\s*(public\s+|private\s+|protected\s+)?(override\s+)?(async\s+)?(get\s+|set\s+)?\w+\s*\(.*\)\s*(\:\s*\S+\s*)?\{?\s*$/.test(line) &&
|
|
345
|
+
// Exclude: class declarations, if/for/while/switch/catch, arrow assigns, plain object props
|
|
346
|
+
!/^\s*(class|if|else|for|while|switch|catch|return|const|let|var|export|import)\b/.test(line) &&
|
|
347
|
+
// Must look like a method: word followed by (
|
|
348
|
+
/^\s*(?:(?:public|private|protected|override|async|get|set)\s+)*\w+\s*\(/.test(line);
|
|
349
|
+
|
|
350
|
+
if (!isFunctionDecl && !isArrowAssign && !isClassMethod) continue;
|
|
340
351
|
|
|
341
352
|
// ── Check 1: Blank line before function ──────────────────────────
|
|
342
353
|
// Allowed to have no blank line: when preceded by opening brace, another decorator,
|
|
@@ -347,15 +358,17 @@ export const sharedRules: Rule[] = [
|
|
|
347
358
|
prevTrimmed === '' || // blank line — correct
|
|
348
359
|
prevTrimmed === '{' || // opening brace of class/block
|
|
349
360
|
prevTrimmed === '(' || // opening paren
|
|
361
|
+
prevTrimmed.endsWith('{') || // e.g. class Foo { or constructor() {
|
|
350
362
|
prevTrimmed.startsWith('//') ||
|
|
351
363
|
prevTrimmed.startsWith('/*') ||
|
|
352
364
|
prevTrimmed.startsWith('*') ||
|
|
353
365
|
prevTrimmed.startsWith('@'); // decorator on previous line
|
|
354
366
|
|
|
355
367
|
if (!isAllowedPrev) {
|
|
368
|
+
const who = isClassMethod ? 'class method' : 'function declaration';
|
|
356
369
|
violations.push({
|
|
357
370
|
line: i + 1,
|
|
358
|
-
message: `Missing blank line before
|
|
371
|
+
message: `Missing blank line before ${who}. Previous line: "${prevTrimmed.substring(0, 60)}"`,
|
|
359
372
|
});
|
|
360
373
|
}
|
|
361
374
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angular.config.d.ts","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"angular.config.d.ts","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAiB,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE1D,QAAA,MAAM,YAAY,EAAE,IAAI,EAkXvB,CAAC;AAKF,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -10,8 +10,42 @@
|
|
|
10
10
|
* - Function calls in templates
|
|
11
11
|
* - RxJS best practices (async pipe, takeUntilDestroyed, signals)
|
|
12
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
|
+
})();
|
|
13
46
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
47
|
exports.angularRules = void 0;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
15
49
|
const guidelines_config_1 = require("./guidelines.config");
|
|
16
50
|
const angularRules = [
|
|
17
51
|
// ── Lifecycle ──────────────────────────────────────────────────────────
|
|
@@ -77,39 +111,80 @@ const angularRules = [
|
|
|
77
111
|
pattern: null,
|
|
78
112
|
customCheck: (file) => {
|
|
79
113
|
const violations = [];
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
114
|
+
// ── 1. Discover signals declared in the companion .ts component file ────
|
|
115
|
+
//
|
|
116
|
+
// Angular signals (signal, computed, toSignal, input, output, viewChild,
|
|
117
|
+
// contentChild, model) are read by calling them as functions — e.g.
|
|
118
|
+
// loading() — which looks identical to a regular method call in a template.
|
|
119
|
+
// We resolve the companion TypeScript file and extract every identifier
|
|
120
|
+
// that is assigned to a signal factory so we can whitelist those calls.
|
|
121
|
+
const signalNames = new Set();
|
|
122
|
+
const tsFilePath = file.absolutePath.replace(/\.html$/, '.ts');
|
|
123
|
+
try {
|
|
124
|
+
if (fs.existsSync(tsFilePath)) {
|
|
125
|
+
const tsContent = fs.readFileSync(tsFilePath, 'utf-8');
|
|
126
|
+
// Matches class field assignments like:
|
|
127
|
+
// loading = signal(false)
|
|
128
|
+
// readonly isReady = computed(() => ...)
|
|
129
|
+
// data = toSignal(obs$)
|
|
130
|
+
// name = input('') / name = input.required<string>()
|
|
131
|
+
// clicked = output() / el = viewChild('ref') / val = model(0)
|
|
132
|
+
const signalDeclPattern = /\b(\w+)\s*=\s*(?:signal|computed|toSignal|input(?:\.required)?|output(?:Required)?|viewChild(?:Required)?|viewChildren|contentChild(?:Required)?|contentChildren|model)\s*[(<]/g;
|
|
133
|
+
let m;
|
|
134
|
+
while ((m = signalDeclPattern.exec(tsContent)) !== null) {
|
|
135
|
+
signalNames.add(m[1]);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// If the companion file cannot be read, fall back to no signal awareness.
|
|
141
|
+
}
|
|
142
|
+
// ── 2. Helper: returns true when every function call in the expression
|
|
143
|
+
// is either a known signal read or an Angular built-in ($any, $event). ──
|
|
144
|
+
const ANGULAR_BUILTINS = new Set(['$any', '$event']);
|
|
145
|
+
const allCallsAreSafe = (expression) => {
|
|
146
|
+
// Without signal metadata we cannot safely whitelist anything.
|
|
147
|
+
if (signalNames.size === 0)
|
|
148
|
+
return false;
|
|
149
|
+
const callPattern = /\b(\w+)\s*\(/g;
|
|
150
|
+
let m;
|
|
151
|
+
while ((m = callPattern.exec(expression)) !== null) {
|
|
152
|
+
if (!signalNames.has(m[1]) && !ANGULAR_BUILTINS.has(m[1])) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
};
|
|
158
|
+
// ── 3. Scan each line ────────────────────────────────────────────────────
|
|
90
159
|
const interpolationRegex = /\{\{[^}]*\w+\s*\([^)]*\)[^}]*\}\}/g;
|
|
91
|
-
|
|
160
|
+
// Property binding regex — excludes event bindings such as (click), (submit) …
|
|
161
|
+
const propertyBindingRegex = /\[(?!click|submit|keyup|keydown|change|input|focus|blur)\w+\]\s*=\s*"([^"]*)"/g;
|
|
92
162
|
for (let i = 0; i < file.lines.length; i++) {
|
|
93
163
|
const line = file.lines[i];
|
|
94
|
-
|
|
164
|
+
const trimmed = line.trim();
|
|
165
|
+
// ── Interpolation: {{ expr() }} ─────────────────────────────────────
|
|
95
166
|
interpolationRegex.lastIndex = 0;
|
|
96
167
|
if (interpolationRegex.test(line)) {
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
if (!trimmed.includes(' | ')) {
|
|
168
|
+
// Pipes like {{ value | date }} are always safe.
|
|
169
|
+
if (!trimmed.includes(' | ') && !allCallsAreSafe(trimmed)) {
|
|
100
170
|
violations.push({
|
|
101
171
|
line: i + 1,
|
|
102
|
-
message: `Function call in interpolation: "${trimmed}". Use a pipe or signal instead.`,
|
|
172
|
+
message: `Function call in interpolation: "${trimmed}". Use a pipe or computed signal instead.`,
|
|
103
173
|
});
|
|
104
174
|
}
|
|
105
175
|
}
|
|
106
|
-
//
|
|
176
|
+
// ── Property bindings: [prop]="expr()" ──────────────────────────────
|
|
107
177
|
propertyBindingRegex.lastIndex = 0;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
178
|
+
let match;
|
|
179
|
+
while ((match = propertyBindingRegex.exec(line)) !== null) {
|
|
180
|
+
const expression = match[1]; // content between the quotes
|
|
181
|
+
if (/\w+\s*\(/.test(expression) && !allCallsAreSafe(expression)) {
|
|
182
|
+
violations.push({
|
|
183
|
+
line: i + 1,
|
|
184
|
+
message: `Function call in property binding: "${trimmed}". Use a signal or computed signal instead.`,
|
|
185
|
+
});
|
|
186
|
+
break; // one violation per line is enough
|
|
187
|
+
}
|
|
113
188
|
}
|
|
114
189
|
}
|
|
115
190
|
return violations;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angular.config.js","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG
|
|
1
|
+
{"version":3,"file":"angular.config.js","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guidelines.config.d.ts","sourceRoot":"","sources":["../../config/guidelines.config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAIhE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAIpD,MAAM,WAAW,IAAI;IACnB,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IAEX,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IAEd,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IAEpB,qFAAqF;IACrF,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE7E;;;OAGG;IACH,YAAY,EAAE,WAAW,EAAE,CAAC;IAE5B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,eAAO,MAAM,WAAW,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"guidelines.config.d.ts","sourceRoot":"","sources":["../../config/guidelines.config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAIhE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAIpD,MAAM,WAAW,IAAI;IACnB,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IAEX,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IAEd,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IAEpB,qFAAqF;IACrF,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE7E;;;OAGG;IACH,YAAY,EAAE,WAAW,EAAE,CAAC;IAE5B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,eAAO,MAAM,WAAW,EAAE,IAAI,EAkV7B,CAAC;AAMF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAG3E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,EAAE,CAgBnE;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,EAAE,CAiBpC"}
|
|
@@ -250,7 +250,16 @@ exports.sharedRules = [
|
|
|
250
250
|
const isArrowAssign = /^\s*(export\s+)?(const|let|var)\s+\w+\s*=\s*(async\s+)?function\s*\(/.test(line) ||
|
|
251
251
|
(/^\s*(export\s+)?(const|let|var)\s+\w+\s*=\s*(async\s+)?\(/.test(line) &&
|
|
252
252
|
(line.includes('=>') || /=\s*(async\s+)?\(\s*$/.test(line)));
|
|
253
|
-
|
|
253
|
+
// Detect class methods (Angular components, services, directives, etc.):
|
|
254
|
+
// foo() {, async foo() {, public/private/protected foo() {
|
|
255
|
+
// override foo() {, get foo() {, set foo() {
|
|
256
|
+
// Also handles method signatures spread across lines via trailing (
|
|
257
|
+
const isClassMethod = /^\s*(public\s+|private\s+|protected\s+)?(override\s+)?(async\s+)?(get\s+|set\s+)?\w+\s*\(.*\)\s*(\:\s*\S+\s*)?\{?\s*$/.test(line) &&
|
|
258
|
+
// Exclude: class declarations, if/for/while/switch/catch, arrow assigns, plain object props
|
|
259
|
+
!/^\s*(class|if|else|for|while|switch|catch|return|const|let|var|export|import)\b/.test(line) &&
|
|
260
|
+
// Must look like a method: word followed by (
|
|
261
|
+
/^\s*(?:(?:public|private|protected|override|async|get|set)\s+)*\w+\s*\(/.test(line);
|
|
262
|
+
if (!isFunctionDecl && !isArrowAssign && !isClassMethod)
|
|
254
263
|
continue;
|
|
255
264
|
// ── Check 1: Blank line before function ──────────────────────────
|
|
256
265
|
// Allowed to have no blank line: when preceded by opening brace, another decorator,
|
|
@@ -260,14 +269,16 @@ exports.sharedRules = [
|
|
|
260
269
|
const isAllowedPrev = prevTrimmed === '' || // blank line — correct
|
|
261
270
|
prevTrimmed === '{' || // opening brace of class/block
|
|
262
271
|
prevTrimmed === '(' || // opening paren
|
|
272
|
+
prevTrimmed.endsWith('{') || // e.g. class Foo { or constructor() {
|
|
263
273
|
prevTrimmed.startsWith('//') ||
|
|
264
274
|
prevTrimmed.startsWith('/*') ||
|
|
265
275
|
prevTrimmed.startsWith('*') ||
|
|
266
276
|
prevTrimmed.startsWith('@'); // decorator on previous line
|
|
267
277
|
if (!isAllowedPrev) {
|
|
278
|
+
const who = isClassMethod ? 'class method' : 'function declaration';
|
|
268
279
|
violations.push({
|
|
269
280
|
line: i + 1,
|
|
270
|
-
message: `Missing blank line before
|
|
281
|
+
message: `Missing blank line before ${who}. Previous line: "${prevTrimmed.substring(0, 60)}"`,
|
|
271
282
|
});
|
|
272
283
|
}
|
|
273
284
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guidelines.config.js","sourceRoot":"","sources":["../../config/guidelines.config.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;
|
|
1
|
+
{"version":3,"file":"guidelines.config.js","sourceRoot":"","sources":["../../config/guidelines.config.ts"],"names":[],"mappings":"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"}
|
package/dist/scripts/cli.js
CHANGED
|
@@ -438,6 +438,8 @@ function initProject() {
|
|
|
438
438
|
// ── Save manifest ─────────────────────────────────────────────────────────
|
|
439
439
|
saveManifest(cwd, manifest);
|
|
440
440
|
console.log(` ${c.green('✓')} Saved manifest to .code-guardian/manifest.json\n`);
|
|
441
|
+
// ── Update .gitignore for .code-guardian/ ────────────────────────────────
|
|
442
|
+
ensureCodeGuardianGitignore(cwd);
|
|
441
443
|
// ── Done! ─────────────────────────────────────────────────────────────────
|
|
442
444
|
console.log(c.bold(c.green('═══════════════════════════════════════════════════════════')));
|
|
443
445
|
console.log(c.bold(c.green(' ✅ Code Guardian initialized successfully!')));
|
|
@@ -468,6 +470,105 @@ function initProject() {
|
|
|
468
470
|
console.log(` 3. Make a commit to test: ${c.cyan('git add . && git commit -m "feat: init code guardian"')}`);
|
|
469
471
|
console.log('');
|
|
470
472
|
}
|
|
473
|
+
// ── .gitignore management for .code-guardian/ ───────────────────────────────
|
|
474
|
+
/**
|
|
475
|
+
* Best-practice .gitignore management for .code-guardian/.
|
|
476
|
+
*
|
|
477
|
+
* SENSITIVE — never commit (passwords, generated reports):
|
|
478
|
+
* .code-guardian/bypass-password.hash
|
|
479
|
+
* .code-guardian/admin-password.hash
|
|
480
|
+
* .code-guardian/CODE_GUARDIAN_REPORT.md
|
|
481
|
+
*
|
|
482
|
+
* TRACKED — must be committed (team config, audit trail):
|
|
483
|
+
* .code-guardian/custom-rules.json
|
|
484
|
+
* .code-guardian/structure-rules.json
|
|
485
|
+
* .code-guardian/naming-rules.json
|
|
486
|
+
* .code-guardian/manifest.json
|
|
487
|
+
* .code-guardian/bypass-log.json
|
|
488
|
+
*
|
|
489
|
+
* STRATEGY:
|
|
490
|
+
* If `.code-guardian` is broadly ignored → replace with surgical pattern:
|
|
491
|
+
* .code-guardian/* (ignore everything inside …)
|
|
492
|
+
* !.code-guardian/custom-rules.json (… except tracked files)
|
|
493
|
+
* …
|
|
494
|
+
* Always add sensitive files to ignore if not present.
|
|
495
|
+
*/
|
|
496
|
+
function ensureCodeGuardianGitignore(cwd) {
|
|
497
|
+
const gitignorePath = path.join(cwd, '.gitignore');
|
|
498
|
+
const sensitiveFiles = [
|
|
499
|
+
'.code-guardian/bypass-password.hash',
|
|
500
|
+
'.code-guardian/admin-password.hash',
|
|
501
|
+
'.code-guardian/CODE_GUARDIAN_REPORT.md',
|
|
502
|
+
];
|
|
503
|
+
const trackedFiles = [
|
|
504
|
+
'.code-guardian/custom-rules.json',
|
|
505
|
+
'.code-guardian/structure-rules.json',
|
|
506
|
+
'.code-guardian/naming-rules.json',
|
|
507
|
+
'.code-guardian/manifest.json',
|
|
508
|
+
'.code-guardian/bypass-log.json',
|
|
509
|
+
];
|
|
510
|
+
let content = fs.existsSync(gitignorePath)
|
|
511
|
+
? fs.readFileSync(gitignorePath, 'utf-8')
|
|
512
|
+
: '';
|
|
513
|
+
let changed = false;
|
|
514
|
+
const messages = [];
|
|
515
|
+
// ── 1. Replace broad .code-guardian ignore with surgical pattern ─────────
|
|
516
|
+
const broadPattern = /^\.code-guardian\/?$/m;
|
|
517
|
+
const broadMatch = broadPattern.exec(content);
|
|
518
|
+
if (broadMatch) {
|
|
519
|
+
const surgicalLines = [
|
|
520
|
+
'.code-guardian/*',
|
|
521
|
+
...trackedFiles.map(f => `!${f}`),
|
|
522
|
+
];
|
|
523
|
+
content = content.replace(broadPattern, surgicalLines.join('\n'));
|
|
524
|
+
changed = true;
|
|
525
|
+
messages.push(` ${c.green('✓')} .gitignore: replaced broad \`.code-guardian\` with surgical pattern:\n` +
|
|
526
|
+
surgicalLines.map(l => ` ${l.startsWith('!') ? c.green(l) + ' (tracked)' : c.dim(l) + ' (ignored)'}`).join('\n'));
|
|
527
|
+
}
|
|
528
|
+
// ── 2. Always ensure sensitive files are explicitly ignored ──────────────
|
|
529
|
+
const toIgnore = sensitiveFiles.filter(f => !content.includes(f));
|
|
530
|
+
if (toIgnore.length > 0) {
|
|
531
|
+
content += [
|
|
532
|
+
'',
|
|
533
|
+
'# Code Guardian — sensitive/generated (do not commit)',
|
|
534
|
+
...toIgnore,
|
|
535
|
+
'',
|
|
536
|
+
].join('\n');
|
|
537
|
+
changed = true;
|
|
538
|
+
messages.push(` ${c.green('✓')} .gitignore: sensitive files added:\n` +
|
|
539
|
+
toIgnore.map(f => ` ${c.dim(f)}`).join('\n'));
|
|
540
|
+
}
|
|
541
|
+
// ── 3. Ensure tracked files are negated if the dir is still pattern-ignored
|
|
542
|
+
if (!broadMatch) {
|
|
543
|
+
// Dir wasn't broadly ignored — check if individual tracked files are ignored
|
|
544
|
+
// and add negations for any that are
|
|
545
|
+
const negationsNeeded = trackedFiles
|
|
546
|
+
.filter(f => {
|
|
547
|
+
const r = (0, child_process_1.spawnSync)('git', ['check-ignore', '--no-index', '-q', f], {
|
|
548
|
+
cwd, stdio: 'pipe',
|
|
549
|
+
});
|
|
550
|
+
return r.status === 0; // ignored
|
|
551
|
+
})
|
|
552
|
+
.map(f => `!${f}`)
|
|
553
|
+
.filter(neg => !content.includes(neg));
|
|
554
|
+
if (negationsNeeded.length > 0) {
|
|
555
|
+
content += [
|
|
556
|
+
'',
|
|
557
|
+
'# Code Guardian — team config files (must be tracked)',
|
|
558
|
+
...negationsNeeded,
|
|
559
|
+
'',
|
|
560
|
+
].join('\n');
|
|
561
|
+
changed = true;
|
|
562
|
+
messages.push(` ${c.green('✓')} .gitignore: un-ignored tracked config files:\n` +
|
|
563
|
+
negationsNeeded.map(l => ` ${c.green(l)}`).join('\n'));
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (changed) {
|
|
567
|
+
fs.writeFileSync(gitignorePath, content, 'utf-8');
|
|
568
|
+
messages.forEach(m => console.log(m));
|
|
569
|
+
console.log('');
|
|
570
|
+
}
|
|
571
|
+
}
|
|
471
572
|
// ── Setup Git Hooks ─────────────────────────────────────────────────────────
|
|
472
573
|
function setupGitHooks(cwd) {
|
|
473
574
|
try {
|