@ankhorage/devtools 1.14.7 → 1.14.8
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 +47 -2
- package/dist/internal/readmeDocs.js +1 -1
- package/dist/owner/synchronizeRenovateOwnerAsync.js +2 -23
- package/dist/policy/renderBunPolicyDocumentation.d.ts +3 -0
- package/dist/policy/renderBunPolicyDocumentation.js +24 -0
- package/dist/tools/eslint/index.js +2 -2
- package/dist/tools/eslint/resolveEslintProfile.d.ts +3 -0
- package/dist/tools/eslint/{profile.js → resolveEslintProfile.js} +8 -18
- package/dist/tools/eslint/resolveEslintProfileFromDetectionInput.d.ts +4 -0
- package/dist/tools/eslint/resolveEslintProfileFromDetectionInput.js +10 -0
- package/dist/types/bunPolicy.d.ts +5 -0
- package/dist/types/bunPolicy.js +1 -0
- package/package.json +4 -2
- package/dist/tools/eslint/profile.d.ts +0 -4
package/README.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- markdownlint-disable MD013 MD033 -->
|
|
2
|
+
<!-- This file is generated by Paradox. Do not edit manually. -->
|
|
3
|
+
|
|
4
|
+
# @ankhorage/devtools
|
|
5
|
+
|
|
6
|
+
        
|
|
7
|
+
|
|
8
|
+
Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
2
11
|
|
|
3
12
|
Shared development tools and repository standards for Ankhorage TypeScript projects.
|
|
4
13
|
|
|
@@ -204,7 +213,7 @@ Agent Skill scripts are always TypeScript files with a `.ts` extension and run w
|
|
|
204
213
|
|
|
205
214
|
`createConfig()` defaults to `profile: 'auto'`.
|
|
206
215
|
|
|
207
|
-
Automatic detection reads the consuming repository's `package.json` and delegates project trait detection to `@ankhorage/
|
|
216
|
+
Automatic detection reads the consuming repository's `package.json` and delegates project trait detection to `@ankhorage/project-detector`. Dependency signals are considered across `dependencies`, `devDependencies`, and `peerDependencies`.
|
|
208
217
|
|
|
209
218
|
Profile precedence is:
|
|
210
219
|
|
|
@@ -375,3 +384,39 @@ A new concern should:
|
|
|
375
384
|
4. add provider commands under `ankh devtools`
|
|
376
385
|
5. include dry-run, status, and idempotence coverage
|
|
377
386
|
6. document its central ownership and repository-owned extension points
|
|
387
|
+
|
|
388
|
+
## CLI
|
|
389
|
+
|
|
390
|
+
Run and synchronize the shared development toolchain through the Ankh CLI.
|
|
391
|
+
|
|
392
|
+
`ankh devtools changeset`, `ankh devtools lint`, `ankh devtools format`, and
|
|
393
|
+
`ankh devtools knip` execute the bundled Changesets, ESLint, Prettier, and Knip versions.
|
|
394
|
+
Repository synchronization is available through
|
|
395
|
+
`ankh devtools sync` and `ankh devtools status`, with focused `agents`, `skills`, `eslint`,
|
|
396
|
+
`prettier`, `knip`, `package`, `workflows`, and `vscode` sync/status subcommands.
|
|
397
|
+
|
|
398
|
+
Sync commands accept an optional target directory and `--dry-run`. Aggregate sync is
|
|
399
|
+
deterministic and idempotent: canonical managed files and skill trees are created or updated,
|
|
400
|
+
unrelated repository-local skills and create-only local extension files remain repository-owned,
|
|
401
|
+
and package metadata is merge-updated without replacing unrelated fields.
|
|
402
|
+
|
|
403
|
+
Fresh repositories can bootstrap the standard setup with `ankh devtools sync .` after adding
|
|
404
|
+
`@ankhorage/devtools`. Existing ESLint configuration is preserved during first migration as a
|
|
405
|
+
local extension before the canonical auto-detecting wrapper is installed.
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
bunx @ankhorage/devtools ankhorage-changeset
|
|
409
|
+
bunx @ankhorage/devtools ankhorage-eslint
|
|
410
|
+
bunx @ankhorage/devtools ankhorage-knip
|
|
411
|
+
bunx @ankhorage/devtools ankhorage-prettier
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Generated documentation
|
|
415
|
+
|
|
416
|
+
- [Interactive documentation app](././paradox/index.html)
|
|
417
|
+
- [Public API reference](././paradox/exports.md)
|
|
418
|
+
- [Component registry](././paradox/components.md)
|
|
419
|
+
- [Architecture overview](././paradox/diagrams/architecture-overview.mmd)
|
|
420
|
+
- [Module relationships](././paradox/diagrams/module-relationships.mmd)
|
|
421
|
+
- [Export graph](././paradox/diagrams/export-graph.mmd)
|
|
422
|
+
- [createKnipMonorepoConfig sequence](././paradox/diagrams/sequences/create-knip-monorepo-config.mmd)
|
|
@@ -26,7 +26,7 @@ const REQUIRED_README_SNIPPETS = [
|
|
|
26
26
|
'devtools.vscode.sync',
|
|
27
27
|
'--dry-run',
|
|
28
28
|
"profile: 'auto'",
|
|
29
|
-
'@ankhorage/
|
|
29
|
+
'@ankhorage/project-detector',
|
|
30
30
|
'ankhorage-changeset',
|
|
31
31
|
'without creating a second Version Packages pull request',
|
|
32
32
|
'chore(release)',
|
|
@@ -3,6 +3,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
|
3
3
|
import { dirname, resolve } from 'node:path';
|
|
4
4
|
import { applyBunRuntimePolicy } from '../policy/applyBunRuntimePolicy.js';
|
|
5
5
|
import { nodeRuntimePolicy } from '../policy/bunRuntimePolicy.js';
|
|
6
|
+
import { renderBunPolicyDocumentation } from '../policy/renderBunPolicyDocumentation.js';
|
|
6
7
|
import { renderRenovateWorkflowAsync } from '../tools/workflows/renderRenovateWorkflowAsync.js';
|
|
7
8
|
import { renderWorkflowAsync } from '../tools/workflows/renderWorkflowAsync.js';
|
|
8
9
|
export async function synchronizeRenovateOwnerAsync(operation, targetDirectory, options = {}) {
|
|
@@ -57,7 +58,7 @@ async function createManagedDefinitionsAsync(targetDirectory, policy) {
|
|
|
57
58
|
},
|
|
58
59
|
{
|
|
59
60
|
relativePath: 'README.md',
|
|
60
|
-
contents:
|
|
61
|
+
contents: renderBunPolicyDocumentation(readme, policy),
|
|
61
62
|
},
|
|
62
63
|
];
|
|
63
64
|
}
|
|
@@ -96,26 +97,6 @@ async function readTargetBunPolicyAsync(targetDirectory) {
|
|
|
96
97
|
version,
|
|
97
98
|
};
|
|
98
99
|
}
|
|
99
|
-
function replaceReadmePolicy(readme, policy) {
|
|
100
|
-
const startIndex = readme.indexOf(README_POLICY_START);
|
|
101
|
-
const endIndex = readme.indexOf(README_POLICY_END);
|
|
102
|
-
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
|
|
103
|
-
throw new Error('README.md must contain one ordered Devtools Bun policy marker pair.');
|
|
104
|
-
}
|
|
105
|
-
if (readme.includes(README_POLICY_START, startIndex + README_POLICY_START.length) ||
|
|
106
|
-
readme.includes(README_POLICY_END, endIndex + README_POLICY_END.length)) {
|
|
107
|
-
throw new Error('README.md must contain exactly one Devtools Bun policy marker pair.');
|
|
108
|
-
}
|
|
109
|
-
const replacement = `${README_POLICY_START}\n\n${renderReadmePolicy(policy)}\n\n${README_POLICY_END}`;
|
|
110
|
-
return `${readme.slice(0, startIndex)}${replacement}${readme.slice(endIndex + README_POLICY_END.length)}`;
|
|
111
|
-
}
|
|
112
|
-
function renderReadmePolicy(policy) {
|
|
113
|
-
return `\`\`\`text
|
|
114
|
-
Bun runtime ${policy.version}
|
|
115
|
-
packageManager ${policy.packageManager}
|
|
116
|
-
@types/bun ${policy.typesRange}
|
|
117
|
-
\`\`\``;
|
|
118
|
-
}
|
|
119
100
|
async function runBunLockfileAsync(operation, targetDirectory) {
|
|
120
101
|
const args = [
|
|
121
102
|
'install',
|
|
@@ -156,5 +137,3 @@ async function syncDefinitionsAsync(targetDirectory, definitions) {
|
|
|
156
137
|
}
|
|
157
138
|
const BUN_VERSION_PATTERN = /const BUN_VERSION = '(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)';/gu;
|
|
158
139
|
const BUN_TYPES_VERSION_PATTERN = /const BUN_TYPES_VERSION = '(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)';/gu;
|
|
159
|
-
const README_POLICY_END = '<!-- devtools-bun-policy:end -->';
|
|
160
|
-
const README_POLICY_START = '<!-- devtools-bun-policy:start -->';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*** Render the managed Bun policy section while preserving the surrounding guide. */
|
|
2
|
+
export function renderBunPolicyDocumentation(readme, policy) {
|
|
3
|
+
const startIndex = readme.indexOf(README_POLICY_START);
|
|
4
|
+
const endIndex = readme.indexOf(README_POLICY_END);
|
|
5
|
+
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
|
|
6
|
+
throw new Error('README.md must contain one ordered Devtools Bun policy marker pair.');
|
|
7
|
+
}
|
|
8
|
+
if (readme.includes(README_POLICY_START, startIndex + README_POLICY_START.length) ||
|
|
9
|
+
readme.includes(README_POLICY_END, endIndex + README_POLICY_END.length)) {
|
|
10
|
+
throw new Error('README.md must contain exactly one Devtools Bun policy marker pair.');
|
|
11
|
+
}
|
|
12
|
+
const replacement = `${README_POLICY_START}\n\n${renderReadmePolicy(policy)}\n\n${README_POLICY_END}`;
|
|
13
|
+
return `${readme.slice(0, startIndex)}${replacement}${readme.slice(endIndex + README_POLICY_END.length)}`;
|
|
14
|
+
}
|
|
15
|
+
/*** Format canonical runtime and type-package versions for the guide. */
|
|
16
|
+
function renderReadmePolicy(policy) {
|
|
17
|
+
return `\`\`\`text
|
|
18
|
+
Bun runtime ${policy.version}
|
|
19
|
+
packageManager ${policy.packageManager}
|
|
20
|
+
@types/bun ${policy.typesRange}
|
|
21
|
+
\`\`\``;
|
|
22
|
+
}
|
|
23
|
+
const README_POLICY_END = '<!-- devtools-bun-policy:end -->';
|
|
24
|
+
const README_POLICY_START = '<!-- devtools-bun-policy:start -->';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Create the shared strict ESLint flat configuration used by consuming repositories.
|
|
3
3
|
*
|
|
4
4
|
* The default `profile: 'auto'` reads the nearest `package.json` from `tsconfigRootDir` and uses
|
|
5
|
-
* `@ankhorage/
|
|
5
|
+
* `@ankhorage/project-detector` to select overlapping project traits. React Native and Expo select
|
|
6
6
|
* the `react-native` profile, React and Next.js select `react`, and other projects use `base`.
|
|
7
7
|
*
|
|
8
8
|
* Every profile includes the shared TypeScript, import, unused-import, Prettier, security, and
|
|
@@ -30,7 +30,7 @@ import securityPlugin from 'eslint-plugin-security';
|
|
|
30
30
|
import simpleImportSort from 'eslint-plugin-simple-import-sort';
|
|
31
31
|
import unusedImports from 'eslint-plugin-unused-imports';
|
|
32
32
|
import tseslint from 'typescript-eslint';
|
|
33
|
-
import { resolveEslintProfile } from './
|
|
33
|
+
import { resolveEslintProfile } from './resolveEslintProfile.js';
|
|
34
34
|
export const defaultIgnores = [
|
|
35
35
|
'**/ios/**',
|
|
36
36
|
'**/android/**',
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DevtoolsConfigOptions, ResolvedDevtoolsEslintProfile } from './types.js';
|
|
2
|
+
/*** Read the consuming package metadata and resolve its requested ESLint profile. */
|
|
3
|
+
export declare function resolveEslintProfile(options: DevtoolsConfigOptions): ResolvedDevtoolsEslintProfile;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
|
-
import {
|
|
2
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
3
3
|
import { resolveProjectPackageJsonPath } from './packageJsonPath.js';
|
|
4
|
+
import { resolveEslintProfileFromDetectionInput } from './resolveEslintProfileFromDetectionInput.js';
|
|
5
|
+
/*** Read the consuming package metadata and resolve its requested ESLint profile. */
|
|
4
6
|
export function resolveEslintProfile(options) {
|
|
5
7
|
const requestedProfile = options.profile ?? 'auto';
|
|
6
8
|
if (requestedProfile !== 'auto')
|
|
@@ -9,14 +11,7 @@ export function resolveEslintProfile(options) {
|
|
|
9
11
|
const input = packageJsonPath === null ? {} : readDetectionInput(packageJsonPath);
|
|
10
12
|
return resolveEslintProfileFromDetectionInput('auto', input);
|
|
11
13
|
}
|
|
12
|
-
|
|
13
|
-
if (requestedProfile !== 'auto')
|
|
14
|
-
return requestedProfile;
|
|
15
|
-
const { traits } = detectProject(input);
|
|
16
|
-
if (traits.has('react-native') || traits.has('expo'))
|
|
17
|
-
return 'react-native';
|
|
18
|
-
return traits.has('react') ? 'react' : 'base';
|
|
19
|
-
}
|
|
14
|
+
/*** Normalize relevant manifest fields without evaluating project configuration. */
|
|
20
15
|
function readDetectionInput(packageJsonPath) {
|
|
21
16
|
const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
22
17
|
if (!isRecord(parsed)) {
|
|
@@ -30,20 +25,18 @@ function readDetectionInput(packageJsonPath) {
|
|
|
30
25
|
...(typeof parsed.packageManager === 'string' ? { packageManager: parsed.packageManager } : {}),
|
|
31
26
|
};
|
|
32
27
|
}
|
|
28
|
+
/*** Include one dependency section only when it contains a record. */
|
|
33
29
|
function optionalDependencyMap(key, value) {
|
|
34
30
|
const dependencyMap = toDependencyMap(value);
|
|
35
31
|
return dependencyMap === undefined ? {} : { [key]: dependencyMap };
|
|
36
32
|
}
|
|
33
|
+
/*** Retain string package ranges from one manifest dependency section. */
|
|
37
34
|
function toDependencyMap(value) {
|
|
38
35
|
if (!isRecord(value))
|
|
39
36
|
return undefined;
|
|
40
|
-
|
|
41
|
-
for (const [name, version] of Object.entries(value)) {
|
|
42
|
-
if (typeof version === 'string')
|
|
43
|
-
dependencies[name] = version;
|
|
44
|
-
}
|
|
45
|
-
return dependencies;
|
|
37
|
+
return Object.fromEntries(Object.entries(value).flatMap(([name, version]) => typeof version === 'string' ? [[name, version]] : []));
|
|
46
38
|
}
|
|
39
|
+
/*** Retain runtime engine signals used by the canonical detector. */
|
|
47
40
|
function optionalEngines(value) {
|
|
48
41
|
if (!isRecord(value))
|
|
49
42
|
return {};
|
|
@@ -53,6 +46,3 @@ function optionalEngines(value) {
|
|
|
53
46
|
};
|
|
54
47
|
return Object.keys(engines).length === 0 ? {} : { engines };
|
|
55
48
|
}
|
|
56
|
-
function isRecord(value) {
|
|
57
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
58
|
-
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProjectDetectionInput } from '@ankhorage/project-detector/types';
|
|
2
|
+
import type { DevtoolsEslintProfile, ResolvedDevtoolsEslintProfile } from './types.js';
|
|
3
|
+
/*** Apply Devtools profile precedence to traits from the canonical project detector. */
|
|
4
|
+
export declare function resolveEslintProfileFromDetectionInput(requestedProfile: DevtoolsEslintProfile, input: ProjectDetectionInput): ResolvedDevtoolsEslintProfile;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { detectProject } from '@ankhorage/project-detector';
|
|
2
|
+
/*** Apply Devtools profile precedence to traits from the canonical project detector. */
|
|
3
|
+
export function resolveEslintProfileFromDetectionInput(requestedProfile, input) {
|
|
4
|
+
if (requestedProfile !== 'auto')
|
|
5
|
+
return requestedProfile;
|
|
6
|
+
const { traits } = detectProject(input);
|
|
7
|
+
if (traits.has('react-native') || traits.has('expo'))
|
|
8
|
+
return 'react-native';
|
|
9
|
+
return traits.has('react') ? 'react' : 'base';
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/devtools",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.8",
|
|
4
4
|
"description": "Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/devtools#readme",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"lint:fix": "eslint . --fix --max-warnings=0",
|
|
101
101
|
"format": "prettier --write .",
|
|
102
102
|
"format:check": "prettier --check .",
|
|
103
|
-
"docs": "bun run docs:check",
|
|
103
|
+
"docs": "paradox && bun run docs:check",
|
|
104
104
|
"docs:check": "bun scripts/check-docs.ts",
|
|
105
105
|
"test": "bun test",
|
|
106
106
|
"changeset": "bun src/cli/bin/changeset.ts",
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
"version-packages": "bun src/cli/bin/changeset.ts version"
|
|
109
109
|
},
|
|
110
110
|
"dependencies": {
|
|
111
|
+
"@ankhorage/project-detector": "^0.1.0",
|
|
111
112
|
"@ankhorage/utility": "^0.5.1",
|
|
112
113
|
"@changesets/cli": "^3.0.2",
|
|
113
114
|
"@eslint/compat": "^2.1.1",
|
|
@@ -127,6 +128,7 @@
|
|
|
127
128
|
"typescript-eslint": "^8.69.0"
|
|
128
129
|
},
|
|
129
130
|
"devDependencies": {
|
|
131
|
+
"@ankhorage/paradox": "^0.1.26",
|
|
130
132
|
"@ankhorage/ankh": "^0.8.11",
|
|
131
133
|
"@ankhorage/doctor": "0.10.8",
|
|
132
134
|
"@techstark/opencv-js": "^5.0.0-release.1",
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { type ProjectDetectionInput } from '@ankhorage/utility/project';
|
|
2
|
-
import type { DevtoolsConfigOptions, DevtoolsEslintProfile, ResolvedDevtoolsEslintProfile } from './types.js';
|
|
3
|
-
export declare function resolveEslintProfile(options: DevtoolsConfigOptions): ResolvedDevtoolsEslintProfile;
|
|
4
|
-
export declare function resolveEslintProfileFromDetectionInput(requestedProfile: DevtoolsEslintProfile, input: ProjectDetectionInput): ResolvedDevtoolsEslintProfile;
|