@ankhorage/devtools 1.0.2 → 1.0.4
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 +99 -10
- package/dist/eslint-cli.d.ts +2 -0
- package/dist/eslint-cli.js +3 -0
- package/dist/internal/runPackageBin.d.ts +1 -0
- package/dist/internal/runPackageBin.js +47 -0
- package/dist/knip-cli.d.ts +2 -0
- package/dist/knip-cli.js +3 -0
- package/dist/knip.d.ts +13 -0
- package/dist/knip.js +13 -0
- package/dist/prettier-cli.d.ts +2 -0
- package/dist/prettier-cli.js +3 -0
- package/dist/types.d.ts +3 -2
- package/package.json +23 -1
package/README.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# devtools
|
|
2
2
|
|
|
3
|
-
Shared ESLint and
|
|
3
|
+
Shared ESLint, Prettier, and Knip configuration for modern TypeScript projects.
|
|
4
4
|
|
|
5
5
|
## What you get
|
|
6
6
|
|
|
7
7
|
- Consistent linting across repos
|
|
8
8
|
- Zero-config Prettier setup
|
|
9
|
+
- Shared Knip static-analysis defaults
|
|
10
|
+
- Bundled tool binaries for ESLint, Prettier, and Knip
|
|
9
11
|
- Strict TypeScript rules without compromise
|
|
10
12
|
- One source of truth for tooling
|
|
11
13
|
|
|
@@ -14,6 +16,8 @@ Shared ESLint and Prettier configuration for modern TypeScript projects.
|
|
|
14
16
|
- Flat ESLint config (latest standard)
|
|
15
17
|
- Preconfigured plugin ecosystem
|
|
16
18
|
- Prettier integration
|
|
19
|
+
- Shared Knip config factory
|
|
20
|
+
- `ankhorage-eslint`, `ankhorage-prettier`, and `ankhorage-knip` binaries
|
|
17
21
|
- Monorepo-friendly
|
|
18
22
|
|
|
19
23
|
## Installation
|
|
@@ -22,22 +26,105 @@ Shared ESLint and Prettier configuration for modern TypeScript projects.
|
|
|
22
26
|
bun add -D @ankhorage/devtools
|
|
23
27
|
```
|
|
24
28
|
|
|
29
|
+
The package owns the ESLint, Prettier, and Knip toolchain. Consuming repos should not install `eslint`, `prettier`, or `knip` directly unless they intentionally need a different version from the shared Ankhorage toolchain.
|
|
30
|
+
|
|
25
31
|
## Usage
|
|
26
32
|
|
|
33
|
+
### Scripts
|
|
34
|
+
|
|
35
|
+
Use the devtools-owned binaries in package scripts:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"scripts": {
|
|
40
|
+
"lint": "ankhorage-eslint . --max-warnings=0",
|
|
41
|
+
"lint:fix": "ankhorage-eslint . --fix --max-warnings=0",
|
|
42
|
+
"format": "ankhorage-prettier --write .",
|
|
43
|
+
"format:check": "ankhorage-prettier --check .",
|
|
44
|
+
"knip": "ankhorage-knip"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
27
49
|
### ESLint
|
|
28
50
|
|
|
51
|
+
Create an `eslint.config.js` file:
|
|
52
|
+
|
|
29
53
|
```js
|
|
30
|
-
import
|
|
54
|
+
import { createConfig } from '@ankhorage/devtools/eslint';
|
|
31
55
|
|
|
32
|
-
export default
|
|
56
|
+
export default createConfig({
|
|
57
|
+
files: ['src/**/*.{ts,tsx}'],
|
|
58
|
+
project: ['./tsconfig.json'],
|
|
59
|
+
tsconfigRootDir: import.meta.dirname,
|
|
60
|
+
});
|
|
33
61
|
```
|
|
34
62
|
|
|
35
63
|
### Prettier
|
|
36
64
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
65
|
+
Create a Prettier config file:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
export { default } from '@ankhorage/devtools/prettier';
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
CommonJS repos can use:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
module.exports = require('@ankhorage/devtools/prettier');
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Knip
|
|
78
|
+
|
|
79
|
+
Create a repo-local `knip.config.ts` file:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { createKnipConfig } from '@ankhorage/devtools/knip';
|
|
83
|
+
|
|
84
|
+
export default createKnipConfig();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Repos can add narrow repo-specific patterns when needed:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { createKnipConfig } from '@ankhorage/devtools/knip';
|
|
91
|
+
|
|
92
|
+
export default createKnipConfig({
|
|
93
|
+
entry: ['scripts/release.ts'],
|
|
94
|
+
project: ['scripts/**/*.ts'],
|
|
95
|
+
ignore: ['fixtures/**'],
|
|
96
|
+
ignoreBinaries: ['custom-tool'],
|
|
97
|
+
ignoreFiles: ['examples/fixture.ts'],
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The shared config intentionally keeps defaults narrow so Knip can use its own zero-config package discovery. Prefer explicit `entry`, `project`, `ignoreBinaries`, `ignoreDependencies`, or `ignoreFiles` over broad ignores.
|
|
102
|
+
|
|
103
|
+
### CI
|
|
104
|
+
|
|
105
|
+
Run the scripts in CI after dependencies are installed:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
- name: Run lint
|
|
109
|
+
run: bun run lint
|
|
110
|
+
|
|
111
|
+
- name: Run format check
|
|
112
|
+
run: bun run format:check
|
|
113
|
+
|
|
114
|
+
- name: Run Knip
|
|
115
|
+
run: bun run knip
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
For workflows that support optional scripts, use the same guard style as the other devtools checks:
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
- name: Run Knip
|
|
122
|
+
run: |
|
|
123
|
+
if node -e "const p=require('./package.json'); process.exit(p.scripts?.knip ? 0 : 1)"; then
|
|
124
|
+
bun run knip
|
|
125
|
+
else
|
|
126
|
+
echo "No knip script found; skipping."
|
|
127
|
+
fi
|
|
41
128
|
```
|
|
42
129
|
|
|
43
130
|
## Use Cases
|
|
@@ -45,10 +132,11 @@ export default config();
|
|
|
45
132
|
- Monorepos with shared standards
|
|
46
133
|
- Teams that want strict, predictable linting
|
|
47
134
|
- Projects avoiding duplicated config
|
|
135
|
+
- Repos that need consistent unused-file, unused-export, and dependency checks
|
|
48
136
|
|
|
49
137
|
## Why this exists
|
|
50
138
|
|
|
51
|
-
Maintaining ESLint
|
|
139
|
+
Maintaining ESLint, Prettier, and Knip configs across multiple repositories leads to:
|
|
52
140
|
|
|
53
141
|
- duplication
|
|
54
142
|
- inconsistency
|
|
@@ -60,8 +148,9 @@ This package centralizes tooling so all projects stay aligned.
|
|
|
60
148
|
|
|
61
149
|
Includes:
|
|
62
150
|
|
|
63
|
-
- ESLint configuration
|
|
64
|
-
- Prettier configuration
|
|
151
|
+
- ESLint configuration and binary wrapper
|
|
152
|
+
- Prettier configuration and binary wrapper
|
|
153
|
+
- Knip configuration and binary wrapper
|
|
65
154
|
|
|
66
155
|
Excludes:
|
|
67
156
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runPackageBin(packageName: string, binName: string): void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === 'object' && value !== null;
|
|
8
|
+
}
|
|
9
|
+
function readPackageBinPath(packageName, binName) {
|
|
10
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`);
|
|
11
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
12
|
+
if (!isRecord(packageJson)) {
|
|
13
|
+
throw new Error(`Package metadata for ${packageName} is not an object.`);
|
|
14
|
+
}
|
|
15
|
+
const { bin } = packageJson;
|
|
16
|
+
let relativeBinPath;
|
|
17
|
+
if (typeof bin === 'string') {
|
|
18
|
+
relativeBinPath = bin;
|
|
19
|
+
}
|
|
20
|
+
else if (isRecord(bin)) {
|
|
21
|
+
const namedBin = bin[binName];
|
|
22
|
+
if (typeof namedBin === 'string') {
|
|
23
|
+
relativeBinPath = namedBin;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (relativeBinPath === undefined) {
|
|
27
|
+
throw new Error(`Package ${packageName} does not expose a ${binName} binary.`);
|
|
28
|
+
}
|
|
29
|
+
return resolve(dirname(packageJsonPath), relativeBinPath);
|
|
30
|
+
}
|
|
31
|
+
export function runPackageBin(packageName, binName) {
|
|
32
|
+
const binPath = readPackageBinPath(packageName, binName);
|
|
33
|
+
const child = spawn(process.execPath, [binPath, ...process.argv.slice(2)], {
|
|
34
|
+
stdio: 'inherit',
|
|
35
|
+
});
|
|
36
|
+
child.on('error', (error) => {
|
|
37
|
+
console.error(error);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
});
|
|
40
|
+
child.on('exit', (code, signal) => {
|
|
41
|
+
if (signal !== null) {
|
|
42
|
+
console.error(`${binName} exited with signal ${signal}.`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
process.exit(code ?? 1);
|
|
46
|
+
});
|
|
47
|
+
}
|
package/dist/knip-cli.js
ADDED
package/dist/knip.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { KnipConfig } from 'knip';
|
|
2
|
+
export interface DevtoolsKnipWorkspaceConfigOptions {
|
|
3
|
+
entry?: string[];
|
|
4
|
+
project?: string[];
|
|
5
|
+
ignore?: string[];
|
|
6
|
+
ignoreBinaries?: string[];
|
|
7
|
+
ignoreDependencies?: (string | RegExp)[];
|
|
8
|
+
ignoreFiles?: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface DevtoolsKnipConfigOptions extends DevtoolsKnipWorkspaceConfigOptions {
|
|
11
|
+
workspaces?: Record<string, DevtoolsKnipWorkspaceConfigOptions>;
|
|
12
|
+
}
|
|
13
|
+
export declare function createKnipConfig(options?: DevtoolsKnipConfigOptions): KnipConfig;
|
package/dist/knip.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function createKnipConfig(options = {}) {
|
|
2
|
+
return {
|
|
3
|
+
...(options.entry === undefined ? {} : { entry: options.entry }),
|
|
4
|
+
...(options.project === undefined ? {} : { project: options.project }),
|
|
5
|
+
...(options.ignore === undefined ? {} : { ignore: options.ignore }),
|
|
6
|
+
...(options.ignoreBinaries === undefined ? {} : { ignoreBinaries: options.ignoreBinaries }),
|
|
7
|
+
...(options.ignoreDependencies === undefined
|
|
8
|
+
? {}
|
|
9
|
+
: { ignoreDependencies: options.ignoreDependencies }),
|
|
10
|
+
...(options.ignoreFiles === undefined ? {} : { ignoreFiles: options.ignoreFiles }),
|
|
11
|
+
...(options.workspaces === undefined ? {} : { workspaces: options.workspaces }),
|
|
12
|
+
};
|
|
13
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type tseslint from 'typescript-eslint';
|
|
2
|
-
|
|
2
|
+
type FlatConfig = ReturnType<typeof tseslint.config>;
|
|
3
3
|
export type FlatConfigItem = FlatConfig[number];
|
|
4
|
-
|
|
4
|
+
interface RestrictedImport {
|
|
5
5
|
name: string;
|
|
6
6
|
message: string;
|
|
7
7
|
}
|
|
@@ -15,3 +15,4 @@ export interface DevtoolsConfigOptions {
|
|
|
15
15
|
overrides?: FlatConfigItem[];
|
|
16
16
|
includePrettier?: boolean;
|
|
17
17
|
}
|
|
18
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/devtools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Shared Lint and Format Configuration for Ankhorage",
|
|
5
5
|
"homepage": "https://github.com/ankhorage/devtools#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -14,11 +14,30 @@
|
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"typescript",
|
|
19
|
+
"eslint",
|
|
20
|
+
"prettier",
|
|
21
|
+
"knip",
|
|
22
|
+
"linting",
|
|
23
|
+
"formatting",
|
|
24
|
+
"static-analysis",
|
|
25
|
+
"developer-tools"
|
|
26
|
+
],
|
|
27
|
+
"bin": {
|
|
28
|
+
"ankhorage-eslint": "./dist/eslint-cli.js",
|
|
29
|
+
"ankhorage-knip": "./dist/knip-cli.js",
|
|
30
|
+
"ankhorage-prettier": "./dist/prettier-cli.js"
|
|
31
|
+
},
|
|
17
32
|
"exports": {
|
|
18
33
|
"./eslint": {
|
|
19
34
|
"types": "./dist/eslint.d.ts",
|
|
20
35
|
"import": "./dist/eslint.js"
|
|
21
36
|
},
|
|
37
|
+
"./knip": {
|
|
38
|
+
"types": "./dist/knip.d.ts",
|
|
39
|
+
"import": "./dist/knip.js"
|
|
40
|
+
},
|
|
22
41
|
"./prettier": {
|
|
23
42
|
"require": "./dist/prettier.cjs"
|
|
24
43
|
}
|
|
@@ -31,7 +50,9 @@
|
|
|
31
50
|
],
|
|
32
51
|
"scripts": {
|
|
33
52
|
"build": "tsc && cp src/prettier.cjs dist/prettier.cjs",
|
|
53
|
+
"knip": "knip",
|
|
34
54
|
"lint": "eslint .",
|
|
55
|
+
"lint:fix": "eslint . --fix --max-warnings=0",
|
|
35
56
|
"format": "prettier --write .",
|
|
36
57
|
"format:check": "prettier --check .",
|
|
37
58
|
"test": "bun test",
|
|
@@ -45,6 +66,7 @@
|
|
|
45
66
|
"eslint-plugin-prettier": "^5.5.5",
|
|
46
67
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
47
68
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
69
|
+
"knip": "^6.12.2",
|
|
48
70
|
"prettier": "^3.8.1",
|
|
49
71
|
"typescript-eslint": "^8.24.0"
|
|
50
72
|
},
|