@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.
Files changed (2) hide show
  1. package/dist/index.js +288 -10
  2. 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: "Large file detected",
432
- message: "This file is larger than the recommended maintainability threshold. Large files can be harder to review, test, and safely modify.",
440
+ title: largeFileCopy.title,
441
+ message: largeFileCopy.message,
433
442
  file: largeFile.relativeFile,
434
- suggestion: "Review whether this file mixes UI, state, data fetching, validation, or business logic. If so, split it into smaller components, hooks, or utilities.",
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 files = await fg(sourceFilePatterns, {
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
- return `Review ${file}.
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 file.
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 file.
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}.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qodfy/core",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Scanner engine for Qodfy, an open-source launch readiness scanner for AI-built apps.",
5
5
  "keywords": [
6
6
  "qodfy",