stackkit-cli 0.4.3 → 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 +26 -2
- package/bin/stackkit.js +10 -1
- package/dist/commands/add.js +128 -10
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.js +483 -0
- package/dist/commands/list.d.ts +1 -1
- package/dist/commands/list.js +59 -38
- package/dist/index.js +11 -13
- package/dist/types/index.d.ts +29 -2
- package/dist/utils/config-utils.d.ts +2 -0
- package/dist/utils/config-utils.js +88 -0
- package/dist/utils/detect.js +12 -2
- package/dist/utils/env-editor.d.ts +0 -1
- package/dist/utils/env-editor.js +50 -25
- package/dist/utils/files.d.ts +8 -0
- package/dist/utils/files.js +51 -0
- package/dist/utils/js-conversion.d.ts +1 -0
- package/dist/utils/js-conversion.js +244 -0
- package/dist/utils/module-utils.d.ts +2 -0
- package/dist/utils/module-utils.js +461 -0
- package/dist/utils/package-manager.js +15 -31
- 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 +75 -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 +63 -0
- package/modules/auth/better-auth/module.json +191 -0
- package/modules/database/mongoose/files/lib/db.ts +68 -0
- package/modules/database/mongoose/files/models/User.ts +34 -0
- package/modules/database/mongoose/module.json +55 -0
- package/modules/database/prisma/files/lib/prisma.ts +4 -0
- package/modules/database/prisma/files/prisma/schema.prisma +8 -0
- package/modules/database/prisma/files/prisma.config.ts +12 -0
- package/modules/database/prisma/module.json +122 -0
- package/package.json +1 -1
- package/templates/express/.env.example +1 -10
- package/templates/express/package.json +15 -21
- package/templates/express/src/app.ts +9 -29
- package/templates/express/src/config/env.ts +3 -14
- package/templates/express/src/features/health/health.controller.ts +18 -0
- package/templates/express/src/features/health/health.route.ts +9 -0
- package/templates/express/src/features/health/health.service.ts +6 -0
- package/templates/express/src/middlewares/error.middleware.ts +2 -2
- package/templates/express/src/server.ts +1 -1
- package/templates/express/template.json +1 -5
- package/templates/express/tsconfig.json +0 -1
- 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/dist/commands/init.d.ts +0 -10
- package/dist/commands/init.js +0 -157
- package/dist/utils/code-inject.d.ts +0 -14
- package/dist/utils/code-inject.js +0 -70
- package/dist/utils/json-editor.d.ts +0 -8
- package/dist/utils/json-editor.js +0 -45
- package/modules/auth/better-auth-express/adapters/mongoose-mongodb.ts +0 -13
- package/modules/auth/better-auth-express/adapters/prisma-mongodb.ts +0 -15
- package/modules/auth/better-auth-express/adapters/prisma-postgresql.ts +0 -15
- package/modules/auth/better-auth-express/files/lib/auth.ts +0 -16
- package/modules/auth/better-auth-express/files/routes/auth.ts +0 -12
- package/modules/auth/better-auth-express/files/schemas/prisma-mongodb-schema.prisma +0 -72
- package/modules/auth/better-auth-express/files/schemas/prisma-postgresql-schema.prisma +0 -72
- package/modules/auth/better-auth-express/module.json +0 -61
- package/modules/auth/better-auth-nextjs/adapters/mongoose-mongodb.ts +0 -24
- package/modules/auth/better-auth-nextjs/adapters/prisma-mongodb.ts +0 -26
- package/modules/auth/better-auth-nextjs/adapters/prisma-postgresql.ts +0 -26
- package/modules/auth/better-auth-nextjs/files/lib/auth.ts +0 -26
- package/modules/auth/better-auth-nextjs/files/schemas/prisma-mongodb-schema.prisma +0 -72
- package/modules/auth/better-auth-nextjs/files/schemas/prisma-postgresql-schema.prisma +0 -72
- package/modules/auth/better-auth-nextjs/module.json +0 -62
- package/modules/auth/better-auth-react/files/lib/auth-client.ts +0 -9
- package/modules/auth/better-auth-react/module.json +0 -28
- package/modules/auth/clerk-express/files/lib/auth.ts +0 -7
- package/modules/auth/clerk-express/module.json +0 -34
- package/modules/auth/clerk-nextjs/files/lib/auth-provider.tsx +0 -5
- package/modules/auth/clerk-nextjs/files/middleware.ts +0 -9
- package/modules/auth/clerk-nextjs/module.json +0 -64
- package/modules/auth/clerk-react/files/lib/auth-provider.tsx +0 -15
- package/modules/auth/clerk-react/module.json +0 -28
- package/modules/database/mongoose-mongodb/files/lib/db.ts +0 -40
- package/modules/database/mongoose-mongodb/module.json +0 -55
- package/modules/database/prisma-mongodb/files/lib/db.ts +0 -9
- package/modules/database/prisma-mongodb/files/prisma/schema.prisma +0 -17
- package/modules/database/prisma-mongodb/module.json +0 -60
- package/modules/database/prisma-postgresql/files/lib/db.ts +0 -9
- package/modules/database/prisma-postgresql/files/prisma/schema.prisma +0 -17
- package/modules/database/prisma-postgresql/module.json +0 -60
- 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
- /package/modules/auth/{better-auth-nextjs → better-auth}/files/api/auth/[...all]/route.ts +0 -0
package/README.md
CHANGED
|
@@ -5,6 +5,9 @@ Add authentication and database modules to existing projects.
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
+
# Check project health and compatibility
|
|
9
|
+
npx stackkit-cli doctor
|
|
10
|
+
|
|
8
11
|
# Add authentication
|
|
9
12
|
npx stackkit-cli add auth
|
|
10
13
|
|
|
@@ -21,19 +24,40 @@ npx stackkit-cli list
|
|
|
21
24
|
- **Shows compatible modules** for your project
|
|
22
25
|
- **Installs dependencies** automatically
|
|
23
26
|
- **Configures everything** - files, env vars, and setup
|
|
27
|
+
- **Health checks** with `doctor` command
|
|
24
28
|
|
|
25
29
|
## Available Modules
|
|
26
30
|
|
|
27
31
|
### Authentication
|
|
28
32
|
|
|
29
33
|
- Better Auth (Next.js, Express, React)
|
|
30
|
-
- Clerk (Next.js, Express, React)
|
|
31
34
|
|
|
32
35
|
### Database
|
|
33
36
|
|
|
34
37
|
- Prisma with PostgreSQL or MongoDB (Next.js, Express)
|
|
35
38
|
- Mongoose with MongoDB (Next.js, Express)
|
|
36
39
|
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
### `doctor`
|
|
43
|
+
|
|
44
|
+
Check your project's health and compatibility with StackKit modules.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
stackkit doctor # Basic health check
|
|
48
|
+
stackkit doctor --verbose # Detailed output
|
|
49
|
+
stackkit doctor --json # Machine-readable JSON output
|
|
50
|
+
stackkit doctor --strict # Treat warnings as errors
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The doctor command:
|
|
54
|
+
- Detects your project type and framework
|
|
55
|
+
- Checks Node.js version compatibility
|
|
56
|
+
- Identifies installed StackKit modules
|
|
57
|
+
- Validates environment variables
|
|
58
|
+
- Checks for configuration conflicts
|
|
59
|
+
- Provides actionable next steps
|
|
60
|
+
|
|
37
61
|
## Documentation
|
|
38
62
|
|
|
39
|
-
Full documentation: [stackkit.dev](https://stackkit.dev) | [GitHub](https://github.com/tariqul420/stackkit)
|
|
63
|
+
Full documentation: [stackkit.dev](https://stackkit.dev) | [GitHub](https://github.com/tariqul420/stackkit/issues)
|
package/bin/stackkit.js
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
try {
|
|
4
|
+
// eslint-disable-next-line
|
|
5
|
+
require("ts-node/register");
|
|
6
|
+
// eslint-disable-next-line
|
|
7
|
+
require("../src/index.ts");
|
|
8
|
+
} catch {
|
|
9
|
+
// eslint-disable-next-line
|
|
10
|
+
require("../dist/index.js");
|
|
11
|
+
}
|
package/dist/commands/add.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.addCommand = addCommand;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
8
9
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
10
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
11
|
const path_1 = __importDefault(require("path"));
|
|
@@ -27,6 +28,62 @@ async function addCommand(module, options) {
|
|
|
27
28
|
logger_1.logger.error(`Module "${module}" not found`);
|
|
28
29
|
process.exit(1);
|
|
29
30
|
}
|
|
31
|
+
// For database modules, ensure provider is selected
|
|
32
|
+
let selectedProvider = options.provider;
|
|
33
|
+
if (moduleMetadata.category === "database" && !selectedProvider) {
|
|
34
|
+
if (typeof moduleMetadata.dependencies === "object" &&
|
|
35
|
+
"providers" in moduleMetadata.dependencies) {
|
|
36
|
+
const providers = Object.keys(moduleMetadata.dependencies.providers || {});
|
|
37
|
+
if (providers.length > 0) {
|
|
38
|
+
const { provider } = await inquirer_1.default.prompt([
|
|
39
|
+
{
|
|
40
|
+
type: "list",
|
|
41
|
+
name: "provider",
|
|
42
|
+
message: "Select database provider:",
|
|
43
|
+
choices: providers.map((p) => ({ name: p, value: p })),
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
selectedProvider = provider;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Merge dependencies based on provider
|
|
51
|
+
const mergedDeps = {};
|
|
52
|
+
const mergedDevDeps = {};
|
|
53
|
+
// Add shared dependencies
|
|
54
|
+
if (moduleMetadata.frameworkConfigs?.shared?.dependencies) {
|
|
55
|
+
Object.assign(mergedDeps, moduleMetadata.frameworkConfigs.shared.dependencies);
|
|
56
|
+
}
|
|
57
|
+
if (moduleMetadata.frameworkConfigs?.shared?.devDependencies) {
|
|
58
|
+
Object.assign(mergedDevDeps, moduleMetadata.frameworkConfigs.shared.devDependencies);
|
|
59
|
+
}
|
|
60
|
+
// Add provider specific dependencies
|
|
61
|
+
if (selectedProvider && moduleMetadata.databaseAdapters?.providers?.[selectedProvider]?.dependencies) {
|
|
62
|
+
Object.assign(mergedDeps, moduleMetadata.databaseAdapters.providers[selectedProvider].dependencies);
|
|
63
|
+
}
|
|
64
|
+
if (selectedProvider && moduleMetadata.databaseAdapters?.providers?.[selectedProvider]?.devDependencies) {
|
|
65
|
+
Object.assign(mergedDevDeps, moduleMetadata.databaseAdapters.providers[selectedProvider].devDependencies);
|
|
66
|
+
}
|
|
67
|
+
// Update metadata with merged deps
|
|
68
|
+
moduleMetadata.dependencies = mergedDeps;
|
|
69
|
+
moduleMetadata.devDependencies = mergedDevDeps;
|
|
70
|
+
// Set variables for replacements
|
|
71
|
+
const variables = {};
|
|
72
|
+
if (selectedProvider) {
|
|
73
|
+
variables.provider = selectedProvider;
|
|
74
|
+
if (selectedProvider === "postgresql") {
|
|
75
|
+
variables.connectionString = "postgresql://user:password@localhost:5432/mydb?schema=public";
|
|
76
|
+
}
|
|
77
|
+
else if (selectedProvider === "mongodb") {
|
|
78
|
+
variables.connectionString = "mongodb://localhost:27017/mydb";
|
|
79
|
+
}
|
|
80
|
+
else if (selectedProvider === "mysql") {
|
|
81
|
+
variables.connectionString = "mysql://user:password@localhost:3306/mydb";
|
|
82
|
+
}
|
|
83
|
+
else if (selectedProvider === "sqlite") {
|
|
84
|
+
variables.connectionString = "file:./dev.db";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
30
87
|
// Check if framework is supported
|
|
31
88
|
if (!moduleMetadata.supportedFrameworks.includes(projectInfo.framework)) {
|
|
32
89
|
logger_1.logger.error(`Module "${module}" does not support ${projectInfo.framework}. Supported: ${moduleMetadata.supportedFrameworks.join(", ")}`);
|
|
@@ -54,9 +111,27 @@ async function addCommand(module, options) {
|
|
|
54
111
|
}
|
|
55
112
|
// Apply module patches
|
|
56
113
|
await applyModulePatches(projectRoot, projectInfo, moduleMetadata, modulesDir, module, options);
|
|
114
|
+
// Apply framework patches
|
|
115
|
+
if (moduleMetadata.frameworkPatches && !options.dryRun) {
|
|
116
|
+
await applyFrameworkPatches(projectRoot, moduleMetadata.frameworkPatches, projectInfo.framework);
|
|
117
|
+
}
|
|
118
|
+
// Run post-install commands
|
|
119
|
+
if (moduleMetadata.postInstall && moduleMetadata.postInstall.length > 0 && !options.dryRun) {
|
|
120
|
+
const postInstallSpinner = logger_1.logger.startSpinner("Running post-install commands...");
|
|
121
|
+
try {
|
|
122
|
+
for (const command of moduleMetadata.postInstall) {
|
|
123
|
+
(0, child_process_1.execSync)(command, { cwd: projectRoot, stdio: "pipe" });
|
|
124
|
+
}
|
|
125
|
+
postInstallSpinner.succeed("Post-install commands completed");
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
postInstallSpinner.fail("Failed to run post-install commands");
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
57
132
|
// Add dependencies
|
|
58
|
-
if (Object.keys(
|
|
59
|
-
const deps = Object.entries(
|
|
133
|
+
if (Object.keys(mergedDeps).length > 0 && options.install !== false) {
|
|
134
|
+
const deps = Object.entries(mergedDeps).map(([name, version]) => `${name}@${version}`);
|
|
60
135
|
if (!options.dryRun) {
|
|
61
136
|
await (0, package_manager_1.addDependencies)(projectRoot, projectInfo.packageManager, deps, false);
|
|
62
137
|
}
|
|
@@ -65,10 +140,8 @@ async function addCommand(module, options) {
|
|
|
65
140
|
}
|
|
66
141
|
}
|
|
67
142
|
// Add dev dependencies
|
|
68
|
-
if (
|
|
69
|
-
Object.
|
|
70
|
-
options.install !== false) {
|
|
71
|
-
const devDeps = Object.entries(moduleMetadata.devDependencies).map(([name, version]) => `${name}@${version}`);
|
|
143
|
+
if (Object.keys(mergedDevDeps).length > 0 && options.install !== false) {
|
|
144
|
+
const devDeps = Object.entries(mergedDevDeps).map(([name, version]) => `${name}@${version}`);
|
|
72
145
|
if (!options.dryRun) {
|
|
73
146
|
await (0, package_manager_1.addDependencies)(projectRoot, projectInfo.packageManager, devDeps, true);
|
|
74
147
|
}
|
|
@@ -77,9 +150,14 @@ async function addCommand(module, options) {
|
|
|
77
150
|
}
|
|
78
151
|
}
|
|
79
152
|
// Add environment variables
|
|
80
|
-
if (moduleMetadata.envVars.length > 0) {
|
|
153
|
+
if (moduleMetadata.envVars && moduleMetadata.envVars.length > 0) {
|
|
154
|
+
// Replace variables in envVars
|
|
155
|
+
const processedEnvVars = moduleMetadata.envVars.map((envVar) => ({
|
|
156
|
+
...envVar,
|
|
157
|
+
value: envVar.value?.replace(/\{\{(\w+)\}\}/g, (match, key) => variables[key] || match),
|
|
158
|
+
}));
|
|
81
159
|
if (!options.dryRun) {
|
|
82
|
-
await (0, env_editor_1.addEnvVariables)(projectRoot,
|
|
160
|
+
await (0, env_editor_1.addEnvVariables)(projectRoot, processedEnvVars, { force: options.force });
|
|
83
161
|
}
|
|
84
162
|
else {
|
|
85
163
|
logger_1.logger.log(` ${chalk_1.default.dim("~")} .env.example`);
|
|
@@ -89,7 +167,7 @@ async function addCommand(module, options) {
|
|
|
89
167
|
logger_1.logger.success(`Added ${chalk_1.default.bold(moduleMetadata.displayName)}`);
|
|
90
168
|
logger_1.logger.newLine();
|
|
91
169
|
// Print next steps
|
|
92
|
-
if (moduleMetadata.envVars.some((v) => v.required)) {
|
|
170
|
+
if (moduleMetadata.envVars && moduleMetadata.envVars.some((v) => v.required)) {
|
|
93
171
|
logger_1.logger.log("Next: Fill in environment variables in .env");
|
|
94
172
|
}
|
|
95
173
|
logger_1.logger.newLine();
|
|
@@ -136,8 +214,10 @@ async function loadModuleMetadata(modulesDir, moduleName, provider) {
|
|
|
136
214
|
}
|
|
137
215
|
return null;
|
|
138
216
|
}
|
|
139
|
-
// (removed duplicate import)
|
|
140
217
|
async function applyModulePatches(projectRoot, projectInfo, moduleMetadata, modulesDir, moduleName, options) {
|
|
218
|
+
if (!moduleMetadata.patches || !Array.isArray(moduleMetadata.patches)) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
141
221
|
// Find the module path
|
|
142
222
|
const moduleBasePath = await findModulePath(modulesDir, moduleName, options.provider);
|
|
143
223
|
if (!moduleBasePath) {
|
|
@@ -208,3 +288,41 @@ async function findModulePath(modulesDir, moduleName, provider) {
|
|
|
208
288
|
}
|
|
209
289
|
return null;
|
|
210
290
|
}
|
|
291
|
+
async function applyFrameworkPatches(projectRoot, patches, framework) {
|
|
292
|
+
const frameworkKey = framework;
|
|
293
|
+
const frameworkPatches = patches[frameworkKey];
|
|
294
|
+
if (!frameworkPatches)
|
|
295
|
+
return;
|
|
296
|
+
for (const [filename, patchConfig] of Object.entries(frameworkPatches)) {
|
|
297
|
+
const filePath = path_1.default.join(projectRoot, filename);
|
|
298
|
+
if (await fs_extra_1.default.pathExists(filePath)) {
|
|
299
|
+
const fileContent = await fs_extra_1.default.readJson(filePath);
|
|
300
|
+
if (patchConfig.merge) {
|
|
301
|
+
const merged = deepMerge(fileContent, patchConfig.merge);
|
|
302
|
+
await fs_extra_1.default.writeJson(filePath, merged, { spaces: 2 });
|
|
303
|
+
const relativePath = path_1.default.relative(projectRoot, filePath);
|
|
304
|
+
logger_1.logger.log(` ${chalk_1.default.blue("~")} ${relativePath}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function deepMerge(target, source) {
|
|
310
|
+
const output = { ...target };
|
|
311
|
+
for (const key in source) {
|
|
312
|
+
if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
|
|
313
|
+
if (target[key]) {
|
|
314
|
+
output[key] = deepMerge(target[key], source[key]);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
output[key] = source[key];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
else if (Array.isArray(source[key])) {
|
|
321
|
+
output[key] = Array.from(new Set([...(target[key] || []), ...source[key]]));
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
output[key] = source[key];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return output;
|
|
328
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface DoctorOptions {
|
|
2
|
+
json?: boolean;
|
|
3
|
+
verbose?: boolean;
|
|
4
|
+
strict?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Main doctor command function that performs health checks on a StackKit project
|
|
8
|
+
* @param options Command line options
|
|
9
|
+
*/
|
|
10
|
+
export declare function doctorCommand(options: DoctorOptions): Promise<void>;
|
|
11
|
+
export {};
|