knip 6.36.0 → 6.38.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 (79) 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 +1 -2
  6. package/dist/binaries/bash-parser.js +1 -1
  7. package/dist/binaries/command.js +20 -9
  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/graph/analyze.js +16 -12
  23. package/dist/manifest/index.js +1 -3
  24. package/dist/plugins/ava/index.js +1 -1
  25. package/dist/plugins/eslint/helpers.d.ts +4 -1
  26. package/dist/plugins/eslint/helpers.js +42 -11
  27. package/dist/plugins/eslint/index.js +2 -2
  28. package/dist/plugins/eslint/resolveFromAST.js +12 -8
  29. package/dist/plugins/eve/index.js +26 -8
  30. package/dist/plugins/github-actions/index.js +1 -1
  31. package/dist/plugins/graphql-codegen/index.js +15 -4
  32. package/dist/plugins/graphql-codegen/types.d.ts +11 -1
  33. package/dist/plugins/graphql-codegen/types.js +6 -0
  34. package/dist/plugins/husky/index.js +1 -1
  35. package/dist/plugins/index.d.ts +2 -0
  36. package/dist/plugins/index.js +4 -0
  37. package/dist/plugins/lefthook/index.js +1 -1
  38. package/dist/plugins/mdx/index.d.ts +3 -0
  39. package/dist/plugins/mdx/index.js +16 -6
  40. package/dist/plugins/mise/scripts.js +5 -5
  41. package/dist/plugins/mocha/index.js +3 -1
  42. package/dist/plugins/mocha/types.d.ts +1 -0
  43. package/dist/plugins/oxlint/index.js +24 -8
  44. package/dist/plugins/oxlint/types.d.ts +1 -0
  45. package/dist/plugins/plop/index.js +2 -2
  46. package/dist/plugins/taskfile/index.js +1 -1
  47. package/dist/plugins/tauri/index.js +1 -1
  48. package/dist/plugins/travis/index.js +1 -1
  49. package/dist/plugins/turbo/index.d.ts +3 -0
  50. package/dist/plugins/turbo/index.js +23 -0
  51. package/dist/plugins/typescript/content-mappers.d.ts +4 -0
  52. package/dist/plugins/typescript/content-mappers.js +4 -0
  53. package/dist/plugins/typescript/index.js +14 -18
  54. package/dist/plugins/typescript-content-mapper/index.d.ts +3 -0
  55. package/dist/plugins/typescript-content-mapper/index.js +23 -0
  56. package/dist/plugins/typescript-content-mapper/types.d.ts +3 -0
  57. package/dist/plugins/typescript-content-mapper/types.js +1 -0
  58. package/dist/plugins/vite-plus/resolveFromAST.js +1 -1
  59. package/dist/schema/configuration.d.ts +33 -0
  60. package/dist/schema/configuration.js +2 -0
  61. package/dist/schema/plugins.d.ts +10 -0
  62. package/dist/schema/plugins.js +2 -0
  63. package/dist/types/PluginNames.d.ts +2 -2
  64. package/dist/types/PluginNames.js +2 -0
  65. package/dist/types/config.d.ts +4 -1
  66. package/dist/types/package-json.d.ts +1 -1
  67. package/dist/types/tsconfig-json.d.ts +1 -3
  68. package/dist/util/create-input-handler.js +3 -3
  69. package/dist/util/create-options.d.ts +28 -2
  70. package/dist/util/jiti.js +1 -0
  71. package/dist/util/modules.d.ts +2 -0
  72. package/dist/util/modules.js +3 -1
  73. package/dist/util/package-json.d.ts +187 -185
  74. package/dist/util/parse-args.d.ts +2 -0
  75. package/dist/util/parse-args.js +6 -1
  76. package/dist/version.d.ts +1 -1
  77. package/dist/version.js +1 -1
  78. package/package.json +5 -5
  79. package/schema.json +20 -0
@@ -822,6 +822,11 @@ export declare class ConfigurationChief {
822
822
  entry?: string | string[] | undefined;
823
823
  project?: string | string[] | undefined;
824
824
  } | undefined;
825
+ turbo?: string | boolean | string[] | {
826
+ config?: string | string[] | undefined;
827
+ entry?: string | string[] | undefined;
828
+ project?: string | string[] | undefined;
829
+ } | undefined;
825
830
  typedoc?: string | boolean | string[] | {
826
831
  config?: string | string[] | undefined;
827
832
  entry?: string | string[] | undefined;
@@ -832,6 +837,11 @@ export declare class ConfigurationChief {
832
837
  entry?: string | string[] | undefined;
833
838
  project?: string | string[] | undefined;
834
839
  } | undefined;
840
+ 'typescript-content-mapper'?: string | boolean | string[] | {
841
+ config?: string | string[] | undefined;
842
+ entry?: string | string[] | undefined;
843
+ project?: string | string[] | undefined;
844
+ } | undefined;
835
845
  unbuild?: string | boolean | string[] | {
836
846
  config?: string | string[] | undefined;
837
847
  entry?: string | string[] | undefined;
@@ -988,10 +998,13 @@ export declare class ConfigurationChief {
988
998
  ignore?: string | string[] | undefined;
989
999
  ignoreFiles?: string | string[] | undefined;
990
1000
  ignoreBinaries?: (string | RegExp)[] | undefined;
1001
+ ignoreGlobalBinaries?: boolean | undefined;
991
1002
  ignoreDependencies?: (string | RegExp)[] | undefined;
992
1003
  ignoreMembers?: (string | RegExp)[] | undefined;
993
1004
  ignoreUnresolved?: (string | RegExp)[] | undefined;
994
- ignoreExportsUsedInFile?: boolean | Record<string, boolean | undefined> | undefined;
1005
+ ignoreExportsUsedInFile?: boolean | {
1006
+ [x: string]: boolean | undefined;
1007
+ } | undefined;
995
1008
  ignoreIssues?: Record<string, ("binaries" | "catalog" | "catalogReferences" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
996
1009
  includeEntryExports?: boolean | undefined;
997
1010
  };
@@ -1007,7 +1020,10 @@ export declare class ConfigurationChief {
1007
1020
  paths: Record<string, string[]>;
1008
1021
  ignore: string[];
1009
1022
  ignoreFiles: string[];
1010
- ignoreExportsUsedInFile: Record<string, boolean | undefined> | import("./types/config.ts").IgnoreExportsUsedInFile;
1023
+ ignoreGlobalBinaries: boolean;
1024
+ ignoreExportsUsedInFile: {
1025
+ [x: string]: boolean | undefined;
1026
+ } | import("./types/config.ts").IgnoreExportsUsedInFile;
1011
1027
  isIncludeEntryExports: boolean;
1012
1028
  angular?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1013
1029
  astro?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -1162,8 +1178,10 @@ export declare class ConfigurationChief {
1162
1178
  tsdown?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1163
1179
  tsup?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1164
1180
  tsx?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1181
+ turbo?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1165
1182
  typedoc?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1166
1183
  typescript?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1184
+ "typescript-content-mapper"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1167
1185
  unbuild?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1168
1186
  unocss?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1169
1187
  "unplugin-auto-import"?: (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);
@@ -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,12 +14,23 @@ 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);
@@ -32,16 +43,16 @@ export const getDependenciesFromCommand = (node, options, fromWords = options.fr
32
43
  return [...resolverFromPlugins(binary, words, options), ...fromNodeOptions];
33
44
  }
34
45
  if (spawningBinaries.includes(binary)) {
35
- return [toBinary(binary), ...fromWords(words, options), ...fromNodeOptions];
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 } : {};
@@ -1,6 +1,9 @@
1
1
  import type { Word } from 'unbash';
2
2
  import type { BinaryResolverOptions, GetInputsFromScriptsOptions, ScriptArg } from '../types/config.ts';
3
- import type { Input } from '../util/input.ts';
3
+ import { type Input } from '../util/input.ts';
4
+ export declare const toCommandBinary: (binary: string, { optionalBinaries }: GetInputsFromScriptsOptions, inputOptions?: {
5
+ dir?: string;
6
+ }) => Input;
4
7
  export declare const toScript: (args: ScriptArg[]) => string;
5
8
  export declare const argsFrom: <T extends string | Word>(args: readonly T[], from: string) => T[];
6
9
  export declare const argsAfter: <T extends string | Word>(args: readonly T[], token: string) => T[];
@@ -1,4 +1,6 @@
1
1
  import parseArgs from '../util/parse-args.js';
2
+ import { toBinary } from '../util/input.js';
3
+ export const toCommandBinary = (binary, { optionalBinaries }, inputOptions = {}) => toBinary(binary, optionalBinaries ? { ...inputOptions, optional: true } : inputOptions);
2
4
  const valueOf = (arg) => (typeof arg === 'string' ? arg : arg.value);
3
5
  export const toScript = (args) => {
4
6
  const parts = [];
@@ -5,7 +5,7 @@ export const styleExtractor = /<style\b((?:[^>"']|"[^"]*"|'[^']*')*)>([\s\S]*?)<
5
5
  const langAttrMatcher = /\blang\s*=\s*["']([^"']+)["']/i;
6
6
  export const blockCommentMatcher = /\/\*[\s\S]*?\*\//g;
7
7
  export const lineCommentMatcher = /^[ \t]*\/\/.*$/gm;
8
- export const importMatcher = /(?<![.\w$#])import\b(?:\s*\(\s*['"][^'"]+['"][^)]*\)|(?!\s*\()[^'"]+['"][^'"]+['"])/g;
8
+ export const importMatcher = /(?<![.\w$#])import\b(?!\s*\.)(?:\s*\(\s*['"][^'"]+['"][^)]*\)|(?!\s*\()[^'"]+['"][^'"]+['"])/g;
9
9
  export const collectImports = text => {
10
10
  if (!text.includes('import'))
11
11
  return '';