@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.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/cli/commands/setup.js +218 -0
- package/dist/cli/generators/build.js +90 -0
- package/dist/cli/generators/git.js +133 -0
- package/dist/cli/generators/github-actions.js +261 -0
- package/dist/cli/generators/index.js +53 -0
- package/dist/cli/generators/linting.js +43 -0
- package/dist/cli/generators/package-json.js +162 -0
- package/dist/cli/generators/readme.js +224 -0
- package/dist/cli/generators/testing.js +78 -0
- package/dist/cli/generators/tsconfig.js +28 -0
- package/dist/cli/index.js +53 -0
- package/dist/cli/utils/install.js +28 -0
- package/package.json +160 -0
- package/scripts/README.md +8 -0
- package/scripts/commitmessage.sh +44 -0
- package/scripts/helloworld.sh +5 -0
- package/tooling/biome/biome.jsonc +47 -0
- package/tooling/commitlint/commitlint.mjs +4 -0
- package/tooling/esbuild/build-sample.mjs +21 -0
- package/tooling/esbuild/index.mjs +102 -0
- package/tooling/eslint/README.md +3 -0
- package/tooling/eslint/base.mjs +122 -0
- package/tooling/eslint/nextjs.mjs +22 -0
- package/tooling/eslint/package.json +35 -0
- package/tooling/eslint/types.d.ts +58 -0
- package/tooling/jest-presets/browser/jest-preset.mjs +14 -0
- package/tooling/jest-presets/node/jest-preset.mjs +13 -0
- package/tooling/nextjs/next.config.js +4 -0
- package/tooling/oxc/.gitkeep +0 -0
- package/tooling/oxc/README.md +1 -0
- package/tooling/playwright/playwright.config.ts +0 -0
- package/tooling/prettier/index.mjs +36 -0
- package/tooling/rolldown/.gitkeep +0 -0
- package/tooling/rollup/.gitkeep +0 -0
- package/tooling/semantic-release/docker.mjs +59 -0
- package/tooling/semantic-release/github.mjs +74 -0
- package/tooling/semantic-release/index.mjs +75 -0
- package/tooling/tsdown/.gitkeep +0 -0
- package/tooling/tsup/index.ts +50 -0
- package/tooling/tsup/tsconfig.cjs.json +7 -0
- package/tooling/tsup/tsconfig.esm.json +9 -0
- package/tooling/tsup/tsconfig.json +11 -0
- package/tooling/tsup/tsconfig.types.json +9 -0
- package/tooling/typescript/README.md +52 -0
- package/tooling/typescript/reset.d.ts +9 -0
- package/tooling/typescript/tsconfig.base.json +78 -0
- package/tooling/typescript/tsconfig.build.json +11 -0
- package/tooling/typescript/tsconfig.express.json +9 -0
- package/tooling/typescript/tsconfig.next.json +19 -0
- package/tooling/typescript/tsconfig.node.json +9 -0
- package/tooling/typescript/tsconfig.react.json +14 -0
- package/tooling/typescript/tsconfig.test.json +8 -0
- package/tooling/vellite/.gitkeep +0 -0
- package/tooling/vite/.gitkeep +0 -0
- package/tooling/vitest/vitest.config.mjs +22 -0
- package/tooling/vitest/vitest.config.react.mjs +27 -0
- package/tooling/vitest/vitest.setup.mjs +3 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export async function generateReadme(config, targetDir) {
|
|
4
|
+
const readmePath = path.join(targetDir, 'README.md');
|
|
5
|
+
const readme = `# ${config.projectName}
|
|
6
|
+
|
|
7
|
+
> Generated with [@rtorcato/js-tooling](https://www.npmjs.com/package/@rtorcato/js-tooling)
|
|
8
|
+
|
|
9
|
+
## Description
|
|
10
|
+
|
|
11
|
+
Your project description here.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
\`\`\`bash
|
|
16
|
+
# Using pnpm (recommended)
|
|
17
|
+
pnpm install
|
|
18
|
+
|
|
19
|
+
# Using npm
|
|
20
|
+
npm install
|
|
21
|
+
|
|
22
|
+
# Using yarn
|
|
23
|
+
yarn install
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
## Development
|
|
27
|
+
|
|
28
|
+
${generateDevelopmentSection(config)}
|
|
29
|
+
|
|
30
|
+
## Testing
|
|
31
|
+
|
|
32
|
+
${generateTestingSection(config)}
|
|
33
|
+
|
|
34
|
+
## Building
|
|
35
|
+
|
|
36
|
+
${generateBuildingSection(config)}
|
|
37
|
+
|
|
38
|
+
## Scripts
|
|
39
|
+
|
|
40
|
+
${generateScriptsSection(config)}
|
|
41
|
+
|
|
42
|
+
## Project Structure
|
|
43
|
+
|
|
44
|
+
\`\`\`
|
|
45
|
+
${config.projectName}/
|
|
46
|
+
├── src/ # Source code
|
|
47
|
+
${config.typescript.enabled ? '├── reset.d.ts # TypeScript reset types' : ''}
|
|
48
|
+
${config.testing.framework !== 'none' ? '├── tests/ # Test files' : ''}
|
|
49
|
+
├── dist/ # Build output${config.projectType === 'library' ? ' (library)' : ''}
|
|
50
|
+
├── package.json
|
|
51
|
+
${config.typescript.enabled ? '├── tsconfig.json # TypeScript configuration' : ''}
|
|
52
|
+
${config.linting.tool === 'biome' || config.linting.tool === 'both' ? '├── biome.jsonc # Biome configuration' : ''}
|
|
53
|
+
${config.linting.tool === 'eslint' || config.linting.tool === 'both' ? '├── eslint.config.mjs # ESLint configuration' : ''}
|
|
54
|
+
${config.linting.tool === 'eslint' ? '├── prettier.config.mjs # Prettier configuration' : ''}
|
|
55
|
+
${config.testing.framework === 'vitest' ? '├── vitest.config.ts # Vitest configuration' : ''}
|
|
56
|
+
${config.testing.framework === 'jest' ? '├── jest.config.mjs # Jest configuration' : ''}
|
|
57
|
+
${config.testing.framework === 'playwright' ? '├── playwright.config.ts # Playwright configuration' : ''}
|
|
58
|
+
${config.bundler === 'tsup' ? '├── tsup.config.ts # tsup configuration' : ''}
|
|
59
|
+
${config.bundler === 'esbuild' ? '├── build.mjs # esbuild configuration' : ''}
|
|
60
|
+
${config.bundler === 'vite' ? '├── vite.config.ts # Vite configuration' : ''}
|
|
61
|
+
${config.commitLint ? '├── commitlint.config.mjs # Commitlint configuration' : ''}
|
|
62
|
+
${config.gitHooks ? '├── .husky/ # Git hooks' : ''}
|
|
63
|
+
└── README.md
|
|
64
|
+
\`\`\`
|
|
65
|
+
|
|
66
|
+
## Tooling
|
|
67
|
+
|
|
68
|
+
This project uses:
|
|
69
|
+
|
|
70
|
+
${generateToolingList(config)}
|
|
71
|
+
|
|
72
|
+
## Contributing
|
|
73
|
+
|
|
74
|
+
1. Fork the repository
|
|
75
|
+
2. Create your feature branch (\`git checkout -b feature/amazing-feature\`)
|
|
76
|
+
3. Commit your changes (\`git commit -m 'feat: add amazing feature'\`)
|
|
77
|
+
4. Push to the branch (\`git push origin feature/amazing-feature\`)
|
|
78
|
+
5. Open a Pull Request
|
|
79
|
+
|
|
80
|
+
${config.commitLint
|
|
81
|
+
? `
|
|
82
|
+
### Commit Convention
|
|
83
|
+
|
|
84
|
+
This project follows [Conventional Commits](https://conventionalcommits.org/):
|
|
85
|
+
|
|
86
|
+
- \`feat:\` new features
|
|
87
|
+
- \`fix:\` bug fixes
|
|
88
|
+
- \`docs:\` documentation changes
|
|
89
|
+
- \`style:\` formatting changes
|
|
90
|
+
- \`refactor:\` code refactoring
|
|
91
|
+
- \`test:\` adding or updating tests
|
|
92
|
+
- \`chore:\` maintenance tasks
|
|
93
|
+
`
|
|
94
|
+
: ''}
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
[Add your license here]
|
|
99
|
+
`;
|
|
100
|
+
await fs.writeFile(readmePath, readme);
|
|
101
|
+
}
|
|
102
|
+
function generateDevelopmentSection(config) {
|
|
103
|
+
const sections = [];
|
|
104
|
+
if (config.bundler === 'vite') {
|
|
105
|
+
sections.push('```bash\npnpm dev\n```');
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
sections.push('Start development by running your preferred development server.');
|
|
109
|
+
}
|
|
110
|
+
if (config.linting.tool !== 'none') {
|
|
111
|
+
const lintCommand = config.linting.tool === 'biome' || config.linting.tool === 'both'
|
|
112
|
+
? 'pnpm check:fix'
|
|
113
|
+
: 'pnpm lint:fix';
|
|
114
|
+
sections.push(`\n### Linting & Formatting\n\n\`\`\`bash\n${lintCommand}\n\`\`\``);
|
|
115
|
+
}
|
|
116
|
+
if (config.typescript.enabled) {
|
|
117
|
+
sections.push('\n### Type Checking\n\n```bash\npnpm typecheck\n```');
|
|
118
|
+
}
|
|
119
|
+
return sections.length > 0 ? sections.join('\n') : 'No specific development commands configured.';
|
|
120
|
+
}
|
|
121
|
+
function generateTestingSection(config) {
|
|
122
|
+
if (config.testing.framework === 'none') {
|
|
123
|
+
return 'No testing framework configured.';
|
|
124
|
+
}
|
|
125
|
+
const commands = [];
|
|
126
|
+
if (config.testing.framework === 'vitest') {
|
|
127
|
+
commands.push('pnpm test # Run tests');
|
|
128
|
+
commands.push('pnpm test:watch # Run tests in watch mode');
|
|
129
|
+
commands.push('pnpm test:ui # Run tests with UI');
|
|
130
|
+
commands.push('pnpm coverage # Generate coverage report');
|
|
131
|
+
}
|
|
132
|
+
else if (config.testing.framework === 'jest') {
|
|
133
|
+
commands.push('pnpm test # Run tests');
|
|
134
|
+
commands.push('pnpm test:watch # Run tests in watch mode');
|
|
135
|
+
commands.push('pnpm coverage # Generate coverage report');
|
|
136
|
+
}
|
|
137
|
+
else if (config.testing.framework === 'playwright') {
|
|
138
|
+
commands.push('pnpm test:e2e # Run E2E tests');
|
|
139
|
+
commands.push('pnpm test:e2e:ui # Run E2E tests with UI');
|
|
140
|
+
}
|
|
141
|
+
return `\`\`\`bash\n${commands.join('\n')}\n\`\`\``;
|
|
142
|
+
}
|
|
143
|
+
function generateBuildingSection(config) {
|
|
144
|
+
if (config.bundler === 'none') {
|
|
145
|
+
return 'No build configuration set up.';
|
|
146
|
+
}
|
|
147
|
+
return '```bash\npnpm build\n```';
|
|
148
|
+
}
|
|
149
|
+
function generateScriptsSection(config) {
|
|
150
|
+
const scripts = [];
|
|
151
|
+
scripts.push('- `pnpm install` - Install dependencies');
|
|
152
|
+
if (config.typescript.enabled) {
|
|
153
|
+
scripts.push('- `pnpm typecheck` - Type check TypeScript');
|
|
154
|
+
}
|
|
155
|
+
if (config.linting.tool !== 'none') {
|
|
156
|
+
if (config.linting.tool === 'biome' || config.linting.tool === 'both') {
|
|
157
|
+
scripts.push('- `pnpm lint` - Lint code with Biome');
|
|
158
|
+
scripts.push('- `pnpm format` - Format code with Biome');
|
|
159
|
+
scripts.push('- `pnpm check:fix` - Lint and format with Biome');
|
|
160
|
+
}
|
|
161
|
+
if (config.linting.tool === 'eslint' || config.linting.tool === 'both') {
|
|
162
|
+
scripts.push('- `pnpm lint` - Lint code with ESLint');
|
|
163
|
+
scripts.push('- `pnpm lint:fix` - Fix ESLint issues');
|
|
164
|
+
scripts.push('- `pnpm format` - Format code with Prettier');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (config.testing.framework !== 'none') {
|
|
168
|
+
scripts.push('- `pnpm test` - Run tests');
|
|
169
|
+
if (config.testing.framework === 'vitest') {
|
|
170
|
+
scripts.push('- `pnpm test:watch` - Run tests in watch mode');
|
|
171
|
+
scripts.push('- `pnpm coverage` - Generate test coverage');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (config.bundler !== 'none') {
|
|
175
|
+
scripts.push('- `pnpm build` - Build for production');
|
|
176
|
+
}
|
|
177
|
+
return scripts.join('\n');
|
|
178
|
+
}
|
|
179
|
+
function generateToolingList(config) {
|
|
180
|
+
const tools = [];
|
|
181
|
+
if (config.typescript.enabled) {
|
|
182
|
+
tools.push('- **TypeScript** - Type-safe JavaScript');
|
|
183
|
+
}
|
|
184
|
+
if (config.linting.tool === 'biome') {
|
|
185
|
+
tools.push('- **Biome** - Fast formatter and linter');
|
|
186
|
+
}
|
|
187
|
+
else if (config.linting.tool === 'eslint') {
|
|
188
|
+
tools.push('- **ESLint** - Linting utility');
|
|
189
|
+
tools.push('- **Prettier** - Code formatter');
|
|
190
|
+
}
|
|
191
|
+
else if (config.linting.tool === 'both') {
|
|
192
|
+
tools.push('- **Biome** - Fast formatter and linter');
|
|
193
|
+
tools.push('- **ESLint** - Additional linting rules');
|
|
194
|
+
}
|
|
195
|
+
if (config.testing.framework === 'vitest') {
|
|
196
|
+
tools.push('- **Vitest** - Fast testing framework');
|
|
197
|
+
}
|
|
198
|
+
else if (config.testing.framework === 'jest') {
|
|
199
|
+
tools.push('- **Jest** - Testing framework');
|
|
200
|
+
}
|
|
201
|
+
else if (config.testing.framework === 'playwright') {
|
|
202
|
+
tools.push('- **Playwright** - End-to-end testing');
|
|
203
|
+
}
|
|
204
|
+
if (config.bundler === 'tsup') {
|
|
205
|
+
tools.push('- **tsup** - TypeScript bundler');
|
|
206
|
+
}
|
|
207
|
+
else if (config.bundler === 'esbuild') {
|
|
208
|
+
tools.push('- **esbuild** - Fast JavaScript bundler');
|
|
209
|
+
}
|
|
210
|
+
else if (config.bundler === 'vite') {
|
|
211
|
+
tools.push('- **Vite** - Fast build tool');
|
|
212
|
+
}
|
|
213
|
+
if (config.gitHooks) {
|
|
214
|
+
tools.push('- **Husky** - Git hooks');
|
|
215
|
+
tools.push('- **lint-staged** - Run linters on staged files');
|
|
216
|
+
}
|
|
217
|
+
if (config.commitLint) {
|
|
218
|
+
tools.push('- **Commitlint** - Conventional commit linting');
|
|
219
|
+
}
|
|
220
|
+
if (config.semanticRelease) {
|
|
221
|
+
tools.push('- **Semantic Release** - Automated versioning and publishing');
|
|
222
|
+
}
|
|
223
|
+
return tools.join('\n');
|
|
224
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export async function generateTestingConfigs(config, targetDir) {
|
|
4
|
+
if (config.testing.framework === 'vitest') {
|
|
5
|
+
await generateVitestConfig(config, targetDir);
|
|
6
|
+
}
|
|
7
|
+
else if (config.testing.framework === 'jest') {
|
|
8
|
+
await generateJestConfig(config, targetDir);
|
|
9
|
+
}
|
|
10
|
+
else if (config.testing.framework === 'playwright') {
|
|
11
|
+
await generatePlaywrightConfig(targetDir);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function generateVitestConfig(config, targetDir) {
|
|
15
|
+
const vitestConfigPath = path.join(targetDir, 'vitest.config.ts');
|
|
16
|
+
const vitestConfig = `import { defineConfig } from 'vitest/config'
|
|
17
|
+
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
test: {
|
|
20
|
+
globals: true,
|
|
21
|
+
environment: '${config.testing.environment === 'browser' ? 'jsdom' : 'node'}',
|
|
22
|
+
setupFiles: ['./vitest.setup.ts']
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
`;
|
|
26
|
+
await fs.writeFile(vitestConfigPath, vitestConfig);
|
|
27
|
+
// Create setup file
|
|
28
|
+
const setupPath = path.join(targetDir, 'vitest.setup.ts');
|
|
29
|
+
const setupContent = `// Vitest setup file
|
|
30
|
+
// Add global test setup here
|
|
31
|
+
`;
|
|
32
|
+
await fs.writeFile(setupPath, setupContent);
|
|
33
|
+
}
|
|
34
|
+
async function generateJestConfig(config, targetDir) {
|
|
35
|
+
const jestConfigPath = path.join(targetDir, 'jest.config.mjs');
|
|
36
|
+
const environment = config.testing.environment === 'browser' ? 'browser' : 'node';
|
|
37
|
+
const jestConfig = `export { default } from '@rtorcato/js-tooling/jest-presets/${environment}/jest-preset'
|
|
38
|
+
`;
|
|
39
|
+
await fs.writeFile(jestConfigPath, jestConfig);
|
|
40
|
+
}
|
|
41
|
+
async function generatePlaywrightConfig(targetDir) {
|
|
42
|
+
const playwrightConfigPath = path.join(targetDir, 'playwright.config.ts');
|
|
43
|
+
const playwrightConfig = `import { defineConfig } from '@playwright/test'
|
|
44
|
+
|
|
45
|
+
export default defineConfig({
|
|
46
|
+
testDir: './tests/e2e',
|
|
47
|
+
fullyParallel: true,
|
|
48
|
+
forbidOnly: !!process.env.CI,
|
|
49
|
+
retries: process.env.CI ? 2 : 0,
|
|
50
|
+
workers: process.env.CI ? 1 : undefined,
|
|
51
|
+
reporter: 'html',
|
|
52
|
+
use: {
|
|
53
|
+
baseURL: 'http://localhost:3000',
|
|
54
|
+
trace: 'on-first-retry',
|
|
55
|
+
},
|
|
56
|
+
projects: [
|
|
57
|
+
{
|
|
58
|
+
name: 'chromium',
|
|
59
|
+
use: { ...devices['Desktop Chrome'] },
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'firefox',
|
|
63
|
+
use: { ...devices['Desktop Firefox'] },
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'webkit',
|
|
67
|
+
use: { ...devices['Desktop Safari'] },
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
webServer: {
|
|
71
|
+
command: 'npm run dev',
|
|
72
|
+
url: 'http://localhost:3000',
|
|
73
|
+
reuseExistingServer: !process.env.CI,
|
|
74
|
+
},
|
|
75
|
+
})
|
|
76
|
+
`;
|
|
77
|
+
await fs.writeFile(playwrightConfigPath, playwrightConfig);
|
|
78
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export async function generateTSConfig(config, targetDir) {
|
|
4
|
+
const tsconfigPath = path.join(targetDir, 'tsconfig.json');
|
|
5
|
+
// Base configuration extends our tooling
|
|
6
|
+
const tsconfig = {
|
|
7
|
+
extends: `@rtorcato/js-tooling/typescript/${config.typescript.config}`,
|
|
8
|
+
compilerOptions: {
|
|
9
|
+
baseUrl: '.',
|
|
10
|
+
paths: {
|
|
11
|
+
'@/*': ['./src/*'],
|
|
12
|
+
'~/*': ['./src/*'],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
include: ['src/**/*', 'reset.d.ts'],
|
|
16
|
+
exclude: ['node_modules', 'dist', 'build'],
|
|
17
|
+
};
|
|
18
|
+
// Adjust for project type
|
|
19
|
+
if (config.projectType === 'library') {
|
|
20
|
+
tsconfig.compilerOptions.outDir = './dist';
|
|
21
|
+
tsconfig.compilerOptions.rootDir = './src';
|
|
22
|
+
}
|
|
23
|
+
if (config.projectType === 'nextjs-app') {
|
|
24
|
+
tsconfig.include = ['next-env.d.ts', 'src', 'app', 'pages', 'components', 'reset.d.ts'];
|
|
25
|
+
tsconfig.exclude.push('.next');
|
|
26
|
+
}
|
|
27
|
+
await fs.writeJson(tsconfigPath, tsconfig, { spaces: 2 });
|
|
28
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
5
|
+
import { setupProject } from './commands/setup.js';
|
|
6
|
+
const program = new Command();
|
|
7
|
+
program
|
|
8
|
+
.name('@rtorcato/js-tooling')
|
|
9
|
+
.description('🛠️ JavaScript and TypeScript tooling setup for modern projects')
|
|
10
|
+
.version(packageJson.version);
|
|
11
|
+
program
|
|
12
|
+
.command('setup')
|
|
13
|
+
.alias('init')
|
|
14
|
+
.description('🚀 Setup tooling for a new or existing project')
|
|
15
|
+
.option('-d, --directory <path>', 'Target directory for setup', process.cwd())
|
|
16
|
+
.option('--skip-install', 'Skip installing dependencies')
|
|
17
|
+
.action(setupProject);
|
|
18
|
+
program
|
|
19
|
+
.command('list')
|
|
20
|
+
.alias('ls')
|
|
21
|
+
.description('📋 List all available tooling configurations')
|
|
22
|
+
.action(() => {
|
|
23
|
+
console.log(chalk.cyan('\n🛠️ Available tooling configurations:\n'));
|
|
24
|
+
const configs = [
|
|
25
|
+
{ name: 'TypeScript', desc: 'Base, React, Next.js, Node.js, Express configurations' },
|
|
26
|
+
{ name: 'ESLint', desc: 'Base and Next.js ESLint configurations' },
|
|
27
|
+
{ name: 'Biome', desc: 'Fast formatter and linter configuration' },
|
|
28
|
+
{ name: 'Prettier', desc: 'Code formatter configuration' },
|
|
29
|
+
{ name: 'Vitest', desc: 'Testing framework configuration' },
|
|
30
|
+
{ name: 'Jest', desc: 'Testing framework presets for browser and Node.js' },
|
|
31
|
+
{ name: 'Playwright', desc: 'End-to-end testing configuration' },
|
|
32
|
+
{ name: 'Commitlint', desc: 'Conventional commit linting' },
|
|
33
|
+
{ name: 'Husky', desc: 'Git hooks for pre-commit validation' },
|
|
34
|
+
{ name: 'Semantic Release', desc: 'Automated versioning and publishing' },
|
|
35
|
+
{ name: 'tsup', desc: 'TypeScript bundler configuration' },
|
|
36
|
+
{ name: 'esbuild', desc: 'Fast JavaScript bundler configuration' },
|
|
37
|
+
];
|
|
38
|
+
configs.forEach(({ name, desc }) => {
|
|
39
|
+
console.log(` ${chalk.green('●')} ${chalk.bold(name)}: ${chalk.gray(desc)}`);
|
|
40
|
+
});
|
|
41
|
+
console.log(chalk.dim('\n💡 Run "js-tooling setup" to configure your project\n'));
|
|
42
|
+
});
|
|
43
|
+
// Handle unknown commands
|
|
44
|
+
program.on('command:*', () => {
|
|
45
|
+
console.error(chalk.red(`\n❌ Unknown command: ${program.args.join(' ')}`));
|
|
46
|
+
console.log(chalk.gray('See --help for a list of available commands.\n'));
|
|
47
|
+
process.exit(1);
|
|
48
|
+
});
|
|
49
|
+
// Show help if no arguments
|
|
50
|
+
if (!process.argv.slice(2).length) {
|
|
51
|
+
program.outputHelp();
|
|
52
|
+
}
|
|
53
|
+
program.parse();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
export async function installDependencies(_config, targetDir) {
|
|
4
|
+
return new Promise((resolve) => {
|
|
5
|
+
console.log(chalk.blue('📦 Installing dependencies with pnpm...'));
|
|
6
|
+
const child = spawn('pnpm', ['install'], {
|
|
7
|
+
cwd: targetDir,
|
|
8
|
+
stdio: 'inherit',
|
|
9
|
+
shell: true,
|
|
10
|
+
});
|
|
11
|
+
child.on('close', (code) => {
|
|
12
|
+
if (code === 0) {
|
|
13
|
+
console.log(chalk.green('✅ Dependencies installed successfully!'));
|
|
14
|
+
resolve();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
console.error(chalk.red(`❌ pnpm install failed with code ${code}`));
|
|
18
|
+
console.log(chalk.yellow('💡 You can install dependencies manually with: pnpm install'));
|
|
19
|
+
resolve(); // Don't reject, just warn
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
child.on('error', (error) => {
|
|
23
|
+
console.error(chalk.red('❌ Error running pnpm install:'), error.message);
|
|
24
|
+
console.log(chalk.yellow('💡 You can install dependencies manually with: pnpm install'));
|
|
25
|
+
resolve(); // Don't reject, just warn
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rtorcato/js-tooling",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "JavaScript and TypeScript tooling for Node.js, React, Next.js, and Vitest.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"tooling",
|
|
8
|
+
"typescript",
|
|
9
|
+
"eslint"
|
|
10
|
+
],
|
|
11
|
+
"author": "Richard Torcato",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/rtorcato/js-tooling.git"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/rtorcato/js-tooling#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/rtorcato/js-tooling/issues"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build-dev": "rimraf ./dist && cross-env NODE_ENV=development node build.mjs && tsc --emitDeclarationOnly --project tsconfig.build.json && pnpm build-cli",
|
|
24
|
+
"build-prod": "rimraf ./dist && cross-env NODE_ENV=production node build.mjs && tsc --emitDeclarationOnly --project tsconfig.build.json && pnpm build-cli",
|
|
25
|
+
"build-cli": "rimraf ./dist/cli && tsc --project src/cli/tsconfig.json",
|
|
26
|
+
"prepublishOnly": "./scripts/fix-bins.sh",
|
|
27
|
+
"==================== Common ====================": "",
|
|
28
|
+
"lint": "pnpm exec biome lint .",
|
|
29
|
+
"format": "pnpm exec biome format .",
|
|
30
|
+
"check:fix": "pnpm exec biome check --fix",
|
|
31
|
+
"check": "pnpm exec biome check .",
|
|
32
|
+
"prepare": "is-ci || husky",
|
|
33
|
+
"typecheck1": "tsc --noEmit",
|
|
34
|
+
"test": "vitest",
|
|
35
|
+
"test:watch": "vitest --watch",
|
|
36
|
+
"coverage": "vitest run --coverage",
|
|
37
|
+
"commit": "cz",
|
|
38
|
+
"================================================": ""
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist/cli/**/*.js",
|
|
42
|
+
"tooling/*",
|
|
43
|
+
"tooling/commitlint/commitlint.config.mjs",
|
|
44
|
+
"tooling/esbuild/index.mjs",
|
|
45
|
+
"tooling/eslint/*.mjs",
|
|
46
|
+
"tooling/jest-presets/**",
|
|
47
|
+
"tooling/prettier/index.mjs",
|
|
48
|
+
"tooling/typescript/*.json",
|
|
49
|
+
"tooling/typescript/reset.d.ts",
|
|
50
|
+
"tooling/vitest/vitest.config.mjs",
|
|
51
|
+
"tooling/tsup/index.ts",
|
|
52
|
+
"tooling/biome/biome.json",
|
|
53
|
+
"tooling/semantic-release/*.mjs",
|
|
54
|
+
"README.md"
|
|
55
|
+
],
|
|
56
|
+
"exports": {
|
|
57
|
+
"./commitlint/config": {
|
|
58
|
+
"import": "./tooling/commitlint/commitlint.mjs"
|
|
59
|
+
},
|
|
60
|
+
"./esbuild": "./tooling/esbuild/index.mjs",
|
|
61
|
+
"./eslint/base": "./tooling/eslint/base.mjs",
|
|
62
|
+
"./eslint/nextjs": "./tooling/eslint/nextjs.mjs",
|
|
63
|
+
"./jest-presets/browser/jest-preset": "./tooling/jest-presets/browser/jest-preset.mjs",
|
|
64
|
+
"./jest-presets/node/jest-preset": "./tooling/jest-presets/node/jest-preset.mjs",
|
|
65
|
+
"./prettier": "./tooling/prettier/index.mjs",
|
|
66
|
+
"./typescript/base": "./tooling/typescript/tsconfig.base.json",
|
|
67
|
+
"./typescript/next": "./tooling/typescript/tsconfig.next.json",
|
|
68
|
+
"./typescript/express": "./tooling/typescript/tsconfig.express.json",
|
|
69
|
+
"./typescript/node": "./tooling/typescript/tsconfig.node.json",
|
|
70
|
+
"./typescript/react": "./tooling/typescript/tsconfig.react.json",
|
|
71
|
+
"./typescript/test": "./tooling/typescript/tsconfig.test.json",
|
|
72
|
+
"./typescript/reset": "./tooling/typescript/reset.d.ts",
|
|
73
|
+
"./vitest/config": "./tooling/vitest/vitest.config.mjs",
|
|
74
|
+
"./tsup": "./tooling/tsup/index.ts",
|
|
75
|
+
"./biome": "./tooling/biome/biome.json",
|
|
76
|
+
"./semantic-release": "./tooling/semantic-release/index.mjs",
|
|
77
|
+
"./semantic-release/github": "./tooling/semantic-release/github.mjs",
|
|
78
|
+
"./semantic-release/docker": "./tooling/semantic-release/docker.mjs"
|
|
79
|
+
},
|
|
80
|
+
"dependencies": {
|
|
81
|
+
"@biomejs/biome": "^2.3.0",
|
|
82
|
+
"@commitlint/cli": "^20.1.0",
|
|
83
|
+
"@commitlint/config-conventional": "^20.0.0",
|
|
84
|
+
"@playwright/test": "^1.56.1",
|
|
85
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
86
|
+
"@semantic-release/exec": "^7.1.0",
|
|
87
|
+
"@semantic-release/git": "^10.0.1",
|
|
88
|
+
"@semantic-release/npm": "^13.1.1",
|
|
89
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
90
|
+
"@total-typescript/ts-reset": "0.6.1",
|
|
91
|
+
"@types/node": "^24.9.1",
|
|
92
|
+
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
|
93
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
94
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
95
|
+
"chalk": "^5.6.2",
|
|
96
|
+
"commander": "^14.0.1",
|
|
97
|
+
"commitizen": "^4.3.1",
|
|
98
|
+
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
99
|
+
"cz-conventional-changelog": "^3.3.0",
|
|
100
|
+
"esbuild": "^0.25.11",
|
|
101
|
+
"esbuild-node-externals": "^1.18.0",
|
|
102
|
+
"fs-extra": "^11.3.2",
|
|
103
|
+
"husky": "^9.1.7",
|
|
104
|
+
"inquirer": "^12.10.0",
|
|
105
|
+
"lint-staged": "^16.2.6",
|
|
106
|
+
"semantic-release": "^25.0.1",
|
|
107
|
+
"typescript": "^5.9.3",
|
|
108
|
+
"typescript-eslint": "latest",
|
|
109
|
+
"vitest": "4.0.2"
|
|
110
|
+
},
|
|
111
|
+
"devDependencies": {
|
|
112
|
+
"@next/eslint-plugin-next": "^16.0.0",
|
|
113
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
114
|
+
"@semantic-release/github": "^12.0.0",
|
|
115
|
+
"@types/fs-extra": "^11.0.4",
|
|
116
|
+
"@types/inquirer": "^9.0.9",
|
|
117
|
+
"cross-env": "^10.1.0",
|
|
118
|
+
"eslint": "9.38.0",
|
|
119
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
120
|
+
"eslint-config-prettier": "10.1.8",
|
|
121
|
+
"eslint-config-turbo": "^2.5.8",
|
|
122
|
+
"eslint-plugin-import": "^2.32.0",
|
|
123
|
+
"eslint-plugin-jest": "29.0.1",
|
|
124
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
125
|
+
"eslint-plugin-react": "^7.37.5",
|
|
126
|
+
"eslint-plugin-react-hooks": "^7.0.0",
|
|
127
|
+
"eslint-plugin-vitest": "0.5.4",
|
|
128
|
+
"is-ci": "^4.1.0",
|
|
129
|
+
"prettier": "^3.6.2",
|
|
130
|
+
"prettier-plugin-tailwindcss": "^0.7.1",
|
|
131
|
+
"rimraf": "6.0.1",
|
|
132
|
+
"ts-jest": "^29.4.5",
|
|
133
|
+
"tsup": "8.5.0"
|
|
134
|
+
},
|
|
135
|
+
"lint-staged": {
|
|
136
|
+
"*.{js,ts,json,md}": [
|
|
137
|
+
"pnpm exec biome lint",
|
|
138
|
+
"pnpm exec biome format",
|
|
139
|
+
"git add"
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
"husky": {
|
|
143
|
+
"hooks": {
|
|
144
|
+
"pre-commit": "lint-staged"
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"bin": {
|
|
148
|
+
"js-tooling": "./dist/cli/index.js",
|
|
149
|
+
"commitmessage": "scripts/commitmessage.sh",
|
|
150
|
+
"helloworld": "scripts/helloworld.sh"
|
|
151
|
+
},
|
|
152
|
+
"config": {
|
|
153
|
+
"commitizen": {
|
|
154
|
+
"path": "cz-conventional-changelog"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"publishConfig": {
|
|
158
|
+
"access": "public"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# chmod +x scripts/commitmessage.sh
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
echo "Select commit type by number:"
|
|
7
|
+
select type in "feat" "fix" "perf" "ci" "WIP" "chore" "docs" "test" "style" "refactor" "build" "BREAKING CHANGE" "revert"; do
|
|
8
|
+
if [ -n "$type" ]; then
|
|
9
|
+
break
|
|
10
|
+
else
|
|
11
|
+
echo "❌ Invalid selection. Try again."
|
|
12
|
+
fi
|
|
13
|
+
done
|
|
14
|
+
|
|
15
|
+
if [[ "$type" =~ ^(feat|fix|perf)$ ]]; then
|
|
16
|
+
echo "Select semantic version by number:"
|
|
17
|
+
select semantic_version in "none" "patch" "minor" "major"; do
|
|
18
|
+
[ -n "$semantic_version" ] && break
|
|
19
|
+
done
|
|
20
|
+
else
|
|
21
|
+
semantic_version="none"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
read -p "Enter commit description: " description
|
|
25
|
+
read -p "Skip CI? (y/n) [n]: " skip_ci
|
|
26
|
+
skip_ci=${skip_ci:-n}
|
|
27
|
+
|
|
28
|
+
msg="$type"
|
|
29
|
+
[ "$semantic_version" != "none" ] && msg="$msg($semantic_version)"
|
|
30
|
+
msg="$msg: $description"
|
|
31
|
+
[ "$skip_ci" = "y" ] && msg="$msg [skip ci]"
|
|
32
|
+
|
|
33
|
+
echo ""
|
|
34
|
+
echo "🔍 Commit preview:"
|
|
35
|
+
echo "$msg"
|
|
36
|
+
read -p "Is this okay? (y/n): " confirm
|
|
37
|
+
[ "$confirm" != "y" ] && echo "❌ Commit aborted." && exit 1
|
|
38
|
+
|
|
39
|
+
git add -A
|
|
40
|
+
git commit -m "$msg"
|
|
41
|
+
|
|
42
|
+
echo ""
|
|
43
|
+
read -p "Do you want to push the commit? (y/n): " push_confirm
|
|
44
|
+
[ "$push_confirm" = "y" ] && git push || echo "🚫 Commit not pushed."
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"root": false,
|
|
3
|
+
"$schema": "https://biomejs.dev/schemas/2.3.0/schema.json",
|
|
4
|
+
"vcs": {
|
|
5
|
+
"enabled": false,
|
|
6
|
+
"clientKind": "git",
|
|
7
|
+
"useIgnoreFile": true
|
|
8
|
+
},
|
|
9
|
+
"files": {
|
|
10
|
+
"ignoreUnknown": false,
|
|
11
|
+
"includes": [
|
|
12
|
+
"**",
|
|
13
|
+
"!**/node_modules",
|
|
14
|
+
"!**/package.json",
|
|
15
|
+
"!**/tsconfig*.json",
|
|
16
|
+
"!**/dist",
|
|
17
|
+
"!**/coverage",
|
|
18
|
+
"!**/.git",
|
|
19
|
+
"!**/.github",
|
|
20
|
+
"!**/.vscode"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"formatter": {
|
|
24
|
+
"enabled": true,
|
|
25
|
+
"indentStyle": "tab",
|
|
26
|
+
"lineWidth": 100
|
|
27
|
+
},
|
|
28
|
+
"assist": { "actions": { "source": { "organizeImports": "on" } } },
|
|
29
|
+
"linter": {
|
|
30
|
+
"enabled": true,
|
|
31
|
+
"rules": {
|
|
32
|
+
"recommended": true,
|
|
33
|
+
"style": {
|
|
34
|
+
"noInferrableTypes": "off"
|
|
35
|
+
}
|
|
36
|
+
// "noUnusedVariables": "error", ❌ Not supported yet
|
|
37
|
+
// "noExplicitAny": "warn" ❌ Not supported yet
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"javascript": {
|
|
41
|
+
"formatter": {
|
|
42
|
+
"quoteStyle": "single",
|
|
43
|
+
"trailingCommas": "es5",
|
|
44
|
+
"semicolons": "asNeeded"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|