@ankhorage/devtools 1.15.8 → 1.16.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 CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/devtools
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v1.15.8](././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) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v1.16.0](././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) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects
9
9
 
@@ -3,12 +3,13 @@
3
3
  *
4
4
  * The default `profile: 'auto'` reads the nearest `package.json` from `tsconfigRootDir` and uses
5
5
  * `@ankhorage/project-detector` to select overlapping project traits. React Native and Expo select
6
- * the `react-native` profile, React and Next.js select `react`, and other projects use `base`.
6
+ * `react-native`, Next.js selects `next`, React selects `react`, and other projects use `base`.
7
7
  *
8
8
  * Every profile includes the shared TypeScript, import, unused-import, Prettier, security, and
9
9
  * quality rules. The common quality limits are 50 effective lines per function, 300 effective
10
10
  * lines per file, and modified cyclomatic complexity 15. React adds React and Hooks correctness
11
- * rules; React Native composes the React profile and adds focused React Native rules.
11
+ * rules; Next.js composes React with Next recommended/Core Web Vitals rules; React Native composes
12
+ * React with focused React Native rules.
12
13
  *
13
14
  * Repository-specific behavior stays additive: `additionalIgnores`, `restrictedImports`, and
14
15
  * `overrides` extend the central policy instead of replacing it. Narrow local overrides remain the
@@ -19,6 +20,7 @@
19
20
  */
20
21
  import { fixupPluginRules } from '@eslint/compat';
21
22
  import js from '@eslint/js';
23
+ import nextPlugin from '@next/eslint-plugin-next';
22
24
  import { defineConfig } from 'eslint/config';
23
25
  import prettierConfig from 'eslint-config-prettier';
24
26
  import importPlugin from 'eslint-plugin-import';
@@ -151,11 +153,14 @@ function createSecurityRules() {
151
153
  };
152
154
  }
153
155
  function createProfileConfigs(profile, files) {
154
- if (profile === 'base') {
156
+ if (profile === 'base')
155
157
  return [];
156
- }
157
158
  const reactConfig = createReactConfig(files);
158
- return profile === 'react-native' ? [reactConfig, createReactNativeConfig(files)] : [reactConfig];
159
+ if (profile === 'next')
160
+ return [reactConfig, createNextConfig(files)];
161
+ if (profile === 'react-native')
162
+ return [reactConfig, createReactNativeConfig(files)];
163
+ return [reactConfig];
159
164
  }
160
165
  function createReactConfig(files) {
161
166
  return {
@@ -178,6 +183,17 @@ function createReactConfig(files) {
178
183
  },
179
184
  };
180
185
  }
186
+ /*** Add Next.js rules without re-registering React, Hooks, TypeScript, or import plugins. */
187
+ function createNextConfig(files) {
188
+ return {
189
+ files,
190
+ plugins: { '@next/next': nextPlugin },
191
+ rules: {
192
+ ...nextPlugin.configs.recommended.rules,
193
+ ...nextPlugin.configs['core-web-vitals'].rules,
194
+ },
195
+ };
196
+ }
181
197
  function createReactNativeConfig(files) {
182
198
  return {
183
199
  files,
@@ -6,5 +6,7 @@ export function resolveEslintProfileFromDetectionInput(requestedProfile, input)
6
6
  const { traits } = detectProject(input);
7
7
  if (traits.has('react-native') || traits.has('expo'))
8
8
  return 'react-native';
9
+ if (traits.has('next'))
10
+ return 'next';
9
11
  return traits.has('react') ? 'react' : 'base';
10
12
  }
@@ -4,7 +4,7 @@ export interface RestrictedImport {
4
4
  readonly name: string;
5
5
  readonly message: string;
6
6
  }
7
- export type DevtoolsEslintProfile = 'auto' | 'base' | 'react' | 'react-native';
7
+ export type DevtoolsEslintProfile = 'auto' | 'base' | 'next' | 'react' | 'react-native';
8
8
  export type ResolvedDevtoolsEslintProfile = Exclude<DevtoolsEslintProfile, 'auto'>;
9
9
  export interface DevtoolsConfigOptions {
10
10
  readonly tsconfigRootDir: string;
@@ -46,6 +46,11 @@ jobs:
46
46
  fetch-depth: 0
47
47
  token: ${{ steps.release-token.outputs.token }}
48
48
 
49
+ - name: Synchronize latest main
50
+ run: |
51
+ git fetch origin main
52
+ git checkout -B main origin/main
53
+
49
54
  - name: Setup Bun
50
55
  uses: oven-sh/setup-bun@v2
51
56
  with:
@@ -75,23 +80,32 @@ jobs:
75
80
  id: release
76
81
  if: hashFiles('.changeset/config.json') != ''
77
82
  run: |
78
- git fetch origin main
79
- git checkout -B main origin/main
80
-
81
83
  if [ -z "$(find .changeset -maxdepth 1 -type f -name '*.md' ! -name README.md -print -quit)" ]; then
82
- current_subject="$(git log -1 --pretty=%s)"
83
- if [ "$current_subject" = "chore(release): version packages [skip ci]" ]; then
84
- echo "Recovering the canonical versioned release commit without another version bump."
84
+ current_version="$(node -p "require('./package.json').version")"
85
+ release_sha=""
86
+ for candidate_sha in $(git rev-list HEAD); do
87
+ candidate_subject="$(git show -s --format=%s "$candidate_sha")"
88
+ if [ "$candidate_subject" != "chore(release): version packages [skip ci]" ]; then
89
+ continue
90
+ fi
91
+ candidate_version="$(git show "${candidate_sha}:package.json" | node -e "let s=''; process.stdin.on('data',(d)=>s+=d); process.stdin.on('end',()=>process.stdout.write(JSON.parse(s).version ?? ''))")"
92
+ if [ "$candidate_version" = "$current_version" ]; then
93
+ release_sha="$candidate_sha"
94
+ break
95
+ fi
96
+ done
97
+
98
+ if [ -n "$release_sha" ]; then
99
+ echo "Recovering canonical release commit $release_sha for version $current_version without another version bump."
85
100
  echo "versioned=true" >> "$GITHUB_OUTPUT"
86
101
  echo "package_name=$(node -p "require('./package.json').name")" >> "$GITHUB_OUTPUT"
87
- echo "package_version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
88
- echo "release_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
102
+ echo "package_version=$current_version" >> "$GITHUB_OUTPUT"
103
+ echo "release_sha=$release_sha" >> "$GITHUB_OUTPUT"
89
104
  else
90
105
  echo "versioned=false" >> "$GITHUB_OUTPUT"
91
106
  fi
92
107
  exit 0
93
108
  fi
94
-
95
109
  before_version="$(node -p "require('./package.json').version")"
96
110
  __ANKH_CHANGESETS_VERSION_COMMAND__
97
111
  if node -e "const p=require('./package.json'); process.exit(p.ankh?.apm === undefined ? 1 : 0)"; then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/devtools",
3
- "version": "1.15.8",
3
+ "version": "1.16.0",
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",
@@ -127,6 +127,7 @@
127
127
  "@changesets/cli": "^3.0.2",
128
128
  "@eslint/compat": "^2.1.1",
129
129
  "@eslint/js": "^10.0.1",
130
+ "@next/eslint-plugin-next": "^16.3.5",
130
131
  "eslint": "^10.10.0",
131
132
  "eslint-config-prettier": "^10.1.8",
132
133
  "eslint-plugin-import": "^2.32.0",