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.
- package/README.md +1 -1
- package/dist/index.js +61 -4
- package/dist/lib/code-generator.d.ts +80 -0
- package/dist/lib/code-generator.js +541 -0
- package/dist/lib/create-project.d.ts +20 -1
- package/dist/lib/create-project.js +154 -96
- package/dist/lib/framework-utils.d.ts +22 -0
- package/dist/lib/framework-utils.js +74 -0
- package/dist/lib/utils/logger.d.ts +16 -0
- package/dist/lib/utils/logger.js +59 -0
- package/dist/lib/utils/module-discovery.d.ts +62 -0
- package/dist/lib/utils/module-discovery.js +180 -0
- package/dist/lib/utils/package-utils.js +2 -2
- package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +6 -0
- package/modules/auth/authjs/files/lib/auth-client.ts +11 -0
- package/modules/auth/authjs/files/lib/auth.ts +36 -0
- package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
- package/modules/auth/authjs/module.json +22 -0
- package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
- package/modules/auth/better-auth/files/lib/auth.ts +77 -1
- package/modules/auth/better-auth/files/lib/email-service.ts +34 -0
- package/modules/auth/better-auth/files/lib/email-templates.ts +89 -0
- package/modules/auth/better-auth/files/schemas/prisma-schema.prisma +7 -7
- package/modules/auth/better-auth/generator.json +83 -0
- package/modules/auth/better-auth/module.json +17 -34
- package/modules/database/mongoose/files/lib/db.ts +63 -0
- package/modules/database/{mongoose-mongodb → mongoose}/files/models/User.ts +0 -5
- package/modules/database/mongoose/generator.json +33 -0
- package/modules/database/mongoose/module.json +15 -0
- package/modules/database/prisma/files/lib/prisma.ts +7 -4
- package/modules/database/prisma/files/prisma/schema.prisma +1 -1
- package/modules/database/prisma/files/prisma.config.ts +2 -2
- package/modules/database/prisma/generator.json +46 -0
- package/modules/database/prisma/module.json +6 -132
- package/package.json +1 -1
- package/templates/express/.env.example +0 -1
- package/templates/express/package.json +4 -4
- package/templates/express/src/app.ts +2 -2
- package/templates/express/src/features/health/health.controller.ts +18 -0
- package/templates/express/src/features/health/health.route.ts +9 -0
- package/templates/express/src/features/health/health.service.ts +6 -0
- package/templates/express/template.json +6 -19
- package/templates/nextjs/lib/env.ts +8 -0
- package/templates/nextjs/package.json +7 -7
- package/templates/nextjs/template.json +5 -1
- package/templates/react-vite/.env.example +1 -2
- package/templates/react-vite/.prettierignore +4 -0
- package/templates/react-vite/.prettierrc +9 -0
- package/templates/react-vite/README.md +22 -0
- package/templates/react-vite/package.json +16 -16
- package/templates/react-vite/src/router.tsx +0 -12
- package/templates/react-vite/template.json +6 -14
- package/templates/react-vite/vite.config.ts +0 -6
- package/dist/lib/utils/config-utils.d.ts +0 -2
- package/dist/lib/utils/config-utils.js +0 -33
- package/dist/lib/utils/file-utils.d.ts +0 -8
- package/dist/lib/utils/file-utils.js +0 -75
- package/dist/lib/utils/module-utils.d.ts +0 -2
- package/dist/lib/utils/module-utils.js +0 -311
- package/modules/auth/clerk/files/express/auth.ts +0 -7
- package/modules/auth/clerk/files/nextjs/auth-provider.tsx +0 -5
- package/modules/auth/clerk/files/nextjs/middleware.ts +0 -9
- package/modules/auth/clerk/files/react/auth-provider.tsx +0 -15
- package/modules/auth/clerk/module.json +0 -115
- package/modules/database/mongoose-mongodb/files/lib/db.ts +0 -78
- package/modules/database/mongoose-mongodb/module.json +0 -70
- package/templates/express/src/features/auth/auth.controller.ts +0 -48
- package/templates/express/src/features/auth/auth.route.ts +0 -10
- package/templates/express/src/features/auth/auth.service.ts +0 -21
- package/templates/react-vite/src/api/services/user.service.ts +0 -18
- package/templates/react-vite/src/pages/UserProfile.tsx +0 -40
- 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
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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: "
|
|
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
|
-
:
|
|
148
|
-
|
|
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 =
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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 =
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
+
}>;
|