@qodfy/core 0.2.4 → 0.2.6
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/index.js +288 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,11 +22,17 @@ var recommendedScanChecks = [
|
|
|
22
22
|
var sourceFilePatterns = ["**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}"];
|
|
23
23
|
var ignoredPaths = [
|
|
24
24
|
"node_modules/**",
|
|
25
|
+
"**/node_modules/**",
|
|
25
26
|
".next/**",
|
|
27
|
+
"**/.next/**",
|
|
26
28
|
"dist/**",
|
|
29
|
+
"**/dist/**",
|
|
27
30
|
"build/**",
|
|
31
|
+
"**/build/**",
|
|
28
32
|
".turbo/**",
|
|
33
|
+
"**/.turbo/**",
|
|
29
34
|
".vercel/**",
|
|
35
|
+
"**/.vercel/**",
|
|
30
36
|
"coverage/**",
|
|
31
37
|
"**/coverage/**",
|
|
32
38
|
".cache/**",
|
|
@@ -281,6 +287,7 @@ async function scanProject(input) {
|
|
|
281
287
|
if (statResult.size > MAX_FILE_SIZE_BYTES) {
|
|
282
288
|
if (runMaintainabilityChecks) {
|
|
283
289
|
largeFiles++;
|
|
290
|
+
const largeFileKind = getMaintainabilityFileKind(relativeFile);
|
|
284
291
|
addIssue({
|
|
285
292
|
ruleId: "maintainability-large-file-skipped",
|
|
286
293
|
category: "maintainability",
|
|
@@ -290,7 +297,7 @@ async function scanProject(input) {
|
|
|
290
297
|
message: "This file is larger than 500KB and was skipped from deep content checks.",
|
|
291
298
|
file: relativeFile,
|
|
292
299
|
suggestion: "Review large generated or bundled files manually.",
|
|
293
|
-
fixPrompt: createLargeFileFixPrompt(relativeFile)
|
|
300
|
+
fixPrompt: createLargeFileFixPrompt(relativeFile, largeFileKind)
|
|
294
301
|
});
|
|
295
302
|
}
|
|
296
303
|
continue;
|
|
@@ -423,16 +430,18 @@ async function scanProject(input) {
|
|
|
423
430
|
}
|
|
424
431
|
}
|
|
425
432
|
for (const largeFile of getReportedLargeFiles(largeFileCandidates)) {
|
|
433
|
+
const largeFileKind = getMaintainabilityFileKind(largeFile.relativeFile);
|
|
434
|
+
const largeFileCopy = getLargeFileIssueCopy(largeFileKind);
|
|
426
435
|
addIssue({
|
|
427
436
|
ruleId: "maintainability-large-file",
|
|
428
437
|
category: "maintainability",
|
|
429
438
|
severity: "info",
|
|
430
439
|
confidence: "low",
|
|
431
|
-
title:
|
|
432
|
-
message:
|
|
440
|
+
title: largeFileCopy.title,
|
|
441
|
+
message: largeFileCopy.message,
|
|
433
442
|
file: largeFile.relativeFile,
|
|
434
|
-
suggestion:
|
|
435
|
-
fixPrompt: createLargeFileFixPrompt(largeFile.relativeFile)
|
|
443
|
+
suggestion: largeFileCopy.suggestion,
|
|
444
|
+
fixPrompt: createLargeFileFixPrompt(largeFile.relativeFile, largeFileKind)
|
|
436
445
|
});
|
|
437
446
|
}
|
|
438
447
|
for (const [variableName, filesUsingVariable] of getSortedMissingEnvUsages(missingEnvUsages)) {
|
|
@@ -578,13 +587,17 @@ async function safeReadJson(filePath) {
|
|
|
578
587
|
}
|
|
579
588
|
async function getSourceFiles(projectPath, addIssue) {
|
|
580
589
|
try {
|
|
581
|
-
const
|
|
590
|
+
const rawFiles = await fg(sourceFilePatterns, {
|
|
582
591
|
cwd: projectPath,
|
|
583
592
|
ignore: ignoredPaths,
|
|
584
593
|
absolute: true,
|
|
585
594
|
onlyFiles: true,
|
|
586
595
|
dot: false
|
|
587
596
|
});
|
|
597
|
+
const files = rawFiles.filter((file) => {
|
|
598
|
+
const relativeFile = normalizePath(path.relative(projectPath, file));
|
|
599
|
+
return !shouldIgnoreSourceFile(relativeFile);
|
|
600
|
+
});
|
|
588
601
|
return files.sort(
|
|
589
602
|
(leftFile, rightFile) => normalizePath(leftFile).localeCompare(normalizePath(rightFile))
|
|
590
603
|
);
|
|
@@ -602,6 +615,31 @@ async function getSourceFiles(projectPath, addIssue) {
|
|
|
602
615
|
return [];
|
|
603
616
|
}
|
|
604
617
|
}
|
|
618
|
+
function shouldIgnoreSourceFile(relativeFile) {
|
|
619
|
+
const normalizedFile = normalizePath(relativeFile);
|
|
620
|
+
const pathParts = normalizedFile.split("/");
|
|
621
|
+
const ignoredPathParts = /* @__PURE__ */ new Set([
|
|
622
|
+
"node_modules",
|
|
623
|
+
".next",
|
|
624
|
+
"dist",
|
|
625
|
+
"build",
|
|
626
|
+
".turbo",
|
|
627
|
+
".vercel",
|
|
628
|
+
"coverage",
|
|
629
|
+
".cache",
|
|
630
|
+
".output",
|
|
631
|
+
".open-next",
|
|
632
|
+
"storybook-static",
|
|
633
|
+
"playwright-report",
|
|
634
|
+
"test-results",
|
|
635
|
+
"generated",
|
|
636
|
+
"__generated__"
|
|
637
|
+
]);
|
|
638
|
+
if (normalizedFile.endsWith(".d.ts") || normalizedFile.endsWith(".map")) {
|
|
639
|
+
return true;
|
|
640
|
+
}
|
|
641
|
+
return pathParts.some((pathPart) => ignoredPathParts.has(pathPart));
|
|
642
|
+
}
|
|
605
643
|
function getEnvExampleVariables(content) {
|
|
606
644
|
const variables = /* @__PURE__ */ new Set();
|
|
607
645
|
for (const line of content.split(/\r?\n/)) {
|
|
@@ -1059,6 +1097,88 @@ function getWebhookSignatureSuggestion(provider) {
|
|
|
1059
1097
|
}
|
|
1060
1098
|
return "Verify the provider signature using the raw request body and signature header before trusting the event.";
|
|
1061
1099
|
}
|
|
1100
|
+
function getMaintainabilityFileKind(relativeFile) {
|
|
1101
|
+
const normalizedFile = normalizePath(relativeFile).toLowerCase();
|
|
1102
|
+
const fileName = path.basename(normalizedFile);
|
|
1103
|
+
if (/(^|\/)app\/api\/.+\/route\.(?:ts|js)$/.test(normalizedFile) || /(^|\/)pages\/api\/.+\.(?:ts|js)$/.test(normalizedFile)) {
|
|
1104
|
+
return "api-route";
|
|
1105
|
+
}
|
|
1106
|
+
if (fileName === "actions.ts" || fileName === "actions.tsx") {
|
|
1107
|
+
return "server-action";
|
|
1108
|
+
}
|
|
1109
|
+
if (fileName === "schema.ts" || fileName === "schemas.ts" || fileName === "validation.ts" || fileName === "validator.ts") {
|
|
1110
|
+
return "schema-or-validation";
|
|
1111
|
+
}
|
|
1112
|
+
if (fileName === "types.ts" || fileName === "type.ts" || fileName === "interfaces.ts") {
|
|
1113
|
+
return "types";
|
|
1114
|
+
}
|
|
1115
|
+
if (fileName === "config.ts" || fileName === "config.js" || fileName === "next.config.ts" || fileName === "tailwind.config.ts") {
|
|
1116
|
+
return "config";
|
|
1117
|
+
}
|
|
1118
|
+
if (normalizedFile.endsWith(".tsx") || normalizedFile.endsWith(".jsx")) {
|
|
1119
|
+
return "react-component";
|
|
1120
|
+
}
|
|
1121
|
+
if (/\.(?:ts|js|mts|cts|mjs|cjs)$/.test(normalizedFile)) {
|
|
1122
|
+
return "typescript-module";
|
|
1123
|
+
}
|
|
1124
|
+
return "unknown";
|
|
1125
|
+
}
|
|
1126
|
+
function getLargeFileIssueCopy(kind) {
|
|
1127
|
+
if (kind === "react-component") {
|
|
1128
|
+
return {
|
|
1129
|
+
title: "Large React component detected",
|
|
1130
|
+
message: "This component is larger than the recommended maintainability threshold. Large components can be harder to review, test, and safely modify.",
|
|
1131
|
+
suggestion: "Review whether this component mixes UI, state, data fetching, validation, or business logic. If so, split it into smaller components, hooks, or utilities."
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
if (kind === "typescript-module") {
|
|
1135
|
+
return {
|
|
1136
|
+
title: "Large TypeScript module detected",
|
|
1137
|
+
message: "This module is larger than the recommended maintainability threshold. Large modules can mix business logic, data access, transformations, constants, or helper functions in one place.",
|
|
1138
|
+
suggestion: "Review whether this module mixes unrelated responsibilities such as data fetching, filtering, mapping, sorting, constants, types, or business rules. If so, split it into smaller modules while preserving public exports."
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
if (kind === "api-route") {
|
|
1142
|
+
return {
|
|
1143
|
+
title: "Large API route detected",
|
|
1144
|
+
message: "This API route is larger than the recommended maintainability threshold. Large route handlers can mix validation, auth, business logic, and response formatting.",
|
|
1145
|
+
suggestion: "Review whether this route mixes validation, authentication, business logic, and response formatting. If so, extract reusable helpers without changing route behavior."
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
if (kind === "server-action") {
|
|
1149
|
+
return {
|
|
1150
|
+
title: "Large server action file detected",
|
|
1151
|
+
message: "This server action file is larger than the recommended maintainability threshold and may mix validation, data mutations, and business rules.",
|
|
1152
|
+
suggestion: "Review whether this file mixes validation, permission checks, mutations, and formatting. If so, extract helpers while preserving action behavior."
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
if (kind === "schema-or-validation") {
|
|
1156
|
+
return {
|
|
1157
|
+
title: "Large schema or validation file detected",
|
|
1158
|
+
message: "This schema or validation file is larger than the recommended maintainability threshold and may mix unrelated validation concerns.",
|
|
1159
|
+
suggestion: "Review whether related schemas or validators can be grouped into smaller files while preserving exported names and validation behavior."
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
if (kind === "types") {
|
|
1163
|
+
return {
|
|
1164
|
+
title: "Large type definition file detected",
|
|
1165
|
+
message: "This type file is larger than the recommended maintainability threshold and may be harder to navigate safely.",
|
|
1166
|
+
suggestion: "Review whether types can be split by domain or feature while preserving public exports and imports."
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
if (kind === "config") {
|
|
1170
|
+
return {
|
|
1171
|
+
title: "Large config file detected",
|
|
1172
|
+
message: "This config file is larger than the recommended maintainability threshold and may mix unrelated configuration concerns.",
|
|
1173
|
+
suggestion: "Review whether configuration values or helper functions can be moved to smaller supporting modules without changing runtime behavior."
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
return {
|
|
1177
|
+
title: "Large file detected",
|
|
1178
|
+
message: "This file is larger than the recommended maintainability threshold. Large files can be harder to review, test, and safely modify.",
|
|
1179
|
+
suggestion: "Review whether this file mixes unrelated responsibilities. If so, split it into smaller modules while preserving behavior."
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1062
1182
|
function createApiAuthFixPrompt(file) {
|
|
1063
1183
|
return `Review the API route at ${file}.
|
|
1064
1184
|
|
|
@@ -1149,16 +1269,17 @@ Return:
|
|
|
1149
1269
|
- The updated .env.example lines.
|
|
1150
1270
|
- A short explanation.`;
|
|
1151
1271
|
}
|
|
1152
|
-
function createLargeFileFixPrompt(file) {
|
|
1153
|
-
|
|
1272
|
+
function createLargeFileFixPrompt(file, kind = getMaintainabilityFileKind(file)) {
|
|
1273
|
+
if (kind === "react-component") {
|
|
1274
|
+
return `Review ${file}.
|
|
1154
1275
|
|
|
1155
|
-
Qodfy detected this as a large
|
|
1276
|
+
Qodfy detected this as a large React component.
|
|
1156
1277
|
|
|
1157
1278
|
Goal:
|
|
1158
1279
|
Suggest a safe refactor plan without changing behavior.
|
|
1159
1280
|
|
|
1160
1281
|
Instructions:
|
|
1161
|
-
- Identify the main responsibilities inside the
|
|
1282
|
+
- Identify the main responsibilities inside the component.
|
|
1162
1283
|
- Suggest smaller components, hooks, or utility files that can be extracted.
|
|
1163
1284
|
- Do not rewrite the whole file at once.
|
|
1164
1285
|
- Do not change UI behavior.
|
|
@@ -1169,6 +1290,163 @@ Return:
|
|
|
1169
1290
|
- A short responsibility breakdown.
|
|
1170
1291
|
- A step-by-step refactor plan.
|
|
1171
1292
|
- The safest first extraction.`;
|
|
1293
|
+
}
|
|
1294
|
+
if (kind === "typescript-module") {
|
|
1295
|
+
return `Review ${file}.
|
|
1296
|
+
|
|
1297
|
+
Qodfy detected this as a large TypeScript module.
|
|
1298
|
+
|
|
1299
|
+
Goal:
|
|
1300
|
+
Create a safe refactor plan without changing behavior.
|
|
1301
|
+
|
|
1302
|
+
Instructions:
|
|
1303
|
+
- Identify the main responsibilities inside this module.
|
|
1304
|
+
- Check whether the file mixes unrelated concerns such as data fetching, filtering, mapping, sorting, constants, types, validation, or business rules.
|
|
1305
|
+
- Suggest smaller TypeScript modules that could be extracted safely.
|
|
1306
|
+
- Do not rewrite the whole file at once.
|
|
1307
|
+
- Do not change business logic.
|
|
1308
|
+
- Do not change public exports unless you also update all imports safely.
|
|
1309
|
+
- Preserve existing function behavior, return types, and error handling.
|
|
1310
|
+
- Prioritize the lowest-risk extraction first.
|
|
1311
|
+
|
|
1312
|
+
Return:
|
|
1313
|
+
- Responsibility breakdown.
|
|
1314
|
+
- Suggested new file/module structure.
|
|
1315
|
+
- Step-by-step refactor plan.
|
|
1316
|
+
- The safest first extraction.
|
|
1317
|
+
- Tests or manual checks to run.`;
|
|
1318
|
+
}
|
|
1319
|
+
if (kind === "api-route") {
|
|
1320
|
+
return `Review the API route at ${file}.
|
|
1321
|
+
|
|
1322
|
+
Qodfy detected this as a large API route file.
|
|
1323
|
+
|
|
1324
|
+
Goal:
|
|
1325
|
+
Create a safe refactor plan without changing HTTP behavior.
|
|
1326
|
+
|
|
1327
|
+
Instructions:
|
|
1328
|
+
- Identify where validation, authentication, business logic, and response formatting happen.
|
|
1329
|
+
- Suggest helper modules that can be extracted without changing the route contract.
|
|
1330
|
+
- Preserve HTTP methods, status codes, headers, auth checks, validation behavior, and response shape.
|
|
1331
|
+
- Do not rewrite the whole route at once.
|
|
1332
|
+
- Do not introduce a new auth provider or validation library.
|
|
1333
|
+
- Prioritize the lowest-risk extraction first.
|
|
1334
|
+
|
|
1335
|
+
Return:
|
|
1336
|
+
- Responsibility breakdown.
|
|
1337
|
+
- Suggested helper/module structure.
|
|
1338
|
+
- Step-by-step refactor plan.
|
|
1339
|
+
- The safest first extraction.
|
|
1340
|
+
- Tests or manual checks to run.`;
|
|
1341
|
+
}
|
|
1342
|
+
if (kind === "server-action") {
|
|
1343
|
+
return `Review the server action file at ${file}.
|
|
1344
|
+
|
|
1345
|
+
Qodfy detected this as a large server action file.
|
|
1346
|
+
|
|
1347
|
+
Goal:
|
|
1348
|
+
Create a safe refactor plan without changing action behavior.
|
|
1349
|
+
|
|
1350
|
+
Instructions:
|
|
1351
|
+
- Identify validation, permission checks, mutations, cache invalidation, formatting, and error handling.
|
|
1352
|
+
- Suggest helper modules that can be extracted safely.
|
|
1353
|
+
- Preserve permissions, validation behavior, data mutations, cache invalidation, return shape, and error handling.
|
|
1354
|
+
- Do not rewrite the whole file at once.
|
|
1355
|
+
- Do not change public action names unless you also update every import safely.
|
|
1356
|
+
- Prioritize the lowest-risk extraction first.
|
|
1357
|
+
|
|
1358
|
+
Return:
|
|
1359
|
+
- Responsibility breakdown.
|
|
1360
|
+
- Suggested helper/module structure.
|
|
1361
|
+
- Step-by-step refactor plan.
|
|
1362
|
+
- The safest first extraction.
|
|
1363
|
+
- Tests or manual checks to run.`;
|
|
1364
|
+
}
|
|
1365
|
+
if (kind === "schema-or-validation") {
|
|
1366
|
+
return `Review the schema or validation file at ${file}.
|
|
1367
|
+
|
|
1368
|
+
Qodfy detected this as a large validation-focused file.
|
|
1369
|
+
|
|
1370
|
+
Goal:
|
|
1371
|
+
Create a safe refactor plan without changing validation behavior.
|
|
1372
|
+
|
|
1373
|
+
Instructions:
|
|
1374
|
+
- Identify related schemas, validators, shared constants, and inferred types.
|
|
1375
|
+
- Suggest smaller validation modules grouped by feature or domain.
|
|
1376
|
+
- Do not change validation rules, error messages, inferred types, or public exports unless you also update all imports safely.
|
|
1377
|
+
- Prioritize the lowest-risk extraction first.
|
|
1378
|
+
|
|
1379
|
+
Return:
|
|
1380
|
+
- Responsibility breakdown.
|
|
1381
|
+
- Suggested file/module structure.
|
|
1382
|
+
- Step-by-step refactor plan.
|
|
1383
|
+
- The safest first extraction.
|
|
1384
|
+
- Tests or manual checks to run.`;
|
|
1385
|
+
}
|
|
1386
|
+
if (kind === "types") {
|
|
1387
|
+
return `Review the type definition file at ${file}.
|
|
1388
|
+
|
|
1389
|
+
Qodfy detected this as a large type file.
|
|
1390
|
+
|
|
1391
|
+
Goal:
|
|
1392
|
+
Create a safe organization plan without changing runtime behavior.
|
|
1393
|
+
|
|
1394
|
+
Instructions:
|
|
1395
|
+
- Identify groups of related types, interfaces, enums, and exported utility types.
|
|
1396
|
+
- Suggest smaller type modules grouped by domain or feature.
|
|
1397
|
+
- Do not change type names, public exports, or imports unless you also update all references safely.
|
|
1398
|
+
- Prioritize the lowest-risk extraction first.
|
|
1399
|
+
|
|
1400
|
+
Return:
|
|
1401
|
+
- Type responsibility breakdown.
|
|
1402
|
+
- Suggested file/module structure.
|
|
1403
|
+
- Step-by-step refactor plan.
|
|
1404
|
+
- The safest first extraction.
|
|
1405
|
+
- Type-check command to run.`;
|
|
1406
|
+
}
|
|
1407
|
+
if (kind === "config") {
|
|
1408
|
+
return `Review the config file at ${file}.
|
|
1409
|
+
|
|
1410
|
+
Qodfy detected this as a large config file.
|
|
1411
|
+
|
|
1412
|
+
Goal:
|
|
1413
|
+
Create a safe simplification plan without changing runtime configuration.
|
|
1414
|
+
|
|
1415
|
+
Instructions:
|
|
1416
|
+
- Identify config sections, constants, plugin setup, and helper functions.
|
|
1417
|
+
- Suggest supporting modules only if extraction reduces complexity.
|
|
1418
|
+
- Preserve all existing config values, plugin order, environment behavior, and exports.
|
|
1419
|
+
- Do not upgrade dependencies or change framework behavior.
|
|
1420
|
+
- Prioritize the lowest-risk extraction first.
|
|
1421
|
+
|
|
1422
|
+
Return:
|
|
1423
|
+
- Config responsibility breakdown.
|
|
1424
|
+
- Suggested supporting module structure.
|
|
1425
|
+
- Step-by-step refactor plan.
|
|
1426
|
+
- The safest first extraction.
|
|
1427
|
+
- Build or validation command to run.`;
|
|
1428
|
+
}
|
|
1429
|
+
return `Review ${file}.
|
|
1430
|
+
|
|
1431
|
+
Qodfy detected this as a large file.
|
|
1432
|
+
|
|
1433
|
+
Goal:
|
|
1434
|
+
Create a safe refactor plan without changing behavior.
|
|
1435
|
+
|
|
1436
|
+
Instructions:
|
|
1437
|
+
- Identify the main responsibilities inside the file.
|
|
1438
|
+
- Suggest smaller files or modules that can be extracted safely.
|
|
1439
|
+
- Do not rewrite the whole file at once.
|
|
1440
|
+
- Do not change public exports unless you also update all imports safely.
|
|
1441
|
+
- Preserve existing behavior, return values, and error handling.
|
|
1442
|
+
- Prioritize the lowest-risk extraction first.
|
|
1443
|
+
|
|
1444
|
+
Return:
|
|
1445
|
+
- Responsibility breakdown.
|
|
1446
|
+
- Suggested file/module structure.
|
|
1447
|
+
- Step-by-step refactor plan.
|
|
1448
|
+
- The safest first extraction.
|
|
1449
|
+
- Tests or manual checks to run.`;
|
|
1172
1450
|
}
|
|
1173
1451
|
function createAiRateLimitFixPrompt(file) {
|
|
1174
1452
|
return `Review the AI-related API route at ${file}.
|