stackkit 0.2.8 → 0.3.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.
Files changed (77) hide show
  1. package/README.md +4 -0
  2. package/bin/stackkit.js +8 -5
  3. package/dist/cli/add.js +4 -9
  4. package/dist/cli/create.js +4 -9
  5. package/dist/cli/doctor.js +11 -32
  6. package/dist/lib/constants.js +3 -4
  7. package/dist/lib/conversion/js-conversion.js +20 -16
  8. package/dist/lib/discovery/installed-detection.js +28 -38
  9. package/dist/lib/discovery/module-discovery.d.ts +0 -15
  10. package/dist/lib/discovery/module-discovery.js +15 -50
  11. package/dist/lib/framework/framework-utils.d.ts +4 -5
  12. package/dist/lib/framework/framework-utils.js +38 -49
  13. package/dist/lib/fs/files.js +1 -1
  14. package/dist/lib/generation/code-generator.d.ts +13 -19
  15. package/dist/lib/generation/code-generator.js +159 -175
  16. package/dist/lib/generation/generator-utils.js +3 -15
  17. package/dist/lib/project/detect.js +11 -19
  18. package/dist/lib/utils/fs-helpers.d.ts +1 -1
  19. package/modules/auth/authjs/generator.json +16 -16
  20. package/modules/auth/better-auth/files/express/middlewares/authorize.ts +178 -40
  21. package/modules/auth/better-auth/files/express/modules/auth/auth.controller.ts +264 -0
  22. package/modules/auth/better-auth/files/express/modules/auth/auth.route.ts +27 -0
  23. package/modules/auth/better-auth/files/express/modules/auth/auth.service.ts +537 -0
  24. package/modules/auth/better-auth/files/express/modules/auth/auth.type.ts +33 -0
  25. package/modules/auth/better-auth/files/express/templates/google-redirect.ejs +91 -0
  26. package/modules/auth/better-auth/files/express/templates/otp.ejs +87 -0
  27. package/modules/auth/better-auth/files/express/types/express.d.ts +6 -8
  28. package/modules/auth/better-auth/files/express/utils/cookie.ts +19 -0
  29. package/modules/auth/better-auth/files/express/utils/jwt.ts +34 -0
  30. package/modules/auth/better-auth/files/express/utils/token.ts +66 -0
  31. package/modules/auth/better-auth/files/nextjs/api/auth/[...all]/route.ts +1 -1
  32. package/modules/auth/better-auth/files/nextjs/lib/auth/auth-guards.ts +11 -1
  33. package/modules/auth/better-auth/files/nextjs/templates/email-otp.tsx +74 -0
  34. package/modules/auth/better-auth/files/shared/config/env.ts +117 -0
  35. package/modules/auth/better-auth/files/shared/lib/auth-client.ts +1 -1
  36. package/modules/auth/better-auth/files/shared/lib/auth.ts +167 -79
  37. package/modules/auth/better-auth/files/shared/mongoose/auth/constants.ts +11 -0
  38. package/modules/auth/better-auth/files/shared/mongoose/auth/helper.ts +51 -0
  39. package/modules/auth/better-auth/files/shared/prisma/schema.prisma +22 -11
  40. package/modules/auth/better-auth/files/shared/utils/email.ts +70 -0
  41. package/modules/auth/better-auth/generator.json +162 -80
  42. package/modules/database/mongoose/files/lib/mongoose.ts +28 -3
  43. package/modules/database/mongoose/generator.json +18 -18
  44. package/modules/database/prisma/generator.json +44 -44
  45. package/package.json +2 -2
  46. package/templates/express/env.example +3 -2
  47. package/templates/express/eslint.config.mjs +7 -0
  48. package/templates/express/node_modules/.bin/acorn +17 -0
  49. package/templates/express/node_modules/.bin/eslint +17 -0
  50. package/templates/express/node_modules/.bin/tsc +17 -0
  51. package/templates/express/node_modules/.bin/tsserver +17 -0
  52. package/templates/express/node_modules/.bin/tsx +17 -0
  53. package/templates/express/package.json +12 -6
  54. package/templates/express/src/app.ts +15 -7
  55. package/templates/express/src/config/cors.ts +8 -7
  56. package/templates/express/src/config/env.ts +28 -5
  57. package/templates/express/src/config/logger.ts +2 -2
  58. package/templates/express/src/config/rate-limit.ts +2 -2
  59. package/templates/express/src/modules/health/health.controller.ts +13 -11
  60. package/templates/express/src/routes/index.ts +1 -6
  61. package/templates/express/src/server.ts +12 -12
  62. package/templates/express/src/shared/errors/app-error.ts +16 -0
  63. package/templates/express/src/shared/middlewares/error.middleware.ts +154 -12
  64. package/templates/express/src/shared/middlewares/not-found.middleware.ts +2 -1
  65. package/templates/express/src/shared/utils/catch-async.ts +11 -0
  66. package/templates/express/src/shared/utils/pagination.ts +6 -1
  67. package/templates/express/src/shared/utils/send-response.ts +25 -0
  68. package/templates/nextjs/lib/env.ts +19 -8
  69. package/modules/auth/better-auth/files/shared/lib/email/email-service.ts +0 -33
  70. package/modules/auth/better-auth/files/shared/lib/email/email-templates.ts +0 -89
  71. package/templates/express/eslint.config.cjs +0 -42
  72. package/templates/express/src/config/helmet.ts +0 -5
  73. package/templates/express/src/modules/health/health.service.ts +0 -6
  74. package/templates/express/src/shared/errors/error-codes.ts +0 -9
  75. package/templates/express/src/shared/logger/logger.ts +0 -20
  76. package/templates/express/src/shared/utils/async-handler.ts +0 -9
  77. package/templates/express/src/shared/utils/response.ts +0 -9
package/README.md CHANGED
@@ -29,6 +29,7 @@ npx stackkit@latest create my-app \
29
29
  ```
30
30
 
31
31
  **Options:**
32
+
32
33
  - `--framework, -f` - nextjs, express, react
33
34
  - `--database, -d` - prisma-postgresql, prisma-mysql, prisma-sqlite, prisma-mongodb, mongoose, none
34
35
  - `--auth, -a` - better-auth, authjs, none
@@ -73,15 +74,18 @@ npx stackkit@latest list
73
74
  ## Supported Technologies
74
75
 
75
76
  **Frameworks:**
77
+
76
78
  - Next.js (App Router)
77
79
  - Express (TypeScript API)
78
80
  - React (Vite SPA)
79
81
 
80
82
  **Databases:**
83
+
81
84
  - Prisma (PostgreSQL, MySQL, SQLite, MongoDB)
82
85
  - Mongoose (MongoDB)
83
86
 
84
87
  **Authentication:**
88
+
85
89
  - Better Auth (All frameworks)
86
90
  - Auth.js (Next.js only)
87
91
 
package/bin/stackkit.js CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
- /* eslint-disable */
2
+ function getErrorMessage(error) {
3
+ if (error instanceof Error) {
4
+ return error.message;
5
+ }
6
+ return String(error);
7
+ }
8
+
3
9
  try {
4
10
  require("../dist/index.js");
5
11
  } catch (err) {
6
- console.error(
7
- "Failed to load compiled CLI (did you run 'npm run build'?)",
8
- err && err.message ? err.message : err,
9
- );
12
+ console.error("Failed to load compiled CLI (did you run 'npm run build'?)", getErrorMessage(err));
10
13
  process.exitCode = 1;
11
14
  }
package/dist/cli/add.js CHANGED
@@ -26,7 +26,6 @@ async function addCommand(module, options) {
26
26
  const projectInfo = await (0, detect_1.detectProjectInfo)(projectRoot);
27
27
  spinner.succeed(`Detected ${projectInfo.framework} (${projectInfo.router} router, ${projectInfo.language})`);
28
28
  const config = await getAddConfig(module, options, projectInfo);
29
- // Refresh project detection in case getAddConfig performed a pre-add (database)
30
29
  const refreshedProjectInfo = await (0, detect_1.detectProjectInfo)(projectRoot);
31
30
  await addModuleToProject(projectRoot, refreshedProjectInfo, config, options);
32
31
  logger_1.logger.newLine();
@@ -110,19 +109,16 @@ async function getAddConfig(module, options, projectInfo) {
110
109
  };
111
110
  }
112
111
  }
113
- // Unknown module type
114
112
  throw new Error(`Unknown module type "${module}". Use "database" or "auth", or specify a provider directly.`);
115
113
  }
116
114
  async function getInteractiveConfig(modulesDir, projectInfo, options) {
117
115
  const projectRoot = process.cwd();
118
116
  const discovered = await (0, module_discovery_1.discoverModules)(modulesDir);
119
- // Prefer discovered framework, then projectInfo.framework; leave empty if unknown
120
117
  const defaultFramework = (discovered.frameworks && discovered.frameworks[0]?.name) || projectInfo?.framework || "";
121
118
  const compatibleAuths = (0, module_discovery_1.getCompatibleAuthOptions)(discovered.auth || [], projectInfo?.framework || defaultFramework, projectInfo?.hasPrisma ? "prisma" : "none", discovered.frameworks);
122
119
  const categories = [
123
120
  { name: "Database", value: "database" },
124
121
  ];
125
- // Offer Auth category when there's at least one compatible auth option
126
122
  if (compatibleAuths.length > 0) {
127
123
  categories.push({ name: "Auth", value: "auth" });
128
124
  }
@@ -155,7 +151,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
155
151
  metadata: (await loadModuleMetadata(modulesDir, "prisma", "prisma")),
156
152
  };
157
153
  }
158
- // Other databases (mongoose, etc.)
159
154
  const meta = (await loadModuleMetadata(modulesDir, selectedDb, selectedDb));
160
155
  if (!meta)
161
156
  throw new Error(`Database provider "${selectedDb}" not found`);
@@ -338,8 +333,8 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
338
333
  selectedModules.database = "mongoose";
339
334
  }
340
335
  }
341
- catch {
342
- // ignore detection errors
336
+ catch (error) {
337
+ void error;
343
338
  }
344
339
  if (config.module === "database" && config.provider) {
345
340
  const parsed = (0, shared_1.parseDatabaseOption)(config.provider);
@@ -394,8 +389,8 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
394
389
  if (shared && shared.devDependencies)
395
390
  Object.assign(mergedDevDeps, shared.devDependencies);
396
391
  }
397
- catch {
398
- // ignore malformed frameworkConfigs
392
+ catch (error) {
393
+ void error;
399
394
  }
400
395
  const variables = {};
401
396
  if (selectedProvider) {
@@ -111,7 +111,6 @@ async function getProjectConfig(projectName, options) {
111
111
  auth = authOpt;
112
112
  }
113
113
  const finalFramework = (framework || (discoveredModules.frameworks[0]?.name ?? ""));
114
- // Validate auth compatibility using discovered module metadata when available
115
114
  if (auth && auth !== "none" && discoveredModules.auth) {
116
115
  const authMeta = discoveredModules.auth.find((a) => a.name === auth);
117
116
  if (authMeta) {
@@ -164,7 +163,6 @@ async function getProjectConfig(projectName, options) {
164
163
  if (discoveredModules.frameworks && discoveredModules.frameworks.length > 0) {
165
164
  return discoveredModules.frameworks.map((f) => ({ name: f.displayName, value: f.name }));
166
165
  }
167
- // Fallback: read templates dir directly
168
166
  try {
169
167
  const templatesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "templates");
170
168
  if (fs_extra_1.default.existsSync(templatesDir)) {
@@ -173,7 +171,7 @@ async function getProjectConfig(projectName, options) {
173
171
  }
174
172
  }
175
173
  catch {
176
- // ignore
174
+ return [];
177
175
  }
178
176
  return [];
179
177
  })(),
@@ -187,7 +185,6 @@ async function getProjectConfig(projectName, options) {
187
185
  if (discoveredModules.databases && discoveredModules.databases.length > 0) {
188
186
  return (0, module_discovery_1.getDatabaseChoices)(discoveredModules.databases, answers.framework);
189
187
  }
190
- // Fallback: scan modules/database directory
191
188
  try {
192
189
  const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules", "database");
193
190
  if (fs_extra_1.default.existsSync(modulesDir)) {
@@ -199,7 +196,7 @@ async function getProjectConfig(projectName, options) {
199
196
  }
200
197
  }
201
198
  catch {
202
- // ignore
199
+ return [{ name: "None", value: "none" }];
203
200
  }
204
201
  return [{ name: "None", value: "none" }];
205
202
  },
@@ -340,8 +337,8 @@ async function composeTemplate(config, targetDir) {
340
337
  await fs_extra_1.default.writeFile(envPath, envContent);
341
338
  }
342
339
  }
343
- catch {
344
- // env copy failed.
340
+ catch (error) {
341
+ void error;
345
342
  }
346
343
  if (config.language === "javascript") {
347
344
  await (0, js_conversion_1.convertToJavaScript)(targetDir, config.framework);
@@ -351,7 +348,6 @@ async function composeTemplate(config, targetDir) {
351
348
  async function processGeneratorEnvVars(config, targetDir) {
352
349
  const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules");
353
350
  const envVars = [];
354
- // Process database generator env vars
355
351
  if (config.database && config.database !== "none") {
356
352
  const dbGeneratorPath = path_1.default.join(modulesDir, "database", config.database, "generator.json");
357
353
  if (await fs_extra_1.default.pathExists(dbGeneratorPath)) {
@@ -372,7 +368,6 @@ async function processGeneratorEnvVars(config, targetDir) {
372
368
  }
373
369
  }
374
370
  }
375
- // Process auth generator env vars
376
371
  if (config.auth && config.auth !== "none") {
377
372
  const authGeneratorPath = path_1.default.join(modulesDir, "auth", config.auth, "generator.json");
378
373
  if (await fs_extra_1.default.pathExists(authGeneratorPath)) {
@@ -10,7 +10,6 @@ const path_1 = __importDefault(require("path"));
10
10
  const installed_detection_1 = require("../lib/discovery/installed-detection");
11
11
  const logger_1 = require("../lib/ui/logger");
12
12
  const package_root_1 = require("../lib/utils/package-root");
13
- // Constants for consistent messaging
14
13
  const MESSAGES = {
15
14
  NO_PACKAGE_JSON: "No package.json found in current directory or any parent directory.",
16
15
  UNSUPPORTED_PROJECT: "Unsupported project type or unable to detect framework.",
@@ -174,7 +173,6 @@ async function detectPackageManager(projectRoot) {
174
173
  }
175
174
  function detectProjectType(packageJson) {
176
175
  const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
177
- // Try to detect using available templates
178
176
  try {
179
177
  const templatesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "templates");
180
178
  if (fs_extra_1.default.existsSync(templatesDir)) {
@@ -189,13 +187,13 @@ function detectProjectType(packageJson) {
189
187
  return tpl.framework;
190
188
  }
191
189
  catch {
192
- // ignore
190
+ continue;
193
191
  }
194
192
  }
195
193
  }
196
194
  }
197
- catch {
198
- // ignore template-based detection errors
195
+ catch (error) {
196
+ void error;
199
197
  }
200
198
  if (deps.next) {
201
199
  return "nextjs";
@@ -233,7 +231,6 @@ function checkNodeVersion() {
233
231
  };
234
232
  }
235
233
  }
236
- // Module detection is delegated to shared utilities in `lib/discovery`.
237
234
  async function checkKeyFiles(projectRoot, projectType, authModules, databaseModules) {
238
235
  const checks = [];
239
236
  const envExampleExists = await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, ".env.example"));
@@ -262,7 +259,6 @@ async function checkKeyFiles(projectRoot, projectType, authModules, databaseModu
262
259
  return checks;
263
260
  }
264
261
  async function checkAuthRoutesExist(projectRoot) {
265
- // Build candidate auth route paths from generator.json files in modules/auth
266
262
  const candidates = new Set();
267
263
  try {
268
264
  const authModulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules", "auth");
@@ -288,13 +284,13 @@ async function checkAuthRoutesExist(projectRoot) {
288
284
  }
289
285
  }
290
286
  catch {
291
- // ignore malformed generator
287
+ continue;
292
288
  }
293
289
  }
294
290
  }
295
291
  }
296
- catch {
297
- // ignore discovery errors
292
+ catch (error) {
293
+ void error;
298
294
  }
299
295
  if (candidates.size === 0)
300
296
  return false;
@@ -310,7 +306,6 @@ async function checkEnvFiles(projectRoot, authModules, databaseModules) {
310
306
  const requiredKeys = [];
311
307
  const missing = [];
312
308
  const present = [];
313
- // Dynamically collect required env keys from generator.json for detected modules
314
309
  try {
315
310
  const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules");
316
311
  async function collectEnvKeys(category, name) {
@@ -327,7 +322,6 @@ async function checkEnvFiles(projectRoot, authModules, databaseModules) {
327
322
  requiredKeys.push(k);
328
323
  }
329
324
  }
330
- // Also check nested operations (e.g., patch-file -> operations)
331
325
  if (Array.isArray(op.operations)) {
332
326
  for (const sub of op.operations) {
333
327
  if (sub.type === "add-env" && sub.envVars && typeof sub.envVars === "object") {
@@ -342,7 +336,7 @@ async function checkEnvFiles(projectRoot, authModules, databaseModules) {
342
336
  }
343
337
  }
344
338
  catch {
345
- // ignore malformed generator
339
+ return;
346
340
  }
347
341
  }
348
342
  for (const db of databaseModules) {
@@ -352,8 +346,8 @@ async function checkEnvFiles(projectRoot, authModules, databaseModules) {
352
346
  await collectEnvKeys("auth", auth);
353
347
  }
354
348
  }
355
- catch {
356
- // If discovery fails, keep requiredKeys empty rather than using hard-coded defaults.
349
+ catch (error) {
350
+ void error;
357
351
  }
358
352
  const envPaths = [".env", ".env.local"];
359
353
  let envContent = "";
@@ -431,14 +425,10 @@ async function checkConfigFiles(projectRoot, projectType, packageJson) {
431
425
  }
432
426
  async function checkDependencies(packageJson) {
433
427
  const outdated = [];
434
- // Simple check: if dependencies have ^ or ~, assume up to date for now
435
- // In production, integrate with npm outdated or similar
436
428
  const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
437
429
  for (const [name, version] of Object.entries(deps || {})) {
438
- if (typeof version === "string" && (version.startsWith("^") || version.startsWith("~"))) {
439
- // Assume up to date if using flexible versioning
440
- }
441
- else {
430
+ const isFlexibleVersion = typeof version === "string" && (version.startsWith("^") || version.startsWith("~"));
431
+ if (!isFlexibleVersion) {
442
432
  outdated.push(name);
443
433
  }
444
434
  }
@@ -473,27 +463,23 @@ async function checkEslintConfigExists(projectRoot) {
473
463
  }
474
464
  function generateSuggestions(authModules, databaseModules) {
475
465
  const suggestions = [];
476
- // Show suggestions based on what's missing
477
466
  if (authModules.length === 0) {
478
467
  suggestions.push("stackkit add auth - Add authentication module");
479
468
  }
480
469
  if (databaseModules.length === 0) {
481
470
  suggestions.push("stackkit add database - Add database module");
482
471
  }
483
- // Always show available commands
484
472
  suggestions.push("stackkit list - View available modules");
485
473
  return suggestions;
486
474
  }
487
475
  function printDoctorReport(report, verbose) {
488
476
  logger_1.logger.header("🔍 StackKit Doctor Report");
489
477
  logger_1.logger.newLine();
490
- // Project info
491
478
  logger_1.logger.log(chalk_1.default.bold("Project"));
492
479
  logger_1.logger.log(` Type: ${report.project.type}`);
493
480
  logger_1.logger.log(` Root: ${report.project.root}`);
494
481
  logger_1.logger.log(` Package Manager: ${report.project.packageManager}`);
495
482
  logger_1.logger.newLine();
496
- // Runtime
497
483
  logger_1.logger.log(chalk_1.default.bold("Runtime"));
498
484
  if (report.runtime.nodeVersionStatus === "success") {
499
485
  logger_1.logger.success(`Node.js: ${report.runtime.nodeVersion}`);
@@ -505,7 +491,6 @@ function printDoctorReport(report, verbose) {
505
491
  logger_1.logger.error(`Node.js: ${report.runtime.nodeVersion}`);
506
492
  }
507
493
  logger_1.logger.newLine();
508
- // Modules
509
494
  logger_1.logger.log(chalk_1.default.bold("Modules"));
510
495
  if (report.modules.auth.length > 0) {
511
496
  logger_1.logger.log(` Auth: ${report.modules.auth.join(", ")}`);
@@ -520,7 +505,6 @@ function printDoctorReport(report, verbose) {
520
505
  logger_1.logger.info("Database: None");
521
506
  }
522
507
  logger_1.logger.newLine();
523
- // Files
524
508
  logger_1.logger.log(chalk_1.default.bold("Files"));
525
509
  if (report.files.envExample) {
526
510
  logger_1.logger.success(MESSAGES.ENV_EXAMPLE_FOUND);
@@ -582,14 +566,12 @@ function printDoctorReport(report, verbose) {
582
566
  }
583
567
  }
584
568
  logger_1.logger.newLine();
585
- // Dependencies
586
569
  if (report.dependencies.outdated.length > 0) {
587
570
  logger_1.logger.log(chalk_1.default.bold("Dependencies"));
588
571
  logger_1.logger.warn(MESSAGES.DEPENDENCY_OUTDATED(report.dependencies.outdated));
589
572
  logger_1.logger.log(" Hint: Run package manager update command");
590
573
  logger_1.logger.newLine();
591
574
  }
592
- // Environment
593
575
  if (report.env.missing.length > 0 || report.env.present.length > 0) {
594
576
  logger_1.logger.log(chalk_1.default.bold("Environment Variables"));
595
577
  if (report.env.present.length > 0) {
@@ -600,7 +582,6 @@ function printDoctorReport(report, verbose) {
600
582
  }
601
583
  logger_1.logger.newLine();
602
584
  }
603
- // Conflicts
604
585
  if (report.conflicts.length > 0) {
605
586
  logger_1.logger.log(chalk_1.default.bold("Conflicts"));
606
587
  report.conflicts.forEach((conflict) => {
@@ -608,7 +589,6 @@ function printDoctorReport(report, verbose) {
608
589
  });
609
590
  logger_1.logger.newLine();
610
591
  }
611
- // Detailed checks if verbose
612
592
  if (verbose) {
613
593
  logger_1.logger.log(chalk_1.default.bold("Detailed Checks"));
614
594
  report.checks.forEach((check) => {
@@ -627,7 +607,6 @@ function printDoctorReport(report, verbose) {
627
607
  });
628
608
  logger_1.logger.newLine();
629
609
  }
630
- // Summary
631
610
  logger_1.logger.log(chalk_1.default.bold("Summary"));
632
611
  logger_1.logger.log(` Errors: ${report.summary.errors}`);
633
612
  logger_1.logger.log(` Warnings: ${report.summary.warnings}`);
@@ -13,7 +13,6 @@ exports.LOCK_FILES = {
13
13
  [exports.PACKAGE_MANAGERS.BUN]: "bun.lockb",
14
14
  [exports.PACKAGE_MANAGERS.NPM]: "package-lock.json",
15
15
  };
16
- // Array of lock files with package managers for iteration
17
16
  exports.LOCK_FILES_ARRAY = [
18
17
  { file: exports.LOCK_FILES.pnpm, pm: exports.PACKAGE_MANAGERS.PNPM },
19
18
  { file: exports.LOCK_FILES.yarn, pm: exports.PACKAGE_MANAGERS.YARN },
@@ -62,9 +61,9 @@ exports.EXCLUDE_FROM_COPY = [
62
61
  exports.DIRECTORY_NAMES.GIT,
63
62
  ];
64
63
  exports.TIMEOUTS = {
65
- PACKAGE_INSTALL: 300000, // 5 minutes in milliseconds
66
- GIT_INIT: 30000, // 30 seconds
67
- RETRY_DELAY_BASE: 1000, // 1 second base delay for retries
64
+ PACKAGE_INSTALL: 300000,
65
+ GIT_INIT: 30000,
66
+ RETRY_DELAY_BASE: 1000,
68
67
  };
69
68
  exports.RETRY_CONFIG = {
70
69
  MAX_ATTEMPTS: 2,
@@ -4,11 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.convertToJavaScript = convertToJavaScript;
7
- /* eslint-disable @typescript-eslint/no-require-imports */
8
7
  const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const module_1 = require("module");
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const logger_1 = require("../ui/logger");
11
11
  const package_root_1 = require("../utils/package-root");
12
+ const nodeRequire = (0, module_1.createRequire)(__filename);
12
13
  const baseDirs = {
13
14
  express: "./src",
14
15
  react: "./src",
@@ -41,10 +42,10 @@ async function convertToJavaScript(targetDir, framework) {
41
42
  }
42
43
  };
43
44
  await removeDtsFiles(targetDir);
44
- const babel = require("@babel/core");
45
+ const babel = nodeRequire("@babel/core");
45
46
  const checkModule = (name) => {
46
47
  try {
47
- require.resolve(name);
48
+ nodeRequire.resolve(name);
48
49
  return true;
49
50
  }
50
51
  catch {
@@ -82,7 +83,7 @@ async function convertToJavaScript(targetDir, framework) {
82
83
  const outFile = fullPath.replace(/\.tsx$/, ".jsx").replace(/\.ts$/, ".js");
83
84
  const presets = [
84
85
  [
85
- require.resolve("@babel/preset-typescript"),
86
+ nodeRequire.resolve("@babel/preset-typescript"),
86
87
  {
87
88
  onlyRemoveTypeImports: true,
88
89
  allowDeclareFields: true,
@@ -93,7 +94,7 @@ async function convertToJavaScript(targetDir, framework) {
93
94
  },
94
95
  ],
95
96
  [
96
- require.resolve("@babel/preset-env"),
97
+ nodeRequire.resolve("@babel/preset-env"),
97
98
  {
98
99
  targets: { node: "18" },
99
100
  modules: false,
@@ -101,14 +102,14 @@ async function convertToJavaScript(targetDir, framework) {
101
102
  ],
102
103
  ];
103
104
  try {
104
- const recast = require("recast");
105
- const { transformFromAstSync } = require("@babel/core");
106
- const transformTypescript = require("@babel/plugin-transform-typescript");
107
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
- let getBabelOptions = require("recast/parsers/_babel_options");
109
- if (getBabelOptions && getBabelOptions.default)
110
- getBabelOptions = getBabelOptions.default;
111
- const babelParser = require("recast/parsers/babel").parser;
105
+ const recast = nodeRequire("recast");
106
+ const { transformFromAstSync } = nodeRequire("@babel/core");
107
+ const transformTypescript = nodeRequire("@babel/plugin-transform-typescript");
108
+ const rawBabelOptions = nodeRequire("recast/parsers/_babel_options");
109
+ const getBabelOptions = typeof rawBabelOptions === "function"
110
+ ? rawBabelOptions
111
+ : (rawBabelOptions.default ?? (() => ({ plugins: [] })));
112
+ const babelParser = nodeRequire("recast/parsers/babel").parser;
112
113
  const ast = recast.parse(code, {
113
114
  parser: {
114
115
  parse: (source, options) => {
@@ -137,7 +138,7 @@ async function convertToJavaScript(targetDir, framework) {
137
138
  continue;
138
139
  }
139
140
  catch {
140
- // ignore recast errors, fall back to babel
141
+ // Fallback to Babel transform.
141
142
  }
142
143
  const result = await babel.transformAsync(code, {
143
144
  filename: entry.name,
@@ -148,6 +149,9 @@ async function convertToJavaScript(targetDir, framework) {
148
149
  babelrc: false,
149
150
  configFile: false,
150
151
  });
152
+ if (!result?.code) {
153
+ continue;
154
+ }
151
155
  await fs_extra_1.default.writeFile(outFile, result.code, "utf8");
152
156
  await fs_extra_1.default.remove(fullPath);
153
157
  }
@@ -190,7 +194,7 @@ async function convertToJavaScript(targetDir, framework) {
190
194
  const templateJsonPath = path_1.default.join(templatesRoot, templateName, "template.json");
191
195
  if (await fs_extra_1.default.pathExists(templateJsonPath)) {
192
196
  try {
193
- const templateJson = await fs_extra_1.default.readJson(templateJsonPath);
197
+ const templateJson = (await fs_extra_1.default.readJson(templateJsonPath));
194
198
  if (Array.isArray(templateJson.fileReplacements)) {
195
199
  fileReplacements = templateJson.fileReplacements;
196
200
  }
@@ -199,7 +203,7 @@ async function convertToJavaScript(targetDir, framework) {
199
203
  }
200
204
  }
201
205
  catch {
202
- // ignore errors reading template.json
206
+ fileReplacements = [];
203
207
  }
204
208
  }
205
209
  }
@@ -8,12 +8,20 @@ exports.detectDatabaseModules = detectDatabaseModules;
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const package_root_1 = require("../utils/package-root");
11
+ async function readJsonSafe(filePath) {
12
+ try {
13
+ return (await fs_extra_1.default.readJson(filePath));
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
11
19
  async function collectModulePkgNames(modulePath) {
12
20
  const pkgNames = [];
13
21
  const genPath = path_1.default.join(modulePath, "generator.json");
14
22
  if (await fs_extra_1.default.pathExists(genPath)) {
15
- try {
16
- const gen = await fs_extra_1.default.readJson(genPath);
23
+ const gen = await readJsonSafe(genPath);
24
+ if (gen && Array.isArray(gen.operations)) {
17
25
  if (Array.isArray(gen.operations)) {
18
26
  for (const op of gen.operations) {
19
27
  if (op.dependencies && typeof op.dependencies === "object") {
@@ -25,26 +33,17 @@ async function collectModulePkgNames(modulePath) {
25
33
  }
26
34
  }
27
35
  }
28
- catch {
29
- // ignore malformed generator
30
- }
31
36
  }
32
- // Also check module.json for declared deps
33
37
  const modJson = path_1.default.join(modulePath, "module.json");
34
38
  if (await fs_extra_1.default.pathExists(modJson)) {
35
- try {
36
- const m = (await fs_extra_1.default.readJson(modJson));
37
- if (m && typeof m === "object") {
38
- const deps = m.dependencies || {};
39
- if (typeof deps === "object")
40
- pkgNames.push(...Object.keys(deps));
41
- const devDeps = m.devDependencies || {};
42
- if (typeof devDeps === "object")
43
- pkgNames.push(...Object.keys(devDeps));
44
- }
45
- }
46
- catch {
47
- // ignore malformed module.json
39
+ const moduleJson = await readJsonSafe(modJson);
40
+ if (moduleJson && typeof moduleJson === "object") {
41
+ const deps = moduleJson.dependencies || {};
42
+ if (typeof deps === "object")
43
+ pkgNames.push(...Object.keys(deps));
44
+ const devDeps = moduleJson.devDependencies || {};
45
+ if (typeof devDeps === "object")
46
+ pkgNames.push(...Object.keys(devDeps));
48
47
  }
49
48
  }
50
49
  return Array.from(new Set(pkgNames));
@@ -60,17 +59,12 @@ async function detectAuthModules(packageJson) {
60
59
  try {
61
60
  const modulePath = path_1.default.join(modulesDir, authDir);
62
61
  const pkgNames = await collectModulePkgNames(modulePath);
63
- // Fallback: check module.json provider/name for display
64
62
  let moduleName = authDir;
65
63
  const modJson = path_1.default.join(modulePath, "module.json");
66
64
  if (await fs_extra_1.default.pathExists(modJson)) {
67
- try {
68
- const m = (await fs_extra_1.default.readJson(modJson));
69
- if (m && m.name)
70
- moduleName = m.name;
71
- }
72
- catch {
73
- // ignore malformed module.json
65
+ const moduleJson = await readJsonSafe(modJson);
66
+ if (moduleJson?.name) {
67
+ moduleName = moduleJson.name;
74
68
  }
75
69
  }
76
70
  for (const pkg of pkgNames) {
@@ -81,13 +75,13 @@ async function detectAuthModules(packageJson) {
81
75
  }
82
76
  }
83
77
  catch {
84
- // ignore per-module errors
78
+ continue;
85
79
  }
86
80
  }
87
81
  }
88
82
  }
89
83
  catch {
90
- // ignore discovery errors
84
+ return Array.from(new Set(modules));
91
85
  }
92
86
  return Array.from(new Set(modules));
93
87
  }
@@ -105,13 +99,9 @@ async function detectDatabaseModules(packageJson) {
105
99
  let moduleName = dbDir;
106
100
  const modJson = path_1.default.join(modulePath, "module.json");
107
101
  if (await fs_extra_1.default.pathExists(modJson)) {
108
- try {
109
- const m = await fs_extra_1.default.readJson(modJson);
110
- if (m && m.name)
111
- moduleName = m.name;
112
- }
113
- catch {
114
- // ignore malformed module.json
102
+ const moduleJson = await readJsonSafe(modJson);
103
+ if (moduleJson?.name) {
104
+ moduleName = moduleJson.name;
115
105
  }
116
106
  }
117
107
  for (const pkg of pkgNames) {
@@ -122,13 +112,13 @@ async function detectDatabaseModules(packageJson) {
122
112
  }
123
113
  }
124
114
  catch {
125
- // ignore per-module errors
115
+ continue;
126
116
  }
127
117
  }
128
118
  }
129
119
  }
130
120
  catch {
131
- // ignore discovery errors
121
+ return Array.from(new Set(modules));
132
122
  }
133
123
  return Array.from(new Set(modules));
134
124
  }
@@ -26,28 +26,13 @@ export interface DiscoveredModules {
26
26
  databases: ModuleMetadata[];
27
27
  auth: ModuleMetadata[];
28
28
  }
29
- /**
30
- * Discover all available modules from the modules directory
31
- */
32
29
  export declare function discoverModules(modulesDir: string): Promise<DiscoveredModules>;
33
- /**
34
- * Get valid database options for CLI
35
- */
36
30
  export declare function getValidDatabaseOptions(databases: ModuleMetadata[]): string[];
37
- /**
38
- * Get valid auth options for CLI
39
- */
40
31
  export declare function getValidAuthOptions(authModules: ModuleMetadata[]): string[];
41
- /**
42
- * Get compatible auth options for given framework and database
43
- */
44
32
  export declare function getCompatibleAuthOptions(authModules: ModuleMetadata[], framework: string, database: string, frameworksMeta?: ModuleMetadata[]): Array<{
45
33
  name: string;
46
34
  value: string;
47
35
  }>;
48
- /**
49
- * Get database choices for inquirer prompts
50
- */
51
36
  export declare function getDatabaseChoices(databases: ModuleMetadata[], framework: string): Array<{
52
37
  name: string;
53
38
  value: string;