devstarter-tool 0.2.1 → 0.2.2
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 +67 -51
- package/dist/cli.js +1 -0
- package/dist/commands/init/collector.js +27 -1
- package/dist/generators/createMonorepo.js +11 -2
- package/dist/generators/createProject.js +10 -2
- package/dist/prompts/initPrompts.js +8 -0
- package/dist/types/project.js +1 -0
- package/dist/utils/installDependencies.js +8 -0
- package/dist/utils/printSummary.js +0 -1
- package/dist/utils/setupVitest.js +31 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
CLI to generate projects with best practices and predefined configurations.
|
|
4
4
|
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Project structures**: Basic (single project) or Monorepo (full-stack)
|
|
8
|
+
- **Automatic dependency installation**: No need to run `npm install` manually
|
|
9
|
+
- **Vitest integration**: Optional testing setup with one flag
|
|
10
|
+
- **Package manager detection**: Automatically uses npm, pnpm, or yarn
|
|
11
|
+
- **Git initialization**: Optional repository setup
|
|
12
|
+
- **Interactive prompts**: Guided project creation
|
|
13
|
+
- **Dry-run mode**: Preview changes before creating files
|
|
14
|
+
|
|
5
15
|
## Installation
|
|
6
16
|
|
|
7
17
|
```bash
|
|
@@ -14,12 +24,26 @@ Or run directly with npx:
|
|
|
14
24
|
npx devstarter-tool init my-app
|
|
15
25
|
```
|
|
16
26
|
|
|
17
|
-
##
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Interactive mode - guided setup
|
|
31
|
+
devstarter init
|
|
18
32
|
|
|
19
|
-
|
|
33
|
+
# Quick project with defaults
|
|
34
|
+
devstarter init my-app -y
|
|
35
|
+
|
|
36
|
+
# Frontend project with Vitest
|
|
37
|
+
devstarter init my-app --type frontend --vitest
|
|
38
|
+
|
|
39
|
+
# Preview without creating files
|
|
40
|
+
devstarter init my-app --dry-run
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
20
44
|
|
|
21
45
|
```bash
|
|
22
|
-
devstarter init [project-name]
|
|
46
|
+
devstarter init [project-name] [options]
|
|
23
47
|
```
|
|
24
48
|
|
|
25
49
|
### Options
|
|
@@ -28,10 +52,10 @@ devstarter init [project-name]
|
|
|
28
52
|
|--------|-------------|
|
|
29
53
|
| `-y, --yes` | Use default values without prompting |
|
|
30
54
|
| `-t, --type <type>` | Project type: `frontend` or `backend` |
|
|
31
|
-
| `--template <name>` | Template to use |
|
|
55
|
+
| `--template <name>` | Template to use (e.g., `basic`, `react`) |
|
|
56
|
+
| `--vitest` | Add Vitest for testing |
|
|
57
|
+
| `--no-git` | Skip Git repository initialization |
|
|
32
58
|
| `--dry-run` | Preview changes without creating files |
|
|
33
|
-
| `--no-git` | Skip git repository initialization |
|
|
34
|
-
| `--no-vitest` | Skip Vitest testing framework setup |
|
|
35
59
|
|
|
36
60
|
### Examples
|
|
37
61
|
|
|
@@ -42,17 +66,17 @@ devstarter init
|
|
|
42
66
|
# Create project with specific name
|
|
43
67
|
devstarter init my-app
|
|
44
68
|
|
|
45
|
-
#
|
|
46
|
-
devstarter init my-app --type frontend
|
|
69
|
+
# Frontend with React template
|
|
70
|
+
devstarter init my-app --type frontend --template react
|
|
47
71
|
|
|
48
|
-
#
|
|
49
|
-
devstarter init my-
|
|
72
|
+
# Backend with testing setup
|
|
73
|
+
devstarter init my-api --type backend --vitest
|
|
50
74
|
|
|
51
|
-
#
|
|
52
|
-
devstarter init my-app --
|
|
75
|
+
# Quick frontend with all defaults
|
|
76
|
+
devstarter init my-app --type frontend -y
|
|
53
77
|
|
|
54
|
-
# Create
|
|
55
|
-
devstarter init my-app --no-
|
|
78
|
+
# Create without Git
|
|
79
|
+
devstarter init my-app --no-git
|
|
56
80
|
```
|
|
57
81
|
|
|
58
82
|
## Project Structures
|
|
@@ -62,13 +86,12 @@ devstarter init my-app --no-vitest
|
|
|
62
86
|
```
|
|
63
87
|
my-app/
|
|
64
88
|
├── src/
|
|
65
|
-
│
|
|
66
|
-
│ └── __tests__/
|
|
67
|
-
│ └── example.test.ts
|
|
68
|
-
├── vitest.config.ts
|
|
89
|
+
│ └── main.ts
|
|
69
90
|
├── package.json
|
|
70
|
-
├──
|
|
71
|
-
|
|
91
|
+
├── tsconfig.json
|
|
92
|
+
├── vitest.config.ts # if --vitest
|
|
93
|
+
├── node_modules/
|
|
94
|
+
└── .git/ # if git initialized
|
|
72
95
|
```
|
|
73
96
|
|
|
74
97
|
### Monorepo (full-stack)
|
|
@@ -76,10 +99,16 @@ my-app/
|
|
|
76
99
|
```
|
|
77
100
|
my-app/
|
|
78
101
|
├── apps/
|
|
79
|
-
│ ├── web/
|
|
80
|
-
│
|
|
102
|
+
│ ├── web/ # frontend template
|
|
103
|
+
│ │ ├── src/
|
|
104
|
+
│ │ ├── package.json
|
|
105
|
+
│ │ └── vitest.config.ts
|
|
106
|
+
│ └── api/ # backend template
|
|
107
|
+
│ ├── src/
|
|
108
|
+
│ ├── package.json
|
|
109
|
+
│ └── vitest.config.ts
|
|
81
110
|
├── packages/
|
|
82
|
-
│ └── shared/
|
|
111
|
+
│ └── shared/ # shared code
|
|
83
112
|
├── package.json
|
|
84
113
|
├── pnpm-workspace.yaml
|
|
85
114
|
├── tsconfig.base.json
|
|
@@ -92,7 +121,7 @@ my-app/
|
|
|
92
121
|
|
|
93
122
|
| Template | Description |
|
|
94
123
|
|----------|-------------|
|
|
95
|
-
| `basic` |
|
|
124
|
+
| `basic` | Vite + TypeScript |
|
|
96
125
|
| `react` | React 18 + Vite + TypeScript |
|
|
97
126
|
|
|
98
127
|
### Backend
|
|
@@ -101,42 +130,29 @@ my-app/
|
|
|
101
130
|
|----------|-------------|
|
|
102
131
|
| `basic` | Express + TypeScript |
|
|
103
132
|
|
|
104
|
-
##
|
|
105
|
-
|
|
106
|
-
- Project structure selection (basic or monorepo)
|
|
107
|
-
- Automatic package manager detection (npm, pnpm, yarn)
|
|
108
|
-
- Interactive template selection
|
|
109
|
-
- Optional Git repository initialization
|
|
110
|
-
- Optional Vitest testing framework setup
|
|
111
|
-
- Dry-run mode to preview changes
|
|
112
|
-
- Automatic project name normalization (kebab-case)
|
|
113
|
-
- Colored output for better readability
|
|
114
|
-
|
|
115
|
-
## Testing Setup (Vitest)
|
|
133
|
+
## Vitest Integration
|
|
116
134
|
|
|
117
|
-
|
|
135
|
+
When using `--vitest`, the CLI adds:
|
|
118
136
|
|
|
119
137
|
- `vitest` as a dev dependency
|
|
120
|
-
- `vitest.config.ts` configuration
|
|
121
|
-
-
|
|
122
|
-
- `test` script in package.json
|
|
123
|
-
|
|
124
|
-
For React projects, it also adds `jsdom` for DOM testing.
|
|
125
|
-
|
|
126
|
-
To skip Vitest setup, use the `--no-vitest` flag:
|
|
138
|
+
- `vitest.config.ts` with basic configuration
|
|
139
|
+
- `test` and `test:run` scripts in package.json
|
|
127
140
|
|
|
128
141
|
```bash
|
|
129
|
-
|
|
130
|
-
|
|
142
|
+
# Create project with Vitest
|
|
143
|
+
devstarter init my-app --vitest
|
|
131
144
|
|
|
132
|
-
|
|
145
|
+
# Then run tests
|
|
146
|
+
cd my-app
|
|
147
|
+
npm test
|
|
148
|
+
```
|
|
133
149
|
|
|
134
|
-
|
|
150
|
+
## Requirements
|
|
135
151
|
|
|
136
152
|
- Node.js 18+
|
|
137
|
-
- npm, pnpm or yarn
|
|
153
|
+
- npm, pnpm, or yarn
|
|
138
154
|
|
|
139
|
-
|
|
155
|
+
## Development
|
|
140
156
|
|
|
141
157
|
```bash
|
|
142
158
|
# Clone repository
|
|
@@ -153,7 +169,7 @@ npm run build
|
|
|
153
169
|
node dist/cli.js init test-app --dry-run
|
|
154
170
|
```
|
|
155
171
|
|
|
156
|
-
###
|
|
172
|
+
### Scripts
|
|
157
173
|
|
|
158
174
|
| Script | Description |
|
|
159
175
|
|--------|-------------|
|
package/dist/cli.js
CHANGED
|
@@ -14,5 +14,6 @@ program
|
|
|
14
14
|
.option('--template <name>', 'Template variant (e.g. basic, react)')
|
|
15
15
|
.option('--dry-run', 'Show what would be generated without creating files')
|
|
16
16
|
.option('--no-git', 'Skip git repository initialization')
|
|
17
|
+
.option('--vitest', 'Add Vitest for testing')
|
|
17
18
|
.action(initCommand);
|
|
18
19
|
program.parse(process.argv);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_INIT_OPTIONS } from '../../types/project.js';
|
|
2
|
-
import { askProjectName, askProjectStructure, askInitQuestions, askTemplate, askInitGit, } from '../../prompts/initPrompts.js';
|
|
2
|
+
import { askProjectName, askProjectStructure, askInitQuestions, askTemplate, askInitGit, askUseVitest, } from '../../prompts/initPrompts.js';
|
|
3
3
|
import { normalizeProjectName } from '../../utils/normalize.js';
|
|
4
4
|
import { detectPackageManager } from '../../utils/detectPackageManager.js';
|
|
5
5
|
import { listTemplates } from '../../utils/listTemplate.js';
|
|
@@ -60,12 +60,25 @@ async function collectBasicContext(projectName, options, useDefaults) {
|
|
|
60
60
|
const templates = listTemplates(projectType);
|
|
61
61
|
const templateFromFlag = resolveTemplateFlag(options.template, templates);
|
|
62
62
|
const template = await collectTemplate(templateFromFlag, templates, useDefaults);
|
|
63
|
+
// Obtener useVitest
|
|
64
|
+
const vitestFlagProvided = options.vitest !== undefined;
|
|
65
|
+
let useVitest;
|
|
66
|
+
if (vitestFlagProvided) {
|
|
67
|
+
useVitest = options.vitest;
|
|
68
|
+
}
|
|
69
|
+
else if (useDefaults) {
|
|
70
|
+
useVitest = DEFAULT_INIT_OPTIONS.useVitest;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
useVitest = (await askUseVitest()).useVitest;
|
|
74
|
+
}
|
|
63
75
|
return {
|
|
64
76
|
structure: 'basic',
|
|
65
77
|
projectName,
|
|
66
78
|
projectType,
|
|
67
79
|
template,
|
|
68
80
|
initGit,
|
|
81
|
+
useVitest,
|
|
69
82
|
packageManager: detectPackageManager(),
|
|
70
83
|
isDryRun: Boolean(options.dryRun),
|
|
71
84
|
};
|
|
@@ -102,12 +115,25 @@ async function collectMonorepoContext(projectName, useDefaults, options) {
|
|
|
102
115
|
initGit = gitAnswer.initGit;
|
|
103
116
|
}
|
|
104
117
|
}
|
|
118
|
+
// Obtener useVitest
|
|
119
|
+
const vitestFlagProvided = options.vitest !== undefined;
|
|
120
|
+
let useVitest;
|
|
121
|
+
if (vitestFlagProvided) {
|
|
122
|
+
useVitest = options.vitest;
|
|
123
|
+
}
|
|
124
|
+
else if (useDefaults) {
|
|
125
|
+
useVitest = DEFAULT_INIT_OPTIONS.useVitest;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
useVitest = (await askUseVitest()).useVitest;
|
|
129
|
+
}
|
|
105
130
|
return {
|
|
106
131
|
structure: 'monorepo',
|
|
107
132
|
projectName,
|
|
108
133
|
webTemplate,
|
|
109
134
|
apiTemplate,
|
|
110
135
|
initGit,
|
|
136
|
+
useVitest,
|
|
111
137
|
packageManager: 'pnpm', // Monorepo usa pnpm por defecto
|
|
112
138
|
isDryRun: Boolean(options.dryRun),
|
|
113
139
|
};
|
|
@@ -3,7 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
import { getTemplatePath } from '../utils/getTemplatePath.js';
|
|
4
4
|
import { copyTemplate } from '../utils/copyTemplate.js';
|
|
5
5
|
import { initGitRepo } from '../utils/git.js';
|
|
6
|
-
|
|
6
|
+
import { setupVitest } from '../utils/setupVitest.js';
|
|
7
|
+
import { installDependencies } from '../utils/installDependencies.js';
|
|
8
|
+
export async function createMonorepo({ projectName, webTemplate, apiTemplate, initGit, useVitest, packageManager, }) {
|
|
7
9
|
// 1. Resolver ruta absoluta del proyecto
|
|
8
10
|
const projectRoot = path.resolve(process.cwd(), projectName);
|
|
9
11
|
// 2. Evitar sobrescribir carpetas existentes
|
|
@@ -32,7 +34,14 @@ export async function createMonorepo({ projectName, webTemplate, apiTemplate, in
|
|
|
32
34
|
}
|
|
33
35
|
// 7. Crear package shared básico
|
|
34
36
|
await createSharedPackage(projectRoot, projectName);
|
|
35
|
-
// 8.
|
|
37
|
+
// 8. Configurar Vitest en apps (si aplica)
|
|
38
|
+
if (useVitest) {
|
|
39
|
+
await setupVitest(path.join(projectRoot, 'apps', 'web'));
|
|
40
|
+
await setupVitest(path.join(projectRoot, 'apps', 'api'));
|
|
41
|
+
}
|
|
42
|
+
// 9. Instalar dependencias
|
|
43
|
+
installDependencies(projectRoot, packageManager);
|
|
44
|
+
// 10. Inicializar Git (si aplica)
|
|
36
45
|
if (initGit) {
|
|
37
46
|
initGitRepo(projectRoot);
|
|
38
47
|
}
|
|
@@ -3,7 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
import { getTemplatePath } from '../utils/getTemplatePath.js';
|
|
4
4
|
import { copyTemplate } from '../utils/copyTemplate.js';
|
|
5
5
|
import { initGitRepo } from '../utils/git.js';
|
|
6
|
-
|
|
6
|
+
import { setupVitest } from '../utils/setupVitest.js';
|
|
7
|
+
import { installDependencies } from '../utils/installDependencies.js';
|
|
8
|
+
export async function createProject({ projectName, projectType, template, initGit, useVitest, packageManager, }) {
|
|
7
9
|
// 1. Resolver ruta absoluta del proyecto
|
|
8
10
|
const projectRoot = path.resolve(process.cwd(), projectName);
|
|
9
11
|
// 2. Evitar sobrescribir carpetas existentes
|
|
@@ -21,7 +23,13 @@ export async function createProject({ projectName, projectType, template, initGi
|
|
|
21
23
|
await copyTemplate(templatePath, projectRoot, {
|
|
22
24
|
projectName,
|
|
23
25
|
});
|
|
24
|
-
// 6.
|
|
26
|
+
// 6. Configurar Vitest (si aplica)
|
|
27
|
+
if (useVitest) {
|
|
28
|
+
await setupVitest(projectRoot);
|
|
29
|
+
}
|
|
30
|
+
// 7. Instalar dependencias
|
|
31
|
+
installDependencies(projectRoot, packageManager);
|
|
32
|
+
// 8. Inicializar Git (si aplica)
|
|
25
33
|
if (initGit) {
|
|
26
34
|
initGitRepo(projectRoot);
|
|
27
35
|
}
|
|
@@ -80,3 +80,11 @@ export async function askInitGit() {
|
|
|
80
80
|
initial: true,
|
|
81
81
|
}, { onCancel });
|
|
82
82
|
}
|
|
83
|
+
export async function askUseVitest() {
|
|
84
|
+
return prompts({
|
|
85
|
+
type: 'confirm',
|
|
86
|
+
name: 'useVitest',
|
|
87
|
+
message: 'Add Vitest for testing?',
|
|
88
|
+
initial: false,
|
|
89
|
+
}, { onCancel });
|
|
90
|
+
}
|
package/dist/types/project.js
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
export function installDependencies(projectRoot, packageManager) {
|
|
3
|
+
const command = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;
|
|
4
|
+
execSync(command, {
|
|
5
|
+
cwd: projectRoot,
|
|
6
|
+
stdio: 'inherit',
|
|
7
|
+
});
|
|
8
|
+
}
|
|
@@ -14,7 +14,6 @@ export function printSummary(context) {
|
|
|
14
14
|
console.log(`${styles.info('- Git:')} ${context.initGit ? styles.success('initialized') : styles.muted('not initialized')}\n`);
|
|
15
15
|
console.log(styles.title('Next steps'));
|
|
16
16
|
console.log(` ${styles.highlight(`cd ${context.projectName}`)}`);
|
|
17
|
-
console.log(` ${styles.highlight(`${context.packageManager} install`)}`);
|
|
18
17
|
console.log(` ${styles.highlight(`${context.packageManager} run dev`)}`);
|
|
19
18
|
console.log('');
|
|
20
19
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const VITEST_CONFIG = `import { defineConfig } from 'vitest/config';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
test: {
|
|
7
|
+
globals: true,
|
|
8
|
+
environment: 'node',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
`;
|
|
12
|
+
export async function setupVitest(projectRoot) {
|
|
13
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
14
|
+
// Leer package.json existente
|
|
15
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
16
|
+
// Añadir devDependencies
|
|
17
|
+
packageJson.devDependencies = {
|
|
18
|
+
...packageJson.devDependencies,
|
|
19
|
+
vitest: '^3.0.0',
|
|
20
|
+
};
|
|
21
|
+
// Añadir scripts de test
|
|
22
|
+
packageJson.scripts = {
|
|
23
|
+
...packageJson.scripts,
|
|
24
|
+
test: 'vitest',
|
|
25
|
+
'test:run': 'vitest run',
|
|
26
|
+
};
|
|
27
|
+
// Escribir package.json actualizado
|
|
28
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
29
|
+
// Crear vitest.config.ts
|
|
30
|
+
await fs.writeFile(path.join(projectRoot, 'vitest.config.ts'), VITEST_CONFIG);
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devstarter-tool",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI to generate projects with best practices (basic or monorepo)",
|
|
6
6
|
"author": "abraham-diaz",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"backend",
|
|
23
23
|
"boilerplate",
|
|
24
24
|
"starter",
|
|
25
|
-
"devstarter"
|
|
25
|
+
"devstarter",
|
|
26
|
+
"vitest",
|
|
27
|
+
"testing"
|
|
26
28
|
],
|
|
27
29
|
"engines": {
|
|
28
30
|
"node": ">=18.0.0"
|