@rtorcato/js-tooling 1.0.6

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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/dist/cli/commands/setup.js +218 -0
  4. package/dist/cli/generators/build.js +90 -0
  5. package/dist/cli/generators/git.js +133 -0
  6. package/dist/cli/generators/github-actions.js +261 -0
  7. package/dist/cli/generators/index.js +53 -0
  8. package/dist/cli/generators/linting.js +43 -0
  9. package/dist/cli/generators/package-json.js +162 -0
  10. package/dist/cli/generators/readme.js +224 -0
  11. package/dist/cli/generators/testing.js +78 -0
  12. package/dist/cli/generators/tsconfig.js +28 -0
  13. package/dist/cli/index.js +53 -0
  14. package/dist/cli/utils/install.js +28 -0
  15. package/package.json +160 -0
  16. package/scripts/README.md +8 -0
  17. package/scripts/commitmessage.sh +44 -0
  18. package/scripts/helloworld.sh +5 -0
  19. package/tooling/biome/biome.jsonc +47 -0
  20. package/tooling/commitlint/commitlint.mjs +4 -0
  21. package/tooling/esbuild/build-sample.mjs +21 -0
  22. package/tooling/esbuild/index.mjs +102 -0
  23. package/tooling/eslint/README.md +3 -0
  24. package/tooling/eslint/base.mjs +122 -0
  25. package/tooling/eslint/nextjs.mjs +22 -0
  26. package/tooling/eslint/package.json +35 -0
  27. package/tooling/eslint/types.d.ts +58 -0
  28. package/tooling/jest-presets/browser/jest-preset.mjs +14 -0
  29. package/tooling/jest-presets/node/jest-preset.mjs +13 -0
  30. package/tooling/nextjs/next.config.js +4 -0
  31. package/tooling/oxc/.gitkeep +0 -0
  32. package/tooling/oxc/README.md +1 -0
  33. package/tooling/playwright/playwright.config.ts +0 -0
  34. package/tooling/prettier/index.mjs +36 -0
  35. package/tooling/rolldown/.gitkeep +0 -0
  36. package/tooling/rollup/.gitkeep +0 -0
  37. package/tooling/semantic-release/docker.mjs +59 -0
  38. package/tooling/semantic-release/github.mjs +74 -0
  39. package/tooling/semantic-release/index.mjs +75 -0
  40. package/tooling/tsdown/.gitkeep +0 -0
  41. package/tooling/tsup/index.ts +50 -0
  42. package/tooling/tsup/tsconfig.cjs.json +7 -0
  43. package/tooling/tsup/tsconfig.esm.json +9 -0
  44. package/tooling/tsup/tsconfig.json +11 -0
  45. package/tooling/tsup/tsconfig.types.json +9 -0
  46. package/tooling/typescript/README.md +52 -0
  47. package/tooling/typescript/reset.d.ts +9 -0
  48. package/tooling/typescript/tsconfig.base.json +78 -0
  49. package/tooling/typescript/tsconfig.build.json +11 -0
  50. package/tooling/typescript/tsconfig.express.json +9 -0
  51. package/tooling/typescript/tsconfig.next.json +19 -0
  52. package/tooling/typescript/tsconfig.node.json +9 -0
  53. package/tooling/typescript/tsconfig.react.json +14 -0
  54. package/tooling/typescript/tsconfig.test.json +8 -0
  55. package/tooling/vellite/.gitkeep +0 -0
  56. package/tooling/vite/.gitkeep +0 -0
  57. package/tooling/vitest/vitest.config.mjs +22 -0
  58. package/tooling/vitest/vitest.config.react.mjs +27 -0
  59. package/tooling/vitest/vitest.setup.mjs +3 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Richard Torcato
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,129 @@
1
+ # js-tooling
2
+
3
+ A comprehensive collection of JavaScript/TypeScript development tools and configurations for modern projects.
4
+
5
+ ## Installation
6
+
7
+ Install the package globally or use it directly with npx:
8
+
9
+ ```bash
10
+
11
+ # Or use with npx
12
+ npx @rtorcato/js-tooling setup
13
+ ```
14
+
15
+ ## Getting started
16
+
17
+ Use the interactive CLI to set up tooling for your project:
18
+
19
+ ```bash
20
+ npx @rtorcato/js-tooling setup
21
+ ```
22
+
23
+ Or import specific configurations:
24
+
25
+ ```javascript
26
+ import '@rtorcato/js-tooling/typescript/base';
27
+ ```
28
+
29
+ ## Available Tools
30
+
31
+ This package includes configurations and presets for:
32
+
33
+ - **TypeScript** - Base configurations for different project types
34
+ - **ESLint** - Linting rules for JavaScript and TypeScript
35
+ - **Prettier** - Code formatting configuration
36
+ - **Biome** - Fast linter and formatter
37
+ - **Vitest** - Testing framework configuration
38
+ - **Jest** - Testing framework presets
39
+ - **Commitlint** - Commit message linting
40
+ - **Semantic Release** - Automated versioning and publishing
41
+ - **GitHub Actions** - CI/CD workflow templates
42
+ - **And more...**
43
+
44
+ ## CI/CD Setup
45
+
46
+ The package includes GitHub Actions workflows and semantic-release configuration. For automated publishing, set these secrets in your GitHub repository:
47
+
48
+ 1. **`NPM_TOKEN`** - npm authentication token for publishing packages
49
+ 2. **`GITHUB_TOKEN`** - automatically provided by GitHub Actions
50
+
51
+ Repository settings: `https://github.com/your-username/your-repo/settings/secrets/actions`
52
+
53
+ ## CLI Commands
54
+
55
+ The package provides several CLI commands:
56
+
57
+ ```bash
58
+ # Interactive project setup wizard
59
+ npx @rtorcato/js-tooling setup
60
+
61
+ # Run commit message helper
62
+ npx @rtorcato/js-tooling commitmessage
63
+
64
+ # Hello world example
65
+ npx @rtorcato/js-tooling helloworld
66
+ ```
67
+
68
+ ## Using with Package Managers
69
+
70
+ ### With pnpm
71
+ ```bash
72
+ # Temporarily install and run
73
+ pnpm --package=@rtorcato/js-tooling dlx setup
74
+
75
+ # Or install globally
76
+ pnpm add -g @rtorcato/js-tooling
77
+ ```
78
+
79
+ ### With npm
80
+ ```bash
81
+ # Use directly
82
+ npx @rtorcato/js-tooling setup
83
+
84
+ # Or install globally
85
+ npm install -g @rtorcato/js-tooling
86
+ ```
87
+
88
+ ## Development
89
+
90
+ To work on this package locally:
91
+
92
+ 1. Clone the repository:
93
+ ```bash
94
+ git clone https://github.com/rtorcato/js-tooling.git
95
+ cd js-tooling
96
+ ```
97
+
98
+ 2. Install dependencies:
99
+ ```bash
100
+ pnpm install
101
+ ```
102
+
103
+ 3. Build the CLI:
104
+ ```bash
105
+ pnpm run build-cli
106
+ ```
107
+
108
+ 4. Link globally for testing:
109
+ ```bash
110
+ pnpm link --global
111
+ ```
112
+
113
+ For more details, refer to the [pnpm link documentation](https://pnpm.io/cli/link).
114
+
115
+ ## Status
116
+
117
+ [![CI](https://github.com/rtorcato/js-tooling/actions/workflows/ci.yml/badge.svg)](https://github.com/rtorcato/js-tooling/actions/workflows/ci.yml)
118
+ [![npm version](https://badge.fury.io/js/@rtorcato%2Fjs-tooling.svg)](https://badge.fury.io/js/@rtorcato%2Fjs-tooling)
119
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
120
+ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/rtorcato/js-tooling)](https://github.com/rtorcato/js-tooling/releases)
121
+ [![GitHub issues](https://img.shields.io/github/issues/rtorcato/js-tooling)](https://github.com/rtorcato/js-tooling/issues)
122
+
123
+ ## Contributing
124
+
125
+ Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) and feel free to submit issues and pull requests.
126
+
127
+ ## License
128
+
129
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,218 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'fs-extra';
3
+ import inquirer from 'inquirer';
4
+ import path from 'node:path';
5
+ import { generateConfigs } from '../generators/index.js';
6
+ import { installDependencies } from '../utils/install.js';
7
+ export async function setupProject(options) {
8
+ const targetDir = path.resolve(options.directory);
9
+ console.log(chalk.cyan('\n🛠️ Welcome to JS Tooling Setup!\n'));
10
+ console.log(chalk.gray(`Setting up tooling in: ${targetDir}\n`));
11
+ try {
12
+ // Check if directory exists and is writable
13
+ await fs.ensureDir(targetDir);
14
+ const config = await promptForConfig();
15
+ console.log(chalk.cyan('\n📝 Generating configuration files...\n'));
16
+ await generateConfigs(config, targetDir);
17
+ if (!options.skipInstall) {
18
+ console.log(chalk.cyan('\n📦 Installing dependencies...\n'));
19
+ await installDependencies(config, targetDir);
20
+ }
21
+ console.log(chalk.green('\n✅ Setup completed successfully!\n'));
22
+ // Show next steps
23
+ showNextSteps(config, targetDir);
24
+ }
25
+ catch (error) {
26
+ console.error(chalk.red('\n❌ Setup failed:'), error);
27
+ process.exit(1);
28
+ }
29
+ }
30
+ async function promptForConfig() {
31
+ const answers = await inquirer.prompt([
32
+ {
33
+ type: 'input',
34
+ name: 'projectName',
35
+ message: '📦 What is your project name?',
36
+ default: path.basename(process.cwd()),
37
+ validate: (input) => input.trim().length > 0 || 'Project name is required',
38
+ },
39
+ {
40
+ type: 'list',
41
+ name: 'projectType',
42
+ message: '🏗️ What type of project are you building?',
43
+ choices: [
44
+ { name: '📚 Library/Package', value: 'library' },
45
+ { name: '🌐 Web Application', value: 'web-app' },
46
+ { name: '🚀 Node.js API', value: 'node-api' },
47
+ { name: '⚡ Next.js App', value: 'nextjs-app' },
48
+ { name: '⚛️ React App', value: 'react-app' },
49
+ ],
50
+ },
51
+ {
52
+ type: 'confirm',
53
+ name: 'useTypeScript',
54
+ message: '📘 Do you want to use TypeScript?',
55
+ default: true,
56
+ },
57
+ {
58
+ type: 'list',
59
+ name: 'tsConfig',
60
+ message: '⚙️ Which TypeScript configuration?',
61
+ choices: (answers) => {
62
+ const baseChoices = [
63
+ { name: '🔧 Base (General purpose)', value: 'base' },
64
+ { name: '🖥️ Node.js', value: 'node' },
65
+ ];
66
+ if (answers.projectType === 'nextjs-app') {
67
+ return [{ name: '⚡ Next.js', value: 'next' }, ...baseChoices];
68
+ }
69
+ if (answers.projectType === 'react-app' || answers.projectType === 'web-app') {
70
+ return [{ name: '⚛️ React', value: 'react' }, ...baseChoices];
71
+ }
72
+ if (answers.projectType === 'node-api') {
73
+ return [
74
+ { name: '🚀 Express/API', value: 'express' },
75
+ { name: '🖥️ Node.js', value: 'node' },
76
+ ];
77
+ }
78
+ return baseChoices;
79
+ },
80
+ when: (answers) => answers.useTypeScript,
81
+ },
82
+ {
83
+ type: 'list',
84
+ name: 'lintingTool',
85
+ message: '🔍 Which linting/formatting tool?',
86
+ choices: [
87
+ { name: '⚡ Biome (Fast, all-in-one)', value: 'biome' },
88
+ { name: '🔧 ESLint (Configurable)', value: 'eslint' },
89
+ { name: '🔥 Both Biome + ESLint', value: 'both' },
90
+ { name: '❌ None', value: 'none' },
91
+ ],
92
+ default: 'biome',
93
+ },
94
+ {
95
+ type: 'list',
96
+ name: 'eslintConfig',
97
+ message: '🔧 Which ESLint configuration?',
98
+ choices: (answers) => {
99
+ const choices = [{ name: '🔧 Base configuration', value: 'base' }];
100
+ if (answers.projectType === 'nextjs-app') {
101
+ choices.unshift({ name: '⚡ Next.js configuration', value: 'nextjs' });
102
+ }
103
+ return choices;
104
+ },
105
+ when: (answers) => answers.lintingTool === 'eslint' || answers.lintingTool === 'both',
106
+ },
107
+ {
108
+ type: 'list',
109
+ name: 'testingFramework',
110
+ message: '🧪 Which testing framework?',
111
+ choices: [
112
+ { name: '⚡ Vitest (Fast, Vite-powered)', value: 'vitest' },
113
+ { name: '🃏 Jest (Traditional)', value: 'jest' },
114
+ { name: '🎭 Playwright (E2E)', value: 'playwright' },
115
+ { name: '❌ None', value: 'none' },
116
+ ],
117
+ default: 'vitest',
118
+ },
119
+ {
120
+ type: 'list',
121
+ name: 'testEnvironment',
122
+ message: '🌍 Test environment?',
123
+ choices: [
124
+ { name: '🖥️ Node.js', value: 'node' },
125
+ { name: '🌐 Browser (DOM)', value: 'browser' },
126
+ { name: '🔄 Both', value: 'both' },
127
+ ],
128
+ when: (answers) => answers.testingFramework === 'jest',
129
+ default: 'node',
130
+ },
131
+ {
132
+ type: 'confirm',
133
+ name: 'gitHooks',
134
+ message: '🪝 Set up Git hooks (Husky + lint-staged)?',
135
+ default: true,
136
+ },
137
+ {
138
+ type: 'confirm',
139
+ name: 'commitLint',
140
+ message: '📝 Set up conventional commit linting?',
141
+ default: true,
142
+ when: (answers) => answers.gitHooks,
143
+ },
144
+ {
145
+ type: 'confirm',
146
+ name: 'semanticRelease',
147
+ message: '🚀 Set up semantic release for automated versioning?',
148
+ default: (answers) => answers.projectType === 'library',
149
+ when: (answers) => answers.projectType === 'library',
150
+ },
151
+ {
152
+ type: 'list',
153
+ name: 'bundler',
154
+ message: '📦 Which bundler/build tool?',
155
+ choices: (answers) => {
156
+ const choices = [
157
+ { name: '📦 tsup (TypeScript packages)', value: 'tsup' },
158
+ { name: '⚡ esbuild (Fast bundling)', value: 'esbuild' },
159
+ { name: '❌ None', value: 'none' },
160
+ ];
161
+ if (answers.projectType === 'web-app' || answers.projectType === 'react-app') {
162
+ choices.unshift({ name: '⚡ Vite (Modern web apps)', value: 'vite' });
163
+ }
164
+ return choices;
165
+ },
166
+ when: (answers) => answers.projectType !== 'nextjs-app', // Next.js has its own bundler
167
+ },
168
+ ]);
169
+ return {
170
+ projectName: answers.projectName,
171
+ projectType: answers.projectType,
172
+ typescript: {
173
+ enabled: answers.useTypeScript || false,
174
+ config: answers.tsConfig || 'base',
175
+ },
176
+ linting: {
177
+ tool: answers.lintingTool || 'none',
178
+ eslintConfig: answers.eslintConfig,
179
+ },
180
+ formatting: {
181
+ tool: answers.lintingTool === 'biome' || answers.lintingTool === 'both'
182
+ ? 'biome'
183
+ : answers.lintingTool === 'eslint'
184
+ ? 'prettier'
185
+ : 'none',
186
+ },
187
+ testing: {
188
+ framework: answers.testingFramework || 'none',
189
+ environment: answers.testEnvironment,
190
+ },
191
+ gitHooks: answers.gitHooks || false,
192
+ commitLint: answers.commitLint || false,
193
+ semanticRelease: answers.semanticRelease || false,
194
+ bundler: answers.bundler || 'none',
195
+ };
196
+ }
197
+ function showNextSteps(config, _targetDir) {
198
+ console.log(chalk.bold('\n📋 Next Steps:\n'));
199
+ const steps = [];
200
+ if (config.typescript.enabled) {
201
+ steps.push('🔧 Customize your tsconfig.json as needed');
202
+ }
203
+ if (config.linting.tool !== 'none') {
204
+ steps.push(`🔍 Run linting with: ${config.linting.tool === 'biome' ? 'pnpm biome check .' : 'pnpm eslint .'}`);
205
+ }
206
+ if (config.testing.framework !== 'none') {
207
+ steps.push(`🧪 Run tests with: pnpm ${config.testing.framework}`);
208
+ }
209
+ if (config.gitHooks) {
210
+ steps.push('🪝 Commit your changes to test the git hooks');
211
+ }
212
+ steps.push('📖 Check the generated README.md for more details');
213
+ steps.forEach((step, index) => {
214
+ console.log(` ${index + 1}. ${step}`);
215
+ });
216
+ console.log(chalk.dim('\n💡 All configuration files have been generated in your project directory.'));
217
+ console.log(chalk.dim(' You can modify them to suit your specific needs.\n'));
218
+ }
@@ -0,0 +1,90 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ export async function generateBuildConfigs(config, targetDir) {
4
+ if (config.bundler === 'tsup') {
5
+ await generateTsupConfig(targetDir);
6
+ }
7
+ else if (config.bundler === 'esbuild') {
8
+ await generateEsbuildConfig(targetDir);
9
+ }
10
+ else if (config.bundler === 'vite') {
11
+ await generateViteConfig(config, targetDir);
12
+ }
13
+ // Generate semantic-release config for GitHub
14
+ if (config.semanticRelease) {
15
+ await generateSemanticReleaseConfig(targetDir);
16
+ }
17
+ }
18
+ async function generateTsupConfig(targetDir) {
19
+ const tsupConfigPath = path.join(targetDir, 'tsup.config.ts');
20
+ const tsupConfig = `import { getConfig } from '@rtorcato/js-tooling/tsup'
21
+
22
+ export default getConfig({
23
+ entry: ['src/index.ts'],
24
+ format: ['cjs', 'esm'],
25
+ dts: true,
26
+ clean: true,
27
+ splitting: false,
28
+ sourcemap: true,
29
+ }, process.env.NODE_ENV || 'development')
30
+ `;
31
+ await fs.writeFile(tsupConfigPath, tsupConfig);
32
+ }
33
+ async function generateEsbuildConfig(targetDir) {
34
+ const esbuildConfigPath = path.join(targetDir, 'build.mjs');
35
+ const esbuildConfig = `import { build } from 'esbuild'
36
+ import { nodeExternalsPlugin } from 'esbuild-node-externals'
37
+
38
+ const isProduction = process.env.NODE_ENV === 'production'
39
+
40
+ await build({
41
+ entryPoints: ['src/index.ts'],
42
+ bundle: true,
43
+ outdir: 'dist',
44
+ format: 'esm',
45
+ target: 'node18',
46
+ platform: 'node',
47
+ minify: isProduction,
48
+ sourcemap: !isProduction,
49
+ plugins: [nodeExternalsPlugin()],
50
+ })
51
+
52
+ console.log('Build completed!')
53
+ `;
54
+ await fs.writeFile(esbuildConfigPath, esbuildConfig);
55
+ }
56
+ async function generateViteConfig(config, targetDir) {
57
+ const viteConfigPath = path.join(targetDir, 'vite.config.ts');
58
+ let viteConfig = `import { defineConfig } from 'vite'
59
+ `;
60
+ if (config.projectType === 'react-app') {
61
+ viteConfig += `import react from '@vitejs/plugin-react'
62
+ `;
63
+ }
64
+ viteConfig += `
65
+ export default defineConfig({
66
+ plugins: [${config.projectType === 'react-app' ? 'react()' : ''}],
67
+ resolve: {
68
+ alias: {
69
+ '@': '/src',
70
+ '~': '/src'
71
+ }
72
+ },
73
+ build: {
74
+ outDir: 'dist',
75
+ sourcemap: true,
76
+ },
77
+ server: {
78
+ port: 3000,
79
+ open: true
80
+ }
81
+ })
82
+ `;
83
+ await fs.writeFile(viteConfigPath, viteConfig);
84
+ }
85
+ async function generateSemanticReleaseConfig(targetDir) {
86
+ const releaseConfigPath = path.join(targetDir, 'release.config.mjs');
87
+ const releaseConfig = `export { default } from '@rtorcato/js-tooling/semantic-release/github'
88
+ `;
89
+ await fs.writeFile(releaseConfigPath, releaseConfig);
90
+ }
@@ -0,0 +1,133 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ export async function generateGitConfigs(config, targetDir) {
4
+ if (config.gitHooks) {
5
+ await generateHuskyConfig(config, targetDir);
6
+ }
7
+ if (config.commitLint) {
8
+ await generateCommitlintConfig(targetDir);
9
+ }
10
+ // Generate .gitignore
11
+ await generateGitignore(config, targetDir);
12
+ }
13
+ async function generateHuskyConfig(config, targetDir) {
14
+ const huskyDir = path.join(targetDir, '.husky');
15
+ await fs.ensureDir(huskyDir);
16
+ // Pre-commit hook
17
+ const preCommitPath = path.join(huskyDir, 'pre-commit');
18
+ const preCommitContent = `#!/usr/bin/env sh
19
+ . "$(dirname -- "$0")/_/husky.sh"
20
+
21
+ npx lint-staged
22
+ `;
23
+ await fs.writeFile(preCommitPath, preCommitContent);
24
+ await fs.chmod(preCommitPath, 0o755);
25
+ // Commit-msg hook (if commitlint is enabled)
26
+ if (config.commitLint) {
27
+ const commitMsgPath = path.join(huskyDir, 'commit-msg');
28
+ const commitMsgContent = `#!/usr/bin/env sh
29
+ . "$(dirname -- "$0")/_/husky.sh"
30
+
31
+ npx --no -- commitlint --edit $1
32
+ `;
33
+ await fs.writeFile(commitMsgPath, commitMsgContent);
34
+ await fs.chmod(commitMsgPath, 0o755);
35
+ }
36
+ // lint-staged configuration in package.json
37
+ const packageJsonPath = path.join(targetDir, 'package.json');
38
+ const packageJson = await fs.readJson(packageJsonPath);
39
+ packageJson['lint-staged'] = {
40
+ '*.{js,ts,jsx,tsx}': [
41
+ config.linting.tool === 'biome' || config.linting.tool === 'both'
42
+ ? 'biome check --fix'
43
+ : 'eslint --fix',
44
+ 'git add',
45
+ ],
46
+ '*.{json,md,yml,yaml}': [
47
+ config.linting.tool === 'biome' || config.linting.tool === 'both'
48
+ ? 'biome format --write'
49
+ : 'prettier --write',
50
+ 'git add',
51
+ ],
52
+ };
53
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
54
+ }
55
+ async function generateCommitlintConfig(targetDir) {
56
+ const commitlintConfigPath = path.join(targetDir, 'commitlint.config.mjs');
57
+ const commitlintConfig = `export { default } from '@rtorcato/js-tooling/commitlint/config'
58
+ `;
59
+ await fs.writeFile(commitlintConfigPath, commitlintConfig);
60
+ }
61
+ async function generateGitignore(config, targetDir) {
62
+ const gitignorePath = path.join(targetDir, '.gitignore');
63
+ let gitignoreContent = `# Dependencies
64
+ node_modules/
65
+ .pnpm-store
66
+
67
+ # Build outputs
68
+ dist/
69
+ build/
70
+ out/
71
+
72
+ # Environment files
73
+ .env
74
+ .env.local
75
+ .env.development.local
76
+ .env.test.local
77
+ .env.production.local
78
+
79
+ # IDE
80
+ .vscode/
81
+ .idea/
82
+ *.swp
83
+ *.swo
84
+
85
+ # OS
86
+ .DS_Store
87
+ Thumbs.db
88
+
89
+ # Logs
90
+ logs
91
+ *.log
92
+ npm-debug.log*
93
+ yarn-debug.log*
94
+ yarn-error.log*
95
+ pnpm-debug.log*
96
+
97
+ # Runtime data
98
+ pids
99
+ *.pid
100
+ *.seed
101
+ *.pid.lock
102
+
103
+ # Coverage directory used by tools like istanbul
104
+ coverage/
105
+ *.lcov
106
+
107
+ # TypeScript
108
+ *.tsbuildinfo
109
+ `;
110
+ // Add framework-specific ignores
111
+ if (config.projectType === 'nextjs-app') {
112
+ gitignoreContent += `
113
+ # Next.js
114
+ .next/
115
+ .vercel
116
+ `;
117
+ }
118
+ if (config.bundler === 'vite') {
119
+ gitignoreContent += `
120
+ # Vite
121
+ .vite/
122
+ `;
123
+ }
124
+ if (config.testing.framework === 'playwright') {
125
+ gitignoreContent += `
126
+ # Playwright
127
+ /test-results/
128
+ /playwright-report/
129
+ /playwright/.cache/
130
+ `;
131
+ }
132
+ await fs.writeFile(gitignorePath, gitignoreContent);
133
+ }