knip 6.35.1 → 6.37.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.
Files changed (109) hide show
  1. package/dist/ConfigurationChief.d.ts +20 -2
  2. package/dist/ConfigurationChief.js +15 -1
  3. package/dist/DependencyDeputy.d.ts +0 -2
  4. package/dist/DependencyDeputy.js +1 -17
  5. package/dist/WorkspaceWorker.js +7 -6
  6. package/dist/binaries/bash-parser.js +1 -1
  7. package/dist/binaries/command.js +21 -10
  8. package/dist/binaries/fallback.js +5 -4
  9. package/dist/binaries/plugins.js +4 -4
  10. package/dist/binaries/resolvers/bun.js +2 -2
  11. package/dist/binaries/resolvers/find.js +5 -4
  12. package/dist/binaries/resolvers/index.d.ts +2 -1
  13. package/dist/binaries/resolvers/index.js +3 -2
  14. package/dist/binaries/resolvers/npm.js +46 -4
  15. package/dist/binaries/resolvers/npx.js +8 -4
  16. package/dist/binaries/resolvers/nub.js +3 -2
  17. package/dist/binaries/resolvers/pnpm.js +17 -10
  18. package/dist/binaries/resolvers/yarn.js +1 -1
  19. package/dist/binaries/util.d.ts +4 -1
  20. package/dist/binaries/util.js +2 -0
  21. package/dist/compilers/compilers.js +1 -1
  22. package/dist/compilers/scss.js +2 -2
  23. package/dist/graph-explorer/cache.d.ts +3 -0
  24. package/dist/graph-explorer/cache.js +6 -0
  25. package/dist/graph-explorer/explorer.d.ts +1 -0
  26. package/dist/graph-explorer/explorer.js +2 -0
  27. package/dist/graph-explorer/operations/build-exports-tree.js +14 -2
  28. package/dist/graph-explorer/operations/get-ambiguous-star-export.d.ts +8 -0
  29. package/dist/graph-explorer/operations/get-ambiguous-star-export.js +11 -0
  30. package/dist/graph-explorer/operations/get-contention.js +265 -122
  31. package/dist/graph-explorer/operations/resolve-export-origins.d.ts +32 -0
  32. package/dist/graph-explorer/operations/resolve-export-origins.js +255 -0
  33. package/dist/graph-explorer/utils.js +8 -0
  34. package/dist/manifest/index.js +1 -3
  35. package/dist/plugins/ava/index.js +1 -1
  36. package/dist/plugins/eslint/helpers.d.ts +2 -1
  37. package/dist/plugins/eslint/helpers.js +59 -14
  38. package/dist/plugins/eslint/index.js +2 -2
  39. package/dist/plugins/eslint/resolveFromAST.js +17 -11
  40. package/dist/plugins/eslint/types.d.ts +3 -3
  41. package/dist/plugins/github-actions/index.js +1 -1
  42. package/dist/plugins/graphql-codegen/index.js +15 -4
  43. package/dist/plugins/graphql-codegen/types.d.ts +11 -1
  44. package/dist/plugins/graphql-codegen/types.js +6 -0
  45. package/dist/plugins/husky/index.js +1 -1
  46. package/dist/plugins/index.d.ts +2 -0
  47. package/dist/plugins/index.js +4 -0
  48. package/dist/plugins/lefthook/index.js +1 -1
  49. package/dist/plugins/mise/scripts.js +5 -5
  50. package/dist/plugins/next/index.js +39 -5
  51. package/dist/plugins/node/index.js +6 -0
  52. package/dist/plugins/tailwind/compiler.js +2 -2
  53. package/dist/plugins/tailwind/index.js +7 -1
  54. package/dist/plugins/taskfile/index.js +1 -1
  55. package/dist/plugins/tauri/index.js +1 -1
  56. package/dist/plugins/textlint/helpers.d.ts +4 -0
  57. package/dist/plugins/textlint/helpers.js +39 -0
  58. package/dist/plugins/textlint/index.d.ts +3 -0
  59. package/dist/plugins/textlint/index.js +52 -0
  60. package/dist/plugins/textlint/types.d.ts +5 -0
  61. package/dist/plugins/textlint/types.js +1 -0
  62. package/dist/plugins/travis/index.js +1 -1
  63. package/dist/plugins/typedoc/index.js +3 -2
  64. package/dist/plugins/typedoc/types.d.ts +2 -2
  65. package/dist/plugins/varlock/index.d.ts +3 -0
  66. package/dist/plugins/varlock/index.js +31 -0
  67. package/dist/plugins/varlock/parse.d.ts +11 -0
  68. package/dist/plugins/varlock/parse.js +185 -0
  69. package/dist/plugins/varlock/scan.d.ts +2 -0
  70. package/dist/plugins/varlock/scan.js +78 -0
  71. package/dist/plugins/vite-plus/resolveFromAST.js +1 -1
  72. package/dist/plugins/vitest/index.js +4 -2
  73. package/dist/reporters/trace.js +30 -1
  74. package/dist/schema/configuration.d.ts +33 -0
  75. package/dist/schema/configuration.js +2 -0
  76. package/dist/schema/plugins.d.ts +10 -0
  77. package/dist/schema/plugins.js +2 -0
  78. package/dist/session/build-maps.js +9 -1
  79. package/dist/session/file-descriptor.js +0 -2
  80. package/dist/session/index.d.ts +1 -1
  81. package/dist/session/types.d.ts +18 -0
  82. package/dist/types/PluginNames.d.ts +2 -2
  83. package/dist/types/PluginNames.js +2 -0
  84. package/dist/types/config.d.ts +5 -1
  85. package/dist/types/module-graph.d.ts +3 -0
  86. package/dist/types/package-json.d.ts +1 -1
  87. package/dist/typescript/get-imports-and-exports.js +43 -9
  88. package/dist/typescript/visitors/exports.js +9 -4
  89. package/dist/typescript/visitors/walk.d.ts +1 -1
  90. package/dist/typescript/visitors/walk.js +4 -1
  91. package/dist/util/array.d.ts +1 -1
  92. package/dist/util/array.js +5 -1
  93. package/dist/util/create-input-handler.js +3 -3
  94. package/dist/util/create-options.d.ts +28 -2
  95. package/dist/util/file-entry-cache.js +1 -1
  96. package/dist/util/glob-core.d.ts +1 -0
  97. package/dist/util/glob-core.js +11 -3
  98. package/dist/util/jiti.js +1 -0
  99. package/dist/util/modules.d.ts +2 -0
  100. package/dist/util/modules.js +3 -1
  101. package/dist/util/package-json.d.ts +185 -183
  102. package/dist/util/parse-args.d.ts +2 -0
  103. package/dist/util/parse-args.js +6 -1
  104. package/dist/util/url.d.ts +1 -0
  105. package/dist/util/url.js +2 -0
  106. package/dist/version.d.ts +1 -1
  107. package/dist/version.js +1 -1
  108. package/package.json +5 -5
  109. package/schema.json +20 -0
@@ -787,6 +787,11 @@ export declare class ConfigurationChief {
787
787
  entry?: string | string[] | undefined;
788
788
  project?: string | string[] | undefined;
789
789
  } | undefined;
790
+ textlint?: string | boolean | string[] | {
791
+ config?: string | string[] | undefined;
792
+ entry?: string | string[] | undefined;
793
+ project?: string | string[] | undefined;
794
+ } | undefined;
790
795
  travis?: string | boolean | string[] | {
791
796
  config?: string | string[] | undefined;
792
797
  entry?: string | string[] | undefined;
@@ -867,6 +872,11 @@ export declare class ConfigurationChief {
867
872
  entry?: string | string[] | undefined;
868
873
  project?: string | string[] | undefined;
869
874
  } | undefined;
875
+ varlock?: string | boolean | string[] | {
876
+ config?: string | string[] | undefined;
877
+ entry?: string | string[] | undefined;
878
+ project?: string | string[] | undefined;
879
+ } | undefined;
870
880
  vercel?: string | boolean | string[] | {
871
881
  config?: string | string[] | undefined;
872
882
  entry?: string | string[] | undefined;
@@ -978,10 +988,13 @@ export declare class ConfigurationChief {
978
988
  ignore?: string | string[] | undefined;
979
989
  ignoreFiles?: string | string[] | undefined;
980
990
  ignoreBinaries?: (string | RegExp)[] | undefined;
991
+ ignoreGlobalBinaries?: boolean | undefined;
981
992
  ignoreDependencies?: (string | RegExp)[] | undefined;
982
993
  ignoreMembers?: (string | RegExp)[] | undefined;
983
994
  ignoreUnresolved?: (string | RegExp)[] | undefined;
984
- ignoreExportsUsedInFile?: boolean | Record<string, boolean | undefined> | undefined;
995
+ ignoreExportsUsedInFile?: boolean | {
996
+ [x: string]: boolean | undefined;
997
+ } | undefined;
985
998
  ignoreIssues?: Record<string, ("binaries" | "catalog" | "catalogReferences" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
986
999
  includeEntryExports?: boolean | undefined;
987
1000
  };
@@ -997,7 +1010,10 @@ export declare class ConfigurationChief {
997
1010
  paths: Record<string, string[]>;
998
1011
  ignore: string[];
999
1012
  ignoreFiles: string[];
1000
- ignoreExportsUsedInFile: Record<string, boolean | undefined> | import("./types/config.ts").IgnoreExportsUsedInFile;
1013
+ ignoreGlobalBinaries: boolean;
1014
+ ignoreExportsUsedInFile: {
1015
+ [x: string]: boolean | undefined;
1016
+ } | import("./types/config.ts").IgnoreExportsUsedInFile;
1001
1017
  isIncludeEntryExports: boolean;
1002
1018
  angular?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1003
1019
  astro?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -1145,6 +1161,7 @@ export declare class ConfigurationChief {
1145
1161
  taskfile?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1146
1162
  tauri?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1147
1163
  temporal?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1164
+ textlint?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1148
1165
  travis?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1149
1166
  "ts-node"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1150
1167
  tsd?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -1161,6 +1178,7 @@ export declare class ConfigurationChief {
1161
1178
  "unplugin-vue-i18n"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1162
1179
  "unplugin-vue-markdown"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1163
1180
  "unplugin-vue-router"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1181
+ varlock?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1164
1182
  vercel?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1165
1183
  "vercel-og"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1166
1184
  vike?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -33,6 +33,7 @@ const isPluginName = (name) => pluginNames.includes(name);
33
33
  const defaultConfig = {
34
34
  ignore: [],
35
35
  ignoreBinaries: [],
36
+ ignoreGlobalBinaries: true,
36
37
  ignoreDependencies: [],
37
38
  ignoreFiles: [],
38
39
  cycles: {},
@@ -100,6 +101,7 @@ export class ConfigurationChief {
100
101
  const ignore = arrayify(rawConfig.ignore ?? defaultConfig.ignore);
101
102
  const ignoreFiles = arrayify(rawConfig.ignoreFiles ?? defaultConfig.ignoreFiles);
102
103
  const ignoreBinaries = rawConfig.ignoreBinaries ?? [];
104
+ const ignoreGlobalBinaries = rawConfig.ignoreGlobalBinaries ?? defaultConfig.ignoreGlobalBinaries;
103
105
  const ignoreDependencies = rawConfig.ignoreDependencies ?? [];
104
106
  const ignoreMembers = rawConfig.ignoreMembers ?? [];
105
107
  const ignoreUnresolved = rawConfig.ignoreUnresolved ?? [];
@@ -119,6 +121,7 @@ export class ConfigurationChief {
119
121
  ignoreFiles,
120
122
  cycles,
121
123
  ignoreBinaries,
124
+ ignoreGlobalBinaries,
122
125
  ignoreDependencies,
123
126
  ignoreMembers,
124
127
  ignoreUnresolved,
@@ -341,6 +344,7 @@ export class ConfigurationChief {
341
344
  const paths = workspaceConfig.paths ?? {};
342
345
  const ignore = arrayify(workspaceConfig.ignore);
343
346
  const ignoreFiles = arrayify(workspaceConfig.ignoreFiles);
347
+ const ignoreGlobalBinaries = workspaceConfig.ignoreGlobalBinaries ?? this.config.ignoreGlobalBinaries;
344
348
  const ignoreExportsUsedInFile = workspaceConfig.ignoreExportsUsedInFile ?? this.config.ignoreExportsUsedInFile;
345
349
  const isIncludeEntryExports = workspaceConfig.includeEntryExports ?? this.config.isIncludeEntryExports;
346
350
  const plugins = {};
@@ -353,7 +357,17 @@ export class ConfigurationChief {
353
357
  plugins[pluginName] = normalizePluginConfig(pluginConfig);
354
358
  }
355
359
  }
356
- return { entry, project, paths, ignore, ignoreFiles, ignoreExportsUsedInFile, isIncludeEntryExports, ...plugins };
360
+ return {
361
+ entry,
362
+ project,
363
+ paths,
364
+ ignore,
365
+ ignoreFiles,
366
+ ignoreGlobalBinaries,
367
+ ignoreExportsUsedInFile,
368
+ isIncludeEntryExports,
369
+ ...plugins,
370
+ };
357
371
  }
358
372
  findWorkspaceByFilePath(filePath) {
359
373
  if (this.workspaceByFileCache.has(filePath))
@@ -17,7 +17,6 @@ export declare class DependencyDeputy {
17
17
  _manifests: WorkspaceManifests;
18
18
  workspacePkgNames: Set<string>;
19
19
  referencedDependencies: Map<string, Set<string>>;
20
- referencedBinaries: Map<string, Set<string>>;
21
20
  hostDependencies: Map<string, HostDependencies>;
22
21
  installedBinaries: Map<string, InstalledBinaries>;
23
22
  hasTypesIncluded: Map<string, Set<string>>;
@@ -57,7 +56,6 @@ export declare class DependencyDeputy {
57
56
  private dependencyCache;
58
57
  getDependencies(workspaceName: string): DependencySet;
59
58
  addReferencedDependency(workspaceName: string, packageName: string): void;
60
- addReferencedBinary(workspaceName: string, binaryName: string): void;
61
59
  setHostDependencies(workspaceName: string, hostDependencies: HostDependencies): void;
62
60
  getHostDependenciesFor(workspaceName: string, dependency: string): {
63
61
  name: string;
@@ -1,5 +1,5 @@
1
1
  import { isBuiltin } from 'node:module';
2
- import { DT_SCOPE, IGNORE_DEFINITELY_TYPED, IGNORED_DEPENDENCIES, IGNORED_GLOBAL_BINARIES, IGNORED_RUNTIME_DEPENDENCIES, ROOT_WORKSPACE_NAME, } from './constants.js';
2
+ import { DT_SCOPE, IGNORE_DEFINITELY_TYPED, IGNORED_DEPENDENCIES, IGNORED_RUNTIME_DEPENDENCIES, ROOT_WORKSPACE_NAME, } from './constants.js';
3
3
  import { getDependencyMetaData } from './manifest/index.js';
4
4
  import { PackagePeeker } from './PackagePeeker.js';
5
5
  import { getDefinitelyTypedFor, getPackageFromDefinitelyTyped, getPackageNameFromModuleSpecifier, isDefinitelyTyped, } from './util/modules.js';
@@ -12,7 +12,6 @@ export class DependencyDeputy {
12
12
  _manifests = new Map();
13
13
  workspacePkgNames = new Set();
14
14
  referencedDependencies;
15
- referencedBinaries;
16
15
  hostDependencies;
17
16
  installedBinaries;
18
17
  hasTypesIncluded;
@@ -21,7 +20,6 @@ export class DependencyDeputy {
21
20
  this.isStrict = isStrict;
22
21
  this.isReportDependencies = isReportDependencies;
23
22
  this.referencedDependencies = new Map();
24
- this.referencedBinaries = new Map();
25
23
  this.hostDependencies = new Map();
26
24
  this.installedBinaries = new Map();
27
25
  this.hasTypesIncluded = new Map();
@@ -106,12 +104,6 @@ export class DependencyDeputy {
106
104
  }
107
105
  this.referencedDependencies.get(workspaceName)?.add(packageName);
108
106
  }
109
- addReferencedBinary(workspaceName, binaryName) {
110
- if (!this.referencedBinaries.has(workspaceName)) {
111
- this.referencedBinaries.set(workspaceName, new Set());
112
- }
113
- this.referencedBinaries.get(workspaceName)?.add(binaryName);
114
- }
115
107
  setHostDependencies(workspaceName, hostDependencies) {
116
108
  this.hostDependencies.set(workspaceName, hostDependencies);
117
109
  }
@@ -167,7 +159,6 @@ export class DependencyDeputy {
167
159
  maybeAddReferencedBinary(workspace, binaryName) {
168
160
  if (!this.isReportDependencies)
169
161
  return new Set();
170
- this.addReferencedBinary(workspace.name, binaryName);
171
162
  const workspaceNames = this.isStrict ? [workspace.name] : [workspace.name, ...workspace.ancestors.toReversed()];
172
163
  for (const name of workspaceNames) {
173
164
  const binaries = this.installedBinaries.get(name);
@@ -180,8 +171,6 @@ export class DependencyDeputy {
180
171
  }
181
172
  }
182
173
  }
183
- if (IGNORED_GLOBAL_BINARIES.has(binaryName))
184
- return new Set();
185
174
  return;
186
175
  }
187
176
  isInDependencies(workspaceName, packageName, isDevOnly) {
@@ -303,11 +292,6 @@ export class DependencyDeputy {
303
292
  const issueSet = issues[type][key];
304
293
  for (const issueKey in issueSet) {
305
294
  const issue = issueSet[issueKey];
306
- if (IGNORED_GLOBAL_BINARIES.has(issue.symbol)) {
307
- delete issueSet[issueKey];
308
- counters[type]--;
309
- continue;
310
- }
311
295
  const manifest = this.getWorkspaceManifest(issue.workspace);
312
296
  if (manifest) {
313
297
  const ignoreItem = findMatch(manifest.ignoreBinaries, issue.symbol);
@@ -214,10 +214,9 @@ export class WorkspaceWorker {
214
214
  const manifest = this.manifest;
215
215
  const containingFilePath = join(cwd, 'package.json');
216
216
  const isProduction = this.options.isProduction;
217
- const knownBinsOnly = false;
218
217
  const rootManifest = this.rootManifest;
219
218
  const getManifest = this.getManifest;
220
- const baseOptions = { manifest, rootManifest, cwd, rootCwd, containingFilePath, knownBinsOnly, getManifest };
219
+ const baseOptions = { manifest, rootManifest, cwd, rootCwd, containingFilePath, getManifest };
221
220
  const baseScriptOptions = { ...baseOptions, isProduction, enabledPlugins: this.enabledPlugins };
222
221
  const [productionScripts, developmentScripts] = getFilteredScripts(manifest.scripts ?? {});
223
222
  const inputsFromManifest = _getInputsFromScripts(Object.values(developmentScripts), baseOptions);
@@ -259,14 +258,15 @@ export class WorkspaceWorker {
259
258
  }
260
259
  };
261
260
  for (const input of [...inputsFromManifest, ...productionInputsFromManifest]) {
261
+ const inputContainingFilePath = input.containingFilePath ?? containingFilePath;
262
262
  if (isCatalog(input)) {
263
- inputs.push({ ...input, containingFilePath });
263
+ inputs.push({ ...input, containingFilePath: inputContainingFilePath });
264
264
  }
265
265
  else if (isConfig(input)) {
266
- storeConfigFilePath(input.pluginName, { ...input, containingFilePath });
266
+ storeConfigFilePath(input.pluginName, { ...input, containingFilePath: inputContainingFilePath });
267
267
  }
268
268
  else if (!isProduction || (isProduction && (input.production || hasProductionInput(input)))) {
269
- inputs.push({ ...input, containingFilePath });
269
+ inputs.push({ ...input, containingFilePath: inputContainingFilePath });
270
270
  }
271
271
  }
272
272
  const runPlugin = async (pluginName, patterns, isResolvedConfigFiles = false) => {
@@ -299,6 +299,7 @@ export class WorkspaceWorker {
299
299
  configFilePath: containingFilePath,
300
300
  configFileDir: cwd,
301
301
  configFileName: '',
302
+ isResolvedConfigFile: isResolvedConfigFiles,
302
303
  getInputsFromScripts: createGetInputsFromScripts(containingFilePath),
303
304
  };
304
305
  if (config.entry) {
@@ -411,7 +412,7 @@ export class WorkspaceWorker {
411
412
  if (plugin.resolve) {
412
413
  const dependencies = (await plugin.resolve(options)) ?? [];
413
414
  for (const id of dependencies)
414
- addInput(id, containingFilePath);
415
+ addInput(id, id.containingFilePath ?? containingFilePath);
415
416
  }
416
417
  if (inputs.some(input => input.specifier.startsWith('!')))
417
418
  for (const input of inputs)
@@ -32,7 +32,7 @@ export const getDependenciesFromScript = (script, options) => {
32
32
  return [];
33
33
  return getDependenciesFromScript(toScript(args), {
34
34
  ...options,
35
- knownBinsOnly: false,
35
+ isForwardedArgs: false,
36
36
  ...opts,
37
37
  });
38
38
  };
@@ -1,10 +1,10 @@
1
1
  import { Plugins, pluginArgsMap } from '../plugins.js';
2
- import { toBinary, toDeferResolve } from '../util/input.js';
3
- import { extractBinary } from '../util/modules.js';
2
+ import { toDeferResolve } from '../util/input.js';
3
+ import { extractBinary, isInNodeModulesBin, isRelativeNodeModulesBin } from '../util/modules.js';
4
4
  import { resolve as fallbackResolve, spawningBinaries } from './fallback.js';
5
- import KnownResolvers from './resolvers/index.js';
5
+ import KnownResolvers, { isPackageManager } from './resolvers/index.js';
6
6
  import { resolve as resolverFromPlugins } from './plugins.js';
7
- import { parseNodeArgs } from './util.js';
7
+ import { parseNodeArgs, toCommandBinary } from './util.js';
8
8
  export const getInputsFromNodeOptions = (prefix) => prefix
9
9
  .filter(a => a.name === 'NODE_OPTIONS' && a.value)
10
10
  .map(a => a.value.value)
@@ -14,34 +14,45 @@ export const getInputsFromNodeOptions = (prefix) => prefix
14
14
  .map(id => toDeferResolve(id));
15
15
  export const getDependenciesFromCommand = (node, options, fromWords = options.fromArgs) => {
16
16
  const text = node.name?.value;
17
- const binary = text ? extractBinary(text) : text;
18
- const { fromArgs } = options;
17
+ if (!text)
18
+ return [];
19
+ const binary = extractBinary(text);
19
20
  if (!binary || binary === '.' || binary === 'source' || binary === '[')
20
21
  return [];
21
22
  if (binary.startsWith('-') || binary.startsWith('..'))
22
23
  return [];
24
+ const isExplicitBin = isInNodeModulesBin(text) || text.startsWith('.bin/');
25
+ if (options.optionalBinaries && (isExplicitBin || isPackageManager(binary))) {
26
+ const { fromArgs } = options;
27
+ options = {
28
+ ...options,
29
+ optionalBinaries: !isExplicitBin,
30
+ fromArgs: (args, opts) => fromArgs(args, { optionalBinaries: false, ...opts }),
31
+ };
32
+ }
33
+ const { fromArgs } = options;
23
34
  const words = node.suffix;
24
35
  if (binary === '!' || binary === 'test')
25
36
  return fromArgs(words);
26
37
  const fromNodeOptions = getInputsFromNodeOptions(node.prefix);
27
38
  if (binary in KnownResolvers) {
28
39
  const resolver = KnownResolvers[binary];
29
- return resolver(binary, words, options);
40
+ return [...resolver(binary, words, options), ...fromNodeOptions];
30
41
  }
31
42
  if (pluginArgsMap.has(binary)) {
32
43
  return [...resolverFromPlugins(binary, words, options), ...fromNodeOptions];
33
44
  }
34
45
  if (spawningBinaries.includes(binary)) {
35
- return [toBinary(binary), ...fromWords(words, options)];
46
+ return [toCommandBinary(binary, options), ...fromWords(words, options), ...fromNodeOptions];
36
47
  }
37
48
  if (binary in Plugins) {
38
49
  const inputs = fallbackResolve(binary, words, options);
39
- if (options.knownBinsOnly)
50
+ if (options.isForwardedArgs)
40
51
  for (const input of inputs)
41
52
  input.optional = true;
42
53
  return [...inputs, ...fromNodeOptions];
43
54
  }
44
- if (options.knownBinsOnly && !text?.startsWith('.'))
55
+ if (options.isForwardedArgs && !text.startsWith('.') && !isRelativeNodeModulesBin(text))
45
56
  return [];
46
57
  return [...fallbackResolve(binary, words, options), ...fromNodeOptions];
47
58
  };
@@ -1,20 +1,21 @@
1
1
  import parseArgs from '../util/parse-args.js';
2
2
  import { compact } from '../util/array.js';
3
- import { toBinary, toDeferResolve, toEntry } from '../util/input.js';
3
+ import { toDeferResolve, toEntry } from '../util/input.js';
4
4
  import { isValidBinary } from '../util/modules.js';
5
5
  import { isAbsolute } from '../util/path.js';
6
- import { argsAfter } from './util.js';
6
+ import { argsAfter, toCommandBinary } from './util.js';
7
7
  export const spawningBinaries = ['cross-env', 'retry-cli'];
8
8
  const endOfCommandBinaries = ['dotenvx', 'env-cmd', 'op'];
9
9
  const positionals = new Set(['babel-node', 'esbuild', 'execa', 'jiti', 'oxnode', 'vite-node', 'zx']);
10
10
  const positionalBinaries = new Set(['concurrently']);
11
11
  export const isWrapper = (binary) => spawningBinaries.includes(binary) || endOfCommandBinaries.includes(binary) || positionalBinaries.has(binary);
12
- export const resolve = (binary, words, { fromArgs }) => {
12
+ export const resolve = (binary, words, options) => {
13
+ const { fromArgs } = options;
13
14
  const parsed = parseArgs(words, { boolean: ['quiet', 'verbose'], '--': endOfCommandBinaries.includes(binary) });
14
15
  const bin = binary.startsWith('.') || (binary.includes('/') && !isAbsolute(binary))
15
16
  ? toEntry(binary)
16
17
  : isValidBinary(binary)
17
- ? toBinary(binary)
18
+ ? toCommandBinary(binary, options)
18
19
  : undefined;
19
20
  const pos = positionals.has(binary) ? [toDeferResolve(parsed._[0])] : [];
20
21
  const newCommand = parsed['--'] && parsed['--'].length > 0 ? fromArgs(argsAfter(words, '--')) : [];
@@ -2,10 +2,10 @@ import parseArgs from '../util/parse-args.js';
2
2
  import { pluginArgsMap } from '../plugins.js';
3
3
  import { compact } from '../util/array.js';
4
4
  import { toBinary, toConfig, toDeferResolve, toDeferResolveEntry, toEntry } from '../util/input.js';
5
- import { extractBinary } from '../util/modules.js';
5
+ import { extractBinary, isInNodeModulesBin } from '../util/modules.js';
6
6
  import { dirname } from '../util/path.js';
7
7
  import { isWrapper as isFallbackWrapper, resolve as fallbackResolve } from './fallback.js';
8
- import { toWordArgs } from './util.js';
8
+ import { toCommandBinary, toWordArgs } from './util.js';
9
9
  const isGlobLikeMatch = /(^!|[*+\\(|{^$])/;
10
10
  const isGlobLike = (value) => isGlobLikeMatch.test(value);
11
11
  const nodeLoadersArgs = { import: ['r', 'experimental-loader', 'require', 'loader'] };
@@ -42,7 +42,7 @@ export const resolve = (binary, words, options) => {
42
42
  if (isGlobLike(id))
43
43
  positionals.push(toEntry(id));
44
44
  else {
45
- if (id.includes('node_modules/.bin/'))
45
+ if (isInNodeModulesBin(id))
46
46
  positionals.push(toBinary(extractBinary(id)));
47
47
  else
48
48
  positionals.push(toDeferResolveEntry(id, { optional: true }));
@@ -66,7 +66,7 @@ export const resolve = (binary, words, options) => {
66
66
  const configFilePaths = config.flatMap(mapToConfigPattern);
67
67
  const inputs = pluginArgs.resolveInputs?.(parsed, { args, cwd, manifest }) ?? [];
68
68
  return [
69
- toBinary(binary, inputOpts),
69
+ toCommandBinary(binary, options, inputOpts),
70
70
  ...positionals,
71
71
  ...resolved.map(id => toDeferResolve(id)),
72
72
  ...resolvedImports.map(id => toDeferResolve(id)),
@@ -2,7 +2,7 @@ import parseArgs from '../../util/parse-args.js';
2
2
  import { toBinary, toEntry } from '../../util/input.js';
3
3
  import { isAbsolute, join } from '../../util/path.js';
4
4
  import { _resolveSync } from '../../util/resolve.js';
5
- import { argsAfter, expandScript } from '../util.js';
5
+ import { argsAfter, expandScript, toCommandBinary } from '../util.js';
6
6
  import { resolveX } from './bunx.js';
7
7
  const commands = new Set([
8
8
  'add',
@@ -53,7 +53,7 @@ const commands = new Set([
53
53
  'x',
54
54
  ]);
55
55
  export const resolve = (_binary, words, options) => {
56
- const binary = toBinary(_binary);
56
+ const binary = toCommandBinary(_binary, options);
57
57
  const parsed = parseArgs(words, { string: ['cwd'] });
58
58
  const [command, script] = parsed._;
59
59
  if (command === 'x') {
@@ -1,7 +1,8 @@
1
- import { toBinary } from '../../util/input.js';
1
+ import { toCommandBinary } from '../util.js';
2
2
  const execFlags = new Set(['-exec', '-execdir']);
3
3
  const execTerminators = new Set([';', '\\;', '+']);
4
- export const resolve = (binary, words, { fromArgs }) => {
4
+ export const resolve = (binary, words, options) => {
5
+ const { fromArgs } = options;
5
6
  const execIdx = words.findIndex(word => execFlags.has(word.value));
6
7
  if (execIdx >= 0) {
7
8
  const cmdWords = [];
@@ -13,7 +14,7 @@ export const resolve = (binary, words, { fromArgs }) => {
13
14
  cmdWords.push(words[i]);
14
15
  }
15
16
  if (cmdWords.length > 0)
16
- return [toBinary(binary), ...fromArgs(cmdWords)];
17
+ return [toCommandBinary(binary, options), ...fromArgs(cmdWords)];
17
18
  }
18
- return [toBinary(binary)];
19
+ return [toCommandBinary(binary, options)];
19
20
  };
@@ -1,9 +1,9 @@
1
+ export declare const isPackageManager: (binary: string) => boolean;
1
2
  declare const _default: {
2
3
  bun: import("../../types/config.ts").BinaryResolver;
3
4
  bunx: import("../../types/config.ts").BinaryResolver;
4
5
  nub: import("../../types/config.ts").BinaryResolver;
5
6
  nubx: import("../../types/config.ts").BinaryResolver;
6
- find: import("../../types/config.ts").BinaryResolver;
7
7
  npm: import("../../types/config.ts").BinaryResolver;
8
8
  npx: import("../../types/config.ts").BinaryResolver;
9
9
  pnpm: import("../../types/config.ts").BinaryResolver;
@@ -11,5 +11,6 @@ declare const _default: {
11
11
  pnpx: import("../../types/config.ts").BinaryResolver;
12
12
  pnx: import("../../types/config.ts").BinaryResolver;
13
13
  yarn: import("../../types/config.ts").BinaryResolver;
14
+ find: import("../../types/config.ts").BinaryResolver;
14
15
  };
15
16
  export default _default;
@@ -7,12 +7,11 @@ import * as nub from './nub.js';
7
7
  import * as pnpm from './pnpm.js';
8
8
  import * as pnpx from './pnpx.js';
9
9
  import * as yarn from './yarn.js';
10
- export default {
10
+ const packageManagerResolvers = {
11
11
  bun: bun.resolve,
12
12
  bunx: bunx.resolve,
13
13
  nub: nub.resolve,
14
14
  nubx: bunx.resolve,
15
- find: find.resolve,
16
15
  npm: npm.resolve,
17
16
  npx: npx.resolve,
18
17
  pnpm: pnpm.resolve,
@@ -21,3 +20,5 @@ export default {
21
20
  pnx: pnpx.resolve,
22
21
  yarn: yarn.resolve,
23
22
  };
23
+ export const isPackageManager = (binary) => binary in packageManagerResolvers;
24
+ export default { ...packageManagerResolvers, find: find.resolve };
@@ -1,12 +1,54 @@
1
1
  import parseArgs from '../../util/parse-args.js';
2
+ import { isBinary, toBinary, toDependency } from '../../util/input.js';
3
+ import { extractBinary, isValidBinary, stripVersionFromSpecifier } from '../../util/modules.js';
4
+ import { isInternal } from '../../util/path.js';
2
5
  import { argsAfter, expandScript } from '../util.js';
3
6
  export const resolve = (_binary, words, options) => {
4
7
  const { fromArgs, manifest } = options;
5
- const parsed = parseArgs(words, { '--': true });
8
+ const parsed = parseArgs(words, {
9
+ isStorePositions: true,
10
+ boolean: ['yes', 'no', 'parseable'],
11
+ string: ['package', 'call'],
12
+ alias: { yes: 'y', parseable: 'p', call: 'c' },
13
+ '--': true,
14
+ });
6
15
  const [command, script] = parsed._;
7
- const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(argsAfter(words, '--'), { knownBinsOnly: true }) : [];
8
- if (command === 'exec')
9
- return _childArgs;
16
+ if (command === 'exec' || command === 'x') {
17
+ const packages = parsed.package ? [parsed.package].flat() : [];
18
+ const packageInputs = packages.map(specifier => toDependency(stripVersionFromSpecifier(specifier), { optional: true }));
19
+ const separator = words.findIndex(word => word.value === '--');
20
+ const args = parsed.positionalIndices.slice(1).map(index => words[index]);
21
+ if (separator !== -1)
22
+ args.push(...words.slice(separator + 1));
23
+ const call = Array.isArray(parsed.call) ? parsed.call.at(-1) : parsed.call;
24
+ if (call)
25
+ return packages.length ? packageInputs : fromArgs([call]);
26
+ const specifier = args[0]?.value;
27
+ if (!specifier)
28
+ return packageInputs;
29
+ const npmWords = separator === -1 ? words : words.slice(0, separator);
30
+ const noInstall = parsed.no || npmWords.some(word => word.value === '--yes=false' || word.value === '--no-yes');
31
+ const inputOptions = noInstall && packages.length === 0 ? undefined : { optional: true };
32
+ const isPackage = packages.length === 0 && specifier.includes('@') && !isInternal(specifier);
33
+ if (isPackage && specifier.startsWith('@')) {
34
+ return [toDependency(stripVersionFromSpecifier(specifier), inputOptions)];
35
+ }
36
+ const inputs = fromArgs([args.map(word => word.text).join(' ')]);
37
+ const first = inputs[0];
38
+ if (first && isBinary(first) && first.specifier === extractBinary(specifier)) {
39
+ if (isPackage)
40
+ inputs[0] = toDependency(stripVersionFromSpecifier(specifier), inputOptions);
41
+ else if (inputOptions)
42
+ first.optional = true;
43
+ }
44
+ else if (isPackage || (!isInternal(specifier) && !specifier.includes('/') && isValidBinary(specifier))) {
45
+ inputs.unshift(isPackage
46
+ ? toDependency(stripVersionFromSpecifier(specifier), inputOptions)
47
+ : toBinary(extractBinary(specifier), inputOptions));
48
+ }
49
+ return [...packageInputs, ...inputs];
50
+ }
51
+ const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(argsAfter(words, '--'), { isForwardedArgs: true }) : [];
10
52
  if (command === 'run' && manifest.scriptNames.has(script)) {
11
53
  return expandScript(script, argsAfter(words, '--'), manifest.scripts, options) ?? _childArgs;
12
54
  }
@@ -3,20 +3,24 @@ import { toBinary, toDependency } from '../../util/input.js';
3
3
  import { stripVersionFromSpecifier } from '../../util/modules.js';
4
4
  import { isInternal } from '../../util/path.js';
5
5
  import { argsFrom } from '../util.js';
6
+ const noInstallFlags = new Set(['--no', '--no-install', '--yes=false', '--no-yes']);
6
7
  export const resolve = (_binary, words, options) => {
7
8
  const { fromArgs } = options;
8
9
  const parsed = parseArgs(words, {
10
+ isStorePositions: true,
9
11
  boolean: ['yes', 'no', 'quiet'],
10
- alias: { yes: 'y', no: 'no-install', package: 'p', call: 'c' },
12
+ alias: { yes: 'y', package: 'p', call: 'c' },
11
13
  });
12
14
  const packageSpecifier = parsed._[0];
13
15
  const specifier = packageSpecifier ? stripVersionFromSpecifier(packageSpecifier) : '';
14
- const packages = parsed.package && !parsed.yes ? [parsed.package].flat().map(stripVersionFromSpecifier) : [];
16
+ const packages = parsed.package ? [parsed.package].flat().map(stripVersionFromSpecifier) : [];
15
17
  const command = parsed.call ? fromArgs([parsed.call]) : [];
16
18
  const isBinary = specifier && !packageSpecifier.includes('@') && !isInternal(specifier);
17
- const opts = parsed.no ? undefined : { optional: true };
19
+ const commandIndex = parsed.positionalIndices[0] ?? words.length;
20
+ const noInstall = words.slice(0, commandIndex).some(word => noInstallFlags.has(word.value));
21
+ const opts = noInstall ? undefined : { optional: true };
18
22
  const dependency = isBinary ? toBinary(specifier, opts) : toDependency(specifier, opts);
19
- const specifiers = dependency && !parsed.yes ? [dependency] : [];
23
+ const specifiers = dependency ? [dependency] : [];
20
24
  return [
21
25
  ...specifiers,
22
26
  ...packages.map(id => toDependency(id, { optional: true })),
@@ -1,7 +1,8 @@
1
1
  import parseArgs from '../../util/parse-args.js';
2
- import { toBinary, toEntry } from '../../util/input.js';
2
+ import { toEntry } from '../../util/input.js';
3
3
  import { isAbsolute, join } from '../../util/path.js';
4
4
  import { _resolveSync } from '../../util/resolve.js';
5
+ import { toCommandBinary } from '../util.js';
5
6
  import { resolveX } from './bunx.js';
6
7
  const runtimes = new Set(['x', 'dlx', 'exec']);
7
8
  const runners = new Set(['run', 'watch']);
@@ -24,7 +25,7 @@ const commands = new Set([
24
25
  'why',
25
26
  ]);
26
27
  export const resolve = (_binary, words, options) => {
27
- const binary = toBinary(_binary);
28
+ const binary = toCommandBinary(_binary, options);
28
29
  const { manifest, cwd, fromArgs } = options;
29
30
  const parsed = parseArgs(words, { string: ['filter'], boolean: ['recursive'], alias: { recursive: 'r' } });
30
31
  const [command, script] = parsed._;
@@ -1,7 +1,7 @@
1
1
  import parseArgs from '../../util/parse-args.js';
2
2
  import { toBinary } from '../../util/input.js';
3
3
  import { isValidBinary } from '../../util/modules.js';
4
- import { argsAfter, expandScript, toWordArgs } from '../util.js';
4
+ import { argsAfter, expandScript } from '../util.js';
5
5
  import { resolveDlx } from './pnpx.js';
6
6
  const commands = [
7
7
  'add',
@@ -90,11 +90,13 @@ const commands = [
90
90
  ];
91
91
  const recursiveCommands = ['recursive', 'multi', 'm'];
92
92
  export const resolve = (_binary, words, options) => {
93
- const parsed = parseArgs(words, {
93
+ const parseOptions = {
94
+ isStorePositions: true,
94
95
  boolean: ['aggregate-output', 'if-present', 'parallel', 'recursive', 'reverse', 'shell-mode', 'silent', 'stream'],
95
96
  alias: { recursive: 'r', silent: 's', 'shell-mode': 'c', filter: 'F' },
96
97
  '--': true,
97
- });
98
+ };
99
+ const parsed = parseArgs(words, parseOptions);
98
100
  const [command] = parsed._;
99
101
  if (command === 'dlx') {
100
102
  const wordsForDlx = words.filter(word => word.value !== 'dlx');
@@ -104,15 +106,20 @@ export const resolve = (_binary, words, options) => {
104
106
  return resolve(_binary, argsAfter(words, command), options);
105
107
  }
106
108
  const { manifest, fromArgs } = options;
107
- if (parsed.filter && !parsed.recursive)
108
- return [];
109
- const childInputs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(argsAfter(words, '--'), { knownBinsOnly: true }) : [];
110
109
  if (command === 'exec') {
111
- if (childInputs.length > 0)
112
- return childInputs;
113
- const rest = parsed._.slice(1);
114
- return rest.length === 1 ? fromArgs(rest.map(String)) : fromArgs(toWordArgs(rest, words));
110
+ const commandIndex = parsed.positionalIndices[0];
111
+ if (commandIndex > 0) {
112
+ const execOptions = parseArgs(words.slice(0, commandIndex), parseOptions);
113
+ if (execOptions.filter && !execOptions.recursive)
114
+ return [];
115
+ }
116
+ const index = commandIndex + 1;
117
+ const rest = words.slice(words[index]?.value === '--' ? index + 1 : index);
118
+ return fromArgs([rest.length === 1 ? rest[0].value : rest.map(word => word.text).join(' ')]);
115
119
  }
120
+ if (parsed.filter && !parsed.recursive)
121
+ return [];
122
+ const childInputs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(argsAfter(words, '--'), { isForwardedArgs: true }) : [];
116
123
  if (command === 'run') {
117
124
  const script = parsed._[1];
118
125
  if (script && manifest.scriptNames.has(script)) {
@@ -56,7 +56,7 @@ export const resolve = (_binary, words, options) => {
56
56
  if (!command && !binary)
57
57
  return [];
58
58
  const dirManifest = (dir && getManifest(dir)) || manifest;
59
- const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(argsAfter(words, '--'), { knownBinsOnly: true }) : [];
59
+ const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(argsAfter(words, '--'), { isForwardedArgs: true }) : [];
60
60
  if (command === 'run') {
61
61
  if (dirManifest.scriptNames.has(binary)) {
62
62
  const opts = dir ? { cwd: dir, manifest: dirManifest } : {};