@regardio/dev 1.6.0 → 1.7.0

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/README.md CHANGED
@@ -1,453 +1,87 @@
1
1
  # @regardio/dev
2
2
 
3
- Developer tooling for testing, linting, and build workflows in Regardio projects.
3
+ A unified developer toolchain for consistent, high-quality TypeScript projects.
4
4
 
5
- ## Philosophy
6
-
7
- We believe in **balanced strictness**: rigorous enough to catch bugs early and maintain consistency, yet practical enough to not impede development velocity.
5
+ ## Purpose
8
6
 
9
- ### Strict by Default
7
+ `@regardio/dev` provides a complete, opinionated development environment that can be adopted by any JavaScript/TypeScript project. It bundles best-in-class tools with sensible defaults, enabling teams to focus on building features rather than configuring tooling.
10
8
 
11
- - **TypeScript strict mode** with `noUncheckedIndexedAccess` and `exactOptionalPropertyTypes`
12
- - **Comprehensive linting** via Biome for code quality, style, and complexity
13
- - **Conventional commits** enforced through commitlint
14
- - **Automated testing** as a first-class concern
9
+ **One dependency. Zero configuration conflicts. Consistent quality across all projects.**
15
10
 
16
- ### Practical in Application
11
+ ## Philosophy
17
12
 
18
- Strictness serves developers, not the other way around. Our approach:
13
+ We believe in **balanced strictness**: rigorous enough to catch bugs early and maintain consistency, yet practical enough to not impede development velocity.
19
14
 
15
+ - **Strict by default** - TypeScript strict mode, comprehensive linting, conventional commits
20
16
  - **Sensible defaults** - Shared configs that work out of the box
21
17
  - **Minimal boilerplate** - Extend presets, override only what's necessary
22
18
  - **Fast feedback** - Quick linting and type checking during development
23
- - **Clear exceptions** - When rules don't apply, document why with `// biome-ignore` or `@ts-expect-error`
24
-
25
- ### The Balance
26
-
27
- We optimize for:
28
-
29
- 1. **Catching bugs before they ship** - Strict types prevent runtime errors
30
- 2. **Readable, maintainable code** - Consistent style reduces cognitive load
31
- 3. **Developer experience** - Tools should help, not hinder
32
- 4. **Team velocity** - Shared understanding through enforced conventions
33
19
 
34
- Exceptions are allowed but must be intentional and documented. The goal is code that's correct, consistent, and a pleasure to work with.
20
+ The goal is code that's correct, consistent, and a pleasure to work with.
35
21
 
36
- ## What's inside
22
+ ## What's Inside
37
23
 
38
- - **CLI bins**: exec-clean, exec-husky, exec-p, exec-s, exec-ts, exec-tsc, flow-release, lint-biome, lint-commit, lint-md
39
- - **Config presets**: Biome, Commitlint, Markdownlint, TypeScript (base/react)
40
- - **Testing configs**: Vitest (node/react), Playwright base config, Testing Library setup
41
- - **Dev dependencies**: All commonly needed testing and linting packages bundled
42
- - **[Developer Documentation](./docs/README.md)**: Foundational principles, testing philosophy, naming conventions
24
+ | Category | Tools |
25
+ |----------|-------|
26
+ | **Linting** | Biome, Markdownlint, Commitlint |
27
+ | **Testing** | Vitest, Playwright, Testing Library |
28
+ | **Build** | TypeScript, tsx, Vite |
29
+ | **Workflow** | Husky, Changesets |
30
+ | **CLI utilities** | exec-clean, exec-p, exec-s, exec-ts, flow-release, lint-biome, lint-md |
43
31
 
44
- ## Install
32
+ ## Quick Start
45
33
 
46
34
  ```bash
47
35
  pnpm add -D @regardio/dev
48
36
  ```
49
37
 
50
- ## Testing
51
-
52
- ### Vitest Configuration
53
-
54
- ```typescript
55
- // vitest.config.ts (Node.js package)
56
- import { defineConfig } from 'vitest/config';
57
- import { vitestNodeConfig } from '@regardio/dev/vitest/node';
58
-
59
- export default defineConfig({ test: vitestNodeConfig });
60
- ```
61
-
62
- ```typescript
63
- // vitest.config.ts (React package)
64
- import { defineConfig } from 'vitest/config';
65
- import { vitestReactConfig } from '@regardio/dev/vitest/react';
66
-
67
- export default defineConfig({ test: vitestReactConfig });
68
- ```
69
-
70
- ### Playwright Configuration
71
-
72
- ```typescript
73
- // playwright.config.ts
74
- import { defineConfig, devices } from '@playwright/test';
75
- import { buildPlaywrightBaseConfig } from '@regardio/dev/playwright';
76
-
77
- export default defineConfig(
78
- buildPlaywrightBaseConfig({
79
- appPort: 5100,
80
- appUrl: 'http://localhost:5100',
81
- devices,
82
- webServerCommand: 'vite preview',
83
- }),
84
- );
85
- ```
86
-
87
- ### Testing Library Setup
88
-
89
- For React packages, create a `src/test-setup.ts`:
90
-
91
- ```typescript
92
- import '@regardio/dev/testing/setup-react';
93
- ```
94
-
95
- ## Config Presets
96
-
97
- - **Biome**: `"extends": ["@regardio/dev/biome"]`
98
- - **TypeScript**: `@regardio/dev/typescript/base.json`, `@regardio/dev/typescript/react.json`
99
- - **Commitlint**: `module.exports = require('@regardio/dev/commitlint');`
100
- - **Markdownlint**: `"extends": "@regardio/dev/markdownlint"`
101
-
102
- ## Scripts (examples)
103
-
104
- ```json
105
- {
106
- "scripts": {
107
- "fix": "exec-p fix:*",
108
- "fix:biome": "lint-biome check --write --unsafe .",
109
- "fix:md": "lint-md --fix \"**/*.md\" \"**/*.mdx\" \"!**/node_modules/**\" \"!**/dist/**\"",
110
- "lint": "exec-p lint:*",
111
- "lint:biome": "lint-biome check .",
112
- "lint:md": "lint-md \"**/*.md\" \"**/*.mdx\" \"!**/node_modules/**\" \"!**/dist/**\"",
113
- "prepare": "exec-husky",
114
- "test": "exec-p test:*",
115
- "test:e2e": "playwright test",
116
- "test:unit": "vitest run",
117
- }
118
- }
119
- ```
120
-
121
- ## Local Config Files
122
-
123
- Each package needs a few local config files that extend the shared presets. Here's the minimal setup:
124
-
125
- ### Required Files
126
-
127
- All config files should be placed in the **package root** (same level as `package.json`):
128
-
129
- | File | Purpose | Extends |
130
- |------|---------|---------|
131
- | `tsconfig.json` | TypeScript base config | `@regardio/dev/typescript/base.json` or `react.json` |
132
- | `tsconfig.build.json` | Build-specific config | `./tsconfig.json` + `@regardio/dev/typescript/build.json` |
133
- | `biome.jsonc` | Linting and formatting | `@regardio/dev/biome` |
134
- | `.commitlintrc.json` | Commit message linting | `@regardio/dev/commitlint` (workspace root only) |
135
- | `.markdownlint.jsonc` | Markdown linting | `@regardio/dev/markdownlint` |
136
- | `vitest.config.ts` | Unit test config | Uses `vitestNodeConfig` or `vitestReactConfig` |
137
- | `playwright.config.ts` | E2E test config | Uses `buildPlaywrightBaseConfig` |
138
- | `.hintrc` | webhint config (optional) | `development` preset |
139
-
140
- ### File Naming Conventions
141
-
142
- - **JSON configs**: Use the standard names expected by each tool
143
- - `.commitlintrc.json` (not `commitlint.config.json`)
144
- - `.markdownlint.jsonc` (supports comments)
145
- - `biome.jsonc` (supports comments, Biome also accepts `biome.json`)
146
- - **TypeScript configs**: Always `tsconfig*.json`
147
- - **Test configs**: `vitest.config.ts`, `playwright.config.ts`
148
- - **Hidden files**: Prefix with `.` for tool-specific configs (`.hintrc`, `.editorconfig`)
149
-
150
- ### Workspace Root vs Package Root
151
-
152
- | Location | Files |
153
- |----------|-------|
154
- | **Workspace root** | `.editorconfig`, `.commitlintrc.json`, `.gitignore`, AI agent configs |
155
- | **Each package** | `tsconfig.json`, `tsconfig.build.json`, `biome.jsonc`, `.markdownlint.jsonc`, test configs |
156
-
157
- ### Example: tsconfig.json (Node.js package)
158
-
159
- ```json
160
- {
161
- "extends": "@regardio/dev/typescript/base.json",
162
- "include": ["src/**/*.ts"]
163
- }
164
- ```
165
-
166
- ### Example: tsconfig.build.json
167
-
168
- ```json
169
- {
170
- "compilerOptions": {
171
- "outDir": "./dist",
172
- "rootDir": "./src"
173
- },
174
- "extends": ["./tsconfig.json", "@regardio/dev/typescript/build.json"],
175
- "include": ["src/**/*.ts"]
176
- }
177
- ```
178
-
179
- ### Example: biome.jsonc
38
+ Extend the shared configs in your project:
180
39
 
181
40
  ```jsonc
182
- {
183
- "$schema": "https://biomejs.dev/schemas/latest/schema.json",
184
- "extends": ["@regardio/dev/biome"]
185
- }
186
- ```
187
-
188
- ## Code Quality Philosophy
189
-
190
- ### Strictness by Default
191
-
192
- We enforce strict checks across the codebase:
193
-
194
- - **TypeScript**: `strict: true`, `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`
195
- - **Biome**: Comprehensive lint rules for correctness, style, and complexity
196
- - **Commits**: Conventional commit format enforced via commitlint
197
-
198
- ### Why So Strict?
199
-
200
- 1. **Catch bugs early** - Strict type checking prevents entire categories of runtime errors
201
- 2. **Consistent codebase** - Uniform style reduces cognitive load when reading code
202
- 3. **Self-documenting** - Explicit types and patterns make intent clear
203
- 4. **Refactoring confidence** - Strong types enable safe, large-scale changes
204
-
205
- ### Exceptions: Few and Intentional
206
-
207
- We allow very few exceptions, and each must be justified:
208
-
209
- - **`// biome-ignore`** - Only when the rule genuinely doesn't apply, don't use it just to make the linter happy. Always add a comment explaining why the exception is necessary.
210
- - **`@ts-expect-error`** - Only for known TypeScript limitations with an explanatory comment. Always include a reason for the exception.
211
- - **`eslint-disable`** - We don't use ESLint directly; all linting is handled by Biome. If you encounter an ESLint rule that needs to be disabled, discuss it with the team first and document the reasoning.
212
-
213
- The goal is balance: strict enough to prevent bugs, flexible enough to not block legitimate patterns.
214
-
215
- ## Editor & AI Configuration
216
-
217
- ### EditorConfig
218
-
219
- Create `.editorconfig` at the workspace root:
220
-
221
- ```ini
222
- root = true
223
-
224
- [*]
225
- charset = utf-8
226
- end_of_line = lf
227
- indent_size = 2
228
- indent_style = tab
229
- insert_final_newline = true
230
- trim_trailing_whitespace = true
231
-
232
- [*.md]
233
- indent_style = space
234
- trim_trailing_whitespace = false
41
+ // biome.jsonc
42
+ { "extends": ["@regardio/dev/biome"] }
235
43
 
236
- [*.{yml,yaml}]
237
- indent_style = space
44
+ // tsconfig.json
45
+ { "extends": "@regardio/dev/typescript/base.json" }
238
46
  ```
239
47
 
240
- ### AI Agent Configuration
48
+ ## Documentation
241
49
 
242
- These files help AI coding assistants understand project conventions.
50
+ Detailed documentation is organized by topic:
243
51
 
244
- #### Claude (CLAUDE.md)
52
+ ### Concepts
245
53
 
246
- ```markdown
247
- # Project Guidelines
54
+ - [Development Principles](./docs/concepts/development-principles.md) - Code quality, architecture, maintainability
55
+ - [Coding Standards](./docs/concepts/coding-standards.md) - TypeScript, React, and general patterns
56
+ - [Naming Conventions](./docs/concepts/naming-conventions.md) - Consistent naming across languages
57
+ - [Commit Conventions](./docs/concepts/commits.md) - Conventional commits and changelog generation
58
+ - [Testing Approach](./docs/concepts/testing.md) - Testing philosophy and patterns
59
+ - [AI Agent Guidelines](./docs/concepts/ai-agents.md) - Instructions for AI coding assistants
248
60
 
249
- ## Code Style
250
- - Use TypeScript with strict mode
251
- - Follow Biome formatting (tabs, no semicolons where optional)
252
- - Prefer functional patterns over classes
61
+ ### Toolchain
253
62
 
254
- ## Testing
255
- - Unit tests with Vitest, E2E with Playwright
256
- - Test files: `*.test.ts` or `*.test.tsx`
63
+ - [TypeScript](./docs/toolchain/typescript.md) - Strict TypeScript configuration
64
+ - [Biome](./docs/toolchain/biome.md) - Linting and formatting
65
+ - [Vitest](./docs/toolchain/vitest.md) - Unit and integration testing
66
+ - [Playwright](./docs/toolchain/playwright.md) - End-to-end testing
67
+ - [Commitlint](./docs/toolchain/commitlint.md) - Commit message validation
68
+ - [Markdownlint](./docs/toolchain/markdownlint.md) - Markdown quality
69
+ - [Husky](./docs/toolchain/husky.md) - Git hooks
70
+ - [Changesets](./docs/toolchain/changesets.md) - Versioning and releases
257
71
 
258
- ## Commits
259
- - Use conventional commits: `feat:`, `fix:`, `docs:`, etc.
260
- ```
261
-
262
- #### Gemini (.gemini/settings.json)
263
-
264
- ```json
265
- {
266
- "codeStyle": {
267
- "language": "typescript",
268
- "formatter": "biome",
269
- "indentation": "tabs"
270
- },
271
- "testing": {
272
- "framework": "vitest",
273
- "e2e": "playwright"
274
- }
275
- }
276
- ```
277
-
278
- #### Windsurf (.windsurf/rules.md)
279
-
280
- ```markdown
281
- # Windsurf Rules
282
-
283
- - Extend shared configs from `@regardio/dev`
284
- - Use `pnpm` for package management
285
- - Follow conventional commits
286
- - Prefer minimal, focused edits
287
- ```
288
-
289
- #### Cursor (.cursor/rules.md)
290
-
291
- ```markdown
292
- # Cursor Rules
293
-
294
- ## Project Structure
295
- - Monorepo with pnpm workspaces
296
- - Shared tooling in `packages/dev`
297
-
298
- ## Coding Standards
299
- - TypeScript strict mode
300
- - Biome for linting and formatting
301
- - Vitest for unit tests, Playwright for E2E
302
-
303
- ## Workflow
304
- - Run `pnpm lint` before committing
305
- - Use conventional commit messages
306
- ```
307
-
308
- ## Bundled Dependencies
309
-
310
- When you add `@regardio/dev` as a dev dependency, you get access to:
72
+ ## Portability
311
73
 
312
- - **Testing**: vitest, @vitest/ui, @playwright/test, @testing-library/react, @testing-library/jest-dom, jsdom
313
- - **Linting**: @biomejs/biome, markdownlint-cli2, @commitlint/cli
314
- - **Build**: typescript, tsx, vite, husky
315
- - **Release**: @changesets/cli for versioning and publishing
316
-
317
- ## Releasing
318
-
319
- This package uses [Changesets](https://github.com/changesets/changesets) for versioning and npm publishing, with a streamlined `flow-release` command that automates the entire process.
320
-
321
- ### Quick Release (Recommended)
322
-
323
- The `flow-release` command handles everything in one step:
324
-
325
- ```bash
326
- # From the package directory:
327
- pnpm release minor "Add new vitest configs"
328
-
329
- # Or use the bin directly after build:
330
- flow-release patch "Fix typo in config"
331
- flow-release minor "Add new feature"
332
- flow-release major "Breaking API change"
333
- ```
334
-
335
- This command:
336
-
337
- 1. Creates a changeset file with the specified bump type and message
338
- 2. Runs `changeset version` to update package.json and CHANGELOG
339
- 3. Updates the lockfile (`pnpm install --ignore-workspace`)
340
- 4. Commits all changes with `chore(release): vX.Y.Z`
341
- 5. Pushes to the current branch
342
-
343
- The GitHub Action then publishes to npm automatically.
344
-
345
- ### Manual Release (Step by Step)
346
-
347
- If you prefer more control:
348
-
349
- ```bash
350
- pnpm changeset # Interactive: create changeset file
351
- git add . && git commit # Commit the changeset
352
- git push # Push to trigger GitHub Action
353
- # GitHub Action creates "Version Packages" PR
354
- # Merge that PR → publishes to npm
355
- ```
74
+ While designed for Regardio projects, this toolchain follows well-established standards and can be adopted by any TypeScript project:
356
75
 
357
- ### Reusing in Other Packages
358
-
359
- The `flow-release` bin is available to any package that depends on `@regardio/dev`:
360
-
361
- ```json
362
- {
363
- "scripts": {
364
- "release": "flow-release"
365
- }
366
- }
367
- ```
368
-
369
- Then run:
370
-
371
- ```bash
372
- pnpm release minor "Your release message"
373
- ```
374
-
375
- **Requirements for other packages:**
376
-
377
- 1. A `.changeset/config.json` file (copy from this package and update `repo`)
378
- 2. A `.github/workflows/release.yml` (copy from this package)
379
- 3. GitHub repo configured with NPM_TOKEN secret and Actions permissions
380
-
381
- ### GitHub Repository Setup
382
-
383
- Before the release action works, configure these in **GitHub repo settings**:
384
-
385
- #### 1. NPM_TOKEN Secret
386
-
387
- ```text
388
- Settings → Secrets and variables → Actions → New repository secret
389
- Name: NPM_TOKEN
390
- Value: <your npm access token with publish permissions>
391
- ```
392
-
393
- To create an npm token:
394
-
395
- ```bash
396
- npm login
397
- npm token create --read-only=false
398
- ```
399
-
400
- #### 2. GitHub Actions Permissions
401
-
402
- ```text
403
- Settings → Actions → General → Workflow permissions
404
- ☑ Read and write permissions
405
- ☑ Allow GitHub Actions to create and approve pull requests
406
- ```
407
-
408
- #### 3. Branch Protection Ruleset
409
-
410
- ```text
411
- Settings → Rules → Rulesets → New ruleset → New branch ruleset
412
-
413
- Ruleset Name: main-protection
414
- Enforcement: Active
415
- Target: Add target → Include by pattern → main
416
-
417
- Rules to enable:
418
- ☑ Restrict deletions
419
- ☑ Require a pull request before merging
420
- ☑ Require status checks to pass
421
- - Require up to date: ☑
422
- - Status checks: Release (appears after first workflow run)
423
- ☑ Block force pushes
424
- ```
425
-
426
- ---
76
+ - All configs extend official tool presets
77
+ - No proprietary conventions or lock-in
78
+ - Standard npm package distribution
79
+ - MIT licensed
427
80
 
428
81
  ## License
429
82
 
430
83
  MIT © [Regardio](https://regard.io)
431
84
 
432
- ## Contact
433
-
434
- - **Website**: [regard.io](https://regard.io)
435
- - **GitHub**: [@regardio](https://github.com/regardio)
436
- - **Email**: [bernd.matzner@regard.io](mailto:bernd.matzner@regard.io)
437
-
438
85
  ## Acknowledgments
439
86
 
440
- This project stands on the shoulders of giants. We're deeply grateful to the Open Source community and the maintainers of the tools that make this possible:
441
-
442
- - [Biome](https://biomejs.dev/) - The Biome team
443
- - [commitlint](https://commitlint.js.org/) - The commitlint team
444
- - [Husky](https://typicode.github.io/husky/) - typicode and contributors
445
- - [markdownlint](https://github.com/DavidAnson/markdownlint) - David Anson and contributors
446
- - [Playwright](https://playwright.dev/) - Microsoft
447
- - [pnpm](https://pnpm.io/) - Zoltan Kochan and contributors
448
- - [React](https://react.dev/) - Meta and contributors
449
- - [TypeScript](https://www.typescriptlang.org/) - Microsoft and contributors
450
- - [Vite](https://vitejs.dev/) - Evan You and the Vite team
451
- - [Vitest](https://vitest.dev/) - Anthony Fu and the Vitest team
452
-
453
- And countless other projects that form the foundation of modern web development. Thank you for sharing your work with the world. 💚
87
+ Built on the shoulders of giants: [Biome](https://biomejs.dev/), [TypeScript](https://www.typescriptlang.org/), [Vitest](https://vitest.dev/), [Playwright](https://playwright.dev/), [Vite](https://vitejs.dev/), and the entire open source ecosystem.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { execSync } from 'node:child_process';
3
- import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync, } from 'node:fs';
4
4
  import { join } from 'node:path';
5
5
  const args = process.argv.slice(2);
6
6
  const bumpType = args[0];
@@ -17,6 +17,18 @@ const run = (cmd) => {
17
17
  const runQuiet = (cmd) => {
18
18
  return execSync(cmd, { encoding: 'utf-8' }).trim();
19
19
  };
20
+ const packageJsonPath = join(process.cwd(), 'package.json');
21
+ if (!existsSync(packageJsonPath)) {
22
+ console.error('No package.json found in current directory');
23
+ process.exit(1);
24
+ }
25
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
26
+ const packageName = packageJson.name;
27
+ if (!packageName) {
28
+ console.error('No "name" field found in package.json');
29
+ process.exit(1);
30
+ }
31
+ console.log(`Releasing ${packageName} with ${bumpType} bump...`);
20
32
  try {
21
33
  const status = runQuiet('git status --porcelain');
22
34
  if (status) {
@@ -28,24 +40,35 @@ catch {
28
40
  process.exit(1);
29
41
  }
30
42
  const changesetDir = join(process.cwd(), '.changeset');
43
+ const changesetConfigPath = join(changesetDir, 'config.json');
44
+ if (!existsSync(changesetConfigPath)) {
45
+ console.error('No .changeset/config.json found.');
46
+ console.error('Run: pnpm changeset init');
47
+ console.error('Then configure .changeset/config.json for your package.');
48
+ process.exit(1);
49
+ }
50
+ mkdirSync(changesetDir, { recursive: true });
51
+ const existingChangesets = readdirSync(changesetDir).filter((f) => f.endsWith('.md') && f !== 'README.md');
52
+ for (const file of existingChangesets) {
53
+ unlinkSync(join(changesetDir, file));
54
+ console.log(`Removed existing changeset: ${file}`);
55
+ }
31
56
  const changesetId = `release-${Date.now()}`;
32
57
  const changesetFile = join(changesetDir, `${changesetId}.md`);
33
58
  const changesetContent = `---
34
- "@regardio/dev": ${bumpType}
59
+ "${packageName}": ${bumpType}
35
60
  ---
36
61
 
37
62
  ${message}
38
63
  `;
39
- mkdirSync(changesetDir, { recursive: true });
40
64
  writeFileSync(changesetFile, changesetContent);
41
65
  console.log(`Created changeset: .changeset/${changesetId}.md`);
42
66
  run('pnpm changeset version');
43
67
  console.log('Updating lockfile...');
44
68
  run('pnpm install --ignore-workspace');
45
69
  run('git add -A');
46
- const packageJsonPath = join(process.cwd(), 'package.json');
47
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
48
- const { version } = packageJson;
70
+ const updatedPackageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
71
+ const { version } = updatedPackageJson;
49
72
  run(`git commit -m "chore(release): v${version}"`);
50
73
  const branch = runQuiet('git branch --show-current');
51
74
  run(`git push origin ${branch}`);
package/package.json CHANGED
@@ -17,11 +17,11 @@
17
17
  "url": "https://github.com/regardio/dev/issues"
18
18
  },
19
19
  "dependencies": {
20
- "@biomejs/biome": "2.3.10",
20
+ "@biomejs/biome": "2.3.11",
21
21
  "@changesets/changelog-github": "0.5.2",
22
22
  "@changesets/cli": "2.29.8",
23
- "@commitlint/cli": "20.2.0",
24
- "@commitlint/config-conventional": "20.2.0",
23
+ "@commitlint/cli": "20.3.0",
24
+ "@commitlint/config-conventional": "20.3.0",
25
25
  "@playwright/test": "1.57.0",
26
26
  "@testing-library/jest-dom": "6.9.1",
27
27
  "@testing-library/react": "16.3.1",
@@ -66,10 +66,7 @@
66
66
  "types": "./dist/vitest/react.d.ts"
67
67
  }
68
68
  },
69
- "files": [
70
- "dist",
71
- "src"
72
- ],
69
+ "files": ["dist", "src"],
73
70
  "homepage": "https://github.com/regardio/dev/blob/main/README.md",
74
71
  "keywords": [
75
72
  "biome",
@@ -105,7 +102,7 @@
105
102
  "lint": "run-p lint:*",
106
103
  "lint:biome": "biome check .",
107
104
  "lint:md": "markdownlint-cli2 \"**/*.md\" \"**/*.mdx\" \"!**/node_modules/**\" \"!**/dist/**\"",
108
- "prepare": "pnpm run build && husky",
105
+ "prepare": "husky",
109
106
  "release": "pnpm exec tsx src/bin/flow-release.ts",
110
107
  "test": "run-p test:*",
111
108
  "test:unit": "vitest run",
@@ -113,5 +110,5 @@
113
110
  },
114
111
  "sideEffects": false,
115
112
  "type": "module",
116
- "version": "1.6.0"
113
+ "version": "1.7.0"
117
114
  }
@@ -1,20 +1,34 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * flow-release: Automate the release flow for @regardio/dev.
3
+ * flow-release: Automate the release flow for any @regardio package.
4
4
  *
5
5
  * Usage: flow-release <patch|minor|major> [message]
6
6
  *
7
7
  * This script:
8
- * 1. Creates a changeset file with the specified bump type
9
- * 2. Runs `changeset version` to apply the version bump
10
- * 3. Updates the lockfile (pnpm install --ignore-workspace)
11
- * 4. Commits all changes
12
- * 5. Pushes to the current branch
8
+ * 1. Reads the package name from package.json
9
+ * 2. Creates a changeset file with the specified bump type
10
+ * 3. Runs `changeset version` to apply the version bump
11
+ * 4. Updates the lockfile (pnpm install --ignore-workspace)
12
+ * 5. Commits all changes
13
+ * 6. Pushes to the current branch
13
14
  *
14
15
  * The GitHub Action will then publish to npm automatically.
16
+ *
17
+ * Prerequisites for adopting packages:
18
+ * - Add @regardio/dev as a devDependency
19
+ * - Create .changeset/config.json (see template in dev docs)
20
+ * - Add .github/workflows/release.yml (see template in dev docs)
21
+ * - Add "release": "flow-release" to package.json scripts
15
22
  */
16
23
  import { execSync } from 'node:child_process';
17
- import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
24
+ import {
25
+ existsSync,
26
+ mkdirSync,
27
+ readdirSync,
28
+ readFileSync,
29
+ unlinkSync,
30
+ writeFileSync,
31
+ } from 'node:fs';
18
32
  import { join } from 'node:path';
19
33
 
20
34
  const args = process.argv.slice(2);
@@ -36,6 +50,25 @@ const runQuiet = (cmd: string): string => {
36
50
  return execSync(cmd, { encoding: 'utf-8' }).trim();
37
51
  };
38
52
 
53
+ // Read package name from package.json
54
+ const packageJsonPath = join(process.cwd(), 'package.json');
55
+ if (!existsSync(packageJsonPath)) {
56
+ console.error('No package.json found in current directory');
57
+ process.exit(1);
58
+ }
59
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as {
60
+ name: string;
61
+ version: string;
62
+ };
63
+ const packageName = packageJson.name;
64
+
65
+ if (!packageName) {
66
+ console.error('No "name" field found in package.json');
67
+ process.exit(1);
68
+ }
69
+
70
+ console.log(`Releasing ${packageName} with ${bumpType} bump...`);
71
+
39
72
  // Ensure we're in a clean git state
40
73
  try {
41
74
  const status = runQuiet('git status --porcelain');
@@ -47,20 +80,39 @@ try {
47
80
  process.exit(1);
48
81
  }
49
82
 
50
- // Generate a unique changeset filename
83
+ // Verify .changeset/config.json exists
51
84
  const changesetDir = join(process.cwd(), '.changeset');
85
+ const changesetConfigPath = join(changesetDir, 'config.json');
86
+ if (!existsSync(changesetConfigPath)) {
87
+ console.error('No .changeset/config.json found.');
88
+ console.error('Run: pnpm changeset init');
89
+ console.error('Then configure .changeset/config.json for your package.');
90
+ process.exit(1);
91
+ }
92
+
93
+ // Clean up existing changesets to ensure only our bump type is applied
94
+ mkdirSync(changesetDir, { recursive: true });
95
+
96
+ const existingChangesets = readdirSync(changesetDir).filter(
97
+ (f) => f.endsWith('.md') && f !== 'README.md',
98
+ );
99
+ for (const file of existingChangesets) {
100
+ unlinkSync(join(changesetDir, file));
101
+ console.log(`Removed existing changeset: ${file}`);
102
+ }
103
+
104
+ // Generate a unique changeset filename
52
105
  const changesetId = `release-${Date.now()}`;
53
106
  const changesetFile = join(changesetDir, `${changesetId}.md`);
54
107
 
55
- // Create the changeset file
108
+ // Create the changeset file with dynamic package name
56
109
  const changesetContent = `---
57
- "@regardio/dev": ${bumpType}
110
+ "${packageName}": ${bumpType}
58
111
  ---
59
112
 
60
113
  ${message}
61
114
  `;
62
115
 
63
- mkdirSync(changesetDir, { recursive: true });
64
116
  writeFileSync(changesetFile, changesetContent);
65
117
  console.log(`Created changeset: .changeset/${changesetId}.md`);
66
118
 
@@ -75,10 +127,11 @@ run('pnpm install --ignore-workspace');
75
127
  // Stage all changes
76
128
  run('git add -A');
77
129
 
78
- // Get the new version
79
- const packageJsonPath = join(process.cwd(), 'package.json');
80
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { version: string };
81
- const { version } = packageJson;
130
+ // Re-read package.json to get the new version after changeset version
131
+ const updatedPackageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as {
132
+ version: string;
133
+ };
134
+ const { version } = updatedPackageJson;
82
135
 
83
136
  // Commit
84
137
  run(`git commit -m "chore(release): v${version}"`);
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
3
+ "access": "public",
4
+ "baseBranch": "main",
5
+ "changelog": ["@changesets/changelog-github", { "repo": "regardio/REPO_NAME" }],
6
+ "commit": false,
7
+ "fixed": [],
8
+ "ignore": [],
9
+ "linked": [],
10
+ "updateInternalDependencies": "patch"
11
+ }
@@ -0,0 +1,8 @@
1
+ # Changesets
2
+
3
+ Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
+ with multi-package repos, or single-package repos to help you version and publish your code. You can
5
+ find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
+
7
+ We have a quick list of common questions to get you started engaging with this project in
8
+ [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -0,0 +1,83 @@
1
+ # Regardio Release Workflow
2
+ # Copy this file to .github/workflows/release.yml in your package
3
+ #
4
+ # Required setup:
5
+ # 1. Create .changeset/config.json (see changeset-config.json template)
6
+ # 2. Add "release": "flow-release" to package.json scripts
7
+ # 3. Configure NPM_TOKEN secret in GitHub repository settings
8
+ # OR use npm provenance with OIDC (recommended, no secret needed)
9
+ #
10
+ # Usage:
11
+ # - Run `pnpm release patch|minor|major "message"` locally
12
+ # - Push to main branch
13
+ # - This workflow publishes to npm and creates a GitHub release
14
+
15
+ name: Release
16
+
17
+ on:
18
+ push:
19
+ branches:
20
+ - main
21
+
22
+ concurrency: ${{ github.workflow }}-${{ github.ref }}
23
+
24
+ jobs:
25
+ release:
26
+ name: Release
27
+ runs-on: ubuntu-latest
28
+ permissions:
29
+ contents: write
30
+ pull-requests: write
31
+ id-token: write
32
+ steps:
33
+ - name: Checkout
34
+ uses: actions/checkout@v4
35
+
36
+ - name: Setup pnpm
37
+ uses: pnpm/action-setup@v4
38
+ with:
39
+ version: 10
40
+
41
+ - name: Setup Node.js
42
+ uses: actions/setup-node@v4
43
+ with:
44
+ node-version: 22
45
+ cache: pnpm
46
+ registry-url: https://registry.npmjs.org
47
+
48
+ - name: Update npm for OIDC support
49
+ run: npm install -g npm@latest
50
+
51
+ - name: Install dependencies
52
+ run: pnpm install --frozen-lockfile
53
+
54
+ - name: Build
55
+ run: pnpm build
56
+
57
+ - name: Publish to npm
58
+ id: publish
59
+ run: |
60
+ PACKAGE_NAME=$(node -p "require('./package.json').name")
61
+ CURRENT_VERSION=$(node -p "require('./package.json').version")
62
+ PUBLISHED_VERSION=$(npm view "$PACKAGE_NAME" version 2>/dev/null || echo '0.0.0')
63
+ echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
64
+ echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
65
+ if [ "$PUBLISHED_VERSION" != "$CURRENT_VERSION" ]; then
66
+ echo "Publishing $PACKAGE_NAME@$CURRENT_VERSION (npm has v$PUBLISHED_VERSION)"
67
+ npm publish --access public --provenance
68
+ echo "published=true" >> $GITHUB_OUTPUT
69
+ else
70
+ echo "Version $CURRENT_VERSION already published, skipping"
71
+ echo "published=false" >> $GITHUB_OUTPUT
72
+ fi
73
+
74
+ - name: Create GitHub Release
75
+ if: steps.publish.outputs.published == 'true'
76
+ uses: softprops/action-gh-release@v2
77
+ with:
78
+ tag_name: v${{ steps.publish.outputs.current_version }}
79
+ name: v${{ steps.publish.outputs.current_version }}
80
+ body_path: CHANGELOG.md
81
+ generate_release_notes: true
82
+ env:
83
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}