knip 6.6.0 → 6.6.1

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.
@@ -5,6 +5,7 @@ import type { ConfigurationHint } from './types/issues.ts';
5
5
  import type { PluginName } from './types/PluginNames.ts';
6
6
  import type { PackageJson } from './types/package-json.ts';
7
7
  import type { DependencySet } from './types/workspace.ts';
8
+ import { type Manifest } from './util/package-json.ts';
8
9
  import type { MainOptions } from './util/create-options.ts';
9
10
  import { type Input } from './util/input.ts';
10
11
  type WorkspaceManagerOptions = {
@@ -13,7 +14,7 @@ type WorkspaceManagerOptions = {
13
14
  config: WorkspaceConfiguration;
14
15
  manifest: PackageJson;
15
16
  dependencies: DependencySet;
16
- rootManifest: PackageJson | undefined;
17
+ rootManifest: Manifest | undefined;
17
18
  handleInput: HandleInput;
18
19
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
19
20
  readFile: (filePath: string) => string;
@@ -32,8 +33,8 @@ export declare class WorkspaceWorker {
32
33
  name: string;
33
34
  dir: string;
34
35
  config: WorkspaceConfiguration;
35
- manifest: PackageJson;
36
- rootManifest: PackageJson | undefined;
36
+ manifest: Manifest;
37
+ rootManifest: Manifest | undefined;
37
38
  dependencies: DependencySet;
38
39
  handleInput: HandleInput;
39
40
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
@@ -5,6 +5,7 @@ import { isDefaultPattern } from './ConfigurationChief.js';
5
5
  import { DEFAULT_EXTENSIONS, ROOT_WORKSPACE_NAME } from './constants.js';
6
6
  import { getFilteredScripts } from './manifest/helpers.js';
7
7
  import { PluginEntries, Plugins } from './plugins.js';
8
+ import { createManifest } from './util/package-json.js';
8
9
  import { collectStringLiterals, isExternalReExportsOnly } from './typescript/ast-helpers.js';
9
10
  import { parseFile } from './typescript/visitors/helpers.js';
10
11
  import { compact } from './util/array.js';
@@ -42,7 +43,7 @@ export class WorkspaceWorker {
42
43
  this.name = name;
43
44
  this.dir = dir;
44
45
  this.config = config;
45
- this.manifest = manifest;
46
+ this.manifest = createManifest(manifest);
46
47
  this.rootManifest = rootManifest;
47
48
  this.dependencies = dependencies;
48
49
  this.negatedWorkspacePatterns = negatedWorkspacePatterns;
@@ -207,10 +208,9 @@ export class WorkspaceWorker {
207
208
  const containingFilePath = join(cwd, 'package.json');
208
209
  const isProduction = this.options.isProduction;
209
210
  const knownBinsOnly = false;
210
- const manifestScriptNames = new Set(Object.keys(manifest.scripts ?? {}));
211
211
  const rootManifest = this.rootManifest;
212
- const baseOptions = { manifestScriptNames, rootManifest, cwd, rootCwd, containingFilePath, knownBinsOnly };
213
- const baseScriptOptions = { ...baseOptions, manifest, isProduction, enabledPlugins: this.enabledPlugins };
212
+ const baseOptions = { manifest, rootManifest, cwd, rootCwd, containingFilePath, knownBinsOnly };
213
+ const baseScriptOptions = { ...baseOptions, isProduction, enabledPlugins: this.enabledPlugins };
214
214
  const [productionScripts, developmentScripts] = getFilteredScripts(manifest.scripts ?? {});
215
215
  const inputsFromManifest = _getInputsFromScripts(Object.values(developmentScripts), baseOptions);
216
216
  const productionInputsFromManifest = _getInputsFromScripts(Object.values(productionScripts), baseOptions);
@@ -9,7 +9,7 @@ const isGlobLikeMatch = /(^!|[*+\\(|{^$])/;
9
9
  const isGlobLike = (value) => isGlobLikeMatch.test(value);
10
10
  const nodeLoadersArgs = { import: ['r', 'experimental-loader', 'require', 'loader'] };
11
11
  export const resolve = (binary, _args, options) => {
12
- const { cwd, fromArgs, containingFilePath } = options;
12
+ const { cwd, fromArgs, containingFilePath, manifest } = options;
13
13
  const [pluginName, pluginArgs] = pluginArgsMap.get(binary) ?? [];
14
14
  if (!pluginArgs)
15
15
  return fallbackResolve(binary, _args, options);
@@ -59,7 +59,7 @@ export const resolve = (binary, _args, options) => {
59
59
  return parsed[id] && pluginName ? [toConfig(pluginName, fn(parsed[id]), inputOpts)] : [];
60
60
  };
61
61
  const configFilePaths = config.flatMap(mapToConfigPattern);
62
- const inputs = pluginArgs.resolveInputs?.(parsed, { args, cwd }) ?? [];
62
+ const inputs = pluginArgs.resolveInputs?.(parsed, { args, cwd, manifest }) ?? [];
63
63
  return [
64
64
  toBinary(binary, inputOpts),
65
65
  ...positionals,
@@ -57,10 +57,10 @@ export const resolve = (_binary, args, options) => {
57
57
  const argsForX = args.filter(arg => arg !== 'x');
58
58
  return resolveX(argsForX, options);
59
59
  }
60
- const { manifestScriptNames, cwd, fromArgs } = options;
61
- if (command === 'run' && manifestScriptNames.has(script))
60
+ const { manifest, cwd, fromArgs } = options;
61
+ if (command === 'run' && manifest.scriptNames.has(script))
62
62
  return [];
63
- if (manifestScriptNames.has(command))
63
+ if (manifest.scriptNames.has(command))
64
64
  return [];
65
65
  if (command !== 'run' && commands.has(command))
66
66
  return [];
@@ -1,12 +1,12 @@
1
1
  import parseArgs from 'minimist';
2
2
  export const resolve = (_binary, args, options) => {
3
- const { fromArgs, manifestScriptNames } = options;
3
+ const { fromArgs, manifest } = options;
4
4
  const parsed = parseArgs(args, { '--': true });
5
5
  const [command, script] = parsed._;
6
6
  const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--'], { knownBinsOnly: true }) : [];
7
7
  if (command === 'exec')
8
8
  return _childArgs;
9
- if (command === 'run' && manifestScriptNames.has(script))
9
+ if (command === 'run' && manifest.scriptNames.has(script))
10
10
  return _childArgs;
11
11
  return [];
12
12
  };
@@ -73,14 +73,14 @@ export const resolve = (_binary, args, options) => {
73
73
  const argsForDlx = args.filter(arg => arg !== 'dlx');
74
74
  return resolveDlx(argsForDlx, options);
75
75
  }
76
- const { manifestScriptNames, fromArgs } = options;
76
+ const { manifest, fromArgs } = options;
77
77
  if (parsed.filter && !parsed.recursive)
78
78
  return [];
79
79
  const childInputs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--'], { knownBinsOnly: true }) : [];
80
80
  if (command === 'exec') {
81
81
  return childInputs.length > 0 ? childInputs : fromArgs(parsed._.slice(1));
82
82
  }
83
- const isScript = manifestScriptNames.has(command);
83
+ const isScript = manifest.scriptNames.has(command);
84
84
  if (isScript || commands.includes(command))
85
85
  return childInputs;
86
86
  return command && isValidBinary(command) ? [toBinary(command)] : [];
@@ -49,7 +49,7 @@ const resolveDlx = (args, options) => {
49
49
  return [...packages.map(id => toDependency(id)), ...command].map(id => isDependency(id) || isBinary(id) ? Object.assign(id, { optional: true }) : id);
50
50
  };
51
51
  export const resolve = (_binary, args, options) => {
52
- const { manifestScriptNames, fromArgs, cwd, rootCwd } = options;
52
+ const { manifest, fromArgs, cwd, rootCwd } = options;
53
53
  const parsed = parseArgs(args, { boolean: ['top-level'], string: ['cwd'], '--': true });
54
54
  const dir = parsed['top-level'] ? rootCwd : parsed.cwd ? join(cwd, parsed.cwd) : undefined;
55
55
  const [command, binary] = parsed._;
@@ -57,7 +57,7 @@ export const resolve = (_binary, args, options) => {
57
57
  return [];
58
58
  const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--'], { knownBinsOnly: true }) : [];
59
59
  if (command === 'run') {
60
- if (manifestScriptNames.has(binary))
60
+ if (manifest.scriptNames.has(binary))
61
61
  return _childArgs;
62
62
  const bin = toBinary(binary, { optional: true });
63
63
  if (dir)
@@ -70,7 +70,7 @@ export const resolve = (_binary, args, options) => {
70
70
  const argsForDlx = args.filter(arg => arg !== 'dlx');
71
71
  return resolveDlx(argsForDlx, options);
72
72
  }
73
- if ((!dir && manifestScriptNames.has(command)) || commands.includes(command))
73
+ if ((!dir && manifest.scriptNames.has(command)) || commands.includes(command))
74
74
  return _childArgs;
75
75
  const opts = dir ? { cwd: dir } : {};
76
76
  return fromArgs(argsFrom(args, command === 'exec' ? binary : command), opts);
@@ -6,6 +6,7 @@ import { createInputHandler } from '../util/create-input-handler.js';
6
6
  import { debugLog, debugLogArray } from '../util/debug.js';
7
7
  import { existsSync } from 'node:fs';
8
8
  import { tryRealpath } from '../util/fs.js';
9
+ import { createManifest } from '../util/package-json.js';
9
10
  import { _glob, _syncGlob, negate, prependDirToPattern as prependDir } from '../util/glob.js';
10
11
  import { isAlias, isConfig, isDeferResolveEntry, isDeferResolveProductionEntry, isEntry, isIgnore, isProductionEntry, isProject, toProductionEntry, } from '../util/input.js';
11
12
  import { loadTSConfig } from '../util/load-tsconfig.js';
@@ -24,7 +25,8 @@ export async function build({ chief, collector, counselor, deputy, principal, is
24
25
  const addIssue = (issue) => collector.addIssue(issue) && options.isWatch && collector.retainIssue(issue);
25
26
  const externalRefsFromInputs = options.isSession ? new Map() : undefined;
26
27
  const handleInput = createInputHandler(deputy, chief, isGitIgnored, addIssue, externalRefsFromInputs, options);
27
- const rootManifest = chief.getManifestForWorkspace('.');
28
+ const rawRootManifest = chief.getManifestForWorkspace('.');
29
+ const rootManifest = rawRootManifest ? createManifest(rawRootManifest) : undefined;
28
30
  for (const workspace of workspaces) {
29
31
  const { name, dir, manifestPath, manifestStr } = workspace;
30
32
  const manifest = chief.getManifestForWorkspace(name);
@@ -330,16 +332,16 @@ export async function build({ chief, collector, counselor, deputy, principal, is
330
332
  }
331
333
  }
332
334
  }
333
- if (file.scripts && file.scripts.size > 0) {
335
+ const manifest = chief.getManifestForWorkspace(workspace.name);
336
+ if (manifest && file.scripts && file.scripts.size > 0) {
334
337
  const dependencies = deputy.getDependencies(workspace.name);
335
- const manifestScriptNames = new Set(Object.keys(chief.getManifestForWorkspace(workspace.name)?.scripts ?? {}));
336
338
  const dir = dirname(filePath);
337
339
  const opts = {
338
340
  cwd: dir,
339
341
  rootCwd: options.cwd,
340
342
  containingFilePath: filePath,
341
343
  dependencies,
342
- manifestScriptNames,
344
+ manifest: createManifest(manifest),
343
345
  rootManifest,
344
346
  };
345
347
  const inputs = _getInputsFromScripts(file.scripts, opts);
@@ -17,13 +17,8 @@ const config = [
17
17
  const isLoadConfig = ({ configFileName, manifest }, dependencies) => {
18
18
  if (isFlatConfig(configFileName))
19
19
  return false;
20
- const version = manifest.devDependencies?.['eslint'] || manifest.dependencies?.['eslint'];
21
- if (version) {
22
- const major = version.match(/\d+/);
23
- if (major && Number.parseInt(major[0], 10) === 9 && dependencies.has('eslint-config-next')) {
24
- return false;
25
- }
26
- }
20
+ if (manifest.getMajor('eslint') === 9 && dependencies.has('eslint-config-next'))
21
+ return false;
27
22
  return true;
28
23
  };
29
24
  const resolveConfig = (localConfig, options) => getInputs(localConfig, options);
@@ -7,10 +7,12 @@ const entry = ['emails/**/*.tsx'];
7
7
  const previewCommands = new Set(['build', 'dev', 'start']);
8
8
  const args = {
9
9
  binaries: ['email'],
10
- resolveInputs: parsed => {
10
+ resolveInputs: (parsed, { manifest }) => {
11
11
  const inputs = [];
12
- if (previewCommands.has(parsed._[0]))
13
- inputs.push(toDependency('@react-email/preview-server'));
12
+ if (previewCommands.has(parsed._[0])) {
13
+ const dep = (manifest.getMajor('react-email') ?? 0) >= 6 ? '@react-email/ui' : '@react-email/preview-server';
14
+ inputs.push(toDependency(dep));
15
+ }
14
16
  if (parsed.dir)
15
17
  inputs.push(toEntry(`${parsed.dir}/**/*.tsx`));
16
18
  return inputs;
@@ -1,16 +1,19 @@
1
+ import { toProductionEntry } from '../../util/input.js';
1
2
  import { hasDependency } from '../../util/plugin.js';
3
+ import { getEntryFromAST } from './resolveFromAST.js';
2
4
  const title = 'Rslib';
3
5
  const enablers = ['@rslib/core'];
4
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
- const entry = ['rslib*.config.{mjs,ts,js,cjs,mts,cts}'];
6
- const resolveConfig = () => {
7
- return [];
7
+ const config = ['rslib*.config.{mjs,ts,js,cjs,mts,cts}'];
8
+ const resolveFromAST = program => {
9
+ const entries = getEntryFromAST(program);
10
+ return [...entries].map(id => toProductionEntry(id, { allowIncludeExports: true }));
8
11
  };
9
12
  const plugin = {
10
13
  title,
11
14
  enablers,
12
15
  isEnabled,
13
- entry,
14
- resolveConfig,
16
+ config,
17
+ resolveFromAST,
15
18
  };
16
19
  export default plugin;
@@ -0,0 +1,2 @@
1
+ import type { Program } from 'oxc-parser';
2
+ export declare const getEntryFromAST: (program: Program) => Set<string>;
@@ -0,0 +1,4 @@
1
+ import { collectPropertyValues } from '../../typescript/ast-helpers.js';
2
+ export const getEntryFromAST = (program) => {
3
+ return collectPropertyValues(program, 'entry');
4
+ };
@@ -1,5 +1,6 @@
1
1
  import type { ParsedArgs } from 'minimist';
2
2
  import type { Input } from '../util/input.ts';
3
+ import type { Manifest } from '../util/package-json.ts';
3
4
  export type ConfigArg = boolean | (string | [string, (id: string) => string])[];
4
5
  export type Args = {
5
6
  binaries?: string[];
@@ -15,5 +16,6 @@ export type Args = {
15
16
  resolveInputs?: (parsed: ParsedArgs, options: {
16
17
  cwd: string;
17
18
  args: string[];
19
+ manifest: Manifest;
18
20
  }) => Input[];
19
21
  };
@@ -5,6 +5,7 @@ import type { knipConfigurationSchema, workspaceConfigurationSchema } from '../s
5
5
  import type { pluginSchema } from '../schema/plugins.ts';
6
6
  import type { ParsedCLIArgs } from '../util/cli-arguments.ts';
7
7
  import type { Input } from '../util/input.ts';
8
+ import type { Manifest } from '../util/package-json.ts';
8
9
  import type { Args } from './args.ts';
9
10
  import type { IssueType, SymbolType } from './issues.ts';
10
11
  import type { Tags } from './options.ts';
@@ -72,18 +73,17 @@ export interface WorkspaceConfiguration extends BaseWorkspaceConfiguration, Part
72
73
  interface BaseOptions {
73
74
  rootCwd: string;
74
75
  cwd: string;
75
- manifestScriptNames: Set<string>;
76
- rootManifest: PackageJson | undefined;
76
+ manifest: Manifest;
77
+ rootManifest: Manifest | undefined;
77
78
  }
78
79
  type IsPluginEnabledOptions = {
79
80
  cwd: string;
80
- manifest: PackageJson;
81
+ manifest: Manifest;
81
82
  dependencies: Set<string>;
82
83
  config: WorkspaceConfiguration;
83
84
  };
84
85
  export type IsPluginEnabled = (options: IsPluginEnabledOptions) => boolean | Promise<boolean>;
85
86
  export interface PluginOptions extends BaseOptions {
86
- manifest: PackageJson;
87
87
  config: EnsuredPluginConfiguration;
88
88
  configFileDir: string;
89
89
  configFileName: string;
@@ -102,10 +102,10 @@ export type SourceMap = {
102
102
  };
103
103
  export interface ResolveSourceMapOptions {
104
104
  cwd: string;
105
- manifest: PackageJson;
105
+ manifest: Manifest;
106
106
  dependencies: Set<string>;
107
107
  rootCwd: string;
108
- rootManifest: PackageJson | undefined;
108
+ rootManifest: Manifest | undefined;
109
109
  }
110
110
  export type ResolveSourceMap = (options: ResolveSourceMapOptions) => Promise<SourceMap[]> | SourceMap[];
111
111
  export type HandleInput = (input: Input) => string | undefined;
@@ -8,5 +8,10 @@ interface ExtendedPackageJson extends PackageJson {
8
8
  export declare const load: (filePath: string) => Promise<ExtendedPackageJson>;
9
9
  export declare const save: (filePath: string, content: ExtendedPackageJson) => Promise<void>;
10
10
  export declare const getEntrySpecifiersFromManifest: (manifest: PackageJson) => Set<string>;
11
+ export type Manifest = PackageJson & {
12
+ scriptNames: Set<string>;
13
+ getMajor: (name: string) => number | undefined;
14
+ };
15
+ export declare const createManifest: (raw: PackageJson) => Manifest;
11
16
  export declare const getManifestImportDependencies: (manifest: PackageJson) => Set<string>;
12
17
  export {};
@@ -87,6 +87,15 @@ export const getEntrySpecifiersFromManifest = (manifest) => {
87
87
  }
88
88
  return entryPaths;
89
89
  };
90
+ export const createManifest = (raw) => Object.assign(raw, {
91
+ ...raw,
92
+ scriptNames: new Set(Object.keys(raw.scripts ?? {})),
93
+ getMajor(name) {
94
+ const range = raw.dependencies?.[name] ?? raw.devDependencies?.[name];
95
+ const match = range?.match(/\d+/)?.[0];
96
+ return match ? Number.parseInt(match, 10) : undefined;
97
+ },
98
+ });
90
99
  export const getManifestImportDependencies = (manifest) => {
91
100
  const dependencies = new Set();
92
101
  if (!manifest.imports)
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "6.6.0";
1
+ export declare const version = "6.6.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '6.6.0';
1
+ export const version = '6.6.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "6.6.0",
3
+ "version": "6.6.1",
4
4
  "description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
5
5
  "keywords": [
6
6
  "analysis",
@@ -1 +0,0 @@
1
- export type RslibConfig = {};
@@ -1 +0,0 @@
1
- export {};