@acme-skunkworks/eslint-config 1.0.4 → 1.1.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 +49 -109
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/infrastructure/scripts/check-changelog-completeness.d.ts +9 -0
- package/dist/infrastructure/scripts/check-changelog-completeness.d.ts.map +1 -0
- package/dist/infrastructure/scripts/check-changelog-completeness.js +69 -0
- package/dist/infrastructure/scripts/finalise-changelog.d.ts.map +1 -1
- package/dist/infrastructure/scripts/finalise-changelog.js +7 -6
- package/dist/infrastructure/send-it/derive-changeset.d.ts.map +1 -1
- package/dist/infrastructure/send-it/derive-changeset.js +7 -3
- package/dist/rules/esm.d.ts +166 -0
- package/dist/rules/esm.d.ts.map +1 -0
- package/dist/rules/esm.js +27 -0
- package/package.json +4 -8
package/README.md
CHANGED
|
@@ -1,142 +1,82 @@
|
|
|
1
1
|
# @acme-skunkworks/eslint-config
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> A shared ESLint v9 flat-config **preset composer** for TypeScript and React projects — import named-export presets and compose only the ones you need.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@acme-skunkworks/eslint-config)
|
|
6
|
+
[](https://www.npmjs.com/package/@acme-skunkworks/eslint-config#provenance)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://www.npmjs.com/package/@acme-skunkworks/eslint-config)
|
|
9
|
+
|
|
10
|
+
Every release is published to npm via OIDC Trusted Publishing with a **provenance attestation** — the artefact is built and signed on GitHub Actions, so consumers can verify exactly which commit and workflow produced it.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
6
13
|
|
|
7
14
|
```bash
|
|
8
15
|
pnpm add -D @acme-skunkworks/eslint-config eslint prettier
|
|
9
16
|
```
|
|
10
17
|
|
|
11
|
-
Every ESLint plugin
|
|
18
|
+
`eslint` (`^8.57.0 || ^9.0.0`) and `prettier` (`^3.0.0`) are **required peer dependencies** — install them alongside. Every ESLint plugin the config uses ships as a regular dependency, so you don't install plugins separately. Node 22+ is required.
|
|
19
|
+
|
|
20
|
+
> **ESLint v8 users:** flat config isn't the default in v8 — set `ESLINT_USE_FLAT_CONFIG=1` so ESLint reads your `eslint.config.js`. ESLint v9 uses flat config by default, so no flag is needed.
|
|
12
21
|
|
|
13
|
-
##
|
|
22
|
+
## Quick start
|
|
14
23
|
|
|
15
|
-
The package
|
|
24
|
+
The package exposes each preset as a named export. Compose them in your `eslint.config.js`:
|
|
16
25
|
|
|
17
26
|
```js
|
|
18
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
base,
|
|
29
|
+
typescript,
|
|
30
|
+
frameworkRouting,
|
|
31
|
+
} from "@acme-skunkworks/eslint-config";
|
|
19
32
|
|
|
20
33
|
export default [
|
|
21
34
|
...base,
|
|
22
35
|
typescript,
|
|
23
36
|
...frameworkRouting,
|
|
24
37
|
// your overrides last so they win
|
|
25
|
-
{
|
|
26
|
-
rules: {
|
|
27
|
-
"@typescript-eslint/no-explicit-any": "warn",
|
|
28
|
-
},
|
|
29
|
-
},
|
|
38
|
+
{ rules: { "@typescript-eslint/no-explicit-any": "warn" } },
|
|
30
39
|
];
|
|
31
40
|
```
|
|
32
41
|
|
|
33
|
-
Pull in the presets
|
|
34
|
-
|
|
35
|
-
| Export | What it covers |
|
|
36
|
-
|---|---|
|
|
37
|
-
| `base` | Plugin-alias hack + global ignores + the canonical baseline + packageJson lint config + commonjs file overrides + the big preferences block (top-level type imports, `func-style: declaration`, prettier integration, import resolver, `no-console` warn, etc.). The "you almost always want this" stack. |
|
|
38
|
-
| `typescript` | Overrides for `**/*.{ts,tsx}` (disables `react/no-unused-prop-types` and `react/prop-types`). |
|
|
39
|
-
| `frameworkRouting` | Disables `canonical/filename-match-exported` for routing dirs (`routes/**`, `app/**`, `pages/**`, `src/routes/**`, `src/pages/**`); re-allows arrow functions on `root.tsx` / `*.route.tsx`. Order matters — must spread **after** `base`. |
|
|
40
|
-
| `astro` | `eslint-plugin-astro/flat/recommended` + Astro-specific overrides. Pull in for Astro projects. |
|
|
41
|
-
| `sanity` | Schema property ordering for `*.schema.ts` and structure-file exceptions. Pull in for projects using Sanity Studio. |
|
|
42
|
-
| `testing` | Relaxes strict TypeScript rules and devDependencies imports for `**/*.{test,spec}.*`, `__tests__/**`, and setup files. |
|
|
43
|
-
| `storybook` | Overrides for `**/*.stories.{ts,tsx}`. |
|
|
44
|
-
| `complexity` | Raises cyclomatic complexity threshold to 40 for `**/scripts/**` (orchestration scripts run linearly). Opt-in. |
|
|
45
|
-
| `e2e` | Disables `react-hooks/rules-of-hooks` for `**/e2e/**` (Playwright `test.extend` callbacks are false positives). Opt-in. |
|
|
46
|
-
| `tableComponents` | Disables `react/no-unstable-nested-components` for `**/*Table.tsx` (TanStack Table / Refine column-cell renderers). Opt-in. |
|
|
47
|
-
|
|
48
|
-
> **Note:** Requires ESLint v9+ with flat config. Node 22+.
|
|
49
|
-
|
|
50
|
-
## 🔄 Migrating from `@robeasthope/eslint-config`
|
|
51
|
-
|
|
52
|
-
This package was previously published as `@robeasthope/eslint-config` from the [`RobEasthope/protomolecule`](https://github.com/RobEasthope/protomolecule) monorepo (versions up to and including v6.2.1). It now ships from this standalone repo under the `@acme-skunkworks` scope, with a named-export composition pattern.
|
|
53
|
-
|
|
54
|
-
### Step 1: rename the dep
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
pnpm remove @robeasthope/eslint-config
|
|
58
|
-
pnpm add -D @acme-skunkworks/eslint-config
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Step 2: switch to named exports
|
|
62
|
-
|
|
63
|
-
The default export still works during the migration window, but is **deprecated** and will be removed in a future major:
|
|
64
|
-
|
|
65
|
-
```js
|
|
66
|
-
// Old (still works in v1, deprecated)
|
|
67
|
-
import eslintConfig from "@acme-skunkworks/eslint-config";
|
|
68
|
-
export default [...eslintConfig];
|
|
69
|
-
|
|
70
|
-
// New (preferred — pull in only what you need)
|
|
71
|
-
import { base, typescript, frameworkRouting } from "@acme-skunkworks/eslint-config";
|
|
72
|
-
export default [...base, typescript, ...frameworkRouting];
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
If your project was a Sanity / Storybook / Astro consumer, opt-in to those presets explicitly. The default export bundled all of them; the new shape makes the dependencies explicit.
|
|
42
|
+
Pull in only the presets your project needs. Array presets are spread with `...`; single-config presets are added as-is — the table below notes which is which.
|
|
76
43
|
|
|
77
|
-
|
|
44
|
+
## Presets
|
|
78
45
|
|
|
79
|
-
|
|
80
|
-
- **Named-export composition.** Each preset is independently importable; consumers compose what they need.
|
|
81
|
-
- **`prettier` is now a `peerDependency`.** Was already a transitive dep via `eslint-plugin-prettier`; this just makes the contract explicit.
|
|
46
|
+
**Core** — the everyday stack:
|
|
82
47
|
|
|
83
|
-
|
|
48
|
+
| Preset | Shape | What it covers |
|
|
49
|
+
| ------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
50
|
+
| `base` | array (`...`) | Plugin-alias hack, global ignores, the canonical baseline, `package.json` lint config, CommonJS **and ESM** file overrides (Node + ES globals for `.cjs` / `.mjs` so standalone scripts parse without `no-undef`), and the `preferences` block (top-level type imports, `func-style: declaration`, Prettier integration, import resolver, `no-console` warn). The "you almost always want this" stack. |
|
|
51
|
+
| `typescript` | single | Overrides for `**/*.{ts,tsx}` — disables `react/no-unused-prop-types` and `react/prop-types`, which are redundant under TypeScript. |
|
|
52
|
+
| `frameworkRouting` | array (`...`) | Turns off `canonical/filename-match-exported` for routing dirs — `routes/**`, `app/**`, `pages/**` (Next.js), `src/routes/**` (SvelteKit), `src/pages/**` (Astro) — and re-allows arrow functions on `root.tsx` / `*.route.tsx`. Spread **after** `base` (see Gotchas). |
|
|
53
|
+
| `testing` | single | Relaxes strict TypeScript rules and `import/no-extraneous-dependencies` for `**/*.{test,spec}.*`, `__tests__/**`, and setup files. |
|
|
84
54
|
|
|
85
|
-
|
|
55
|
+
**Opt-in** — pull in per project:
|
|
86
56
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
-
|
|
57
|
+
| Preset | Shape | What it covers |
|
|
58
|
+
| ----------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
59
|
+
| `astro` | array (`...`) | `eslint-plugin-astro/flat/recommended` plus Astro-specific overrides. |
|
|
60
|
+
| `sanity` | array (`...`) | Schema property ordering for `*.schema.ts` and structure-file exceptions, for Sanity Studio projects. |
|
|
61
|
+
| `storybook` | single | Overrides for `**/*.stories.{ts,tsx}`. |
|
|
62
|
+
| `complexity` | array (`...`) | Raises the cyclomatic-complexity threshold to 40 for `**/scripts/**`, where orchestration scripts run linearly. |
|
|
63
|
+
| `e2e` | single | Disables `react-hooks/rules-of-hooks` for `**/e2e/**` — Playwright `test.extend` callbacks are false positives. |
|
|
64
|
+
| `tableComponents` | single | Disables `react/no-unstable-nested-components` for `**/*Table.tsx` — TanStack Table / Refine column-cell renderers. |
|
|
93
65
|
|
|
94
|
-
|
|
66
|
+
> A deprecated **default export** still bundles the v6.x composition for back-compat during migration. New code should use the named exports above. See the [migration guide](MIGRATION_FROM_PROTOMOLECULE.md).
|
|
95
67
|
|
|
96
|
-
|
|
68
|
+
## Gotchas
|
|
97
69
|
|
|
98
|
-
|
|
99
|
-
import { base, typescript } from "@acme-skunkworks/eslint-config";
|
|
100
|
-
|
|
101
|
-
export default [
|
|
102
|
-
...base,
|
|
103
|
-
typescript,
|
|
104
|
-
{
|
|
105
|
-
rules: {
|
|
106
|
-
"@typescript-eslint/no-explicit-any": "warn",
|
|
107
|
-
"react/prop-types": "off",
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
];
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Add additional plugins by configuring them directly:
|
|
114
|
-
|
|
115
|
-
```js
|
|
116
|
-
import { base, typescript } from "@acme-skunkworks/eslint-config";
|
|
117
|
-
import pluginReact from "eslint-plugin-react";
|
|
70
|
+
Two ordering rules are easy to get wrong and fail **silently** — the config still loads, but the intended override never wins:
|
|
118
71
|
|
|
119
|
-
export
|
|
120
|
-
|
|
121
|
-
typescript,
|
|
122
|
-
{
|
|
123
|
-
plugins: { react: pluginReact },
|
|
124
|
-
rules: { "react/jsx-uses-react": "error" },
|
|
125
|
-
},
|
|
126
|
-
];
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## 🔧 Development
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
pnpm install # install deps
|
|
133
|
-
pnpm run build # tsc → dist/
|
|
134
|
-
pnpm lint # lint this package's own source
|
|
135
|
-
pnpm lint:fix # auto-fix
|
|
136
|
-
```
|
|
72
|
+
- **Spread `frameworkRouting` _after_ `...base`.** Its `func-style` override must come later in the array than the `preferences` block (which `base` includes), or `base` wins and the React Router 7 typed-export pattern breaks.
|
|
73
|
+
- **`frameworkRouting` is an ordered pair of configs** for the same reason — its second element (the React Router exceptions) must stay after its first, which in turn must follow `preferences`. If you ever expand the spread into individual elements, preserve their order.
|
|
137
74
|
|
|
138
|
-
|
|
75
|
+
Full rationale (and the protomolecule issues behind it) is in [`CLAUDE.md`](CLAUDE.md).
|
|
139
76
|
|
|
140
|
-
|
|
77
|
+
## Links
|
|
141
78
|
|
|
142
|
-
|
|
79
|
+
- [Changelog](CHANGELOG.md)
|
|
80
|
+
- [Migration guide](MIGRATION_FROM_PROTOMOLECULE.md) — moving from `@robeasthope/eslint-config`
|
|
81
|
+
- [Repository](https://github.com/acme-skunkworks/eslint-config)
|
|
82
|
+
- [Licence](LICENSE) — MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Linter } from "eslint";
|
|
|
2
2
|
/**
|
|
3
3
|
* Base preset — the "you almost always want this" stack:
|
|
4
4
|
* plugin-alias hack, global ignores, the canonical baseline, packageJson
|
|
5
|
-
* lint config, commonjs file overrides, and the big preferences block
|
|
5
|
+
* lint config, commonjs + esm file overrides, and the big preferences block
|
|
6
6
|
* (top-level type imports, func-style, prettier, import resolver, etc.).
|
|
7
7
|
*/
|
|
8
8
|
export declare const base: Linter.Config[];
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAerC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,EAU/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAA4B,CAAC;AAE7D;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAG3C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAkB,CAAC;AAEhD;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD;;GAEG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D;;;;;;;;GAQG;AACH,QAAA,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EASjC,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
import { astro } from "./rules/astro.js";
|
|
4
4
|
import { commonjs } from "./rules/commonjs.js";
|
|
5
|
+
import { esm } from "./rules/esm.js";
|
|
5
6
|
import { frameworkRouting as frameworkRoutingRule } from "./rules/frameworkRouting.js";
|
|
6
7
|
import { ignoredFileAndFolders } from "./rules/ignoredFileAndFolders.js";
|
|
7
8
|
import { packageJson } from "./rules/packageJson.js";
|
|
@@ -26,7 +27,7 @@ const importXAlias = {
|
|
|
26
27
|
/**
|
|
27
28
|
* Base preset — the "you almost always want this" stack:
|
|
28
29
|
* plugin-alias hack, global ignores, the canonical baseline, packageJson
|
|
29
|
-
* lint config, commonjs file overrides, and the big preferences block
|
|
30
|
+
* lint config, commonjs + esm file overrides, and the big preferences block
|
|
30
31
|
* (top-level type imports, func-style, prettier, import resolver, etc.).
|
|
31
32
|
*/
|
|
32
33
|
export const base = [
|
|
@@ -37,6 +38,7 @@ export const base = [
|
|
|
37
38
|
...eslintConfigCanonicalAuto,
|
|
38
39
|
packageJson,
|
|
39
40
|
commonjs,
|
|
41
|
+
esm,
|
|
40
42
|
preferences,
|
|
41
43
|
];
|
|
42
44
|
/**
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env -S npx tsx
|
|
2
|
+
export declare function isReleaseTriggering(prTitle: string): boolean;
|
|
3
|
+
export declare function hasChangelogEntry(changedFiles: readonly string[]): boolean;
|
|
4
|
+
export type CompletenessResult = {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
reason: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function checkCompleteness(prTitle: string, changedFiles: readonly string[]): CompletenessResult;
|
|
9
|
+
//# sourceMappingURL=check-changelog-completeness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-changelog-completeness.d.ts","sourceRoot":"","sources":["../../../infrastructure/scripts/check-changelog-completeness.ts"],"names":[],"mappings":";AAwBA,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAG5D;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI1E;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,kBAAkB,CAmBpB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env -S npx tsx
|
|
2
|
+
// Changelog-completeness gate (SK-371). A release-triggering PR title
|
|
3
|
+
// (`feat`/`fix`/`perf`/`revert`/breaking) MUST carry a dated `changelog/` entry. This restores
|
|
4
|
+
// the coupling Changesets gave for free — no changeset → no release — now that
|
|
5
|
+
// release-please infers the bump from the Conventional-Commit PR title rather
|
|
6
|
+
// than an explicit file. Wired into ci.yml's build-and-lint job.
|
|
7
|
+
//
|
|
8
|
+
// "Release-triggering" mirrors release-please's default node bump table:
|
|
9
|
+
// `feat` (minor), `fix`/`perf`/`revert` (patch), and a `!` breaking marker
|
|
10
|
+
// (major) cut a release; `docs`/`chore`/`ci`/`refactor`/`test`/`build`/`style`
|
|
11
|
+
// do not.
|
|
12
|
+
//
|
|
13
|
+
// Inputs (env, set by the workflow):
|
|
14
|
+
// PR_TITLE — the pull request title (github.event.pull_request.title)
|
|
15
|
+
// BASE_REF — the base branch name (github.base_ref); defaults to "main"
|
|
16
|
+
// Reads changed files from `git diff --name-only origin/<BASE_REF>...HEAD`.
|
|
17
|
+
// Pure functions live exported for vitest.
|
|
18
|
+
import { execFileSync } from "node:child_process";
|
|
19
|
+
const RELEASE_TRIGGERING_TYPE = /^(feat|fix|perf|revert)(\([^)]+\))?:/;
|
|
20
|
+
const BREAKING_SUBJECT = /^[a-z]+(\([^)]+\))?!:/;
|
|
21
|
+
const CHANGELOG_ENTRY = /^changelog\/.+\.md$/;
|
|
22
|
+
export function isReleaseTriggering(prTitle) {
|
|
23
|
+
const title = prTitle.trim();
|
|
24
|
+
return BREAKING_SUBJECT.test(title) || RELEASE_TRIGGERING_TYPE.test(title);
|
|
25
|
+
}
|
|
26
|
+
export function hasChangelogEntry(changedFiles) {
|
|
27
|
+
return changedFiles.some((file) => CHANGELOG_ENTRY.test(file) && file !== "changelog/README.md");
|
|
28
|
+
}
|
|
29
|
+
export function checkCompleteness(prTitle, changedFiles) {
|
|
30
|
+
if (!isReleaseTriggering(prTitle)) {
|
|
31
|
+
return {
|
|
32
|
+
ok: true,
|
|
33
|
+
reason: `PR title "${prTitle}" is not release-triggering — no changelog entry required.`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (hasChangelogEntry(changedFiles)) {
|
|
37
|
+
return {
|
|
38
|
+
ok: true,
|
|
39
|
+
reason: "Release-triggering PR title with a changelog/ entry present.",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
reason: `PR title "${prTitle}" triggers a release (feat/fix/perf/revert/breaking) but no changelog/*.md entry is present in the diff vs the base branch. Run /send-it (or add a dated changelog/ entry) so the release carries notes.`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function readChangedFiles(baseRef) {
|
|
48
|
+
const out = execFileSync("git", ["diff", "--name-only", `origin/${baseRef}...HEAD`], { encoding: "utf8" });
|
|
49
|
+
return out
|
|
50
|
+
.split("\n")
|
|
51
|
+
.map((line) => line.trim())
|
|
52
|
+
.filter(Boolean);
|
|
53
|
+
}
|
|
54
|
+
function main() {
|
|
55
|
+
const prTitle = process.env.PR_TITLE ?? "";
|
|
56
|
+
const baseRef = process.env.BASE_REF || "main";
|
|
57
|
+
if (!prTitle) {
|
|
58
|
+
console.error("PR_TITLE is not set — cannot run the changelog-completeness gate.");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
const result = checkCompleteness(prTitle, readChangedFiles(baseRef));
|
|
62
|
+
console.log(result.reason);
|
|
63
|
+
if (!result.ok) {
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
68
|
+
main();
|
|
69
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalise-changelog.d.ts","sourceRoot":"","sources":["../../../infrastructure/scripts/finalise-changelog.ts"],"names":[],"mappings":";AAuBA,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,YAAY,EAAE,IAAI,GAAG,MAAM,CAAC;IAC5B,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,IAAI,GAAG,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,UAAU,CAAC;AAE/D,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC;AAMtE;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,UAAU,GACpB,IAAI,GAAG,MAAM,CAgCf;AAaD;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"finalise-changelog.d.ts","sourceRoot":"","sources":["../../../infrastructure/scripts/finalise-changelog.ts"],"names":[],"mappings":";AAuBA,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,YAAY,EAAE,IAAI,GAAG,MAAM,CAAC;IAC5B,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,IAAI,GAAG,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,UAAU,CAAC;AAE/D,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC;AAMtE;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,UAAU,GACpB,IAAI,GAAG,MAAM,CAgCf;AAaD;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CA6EpD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
|
-
// Release-time finalisation of changelog entries — run by
|
|
3
|
-
//
|
|
4
|
-
// committed into the
|
|
5
|
-
//
|
|
2
|
+
// Release-time finalisation of changelog entries — run by the orchestrator
|
|
3
|
+
// right after `release-please release-pr` (SK-371/SK-376), so the result is
|
|
4
|
+
// committed into the release PR (no separate workflow, no bot push to main).
|
|
5
|
+
// Reads the just-bumped version from package.json, which release-please updated.
|
|
6
6
|
//
|
|
7
7
|
// For every entry that isn't finalised yet (empty `version`):
|
|
8
8
|
// 1. resolve its merged PR from the `branch` field via `gh` and enrich
|
|
@@ -119,8 +119,9 @@ export function makeResolver(run) {
|
|
|
119
119
|
}
|
|
120
120
|
return (branch) => {
|
|
121
121
|
// Enrichment is best-effort metadata: a gh/git failure here must NOT abort
|
|
122
|
-
//
|
|
123
|
-
// null — the entry still gets version-stamped, just without
|
|
122
|
+
// the release-please release-PR build and block the release. On any error,
|
|
123
|
+
// warn and return null — the entry still gets version-stamped, just without
|
|
124
|
+
// PR metadata.
|
|
124
125
|
try {
|
|
125
126
|
return resolve(branch);
|
|
126
127
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive-changeset.d.ts","sourceRoot":"","sources":["../../../infrastructure/send-it/derive-changeset.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"derive-changeset.d.ts","sourceRoot":"","sources":["../../../infrastructure/send-it/derive-changeset.ts"],"names":[],"mappings":";AAoBA,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYjD;AAED,MAAM,MAAM,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AACtE,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAK/C,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAmB3D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAO7D"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
|
-
// Derives the deterministic bits
|
|
2
|
+
// Derives the deterministic bits /send-it needs from the branch commits.
|
|
3
3
|
// Run: pnpm tsx infrastructure/send-it/derive-changeset.ts
|
|
4
4
|
//
|
|
5
|
+
// Since SK-371 there is no changeset file; /send-it uses these to name the dated
|
|
6
|
+
// changelog/ entry and to compose the Conventional Commits PR title (the
|
|
7
|
+
// release-please bump signal). The filename is retained for git history.
|
|
8
|
+
//
|
|
5
9
|
// Fields:
|
|
6
|
-
// slug : branch-name-derived
|
|
7
|
-
// bump : major | minor | patch (
|
|
10
|
+
// slug : branch-name-derived slug (changelog/<ts>-<slug>.md filename)
|
|
11
|
+
// bump : major | minor | patch (drives the PR-title prefix: feat!/feat/fix)
|
|
8
12
|
// body : a one-line draft summary (the slash command may rewrite this)
|
|
9
13
|
//
|
|
10
14
|
// Reads from git via `git branch --show-current` and `git log origin/main..HEAD`
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Part of `base` — applied to every consumer.
|
|
3
|
+
*
|
|
4
|
+
* `.mjs` parser shim: the ESM counterpart to `commonjs`. Standalone ES-module
|
|
5
|
+
* scripts (`.mjs`) — build/maintenance tooling, skill helpers — run in Node but
|
|
6
|
+
* are not members of any tsconfig project, so the flat config gives them no
|
|
7
|
+
* environment globals and `console` / `process` trip `no-undef`. This sets
|
|
8
|
+
* `sourceType: "module"` plus Node + ES2021 globals so they parse cleanly. No
|
|
9
|
+
* rules — only `languageOptions`.
|
|
10
|
+
* @see https://eslint.org/docs/latest/use/configure/language-options
|
|
11
|
+
*/
|
|
12
|
+
export declare const esm: {
|
|
13
|
+
files: string[];
|
|
14
|
+
ignores: string[];
|
|
15
|
+
languageOptions: {
|
|
16
|
+
globals: {
|
|
17
|
+
AggregateError: false;
|
|
18
|
+
Array: false;
|
|
19
|
+
ArrayBuffer: false;
|
|
20
|
+
Atomics: false;
|
|
21
|
+
BigInt: false;
|
|
22
|
+
BigInt64Array: false;
|
|
23
|
+
BigUint64Array: false;
|
|
24
|
+
Boolean: false;
|
|
25
|
+
DataView: false;
|
|
26
|
+
Date: false;
|
|
27
|
+
decodeURI: false;
|
|
28
|
+
decodeURIComponent: false;
|
|
29
|
+
encodeURI: false;
|
|
30
|
+
encodeURIComponent: false;
|
|
31
|
+
Error: false;
|
|
32
|
+
escape: false;
|
|
33
|
+
eval: false;
|
|
34
|
+
EvalError: false;
|
|
35
|
+
FinalizationRegistry: false;
|
|
36
|
+
Float32Array: false;
|
|
37
|
+
Float64Array: false;
|
|
38
|
+
Function: false;
|
|
39
|
+
globalThis: false;
|
|
40
|
+
Infinity: false;
|
|
41
|
+
Int16Array: false;
|
|
42
|
+
Int32Array: false;
|
|
43
|
+
Int8Array: false;
|
|
44
|
+
Intl: false;
|
|
45
|
+
isFinite: false;
|
|
46
|
+
isNaN: false;
|
|
47
|
+
JSON: false;
|
|
48
|
+
Map: false;
|
|
49
|
+
Math: false;
|
|
50
|
+
NaN: false;
|
|
51
|
+
Number: false;
|
|
52
|
+
Object: false;
|
|
53
|
+
parseFloat: false;
|
|
54
|
+
parseInt: false;
|
|
55
|
+
Promise: false;
|
|
56
|
+
Proxy: false;
|
|
57
|
+
RangeError: false;
|
|
58
|
+
ReferenceError: false;
|
|
59
|
+
Reflect: false;
|
|
60
|
+
RegExp: false;
|
|
61
|
+
Set: false;
|
|
62
|
+
SharedArrayBuffer: false;
|
|
63
|
+
String: false;
|
|
64
|
+
Symbol: false;
|
|
65
|
+
SyntaxError: false;
|
|
66
|
+
TypeError: false;
|
|
67
|
+
Uint16Array: false;
|
|
68
|
+
Uint32Array: false;
|
|
69
|
+
Uint8Array: false;
|
|
70
|
+
Uint8ClampedArray: false;
|
|
71
|
+
undefined: false;
|
|
72
|
+
unescape: false;
|
|
73
|
+
URIError: false;
|
|
74
|
+
WeakMap: false;
|
|
75
|
+
WeakRef: false;
|
|
76
|
+
WeakSet: false;
|
|
77
|
+
__dirname: false;
|
|
78
|
+
__filename: false;
|
|
79
|
+
AbortController: false;
|
|
80
|
+
AbortSignal: false;
|
|
81
|
+
AsyncDisposableStack: false;
|
|
82
|
+
atob: false;
|
|
83
|
+
Blob: false;
|
|
84
|
+
BroadcastChannel: false;
|
|
85
|
+
btoa: false;
|
|
86
|
+
Buffer: false;
|
|
87
|
+
ByteLengthQueuingStrategy: false;
|
|
88
|
+
clearImmediate: false;
|
|
89
|
+
clearInterval: false;
|
|
90
|
+
clearTimeout: false;
|
|
91
|
+
CloseEvent: false;
|
|
92
|
+
CompressionStream: false;
|
|
93
|
+
console: false;
|
|
94
|
+
CountQueuingStrategy: false;
|
|
95
|
+
crypto: false;
|
|
96
|
+
Crypto: false;
|
|
97
|
+
CryptoKey: false;
|
|
98
|
+
CustomEvent: false;
|
|
99
|
+
DecompressionStream: false;
|
|
100
|
+
DisposableStack: false;
|
|
101
|
+
DOMException: false;
|
|
102
|
+
ErrorEvent: false;
|
|
103
|
+
Event: false;
|
|
104
|
+
EventTarget: false;
|
|
105
|
+
exports: true;
|
|
106
|
+
fetch: false;
|
|
107
|
+
File: false;
|
|
108
|
+
FormData: false;
|
|
109
|
+
global: false;
|
|
110
|
+
Headers: false;
|
|
111
|
+
localStorage: false;
|
|
112
|
+
MessageChannel: false;
|
|
113
|
+
MessageEvent: false;
|
|
114
|
+
MessagePort: false;
|
|
115
|
+
module: false;
|
|
116
|
+
navigator: false;
|
|
117
|
+
Navigator: false;
|
|
118
|
+
performance: false;
|
|
119
|
+
Performance: false;
|
|
120
|
+
PerformanceEntry: false;
|
|
121
|
+
PerformanceMark: false;
|
|
122
|
+
PerformanceMeasure: false;
|
|
123
|
+
PerformanceObserver: false;
|
|
124
|
+
PerformanceObserverEntryList: false;
|
|
125
|
+
PerformanceResourceTiming: false;
|
|
126
|
+
process: false;
|
|
127
|
+
queueMicrotask: false;
|
|
128
|
+
ReadableByteStreamController: false;
|
|
129
|
+
ReadableStream: false;
|
|
130
|
+
ReadableStreamBYOBReader: false;
|
|
131
|
+
ReadableStreamBYOBRequest: false;
|
|
132
|
+
ReadableStreamDefaultController: false;
|
|
133
|
+
ReadableStreamDefaultReader: false;
|
|
134
|
+
Request: false;
|
|
135
|
+
require: false;
|
|
136
|
+
Response: false;
|
|
137
|
+
sessionStorage: false;
|
|
138
|
+
setImmediate: false;
|
|
139
|
+
setInterval: false;
|
|
140
|
+
setTimeout: false;
|
|
141
|
+
Storage: false;
|
|
142
|
+
structuredClone: false;
|
|
143
|
+
SubtleCrypto: false;
|
|
144
|
+
SuppressedError: false;
|
|
145
|
+
TextDecoder: false;
|
|
146
|
+
TextDecoderStream: false;
|
|
147
|
+
TextEncoder: false;
|
|
148
|
+
TextEncoderStream: false;
|
|
149
|
+
TransformStream: false;
|
|
150
|
+
TransformStreamDefaultController: false;
|
|
151
|
+
URL: false;
|
|
152
|
+
URLPattern: false;
|
|
153
|
+
URLSearchParams: false;
|
|
154
|
+
WebAssembly: false;
|
|
155
|
+
WebSocket: false;
|
|
156
|
+
WritableStream: false;
|
|
157
|
+
WritableStreamDefaultController: false;
|
|
158
|
+
WritableStreamDefaultWriter: false;
|
|
159
|
+
};
|
|
160
|
+
parserOptions: {
|
|
161
|
+
ecmaVersion: string;
|
|
162
|
+
};
|
|
163
|
+
sourceType: string;
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=esm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esm.d.ts","sourceRoot":"","sources":["../../rules/esm.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcS,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import globals from "globals";
|
|
2
|
+
/**
|
|
3
|
+
* Part of `base` — applied to every consumer.
|
|
4
|
+
*
|
|
5
|
+
* `.mjs` parser shim: the ESM counterpart to `commonjs`. Standalone ES-module
|
|
6
|
+
* scripts (`.mjs`) — build/maintenance tooling, skill helpers — run in Node but
|
|
7
|
+
* are not members of any tsconfig project, so the flat config gives them no
|
|
8
|
+
* environment globals and `console` / `process` trip `no-undef`. This sets
|
|
9
|
+
* `sourceType: "module"` plus Node + ES2021 globals so they parse cleanly. No
|
|
10
|
+
* rules — only `languageOptions`.
|
|
11
|
+
* @see https://eslint.org/docs/latest/use/configure/language-options
|
|
12
|
+
*/
|
|
13
|
+
export const esm = {
|
|
14
|
+
files: ["**/*.mjs"],
|
|
15
|
+
// Exclude node_modules
|
|
16
|
+
ignores: ["**/node_modules/**"],
|
|
17
|
+
languageOptions: {
|
|
18
|
+
globals: {
|
|
19
|
+
...globals.node,
|
|
20
|
+
...globals.es2021,
|
|
21
|
+
},
|
|
22
|
+
parserOptions: {
|
|
23
|
+
ecmaVersion: "latest",
|
|
24
|
+
},
|
|
25
|
+
sourceType: "module",
|
|
26
|
+
},
|
|
27
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acme-skunkworks/eslint-config",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Shared ESLint flat-config preset with TypeScript, React, Astro, Sanity, and Storybook support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"act:release:dry": "act push -W .github/workflows/release.yml",
|
|
47
47
|
"build": "tsc",
|
|
48
48
|
"changelog:finalise": "tsx infrastructure/scripts/finalise-changelog.ts",
|
|
49
|
-
"changeset:version": "changeset version && pnpm changelog:finalise",
|
|
50
49
|
"ci:list": "gh run list --limit 10",
|
|
51
50
|
"ci:view": "gh run view",
|
|
52
51
|
"ci:watch": "gh run watch $(gh run list -L 1 --json databaseId -q '.[0].databaseId // empty')",
|
|
@@ -54,14 +53,13 @@
|
|
|
54
53
|
"format": "npx prettier --write .",
|
|
55
54
|
"lint": "eslint 'index.ts' 'rules/**/*.ts' 'infrastructure/scripts/**/*.ts' 'infrastructure/send-it/**/*.ts' --cache --cache-location ./.eslintcache",
|
|
56
55
|
"lint:fix": "eslint 'index.ts' 'rules/**/*.ts' 'infrastructure/scripts/**/*.ts' 'infrastructure/send-it/**/*.ts' --fix --cache --cache-location ./.eslintcache",
|
|
57
|
-
"lint:md": "markdownlint-cli2 '**/*.{md,mdx}' '!**/node_modules/**' '!**/dist/**' '!**/.turbo/**' '!**/.astro/**'
|
|
58
|
-
"lint:md:fix": "markdownlint-cli2 --fix '**/*.{md,mdx}' '!**/node_modules/**' '!**/dist/**' '!**/.turbo/**' '!**/.astro/**'
|
|
56
|
+
"lint:md": "markdownlint-cli2 '**/*.{md,mdx}' '!**/node_modules/**' '!**/dist/**' '!**/.turbo/**' '!**/.astro/**'",
|
|
57
|
+
"lint:md:fix": "markdownlint-cli2 --fix '**/*.{md,mdx}' '!**/node_modules/**' '!**/dist/**' '!**/.turbo/**' '!**/.astro/**'",
|
|
59
58
|
"lint:sh": "bash -c 'if command -v shellcheck >/dev/null 2>&1; then shellcheck infrastructure/scripts/*.sh .husky/pre-commit .husky/pre-push .husky/commit-msg; elif [ \"$(uname -s)\" = \"Darwin\" ]; then echo \"⚠️ shellcheck not installed — skipping. Install: brew install shellcheck\"; else echo \"⚠️ shellcheck not installed — skipping. Install: apt-get install shellcheck\"; fi'",
|
|
60
59
|
"lint:workflows": "actionlint",
|
|
61
60
|
"lint:yaml": "yamllint .",
|
|
62
61
|
"prepare": "husky",
|
|
63
62
|
"prepublishOnly": "pnpm run build",
|
|
64
|
-
"release": "pnpm run build && changeset publish",
|
|
65
63
|
"release:manual": "pnpm run build && npm publish --access public --provenance=false",
|
|
66
64
|
"release:manual:dry": "pnpm run build && npm publish --access public --provenance=false --dry-run",
|
|
67
65
|
"sort-pkg-json": "sort-package-json",
|
|
@@ -69,8 +67,7 @@
|
|
|
69
67
|
"test:sh": "bash -c 'if command -v bats >/dev/null 2>&1; then bats infrastructure/tests/*.bats; elif [ \"$(uname -s)\" = \"Darwin\" ]; then echo \"⚠️ bats not installed — skipping. Install: brew install bats-core\"; else echo \"⚠️ bats not installed — skipping. Install: apt-get install bats\"; fi'",
|
|
70
68
|
"test:watch": "vitest",
|
|
71
69
|
"tsc": "tsc --noEmit",
|
|
72
|
-
"validate:changelog": "tsx infrastructure/scripts/validate-changelog.ts"
|
|
73
|
-
"version": "changeset version"
|
|
70
|
+
"validate:changelog": "tsx infrastructure/scripts/validate-changelog.ts"
|
|
74
71
|
},
|
|
75
72
|
"lint-staged": {
|
|
76
73
|
"**/*": [
|
|
@@ -114,7 +111,6 @@
|
|
|
114
111
|
},
|
|
115
112
|
"devDependencies": {
|
|
116
113
|
"@acme-skunkworks/markdownlint-config": "^2.0.0",
|
|
117
|
-
"@changesets/cli": "^2.31.0",
|
|
118
114
|
"@types/eslint": "^9.6.1",
|
|
119
115
|
"@types/node": "^25.6.0",
|
|
120
116
|
"gray-matter": "^4.0.3",
|