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 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
- ## Usage
27
+ ## Quick Start
28
+
29
+ ```bash
30
+ # Interactive mode - guided setup
31
+ devstarter init
18
32
 
19
- ### Basic command
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
- # Create frontend project without prompts
46
- devstarter init my-app --type frontend -y
69
+ # Frontend with React template
70
+ devstarter init my-app --type frontend --template react
47
71
 
48
- # Preview what files would be created
49
- devstarter init my-app --type frontend --dry-run
72
+ # Backend with testing setup
73
+ devstarter init my-api --type backend --vitest
50
74
 
51
- # Create project without git initialization
52
- devstarter init my-app --no-git
75
+ # Quick frontend with all defaults
76
+ devstarter init my-app --type frontend -y
53
77
 
54
- # Create project without Vitest setup
55
- devstarter init my-app --no-vitest
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
- ├── main.ts (or main.tsx for React)
66
- │ └── __tests__/
67
- │ └── example.test.ts
68
- ├── vitest.config.ts
89
+ └── main.ts
69
90
  ├── package.json
70
- ├── README.md
71
- └── .git/ (if git is initialized)
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/ <- frontend template
80
- └── api/ <- backend template
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/ <- shared code
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` | Minimal TypeScript with basic structure |
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
- ## Features
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
- By default, projects are created with Vitest configured. This includes:
135
+ When using `--vitest`, the CLI adds:
118
136
 
119
137
  - `vitest` as a dev dependency
120
- - `vitest.config.ts` configuration file
121
- - Example test file in `src/__tests__/example.test.ts`
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
- devstarter init my-app --no-vitest
130
- ```
142
+ # Create project with Vitest
143
+ devstarter init my-app --vitest
131
144
 
132
- ## Development
145
+ # Then run tests
146
+ cd my-app
147
+ npm test
148
+ ```
133
149
 
134
- ### Requirements
150
+ ## Requirements
135
151
 
136
152
  - Node.js 18+
137
- - npm, pnpm or yarn
153
+ - npm, pnpm, or yarn
138
154
 
139
- ### Setup
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
- ### Available Scripts
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
- export async function createMonorepo({ projectName, webTemplate, apiTemplate, initGit, }) {
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. Inicializar Git (si aplica)
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
- export async function createProject({ projectName, projectType, template, initGit, }) {
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. Inicializar Git (si aplica)
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
+ }
@@ -2,4 +2,5 @@ export const DEFAULT_INIT_OPTIONS = {
2
2
  projectStructure: 'basic',
3
3
  projectType: 'frontend',
4
4
  initGit: true,
5
+ useVitest: false,
5
6
  };
@@ -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.1",
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"