create-stackkit-app 0.4.4 → 0.4.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 (72) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +61 -4
  3. package/dist/lib/code-generator.d.ts +80 -0
  4. package/dist/lib/code-generator.js +541 -0
  5. package/dist/lib/create-project.d.ts +20 -1
  6. package/dist/lib/create-project.js +154 -96
  7. package/dist/lib/framework-utils.d.ts +22 -0
  8. package/dist/lib/framework-utils.js +74 -0
  9. package/dist/lib/utils/logger.d.ts +16 -0
  10. package/dist/lib/utils/logger.js +59 -0
  11. package/dist/lib/utils/module-discovery.d.ts +62 -0
  12. package/dist/lib/utils/module-discovery.js +180 -0
  13. package/dist/lib/utils/package-utils.js +2 -2
  14. package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +6 -0
  15. package/modules/auth/authjs/files/lib/auth-client.ts +11 -0
  16. package/modules/auth/authjs/files/lib/auth.ts +36 -0
  17. package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
  18. package/modules/auth/authjs/module.json +22 -0
  19. package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
  20. package/modules/auth/better-auth/files/lib/auth.ts +77 -1
  21. package/modules/auth/better-auth/files/lib/email-service.ts +34 -0
  22. package/modules/auth/better-auth/files/lib/email-templates.ts +89 -0
  23. package/modules/auth/better-auth/files/schemas/prisma-schema.prisma +7 -7
  24. package/modules/auth/better-auth/generator.json +83 -0
  25. package/modules/auth/better-auth/module.json +17 -34
  26. package/modules/database/mongoose/files/lib/db.ts +63 -0
  27. package/modules/database/{mongoose-mongodb → mongoose}/files/models/User.ts +0 -5
  28. package/modules/database/mongoose/generator.json +33 -0
  29. package/modules/database/mongoose/module.json +15 -0
  30. package/modules/database/prisma/files/lib/prisma.ts +7 -4
  31. package/modules/database/prisma/files/prisma/schema.prisma +1 -1
  32. package/modules/database/prisma/files/prisma.config.ts +2 -2
  33. package/modules/database/prisma/generator.json +46 -0
  34. package/modules/database/prisma/module.json +6 -132
  35. package/package.json +1 -1
  36. package/templates/express/.env.example +0 -1
  37. package/templates/express/package.json +4 -4
  38. package/templates/express/src/app.ts +2 -2
  39. package/templates/express/src/features/health/health.controller.ts +18 -0
  40. package/templates/express/src/features/health/health.route.ts +9 -0
  41. package/templates/express/src/features/health/health.service.ts +6 -0
  42. package/templates/express/template.json +6 -19
  43. package/templates/nextjs/lib/env.ts +8 -0
  44. package/templates/nextjs/package.json +7 -7
  45. package/templates/nextjs/template.json +5 -1
  46. package/templates/react-vite/.env.example +1 -2
  47. package/templates/react-vite/.prettierignore +4 -0
  48. package/templates/react-vite/.prettierrc +9 -0
  49. package/templates/react-vite/README.md +22 -0
  50. package/templates/react-vite/package.json +16 -16
  51. package/templates/react-vite/src/router.tsx +0 -12
  52. package/templates/react-vite/template.json +6 -14
  53. package/templates/react-vite/vite.config.ts +0 -6
  54. package/dist/lib/utils/config-utils.d.ts +0 -2
  55. package/dist/lib/utils/config-utils.js +0 -33
  56. package/dist/lib/utils/file-utils.d.ts +0 -8
  57. package/dist/lib/utils/file-utils.js +0 -75
  58. package/dist/lib/utils/module-utils.d.ts +0 -2
  59. package/dist/lib/utils/module-utils.js +0 -311
  60. package/modules/auth/clerk/files/express/auth.ts +0 -7
  61. package/modules/auth/clerk/files/nextjs/auth-provider.tsx +0 -5
  62. package/modules/auth/clerk/files/nextjs/middleware.ts +0 -9
  63. package/modules/auth/clerk/files/react/auth-provider.tsx +0 -15
  64. package/modules/auth/clerk/module.json +0 -115
  65. package/modules/database/mongoose-mongodb/files/lib/db.ts +0 -78
  66. package/modules/database/mongoose-mongodb/module.json +0 -70
  67. package/templates/express/src/features/auth/auth.controller.ts +0 -48
  68. package/templates/express/src/features/auth/auth.route.ts +0 -10
  69. package/templates/express/src/features/auth/auth.service.ts +0 -21
  70. package/templates/react-vite/src/api/services/user.service.ts +0 -18
  71. package/templates/react-vite/src/pages/UserProfile.tsx +0 -40
  72. package/templates/react-vite/src/types/user.d.ts +0 -6
@@ -8,30 +8,108 @@ const chalk_1 = __importDefault(require("chalk"));
8
8
  const child_process_1 = require("child_process");
9
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
10
10
  const inquirer_1 = __importDefault(require("inquirer"));
11
- const ora_1 = __importDefault(require("ora"));
12
11
  const path_1 = __importDefault(require("path"));
13
12
  const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
14
- const file_utils_1 = require("./utils/file-utils");
15
13
  const git_utils_1 = require("./utils/git-utils");
16
14
  const js_conversion_1 = require("./utils/js-conversion");
17
- const module_utils_1 = require("./utils/module-utils");
15
+ const logger_1 = require("./utils/logger");
16
+ const code_generator_1 = require("./code-generator");
17
+ const framework_utils_1 = require("./framework-utils");
18
18
  const package_utils_1 = require("./utils/package-utils");
19
- async function createProject(projectName) {
20
- // eslint-disable-next-line no-console
21
- console.log(chalk_1.default.bold.cyan("\n Create StackKit App\n"));
22
- const config = await getProjectConfig(projectName);
19
+ const module_discovery_1 = require("./utils/module-discovery");
20
+ async function createProject(projectName, options) {
21
+ logger_1.logger.newLine();
22
+ logger_1.logger.log(chalk_1.default.bold.cyan("Create StackKit App"));
23
+ logger_1.logger.newLine();
24
+ const config = await getProjectConfig(projectName, options);
23
25
  const targetDir = path_1.default.join(process.cwd(), config.projectName);
24
26
  if (await fs_extra_1.default.pathExists(targetDir)) {
25
- // eslint-disable-next-line no-console
26
- console.log(chalk_1.default.red(`\n✖ Directory "${config.projectName}" already exists`));
27
- // eslint-disable-next-line no-console
28
- console.log(chalk_1.default.gray("Please choose a different name or remove the existing directory.\n"));
27
+ logger_1.logger.error(`Directory "${config.projectName}" already exists`);
28
+ logger_1.logger.log(chalk_1.default.gray("Please choose a different name or remove the existing directory.\n"));
29
29
  process.exit(1);
30
30
  }
31
- await generateProject(config, targetDir);
31
+ await generateProject(config, targetDir, options);
32
32
  showNextSteps(config);
33
33
  }
34
- async function getProjectConfig(projectName) {
34
+ async function getProjectConfig(projectName, options) {
35
+ // Discover available modules
36
+ const modulesDir = path_1.default.join(__dirname, "..", "..", "modules");
37
+ const discoveredModules = await (0, module_discovery_1.discoverModules)(modulesDir);
38
+ if (options && Object.keys(options).length > 0) {
39
+ if (options.yes || options.y) {
40
+ return {
41
+ projectName: projectName || "my-app",
42
+ framework: "nextjs",
43
+ database: "prisma",
44
+ prismaProvider: "postgresql",
45
+ auth: "better-auth",
46
+ language: "typescript",
47
+ packageManager: "pnpm",
48
+ };
49
+ }
50
+ // Validate options using discovered modules
51
+ const validFrameworks = discoveredModules.frameworks.map(f => f.name);
52
+ const framework = options.framework || options.f;
53
+ if (framework && !validFrameworks.includes(framework)) {
54
+ throw new Error(`Invalid framework: ${framework}. Valid options: ${validFrameworks.join(', ')}`);
55
+ }
56
+ const validDatabases = (0, module_discovery_1.getValidDatabaseOptions)(discoveredModules.databases);
57
+ // Also allow base database names like 'prisma', 'mongoose'
58
+ const validBaseDatabases = discoveredModules.databases.map(db => db.name);
59
+ const allValidDatabases = [...validDatabases, ...validBaseDatabases];
60
+ const db = options.database || options.d;
61
+ if (db && !allValidDatabases.includes(db)) {
62
+ throw new Error(`Invalid database: ${db}. Valid options: ${allValidDatabases.filter((v, i, arr) => arr.indexOf(v) === i).join(', ')}`);
63
+ }
64
+ const validAuth = (0, module_discovery_1.getValidAuthOptions)(discoveredModules.auth);
65
+ const authOpt = options.auth || options.a;
66
+ if (authOpt && !validAuth.includes(authOpt)) {
67
+ throw new Error(`Invalid auth: ${authOpt}. Valid options: ${validAuth.join(', ')}`);
68
+ }
69
+ const validLanguages = ['typescript', 'javascript'];
70
+ const language = options.language || options.l;
71
+ if (language && !validLanguages.includes(language)) {
72
+ throw new Error(`Invalid language: ${language}. Valid options: ${validLanguages.join(', ')}`);
73
+ }
74
+ const validPackageManagers = ['pnpm', 'npm', 'yarn', 'bun'];
75
+ const pm = options.packageManager || options.p;
76
+ if (pm && !validPackageManagers.includes(pm)) {
77
+ throw new Error(`Invalid package manager: ${pm}. Valid options: ${validPackageManagers.join(', ')}`);
78
+ }
79
+ let database = "none";
80
+ let prismaProvider;
81
+ if (db && db !== "none") {
82
+ const parsed = (0, module_discovery_1.parseDatabaseOption)(db);
83
+ database = parsed.database;
84
+ prismaProvider = parsed.provider;
85
+ }
86
+ let auth = "none";
87
+ if (authOpt && authOpt !== "none") {
88
+ auth = authOpt;
89
+ }
90
+ const finalFramework = (framework || "nextjs");
91
+ if (finalFramework === "react-vite") {
92
+ database = "none";
93
+ prismaProvider = undefined;
94
+ }
95
+ // Validate auth compatibility
96
+ if (auth === "authjs" && (database !== "prisma" || finalFramework !== "nextjs")) {
97
+ throw new Error("Auth.js is only supported with Next.js and Prisma database");
98
+ }
99
+ if (auth === "better-auth" && database === "none" && finalFramework !== "react-vite") {
100
+ throw new Error("Better Auth requires a database for server frameworks");
101
+ }
102
+ return {
103
+ projectName: projectName || "my-app",
104
+ framework: finalFramework,
105
+ database,
106
+ prismaProvider,
107
+ auth,
108
+ language: (language || "typescript"),
109
+ packageManager: (pm || "pnpm"),
110
+ };
111
+ }
112
+ // Use discovered modules for interactive prompts
35
113
  const answers = (await inquirer_1.default.prompt([
36
114
  {
37
115
  type: "input",
@@ -54,26 +132,21 @@ async function getProjectConfig(projectName) {
54
132
  type: "list",
55
133
  name: "framework",
56
134
  message: "Select framework:",
57
- choices: [
58
- { name: "Next.js", value: "nextjs" },
59
- { name: "Express.js", value: "express" },
60
- { name: "React (Vite)", value: "react-vite" },
61
- ],
135
+ choices: discoveredModules.frameworks.map(f => ({
136
+ name: f.displayName,
137
+ value: f.name
138
+ })),
62
139
  },
63
140
  {
64
141
  type: "list",
65
142
  name: "database",
66
143
  message: "Select database/ORM:",
67
144
  when: (answers) => answers.framework !== "react-vite",
68
- choices: [
69
- { name: "Prisma", value: "prisma" },
70
- { name: "Mongoose + MongoDB", value: "mongoose-mongodb" },
71
- { name: "None", value: "none" },
72
- ],
145
+ choices: (answers) => (0, module_discovery_1.getDatabaseChoices)(discoveredModules.databases, answers.framework),
73
146
  },
74
147
  {
75
148
  type: "list",
76
- name: "dbProvider",
149
+ name: "prismaProvider",
77
150
  message: "Select database provider for Prisma:",
78
151
  when: (answers) => answers.database === "prisma",
79
152
  choices: [
@@ -87,34 +160,8 @@ async function getProjectConfig(projectName) {
87
160
  type: "list",
88
161
  name: "auth",
89
162
  message: "Select authentication:",
90
- when: (answers) => answers.database !== "none" || answers.framework === "react-vite",
91
- choices: (answers) => {
92
- if (answers.framework === "react-vite") {
93
- return [
94
- { name: "Better Auth", value: "better-auth" },
95
- { name: "Clerk", value: "clerk" },
96
- { name: "None", value: "none" },
97
- ];
98
- }
99
- // Next.js apps
100
- if (answers.framework === "nextjs") {
101
- return [
102
- { name: "Better Auth", value: "better-auth" },
103
- { name: "Clerk", value: "clerk" },
104
- { name: "None", value: "none" },
105
- ];
106
- }
107
- // Express apps
108
- if (answers.framework === "express") {
109
- return [
110
- { name: "Better Auth", value: "better-auth" },
111
- { name: "Clerk", value: "clerk" },
112
- { name: "None", value: "none" },
113
- ];
114
- }
115
- // Default - no auth
116
- return [{ name: "None", value: "none" }];
117
- },
163
+ when: (answers) => (answers.database !== "none" || answers.framework === "react-vite"),
164
+ choices: (answers) => (0, module_discovery_1.getCompatibleAuthOptions)(discoveredModules.auth, answers.framework, answers.database || "none"),
118
165
  },
119
166
  {
120
167
  type: "list",
@@ -139,20 +186,21 @@ async function getProjectConfig(projectName) {
139
186
  default: "pnpm",
140
187
  },
141
188
  ]));
189
+ const parsedDb = answers.database ? (0, module_discovery_1.parseDatabaseOption)(answers.database) : { database: 'none' };
142
190
  return {
143
191
  projectName: (projectName || answers.projectName),
144
192
  framework: answers.framework,
145
193
  database: (answers.framework === "react-vite"
146
194
  ? "none"
147
- : answers.database),
148
- dbProvider: answers.dbProvider,
149
- auth: answers.auth || "none",
195
+ : parsedDb.database),
196
+ prismaProvider: answers.prismaProvider || parsedDb.provider,
197
+ auth: (answers.auth || "none"),
150
198
  language: answers.language,
151
199
  packageManager: answers.packageManager,
152
200
  };
153
201
  }
154
- async function generateProject(config, targetDir) {
155
- const copySpinner = (0, ora_1.default)("Creating project files...").start();
202
+ async function generateProject(config, targetDir, options) {
203
+ const copySpinner = logger_1.logger.startSpinner("Creating project files...");
156
204
  let postInstallCommands = [];
157
205
  try {
158
206
  postInstallCommands = await composeTemplate(config, targetDir);
@@ -163,18 +211,20 @@ async function generateProject(config, targetDir) {
163
211
  throw error;
164
212
  }
165
213
  // Install dependencies
166
- const installSpinner = (0, ora_1.default)("Installing dependencies...").start();
167
- try {
168
- await (0, package_utils_1.installDependencies)(targetDir, config.packageManager);
169
- installSpinner.succeed("Dependencies installed");
170
- }
171
- catch (error) {
172
- installSpinner.fail("Failed to install dependencies");
173
- throw error;
214
+ if (options?.install !== false && !options?.['skip-install']) {
215
+ const installSpinner = logger_1.logger.startSpinner("Installing dependencies...");
216
+ try {
217
+ await (0, package_utils_1.installDependencies)(targetDir, config.packageManager);
218
+ installSpinner.succeed("Dependencies installed");
219
+ }
220
+ catch (error) {
221
+ installSpinner.fail("Failed to install dependencies");
222
+ throw error;
223
+ }
174
224
  }
175
225
  // Run post-install commands
176
226
  if (postInstallCommands.length > 0) {
177
- const postInstallSpinner = (0, ora_1.default)("Running post-install commands...").start();
227
+ const postInstallSpinner = logger_1.logger.startSpinner("Running post-install commands...");
178
228
  try {
179
229
  for (const command of postInstallCommands) {
180
230
  (0, child_process_1.execSync)(command, { cwd: targetDir, stdio: "pipe" });
@@ -187,19 +237,41 @@ async function generateProject(config, targetDir) {
187
237
  }
188
238
  }
189
239
  // Initialize git
190
- const gitSpinner = (0, ora_1.default)("Initializing git repository...").start();
191
- try {
192
- await (0, git_utils_1.initGit)(targetDir);
193
- gitSpinner.succeed("Git repository initialized");
194
- }
195
- catch {
196
- gitSpinner.warn("Failed to initialize git repository");
240
+ if (options?.git !== false && !options?.['no-git']) {
241
+ const gitSpinner = logger_1.logger.startSpinner("Initializing git repository...");
242
+ try {
243
+ await (0, git_utils_1.initGit)(targetDir);
244
+ gitSpinner.succeed("Git repository initialized");
245
+ }
246
+ catch {
247
+ gitSpinner.warn("Failed to initialize git repository");
248
+ }
197
249
  }
198
250
  }
199
251
  async function composeTemplate(config, targetDir) {
200
252
  const templatesDir = path_1.default.join(__dirname, "..", "..", "templates");
253
+ const modulesDir = path_1.default.join(__dirname, "..", "..", "modules");
201
254
  await fs_extra_1.default.ensureDir(targetDir);
202
- await (0, file_utils_1.copyBaseFramework)(templatesDir, targetDir, config.framework);
255
+ // Load framework configuration
256
+ const frameworkConfig = await framework_utils_1.FrameworkUtils.loadFrameworkConfig(config.framework, templatesDir);
257
+ // Initialize advanced code generator
258
+ const generator = new code_generator_1.AdvancedCodeGenerator(frameworkConfig);
259
+ await generator.loadGenerators(modulesDir);
260
+ // Generate project using advanced code generator
261
+ const features = [];
262
+ const postInstallCommands = await generator.generate({
263
+ framework: config.framework,
264
+ database: config.database === 'none' ? undefined : config.database,
265
+ auth: config.auth === 'none' ? undefined : config.auth,
266
+ prismaProvider: config.prismaProvider,
267
+ }, features, targetDir);
268
+ // Update project name in package.json
269
+ const packageJsonPath = path_1.default.join(targetDir, "package.json");
270
+ if (await fs_extra_1.default.pathExists(packageJsonPath)) {
271
+ const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
272
+ packageJson.name = config.projectName;
273
+ await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
274
+ }
203
275
  // Ensure .env exists: if .env.example was copied from the template, create .env from it
204
276
  try {
205
277
  const envExamplePath = path_1.default.join(targetDir, ".env.example");
@@ -212,32 +284,18 @@ async function composeTemplate(config, targetDir) {
212
284
  catch {
213
285
  // non-fatal
214
286
  }
215
- const postInstallCommands = [];
216
- if (config.database !== "none") {
217
- const dbPostInstall = await (0, module_utils_1.mergeDatabaseConfig)(templatesDir, targetDir, config.database, config.framework, config.dbProvider);
218
- postInstallCommands.push(...dbPostInstall);
219
- }
220
- if (config.auth !== "none") {
221
- await (0, module_utils_1.mergeAuthConfig)(templatesDir, targetDir, config.framework, config.auth, config.database, config.dbProvider);
222
- }
223
- const packageJsonPath = path_1.default.join(targetDir, "package.json");
224
- if (await fs_extra_1.default.pathExists(packageJsonPath)) {
225
- const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
226
- packageJson.name = config.projectName;
227
- await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
228
- }
229
287
  if (config.language === "javascript") {
230
288
  await (0, js_conversion_1.convertToJavaScript)(targetDir, config.framework);
231
289
  }
290
+ // For now, return empty array as post-install commands are handled by the generator
232
291
  return postInstallCommands;
233
292
  }
234
293
  function showNextSteps(config) {
235
- // eslint-disable-next-line no-console
236
- console.log(chalk_1.default.green.bold(`\n✓ Created ${config.projectName}\n`));
237
- // eslint-disable-next-line no-console
238
- console.log(chalk_1.default.bold("Next steps:"));
239
- // eslint-disable-next-line no-console
240
- console.log(chalk_1.default.cyan(` cd ${config.projectName}`));
241
- // eslint-disable-next-line no-console
242
- console.log(chalk_1.default.cyan(` ${config.packageManager} run dev\n`));
294
+ logger_1.logger.newLine();
295
+ logger_1.logger.success(`Created ${config.projectName}`);
296
+ logger_1.logger.newLine();
297
+ logger_1.logger.log("Next steps:");
298
+ logger_1.logger.log(` cd ${config.projectName}`);
299
+ logger_1.logger.log(` ${config.packageManager} run dev`);
300
+ logger_1.logger.newLine();
243
301
  }
@@ -0,0 +1,22 @@
1
+ export interface FrameworkConfig {
2
+ name: string;
3
+ displayName: string;
4
+ compatibility: {
5
+ databases: string[];
6
+ auth: string[];
7
+ };
8
+ }
9
+ export interface ModuleConfig {
10
+ name: string;
11
+ displayName: string;
12
+ type: 'database' | 'auth';
13
+ compatibility?: {
14
+ frameworks?: string[];
15
+ databases?: string[];
16
+ };
17
+ }
18
+ export declare class FrameworkUtils {
19
+ private static frameworkConfigs;
20
+ static loadFrameworkConfig(frameworkName: string, templatesDir: string): Promise<FrameworkConfig>;
21
+ static isCompatible(framework: string, database?: string, auth?: string): boolean;
22
+ }
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FrameworkUtils = void 0;
37
+ const fs = __importStar(require("fs-extra"));
38
+ const path = __importStar(require("path"));
39
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
40
+ class FrameworkUtils {
41
+ static async loadFrameworkConfig(frameworkName, templatesDir) {
42
+ const configPath = path.join(templatesDir, frameworkName, 'template.json');
43
+ if (await fs.pathExists(configPath)) {
44
+ const config = await fs.readJson(configPath);
45
+ this.frameworkConfigs.set(frameworkName, config);
46
+ return config;
47
+ }
48
+ // Default config if no template.json exists
49
+ const defaultConfig = {
50
+ name: frameworkName,
51
+ displayName: frameworkName.charAt(0).toUpperCase() + frameworkName.slice(1),
52
+ compatibility: {
53
+ databases: ['prisma', 'mongoose'],
54
+ auth: ['better-auth', 'authjs'],
55
+ },
56
+ };
57
+ this.frameworkConfigs.set(frameworkName, defaultConfig);
58
+ return defaultConfig;
59
+ }
60
+ static isCompatible(framework, database, auth) {
61
+ const config = this.frameworkConfigs.get(framework);
62
+ if (!config)
63
+ return true; // Assume compatible if no config
64
+ if (database && !config.compatibility.databases.includes(database)) {
65
+ return false;
66
+ }
67
+ if (auth && !config.compatibility.auth.includes(auth)) {
68
+ return false;
69
+ }
70
+ return true;
71
+ }
72
+ }
73
+ exports.FrameworkUtils = FrameworkUtils;
74
+ FrameworkUtils.frameworkConfigs = new Map();
@@ -0,0 +1,16 @@
1
+ import { Ora } from "ora";
2
+ export declare class Logger {
3
+ private spinner;
4
+ info(message: string): void;
5
+ success(message: string): void;
6
+ error(message: string): void;
7
+ warn(message: string): void;
8
+ log(message: string): void;
9
+ newLine(): void;
10
+ startSpinner(text: string): Ora;
11
+ stopSpinner(success?: boolean, text?: string): void;
12
+ updateSpinner(text: string): void;
13
+ header(text: string): void;
14
+ footer(): void;
15
+ }
16
+ export declare const logger: Logger;
@@ -0,0 +1,59 @@
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.logger = exports.Logger = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ class Logger {
10
+ constructor() {
11
+ this.spinner = null;
12
+ }
13
+ info(message) {
14
+ process.stdout.write(chalk_1.default.blue("ℹ") + " " + message + "\n");
15
+ }
16
+ success(message) {
17
+ process.stdout.write(chalk_1.default.green("✔") + " " + message + "\n");
18
+ }
19
+ error(message) {
20
+ process.stderr.write(chalk_1.default.red("✖") + " " + message + "\n");
21
+ }
22
+ warn(message) {
23
+ process.stdout.write(chalk_1.default.yellow("⚠") + " " + message + "\n");
24
+ }
25
+ log(message) {
26
+ process.stdout.write(message + "\n");
27
+ }
28
+ newLine() {
29
+ process.stdout.write("\n");
30
+ }
31
+ startSpinner(text) {
32
+ this.spinner = (0, ora_1.default)(text).start();
33
+ return this.spinner;
34
+ }
35
+ stopSpinner(success = true, text) {
36
+ if (this.spinner) {
37
+ if (success) {
38
+ this.spinner.succeed(text);
39
+ }
40
+ else {
41
+ this.spinner.fail(text);
42
+ }
43
+ this.spinner = null;
44
+ }
45
+ }
46
+ updateSpinner(text) {
47
+ if (this.spinner) {
48
+ this.spinner.text = text;
49
+ }
50
+ }
51
+ header(text) {
52
+ process.stdout.write(chalk_1.default.bold.cyan(text) + "\n");
53
+ }
54
+ footer() {
55
+ process.stdout.write("\n");
56
+ }
57
+ }
58
+ exports.Logger = Logger;
59
+ exports.logger = new Logger();
@@ -0,0 +1,62 @@
1
+ export interface ModuleMetadata {
2
+ name: string;
3
+ displayName: string;
4
+ description: string;
5
+ category: string;
6
+ provider?: string;
7
+ supportedFrameworks?: string[];
8
+ databaseAdapters?: Record<string, unknown>;
9
+ frameworkConfigs?: Record<string, unknown>;
10
+ dependencies?: Record<string, unknown>;
11
+ devDependencies?: Record<string, unknown>;
12
+ envVars?: Record<string, unknown>;
13
+ patches?: unknown[];
14
+ postInstall?: string[];
15
+ compatibility?: {
16
+ databases?: string[];
17
+ auth?: string[];
18
+ languages?: string[];
19
+ };
20
+ framework?: string;
21
+ files?: string[];
22
+ scripts?: Record<string, string>;
23
+ jsScripts?: Record<string, string>;
24
+ }
25
+ export interface DiscoveredModules {
26
+ frameworks: ModuleMetadata[];
27
+ databases: ModuleMetadata[];
28
+ auth: ModuleMetadata[];
29
+ }
30
+ /**
31
+ * Discover all available modules from the modules directory
32
+ */
33
+ export declare function discoverModules(modulesDir: string): Promise<DiscoveredModules>;
34
+ /**
35
+ * Get valid database options for CLI
36
+ */
37
+ export declare function getValidDatabaseOptions(databases: ModuleMetadata[]): string[];
38
+ /**
39
+ * Get valid auth options for CLI
40
+ */
41
+ export declare function getValidAuthOptions(authModules: ModuleMetadata[]): string[];
42
+ /**
43
+ * Parse database option into database name and provider
44
+ */
45
+ export declare function parseDatabaseOption(dbOption: string): {
46
+ database: string;
47
+ provider?: string;
48
+ };
49
+ /**
50
+ * Get compatible auth options for given framework and database
51
+ */
52
+ export declare function getCompatibleAuthOptions(authModules: ModuleMetadata[], framework: string, database: string): Array<{
53
+ name: string;
54
+ value: string;
55
+ }>;
56
+ /**
57
+ * Get database choices for inquirer prompts
58
+ */
59
+ export declare function getDatabaseChoices(databases: ModuleMetadata[], framework: string): Array<{
60
+ name: string;
61
+ value: string;
62
+ }>;