create-bodhi-js 0.1.0
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/LICENSE +21 -0
- package/README.md +143 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +242 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BodhiSearch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# create-bodhi-js
|
|
2
|
+
|
|
3
|
+
Scaffold Bodhi-powered applications with React, TypeScript, Vite, Tailwind CSS, shadcn/ui, and comprehensive tooling.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Interactive mode
|
|
9
|
+
npm create bodhi-js@latest
|
|
10
|
+
|
|
11
|
+
# With project name
|
|
12
|
+
npm create bodhi-js@latest my-app
|
|
13
|
+
|
|
14
|
+
# With options
|
|
15
|
+
npm create bodhi-js@latest my-app -- --template react --github-pages
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
**Core Stack**:
|
|
21
|
+
- ⚡ [Vite 7](https://vite.dev/) - Next generation frontend tooling
|
|
22
|
+
- ⚛️ [React 19](https://react.dev/) - Latest React with modern patterns
|
|
23
|
+
- 📘 [TypeScript](https://www.typescriptlang.org/) - Strict mode enabled
|
|
24
|
+
- 🎨 [Tailwind CSS v4](https://tailwindcss.com/) - Utility-first CSS
|
|
25
|
+
- 🧩 [shadcn/ui](https://ui.shadcn.com/) - Re-usable components
|
|
26
|
+
- 🤖 [bodhi-js-react](https://github.com/BodhiSearch/bodhi-browser) - Local LLM integration
|
|
27
|
+
|
|
28
|
+
**Code Quality**:
|
|
29
|
+
- 🔍 ESLint 9 + Prettier
|
|
30
|
+
- 📝 EditorConfig
|
|
31
|
+
- 🎯 Strict TypeScript
|
|
32
|
+
|
|
33
|
+
**Testing**:
|
|
34
|
+
- ✅ [Vitest](https://vitest.dev/) - Unit testing
|
|
35
|
+
- 🎭 [Playwright](https://playwright.dev/) - E2E testing
|
|
36
|
+
|
|
37
|
+
**CI/CD** (optional):
|
|
38
|
+
- 🔄 GitHub Actions
|
|
39
|
+
- 📦 GitHub Pages deployment
|
|
40
|
+
- 🤖 Dependabot
|
|
41
|
+
|
|
42
|
+
## Options
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Usage: create-bodhi-js [project-name] [options]
|
|
46
|
+
|
|
47
|
+
Arguments:
|
|
48
|
+
project-name Name of the project
|
|
49
|
+
|
|
50
|
+
Options:
|
|
51
|
+
-V, --version output the version number
|
|
52
|
+
-t, --template <name> Template to use (react, svelte, vue) (default: "react")
|
|
53
|
+
--no-install Skip dependency installation
|
|
54
|
+
--no-git Skip git initialization
|
|
55
|
+
--github-pages Enable GitHub Pages deployment setup
|
|
56
|
+
-h, --help display help for command
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Templates
|
|
60
|
+
|
|
61
|
+
### Available Templates
|
|
62
|
+
|
|
63
|
+
- **react** - React + TypeScript + Vite + Tailwind + shadcn/ui + bodhi-js-react (default)
|
|
64
|
+
|
|
65
|
+
### Custom Templates
|
|
66
|
+
|
|
67
|
+
Use any Git repository as a template:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm create bodhi-js@latest my-app -- --template gh:username/my-template
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Supported Git providers (via [giget](https://github.com/unjs/giget)):
|
|
74
|
+
- GitHub: `gh:user/repo`
|
|
75
|
+
- GitLab: `gitlab:user/repo`
|
|
76
|
+
- BitBucket: `bitbucket:user/repo`
|
|
77
|
+
|
|
78
|
+
## What's Included?
|
|
79
|
+
|
|
80
|
+
When you scaffold a project with `create-bodhi-js`, you get:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
my-app/
|
|
84
|
+
├── .github/ # GitHub templates and workflows
|
|
85
|
+
│ ├── workflows/ # CI/CD pipelines
|
|
86
|
+
│ ├── ISSUE_TEMPLATE/ # Issue templates
|
|
87
|
+
│ └── ...
|
|
88
|
+
├── e2e/ # Playwright E2E tests
|
|
89
|
+
├── public/ # Static assets
|
|
90
|
+
├── src/
|
|
91
|
+
│ ├── components/ # React components
|
|
92
|
+
│ │ └── ui/ # shadcn/ui components
|
|
93
|
+
│ ├── hooks/ # Custom React hooks
|
|
94
|
+
│ ├── lib/ # Utility functions
|
|
95
|
+
│ ├── test/ # Test setup
|
|
96
|
+
│ ├── App.tsx # Main app component
|
|
97
|
+
│ ├── main.tsx # Entry point
|
|
98
|
+
│ ├── env.ts # Environment variable validation
|
|
99
|
+
│ └── index.css # Global styles
|
|
100
|
+
├── .editorconfig # Editor configuration
|
|
101
|
+
├── .prettierrc # Prettier configuration
|
|
102
|
+
├── components.json # shadcn/ui configuration
|
|
103
|
+
├── eslint.config.js # ESLint configuration
|
|
104
|
+
├── playwright.config.ts # Playwright configuration
|
|
105
|
+
├── tsconfig.json # TypeScript configuration
|
|
106
|
+
├── vite.config.ts # Vite configuration
|
|
107
|
+
└── package.json # Dependencies and scripts
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Post-Installation
|
|
111
|
+
|
|
112
|
+
After scaffolding your project:
|
|
113
|
+
|
|
114
|
+
1. **Configure environment variables**:
|
|
115
|
+
```bash
|
|
116
|
+
cp .env.example .env
|
|
117
|
+
# Edit .env with your Bodhi OAuth credentials
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
2. **Start development server**:
|
|
121
|
+
```bash
|
|
122
|
+
npm run dev
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
3. **Run tests**:
|
|
126
|
+
```bash
|
|
127
|
+
npm test # Unit tests
|
|
128
|
+
npm run test:e2e # E2E tests
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
4. **Build for production**:
|
|
132
|
+
```bash
|
|
133
|
+
npm run build
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
139
|
+
|
|
140
|
+
## Related
|
|
141
|
+
|
|
142
|
+
- [bodhi-browser](https://github.com/BodhiSearch/bodhi-browser) - Bodhi Browser Extension
|
|
143
|
+
- [template-bodhi-react-vite](https://github.com/BodhiSearch/template-bodhi-react-vite) - React template source
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
|
|
7
|
+
// src/cli.ts
|
|
8
|
+
import * as p from "@clack/prompts";
|
|
9
|
+
import pc from "picocolors";
|
|
10
|
+
|
|
11
|
+
// src/scaffold.ts
|
|
12
|
+
import { downloadTemplate } from "giget";
|
|
13
|
+
import { promises as fs2 } from "fs";
|
|
14
|
+
import path2 from "path";
|
|
15
|
+
|
|
16
|
+
// src/processor.ts
|
|
17
|
+
import Handlebars from "handlebars";
|
|
18
|
+
import { promises as fs } from "fs";
|
|
19
|
+
import path from "path";
|
|
20
|
+
var TEMPLATE_FILES = [
|
|
21
|
+
"package.json",
|
|
22
|
+
"vite.config.ts",
|
|
23
|
+
"index.html",
|
|
24
|
+
"public/404.html",
|
|
25
|
+
"README.md",
|
|
26
|
+
"playwright.config.ts"
|
|
27
|
+
];
|
|
28
|
+
async function processTemplates(targetDir, vars) {
|
|
29
|
+
for (const file of TEMPLATE_FILES) {
|
|
30
|
+
const filePath = path.join(targetDir, file);
|
|
31
|
+
try {
|
|
32
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
33
|
+
const template = Handlebars.compile(content);
|
|
34
|
+
const rendered = template(vars);
|
|
35
|
+
await fs.writeFile(filePath, rendered, "utf-8");
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/scaffold.ts
|
|
42
|
+
import { exec } from "child_process";
|
|
43
|
+
import { promisify } from "util";
|
|
44
|
+
var execAsync = promisify(exec);
|
|
45
|
+
async function scaffold(options) {
|
|
46
|
+
const {
|
|
47
|
+
projectName,
|
|
48
|
+
templateUrl,
|
|
49
|
+
githubOrg,
|
|
50
|
+
githubPages,
|
|
51
|
+
basePath,
|
|
52
|
+
pathSegmentsToKeep,
|
|
53
|
+
install,
|
|
54
|
+
git
|
|
55
|
+
} = options;
|
|
56
|
+
const targetDir = path2.resolve(process.cwd(), projectName);
|
|
57
|
+
try {
|
|
58
|
+
await fs2.access(targetDir);
|
|
59
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
if (err.code !== "ENOENT") {
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
await downloadTemplate(templateUrl, {
|
|
66
|
+
dir: targetDir,
|
|
67
|
+
offline: false
|
|
68
|
+
});
|
|
69
|
+
const templateSubdir = path2.join(targetDir, "template");
|
|
70
|
+
try {
|
|
71
|
+
await fs2.access(templateSubdir);
|
|
72
|
+
const files = await fs2.readdir(templateSubdir);
|
|
73
|
+
for (const file of files) {
|
|
74
|
+
await fs2.rename(path2.join(templateSubdir, file), path2.join(targetDir, file));
|
|
75
|
+
}
|
|
76
|
+
await fs2.rmdir(templateSubdir);
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
const dotfiles = ["_gitignore", "_editorconfig", "_prettierrc", "_prettierignore"];
|
|
80
|
+
for (const file of dotfiles) {
|
|
81
|
+
const oldPath = path2.join(targetDir, file);
|
|
82
|
+
const newPath = path2.join(targetDir, file.replace("_", "."));
|
|
83
|
+
try {
|
|
84
|
+
await fs2.rename(oldPath, newPath);
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
await processTemplates(targetDir, {
|
|
89
|
+
projectName,
|
|
90
|
+
githubOrg,
|
|
91
|
+
githubPages,
|
|
92
|
+
basePath,
|
|
93
|
+
pathSegmentsToKeep
|
|
94
|
+
});
|
|
95
|
+
if (!githubPages) {
|
|
96
|
+
const filesToDelete = [
|
|
97
|
+
path2.join(targetDir, ".github/workflows/deploy-pages.yml"),
|
|
98
|
+
path2.join(targetDir, "public/404.html")
|
|
99
|
+
];
|
|
100
|
+
for (const file of filesToDelete) {
|
|
101
|
+
try {
|
|
102
|
+
await fs2.unlink(file);
|
|
103
|
+
} catch {
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const metaFiles = ["template.json", "test-template.sh", "TECH.md"];
|
|
108
|
+
for (const file of metaFiles) {
|
|
109
|
+
try {
|
|
110
|
+
await fs2.unlink(path2.join(targetDir, file));
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (git) {
|
|
115
|
+
try {
|
|
116
|
+
await execAsync("git init", { cwd: targetDir });
|
|
117
|
+
await execAsync("git add .", { cwd: targetDir });
|
|
118
|
+
await execAsync('git commit -m "chore: initial commit from create-bodhi-js"', {
|
|
119
|
+
cwd: targetDir
|
|
120
|
+
});
|
|
121
|
+
} catch {
|
|
122
|
+
console.warn("Warning: Git initialization failed");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (install) {
|
|
126
|
+
await execAsync("npm install", { cwd: targetDir });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/templates.ts
|
|
131
|
+
var TEMPLATES = {
|
|
132
|
+
react: "gh:BodhiSearch/template-bodhi-react-vite"
|
|
133
|
+
// Future templates
|
|
134
|
+
// svelte: 'gh:BodhiSearch/template-bodhi-svelte-vite',
|
|
135
|
+
// vue: 'gh:BodhiSearch/template-bodhi-vue-vite',
|
|
136
|
+
};
|
|
137
|
+
function resolveTemplate(name) {
|
|
138
|
+
if (TEMPLATES[name]) {
|
|
139
|
+
return TEMPLATES[name];
|
|
140
|
+
}
|
|
141
|
+
if (name.includes(":")) {
|
|
142
|
+
return name;
|
|
143
|
+
}
|
|
144
|
+
throw new Error(
|
|
145
|
+
`Unknown template: ${name}
|
|
146
|
+
|
|
147
|
+
Available templates:
|
|
148
|
+
${Object.keys(TEMPLATES).map((t) => ` - ${t}`).join("\n")}
|
|
149
|
+
|
|
150
|
+
Or use a custom template: gh:user/repo`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/cli.ts
|
|
155
|
+
async function create(projectName, options) {
|
|
156
|
+
console.log();
|
|
157
|
+
p.intro(pc.bgCyan(pc.black(" create-bodhi-js ")));
|
|
158
|
+
let targetDir = projectName;
|
|
159
|
+
const template = options.template;
|
|
160
|
+
if (!targetDir) {
|
|
161
|
+
const result = await p.text({
|
|
162
|
+
message: "Project name:",
|
|
163
|
+
placeholder: "my-bodhi-app",
|
|
164
|
+
validate: (value) => {
|
|
165
|
+
if (!value) return "Project name is required";
|
|
166
|
+
if (!/^[a-z0-9-]+$/.test(value)) return "Use lowercase letters, numbers, and hyphens only";
|
|
167
|
+
return void 0;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
if (p.isCancel(result)) {
|
|
171
|
+
p.cancel("Operation cancelled");
|
|
172
|
+
process.exit(0);
|
|
173
|
+
}
|
|
174
|
+
targetDir = result;
|
|
175
|
+
}
|
|
176
|
+
let templateUrl;
|
|
177
|
+
try {
|
|
178
|
+
templateUrl = resolveTemplate(template);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
p.log.error(error.message);
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
let enableGithubPages = options.githubPages ?? false;
|
|
184
|
+
if (!options.githubPages) {
|
|
185
|
+
const result = await p.confirm({
|
|
186
|
+
message: "Enable GitHub Pages deployment?",
|
|
187
|
+
initialValue: false
|
|
188
|
+
});
|
|
189
|
+
if (p.isCancel(result)) {
|
|
190
|
+
p.cancel("Operation cancelled");
|
|
191
|
+
process.exit(0);
|
|
192
|
+
}
|
|
193
|
+
enableGithubPages = result;
|
|
194
|
+
}
|
|
195
|
+
let githubOrg = "";
|
|
196
|
+
let basePath = "/";
|
|
197
|
+
let pathSegmentsToKeep = 0;
|
|
198
|
+
if (enableGithubPages) {
|
|
199
|
+
const orgResult = await p.text({
|
|
200
|
+
message: "GitHub organization/username:",
|
|
201
|
+
placeholder: "my-org"
|
|
202
|
+
});
|
|
203
|
+
if (p.isCancel(orgResult)) {
|
|
204
|
+
p.cancel("Operation cancelled");
|
|
205
|
+
process.exit(0);
|
|
206
|
+
}
|
|
207
|
+
githubOrg = orgResult;
|
|
208
|
+
basePath = `/${targetDir}/`;
|
|
209
|
+
pathSegmentsToKeep = 1;
|
|
210
|
+
}
|
|
211
|
+
const spinner2 = p.spinner();
|
|
212
|
+
spinner2.start("Scaffolding project...");
|
|
213
|
+
try {
|
|
214
|
+
await scaffold({
|
|
215
|
+
projectName: targetDir,
|
|
216
|
+
templateUrl,
|
|
217
|
+
githubOrg,
|
|
218
|
+
githubPages: enableGithubPages,
|
|
219
|
+
basePath,
|
|
220
|
+
pathSegmentsToKeep,
|
|
221
|
+
install: options.install,
|
|
222
|
+
git: options.git
|
|
223
|
+
});
|
|
224
|
+
spinner2.stop("Project scaffolded successfully!");
|
|
225
|
+
p.note(
|
|
226
|
+
[`cd ${targetDir}`, !options.install && "npm install", "npm run dev"].filter(Boolean).join("\n"),
|
|
227
|
+
"Next steps"
|
|
228
|
+
);
|
|
229
|
+
p.outro(pc.green("Happy coding! \u{1F680}"));
|
|
230
|
+
} catch (error) {
|
|
231
|
+
spinner2.stop("Failed to scaffold project");
|
|
232
|
+
p.log.error(error.message);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// src/index.ts
|
|
238
|
+
var program = new Command();
|
|
239
|
+
program.name("create-bodhi-js").description("Scaffold Bodhi-powered applications").version("0.1.0").argument("[project-name]", "Name of the project").option("-t, --template <name>", "Template to use (react, svelte, vue)", "react").option("--no-install", "Skip dependency installation").option("--no-git", "Skip git initialization").option("--github-pages", "Enable GitHub Pages deployment setup").action(async (projectName, options) => {
|
|
240
|
+
await create(projectName, options);
|
|
241
|
+
});
|
|
242
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-bodhi-js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold Bodhi-powered applications with React, TypeScript, Vite, and more",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-bodhi-js": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "tsx src/index.ts",
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"lint": "eslint . --max-warnings 0",
|
|
20
|
+
"lint:fix": "eslint . --fix",
|
|
21
|
+
"check": "npm run lint && npm run typecheck",
|
|
22
|
+
"check:fix": "npm run lint:fix && npm run typecheck",
|
|
23
|
+
"test": "echo \"Tests coming soon\" && exit 0",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"create-bodhi-js",
|
|
28
|
+
"bodhi",
|
|
29
|
+
"bodhi-js",
|
|
30
|
+
"react",
|
|
31
|
+
"vite",
|
|
32
|
+
"typescript",
|
|
33
|
+
"template",
|
|
34
|
+
"scaffolding",
|
|
35
|
+
"cli"
|
|
36
|
+
],
|
|
37
|
+
"author": "BodhiSearch",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/BodhiSearch/create-bodhi-js.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/BodhiSearch/create-bodhi-js/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/BodhiSearch/create-bodhi-js#readme",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@clack/prompts": "^0.11.0",
|
|
49
|
+
"commander": "^14.0.2",
|
|
50
|
+
"giget": "^2.0.0",
|
|
51
|
+
"handlebars": "^4.7.8",
|
|
52
|
+
"picocolors": "^1.1.1"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@eslint/js": "^9.39.1",
|
|
56
|
+
"@types/node": "^25.0.3",
|
|
57
|
+
"eslint": "^9.39.1",
|
|
58
|
+
"eslint-config-prettier": "^10.1.8",
|
|
59
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
60
|
+
"globals": "^17.0.0",
|
|
61
|
+
"prettier": "^3.7.4",
|
|
62
|
+
"tsup": "^8.5.0",
|
|
63
|
+
"tsx": "^4.19.2",
|
|
64
|
+
"typescript": "^5.9.3",
|
|
65
|
+
"typescript-eslint": "^8.46.4"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": ">=18.0.0"
|
|
69
|
+
}
|
|
70
|
+
}
|