@ankhorage/devtools 1.0.4 → 1.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
@@ -16,7 +16,7 @@ Shared ESLint, Prettier, and Knip configuration for modern TypeScript projects.
16
16
  - Flat ESLint config (latest standard)
17
17
  - Preconfigured plugin ecosystem
18
18
  - Prettier integration
19
- - Shared Knip config factory
19
+ - Shared Knip config factories
20
20
  - `ankhorage-eslint`, `ankhorage-prettier`, and `ankhorage-knip` binaries
21
21
  - Monorepo-friendly
22
22
 
@@ -98,7 +98,41 @@ export default createKnipConfig({
98
98
  });
99
99
  ```
100
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.
101
+ For workspaces-based monorepos, use the monorepo preset:
102
+
103
+ ```ts
104
+ import { createKnipMonorepoConfig } from '@ankhorage/devtools/knip';
105
+
106
+ export default createKnipMonorepoConfig({
107
+ root: {
108
+ ignoreFiles: ['.prettierrc.js', 'eslint.config.js'],
109
+ },
110
+ });
111
+ ```
112
+
113
+ By default, the monorepo preset configures Knip workspaces for the root package, `packages/*`, and `apps/*`. Repos can override those defaults or add extra workspace globs:
114
+
115
+ ```ts
116
+ import { createKnipMonorepoConfig } from '@ankhorage/devtools/knip';
117
+
118
+ export default createKnipMonorepoConfig({
119
+ workspaceGlobs: ['packages/*', 'apps/*', 'examples/*'],
120
+ workspaceDefaults: {
121
+ ignoreFiles: ['fixtures/**'],
122
+ },
123
+ workspaces: {
124
+ '.': {
125
+ ignoreFiles: ['.prettierrc.js', 'eslint.config.js'],
126
+ },
127
+ 'apps/editor': {
128
+ ignoreFiles: ['babel.config.js'],
129
+ ignoreDependencies: ['babel-preset-expo'],
130
+ },
131
+ },
132
+ });
133
+ ```
134
+
135
+ The shared config intentionally keeps defaults narrow so Knip can still report real unused files, exports, dependencies, and binaries. Prefer explicit `entry`, `project`, `ignoreBinaries`, `ignoreDependencies`, or `ignoreFiles` over broad ignores.
102
136
 
103
137
  ### CI
104
138
 
@@ -1,13 +1,24 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { readFileSync } from 'node:fs';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
3
  import { createRequire } from 'node:module';
4
- import { dirname, resolve } from 'node:path';
4
+ import { dirname, join, resolve } from 'node:path';
5
5
  const require = createRequire(import.meta.url);
6
6
  function isRecord(value) {
7
7
  return typeof value === 'object' && value !== null;
8
8
  }
9
+ function findPackageJsonPath(packageName) {
10
+ let currentDirectory = dirname(require.resolve(packageName));
11
+ while (currentDirectory !== dirname(currentDirectory)) {
12
+ const packageJsonPath = join(currentDirectory, 'package.json');
13
+ if (existsSync(packageJsonPath)) {
14
+ return packageJsonPath;
15
+ }
16
+ currentDirectory = dirname(currentDirectory);
17
+ }
18
+ throw new Error(`Could not find package metadata for ${packageName}.`);
19
+ }
9
20
  function readPackageBinPath(packageName, binName) {
10
- const packageJsonPath = require.resolve(`${packageName}/package.json`);
21
+ const packageJsonPath = findPackageJsonPath(packageName);
11
22
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
12
23
  if (!isRecord(packageJson)) {
13
24
  throw new Error(`Package metadata for ${packageName} is not an object.`);
package/dist/knip.d.ts CHANGED
@@ -10,4 +10,11 @@ export interface DevtoolsKnipWorkspaceConfigOptions {
10
10
  export interface DevtoolsKnipConfigOptions extends DevtoolsKnipWorkspaceConfigOptions {
11
11
  workspaces?: Record<string, DevtoolsKnipWorkspaceConfigOptions>;
12
12
  }
13
+ export interface DevtoolsKnipMonorepoConfigOptions {
14
+ root?: DevtoolsKnipWorkspaceConfigOptions;
15
+ workspaceDefaults?: DevtoolsKnipWorkspaceConfigOptions;
16
+ workspaceGlobs?: string[];
17
+ workspaces?: Record<string, DevtoolsKnipWorkspaceConfigOptions>;
18
+ }
13
19
  export declare function createKnipConfig(options?: DevtoolsKnipConfigOptions): KnipConfig;
20
+ export declare function createKnipMonorepoConfig(options?: DevtoolsKnipMonorepoConfigOptions): KnipConfig;
package/dist/knip.js CHANGED
@@ -1,3 +1,4 @@
1
+ const DEFAULT_MONOREPO_WORKSPACE_GLOBS = ['packages/*', 'apps/*'];
1
2
  export function createKnipConfig(options = {}) {
2
3
  return {
3
4
  ...(options.entry === undefined ? {} : { entry: options.entry }),
@@ -11,3 +12,20 @@ export function createKnipConfig(options = {}) {
11
12
  ...(options.workspaces === undefined ? {} : { workspaces: options.workspaces }),
12
13
  };
13
14
  }
15
+ export function createKnipMonorepoConfig(options = {}) {
16
+ const explicitWorkspaces = options.workspaces ?? {};
17
+ const workspaceGlobs = options.workspaceGlobs ?? [...DEFAULT_MONOREPO_WORKSPACE_GLOBS];
18
+ const workspaces = {
19
+ '.': options.root ?? {},
20
+ };
21
+ for (const workspaceGlob of workspaceGlobs) {
22
+ workspaces[workspaceGlob] = {
23
+ ...(options.workspaceDefaults ?? {}),
24
+ ...(explicitWorkspaces[workspaceGlob] ?? {}),
25
+ };
26
+ }
27
+ for (const [workspaceGlob, workspaceConfig] of Object.entries(explicitWorkspaces)) {
28
+ workspaces[workspaceGlob] = workspaceConfig;
29
+ }
30
+ return createKnipConfig({ workspaces });
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/devtools",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Shared Lint and Format Configuration for Ankhorage",
5
5
  "homepage": "https://github.com/ankhorage/devtools#readme",
6
6
  "bugs": {