@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
@@ -0,0 +1,261 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ export async function generateGitHubActions(config, targetDir) {
4
+ const workflowsDir = path.join(targetDir, '.github', 'workflows');
5
+ await fs.ensureDir(workflowsDir);
6
+ const workflowPath = path.join(workflowsDir, 'ci.yml');
7
+ const workflow = generateWorkflowYAML(config);
8
+ await fs.writeFile(workflowPath, workflow);
9
+ }
10
+ function generateWorkflowYAML(config) {
11
+ const hasTests = config.testing.framework !== 'none';
12
+ const hasTypeScript = config.typescript.enabled;
13
+ const hasBuild = config.bundler !== 'none';
14
+ const isLibrary = config.projectType === 'library';
15
+ return `name: 🚀 CI/CD Pipeline
16
+
17
+ on:
18
+ push:
19
+ branches: [main, release, develop]
20
+ pull_request:
21
+ branches: [main]
22
+ workflow_dispatch:
23
+
24
+ concurrency:
25
+ group: \${{ github.workflow }}-\${{ github.ref }}
26
+ cancel-in-progress: true
27
+
28
+ jobs:
29
+ check-skip:
30
+ runs-on: ubuntu-latest
31
+ outputs:
32
+ should-skip: \${{ steps.skip-check.outputs.should-skip }}
33
+ steps:
34
+ - name: Check for skip CI
35
+ id: skip-check
36
+ run: |
37
+ if [[ "\${{ github.event.head_commit.message }}" =~ \\[(ci skip|skip ci)\\] ]]; then
38
+ echo "should-skip=true" >> $GITHUB_OUTPUT
39
+ else
40
+ echo "should-skip=false" >> $GITHUB_OUTPUT
41
+ fi
42
+
43
+ dependencies:
44
+ runs-on: ubuntu-latest
45
+ needs: check-skip
46
+ if: needs.check-skip.outputs.should-skip != 'true'
47
+ outputs:
48
+ cache-key: \${{ steps.cache-key.outputs.key }}
49
+ steps:
50
+ - name: 📦 Checkout repository
51
+ uses: actions/checkout@v4
52
+
53
+ - name: 📦 Setup Node.js
54
+ uses: actions/setup-node@v4
55
+ with:
56
+ node-version: '20'
57
+
58
+ - name: 📦 Setup pnpm
59
+ uses: pnpm/action-setup@v4
60
+ with:
61
+ version: latest
62
+
63
+ - name: 📦 Generate cache key
64
+ id: cache-key
65
+ run: echo "key=\${{ runner.os }}-pnpm-\${{ hashFiles('**/pnpm-lock.yaml') }}" >> $GITHUB_OUTPUT
66
+
67
+ - name: 📦 Cache dependencies
68
+ uses: actions/cache@v4
69
+ with:
70
+ path: |
71
+ ~/.pnpm-store
72
+ node_modules
73
+ key: \${{ steps.cache-key.outputs.key }}
74
+ restore-keys: |
75
+ \${{ runner.os }}-pnpm-
76
+
77
+ - name: 📦 Install dependencies
78
+ run: pnpm install --frozen-lockfile
79
+
80
+ lint:
81
+ runs-on: ubuntu-latest
82
+ needs: [dependencies, check-skip]
83
+ if: needs.check-skip.outputs.should-skip != 'true'
84
+ steps:
85
+ - name: 📦 Checkout repository
86
+ uses: actions/checkout@v4
87
+
88
+ - name: 📦 Setup Node.js
89
+ uses: actions/setup-node@v4
90
+ with:
91
+ node-version: '20'
92
+
93
+ - name: 📦 Setup pnpm
94
+ uses: pnpm/action-setup@v4
95
+ with:
96
+ version: latest
97
+
98
+ - name: 📦 Restore dependencies cache
99
+ uses: actions/cache@v4
100
+ with:
101
+ path: |
102
+ ~/.pnpm-store
103
+ node_modules
104
+ key: \${{ needs.dependencies.outputs.cache-key }}
105
+
106
+ - name: 🔍 Run linting
107
+ run: ${config.linting.tool === 'biome' || config.linting.tool === 'both' ? 'pnpm check' : 'pnpm lint'}
108
+ ${hasTypeScript
109
+ ? `
110
+ typecheck:
111
+ runs-on: ubuntu-latest
112
+ needs: [dependencies, check-skip]
113
+ if: needs.check-skip.outputs.should-skip != 'true'
114
+ steps:
115
+ - name: 📦 Checkout repository
116
+ uses: actions/checkout@v4
117
+
118
+ - name: 📦 Setup Node.js
119
+ uses: actions/setup-node@v4
120
+ with:
121
+ node-version: '20'
122
+
123
+ - name: 📦 Setup pnpm
124
+ uses: pnpm/action-setup@v4
125
+ with:
126
+ version: latest
127
+
128
+ - name: 📦 Restore dependencies cache
129
+ uses: actions/cache@v4
130
+ with:
131
+ path: |
132
+ ~/.pnpm-store
133
+ node_modules
134
+ key: \${{ needs.dependencies.outputs.cache-key }}
135
+
136
+ - name: 🔍 Type check
137
+ run: pnpm typecheck`
138
+ : ''}
139
+ ${hasTests
140
+ ? `
141
+ test:
142
+ runs-on: ubuntu-latest
143
+ needs: [dependencies, check-skip]
144
+ if: needs.check-skip.outputs.should-skip != 'true'
145
+ steps:
146
+ - name: 📦 Checkout repository
147
+ uses: actions/checkout@v4
148
+
149
+ - name: 📦 Setup Node.js
150
+ uses: actions/setup-node@v4
151
+ with:
152
+ node-version: '20'
153
+
154
+ - name: 📦 Setup pnpm
155
+ uses: pnpm/action-setup@v4
156
+ with:
157
+ version: latest
158
+
159
+ - name: 📦 Restore dependencies cache
160
+ uses: actions/cache@v4
161
+ with:
162
+ path: |
163
+ ~/.pnpm-store
164
+ node_modules
165
+ key: \${{ needs.dependencies.outputs.cache-key }}
166
+
167
+ - name: 🧪 Run tests
168
+ run: pnpm test`
169
+ : ''}
170
+ ${hasBuild
171
+ ? `
172
+ build:
173
+ runs-on: ubuntu-latest
174
+ needs: [dependencies, check-skip]
175
+ if: needs.check-skip.outputs.should-skip != 'true'
176
+ steps:
177
+ - name: 📦 Checkout repository
178
+ uses: actions/checkout@v4
179
+
180
+ - name: 📦 Setup Node.js
181
+ uses: actions/setup-node@v4
182
+ with:
183
+ node-version: '20'
184
+
185
+ - name: 📦 Setup pnpm
186
+ uses: pnpm/action-setup@v4
187
+ with:
188
+ version: latest
189
+
190
+ - name: 📦 Restore dependencies cache
191
+ uses: actions/cache@v4
192
+ with:
193
+ path: |
194
+ ~/.pnpm-store
195
+ node_modules
196
+ key: \${{ needs.dependencies.outputs.cache-key }}
197
+
198
+ - name: 🏗️ Build project
199
+ run: pnpm build
200
+
201
+ - name: 📦 Upload build artifacts
202
+ uses: actions/upload-artifact@v4
203
+ with:
204
+ name: build-artifacts
205
+ path: |
206
+ dist/
207
+ package.json
208
+ README.md
209
+ retention-days: 7`
210
+ : ''}
211
+ ${isLibrary && config.semanticRelease
212
+ ? `
213
+ release:
214
+ runs-on: ubuntu-latest
215
+ needs: [dependencies, lint${hasTypeScript ? ', typecheck' : ''}${hasTests ? ', test' : ''}${hasBuild ? ', build' : ''}, check-skip]
216
+ if: needs.check-skip.outputs.should-skip != 'true' && github.ref == 'refs/heads/main'
217
+ permissions:
218
+ contents: write
219
+ issues: write
220
+ pull-requests: write
221
+ id-token: write
222
+ steps:
223
+ - name: 📦 Checkout repository
224
+ uses: actions/checkout@v4
225
+ with:
226
+ fetch-depth: 0
227
+ token: \${{ secrets.GITHUB_TOKEN }}
228
+
229
+ - name: 📦 Setup Node.js
230
+ uses: actions/setup-node@v4
231
+ with:
232
+ node-version: '20'
233
+ registry-url: 'https://registry.npmjs.org'
234
+
235
+ - name: 📦 Setup pnpm
236
+ uses: pnpm/action-setup@v4
237
+ with:
238
+ version: latest
239
+
240
+ - name: 📦 Restore dependencies cache
241
+ uses: actions/cache@v4
242
+ with:
243
+ path: |
244
+ ~/.pnpm-store
245
+ node_modules
246
+ key: \${{ needs.dependencies.outputs.cache-key }}
247
+
248
+ - name: 🔧 Configure Git
249
+ run: |
250
+ git config --global user.name "github-actions[bot]"
251
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
252
+
253
+ - name: 🚀 Run semantic-release
254
+ env:
255
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
256
+ NPM_TOKEN: \${{ secrets.NPM_TOKEN }}
257
+ NODE_AUTH_TOKEN: \${{ secrets.NPM_TOKEN }}
258
+ run: npx semantic-release`
259
+ : ''}
260
+ `;
261
+ }
@@ -0,0 +1,53 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { generateBuildConfigs } from './build.js';
5
+ import { generateGitConfigs } from './git.js';
6
+ import { generateGitHubActions } from './github-actions.js';
7
+ import { generateLintingConfigs } from './linting.js';
8
+ import { generatePackageJson } from './package-json.js';
9
+ import { generateReadme } from './readme.js';
10
+ import { generateTestingConfigs } from './testing.js';
11
+ import { generateTSConfig } from './tsconfig.js';
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+ export async function generateConfigs(config, targetDir) {
15
+ // Generate package.json
16
+ await generatePackageJson(config, targetDir);
17
+ // Generate TypeScript configuration
18
+ if (config.typescript.enabled) {
19
+ await generateTSConfig(config, targetDir);
20
+ }
21
+ // Generate linting configurations
22
+ if (config.linting.tool !== 'none') {
23
+ await generateLintingConfigs(config, targetDir);
24
+ }
25
+ // Generate testing configurations
26
+ if (config.testing.framework !== 'none') {
27
+ await generateTestingConfigs(config, targetDir);
28
+ }
29
+ // Generate git configurations
30
+ if (config.gitHooks || config.commitLint) {
31
+ await generateGitConfigs(config, targetDir);
32
+ }
33
+ // Generate GitHub Actions workflow
34
+ await generateGitHubActions(config, targetDir);
35
+ // Generate build configurations
36
+ if (config.bundler !== 'none') {
37
+ await generateBuildConfigs(config, targetDir);
38
+ }
39
+ // Generate README
40
+ await generateReadme(config, targetDir);
41
+ // Copy ts-reset if TypeScript is enabled
42
+ if (config.typescript.enabled) {
43
+ await copyTSReset(targetDir);
44
+ }
45
+ }
46
+ async function copyTSReset(targetDir) {
47
+ const toolingRoot = path.resolve(__dirname, '../../../tooling');
48
+ const resetPath = path.join(toolingRoot, 'typescript', 'reset.d.ts');
49
+ const targetPath = path.join(targetDir, 'reset.d.ts');
50
+ if (await fs.pathExists(resetPath)) {
51
+ await fs.copy(resetPath, targetPath);
52
+ }
53
+ }
@@ -0,0 +1,43 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ export async function generateLintingConfigs(config, targetDir) {
4
+ // Generate Biome config
5
+ if (config.linting.tool === 'biome' || config.linting.tool === 'both') {
6
+ await generateBiomeConfig(targetDir);
7
+ }
8
+ // Generate ESLint config
9
+ if (config.linting.tool === 'eslint' || config.linting.tool === 'both') {
10
+ await generateESLintConfig(config, targetDir);
11
+ }
12
+ // Generate Prettier config if using ESLint
13
+ if (config.linting.tool === 'eslint') {
14
+ await generatePrettierConfig(targetDir);
15
+ }
16
+ }
17
+ async function generateBiomeConfig(targetDir) {
18
+ const biomeConfigPath = path.join(targetDir, 'biome.jsonc');
19
+ const biomeConfig = {
20
+ $schema: 'https://biomejs.dev/schemas/1.9.4/schema.json',
21
+ extends: ['@rtorcato/js-tooling/biome'],
22
+ files: {
23
+ include: ['src/**/*', '*.ts', '*.js', '*.tsx', '*.jsx'],
24
+ ignore: ['node_modules', 'dist', 'build', '.next'],
25
+ },
26
+ };
27
+ await fs.writeJson(biomeConfigPath, biomeConfig, { spaces: 2 });
28
+ }
29
+ async function generateESLintConfig(config, targetDir) {
30
+ const eslintConfigPath = path.join(targetDir, 'eslint.config.mjs');
31
+ const configType = config.linting.eslintConfig || 'base';
32
+ const eslintConfig = `import { default as config } from '@rtorcato/js-tooling/eslint/${configType}'
33
+
34
+ export default config
35
+ `;
36
+ await fs.writeFile(eslintConfigPath, eslintConfig);
37
+ }
38
+ async function generatePrettierConfig(targetDir) {
39
+ const prettierConfigPath = path.join(targetDir, 'prettier.config.mjs');
40
+ const prettierConfig = `export { default } from '@rtorcato/js-tooling/prettier'
41
+ `;
42
+ await fs.writeFile(prettierConfigPath, prettierConfig);
43
+ }
@@ -0,0 +1,162 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ export async function generatePackageJson(config, targetDir) {
4
+ const packageJsonPath = path.join(targetDir, 'package.json');
5
+ let existingPackageJson = {};
6
+ if (await fs.pathExists(packageJsonPath)) {
7
+ existingPackageJson = await fs.readJson(packageJsonPath);
8
+ }
9
+ const packageJson = {
10
+ name: config.projectName,
11
+ version: '0.1.0',
12
+ description: '',
13
+ type: 'module',
14
+ ...existingPackageJson,
15
+ scripts: {
16
+ ...getScripts(config),
17
+ ...existingPackageJson?.scripts,
18
+ },
19
+ dependencies: {
20
+ ...existingPackageJson?.dependencies,
21
+ },
22
+ devDependencies: {
23
+ '@rtorcato/js-tooling': 'latest',
24
+ ...getDependencies(config),
25
+ ...existingPackageJson?.devDependencies,
26
+ },
27
+ };
28
+ // Add additional package.json fields based on project type
29
+ if (config.projectType === 'library') {
30
+ packageJson.main = './dist/index.js';
31
+ packageJson.module = './dist/index.mjs';
32
+ packageJson.types = './dist/index.d.ts';
33
+ packageJson.exports = {
34
+ '.': {
35
+ import: './dist/index.mjs',
36
+ require: './dist/index.js',
37
+ types: './dist/index.d.ts',
38
+ },
39
+ };
40
+ packageJson.files = ['dist'];
41
+ packageJson.publishConfig = {
42
+ access: 'public',
43
+ };
44
+ }
45
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
46
+ }
47
+ function getScripts(config) {
48
+ const scripts = {};
49
+ // TypeScript scripts
50
+ if (config.typescript.enabled) {
51
+ scripts['typecheck'] = 'tsc --noEmit';
52
+ }
53
+ // Linting scripts
54
+ if (config.linting.tool === 'biome' || config.linting.tool === 'both') {
55
+ scripts['lint'] = 'biome lint .';
56
+ scripts['format'] = 'biome format .';
57
+ scripts['check'] = 'biome check .';
58
+ scripts['check:fix'] = 'biome check --fix .';
59
+ }
60
+ else if (config.linting.tool === 'eslint') {
61
+ scripts['lint'] = 'eslint .';
62
+ scripts['lint:fix'] = 'eslint . --fix';
63
+ scripts['format'] = 'prettier --write .';
64
+ }
65
+ // Testing scripts
66
+ if (config.testing.framework === 'vitest') {
67
+ scripts['test'] = 'vitest';
68
+ scripts['test:watch'] = 'vitest --watch';
69
+ scripts['test:ui'] = 'vitest --ui';
70
+ scripts['coverage'] = 'vitest run --coverage';
71
+ }
72
+ else if (config.testing.framework === 'jest') {
73
+ scripts['test'] = 'jest';
74
+ scripts['test:watch'] = 'jest --watch';
75
+ scripts['coverage'] = 'jest --coverage';
76
+ }
77
+ else if (config.testing.framework === 'playwright') {
78
+ scripts['test:e2e'] = 'playwright test';
79
+ scripts['test:e2e:ui'] = 'playwright test --ui';
80
+ }
81
+ // Build scripts
82
+ if (config.bundler === 'tsup') {
83
+ scripts['build'] = 'tsup';
84
+ scripts['build:watch'] = 'tsup --watch';
85
+ }
86
+ else if (config.bundler === 'esbuild') {
87
+ scripts['build'] = 'node build.mjs';
88
+ }
89
+ else if (config.bundler === 'vite') {
90
+ scripts['build'] = 'vite build';
91
+ scripts['dev'] = 'vite';
92
+ scripts['preview'] = 'vite preview';
93
+ }
94
+ // Git hooks
95
+ if (config.gitHooks) {
96
+ scripts['prepare'] = 'husky';
97
+ }
98
+ // Semantic release
99
+ if (config.semanticRelease) {
100
+ scripts['release'] = 'semantic-release';
101
+ }
102
+ return scripts;
103
+ }
104
+ function getDependencies(config) {
105
+ const deps = {};
106
+ // TypeScript
107
+ if (config.typescript.enabled) {
108
+ deps['typescript'] = '^5.9.3';
109
+ deps['@types/node'] = '^24.0.0';
110
+ }
111
+ // Linting tools
112
+ if (config.linting.tool === 'biome' || config.linting.tool === 'both') {
113
+ deps['@biomejs/biome'] = '^2.3.0';
114
+ }
115
+ if (config.linting.tool === 'eslint' || config.linting.tool === 'both') {
116
+ deps['eslint'] = '^9.0.0';
117
+ deps['prettier'] = '^3.0.0';
118
+ }
119
+ // Testing frameworks
120
+ if (config.testing.framework === 'vitest') {
121
+ deps['vitest'] = '^4.0.0';
122
+ if (config.testing.environment === 'browser' || config.testing.environment === 'both') {
123
+ deps['@vitest/ui'] = '^4.0.0';
124
+ deps['jsdom'] = '^25.0.0';
125
+ }
126
+ }
127
+ else if (config.testing.framework === 'jest') {
128
+ deps['jest'] = '^29.0.0';
129
+ if (config.typescript.enabled) {
130
+ deps['ts-jest'] = '^29.0.0';
131
+ }
132
+ }
133
+ else if (config.testing.framework === 'playwright') {
134
+ deps['@playwright/test'] = '^1.56.0';
135
+ }
136
+ // Build tools
137
+ if (config.bundler === 'tsup') {
138
+ deps['tsup'] = '^8.0.0';
139
+ }
140
+ else if (config.bundler === 'esbuild') {
141
+ deps['esbuild'] = '^0.25.0';
142
+ }
143
+ else if (config.bundler === 'vite') {
144
+ deps['vite'] = '^6.0.0';
145
+ }
146
+ // Git hooks
147
+ if (config.gitHooks) {
148
+ deps['husky'] = '^9.0.0';
149
+ deps['lint-staged'] = '^16.0.0';
150
+ }
151
+ // Commit linting
152
+ if (config.commitLint) {
153
+ deps['@commitlint/cli'] = '^20.0.0';
154
+ deps['@commitlint/config-conventional'] = '^20.0.0';
155
+ }
156
+ // Semantic release
157
+ if (config.semanticRelease) {
158
+ deps['semantic-release'] = '^25.0.0';
159
+ deps['@semantic-release/github'] = '^12.0.0';
160
+ }
161
+ return deps;
162
+ }