@object-ui/create-plugin 0.3.1
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 +88 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +331 -0
- package/package.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 ObjectQL
|
|
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,88 @@
|
|
|
1
|
+
# @object-ui/create-plugin
|
|
2
|
+
|
|
3
|
+
CLI tool to quickly scaffold new ObjectUI plugins with best practices.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Using pnpm
|
|
9
|
+
pnpm create @object-ui/plugin my-plugin
|
|
10
|
+
|
|
11
|
+
# Using npm
|
|
12
|
+
npm create @object-ui/plugin my-plugin
|
|
13
|
+
|
|
14
|
+
# Using npx
|
|
15
|
+
npx @object-ui/create-plugin my-plugin
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## What Gets Generated
|
|
19
|
+
|
|
20
|
+
The tool creates a complete plugin package structure:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
packages/plugin-my-plugin/
|
|
24
|
+
├── src/
|
|
25
|
+
│ ├── index.tsx # Plugin export & registration
|
|
26
|
+
│ ├── MyPluginImpl.tsx # Component implementation
|
|
27
|
+
│ ├── MyPluginImpl.test.tsx # Tests
|
|
28
|
+
│ └── types.ts # Schema definitions
|
|
29
|
+
├── package.json
|
|
30
|
+
├── tsconfig.json
|
|
31
|
+
├── vite.config.ts
|
|
32
|
+
└── README.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- ✅ TypeScript support out of the box
|
|
38
|
+
- ✅ Vite build configuration
|
|
39
|
+
- ✅ Component registration with ComponentRegistry
|
|
40
|
+
- ✅ Test setup with Vitest
|
|
41
|
+
- ✅ Proper package.json with workspace dependencies
|
|
42
|
+
- ✅ README template
|
|
43
|
+
- ✅ Type definitions
|
|
44
|
+
|
|
45
|
+
## Interactive Mode
|
|
46
|
+
|
|
47
|
+
Run without arguments for interactive prompts:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pnpm create @object-ui/plugin
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You'll be prompted for:
|
|
54
|
+
- Plugin name
|
|
55
|
+
- Description
|
|
56
|
+
- Author name
|
|
57
|
+
|
|
58
|
+
## Options
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pnpm create @object-ui/plugin my-plugin --description "My awesome plugin" --author "Your Name"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## After Creation
|
|
65
|
+
|
|
66
|
+
1. Navigate to the plugin directory:
|
|
67
|
+
```bash
|
|
68
|
+
cd packages/plugin-my-plugin
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
2. Install dependencies:
|
|
72
|
+
```bash
|
|
73
|
+
pnpm install
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
3. Build the plugin:
|
|
77
|
+
```bash
|
|
78
|
+
pnpm build
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
4. Run tests:
|
|
82
|
+
```bash
|
|
83
|
+
pnpm test
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import prompts from "prompts";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import fs from "fs-extra";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
var __dirname = path.dirname(__filename);
|
|
12
|
+
var program = new Command();
|
|
13
|
+
async function createPlugin(pluginName, options = {}) {
|
|
14
|
+
console.log(chalk.blue("\n\u{1F680} ObjectUI Plugin Generator\n"));
|
|
15
|
+
if (!pluginName) {
|
|
16
|
+
const response = await prompts({
|
|
17
|
+
type: "text",
|
|
18
|
+
name: "name",
|
|
19
|
+
message: "Plugin name (without prefix):",
|
|
20
|
+
validate: (value) => {
|
|
21
|
+
if (value.length === 0) return "Plugin name is required";
|
|
22
|
+
if (!/^[a-z0-9-]+$/.test(value)) {
|
|
23
|
+
return "Plugin name must contain only lowercase letters, numbers, and hyphens";
|
|
24
|
+
}
|
|
25
|
+
if (value.includes("..") || value.includes("/") || value.includes("\\")) {
|
|
26
|
+
return 'Plugin name cannot contain path separators or ".."';
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
pluginName = response.name;
|
|
32
|
+
if (!pluginName) {
|
|
33
|
+
console.log(chalk.red("\n\u274C Plugin name is required"));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (!/^[a-z0-9-]+$/.test(pluginName)) {
|
|
38
|
+
console.log(chalk.red("\n\u274C Plugin name must contain only lowercase letters, numbers, and hyphens"));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
if (pluginName.includes("..") || pluginName.includes("/") || pluginName.includes("\\") || path.isAbsolute(pluginName)) {
|
|
42
|
+
console.log(chalk.red("\n\u274C Invalid plugin name: path traversal detected"));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const cleanName = pluginName.replace(/^plugin-/, "").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
|
|
46
|
+
if (cleanName.length === 0) {
|
|
47
|
+
console.log(chalk.red("\n\u274C Plugin name cannot be empty after sanitization"));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
const fullPackageName = `plugin-${cleanName}`;
|
|
51
|
+
const pascalCaseName = cleanName.split("-").filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
52
|
+
const answers = await prompts([
|
|
53
|
+
{
|
|
54
|
+
type: "text",
|
|
55
|
+
name: "description",
|
|
56
|
+
message: "Plugin description:",
|
|
57
|
+
initial: options.description || `${pascalCaseName} plugin for ObjectUI`
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: "text",
|
|
61
|
+
name: "author",
|
|
62
|
+
message: "Author name:",
|
|
63
|
+
initial: options.author || ""
|
|
64
|
+
}
|
|
65
|
+
]);
|
|
66
|
+
const targetDir = path.join(process.cwd(), "packages", fullPackageName);
|
|
67
|
+
if (fs.existsSync(targetDir)) {
|
|
68
|
+
console.log(chalk.red(`
|
|
69
|
+
\u274C Directory already exists: ${targetDir}`));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
console.log(chalk.green(`
|
|
73
|
+
\u2728 Creating plugin: ${fullPackageName}...
|
|
74
|
+
`));
|
|
75
|
+
fs.mkdirpSync(targetDir);
|
|
76
|
+
fs.mkdirpSync(path.join(targetDir, "src"));
|
|
77
|
+
const templateDir = path.join(__dirname, "..", "templates", "plugin");
|
|
78
|
+
const vars = {
|
|
79
|
+
PACKAGE_NAME: `@object-ui/${fullPackageName}`,
|
|
80
|
+
PLUGIN_NAME: cleanName,
|
|
81
|
+
PASCAL_NAME: pascalCaseName,
|
|
82
|
+
DESCRIPTION: answers.description,
|
|
83
|
+
AUTHOR: answers.author,
|
|
84
|
+
VERSION: "0.1.0",
|
|
85
|
+
YEAR: (/* @__PURE__ */ new Date()).getFullYear()
|
|
86
|
+
};
|
|
87
|
+
const packageJson = {
|
|
88
|
+
name: vars.PACKAGE_NAME,
|
|
89
|
+
version: vars.VERSION,
|
|
90
|
+
type: "module",
|
|
91
|
+
license: "MIT",
|
|
92
|
+
description: vars.DESCRIPTION,
|
|
93
|
+
main: "dist/index.umd.cjs",
|
|
94
|
+
module: "dist/index.js",
|
|
95
|
+
types: "dist/index.d.ts",
|
|
96
|
+
exports: {
|
|
97
|
+
".": {
|
|
98
|
+
types: "./dist/index.d.ts",
|
|
99
|
+
import: "./dist/index.js",
|
|
100
|
+
require: "./dist/index.umd.cjs"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
scripts: {
|
|
104
|
+
build: "vite build",
|
|
105
|
+
test: "vitest run",
|
|
106
|
+
lint: "eslint ."
|
|
107
|
+
},
|
|
108
|
+
dependencies: {
|
|
109
|
+
"@object-ui/components": "workspace:*",
|
|
110
|
+
"@object-ui/core": "workspace:*",
|
|
111
|
+
"@object-ui/react": "workspace:*",
|
|
112
|
+
"@object-ui/types": "workspace:*",
|
|
113
|
+
"lucide-react": "^0.563.0"
|
|
114
|
+
},
|
|
115
|
+
peerDependencies: {
|
|
116
|
+
react: "^18.0.0 || ^19.0.0",
|
|
117
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
118
|
+
},
|
|
119
|
+
devDependencies: {
|
|
120
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
121
|
+
typescript: "^5.9.3",
|
|
122
|
+
vite: "^7.3.1",
|
|
123
|
+
"vite-plugin-dts": "^4.5.4",
|
|
124
|
+
vitest: "^4.0.18"
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
fs.writeFileSync(
|
|
128
|
+
path.join(targetDir, "package.json"),
|
|
129
|
+
JSON.stringify(packageJson, null, 2)
|
|
130
|
+
);
|
|
131
|
+
const tsconfig = {
|
|
132
|
+
extends: "../../tsconfig.json",
|
|
133
|
+
compilerOptions: {
|
|
134
|
+
outDir: "./dist",
|
|
135
|
+
rootDir: "./src",
|
|
136
|
+
declaration: true,
|
|
137
|
+
declarationMap: true
|
|
138
|
+
},
|
|
139
|
+
include: ["src/**/*"],
|
|
140
|
+
exclude: ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
|
|
141
|
+
};
|
|
142
|
+
fs.writeFileSync(
|
|
143
|
+
path.join(targetDir, "tsconfig.json"),
|
|
144
|
+
JSON.stringify(tsconfig, null, 2)
|
|
145
|
+
);
|
|
146
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
147
|
+
import react from '@vitejs/plugin-react';
|
|
148
|
+
import dts from 'vite-plugin-dts';
|
|
149
|
+
import * as path from 'path';
|
|
150
|
+
|
|
151
|
+
export default defineConfig({
|
|
152
|
+
plugins: [
|
|
153
|
+
react(),
|
|
154
|
+
dts({
|
|
155
|
+
insertTypesEntry: true,
|
|
156
|
+
}),
|
|
157
|
+
],
|
|
158
|
+
build: {
|
|
159
|
+
lib: {
|
|
160
|
+
entry: path.resolve(__dirname, 'src/index.tsx'),
|
|
161
|
+
name: '${pascalCaseName}',
|
|
162
|
+
formats: ['es', 'umd'],
|
|
163
|
+
fileName: (format) => \`index.\${format === 'es' ? 'js' : 'umd.cjs'}\`,
|
|
164
|
+
},
|
|
165
|
+
rollupOptions: {
|
|
166
|
+
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
|
167
|
+
output: {
|
|
168
|
+
globals: {
|
|
169
|
+
react: 'React',
|
|
170
|
+
'react-dom': 'ReactDOM',
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
`;
|
|
177
|
+
fs.writeFileSync(path.join(targetDir, "vite.config.ts"), viteConfig);
|
|
178
|
+
const readme = `# ${vars.PACKAGE_NAME}
|
|
179
|
+
|
|
180
|
+
${vars.DESCRIPTION}
|
|
181
|
+
|
|
182
|
+
## Installation
|
|
183
|
+
|
|
184
|
+
\`\`\`bash
|
|
185
|
+
pnpm add ${vars.PACKAGE_NAME}
|
|
186
|
+
\`\`\`
|
|
187
|
+
|
|
188
|
+
## Usage
|
|
189
|
+
|
|
190
|
+
\`\`\`tsx
|
|
191
|
+
import { ${pascalCaseName} } from '${vars.PACKAGE_NAME}';
|
|
192
|
+
|
|
193
|
+
// Use the component
|
|
194
|
+
<${pascalCaseName} />
|
|
195
|
+
\`\`\`
|
|
196
|
+
|
|
197
|
+
## Development
|
|
198
|
+
|
|
199
|
+
\`\`\`bash
|
|
200
|
+
# Build the plugin
|
|
201
|
+
pnpm build
|
|
202
|
+
|
|
203
|
+
# Run tests
|
|
204
|
+
pnpm test
|
|
205
|
+
|
|
206
|
+
# Lint code
|
|
207
|
+
pnpm lint
|
|
208
|
+
\`\`\`
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT \xA9 ${vars.AUTHOR}
|
|
213
|
+
`;
|
|
214
|
+
fs.writeFileSync(path.join(targetDir, "README.md"), readme);
|
|
215
|
+
const indexFile = `/**
|
|
216
|
+
* ObjectUI
|
|
217
|
+
* Copyright (c) ${vars.YEAR}-present ObjectStack Inc.
|
|
218
|
+
*
|
|
219
|
+
* This source code is licensed under the MIT license found in the
|
|
220
|
+
* LICENSE file in the root directory of this source tree.
|
|
221
|
+
*/
|
|
222
|
+
|
|
223
|
+
import React from 'react';
|
|
224
|
+
import { ComponentRegistry } from '@object-ui/core';
|
|
225
|
+
import { ${pascalCaseName} } from './${pascalCaseName}Impl';
|
|
226
|
+
|
|
227
|
+
export { ${pascalCaseName} };
|
|
228
|
+
export type { ${pascalCaseName}Props } from './${pascalCaseName}Impl';
|
|
229
|
+
|
|
230
|
+
// Register component with ComponentRegistry
|
|
231
|
+
const ${pascalCaseName}Renderer: React.FC<{ schema: any }> = ({ schema }) => {
|
|
232
|
+
return <${pascalCaseName} {...schema} />;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
ComponentRegistry.register('${cleanName}', ${pascalCaseName}Renderer, {
|
|
236
|
+
label: '${pascalCaseName}',
|
|
237
|
+
category: 'plugin',
|
|
238
|
+
inputs: [
|
|
239
|
+
// Define your component inputs here
|
|
240
|
+
],
|
|
241
|
+
defaultProps: {
|
|
242
|
+
// Define default props here
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
`;
|
|
246
|
+
fs.writeFileSync(path.join(targetDir, "src", "index.tsx"), indexFile);
|
|
247
|
+
const implFile = `/**
|
|
248
|
+
* ObjectUI
|
|
249
|
+
* Copyright (c) ${vars.YEAR}-present ObjectStack Inc.
|
|
250
|
+
*
|
|
251
|
+
* This source code is licensed under the MIT license found in the
|
|
252
|
+
* LICENSE file in the root directory of this source tree.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
import React from 'react';
|
|
256
|
+
|
|
257
|
+
export interface ${pascalCaseName}Props {
|
|
258
|
+
// Define your props here
|
|
259
|
+
className?: string;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* ${pascalCaseName} component
|
|
264
|
+
*/
|
|
265
|
+
export const ${pascalCaseName}: React.FC<${pascalCaseName}Props> = ({ className }) => {
|
|
266
|
+
return (
|
|
267
|
+
<div className={className}>
|
|
268
|
+
<h2>${pascalCaseName} Plugin</h2>
|
|
269
|
+
<p>Implement your plugin logic here.</p>
|
|
270
|
+
</div>
|
|
271
|
+
);
|
|
272
|
+
};
|
|
273
|
+
`;
|
|
274
|
+
fs.writeFileSync(
|
|
275
|
+
path.join(targetDir, "src", `${pascalCaseName}Impl.tsx`),
|
|
276
|
+
implFile
|
|
277
|
+
);
|
|
278
|
+
const typesFile = `/**
|
|
279
|
+
* ObjectUI
|
|
280
|
+
* Copyright (c) ${vars.YEAR}-present ObjectStack Inc.
|
|
281
|
+
*
|
|
282
|
+
* This source code is licensed under the MIT license found in the
|
|
283
|
+
* LICENSE file in the root directory of this source tree.
|
|
284
|
+
*/
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Schema definition for ${pascalCaseName}
|
|
288
|
+
*/
|
|
289
|
+
export interface ${pascalCaseName}Schema {
|
|
290
|
+
type: '${cleanName}';
|
|
291
|
+
id?: string;
|
|
292
|
+
className?: string;
|
|
293
|
+
// Add schema properties here
|
|
294
|
+
}
|
|
295
|
+
`;
|
|
296
|
+
fs.writeFileSync(path.join(targetDir, "src", "types.ts"), typesFile);
|
|
297
|
+
const testFile = `/**
|
|
298
|
+
* ObjectUI
|
|
299
|
+
* Copyright (c) ${vars.YEAR}-present ObjectStack Inc.
|
|
300
|
+
*
|
|
301
|
+
* This source code is licensed under the MIT license found in the
|
|
302
|
+
* LICENSE file in the root directory of this source tree.
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
import { describe, it, expect } from 'vitest';
|
|
306
|
+
import { render, screen } from '@testing-library/react';
|
|
307
|
+
import React from 'react';
|
|
308
|
+
import { ${pascalCaseName} } from './${pascalCaseName}Impl';
|
|
309
|
+
|
|
310
|
+
describe('${pascalCaseName}', () => {
|
|
311
|
+
it('should render', () => {
|
|
312
|
+
render(<${pascalCaseName} />);
|
|
313
|
+
expect(screen.getByText('${pascalCaseName} Plugin')).toBeInTheDocument();
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
`;
|
|
317
|
+
fs.writeFileSync(
|
|
318
|
+
path.join(targetDir, "src", `${pascalCaseName}Impl.test.tsx`),
|
|
319
|
+
testFile
|
|
320
|
+
);
|
|
321
|
+
console.log(chalk.green("\u2705 Plugin created successfully!\n"));
|
|
322
|
+
console.log(chalk.blue("Next steps:\n"));
|
|
323
|
+
console.log(chalk.gray(` cd packages/${fullPackageName}`));
|
|
324
|
+
console.log(chalk.gray(" pnpm install"));
|
|
325
|
+
console.log(chalk.gray(" pnpm build\n"));
|
|
326
|
+
console.log(chalk.blue("To use the plugin:\n"));
|
|
327
|
+
console.log(chalk.gray(` import { ${pascalCaseName} } from '${vars.PACKAGE_NAME}';
|
|
328
|
+
`));
|
|
329
|
+
}
|
|
330
|
+
program.name("create-plugin").description("Create a new ObjectUI plugin").argument("[plugin-name]", "Name of the plugin (without plugin- prefix)").option("-d, --description <description>", "Plugin description").option("-a, --author <author>", "Author name").action(createPlugin);
|
|
331
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@object-ui/create-plugin",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "CLI tool to scaffold ObjectUI plugins",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-plugin": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"templates"
|
|
13
|
+
],
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"chalk": "^5.4.1",
|
|
16
|
+
"commander": "^14.0.2",
|
|
17
|
+
"fs-extra": "^11.2.0",
|
|
18
|
+
"prompts": "^2.4.2"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/fs-extra": "^11.0.4",
|
|
22
|
+
"@types/node": "^25.0.10",
|
|
23
|
+
"@types/prompts": "^2.4.9",
|
|
24
|
+
"tsup": "^8.0.0",
|
|
25
|
+
"typescript": "^5.9.3",
|
|
26
|
+
"vitest": "^4.0.18"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup",
|
|
30
|
+
"dev": "tsup --watch",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"lint": "eslint ."
|
|
33
|
+
}
|
|
34
|
+
}
|