@howells/husky 0.1.0 → 0.1.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 CHANGED
@@ -18,7 +18,7 @@ In `package.json`:
18
18
  "prepare": "howells-husky"
19
19
  },
20
20
  "lint-staged": {
21
- "*.{js,ts,jsx,tsx,json,jsonc,css}": "howells-format"
21
+ "*.{js,ts,jsx,tsx,json,jsonc,css}": "howells-ox-fix"
22
22
  }
23
23
  }
24
24
  ```
@@ -29,7 +29,9 @@ That's it. On `pnpm install`, the hooks are installed automatically.
29
29
 
30
30
  ### Pre-commit
31
31
 
32
- Runs `pnpm lint-staged` — formats staged files with `howells-format`.
32
+ Runs `pnpm lint-staged` — formats staged files with the configured Howells formatter.
33
+ Use `howells-ox-fix` for projects on the Ox lint path. `howells-format` remains supported
34
+ for older projects.
33
35
 
34
36
  ### Pre-push
35
37
 
@@ -41,7 +43,7 @@ Your `package.json` must have:
41
43
 
42
44
  - `"typecheck"` script (e.g. `tsc --noEmit` or `turbo run typecheck`)
43
45
  - `"lint"` script (e.g. `howells-lint` or `turbo run lint`)
44
- - `"lint-staged"` config using `howells-format`
46
+ - `"lint-staged"` config using `howells-ox-fix` or `howells-format`
45
47
 
46
48
  ## Why a package?
47
49
 
@@ -16,13 +16,46 @@
16
16
  */
17
17
 
18
18
  import { spawnSync } from "node:child_process";
19
- import { copyFileSync, existsSync, mkdirSync, readFileSync, chmodSync } from "node:fs";
19
+ import {
20
+ copyFileSync,
21
+ existsSync,
22
+ mkdirSync,
23
+ readFileSync,
24
+ chmodSync,
25
+ } from "node:fs";
20
26
  import { dirname, join, resolve } from "node:path";
21
27
  import { fileURLToPath } from "node:url";
22
28
 
23
- const __dirname = dirname(fileURLToPath(import.meta.url));
29
+ const __dirname = import.meta.dirname;
24
30
  const packageRoot = resolve(__dirname, "..");
25
31
  const projectRoot = process.cwd();
32
+ // `howells-fix` is the current canonical @howells/lint fixer; `howells-ox-fix`
33
+ // and `howells-format` are earlier names still in use by repos mid-migration.
34
+ // Accept all three so a correct lint-staged config never draws a false warning.
35
+ const lintStagedFormatterCommands = [
36
+ "howells-fix",
37
+ "howells-ox-fix",
38
+ "howells-format",
39
+ ];
40
+ const recommendedLintStagedCommand = "howells-fix";
41
+
42
+ function lintStagedCommandValues(config) {
43
+ return Object.values(config).flatMap((value) => {
44
+ if (typeof value === "string") {
45
+ return [value];
46
+ }
47
+ if (Array.isArray(value)) {
48
+ return value.filter((item) => typeof item === "string");
49
+ }
50
+ return [];
51
+ });
52
+ }
53
+
54
+ function usesSupportedFormatter(command) {
55
+ return lintStagedFormatterCommands.some((formatter) =>
56
+ command.includes(formatter)
57
+ );
58
+ }
26
59
 
27
60
  // Skip in CI environments — hooks aren't needed there
28
61
  if (process.env.CI === "true" || process.env.VERCEL === "1") {
@@ -38,19 +71,22 @@ if (!existsSync(join(projectRoot, ".git"))) {
38
71
  const huskyBin = resolve(packageRoot, "node_modules", ".bin", "husky");
39
72
  const huskyResult = spawnSync(huskyBin, [], {
40
73
  cwd: projectRoot,
41
- stdio: "inherit",
42
74
  env: process.env,
75
+ stdio: "inherit",
43
76
  });
44
77
 
45
78
  if (huskyResult.error) {
46
79
  // Fallback: try resolving husky from the project's node_modules
47
80
  const fallbackResult = spawnSync("npx", ["husky"], {
48
81
  cwd: projectRoot,
49
- stdio: "inherit",
50
82
  env: process.env,
83
+ stdio: "inherit",
51
84
  });
52
85
 
53
- if (fallbackResult.error || (fallbackResult.status !== null && fallbackResult.status !== 0)) {
86
+ if (
87
+ fallbackResult.error ||
88
+ (fallbackResult.status !== null && fallbackResult.status !== 0)
89
+ ) {
54
90
  console.error("[@howells/husky] Failed to initialise husky");
55
91
  process.exit(1);
56
92
  }
@@ -75,30 +111,28 @@ for (const hook of hooks) {
75
111
  // Step 3: Validate lint-staged config
76
112
  const packageJsonPath = join(projectRoot, "package.json");
77
113
  if (existsSync(packageJsonPath)) {
78
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
114
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
79
115
 
80
116
  if (!packageJson["lint-staged"]) {
81
117
  console.warn(
82
- '[@howells/husky] Warning: no "lint-staged" config found in package.json.',
118
+ '[@howells/husky] Warning: no "lint-staged" config found in package.json.'
83
119
  );
84
120
  console.warn(
85
- ' Add: "lint-staged": { "*.{js,ts,jsx,tsx,json,jsonc,css}": "howells-format" }',
121
+ ` Add: "lint-staged": { "*.{js,ts,jsx,tsx,json,jsonc,css}": "${recommendedLintStagedCommand}" }`
86
122
  );
87
123
  }
88
124
 
89
- // Check that the lint-staged command uses howells-format
125
+ // Check that the lint-staged command uses a supported Howells formatter.
90
126
  const lsConfig = packageJson["lint-staged"];
91
127
  if (lsConfig) {
92
- const commands = Object.values(lsConfig);
93
- const usesHowells = commands.some(
94
- (cmd) => typeof cmd === "string" && cmd.includes("howells-format"),
95
- );
128
+ const commands = lintStagedCommandValues(lsConfig);
129
+ const usesHowells = commands.some(usesSupportedFormatter);
96
130
  if (!usesHowells) {
97
131
  console.warn(
98
- "[@howells/husky] Warning: lint-staged should use howells-format.",
132
+ "[@howells/husky] Warning: lint-staged should use a supported Howells formatter."
99
133
  );
100
134
  console.warn(
101
- ' Expected: "*.{js,ts,jsx,tsx,json,jsonc,css}": "howells-format"',
135
+ ` Expected: "*.{js,ts,jsx,tsx,json,jsonc,css}": "${recommendedLintStagedCommand}"`
102
136
  );
103
137
  }
104
138
  }
@@ -107,12 +141,12 @@ if (existsSync(packageJsonPath)) {
107
141
  const scripts = packageJson.scripts || {};
108
142
  if (!scripts.typecheck) {
109
143
  console.warn(
110
- '[@howells/husky] Warning: no "typecheck" script found. Pre-push hook requires it.',
144
+ '[@howells/husky] Warning: no "typecheck" script found. Pre-push hook requires it.'
111
145
  );
112
146
  }
113
147
  if (!scripts.lint) {
114
148
  console.warn(
115
- '[@howells/husky] Warning: no "lint" script found. Pre-push hook requires it.',
149
+ '[@howells/husky] Warning: no "lint" script found. Pre-push hook requires it.'
116
150
  );
117
151
  }
118
152
  }
package/package.json CHANGED
@@ -1,21 +1,29 @@
1
1
  {
2
2
  "name": "@howells/husky",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Standardised git hooks for Howells projects. Immutable pre-commit and pre-push configuration.",
5
5
  "license": "MIT",
6
+ "bin": {
7
+ "howells-husky": "bin/howells-husky.mjs"
8
+ },
6
9
  "files": [
7
10
  "bin/*.mjs",
8
11
  "hooks/*",
9
12
  "README.md"
10
13
  ],
11
- "bin": {
12
- "howells-husky": "bin/howells-husky.mjs"
14
+ "exports": {
15
+ "./package.json": "./package.json"
16
+ },
17
+ "scripts": {
18
+ "lint": "howells-ox-check --config=oxlint.config.ts package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
19
+ "lint:fix": "howells-ox-fix --config=oxlint.config.ts package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts",
20
+ "format": "howells-oxfmt --write package.json bin hooks README.md oxlint.config.ts oxfmt.config.ts README.md"
13
21
  },
14
22
  "dependencies": {
15
23
  "husky": "^9.1.7",
16
24
  "lint-staged": "^16.4.0"
17
25
  },
18
- "exports": {
19
- "./package.json": "./package.json"
26
+ "devDependencies": {
27
+ "@howells/lint": "^0.2.1"
20
28
  }
21
29
  }