@jabrown93/dev-config 0.0.0-development
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/LICENSE +21 -0
- package/README.md +130 -0
- package/commitlint.config.js +14 -0
- package/eslint.js +111 -0
- package/lint-staged.js +27 -0
- package/package.json +88 -0
- package/prettier.json +7 -0
- package/release.js +138 -0
- package/tsconfig.base.json +18 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jared Brown
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# @jabrown93/dev-config
|
|
2
|
+
|
|
3
|
+
Shared JS/TS dev-tooling config for `jabrown93` repos: TypeScript, ESLint, Prettier,
|
|
4
|
+
commitlint, lint-staged, and semantic-release. One published package instead of six
|
|
5
|
+
hand-copied config files per repo — bump this package's version and Renovate proposes the
|
|
6
|
+
same bump everywhere it's used, the same way runtime dependency bumps already flow.
|
|
7
|
+
|
|
8
|
+
This is the npm-package analog of [`jabrown93/.github`](https://github.com/jabrown93/.github),
|
|
9
|
+
which centralizes reusable GitHub Actions workflows the same way. That repo is deliberately
|
|
10
|
+
unpublished (`private: true`, consumed via `uses:`); this one is a real published package
|
|
11
|
+
because its configs are consumed at author/commit time via `devDependency` + `extends`, not
|
|
12
|
+
by Actions.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
Add the package:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npm install --save-dev @jabrown93/dev-config
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### TypeScript
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
// tsconfig.json
|
|
26
|
+
{
|
|
27
|
+
"extends": "@jabrown93/dev-config/tsconfig",
|
|
28
|
+
"compilerOptions": {
|
|
29
|
+
"rootDir": "src",
|
|
30
|
+
"outDir": "dist"
|
|
31
|
+
},
|
|
32
|
+
"include": ["src"]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`rootDir`/`outDir` must stay in the **consumer's own** `tsconfig.json`, not the shared base:
|
|
37
|
+
TypeScript resolves an extended config's relative paths against _that config file's own
|
|
38
|
+
location_, so a `rootDir`/`outDir` baked into this package would resolve to paths inside
|
|
39
|
+
`node_modules/@jabrown93/dev-config/`, not the consumer's own `src`/`dist` — breaking every
|
|
40
|
+
consumer with a `TS6059` "not under rootDir" error.
|
|
41
|
+
|
|
42
|
+
### ESLint (flat config)
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
// eslint.config.mjs
|
|
46
|
+
import base from '@jabrown93/dev-config/eslint';
|
|
47
|
+
|
|
48
|
+
export default [...base, { ignores: ['**/dist'] }];
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The only thing that's ever differed across the fleet is `ignores` — add repo-specific entries
|
|
52
|
+
after the shared base.
|
|
53
|
+
|
|
54
|
+
### Prettier
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
// package.json
|
|
58
|
+
{
|
|
59
|
+
"prettier": "@jabrown93/dev-config/prettier"
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Delete any local `.prettierrc.json` — Prettier uses one config source, not both.
|
|
64
|
+
|
|
65
|
+
### commitlint
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
// commitlint.config.js
|
|
69
|
+
export default { extends: ['@jabrown93/dev-config/commitlint'] };
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### lint-staged
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
// .lintstagedrc.js
|
|
76
|
+
export { default } from '@jabrown93/dev-config/lint-staged';
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Delete any local `.lintstagedrc.json` or an inline `lint-staged` key in `package.json` — only
|
|
80
|
+
one lint-staged config source should exist per repo.
|
|
81
|
+
|
|
82
|
+
### semantic-release
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
// .releaserc.json
|
|
86
|
+
{ "extends": "@jabrown93/dev-config/release" }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`extends` is a resolver string, not code — this works from a `.releaserc.json` even though the
|
|
90
|
+
referenced module runs code at load time.
|
|
91
|
+
|
|
92
|
+
This config suppresses routine `fix(deps)` commits on ordinary pushes and promotes them into a
|
|
93
|
+
single weekly patch release when the caller's workflow sets `RELEASE_DEPS=true` (see
|
|
94
|
+
`jabrown93/.github`'s README, "Weekly dependency releases"). **A consumer's `release.yml` must
|
|
95
|
+
add a `schedule` (and ideally `workflow_dispatch`) trigger for this to ever fire** — without
|
|
96
|
+
one, `fix(deps)` commits are suppressed forever, not just batched. See this repo's own
|
|
97
|
+
`.github/workflows/release.yml`, or `homebridge-smartrent`'s, for the trigger shape to copy.
|
|
98
|
+
|
|
99
|
+
### What stays per-repo
|
|
100
|
+
|
|
101
|
+
No npm-`extends` mechanism exists for `.prettierignore` or `.nvmrc` — those stay hand-maintained
|
|
102
|
+
per repo.
|
|
103
|
+
|
|
104
|
+
## What's exported
|
|
105
|
+
|
|
106
|
+
| Subpath | Contents |
|
|
107
|
+
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| `@jabrown93/dev-config/tsconfig` | Shared `compilerOptions` (target/module/strict/etc.) — no `rootDir`/`outDir`/`include`/`exclude`, those must stay in the consumer's own tsconfig (see above) |
|
|
109
|
+
| `@jabrown93/dev-config/eslint` | Flat-config array (parser, `eslint:recommended` + `@typescript-eslint/recommended`, the fleet's stylistic rules) |
|
|
110
|
+
| `@jabrown93/dev-config/prettier` | The 5 shared Prettier options |
|
|
111
|
+
| `@jabrown93/dev-config/commitlint` | `@commitlint/config-conventional` + 4 rule overrides |
|
|
112
|
+
| `@jabrown93/dev-config/lint-staged` | `eslint --fix` on staged js/mjs/ts + `prettier --write` on staged js/mjs/ts/json/md/yml |
|
|
113
|
+
| `@jabrown93/dev-config/release` | semantic-release config: branches `main`/`next`/`beta`/`alpha`, conventionalcommits preset, CHANGELOG trim, CycloneDX SBOM release asset, `fix(deps)` weekly roll-up |
|
|
114
|
+
|
|
115
|
+
## Dependency split
|
|
116
|
+
|
|
117
|
+
Tools whose **bin** a consumer invokes directly (`eslint`, `prettier`, `typescript`, `husky`,
|
|
118
|
+
`lint-staged`, `semantic-release`, `@commitlint/cli`, plus each repo's own test runner) stay as
|
|
119
|
+
**direct devDependencies in the consumer**. Packages this config resolves internally at
|
|
120
|
+
runtime and a consumer never invokes directly (`@typescript-eslint/*`, `@eslint/js`,
|
|
121
|
+
`@eslint/eslintrc`, `@commitlint/config-conventional`, every `@semantic-release/*` plugin,
|
|
122
|
+
`conventional-changelog-conventionalcommits`) are `dependencies` **of this package** — they
|
|
123
|
+
arrive in a consumer's tree via normal npm hoisting when this package installs, and a version
|
|
124
|
+
bump here is the only place those need touching.
|
|
125
|
+
|
|
126
|
+
## Versioning
|
|
127
|
+
|
|
128
|
+
Released automatically by semantic-release from Conventional Commits on `main` — see
|
|
129
|
+
`.releaserc.js` (a relative re-export of `release.js`; this repo can't `extends` its own
|
|
130
|
+
published package). Don't hand-edit `package.json`'s version.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Shared commitlint configuration for jabrown93 repos. This file doubles as
|
|
2
|
+
// dev-config's own active commitlint config (auto-discovered by commitlint's
|
|
3
|
+
// standard filename search) and the shareable module consumers reference:
|
|
4
|
+
//
|
|
5
|
+
// export default { extends: ['@jabrown93/dev-config/commitlint'] };
|
|
6
|
+
export default {
|
|
7
|
+
extends: ['@commitlint/config-conventional'],
|
|
8
|
+
rules: {
|
|
9
|
+
'body-max-line-length': [2, 'never', '500'],
|
|
10
|
+
'body-max-length': [2, 'never', '2000'],
|
|
11
|
+
'footer-max-line-length': [2, 'never', '500'],
|
|
12
|
+
'subject-case': [2, 'never', ['upper-case', 'pascal-case', 'start-case']],
|
|
13
|
+
},
|
|
14
|
+
};
|
package/eslint.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import tsParser from '@typescript-eslint/parser';
|
|
4
|
+
import js from '@eslint/js';
|
|
5
|
+
import { FlatCompat } from '@eslint/eslintrc';
|
|
6
|
+
import globals from 'globals';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const compat = new FlatCompat({
|
|
11
|
+
baseDirectory: __dirname,
|
|
12
|
+
recommendedConfig: js.configs.recommended,
|
|
13
|
+
allConfig: js.configs.all,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Shared ESLint flat-config base for jabrown93 TypeScript projects. Import
|
|
17
|
+
// this array and append repo-specific entries -- historically the only thing
|
|
18
|
+
// that's ever differed across the fleet is `ignores`:
|
|
19
|
+
//
|
|
20
|
+
// import base from '@jabrown93/dev-config/eslint';
|
|
21
|
+
// export default [...base, { ignores: ['**/homebridge-ui', '**/dist', 'package-lock.json', 'package.json'] }];
|
|
22
|
+
//
|
|
23
|
+
// Note: `compat.extends()` resolves plugin packages (e.g.
|
|
24
|
+
// @typescript-eslint/eslint-plugin) via Node module resolution starting at
|
|
25
|
+
// this file's own directory, which after install is inside the consumer's
|
|
26
|
+
// node_modules/@jabrown93/dev-config -- resolution walks up to the
|
|
27
|
+
// consumer's top-level node_modules, so this depends on npm hoisting
|
|
28
|
+
// @typescript-eslint/eslint-plugin from this package's own `dependencies`.
|
|
29
|
+
// That's the standard shareable-eslint-config pattern; verify with
|
|
30
|
+
// `npx eslint --print-config <file>` after adopting if something doesn't
|
|
31
|
+
// resolve.
|
|
32
|
+
export default [
|
|
33
|
+
...compat.extends(
|
|
34
|
+
'eslint:recommended',
|
|
35
|
+
'plugin:@typescript-eslint/eslint-recommended',
|
|
36
|
+
'plugin:@typescript-eslint/recommended'
|
|
37
|
+
),
|
|
38
|
+
{
|
|
39
|
+
languageOptions: {
|
|
40
|
+
parser: tsParser,
|
|
41
|
+
// 2022 to match the shared tsconfig's own `target`/`lib` -- the fleet's
|
|
42
|
+
// original 2018 left ES2020+ built-in globals (AggregateError, WeakRef,
|
|
43
|
+
// FinalizationRegistry, ...) out of ESLint's recognized-globals set, so
|
|
44
|
+
// `eslint:recommended`'s no-undef flagged valid, runtime-supported code
|
|
45
|
+
// as undefined.
|
|
46
|
+
ecmaVersion: 2022,
|
|
47
|
+
sourceType: 'module',
|
|
48
|
+
// The fleet's original config never set `globals`, so flat config
|
|
49
|
+
// assumed no runtime environment -- `no-undef` would flag bare
|
|
50
|
+
// `console`/`process` as undefined. This never surfaced because no
|
|
51
|
+
// fleet src/*.ts file happened to reference either through the actual
|
|
52
|
+
// matched lint glob; it's a real gap for Node-targeted TS, not
|
|
53
|
+
// intentional. Fixed here rather than carried forward.
|
|
54
|
+
globals: { ...globals.node },
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
rules: {
|
|
58
|
+
// avoidEscape: prettier picks whichever quote style needs fewer
|
|
59
|
+
// escapes for a given string (e.g. a shell one-liner containing
|
|
60
|
+
// single quotes gets double-quoted); without avoidEscape, this rule
|
|
61
|
+
// and prettier fight over any string like that forever. The fleet's
|
|
62
|
+
// original config lacked this option -- never surfaced because no
|
|
63
|
+
// fleet string needed it, until this package's own release.js did.
|
|
64
|
+
quotes: ['warn', 'single', { avoidEscape: true }],
|
|
65
|
+
|
|
66
|
+
indent: [
|
|
67
|
+
'warn',
|
|
68
|
+
2,
|
|
69
|
+
{
|
|
70
|
+
SwitchCase: 1,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
semi: ['off'],
|
|
75
|
+
'comma-dangle': ['warn', 'only-multiline'],
|
|
76
|
+
'dot-notation': 'off',
|
|
77
|
+
eqeqeq: 'warn',
|
|
78
|
+
curly: ['warn', 'all'],
|
|
79
|
+
'brace-style': ['warn'],
|
|
80
|
+
'prefer-arrow-callback': ['warn'],
|
|
81
|
+
'max-len': ['warn', 140],
|
|
82
|
+
'no-console': ['warn'],
|
|
83
|
+
'comma-spacing': ['error'],
|
|
84
|
+
|
|
85
|
+
'no-multi-spaces': [
|
|
86
|
+
'warn',
|
|
87
|
+
{
|
|
88
|
+
ignoreEOLComments: true,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
|
|
92
|
+
'no-trailing-spaces': ['warn'],
|
|
93
|
+
|
|
94
|
+
'lines-between-class-members': [
|
|
95
|
+
'warn',
|
|
96
|
+
'always',
|
|
97
|
+
{
|
|
98
|
+
exceptAfterSingleLine: true,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
|
|
102
|
+
// The fleet's original config also listed a core `no-non-null-assertion`
|
|
103
|
+
// rule -- there is no such core ESLint rule (only the
|
|
104
|
+
// @typescript-eslint-prefixed one below exists), so it was a no-op.
|
|
105
|
+
// Dropped here rather than carried forward.
|
|
106
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
107
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
108
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
];
|
package/lint-staged.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Shared lint-staged configuration for jabrown93 repos.
|
|
2
|
+
//
|
|
3
|
+
// export { default } from '@jabrown93/dev-config/lint-staged';
|
|
4
|
+
//
|
|
5
|
+
// Fixes vs. the fleet's prior per-repo copies:
|
|
6
|
+
// - eslint is scoped to the actually-staged js/mjs/ts files (lint-staged
|
|
7
|
+
// appends staged filenames as arguments) instead of a hardcoded
|
|
8
|
+
// `src/**.ts` glob that ran regardless of what was staged.
|
|
9
|
+
// - No `bash -c` wrapper -- that swallowed the staged filenames lint-staged
|
|
10
|
+
// appends (they became unreferenced bash positional args), so eslint
|
|
11
|
+
// fell back to linting the whole repo instead of just staged files.
|
|
12
|
+
// - eslint and prettier are ordered commands under the SAME glob key for
|
|
13
|
+
// js/mjs/ts, not two separate keys that both match those files: distinct
|
|
14
|
+
// glob-key groups run concurrently by default, so two separate keys both
|
|
15
|
+
// matching the same file let eslint and prettier read/write it at the
|
|
16
|
+
// same time -- e.g. prettier can clobber an eslint-only fix while both
|
|
17
|
+
// processes still exit 0, staging code that passes the hook but would
|
|
18
|
+
// fail a real lint run. json/md/yml don't overlap with the first key at
|
|
19
|
+
// all (eslint has no parser configured for them anyway), so they're a
|
|
20
|
+
// second, disjoint key rather than sharing one with js/mjs/ts.
|
|
21
|
+
export default {
|
|
22
|
+
'*.{js,mjs,ts}': [
|
|
23
|
+
'eslint --fix --max-warnings=0 --no-warn-ignored',
|
|
24
|
+
'prettier --write',
|
|
25
|
+
],
|
|
26
|
+
'*.{json,md,yml}': 'prettier --write',
|
|
27
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jabrown93/dev-config",
|
|
3
|
+
"version": "0.0.0-development",
|
|
4
|
+
"description": "Shared JS/TS dev-tooling config (tsconfig, eslint, prettier, commitlint, lint-staged, semantic-release) for jabrown93 repos",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"eslint-config",
|
|
7
|
+
"tsconfig",
|
|
8
|
+
"prettier-config",
|
|
9
|
+
"commitlint-config",
|
|
10
|
+
"lint-staged-config",
|
|
11
|
+
"semantic-release-config"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/jabrown93/dev-config#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/jabrown93/dev-config/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/jabrown93/dev-config.git"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": {
|
|
23
|
+
"name": "Jared Brown",
|
|
24
|
+
"email": "npm@jaredbrown.io",
|
|
25
|
+
"url": "https://github.com/jabrown93"
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": "^22.14.0 || ^24.11.0 || ^26.0.0"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"tsconfig.base.json",
|
|
36
|
+
"eslint.js",
|
|
37
|
+
"prettier.json",
|
|
38
|
+
"commitlint.config.js",
|
|
39
|
+
"lint-staged.js",
|
|
40
|
+
"release.js"
|
|
41
|
+
],
|
|
42
|
+
"exports": {
|
|
43
|
+
"./tsconfig": "./tsconfig.base.json",
|
|
44
|
+
"./eslint": "./eslint.js",
|
|
45
|
+
"./prettier": "./prettier.json",
|
|
46
|
+
"./commitlint": "./commitlint.config.js",
|
|
47
|
+
"./lint-staged": "./lint-staged.js",
|
|
48
|
+
"./release": "./release.js"
|
|
49
|
+
},
|
|
50
|
+
"prettier": "./prettier.json",
|
|
51
|
+
"scripts": {
|
|
52
|
+
"lint": "eslint .",
|
|
53
|
+
"lint:fix": "eslint . --fix",
|
|
54
|
+
"format": "prettier --write .",
|
|
55
|
+
"prettier": "prettier --check .",
|
|
56
|
+
"build": "echo \"no build step -- plain JS/JSON config package\"",
|
|
57
|
+
"test": "node scripts/verify-exports.mjs",
|
|
58
|
+
"semantic-release": "cross-env semantic-release --no-ci",
|
|
59
|
+
"release": "npm-run-all build semantic-release",
|
|
60
|
+
"prepare": "husky"
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"@commitlint/config-conventional": "21.2.0",
|
|
64
|
+
"@eslint/eslintrc": "3.3.6",
|
|
65
|
+
"@eslint/js": "10.0.1",
|
|
66
|
+
"@semantic-release/changelog": "6.0.3",
|
|
67
|
+
"@semantic-release/commit-analyzer": "13.0.1",
|
|
68
|
+
"@semantic-release/exec": "7.1.0",
|
|
69
|
+
"@semantic-release/git": "10.0.1",
|
|
70
|
+
"@semantic-release/github": "12.0.9",
|
|
71
|
+
"@semantic-release/npm": "13.1.5",
|
|
72
|
+
"@semantic-release/release-notes-generator": "14.1.1",
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "8.64.0",
|
|
74
|
+
"@typescript-eslint/parser": "8.64.0",
|
|
75
|
+
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
76
|
+
"globals": "17.7.0"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@commitlint/cli": "21.2.1",
|
|
80
|
+
"cross-env": "10.1.0",
|
|
81
|
+
"eslint": "10.7.0",
|
|
82
|
+
"husky": "9.1.7",
|
|
83
|
+
"lint-staged": "17.0.8",
|
|
84
|
+
"npm-run-all2": "9.0.2",
|
|
85
|
+
"prettier": "3.9.5",
|
|
86
|
+
"semantic-release": "25.0.7"
|
|
87
|
+
}
|
|
88
|
+
}
|
package/prettier.json
ADDED
package/release.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Shared semantic-release configuration for jabrown93 npm packages.
|
|
2
|
+
//
|
|
3
|
+
// Consumers reference this with a one-line `.releaserc.json` (or `.js`):
|
|
4
|
+
// { "extends": "@jabrown93/dev-config/release" }
|
|
5
|
+
// "extends" is just a resolver string -- semantic-release/cosmiconfig loads
|
|
6
|
+
// and executes this module regardless of the local file's own extension, so
|
|
7
|
+
// a plain JSON local file works fine even though this module runs code.
|
|
8
|
+
//
|
|
9
|
+
// Versioning is automated from Conventional Commits:
|
|
10
|
+
// * push to `main`/`next` -> stable release (feat -> minor, fix/perf -> patch, ! -> major)
|
|
11
|
+
// * push to `beta`/`alpha` -> prerelease (vX.Y.Z-beta.N / -alpha.N)
|
|
12
|
+
//
|
|
13
|
+
// Routine runtime dependency bumps (fix(deps), from Renovate via the shared
|
|
14
|
+
// preset in jabrown93/.github) do NOT cut a release on ordinary pushes --
|
|
15
|
+
// they would otherwise publish a new npm version per merged Renovate PR. A
|
|
16
|
+
// weekly scheduled run (see jabrown93/.github's README, "Weekly dependency
|
|
17
|
+
// releases") sets RELEASE_DEPS=true, which promotes the accumulated bumps
|
|
18
|
+
// into one patch release. Vulnerability fixes are typed fix(security) by the
|
|
19
|
+
// preset, not fix(deps), so they are unaffected by the suppression and still
|
|
20
|
+
// release immediately.
|
|
21
|
+
//
|
|
22
|
+
// IMPORTANT for adopters: a consumer's release.yml caller must add a
|
|
23
|
+
// `schedule` (and ideally `workflow_dispatch`) trigger for RELEASE_DEPS to
|
|
24
|
+
// ever become true -- without it, fix(deps) commits are suppressed forever,
|
|
25
|
+
// not just batched. See jabrown93/homebridge-smartrent's release.yml for the
|
|
26
|
+
// trigger shape to copy.
|
|
27
|
+
const releaseDeps = process.env.RELEASE_DEPS === 'true';
|
|
28
|
+
|
|
29
|
+
const depReleaseRules = [
|
|
30
|
+
// Required: commit-analyzer evaluates every matching custom rule and keeps
|
|
31
|
+
// the highest release type, so without this a breaking fix(deps)! would
|
|
32
|
+
// match ONLY the suppression rule below and never release. Listed first so
|
|
33
|
+
// the analyzer short-circuits on major.
|
|
34
|
+
{ type: 'fix', scope: 'deps', breaking: true, release: 'major' },
|
|
35
|
+
releaseDeps
|
|
36
|
+
? { type: 'fix', scope: 'deps', release: 'patch' }
|
|
37
|
+
: { type: 'fix', scope: 'deps', release: false },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const noteKeywords = ['BREAKING CHANGE', 'BREAKING CHANGES', 'BREAKING'];
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
// NOTE: `branches` (plural) -- this is the key semantic-release actually
|
|
44
|
+
// reads. Two of the fleet's original per-repo .releaserc.json files had
|
|
45
|
+
// this as `"branch"` (singular), so that array was silently ignored and
|
|
46
|
+
// semantic-release fell back to its own default (`main` + `next` +
|
|
47
|
+
// `beta`/`alpha` prereleases, close to but not verified identical to what
|
|
48
|
+
// was intended) -- fixed by centralizing.
|
|
49
|
+
branches: [
|
|
50
|
+
'main',
|
|
51
|
+
'next',
|
|
52
|
+
{ name: 'beta', prerelease: true },
|
|
53
|
+
{ name: 'alpha', prerelease: true },
|
|
54
|
+
],
|
|
55
|
+
plugins: [
|
|
56
|
+
[
|
|
57
|
+
'@semantic-release/commit-analyzer',
|
|
58
|
+
{
|
|
59
|
+
// `preset` is not a semantic-release core option -- there is no
|
|
60
|
+
// top-level fallback; each plugin reads it only from its own tuple's
|
|
61
|
+
// options (verified against @semantic-release/commit-analyzer's and
|
|
62
|
+
// release-notes-generator's own loaders, and semantic-release core
|
|
63
|
+
// itself has zero references to "preset" anywhere). A top-level
|
|
64
|
+
// `preset` key here would be silently ignored, and both plugins
|
|
65
|
+
// would fall back to the Angular preset instead -- the fleet's
|
|
66
|
+
// original per-repo configs all had exactly that silent bug.
|
|
67
|
+
preset: 'conventionalcommits',
|
|
68
|
+
parserOpts: { noteKeywords },
|
|
69
|
+
releaseRules: depReleaseRules,
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
[
|
|
73
|
+
'@semantic-release/exec',
|
|
74
|
+
{
|
|
75
|
+
// Trims a duplicate leading "Unreleased"-style CHANGELOG heading on
|
|
76
|
+
// release branches. Present in 3 of the 4 fleet repos; the 4th
|
|
77
|
+
// (philips-hue-sync-box) was missing it -- restored here.
|
|
78
|
+
//
|
|
79
|
+
// Guarded on the file existing: this step runs before
|
|
80
|
+
// @semantic-release/changelog's own `prepare` hook (the one that
|
|
81
|
+
// creates CHANGELOG.md), so on a repo's very first-ever release --
|
|
82
|
+
// this package's own included -- there's no file yet and a bare
|
|
83
|
+
// `sed -i` would exit nonzero and abort the release.
|
|
84
|
+
prepareCmd:
|
|
85
|
+
"test ${branch.type} != release || test ! -f CHANGELOG.md || sed -i '/^## \\[/h;x;/^[^]]*-/{x;d};x' CHANGELOG.md",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
[
|
|
89
|
+
'@semantic-release/release-notes-generator',
|
|
90
|
+
{
|
|
91
|
+
preset: 'conventionalcommits',
|
|
92
|
+
parserOpts: { noteKeywords },
|
|
93
|
+
writerOpts: { commitsSort: ['subject', 'scope'] },
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
'@semantic-release/changelog',
|
|
98
|
+
{
|
|
99
|
+
changelogTitle:
|
|
100
|
+
'# Changelog\n\nAll notable changes to this project will be documented ' +
|
|
101
|
+
'in this file. See\n[Conventional Commits](https://conventionalcommits.org) ' +
|
|
102
|
+
'for commit guidelines.',
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
['@semantic-release/npm', { tarballDir: 'dist' }],
|
|
106
|
+
[
|
|
107
|
+
'@semantic-release/exec',
|
|
108
|
+
{
|
|
109
|
+
prepareCmd:
|
|
110
|
+
'npx --yes @cyclonedx/cyclonedx-npm@4.2.1 --ignore-npm-errors --output-format JSON --output-file sbom.cdx.json',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
[
|
|
114
|
+
'@semantic-release/github',
|
|
115
|
+
{
|
|
116
|
+
assets: [
|
|
117
|
+
{ path: 'sbom.cdx.json', label: 'CycloneDX SBOM (sbom.cdx.json)' },
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
[
|
|
122
|
+
'@semantic-release/git',
|
|
123
|
+
{
|
|
124
|
+
// `chore(release): ... [skip ci]` -- 3 of the 4 fleet repos used
|
|
125
|
+
// `ci(release): ...` with no `[skip ci]`. GitHub Actions natively
|
|
126
|
+
// skips ALL workflows (build.yml + release.yml) for a push whose
|
|
127
|
+
// HEAD commit message contains `[skip ci]`, so omitting it means the
|
|
128
|
+
// version-bump commit this plugin creates re-triggers a full
|
|
129
|
+
// lint/build/test matrix and a whole redundant semantic-release run
|
|
130
|
+
// for nothing (semantic-release itself no-ops since there's nothing
|
|
131
|
+
// new to release, but the CI run still executes). Standardized on
|
|
132
|
+
// the more efficient form (already used by philips-hue-sync-box).
|
|
133
|
+
message:
|
|
134
|
+
'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}',
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
],
|
|
138
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": ["ES2022"],
|
|
4
|
+
"module": "nodenext",
|
|
5
|
+
"target": "ES2022",
|
|
6
|
+
"moduleResolution": "nodenext",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationMap": true,
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"noImplicitAny": false,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"skipLibCheck": true
|
|
17
|
+
}
|
|
18
|
+
}
|