knip 4.1.0 → 4.2.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.
Files changed (65) hide show
  1. package/dist/ConfigurationChief.d.ts +14 -12
  2. package/dist/ConfigurationChief.js +37 -25
  3. package/dist/ConfigurationValidator.d.ts +56 -0
  4. package/dist/ConfigurationValidator.js +1 -0
  5. package/dist/DependencyDeputy.d.ts +16 -17
  6. package/dist/DependencyDeputy.js +40 -27
  7. package/dist/IssueFixer.js +1 -1
  8. package/dist/ProjectPrincipal.d.ts +1 -1
  9. package/dist/ProjectPrincipal.js +4 -4
  10. package/dist/WorkspaceWorker.d.ts +15 -23
  11. package/dist/WorkspaceWorker.js +31 -53
  12. package/dist/binaries/bash-parser.d.ts +2 -6
  13. package/dist/binaries/bash-parser.js +7 -6
  14. package/dist/binaries/index.js +2 -4
  15. package/dist/binaries/resolvers/bun.js +2 -3
  16. package/dist/binaries/resolvers/fallback.js +0 -1
  17. package/dist/binaries/resolvers/index.d.ts +15 -11
  18. package/dist/binaries/resolvers/index.js +26 -11
  19. package/dist/binaries/resolvers/npx.js +4 -5
  20. package/dist/binaries/resolvers/pnpm.js +2 -3
  21. package/dist/binaries/resolvers/ts-node.d.ts +2 -0
  22. package/dist/binaries/resolvers/ts-node.js +16 -0
  23. package/dist/binaries/resolvers/yarn.js +3 -4
  24. package/dist/binaries/types.d.ts +7 -11
  25. package/dist/compilers/index.d.ts +13 -3
  26. package/dist/compilers/index.js +3 -8
  27. package/dist/index.js +36 -20
  28. package/dist/manifest/helpers.d.ts +8 -2
  29. package/dist/manifest/helpers.js +14 -1
  30. package/dist/manifest/index.d.ts +3 -8
  31. package/dist/manifest/index.js +6 -21
  32. package/dist/plugins/ava/index.js +2 -6
  33. package/dist/plugins/eleventy/index.js +4 -4
  34. package/dist/plugins/eslint/helpers.d.ts +2 -2
  35. package/dist/plugins/github-actions/index.js +5 -13
  36. package/dist/plugins/husky/index.js +2 -6
  37. package/dist/plugins/index.d.ts +1 -0
  38. package/dist/plugins/index.js +1 -0
  39. package/dist/plugins/lefthook/index.js +3 -3
  40. package/dist/plugins/lint-staged/index.js +1 -2
  41. package/dist/plugins/netlify/helpers.d.ts +2 -0
  42. package/dist/plugins/netlify/helpers.js +4 -0
  43. package/dist/plugins/netlify/index.d.ts +10 -0
  44. package/dist/plugins/netlify/index.js +38 -0
  45. package/dist/plugins/netlify/types.d.ts +11 -0
  46. package/dist/plugins/netlify/types.js +1 -0
  47. package/dist/plugins/nx/index.js +2 -2
  48. package/dist/plugins/release-it/index.js +2 -2
  49. package/dist/plugins/vitest/index.js +7 -8
  50. package/dist/plugins/wireit/index.js +2 -2
  51. package/dist/types/config.d.ts +0 -2
  52. package/dist/types/package-json.d.ts +3 -2
  53. package/dist/types/plugins.d.ts +11 -6
  54. package/dist/types/workspace.d.ts +11 -9
  55. package/dist/typescript/createHosts.js +2 -2
  56. package/dist/util/fs.d.ts +1 -0
  57. package/dist/util/fs.js +5 -0
  58. package/dist/util/loader.js +4 -1
  59. package/dist/util/modules.d.ts +1 -1
  60. package/dist/util/regex.d.ts +0 -1
  61. package/dist/util/regex.js +0 -1
  62. package/dist/version.d.ts +1 -1
  63. package/dist/version.js +1 -1
  64. package/package.json +2 -1
  65. package/schema.json +4 -0
package/dist/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import micromatch from 'micromatch';
2
2
  import { _getDependenciesFromScripts } from './binaries/index.js';
3
- import { getExtensions, mergeCompilers } from './compilers/index.js';
3
+ import { getCompilerExtensions, getIncludedCompilers } from './compilers/index.js';
4
4
  import { ConfigurationChief } from './ConfigurationChief.js';
5
5
  import { ConsoleStreamer } from './ConsoleStreamer.js';
6
6
  import { DependencyDeputy } from './DependencyDeputy.js';
7
7
  import { IssueCollector } from './IssueCollector.js';
8
8
  import { IssueFixer } from './IssueFixer.js';
9
+ import { getFilteredScripts } from './manifest/helpers.js';
9
10
  import { PrincipalFactory } from './PrincipalFactory.js';
10
11
  import { ProjectPrincipal } from './ProjectPrincipal.js';
11
12
  import { debugLogObject, debugLogArray, debugLog, exportLookupLog } from './util/debug.js';
@@ -28,8 +29,8 @@ export const main = async (unresolvedConfiguration) => {
28
29
  const isGitIgnored = await isGitIgnoredFn({ cwd, gitignore });
29
30
  streamer.cast('Reading workspace configuration(s)...');
30
31
  await chief.init();
31
- const workspaces = chief.getWorkspaces();
32
- const report = chief.getIssueTypesToReport();
32
+ const workspaces = chief.getIncludedWorkspaces();
33
+ const report = chief.getIncludedIssueTypes();
33
34
  const rules = chief.getRules();
34
35
  const filters = chief.getFilters();
35
36
  const fixer = new IssueFixer({ isEnabled: isFix, cwd, fixTypes });
@@ -40,7 +41,7 @@ export const main = async (unresolvedConfiguration) => {
40
41
  const isReportClassMembers = report.classMembers;
41
42
  const collector = new IssueCollector({ cwd, rules, filters });
42
43
  const enabledPluginsStore = new Map();
43
- deputy.addIgnored(chief.config.ignoreBinaries, chief.config.ignoreDependencies);
44
+ deputy.setIgnored(chief.config.ignoreBinaries, chief.config.ignoreDependencies);
44
45
  const o = () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors }));
45
46
  debugLogObject('*', 'Included workspaces', () => workspaces.map(w => w.pkgName));
46
47
  debugLogObject('*', 'Included workspace configs', o);
@@ -87,12 +88,18 @@ export const main = async (unresolvedConfiguration) => {
87
88
  }
88
89
  };
89
90
  for (const workspace of workspaces) {
90
- const { name, dir, ancestors, pkgName, manifestPath, manifest } = workspace;
91
+ const { name, dir, ancestors, pkgName, manifestPath } = workspace;
91
92
  streamer.cast(`Analyzing workspace ${name}...`);
92
- const compilers = mergeCompilers(chief.config.syncCompilers, chief.config.asyncCompilers, manifest);
93
- const extensions = getExtensions(compilers);
93
+ const manifest = chief.getManifestForWorkspace(dir);
94
+ const { ignoreBinaries, ignoreDependencies } = chief.getIgnores(name);
95
+ deputy.addWorkspace({ name, cwd, dir, manifestPath, manifest, ignoreBinaries, ignoreDependencies });
96
+ const dependencies = deputy.getDependencies(name);
97
+ const compilers = getIncludedCompilers(chief.config.syncCompilers, chief.config.asyncCompilers, dependencies);
98
+ const extensions = getCompilerExtensions(compilers);
94
99
  const config = chief.getConfigForWorkspace(name, extensions);
95
- deputy.addWorkspace({ name, dir, manifestPath, manifest, ...config });
100
+ const filteredScripts = getFilteredScripts({ isProduction, scripts: manifest.scripts });
101
+ const manifestScripts = Object.values(filteredScripts);
102
+ const manifestScriptNames = new Set(Object.keys(manifest.scripts ?? {}));
96
103
  const { compilerOptions, definitionPaths } = await loadTSConfig(join(dir, tsConfigFile ?? 'tsconfig.json'));
97
104
  const principal = factory.getPrincipal({
98
105
  cwd: dir,
@@ -109,6 +116,7 @@ export const main = async (unresolvedConfiguration) => {
109
116
  cwd,
110
117
  config,
111
118
  manifest,
119
+ dependencies,
112
120
  isProduction,
113
121
  isStrict,
114
122
  rootIgnore: chief.config.ignore,
@@ -121,18 +129,21 @@ export const main = async (unresolvedConfiguration) => {
121
129
  const ignore = worker.getIgnorePatterns();
122
130
  const sharedGlobOptions = { cwd, workingDir: dir, gitignore };
123
131
  collector.addIgnorePatterns(ignore.map(pattern => join(cwd, pattern)));
124
- const entryPathsFromManifest = await getEntryPathFromManifest(manifest, { ...sharedGlobOptions, ignore });
125
- debugLogArray(name, 'Entry paths in package.json', entryPathsFromManifest);
126
- principal.addEntryPaths(entryPathsFromManifest);
127
- const dependencies = await worker.findAllDependencies();
128
- const { referencedDependencies, hostDependencies, installedBinaries, hasTypesIncluded, enabledPlugins, entryFilePatterns, productionEntryFilePatterns, } = dependencies;
129
- principal.addReferencedDependencies(referencedDependencies, name);
130
- deputy.addHostDependencies(name, hostDependencies);
131
- deputy.setInstalledBinaries(name, installedBinaries);
132
- deputy.setHasTypesIncluded(name, hasTypesIncluded);
132
+ {
133
+ const options = { manifestScriptNames, cwd: dir, dependencies };
134
+ const dependenciesFromManifest = _getDependenciesFromScripts(manifestScripts, options);
135
+ principal.addReferencedDependencies(name, new Set(dependenciesFromManifest.map(id => [manifestPath, id])));
136
+ }
137
+ {
138
+ const entryPathsFromManifest = await getEntryPathFromManifest(manifest, { ...sharedGlobOptions, ignore });
139
+ debugLogArray(name, 'Entry paths in package.json', entryPathsFromManifest);
140
+ principal.addEntryPaths(entryPathsFromManifest);
141
+ }
142
+ const { referencedDependencies, enabledPlugins, entryFilePatterns, productionEntryFilePatterns } = await worker.findDependenciesByPlugins();
133
143
  enabledPluginsStore.set(name, enabledPlugins);
144
+ principal.addReferencedDependencies(name, referencedDependencies);
134
145
  if (isProduction) {
135
- const negatedEntryPatterns = entryFilePatterns.map(negate);
146
+ const negatedEntryPatterns = Array.from(entryFilePatterns).map(negate);
136
147
  {
137
148
  const patterns = worker.getProductionEntryFilePatterns(negatedEntryPatterns);
138
149
  const workspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns });
@@ -140,7 +151,8 @@ export const main = async (unresolvedConfiguration) => {
140
151
  principal.addEntryPaths(workspaceEntryPaths);
141
152
  }
142
153
  {
143
- const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns: productionEntryFilePatterns });
154
+ const patterns = Array.from(productionEntryFilePatterns);
155
+ const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns });
144
156
  debugLogArray(name, `Production plugin entry paths`, pluginWorkspaceEntryPaths);
145
157
  principal.addEntryPaths(pluginWorkspaceEntryPaths, { skipExportsAnalysis: true });
146
158
  }
@@ -265,7 +277,11 @@ export const main = async (unresolvedConfiguration) => {
265
277
  const { specifier, pos, line, col } = unresolvedImport;
266
278
  collector.addIssue({ type: 'unresolved', filePath, symbol: specifier, pos, line, col });
267
279
  });
268
- _getDependenciesFromScripts(scripts, { cwd: dirname(filePath) }).forEach(specifier => {
280
+ _getDependenciesFromScripts(scripts, {
281
+ cwd: dirname(filePath),
282
+ manifestScriptNames: new Set(),
283
+ dependencies: deputy.getDependencies(workspace.name),
284
+ }).forEach(specifier => {
269
285
  handleReferencedDependency({ specifier, containingFilePath: filePath, principal: _principal, workspace });
270
286
  });
271
287
  }
@@ -1,7 +1,13 @@
1
- type Options = {
1
+ import type { Scripts } from '../types/package-json.js';
2
+ type LoadPackageManifestOptions = {
2
3
  dir: string;
3
4
  packageName: string;
4
5
  cwd: string;
5
6
  };
6
- export declare const getPackageManifest: ({ dir, packageName, cwd }: Options) => Promise<any>;
7
+ export declare const loadPackageManifest: ({ dir, packageName, cwd }: LoadPackageManifestOptions) => any;
8
+ type GetFilteredScriptsOptions = {
9
+ isProduction: boolean;
10
+ scripts?: Scripts;
11
+ };
12
+ export declare const getFilteredScripts: ({ isProduction, scripts }: GetFilteredScriptsOptions) => Scripts;
7
13
  export {};
@@ -1,6 +1,6 @@
1
1
  import { join } from '../util/path.js';
2
2
  import { _require } from '../util/require.js';
3
- export const getPackageManifest = async ({ dir, packageName, cwd }) => {
3
+ export const loadPackageManifest = ({ dir, packageName, cwd }) => {
4
4
  try {
5
5
  return _require(join(dir, 'node_modules', packageName, 'package.json'));
6
6
  }
@@ -14,3 +14,16 @@ export const getPackageManifest = async ({ dir, packageName, cwd }) => {
14
14
  }
15
15
  }
16
16
  };
17
+ export const getFilteredScripts = ({ isProduction, scripts }) => {
18
+ if (!scripts)
19
+ return {};
20
+ if (!isProduction)
21
+ return scripts;
22
+ const scriptFilter = new Set(['start', 'postinstall']);
23
+ const filteredScripts = {};
24
+ for (let scriptName in scripts) {
25
+ if (scriptFilter.has(scriptName))
26
+ filteredScripts[scriptName] = scripts[scriptName];
27
+ }
28
+ return filteredScripts;
29
+ };
@@ -1,17 +1,12 @@
1
- /// <reference types="npmcli__package-json" />
2
1
  import type { InstalledBinaries, HostDependencies } from '../types/workspace.js';
3
- import type { PackageJson } from '@npmcli/package-json';
4
2
  type Options = {
5
- manifest: PackageJson;
6
- isProduction: boolean;
7
- isStrict: boolean;
3
+ packageNames: string[];
8
4
  dir: string;
9
5
  cwd: string;
10
6
  };
11
- export declare const findDependencies: ({ manifest, isProduction, isStrict, dir, cwd }: Options) => Promise<{
12
- dependencies: string[];
7
+ export declare const getDependencyMetaData: ({ cwd, dir, packageNames }: Options) => {
13
8
  hostDependencies: HostDependencies;
14
9
  installedBinaries: InstalledBinaries;
15
10
  hasTypesIncluded: Set<string>;
16
- }>;
11
+ };
17
12
  export {};
@@ -1,26 +1,12 @@
1
- import { _getDependenciesFromScripts } from '../binaries/index.js';
2
1
  import { isDefinitelyTyped } from '../util/modules.js';
3
2
  import { timerify } from '../util/Performance.js';
4
- import { getPackageManifest } from './helpers.js';
5
- const findManifestDependencies = async ({ manifest, isProduction, isStrict, dir, cwd }) => {
6
- const scriptFilter = isProduction ? ['start', 'postinstall'] : [];
3
+ import { loadPackageManifest } from './helpers.js';
4
+ const _getDependencyMetaData = ({ cwd, dir, packageNames }) => {
7
5
  const hostDependencies = new Map();
8
- const scripts = Object.entries(manifest.scripts ?? {}).reduce((scripts, [scriptName, script]) => {
9
- if (script && (scriptFilter.length === 0 || scriptFilter.includes(scriptName))) {
10
- scripts.push(script);
11
- }
12
- return scripts;
13
- }, []);
14
- const dependencies = _getDependenciesFromScripts(scripts, { cwd: dir, manifest });
15
6
  const installedBinaries = new Map();
16
7
  const hasTypesIncluded = new Set();
17
- const packageNames = [
18
- ...Object.keys(manifest.dependencies ?? {}),
19
- ...(isStrict ? Object.keys(manifest.peerDependencies ?? {}) : []),
20
- ...(isProduction ? [] : Object.keys(manifest.devDependencies ?? {})),
21
- ];
22
8
  for (const packageName of packageNames) {
23
- const manifest = await getPackageManifest({ dir, packageName, cwd });
9
+ const manifest = loadPackageManifest({ cwd, dir, packageName });
24
10
  if (manifest) {
25
11
  const binaryName = packageName.replace(/^@[^/]+\//, '');
26
12
  const binaries = typeof manifest.bin === 'string' ? [binaryName] : Object.keys(manifest.bin ?? {});
@@ -45,10 +31,10 @@ const findManifestDependencies = async ({ manifest, isProduction, isStrict, dir,
45
31
  isPeerOptional: manifest.peerDependenciesMeta?.[packagePeerDependency]?.optional ?? false,
46
32
  };
47
33
  if (hostDependencies.has(packagePeerDependency)) {
48
- hostDependencies.get(packagePeerDependency)?.add(hostDependency);
34
+ hostDependencies.get(packagePeerDependency).push(hostDependency);
49
35
  }
50
36
  else {
51
- hostDependencies.set(packagePeerDependency, new Set([hostDependency]));
37
+ hostDependencies.set(packagePeerDependency, [hostDependency]);
52
38
  }
53
39
  }
54
40
  if (!isDefinitelyTyped(packageName) && (manifest.types || manifest.typings))
@@ -56,10 +42,9 @@ const findManifestDependencies = async ({ manifest, isProduction, isStrict, dir,
56
42
  }
57
43
  }
58
44
  return {
59
- dependencies,
60
45
  hostDependencies,
61
46
  installedBinaries,
62
47
  hasTypesIncluded,
63
48
  };
64
49
  };
65
- export const findDependencies = timerify(findManifestDependencies);
50
+ export const getDependencyMetaData = timerify(_getDependencyMetaData);
@@ -19,7 +19,7 @@ const ENTRY_FILE_PATTERNS = [
19
19
  '!**/test?(s)/**/{helper,fixture}?(s)/**/*',
20
20
  ];
21
21
  const findAvaDependencies = async (configFilePath, options) => {
22
- const { cwd, manifest, isProduction, config } = options;
22
+ const { manifest, isProduction, config } = options;
23
23
  let localConfig = basename(configFilePath) === 'package.json' ? manifest.ava : await load(configFilePath);
24
24
  if (typeof localConfig === 'function')
25
25
  localConfig = localConfig();
@@ -29,11 +29,7 @@ const findAvaDependencies = async (configFilePath, options) => {
29
29
  const nodeArgs = localConfig.nodeArguments ?? [];
30
30
  const requireArgs = (localConfig.require ?? []).map(require => `--require ${require}`);
31
31
  const fakeCommand = `node ${nodeArgs.join(' ')} ${requireArgs.join(' ')}`;
32
- const dependencies = getDependenciesFromScripts([fakeCommand], {
33
- cwd,
34
- manifest,
35
- knownGlobalsOnly: true,
36
- });
32
+ const dependencies = getDependenciesFromScripts([fakeCommand], { ...options, knownGlobalsOnly: true });
37
33
  return [...entryPatterns, ...dependencies];
38
34
  };
39
35
  const findDependencies = timerify(findAvaDependencies);
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_EXTENSIONS } from '../../constants.js';
2
2
  import { isDirectory } from '../../util/fs.js';
3
- import { dirname, isInternal, join } from '../../util/path.js';
3
+ import { dirname, isInNodeModules, join } from '../../util/path.js';
4
4
  import { timerify } from '../../util/Performance.js';
5
5
  import { hasDependency, load } from '../../util/plugin.js';
6
6
  import { toProductionEntryPattern } from '../../util/protocols.js';
@@ -33,11 +33,11 @@ const findEleventyDependencies = async (configFilePath, options) => {
33
33
  if (isDir) {
34
34
  copiedEntries.add(join(path, `**/*.{${exts}}`));
35
35
  }
36
- else if (isInternal(path)) {
37
- copiedEntries.add(path);
36
+ else if (isInNodeModules(path)) {
37
+ copiedPackages.add(path);
38
38
  }
39
39
  else {
40
- copiedPackages.add(path);
40
+ copiedEntries.add(path);
41
41
  }
42
42
  }
43
43
  return [
@@ -1,7 +1,7 @@
1
- import type { PackageJsonWithPlugins } from '../../types/package-json.js';
1
+ import type { PackageJson } from '../../types/package-json.js';
2
2
  type GetDependenciesDeep = (configFilePath: string, options: {
3
3
  cwd: string;
4
- manifest: PackageJsonWithPlugins;
4
+ manifest: PackageJson;
5
5
  }, dependencies?: Set<string>) => Promise<Set<string>>;
6
6
  export declare const getDependenciesDeep: GetDependenciesDeep;
7
7
  export {};
@@ -11,7 +11,7 @@ const ENABLERS = 'This plugin is enabled when a `.yml` or `.yaml` file is found
11
11
  const isEnabled = async ({ cwd }) => Boolean(await _firstGlob({ cwd, patterns: ['.github/workflows/*.{yml,yaml}'] }));
12
12
  const CONFIG_FILE_PATTERNS = ['.github/workflows/*.{yml,yaml}', '.github/**/action.{yml,yaml}'];
13
13
  const findGithubActionsDependencies = async (configFilePath, options) => {
14
- const { cwd, manifest, isProduction } = options;
14
+ const { isProduction } = options;
15
15
  const configFileName = basename(configFilePath);
16
16
  if (isProduction)
17
17
  return [];
@@ -19,22 +19,14 @@ const findGithubActionsDependencies = async (configFilePath, options) => {
19
19
  if (!config)
20
20
  return [];
21
21
  const scripts = getValuesByKeyDeep(config, 'run').filter(isString);
22
- return [
23
- ...getActionDependencies(),
24
- ...getDependenciesFromScripts(scripts, {
25
- cwd,
26
- manifest,
27
- knownGlobalsOnly: true,
28
- }),
29
- ];
30
- function getActionDependencies() {
22
+ const getActionDependencies = () => {
31
23
  const isActionManifest = configFileName === 'action.yml' || configFileName === 'action.yaml';
32
- if (!isActionManifest || !config?.runs?.using?.startsWith('node')) {
24
+ if (!isActionManifest || !config?.runs?.using?.startsWith('node'))
33
25
  return [];
34
- }
35
26
  const scripts = [config.runs.pre, config.runs.main, config.runs.post].filter(isString);
36
27
  return scripts.map(script => join(dirname(configFilePath), script));
37
- }
28
+ };
29
+ return [...getActionDependencies(), ...getDependenciesFromScripts(scripts, { ...options, knownGlobalsOnly: true })];
38
30
  };
39
31
  const findDependencies = timerify(findGithubActionsDependencies);
40
32
  export default {
@@ -8,17 +8,13 @@ const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
8
8
  const gitHookPaths = getGitHookPaths('.husky');
9
9
  const CONFIG_FILE_PATTERNS = [...gitHookPaths];
10
10
  const findHuskyDependencies = async (configFilePath, options) => {
11
- const { cwd, manifest, isProduction } = options;
11
+ const { isProduction } = options;
12
12
  if (isProduction || configFilePath === FAKE_PATH)
13
13
  return [];
14
14
  const script = await loadFile(configFilePath);
15
15
  if (!script)
16
16
  return [];
17
- return getDependenciesFromScripts(String(script), {
18
- cwd,
19
- manifest,
20
- knownGlobalsOnly: true,
21
- });
17
+ return getDependenciesFromScripts(String(script), { ...options, knownGlobalsOnly: true });
22
18
  };
23
19
  const findDependencies = timerify(findHuskyDependencies);
24
20
  export default {
@@ -21,6 +21,7 @@ export { default as lintStaged } from './lint-staged/index.js';
21
21
  export { default as linthtml } from './linthtml/index.js';
22
22
  export { default as markdownlint } from './markdownlint/index.js';
23
23
  export { default as mocha } from './mocha/index.js';
24
+ export { default as netlify } from './netlify/index.js';
24
25
  export { default as next } from './next/index.js';
25
26
  export { default as nodeTestRunner } from './node-test-runner/index.js';
26
27
  export { default as npmPackageJsonLint } from './npm-package-json-lint/index.js';
@@ -21,6 +21,7 @@ export { default as lintStaged } from './lint-staged/index.js';
21
21
  export { default as linthtml } from './linthtml/index.js';
22
22
  export { default as markdownlint } from './markdownlint/index.js';
23
23
  export { default as mocha } from './mocha/index.js';
24
+ export { default as netlify } from './netlify/index.js';
24
25
  export { default as next } from './next/index.js';
25
26
  export { default as nodeTestRunner } from './node-test-runner/index.js';
26
27
  export { default as npmPackageJsonLint } from './npm-package-json-lint/index.js';
@@ -10,7 +10,7 @@ const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
10
10
  const gitHookPaths = getGitHookPaths();
11
11
  const CONFIG_FILE_PATTERNS = ['lefthook.yml', ...gitHookPaths];
12
12
  const findLefthookDependencies = async (configFilePath, options) => {
13
- const { cwd, manifest, isProduction } = options;
13
+ const { manifest, isProduction } = options;
14
14
  if (isProduction)
15
15
  return [];
16
16
  const dependencies = manifest.devDependencies ? Object.keys(manifest.devDependencies) : [];
@@ -20,12 +20,12 @@ const findLefthookDependencies = async (configFilePath, options) => {
20
20
  return [];
21
21
  const scripts = getValuesByKeyDeep(localConfig, 'run').filter((run) => typeof run === 'string');
22
22
  const lefthook = process.env.CI ? ENABLERS.filter(dependency => dependencies.includes(dependency)) : [];
23
- return [...lefthook, ...getDependenciesFromScripts(scripts, { cwd, manifest, knownGlobalsOnly: true })];
23
+ return [...lefthook, ...getDependenciesFromScripts(scripts, { ...options, knownGlobalsOnly: true })];
24
24
  }
25
25
  const script = await loadFile(configFilePath);
26
26
  if (!script)
27
27
  return [];
28
- const scriptDependencies = getDependenciesFromScripts([script], { cwd, manifest, knownGlobalsOnly: false });
28
+ const scriptDependencies = getDependenciesFromScripts([script], options);
29
29
  const matches = scriptDependencies.find(dep => dependencies.includes(fromBinary(dep)));
30
30
  return matches ? [matches] : [];
31
31
  };
@@ -14,7 +14,7 @@ const CONFIG_FILE_PATTERNS = [
14
14
  'package.json',
15
15
  ];
16
16
  const findLintStagedDependencies = async (configFilePath, options) => {
17
- const { cwd, manifest, isProduction } = options;
17
+ const { manifest, isProduction } = options;
18
18
  if (isProduction)
19
19
  return [];
20
20
  let localConfig = basename(configFilePath) === 'package.json' ? manifest['lint-staged'] : await load(configFilePath);
@@ -25,7 +25,6 @@ const findLintStagedDependencies = async (configFilePath, options) => {
25
25
  const dependencies = new Set();
26
26
  for (const entry of Object.values(localConfig).flat()) {
27
27
  const scripts = [typeof entry === 'function' ? await entry([]) : entry].flat();
28
- const options = { cwd, manifest };
29
28
  getDependenciesFromScripts(scripts, options).forEach(identifier => dependencies.add(identifier));
30
29
  }
31
30
  return Array.from(dependencies);
@@ -0,0 +1,2 @@
1
+ import type { FunctionsConfig } from './types.js';
2
+ export declare const extractFunctionsConfigProperty: (config: FunctionsConfig, property: keyof FunctionsConfig) => string[];
@@ -0,0 +1,4 @@
1
+ export const extractFunctionsConfigProperty = (config, property) => [
2
+ ...(config[property] ?? []),
3
+ ...Object.values(config).filter(x => typeof x === 'object' && property in x).flatMap(x => x[property] || []),
4
+ ];
@@ -0,0 +1,10 @@
1
+ import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ declare const _default: {
3
+ NAME: string;
4
+ ENABLERS: (string | RegExp)[];
5
+ isEnabled: IsPluginEnabledCallback;
6
+ CONFIG_FILE_PATTERNS: string[];
7
+ PRODUCTION_ENTRY_FILE_PATTERNS: string[];
8
+ findDependencies: GenericPluginCallback;
9
+ };
10
+ export default _default;
@@ -0,0 +1,38 @@
1
+ import { join } from '../../util/path.js';
2
+ import { timerify } from '../../util/Performance.js';
3
+ import { hasDependency, load } from '../../util/plugin.js';
4
+ import { toProductionEntryPattern } from '../../util/protocols.js';
5
+ import { extractFunctionsConfigProperty } from './helpers.js';
6
+ const NAME = 'Netlify';
7
+ const ENABLERS = [/^@netlify\/plugin-/, 'netlify-cli', '@netlify/functions'];
8
+ const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
9
+ const CONFIG_FILE_PATTERNS = ['netlify.toml'];
10
+ const NETLIFY_FUNCTIONS_DIR = 'netlify/functions';
11
+ const NETLIFY_FUNCTIONS_EXTS = 'js,mjs,cjs,ts,mts,cts';
12
+ const PRODUCTION_ENTRY_FILE_PATTERNS = [`${NETLIFY_FUNCTIONS_DIR}/**/*.{${NETLIFY_FUNCTIONS_EXTS}}`];
13
+ const findPluginDependencies = async (configFilePath, options) => {
14
+ const { config } = options;
15
+ const localConfig = await load(configFilePath);
16
+ if (!localConfig)
17
+ return config.entry
18
+ ? config.entry.map(toProductionEntryPattern)
19
+ : PRODUCTION_ENTRY_FILE_PATTERNS.map(toProductionEntryPattern);
20
+ const dependencies = [
21
+ ...(localConfig?.plugins?.map(plugin => plugin.package) ?? []),
22
+ ...extractFunctionsConfigProperty(localConfig.functions || {}, 'external_node_modules'),
23
+ ];
24
+ const entryFiles = [
25
+ ...extractFunctionsConfigProperty(localConfig.functions || {}, 'included_files'),
26
+ join(localConfig.functions?.directory ?? NETLIFY_FUNCTIONS_DIR, `**/*.{${NETLIFY_FUNCTIONS_EXTS}}`),
27
+ ].filter(file => !file.startsWith('!'));
28
+ return [...dependencies, ...entryFiles.map(toProductionEntryPattern)];
29
+ };
30
+ const findDependencies = timerify(findPluginDependencies);
31
+ export default {
32
+ NAME,
33
+ ENABLERS,
34
+ isEnabled,
35
+ CONFIG_FILE_PATTERNS,
36
+ PRODUCTION_ENTRY_FILE_PATTERNS,
37
+ findDependencies,
38
+ };
@@ -0,0 +1,11 @@
1
+ export type NetlifyConfig = {
2
+ plugins?: {
3
+ package: string;
4
+ }[];
5
+ functions?: FunctionsConfig;
6
+ };
7
+ export type FunctionsConfig = {
8
+ directory?: string;
9
+ external_node_modules?: string[];
10
+ included_files?: string[];
11
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -6,7 +6,7 @@ const ENABLERS = ['nx', /^@nrwl\//, /^@nx\//];
6
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
7
7
  const CONFIG_FILE_PATTERNS = ['project.json', '{apps,libs}/**/project.json'];
8
8
  const findNxDependencies = async (configFilePath, options) => {
9
- const { cwd, manifest, isProduction } = options;
9
+ const { isProduction } = options;
10
10
  if (isProduction)
11
11
  return [];
12
12
  const localConfig = await load(configFilePath);
@@ -20,7 +20,7 @@ const findNxDependencies = async (configFilePath, options) => {
20
20
  const scripts = targets
21
21
  .filter(target => target.executor === 'nx:run-commands')
22
22
  .flatMap(target => target.options?.commands ?? (target.options?.command ? [target.options.command] : []));
23
- const dependencies = getDependenciesFromScripts(scripts, { cwd, manifest });
23
+ const dependencies = getDependenciesFromScripts(scripts, options);
24
24
  return compact([...executors, ...dependencies]);
25
25
  };
26
26
  const findDependencies = timerify(findNxDependencies);
@@ -7,7 +7,7 @@ const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
7
7
  const PACKAGE_JSON_PATH = 'release-it';
8
8
  const CONFIG_FILE_PATTERNS = ['.release-it.json', '.release-it.{js,cjs}', '.release-it.{yml,yaml}', 'package.json'];
9
9
  const findReleaseItDependencies = async (configFilePath, options) => {
10
- const { cwd, manifest, isProduction } = options;
10
+ const { manifest, isProduction } = options;
11
11
  if (isProduction)
12
12
  return [];
13
13
  const localConfig = basename(configFilePath) === 'package.json' ? manifest[PACKAGE_JSON_PATH] : await load(configFilePath);
@@ -21,7 +21,7 @@ const findReleaseItDependencies = async (configFilePath, options) => {
21
21
  if (typeof localConfig.gitlab?.releaseNotes === 'string') {
22
22
  scripts.push(localConfig.gitlab.releaseNotes);
23
23
  }
24
- const dependencies = getDependenciesFromScripts(scripts, { cwd, manifest });
24
+ const dependencies = getDependenciesFromScripts(scripts, options);
25
25
  return [...plugins, ...dependencies];
26
26
  };
27
27
  const findDependencies = timerify(findReleaseItDependencies);
@@ -16,12 +16,12 @@ const resolveEntry = (containingFilePath, specifier) => {
16
16
  return toEntryPattern(relative(dir, resolvedPath));
17
17
  return specifier;
18
18
  };
19
- const enablesCoverageInScript = /vitest(.+)--coverage(?:\.enabled(?:=true)?)?/;
20
- const hasScriptWithCoverage = (scripts) => {
21
- return Object.values(scripts).some(script => {
22
- return enablesCoverageInScript.test(script);
23
- });
24
- };
19
+ const isVitestCoverageCommand = /vitest(.+)--coverage(?:\.enabled(?:=true)?)?/;
20
+ const hasScriptWithCoverage = (scripts) => scripts
21
+ ? Object.values(scripts).some(script => {
22
+ return isVitestCoverageCommand.test(script);
23
+ })
24
+ : false;
25
25
  const findConfigDependencies = (configFilePath, localConfig, options) => {
26
26
  const { isProduction, config, manifest } = options;
27
27
  const testConfig = localConfig.test;
@@ -30,8 +30,7 @@ const findConfigDependencies = (configFilePath, localConfig, options) => {
30
30
  return entryPatterns;
31
31
  const environments = testConfig.environment ? [getEnvPackageName(testConfig.environment)] : [];
32
32
  const reporters = getExternalReporters(testConfig.reporters);
33
- const hasCoverageEnabled = (testConfig.coverage && testConfig.coverage.enabled !== false) ||
34
- (manifest.scripts !== undefined && hasScriptWithCoverage(manifest.scripts));
33
+ const hasCoverageEnabled = (testConfig.coverage && testConfig.coverage.enabled !== false) || hasScriptWithCoverage(manifest.scripts);
35
34
  const coverage = hasCoverageEnabled ? [`@vitest/coverage-${testConfig.coverage?.provider ?? 'v8'}`] : [];
36
35
  const setupFiles = [testConfig.setupFiles ?? []].flat().map(v => resolveEntry(configFilePath, v));
37
36
  const globalSetup = [testConfig.globalSetup ?? []].flat().map(v => resolveEntry(configFilePath, v));
@@ -6,14 +6,14 @@ const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
6
6
  const PACKAGE_JSON_PATH = 'wireit';
7
7
  const CONFIG_FILE_PATTERNS = ['package.json'];
8
8
  const findWireItDependencies = async (_configFilePath, options) => {
9
- const { cwd, manifest, isProduction } = options;
9
+ const { manifest, isProduction } = options;
10
10
  if (isProduction)
11
11
  return [];
12
12
  const localConfig = manifest[PACKAGE_JSON_PATH];
13
13
  if (!localConfig)
14
14
  return [];
15
15
  const scripts = Object.values(localConfig).flatMap(({ command: script }) => (script ? [script] : []));
16
- const scriptDependencies = getDependenciesFromScripts(scripts, { cwd, manifest });
16
+ const scriptDependencies = getDependenciesFromScripts(scripts, options);
17
17
  return scriptDependencies;
18
18
  };
19
19
  const findDependencies = timerify(findWireItDependencies);
@@ -21,8 +21,6 @@ interface BaseWorkspaceConfiguration {
21
21
  project: NormalizedGlob;
22
22
  paths: Record<string, string[]>;
23
23
  ignore: NormalizedGlob;
24
- ignoreBinaries: IgnorePatterns;
25
- ignoreDependencies: IgnorePatterns;
26
24
  isIncludeEntryExports: boolean;
27
25
  }
28
26
  export interface WorkspaceConfiguration extends BaseWorkspaceConfiguration, Partial<PluginsConfiguration> {
@@ -20,7 +20,8 @@ type PluginKeys = {
20
20
  [K in keyof PluginMap]: ExtractKeys<PluginMap[K], K>;
21
21
  };
22
22
  type Plugins = MergeUnion<PluginKeys[keyof PluginMap]>;
23
- export type PackageJsonWithPlugins = {
23
+ export type Scripts = Record<string, string>;
24
+ export type PackageJson = {
24
25
  name?: string;
25
26
  main?: string;
26
27
  bin?: string | Record<string, string>;
@@ -29,7 +30,7 @@ export type PackageJsonWithPlugins = {
29
30
  packages?: string[];
30
31
  };
31
32
  exports?: Exports;
32
- scripts?: Record<string, string>;
33
+ scripts?: Scripts;
33
34
  dependencies?: Dependency;
34
35
  devDependencies?: Dependency;
35
36
  peerDependencies?: Dependency;
@@ -1,19 +1,24 @@
1
1
  import type { EnsuredPluginConfiguration, WorkspaceConfiguration } from './config.js';
2
- import type { PackageJsonWithPlugins } from './package-json.js';
2
+ import type { PackageJson } from './package-json.js';
3
+ import type { DependencySet } from './workspace.js';
4
+ export interface BaseOptions {
5
+ cwd: string;
6
+ manifestScriptNames: Set<string>;
7
+ dependencies: DependencySet;
8
+ }
3
9
  type IsPluginEnabledCallbackOptions = {
4
10
  cwd: string;
5
- manifest: PackageJsonWithPlugins;
11
+ manifest: PackageJson;
6
12
  dependencies: Set<string>;
7
13
  config: WorkspaceConfiguration;
8
14
  };
9
15
  export type IsPluginEnabledCallback = (options: IsPluginEnabledCallbackOptions) => boolean | Promise<boolean>;
10
- export type GenericPluginCallbackOptions = {
11
- cwd: string;
12
- manifest: PackageJsonWithPlugins;
16
+ export interface GenericPluginCallbackOptions extends BaseOptions {
17
+ manifest: PackageJson;
13
18
  config: EnsuredPluginConfiguration;
14
19
  isProduction: boolean;
15
20
  enabledPlugins: string[];
16
- };
21
+ }
17
22
  export type GenericPluginCallback = (configFilePath: string, options: GenericPluginCallbackOptions) => Promise<string[]> | string[];
18
23
  export interface Plugin {
19
24
  NAME: string;