stackkit-cli 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 +26 -2
- package/bin/stackkit.js +1 -1
- package/dist/commands/add.js +20 -39
- 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 +15 -0
- 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 +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/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/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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "dotenv/config";
|
|
2
|
-
import { defineConfig } from "prisma/config";
|
|
2
|
+
import { defineConfig, env } from "prisma/config";
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
schema: "prisma/schema.prisma",
|
|
@@ -7,6 +7,6 @@ export default defineConfig({
|
|
|
7
7
|
path: "prisma/migrations",
|
|
8
8
|
},
|
|
9
9
|
datasource: {
|
|
10
|
-
url:
|
|
10
|
+
url: env('DATABASE_URL'),
|
|
11
11
|
},
|
|
12
12
|
});
|
|
@@ -49,7 +49,6 @@
|
|
|
49
49
|
{
|
|
50
50
|
"key": "DATABASE_URL",
|
|
51
51
|
"value": "{{connectionString}}",
|
|
52
|
-
"description": "Database connection URL",
|
|
53
52
|
"required": true
|
|
54
53
|
}
|
|
55
54
|
],
|
|
@@ -58,31 +57,26 @@
|
|
|
58
57
|
{
|
|
59
58
|
"key": "DATABASE_HOST",
|
|
60
59
|
"value": "localhost",
|
|
61
|
-
"description": "MySQL host",
|
|
62
60
|
"required": true
|
|
63
61
|
},
|
|
64
62
|
{
|
|
65
63
|
"key": "DATABASE_USER",
|
|
66
64
|
"value": "",
|
|
67
|
-
"description": "MySQL username",
|
|
68
65
|
"required": true
|
|
69
66
|
},
|
|
70
67
|
{
|
|
71
68
|
"key": "DATABASE_PASSWORD",
|
|
72
69
|
"value": "",
|
|
73
|
-
"description": "MySQL password",
|
|
74
70
|
"required": true
|
|
75
71
|
},
|
|
76
72
|
{
|
|
77
73
|
"key": "DATABASE_NAME",
|
|
78
74
|
"value": "mydb",
|
|
79
|
-
"description": "MySQL database name",
|
|
80
75
|
"required": true
|
|
81
76
|
},
|
|
82
77
|
{
|
|
83
78
|
"key": "DATABASE_PORT",
|
|
84
79
|
"value": "3306",
|
|
85
|
-
"description": "MySQL port",
|
|
86
80
|
"required": false
|
|
87
81
|
}
|
|
88
82
|
]
|
|
@@ -94,24 +88,12 @@
|
|
|
94
88
|
"merge": {
|
|
95
89
|
"compilerOptions": {
|
|
96
90
|
"baseUrl": ".",
|
|
97
|
-
"paths": {
|
|
98
|
-
"@/*": ["./src/*"]
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
"include": ["src/**/*"],
|
|
102
|
-
"exclude": ["node_modules", "dist", "prisma/migrations"]
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
"nextjs": {
|
|
107
|
-
"tsconfig.json": {
|
|
108
|
-
"merge": {
|
|
109
|
-
"compilerOptions": {
|
|
110
91
|
"paths": {
|
|
111
92
|
"@/*": ["./*"]
|
|
112
93
|
}
|
|
113
94
|
},
|
|
114
|
-
"
|
|
95
|
+
"include": ["src/**/*", "lib/**/*"],
|
|
96
|
+
"exclude": ["node_modules", "dist", "lib/generated/prisma"]
|
|
115
97
|
}
|
|
116
98
|
}
|
|
117
99
|
}
|
|
@@ -131,9 +113,9 @@
|
|
|
131
113
|
},
|
|
132
114
|
{
|
|
133
115
|
"type": "create-file",
|
|
134
|
-
"description": "
|
|
135
|
-
"source": "lib/
|
|
136
|
-
"destination": "{{lib}}/
|
|
116
|
+
"description": "{{dbDescription}}",
|
|
117
|
+
"source": "lib/{{dbFile}}",
|
|
118
|
+
"destination": "{{lib}}/{{dbFile}}"
|
|
137
119
|
}
|
|
138
120
|
],
|
|
139
121
|
"postInstall": ["npx prisma generate"]
|
package/package.json
CHANGED
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"@types/cors": "^2.8.19",
|
|
23
23
|
"@types/express": "^5.0.6",
|
|
24
24
|
"@types/morgan": "^1.9.10",
|
|
25
|
-
"@types/node": "^25.0.
|
|
26
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
27
|
-
"@typescript-eslint/parser": "^8.
|
|
25
|
+
"@types/node": "^25.0.8",
|
|
26
|
+
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
|
27
|
+
"@typescript-eslint/parser": "^8.53.0",
|
|
28
28
|
"cross-env": "^10.1.0",
|
|
29
29
|
"eslint": "^9.39.2",
|
|
30
30
|
"tsx": "^4.21.0",
|
|
31
31
|
"typescript": "^5.9.3"
|
|
32
32
|
}
|
|
33
|
-
}
|
|
33
|
+
}
|
|
@@ -3,7 +3,7 @@ import express, { Application, NextFunction, Request, Response } from "express";
|
|
|
3
3
|
import helmet from "helmet";
|
|
4
4
|
import morgan from "morgan";
|
|
5
5
|
import { env } from "./config/env";
|
|
6
|
-
import { authRoutes } from "./features/
|
|
6
|
+
import { authRoutes } from "./features/health/health.route";
|
|
7
7
|
import { errorHandler } from "./middlewares/error.middleware";
|
|
8
8
|
|
|
9
9
|
// app initialization
|
|
@@ -35,7 +35,7 @@ app.get("/", (_req: Request, res: Response) => {
|
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
// routes
|
|
38
|
-
app.use("/api/
|
|
38
|
+
app.use("/api/health", authRoutes);
|
|
39
39
|
|
|
40
40
|
// unhandled routes
|
|
41
41
|
app.use((req: Request, _res: Response, next: NextFunction) => {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NextFunction, Request, Response } from "express";
|
|
2
|
+
|
|
3
|
+
const health = async (_req: Request, res: Response, next: NextFunction) => {
|
|
4
|
+
try {
|
|
5
|
+
res.status(200).json({
|
|
6
|
+
success: true,
|
|
7
|
+
message: "API is healthy!",
|
|
8
|
+
timestamp: new Date().toISOString(),
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
});
|
|
11
|
+
} catch (error) {
|
|
12
|
+
next(error);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const healthController = {
|
|
17
|
+
health,
|
|
18
|
+
};
|
|
@@ -15,13 +15,13 @@
|
|
|
15
15
|
"react-dom": "19.2.3"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@tailwindcss/postcss": "^4",
|
|
19
|
-
"@types/node": "^
|
|
20
|
-
"@types/react": "^19",
|
|
21
|
-
"@types/react-dom": "^19",
|
|
22
|
-
"eslint": "^9",
|
|
18
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
19
|
+
"@types/node": "^25.0.8",
|
|
20
|
+
"@types/react": "^19.2.8",
|
|
21
|
+
"@types/react-dom": "^19.2.3",
|
|
22
|
+
"eslint": "^9.39.2",
|
|
23
23
|
"eslint-config-next": "16.1.1",
|
|
24
|
-
"tailwindcss": "^4",
|
|
25
|
-
"typescript": "^5"
|
|
24
|
+
"tailwindcss": "^4.1.18",
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
VITE_API_URL=http://localhost:3000
|
|
1
|
+
VITE_API_URL=http://localhost:3000
|
|
@@ -14,6 +14,7 @@ A production-ready React starter template with TypeScript, Vite, and essential l
|
|
|
14
14
|
- **SEO Ready** with React Helmet Async
|
|
15
15
|
- **Error Boundaries** for graceful error handling
|
|
16
16
|
- **ESLint** for code quality
|
|
17
|
+
- **Prettier** for code formatting
|
|
17
18
|
- **Custom Hooks** included
|
|
18
19
|
|
|
19
20
|
## Quick Start
|
|
@@ -30,6 +31,18 @@ pnpm build
|
|
|
30
31
|
|
|
31
32
|
# Preview production build
|
|
32
33
|
pnpm preview
|
|
34
|
+
|
|
35
|
+
# Run linter
|
|
36
|
+
pnpm lint
|
|
37
|
+
|
|
38
|
+
# Fix linting issues
|
|
39
|
+
pnpm lint:fix
|
|
40
|
+
|
|
41
|
+
# Format code
|
|
42
|
+
pnpm format
|
|
43
|
+
|
|
44
|
+
# Check formatting
|
|
45
|
+
pnpm format:check
|
|
33
46
|
```
|
|
34
47
|
|
|
35
48
|
## Project Structure
|
|
@@ -44,6 +57,7 @@ src/
|
|
|
44
57
|
├── pages/ # Route pages
|
|
45
58
|
├── types/ # TypeScript types
|
|
46
59
|
├── utils/ # Helper functions
|
|
60
|
+
├── test/ # Test setup
|
|
47
61
|
├── App.tsx # Main app component
|
|
48
62
|
├── main.tsx # Entry point
|
|
49
63
|
└── index.css # Global styles
|
|
@@ -51,6 +65,14 @@ src/
|
|
|
51
65
|
|
|
52
66
|
## Environment Variables
|
|
53
67
|
|
|
68
|
+
Copy `.env.example` to `.env` and update the values:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cp .env.example .env
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Environment Variables
|
|
75
|
+
|
|
54
76
|
Create a `.env` file:
|
|
55
77
|
|
|
56
78
|
```env
|
|
@@ -12,33 +12,33 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@tailwindcss/vite": "^4.1.18",
|
|
15
|
-
"@tanstack/react-query": "^5.
|
|
16
|
-
"@tanstack/react-query-devtools": "^5.
|
|
17
|
-
"axios": "^1.
|
|
15
|
+
"@tanstack/react-query": "^5.90.16",
|
|
16
|
+
"@tanstack/react-query-devtools": "^5.91.2",
|
|
17
|
+
"axios": "^1.13.2",
|
|
18
18
|
"class-variance-authority": "^0.7.1",
|
|
19
19
|
"clsx": "^2.1.1",
|
|
20
|
-
"react": "^19.2.
|
|
21
|
-
"react-dom": "^19.2.
|
|
20
|
+
"react": "^19.2.3",
|
|
21
|
+
"react-dom": "^19.2.3",
|
|
22
22
|
"react-helmet-async": "^2.0.5",
|
|
23
|
-
"react-hot-toast": "^2.
|
|
23
|
+
"react-hot-toast": "^2.6.0",
|
|
24
24
|
"react-router": "^7.12.0",
|
|
25
25
|
"tailwind-merge": "^3.4.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@eslint/js": "^9.39.
|
|
29
|
-
"@types/node": "^
|
|
30
|
-
"@types/react": "^19.2.
|
|
28
|
+
"@eslint/js": "^9.39.2",
|
|
29
|
+
"@types/node": "^25.0.8",
|
|
30
|
+
"@types/react": "^19.2.8",
|
|
31
31
|
"@types/react-dom": "^19.2.3",
|
|
32
|
-
"@vitejs/plugin-react": "^5.1.
|
|
32
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
33
33
|
"autoprefixer": "^10.4.23",
|
|
34
|
-
"eslint": "^9.39.
|
|
34
|
+
"eslint": "^9.39.2",
|
|
35
35
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
36
|
-
"eslint-plugin-react-refresh": "^0.4.
|
|
37
|
-
"globals": "^
|
|
36
|
+
"eslint-plugin-react-refresh": "^0.4.26",
|
|
37
|
+
"globals": "^17.0.0",
|
|
38
38
|
"postcss": "^8.5.6",
|
|
39
39
|
"tailwindcss": "^4.1.18",
|
|
40
40
|
"typescript": "~5.9.3",
|
|
41
|
-
"typescript-eslint": "^8.
|
|
42
|
-
"vite": "^7.
|
|
41
|
+
"typescript-eslint": "^8.53.0",
|
|
42
|
+
"vite": "^7.3.1"
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { createBrowserRouter } from "react-router";
|
|
2
|
-
import { userService } from "./api/services/user.service";
|
|
3
2
|
import { ErrorBoundary } from "./components/ErrorBoundary";
|
|
4
3
|
import Layout from "./components/Layout";
|
|
5
4
|
import About from "./pages/About";
|
|
6
5
|
import Home from "./pages/Home";
|
|
7
6
|
import NotFound from "./pages/NotFound";
|
|
8
|
-
import UserProfile from "./pages/UserProfile";
|
|
9
7
|
|
|
10
8
|
export const router = createBrowserRouter([
|
|
11
9
|
{
|
|
@@ -15,16 +13,6 @@ export const router = createBrowserRouter([
|
|
|
15
13
|
children: [
|
|
16
14
|
{ index: true, Component: Home },
|
|
17
15
|
{ path: "about", Component: About },
|
|
18
|
-
{
|
|
19
|
-
path: "users/:userId",
|
|
20
|
-
loader: async ({ params }) => {
|
|
21
|
-
const id = params.userId;
|
|
22
|
-
if (!id) throw new Response("Missing user id", { status: 400 });
|
|
23
|
-
const user = await userService.getUser(id);
|
|
24
|
-
return user;
|
|
25
|
-
},
|
|
26
|
-
Component: UserProfile,
|
|
27
|
-
},
|
|
28
16
|
{ path: "*", Component: NotFound },
|
|
29
17
|
],
|
|
30
18
|
},
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import tailwindcss from "@tailwindcss/vite";
|
|
2
2
|
import react from "@vitejs/plugin-react";
|
|
3
|
-
import path from "path";
|
|
4
3
|
import { defineConfig } from "vite";
|
|
5
4
|
|
|
6
5
|
export default defineConfig({
|
|
7
6
|
plugins: [react(), tailwindcss()],
|
|
8
|
-
resolve: {
|
|
9
|
-
alias: {
|
|
10
|
-
"@": path.resolve(__dirname, "./src"),
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
7
|
});
|
package/dist/commands/init.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { PackageManager } from "../utils/package-manager";
|
|
2
|
-
interface InitOptions {
|
|
3
|
-
template?: string;
|
|
4
|
-
pm?: PackageManager;
|
|
5
|
-
install?: boolean;
|
|
6
|
-
git?: boolean;
|
|
7
|
-
yes?: boolean;
|
|
8
|
-
}
|
|
9
|
-
export declare function initCommand(projectName: string | undefined, options: InitOptions): Promise<void>;
|
|
10
|
-
export {};
|
package/dist/commands/init.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
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.initCommand = initCommand;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
-
const path_1 = __importDefault(require("path"));
|
|
11
|
-
const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
12
|
-
const files_1 = require("../utils/files");
|
|
13
|
-
const logger_1 = require("../utils/logger");
|
|
14
|
-
const package_manager_1 = require("../utils/package-manager");
|
|
15
|
-
async function initCommand(projectName, options) {
|
|
16
|
-
try {
|
|
17
|
-
// Validate package manager option
|
|
18
|
-
if (options.pm && !["npm", "yarn", "pnpm", "bun"].includes(options.pm)) {
|
|
19
|
-
logger_1.logger.error(`Invalid package manager: ${options.pm}. Use npm, yarn, pnpm, or bun.`);
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
// Get available templates
|
|
23
|
-
const templatesDir = path_1.default.join(__dirname, "..", "..", "templates");
|
|
24
|
-
const templates = await getAvailableTemplates(templatesDir);
|
|
25
|
-
if (templates.length === 0) {
|
|
26
|
-
logger_1.logger.error("No templates found");
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
// Prompt for project details if not using --yes
|
|
30
|
-
let answers;
|
|
31
|
-
if (options.yes) {
|
|
32
|
-
answers = {
|
|
33
|
-
projectName: projectName || "my-app",
|
|
34
|
-
template: options.template || templates[0].name,
|
|
35
|
-
packageManager: options.pm || "pnpm",
|
|
36
|
-
install: options.install !== false,
|
|
37
|
-
git: options.git !== false,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
const prompted = await inquirer_1.default.prompt([
|
|
42
|
-
{
|
|
43
|
-
type: "input",
|
|
44
|
-
name: "projectName",
|
|
45
|
-
message: "Project name:",
|
|
46
|
-
default: projectName || "my-app",
|
|
47
|
-
when: !projectName,
|
|
48
|
-
validate: (input) => {
|
|
49
|
-
const validation = (0, validate_npm_package_name_1.default)(input);
|
|
50
|
-
if (!validation.validForNewPackages) {
|
|
51
|
-
return validation.errors?.[0] || "Invalid package name";
|
|
52
|
-
}
|
|
53
|
-
return true;
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
type: "list",
|
|
58
|
-
name: "template",
|
|
59
|
-
message: "Select a template:",
|
|
60
|
-
choices: templates.map((t) => ({
|
|
61
|
-
name: t.displayName,
|
|
62
|
-
value: t.name,
|
|
63
|
-
})),
|
|
64
|
-
when: !options.template,
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
type: "list",
|
|
68
|
-
name: "packageManager",
|
|
69
|
-
message: "Select a package manager:",
|
|
70
|
-
choices: [
|
|
71
|
-
{ name: "pnpm (recommended)", value: "pnpm" },
|
|
72
|
-
{ name: "npm", value: "npm" },
|
|
73
|
-
{ name: "yarn", value: "yarn" },
|
|
74
|
-
{ name: "bun", value: "bun" },
|
|
75
|
-
],
|
|
76
|
-
default: "pnpm",
|
|
77
|
-
when: !options.pm,
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: "confirm",
|
|
81
|
-
name: "install",
|
|
82
|
-
message: "Install dependencies?",
|
|
83
|
-
default: true,
|
|
84
|
-
when: options.install !== false,
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
type: "confirm",
|
|
88
|
-
name: "git",
|
|
89
|
-
message: "Initialize git repository?",
|
|
90
|
-
default: true,
|
|
91
|
-
when: options.git !== false,
|
|
92
|
-
},
|
|
93
|
-
]);
|
|
94
|
-
answers = {
|
|
95
|
-
projectName: projectName || prompted.projectName,
|
|
96
|
-
template: options.template || prompted.template,
|
|
97
|
-
packageManager: options.pm || prompted.packageManager,
|
|
98
|
-
install: options.install !== false && (prompted.install ?? true),
|
|
99
|
-
git: options.git !== false && (prompted.git ?? true),
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
const targetDir = path_1.default.join(process.cwd(), answers.projectName);
|
|
103
|
-
// Check if directory exists
|
|
104
|
-
if (await fs_extra_1.default.pathExists(targetDir)) {
|
|
105
|
-
logger_1.logger.error(`Directory "${answers.projectName}" already exists`);
|
|
106
|
-
logger_1.logger.info("Please choose a different name or remove the existing directory.");
|
|
107
|
-
process.exit(1);
|
|
108
|
-
}
|
|
109
|
-
// Validate template exists
|
|
110
|
-
const selectedTemplate = templates.find((t) => t.name === answers.template);
|
|
111
|
-
if (!selectedTemplate) {
|
|
112
|
-
logger_1.logger.error(`Template "${answers.template}" not found`);
|
|
113
|
-
process.exit(1);
|
|
114
|
-
}
|
|
115
|
-
logger_1.logger.newLine();
|
|
116
|
-
// Copy template
|
|
117
|
-
const templatePath = path_1.default.join(templatesDir, answers.template);
|
|
118
|
-
await (0, files_1.copyTemplate)(templatePath, targetDir, answers.projectName);
|
|
119
|
-
// Install dependencies
|
|
120
|
-
if (answers.install) {
|
|
121
|
-
await (0, package_manager_1.installDependencies)(targetDir, answers.packageManager);
|
|
122
|
-
}
|
|
123
|
-
// Initialize git
|
|
124
|
-
if (answers.git) {
|
|
125
|
-
await (0, package_manager_1.initGit)(targetDir);
|
|
126
|
-
}
|
|
127
|
-
logger_1.logger.newLine();
|
|
128
|
-
logger_1.logger.success(`Created ${chalk_1.default.bold(answers.projectName)}`);
|
|
129
|
-
logger_1.logger.newLine();
|
|
130
|
-
logger_1.logger.log(`Next steps:`);
|
|
131
|
-
logger_1.logger.log(` ${chalk_1.default.cyan("cd")} ${answers.projectName}`);
|
|
132
|
-
if (!answers.install) {
|
|
133
|
-
logger_1.logger.log(` ${chalk_1.default.cyan(answers.packageManager)} install`);
|
|
134
|
-
}
|
|
135
|
-
logger_1.logger.log(` ${chalk_1.default.cyan(answers.packageManager)} ${answers.packageManager === "npm" ? "run " : ""}dev`);
|
|
136
|
-
logger_1.logger.newLine();
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
logger_1.logger.error(`Failed to create project: ${error.message}`);
|
|
140
|
-
process.exit(1);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
async function getAvailableTemplates(templatesDir) {
|
|
144
|
-
if (!(await fs_extra_1.default.pathExists(templatesDir))) {
|
|
145
|
-
return [];
|
|
146
|
-
}
|
|
147
|
-
const templateDirs = await fs_extra_1.default.readdir(templatesDir);
|
|
148
|
-
const templates = [];
|
|
149
|
-
for (const dir of templateDirs) {
|
|
150
|
-
const metadataPath = path_1.default.join(templatesDir, dir, "template.json");
|
|
151
|
-
if (await fs_extra_1.default.pathExists(metadataPath)) {
|
|
152
|
-
const metadata = await fs_extra_1.default.readJSON(metadataPath);
|
|
153
|
-
templates.push(metadata);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return templates;
|
|
157
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface CodeInjection {
|
|
2
|
-
id: string;
|
|
3
|
-
code: string;
|
|
4
|
-
description: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function injectCode(filePath: string, injection: CodeInjection, position: "append" | "prepend" | {
|
|
7
|
-
after: string;
|
|
8
|
-
} | {
|
|
9
|
-
before: string;
|
|
10
|
-
}, options?: {
|
|
11
|
-
force?: boolean;
|
|
12
|
-
}): Promise<void>;
|
|
13
|
-
export declare function removeInjection(content: string, id: string): string;
|
|
14
|
-
export declare function hasInjection(content: string, id: string): boolean;
|
|
@@ -1,70 +0,0 @@
|
|
|
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.injectCode = injectCode;
|
|
7
|
-
exports.removeInjection = removeInjection;
|
|
8
|
-
exports.hasInjection = hasInjection;
|
|
9
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
-
const CODE_MARKER_START = (id) => `// StackKit:${id}:start`;
|
|
11
|
-
const CODE_MARKER_END = (id) => `// StackKit:${id}:end`;
|
|
12
|
-
async function injectCode(filePath, injection, position, options = {}) {
|
|
13
|
-
if (!(await fs_extra_1.default.pathExists(filePath))) {
|
|
14
|
-
throw new Error(`File not found: ${filePath}`);
|
|
15
|
-
}
|
|
16
|
-
let content = await fs_extra_1.default.readFile(filePath, "utf-8");
|
|
17
|
-
// Check if already injected
|
|
18
|
-
const startMarker = CODE_MARKER_START(injection.id);
|
|
19
|
-
if (content.includes(startMarker) && !options.force) {
|
|
20
|
-
return; // Already injected, skip
|
|
21
|
-
}
|
|
22
|
-
// Remove old injection if force is true
|
|
23
|
-
if (options.force) {
|
|
24
|
-
content = removeInjection(content, injection.id);
|
|
25
|
-
}
|
|
26
|
-
// Prepare the code block with markers
|
|
27
|
-
const markedCode = `\n${startMarker}\n${injection.code}\n${CODE_MARKER_END(injection.id)}\n`;
|
|
28
|
-
// Inject based on position
|
|
29
|
-
if (position === "append") {
|
|
30
|
-
content += markedCode;
|
|
31
|
-
}
|
|
32
|
-
else if (position === "prepend") {
|
|
33
|
-
content = markedCode + content;
|
|
34
|
-
}
|
|
35
|
-
else if ("after" in position) {
|
|
36
|
-
const index = content.indexOf(position.after);
|
|
37
|
-
if (index === -1) {
|
|
38
|
-
throw new Error(`Could not find marker: ${position.after}`);
|
|
39
|
-
}
|
|
40
|
-
const insertPos = index + position.after.length;
|
|
41
|
-
content = content.slice(0, insertPos) + markedCode + content.slice(insertPos);
|
|
42
|
-
}
|
|
43
|
-
else if ("before" in position) {
|
|
44
|
-
const index = content.indexOf(position.before);
|
|
45
|
-
if (index === -1) {
|
|
46
|
-
throw new Error(`Could not find marker: ${position.before}`);
|
|
47
|
-
}
|
|
48
|
-
content = content.slice(0, index) + markedCode + content.slice(index);
|
|
49
|
-
}
|
|
50
|
-
await fs_extra_1.default.writeFile(filePath, content, "utf-8");
|
|
51
|
-
}
|
|
52
|
-
function removeInjection(content, id) {
|
|
53
|
-
const startMarker = CODE_MARKER_START(id);
|
|
54
|
-
const endMarker = CODE_MARKER_END(id);
|
|
55
|
-
const startIndex = content.indexOf(startMarker);
|
|
56
|
-
if (startIndex === -1) {
|
|
57
|
-
return content;
|
|
58
|
-
}
|
|
59
|
-
const endIndex = content.indexOf(endMarker, startIndex);
|
|
60
|
-
if (endIndex === -1) {
|
|
61
|
-
return content;
|
|
62
|
-
}
|
|
63
|
-
// Remove everything from start marker to end marker (inclusive)
|
|
64
|
-
const before = content.slice(0, startIndex);
|
|
65
|
-
const after = content.slice(endIndex + endMarker.length);
|
|
66
|
-
return before + after;
|
|
67
|
-
}
|
|
68
|
-
function hasInjection(content, id) {
|
|
69
|
-
return content.includes(CODE_MARKER_START(id));
|
|
70
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export declare function modifyJson(filePath: string, modifier: (_json: Record<string, unknown>) => Record<string, unknown>, options?: {
|
|
2
|
-
create?: boolean;
|
|
3
|
-
force?: boolean;
|
|
4
|
-
}): Promise<void>;
|
|
5
|
-
export declare function addToPackageJson(filePath: string, section: "dependencies" | "devDependencies" | "scripts", additions: Record<string, string>): Promise<void>;
|
|
6
|
-
export declare function setJsonValue(filePath: string, path: string, value: unknown, options?: {
|
|
7
|
-
merge?: boolean;
|
|
8
|
-
}): Promise<void>;
|