stackkit 0.2.1 → 0.2.3
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/bin/stackkit.js +10 -3
- package/dist/cli/add.js +224 -54
- package/dist/cli/create.js +74 -32
- package/dist/cli/doctor.js +38 -159
- package/dist/cli/list.js +10 -40
- package/dist/index.js +4 -4
- package/dist/lib/discovery/installed-detection.d.ts +7 -0
- package/dist/lib/discovery/installed-detection.js +134 -0
- package/dist/lib/discovery/module-discovery.js +7 -14
- package/dist/lib/discovery/shared.js +9 -7
- package/dist/lib/generation/code-generator.d.ts +2 -0
- package/dist/lib/generation/code-generator.js +114 -2
- package/dist/lib/generation/generator-utils.d.ts +1 -1
- package/dist/lib/generation/generator-utils.js +5 -3
- package/dist/lib/project/detect.js +59 -29
- package/dist/types/index.d.ts +21 -17
- package/modules/auth/better-auth/files/lib/auth.ts +2 -2
- package/package.json +6 -3
- package/templates/express/env.example +2 -0
- package/templates/express/gitignore +23 -0
- package/templates/nextjs/env.example +1 -0
- package/templates/nextjs/gitignore +42 -0
- package/templates/react/env.example +1 -0
- package/templates/react/gitignore +44 -0
- package/templates/react/prettierignore +4 -0
- package/templates/react/prettierrc +9 -0
- package/templates/react/src/utils/utils.ts +1 -1
package/dist/cli/doctor.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
|
352
|
-
const authRoutesExist = await checkAuthRoutesExist(projectRoot
|
|
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
|
|
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 {
|
|
@@ -397,22 +297,10 @@ async function checkAuthRoutesExist(projectRoot, projectType) {
|
|
|
397
297
|
// ignore discovery errors
|
|
398
298
|
}
|
|
399
299
|
// Fallback to known common paths if generators don't provide any
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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);
|
|
300
|
+
// If generators provided candidate routes, check them. Otherwise
|
|
301
|
+
// do not assume any hard-coded route locations.
|
|
302
|
+
if (candidates.size === 0)
|
|
303
|
+
return false;
|
|
416
304
|
for (const routePath of candidates) {
|
|
417
305
|
if (await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, routePath))) {
|
|
418
306
|
return true;
|
|
@@ -468,16 +356,7 @@ async function checkEnvFiles(projectRoot, authModules, databaseModules) {
|
|
|
468
356
|
}
|
|
469
357
|
}
|
|
470
358
|
catch {
|
|
471
|
-
//
|
|
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
|
-
}
|
|
359
|
+
// If discovery fails, keep requiredKeys empty rather than using hard-coded defaults.
|
|
481
360
|
}
|
|
482
361
|
const envPaths = [".env", ".env.local"];
|
|
483
362
|
let envContent = "";
|
|
@@ -603,7 +482,7 @@ function generateSuggestions(authModules, databaseModules) {
|
|
|
603
482
|
suggestions.push("stackkit add auth - Add authentication module");
|
|
604
483
|
}
|
|
605
484
|
if (databaseModules.length === 0) {
|
|
606
|
-
suggestions.push("stackkit add
|
|
485
|
+
suggestions.push("stackkit add database - Add database module");
|
|
607
486
|
}
|
|
608
487
|
// Always show available commands
|
|
609
488
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
acc[
|
|
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
|
-
//
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
.
|
|
85
|
-
|
|
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
|
@@ -99,12 +99,12 @@ function buildOptionHints() {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
return {
|
|
102
|
-
databaseHint: dbs.length > 0 ? dbs.join(", ") : "
|
|
103
|
-
authHint: auths.length > 0 ? auths.join(", ") : "
|
|
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: "
|
|
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
|
|
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}`)
|
|
@@ -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
|
|
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 */
|
|
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 */
|
|
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
|
+
}
|
|
@@ -128,11 +128,8 @@ function getValidDatabaseOptions(databases) {
|
|
|
128
128
|
options.push("prisma");
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
else if (db.name === "mongoose") {
|
|
132
|
-
options.push("mongoose");
|
|
133
|
-
}
|
|
134
131
|
else {
|
|
135
|
-
// For other databases, add the name directly
|
|
132
|
+
// For other databases, add the module name directly (generic handling)
|
|
136
133
|
options.push(db.name);
|
|
137
134
|
}
|
|
138
135
|
}
|
|
@@ -161,12 +158,10 @@ function getCompatibleAuthOptions(authModules, framework, database) {
|
|
|
161
158
|
}
|
|
162
159
|
// Normalize database option (handle prisma-<provider> values)
|
|
163
160
|
const parsedDb = (0, shared_1.parseDatabaseOption)(database || "").database;
|
|
164
|
-
//
|
|
165
|
-
if (auth.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (auth.name === "better-auth" && parsedDb === "none" && framework !== "react") {
|
|
169
|
-
continue;
|
|
161
|
+
// If module provides explicit compatibility matrix, use it
|
|
162
|
+
if (auth.compatibility && auth.compatibility.databases) {
|
|
163
|
+
if (!auth.compatibility.databases.includes(parsedDb))
|
|
164
|
+
continue;
|
|
170
165
|
}
|
|
171
166
|
compatible.push({
|
|
172
167
|
name: auth.displayName,
|
|
@@ -200,11 +195,9 @@ function getDatabaseChoices(databases, framework) {
|
|
|
200
195
|
choices.push({ name: "Prisma", value: "prisma" });
|
|
201
196
|
}
|
|
202
197
|
}
|
|
203
|
-
else if (db.name === "mongoose") {
|
|
204
|
-
choices.push({ name: "Mongoose", value: "mongoose" });
|
|
205
|
-
}
|
|
206
198
|
else {
|
|
207
|
-
|
|
199
|
+
// Generic handling for other database modules
|
|
200
|
+
choices.push({ name: db.displayName || db.name, value: db.name });
|
|
208
201
|
}
|
|
209
202
|
}
|
|
210
203
|
// Add "None" at the end
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.parseDatabaseOption = parseDatabaseOption;
|
|
7
7
|
exports.getPrismaProvidersFromGenerator = getPrismaProvidersFromGenerator;
|
|
8
8
|
exports.isPrismaOption = isPrismaOption;
|
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
10
|
const path_1 = __importDefault(require("path"));
|
|
10
11
|
const package_root_1 = require("../utils/package-root");
|
|
11
12
|
function parseDatabaseOption(dbOption) {
|
|
@@ -19,20 +20,21 @@ function parseDatabaseOption(dbOption) {
|
|
|
19
20
|
}
|
|
20
21
|
if (dbOption === "prisma")
|
|
21
22
|
return { database: "prisma" };
|
|
22
|
-
if (dbOption === "mongoose")
|
|
23
|
-
return { database: "mongoose" };
|
|
24
23
|
return { database: dbOption };
|
|
25
24
|
}
|
|
26
25
|
function getPrismaProvidersFromGenerator(modulesDir) {
|
|
27
26
|
const pkgRoot = modulesDir || (0, package_root_1.getPackageRoot)();
|
|
28
27
|
const genPath = path_1.default.join(pkgRoot, "modules", "database", "prisma", "generator.json");
|
|
29
28
|
try {
|
|
30
|
-
const gen =
|
|
29
|
+
const gen = fs_extra_1.default.readJsonSync(genPath, { throws: false });
|
|
31
30
|
const providers = new Set();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
const ops = gen && typeof gen === "object" ? gen["operations"] : undefined;
|
|
32
|
+
if (Array.isArray(ops)) {
|
|
33
|
+
for (const op of ops) {
|
|
34
|
+
const cond = op && typeof op === "object" ? op["condition"] : undefined;
|
|
35
|
+
if (cond && typeof cond["prismaProvider"] === "string") {
|
|
36
|
+
providers.add(String(cond["prismaProvider"]));
|
|
37
|
+
}
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
return Array.from(providers);
|
|
@@ -53,6 +53,7 @@ export declare class AdvancedCodeGenerator {
|
|
|
53
53
|
private generators;
|
|
54
54
|
private frameworkConfig;
|
|
55
55
|
private postInstallCommands;
|
|
56
|
+
private createdFiles;
|
|
56
57
|
constructor(frameworkConfig: FrameworkConfig);
|
|
57
58
|
loadGenerators(modulesPath: string): Promise<void>;
|
|
58
59
|
private evaluateCondition;
|
|
@@ -65,6 +66,7 @@ export declare class AdvancedCodeGenerator {
|
|
|
65
66
|
auth?: string;
|
|
66
67
|
prismaProvider?: string;
|
|
67
68
|
}, features: string[], outputPath: string): Promise<string[]>;
|
|
69
|
+
getCreatedFiles(): string[];
|
|
68
70
|
private executeOperation;
|
|
69
71
|
private copyTemplate;
|
|
70
72
|
private processOperationTemplates;
|