@ankhorage/devtools 2.0.4 → 2.0.6

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
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/devtools
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v2.0.4](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: warnings](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v2.0.6](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: warnings](././paradox/badges/docs.svg)
7
7
 
8
8
  Shared tooling, repository automation, and agent standards for Ankhorage TypeScript projects
9
9
 
@@ -8,9 +8,9 @@ export declare const eslintManagedFiles: readonly [{
8
8
  }, {
9
9
  readonly relativePath: "eslint.examples.config.mjs";
10
10
  readonly contents: "// This file is managed by @ankhorage/devtools.\nimport { existsSync } from 'node:fs';\n\nimport { createConfig } from '@ankhorage/devtools/eslint';\nimport localConfig from './eslint.local.config.mjs';\n\nconst exampleFiles = ['examples/**/*.{ts,tsx}'];\nconst localEntries = Array.isArray(localConfig) ? localConfig : [localConfig];\nconst rootProjects = ['./tsconfig.eslint.json', './tsconfig.json'].filter((project) =>\n existsSync(new URL(project, import.meta.url)),\n);\n\nexport default [\n ...createConfig({\n files: exampleFiles,\n project: [...rootProjects, './examples/**/tsconfig.json'],\n tsconfigRootDir: import.meta.dirname,\n }),\n ...localEntries,\n];\n";
11
- readonly isApplicable: typeof hasExamplesDirectory;
11
+ readonly isApplicable: typeof hasTypeScriptExamples;
12
12
  }];
13
13
  declare function renderInitialLocalConfig(targetDirectory: string): Promise<string>;
14
- /*** Report whether the target repository owns public examples at its root. */
15
- declare function hasExamplesDirectory(targetDirectory: string): Promise<boolean>;
14
+ /*** Report whether the target repository owns TypeScript source examples at its root. */
15
+ declare function hasTypeScriptExamples(targetDirectory: string): Promise<boolean>;
16
16
  export {};
@@ -1,4 +1,4 @@
1
- import { readFile, stat } from 'node:fs/promises';
1
+ import { readdir, readFile } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
  const ESLINT_CONFIG = `import { createConfig } from '@ankhorage/devtools/eslint';
4
4
  import localConfig from './eslint.local.config.mjs';
@@ -17,6 +17,17 @@ export default [
17
17
  const EMPTY_LOCAL_CONFIG = `export default [];
18
18
  `;
19
19
  const EXAMPLES_OWNERSHIP_MARKER = '// This file is managed by @ankhorage/devtools.\n';
20
+ const IGNORED_EXAMPLE_DIRECTORY_NAMES = new Set([
21
+ '.expo',
22
+ '.next',
23
+ 'android',
24
+ 'build',
25
+ 'dist',
26
+ 'files',
27
+ 'ios',
28
+ 'node_modules',
29
+ 'templates',
30
+ ]);
20
31
  const ESLINT_EXAMPLES_CONFIG = `${EXAMPLES_OWNERSHIP_MARKER}import { existsSync } from 'node:fs';
21
32
 
22
33
  import { createConfig } from '@ankhorage/devtools/eslint';
@@ -50,7 +61,7 @@ export const eslintManagedFiles = [
50
61
  {
51
62
  relativePath: 'eslint.examples.config.mjs',
52
63
  contents: ESLINT_EXAMPLES_CONFIG,
53
- isApplicable: hasExamplesDirectory,
64
+ isApplicable: hasTypeScriptExamples,
54
65
  },
55
66
  ];
56
67
  async function renderInitialLocalConfig(targetDirectory) {
@@ -68,11 +79,18 @@ async function renderInitialLocalConfig(targetDirectory) {
68
79
  function isNodeError(error) {
69
80
  return error instanceof Error && 'code' in error;
70
81
  }
71
- /*** Report whether the target repository owns public examples at its root. */
72
- async function hasExamplesDirectory(targetDirectory) {
82
+ /*** Report whether the target repository owns TypeScript source examples at its root. */
83
+ async function hasTypeScriptExamples(targetDirectory) {
73
84
  await assertExamplesConfigOwnershipAsync(targetDirectory);
85
+ return await containsTypeScriptExampleAsync(resolve(targetDirectory, 'examples'));
86
+ }
87
+ /*** Report whether a directory tree contains a TypeScript or TSX source example. */
88
+ async function containsTypeScriptExampleAsync(directory) {
74
89
  try {
75
- return (await stat(resolve(targetDirectory, 'examples'))).isDirectory();
90
+ const entries = await readdir(directory, { withFileTypes: true });
91
+ return (await Promise.all(entries.map(async (entry) => entry.isDirectory() && !IGNORED_EXAMPLE_DIRECTORY_NAMES.has(entry.name)
92
+ ? await containsTypeScriptExampleAsync(resolve(directory, entry.name))
93
+ : entry.isFile() && isTypeScriptExampleSource(entry.name)))).some(Boolean);
76
94
  }
77
95
  catch (error) {
78
96
  if (isNodeError(error) && error.code === 'ENOENT') {
@@ -81,6 +99,10 @@ async function hasExamplesDirectory(targetDirectory) {
81
99
  throw error;
82
100
  }
83
101
  }
102
+ /*** Report whether a file is lintable TypeScript example source rather than a declaration. */
103
+ function isTypeScriptExampleSource(fileName) {
104
+ return /\.tsx?$/u.test(fileName) && !fileName.endsWith('.d.ts');
105
+ }
84
106
  /*** Require explicit adoption of consumer overrides before managing an existing examples config. */
85
107
  async function assertExamplesConfigOwnershipAsync(targetDirectory) {
86
108
  let contents;
@@ -83,19 +83,6 @@ jobs:
83
83
  echo "No test script found; skipping."
84
84
  fi
85
85
 
86
- - name: Run standalone contract
87
- run: |
88
- if node -e "const p=require('./package.json'); const required=p.private!==true&&p.publishConfig?.access==='public'; process.exit(required||p.scripts?.['test:standalone']?0:1)"; then
89
- if node -e "const p=require('./package.json'); process.exit(p.scripts?.['test:standalone']?0:1)"; then
90
- bun run test:standalone
91
- else
92
- echo "::error title=Standalone contract test required::Public packages must define test:standalone."
93
- exit 1
94
- fi
95
- else
96
- echo "No standalone owner test required; skipping."
97
- fi
98
-
99
86
  - name: Run typecheck
100
87
  run: |
101
88
  if node -e "const p=require('./package.json'); process.exit(p.scripts?.typecheck ? 0 : 1)"; then
@@ -76,17 +76,8 @@ jobs:
76
76
  echo "No build script found; skipping."
77
77
  fi
78
78
 
79
- - name: Validate standalone release contract
80
- run: |
81
- BUN_INSTALL_CACHE_DIR="${RUNNER_TEMP}/doctor-cache" bunx @ankhorage/doctor@__ANKH_DOCTOR_VERSION__ validate .
82
- if node -e "const p=require('./package.json'); const required=p.private!==true&&p.publishConfig?.access==='public'; process.exit(required||p.scripts?.['test:standalone']?0:1)"; then
83
- if node -e "const p=require('./package.json'); process.exit(p.scripts?.['test:standalone']?0:1)"; then
84
- bun run test:standalone
85
- else
86
- echo "::error title=Standalone contract test required::Public packages must define test:standalone."
87
- exit 1
88
- fi
89
- fi
79
+ - name: Validate release contract
80
+ run: BUN_INSTALL_CACHE_DIR="${RUNNER_TEMP}/doctor-cache" bunx @ankhorage/doctor@__ANKH_DOCTOR_VERSION__ validate .
90
81
 
91
82
  - name: Version packages directly on main
92
83
  id: release
@@ -168,9 +159,6 @@ jobs:
168
159
  if node -e "const p=require('./package.json'); process.exit(p.scripts?.build?0:1)"; then
169
160
  bun run build
170
161
  fi
171
- if node -e "const p=require('./package.json'); process.exit(p.scripts?.['test:standalone']?0:1)"; then
172
- bun run test:standalone
173
- fi
174
162
  pack_dir="$(mktemp -d "${RUNNER_TEMP}/standalone-pack.XXXXXX")"
175
163
  install_dir="$(mktemp -d "${RUNNER_TEMP}/standalone-install.XXXXXX")"
176
164
  npm pack --ignore-scripts --pack-destination "$pack_dir" >/dev/null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/devtools",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "Shared tooling, repository automation, and agent standards for Ankhorage TypeScript projects",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/ankhorage/devtools#readme",