@howells/husky 0.2.0 → 0.2.2
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 +7 -4
- package/bin/detect.mjs +21 -0
- package/bin/howells-husky.mjs +19 -9
- package/hooks/pre-commit +0 -0
- package/hooks/pre-push +6 -2
- package/package.json +8 -9
package/README.md
CHANGED
|
@@ -23,6 +23,8 @@ In `package.json`:
|
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
Standard external lint-staged configuration files are supported as an alternative to the inline `package.json` entry. Use one when path-aware or computed commands are needed.
|
|
27
|
+
|
|
26
28
|
That's it. On `pnpm install`, the hooks are installed automatically.
|
|
27
29
|
|
|
28
30
|
## What it does
|
|
@@ -33,7 +35,7 @@ Runs `pnpm lint-staged` — formats staged files with the configured Howells for
|
|
|
33
35
|
|
|
34
36
|
### Pre-push
|
|
35
37
|
|
|
36
|
-
Runs `pnpm typecheck`
|
|
38
|
+
Runs the project's `pnpm prepush` script when one exists, so each repository can define the narrowest appropriate gate for its own architecture. Projects without that script retain the backward-compatible `pnpm typecheck` followed by `pnpm lint` fallback. The selected gate must pass before code reaches the remote.
|
|
37
39
|
|
|
38
40
|
Both run against the **working directory**, so their result only describes what is being pushed when the working directory is what is being pushed. Git names the refs on stdin, so the hook can tell:
|
|
39
41
|
|
|
@@ -58,9 +60,10 @@ What changed is that it is no longer silent. If an install replaces a hook whose
|
|
|
58
60
|
|
|
59
61
|
Your `package.json` must have:
|
|
60
62
|
|
|
61
|
-
- `"
|
|
62
|
-
- `"
|
|
63
|
-
- `"lint
|
|
63
|
+
- a `"prepush"` script appropriate to the repository, or both:
|
|
64
|
+
- a `"typecheck"` script (e.g. `tsc --noEmit` or `turbo run typecheck`)
|
|
65
|
+
- a `"lint"` script (e.g. `howells-lint` or `turbo run lint`)
|
|
66
|
+
- inline or standard external lint-staged configuration; static inline commands use `howells-fix` (`howells-ox-fix` and `howells-format` remain accepted for projects mid-migration)
|
|
64
67
|
|
|
65
68
|
## Why a package?
|
|
66
69
|
|
package/bin/detect.mjs
CHANGED
|
@@ -16,6 +16,27 @@ export const lintStagedFormatterCommands = [
|
|
|
16
16
|
|
|
17
17
|
export const recommendedLintStagedCommand = "howells-fix";
|
|
18
18
|
|
|
19
|
+
// Standard configuration names supported by lint-staged. Package-level files
|
|
20
|
+
// in a monorepo are discovered by lint-staged itself; the installer only needs
|
|
21
|
+
// to recognise the root configuration it is responsible for validating.
|
|
22
|
+
export const lintStagedConfigFileNames = [
|
|
23
|
+
".lintstagedrc",
|
|
24
|
+
".lintstagedrc.json",
|
|
25
|
+
".lintstagedrc.yaml",
|
|
26
|
+
".lintstagedrc.yml",
|
|
27
|
+
".lintstagedrc.js",
|
|
28
|
+
".lintstagedrc.mjs",
|
|
29
|
+
".lintstagedrc.cjs",
|
|
30
|
+
"lint-staged.config.js",
|
|
31
|
+
"lint-staged.config.mjs",
|
|
32
|
+
"lint-staged.config.cjs",
|
|
33
|
+
"lint-staged.config.ts",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export function findLintStagedConfigFile(exists) {
|
|
37
|
+
return lintStagedConfigFileNames.find((file) => exists(file));
|
|
38
|
+
}
|
|
39
|
+
|
|
19
40
|
/**
|
|
20
41
|
* Flatten a lint-staged config object into the list of command strings it runs.
|
|
21
42
|
* Values may be a single command string or an array of them.
|
package/bin/howells-husky.mjs
CHANGED
|
@@ -27,6 +27,7 @@ import path from "node:path";
|
|
|
27
27
|
|
|
28
28
|
import {
|
|
29
29
|
fallbackFailed,
|
|
30
|
+
findLintStagedConfigFile,
|
|
30
31
|
lintStagedCommandValues,
|
|
31
32
|
recommendedLintStagedCommand,
|
|
32
33
|
shouldUseNpxFallback,
|
|
@@ -38,7 +39,11 @@ const packageRoot = path.resolve(scriptDir, "..");
|
|
|
38
39
|
const projectRoot = process.cwd();
|
|
39
40
|
|
|
40
41
|
// Skip in CI environments — hooks aren't needed there
|
|
41
|
-
if (
|
|
42
|
+
if (
|
|
43
|
+
process.env.HUSKY === "0" ||
|
|
44
|
+
process.env.CI === "true" ||
|
|
45
|
+
process.env.VERCEL === "1"
|
|
46
|
+
) {
|
|
42
47
|
process.exit(0);
|
|
43
48
|
}
|
|
44
49
|
|
|
@@ -113,17 +118,21 @@ for (const hook of hooks) {
|
|
|
113
118
|
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
114
119
|
if (existsSync(packageJsonPath)) {
|
|
115
120
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
121
|
+
const externalLintStagedConfig = findLintStagedConfigFile((file) =>
|
|
122
|
+
existsSync(path.join(projectRoot, file))
|
|
123
|
+
);
|
|
116
124
|
|
|
117
|
-
if (!packageJson["lint-staged"]) {
|
|
125
|
+
if (!packageJson["lint-staged"] && !externalLintStagedConfig) {
|
|
118
126
|
console.warn(
|
|
119
|
-
|
|
127
|
+
"[@howells/husky] Warning: no inline or external lint-staged config found."
|
|
120
128
|
);
|
|
121
129
|
console.warn(
|
|
122
130
|
` Add: "lint-staged": { "*.{js,ts,jsx,tsx,json,jsonc,css}": "${recommendedLintStagedCommand}" }`
|
|
123
131
|
);
|
|
124
132
|
}
|
|
125
133
|
|
|
126
|
-
//
|
|
134
|
+
// Inline static configs can be checked directly. External JavaScript configs
|
|
135
|
+
// may compute commands dynamically, so lint-staged owns their validation.
|
|
127
136
|
const lsConfig = packageJson["lint-staged"];
|
|
128
137
|
if (lsConfig) {
|
|
129
138
|
const commands = lintStagedCommandValues(lsConfig);
|
|
@@ -138,16 +147,17 @@ if (existsSync(packageJsonPath)) {
|
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
149
|
|
|
141
|
-
//
|
|
150
|
+
// Projects can own an appropriately scoped pre-push gate. Older projects
|
|
151
|
+
// retain the package's typecheck + lint fallback until they add one.
|
|
142
152
|
const scripts = packageJson.scripts || {};
|
|
143
|
-
if (!scripts.typecheck) {
|
|
153
|
+
if (!scripts.prepush && !scripts.typecheck) {
|
|
144
154
|
console.warn(
|
|
145
|
-
'[@howells/husky] Warning: no "typecheck" script found. Pre-push hook requires
|
|
155
|
+
'[@howells/husky] Warning: no "prepush" or "typecheck" script found. Pre-push hook requires one.'
|
|
146
156
|
);
|
|
147
157
|
}
|
|
148
|
-
if (!scripts.lint) {
|
|
158
|
+
if (!scripts.prepush && !scripts.lint) {
|
|
149
159
|
console.warn(
|
|
150
|
-
'[@howells/husky] Warning: no "lint" script found. Pre-push hook requires
|
|
160
|
+
'[@howells/husky] Warning: no "prepush" or "lint" script found. Pre-push hook requires one.'
|
|
151
161
|
);
|
|
152
162
|
}
|
|
153
163
|
}
|
package/hooks/pre-commit
CHANGED
|
File without changes
|
package/hooks/pre-push
CHANGED
|
@@ -54,5 +54,9 @@ if [ "$saw_ref" = "0" ]; then
|
|
|
54
54
|
echo "[@howells/husky] No refs on stdin; checking the working directory."
|
|
55
55
|
fi
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
pnpm
|
|
57
|
+
if node -e 'const scripts = require("./package.json").scripts; process.exit(typeof scripts?.prepush === "string" ? 0 : 1)'; then
|
|
58
|
+
pnpm prepush
|
|
59
|
+
else
|
|
60
|
+
pnpm typecheck || exit 1
|
|
61
|
+
pnpm lint || exit 1
|
|
62
|
+
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@howells/husky",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Standardised git hooks for Howells projects. Immutable pre-commit and pre-push configuration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,12 +21,6 @@
|
|
|
21
21
|
"exports": {
|
|
22
22
|
"./package.json": "./package.json"
|
|
23
23
|
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"lint": "howells-check --config=oxlint.config.ts package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
|
|
26
|
-
"lint:fix": "howells-fix --config=oxlint.config.ts package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
|
|
27
|
-
"format": "howells-oxfmt --write package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
|
|
28
|
-
"test": "node --test bin/detect.test.mjs bin/pre-push.test.mjs"
|
|
29
|
-
},
|
|
30
24
|
"dependencies": {
|
|
31
25
|
"husky": "^9.1.7",
|
|
32
26
|
"lint-staged": "^16.4.0"
|
|
@@ -37,5 +31,10 @@
|
|
|
37
31
|
"engines": {
|
|
38
32
|
"node": ">=24.15.0"
|
|
39
33
|
},
|
|
40
|
-
"
|
|
41
|
-
|
|
34
|
+
"scripts": {
|
|
35
|
+
"lint": "howells-check --config=oxlint.config.ts package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
|
|
36
|
+
"lint:fix": "howells-fix --config=oxlint.config.ts package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
|
|
37
|
+
"format": "howells-oxfmt --write package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
|
|
38
|
+
"test": "node --test bin/detect.test.mjs bin/pre-push.test.mjs"
|
|
39
|
+
}
|
|
40
|
+
}
|