@hatem427/code-guard-ci 3.3.0 → 3.4.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/config/angular.config.ts +29 -708
- package/config/guidelines.config.ts +5 -130
- package/config/nextjs.config.ts +27 -511
- package/config/react.config.ts +19 -614
- package/dist/config/angular.config.d.ts +5 -8
- package/dist/config/angular.config.d.ts.map +1 -1
- package/dist/config/angular.config.js +28 -666
- 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 +5 -127
- package/dist/config/guidelines.config.js.map +1 -1
- package/dist/config/nextjs.config.d.ts +7 -9
- package/dist/config/nextjs.config.d.ts.map +1 -1
- package/dist/config/nextjs.config.js +26 -472
- package/dist/config/nextjs.config.js.map +1 -1
- package/dist/config/react.config.d.ts +4 -5
- package/dist/config/react.config.d.ts.map +1 -1
- package/dist/config/react.config.js +19 -586
- package/dist/config/react.config.js.map +1 -1
- package/dist/scripts/auto-fix.d.ts +0 -5
- package/dist/scripts/auto-fix.d.ts.map +1 -1
- package/dist/scripts/auto-fix.js +0 -5
- package/dist/scripts/auto-fix.js.map +1 -1
- package/dist/scripts/cli.js +211 -415
- 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 +71 -15
- package/dist/scripts/config-generators/ai-config-generator.js.map +1 -1
- package/dist/scripts/config-generators/eslint-generator.d.ts.map +1 -1
- package/dist/scripts/config-generators/eslint-generator.js +13 -625
- package/dist/scripts/config-generators/eslint-generator.js.map +1 -1
- package/dist/scripts/config-generators/index.d.ts +0 -1
- package/dist/scripts/config-generators/index.d.ts.map +1 -1
- package/dist/scripts/config-generators/index.js +1 -5
- package/dist/scripts/config-generators/index.js.map +1 -1
- package/dist/scripts/config-generators/typescript-generator.d.ts.map +1 -1
- package/dist/scripts/config-generators/typescript-generator.js +0 -33
- package/dist/scripts/config-generators/typescript-generator.js.map +1 -1
- package/dist/scripts/config-generators/vscode-generator.d.ts.map +1 -1
- package/dist/scripts/config-generators/vscode-generator.js +28 -171
- package/dist/scripts/config-generators/vscode-generator.js.map +1 -1
- package/dist/scripts/generate-pr-checklist.d.ts +0 -5
- package/dist/scripts/generate-pr-checklist.d.ts.map +1 -1
- package/dist/scripts/generate-pr-checklist.js +1 -6
- package/dist/scripts/generate-pr-checklist.js.map +1 -1
- package/dist/scripts/postinstall.js +0 -38
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/scripts/precommit-check.d.ts +0 -5
- package/dist/scripts/precommit-check.d.ts.map +1 -1
- package/dist/scripts/precommit-check.js +92 -149
- package/dist/scripts/precommit-check.js.map +1 -1
- package/dist/scripts/utils/naming-validator.d.ts.map +1 -1
- package/dist/scripts/utils/naming-validator.js +2 -96
- package/dist/scripts/utils/naming-validator.js.map +1 -1
- package/dist/scripts/utils/project-detector.d.ts +9 -12
- package/dist/scripts/utils/project-detector.d.ts.map +1 -1
- package/dist/scripts/utils/project-detector.js +11 -63
- package/dist/scripts/utils/project-detector.js.map +1 -1
- package/dist/scripts/utils/report-generator.js +5 -17
- package/dist/scripts/utils/report-generator.js.map +1 -1
- package/dist/scripts/utils/structure-validator.d.ts.map +1 -1
- package/dist/scripts/utils/structure-validator.js +0 -50
- package/dist/scripts/utils/structure-validator.js.map +1 -1
- package/package.json +1 -12
- package/scripts/auto-fix.ts +0 -5
- package/scripts/cli.ts +226 -451
- package/scripts/config-generators/ai-config-generator.ts +78 -28
- package/scripts/config-generators/eslint-generator.ts +7 -621
- package/scripts/config-generators/index.ts +0 -1
- package/scripts/config-generators/typescript-generator.ts +0 -36
- package/scripts/config-generators/vscode-generator.ts +40 -178
- package/scripts/generate-pr-checklist.ts +1 -6
- package/scripts/postinstall.ts +0 -38
- package/scripts/precommit-check.ts +113 -278
- package/scripts/utils/naming-validator.ts +2 -104
- package/scripts/utils/project-detector.ts +11 -78
- package/scripts/utils/report-generator.ts +5 -19
- package/scripts/utils/structure-validator.ts +0 -54
- package/config/fastify.config.ts +0 -326
- package/config/hono.config.ts +0 -331
- package/config/nestjs.config.ts +0 -500
- package/config/python.config.ts +0 -512
- package/templates/feature-doc-api.md +0 -101
- package/templates/feature-doc-backend.md +0 -114
- package/templates/feature-doc-service.md +0 -113
- package/templates/feature-doc-ui.md +0 -91
package/config/hono.config.ts
DELETED
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ============================================================================
|
|
3
|
-
* hono.config.ts — Hono-specific coding rules
|
|
4
|
-
* ============================================================================
|
|
5
|
-
*
|
|
6
|
-
* Registers rules that apply to Hono (edge + server) projects:
|
|
7
|
-
* - Zod validation enforcement
|
|
8
|
-
* - Context variable typing
|
|
9
|
-
* - Middleware chaining patterns
|
|
10
|
-
* - HTTPException usage
|
|
11
|
-
* - Environment access patterns
|
|
12
|
-
* - Stateless / edge-first patterns
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { registerRules, Rule } from './guidelines.config';
|
|
16
|
-
|
|
17
|
-
const honoRules: Rule[] = [
|
|
18
|
-
|
|
19
|
-
// ── Validation ────────────────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
// ─────────────────────────────────────────
|
|
22
|
-
// RULE: hono-use-zod-validator
|
|
23
|
-
// ROLE: Enforce schema-based request validation
|
|
24
|
-
// PURPOSE: Accessing c.req.json() or c.req.query() without validation
|
|
25
|
-
// passes raw untyped data to your handlers. Using @hono/zod-validator
|
|
26
|
-
// ensures type safety and returns a 400 automatically on bad input.
|
|
27
|
-
// EXAMPLE:
|
|
28
|
-
// WRONG:
|
|
29
|
-
// app.post('/users', async (c) => {
|
|
30
|
-
// const body = await c.req.json(); // untyped, unvalidated
|
|
31
|
-
// });
|
|
32
|
-
// RIGHT:
|
|
33
|
-
// import { zValidator } from '@hono/zod-validator';
|
|
34
|
-
// app.post('/users', zValidator('json', CreateUserSchema), async (c) => {
|
|
35
|
-
// const body = c.req.valid('json'); // typed and validated
|
|
36
|
-
// });
|
|
37
|
-
// ─────────────────────────────────────────
|
|
38
|
-
{
|
|
39
|
-
id: 'hono-use-zod-validator',
|
|
40
|
-
label: 'Use zValidator for request body validation',
|
|
41
|
-
description:
|
|
42
|
-
'Use @hono/zod-validator middleware on routes that accept request bodies. Calling c.req.json() directly bypasses type safety and validation.',
|
|
43
|
-
severity: 'error',
|
|
44
|
-
fileExtensions: ['ts'],
|
|
45
|
-
pattern: null,
|
|
46
|
-
customCheck: (file) => {
|
|
47
|
-
const violations: Array<{ line: number | null; message: string }> = [];
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
!file.relativePath.includes('/routes/') &&
|
|
51
|
-
!file.relativePath.endsWith('.route.ts') &&
|
|
52
|
-
!file.relativePath.endsWith('.routes.ts')
|
|
53
|
-
) {
|
|
54
|
-
return [];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Detect routes that use c.req.json() without zValidator
|
|
58
|
-
for (let i = 0; i < file.lines.length; i++) {
|
|
59
|
-
const line = file.lines[i];
|
|
60
|
-
if (/c\.req\.json\s*\(/.test(line)) {
|
|
61
|
-
// Check surrounding context for zValidator
|
|
62
|
-
const context = file.lines.slice(Math.max(0, i - 10), i).join('\n');
|
|
63
|
-
if (!context.includes('zValidator') && !context.includes('z.object')) {
|
|
64
|
-
violations.push({
|
|
65
|
-
line: i + 1,
|
|
66
|
-
message:
|
|
67
|
-
'c.req.json() used without zValidator middleware. Use zValidator("json", schema) before the handler and access via c.req.valid("json").',
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return violations;
|
|
74
|
-
},
|
|
75
|
-
applicableTo: ['hono'],
|
|
76
|
-
category: 'Validation',
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
// ─────────────────────────────────────────
|
|
80
|
-
// RULE: hono-use-valid-not-json
|
|
81
|
-
// ROLE: Enforce validated data access after zValidator
|
|
82
|
-
// PURPOSE: After applying zValidator middleware, handlers must use
|
|
83
|
-
// c.req.valid() to access the validated, typed data.
|
|
84
|
-
// c.req.json() bypasses validation and returns raw untyped data.
|
|
85
|
-
// EXAMPLE:
|
|
86
|
-
// WRONG:
|
|
87
|
-
// app.post('/user', zValidator('json', schema), async (c) => {
|
|
88
|
-
// const body = await c.req.json(); // still untyped!
|
|
89
|
-
// });
|
|
90
|
-
// RIGHT:
|
|
91
|
-
// app.post('/user', zValidator('json', schema), async (c) => {
|
|
92
|
-
// const body = c.req.valid('json'); // typed + validated
|
|
93
|
-
// });
|
|
94
|
-
// ─────────────────────────────────────────
|
|
95
|
-
{
|
|
96
|
-
id: 'hono-use-valid-not-json',
|
|
97
|
-
label: 'After zValidator, use c.req.valid() not c.req.json()',
|
|
98
|
-
description:
|
|
99
|
-
'When zValidator middleware is applied, access validated data via c.req.valid("json") instead of await c.req.json(). The latter bypasses type narrowing.',
|
|
100
|
-
severity: 'warning',
|
|
101
|
-
fileExtensions: ['ts'],
|
|
102
|
-
pattern: null,
|
|
103
|
-
customCheck: (file) => {
|
|
104
|
-
const violations: Array<{ line: number | null; message: string }> = [];
|
|
105
|
-
|
|
106
|
-
if (!file.content.includes('zValidator')) return [];
|
|
107
|
-
|
|
108
|
-
for (let i = 0; i < file.lines.length; i++) {
|
|
109
|
-
if (/await c\.req\.json\s*\(/.test(file.lines[i])) {
|
|
110
|
-
violations.push({
|
|
111
|
-
line: i + 1,
|
|
112
|
-
message:
|
|
113
|
-
'zValidator is used in this file. Replace await c.req.json() with c.req.valid("json") to access the typed validated data.',
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return violations;
|
|
119
|
-
},
|
|
120
|
-
applicableTo: ['hono'],
|
|
121
|
-
category: 'Validation',
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
// ── Error Handling ────────────────────────────────────────────────────────
|
|
125
|
-
|
|
126
|
-
// ─────────────────────────────────────────
|
|
127
|
-
// RULE: hono-use-http-exception
|
|
128
|
-
// ROLE: Enforce HTTPException for expected errors
|
|
129
|
-
// PURPOSE: Throwing a raw Error in a Hono handler produces a generic 500
|
|
130
|
-
// response with no meaningful body. HTTPException allows you to set
|
|
131
|
-
// a specific status code and message that will be formatted by
|
|
132
|
-
// Hono's onError handler consistently.
|
|
133
|
-
// EXAMPLE:
|
|
134
|
-
// WRONG:
|
|
135
|
-
// throw new Error('User not found');
|
|
136
|
-
// RIGHT:
|
|
137
|
-
// throw new HTTPException(404, { message: 'User not found' });
|
|
138
|
-
// ─────────────────────────────────────────
|
|
139
|
-
{
|
|
140
|
-
id: 'hono-use-http-exception',
|
|
141
|
-
label: 'Use HTTPException instead of raw Error',
|
|
142
|
-
description:
|
|
143
|
-
'Throw HTTPException from hono with a status code and message for expected errors (404, 401, 400, etc.). Raw Error objects produce unformatted 500 responses.',
|
|
144
|
-
severity: 'warning',
|
|
145
|
-
fileExtensions: ['ts'],
|
|
146
|
-
pattern: null,
|
|
147
|
-
customCheck: (file) => {
|
|
148
|
-
const violations: Array<{ line: number | null; message: string }> = [];
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
!file.relativePath.includes('/routes/') &&
|
|
152
|
-
!file.relativePath.includes('/handlers/') &&
|
|
153
|
-
!file.relativePath.endsWith('.route.ts') &&
|
|
154
|
-
!file.relativePath.endsWith('.handler.ts')
|
|
155
|
-
) {
|
|
156
|
-
return [];
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
for (let i = 0; i < file.lines.length; i++) {
|
|
160
|
-
if (/throw\s+new\s+Error\s*\(/.test(file.lines[i])) {
|
|
161
|
-
violations.push({
|
|
162
|
-
line: i + 1,
|
|
163
|
-
message:
|
|
164
|
-
'Raw Error thrown. Use HTTPException: throw new HTTPException(404, { message: "Not found" })',
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return violations;
|
|
170
|
-
},
|
|
171
|
-
applicableTo: ['hono'],
|
|
172
|
-
category: 'Error Handling',
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
// ── Context Variables ─────────────────────────────────────────────────────
|
|
176
|
-
|
|
177
|
-
// ─────────────────────────────────────────
|
|
178
|
-
// RULE: hono-type-context-variables
|
|
179
|
-
// ROLE: Enforce typed context variables
|
|
180
|
-
// PURPOSE: Using c.get() and c.set() without typed Variables means the
|
|
181
|
-
// TypeScript compiler cannot verify keys exist, leading to
|
|
182
|
-
// undefined value bugs at runtime.
|
|
183
|
-
// EXAMPLE:
|
|
184
|
-
// WRONG:
|
|
185
|
-
// app.use(async (c, next) => {
|
|
186
|
-
// c.set('user', user); // no type checking on 'user' key
|
|
187
|
-
// });
|
|
188
|
-
// RIGHT:
|
|
189
|
-
// type Variables = { user: User };
|
|
190
|
-
// const app = new Hono<{ Variables: Variables }>();
|
|
191
|
-
// app.use(async (c, next) => { c.set('user', user); });
|
|
192
|
-
// ─────────────────────────────────────────
|
|
193
|
-
{
|
|
194
|
-
id: 'hono-type-context-variables',
|
|
195
|
-
label: 'Type context Variables for c.get() / c.set()',
|
|
196
|
-
description:
|
|
197
|
-
'Declare a typed Variables interface and pass it as a generic to new Hono<{ Variables: Variables }>(). This enables TypeScript to validate context variable keys and values.',
|
|
198
|
-
severity: 'warning',
|
|
199
|
-
fileExtensions: ['ts'],
|
|
200
|
-
pattern: null,
|
|
201
|
-
customCheck: (file) => {
|
|
202
|
-
const hasContextSet = /c\.set\s*\(/.test(file.content);
|
|
203
|
-
const hasHonoGeneric = /new\s+Hono\s*</.test(file.content);
|
|
204
|
-
const hasVariablesType = /Variables\s*=\s*\{/.test(file.content);
|
|
205
|
-
|
|
206
|
-
if (hasContextSet && !hasHonoGeneric && !hasVariablesType) {
|
|
207
|
-
return [
|
|
208
|
-
{
|
|
209
|
-
line: null,
|
|
210
|
-
message:
|
|
211
|
-
'c.set() is used without typed Variables. Define: type Variables = { ... } and use new Hono<{ Variables: Variables }>().',
|
|
212
|
-
},
|
|
213
|
-
];
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return [];
|
|
217
|
-
},
|
|
218
|
-
applicableTo: ['hono'],
|
|
219
|
-
category: 'Type Safety',
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
// ── Environment Access ────────────────────────────────────────────────────
|
|
223
|
-
|
|
224
|
-
// ─────────────────────────────────────────
|
|
225
|
-
// RULE: hono-use-c-env
|
|
226
|
-
// ROLE: Enforce correct env access on edge runtimes
|
|
227
|
-
// PURPOSE: On Cloudflare Workers and similar runtimes, process.env is
|
|
228
|
-
// unavailable. Environment bindings are accessed via c.env.
|
|
229
|
-
// Even on Node.js, centralising env access via c.env makes
|
|
230
|
-
// the app portable across runtimes.
|
|
231
|
-
// EXAMPLE:
|
|
232
|
-
// WRONG:
|
|
233
|
-
// const secret = process.env['JWT_SECRET'];
|
|
234
|
-
// RIGHT:
|
|
235
|
-
// // In Hono handler:
|
|
236
|
-
// const secret = c.env.JWT_SECRET;
|
|
237
|
-
// ─────────────────────────────────────────
|
|
238
|
-
{
|
|
239
|
-
id: 'hono-use-c-env',
|
|
240
|
-
label: 'Use c.env for environment variables (edge-compatible)',
|
|
241
|
-
description:
|
|
242
|
-
'Prefer c.env over process.env for environment variables. process.env is not available in Cloudflare Workers or Deno and makes apps runtime-specific.',
|
|
243
|
-
severity: 'warning',
|
|
244
|
-
fileExtensions: ['ts'],
|
|
245
|
-
pattern: null,
|
|
246
|
-
customCheck: (file) => {
|
|
247
|
-
const violations: Array<{ line: number | null; message: string }> = [];
|
|
248
|
-
|
|
249
|
-
if (
|
|
250
|
-
!file.relativePath.includes('/routes/') &&
|
|
251
|
-
!file.relativePath.includes('/handlers/') &&
|
|
252
|
-
!file.relativePath.endsWith('.route.ts') &&
|
|
253
|
-
!file.relativePath.endsWith('.handler.ts') &&
|
|
254
|
-
!file.relativePath.endsWith('.middleware.ts')
|
|
255
|
-
) {
|
|
256
|
-
return [];
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
for (let i = 0; i < file.lines.length; i++) {
|
|
260
|
-
if (/process\.env\b/.test(file.lines[i])) {
|
|
261
|
-
violations.push({
|
|
262
|
-
line: i + 1,
|
|
263
|
-
message:
|
|
264
|
-
'process.env used in Hono handler/route. Use c.env.VARIABLE_NAME for edge-runtime portability.',
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return violations;
|
|
270
|
-
},
|
|
271
|
-
applicableTo: ['hono'],
|
|
272
|
-
category: 'Security',
|
|
273
|
-
},
|
|
274
|
-
|
|
275
|
-
// ── Route Organisation ────────────────────────────────────────────────────
|
|
276
|
-
|
|
277
|
-
// ─────────────────────────────────────────
|
|
278
|
-
// RULE: hono-use-sub-apps
|
|
279
|
-
// ROLE: Enforce composable route architecture
|
|
280
|
-
// PURPOSE: Defining all routes on a single root Hono instance leads to a
|
|
281
|
-
// monolithic file. Sub-apps (separate Hono instances per domain)
|
|
282
|
-
// composed via app.route() enable feature isolation and per-domain
|
|
283
|
-
// middleware application.
|
|
284
|
-
// EXAMPLE:
|
|
285
|
-
// WRONG:
|
|
286
|
-
// app.get('/users', ...)
|
|
287
|
-
// app.post('/users', ...)
|
|
288
|
-
// app.get('/products', ...) // all in one file
|
|
289
|
-
// RIGHT:
|
|
290
|
-
// // users.route.ts
|
|
291
|
-
// const users = new Hono();
|
|
292
|
-
// users.get('/', ...)
|
|
293
|
-
// export default users;
|
|
294
|
-
// // app.ts
|
|
295
|
-
// app.route('/users', users);
|
|
296
|
-
// ─────────────────────────────────────────
|
|
297
|
-
{
|
|
298
|
-
id: 'hono-use-sub-apps',
|
|
299
|
-
label: 'Organise routes as Hono sub-apps using app.route()',
|
|
300
|
-
description:
|
|
301
|
-
'Define each domain\'s routes in a separate Hono sub-app and compose them via app.route("/prefix", subApp). Avoid putting all routes on a single root instance.',
|
|
302
|
-
severity: 'info',
|
|
303
|
-
fileExtensions: ['ts'],
|
|
304
|
-
pattern: null,
|
|
305
|
-
customCheck: (file) => {
|
|
306
|
-
if (!file.relativePath.endsWith('index.ts') && !file.relativePath.endsWith('app.ts')) {
|
|
307
|
-
return [];
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const routeCount = (file.content.match(/app\.\s*(?:get|post|put|patch|delete)\s*\(/g) || []).length;
|
|
311
|
-
|
|
312
|
-
if (routeCount > 5) {
|
|
313
|
-
return [
|
|
314
|
-
{
|
|
315
|
-
line: null,
|
|
316
|
-
message: `${routeCount} routes defined on a single Hono instance. Extract into domain sub-apps and use app.route('/prefix', subApp).`,
|
|
317
|
-
},
|
|
318
|
-
];
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return [];
|
|
322
|
-
},
|
|
323
|
-
applicableTo: ['hono'],
|
|
324
|
-
category: 'Architecture',
|
|
325
|
-
},
|
|
326
|
-
];
|
|
327
|
-
|
|
328
|
-
// Register all Hono-specific rules
|
|
329
|
-
registerRules('hono', honoRules);
|
|
330
|
-
|
|
331
|
-
export { honoRules };
|