@rtorcato/js-tooling 2.5.0 → 2.5.1

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.
@@ -124,9 +124,10 @@ const FIXERS = [
124
124
  },
125
125
  {
126
126
  target: 'husky',
127
- description: 'Set up Husky + lint-staged (deep-merges existing lint-staged field)',
127
+ description: 'Set up Husky + lint-staged',
128
128
  appliesTo: ['Husky', 'lint-staged'],
129
129
  outputs: ['.husky/pre-commit', 'package.json (lint-staged field)'],
130
+ riskLevel: 'safe-merge',
130
131
  canFixDrift: true,
131
132
  async run({ targetDir, pkg }) {
132
133
  const pkgPath = path.join(targetDir, 'package.json');
@@ -209,9 +210,10 @@ const FIXERS = [
209
210
  },
210
211
  {
211
212
  target: 'engines',
212
- description: 'Add engines.node to package.json (never overwrites)',
213
+ description: 'Add engines.node to package.json',
213
214
  appliesTo: ['engines.node'],
214
215
  outputs: ['package.json (engines.node field)'],
216
+ riskLevel: 'safe-merge',
215
217
  canFixDrift: true,
216
218
  async run({ targetDir }) {
217
219
  const result = await ensureEnginesNode(targetDir);
@@ -234,6 +236,7 @@ const FIXERS = [
234
236
  description: 'Add @rtorcato/js-tooling to devDependencies',
235
237
  appliesTo: ['package.json'],
236
238
  outputs: ['package.json (devDependencies)'],
239
+ riskLevel: 'safe-merge',
237
240
  canFixDrift: true,
238
241
  async run({ targetDir, pkg }) {
239
242
  const pkgPath = path.join(targetDir, 'package.json');
@@ -282,15 +285,29 @@ async function applyFixer(fixer, result, targetDir, pkg, dryRun, silent) {
282
285
  }
283
286
  return { filesWritten, dryRun: false };
284
287
  }
288
+ function promptMessageFor(fixer, result) {
289
+ const risk = fixer.riskLevel ?? 'destructive';
290
+ if (risk === 'safe-merge') {
291
+ return { message: `${fixer.description} (existing fields preserved)?`, default: true };
292
+ }
293
+ if (risk === 'safe-add') {
294
+ return { message: `${fixer.description}?`, default: true };
295
+ }
296
+ // destructive
297
+ if (result.status === 'drift') {
298
+ return {
299
+ message: `⚠️ ${fixer.description} — overwrite existing file? user customizations will be lost`,
300
+ default: false,
301
+ };
302
+ }
303
+ return { message: `Apply ${fixer.description}?`, default: true };
304
+ }
285
305
  async function confirmApply(fixer, result, assumeYes) {
286
306
  if (assumeYes)
287
307
  return true;
288
- const isDrift = result.status === 'drift';
289
- const message = isDrift
290
- ? `⚠️ ${fixer.description} — overwrite existing file? user customizations will be lost`
291
- : `Apply ${fixer.description}?`;
308
+ const { message, default: defaultValue } = promptMessageFor(fixer, result);
292
309
  const { confirm } = await inquirer.prompt([
293
- { type: 'confirm', name: 'confirm', message, default: !isDrift },
310
+ { type: 'confirm', name: 'confirm', message, default: defaultValue },
294
311
  ]);
295
312
  return confirm === true;
296
313
  }
@@ -53,32 +53,17 @@ console.log('Build completed!')
53
53
  `;
54
54
  await fs.writeFile(esbuildConfigPath, esbuildConfig);
55
55
  }
56
- async function generateViteConfig(config, targetDir) {
56
+ export async function generateViteConfig(config, targetDir) {
57
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
- })
58
+ // React apps need the plugin; we layer it on top of the shipped preset.
59
+ const viteConfig = config.projectType === 'react-app'
60
+ ? `import preset from '@rtorcato/js-tooling/vite'
61
+ import react from '@vitejs/plugin-react'
62
+ import { defineConfig, mergeConfig } from 'vite'
63
+
64
+ export default mergeConfig(preset, defineConfig({ plugins: [react()] }))
65
+ `
66
+ : `export { default } from '@rtorcato/js-tooling/vite'
82
67
  `;
83
68
  await fs.writeFile(viteConfigPath, viteConfig);
84
69
  }
@@ -38,41 +38,9 @@ async function generateJestConfig(config, targetDir) {
38
38
  `;
39
39
  await fs.writeFile(jestConfigPath, jestConfig);
40
40
  }
41
- async function generatePlaywrightConfig(targetDir) {
41
+ export async function generatePlaywrightConfig(targetDir) {
42
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
- })
43
+ const playwrightConfig = `export { default } from '@rtorcato/js-tooling/playwright'
76
44
  `;
77
45
  await fs.writeFile(playwrightConfigPath, playwrightConfig);
78
46
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rtorcato/js-tooling",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "JavaScript and TypeScript tooling for Node.js, React, Next.js, and Vitest.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -47,10 +47,14 @@
47
47
  "tooling/eslint/*.d.mts",
48
48
  "tooling/eslint/types.d.ts",
49
49
  "tooling/jest-presets/**",
50
+ "tooling/playwright/playwright.config.mjs",
51
+ "tooling/playwright/playwright.config.d.mts",
50
52
  "tooling/prettier/index.mjs",
51
53
  "tooling/prettier/index.d.mts",
52
54
  "tooling/typescript/*.json",
53
55
  "tooling/typescript/reset.d.ts",
56
+ "tooling/vite/vite.config.mjs",
57
+ "tooling/vite/vite.config.d.mts",
54
58
  "tooling/vitest/vitest.config.mjs",
55
59
  "tooling/vitest/vitest.config.d.mts",
56
60
  "tooling/vitest/vitest.config.react.mjs",
@@ -88,6 +92,10 @@
88
92
  "types": "./tooling/jest-presets/node/jest-preset.d.mts",
89
93
  "import": "./tooling/jest-presets/node/jest-preset.mjs"
90
94
  },
95
+ "./playwright": {
96
+ "types": "./tooling/playwright/playwright.config.d.mts",
97
+ "import": "./tooling/playwright/playwright.config.mjs"
98
+ },
91
99
  "./prettier": {
92
100
  "types": "./tooling/prettier/index.d.mts",
93
101
  "import": "./tooling/prettier/index.mjs"
@@ -99,6 +107,10 @@
99
107
  "./typescript/react": "./tooling/typescript/tsconfig.react.json",
100
108
  "./typescript/test": "./tooling/typescript/tsconfig.test.json",
101
109
  "./typescript/reset": "./tooling/typescript/reset.d.ts",
110
+ "./vite": {
111
+ "types": "./tooling/vite/vite.config.d.mts",
112
+ "import": "./tooling/vite/vite.config.mjs"
113
+ },
102
114
  "./vitest/config": {
103
115
  "types": "./tooling/vitest/vitest.config.d.mts",
104
116
  "import": "./tooling/vitest/vitest.config.mjs"
@@ -20,8 +20,9 @@ export default {
20
20
  "test",
21
21
  ],
22
22
  ],
23
- // Enforce length limits (strict)
24
- "header-max-length": [2, "always", 50],
23
+ // Enforce length limits: 72 chars matches the conventional-commits
24
+ // recommendation and git's default email format
25
+ "header-max-length": [2, "always", 72],
25
26
  "body-max-line-length": [2, "always", 72],
26
27
  "footer-max-line-length": [2, "always", 72],
27
28
  // Enforce case rules (allow common patterns)
@@ -0,0 +1,4 @@
1
+ import type { PlaywrightTestConfig } from '@playwright/test'
2
+
3
+ declare const config: PlaywrightTestConfig
4
+ export default config
@@ -0,0 +1,19 @@
1
+ import { defineConfig, devices } from '@playwright/test'
2
+
3
+ export default defineConfig({
4
+ testDir: './tests/e2e',
5
+ fullyParallel: true,
6
+ forbidOnly: !!process.env.CI,
7
+ retries: process.env.CI ? 2 : 0,
8
+ workers: process.env.CI ? 1 : undefined,
9
+ reporter: 'html',
10
+ use: {
11
+ baseURL: process.env.PLAYWRIGHT_BASE_URL ?? 'http://localhost:3000',
12
+ trace: 'on-first-retry',
13
+ },
14
+ projects: [
15
+ { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
16
+ { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
17
+ { name: 'webkit', use: { ...devices['Desktop Safari'] } },
18
+ ],
19
+ })
@@ -0,0 +1,4 @@
1
+ import type { UserConfig } from 'vite'
2
+
3
+ declare const config: UserConfig
4
+ export default config
@@ -0,0 +1,18 @@
1
+ import { defineConfig } from 'vite'
2
+
3
+ export default defineConfig({
4
+ resolve: {
5
+ alias: {
6
+ '@': '/src',
7
+ '~': '/src',
8
+ },
9
+ },
10
+ build: {
11
+ outDir: 'dist',
12
+ sourcemap: true,
13
+ },
14
+ server: {
15
+ port: 3000,
16
+ open: true,
17
+ },
18
+ })