stackkit 0.2.2 → 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 (34) hide show
  1. package/bin/stackkit.js +10 -3
  2. package/dist/cli/add.js +188 -61
  3. package/dist/cli/create.js +75 -35
  4. package/dist/cli/doctor.js +36 -161
  5. package/dist/cli/list.js +10 -40
  6. package/dist/index.js +6 -6
  7. package/dist/lib/conversion/js-conversion.js +27 -11
  8. package/dist/lib/discovery/installed-detection.d.ts +7 -0
  9. package/dist/lib/discovery/installed-detection.js +134 -0
  10. package/dist/lib/discovery/module-discovery.d.ts +1 -1
  11. package/dist/lib/discovery/module-discovery.js +26 -17
  12. package/dist/lib/discovery/shared.js +9 -7
  13. package/dist/lib/generation/code-generator.d.ts +2 -0
  14. package/dist/lib/generation/code-generator.js +98 -4
  15. package/dist/lib/generation/generator-utils.d.ts +1 -1
  16. package/dist/lib/generation/generator-utils.js +5 -3
  17. package/dist/lib/project/detect.js +59 -29
  18. package/dist/types/index.d.ts +21 -17
  19. package/modules/auth/better-auth/files/lib/auth.ts +2 -2
  20. package/package.json +13 -10
  21. package/templates/express/gitignore +23 -0
  22. package/templates/nextjs/gitignore +42 -0
  23. package/templates/nextjs/next-env.d.ts +6 -0
  24. package/templates/react/dist/assets/index-D4AHT4dU.js +193 -0
  25. package/templates/react/dist/assets/index-rpwj5ZOX.css +1 -0
  26. package/templates/react/dist/index.html +14 -0
  27. package/templates/react/dist/vite.svg +1 -0
  28. package/templates/react/gitignore +44 -0
  29. package/templates/react/src/utils/utils.ts +1 -1
  30. /package/templates/express/{.env.example → env.example} +0 -0
  31. /package/templates/nextjs/{.env.example → env.example} +0 -0
  32. /package/templates/react/{.env.example → env.example} +0 -0
  33. /package/templates/react/{.prettierignore → prettierignore} +0 -0
  34. /package/templates/react/{.prettierrc → prettierrc} +0 -0
@@ -7,12 +7,13 @@ exports.doctorCommand = doctorCommand;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const path_1 = __importDefault(require("path"));
10
+ const installed_detection_1 = require("../lib/discovery/installed-detection");
10
11
  const logger_1 = require("../lib/ui/logger");
11
12
  const package_root_1 = require("../lib/utils/package-root");
12
13
  // Constants for consistent messaging
13
14
  const MESSAGES = {
14
15
  NO_PACKAGE_JSON: "No package.json found in current directory or any parent directory.",
15
- UNSUPPORTED_PROJECT: "Unsupported project type. Only Next.js, Express, and React projects are supported.",
16
+ UNSUPPORTED_PROJECT: "Unsupported project type or unable to detect framework.",
16
17
  NODE_TOO_OLD: (version) => `Node.js version ${version} is not supported. Minimum required: Node 18.`,
17
18
  NODE_WARNING: (version) => `Node.js version ${version} is supported but Node 20+ is recommended.`,
18
19
  NODE_SUCCESS: (version) => `Node.js version ${version} is supported.`,
@@ -84,8 +85,8 @@ async function runDoctorChecks() {
84
85
  }
85
86
  const nodeVersionCheck = checkNodeVersion();
86
87
  checks.push(nodeVersionCheck);
87
- const authModules = detectAuthModules(packageJson);
88
- const databaseModules = detectDatabaseModules(packageJson);
88
+ const authModules = await (0, installed_detection_1.detectAuthModules)(packageJson);
89
+ const databaseModules = await (0, installed_detection_1.detectDatabaseModules)(packageJson);
89
90
  const filesCheck = await checkKeyFiles(projectRoot, projectType, authModules, databaseModules);
90
91
  checks.push(...filesCheck);
91
92
  const envCheck = await checkEnvFiles(projectRoot, authModules, databaseModules);
@@ -124,7 +125,7 @@ async function runDoctorChecks() {
124
125
  prismaSchema: databaseModules.includes("prisma")
125
126
  ? await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, "prisma", "schema.prisma"))
126
127
  : undefined,
127
- authRoutes: authModules.length > 0 ? await checkAuthRoutesExist(projectRoot, projectType) : undefined,
128
+ authRoutes: authModules.length > 0 ? await checkAuthRoutesExist(projectRoot) : undefined,
128
129
  tsconfig: await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, "tsconfig.json")),
129
130
  eslintConfig: await checkEslintConfigExists(projectRoot),
130
131
  git: await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, ".git")),
@@ -173,6 +174,29 @@ async function detectPackageManager(projectRoot) {
173
174
  }
174
175
  function detectProjectType(packageJson) {
175
176
  const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
177
+ // Try to detect using available templates
178
+ try {
179
+ const templatesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "templates");
180
+ if (fs_extra_1.default.existsSync(templatesDir)) {
181
+ const dirs = fs_extra_1.default.readdirSync(templatesDir);
182
+ for (const d of dirs) {
183
+ const tplPath = path_1.default.join(templatesDir, d, "template.json");
184
+ if (!fs_extra_1.default.existsSync(tplPath))
185
+ continue;
186
+ try {
187
+ const tpl = JSON.parse(fs_extra_1.default.readFileSync(tplPath, "utf-8"));
188
+ if (tpl && tpl.framework && deps[tpl.framework])
189
+ return tpl.framework;
190
+ }
191
+ catch {
192
+ // ignore
193
+ }
194
+ }
195
+ }
196
+ }
197
+ catch {
198
+ // ignore template-based detection errors
199
+ }
176
200
  if (deps.next) {
177
201
  return "nextjs";
178
202
  }
@@ -209,129 +233,7 @@ function checkNodeVersion() {
209
233
  };
210
234
  }
211
235
  }
212
- function detectAuthModules(packageJson) {
213
- const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
214
- const modules = [];
215
- try {
216
- const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules", "auth");
217
- if (fs_extra_1.default.existsSync(modulesDir)) {
218
- const authDirs = fs_extra_1.default.readdirSync(modulesDir);
219
- for (const authDir of authDirs) {
220
- try {
221
- const genPath = path_1.default.join(modulesDir, authDir, "generator.json");
222
- const modJson = path_1.default.join(modulesDir, authDir, "module.json");
223
- let pkgNames = [];
224
- if (fs_extra_1.default.existsSync(genPath)) {
225
- const gen = JSON.parse(fs_extra_1.default.readFileSync(genPath, "utf-8"));
226
- if (Array.isArray(gen.operations)) {
227
- for (const op of gen.operations) {
228
- if (op.dependencies && typeof op.dependencies === "object") {
229
- pkgNames.push(...Object.keys(op.dependencies));
230
- }
231
- if (op.devDependencies && typeof op.devDependencies === "object") {
232
- pkgNames.push(...Object.keys(op.devDependencies));
233
- }
234
- }
235
- }
236
- }
237
- // Fallback: check module.json provider/name
238
- let moduleName = authDir;
239
- if (fs_extra_1.default.existsSync(modJson)) {
240
- try {
241
- const m = JSON.parse(fs_extra_1.default.readFileSync(modJson, "utf-8"));
242
- if (m && m.name)
243
- moduleName = m.name;
244
- }
245
- catch {
246
- /* ignore */
247
- }
248
- }
249
- for (const pkg of pkgNames) {
250
- if (deps[pkg]) {
251
- modules.push(moduleName);
252
- break;
253
- }
254
- }
255
- }
256
- catch {
257
- // ignore per-module errors
258
- }
259
- }
260
- }
261
- }
262
- catch {
263
- // ignore discovery errors
264
- }
265
- // Fallback to original simple checks if nothing found
266
- if (modules.length === 0) {
267
- if (deps["better-auth"])
268
- modules.push("better-auth");
269
- if (deps["next-auth"])
270
- modules.push("authjs");
271
- }
272
- return Array.from(new Set(modules));
273
- }
274
- function detectDatabaseModules(packageJson) {
275
- const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
276
- const modules = [];
277
- try {
278
- const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules", "database");
279
- if (fs_extra_1.default.existsSync(modulesDir)) {
280
- const dbDirs = fs_extra_1.default.readdirSync(modulesDir);
281
- for (const dbDir of dbDirs) {
282
- try {
283
- const genPath = path_1.default.join(modulesDir, dbDir, "generator.json");
284
- const modJson = path_1.default.join(modulesDir, dbDir, "module.json");
285
- let pkgNames = [];
286
- if (fs_extra_1.default.existsSync(genPath)) {
287
- const gen = JSON.parse(fs_extra_1.default.readFileSync(genPath, "utf-8"));
288
- if (Array.isArray(gen.operations)) {
289
- for (const op of gen.operations) {
290
- if (op.dependencies && typeof op.dependencies === "object") {
291
- pkgNames.push(...Object.keys(op.dependencies));
292
- }
293
- if (op.devDependencies && typeof op.devDependencies === "object") {
294
- pkgNames.push(...Object.keys(op.devDependencies));
295
- }
296
- }
297
- }
298
- }
299
- let moduleName = dbDir;
300
- if (fs_extra_1.default.existsSync(modJson)) {
301
- try {
302
- const m = JSON.parse(fs_extra_1.default.readFileSync(modJson, "utf-8"));
303
- if (m && m.name)
304
- moduleName = m.name;
305
- }
306
- catch {
307
- /* ignore */
308
- }
309
- }
310
- for (const pkg of pkgNames) {
311
- if (deps[pkg]) {
312
- modules.push(moduleName);
313
- break;
314
- }
315
- }
316
- }
317
- catch {
318
- // ignore per-module errors
319
- }
320
- }
321
- }
322
- }
323
- catch {
324
- // ignore discovery errors
325
- }
326
- // Fallback to original checks if nothing found
327
- if (modules.length === 0) {
328
- if (deps["@prisma/client"] || deps["prisma"])
329
- modules.push("prisma");
330
- if (deps["mongoose"])
331
- modules.push("mongoose");
332
- }
333
- return Array.from(new Set(modules));
334
- }
236
+ // Module detection is delegated to shared utilities in `lib/discovery`.
335
237
  async function checkKeyFiles(projectRoot, projectType, authModules, databaseModules) {
336
238
  const checks = [];
337
239
  const envExampleExists = await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, ".env.example"));
@@ -348,8 +250,8 @@ async function checkKeyFiles(projectRoot, projectType, authModules, databaseModu
348
250
  message: schemaExists ? "Prisma schema found" : "Prisma schema missing (required for Prisma)",
349
251
  });
350
252
  }
351
- if (authModules.length > 0 && projectType === "nextjs") {
352
- const authRoutesExist = await checkAuthRoutesExist(projectRoot, projectType);
253
+ if (authModules.length > 0) {
254
+ const authRoutesExist = await checkAuthRoutesExist(projectRoot);
353
255
  checks.push({
354
256
  status: authRoutesExist ? "success" : "warning",
355
257
  message: authRoutesExist
@@ -359,9 +261,7 @@ async function checkKeyFiles(projectRoot, projectType, authModules, databaseModu
359
261
  }
360
262
  return checks;
361
263
  }
362
- async function checkAuthRoutesExist(projectRoot, projectType) {
363
- if (projectType !== "nextjs")
364
- return true; // Skip for non-Next.js
264
+ async function checkAuthRoutesExist(projectRoot) {
365
265
  // Build candidate auth route paths from generator.json files in modules/auth
366
266
  const candidates = new Set();
367
267
  try {
@@ -396,23 +296,8 @@ async function checkAuthRoutesExist(projectRoot, projectType) {
396
296
  catch {
397
297
  // ignore discovery errors
398
298
  }
399
- // Fallback to known common paths if generators don't provide any
400
- const fallback = [
401
- "app/api/auth/[...nextauth]/route.ts",
402
- "app/api/auth/[...nextauth]/route.js",
403
- "src/app/api/auth/[...nextauth]/route.ts",
404
- "src/app/api/auth/[...nextauth]/route.js",
405
- "pages/api/auth/[...nextauth].ts",
406
- "pages/api/auth/[...nextauth].js",
407
- "src/pages/api/auth/[...nextauth].ts",
408
- "src/pages/api/auth/[...nextauth].js",
409
- "app/api/auth/[...all]/route.ts",
410
- "app/api/auth/[...all]/route.js",
411
- "src/app/api/auth/[...all]/route.ts",
412
- "src/app/api/auth/[...all]/route.js",
413
- ];
414
- for (const p of fallback)
415
- candidates.add(p);
299
+ if (candidates.size === 0)
300
+ return false;
416
301
  for (const routePath of candidates) {
417
302
  if (await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, routePath))) {
418
303
  return true;
@@ -468,16 +353,7 @@ async function checkEnvFiles(projectRoot, authModules, databaseModules) {
468
353
  }
469
354
  }
470
355
  catch {
471
- // fallback to previous minimal checks if discovery fails
472
- if (databaseModules.includes("prisma")) {
473
- requiredKeys.push("DATABASE_URL");
474
- }
475
- if (authModules.includes("authjs")) {
476
- requiredKeys.push("NEXTAUTH_SECRET", "NEXTAUTH_URL");
477
- }
478
- if (authModules.includes("better-auth")) {
479
- requiredKeys.push("BETTER_AUTH_SECRET", "BETTER_AUTH_URL");
480
- }
356
+ // If discovery fails, keep requiredKeys empty rather than using hard-coded defaults.
481
357
  }
482
358
  const envPaths = [".env", ".env.local"];
483
359
  let envContent = "";
@@ -563,7 +439,6 @@ async function checkDependencies(packageJson) {
563
439
  // Assume up to date if using flexible versioning
564
440
  }
565
441
  else {
566
- // Assume outdated if using exact versions (simplified check)
567
442
  outdated.push(name);
568
443
  }
569
444
  }
@@ -603,7 +478,7 @@ function generateSuggestions(authModules, databaseModules) {
603
478
  suggestions.push("stackkit add auth - Add authentication module");
604
479
  }
605
480
  if (databaseModules.length === 0) {
606
- suggestions.push("stackkit add db - Add database module");
481
+ suggestions.push("stackkit add database - Add database module");
607
482
  }
608
483
  // Always show available commands
609
484
  suggestions.push("stackkit list - View available modules");
package/dist/cli/list.js CHANGED
@@ -7,7 +7,6 @@ exports.listCommand = listCommand;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const path_1 = __importDefault(require("path"));
10
- const module_discovery_1 = require("../lib/discovery/module-discovery");
11
10
  const shared_1 = require("../lib/discovery/shared");
12
11
  const logger_1 = require("../lib/ui/logger");
13
12
  const package_root_1 = require("../lib/utils/package-root");
@@ -28,7 +27,7 @@ async function listCommand(options) {
28
27
  frameworks.forEach((framework, index) => {
29
28
  const isLast = index === frameworks.length - 1;
30
29
  const prefix = isLast ? "└──" : "├──";
31
- logger_1.logger.log(` ${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(framework.displayName)}`);
30
+ logger_1.logger.log(` ${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(framework.displayName || framework.name)}`);
32
31
  });
33
32
  logger_1.logger.newLine();
34
33
  }
@@ -36,22 +35,14 @@ async function listCommand(options) {
36
35
  if (showModules) {
37
36
  const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules");
38
37
  const modules = await getAvailableModules(modulesDir);
39
- // Discover modules to derive provider lists dynamically
40
- let discovered;
41
- try {
42
- discovered = await (0, module_discovery_1.discoverModules)(path_1.default.join((0, package_root_1.getPackageRoot)(), "modules"));
43
- }
44
- catch {
45
- discovered = { frameworks: [], databases: [], auth: [] };
46
- }
47
38
  if (modules.length > 0) {
48
39
  hasModules = true;
49
40
  logger_1.logger.log(chalk_1.default.bold.magenta("MODULES"));
50
41
  const grouped = modules.reduce((acc, mod) => {
51
- if (!acc[mod.category]) {
52
- acc[mod.category] = [];
53
- }
54
- acc[mod.category].push(mod);
42
+ const cat = mod.category || "other";
43
+ if (!acc[cat])
44
+ acc[cat] = [];
45
+ acc[cat].push(mod);
55
46
  return acc;
56
47
  }, {});
57
48
  const categories = Object.keys(grouped);
@@ -78,32 +69,11 @@ async function listCommand(options) {
78
69
  : isLastMod
79
70
  ? "│ └──"
80
71
  : "│ ├──";
81
- // Compute provider names from discovered database choices
82
- const choices = (0, module_discovery_1.getDatabaseChoices)(discovered.databases || [], "nextjs");
83
- const prismaProviders = choices
84
- .filter((c) => c.value.startsWith("prisma-"))
85
- .map((c) => {
86
- const m = c.name.match(/\(([^)]+)\)/);
87
- return m ? m[1] : c.name;
88
- });
89
- const providersText = prismaProviders.length > 0
90
- ? prismaProviders.join(", ")
91
- : (() => {
92
- const detected = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)()).map((p) => {
93
- if (p === "postgresql")
94
- return "PostgreSQL";
95
- if (p === "mongodb")
96
- return "MongoDB";
97
- if (p === "mysql")
98
- return "MySQL";
99
- if (p === "sqlite")
100
- return "SQLite";
101
- return p;
102
- });
103
- return detected.length > 0
104
- ? detected.join(", ")
105
- : "PostgreSQL, MongoDB, MySQL, SQLite";
106
- })();
72
+ // Derive provider list directly from the Prisma generator metadata
73
+ const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
74
+ const providersText = providers.length
75
+ ? providers.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(", ")
76
+ : "None";
107
77
  logger_1.logger.log(` ${chalk_1.default.gray(providerPrefix)} ${chalk_1.default.dim(`Providers: ${providersText}`)}`);
108
78
  }
109
79
  });
package/dist/index.js CHANGED
@@ -78,7 +78,7 @@ function buildOptionHints() {
78
78
  }
79
79
  }
80
80
  catch {
81
- /* ignore */
81
+ // ignore malformed module.json
82
82
  }
83
83
  }
84
84
  }
@@ -93,18 +93,18 @@ function buildOptionHints() {
93
93
  auths.push(m.name);
94
94
  }
95
95
  catch {
96
- /* ignore */
96
+ // ignore malformed module.json
97
97
  }
98
98
  }
99
99
  }
100
100
  }
101
101
  return {
102
- databaseHint: dbs.length > 0 ? dbs.join(", ") : "prisma, mongoose, none",
103
- authHint: auths.length > 0 ? auths.join(", ") : "better-auth, authjs, none",
102
+ databaseHint: dbs.length > 0 ? dbs.join(", ") : "none",
103
+ authHint: auths.length > 0 ? auths.join(", ") : "none",
104
104
  };
105
105
  }
106
106
  catch {
107
- return { databaseHint: "prisma, mongoose, none", authHint: "better-auth, authjs, none" };
107
+ return { databaseHint: "none", authHint: "none" };
108
108
  }
109
109
  }
110
110
  const hints = buildOptionHints();
@@ -134,7 +134,7 @@ program
134
134
  .command("create [project-name]")
135
135
  .description("Create a new StackKit project")
136
136
  .usage("[project-name] [options]")
137
- .option("-f, --framework <framework>", "Framework: nextjs, express, react")
137
+ .option("-f, --framework <framework>", "Framework (discovered)")
138
138
  .option("-d, --database <database>", `Database: ${hints.databaseHint}`)
139
139
  .option("--prisma-provider <provider>", "Prisma provider")
140
140
  .option("-a, --auth <auth>", `Auth: ${hints.authHint}`)
@@ -7,6 +7,7 @@ exports.convertToJavaScript = convertToJavaScript;
7
7
  /* eslint-disable @typescript-eslint/no-require-imports */
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const path_1 = __importDefault(require("path"));
10
+ const logger_1 = require("../ui/logger");
10
11
  const package_root_1 = require("../utils/package-root");
11
12
  const baseDirs = {
12
13
  express: "./src",
@@ -41,6 +42,32 @@ async function convertToJavaScript(targetDir, framework) {
41
42
  };
42
43
  await removeDtsFiles(targetDir);
43
44
  const babel = require("@babel/core");
45
+ const checkModule = (name) => {
46
+ try {
47
+ require.resolve(name);
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ };
54
+ const hasRecast = checkModule("recast");
55
+ const hasBabelParser = checkModule("@babel/parser");
56
+ const hasTransformTypescript = checkModule("@babel/plugin-transform-typescript");
57
+ if (!hasRecast || !hasBabelParser || !hasTransformTypescript) {
58
+ const packageRoot = (0, package_root_1.getPackageRoot)();
59
+ const missing = [];
60
+ if (!hasRecast)
61
+ missing.push("recast");
62
+ if (!hasBabelParser)
63
+ missing.push("@babel/parser");
64
+ if (!hasTransformTypescript)
65
+ missing.push("@babel/plugin-transform-typescript");
66
+ logger_1.logger.warn(`Optional tooling missing: ${missing.join(", ")}. Generated JavaScript may contain transformed JSX.`);
67
+ if (process.env.STACKKIT_VERBOSE === "1" || process.env.DEBUG) {
68
+ logger_1.logger.info(`To ensure generated JavaScript preserves JSX, add these to the CLI package dependencies or run 'pnpm install' in ${packageRoot}`);
69
+ }
70
+ }
44
71
  const transpileAllTsFiles = async (dir) => {
45
72
  const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
46
73
  for (const entry of entries) {
@@ -73,20 +100,10 @@ async function convertToJavaScript(targetDir, framework) {
73
100
  },
74
101
  ],
75
102
  ];
76
- if (isTsx) {
77
- presets.push([
78
- require.resolve("@babel/preset-react"),
79
- {
80
- runtime: "automatic",
81
- },
82
- ]);
83
- }
84
- // Use recast + Babel AST transform (same approach as transform.tools)
85
103
  try {
86
104
  const recast = require("recast");
87
105
  const { transformFromAstSync } = require("@babel/core");
88
106
  const transformTypescript = require("@babel/plugin-transform-typescript");
89
- // getBabelOptions may be exported as default or directly
90
107
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
108
  let getBabelOptions = require("recast/parsers/_babel_options");
92
109
  if (getBabelOptions && getBabelOptions.default)
@@ -96,7 +113,6 @@ async function convertToJavaScript(targetDir, framework) {
96
113
  parser: {
97
114
  parse: (source, options) => {
98
115
  const babelOptions = getBabelOptions(options || {});
99
- // ensure typescript and jsx handling
100
116
  if (isTsx) {
101
117
  babelOptions.plugins.push("typescript", "jsx");
102
118
  }
@@ -0,0 +1,7 @@
1
+ interface PackageJsonLike {
2
+ dependencies?: Record<string, string>;
3
+ devDependencies?: Record<string, string>;
4
+ }
5
+ export declare function detectAuthModules(packageJson: PackageJsonLike): Promise<string[]>;
6
+ export declare function detectDatabaseModules(packageJson: PackageJsonLike): Promise<string[]>;
7
+ export {};
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.detectAuthModules = detectAuthModules;
7
+ exports.detectDatabaseModules = detectDatabaseModules;
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const package_root_1 = require("../utils/package-root");
11
+ async function collectModulePkgNames(modulePath) {
12
+ const pkgNames = [];
13
+ const genPath = path_1.default.join(modulePath, "generator.json");
14
+ if (await fs_extra_1.default.pathExists(genPath)) {
15
+ try {
16
+ const gen = await fs_extra_1.default.readJson(genPath);
17
+ if (Array.isArray(gen.operations)) {
18
+ for (const op of gen.operations) {
19
+ if (op.dependencies && typeof op.dependencies === "object") {
20
+ pkgNames.push(...Object.keys(op.dependencies));
21
+ }
22
+ if (op.devDependencies && typeof op.devDependencies === "object") {
23
+ pkgNames.push(...Object.keys(op.devDependencies));
24
+ }
25
+ }
26
+ }
27
+ }
28
+ catch {
29
+ // ignore malformed generator
30
+ }
31
+ }
32
+ // Also check module.json for declared deps
33
+ const modJson = path_1.default.join(modulePath, "module.json");
34
+ 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
48
+ }
49
+ }
50
+ return Array.from(new Set(pkgNames));
51
+ }
52
+ async function detectAuthModules(packageJson) {
53
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
54
+ const modules = [];
55
+ try {
56
+ const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules", "auth");
57
+ if (await fs_extra_1.default.pathExists(modulesDir)) {
58
+ const authDirs = await fs_extra_1.default.readdir(modulesDir);
59
+ for (const authDir of authDirs) {
60
+ try {
61
+ const modulePath = path_1.default.join(modulesDir, authDir);
62
+ const pkgNames = await collectModulePkgNames(modulePath);
63
+ // Fallback: check module.json provider/name for display
64
+ let moduleName = authDir;
65
+ const modJson = path_1.default.join(modulePath, "module.json");
66
+ 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
74
+ }
75
+ }
76
+ for (const pkg of pkgNames) {
77
+ if (deps[pkg]) {
78
+ modules.push(moduleName);
79
+ break;
80
+ }
81
+ }
82
+ }
83
+ catch {
84
+ // ignore per-module errors
85
+ }
86
+ }
87
+ }
88
+ }
89
+ catch {
90
+ // ignore discovery errors
91
+ }
92
+ return Array.from(new Set(modules));
93
+ }
94
+ async function detectDatabaseModules(packageJson) {
95
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
96
+ const modules = [];
97
+ try {
98
+ const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules", "database");
99
+ if (await fs_extra_1.default.pathExists(modulesDir)) {
100
+ const dbDirs = await fs_extra_1.default.readdir(modulesDir);
101
+ for (const dbDir of dbDirs) {
102
+ try {
103
+ const modulePath = path_1.default.join(modulesDir, dbDir);
104
+ const pkgNames = await collectModulePkgNames(modulePath);
105
+ let moduleName = dbDir;
106
+ const modJson = path_1.default.join(modulePath, "module.json");
107
+ 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
115
+ }
116
+ }
117
+ for (const pkg of pkgNames) {
118
+ if (deps[pkg]) {
119
+ modules.push(moduleName);
120
+ break;
121
+ }
122
+ }
123
+ }
124
+ catch {
125
+ // ignore per-module errors
126
+ }
127
+ }
128
+ }
129
+ }
130
+ catch {
131
+ // ignore discovery errors
132
+ }
133
+ return Array.from(new Set(modules));
134
+ }
@@ -41,7 +41,7 @@ export declare function getValidAuthOptions(authModules: ModuleMetadata[]): stri
41
41
  /**
42
42
  * Get compatible auth options for given framework and database
43
43
  */
44
- export declare function getCompatibleAuthOptions(authModules: ModuleMetadata[], framework: string, database: string): Array<{
44
+ export declare function getCompatibleAuthOptions(authModules: ModuleMetadata[], framework: string, database: string, frameworksMeta?: ModuleMetadata[]): Array<{
45
45
  name: string;
46
46
  value: string;
47
47
  }>;