@empline/preflight 1.1.56 → 1.1.58
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/dist/checks/accessibility/accessibility-validation.d.ts +10 -0
- package/dist/checks/accessibility/accessibility-validation.d.ts.map +1 -0
- package/dist/checks/accessibility/accessibility-validation.js +538 -0
- package/dist/checks/accessibility/accessibility-validation.js.map +1 -0
- package/dist/checks/checkout/checkout-flow-validation.d.ts +10 -0
- package/dist/checks/checkout/checkout-flow-validation.d.ts.map +1 -0
- package/dist/checks/checkout/checkout-flow-validation.js +473 -0
- package/dist/checks/checkout/checkout-flow-validation.js.map +1 -0
- package/dist/checks/database/enum-sync-validation.d.ts +10 -0
- package/dist/checks/database/enum-sync-validation.d.ts.map +1 -0
- package/dist/checks/database/enum-sync-validation.js +409 -0
- package/dist/checks/database/enum-sync-validation.js.map +1 -0
- package/dist/checks/email/email-validation.d.ts +10 -0
- package/dist/checks/email/email-validation.d.ts.map +1 -0
- package/dist/checks/email/email-validation.js +456 -0
- package/dist/checks/email/email-validation.js.map +1 -0
- package/dist/checks/observability/observability-validation.d.ts +10 -0
- package/dist/checks/observability/observability-validation.d.ts.map +1 -0
- package/dist/checks/observability/observability-validation.js +448 -0
- package/dist/checks/observability/observability-validation.js.map +1 -0
- package/dist/checks/seo/seo-validation.d.ts +10 -0
- package/dist/checks/seo/seo-validation.d.ts.map +1 -0
- package/dist/checks/seo/seo-validation.js +497 -0
- package/dist/checks/seo/seo-validation.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,448 @@
|
|
|
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
|
+
* Observability Validation Preflight (BLOCKING)
|
|
41
|
+
*
|
|
42
|
+
* Validates observability best practices for production-ready applications:
|
|
43
|
+
*
|
|
44
|
+
* 1. Error Boundaries:
|
|
45
|
+
* - App has global error boundary (app/error.tsx)
|
|
46
|
+
* - Critical routes have error boundaries
|
|
47
|
+
* - Error boundaries log to monitoring service
|
|
48
|
+
*
|
|
49
|
+
* 2. Error Handling:
|
|
50
|
+
* - API routes have try/catch with proper error responses
|
|
51
|
+
* - Server actions handle errors gracefully
|
|
52
|
+
* - No unhandled promise rejections
|
|
53
|
+
*
|
|
54
|
+
* 3. Logging:
|
|
55
|
+
* - Critical operations have logging
|
|
56
|
+
* - No console.log in production code (use proper logger)
|
|
57
|
+
* - Sensitive data not logged
|
|
58
|
+
*
|
|
59
|
+
* 4. Performance Tracking:
|
|
60
|
+
* - Web vitals tracking present
|
|
61
|
+
* - Database query performance monitoring
|
|
62
|
+
* - API response time tracking
|
|
63
|
+
*
|
|
64
|
+
* 5. Health Checks:
|
|
65
|
+
* - Health check endpoint exists
|
|
66
|
+
* - Database connectivity check
|
|
67
|
+
*/
|
|
68
|
+
const fs = __importStar(require("node:fs"));
|
|
69
|
+
const path = __importStar(require("node:path"));
|
|
70
|
+
const glob_1 = require("glob");
|
|
71
|
+
const console_chars_1 = require("../../utils/console-chars");
|
|
72
|
+
exports.id = "observability/observability-validation";
|
|
73
|
+
exports.name = "Observability Validation";
|
|
74
|
+
exports.description = "Validates error handling, logging, and monitoring best practices";
|
|
75
|
+
exports.category = "observability";
|
|
76
|
+
exports.blocking = true;
|
|
77
|
+
exports.tags = ["observability", "errors", "logging", "monitoring", "performance"];
|
|
78
|
+
function getLineNumber(content, index) {
|
|
79
|
+
return content.substring(0, index).split("\n").length;
|
|
80
|
+
}
|
|
81
|
+
async function checkErrorBoundaries() {
|
|
82
|
+
const issues = [];
|
|
83
|
+
const cwd = process.cwd();
|
|
84
|
+
// Check for global error boundary
|
|
85
|
+
const globalErrorPath = path.join(cwd, "app", "error.tsx");
|
|
86
|
+
if (!fs.existsSync(globalErrorPath)) {
|
|
87
|
+
issues.push({
|
|
88
|
+
rule: "global-error-boundary",
|
|
89
|
+
message: "Missing global error boundary (app/error.tsx)",
|
|
90
|
+
file: "app/error.tsx",
|
|
91
|
+
severity: "error",
|
|
92
|
+
suggestion: "Create app/error.tsx to handle uncaught errors gracefully",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// Check error boundary quality
|
|
97
|
+
const content = fs.readFileSync(globalErrorPath, "utf-8");
|
|
98
|
+
// Should be a client component
|
|
99
|
+
if (!content.includes('"use client"') && !content.includes("'use client'")) {
|
|
100
|
+
issues.push({
|
|
101
|
+
rule: "error-boundary-client",
|
|
102
|
+
message: "Error boundary should be a client component",
|
|
103
|
+
file: "app/error.tsx",
|
|
104
|
+
severity: "error",
|
|
105
|
+
suggestion: 'Add "use client" directive at the top',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// Should have reset functionality
|
|
109
|
+
if (!content.includes("reset")) {
|
|
110
|
+
issues.push({
|
|
111
|
+
rule: "error-boundary-reset",
|
|
112
|
+
message: "Error boundary missing reset functionality",
|
|
113
|
+
file: "app/error.tsx",
|
|
114
|
+
severity: "warning",
|
|
115
|
+
suggestion: "Add reset() call to allow users to retry",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// Should log errors (check for common logging patterns)
|
|
119
|
+
const hasLogging = /console\.error|logger\.|Sentry\.|captureException|reportError|logError/i.test(content);
|
|
120
|
+
if (!hasLogging) {
|
|
121
|
+
issues.push({
|
|
122
|
+
rule: "error-boundary-logging",
|
|
123
|
+
message: "Error boundary should log errors for monitoring",
|
|
124
|
+
file: "app/error.tsx",
|
|
125
|
+
severity: "warning",
|
|
126
|
+
suggestion: "Add error logging to capture errors in production",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Check for global-error.tsx (handles errors in root layout)
|
|
131
|
+
const globalGlobalErrorPath = path.join(cwd, "app", "global-error.tsx");
|
|
132
|
+
if (!fs.existsSync(globalGlobalErrorPath)) {
|
|
133
|
+
issues.push({
|
|
134
|
+
rule: "global-global-error",
|
|
135
|
+
message: "Missing app/global-error.tsx for root layout errors",
|
|
136
|
+
file: "app/global-error.tsx",
|
|
137
|
+
severity: "warning",
|
|
138
|
+
suggestion: "Create app/global-error.tsx to handle errors in the root layout",
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// Check for not-found.tsx
|
|
142
|
+
const notFoundPath = path.join(cwd, "app", "not-found.tsx");
|
|
143
|
+
if (!fs.existsSync(notFoundPath)) {
|
|
144
|
+
issues.push({
|
|
145
|
+
rule: "not-found-page",
|
|
146
|
+
message: "Missing custom 404 page (app/not-found.tsx)",
|
|
147
|
+
file: "app/not-found.tsx",
|
|
148
|
+
severity: "warning",
|
|
149
|
+
suggestion: "Create app/not-found.tsx for better user experience",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return issues;
|
|
153
|
+
}
|
|
154
|
+
async function checkApiErrorHandling() {
|
|
155
|
+
const issues = [];
|
|
156
|
+
const apiFiles = await (0, glob_1.glob)("app/api/**/route.ts", {
|
|
157
|
+
cwd: process.cwd(),
|
|
158
|
+
absolute: true,
|
|
159
|
+
});
|
|
160
|
+
for (const file of apiFiles) {
|
|
161
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
162
|
+
const relativePath = path.relative(process.cwd(), file);
|
|
163
|
+
// Check for try/catch in handler functions
|
|
164
|
+
const hasExportedHandlers = /export\s+(?:async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE)/g.test(content);
|
|
165
|
+
if (hasExportedHandlers) {
|
|
166
|
+
// Check if there's proper error handling
|
|
167
|
+
const hasTryCatch = /try\s*\{[\s\S]*?\}\s*catch/g.test(content);
|
|
168
|
+
const hasErrorResponse = /NextResponse\.json\s*\([^)]*(?:error|status:\s*[45]\d\d)/i.test(content) ||
|
|
169
|
+
/return\s+new\s+Response\s*\([^)]*(?:status:\s*[45]\d\d)/i.test(content);
|
|
170
|
+
if (!hasTryCatch && !hasErrorResponse) {
|
|
171
|
+
issues.push({
|
|
172
|
+
rule: "api-error-handling",
|
|
173
|
+
message: "API route missing error handling",
|
|
174
|
+
file: relativePath,
|
|
175
|
+
severity: "warning",
|
|
176
|
+
suggestion: "Add try/catch blocks and return proper error responses",
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
// Check for unhandled async operations
|
|
180
|
+
const hasAwaitWithoutTry = /(?<!try\s*\{[^}]*)\bawait\s+(?!.*catch)/m.test(content);
|
|
181
|
+
if (hasAwaitWithoutTry && !hasTryCatch) {
|
|
182
|
+
issues.push({
|
|
183
|
+
rule: "api-unhandled-async",
|
|
184
|
+
message: "API route has await without try/catch",
|
|
185
|
+
file: relativePath,
|
|
186
|
+
severity: "warning",
|
|
187
|
+
suggestion: "Wrap async operations in try/catch",
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return issues;
|
|
193
|
+
}
|
|
194
|
+
async function checkLoggingPractices() {
|
|
195
|
+
const issues = [];
|
|
196
|
+
const codeFiles = await (0, glob_1.glob)([
|
|
197
|
+
"app/**/*.ts",
|
|
198
|
+
"app/**/*.tsx",
|
|
199
|
+
"lib/**/*.ts",
|
|
200
|
+
], {
|
|
201
|
+
cwd: process.cwd(),
|
|
202
|
+
ignore: ["**/*.test.ts", "**/*.spec.ts", "**/node_modules/**"],
|
|
203
|
+
absolute: true,
|
|
204
|
+
});
|
|
205
|
+
let consoleLogCount = 0;
|
|
206
|
+
const consoleLogFiles = [];
|
|
207
|
+
for (const file of codeFiles) {
|
|
208
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
209
|
+
const relativePath = path.relative(process.cwd(), file);
|
|
210
|
+
// Check for console.log (should use proper logger in production)
|
|
211
|
+
const consoleLogRegex = /console\.log\s*\(/g;
|
|
212
|
+
let match;
|
|
213
|
+
while ((match = consoleLogRegex.exec(content)) !== null) {
|
|
214
|
+
// Skip if it's in a comment or preflight-ignore
|
|
215
|
+
const lineStart = content.lastIndexOf("\n", match.index) + 1;
|
|
216
|
+
const line = content.substring(lineStart, content.indexOf("\n", match.index));
|
|
217
|
+
if (line.includes("//") || line.includes("preflight-ignore"))
|
|
218
|
+
continue;
|
|
219
|
+
consoleLogCount++;
|
|
220
|
+
if (!consoleLogFiles.includes(relativePath)) {
|
|
221
|
+
consoleLogFiles.push(relativePath);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Check for logging sensitive data patterns
|
|
225
|
+
const sensitivePatterns = [
|
|
226
|
+
/console\.\w+\s*\([^)]*password/i,
|
|
227
|
+
/console\.\w+\s*\([^)]*secret/i,
|
|
228
|
+
/console\.\w+\s*\([^)]*token(?!Type)/i,
|
|
229
|
+
/console\.\w+\s*\([^)]*apiKey/i,
|
|
230
|
+
/logger\.\w+\s*\([^)]*password/i,
|
|
231
|
+
];
|
|
232
|
+
for (const pattern of sensitivePatterns) {
|
|
233
|
+
if (pattern.test(content)) {
|
|
234
|
+
issues.push({
|
|
235
|
+
rule: "sensitive-data-logging",
|
|
236
|
+
message: "Potential sensitive data in logs",
|
|
237
|
+
file: relativePath,
|
|
238
|
+
severity: "error",
|
|
239
|
+
suggestion: "Never log passwords, secrets, tokens, or API keys",
|
|
240
|
+
});
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Report console.log usage summary
|
|
246
|
+
if (consoleLogCount > 10) {
|
|
247
|
+
issues.push({
|
|
248
|
+
rule: "console-log-usage",
|
|
249
|
+
message: `Found ${consoleLogCount} console.log statements in ${consoleLogFiles.length} files`,
|
|
250
|
+
file: consoleLogFiles[0] || "multiple files",
|
|
251
|
+
severity: "warning",
|
|
252
|
+
suggestion: "Consider using a structured logger for production code",
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return issues;
|
|
256
|
+
}
|
|
257
|
+
async function checkHealthEndpoint() {
|
|
258
|
+
const issues = [];
|
|
259
|
+
const cwd = process.cwd();
|
|
260
|
+
// Check for health check endpoint
|
|
261
|
+
const healthPaths = [
|
|
262
|
+
path.join(cwd, "app", "api", "health", "route.ts"),
|
|
263
|
+
path.join(cwd, "app", "api", "healthz", "route.ts"),
|
|
264
|
+
path.join(cwd, "app", "api", "health-check", "route.ts"),
|
|
265
|
+
path.join(cwd, "pages", "api", "health.ts"),
|
|
266
|
+
];
|
|
267
|
+
const hasHealthEndpoint = healthPaths.some(p => fs.existsSync(p));
|
|
268
|
+
if (!hasHealthEndpoint) {
|
|
269
|
+
issues.push({
|
|
270
|
+
rule: "health-endpoint",
|
|
271
|
+
message: "Missing health check endpoint",
|
|
272
|
+
file: "app/api/health/route.ts",
|
|
273
|
+
severity: "warning",
|
|
274
|
+
suggestion: "Create a /api/health endpoint for monitoring and load balancers",
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// Check health endpoint quality
|
|
279
|
+
const healthPath = healthPaths.find(p => fs.existsSync(p));
|
|
280
|
+
if (healthPath) {
|
|
281
|
+
const content = fs.readFileSync(healthPath, "utf-8");
|
|
282
|
+
const relativePath = path.relative(cwd, healthPath);
|
|
283
|
+
// Should check database connectivity
|
|
284
|
+
const checksDatabase = /prisma|database|db\./i.test(content);
|
|
285
|
+
if (!checksDatabase) {
|
|
286
|
+
issues.push({
|
|
287
|
+
rule: "health-db-check",
|
|
288
|
+
message: "Health endpoint doesn't check database connectivity",
|
|
289
|
+
file: relativePath,
|
|
290
|
+
severity: "info",
|
|
291
|
+
suggestion: "Add database connectivity check to health endpoint",
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return issues;
|
|
297
|
+
}
|
|
298
|
+
async function checkPerformanceMonitoring() {
|
|
299
|
+
const issues = [];
|
|
300
|
+
// Check for web vitals tracking
|
|
301
|
+
const webVitalsFiles = await (0, glob_1.glob)([
|
|
302
|
+
"app/**/web-vitals*.ts",
|
|
303
|
+
"lib/**/web-vitals*.ts",
|
|
304
|
+
"instrumentation.ts",
|
|
305
|
+
"app/layout.tsx",
|
|
306
|
+
], {
|
|
307
|
+
cwd: process.cwd(),
|
|
308
|
+
absolute: true,
|
|
309
|
+
});
|
|
310
|
+
let hasWebVitals = false;
|
|
311
|
+
for (const file of webVitalsFiles) {
|
|
312
|
+
if (!fs.existsSync(file))
|
|
313
|
+
continue;
|
|
314
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
315
|
+
if (content.includes("reportWebVitals") || content.includes("web-vitals") || content.includes("@vercel/speed-insights")) {
|
|
316
|
+
hasWebVitals = true;
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (!hasWebVitals) {
|
|
321
|
+
issues.push({
|
|
322
|
+
rule: "web-vitals-tracking",
|
|
323
|
+
message: "No Web Vitals tracking detected",
|
|
324
|
+
file: "app/layout.tsx",
|
|
325
|
+
severity: "info",
|
|
326
|
+
suggestion: "Add @vercel/speed-insights or custom Web Vitals tracking",
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
// Check for analytics
|
|
330
|
+
const layoutPath = path.join(process.cwd(), "app", "layout.tsx");
|
|
331
|
+
if (fs.existsSync(layoutPath)) {
|
|
332
|
+
const content = fs.readFileSync(layoutPath, "utf-8");
|
|
333
|
+
const hasAnalytics = /Analytics|GoogleAnalytics|gtag|plausible|umami|posthog|@vercel\/analytics/i.test(content);
|
|
334
|
+
if (!hasAnalytics) {
|
|
335
|
+
issues.push({
|
|
336
|
+
rule: "analytics-tracking",
|
|
337
|
+
message: "No analytics tracking detected in root layout",
|
|
338
|
+
file: "app/layout.tsx",
|
|
339
|
+
severity: "info",
|
|
340
|
+
suggestion: "Consider adding analytics to track user behavior",
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return issues;
|
|
345
|
+
}
|
|
346
|
+
async function run() {
|
|
347
|
+
const startTime = Date.now();
|
|
348
|
+
const allIssues = [];
|
|
349
|
+
// Run all checks
|
|
350
|
+
allIssues.push(...await checkErrorBoundaries());
|
|
351
|
+
allIssues.push(...await checkApiErrorHandling());
|
|
352
|
+
allIssues.push(...await checkLoggingPractices());
|
|
353
|
+
allIssues.push(...await checkHealthEndpoint());
|
|
354
|
+
allIssues.push(...await checkPerformanceMonitoring());
|
|
355
|
+
// Convert to findings
|
|
356
|
+
const findings = allIssues.map(issue => ({
|
|
357
|
+
level: issue.severity,
|
|
358
|
+
message: issue.message,
|
|
359
|
+
file: issue.file,
|
|
360
|
+
startLine: issue.line,
|
|
361
|
+
ruleId: issue.rule,
|
|
362
|
+
suggestion: issue.suggestion,
|
|
363
|
+
}));
|
|
364
|
+
const errors = findings.filter(f => f.level === "error");
|
|
365
|
+
const warnings = findings.filter(f => f.level === "warning");
|
|
366
|
+
const infos = findings.filter(f => f.level === "info");
|
|
367
|
+
return {
|
|
368
|
+
passed: errors.length === 0,
|
|
369
|
+
findings,
|
|
370
|
+
duration: Date.now() - startTime,
|
|
371
|
+
metadata: {
|
|
372
|
+
errors: errors.length,
|
|
373
|
+
warnings: warnings.length,
|
|
374
|
+
infos: infos.length,
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
async function main() {
|
|
379
|
+
console.log(`\n${console_chars_1.emoji.chart} OBSERVABILITY VALIDATION`);
|
|
380
|
+
console.log((0, console_chars_1.createDivider)(65, "heavy"));
|
|
381
|
+
const result = await run();
|
|
382
|
+
const { errors, warnings, infos } = result.metadata || {};
|
|
383
|
+
console.log(`\n${console_chars_1.emoji.search} Checking observability practices...`);
|
|
384
|
+
console.log(`\n${console_chars_1.emoji.chart} Summary:`);
|
|
385
|
+
console.log(` Errors: ${errors}`);
|
|
386
|
+
console.log(` Warnings: ${warnings}`);
|
|
387
|
+
console.log(` Info: ${infos}`);
|
|
388
|
+
if (result.passed && warnings === 0) {
|
|
389
|
+
console.log(`\n${console_chars_1.emoji.success} OBSERVABILITY VALIDATION PASSED`);
|
|
390
|
+
console.log(`\nAll observability best practices are followed.`);
|
|
391
|
+
process.exit(0);
|
|
392
|
+
}
|
|
393
|
+
// Group by rule
|
|
394
|
+
const findingsByRule = new Map();
|
|
395
|
+
for (const finding of result.findings) {
|
|
396
|
+
const ruleId = finding.ruleId || "unknown";
|
|
397
|
+
if (!findingsByRule.has(ruleId)) {
|
|
398
|
+
findingsByRule.set(ruleId, []);
|
|
399
|
+
}
|
|
400
|
+
findingsByRule.get(ruleId).push(finding);
|
|
401
|
+
}
|
|
402
|
+
// Print errors
|
|
403
|
+
const errorFindings = result.findings.filter(f => f.level === "error");
|
|
404
|
+
if (errorFindings.length > 0) {
|
|
405
|
+
console.log(`\n${console_chars_1.emoji.error} Errors (blocking):`);
|
|
406
|
+
for (const finding of errorFindings) {
|
|
407
|
+
console.log(`\n ${finding.file}${finding.startLine ? `:${finding.startLine}` : ""}`);
|
|
408
|
+
console.log(` ${finding.message}`);
|
|
409
|
+
if (finding.suggestion) {
|
|
410
|
+
console.log(` ${console_chars_1.emoji.hint} ${finding.suggestion}`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Print warnings
|
|
415
|
+
const warningFindings = result.findings.filter(f => f.level === "warning");
|
|
416
|
+
if (warningFindings.length > 0) {
|
|
417
|
+
console.log(`\n${console_chars_1.emoji.warning} Warnings:`);
|
|
418
|
+
for (const finding of warningFindings.slice(0, 10)) {
|
|
419
|
+
console.log(`\n ${finding.file}`);
|
|
420
|
+
console.log(` ${finding.message}`);
|
|
421
|
+
if (finding.suggestion) {
|
|
422
|
+
console.log(` ${console_chars_1.emoji.hint} ${finding.suggestion}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (warningFindings.length > 10) {
|
|
426
|
+
console.log(`\n ... and ${warningFindings.length - 10} more warnings`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
console.log(`\n${console_chars_1.emoji.info} Observability Best Practices:`);
|
|
430
|
+
console.log(` - Global error boundary (app/error.tsx)`);
|
|
431
|
+
console.log(` - API routes with try/catch and proper error responses`);
|
|
432
|
+
console.log(` - Health check endpoint for monitoring`);
|
|
433
|
+
console.log(` - No sensitive data in logs`);
|
|
434
|
+
console.log(` - Web Vitals and analytics tracking`);
|
|
435
|
+
if (!result.passed) {
|
|
436
|
+
console.log(`\n${console_chars_1.emoji.error} OBSERVABILITY VALIDATION FAILED`);
|
|
437
|
+
process.exit(1);
|
|
438
|
+
}
|
|
439
|
+
console.log(`\n${console_chars_1.emoji.success} OBSERVABILITY VALIDATION PASSED`);
|
|
440
|
+
process.exit(0);
|
|
441
|
+
}
|
|
442
|
+
if (require.main === module) {
|
|
443
|
+
main().catch((err) => {
|
|
444
|
+
console.error(`${console_chars_1.emoji.error} Preflight failed:`, err);
|
|
445
|
+
process.exit(1);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
//# sourceMappingURL=observability-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-validation.js","sourceRoot":"","sources":["../../../src/checks/observability/observability-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 = "seo/seo-validation";
|
|
4
|
+
export declare const name = "SEO Validation";
|
|
5
|
+
export declare const description = "Validates SEO best practices (metadata, Open Graph, structured data, technical SEO)";
|
|
6
|
+
export declare const category = "seo";
|
|
7
|
+
export declare const blocking = true;
|
|
8
|
+
export declare const tags: string[];
|
|
9
|
+
export declare function run(): Promise<PreflightCheckResult>;
|
|
10
|
+
//# sourceMappingURL=seo-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-validation.d.ts","sourceRoot":"","sources":["../../../src/checks/seo/seo-validation.ts"],"names":[],"mappings":";AAiCA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAG1E,eAAO,MAAM,EAAE,uBAAuB,CAAC;AACvC,eAAO,MAAM,IAAI,mBAAmB,CAAC;AACrC,eAAO,MAAM,WAAW,wFAAwF,CAAC;AACjH,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAAgE,CAAC;AAwUlF,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CA0EzD"}
|