@regardio/dev 2.4.0 → 2.4.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.
@@ -72,15 +72,13 @@ function runShipHotfix(subcommand, subArgs, cwd = process.cwd()) {
72
72
  process.exit(0);
73
73
  }
74
74
  console.log("\nBumping versions and updating CHANGELOGs...");
75
- for (const { package: pkg, bump } of bumps) {
76
- const originalCwd = process.cwd();
77
- process.chdir(pkg.path);
78
- try {
79
- runScript(`--filter-root release:${bump}`);
80
- } catch {
81
- runScript(`commit-and-tag-version ${bump === "patch" ? "" : `--release-as ${bump}`}`);
82
- }
83
- process.chdir(originalCwd);
75
+ const hasMajor = bumps.some((b) => b.bump === "major");
76
+ const hasMinor = bumps.some((b) => b.bump === "minor");
77
+ const highestBump = hasMajor ? "major" : hasMinor ? "minor" : "patch";
78
+ try {
79
+ runScript(`release:${highestBump}`);
80
+ } catch {
81
+ console.log("No release script found - skipping versioning (non-publishing repo)");
84
82
  }
85
83
  console.log("\nFetching latest state from origin...");
86
84
  git("fetch", "origin");
@@ -42,6 +42,14 @@ function runShipProduction(cwd = process.cwd()) {
42
42
  }
43
43
  console.log("\nCommits to be shipped to production:");
44
44
  console.log(ahead);
45
+ console.log("\nRunning quality checks on main...");
46
+ try {
47
+ runQualityChecks();
48
+ } catch {
49
+ console.error("\nQuality checks failed on main. Fix issues before shipping.");
50
+ process.exit(1);
51
+ }
52
+ console.log("✅ Quality checks passed");
45
53
  const packages = getWorkspacePackages(cwd);
46
54
  if (packages.length === 0) {
47
55
  console.error("No publishable workspace packages found.");
@@ -57,24 +65,14 @@ function runShipProduction(cwd = process.cwd()) {
57
65
  console.log("Aborted.");
58
66
  process.exit(0);
59
67
  }
60
- console.log("\nRunning quality checks on main...");
68
+ console.log("\nBumping versions and updating CHANGELOGs...");
69
+ const hasMajor = bumps.some((b) => b.bump === "major");
70
+ const hasMinor = bumps.some((b) => b.bump === "minor");
71
+ const highestBump = hasMajor ? "major" : hasMinor ? "minor" : "patch";
61
72
  try {
62
- runQualityChecks();
73
+ runScript(`release:${highestBump}`);
63
74
  } catch {
64
- console.error("\nQuality checks failed on main. Fix issues before shipping.");
65
- process.exit(1);
66
- }
67
- console.log("✅ Quality checks passed");
68
- console.log("\nBumping versions and updating CHANGELOGs...");
69
- for (const { package: pkg, bump } of bumps) {
70
- const originalCwd = process.cwd();
71
- process.chdir(pkg.path);
72
- try {
73
- runScript(`--filter-root release:${bump}`);
74
- } catch {
75
- runScript(`commit-and-tag-version ${bump === "patch" ? "" : `--release-as ${bump}`}`);
76
- }
77
- process.chdir(originalCwd);
75
+ console.log("No release script found - skipping versioning (non-publishing repo)");
78
76
  }
79
77
  console.log("\nMerging main into production...");
80
78
  git("checkout", "production");
@@ -10,9 +10,9 @@ interface BuildPlaywrightBaseConfigParams {
10
10
  webServerCommand: string;
11
11
  }
12
12
  /**
13
- * Build a base Playwright config object with Regardio defaults.
14
- * Consumers should wrap with defineConfig() in their local playwright.config.ts
15
- */
13
+ * Build a base Playwright config object with Regardio defaults.
14
+ * Consumers should wrap with defineConfig() in their local playwright.config.ts
15
+ */
16
16
  declare function buildPlaywrightBaseConfig({
17
17
  appUrl,
18
18
  appPort,
@@ -1,11 +1,11 @@
1
1
  //#region src/vitest/node.d.ts
2
2
  /**
3
- * Base Vitest configuration for Node.js packages.
4
- * Use with defineConfig() in your vitest.config.ts
5
- */
3
+ * Base Vitest configuration for Node.js packages.
4
+ * Use with defineConfig() in your vitest.config.ts
5
+ */
6
6
  declare const vitestNodeConfig: {
7
7
  coverage: {
8
- provider: "v8";
8
+ provider: 'v8';
9
9
  thresholds: {
10
10
  branches: number;
11
11
  functions: number;
@@ -1,11 +1,11 @@
1
1
  //#region src/vitest/react.d.ts
2
2
  /**
3
- * Vitest configuration for React packages with jsdom environment.
4
- * Use with defineConfig() in your vitest.config.ts
5
- */
3
+ * Vitest configuration for React packages with jsdom environment.
4
+ * Use with defineConfig() in your vitest.config.ts
5
+ */
6
6
  declare const vitestReactConfig: {
7
7
  coverage: {
8
- provider: "v8";
8
+ provider: 'v8';
9
9
  thresholds: {
10
10
  branches: number;
11
11
  functions: number;
@@ -25,7 +25,7 @@ main → staging (optional) → production
25
25
  - **`staging`** — optional validation environment. No versioning happens here.
26
26
  - **`production`** — versioned, published code only.
27
27
 
28
- When `ship-production` runs, it discovers all publishable workspace packages and asks you to assign a bump type — `0` (skip), `1` (patch), `2` (minor), or `3` (major) — to each one individually. Packages you skip are left untouched. For each package with a bump, it first tries to run the release script from the root package.json (using `--filter-root release:<type>`), and if that fails, falls back to running `commit-and-tag-version` directly with the appropriate bump flag. This bumps that package's version, rewrites its `CHANGELOG.md` using commits since its last scoped tag, and commits on `main`. The branches merge once after all bumps are applied. CI on `production` publishes only the packages whose version changed.
28
+ When `ship-production` runs, it discovers all publishable workspace packages and asks you to assign a bump type — `0` (skip), `1` (patch), `2` (minor), or `3` (major) — to each one individually. Packages you skip are left untouched. It determines the highest bump type across all selected packages and runs `pnpm release:<type>` at the root, which bumps versions, rewrites `CHANGELOG.md`, and commits on `main`. If no release script exists (non-publishing repos like channels), versioning is skipped entirely and only the git merges happen. The branches merge once after all bumps are applied. CI on `production` publishes only the packages whose version changed.
29
29
 
30
30
  ## How It Works
31
31
 
@@ -53,7 +53,8 @@ main ───────────┤ quality checks pass ├──►
53
53
  ship-production
54
54
  ┌──────────────────────────┐
55
55
  │ quality checks on main │
56
- pnpm release
56
+ select packages/bumps
57
+ │ pnpm release:<type>* │
57
58
  main ───────────┤ bumps version + ├──► production
58
59
  │ rewrites CHANGELOG.md │
59
60
  │ ff-merge main → prod │
@@ -76,7 +77,7 @@ production ─────┤ create hotfix/fix-name ├──► hotfix/fix-n
76
77
  ship-hotfix finish
77
78
  ┌──────────────────────────┐
78
79
  │ quality checks │
79
- │ pnpm release
80
+ │ pnpm release:<type>*
80
81
  hotfix/fix-name ┤ bumps version + ├──► production → staging → main
81
82
  │ rewrites CHANGELOG.md │
82
83
  │ merge to production │
@@ -137,10 +138,10 @@ This will:
137
138
  1. Guard: must be on `main`, working tree clean
138
139
  2. Fetch and verify `staging` + `production` branches exist
139
140
  3. Show commits to be shipped
140
- 4. For each publishable package: choose `0 (skip) / 1 (patch) / 2 (minor) / 3 (major)`
141
- 5. Confirm the planned bumps abort if declined or all skipped
142
- 6. Run full quality suite on `main` aborts on failure
143
- 7. For each non-skipped package: run release script from root (if defined) or `commit-and-tag-version` directly — bumps version, rewrites `CHANGELOG.md`, commits
141
+ 4. Run full quality suite on `main` aborts on failure
142
+ 5. For each publishable package: choose `0 (skip) / 1 (patch) / 2 (minor) / 3 (major)`
143
+ 6. Confirm the planned bumps abort if declined or all skipped
144
+ 7. Run `pnpm release:<type>` at the root (highest bump type) — bumps versions, rewrites `CHANGELOG.md`, commits. If no release script exists, skip versioning.
144
145
  8. Fast-forward merge `main` into `production` and push
145
146
  9. Sync `staging` with `production`
146
147
  10. Push `main` with `--follow-tags` to push all new version tags
@@ -167,15 +168,15 @@ git add . && git commit -m "fix: ..."
167
168
  pnpm ship:hotfix finish
168
169
  ```
169
170
 
170
- `finish` asks you to assign a bump type (`0` (skip), `1` (patch), `2` (minor), or `3` (major)) to each publishable package, runs the release script from root (if defined) or `commit-and-tag-version` directly for each non-skipped one to bump versions and update `CHANGELOG.md`, then merges `hotfix → production → staging → main` and deletes the hotfix branch. CI publishes from `production`.
171
+ `finish` asks you to assign a bump type (`0` (skip), `1` (patch), `2` (minor), or `3` (major)) to each publishable package, runs `pnpm release:<type>` at the root (highest bump type) to bump versions and update `CHANGELOG.md`. If no release script exists, versioning is skipped. Then it merges `hotfix → production → staging → main` and deletes the hotfix branch. CI publishes from `production`.
171
172
 
172
173
  ## Adoption
173
174
 
174
175
  Install `@regardio/dev` and:
175
176
 
176
- 1. **Add the scripts to `package.json`** (optional, for monorepos):
177
+ 1. **Add the scripts to `package.json`** (optional, for publishing repos):
177
178
 
178
- In a monorepo, you can define release scripts in the root `package.json` to centralize version management. The ship scripts will use these if available, and fall back to running `commit-and-tag-version` directly if not.
179
+ For repos that publish to npm, add release scripts to the root `package.json`:
179
180
 
180
181
  ```json
181
182
  {
@@ -191,7 +192,7 @@ Install `@regardio/dev` and:
191
192
  }
192
193
  ```
193
194
 
194
- For single-package repos or when you prefer direct `commit-and-tag-version` usage, you can omit the release scripts — the ship commands will call `commit-and-tag-version` directly.
195
+ For non-publishing repos (e.g., channels that deploy to servers), omit the release scripts — the ship commands will skip versioning and only perform the git merges. This makes the tools reusable across both publishing and non-publishing repositories.
195
196
 
196
197
  2. **Add a `.versionrc.json` to each publishable package** with a scoped `tagPrefix` so tags and changelogs stay isolated per package:
197
198
 
@@ -238,9 +239,11 @@ pnpm typecheck # Must succeed
238
239
  pnpm test # Must succeed
239
240
  ```
240
241
 
241
- ## Private Packages
242
+ ## Private Packages and Non-Publishing Repos
242
243
 
243
- Packages that should never be published to npm must set `"private": true` in `package.json`. `pnpm -r publish` skips them automatically. The git flow (`ship-staging`, `ship-production`, `ship-hotfix`) works identically — version bumps and branch promotion continue as normal; only the npm publish step is skipped.
244
+ Packages that should never be published to npm must set `"private": true` in `package.json`. `pnpm -r publish` skips them automatically.
245
+
246
+ For non-publishing repos (e.g., channels that deploy directly to servers instead of npm), omit the `release:*` scripts from `package.json`. The ship tools will skip versioning entirely and only perform the git merges. CI can then handle deployment to servers based on the `production` branch.
244
247
 
245
248
  ## Related
246
249
 
@@ -17,33 +17,62 @@ Strict, shared TypeScript presets for Regardio projects. Extending from `@regard
17
17
 
18
18
  | Preset | Use case |
19
19
  |--------|----------|
20
- | `@regardio/dev/typescript/base` | Node.js packages, libraries |
21
- | `@regardio/dev/typescript/react` | React applications and components |
22
- | `@regardio/dev/typescript/build` | Build-specific settings (extends base) |
20
+ | `@regardio/dev/typescript/base` | Non-publishing packages and meta-configs (e.g. the workspace root) |
21
+ | `@regardio/dev/typescript/library` | Published Node.js packages adds declaration enforcement |
22
+ | `@regardio/dev/typescript/react` | React apps and channels — adds JSX and DOM libs |
23
+ | `@regardio/dev/typescript/react-library` | Published React packages — JSX, DOM libs, and declaration enforcement |
24
+ | `@regardio/dev/typescript/build` | Build-time emission settings (pair with any of the above) |
25
+
26
+ ### Choosing a preset
27
+
28
+ The guiding question is whether the package **publishes type declarations** to consumers.
29
+
30
+ - **App or channel** (`private: true`) → `react` (or `base` for non-React)
31
+ - **Published library without React** → `library`
32
+ - **Published library with React** → `react-library`
33
+
34
+ The `library` and `react-library` presets add two settings on top of the base:
35
+
36
+ - `declaration: true` — validates that `.d.ts` files can be generated (even when `noEmit: true` during typecheck)
37
+ - `isolatedDeclarations: true` — enforces that every exported declaration carries an explicit type annotation, enabling per-file parallel declaration generation
38
+
39
+ `isolatedDeclarations` is a library-authoring constraint. It requires explicit return types on exported functions and explicit annotations on exported variables. Applying it to app code is unnecessarily strict — especially with frameworks like TanStack Router whose `Route` objects carry deeply inferred generics that cannot be spelled out without extraordinary verbosity.
23
40
 
24
41
  ## Configuration
25
42
 
26
- ### `tsconfig.json`
43
+ ### App or channel
27
44
 
28
45
  ```json
29
46
  {
30
- "extends": "@regardio/dev/typescript/base",
47
+ "compilerOptions": {
48
+ "paths": { "#/*": ["./src/*"] }
49
+ },
50
+ "extends": "@regardio/dev/typescript/react",
51
+ "include": ["**/*.ts", "**/*.tsx", "**/*.d.ts"]
52
+ }
53
+ ```
54
+
55
+ ### Published Node.js library
56
+
57
+ ```json
58
+ {
59
+ "extends": "@regardio/dev/typescript/library",
31
60
  "include": ["src/**/*.ts"]
32
61
  }
33
62
  ```
34
63
 
35
- For React projects:
64
+ ### Published React library
36
65
 
37
66
  ```json
38
67
  {
39
- "extends": "@regardio/dev/typescript/react",
68
+ "extends": "@regardio/dev/typescript/react-library",
40
69
  "include": ["src/**/*.ts", "src/**/*.tsx"]
41
70
  }
42
71
  ```
43
72
 
44
73
  ### `tsconfig.build.json`
45
74
 
46
- A separate build config for production output:
75
+ Pair any preset with `build` for production output:
47
76
 
48
77
  ```json
49
78
  {
@@ -51,28 +80,26 @@ A separate build config for production output:
51
80
  "outDir": "./dist",
52
81
  "rootDir": "./src"
53
82
  },
54
- "extends": ["./tsconfig.json", "@regardio/dev/typescript/build"],
55
- "include": ["src/**/*.ts"]
83
+ "extends": ["./tsconfig.json", "@regardio/dev/typescript/build"]
56
84
  }
57
85
  ```
58
86
 
59
87
  ## Strict settings
60
88
 
61
- The base config turns on strict type-checking across the board:
89
+ All presets share the same strict type-checking baseline:
62
90
 
63
91
  - `strict: true` — every strict type-checking option
64
92
  - `noUncheckedIndexedAccess: true` — adds `undefined` to index signatures
65
- - `exactOptionalPropertyTypes: true` — distinguishes `undefined` from missing
66
93
  - `noImplicitReturns: true` — every code path returns a value
67
94
  - `noFallthroughCasesInSwitch: true` — prevents switch-fallthrough surprises
95
+ - `verbatimModuleSyntax: true` — `import type` vs. `import` must be explicit
68
96
 
69
97
  ## Scripts
70
98
 
71
99
  ```json
72
100
  {
73
101
  "scripts": {
74
- "build": "exec-tsc --project tsconfig.build.json",
75
- "typecheck": "exec-tsc --noEmit"
102
+ "typecheck": "tsc --noEmit"
76
103
  }
77
104
  }
78
105
  ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package.json",
3
3
  "name": "@regardio/dev",
4
- "version": "2.4.0",
4
+ "version": "2.4.1",
5
5
  "private": false,
6
6
  "description": "Regardio development presets: biome, typescript, commitlint, markdownlint, vitest, playwright, sqlfluff, husky, and GitLab-flow ship tooling",
7
7
  "keywords": [
@@ -44,7 +44,9 @@
44
44
  },
45
45
  "./typescript/base": "./src/typescript/base.json",
46
46
  "./typescript/build": "./src/typescript/build.json",
47
+ "./typescript/library": "./src/typescript/library.json",
47
48
  "./typescript/react": "./src/typescript/react.json",
49
+ "./typescript/react-library": "./src/typescript/react-library.json",
48
50
  "./vitest/node": {
49
51
  "import": "./dist/vitest/node.mjs",
50
52
  "types": "./dist/vitest/node.d.mts"
@@ -61,6 +63,7 @@
61
63
  },
62
64
  "files": [
63
65
  "dist",
66
+ "LICENSE",
64
67
  "src/biome",
65
68
  "src/commitlint",
66
69
  "src/markdownlint",
@@ -73,7 +76,7 @@
73
76
  "@total-typescript/ts-reset": "0.6.1",
74
77
  "@types/node": "25.6.0",
75
78
  "@vitest/coverage-v8": "4.1.5",
76
- "tsdown": "0.21.10",
79
+ "tsdown": "0.22.0",
77
80
  "vitest": "4.1.5"
78
81
  },
79
82
  "peerDependencies": {
@@ -90,9 +93,6 @@
90
93
  "typescript": ">=6",
91
94
  "vitest": ">=4"
92
95
  },
93
- "engines": {
94
- "node": ">=24"
95
- },
96
96
  "scripts": {
97
97
  "build": "tsdown",
98
98
  "clean": "rimraf .turbo dist",
@@ -7,13 +7,11 @@
7
7
  "allowUnusedLabels": false,
8
8
  "alwaysStrict": true,
9
9
  "checkJs": false,
10
- "declaration": true,
11
10
  "esModuleInterop": true,
12
11
  "exactOptionalPropertyTypes": false,
13
12
  "forceConsistentCasingInFileNames": true,
14
13
  "incremental": false,
15
14
  "inlineSources": false,
16
- "isolatedDeclarations": true,
17
15
  "isolatedModules": true,
18
16
  "module": "ESNext",
19
17
  "moduleDetection": "force",
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://www.schemastore.org/tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "isolatedDeclarations": true
6
+ },
7
+ "extends": "./base.json"
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://www.schemastore.org/tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "isolatedDeclarations": true
6
+ },
7
+ "extends": "./react.json"
8
+ }