stackkit 0.2.3 → 0.2.7
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/dist/cli/add.js +2 -16
- package/dist/cli/create.js +2 -5
- package/dist/cli/doctor.js +0 -4
- package/dist/cli/list.js +73 -83
- package/dist/index.js +25 -44
- package/dist/lib/constants.d.ts +110 -0
- package/dist/lib/constants.js +112 -0
- package/dist/lib/conversion/js-conversion.js +27 -11
- package/dist/lib/discovery/installed-detection.js +3 -3
- package/dist/lib/discovery/module-discovery.d.ts +1 -1
- package/dist/lib/discovery/module-discovery.js +22 -6
- package/dist/lib/env/env-editor.js +41 -47
- package/dist/lib/fs/files.d.ts +0 -1
- package/dist/lib/fs/files.js +12 -40
- package/dist/lib/generation/code-generator.d.ts +4 -1
- package/dist/lib/generation/code-generator.js +39 -13
- package/dist/lib/pm/package-manager.d.ts +1 -1
- package/dist/lib/pm/package-manager.js +130 -14
- package/dist/lib/ui/logger.d.ts +8 -1
- package/dist/lib/ui/logger.js +60 -3
- package/dist/lib/utils/fs-helpers.d.ts +12 -0
- package/dist/lib/utils/fs-helpers.js +61 -0
- package/dist/lib/utils/json-loader.d.ts +6 -0
- package/dist/lib/utils/json-loader.js +34 -0
- package/dist/lib/utils/module-loader.d.ts +9 -0
- package/dist/lib/utils/module-loader.js +98 -0
- package/dist/lib/utils/package-root.d.ts +1 -0
- package/dist/lib/utils/package-root.js +75 -2
- package/dist/lib/utils/path-resolver.d.ts +9 -0
- package/dist/lib/utils/path-resolver.js +44 -0
- package/modules/auth/authjs/files/nextjs/api/auth/[...nextauth]/route.ts +3 -0
- package/modules/auth/authjs/files/nextjs/proxy.ts +1 -0
- package/modules/auth/authjs/files/shared/lib/auth.ts +119 -0
- package/modules/auth/authjs/files/{prisma → shared/prisma}/schema.prisma +11 -1
- package/modules/auth/authjs/generator.json +18 -8
- package/modules/auth/better-auth/files/express/middlewares/authorize.ts +54 -0
- package/modules/auth/better-auth/files/express/types/express.d.ts +16 -0
- package/modules/auth/better-auth/files/nextjs/lib/auth/auth-guards.ts +31 -0
- package/modules/auth/better-auth/files/nextjs/proxy.ts +34 -0
- package/modules/auth/better-auth/files/{lib → shared/lib}/auth-client.ts +1 -1
- package/modules/auth/better-auth/files/{lib → shared/lib}/auth.ts +46 -20
- package/modules/auth/better-auth/files/{prisma → shared/prisma}/schema.prisma +11 -2
- package/modules/auth/better-auth/generator.json +74 -19
- package/modules/database/mongoose/generator.json +16 -2
- package/modules/database/prisma/files/lib/prisma.ts +1 -1
- package/modules/database/prisma/files/prisma/schema.prisma +1 -2
- package/modules/database/prisma/generator.json +8 -1
- package/package.json +7 -7
- package/templates/express/env.example +2 -1
- package/templates/express/package.json +3 -4
- package/templates/express/src/app.ts +18 -25
- package/templates/express/src/config/cors.ts +12 -0
- package/templates/express/src/config/helmet.ts +5 -0
- package/templates/express/src/config/logger.ts +6 -0
- package/templates/express/src/config/rate-limit.ts +11 -0
- package/templates/express/src/{features → modules}/health/health.route.ts +1 -1
- package/templates/express/src/routes/index.ts +12 -0
- package/templates/express/src/shared/errors/api-error.ts +14 -0
- package/templates/express/src/shared/errors/error-codes.ts +9 -0
- package/templates/express/src/shared/logger/logger.ts +20 -0
- package/templates/express/src/{middlewares → shared/middlewares}/error.middleware.ts +1 -1
- package/templates/express/src/shared/middlewares/not-found.middleware.ts +9 -0
- package/templates/express/src/shared/utils/async-handler.ts +9 -0
- package/templates/express/src/shared/utils/pagination.ts +6 -0
- package/templates/express/src/shared/utils/response.ts +9 -0
- package/templates/express/tsconfig.json +9 -3
- package/templates/nextjs/next-env.d.ts +6 -0
- package/templates/react/dist/assets/index-D4AHT4dU.js +193 -0
- package/templates/react/dist/assets/index-rpwj5ZOX.css +1 -0
- package/templates/react/dist/index.html +14 -0
- package/templates/react/dist/vite.svg +1 -0
- package/templates/react/src/app/layouts/dashboard-layout.tsx +8 -0
- package/templates/react/src/app/layouts/public-layout.tsx +5 -0
- package/templates/react/src/app/providers.tsx +20 -0
- package/templates/react/src/app/router.tsx +21 -0
- package/templates/react/src/{pages/About.tsx → features/about/pages/about.tsx} +1 -1
- package/templates/react/src/{pages/Home.tsx → features/home/pages/home.tsx} +1 -1
- package/templates/react/src/main.tsx +2 -2
- package/templates/react/src/{api/client.ts → shared/api/http.ts} +1 -1
- package/templates/react/src/{pages/NotFound.tsx → shared/pages/not-found.tsx} +1 -1
- package/dist/lib/git-utils.d.ts +0 -1
- package/dist/lib/git-utils.js +0 -29
- package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +0 -2
- package/modules/auth/authjs/files/lib/auth.ts +0 -22
- package/templates/express/.env.example +0 -2
- package/templates/nextjs/.env.example +0 -1
- package/templates/react/.env.example +0 -1
- package/templates/react/.prettierignore +0 -4
- package/templates/react/.prettierrc +0 -9
- /package/modules/auth/better-auth/files/{api → nextjs/api}/auth/[...all]/route.ts +0 -0
- /package/modules/auth/better-auth/files/{lib → shared/lib/email}/email-service.ts +0 -0
- /package/modules/auth/better-auth/files/{lib → shared/lib/email}/email-templates.ts +0 -0
- /package/templates/express/src/{features → modules}/health/health.controller.ts +0 -0
- /package/templates/express/src/{features → modules}/health/health.service.ts +0 -0
- /package/templates/react/src/{components/ErrorBoundary.tsx → shared/components/error-boundary.tsx} +0 -0
- /package/templates/react/src/{components/Layout.tsx → shared/components/layout.tsx} +0 -0
- /package/templates/react/src/{components/Loading.tsx → shared/components/loading.tsx} +0 -0
- /package/templates/react/src/{components/SEO.tsx → shared/components/seo.tsx} +0 -0
- /package/templates/react/src/{lib/queryClient.ts → shared/lib/query-client.ts} +0 -0
package/dist/cli/add.js
CHANGED
|
@@ -31,10 +31,7 @@ async function addCommand(module, options) {
|
|
|
31
31
|
await addModuleToProject(projectRoot, refreshedProjectInfo, config, options);
|
|
32
32
|
logger_1.logger.newLine();
|
|
33
33
|
if (config.preAdded && config.preAdded.length > 0) {
|
|
34
|
-
const addedNames = [
|
|
35
|
-
...config.preAdded.map((p) => p.displayName),
|
|
36
|
-
config.displayName,
|
|
37
|
-
].map((s) => chalk_1.default.bold(s));
|
|
34
|
+
const addedNames = [...config.preAdded.map((p) => p.displayName), config.displayName].map((s) => chalk_1.default.bold(s));
|
|
38
35
|
logger_1.logger.success(`Added ${addedNames.join(" and ")}`);
|
|
39
36
|
}
|
|
40
37
|
else {
|
|
@@ -121,7 +118,7 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
|
|
|
121
118
|
const discovered = await (0, module_discovery_1.discoverModules)(modulesDir);
|
|
122
119
|
// Prefer discovered framework, then projectInfo.framework; leave empty if unknown
|
|
123
120
|
const defaultFramework = (discovered.frameworks && discovered.frameworks[0]?.name) || projectInfo?.framework || "";
|
|
124
|
-
const compatibleAuths = (0, module_discovery_1.getCompatibleAuthOptions)(discovered.auth || [], projectInfo?.framework || defaultFramework, projectInfo?.hasPrisma ? "prisma" : "none");
|
|
121
|
+
const compatibleAuths = (0, module_discovery_1.getCompatibleAuthOptions)(discovered.auth || [], projectInfo?.framework || defaultFramework, projectInfo?.hasPrisma ? "prisma" : "none", discovered.frameworks);
|
|
125
122
|
const categories = [
|
|
126
123
|
{ name: "Database", value: "database" },
|
|
127
124
|
];
|
|
@@ -171,7 +168,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
|
|
|
171
168
|
}
|
|
172
169
|
else if (category === "auth") {
|
|
173
170
|
let preAddedForReturn;
|
|
174
|
-
// If no database detected, require the user to select/add a database first
|
|
175
171
|
if (!projectInfo?.hasDatabase) {
|
|
176
172
|
logger_1.logger.warn("No database detected in the project. Authentication requires a database.");
|
|
177
173
|
const dbChoices = (0, module_discovery_1.getDatabaseChoices)(discovered.databases || [], projectInfo?.framework || defaultFramework);
|
|
@@ -188,7 +184,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
|
|
|
188
184
|
logger_1.logger.info("Cancelled — authentication requires a database");
|
|
189
185
|
process.exit(0);
|
|
190
186
|
}
|
|
191
|
-
// Build a database AddConfig and add it immediately, then refresh projectInfo
|
|
192
187
|
let dbConfig;
|
|
193
188
|
if (selectedDb.startsWith("prisma-")) {
|
|
194
189
|
const provider = selectedDb.split("-")[1];
|
|
@@ -210,13 +205,9 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
|
|
|
210
205
|
metadata: meta,
|
|
211
206
|
};
|
|
212
207
|
}
|
|
213
|
-
// Add the database first (suppress its top-level success message)
|
|
214
208
|
await addModuleToProject(projectRoot, projectInfo || (await (0, detect_1.detectProjectInfo)(projectRoot)), dbConfig, options);
|
|
215
|
-
// Refresh project info after database install and record pre-added
|
|
216
209
|
projectInfo = await (0, detect_1.detectProjectInfo)(projectRoot);
|
|
217
|
-
// attach preAdded so caller can summarize chained additions
|
|
218
210
|
dbConfig.preAdded = dbConfig.preAdded || [];
|
|
219
|
-
// store for returning later
|
|
220
211
|
preAddedForReturn = dbConfig;
|
|
221
212
|
}
|
|
222
213
|
const dbString = projectInfo?.hasPrisma ? "prisma" : "none";
|
|
@@ -249,7 +240,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
|
|
|
249
240
|
displayName: metadata.displayName || selectedAuth,
|
|
250
241
|
metadata,
|
|
251
242
|
};
|
|
252
|
-
// If we added a DB earlier in this flow, include it for grouped messaging
|
|
253
243
|
if (typeof preAddedForReturn !== "undefined" && preAddedForReturn) {
|
|
254
244
|
result.preAdded = [preAddedForReturn];
|
|
255
245
|
}
|
|
@@ -257,7 +247,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
|
|
|
257
247
|
}
|
|
258
248
|
throw new Error("Invalid selection");
|
|
259
249
|
}
|
|
260
|
-
/* removed unused getProviderConfig — discovery-based flows handle providers */
|
|
261
250
|
async function addModuleToProject(projectRoot, projectInfo, config, options) {
|
|
262
251
|
const moduleMetadata = config.metadata;
|
|
263
252
|
const selectedProvider = config.provider;
|
|
@@ -329,14 +318,11 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
|
|
|
329
318
|
}
|
|
330
319
|
}
|
|
331
320
|
const selectedModules = { framework: projectInfo.framework };
|
|
332
|
-
// Populate database context from detected project state so generator conditions work
|
|
333
321
|
try {
|
|
334
322
|
const pkg = await fs_extra_1.default.readJson(path_1.default.join(projectRoot, "package.json"));
|
|
335
323
|
const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
336
324
|
if (projectInfo.hasPrisma) {
|
|
337
325
|
selectedModules.database = "prisma";
|
|
338
|
-
// Parse provider specifically from the `datasource` block to avoid
|
|
339
|
-
// capturing the generator block (which uses provider = "prisma-client-js").
|
|
340
326
|
const prismaSchema = path_1.default.join(projectRoot, "prisma", "schema.prisma");
|
|
341
327
|
if (await fs_extra_1.default.pathExists(prismaSchema)) {
|
|
342
328
|
const content = await fs_extra_1.default.readFile(prismaSchema, "utf-8");
|
package/dist/cli/create.js
CHANGED
|
@@ -16,7 +16,6 @@ const shared_1 = require("../lib/discovery/shared");
|
|
|
16
16
|
const env_editor_1 = require("../lib/env/env-editor");
|
|
17
17
|
const framework_utils_1 = require("../lib/framework/framework-utils");
|
|
18
18
|
const code_generator_1 = require("../lib/generation/code-generator");
|
|
19
|
-
const git_utils_1 = require("../lib/git-utils");
|
|
20
19
|
const package_manager_1 = require("../lib/pm/package-manager");
|
|
21
20
|
const logger_1 = require("../lib/ui/logger");
|
|
22
21
|
const package_root_1 = require("../lib/utils/package-root");
|
|
@@ -205,8 +204,6 @@ async function getProjectConfig(projectName, options) {
|
|
|
205
204
|
return [{ name: "None", value: "none" }];
|
|
206
205
|
},
|
|
207
206
|
},
|
|
208
|
-
// If a prisma-* choice is selected above, `prismaProvider` will be derived from it,
|
|
209
|
-
// otherwise prompt for provider when `prisma` is selected directly.
|
|
210
207
|
{
|
|
211
208
|
type: "list",
|
|
212
209
|
name: "prismaProvider",
|
|
@@ -222,7 +219,7 @@ async function getProjectConfig(projectName, options) {
|
|
|
222
219
|
name: "auth",
|
|
223
220
|
message: "Select authentication:",
|
|
224
221
|
when: (answers) => answers.database !== "none" || answers.framework === "react",
|
|
225
|
-
choices: (answers) => (0, module_discovery_1.getCompatibleAuthOptions)(discoveredModules.auth, answers.framework, answers.database || "none"),
|
|
222
|
+
choices: (answers) => (0, module_discovery_1.getCompatibleAuthOptions)(discoveredModules.auth, answers.framework, answers.database || "none", discoveredModules.frameworks),
|
|
226
223
|
},
|
|
227
224
|
{
|
|
228
225
|
type: "list",
|
|
@@ -306,7 +303,7 @@ async function generateProject(config, targetDir, options) {
|
|
|
306
303
|
if (options?.git !== false && !(options?.["no-git"] || options?.noGit)) {
|
|
307
304
|
const gitSpinner = logger_1.logger.startSpinner("Initializing git repository...");
|
|
308
305
|
try {
|
|
309
|
-
await (0,
|
|
306
|
+
await (0, package_manager_1.initGit)(targetDir);
|
|
310
307
|
gitSpinner.succeed("Git repository initialized");
|
|
311
308
|
}
|
|
312
309
|
catch (error) {
|
package/dist/cli/doctor.js
CHANGED
|
@@ -296,9 +296,6 @@ async function checkAuthRoutesExist(projectRoot) {
|
|
|
296
296
|
catch {
|
|
297
297
|
// ignore discovery errors
|
|
298
298
|
}
|
|
299
|
-
// Fallback to known common paths if generators don't provide any
|
|
300
|
-
// If generators provided candidate routes, check them. Otherwise
|
|
301
|
-
// do not assume any hard-coded route locations.
|
|
302
299
|
if (candidates.size === 0)
|
|
303
300
|
return false;
|
|
304
301
|
for (const routePath of candidates) {
|
|
@@ -442,7 +439,6 @@ async function checkDependencies(packageJson) {
|
|
|
442
439
|
// Assume up to date if using flexible versioning
|
|
443
440
|
}
|
|
444
441
|
else {
|
|
445
|
-
// Assume outdated if using exact versions (simplified check)
|
|
446
442
|
outdated.push(name);
|
|
447
443
|
}
|
|
448
444
|
}
|
package/dist/cli/list.js
CHANGED
|
@@ -9,6 +9,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const shared_1 = require("../lib/discovery/shared");
|
|
11
11
|
const logger_1 = require("../lib/ui/logger");
|
|
12
|
+
const module_loader_1 = require("../lib/utils/module-loader");
|
|
12
13
|
const package_root_1 = require("../lib/utils/package-root");
|
|
13
14
|
async function listCommand(options) {
|
|
14
15
|
const showFrameworks = !options.modules || options.frameworks;
|
|
@@ -16,72 +17,22 @@ async function listCommand(options) {
|
|
|
16
17
|
try {
|
|
17
18
|
logger_1.logger.header("StackKit Resources");
|
|
18
19
|
logger_1.logger.newLine();
|
|
19
|
-
let
|
|
20
|
-
let hasModules = false;
|
|
20
|
+
let hasContent = false;
|
|
21
21
|
if (showFrameworks) {
|
|
22
|
-
const
|
|
23
|
-
const frameworks = await getAvailableFrameworks(templatesDir);
|
|
22
|
+
const frameworks = await getAvailableFrameworks();
|
|
24
23
|
if (frameworks.length > 0) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
frameworks.forEach((framework, index) => {
|
|
28
|
-
const isLast = index === frameworks.length - 1;
|
|
29
|
-
const prefix = isLast ? "└──" : "├──";
|
|
30
|
-
logger_1.logger.log(` ${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(framework.displayName || framework.name)}`);
|
|
31
|
-
});
|
|
32
|
-
logger_1.logger.newLine();
|
|
24
|
+
hasContent = true;
|
|
25
|
+
printFrameworks(frameworks);
|
|
33
26
|
}
|
|
34
27
|
}
|
|
35
28
|
if (showModules) {
|
|
36
|
-
const
|
|
37
|
-
const modules = await getAvailableModules(modulesDir);
|
|
29
|
+
const modules = await getAvailableModules();
|
|
38
30
|
if (modules.length > 0) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const grouped = modules.reduce((acc, mod) => {
|
|
42
|
-
const cat = mod.category || "other";
|
|
43
|
-
if (!acc[cat])
|
|
44
|
-
acc[cat] = [];
|
|
45
|
-
acc[cat].push(mod);
|
|
46
|
-
return acc;
|
|
47
|
-
}, {});
|
|
48
|
-
const categories = Object.keys(grouped);
|
|
49
|
-
categories.forEach((category, categoryIndex) => {
|
|
50
|
-
const mods = grouped[category];
|
|
51
|
-
const isLastCategory = categoryIndex === categories.length - 1;
|
|
52
|
-
const categoryPrefix = isLastCategory ? "└──" : "├──";
|
|
53
|
-
logger_1.logger.log(` ${chalk_1.default.gray(categoryPrefix)} ${chalk_1.default.yellow(formatCategoryName(category))} ${chalk_1.default.dim(`(${mods.length})`)}`);
|
|
54
|
-
mods.forEach((mod, modIndex) => {
|
|
55
|
-
const isLastMod = modIndex === mods.length - 1;
|
|
56
|
-
const modPrefix = isLastCategory
|
|
57
|
-
? isLastMod
|
|
58
|
-
? " └──"
|
|
59
|
-
: " ├──"
|
|
60
|
-
: isLastMod
|
|
61
|
-
? "│ └──"
|
|
62
|
-
: "│ ├──";
|
|
63
|
-
logger_1.logger.log(` ${chalk_1.default.gray(modPrefix)} ${chalk_1.default.green(mod.displayName)}`);
|
|
64
|
-
if (mod.category === "database" && mod.name === "prisma") {
|
|
65
|
-
const providerPrefix = isLastCategory
|
|
66
|
-
? isLastMod
|
|
67
|
-
? " └──"
|
|
68
|
-
: " ├──"
|
|
69
|
-
: isLastMod
|
|
70
|
-
? "│ └──"
|
|
71
|
-
: "│ ├──";
|
|
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";
|
|
77
|
-
logger_1.logger.log(` ${chalk_1.default.gray(providerPrefix)} ${chalk_1.default.dim(`Providers: ${providersText}`)}`);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
logger_1.logger.newLine();
|
|
31
|
+
hasContent = true;
|
|
32
|
+
printModules(modules);
|
|
82
33
|
}
|
|
83
34
|
}
|
|
84
|
-
if (!
|
|
35
|
+
if (!hasContent) {
|
|
85
36
|
logger_1.logger.log(chalk_1.default.dim("No resources available"));
|
|
86
37
|
logger_1.logger.newLine();
|
|
87
38
|
}
|
|
@@ -93,18 +44,79 @@ async function listCommand(options) {
|
|
|
93
44
|
process.exit(1);
|
|
94
45
|
}
|
|
95
46
|
}
|
|
96
|
-
|
|
47
|
+
function printFrameworks(frameworks) {
|
|
48
|
+
logger_1.logger.log(chalk_1.default.bold.blue("FRAMEWORKS"));
|
|
49
|
+
frameworks.forEach((framework, index) => {
|
|
50
|
+
const isLast = index === frameworks.length - 1;
|
|
51
|
+
const prefix = isLast ? "└──" : "├──";
|
|
52
|
+
logger_1.logger.log(` ${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(framework.displayName)}`);
|
|
53
|
+
});
|
|
54
|
+
logger_1.logger.newLine();
|
|
55
|
+
}
|
|
56
|
+
function printModules(modules) {
|
|
57
|
+
logger_1.logger.log(chalk_1.default.bold.magenta("MODULES"));
|
|
58
|
+
const grouped = groupModulesByCategory(modules);
|
|
59
|
+
const categories = Object.keys(grouped);
|
|
60
|
+
categories.forEach((category, categoryIndex) => {
|
|
61
|
+
const mods = grouped[category];
|
|
62
|
+
const isLastCategory = categoryIndex === categories.length - 1;
|
|
63
|
+
const categoryPrefix = isLastCategory ? "└──" : "├──";
|
|
64
|
+
logger_1.logger.log(` ${chalk_1.default.gray(categoryPrefix)} ${chalk_1.default.yellow(formatCategoryName(category))} ${chalk_1.default.dim(`(${mods.length})`)}`);
|
|
65
|
+
mods.forEach((mod, modIndex) => {
|
|
66
|
+
const isLastMod = modIndex === mods.length - 1;
|
|
67
|
+
const modPrefix = getModulePrefix(isLastCategory, isLastMod);
|
|
68
|
+
logger_1.logger.log(` ${chalk_1.default.gray(modPrefix)} ${chalk_1.default.green(mod.displayName)}`);
|
|
69
|
+
if (mod.category === "database" && mod.name === "prisma") {
|
|
70
|
+
printPrismaProviders(isLastCategory, isLastMod);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
logger_1.logger.newLine();
|
|
75
|
+
}
|
|
76
|
+
function printPrismaProviders(isLastCategory, isLastMod) {
|
|
77
|
+
const providerPrefix = getProviderPrefix(isLastCategory, isLastMod);
|
|
78
|
+
const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
|
|
79
|
+
const providersText = providers.length
|
|
80
|
+
? providers.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(", ")
|
|
81
|
+
: "None";
|
|
82
|
+
logger_1.logger.log(` ${chalk_1.default.gray(providerPrefix)} ${chalk_1.default.dim(`Providers: ${providersText}`)}`);
|
|
83
|
+
}
|
|
84
|
+
function getModulePrefix(isLastCategory, isLastMod) {
|
|
85
|
+
if (isLastCategory) {
|
|
86
|
+
return isLastMod ? " └──" : " ├──";
|
|
87
|
+
}
|
|
88
|
+
return isLastMod ? "│ └──" : "│ ├──";
|
|
89
|
+
}
|
|
90
|
+
function getProviderPrefix(isLastCategory, isLastMod) {
|
|
91
|
+
if (isLastCategory) {
|
|
92
|
+
return isLastMod ? " └──" : " ├──";
|
|
93
|
+
}
|
|
94
|
+
return isLastMod ? "│ └──" : "│ ├──";
|
|
95
|
+
}
|
|
96
|
+
function groupModulesByCategory(modules) {
|
|
97
|
+
return modules.reduce((acc, mod) => {
|
|
98
|
+
const cat = mod.category || "other";
|
|
99
|
+
if (!acc[cat])
|
|
100
|
+
acc[cat] = [];
|
|
101
|
+
acc[cat].push(mod);
|
|
102
|
+
return acc;
|
|
103
|
+
}, {});
|
|
104
|
+
}
|
|
105
|
+
async function getAvailableFrameworks() {
|
|
106
|
+
const templatesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "templates");
|
|
97
107
|
if (!(await fs_extra_1.default.pathExists(templatesDir))) {
|
|
98
108
|
return [];
|
|
99
109
|
}
|
|
100
110
|
const frameworkDirs = await fs_extra_1.default.readdir(templatesDir);
|
|
101
|
-
|
|
111
|
+
return frameworkDirs
|
|
102
112
|
.filter((dir) => dir !== "node_modules" && dir !== ".git")
|
|
103
113
|
.map((dir) => ({
|
|
104
114
|
name: dir,
|
|
105
115
|
displayName: formatFrameworkName(dir),
|
|
106
116
|
}));
|
|
107
|
-
|
|
117
|
+
}
|
|
118
|
+
async function getAvailableModules() {
|
|
119
|
+
return (0, module_loader_1.getAllModules)();
|
|
108
120
|
}
|
|
109
121
|
function formatFrameworkName(name) {
|
|
110
122
|
return name
|
|
@@ -115,25 +127,3 @@ function formatFrameworkName(name) {
|
|
|
115
127
|
function formatCategoryName(name) {
|
|
116
128
|
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
117
129
|
}
|
|
118
|
-
async function getAvailableModules(modulesDir) {
|
|
119
|
-
if (!(await fs_extra_1.default.pathExists(modulesDir))) {
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
122
|
-
const modules = [];
|
|
123
|
-
const categories = await fs_extra_1.default.readdir(modulesDir);
|
|
124
|
-
for (const category of categories) {
|
|
125
|
-
const categoryPath = path_1.default.join(modulesDir, category);
|
|
126
|
-
const stat = await fs_extra_1.default.stat(categoryPath);
|
|
127
|
-
if (!stat.isDirectory())
|
|
128
|
-
continue;
|
|
129
|
-
const moduleDirs = await fs_extra_1.default.readdir(categoryPath);
|
|
130
|
-
for (const moduleDir of moduleDirs) {
|
|
131
|
-
const metadataPath = path_1.default.join(categoryPath, moduleDir, "module.json");
|
|
132
|
-
if (await fs_extra_1.default.pathExists(metadataPath)) {
|
|
133
|
-
const metadata = await fs_extra_1.default.readJSON(metadataPath);
|
|
134
|
-
modules.push(metadata);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return modules;
|
|
139
|
-
}
|
package/dist/index.js
CHANGED
|
@@ -36,65 +36,51 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
const commander_1 = require("commander");
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
|
-
const fs_1 = require("fs");
|
|
40
39
|
const path_1 = require("path");
|
|
41
40
|
const add_1 = require("./cli/add");
|
|
42
41
|
const create_1 = require("./cli/create");
|
|
43
42
|
const doctor_1 = require("./cli/doctor");
|
|
44
43
|
const list_1 = require("./cli/list");
|
|
44
|
+
const constants_1 = require("./lib/constants");
|
|
45
45
|
const shared_1 = require("./lib/discovery/shared");
|
|
46
46
|
const logger_1 = require("./lib/ui/logger");
|
|
47
|
+
const json_loader_1 = require("./lib/utils/json-loader");
|
|
47
48
|
const package_root_1 = require("./lib/utils/package-root");
|
|
48
|
-
const
|
|
49
|
+
const path_resolver_1 = require("./lib/utils/path-resolver");
|
|
50
|
+
const packageJson = (0, json_loader_1.loadJsonSync)((0, path_1.join)(__dirname, "../package.json"));
|
|
49
51
|
function buildOptionHints() {
|
|
50
52
|
try {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
+
const databaseModulesPath = (0, path_resolver_1.getDatabaseModulesPath)();
|
|
54
|
+
const authModulesPath = (0, path_resolver_1.getAuthModulesPath)();
|
|
53
55
|
const dbs = [];
|
|
54
56
|
const auths = [];
|
|
55
|
-
if (fs.existsSync(
|
|
56
|
-
for (const d of fs.readdirSync(
|
|
57
|
-
const moduleJson = (0,
|
|
57
|
+
if (fs.existsSync(databaseModulesPath)) {
|
|
58
|
+
for (const d of fs.readdirSync(databaseModulesPath)) {
|
|
59
|
+
const moduleJson = (0, path_resolver_1.getModuleJsonPath)(constants_1.MODULE_CATEGORIES.DATABASE, d);
|
|
58
60
|
if (fs.existsSync(moduleJson)) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (providers.length > 0) {
|
|
65
|
-
for (const p of providers)
|
|
66
|
-
dbs.push(`prisma-${p}`);
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
dbs.push("prisma");
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
dbs.push("prisma");
|
|
74
|
-
}
|
|
61
|
+
const m = (0, json_loader_1.loadJsonSync)(moduleJson);
|
|
62
|
+
if (m && m.name === "prisma") {
|
|
63
|
+
const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
|
|
64
|
+
if (providers.length > 0) {
|
|
65
|
+
providers.forEach((p) => dbs.push(`prisma-${p}`));
|
|
75
66
|
}
|
|
76
|
-
else
|
|
77
|
-
dbs.push(
|
|
67
|
+
else {
|
|
68
|
+
dbs.push("prisma");
|
|
78
69
|
}
|
|
79
70
|
}
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
else if (m && m.name) {
|
|
72
|
+
dbs.push(m.name);
|
|
82
73
|
}
|
|
83
74
|
}
|
|
84
75
|
}
|
|
85
76
|
}
|
|
86
|
-
if (fs.existsSync(
|
|
87
|
-
for (const a of fs.readdirSync(
|
|
88
|
-
const moduleJson = (0,
|
|
77
|
+
if (fs.existsSync(authModulesPath)) {
|
|
78
|
+
for (const a of fs.readdirSync(authModulesPath)) {
|
|
79
|
+
const moduleJson = (0, path_resolver_1.getModuleJsonPath)(constants_1.MODULE_CATEGORIES.AUTH, a);
|
|
89
80
|
if (fs.existsSync(moduleJson)) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
auths.push(m.name);
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
/* ignore */
|
|
97
|
-
}
|
|
81
|
+
const m = (0, json_loader_1.loadJsonSync)(moduleJson);
|
|
82
|
+
if (m && m.name)
|
|
83
|
+
auths.push(m.name);
|
|
98
84
|
}
|
|
99
85
|
}
|
|
100
86
|
}
|
|
@@ -112,7 +98,7 @@ const program = new commander_1.Command();
|
|
|
112
98
|
program
|
|
113
99
|
.name("stackkit")
|
|
114
100
|
.description("CLI for creating and managing StackKit projects")
|
|
115
|
-
.version(packageJson.
|
|
101
|
+
.version(packageJson?.version || "0.0.0")
|
|
116
102
|
.configureHelp({
|
|
117
103
|
subcommandTerm: (cmd) => {
|
|
118
104
|
const name = cmd.name();
|
|
@@ -129,7 +115,6 @@ program
|
|
|
129
115
|
return name + " [options]";
|
|
130
116
|
},
|
|
131
117
|
});
|
|
132
|
-
// Create command
|
|
133
118
|
program
|
|
134
119
|
.command("create [project-name]")
|
|
135
120
|
.description("Create a new StackKit project")
|
|
@@ -152,7 +137,6 @@ program
|
|
|
152
137
|
process.exit(1);
|
|
153
138
|
}
|
|
154
139
|
});
|
|
155
|
-
// Add command
|
|
156
140
|
program
|
|
157
141
|
.command("add [module]")
|
|
158
142
|
.description("Add a module or category to your existing project")
|
|
@@ -171,7 +155,6 @@ program
|
|
|
171
155
|
process.exit(1);
|
|
172
156
|
}
|
|
173
157
|
});
|
|
174
|
-
// Doctor command
|
|
175
158
|
program
|
|
176
159
|
.command("doctor")
|
|
177
160
|
.description("Check project health and compatibility with StackKit modules")
|
|
@@ -187,7 +170,6 @@ program
|
|
|
187
170
|
process.exit(1);
|
|
188
171
|
}
|
|
189
172
|
});
|
|
190
|
-
// List command
|
|
191
173
|
program
|
|
192
174
|
.command("list")
|
|
193
175
|
.description("List available frameworks and modules")
|
|
@@ -202,7 +184,6 @@ program
|
|
|
202
184
|
process.exit(1);
|
|
203
185
|
}
|
|
204
186
|
});
|
|
205
|
-
// Error handling
|
|
206
187
|
program.on("command:*", () => {
|
|
207
188
|
logger_1.logger.error(`Invalid command: ${program.args.join(" ")}`);
|
|
208
189
|
logger_1.logger.log("Run stackkit --help for a list of available commands.");
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
export declare const PACKAGE_MANAGERS: {
|
|
2
|
+
PNPM: "pnpm";
|
|
3
|
+
NPM: "npm";
|
|
4
|
+
YARN: "yarn";
|
|
5
|
+
BUN: "bun";
|
|
6
|
+
};
|
|
7
|
+
export declare const LOCK_FILES: {
|
|
8
|
+
readonly pnpm: "pnpm-lock.yaml";
|
|
9
|
+
readonly yarn: "yarn.lock";
|
|
10
|
+
readonly bun: "bun.lockb";
|
|
11
|
+
readonly npm: "package-lock.json";
|
|
12
|
+
};
|
|
13
|
+
export declare const LOCK_FILES_ARRAY: readonly [{
|
|
14
|
+
readonly file: "pnpm-lock.yaml";
|
|
15
|
+
readonly pm: "pnpm";
|
|
16
|
+
}, {
|
|
17
|
+
readonly file: "yarn.lock";
|
|
18
|
+
readonly pm: "yarn";
|
|
19
|
+
}, {
|
|
20
|
+
readonly file: "bun.lockb";
|
|
21
|
+
readonly pm: "bun";
|
|
22
|
+
}, {
|
|
23
|
+
readonly file: "package-lock.json";
|
|
24
|
+
readonly pm: "npm";
|
|
25
|
+
}];
|
|
26
|
+
export declare const LANGUAGES: {
|
|
27
|
+
TYPESCRIPT: "typescript";
|
|
28
|
+
JAVASCRIPT: "javascript";
|
|
29
|
+
};
|
|
30
|
+
export declare const MODULE_CATEGORIES: {
|
|
31
|
+
DATABASE: "database";
|
|
32
|
+
AUTH: "auth";
|
|
33
|
+
FRAMEWORK: "framework";
|
|
34
|
+
};
|
|
35
|
+
export declare const DIRECTORY_NAMES: {
|
|
36
|
+
readonly MODULES: "modules";
|
|
37
|
+
readonly TEMPLATES: "templates";
|
|
38
|
+
readonly NODE_MODULES: "node_modules";
|
|
39
|
+
readonly GIT: ".git";
|
|
40
|
+
readonly PRISMA: "prisma";
|
|
41
|
+
readonly FILES: "files";
|
|
42
|
+
readonly SRC: "src";
|
|
43
|
+
readonly DIST: "dist";
|
|
44
|
+
readonly BIN: "bin";
|
|
45
|
+
};
|
|
46
|
+
export declare const FILE_NAMES: {
|
|
47
|
+
readonly PACKAGE_JSON: "package.json";
|
|
48
|
+
readonly TSCONFIG_JSON: "tsconfig.json";
|
|
49
|
+
readonly MODULE_JSON: "module.json";
|
|
50
|
+
readonly GENERATOR_JSON: "generator.json";
|
|
51
|
+
readonly TEMPLATE_JSON: "template.json";
|
|
52
|
+
readonly CONFIG_JSON: "config.json";
|
|
53
|
+
readonly ENV: ".env";
|
|
54
|
+
readonly ENV_LOCAL: ".env.local";
|
|
55
|
+
readonly ENV_EXAMPLE: ".env.example";
|
|
56
|
+
readonly GITIGNORE: ".gitignore";
|
|
57
|
+
readonly README: "README.md";
|
|
58
|
+
readonly SCHEMA_PRISMA: "schema.prisma";
|
|
59
|
+
};
|
|
60
|
+
export declare const ENV_FILES: readonly [".env", ".env.local"];
|
|
61
|
+
export declare const EXCLUDE_FROM_COPY: readonly ["template.json", "config.json", "node_modules", ".git"];
|
|
62
|
+
export declare const TIMEOUTS: {
|
|
63
|
+
readonly PACKAGE_INSTALL: 300000;
|
|
64
|
+
readonly GIT_INIT: 30000;
|
|
65
|
+
readonly RETRY_DELAY_BASE: 1000;
|
|
66
|
+
};
|
|
67
|
+
export declare const RETRY_CONFIG: {
|
|
68
|
+
readonly MAX_ATTEMPTS: 2;
|
|
69
|
+
readonly PACKAGE_ROOT_MAX_ATTEMPTS: 10;
|
|
70
|
+
};
|
|
71
|
+
export declare const ENV_PATTERNS: {
|
|
72
|
+
readonly KEY: RegExp;
|
|
73
|
+
readonly COMMENT: RegExp;
|
|
74
|
+
};
|
|
75
|
+
export declare const ROUTER_TYPES: {
|
|
76
|
+
readonly APP: "app";
|
|
77
|
+
readonly PAGES: "pages";
|
|
78
|
+
};
|
|
79
|
+
export declare const DISPLAY_NAMES: {
|
|
80
|
+
readonly database: "Database";
|
|
81
|
+
readonly auth: "Auth";
|
|
82
|
+
readonly framework: "Framework";
|
|
83
|
+
};
|
|
84
|
+
export declare const ERROR_MESSAGES: {
|
|
85
|
+
readonly NO_PACKAGE_JSON: "No package.json found in current directory or any parent directory.";
|
|
86
|
+
readonly INVALID_DIRECTORY: "Target directory already exists and is not empty.";
|
|
87
|
+
readonly INVALID_PROJECT_NAME: "Invalid project name. Please use a valid npm package name.";
|
|
88
|
+
readonly UNKNOWN_MODULE_TYPE: (module: string) => string;
|
|
89
|
+
readonly MODULE_NOT_FOUND: (moduleName: string) => string;
|
|
90
|
+
readonly TEMPLATE_NOT_FOUND: (framework: string) => string;
|
|
91
|
+
readonly GIT_INIT_FAILED: "Failed to initialize git repository";
|
|
92
|
+
readonly PACKAGE_INSTALL_FAILED: "Failed to install dependencies";
|
|
93
|
+
};
|
|
94
|
+
export declare const SUCCESS_MESSAGES: {
|
|
95
|
+
readonly PROJECT_CREATED: "✨ Project created successfully!";
|
|
96
|
+
readonly MODULE_ADDED: "✨ Module added successfully!";
|
|
97
|
+
readonly DEPENDENCIES_INSTALLED: "✓ Dependencies installed";
|
|
98
|
+
readonly GIT_INITIALIZED: "✓ Git repository initialized";
|
|
99
|
+
};
|
|
100
|
+
export declare const CLI_COLORS: {
|
|
101
|
+
readonly PRIMARY: "cyan";
|
|
102
|
+
readonly SUCCESS: "green";
|
|
103
|
+
readonly WARNING: "yellow";
|
|
104
|
+
readonly ERROR: "red";
|
|
105
|
+
readonly INFO: "blue";
|
|
106
|
+
readonly HEADER: "magenta";
|
|
107
|
+
};
|
|
108
|
+
export declare const PACKAGE_NAME: "stackkit";
|
|
109
|
+
export declare const DEFAULT_PACKAGE_MANAGER: "npm";
|
|
110
|
+
export declare const DEFAULT_LANGUAGE: "typescript";
|