@rtorcato/repo-tooling 3.2.2 → 3.2.4
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/dist/cli/generators/linting.js +11 -1
- package/dist/cli/generators/package-json.js +27 -0
- package/dist/cli/generators/testing.js +12 -1
- package/dist/cli/generators/tsconfig.js +6 -0
- package/dist/cli/generators/typedoc.js +1 -1
- package/dist/languages/js/ci.js +6 -6
- package/dist/languages/swift/ci.js +2 -2
- package/package.json +1 -1
- package/tooling/commitlint/commitlint.mjs +11 -1
- package/tooling/eslint/base.mjs +8 -0
- package/tooling/github-actions/workflows/cloudflare-pages.yml +2 -2
- package/tooling/github-actions/workflows/docker-publish.yml +1 -1
- package/tooling/github-actions/workflows/preview-deployments.yml +2 -2
- package/tooling/github-actions/workflows/vercel-deploy.yml +2 -2
- package/tooling/typescript/tsconfig.base.json +6 -2
- package/tooling/typescript/tsconfig.next.json +8 -1
- package/tooling/typescript/tsconfig.react.json +7 -1
|
@@ -40,7 +40,17 @@ export async function generateBiomeConfig(targetDir) {
|
|
|
40
40
|
export async function generateESLintConfig(config, targetDir) {
|
|
41
41
|
const eslintConfigPath = path.join(targetDir, 'eslint.config.mjs');
|
|
42
42
|
const configType = config.linting.eslintConfig || 'base';
|
|
43
|
-
|
|
43
|
+
// eslint/nextjs is a fragment: it registers the @next/next plugin and its
|
|
44
|
+
// rules but sets no parser, so on its own it can't even parse .tsx ("Parsing
|
|
45
|
+
// error: Unexpected token <"). It has to be layered onto the base config,
|
|
46
|
+
// which is what brings typescript-eslint.
|
|
47
|
+
const eslintConfig = configType === 'nextjs'
|
|
48
|
+
? `import base from '@rtorcato/repo-tooling/eslint/base'
|
|
49
|
+
import nextjs from '@rtorcato/repo-tooling/eslint/nextjs'
|
|
50
|
+
|
|
51
|
+
export default [...base, ...nextjs]
|
|
52
|
+
`
|
|
53
|
+
: `import { default as config } from '@rtorcato/repo-tooling/eslint/${configType}'
|
|
44
54
|
|
|
45
55
|
export default config
|
|
46
56
|
`;
|
|
@@ -237,6 +237,24 @@ function getDependencies(config) {
|
|
|
237
237
|
if (config.linting.tool === 'eslint' || config.linting.tool === 'both') {
|
|
238
238
|
deps['eslint'] = '^9.0.0';
|
|
239
239
|
deps['prettier'] = '^3.0.0';
|
|
240
|
+
// Everything tooling/eslint/base.mjs imports. All optional peers of
|
|
241
|
+
// repo-tooling, so pnpm skips them and `eslint .` dies on the config
|
|
242
|
+
// import — the scaffold shipped a lint script that could never run.
|
|
243
|
+
deps['@eslint/js'] = '^9.0.0';
|
|
244
|
+
deps['@typescript-eslint/eslint-plugin'] = '^8.0.0';
|
|
245
|
+
deps['typescript-eslint'] = '^8.0.0';
|
|
246
|
+
deps['eslint-plugin-import'] = '^2.0.0';
|
|
247
|
+
deps['eslint-plugin-jest'] = '^29.0.0';
|
|
248
|
+
}
|
|
249
|
+
// The shipped prettier preset lists this in `plugins`, and the nextjs eslint
|
|
250
|
+
// preset imports the Next plugin. Both are only *optional* peers of
|
|
251
|
+
// repo-tooling, so pnpm skips them and the scaffold's first format/lint dies
|
|
252
|
+
// with ERR_MODULE_NOT_FOUND.
|
|
253
|
+
if (config.formatting.tool === 'prettier') {
|
|
254
|
+
deps['@ianvs/prettier-plugin-sort-imports'] = '^4.7.0';
|
|
255
|
+
}
|
|
256
|
+
if (config.linting.eslintConfig === 'nextjs') {
|
|
257
|
+
deps['@next/eslint-plugin-next'] = '^16.2.11';
|
|
240
258
|
}
|
|
241
259
|
// Testing frameworks
|
|
242
260
|
if (config.testing.framework === 'vitest') {
|
|
@@ -266,6 +284,10 @@ function getDependencies(config) {
|
|
|
266
284
|
}
|
|
267
285
|
else if (config.bundler === 'esbuild') {
|
|
268
286
|
deps['esbuild'] = '^0.25.0';
|
|
287
|
+
// The generated build.mjs imports this directly. It's only an *optional*
|
|
288
|
+
// peer of repo-tooling, so pnpm won't pull it in — without it here every
|
|
289
|
+
// esbuild scaffold fails its first `pnpm build` with ERR_MODULE_NOT_FOUND.
|
|
290
|
+
deps['esbuild-node-externals'] = '^1.18.0';
|
|
269
291
|
}
|
|
270
292
|
else if (config.bundler === 'rollup') {
|
|
271
293
|
deps['rollup'] = '^4.0.0';
|
|
@@ -278,6 +300,11 @@ function getDependencies(config) {
|
|
|
278
300
|
}
|
|
279
301
|
else if (config.bundler === 'vite') {
|
|
280
302
|
deps['vite'] = '^6.0.0';
|
|
303
|
+
// generateViteConfig emits `import react from '@vitejs/plugin-react'` for
|
|
304
|
+
// react-app, so the plugin has to be installed or `vite build` can't even
|
|
305
|
+
// load the config. Keep this condition in step with that one.
|
|
306
|
+
if (config.projectType === 'react-app')
|
|
307
|
+
deps['@vitejs/plugin-react'] = '^5.0.0';
|
|
281
308
|
}
|
|
282
309
|
// Tailwind CSS v4 — CSS-first, wired via the PostCSS plugin.
|
|
283
310
|
if (config.tailwind) {
|
|
@@ -16,10 +16,21 @@ export async function generateTestingConfigs(config, targetDir) {
|
|
|
16
16
|
}
|
|
17
17
|
export async function generateVitestConfig(config, targetDir) {
|
|
18
18
|
const vitestConfigPath = path.join(targetDir, 'vitest.config.ts');
|
|
19
|
+
// Vite reads `jsx` from tsconfig, and the next preset sets it to "preserve" so
|
|
20
|
+
// Next's own compiler handles the transform. Vitest has no such compiler, so
|
|
21
|
+
// .tsx tests fail to parse ("Unexpected token <") unless we opt back in here.
|
|
22
|
+
// `oxc` (not `esbuild`) is the Vite 8 spelling — vitest ^4 resolves Vite 8,
|
|
23
|
+
// and Vite 8 silently ignores the old `esbuild` key.
|
|
24
|
+
const jsxOverride = config.projectType === 'nextjs-app'
|
|
25
|
+
? ` // tsconfig sets jsx: "preserve" for Next's compiler; vitest needs a
|
|
26
|
+
// transform of its own or .tsx tests won't parse.
|
|
27
|
+
oxc: { jsx: { runtime: 'automatic' } },
|
|
28
|
+
`
|
|
29
|
+
: '';
|
|
19
30
|
const vitestConfig = `import { defineConfig } from 'vitest/config'
|
|
20
31
|
|
|
21
32
|
export default defineConfig({
|
|
22
|
-
test: {
|
|
33
|
+
${jsxOverride} test: {
|
|
23
34
|
globals: true,
|
|
24
35
|
environment: '${config.testing.environment === 'browser' ? 'jsdom' : 'node'}',
|
|
25
36
|
setupFiles: ['./vitest.setup.ts'],
|
|
@@ -19,6 +19,12 @@ export async function generateTSConfig(config, targetDir) {
|
|
|
19
19
|
tsconfig.compilerOptions.outDir = './dist';
|
|
20
20
|
tsconfig.compilerOptions.rootDir = './src';
|
|
21
21
|
}
|
|
22
|
+
// web-app is the only browser target that lands on the `base` preset, whose
|
|
23
|
+
// lib is ES2022 — so `document`/`window` don't typecheck. The react and next
|
|
24
|
+
// presets already add the DOM libs themselves.
|
|
25
|
+
if (config.projectType === 'web-app' && preset === 'base') {
|
|
26
|
+
tsconfig.compilerOptions.lib = ['ES2022', 'DOM', 'DOM.Iterable'];
|
|
27
|
+
}
|
|
22
28
|
if (config.projectType === 'nextjs-app') {
|
|
23
29
|
tsconfig.include = ['next-env.d.ts', 'src', 'app', 'pages', 'components', 'reset.d.ts'];
|
|
24
30
|
tsconfig.exclude.push('.next');
|
package/dist/languages/js/ci.js
CHANGED
|
@@ -15,7 +15,7 @@ const SETUP_STEPS = ` - name: 📦 Checkout repository
|
|
|
15
15
|
uses: actions/checkout@v7
|
|
16
16
|
|
|
17
17
|
- name: 📦 Setup Node.js
|
|
18
|
-
uses: actions/setup-node@
|
|
18
|
+
uses: actions/setup-node@v7
|
|
19
19
|
with:
|
|
20
20
|
node-version-file: .nvmrc
|
|
21
21
|
|
|
@@ -23,7 +23,7 @@ const SETUP_STEPS = ` - name: 📦 Checkout repository
|
|
|
23
23
|
uses: pnpm/action-setup@v6
|
|
24
24
|
|
|
25
25
|
- name: 📦 Restore dependencies cache
|
|
26
|
-
uses: actions/cache@
|
|
26
|
+
uses: actions/cache@v6
|
|
27
27
|
with:
|
|
28
28
|
path: |
|
|
29
29
|
~/.pnpm-store
|
|
@@ -38,7 +38,7 @@ const DEPENDENCIES_JOB = {
|
|
|
38
38
|
uses: actions/checkout@v7
|
|
39
39
|
|
|
40
40
|
- name: 📦 Setup Node.js
|
|
41
|
-
uses: actions/setup-node@
|
|
41
|
+
uses: actions/setup-node@v7
|
|
42
42
|
with:
|
|
43
43
|
node-version-file: .nvmrc
|
|
44
44
|
|
|
@@ -50,7 +50,7 @@ const DEPENDENCIES_JOB = {
|
|
|
50
50
|
run: echo "key=\${{ runner.os }}-pnpm-\${{ hashFiles('**/pnpm-lock.yaml') }}" >> $GITHUB_OUTPUT
|
|
51
51
|
|
|
52
52
|
- name: 📦 Cache dependencies
|
|
53
|
-
uses: actions/cache@
|
|
53
|
+
uses: actions/cache@v6
|
|
54
54
|
with:
|
|
55
55
|
path: |
|
|
56
56
|
~/.pnpm-store
|
|
@@ -164,7 +164,7 @@ ${attw}${publint}
|
|
|
164
164
|
token: \${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
|
165
165
|
|
|
166
166
|
- name: 📦 Setup Node.js
|
|
167
|
-
uses: actions/setup-node@
|
|
167
|
+
uses: actions/setup-node@v7
|
|
168
168
|
with:
|
|
169
169
|
node-version-file: .nvmrc
|
|
170
170
|
registry-url: 'https://registry.npmjs.org'
|
|
@@ -173,7 +173,7 @@ ${attw}${publint}
|
|
|
173
173
|
uses: pnpm/action-setup@v6
|
|
174
174
|
|
|
175
175
|
- name: 📦 Restore dependencies cache
|
|
176
|
-
uses: actions/cache@
|
|
176
|
+
uses: actions/cache@v6
|
|
177
177
|
with:
|
|
178
178
|
path: |
|
|
179
179
|
~/.pnpm-store
|
|
@@ -45,7 +45,7 @@ const XCODE_SETUP = ` - name: 📦 Checkout repository
|
|
|
45
45
|
* to rebuild; key on Package.resolved so the cache invalidates with the graph.
|
|
46
46
|
*/
|
|
47
47
|
const SPM_CACHE = ` - name: 📦 Cache SwiftPM
|
|
48
|
-
uses: actions/cache@
|
|
48
|
+
uses: actions/cache@v6
|
|
49
49
|
with:
|
|
50
50
|
path: |
|
|
51
51
|
.build
|
|
@@ -118,7 +118,7 @@ ${pkg.platforms.map((p) => ` - ${p}`).join('\n')}`,
|
|
|
118
118
|
steps: `${XCODE_SETUP}
|
|
119
119
|
|
|
120
120
|
- name: 📦 Cache DerivedData
|
|
121
|
-
uses: actions/cache@
|
|
121
|
+
uses: actions/cache@v6
|
|
122
122
|
with:
|
|
123
123
|
path: ~/Library/Developer/Xcode/DerivedData
|
|
124
124
|
key: \${{ runner.os }}-derived-\${{ matrix.platform }}-\${{ hashFiles('**/Package.resolved') }}
|
package/package.json
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
extends: ["@commitlint/config-conventional"],
|
|
3
|
-
ignores: [
|
|
3
|
+
ignores: [
|
|
4
|
+
(commit) => commit.includes("[skip ci]"),
|
|
5
|
+
// Bot commit bodies are machine-written blocks (dependabot's
|
|
6
|
+
// `- dependency-name: …` YAML) that never wrap at 72, so every bot PR
|
|
7
|
+
// failed body-max-line-length. commitlint can't relax a single rule per
|
|
8
|
+
// commit, so skip bot commits wholesale — squash-merge uses the PR
|
|
9
|
+
// title, which is still linted on the merge commit.
|
|
10
|
+
// ponytail: matches the trailer, not a bare "[bot]", so a human commit
|
|
11
|
+
// that merely mentions a bot is still linted.
|
|
12
|
+
(commit) => /^Signed-off-by: .*\[bot\]/m.test(commit),
|
|
13
|
+
],
|
|
4
14
|
rules: {
|
|
5
15
|
// Enforce strict type validation
|
|
6
16
|
"type-enum": [
|
package/tooling/eslint/base.mjs
CHANGED
|
@@ -43,6 +43,14 @@ export default tseslint.config(
|
|
|
43
43
|
ignores: [
|
|
44
44
|
//
|
|
45
45
|
'**/*.config.js',
|
|
46
|
+
// Root-level TS config files are outside the tsconfig `include` of every
|
|
47
|
+
// app preset, and this config lints type-aware (parserOptions.project),
|
|
48
|
+
// so linting them fails with "file was not found in any of the provided
|
|
49
|
+
// project(s)". The .js forms were already ignored; these are the same
|
|
50
|
+
// thing (the scaffold emits vitest.config.ts / vitest.setup.ts).
|
|
51
|
+
'**/*.config.ts',
|
|
52
|
+
'**/*.config.mts',
|
|
53
|
+
'**/*.setup.ts',
|
|
46
54
|
'.turbo',
|
|
47
55
|
'dist',
|
|
48
56
|
'build',
|
|
@@ -18,10 +18,10 @@ jobs:
|
|
|
18
18
|
runs-on: ubuntu-latest
|
|
19
19
|
steps:
|
|
20
20
|
- name: Checkout
|
|
21
|
-
uses: actions/checkout@
|
|
21
|
+
uses: actions/checkout@v7
|
|
22
22
|
|
|
23
23
|
- name: Setup Node.js
|
|
24
|
-
uses: actions/setup-node@
|
|
24
|
+
uses: actions/setup-node@v7
|
|
25
25
|
with:
|
|
26
26
|
node-version-file: .nvmrc
|
|
27
27
|
|
|
@@ -20,10 +20,10 @@ jobs:
|
|
|
20
20
|
runs-on: ubuntu-latest
|
|
21
21
|
steps:
|
|
22
22
|
- name: Checkout
|
|
23
|
-
uses: actions/checkout@
|
|
23
|
+
uses: actions/checkout@v7
|
|
24
24
|
|
|
25
25
|
- name: Setup Node.js
|
|
26
|
-
uses: actions/setup-node@
|
|
26
|
+
uses: actions/setup-node@v7
|
|
27
27
|
with:
|
|
28
28
|
node-version-file: .nvmrc
|
|
29
29
|
|
|
@@ -20,10 +20,10 @@ jobs:
|
|
|
20
20
|
runs-on: ubuntu-latest
|
|
21
21
|
steps:
|
|
22
22
|
- name: Checkout
|
|
23
|
-
uses: actions/checkout@
|
|
23
|
+
uses: actions/checkout@v7
|
|
24
24
|
|
|
25
25
|
- name: Setup Node.js
|
|
26
|
-
uses: actions/setup-node@
|
|
26
|
+
uses: actions/setup-node@v7
|
|
27
27
|
with:
|
|
28
28
|
node-version-file: .nvmrc
|
|
29
29
|
|
|
@@ -9,8 +9,12 @@
|
|
|
9
9
|
// "moduleResolution": "node", // Prefer "bundler" if you're using Vite, esbuild, etc.
|
|
10
10
|
// "target": "esnext", //
|
|
11
11
|
"lib": ["ES2022"], // Specify library files to be included in the compilation
|
|
12
|
-
|
|
13
|
-
"
|
|
12
|
+
// ${configDir} for the same reason as paths/tsBuildInfoFile below: a bare
|
|
13
|
+
// "src" resolves against THIS file, i.e. inside node_modules, so every
|
|
14
|
+
// consumer that didn't redeclare rootDir got TS6059 "not under rootDir" the
|
|
15
|
+
// moment a file outside the preset's own directory entered the program.
|
|
16
|
+
"rootDir": "${configDir}/src",
|
|
17
|
+
"outDir": "${configDir}/dist",
|
|
14
18
|
|
|
15
19
|
|
|
16
20
|
// 🔍 JavaScript Support
|
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
"extends": "./tsconfig.base.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"jsx": "preserve", // Let Next.js handle JSX transformation
|
|
5
|
+
// The base pins rootDir to src/, but `include` below spans app/, pages/ and
|
|
6
|
+
// components/ — all siblings of src/ — so tsc raised TS6059 on any Next repo
|
|
7
|
+
// using the app router. These presets are noEmit, so rootDir buys nothing
|
|
8
|
+
// here beyond that trap; widen it to the project root.
|
|
9
|
+
"rootDir": "${configDir}",
|
|
5
10
|
"lib": ["DOM", "DOM.Iterable", "ESNext"], // Include DOM types for browser APIs
|
|
6
11
|
"module": "esnext", // Next.js expects ESNext modules
|
|
7
12
|
"moduleResolution": "bundler", // Modern module resolution for Next.js
|
|
8
13
|
"allowJs": true, // Allow JavaScript files
|
|
9
14
|
"esModuleInterop": true, // Interop for CommonJS/ESM
|
|
10
|
-
|
|
15
|
+
// No "tailwindcss" — see tsconfig.react.json; it broke TS2688 for every
|
|
16
|
+
// project without Tailwind installed.
|
|
17
|
+
"types": ["react", "vitest"],
|
|
11
18
|
"plugins": [ { "name": "next" } ], // Next.js plugin for TypeScript
|
|
12
19
|
// ${configDir} anchors paths to the consuming project (drops deprecated baseUrl)
|
|
13
20
|
"paths": {
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
"extends": "./tsconfig.base.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"jsx": "react-jsx", // Use the new JSX transform for React 17+
|
|
5
|
+
// Same TS6059 trap as the next preset: `include` below covers index.d.ts and
|
|
6
|
+
// types/ alongside src/, which a src-rooted rootDir can't contain.
|
|
7
|
+
"rootDir": "${configDir}",
|
|
5
8
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],// Include DOM types for browser APIs
|
|
6
|
-
"
|
|
9
|
+
// No "tailwindcss": listing it here made tsc fail with TS2688 on every React
|
|
10
|
+
// project that doesn't install Tailwind. Tailwind v4 is CSS-first and ships
|
|
11
|
+
// no ambient types a project needs, so nothing is lost by dropping it.
|
|
12
|
+
"types": ["react", "react-dom", "vitest"],
|
|
7
13
|
// ${configDir} anchors paths to the consuming project (drops deprecated baseUrl)
|
|
8
14
|
"paths": {
|
|
9
15
|
"~/*": ["${configDir}/src/*"],
|