@empline/preflight 1.1.58 → 1.1.59

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 (32) hide show
  1. package/dist/checks/accessibility/accessibility-validation.d.ts.map +1 -1
  2. package/dist/checks/accessibility/accessibility-validation.js +131 -14
  3. package/dist/checks/accessibility/accessibility-validation.js.map +1 -1
  4. package/dist/checks/accessibility/wcag-advanced-validation.d.ts +10 -0
  5. package/dist/checks/accessibility/wcag-advanced-validation.d.ts.map +1 -0
  6. package/dist/checks/accessibility/wcag-advanced-validation.js +622 -0
  7. package/dist/checks/accessibility/wcag-advanced-validation.js.map +1 -0
  8. package/dist/checks/database/query-performance-validation.d.ts +10 -0
  9. package/dist/checks/database/query-performance-validation.d.ts.map +1 -0
  10. package/dist/checks/database/query-performance-validation.js +544 -0
  11. package/dist/checks/database/query-performance-validation.js.map +1 -0
  12. package/dist/checks/react/react-patterns-validation.d.ts +10 -0
  13. package/dist/checks/react/react-patterns-validation.d.ts.map +1 -0
  14. package/dist/checks/react/react-patterns-validation.js +559 -0
  15. package/dist/checks/react/react-patterns-validation.js.map +1 -0
  16. package/dist/checks/security/security-headers-validation.d.ts +10 -0
  17. package/dist/checks/security/security-headers-validation.d.ts.map +1 -0
  18. package/dist/checks/security/security-headers-validation.js +594 -0
  19. package/dist/checks/security/security-headers-validation.js.map +1 -0
  20. package/dist/reporters/github-reporter.d.ts +35 -0
  21. package/dist/reporters/github-reporter.d.ts.map +1 -0
  22. package/dist/reporters/github-reporter.js +397 -0
  23. package/dist/reporters/github-reporter.js.map +1 -0
  24. package/dist/reporters/html-report.d.ts +12 -0
  25. package/dist/reporters/html-report.d.ts.map +1 -0
  26. package/dist/reporters/html-report.js +469 -0
  27. package/dist/reporters/html-report.js.map +1 -0
  28. package/dist/reporters/index.d.ts +8 -0
  29. package/dist/reporters/index.d.ts.map +1 -0
  30. package/dist/reporters/index.js +18 -0
  31. package/dist/reporters/index.js.map +1 -0
  32. package/package.json +1 -1
@@ -0,0 +1,559 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
38
+ exports.run = run;
39
+ /**
40
+ * React Patterns Validation Preflight (BLOCKING)
41
+ *
42
+ * Validates advanced React patterns and best practices:
43
+ *
44
+ * 1. Server Components:
45
+ * - Server components don't use client-only APIs
46
+ * - "use client" directive placement
47
+ * - Proper data fetching patterns
48
+ *
49
+ * 2. Suspense & Error Boundaries:
50
+ * - Async components wrapped in Suspense
51
+ * - Error boundaries for lazy-loaded components
52
+ * - Loading states for async operations
53
+ *
54
+ * 3. Hooks Best Practices:
55
+ * - useCallback/useMemo dependencies complete
56
+ * - useEffect cleanup for subscriptions
57
+ * - Custom hooks use "use" prefix
58
+ * - No hooks in conditionals/loops
59
+ *
60
+ * 4. State Management:
61
+ * - Context value stability
62
+ * - Avoid prop drilling anti-patterns
63
+ * - State updates during render
64
+ *
65
+ * 5. Performance Patterns:
66
+ * - Key prop stability in lists
67
+ * - Avoid inline object/function creation in JSX
68
+ * - Memoization where beneficial
69
+ */
70
+ const fs = __importStar(require("node:fs"));
71
+ const path = __importStar(require("node:path"));
72
+ const glob_1 = require("glob");
73
+ const console_chars_1 = require("../../utils/console-chars");
74
+ exports.id = "react/react-patterns-validation";
75
+ exports.name = "React Patterns Validation";
76
+ exports.description = "Validates React patterns, hooks, Server Components, and performance best practices";
77
+ exports.category = "react";
78
+ exports.blocking = true;
79
+ exports.tags = ["react", "hooks", "server-components", "suspense", "performance"];
80
+ function getLineNumber(content, index) {
81
+ return content.substring(0, index).split("\n").length;
82
+ }
83
+ async function checkServerComponents() {
84
+ const issues = [];
85
+ const files = await (0, glob_1.glob)([
86
+ "app/**/*.tsx",
87
+ "app/**/*.ts",
88
+ ], {
89
+ cwd: process.cwd(),
90
+ ignore: ["**/node_modules/**", "**/*.test.tsx", "**/*.spec.tsx"],
91
+ absolute: true,
92
+ });
93
+ // Client-only APIs that shouldn't be in server components
94
+ const clientOnlyPatterns = [
95
+ { pattern: /\buseState\s*\(/, name: "useState" },
96
+ { pattern: /\buseEffect\s*\(/, name: "useEffect" },
97
+ { pattern: /\buseRef\s*\(/, name: "useRef" },
98
+ { pattern: /\buseReducer\s*\(/, name: "useReducer" },
99
+ { pattern: /\buseLayoutEffect\s*\(/, name: "useLayoutEffect" },
100
+ { pattern: /\bwindow\b\./, name: "window" },
101
+ { pattern: /\bdocument\b\./, name: "document" },
102
+ { pattern: /\blocalStorage\b\./, name: "localStorage" },
103
+ { pattern: /\bsessionStorage\b\./, name: "sessionStorage" },
104
+ { pattern: /\baddEventListener\s*\(/, name: "addEventListener" },
105
+ ];
106
+ for (const file of files) {
107
+ if (!fs.existsSync(file))
108
+ continue;
109
+ const content = fs.readFileSync(file, "utf-8");
110
+ const relativePath = path.relative(process.cwd(), file);
111
+ // Skip if it's a client component
112
+ const isClientComponent = /^["']use client["']/m.test(content);
113
+ if (isClientComponent)
114
+ continue;
115
+ // Skip files that are clearly server-side (API routes, server actions)
116
+ if (relativePath.includes("/api/") || content.includes("use server"))
117
+ continue;
118
+ // Check for client-only patterns
119
+ for (const { pattern, name } of clientOnlyPatterns) {
120
+ let match;
121
+ const regex = new RegExp(pattern.source, "g");
122
+ while ((match = regex.exec(content)) !== null) {
123
+ // Skip if it's in a comment
124
+ const lineStart = content.lastIndexOf("\n", match.index) + 1;
125
+ const line = content.substring(lineStart, match.index);
126
+ if (line.includes("//") || line.includes("/*"))
127
+ continue;
128
+ issues.push({
129
+ rule: "server-component-client-api",
130
+ message: `Server component uses client-only API: ${name}`,
131
+ file: relativePath,
132
+ line: getLineNumber(content, match.index),
133
+ severity: "error",
134
+ suggestion: `Add "use client" directive or move this code to a client component`,
135
+ });
136
+ }
137
+ }
138
+ }
139
+ return issues;
140
+ }
141
+ async function checkSuspenseAndBoundaries() {
142
+ const issues = [];
143
+ const files = await (0, glob_1.glob)([
144
+ "app/**/*.tsx",
145
+ "components/**/*.tsx",
146
+ "src/**/*.tsx",
147
+ ], {
148
+ cwd: process.cwd(),
149
+ ignore: ["**/node_modules/**", "**/*.test.tsx", "**/*.spec.tsx"],
150
+ absolute: true,
151
+ });
152
+ for (const file of files) {
153
+ if (!fs.existsSync(file))
154
+ continue;
155
+ const content = fs.readFileSync(file, "utf-8");
156
+ const relativePath = path.relative(process.cwd(), file);
157
+ // Check for React.lazy without Suspense
158
+ const lazyRegex = /React\.lazy\s*\(|lazy\s*\(\s*\(\)/g;
159
+ if (lazyRegex.test(content)) {
160
+ const hasSuspense = /<Suspense/i.test(content);
161
+ if (!hasSuspense) {
162
+ issues.push({
163
+ rule: "lazy-needs-suspense",
164
+ message: "React.lazy used without Suspense boundary in file",
165
+ file: relativePath,
166
+ severity: "warning",
167
+ suggestion: "Wrap lazy-loaded components in <Suspense fallback={...}>",
168
+ });
169
+ }
170
+ }
171
+ // Check for dynamic imports in Next.js without loading state
172
+ const dynamicRegex = /dynamic\s*\(\s*\(\)\s*=>\s*import/g;
173
+ let match;
174
+ while ((match = dynamicRegex.exec(content)) !== null) {
175
+ // Check for loading option
176
+ const surroundingCode = content.substring(match.index, match.index + 200);
177
+ const hasLoadingOption = /loading\s*:/.test(surroundingCode);
178
+ if (!hasLoadingOption) {
179
+ issues.push({
180
+ rule: "dynamic-loading-state",
181
+ message: "next/dynamic without loading option",
182
+ file: relativePath,
183
+ line: getLineNumber(content, match.index),
184
+ severity: "info",
185
+ suggestion: "Add loading: () => <Loading /> option for better UX",
186
+ });
187
+ }
188
+ }
189
+ // Check for async components without error handling
190
+ const asyncComponentRegex = /export\s+(?:default\s+)?async\s+function\s+(\w+)/g;
191
+ while ((match = asyncComponentRegex.exec(content)) !== null) {
192
+ const componentName = match[1];
193
+ // Check if there's an error.tsx in the same directory for pages
194
+ if (relativePath.includes("app/") && relativePath.includes("page.tsx")) {
195
+ const dir = path.dirname(file);
196
+ const errorFile = path.join(dir, "error.tsx");
197
+ if (!fs.existsSync(errorFile)) {
198
+ issues.push({
199
+ rule: "async-component-error-boundary",
200
+ message: `Async page component ${componentName} has no error.tsx in same directory`,
201
+ file: relativePath,
202
+ line: getLineNumber(content, match.index),
203
+ severity: "info",
204
+ suggestion: "Create error.tsx to handle component errors gracefully",
205
+ });
206
+ }
207
+ }
208
+ }
209
+ }
210
+ return issues;
211
+ }
212
+ async function checkHooksPatterns() {
213
+ const issues = [];
214
+ const files = await (0, glob_1.glob)([
215
+ "app/**/*.tsx",
216
+ "components/**/*.tsx",
217
+ "src/**/*.tsx",
218
+ "hooks/**/*.ts",
219
+ "lib/**/*.ts",
220
+ ], {
221
+ cwd: process.cwd(),
222
+ ignore: ["**/node_modules/**", "**/*.test.tsx", "**/*.spec.tsx"],
223
+ absolute: true,
224
+ });
225
+ for (const file of files) {
226
+ if (!fs.existsSync(file))
227
+ continue;
228
+ const content = fs.readFileSync(file, "utf-8");
229
+ const relativePath = path.relative(process.cwd(), file);
230
+ // Check for hooks in conditionals
231
+ const hookInConditionalRegex = /if\s*\([^)]*\)\s*\{[^}]*\b(use\w+)\s*\(/g;
232
+ let match;
233
+ while ((match = hookInConditionalRegex.exec(content)) !== null) {
234
+ issues.push({
235
+ rule: "hooks-no-conditional",
236
+ message: `Hook ${match[1]} called inside conditional`,
237
+ file: relativePath,
238
+ line: getLineNumber(content, match.index),
239
+ severity: "error",
240
+ suggestion: "Move hook call to top level of component",
241
+ });
242
+ }
243
+ // Check for hooks in loops
244
+ const hookInLoopRegex = /(?:for|while)\s*\([^)]*\)\s*\{[^}]*\b(use\w+)\s*\(/g;
245
+ while ((match = hookInLoopRegex.exec(content)) !== null) {
246
+ issues.push({
247
+ rule: "hooks-no-loop",
248
+ message: `Hook ${match[1]} called inside loop`,
249
+ file: relativePath,
250
+ line: getLineNumber(content, match.index),
251
+ severity: "error",
252
+ suggestion: "Hooks must be called at top level, not in loops",
253
+ });
254
+ }
255
+ // Check for useEffect without cleanup for subscriptions
256
+ const useEffectWithSubscription = /useEffect\s*\(\s*\(\)\s*=>\s*\{[^}]*(?:subscribe|addEventListener|setInterval|setTimeout)[^}]*\}/g;
257
+ while ((match = useEffectWithSubscription.exec(content)) !== null) {
258
+ const effectContent = match[0];
259
+ const hasCleanup = /return\s*\(\s*\)\s*=>/.test(effectContent) ||
260
+ /return\s+\(\s*\)\s*=>/.test(effectContent) ||
261
+ /return\s*function/.test(effectContent);
262
+ if (!hasCleanup) {
263
+ issues.push({
264
+ rule: "useeffect-cleanup",
265
+ message: "useEffect with subscription/timer missing cleanup",
266
+ file: relativePath,
267
+ line: getLineNumber(content, match.index),
268
+ severity: "warning",
269
+ suggestion: "Return cleanup function to unsubscribe/clear timer",
270
+ });
271
+ }
272
+ }
273
+ // Check for custom hooks not following naming convention
274
+ const customHookRegex = /export\s+(?:const|function)\s+(\w+)\s*(?:=|:|\()/g;
275
+ while ((match = customHookRegex.exec(content)) !== null) {
276
+ const funcName = match[1];
277
+ // If file is in hooks folder or function uses hooks but doesn't start with "use"
278
+ const isInHooksFolder = relativePath.includes("/hooks/") || relativePath.includes("\\hooks\\");
279
+ const usesHooks = /\buse(?:State|Effect|Ref|Callback|Memo|Context|Reducer)\s*\(/.test(content.substring(match.index, match.index + 500));
280
+ if ((isInHooksFolder || usesHooks) && !funcName.startsWith("use") && funcName !== "default") {
281
+ // Skip if it's clearly a component (returns JSX)
282
+ const functionBody = content.substring(match.index, match.index + 1000);
283
+ const isComponent = /<\w+|return\s*\(?\s*</.test(functionBody);
284
+ if (!isComponent && usesHooks) {
285
+ issues.push({
286
+ rule: "custom-hook-naming",
287
+ message: `Function "${funcName}" uses hooks but doesn't start with "use"`,
288
+ file: relativePath,
289
+ line: getLineNumber(content, match.index),
290
+ severity: "warning",
291
+ suggestion: `Rename to "use${funcName.charAt(0).toUpperCase() + funcName.slice(1)}"`,
292
+ });
293
+ }
294
+ }
295
+ }
296
+ // Check for missing dependencies in useEffect/useCallback/useMemo
297
+ // This is a simplified check - full check requires AST parsing
298
+ const emptyDepsRegex = /(useEffect|useCallback|useMemo)\s*\([^,]+,\s*\[\s*\]\s*\)/g;
299
+ while ((match = emptyDepsRegex.exec(content)) !== null) {
300
+ const hookName = match[1];
301
+ const hookContent = match[0];
302
+ // Check if the callback uses variables that might need to be dependencies
303
+ const callbackMatch = hookContent.match(/\(\)\s*=>\s*\{([^}]+)\}/);
304
+ if (callbackMatch) {
305
+ const callback = callbackMatch[1];
306
+ // Look for common patterns that suggest missing dependencies
307
+ const usesExternalVars = /\b(props\.|state\.|count|value|data|user|id)\b/.test(callback);
308
+ if (usesExternalVars) {
309
+ issues.push({
310
+ rule: "hook-deps-check",
311
+ message: `${hookName} with empty deps array may have missing dependencies`,
312
+ file: relativePath,
313
+ line: getLineNumber(content, match.index),
314
+ severity: "info",
315
+ suggestion: "Review dependency array - variables used inside may need to be included",
316
+ });
317
+ }
318
+ }
319
+ }
320
+ }
321
+ return issues;
322
+ }
323
+ async function checkContextPatterns() {
324
+ const issues = [];
325
+ const files = await (0, glob_1.glob)([
326
+ "app/**/*.tsx",
327
+ "components/**/*.tsx",
328
+ "contexts/**/*.tsx",
329
+ "providers/**/*.tsx",
330
+ "src/**/*.tsx",
331
+ ], {
332
+ cwd: process.cwd(),
333
+ ignore: ["**/node_modules/**", "**/*.test.tsx", "**/*.spec.tsx"],
334
+ absolute: true,
335
+ });
336
+ for (const file of files) {
337
+ if (!fs.existsSync(file))
338
+ continue;
339
+ const content = fs.readFileSync(file, "utf-8");
340
+ const relativePath = path.relative(process.cwd(), file);
341
+ // Check for inline object creation in context value
342
+ const contextValueRegex = /<(\w+Context)\.Provider\s+value\s*=\s*\{\s*\{/g;
343
+ let match;
344
+ while ((match = contextValueRegex.exec(content)) !== null) {
345
+ // Check if it's using useMemo
346
+ const surroundingCode = content.substring(Math.max(0, match.index - 500), match.index);
347
+ const hasMemo = /useMemo\s*\([^)]*\)\s*$/.test(surroundingCode.trim());
348
+ if (!hasMemo) {
349
+ issues.push({
350
+ rule: "context-value-stability",
351
+ message: `${match[1]} value is created inline (new object each render)`,
352
+ file: relativePath,
353
+ line: getLineNumber(content, match.index),
354
+ severity: "warning",
355
+ suggestion: "Use useMemo to memoize context value object",
356
+ });
357
+ }
358
+ }
359
+ }
360
+ return issues;
361
+ }
362
+ async function checkKeyPropPatterns() {
363
+ const issues = [];
364
+ const files = await (0, glob_1.glob)([
365
+ "app/**/*.tsx",
366
+ "components/**/*.tsx",
367
+ "src/**/*.tsx",
368
+ ], {
369
+ cwd: process.cwd(),
370
+ ignore: ["**/node_modules/**", "**/*.test.tsx", "**/*.spec.tsx"],
371
+ absolute: true,
372
+ });
373
+ for (const file of files) {
374
+ if (!fs.existsSync(file))
375
+ continue;
376
+ const content = fs.readFileSync(file, "utf-8");
377
+ const relativePath = path.relative(process.cwd(), file);
378
+ // Check for index as key in maps
379
+ const indexAsKeyRegex = /\.map\s*\([^)]*,\s*(\w+)\s*\)[^{]*key\s*=\s*\{\s*\1\s*\}/g;
380
+ let match;
381
+ while ((match = indexAsKeyRegex.exec(content)) !== null) {
382
+ issues.push({
383
+ rule: "key-no-index",
384
+ message: "Using array index as key prop",
385
+ file: relativePath,
386
+ line: getLineNumber(content, match.index),
387
+ severity: "warning",
388
+ suggestion: "Use unique stable identifier instead of index for key",
389
+ });
390
+ }
391
+ // Alternative pattern: key={i} or key={index}
392
+ const indexKeyPatterns = /\.map\s*\(\s*\([^,)]*,\s*(i|index|idx)\s*\)[^}]*key\s*=\s*\{\s*\1\s*\}/g;
393
+ while ((match = indexKeyPatterns.exec(content)) !== null) {
394
+ issues.push({
395
+ rule: "key-no-index",
396
+ message: "Using array index as key prop",
397
+ file: relativePath,
398
+ line: getLineNumber(content, match.index),
399
+ severity: "warning",
400
+ suggestion: "Use unique stable identifier (e.g., item.id) for key",
401
+ });
402
+ }
403
+ // Check for Math.random() or Date.now() as key
404
+ const unstableKeyRegex = /key\s*=\s*\{\s*(?:Math\.random\s*\(\)|Date\.now\s*\(\)|crypto\.randomUUID\s*\(\))/g;
405
+ while ((match = unstableKeyRegex.exec(content)) !== null) {
406
+ issues.push({
407
+ rule: "key-no-random",
408
+ message: "Using random/timestamp as key causes remounts",
409
+ file: relativePath,
410
+ line: getLineNumber(content, match.index),
411
+ severity: "error",
412
+ suggestion: "Use stable unique identifier from data",
413
+ });
414
+ }
415
+ }
416
+ return issues;
417
+ }
418
+ async function checkPerformancePatterns() {
419
+ const issues = [];
420
+ const files = await (0, glob_1.glob)([
421
+ "app/**/*.tsx",
422
+ "components/**/*.tsx",
423
+ "src/**/*.tsx",
424
+ ], {
425
+ cwd: process.cwd(),
426
+ ignore: ["**/node_modules/**", "**/*.test.tsx", "**/*.spec.tsx"],
427
+ absolute: true,
428
+ });
429
+ for (const file of files) {
430
+ if (!fs.existsSync(file))
431
+ continue;
432
+ const content = fs.readFileSync(file, "utf-8");
433
+ const relativePath = path.relative(process.cwd(), file);
434
+ // Check for inline function in JSX props (common perf issue)
435
+ // Only flag if not onClick/onChange (event handlers are often fine inline)
436
+ const inlineFunctionRegex = /\b(?!onClick|onChange|onSubmit|onBlur|onFocus|onKeyDown|onKeyUp|onMouseEnter|onMouseLeave)(\w+)\s*=\s*\{\s*\(\s*\)\s*=>/g;
437
+ let match;
438
+ let inlineCount = 0;
439
+ while ((match = inlineFunctionRegex.exec(content)) !== null) {
440
+ inlineCount++;
441
+ }
442
+ if (inlineCount > 10) {
443
+ issues.push({
444
+ rule: "inline-function-props",
445
+ message: `${inlineCount} inline arrow functions in props (may cause re-renders)`,
446
+ file: relativePath,
447
+ severity: "info",
448
+ suggestion: "Consider useCallback for frequently re-rendered components",
449
+ });
450
+ }
451
+ // Check for inline object creation in props
452
+ const inlineObjectRegex = /\b(?!style|className)(\w+)\s*=\s*\{\s*\{\s*\w+\s*:/g;
453
+ let objectCount = 0;
454
+ while ((match = inlineObjectRegex.exec(content)) !== null) {
455
+ objectCount++;
456
+ }
457
+ if (objectCount > 10) {
458
+ issues.push({
459
+ rule: "inline-object-props",
460
+ message: `${objectCount} inline objects in props (may cause re-renders)`,
461
+ file: relativePath,
462
+ severity: "info",
463
+ suggestion: "Consider useMemo or extracting to constants",
464
+ });
465
+ }
466
+ }
467
+ return issues;
468
+ }
469
+ async function run() {
470
+ const startTime = Date.now();
471
+ const allIssues = [];
472
+ // Run all React pattern checks
473
+ allIssues.push(...await checkServerComponents());
474
+ allIssues.push(...await checkSuspenseAndBoundaries());
475
+ allIssues.push(...await checkHooksPatterns());
476
+ allIssues.push(...await checkContextPatterns());
477
+ allIssues.push(...await checkKeyPropPatterns());
478
+ allIssues.push(...await checkPerformancePatterns());
479
+ // Convert to findings
480
+ const findings = allIssues.map(issue => ({
481
+ level: issue.severity,
482
+ message: issue.message,
483
+ file: issue.file,
484
+ startLine: issue.line,
485
+ ruleId: issue.rule,
486
+ suggestion: issue.suggestion,
487
+ }));
488
+ const errors = findings.filter(f => f.level === "error");
489
+ const warnings = findings.filter(f => f.level === "warning");
490
+ const infos = findings.filter(f => f.level === "info");
491
+ return {
492
+ passed: errors.length === 0,
493
+ findings,
494
+ duration: Date.now() - startTime,
495
+ metadata: {
496
+ errors: errors.length,
497
+ warnings: warnings.length,
498
+ infos: infos.length,
499
+ },
500
+ };
501
+ }
502
+ async function main() {
503
+ console.log(`\n${console_chars_1.emoji.components} REACT PATTERNS VALIDATION`);
504
+ console.log((0, console_chars_1.createDivider)(65, "heavy"));
505
+ const result = await run();
506
+ const { errors, warnings, infos } = result.metadata || {};
507
+ console.log(`\n${console_chars_1.emoji.search} Checking React patterns...`);
508
+ console.log(`\n${console_chars_1.emoji.chart} Summary:`);
509
+ console.log(` Errors: ${errors}`);
510
+ console.log(` Warnings: ${warnings}`);
511
+ console.log(` Info: ${infos}`);
512
+ if (result.passed && warnings === 0) {
513
+ console.log(`\n${console_chars_1.emoji.success} REACT PATTERNS VALIDATION PASSED`);
514
+ console.log(`\nAll React best practices are followed.`);
515
+ process.exit(0);
516
+ }
517
+ // Print findings by category
518
+ const errorFindings = result.findings.filter(f => f.level === "error");
519
+ if (errorFindings.length > 0) {
520
+ console.log(`\n${console_chars_1.emoji.error} Errors (blocking):`);
521
+ for (const finding of errorFindings) {
522
+ console.log(`\n ${finding.file}${finding.startLine ? `:${finding.startLine}` : ""}`);
523
+ console.log(` ${finding.message}`);
524
+ if (finding.suggestion) {
525
+ console.log(` ${console_chars_1.emoji.hint} ${finding.suggestion}`);
526
+ }
527
+ }
528
+ }
529
+ const warningFindings = result.findings.filter(f => f.level === "warning");
530
+ if (warningFindings.length > 0) {
531
+ console.log(`\n${console_chars_1.emoji.warning} Warnings:`);
532
+ for (const finding of warningFindings.slice(0, 10)) {
533
+ console.log(`\n ${finding.file}${finding.startLine ? `:${finding.startLine}` : ""}`);
534
+ console.log(` ${finding.message}`);
535
+ }
536
+ if (warningFindings.length > 10) {
537
+ console.log(`\n ... and ${warningFindings.length - 10} more warnings`);
538
+ }
539
+ }
540
+ console.log(`\n${console_chars_1.emoji.info} React Best Practices:`);
541
+ console.log(` - Server components must not use client APIs`);
542
+ console.log(` - Lazy-loaded components need Suspense`);
543
+ console.log(` - Hooks called at top level only`);
544
+ console.log(` - useEffect cleanup for subscriptions`);
545
+ console.log(` - Stable keys for list items`);
546
+ if (!result.passed) {
547
+ console.log(`\n${console_chars_1.emoji.error} REACT PATTERNS VALIDATION FAILED`);
548
+ process.exit(1);
549
+ }
550
+ console.log(`\n${console_chars_1.emoji.success} REACT PATTERNS VALIDATION PASSED`);
551
+ process.exit(0);
552
+ }
553
+ if (require.main === module) {
554
+ main().catch((err) => {
555
+ console.error(`${console_chars_1.emoji.error} Preflight failed:`, err);
556
+ process.exit(1);
557
+ });
558
+ }
559
+ //# sourceMappingURL=react-patterns-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-patterns-validation.js","sourceRoot":"","sources":["../../../src/checks/react/react-patterns-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { PreflightCheckResult } from "../../core/types";
3
+ export declare const id = "security/security-headers-validation";
4
+ export declare const name = "Security Headers Validation";
5
+ export declare const description = "Validates security headers, cookies, SRI, CORS, and OWASP best practices";
6
+ export declare const category = "security";
7
+ export declare const blocking = true;
8
+ export declare const tags: string[];
9
+ export declare function run(): Promise<PreflightCheckResult>;
10
+ //# sourceMappingURL=security-headers-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-headers-validation.d.ts","sourceRoot":"","sources":["../../../src/checks/security/security-headers-validation.ts"],"names":[],"mappings":";AAkCA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAG1E,eAAO,MAAM,EAAE,yCAAyC,CAAC;AACzD,eAAO,MAAM,IAAI,gCAAgC,CAAC;AAClD,eAAO,MAAM,WAAW,6EAA6E,CAAC;AACtG,eAAO,MAAM,QAAQ,aAAa,CAAC;AACnC,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAA6D,CAAC;AAye/E,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAuCzD"}