@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 +47 -413
- package/dist/bin/flow-release.js +29 -6
- package/package.json +6 -9
- package/src/bin/flow-release.ts +68 -15
- package/src/templates/changeset-config.json +11 -0
- package/src/templates/changeset-readme.md +8 -0
- package/src/templates/release.yml +83 -0
package/README.md
CHANGED
|
@@ -1,453 +1,87 @@
|
|
|
1
1
|
# @regardio/dev
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A unified developer toolchain for consistent, high-quality TypeScript projects.
|
|
4
4
|
|
|
5
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11
|
+
## Philosophy
|
|
17
12
|
|
|
18
|
-
|
|
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
|
-
|
|
20
|
+
The goal is code that's correct, consistent, and a pleasure to work with.
|
|
35
21
|
|
|
36
|
-
## What's
|
|
22
|
+
## What's Inside
|
|
37
23
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
##
|
|
32
|
+
## Quick Start
|
|
45
33
|
|
|
46
34
|
```bash
|
|
47
35
|
pnpm add -D @regardio/dev
|
|
48
36
|
```
|
|
49
37
|
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
237
|
-
|
|
44
|
+
// tsconfig.json
|
|
45
|
+
{ "extends": "@regardio/dev/typescript/base.json" }
|
|
238
46
|
```
|
|
239
47
|
|
|
240
|
-
|
|
48
|
+
## Documentation
|
|
241
49
|
|
|
242
|
-
|
|
50
|
+
Detailed documentation is organized by topic:
|
|
243
51
|
|
|
244
|
-
|
|
52
|
+
### Concepts
|
|
245
53
|
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
|
|
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
|
-
|
|
255
|
-
-
|
|
256
|
-
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
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.
|
package/dist/bin/flow-release.js
CHANGED
|
@@ -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
|
-
"
|
|
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
|
|
47
|
-
const
|
|
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.
|
|
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.
|
|
24
|
-
"@commitlint/config-conventional": "20.
|
|
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": "
|
|
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.
|
|
113
|
+
"version": "1.7.0"
|
|
117
114
|
}
|
package/src/bin/flow-release.ts
CHANGED
|
@@ -1,20 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* flow-release: Automate the release flow for @regardio
|
|
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.
|
|
9
|
-
* 2.
|
|
10
|
-
* 3.
|
|
11
|
-
* 4.
|
|
12
|
-
* 5.
|
|
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 {
|
|
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
|
-
//
|
|
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
|
-
"
|
|
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
|
-
//
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
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 }}
|