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.
Files changed (73) hide show
  1. package/README.md +26 -2
  2. package/bin/stackkit.js +1 -1
  3. package/dist/commands/add.js +20 -39
  4. package/dist/commands/doctor.d.ts +11 -0
  5. package/dist/commands/doctor.js +483 -0
  6. package/dist/commands/list.d.ts +1 -1
  7. package/dist/commands/list.js +59 -38
  8. package/dist/index.js +11 -13
  9. package/dist/types/index.d.ts +15 -0
  10. package/dist/utils/config-utils.d.ts +2 -0
  11. package/dist/utils/config-utils.js +88 -0
  12. package/dist/utils/detect.js +12 -2
  13. package/dist/utils/env-editor.d.ts +0 -1
  14. package/dist/utils/env-editor.js +50 -25
  15. package/dist/utils/files.d.ts +8 -0
  16. package/dist/utils/files.js +51 -0
  17. package/dist/utils/js-conversion.d.ts +1 -0
  18. package/dist/utils/js-conversion.js +244 -0
  19. package/dist/utils/module-utils.d.ts +2 -0
  20. package/dist/utils/module-utils.js +461 -0
  21. package/dist/utils/package-manager.js +15 -31
  22. package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +6 -0
  23. package/modules/auth/authjs/files/lib/auth-client.ts +11 -0
  24. package/modules/auth/authjs/files/lib/auth.ts +41 -0
  25. package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
  26. package/modules/auth/authjs/module.json +95 -0
  27. package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
  28. package/modules/auth/better-auth/files/lib/auth.ts +62 -0
  29. package/modules/auth/better-auth/files/lib/email-service.ts +34 -0
  30. package/modules/auth/better-auth/files/lib/email-templates.ts +89 -0
  31. package/modules/auth/better-auth/files/schemas/prisma-schema.prisma +1 -1
  32. package/modules/auth/better-auth/module.json +164 -27
  33. package/modules/database/mongoose/files/lib/db.ts +68 -0
  34. package/modules/database/{mongoose-mongodb → mongoose}/files/models/User.ts +0 -5
  35. package/modules/database/{mongoose-mongodb → mongoose}/module.json +9 -24
  36. package/modules/database/prisma/files/lib/prisma.ts +1 -3
  37. package/modules/database/prisma/files/prisma/schema.prisma +1 -1
  38. package/modules/database/prisma/files/prisma.config.ts +2 -2
  39. package/modules/database/prisma/module.json +5 -23
  40. package/package.json +1 -1
  41. package/templates/express/.env.example +0 -1
  42. package/templates/express/package.json +4 -4
  43. package/templates/express/src/app.ts +2 -2
  44. package/templates/express/src/features/health/health.controller.ts +18 -0
  45. package/templates/express/src/features/health/health.route.ts +9 -0
  46. package/templates/express/src/features/health/health.service.ts +6 -0
  47. package/templates/nextjs/lib/env.ts +8 -0
  48. package/templates/nextjs/package.json +7 -7
  49. package/templates/react-vite/.env.example +1 -2
  50. package/templates/react-vite/.prettierignore +4 -0
  51. package/templates/react-vite/.prettierrc +9 -0
  52. package/templates/react-vite/README.md +22 -0
  53. package/templates/react-vite/package.json +16 -16
  54. package/templates/react-vite/src/router.tsx +0 -12
  55. package/templates/react-vite/vite.config.ts +0 -6
  56. package/dist/commands/init.d.ts +0 -10
  57. package/dist/commands/init.js +0 -157
  58. package/dist/utils/code-inject.d.ts +0 -14
  59. package/dist/utils/code-inject.js +0 -70
  60. package/dist/utils/json-editor.d.ts +0 -8
  61. package/dist/utils/json-editor.js +0 -45
  62. package/modules/auth/clerk/files/express/auth.ts +0 -7
  63. package/modules/auth/clerk/files/nextjs/auth-provider.tsx +0 -5
  64. package/modules/auth/clerk/files/nextjs/middleware.ts +0 -9
  65. package/modules/auth/clerk/files/react/auth-provider.tsx +0 -15
  66. package/modules/auth/clerk/module.json +0 -115
  67. package/modules/database/mongoose-mongodb/files/lib/db.ts +0 -78
  68. package/templates/express/src/features/auth/auth.controller.ts +0 -48
  69. package/templates/express/src/features/auth/auth.route.ts +0 -10
  70. package/templates/express/src/features/auth/auth.service.ts +0 -21
  71. package/templates/react-vite/src/api/services/user.service.ts +0 -18
  72. package/templates/react-vite/src/pages/UserProfile.tsx +0 -40
  73. package/templates/react-vite/src/types/user.d.ts +0 -6
@@ -1,6 +1,4 @@
1
1
  import "dotenv/config";
2
- import { PrismaClient } from "@/generated/prisma/client";
3
-
2
+ import { PrismaClient } from "./generated/prisma/client";
4
3
  {{prismaClientInit}}
5
-
6
4
  export { prisma };
@@ -1,6 +1,6 @@
1
1
  generator client {
2
2
  provider = "prisma-client"
3
- output = "../generated/prisma"
3
+ output = "../lib/generated/prisma"
4
4
  }
5
5
 
6
6
  datasource db {
@@ -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: process.env["DATABASE_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
- "exclude": ["node_modules", ".next", "out", "prisma/migrations"]
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": "Create Prisma client singleton",
135
- "source": "lib/prisma.ts",
136
- "destination": "{{lib}}/prisma.ts"
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stackkit-cli",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "CLI for StackKit - Production-ready project generator and module system",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -1,3 +1,2 @@
1
- # APP CONFIGURATION
2
1
  PORT=3000
3
2
  NODE_ENV=development
@@ -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.6",
26
- "@typescript-eslint/eslint-plugin": "^8.52.0",
27
- "@typescript-eslint/parser": "^8.52.0",
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/auth/auth.route";
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/auth", authRoutes);
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
+ };
@@ -0,0 +1,9 @@
1
+ import { Router } from "express";
2
+ import { healthController } from "./health.controller";
3
+
4
+ const router = Router();
5
+
6
+ // demo route
7
+ router.get("/", healthController.health);
8
+
9
+ export const authRoutes = router;
@@ -0,0 +1,6 @@
1
+ // Demo service - placeholder for future use
2
+ // Add your service logic here when needed
3
+
4
+ export const healthServices = {
5
+ // placeholder
6
+ };
@@ -0,0 +1,8 @@
1
+ export const env = {
2
+ app: {
3
+ url: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
4
+ },
5
+
6
+ isDev: process.env.NODE_ENV === "development",
7
+ isProd: process.env.NODE_ENV === "production",
8
+ } as const;
@@ -15,13 +15,13 @@
15
15
  "react-dom": "19.2.3"
16
16
  },
17
17
  "devDependencies": {
18
- "@tailwindcss/postcss": "^4",
19
- "@types/node": "^20",
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
- # API Configuration
2
- VITE_API_URL=http://localhost:3000
1
+ VITE_API_URL=http://localhost:3000
@@ -0,0 +1,4 @@
1
+ dist
2
+ node_modules
3
+ coverage
4
+ *.log
@@ -0,0 +1,9 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "all",
4
+ "singleQuote": false,
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "useTabs": false,
8
+ "arrowParens": "always"
9
+ }
@@ -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.62.0",
16
- "@tanstack/react-query-devtools": "^5.62.0",
17
- "axios": "^1.7.7",
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.0",
21
- "react-dom": "^19.2.0",
20
+ "react": "^19.2.3",
21
+ "react-dom": "^19.2.3",
22
22
  "react-helmet-async": "^2.0.5",
23
- "react-hot-toast": "^2.4.1",
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.1",
29
- "@types/node": "^24.10.1",
30
- "@types/react": "^19.2.5",
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.1",
32
+ "@vitejs/plugin-react": "^5.1.2",
33
33
  "autoprefixer": "^10.4.23",
34
- "eslint": "^9.39.1",
34
+ "eslint": "^9.39.2",
35
35
  "eslint-plugin-react-hooks": "^7.0.1",
36
- "eslint-plugin-react-refresh": "^0.4.24",
37
- "globals": "^16.5.0",
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.46.4",
42
- "vite": "^7.2.4"
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
  });
@@ -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 {};
@@ -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>;