@ankhorage/devtools 1.1.1 → 1.2.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 +165 -138
- package/dist/cli/bin/eslint.js +4 -0
- package/dist/cli/bin/knip.js +4 -0
- package/dist/cli/bin/prettier.js +4 -0
- package/dist/cli/commands.d.ts +25 -0
- package/dist/cli/commands.js +92 -0
- package/dist/cli/index.d.ts +5 -5
- package/dist/cli/index.js +3 -4
- package/dist/cli/runExternalTool.d.ts +31 -0
- package/dist/{internal/runDevtoolsCommand.js → cli/runExternalTool.js} +3 -3
- package/dist/cli/runProviderCommand.d.ts +8 -0
- package/dist/cli/runProviderCommand.js +11 -0
- package/dist/cli/runRepositoryCommand.d.ts +16 -0
- package/dist/cli/runRepositoryCommand.js +108 -0
- package/dist/cli/runStandaloneTool.d.ts +3 -0
- package/dist/cli/runStandaloneTool.js +5 -0
- package/dist/internal/readmeDocs.js +7 -7
- package/dist/{eslint.d.ts → tools/eslint/index.d.ts} +2 -4
- package/dist/{eslint.js → tools/eslint/index.js} +1 -5
- package/dist/tools/eslint/types.d.ts +18 -0
- package/dist/tools/knip/index.d.ts +20 -0
- package/dist/tools/shared/managedFiles.d.ts +20 -0
- package/dist/tools/shared/managedFiles.js +84 -0
- package/dist/tools/vscode/files/extensions.json +9 -0
- package/dist/tools/vscode/files/settings.json +15 -0
- package/dist/tools/vscode/index.d.ts +7 -0
- package/dist/tools/vscode/index.js +10 -0
- package/dist/tools/workflows/files/ci.yml +88 -0
- package/dist/tools/workflows/files/release.yml +65 -0
- package/dist/tools/workflows/index.d.ts +7 -0
- package/dist/tools/workflows/index.js +10 -0
- package/package.json +21 -15
- package/dist/eslint-cli.js +0 -4
- package/dist/internal/devtoolsCommands.d.ts +0 -11
- package/dist/internal/devtoolsCommands.js +0 -39
- package/dist/internal/runDevtoolsCommand.d.ts +0 -31
- package/dist/internal/runStandaloneDevtoolsCommand.d.ts +0 -3
- package/dist/internal/runStandaloneDevtoolsCommand.js +0 -5
- package/dist/knip-cli.js +0 -4
- package/dist/knip.d.ts +0 -20
- package/dist/prettier-cli.js +0 -4
- package/dist/types.d.ts +0 -18
- /package/dist/{eslint-cli.d.ts → cli/bin/eslint.d.ts} +0 -0
- /package/dist/{knip-cli.d.ts → cli/bin/knip.d.ts} +0 -0
- /package/dist/{prettier-cli.d.ts → cli/bin/prettier.d.ts} +0 -0
- /package/dist/{types.js → tools/eslint/types.js} +0 -0
- /package/dist/{knip.js → tools/knip/index.js} +0 -0
- /package/dist/{prettier.cjs → tools/prettier/index.cjs} +0 -0
package/README.md
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
# devtools
|
|
2
2
|
|
|
3
|
-
Shared
|
|
3
|
+
Shared development tools and repository standards for Ankhorage TypeScript projects.
|
|
4
4
|
|
|
5
|
-
## What
|
|
5
|
+
## What it owns
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- Zero-config Prettier setup
|
|
9
|
-
- Shared Knip static-analysis defaults
|
|
10
|
-
- Bundled tool binaries for ESLint, Prettier, and Knip
|
|
11
|
-
- Ankh provider commands for lint, format, and Knip
|
|
12
|
-
- Strict TypeScript rules without compromise
|
|
13
|
-
- One source of truth for tooling
|
|
7
|
+
`@ankhorage/devtools` is the single source of truth for these equal, separate concerns:
|
|
14
8
|
|
|
15
|
-
|
|
9
|
+
```text
|
|
10
|
+
src/
|
|
11
|
+
├── cli/
|
|
12
|
+
└── tools/
|
|
13
|
+
├── eslint/
|
|
14
|
+
├── prettier/
|
|
15
|
+
├── knip/
|
|
16
|
+
├── workflows/
|
|
17
|
+
└── vscode/
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- `eslint`: shared flat ESLint configuration and the bundled ESLint runner
|
|
21
|
+
- `prettier`: shared Prettier configuration and the bundled Prettier runner
|
|
22
|
+
- `knip`: shared Knip configuration and the bundled Knip runner
|
|
23
|
+
- `workflows`: canonical `.github/workflows/ci.yml` and `release.yml`
|
|
24
|
+
- `vscode`: canonical `.vscode/settings.json` and `extensions.json`
|
|
16
25
|
|
|
17
|
-
|
|
18
|
-
- Preconfigured plugin ecosystem
|
|
19
|
-
- Prettier integration
|
|
20
|
-
- Shared Knip config factories
|
|
21
|
-
- `ankhorage-eslint`, `ankhorage-prettier`, and `ankhorage-knip` binaries
|
|
22
|
-
- `ankh devtools lint`, `ankh devtools format`, and `ankh devtools knip`
|
|
23
|
-
- Monorepo-friendly
|
|
26
|
+
There is no generic template layer around these concerns. Each tool owns its canonical files and behavior.
|
|
24
27
|
|
|
25
28
|
## Installation
|
|
26
29
|
|
|
@@ -28,23 +31,43 @@ Shared ESLint, Prettier, and Knip configuration for modern TypeScript projects.
|
|
|
28
31
|
bun add -D @ankhorage/devtools
|
|
29
32
|
```
|
|
30
33
|
|
|
31
|
-
The package owns the ESLint, Prettier, and Knip
|
|
34
|
+
The package owns the ESLint, Prettier, and Knip versions used by consuming repositories. Do not install those tools directly unless a repository intentionally opts out of the shared Ankhorage toolchain.
|
|
35
|
+
|
|
36
|
+
## Ankh provider
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
The package is discovered under the `devtools` category and exposes these capabilities:
|
|
34
39
|
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
- `devtools.lint`
|
|
41
|
+
- `devtools.format`
|
|
42
|
+
- `devtools.knip`
|
|
43
|
+
- `devtools.sync`
|
|
44
|
+
- `devtools.status`
|
|
45
|
+
- `devtools.workflows.sync`
|
|
46
|
+
- `devtools.workflows.status`
|
|
47
|
+
- `devtools.vscode.sync`
|
|
48
|
+
- `devtools.vscode.status`
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
The canonical command prefix is always:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
ankh devtools ...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Tool commands
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
ankh devtools lint -- --max-warnings=0 .
|
|
60
|
+
ankh devtools format -- --check .
|
|
61
|
+
ankh devtools knip -- --production
|
|
62
|
+
```
|
|
42
63
|
|
|
43
|
-
|
|
64
|
+
These commands delegate to the same bundled tools as the package binaries:
|
|
44
65
|
|
|
45
|
-
|
|
66
|
+
- `ankh devtools lint` → `ankhorage-eslint`
|
|
67
|
+
- `ankh devtools format` → `ankhorage-prettier`
|
|
68
|
+
- `ankh devtools knip` → `ankhorage-knip`
|
|
46
69
|
|
|
47
|
-
|
|
70
|
+
Recommended package scripts:
|
|
48
71
|
|
|
49
72
|
```json
|
|
50
73
|
{
|
|
@@ -58,165 +81,169 @@ Use the devtools-owned binaries in package scripts:
|
|
|
58
81
|
}
|
|
59
82
|
```
|
|
60
83
|
|
|
61
|
-
|
|
84
|
+
## Repository synchronization
|
|
62
85
|
|
|
63
|
-
|
|
86
|
+
### Synchronize all managed files
|
|
64
87
|
|
|
65
88
|
```bash
|
|
66
|
-
ankh devtools
|
|
67
|
-
ankh devtools format -- --check .
|
|
68
|
-
ankh devtools knip -- --production
|
|
89
|
+
ankh devtools sync .
|
|
69
90
|
```
|
|
70
91
|
|
|
71
|
-
|
|
92
|
+
The target path is optional and defaults to the current working directory:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
ankh devtools sync
|
|
96
|
+
```
|
|
72
97
|
|
|
73
|
-
|
|
74
|
-
- `ankh devtools format` -> `ankhorage-prettier`
|
|
75
|
-
- `ankh devtools knip` -> `ankhorage-knip`
|
|
98
|
+
### Report drift without changing files
|
|
76
99
|
|
|
77
|
-
|
|
100
|
+
```bash
|
|
101
|
+
ankh devtools status .
|
|
102
|
+
```
|
|
78
103
|
|
|
79
|
-
|
|
104
|
+
`status` exits with code `1` when any managed file is missing or outdated. It exits with code `0` when all managed files are current.
|
|
80
105
|
|
|
81
|
-
|
|
82
|
-
import { createConfig } from '@ankhorage/devtools/eslint';
|
|
106
|
+
Example output:
|
|
83
107
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
108
|
+
```text
|
|
109
|
+
✓ .github/workflows/ci.yml
|
|
110
|
+
✗ .github/workflows/release.yml outdated
|
|
111
|
+
+ .vscode/settings.json missing
|
|
112
|
+
✓ .vscode/extensions.json
|
|
89
113
|
```
|
|
90
114
|
|
|
91
|
-
###
|
|
115
|
+
### Synchronize one concern
|
|
92
116
|
|
|
93
|
-
|
|
117
|
+
```bash
|
|
118
|
+
ankh devtools workflows sync .
|
|
119
|
+
ankh devtools vscode sync .
|
|
120
|
+
```
|
|
94
121
|
|
|
95
|
-
|
|
96
|
-
|
|
122
|
+
### Report one concern
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
ankh devtools workflows status .
|
|
126
|
+
ankh devtools vscode status .
|
|
97
127
|
```
|
|
98
128
|
|
|
99
|
-
|
|
129
|
+
### Preview synchronization
|
|
100
130
|
|
|
101
|
-
```
|
|
102
|
-
|
|
131
|
+
```bash
|
|
132
|
+
ankh devtools sync . --dry-run
|
|
133
|
+
ankh devtools workflows sync . --dry-run
|
|
134
|
+
ankh devtools vscode sync . --dry-run
|
|
103
135
|
```
|
|
104
136
|
|
|
105
|
-
|
|
137
|
+
A dry run reports `would create` and `would update` actions without writing any files.
|
|
106
138
|
|
|
107
|
-
|
|
139
|
+
## Synchronization guarantees
|
|
108
140
|
|
|
109
|
-
|
|
110
|
-
import { createKnipConfig } from '@ankhorage/devtools/knip';
|
|
141
|
+
Synchronization is deterministic and idempotent:
|
|
111
142
|
|
|
112
|
-
|
|
113
|
-
|
|
143
|
+
- missing managed files are created
|
|
144
|
+
- outdated managed files are replaced with the canonical package version
|
|
145
|
+
- current managed files are left untouched
|
|
146
|
+
- unrelated files are never modified
|
|
147
|
+
- unknown files in `.github/workflows` and `.vscode` are never deleted
|
|
148
|
+
- repeating `sync` after a successful run produces only `unchanged` results
|
|
149
|
+
- invalid target paths and write failures return a non-zero exit code
|
|
114
150
|
|
|
115
|
-
|
|
151
|
+
The canonical files are packaged with `@ankhorage/devtools`; synchronization does not fetch mutable files from GitHub at runtime.
|
|
116
152
|
|
|
117
|
-
|
|
118
|
-
import { createKnipConfig } from '@ankhorage/devtools/knip';
|
|
153
|
+
## Managed GitHub Actions workflows
|
|
119
154
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
ignoreFiles: ['examples/fixture.ts'],
|
|
126
|
-
});
|
|
155
|
+
`workflows` owns exactly:
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
.github/workflows/ci.yml
|
|
159
|
+
.github/workflows/release.yml
|
|
127
160
|
```
|
|
128
161
|
|
|
129
|
-
|
|
162
|
+
The CI workflow:
|
|
130
163
|
|
|
131
|
-
|
|
132
|
-
|
|
164
|
+
- checks out full history
|
|
165
|
+
- installs the pinned Bun version
|
|
166
|
+
- installs dependencies with `bun install --frozen-lockfile`
|
|
167
|
+
- runs `bunx @ankhorage/ankh doctor validate .`
|
|
168
|
+
- conditionally runs build, lint, format check, Knip, tests, and typecheck when scripts exist
|
|
169
|
+
- conditionally runs `changeset:status` for pull requests when the script exists
|
|
133
170
|
|
|
134
|
-
|
|
135
|
-
root: {
|
|
136
|
-
ignoreFiles: ['.prettierrc.js', 'eslint.config.js'],
|
|
137
|
-
},
|
|
138
|
-
});
|
|
139
|
-
```
|
|
171
|
+
The release workflow:
|
|
140
172
|
|
|
141
|
-
|
|
173
|
+
- checks out full history
|
|
174
|
+
- configures Bun and Node for npm publishing
|
|
175
|
+
- installs dependencies with the frozen lockfile
|
|
176
|
+
- conditionally builds
|
|
177
|
+
- runs the Changesets release PR/publish flow
|
|
178
|
+
- protects release execution with a concurrency group
|
|
179
|
+
- skips cleanly when no Changesets configuration exists
|
|
142
180
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
},
|
|
151
|
-
workspaces: {
|
|
152
|
-
'.': {
|
|
153
|
-
ignoreFiles: ['.prettierrc.js', 'eslint.config.js'],
|
|
154
|
-
},
|
|
155
|
-
'apps/editor': {
|
|
156
|
-
ignoreFiles: ['babel.config.js'],
|
|
157
|
-
ignoreDependencies: ['babel-preset-expo'],
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
});
|
|
181
|
+
## Managed VS Code configuration
|
|
182
|
+
|
|
183
|
+
`vscode` owns exactly:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
.vscode/settings.json
|
|
187
|
+
.vscode/extensions.json
|
|
161
188
|
```
|
|
162
189
|
|
|
163
|
-
The shared
|
|
190
|
+
The shared settings use the workspace TypeScript SDK, enable the workspace-SDK prompt, configure intentional ESLint save actions, and enforce basic whitespace/newline consistency.
|
|
164
191
|
|
|
165
|
-
|
|
192
|
+
The extension recommendations are limited to the standard Ankhorage workflow:
|
|
166
193
|
|
|
167
|
-
|
|
194
|
+
- Bun
|
|
195
|
+
- ESLint
|
|
196
|
+
- Prettier
|
|
197
|
+
- YAML
|
|
198
|
+
- GitHub Actions
|
|
168
199
|
|
|
169
|
-
|
|
170
|
-
- name: Run lint
|
|
171
|
-
run: bun run lint
|
|
200
|
+
`launch.json` is intentionally not managed globally. Libraries, CLIs, Expo packages, services, and integration repositories require different debug configurations.
|
|
172
201
|
|
|
173
|
-
|
|
174
|
-
run: bun run format:check
|
|
202
|
+
## ESLint
|
|
175
203
|
|
|
176
|
-
|
|
177
|
-
run: bun run knip
|
|
178
|
-
```
|
|
204
|
+
Create `eslint.config.mjs`:
|
|
179
205
|
|
|
180
|
-
|
|
206
|
+
```js
|
|
207
|
+
import { createConfig } from '@ankhorage/devtools/eslint';
|
|
181
208
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
else
|
|
188
|
-
echo "No knip script found; skipping."
|
|
189
|
-
fi
|
|
209
|
+
export default createConfig({
|
|
210
|
+
files: ['src/**/*.{ts,tsx}'],
|
|
211
|
+
project: ['./tsconfig.json'],
|
|
212
|
+
tsconfigRootDir: import.meta.dirname,
|
|
213
|
+
});
|
|
190
214
|
```
|
|
191
215
|
|
|
192
|
-
##
|
|
216
|
+
## Prettier
|
|
193
217
|
|
|
194
|
-
|
|
195
|
-
- Teams that want strict, predictable linting
|
|
196
|
-
- Projects avoiding duplicated config
|
|
197
|
-
- Repos that need consistent unused-file, unused-export, and dependency checks
|
|
218
|
+
ES modules:
|
|
198
219
|
|
|
199
|
-
|
|
220
|
+
```js
|
|
221
|
+
export { default } from '@ankhorage/devtools/prettier';
|
|
222
|
+
```
|
|
200
223
|
|
|
201
|
-
|
|
224
|
+
CommonJS:
|
|
202
225
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
226
|
+
```js
|
|
227
|
+
module.exports = require('@ankhorage/devtools/prettier');
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Knip
|
|
206
231
|
|
|
207
|
-
|
|
232
|
+
```ts
|
|
233
|
+
import { createKnipConfig } from '@ankhorage/devtools/knip';
|
|
208
234
|
|
|
209
|
-
|
|
235
|
+
export default createKnipConfig();
|
|
236
|
+
```
|
|
210
237
|
|
|
211
|
-
|
|
238
|
+
Monorepos can use `createKnipMonorepoConfig` and add narrow repository-specific entries, projects, ignores, binaries, dependencies, or workspace overrides.
|
|
212
239
|
|
|
213
|
-
|
|
214
|
-
- Prettier configuration and binary wrapper
|
|
215
|
-
- Knip configuration and binary wrapper
|
|
216
|
-
- Ankh provider descriptors and handlers for lint, format, and Knip
|
|
240
|
+
## Adding another managed concern
|
|
217
241
|
|
|
218
|
-
|
|
242
|
+
A new concern should:
|
|
219
243
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
244
|
+
1. live in its own sibling directory under `src/tools`
|
|
245
|
+
2. define only the files and behavior it owns
|
|
246
|
+
3. expose deterministic status and synchronization through the shared managed-file engine
|
|
247
|
+
4. add provider commands under `ankh devtools`
|
|
248
|
+
5. include source-tree, built-package, dry-run, status, and idempotence coverage
|
|
249
|
+
6. document overwrite and exit-code behavior
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type DevtoolsToolName = 'format' | 'knip' | 'lint';
|
|
2
|
+
type DevtoolsManagedScope = 'all' | 'vscode' | 'workflows';
|
|
3
|
+
type DevtoolsManagedOperation = 'status' | 'sync';
|
|
4
|
+
type DevtoolsCapability = 'devtools.format' | 'devtools.knip' | 'devtools.lint' | 'devtools.status' | 'devtools.sync' | 'devtools.vscode.status' | 'devtools.vscode.sync' | 'devtools.workflows.status' | 'devtools.workflows.sync';
|
|
5
|
+
interface DevtoolsCommandBase {
|
|
6
|
+
readonly path: readonly [string, ...string[]];
|
|
7
|
+
readonly capability: DevtoolsCapability;
|
|
8
|
+
readonly summary: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DevtoolsExternalCommandDefinition extends DevtoolsCommandBase {
|
|
11
|
+
readonly kind: 'external';
|
|
12
|
+
readonly toolName: DevtoolsToolName;
|
|
13
|
+
readonly packageName: 'eslint' | 'knip' | 'prettier';
|
|
14
|
+
readonly binName: 'eslint' | 'knip' | 'prettier';
|
|
15
|
+
}
|
|
16
|
+
export interface DevtoolsRepositoryCommandDefinition extends DevtoolsCommandBase {
|
|
17
|
+
readonly kind: 'repository';
|
|
18
|
+
readonly scope: DevtoolsManagedScope;
|
|
19
|
+
readonly operation: DevtoolsManagedOperation;
|
|
20
|
+
}
|
|
21
|
+
export type DevtoolsCommandDefinition = DevtoolsExternalCommandDefinition | DevtoolsRepositoryCommandDefinition;
|
|
22
|
+
export declare function getDevtoolsCommands(): readonly DevtoolsCommandDefinition[];
|
|
23
|
+
export declare function findDevtoolsCommandByPath(path: readonly string[]): DevtoolsCommandDefinition | null;
|
|
24
|
+
export declare function getDevtoolsToolCommand(toolName: DevtoolsToolName): DevtoolsExternalCommandDefinition;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const DEVTOOLS_COMMANDS = [
|
|
2
|
+
{
|
|
3
|
+
kind: 'external',
|
|
4
|
+
toolName: 'lint',
|
|
5
|
+
path: ['lint'],
|
|
6
|
+
capability: 'devtools.lint',
|
|
7
|
+
summary: 'Run the shared ESLint toolchain.',
|
|
8
|
+
packageName: 'eslint',
|
|
9
|
+
binName: 'eslint',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
kind: 'external',
|
|
13
|
+
toolName: 'format',
|
|
14
|
+
path: ['format'],
|
|
15
|
+
capability: 'devtools.format',
|
|
16
|
+
summary: 'Run the shared Prettier toolchain.',
|
|
17
|
+
packageName: 'prettier',
|
|
18
|
+
binName: 'prettier',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
kind: 'external',
|
|
22
|
+
toolName: 'knip',
|
|
23
|
+
path: ['knip'],
|
|
24
|
+
capability: 'devtools.knip',
|
|
25
|
+
summary: 'Run the shared Knip toolchain.',
|
|
26
|
+
packageName: 'knip',
|
|
27
|
+
binName: 'knip',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
kind: 'repository',
|
|
31
|
+
path: ['sync'],
|
|
32
|
+
capability: 'devtools.sync',
|
|
33
|
+
summary: 'Synchronize all centrally managed repository files.',
|
|
34
|
+
scope: 'all',
|
|
35
|
+
operation: 'sync',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
kind: 'repository',
|
|
39
|
+
path: ['status'],
|
|
40
|
+
capability: 'devtools.status',
|
|
41
|
+
summary: 'Report drift for all centrally managed repository files.',
|
|
42
|
+
scope: 'all',
|
|
43
|
+
operation: 'status',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
kind: 'repository',
|
|
47
|
+
path: ['workflows', 'sync'],
|
|
48
|
+
capability: 'devtools.workflows.sync',
|
|
49
|
+
summary: 'Synchronize the canonical GitHub Actions workflows.',
|
|
50
|
+
scope: 'workflows',
|
|
51
|
+
operation: 'sync',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
kind: 'repository',
|
|
55
|
+
path: ['workflows', 'status'],
|
|
56
|
+
capability: 'devtools.workflows.status',
|
|
57
|
+
summary: 'Report drift for the canonical GitHub Actions workflows.',
|
|
58
|
+
scope: 'workflows',
|
|
59
|
+
operation: 'status',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
kind: 'repository',
|
|
63
|
+
path: ['vscode', 'sync'],
|
|
64
|
+
capability: 'devtools.vscode.sync',
|
|
65
|
+
summary: 'Synchronize the canonical VS Code workspace configuration.',
|
|
66
|
+
scope: 'vscode',
|
|
67
|
+
operation: 'sync',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
kind: 'repository',
|
|
71
|
+
path: ['vscode', 'status'],
|
|
72
|
+
capability: 'devtools.vscode.status',
|
|
73
|
+
summary: 'Report drift for the canonical VS Code workspace configuration.',
|
|
74
|
+
scope: 'vscode',
|
|
75
|
+
operation: 'status',
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
export function getDevtoolsCommands() {
|
|
79
|
+
return DEVTOOLS_COMMANDS;
|
|
80
|
+
}
|
|
81
|
+
export function findDevtoolsCommandByPath(path) {
|
|
82
|
+
return (DEVTOOLS_COMMANDS.find((command) => command.path.length === path.length &&
|
|
83
|
+
command.path.every((segment, index) => segment === path[index])) ?? null);
|
|
84
|
+
}
|
|
85
|
+
export function getDevtoolsToolCommand(toolName) {
|
|
86
|
+
for (const command of DEVTOOLS_COMMANDS) {
|
|
87
|
+
if (command.kind === 'external' && command.toolName === toolName) {
|
|
88
|
+
return command;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
throw new Error(`Unknown devtools tool command: ${toolName}`);
|
|
92
|
+
}
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -2,16 +2,16 @@ declare const provider: {
|
|
|
2
2
|
id: string;
|
|
3
3
|
category: string;
|
|
4
4
|
version: string;
|
|
5
|
-
capabilities: ("devtools.format" | "devtools.knip" | "devtools.lint")[];
|
|
5
|
+
capabilities: ("devtools.format" | "devtools.knip" | "devtools.lint" | "devtools.status" | "devtools.sync" | "devtools.vscode.status" | "devtools.vscode.sync" | "devtools.workflows.status" | "devtools.workflows.sync")[];
|
|
6
6
|
commands: {
|
|
7
|
-
path: [
|
|
8
|
-
capability: "devtools.format" | "devtools.knip" | "devtools.lint";
|
|
7
|
+
path: [string, ...string[]];
|
|
8
|
+
capability: "devtools.format" | "devtools.knip" | "devtools.lint" | "devtools.status" | "devtools.sync" | "devtools.vscode.status" | "devtools.vscode.sync" | "devtools.workflows.status" | "devtools.workflows.sync";
|
|
9
9
|
summary: string;
|
|
10
10
|
}[];
|
|
11
11
|
handlers: {
|
|
12
|
-
path: [
|
|
12
|
+
path: [string, ...string[]];
|
|
13
13
|
handler: (request: import("@ankhorage/ankh").AnkhCommandExecutionRequest) => Promise<{
|
|
14
|
-
exitCode: number;
|
|
14
|
+
readonly exitCode: number;
|
|
15
15
|
}>;
|
|
16
16
|
}[];
|
|
17
17
|
};
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { getDevtoolsCommands } from '
|
|
3
|
-
import {
|
|
2
|
+
import { getDevtoolsCommands } from './commands.js';
|
|
3
|
+
import { runProviderCommand } from './runProviderCommand.js';
|
|
4
4
|
const packageVersion = readPackageVersion();
|
|
5
5
|
const commands = getDevtoolsCommands();
|
|
6
6
|
const provider = {
|
|
@@ -16,8 +16,7 @@ const provider = {
|
|
|
16
16
|
handlers: commands.map((command) => ({
|
|
17
17
|
path: [...command.path],
|
|
18
18
|
handler: async (request) => {
|
|
19
|
-
|
|
20
|
-
return { exitCode: result.exitCode };
|
|
19
|
+
return await runProviderCommand(command, request.argv, request.context);
|
|
21
20
|
},
|
|
22
21
|
})),
|
|
23
22
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DevtoolsExternalCommandDefinition } from './commands.js';
|
|
2
|
+
export interface DevtoolsRunResult {
|
|
3
|
+
readonly exitCode: number;
|
|
4
|
+
}
|
|
5
|
+
interface DevtoolsRunnerOptions {
|
|
6
|
+
readonly cwd?: string;
|
|
7
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
8
|
+
}
|
|
9
|
+
interface ResolvedExecutionTarget {
|
|
10
|
+
readonly command: string;
|
|
11
|
+
readonly args: readonly string[];
|
|
12
|
+
readonly shell: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface SpawnedProcess {
|
|
15
|
+
on(event: 'error', listener: (error: Error) => void): SpawnedProcess;
|
|
16
|
+
on(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): SpawnedProcess;
|
|
17
|
+
}
|
|
18
|
+
type SpawnProcess = (command: string, args: readonly string[], options: {
|
|
19
|
+
readonly cwd: string;
|
|
20
|
+
readonly env: NodeJS.ProcessEnv;
|
|
21
|
+
readonly shell: boolean;
|
|
22
|
+
readonly stdio: 'inherit';
|
|
23
|
+
}) => SpawnedProcess;
|
|
24
|
+
interface DevtoolsRunnerDependencies {
|
|
25
|
+
readonly logError: (message: string) => void;
|
|
26
|
+
readonly resolveExecutionTarget: (command: DevtoolsExternalCommandDefinition) => Promise<ResolvedExecutionTarget>;
|
|
27
|
+
readonly spawnProcess: SpawnProcess;
|
|
28
|
+
}
|
|
29
|
+
export declare function runExternalTool(command: DevtoolsExternalCommandDefinition, argv: readonly string[], options?: DevtoolsRunnerOptions): Promise<DevtoolsRunResult>;
|
|
30
|
+
export declare function runExternalToolWithDependencies(command: DevtoolsExternalCommandDefinition, argv: readonly string[], options: DevtoolsRunnerOptions | undefined, dependencies: DevtoolsRunnerDependencies): Promise<DevtoolsRunResult>;
|
|
31
|
+
export {};
|
|
@@ -11,10 +11,10 @@ const defaultRunnerDependencies = {
|
|
|
11
11
|
resolveExecutionTarget,
|
|
12
12
|
spawnProcess: (command, args, options) => spawn(command, args, options),
|
|
13
13
|
};
|
|
14
|
-
export async function
|
|
15
|
-
return
|
|
14
|
+
export async function runExternalTool(command, argv, options) {
|
|
15
|
+
return await runExternalToolWithDependencies(command, argv, options, defaultRunnerDependencies);
|
|
16
16
|
}
|
|
17
|
-
export async function
|
|
17
|
+
export async function runExternalToolWithDependencies(command, argv, options, dependencies) {
|
|
18
18
|
let executionTarget;
|
|
19
19
|
try {
|
|
20
20
|
executionTarget = await dependencies.resolveExecutionTarget(command);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DevtoolsCommandDefinition } from './commands.js';
|
|
2
|
+
import { type DevtoolsRepositoryCommandContext } from './runRepositoryCommand.js';
|
|
3
|
+
export interface DevtoolsProviderCommandContext extends DevtoolsRepositoryCommandContext {
|
|
4
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
5
|
+
}
|
|
6
|
+
export declare function runProviderCommand(command: DevtoolsCommandDefinition, argv: readonly string[], context: DevtoolsProviderCommandContext): Promise<{
|
|
7
|
+
readonly exitCode: number;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { runExternalTool } from './runExternalTool.js';
|
|
2
|
+
import { runRepositoryCommand, } from './runRepositoryCommand.js';
|
|
3
|
+
export async function runProviderCommand(command, argv, context) {
|
|
4
|
+
if (command.kind === 'external') {
|
|
5
|
+
return await runExternalTool(command, argv, {
|
|
6
|
+
cwd: context.cwd,
|
|
7
|
+
env: { ...context.env },
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
return await runRepositoryCommand(command, argv, context);
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DevtoolsRepositoryCommandDefinition } from './commands.js';
|
|
2
|
+
export interface DevtoolsRepositoryCommandContext {
|
|
3
|
+
readonly cwd: string;
|
|
4
|
+
writeStdout(text: string): void;
|
|
5
|
+
writeStderr(text: string): void;
|
|
6
|
+
}
|
|
7
|
+
export interface DevtoolsRepositoryCommandResult {
|
|
8
|
+
readonly exitCode: number;
|
|
9
|
+
}
|
|
10
|
+
interface ParsedRepositoryArguments {
|
|
11
|
+
readonly dryRun: boolean;
|
|
12
|
+
readonly targetPath: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function runRepositoryCommand(command: DevtoolsRepositoryCommandDefinition, argv: readonly string[], context: DevtoolsRepositoryCommandContext): Promise<DevtoolsRepositoryCommandResult>;
|
|
15
|
+
export declare function parseRepositoryArguments(argv: readonly string[], allowDryRun: boolean): ParsedRepositoryArguments;
|
|
16
|
+
export {};
|