knip 5.59.1 → 5.60.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 (41) hide show
  1. package/dist/ConfigurationChief.d.ts +6 -0
  2. package/dist/ConfigurationChief.js +31 -3
  3. package/dist/DependencyDeputy.d.ts +4 -4
  4. package/dist/DependencyDeputy.js +22 -25
  5. package/dist/WorkspaceWorker.d.ts +3 -1
  6. package/dist/WorkspaceWorker.js +33 -0
  7. package/dist/cli.js +2 -1
  8. package/dist/graph/analyze.js +3 -3
  9. package/dist/graph/build.js +17 -11
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +3 -0
  12. package/dist/plugins/eleventy/helpers.d.ts +8 -0
  13. package/dist/plugins/eleventy/helpers.js +8 -0
  14. package/dist/plugins/eleventy/index.js +1 -1
  15. package/dist/plugins/index.d.ts +1 -0
  16. package/dist/plugins/node/index.d.ts +1 -0
  17. package/dist/plugins/node/index.js +1 -0
  18. package/dist/plugins/storybook/index.js +3 -3
  19. package/dist/reporters/codeclimate.js +1 -1
  20. package/dist/reporters/codeowners.js +1 -1
  21. package/dist/reporters/compact.js +1 -1
  22. package/dist/reporters/disclosure.js +1 -1
  23. package/dist/reporters/index.d.ts +1 -1
  24. package/dist/reporters/json.js +1 -1
  25. package/dist/reporters/markdown.js +1 -1
  26. package/dist/reporters/symbols.d.ts +1 -1
  27. package/dist/reporters/symbols.js +5 -23
  28. package/dist/reporters/util/configuration-hints.d.ts +2 -0
  29. package/dist/reporters/util/configuration-hints.js +62 -0
  30. package/dist/reporters/{util.d.ts → util/util.d.ts} +5 -3
  31. package/dist/reporters/{util.js → util/util.js} +7 -6
  32. package/dist/reporters/watch.js +1 -1
  33. package/dist/types/issues.d.ts +5 -1
  34. package/dist/types/workspace.d.ts +3 -3
  35. package/dist/util/regex.d.ts +1 -1
  36. package/dist/util/regex.js +1 -1
  37. package/dist/util/string.d.ts +1 -0
  38. package/dist/util/string.js +1 -1
  39. package/dist/version.d.ts +1 -1
  40. package/dist/version.js +1 -1
  41. package/package.json +10 -10
@@ -1,7 +1,11 @@
1
+ import type { z } from 'zod';
2
+ import { knipConfigurationSchema } from './schema/configuration.js';
1
3
  import type { Configuration, IgnorePatterns, WorkspaceConfiguration } from './types/config.js';
4
+ import type { ConfigurationHints } from './types/issues.js';
2
5
  import type { PackageJson, WorkspacePackage } from './types/package-json.js';
3
6
  import { type WorkspaceGraph } from './util/create-workspace-graph.js';
4
7
  import { type CLIArguments } from './util/get-included-issue-types.js';
8
+ export declare const isDefaultPattern: (type: "entry" | "project", id: string) => boolean;
5
9
  type ConfigurationManagerOptions = {
6
10
  cwd: string;
7
11
  isProduction: boolean;
@@ -42,8 +46,10 @@ export declare class ConfigurationChief {
42
46
  includedWorkspaces: Workspace[];
43
47
  resolvedConfigFilePath?: string;
44
48
  rawConfig?: any;
49
+ parsedConfig?: z.infer<typeof knipConfigurationSchema>;
45
50
  constructor({ cwd, isProduction, isStrict, isIncludeEntryExports, workspace }: ConfigurationManagerOptions);
46
51
  init(): Promise<void>;
52
+ getConfigurationHints(): ConfigurationHints;
47
53
  private loadResolvedConfigurationFile;
48
54
  getRules(): import("./types/issues.js").Rules;
49
55
  getFilters(): {
@@ -19,14 +19,22 @@ import { getKeysByValue } from './util/object.js';
19
19
  import { join, relative } from './util/path.js';
20
20
  import { normalizePluginConfig } from './util/plugin.js';
21
21
  import { toRegexOrString } from './util/regex.js';
22
+ import { ELLIPSIS } from './util/string.js';
22
23
  import { splitTags } from './util/tag.js';
23
24
  import { unwrapFunction } from './util/unwrap-function.js';
24
25
  import { byPathDepth } from './util/workspace.js';
25
26
  const { config: rawConfigArg } = parsedArgValues;
27
+ const defaultBaseFilenamePattern = '{index,cli,main}';
28
+ export const isDefaultPattern = (type, id) => {
29
+ if (type === 'project')
30
+ return id.startsWith('**/*.{js,mjs,cjs,jsx,ts,tsx,mts,cts');
31
+ return (id.startsWith('{index,cli,main}.{js,mjs,cjs,jsx,ts,tsx,mts,cts') ||
32
+ id.startsWith('src/{index,cli,main}.{js,mjs,cjs,jsx,ts,tsx,mts,cts'));
33
+ };
26
34
  const getDefaultWorkspaceConfig = (extensions = []) => {
27
35
  const exts = [...DEFAULT_EXTENSIONS, ...extensions].map(ext => ext.slice(1)).join(',');
28
36
  return {
29
- entry: [`{index,cli,main}.{${exts}}!`, `src/{index,cli,main}.{${exts}}!`],
37
+ entry: [`${defaultBaseFilenamePattern}.{${exts}}!`, `src/${defaultBaseFilenamePattern}.{${exts}}!`],
30
38
  project: [`**/*.{${exts}}!`],
31
39
  };
32
40
  };
@@ -69,6 +77,7 @@ export class ConfigurationChief {
69
77
  includedWorkspaces = [];
70
78
  resolvedConfigFilePath;
71
79
  rawConfig;
80
+ parsedConfig;
72
81
  constructor({ cwd, isProduction, isStrict, isIncludeEntryExports, workspace }) {
73
82
  this.cwd = cwd;
74
83
  this.isProduction = isProduction;
@@ -101,10 +110,29 @@ export class ConfigurationChief {
101
110
  this.rawConfig = this.resolvedConfigFilePath
102
111
  ? await this.loadResolvedConfigurationFile(this.resolvedConfigFilePath)
103
112
  : manifest.knip;
104
- const parsedConfig = this.rawConfig ? knipConfigurationSchema.parse(partitionCompilers(this.rawConfig)) : {};
105
- this.config = this.normalize(parsedConfig);
113
+ this.parsedConfig = this.rawConfig ? knipConfigurationSchema.parse(partitionCompilers(this.rawConfig)) : {};
114
+ this.config = this.normalize(this.parsedConfig);
106
115
  await this.setWorkspaces();
107
116
  }
117
+ getConfigurationHints() {
118
+ const hints = new Set();
119
+ const config = this.parsedConfig;
120
+ if (config) {
121
+ if (this.workspacePackages.size > 1) {
122
+ const entry = arrayify(config.entry);
123
+ if (entry.length > 0) {
124
+ const identifier = `[${entry[0]}${entry.length > 1 ? `, ${ELLIPSIS}` : ''}]`;
125
+ hints.add({ type: 'entry-top-level', identifier });
126
+ }
127
+ const project = arrayify(config.project);
128
+ if (project.length > 0) {
129
+ const identifier = `[${project[0]}${project.length > 1 ? `, ${ELLIPSIS}` : ''}]`;
130
+ hints.add({ type: 'project-top-level', identifier });
131
+ }
132
+ }
133
+ }
134
+ return hints;
135
+ }
108
136
  async loadResolvedConfigurationFile(configPath) {
109
137
  const loadedValue = await _load(configPath);
110
138
  try {
@@ -16,7 +16,7 @@ export declare class DependencyDeputy {
16
16
  installedBinaries: Map<string, InstalledBinaries>;
17
17
  hasTypesIncluded: Map<string, Set<string>>;
18
18
  constructor({ isProduction, isStrict }: Options);
19
- addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ignoreDependencies, ignoreBinaries, ignoreUnresolved, }: {
19
+ addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ignoreDependencies: id, ignoreBinaries: ib, ignoreUnresolved: iu, }: {
20
20
  name: string;
21
21
  cwd: string;
22
22
  dir: string;
@@ -39,9 +39,9 @@ export declare class DependencyDeputy {
39
39
  ignoreDependencies: (string | RegExp)[];
40
40
  ignoreBinaries: (string | RegExp)[];
41
41
  ignoreUnresolved: (string | RegExp)[];
42
- usedIgnoreDependencies: Set<string | RegExp>;
43
- usedIgnoreBinaries: Set<string | RegExp>;
44
- usedIgnoreUnresolved: Set<string | RegExp>;
42
+ unusedIgnoreDependencies: Set<string | RegExp>;
43
+ unusedIgnoreBinaries: Set<string | RegExp>;
44
+ unusedIgnoreUnresolved: Set<string | RegExp>;
45
45
  } | undefined;
46
46
  getProductionDependencies(workspaceName: string): DependencyArray;
47
47
  getDevDependencies(workspaceName: string): DependencyArray;
@@ -22,7 +22,7 @@ export class DependencyDeputy {
22
22
  this.installedBinaries = new Map();
23
23
  this.hasTypesIncluded = new Map();
24
24
  }
25
- addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ignoreDependencies, ignoreBinaries, ignoreUnresolved, }) {
25
+ addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ignoreDependencies: id, ignoreBinaries: ib, ignoreUnresolved: iu, }) {
26
26
  const dependencies = Object.keys(manifest.dependencies ?? {});
27
27
  const peerDependencies = Object.keys(manifest.peerDependencies ?? {});
28
28
  const optionalDependencies = Object.keys(manifest.optionalDependencies ?? {});
@@ -46,16 +46,19 @@ export class DependencyDeputy {
46
46
  this.setHostDependencies(name, hostDependencies);
47
47
  this.setInstalledBinaries(name, installedBinaries);
48
48
  this.setHasTypesIncluded(name, hasTypesIncluded);
49
+ const ignoreDependencies = id.map(toRegexOrString);
50
+ const ignoreBinaries = ib.map(toRegexOrString);
51
+ const ignoreUnresolved = iu.map(toRegexOrString);
49
52
  this._manifests.set(name, {
50
53
  workspaceDir: dir,
51
54
  manifestPath,
52
55
  manifestStr,
53
- ignoreDependencies: ignoreDependencies.map(toRegexOrString),
54
- ignoreBinaries: ignoreBinaries.map(toRegexOrString),
55
- ignoreUnresolved: ignoreUnresolved.map(toRegexOrString),
56
- usedIgnoreDependencies: new Set(),
57
- usedIgnoreBinaries: new Set(),
58
- usedIgnoreUnresolved: new Set(),
56
+ ignoreDependencies,
57
+ ignoreBinaries,
58
+ ignoreUnresolved,
59
+ unusedIgnoreDependencies: new Set(ignoreDependencies),
60
+ unusedIgnoreBinaries: new Set(ignoreBinaries),
61
+ unusedIgnoreUnresolved: new Set(ignoreUnresolved),
59
62
  dependencies,
60
63
  devDependencies,
61
64
  peerDependencies: new Set(peerDependencies),
@@ -241,7 +244,7 @@ export class DependencyDeputy {
241
244
  if (ignoreItem) {
242
245
  delete issueSet[issueKey];
243
246
  counters[type]--;
244
- manifest.usedIgnoreDependencies.add(ignoreItem);
247
+ manifest.unusedIgnoreDependencies.delete(ignoreItem);
245
248
  }
246
249
  else if (issue.workspace !== ROOT_WORKSPACE_NAME) {
247
250
  const manifest = this.getWorkspaceManifest(ROOT_WORKSPACE_NAME);
@@ -250,7 +253,7 @@ export class DependencyDeputy {
250
253
  if (ignoreItem) {
251
254
  delete issueSet[issueKey];
252
255
  counters[type]--;
253
- manifest.usedIgnoreDependencies.add(ignoreItem);
256
+ manifest.unusedIgnoreDependencies.delete(ignoreItem);
254
257
  }
255
258
  }
256
259
  }
@@ -275,7 +278,7 @@ export class DependencyDeputy {
275
278
  if (ignoreItem) {
276
279
  delete issueSet[issueKey];
277
280
  counters[type]--;
278
- manifest.usedIgnoreBinaries.add(ignoreItem);
281
+ manifest.unusedIgnoreBinaries.delete(ignoreItem);
279
282
  }
280
283
  else {
281
284
  const manifest = this.getWorkspaceManifest(ROOT_WORKSPACE_NAME);
@@ -284,7 +287,7 @@ export class DependencyDeputy {
284
287
  if (ignoreItem) {
285
288
  delete issueSet[issueKey];
286
289
  counters[type]--;
287
- manifest.usedIgnoreBinaries.add(ignoreItem);
290
+ manifest.unusedIgnoreBinaries.delete(ignoreItem);
288
291
  }
289
292
  }
290
293
  }
@@ -303,7 +306,7 @@ export class DependencyDeputy {
303
306
  if (ignoreItem) {
304
307
  delete issueSet[issueKey];
305
308
  counters.unresolved--;
306
- manifest.usedIgnoreUnresolved.add(ignoreItem);
309
+ manifest.unusedIgnoreUnresolved.delete(ignoreItem);
307
310
  }
308
311
  else {
309
312
  const manifest = this.getWorkspaceManifest(ROOT_WORKSPACE_NAME);
@@ -312,7 +315,7 @@ export class DependencyDeputy {
312
315
  if (ignoreItem) {
313
316
  delete issueSet[issueKey];
314
317
  counters.unresolved--;
315
- manifest.usedIgnoreUnresolved.add(ignoreItem);
318
+ manifest.unusedIgnoreUnresolved.delete(ignoreItem);
316
319
  }
317
320
  }
318
321
  }
@@ -332,20 +335,14 @@ export class DependencyDeputy {
332
335
  getConfigurationHints() {
333
336
  const configurationHints = new Set();
334
337
  for (const [workspaceName, manifest] of this._manifests.entries()) {
335
- for (const identifier of manifest.ignoreDependencies) {
336
- if (!manifest.usedIgnoreDependencies.has(identifier)) {
337
- configurationHints.add({ workspaceName, identifier, type: 'ignoreDependencies' });
338
- }
338
+ for (const identifier of manifest.unusedIgnoreDependencies) {
339
+ configurationHints.add({ workspaceName, identifier, type: 'ignoreDependencies' });
339
340
  }
340
- for (const identifier of manifest.ignoreBinaries) {
341
- if (!manifest.usedIgnoreBinaries.has(identifier)) {
342
- configurationHints.add({ workspaceName, identifier, type: 'ignoreBinaries' });
343
- }
341
+ for (const identifier of manifest.unusedIgnoreBinaries) {
342
+ configurationHints.add({ workspaceName, identifier, type: 'ignoreBinaries' });
344
343
  }
345
- for (const identifier of manifest.ignoreUnresolved) {
346
- if (!manifest.usedIgnoreUnresolved.has(identifier)) {
347
- configurationHints.add({ workspaceName, identifier, type: 'ignoreUnresolved' });
348
- }
344
+ for (const identifier of manifest.unusedIgnoreUnresolved) {
345
+ configurationHints.add({ workspaceName, identifier, type: 'ignoreUnresolved' });
349
346
  }
350
347
  }
351
348
  return configurationHints;
@@ -1,7 +1,8 @@
1
1
  import { CacheConsultant } from './CacheConsultant.js';
2
- import type { Workspace } from './ConfigurationChief.js';
2
+ import { type Workspace } from './ConfigurationChief.js';
3
3
  import type { PluginName } from './types/PluginNames.js';
4
4
  import type { Configuration, GetReferencedInternalFilePath, GetSourceFile, WorkspaceConfiguration } from './types/config.js';
5
+ import type { ConfigurationHints } from './types/issues.js';
5
6
  import type { PackageJson } from './types/package-json.js';
6
7
  import type { DependencySet } from './types/workspace.js';
7
8
  import { type Input } from './util/input.js';
@@ -63,6 +64,7 @@ export declare class WorkspaceWorker {
63
64
  private getConfigurationFilePatterns;
64
65
  getIgnorePatterns(): string[];
65
66
  runPlugins(): Promise<Input[]>;
67
+ getConfigurationHints(type: 'entry' | 'project', patterns: string[], filePaths: string[], includedPaths: Set<string>): ConfigurationHints;
66
68
  onDispose(): void;
67
69
  }
68
70
  export {};
@@ -1,8 +1,11 @@
1
+ import picomatch from 'picomatch';
1
2
  import { CacheConsultant } from './CacheConsultant.js';
3
+ import { isDefaultPattern } from './ConfigurationChief.js';
2
4
  import { _getInputsFromScripts } from './binaries/index.js';
3
5
  import { ROOT_WORKSPACE_NAME } from './constants.js';
4
6
  import { getFilteredScripts } from './manifest/helpers.js';
5
7
  import { PluginEntries, Plugins } from './plugins.js';
8
+ import { timerify } from './util/Performance.js';
6
9
  import { compact } from './util/array.js';
7
10
  import { debugLogArray, debugLogObject } from './util/debug.js';
8
11
  import { _glob, hasNoProductionSuffix, hasProductionSuffix, negate, prependDirToPattern } from './util/glob.js';
@@ -10,6 +13,7 @@ import { isConfig, toConfig, toDebugString, toEntry, toProductionEntry, } from '
10
13
  import { getKeysByValue } from './util/object.js';
11
14
  import { basename, dirname, join } from './util/path.js';
12
15
  import { loadConfigForPlugin } from './util/plugin.js';
16
+ import { ELLIPSIS } from './util/string.js';
13
17
  const nullConfig = { config: null, entry: null, project: null };
14
18
  const initEnabledPluginsMap = () => Object.keys(Plugins).reduce((enabled, pluginName) => ({ ...enabled, [pluginName]: false }), {});
15
19
  export class WorkspaceWorker {
@@ -50,6 +54,7 @@ export class WorkspaceWorker {
50
54
  this.findWorkspaceByFilePath = findWorkspaceByFilePath;
51
55
  this.getSourceFile = getSourceFile;
52
56
  this.cache = new CacheConsultant({ name: `plugins-${name}`, isEnabled: isCache, cacheLocation, isProduction });
57
+ this.getConfigurationHints = timerify(this.getConfigurationHints.bind(this), 'worker.getConfigurationHints');
53
58
  }
54
59
  async init() {
55
60
  this.enabledPlugins = await this.determineEnabledPlugins();
@@ -337,6 +342,34 @@ export class WorkspaceWorker {
337
342
  debugLogArray(wsName, 'Plugin dependencies', () => compact(inputs.map(toDebugString)));
338
343
  return inputs;
339
344
  }
345
+ getConfigurationHints(type, patterns, filePaths, includedPaths) {
346
+ const hints = new Set();
347
+ const entries = this.config[type].filter(pattern => !pattern.startsWith('!'));
348
+ const workspaceName = this.name;
349
+ const userDefinedPatterns = entries.filter(id => !isDefaultPattern(type, id));
350
+ if (userDefinedPatterns.length === 0)
351
+ return hints;
352
+ if (filePaths.length === 0) {
353
+ const identifier = `[${entries[0]}${entries.length > 1 ? `, ${ELLIPSIS}` : ''}]`;
354
+ hints.add({ type: `${type}-empty`, identifier, workspaceName });
355
+ return hints;
356
+ }
357
+ for (const pattern of patterns) {
358
+ if (pattern.startsWith('!'))
359
+ continue;
360
+ const filePathOrPattern = join(this.dir, pattern.replace(/!$/, ''));
361
+ if (includedPaths.has(filePathOrPattern)) {
362
+ hints.add({ type: `${type}-redundant`, identifier: pattern, workspaceName });
363
+ }
364
+ else {
365
+ const matcher = picomatch(filePathOrPattern);
366
+ if (!filePaths.some(filePath => matcher(filePath))) {
367
+ hints.add({ type: `${type}-empty`, identifier: pattern, workspaceName });
368
+ }
369
+ }
370
+ }
371
+ return hints;
372
+ }
340
373
  onDispose() {
341
374
  this.cache.reconcile();
342
375
  }
package/dist/cli.js CHANGED
@@ -23,7 +23,7 @@ const isShowProgress = isNoProgress === false && process.stdout.isTTY && typeof
23
23
  const workspace = rawWorkspaceArg ? toPosix(rawWorkspaceArg).replace(/^\.\//, '').replace(/\/$/, '') : undefined;
24
24
  const run = async () => {
25
25
  try {
26
- const { report, issues, counters, rules, tagHints, configurationHints, isTreatConfigHintsAsErrors } = await main({
26
+ const { report, issues, counters, rules, tagHints, configurationHints, isTreatConfigHintsAsErrors, includedWorkspaces, } = await main({
27
27
  cacheLocation,
28
28
  cwd,
29
29
  excludedIssueTypes,
@@ -65,6 +65,7 @@ const run = async () => {
65
65
  isShowProgress,
66
66
  options: reporterOptions,
67
67
  preprocessorOptions,
68
+ includedWorkspaces,
68
69
  };
69
70
  const finalData = await runPreprocessors(preprocessor, initialData);
70
71
  await runReporters(reporter, finalData);
@@ -45,7 +45,7 @@ export const analyze = async (options) => {
45
45
  const { isReferenced, reExportingEntryFile, traceNode } = isIdentifierReferenced(filePath, identifier, isIncludeEntryExports);
46
46
  if ((isReferenced || exportedItem.refs[1]) && isIgnored) {
47
47
  for (const tagName of exportedItem.jsDocTags) {
48
- if (tags[1].includes(tagName.replace(/^\@/, ''))) {
48
+ if (tags[1].includes(tagName.replace(/^@/, ''))) {
49
49
  collector.addTagHint({ type: 'tag', filePath, identifier, tagName });
50
50
  }
51
51
  }
@@ -96,7 +96,7 @@ export const analyze = async (options) => {
96
96
  }
97
97
  else if (isIgnored) {
98
98
  for (const tagName of exportedItem.jsDocTags) {
99
- if (tags[1].includes(tagName.replace(/^\@/, ''))) {
99
+ if (tags[1].includes(tagName.replace(/^@/, ''))) {
100
100
  collector.addTagHint({ type: 'tag', filePath, identifier: id, tagName });
101
101
  }
102
102
  }
@@ -110,7 +110,7 @@ export const analyze = async (options) => {
110
110
  if (shouldIgnoreTags(member.jsDocTags)) {
111
111
  const identifier = `${exportedItem.identifier}.${member.identifier}`;
112
112
  for (const tagName of exportedItem.jsDocTags) {
113
- if (tags[1].includes(tagName.replace(/^\@/, ''))) {
113
+ if (tags[1].includes(tagName.replace(/^@/, ''))) {
114
114
  collector.addTagHint({ type: 'tag', filePath, identifier, tagName });
115
115
  }
116
116
  }
@@ -179,12 +179,6 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
179
179
  }
180
180
  }
181
181
  else {
182
- {
183
- const label = 'entry paths';
184
- const patterns = worker.getEntryFilePatterns();
185
- const workspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, gitignore: false, label });
186
- principal.addEntryPaths(workspaceEntryPaths);
187
- }
188
182
  {
189
183
  const label = 'entry paths from plugins (skip exports analysis)';
190
184
  const patterns = worker.getPluginEntryFilePatterns([
@@ -201,11 +195,13 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
201
195
  principal.addEntryPaths(pluginWorkspaceEntryPaths);
202
196
  }
203
197
  {
204
- const label = 'project paths';
205
- const patterns = worker.getProjectFilePatterns([...productionPatternsSkipExports, ...projectFilePatterns]);
206
- const workspaceProjectPaths = await _glob({ ...sharedGlobOptions, patterns, label });
207
- for (const projectPath of workspaceProjectPaths)
208
- principal.addProjectPath(projectPath);
198
+ const label = 'entry paths';
199
+ const patterns = worker.getEntryFilePatterns();
200
+ const entryPaths = await _glob({ ...sharedGlobOptions, patterns, gitignore: false, label });
201
+ const hints = worker.getConfigurationHints('entry', patterns, entryPaths, principal.entryPaths);
202
+ for (const hint of hints)
203
+ collector.addConfigurationHint(hint);
204
+ principal.addEntryPaths(entryPaths);
209
205
  }
210
206
  {
211
207
  const label = 'project paths from plugins';
@@ -220,6 +216,16 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
220
216
  const configurationEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
221
217
  principal.addEntryPaths(configurationEntryPaths, { skipExportsAnalysis: true });
222
218
  }
219
+ {
220
+ const label = 'project paths';
221
+ const patterns = worker.getProjectFilePatterns([...productionPatternsSkipExports, ...projectFilePatterns]);
222
+ const projectPaths = await _glob({ ...sharedGlobOptions, patterns, label });
223
+ const hints = worker.getConfigurationHints('project', config.project, projectPaths, principal.projectPaths);
224
+ for (const hint of hints)
225
+ collector.addConfigurationHint(hint);
226
+ for (const projectPath of projectPaths)
227
+ principal.addProjectPath(projectPath);
228
+ }
223
229
  }
224
230
  if (chief.resolvedConfigFilePath) {
225
231
  principal.addEntryPath(chief.resolvedConfigFilePath, { skipExportsAnalysis: true });
package/dist/index.d.ts CHANGED
@@ -9,4 +9,5 @@ export declare const main: (unresolvedConfiguration: CommandLineOptions) => Prom
9
9
  tagHints: Set<import("./types/issues.js").TagHint>;
10
10
  configurationHints: Set<import("./types/issues.js").ConfigurationHint>;
11
11
  isTreatConfigHintsAsErrors: boolean;
12
+ includedWorkspaces: import("./ConfigurationChief.js").Workspace[];
12
13
  }>;
package/dist/index.js CHANGED
@@ -81,6 +81,8 @@ export const main = async (unresolvedConfiguration) => {
81
81
  unreferencedFiles,
82
82
  });
83
83
  const { issues, counters, tagHints, configurationHints } = collector.getIssues();
84
+ for (const hint of chief.getConfigurationHints())
85
+ collector.addConfigurationHint(hint);
84
86
  if (isWatch) {
85
87
  const isIgnored = (filePath) => filePath.startsWith(cacheLocation) || filePath.includes('/.git/') || isGitIgnored(filePath);
86
88
  const watchHandler = await getWatchHandler({
@@ -122,5 +124,6 @@ export const main = async (unresolvedConfiguration) => {
122
124
  tagHints,
123
125
  configurationHints,
124
126
  isTreatConfigHintsAsErrors: chief.config.isTreatConfigHintsAsErrors,
127
+ includedWorkspaces: chief.includedWorkspaces,
125
128
  };
126
129
  };
@@ -74,6 +74,14 @@ export declare class DummyEleventyConfig {
74
74
  setDataFileSuffixes(): void;
75
75
  setDataFileBaseName(): void;
76
76
  getMergingConfigObject(): void;
77
+ isVirtualTemplate(): void;
78
+ setInputDirectory(): void;
79
+ setOutputDirectory(): void;
80
+ setDataDirectory(): void;
81
+ setIncludesDirectory(): void;
82
+ setLayoutsDirectory(): void;
83
+ setFreezeReservedData(): void;
84
+ addDateParsing(): void;
77
85
  _uniqueId: {};
78
86
  events: {};
79
87
  benchmarkManager: {};
@@ -83,6 +83,14 @@ export class DummyEleventyConfig {
83
83
  setDataFileSuffixes() { }
84
84
  setDataFileBaseName() { }
85
85
  getMergingConfigObject() { }
86
+ isVirtualTemplate() { }
87
+ setInputDirectory() { }
88
+ setOutputDirectory() { }
89
+ setDataDirectory() { }
90
+ setIncludesDirectory() { }
91
+ setLayoutsDirectory() { }
92
+ setFreezeReservedData() { }
93
+ addDateParsing() { }
86
94
  _uniqueId = {};
87
95
  events = {};
88
96
  benchmarkManager = {};
@@ -16,7 +16,7 @@ const resolveConfig = async (localConfig, options) => {
16
16
  localConfig = (await localConfig(dummyUserConfig));
17
17
  const inputDir = localConfig?.dir?.input || defaultEleventyConfig.dir.input;
18
18
  const dataDir = localConfig?.dir?.data || defaultEleventyConfig.dir.data;
19
- const templateFormats = localConfig.templateFormats || defaultEleventyConfig.templateFormats;
19
+ const templateFormats = localConfig?.templateFormats || defaultEleventyConfig.templateFormats;
20
20
  const exts = DEFAULT_EXTENSIONS.map(extname => extname.slice(1)).join(',');
21
21
  const copiedEntries = new Set();
22
22
  const copiedPackages = new Set();
@@ -394,6 +394,7 @@ export declare const Plugins: {
394
394
  positional: boolean;
395
395
  nodeImportArgs: boolean;
396
396
  resolve: string[];
397
+ boolean: string[];
397
398
  args: (args: string[]) => string[];
398
399
  };
399
400
  };
@@ -10,6 +10,7 @@ declare const _default: {
10
10
  positional: boolean;
11
11
  nodeImportArgs: boolean;
12
12
  resolve: string[];
13
+ boolean: string[];
13
14
  args: (args: string[]) => string[];
14
15
  };
15
16
  };
@@ -16,6 +16,7 @@ const args = {
16
16
  positional: true,
17
17
  nodeImportArgs: true,
18
18
  resolve: ['test-reporter'],
19
+ boolean: ['deprecation', 'experimental-strip-types', 'harmony', 'test-only', 'test', 'warnings', 'watch'],
19
20
  args: (args) => args.filter(arg => !/--test-reporter[= ](spec|tap|dot|junit|lcov)/.test(arg)),
20
21
  };
21
22
  export default {
@@ -4,11 +4,11 @@ import { hasDependency } from '../../util/plugin.js';
4
4
  const title = 'Storybook';
5
5
  const enablers = [/^@storybook\//, '@nrwl/storybook'];
6
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
7
- const config = ['.storybook/{main,test-runner}.{js,ts,mts}'];
7
+ const config = ['.{storybook,rnstorybook}/{main,test-runner}.{js,ts,mts}'];
8
8
  const stories = ['**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))'];
9
- const restEntry = ['.storybook/{manager,preview}.{js,jsx,ts,tsx}'];
9
+ const restEntry = ['.{storybook,rnstorybook}/{manager,preview,index,vitest.setup}.{js,jsx,ts,tsx}'];
10
10
  const entry = [...restEntry, ...stories];
11
- const project = ['.storybook/**/*.{js,jsx,ts,tsx,mts}'];
11
+ const project = ['.{storybook,rnstorybook}/**/*.{js,jsx,ts,tsx,mts}'];
12
12
  const resolveConfig = async (localConfig, options) => {
13
13
  const { cwd, configFileDir } = options;
14
14
  const strs = typeof localConfig?.stories === 'function' ? await localConfig.stories(stories) : localConfig?.stories;
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { ISSUE_TYPE_TITLE } from '../constants.js';
3
3
  import { toRelative } from '../util/path.js';
4
- import { getIssueTypeTitle } from './util.js';
4
+ import { getIssueTypeTitle } from './util/util.js';
5
5
  export default async ({ report, issues }) => {
6
6
  const entries = [];
7
7
  for (const [type, isReportType] of Object.entries(report)) {
@@ -1,6 +1,6 @@
1
1
  import { createOwnershipEngine } from '../util/codeowners.js';
2
2
  import { relative, resolve } from '../util/path.js';
3
- import { getColoredTitle, getIssueLine, getIssueTypeTitle } from './util.js';
3
+ import { getColoredTitle, getIssueLine, getIssueTypeTitle } from './util/util.js';
4
4
  const logIssueRecord = (issues) => {
5
5
  const sortedByFilePath = issues.sort((a, b) => (a.owner < b.owner ? -1 : 1));
6
6
  for (const { filePath, symbols, owner, parentSymbol } of sortedByFilePath) {
@@ -1,5 +1,5 @@
1
1
  import { toRelative } from '../util/path.js';
2
- import { getColoredTitle, getIssueLine, getIssueTypeTitle } from './util.js';
2
+ import { getColoredTitle, getIssueLine, getIssueTypeTitle } from './util/util.js';
3
3
  const logIssueSet = (issues) => {
4
4
  for (const filePath of issues.sort())
5
5
  console.log(toRelative(filePath));
@@ -1,4 +1,4 @@
1
- import { getIssueTypeTitle, getTableForType } from './util.js';
1
+ import { getIssueTypeTitle, getTableForType } from './util/util.js';
2
2
  export default ({ report, issues }) => {
3
3
  const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
4
4
  for (let [reportType, isReportType] of Object.entries(report)) {
@@ -1,5 +1,5 @@
1
1
  declare const _default: {
2
- symbols: ({ report, issues, tagHints, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, isShowProgress, }: import("../index.js").ReporterOptions) => void;
2
+ symbols: (options: import("../index.js").ReporterOptions) => void;
3
3
  compact: ({ report, issues, isShowProgress }: import("../index.js").ReporterOptions) => void;
4
4
  codeowners: ({ report, issues, isShowProgress, options }: import("../index.js").ReporterOptions) => void;
5
5
  disclosure: ({ report, issues }: import("../index.js").ReporterOptions) => void;
@@ -1,7 +1,7 @@
1
1
  import { createOwnershipEngine } from '../util/codeowners.js';
2
2
  import { isFile } from '../util/fs.js';
3
3
  import { relative, resolve } from '../util/path.js';
4
- import { convert } from './util.js';
4
+ import { convert } from './util/util.js';
5
5
  export default async ({ report, issues, options }) => {
6
6
  let opts = {};
7
7
  try {
@@ -1,5 +1,5 @@
1
1
  import { relative, toRelative } from '../util/path.js';
2
- import { getIssueTypeTitle } from './util.js';
2
+ import { getIssueTypeTitle } from './util/util.js';
3
3
  export default ({ report, issues }) => {
4
4
  console.log('# Knip report\n');
5
5
  const getFilePath = (issue) => {
@@ -1,3 +1,3 @@
1
1
  import type { ReporterOptions } from '../types/issues.js';
2
- declare const _default: ({ report, issues, tagHints, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, isShowProgress, }: ReporterOptions) => void;
2
+ declare const _default: (options: ReporterOptions) => void;
3
3
  export default _default;
@@ -1,7 +1,7 @@
1
- import { ROOT_WORKSPACE_NAME } from '../constants.js';
2
- import { toRelative } from '../util/path.js';
3
- import { dim, getColoredTitle, getDimmedTitle, getIssueTypeTitle, getTableForType, plain } from './util.js';
4
- export default ({ report, issues, tagHints, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, isShowProgress, }) => {
1
+ import { printConfigurationHints } from './util/configuration-hints.js';
2
+ import { getColoredTitle, getIssueTypeTitle, getTableForType } from './util/util.js';
3
+ export default (options) => {
4
+ const { report, issues, isDisableConfigHints, isShowProgress } = options;
5
5
  const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
6
6
  let totalIssues = 0;
7
7
  for (let [reportType, isReportType] of Object.entries(report)) {
@@ -18,25 +18,7 @@ export default ({ report, issues, tagHints, configurationHints, isDisableConfigH
18
18
  }
19
19
  }
20
20
  if (!isDisableConfigHints) {
21
- if (configurationHints.size > 0) {
22
- const getTitle = isTreatConfigHintsAsErrors ? getColoredTitle : getDimmedTitle;
23
- console.log(getTitle('Configuration hints', configurationHints.size));
24
- const style = isTreatConfigHintsAsErrors ? plain : dim;
25
- for (const hint of configurationHints) {
26
- const { type, workspaceName, identifier } = hint;
27
- const message = `Unused item in ${type}`;
28
- const workspace = workspaceName && workspaceName !== ROOT_WORKSPACE_NAME ? ` (workspace: ${workspaceName})` : '';
29
- console.warn(style(`${message}${workspace}:`), identifier);
30
- }
31
- }
32
- if (tagHints.size > 0) {
33
- console.log(getColoredTitle('Tag issues', tagHints.size));
34
- for (const hint of tagHints) {
35
- const { filePath, identifier, tagName } = hint;
36
- const message = `Unused tag in ${toRelative(filePath)}:`;
37
- console.warn(dim(message), `${identifier} → ${tagName}`);
38
- }
39
- }
21
+ printConfigurationHints(options);
40
22
  }
41
23
  if (totalIssues === 0 && isShowProgress) {
42
24
  console.log('✂️ Excellent, Knip found no issues.');
@@ -0,0 +1,2 @@
1
+ import type { ReporterOptions } from '../../types/issues.js';
2
+ export declare const printConfigurationHints: ({ counters, issues, tagHints, configurationHints, isTreatConfigHintsAsErrors, includedWorkspaces, }: ReporterOptions) => void;
@@ -0,0 +1,62 @@
1
+ import { toRelative } from '../../util/path.js';
2
+ import { byPathDepth } from '../../util/workspace.js';
3
+ import { bright, dim, getColoredTitle, getDimmedTitle, plain, yellow } from './util.js';
4
+ const id = (id) => bright(id.toString() + (id === '.' ? ' (root)' : ''));
5
+ const type = (id) => yellow(id.split('-').at(0));
6
+ const workspace = ({ isRootOnly, workspaceName: id }) => isRootOnly ? '' : id === '.' ? ` in root ${yellow('"."')} workspace` : ` in ${yellow(id ?? '.')}`;
7
+ const unused = (options) => `Remove from ${type(options.type)}${options.workspaceName === '.' ? '' : `${workspace(options)}`}: ${id(options.identifier)}`;
8
+ const empty = (options) => `Refine ${type(options.type)}${workspace(options)}: ${id(options.identifier)} (no files found)`;
9
+ const remove = (options) => `Remove ${type(options.type)}${workspace(options)}: ${id(options.identifier)}`;
10
+ const add = (options) => `Add to or refine in ${yellow('workspaces')}: ${id(options.identifier)} (${options.size} unused files)`;
11
+ const topLevel = (options) => `Remove or move unused top-level ${type(options.type)} to ${yellow('"."')}: ${id(options.identifier)}`;
12
+ const hintPrinters = new Map([
13
+ ['ignoreBinaries', { print: unused }],
14
+ ['ignoreDependencies', { print: unused }],
15
+ ['ignoreUnresolved', { print: unused }],
16
+ ['ignoreWorkspaces', { print: unused }],
17
+ ['entry-empty', { print: empty }],
18
+ ['project-empty', { print: empty }],
19
+ ['entry-redundant', { print: remove }],
20
+ ['project-redundant', { print: remove }],
21
+ ['workspace-unconfigured', { print: add }],
22
+ ['entry-top-level', { print: topLevel }],
23
+ ['project-top-level', { print: topLevel }],
24
+ ]);
25
+ export const printConfigurationHints = ({ counters, issues, tagHints, configurationHints, isTreatConfigHintsAsErrors, includedWorkspaces, }) => {
26
+ if (counters.files > 20) {
27
+ const workspaces = includedWorkspaces
28
+ .map(workspace => workspace.dir)
29
+ .sort(byPathDepth)
30
+ .reverse()
31
+ .map(dir => ({ dir, size: 0 }));
32
+ for (const filePath of issues.files) {
33
+ const workspace = workspaces.find(ws => filePath.startsWith(ws.dir));
34
+ if (workspace)
35
+ workspace.size++;
36
+ }
37
+ const hlWorkspaces = workspaces.sort((a, b) => b.size - a.size).filter(ws => ws.size > 1);
38
+ for (const { dir, size } of hlWorkspaces) {
39
+ const identifier = toRelative(dir) || '.';
40
+ configurationHints.add({ type: 'workspace-unconfigured', workspaceName: identifier, identifier, size });
41
+ }
42
+ }
43
+ if (configurationHints.size > 0) {
44
+ const getTitle = isTreatConfigHintsAsErrors ? getColoredTitle : getDimmedTitle;
45
+ const style = isTreatConfigHintsAsErrors ? plain : dim;
46
+ console.log(getTitle('Configuration hints', configurationHints.size));
47
+ const isRootOnly = includedWorkspaces.length === 1 && includedWorkspaces[0].name === '.';
48
+ for (const hint of configurationHints) {
49
+ const hintPrinter = hintPrinters.get(hint.type);
50
+ if (hintPrinter)
51
+ console.warn(style(hintPrinter.print({ ...hint, isRootOnly })));
52
+ }
53
+ }
54
+ if (tagHints.size > 0) {
55
+ console.log(getColoredTitle('Tag issues', tagHints.size));
56
+ for (const hint of tagHints) {
57
+ const { filePath, identifier, tagName } = hint;
58
+ const message = `Unused tag in ${toRelative(filePath)}:`;
59
+ console.warn(dim(message), `${identifier} → ${tagName}`);
60
+ }
61
+ }
62
+ };
@@ -1,8 +1,10 @@
1
- import { ISSUE_TYPE_TITLE } from '../constants.js';
2
- import { type Issue, type IssueSeverity, type IssueSymbol } from '../types/issues.js';
3
- import { Table } from '../util/table.js';
1
+ import { ISSUE_TYPE_TITLE } from '../../constants.js';
2
+ import { type Issue, type IssueSeverity, type IssueSymbol } from '../../types/issues.js';
3
+ import { Table } from '../../util/table.js';
4
4
  export declare const plain: (text: string) => string;
5
5
  export declare const dim: import("picocolors/types.js").Formatter;
6
+ export declare const bright: import("picocolors/types.js").Formatter;
7
+ export declare const yellow: import("picocolors/types.js").Formatter;
6
8
  export declare const getIssueTypeTitle: (reportType: keyof typeof ISSUE_TYPE_TITLE) => string;
7
9
  export declare const getColoredTitle: (title: string, count: number) => string;
8
10
  export declare const getDimmedTitle: (title: string, count: number) => string;
@@ -1,14 +1,15 @@
1
1
  import picocolors from 'picocolors';
2
- import { ISSUE_TYPE_TITLE } from '../constants.js';
3
- import { SymbolType } from '../types/issues.js';
4
- import { relative } from '../util/path.js';
5
- import { Table } from '../util/table.js';
2
+ import { ISSUE_TYPE_TITLE } from '../../constants.js';
3
+ import { SymbolType } from '../../types/issues.js';
4
+ import { relative } from '../../util/path.js';
5
+ import { Table } from '../../util/table.js';
6
6
  export const plain = (text) => text;
7
7
  export const dim = picocolors.gray;
8
- const bright = picocolors.whiteBright;
8
+ export const bright = picocolors.whiteBright;
9
+ export const yellow = picocolors.yellow;
9
10
  export const getIssueTypeTitle = (reportType) => ISSUE_TYPE_TITLE[reportType];
10
11
  export const getColoredTitle = (title, count) => `${picocolors.yellowBright(picocolors.underline(title))} (${count})`;
11
- export const getDimmedTitle = (title, count) => `${picocolors.yellow(`${picocolors.underline(title)} (${count})`)}`;
12
+ export const getDimmedTitle = (title, count) => `${yellow(`${picocolors.underline(title)} (${count})`)}`;
12
13
  export const getIssueLine = ({ owner, filePath, symbols, parentSymbol, severity }) => {
13
14
  const symbol = symbols ? `: ${symbols.map(s => s.symbol).join(', ')}` : '';
14
15
  const parent = parentSymbol ? ` (${parentSymbol})` : '';
@@ -1,7 +1,7 @@
1
1
  import picocolors from 'picocolors';
2
2
  import { perfObserver } from '../util/Performance.js';
3
3
  import { prettyMilliseconds } from '../util/string.js';
4
- import { getIssueTypeTitle, getTableForType } from './util.js';
4
+ import { getIssueTypeTitle, getTableForType } from './util/util.js';
5
5
  export default ({ report, issues, streamer, startTime, size, isDebug }) => {
6
6
  const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
7
7
  let totalIssues = 0;
@@ -1,3 +1,4 @@
1
+ import type { Workspace } from '../ConfigurationChief.js';
1
2
  export declare enum SymbolType {
2
3
  VARIABLE = "variable",
3
4
  TYPE = "type",
@@ -67,16 +68,19 @@ export type ReporterOptions = {
67
68
  isShowProgress: boolean;
68
69
  options: string;
69
70
  preprocessorOptions: string;
71
+ includedWorkspaces: Workspace[];
70
72
  };
71
73
  export type Reporter = (options: ReporterOptions) => void;
72
74
  export type Preprocessor = (options: ReporterOptions) => ReporterOptions;
73
75
  export type IssueSeverity = 'error' | 'warn' | 'off';
74
76
  export type Rules = Record<IssueType, IssueSeverity>;
75
77
  export type ConfigurationHints = Set<ConfigurationHint>;
78
+ export type ConfigurationHintType = 'ignoreBinaries' | 'ignoreDependencies' | 'ignoreUnresolved' | 'ignoreWorkspaces' | 'entry-redundant' | 'project-redundant' | 'entry-top-level' | 'project-top-level' | 'entry-empty' | 'project-empty' | 'workspace-unconfigured';
76
79
  export type ConfigurationHint = {
77
- type: 'ignoreBinaries' | 'ignoreDependencies' | 'ignoreUnresolved' | 'ignoreWorkspaces';
80
+ type: ConfigurationHintType;
78
81
  identifier: string | RegExp;
79
82
  workspaceName?: string;
83
+ size?: number;
80
84
  };
81
85
  type TagHints = Set<TagHint>;
82
86
  export type TagHint = {
@@ -12,9 +12,9 @@ type WorkspaceManifest = {
12
12
  ignoreDependencies: (string | RegExp)[];
13
13
  ignoreBinaries: (string | RegExp)[];
14
14
  ignoreUnresolved: (string | RegExp)[];
15
- usedIgnoreDependencies: Set<string | RegExp>;
16
- usedIgnoreBinaries: Set<string | RegExp>;
17
- usedIgnoreUnresolved: Set<string | RegExp>;
15
+ unusedIgnoreDependencies: Set<string | RegExp>;
16
+ unusedIgnoreBinaries: Set<string | RegExp>;
17
+ unusedIgnoreUnresolved: Set<string | RegExp>;
18
18
  };
19
19
  export type WorkspaceManifests = Map<string, WorkspaceManifest>;
20
20
  export type HostDependencies = Map<string, Array<{
@@ -1,3 +1,3 @@
1
1
  export declare const toRegexOrString: (value: string | RegExp) => string | RegExp;
2
- export declare const findMatch: (haystack: undefined | (string | RegExp)[], needle: string) => string | RegExp | undefined;
2
+ export declare const findMatch: (haystack: (string | RegExp)[], needle: string) => string | RegExp | undefined;
3
3
  export declare const isIdChar: (text: string) => boolean;
@@ -1,6 +1,6 @@
1
1
  const isRegexLikeMatch = /[*+\\(|{^$]/;
2
2
  const isRegexLike = (value) => isRegexLikeMatch.test(value);
3
3
  export const toRegexOrString = (value) => typeof value === 'string' && isRegexLike(value) ? new RegExp(value) : value;
4
- export const findMatch = (haystack, needle) => haystack?.find(n => (typeof n === 'string' ? n === needle : n.test(needle)));
4
+ export const findMatch = (haystack, needle) => haystack.find(n => (typeof n === 'string' ? n === needle : n.test(needle)));
5
5
  const idCharMatch = /[a-zA-Z0-9$_]/;
6
6
  export const isIdChar = (text) => idCharMatch.test(text);
@@ -1,3 +1,4 @@
1
+ export declare const ELLIPSIS = "\u2026";
1
2
  export declare const truncate: (text: string, width: number) => string;
2
3
  export declare const truncateStart: (text: string, width: number) => string;
3
4
  export declare const pad: (text: string, width: number, fillString?: string, align?: "left" | "center" | "right") => string;
@@ -1,6 +1,6 @@
1
1
  import { stripVTControlCharacters } from 'node:util';
2
2
  const CONTROL_CHARACTERS = /\u001b\[[0-9;]+m/g;
3
- const ELLIPSIS = '…';
3
+ export const ELLIPSIS = '…';
4
4
  const getTruncatedParts = (input, limit, fromStart) => {
5
5
  const parts = [];
6
6
  let width = 0;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.59.1";
1
+ export declare const version = "5.60.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.59.1';
1
+ export const version = '5.60.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.59.1",
3
+ "version": "5.60.1",
4
4
  "description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {
@@ -63,15 +63,15 @@
63
63
  "dependencies": {
64
64
  "@nodelib/fs.walk": "^1.2.3",
65
65
  "fast-glob": "^3.3.3",
66
- "formatly": "^0.2.3",
66
+ "formatly": "^0.2.4",
67
67
  "jiti": "^2.4.2",
68
68
  "js-yaml": "^4.1.0",
69
69
  "minimist": "^1.2.8",
70
- "oxc-resolver": "^9.0.2",
71
- "picocolors": "^1.1.0",
70
+ "oxc-resolver": "^11.1.0",
71
+ "picocolors": "^1.1.1",
72
72
  "picomatch": "^4.0.1",
73
- "smol-toml": "^1.3.1",
74
- "strip-json-comments": "5.0.1",
73
+ "smol-toml": "^1.3.4",
74
+ "strip-json-comments": "5.0.2",
75
75
  "zod": "^3.22.4",
76
76
  "zod-validation-error": "^3.0.3"
77
77
  },
@@ -81,16 +81,16 @@
81
81
  },
82
82
  "devDependencies": {
83
83
  "@jest/types": "^29.6.3",
84
- "@release-it/bumper": "^7.0.2",
85
- "@types/bun": "1.2.4",
84
+ "@release-it/bumper": "^7.0.5",
85
+ "@types/bun": "1.2.15",
86
86
  "@types/js-yaml": "^4.0.9",
87
87
  "@types/minimist": "^1.2.5",
88
88
  "@types/picomatch": "3.0.1",
89
89
  "@types/webpack": "^5.28.5",
90
- "@wdio/types": "^9.5.0",
90
+ "@wdio/types": "^9.15.0",
91
91
  "codeclimate-types": "^0.3.1",
92
92
  "glob": "^11.0.2",
93
- "release-it": "^19.0.1",
93
+ "release-it": "^19.0.3",
94
94
  "tsx": "^4.19.4",
95
95
  "type-fest": "^4.31.0",
96
96
  "typescript": "^5.5.2"