create-stackkit-app 0.4.4 → 0.4.5
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 +62 -4
- package/dist/lib/create-project.d.ts +20 -1
- package/dist/lib/create-project.js +133 -48
- package/dist/lib/utils/config-utils.js +56 -1
- package/dist/lib/utils/logger.d.ts +16 -0
- package/dist/lib/utils/logger.js +59 -0
- package/dist/lib/utils/module-utils.js +346 -196
- 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 +41 -0
- package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
- package/modules/auth/authjs/module.json +95 -0
- package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
- package/modules/auth/better-auth/files/lib/auth.ts +62 -0
- 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 +1 -1
- package/modules/auth/better-auth/module.json +164 -27
- package/modules/database/mongoose/files/lib/db.ts +68 -0
- package/modules/database/{mongoose-mongodb → mongoose}/files/models/User.ts +0 -5
- package/modules/database/{mongoose-mongodb → mongoose}/module.json +9 -24
- package/modules/database/prisma/files/lib/prisma.ts +1 -3
- package/modules/database/prisma/files/prisma/schema.prisma +1 -1
- package/modules/database/prisma/files/prisma.config.ts +2 -2
- package/modules/database/prisma/module.json +5 -23
- 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/nextjs/lib/env.ts +8 -0
- package/templates/nextjs/package.json +7 -7
- 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/vite.config.ts +0 -6
- 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/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
|
@@ -42,27 +42,77 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
42
42
|
const path_1 = __importStar(require("path"));
|
|
43
43
|
const config_utils_1 = require("./config-utils");
|
|
44
44
|
const file_utils_1 = require("./file-utils");
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
const logger_1 = require("./logger");
|
|
46
|
+
/**
|
|
47
|
+
* Process environment variables with variable replacement
|
|
48
|
+
*/
|
|
49
|
+
function processEnvVars(envVarList, variables) {
|
|
50
|
+
const envVars = {};
|
|
51
|
+
for (const envVar of envVarList) {
|
|
52
|
+
let value = envVar.value;
|
|
53
|
+
for (const [key, val] of Object.entries(variables)) {
|
|
54
|
+
value = value.replace(new RegExp(`{{${key}}}`, "g"), val);
|
|
55
|
+
}
|
|
56
|
+
envVars[envVar.key] = value;
|
|
52
57
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
return envVars;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get framework-specific paths for file placement
|
|
62
|
+
*/
|
|
63
|
+
function getFrameworkPaths(framework) {
|
|
64
|
+
switch (framework) {
|
|
65
|
+
case "nextjs":
|
|
66
|
+
return { lib: "lib", router: "app", models: "lib/models" };
|
|
67
|
+
case "express":
|
|
68
|
+
return { lib: "lib", router: "src", models: "lib/models" };
|
|
69
|
+
case "react-vite":
|
|
70
|
+
return { lib: "src/lib", router: "src", models: "src/models" };
|
|
71
|
+
default:
|
|
72
|
+
return { lib: "src/lib", router: "src", models: "src/models" };
|
|
57
73
|
}
|
|
58
|
-
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate variables based on database, framework, and provider
|
|
77
|
+
*/
|
|
78
|
+
function generateVariables(database, framework, dbProvider, auth) {
|
|
59
79
|
const variables = {};
|
|
80
|
+
// Database-specific variables
|
|
81
|
+
variables.dbFile = database === "prisma" ? "prisma.ts" : "db.ts";
|
|
82
|
+
variables.dbDescription =
|
|
83
|
+
database === "prisma"
|
|
84
|
+
? "Create Prisma client singleton"
|
|
85
|
+
: "Create MongoDB connection with Mongoose";
|
|
86
|
+
// Auth-specific variables
|
|
87
|
+
if (auth) {
|
|
88
|
+
variables.authFile = "auth.ts";
|
|
89
|
+
variables.authDescription = `Create ${auth} authentication configuration`;
|
|
90
|
+
// Dynamic dbImport for auth modules
|
|
91
|
+
const libPath = framework === "nextjs" ? "@/lib" : ".";
|
|
92
|
+
const adapterImport = 'import { prismaAdapter } from "better-auth/adapters/prisma";';
|
|
93
|
+
if (database === "prisma") {
|
|
94
|
+
variables.dbImport = `import { prisma } from "${libPath}/prisma";
|
|
95
|
+
${adapterImport}`;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
variables.dbImport =
|
|
99
|
+
database === "prisma"
|
|
100
|
+
? `import { prisma } from "${libPath}/prisma";`
|
|
101
|
+
: `import { client } from "${libPath}/db";`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// Framework-specific database import for database modules
|
|
106
|
+
const libPath = framework === "nextjs" ? "@/lib" : ".";
|
|
107
|
+
variables.dbImport = database === "prisma" ? `${libPath}/prisma` : `${libPath}/db`;
|
|
108
|
+
}
|
|
109
|
+
// Provider-specific variables
|
|
60
110
|
if (dbProvider) {
|
|
61
111
|
variables.provider = dbProvider;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
import { PrismaPg } from "@prisma/adapter-pg";
|
|
112
|
+
switch (dbProvider) {
|
|
113
|
+
case "postgresql":
|
|
114
|
+
variables.connectionString = "postgresql://user:password@localhost:5432/mydb?schema=public";
|
|
115
|
+
variables.prismaClientInit = `import { PrismaPg } from "@prisma/adapter-pg";
|
|
66
116
|
|
|
67
117
|
const globalForPrisma = global as unknown as {
|
|
68
118
|
prisma: PrismaClient | undefined;
|
|
@@ -78,17 +128,16 @@ const prisma = globalForPrisma.prisma ?? new PrismaClient({
|
|
|
78
128
|
|
|
79
129
|
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
|
80
130
|
`;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
131
|
+
break;
|
|
132
|
+
case "mongodb":
|
|
133
|
+
variables.connectionString = "mongodb+srv://username:password@cluster.mongodb.net/mydb";
|
|
134
|
+
variables.prismaClientInit = `
|
|
85
135
|
const prisma = new PrismaClient()
|
|
86
136
|
`;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
import { PrismaMariaDb } from '@prisma/adapter-mariadb';
|
|
137
|
+
break;
|
|
138
|
+
case "mysql":
|
|
139
|
+
variables.connectionString = "mysql://user:password@localhost:3306/mydb";
|
|
140
|
+
variables.prismaClientInit = `import { PrismaMariaDb } from '@prisma/adapter-mariadb';
|
|
92
141
|
|
|
93
142
|
const adapter = new PrismaMariaDb({
|
|
94
143
|
host: process.env.DATABASE_HOST,
|
|
@@ -99,213 +148,314 @@ const adapter = new PrismaMariaDb({
|
|
|
99
148
|
});
|
|
100
149
|
const prisma = new PrismaClient({ adapter });
|
|
101
150
|
`;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
|
|
151
|
+
break;
|
|
152
|
+
case "sqlite":
|
|
153
|
+
variables.connectionString = "file:./dev.db";
|
|
154
|
+
variables.prismaClientInit = `import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
|
|
107
155
|
|
|
108
156
|
const adapter = new PrismaBetterSqlite3({ url: process.env.DATABASE_URL });
|
|
109
157
|
const prisma = new PrismaClient({ adapter });
|
|
110
158
|
`;
|
|
159
|
+
break;
|
|
111
160
|
}
|
|
112
161
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
162
|
+
return variables;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Process a single patch with variable replacement
|
|
166
|
+
*/
|
|
167
|
+
async function processPatch(patch, filesDir, targetDir, variables, frameworkPaths) {
|
|
168
|
+
if (patch.type === "create-file") {
|
|
169
|
+
if (!patch.source || !patch.destination)
|
|
170
|
+
return;
|
|
171
|
+
try {
|
|
172
|
+
// Replace variables in source and destination
|
|
173
|
+
const sourcePath = patch.source.replace(/\{\{(\w+)\}\}/g, (match, key) => variables[key] || match);
|
|
174
|
+
const sourceFile = (0, path_1.join)(filesDir, sourcePath);
|
|
175
|
+
let destFile = (0, path_1.join)(targetDir, patch.destination.replace(/\{\{(\w+)\}\}/g, (match, key) => variables[key] || match));
|
|
176
|
+
// Apply framework-specific path replacements
|
|
177
|
+
destFile = destFile
|
|
178
|
+
.replace("{{lib}}", frameworkPaths.lib)
|
|
179
|
+
.replace("{{router}}", frameworkPaths.router)
|
|
180
|
+
.replace("{{models}}", frameworkPaths.models);
|
|
181
|
+
if (!(await fs_extra_1.default.pathExists(sourceFile))) {
|
|
182
|
+
logger_1.logger.warn(`Source file not found: ${sourceFile}`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(destFile));
|
|
186
|
+
const ext = path_1.default.extname(sourceFile);
|
|
187
|
+
if ([".ts", ".js", ".tsx", ".prisma", ".json"].includes(ext)) {
|
|
188
|
+
let content = await fs_extra_1.default.readFile(sourceFile, "utf-8");
|
|
189
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
190
|
+
content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
|
|
191
|
+
}
|
|
192
|
+
await fs_extra_1.default.writeFile(destFile, content);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
await fs_extra_1.default.copy(sourceFile, destFile, { overwrite: false });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
logger_1.logger.error(`Failed to process patch ${patch.description}: ${error.message}`);
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else if (patch.type === "patch-file") {
|
|
204
|
+
if (!patch.file)
|
|
205
|
+
return;
|
|
206
|
+
try {
|
|
207
|
+
const filePath = (0, path_1.join)(targetDir, patch.file);
|
|
208
|
+
if (!(await fs_extra_1.default.pathExists(filePath))) {
|
|
209
|
+
logger_1.logger.warn(`File to patch not found: ${filePath}`);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
let content = await fs_extra_1.default.readFile(filePath, "utf-8");
|
|
213
|
+
for (const operation of patch.operations || []) {
|
|
214
|
+
if (operation.type === "add-import" && operation.imports) {
|
|
215
|
+
// Add imports at the top of the file, after existing imports
|
|
216
|
+
const imports = operation.imports.join("\n");
|
|
217
|
+
// Find the last import statement
|
|
218
|
+
const importRegex = /^import\s+.*$/gm;
|
|
219
|
+
const matches = [...content.matchAll(importRegex)];
|
|
220
|
+
if (matches.length > 0) {
|
|
221
|
+
const lastImport = matches[matches.length - 1];
|
|
222
|
+
const insertIndex = (lastImport.index ?? 0) + lastImport[0].length;
|
|
223
|
+
content = content.slice(0, insertIndex) + "\n" + imports + content.slice(insertIndex);
|
|
134
224
|
}
|
|
135
225
|
else {
|
|
136
|
-
|
|
226
|
+
// No imports found, add at the beginning
|
|
227
|
+
content = imports + "\n\n" + content;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (operation.type === "add-code") {
|
|
231
|
+
if (operation.after && operation.code) {
|
|
232
|
+
const insertIndex = content.indexOf(operation.after);
|
|
233
|
+
if (insertIndex !== -1) {
|
|
234
|
+
const afterIndex = insertIndex + operation.after.length;
|
|
235
|
+
content = content.slice(0, afterIndex) + operation.code + content.slice(afterIndex);
|
|
236
|
+
}
|
|
137
237
|
}
|
|
138
238
|
}
|
|
139
239
|
}
|
|
240
|
+
await fs_extra_1.default.writeFile(filePath, content);
|
|
140
241
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
...(dbProvider ? moduleData.dependencies.providers[dbProvider] : {}),
|
|
145
|
-
};
|
|
146
|
-
const devDependencies = {
|
|
147
|
-
...moduleData.devDependencies.common,
|
|
148
|
-
...(dbProvider ? moduleData.devDependencies.providers[dbProvider] : {}),
|
|
149
|
-
};
|
|
150
|
-
await (0, file_utils_1.mergePackageJson)(targetDir, {
|
|
151
|
-
dependencies,
|
|
152
|
-
devDependencies,
|
|
153
|
-
});
|
|
154
|
-
const envVars = {};
|
|
155
|
-
const commonEnvVars = Array.isArray(moduleData.envVars) ? moduleData.envVars : moduleData.envVars?.common || [];
|
|
156
|
-
const providerEnvVars = dbProvider && moduleData.envVars?.providers?.[dbProvider] ? moduleData.envVars.providers[dbProvider] : [];
|
|
157
|
-
const allEnvVars = [...commonEnvVars, ...providerEnvVars];
|
|
158
|
-
for (const envVar of allEnvVars) {
|
|
159
|
-
let value = envVar.value;
|
|
160
|
-
for (const [key, val] of Object.entries(variables)) {
|
|
161
|
-
value = value.replace(new RegExp(`{{${key}}}`, "g"), val);
|
|
162
|
-
}
|
|
163
|
-
envVars[envVar.key] = value;
|
|
164
|
-
}
|
|
165
|
-
await (0, file_utils_1.mergeEnvFile)(targetDir, envVars);
|
|
166
|
-
if (moduleData.frameworkPatches) {
|
|
167
|
-
const frameworkKey = framework === "react-vite" ? "react" : framework;
|
|
168
|
-
const patches = moduleData.frameworkPatches[frameworkKey];
|
|
169
|
-
if (patches) {
|
|
170
|
-
await (0, config_utils_1.applyFrameworkPatches)(targetDir, patches);
|
|
242
|
+
catch (error) {
|
|
243
|
+
logger_1.logger.error(`Failed to process patch-file ${patch.description}: ${error.message}`);
|
|
244
|
+
throw error;
|
|
171
245
|
}
|
|
172
246
|
}
|
|
173
|
-
return moduleData.postInstall || [];
|
|
174
247
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
// eslint-disable-next-line no-console
|
|
181
|
-
console.warn(`Auth module not found: ${authKey}`);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
// Read module.json
|
|
185
|
-
const moduleJsonPath = (0, path_1.join)(authModulePath, "module.json");
|
|
248
|
+
/**
|
|
249
|
+
* Validate and extract module data
|
|
250
|
+
*/
|
|
251
|
+
async function loadModuleData(modulePath) {
|
|
252
|
+
const moduleJsonPath = (0, path_1.join)(modulePath, "module.json");
|
|
186
253
|
if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
|
|
187
|
-
|
|
254
|
+
throw new Error(`Module configuration not found: ${moduleJsonPath}`);
|
|
188
255
|
}
|
|
189
256
|
const moduleData = await fs_extra_1.default.readJson(moduleJsonPath);
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
console.warn(`Auth ${authKey} does not support framework ${framework}`);
|
|
193
|
-
return;
|
|
257
|
+
if (!moduleData) {
|
|
258
|
+
throw new Error(`Invalid module configuration: ${moduleJsonPath}`);
|
|
194
259
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
260
|
+
return moduleData;
|
|
261
|
+
}
|
|
262
|
+
async function mergeDatabaseConfig(templatesDir, targetDir, database, framework, dbProvider) {
|
|
263
|
+
try {
|
|
264
|
+
const modulesDir = (0, path_1.join)(templatesDir, "..", "modules");
|
|
265
|
+
const dbModulePath = (0, path_1.join)(modulesDir, "database", database);
|
|
266
|
+
if (!(await fs_extra_1.default.pathExists(dbModulePath))) {
|
|
267
|
+
logger_1.logger.warn(`Database module not found: ${database}`);
|
|
268
|
+
return [];
|
|
202
269
|
}
|
|
270
|
+
const moduleData = await loadModuleData(dbModulePath);
|
|
271
|
+
const variables = generateVariables(database, framework, dbProvider);
|
|
272
|
+
const frameworkPaths = getFrameworkPaths(framework);
|
|
273
|
+
const filesDir = (0, path_1.join)(dbModulePath, "files");
|
|
274
|
+
if (await fs_extra_1.default.pathExists(filesDir)) {
|
|
275
|
+
for (const patch of moduleData.patches || []) {
|
|
276
|
+
await processPatch(patch, filesDir, targetDir, variables, frameworkPaths);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Merge dependencies
|
|
280
|
+
let dependencies = {};
|
|
281
|
+
let devDependencies = {};
|
|
282
|
+
if (moduleData.dependencies) {
|
|
283
|
+
if (moduleData.dependencies.common || moduleData.dependencies.providers) {
|
|
284
|
+
// Structured dependencies (common + providers)
|
|
285
|
+
dependencies = {
|
|
286
|
+
...moduleData.dependencies.common,
|
|
287
|
+
...(dbProvider ? moduleData.dependencies.providers?.[dbProvider] : {}),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
// Flat dependencies structure
|
|
292
|
+
dependencies = { ...moduleData.dependencies };
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (moduleData.devDependencies) {
|
|
296
|
+
if (moduleData.devDependencies.common || moduleData.devDependencies.providers) {
|
|
297
|
+
// Structured devDependencies
|
|
298
|
+
devDependencies = {
|
|
299
|
+
...moduleData.devDependencies.common,
|
|
300
|
+
...(dbProvider ? moduleData.devDependencies.providers?.[dbProvider] : {}),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
// Flat devDependencies structure
|
|
305
|
+
devDependencies = { ...moduleData.devDependencies };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
await (0, file_utils_1.mergePackageJson)(targetDir, { dependencies, devDependencies });
|
|
309
|
+
// Process environment variables
|
|
310
|
+
const envVars = {};
|
|
311
|
+
const commonEnvVars = Array.isArray(moduleData.envVars)
|
|
312
|
+
? moduleData.envVars
|
|
313
|
+
: moduleData.envVars?.common || [];
|
|
314
|
+
const providerEnvVars = dbProvider && moduleData.envVars?.providers?.[dbProvider]
|
|
315
|
+
? moduleData.envVars.providers[dbProvider]
|
|
316
|
+
: [];
|
|
317
|
+
const allEnvVars = [...commonEnvVars, ...providerEnvVars];
|
|
318
|
+
Object.assign(envVars, processEnvVars(allEnvVars, variables));
|
|
319
|
+
await (0, file_utils_1.mergeEnvFile)(targetDir, envVars);
|
|
320
|
+
// Apply framework-specific patches
|
|
321
|
+
if (moduleData.frameworkPatches) {
|
|
322
|
+
const frameworkKey = framework === "react-vite" ? "react" : framework;
|
|
323
|
+
const patches = moduleData.frameworkPatches[frameworkKey];
|
|
324
|
+
if (patches) {
|
|
325
|
+
await (0, config_utils_1.applyFrameworkPatches)(targetDir, patches);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return moduleData.postInstall || [];
|
|
203
329
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
else if (framework === "express") {
|
|
209
|
-
variables.dbImport = "../db";
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
variables.dbImport = "../db";
|
|
330
|
+
catch (error) {
|
|
331
|
+
logger_1.logger.error(`Failed to merge database config for ${database}: ${error.message}`);
|
|
332
|
+
throw error;
|
|
213
333
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
334
|
+
}
|
|
335
|
+
async function mergeAuthConfig(templatesDir, targetDir, framework, auth, database = "none", dbProvider) {
|
|
336
|
+
try {
|
|
337
|
+
const modulesDir = (0, path_1.join)(templatesDir, "..", "modules");
|
|
338
|
+
const authModulePath = (0, path_1.join)(modulesDir, "auth", auth);
|
|
339
|
+
if (!(await fs_extra_1.default.pathExists(authModulePath))) {
|
|
340
|
+
logger_1.logger.warn(`Auth module not found: ${auth}`);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const moduleData = await loadModuleData(authModulePath);
|
|
344
|
+
if (moduleData.supportedFrameworks && !moduleData.supportedFrameworks.includes(framework)) {
|
|
345
|
+
logger_1.logger.warn(`Auth ${auth} does not support framework ${framework}`);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
let frameworkConfig = null;
|
|
349
|
+
if (moduleData.frameworkConfigs) {
|
|
350
|
+
frameworkConfig = moduleData.frameworkConfigs[framework];
|
|
351
|
+
if (!frameworkConfig) {
|
|
352
|
+
logger_1.logger.warn(`No config for framework ${framework} in ${auth}`);
|
|
353
|
+
return;
|
|
219
354
|
}
|
|
220
|
-
|
|
221
|
-
|
|
355
|
+
const shared = moduleData.frameworkConfigs.shared;
|
|
356
|
+
if (shared) {
|
|
357
|
+
frameworkConfig = {
|
|
358
|
+
...shared,
|
|
359
|
+
...frameworkConfig,
|
|
360
|
+
};
|
|
222
361
|
}
|
|
223
|
-
|
|
224
|
-
|
|
362
|
+
}
|
|
363
|
+
const variables = generateVariables(database, framework, dbProvider, auth);
|
|
364
|
+
const frameworkPaths = getFrameworkPaths(framework);
|
|
365
|
+
// Handle database adapters first to set variables
|
|
366
|
+
if (database !== "none" && moduleData.databaseAdapters) {
|
|
367
|
+
let adapterKey = database;
|
|
368
|
+
if (database === "prisma" && dbProvider) {
|
|
369
|
+
adapterKey = `prisma-${dbProvider}`;
|
|
225
370
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
.
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
371
|
+
const adapterConfig = moduleData.databaseAdapters[adapterKey];
|
|
372
|
+
if (adapterConfig) {
|
|
373
|
+
// Generate adapter code based on database type
|
|
374
|
+
if (database === "prisma" && dbProvider) {
|
|
375
|
+
variables.databaseAdapter = `database: prismaAdapter(prisma, {\n provider: "${dbProvider}",\n }),`;
|
|
376
|
+
}
|
|
377
|
+
if (adapterConfig.schema && adapterConfig.schemaDestination) {
|
|
378
|
+
const schemaSource = (0, path_1.join)(authModulePath, adapterConfig.schema);
|
|
379
|
+
const schemaDest = (0, path_1.join)(targetDir, adapterConfig.schemaDestination);
|
|
380
|
+
if (await fs_extra_1.default.pathExists(schemaSource)) {
|
|
381
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(schemaDest));
|
|
382
|
+
let content = await fs_extra_1.default.readFile(schemaSource, "utf-8");
|
|
383
|
+
// Set schema variables for Prisma
|
|
384
|
+
if (dbProvider === "postgresql") {
|
|
385
|
+
variables.provider = "postgresql";
|
|
386
|
+
variables.idDefault = "@default(cuid())";
|
|
387
|
+
variables.userIdType = "";
|
|
388
|
+
}
|
|
389
|
+
else if (dbProvider === "mongodb") {
|
|
390
|
+
variables.provider = "mongodb";
|
|
391
|
+
variables.idDefault = '@default(auto()) @map("_id") @db.ObjectId';
|
|
392
|
+
variables.userIdType = "@db.ObjectId";
|
|
393
|
+
}
|
|
394
|
+
else if (dbProvider === "mysql") {
|
|
395
|
+
variables.provider = "mysql";
|
|
396
|
+
variables.idDefault = "@default(cuid())";
|
|
397
|
+
variables.userIdType = "";
|
|
398
|
+
}
|
|
399
|
+
else if (dbProvider === "sqlite") {
|
|
400
|
+
variables.provider = "sqlite";
|
|
401
|
+
variables.idDefault = "@default(cuid())";
|
|
402
|
+
variables.userIdType = "";
|
|
403
|
+
}
|
|
242
404
|
for (const [key, value] of Object.entries(variables)) {
|
|
243
405
|
content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
|
|
244
406
|
}
|
|
245
|
-
await fs_extra_1.default.writeFile(
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
await fs_extra_1.default.copy(sourceFile, destFile, { overwrite: false });
|
|
407
|
+
await fs_extra_1.default.writeFile(schemaDest, content, { flag: "a" }); // append
|
|
249
408
|
}
|
|
250
409
|
}
|
|
410
|
+
if (adapterConfig.dependencies) {
|
|
411
|
+
const commonDeps = moduleData.databaseAdapters.common?.dependencies || {};
|
|
412
|
+
const commonDevDeps = moduleData.databaseAdapters.common?.devDependencies || {};
|
|
413
|
+
const specificDeps = adapterConfig.dependencies;
|
|
414
|
+
const specificDevDeps = adapterConfig.devDependencies || {};
|
|
415
|
+
await (0, file_utils_1.mergePackageJson)(targetDir, {
|
|
416
|
+
dependencies: { ...commonDeps, ...specificDeps },
|
|
417
|
+
devDependencies: { ...commonDevDeps, ...specificDevDeps },
|
|
418
|
+
});
|
|
419
|
+
}
|
|
251
420
|
}
|
|
252
421
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(apiDest));
|
|
260
|
-
await fs_extra_1.default.copy(apiSource, apiDest, { overwrite: false });
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
if (database !== "none" && moduleData.databaseAdapters) {
|
|
264
|
-
let adapterKey = database;
|
|
265
|
-
if (database === "prisma" && dbProvider) {
|
|
266
|
-
adapterKey = `prisma-${dbProvider}`;
|
|
422
|
+
const filesDir = (0, path_1.join)(authModulePath, "files");
|
|
423
|
+
if (await fs_extra_1.default.pathExists(filesDir)) {
|
|
424
|
+
const patches = frameworkConfig?.patches || moduleData.patches || [];
|
|
425
|
+
for (const patch of patches) {
|
|
426
|
+
await processPatch(patch, filesDir, targetDir, variables, frameworkPaths);
|
|
427
|
+
}
|
|
267
428
|
}
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(schemaDest));
|
|
276
|
-
let content = await fs_extra_1.default.readFile(schemaSource, "utf-8");
|
|
277
|
-
// Set schema variables
|
|
278
|
-
if (dbProvider === "postgresql") {
|
|
279
|
-
variables.provider = "postgresql";
|
|
280
|
-
variables.idDefault = "@default(cuid())";
|
|
281
|
-
variables.userIdType = "";
|
|
282
|
-
}
|
|
283
|
-
else if (dbProvider === "mongodb") {
|
|
284
|
-
variables.provider = "mongodb";
|
|
285
|
-
variables.idDefault = '@default(auto()) @map("_id") @db.ObjectId';
|
|
286
|
-
variables.userIdType = "@db.ObjectId";
|
|
287
|
-
}
|
|
288
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
289
|
-
content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
|
|
290
|
-
}
|
|
291
|
-
await fs_extra_1.default.writeFile(schemaDest, content, { flag: "a" }); // append
|
|
292
|
-
}
|
|
429
|
+
// Add framework-specific patches
|
|
430
|
+
if (framework === "nextjs") {
|
|
431
|
+
const apiSource = (0, path_1.join)(filesDir, "api/auth/[...all]/route.ts");
|
|
432
|
+
const apiDest = (0, path_1.join)(targetDir, "app/api/auth/[...all]/route.ts");
|
|
433
|
+
if (await fs_extra_1.default.pathExists(apiSource)) {
|
|
434
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(apiDest));
|
|
435
|
+
await fs_extra_1.default.copy(apiSource, apiDest, { overwrite: false });
|
|
293
436
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
437
|
+
}
|
|
438
|
+
// Merge package.json
|
|
439
|
+
await (0, file_utils_1.mergePackageJson)(targetDir, {
|
|
440
|
+
dependencies: frameworkConfig?.dependencies || moduleData.dependencies,
|
|
441
|
+
devDependencies: frameworkConfig?.devDependencies || moduleData.devDependencies,
|
|
442
|
+
});
|
|
443
|
+
// Process environment variables
|
|
444
|
+
const envVars = {};
|
|
445
|
+
const envVarList = frameworkConfig?.envVars || moduleData.envVars || [];
|
|
446
|
+
Object.assign(envVars, processEnvVars(envVarList, variables));
|
|
447
|
+
await (0, file_utils_1.mergeEnvFile)(targetDir, envVars);
|
|
448
|
+
// Apply framework-specific patches
|
|
449
|
+
if (moduleData.frameworkPatches) {
|
|
450
|
+
const frameworkKey = framework === "react-vite" ? "react" : framework;
|
|
451
|
+
const patches = moduleData.frameworkPatches[frameworkKey];
|
|
452
|
+
if (patches) {
|
|
453
|
+
await (0, config_utils_1.applyFrameworkPatches)(targetDir, patches);
|
|
298
454
|
}
|
|
299
455
|
}
|
|
300
456
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
});
|
|
305
|
-
const envVars = {};
|
|
306
|
-
const envVarList = frameworkConfig?.envVars || moduleData.envVars || [];
|
|
307
|
-
for (const envVar of envVarList) {
|
|
308
|
-
envVars[envVar.key] = envVar.value;
|
|
457
|
+
catch (error) {
|
|
458
|
+
logger_1.logger.error(`Failed to merge auth config for ${auth}: ${error.message}`);
|
|
459
|
+
throw error;
|
|
309
460
|
}
|
|
310
|
-
await (0, file_utils_1.mergeEnvFile)(targetDir, envVars);
|
|
311
461
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.installDependencies = installDependencies;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
|
+
const logger_1 = require("./logger");
|
|
5
6
|
async function installDependencies(cwd, packageManager) {
|
|
6
7
|
const commands = {
|
|
7
8
|
npm: "npm install",
|
|
@@ -23,8 +24,7 @@ async function installDependencies(cwd, packageManager) {
|
|
|
23
24
|
const fallbacks = ["pnpm", "npm", "yarn", "bun"];
|
|
24
25
|
const found = fallbacks.find((p) => isAvailable(p));
|
|
25
26
|
if (found) {
|
|
26
|
-
|
|
27
|
-
console.warn(`Selected package manager '${chosen}' was not found. Falling back to '${found}'.`);
|
|
27
|
+
logger_1.logger.warn(`Selected package manager '${chosen}' was not found. Falling back to '${found}'.`);
|
|
28
28
|
chosen = found;
|
|
29
29
|
}
|
|
30
30
|
else {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { getServerSession } from "next-auth/next";
|
|
2
|
+
import { authOptions } from "@/lib/auth";
|
|
3
|
+
|
|
4
|
+
export async function getSession() {
|
|
5
|
+
return await getServerSession(authOptions);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function getCurrentUser() {
|
|
9
|
+
const session = await getSession();
|
|
10
|
+
return session?.user;
|
|
11
|
+
}
|