knip 5.45.0 → 5.46.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.
@@ -172,5 +172,6 @@ export declare class ConfigurationChief {
172
172
  getIncludedIssueTypes(cliArgs: CLIArguments): import("./types/issues.js").Report;
173
173
  findWorkspaceByFilePath(filePath: string): Workspace | undefined;
174
174
  getUnusedIgnoredWorkspaces(): string[];
175
+ getTags(): import("./types/cli.js").Tags;
175
176
  }
176
177
  export {};
@@ -18,6 +18,7 @@ import { getKeysByValue } from './util/object.js';
18
18
  import { join, relative } from './util/path.js';
19
19
  import { normalizePluginConfig } from './util/plugin.js';
20
20
  import { toRegexOrString } from './util/regex.js';
21
+ import { splitTags } from './util/tag.js';
21
22
  import { unwrapFunction } from './util/unwrap-function.js';
22
23
  import { byPathDepth } from './util/workspace.js';
23
24
  const { config: rawConfigArg } = parsedArgValues;
@@ -43,6 +44,7 @@ const defaultConfig = {
43
44
  syncCompilers: new Map(),
44
45
  asyncCompilers: new Map(),
45
46
  rootPluginConfigs: {},
47
+ tags: [],
46
48
  };
47
49
  export class ConfigurationChief {
48
50
  cwd;
@@ -150,6 +152,7 @@ export class ConfigurationChief {
150
152
  syncCompilers: new Map(Object.entries(syncCompilers ?? {})),
151
153
  asyncCompilers: new Map(Object.entries(asyncCompilers ?? {})),
152
154
  rootPluginConfigs,
155
+ tags: rawConfig.tags ?? [],
153
156
  };
154
157
  }
155
158
  async setWorkspaces() {
@@ -371,4 +374,7 @@ export class ConfigurationChief {
371
374
  return !isDirectory(dir) || isFile(join(dir, 'package.json'));
372
375
  });
373
376
  }
377
+ getTags() {
378
+ return splitTags(this.config.tags);
379
+ }
374
380
  }
@@ -40,7 +40,8 @@ export class IssueCollector {
40
40
  if (this.isMatch(filePath))
41
41
  continue;
42
42
  this.issues.files.add(filePath);
43
- this.issues._files.add({ type: 'files', filePath, symbol: relative(filePath), severity: this.rules.files });
43
+ const symbol = relative(filePath);
44
+ this.issues._files[symbol] = [{ type: 'files', filePath, symbol, severity: this.rules.files }];
44
45
  this.counters.files++;
45
46
  this.counters.processed++;
46
47
  }
@@ -57,7 +57,7 @@ export class IssueFixer {
57
57
  async removeUnusedFiles(issues) {
58
58
  if (!this.isFixFiles)
59
59
  return;
60
- for (const issue of issues._files) {
60
+ for (const issue of Object.values(issues._files).flatMap(Object.values)) {
61
61
  await rm(issue.filePath);
62
62
  issue.isFixed = true;
63
63
  }
@@ -5,7 +5,7 @@ import { isAbsolute, join } from '../../util/path.js';
5
5
  import { resolveX } from './bunx.js';
6
6
  const commands = ['add', 'create', 'init', 'install', 'link', 'pm', 'remove', 'run', 'test', 'update', 'upgrade', 'x'];
7
7
  export const resolve = (_binary, args, options) => {
8
- const parsed = parseArgs(args);
8
+ const parsed = parseArgs(args, { string: ['cwd'] });
9
9
  const [command, script] = parsed._;
10
10
  if (command === 'x') {
11
11
  const argsForX = args.filter(arg => arg !== 'x');
@@ -14,11 +14,15 @@ export const resolve = (_binary, args, options) => {
14
14
  const { manifestScriptNames, cwd, fromArgs } = options;
15
15
  if (command === 'run' && manifestScriptNames.has(script))
16
16
  return [];
17
- if (manifestScriptNames.has(command) || commands.includes(command))
17
+ if (manifestScriptNames.has(command))
18
+ return [];
19
+ if (command !== 'run' && commands.includes(command))
18
20
  return [];
19
21
  const filePath = command === 'run' ? script : command;
20
22
  const absFilePath = isAbsolute(filePath) ? filePath : join(cwd, filePath);
21
23
  if (isFile(absFilePath))
22
24
  return [toEntry(absFilePath)];
23
- return fromArgs(args);
25
+ const dir = parsed.cwd ? join(cwd, parsed.cwd) : undefined;
26
+ const opts = dir ? { cwd: dir } : {};
27
+ return command === 'run' ? [] : fromArgs(args, opts);
24
28
  };
@@ -52,6 +52,8 @@ export const resolve = (_binary, args, options) => {
52
52
  const parsed = parseArgs(args, { boolean: ['top-level'], string: ['cwd'] });
53
53
  const dir = parsed['top-level'] ? rootCwd : parsed.cwd ? join(cwd, parsed.cwd) : undefined;
54
54
  const [command, binary] = parsed._;
55
+ if (!command && !binary)
56
+ return [];
55
57
  if (command === 'run') {
56
58
  if (manifestScriptNames.has(binary))
57
59
  return [];
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import { splitTags } from './util/tag.js';
10
10
  import { isTrace } from './util/trace.js';
11
11
  import { version } from './version.js';
12
12
  const defaultCacheLocation = join(cwd, 'node_modules', '.cache', 'knip');
13
- const { 'allow-remove-files': isRemoveFiles = false, cache: isCache = false, 'cache-location': cacheLocation = defaultCacheLocation, debug: isDebug = false, dependencies: isDependenciesShorthand = false, exclude: excludedIssueTypes = [], 'experimental-tags': experimentalTags = [], exports: isExportsShorthand = false, files: isFilesShorthand = false, fix: isFix = false, 'fix-type': fixTypes = [], help: isHelp, include: includedIssueTypes = [], 'include-entry-exports': isIncludeEntryExports = false, 'include-libs': isIncludeLibs = false, 'isolate-workspaces': isIsolateWorkspaces = false, 'max-issues': maxIssues = '0', 'no-config-hints': isHideConfigHints = false, 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = isDebug || isTrace, preprocessor = [], 'preprocessor-options': preprocessorOptions = '', production: isProduction = false, reporter = ['symbols'], 'reporter-options': reporterOptions = '', strict: isStrict = false, tags = [], tsConfig, version: isVersion, watch: isWatch = false, workspace: rawWorkspaceArg, } = parsedArgValues;
13
+ const { 'allow-remove-files': isRemoveFiles = false, cache: isCache = false, 'cache-location': cacheLocation = defaultCacheLocation, debug: isDebug = false, dependencies: isDependenciesShorthand = false, exclude: excludedIssueTypes = [], 'experimental-tags': experimentalTags = [], exports: isExportsShorthand = false, files: isFilesShorthand = false, fix: isFix = false, 'fix-type': fixTypes = [], help: isHelp, include: includedIssueTypes = [], 'include-entry-exports': isIncludeEntryExports = false, 'include-libs': isIncludeLibs = false, 'isolate-workspaces': isIsolateWorkspaces = false, 'max-issues': maxIssues = '0', 'no-config-hints': isDisableConfigHints = false, 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = isDebug || isTrace, preprocessor = [], 'preprocessor-options': preprocessorOptions = '', production: isProduction = false, reporter = ['symbols'], 'reporter-options': reporterOptions = '', strict: isStrict = false, tags = [], 'treat-config-hints-as-errors': isTreatConfigHintsAsErrors = false, tsConfig, version: isVersion, watch: isWatch = false, workspace: rawWorkspaceArg, } = parsedArgValues;
14
14
  if (isHelp) {
15
15
  console.log(helpText);
16
16
  process.exit(0);
@@ -36,7 +36,7 @@ const run = async () => {
36
36
  isExportsShorthand,
37
37
  isFilesShorthand,
38
38
  isFix: isFix || fixTypes.length > 0,
39
- isHideConfigHints,
39
+ isDisableConfigHints,
40
40
  isIncludeEntryExports,
41
41
  isIncludeLibs,
42
42
  isIsolateWorkspaces,
@@ -57,7 +57,8 @@ const run = async () => {
57
57
  counters,
58
58
  tagHints,
59
59
  configurationHints,
60
- noConfigHints: isHideConfigHints,
60
+ isDisableConfigHints,
61
+ isTreatConfigHintsAsErrors,
61
62
  cwd,
62
63
  isProduction,
63
64
  isShowProgress,
@@ -83,7 +84,8 @@ const run = async () => {
83
84
  if (isIsolateWorkspaces && report.classMembers) {
84
85
  logWarning('WARNING', 'Class members are not tracked when using the --isolate-workspaces flag');
85
86
  }
86
- if (!noExitCode && totalErrorCount > Number(maxIssues)) {
87
+ if ((!noExitCode && totalErrorCount > Number(maxIssues)) ||
88
+ (isTreatConfigHintsAsErrors && configurationHints.size > 0)) {
87
89
  process.exit(1);
88
90
  }
89
91
  }
@@ -5,6 +5,7 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
5
5
  syncCompilers: Record<string, SyncCompilerFn>;
6
6
  asyncCompilers: Record<string, AsyncCompilerFn>;
7
7
  exclude?: ("dependencies" | "exports" | "files" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
8
+ tags?: string[] | undefined;
8
9
  include?: ("dependencies" | "exports" | "files" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
9
10
  node?: string | boolean | string[] | {
10
11
  config?: string | string[] | undefined;
@@ -17,7 +17,7 @@ interface AnalyzeOptions {
17
17
  fixer: IssueFixer;
18
18
  graph: ModuleGraph;
19
19
  isFix: boolean;
20
- isHideConfigHints: boolean;
20
+ isDisableConfigHints: boolean;
21
21
  isIncludeLibs: boolean;
22
22
  isProduction: boolean;
23
23
  report: Report;
@@ -5,13 +5,13 @@ import { findMatch } from '../util/regex.js';
5
5
  import { getShouldIgnoreHandler, getShouldIgnoreTagHandler } from '../util/tag.js';
6
6
  import { createAndPrintTrace, printTrace } from '../util/trace.js';
7
7
  export const analyze = async (options) => {
8
- const { analyzedFiles, chief, collector, deputy, entryPaths, factory, fixer, graph, isFix, isHideConfigHints, isIncludeLibs, isProduction, report, streamer, tags, unreferencedFiles, workspace, } = options;
8
+ const { analyzedFiles, chief, collector, deputy, entryPaths, factory, fixer, graph, isFix, isDisableConfigHints, isIncludeLibs, isProduction, report, streamer, tags, unreferencedFiles, workspace, } = options;
9
9
  const isReportDependencies = report.dependencies || report.unlisted || report.unresolved;
10
10
  const isReportValues = report.exports || report.nsExports || report.classMembers;
11
11
  const isReportTypes = report.types || report.nsTypes || report.enumMembers;
12
12
  const isReportClassMembers = report.classMembers;
13
13
  const isSkipLibs = !(isIncludeLibs || isReportClassMembers);
14
- const isShowConfigHints = !workspace && !isProduction && !isHideConfigHints;
14
+ const isShowConfigHints = !workspace && !isProduction && !isDisableConfigHints;
15
15
  const shouldIgnore = getShouldIgnoreHandler(isProduction);
16
16
  const shouldIgnoreTags = getShouldIgnoreTagHandler(tags);
17
17
  const isIdentifierReferenced = getIsIdentifierReferencedHandler(graph, entryPaths);
@@ -94,12 +94,12 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
94
94
  const entryFilePatterns = new Set();
95
95
  const productionEntryFilePatterns = new Set();
96
96
  for (const input of inputs) {
97
- const s = input.specifier;
97
+ const specifier = input.specifier;
98
98
  if (isEntry(input)) {
99
- entryFilePatterns.add(isAbsolute(s) ? relative(dir, s) : s);
99
+ entryFilePatterns.add(isAbsolute(specifier) ? relative(dir, specifier) : specifier);
100
100
  }
101
101
  else if (isProductionEntry(input)) {
102
- productionEntryFilePatterns.add(isAbsolute(s) ? relative(dir, s) : s);
102
+ productionEntryFilePatterns.add(isAbsolute(specifier) ? relative(dir, specifier) : specifier);
103
103
  }
104
104
  else if (!isConfig(input)) {
105
105
  const ws = (input.containingFilePath && chief.findWorkspaceByFilePath(input.containingFilePath)) || workspace;
@@ -217,13 +217,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
217
217
  const dependencies = deputy.getDependencies(workspace.name);
218
218
  const manifestScriptNames = new Set(Object.keys(chief.getManifestForWorkspace(workspace.name)?.scripts ?? {}));
219
219
  const dir = dirname(filePath);
220
- const options = {
221
- cwd: dir,
222
- rootCwd: cwd,
223
- containingFilePath: filePath,
224
- dependencies,
225
- manifestScriptNames,
226
- };
220
+ const options = { cwd: dir, rootCwd: cwd, containingFilePath: filePath, dependencies, manifestScriptNames };
227
221
  const inputs = _getInputsFromScripts(scripts, options);
228
222
  for (const input of inputs) {
229
223
  input.containingFilePath ??= filePath;
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import { debugLogObject } from './util/debug.js';
11
11
  import { getGitIgnoredHandler } from './util/glob-core.js';
12
12
  import { getWatchHandler } from './util/watch.js';
13
13
  export const main = async (unresolvedConfiguration) => {
14
- const { cacheLocation, cwd, excludedIssueTypes, fixTypes, gitignore, includedIssueTypes, isCache, isDebug, isDependenciesShorthand, isExportsShorthand, isFilesShorthand, isFix, isHideConfigHints, isIncludeEntryExports, isIncludeLibs, isIsolateWorkspaces, isProduction, isRemoveFiles, isShowProgress, isStrict, isWatch, tags, tsConfigFile, workspace, } = unresolvedConfiguration;
14
+ const { cacheLocation, cwd, excludedIssueTypes, fixTypes, gitignore, includedIssueTypes, isCache, isDebug, isDependenciesShorthand, isExportsShorthand, isFilesShorthand, isFix, isDisableConfigHints, isIncludeEntryExports, isIncludeLibs, isIsolateWorkspaces, isProduction, isRemoveFiles, isShowProgress, isStrict, isWatch, tags, tsConfigFile, workspace, } = unresolvedConfiguration;
15
15
  debugLogObject('*', 'Unresolved configuration (from CLI arguments)', unresolvedConfiguration);
16
16
  const chief = new ConfigurationChief({ cwd, isProduction, isStrict, isIncludeEntryExports, workspace });
17
17
  const deputy = new DependencyDeputy({ isProduction, isStrict });
@@ -29,6 +29,7 @@ export const main = async (unresolvedConfiguration) => {
29
29
  });
30
30
  const rules = chief.getRules();
31
31
  const filters = chief.getFilters();
32
+ const finalTags = tags[0].length > 0 || tags[1].length > 0 ? tags : chief.getTags();
32
33
  const fixer = new IssueFixer({ isEnabled: isFix, cwd, fixTypes, isRemoveFiles });
33
34
  debugLogObject('*', 'Included issue types', report);
34
35
  const isReportClassMembers = report.classMembers;
@@ -57,7 +58,7 @@ export const main = async (unresolvedConfiguration) => {
57
58
  isWatch,
58
59
  report,
59
60
  streamer,
60
- tags,
61
+ tags: finalTags,
61
62
  tsConfigFile,
62
63
  workspaces,
63
64
  });
@@ -71,12 +72,12 @@ export const main = async (unresolvedConfiguration) => {
71
72
  fixer,
72
73
  graph,
73
74
  isFix,
74
- isHideConfigHints,
75
+ isDisableConfigHints,
75
76
  isIncludeLibs,
76
77
  isProduction,
77
78
  report,
78
79
  streamer,
79
- tags,
80
+ tags: finalTags,
80
81
  unreferencedFiles,
81
82
  workspace,
82
83
  });
@@ -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}'];
7
+ const config = ['.storybook/{main,test-runner}.{js,ts,mts}'];
8
8
  const stories = ['**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))'];
9
9
  const restEntry = ['.storybook/{manager,preview}.{js,jsx,ts,tsx}'];
10
10
  const entry = [...restEntry, ...stories];
11
- const project = ['.storybook/**/*.{js,jsx,ts,tsx}'];
11
+ const project = ['.storybook/**/*.{js,jsx,ts,tsx,mts}'];
12
12
  const resolveEntryPaths = async (localConfig, options) => {
13
13
  const { cwd, configFileDir } = options;
14
14
  const strs = typeof localConfig?.stories === 'function' ? await localConfig.stories(stories) : localConfig?.stories;
@@ -0,0 +1,3 @@
1
+ import type { ReporterOptions } from '../types/issues.js';
2
+ declare const _default: ({ report, issues }: ReporterOptions) => Promise<void>;
3
+ export default _default;
@@ -0,0 +1,87 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { toRelative } from '../util/path.js';
3
+ import { getTitle } from './util.js';
4
+ export default async ({ report, issues }) => {
5
+ const entries = [];
6
+ for (const [type, isReportType] of Object.entries(report)) {
7
+ if (!isReportType) {
8
+ continue;
9
+ }
10
+ const fixedType = type === 'files' ? '_files' : type;
11
+ for (const issue of flatten(issues[fixedType])) {
12
+ const { filePath } = issue;
13
+ if (fixedType === 'duplicates' && issue.symbols) {
14
+ entries.push(...issue.symbols.map(symbol => ({
15
+ type: 'issue',
16
+ check_name: getTitle(fixedType),
17
+ description: getSymbolDescription({ symbol, parentSymbol: issue.parentSymbol }),
18
+ categories: ['Duplication'],
19
+ location: createLocation(filePath, symbol.line, symbol.col),
20
+ severity: convertSeverity(issue.severity),
21
+ fingerprint: createFingerprint(filePath, symbol.symbol, symbol.pos),
22
+ })));
23
+ }
24
+ else {
25
+ entries.push({
26
+ type: 'issue',
27
+ check_name: getTitle(fixedType),
28
+ description: getIssueDescription(issue),
29
+ categories: ['Bug Risk'],
30
+ location: createLocation(filePath, issue.line, issue.col),
31
+ severity: convertSeverity(issue.severity),
32
+ fingerprint: createFingerprint(filePath, issue.symbol, issue.pos),
33
+ });
34
+ }
35
+ }
36
+ }
37
+ const output = JSON.stringify(entries);
38
+ process.stdout._handle?.setBlocking?.(true);
39
+ process.stdout.write(`${output}\n`);
40
+ };
41
+ function flatten(issues) {
42
+ return Object.values(issues).flatMap(Object.values);
43
+ }
44
+ function convertSeverity(severity) {
45
+ switch (severity) {
46
+ case 'error':
47
+ return 'major';
48
+ case 'warn':
49
+ return 'minor';
50
+ default:
51
+ return 'info';
52
+ }
53
+ }
54
+ function getIssueDescription({ symbol, symbols, parentSymbol }) {
55
+ const symbolDescription = symbols ? `${symbols.map(s => s.symbol).join(', ')}` : symbol;
56
+ return `${symbolDescription}${parentSymbol ? ` (${parentSymbol})` : ''}`;
57
+ }
58
+ function getSymbolDescription({ symbol, parentSymbol }) {
59
+ return `${symbol.symbol}${parentSymbol ? ` (${parentSymbol})` : ''}`;
60
+ }
61
+ function createLocation(filePath, line, col) {
62
+ if (col !== undefined) {
63
+ return {
64
+ path: toRelative(filePath),
65
+ positions: {
66
+ begin: {
67
+ line: line ?? 0,
68
+ column: col,
69
+ },
70
+ },
71
+ };
72
+ }
73
+ return {
74
+ path: toRelative(filePath),
75
+ lines: {
76
+ begin: line ?? 0,
77
+ end: line ?? 0,
78
+ },
79
+ };
80
+ }
81
+ function createFingerprint(filePath, message, pos) {
82
+ const md5 = createHash('md5');
83
+ md5.update(filePath);
84
+ md5.update(message);
85
+ md5.update(pos?.toString() ?? '');
86
+ return md5.digest('hex');
87
+ }
@@ -16,7 +16,7 @@ export default ({ report, issues, isShowProgress }) => {
16
16
  ? Object.values(issues[reportType]).flatMap(Object.values)
17
17
  : Object.values(issues[reportType]).map(issues => {
18
18
  const items = Object.values(issues);
19
- return { ...items[0], symbols: items.map(issue => issue.symbol) };
19
+ return { ...items[0], symbols: items };
20
20
  });
21
21
  if (issuesForType.length > 0) {
22
22
  title && logTitle(title, issuesForType.length);
@@ -1,5 +1,5 @@
1
1
  import EasyTable from 'easy-table';
2
- import { relative, toRelative } from '../util/path.js';
2
+ import { relative } from '../util/path.js';
3
3
  import { getTitle } from './util.js';
4
4
  const printHeader = (size, title) => console.log(`<details>\n${title ? `<summary>${title} (${size})</summary>\n` : ''}\n\`\`\``);
5
5
  const printFooter = () => console.log('```\n\n</details>\n');
@@ -10,7 +10,7 @@ const logIssueRecord = (issues) => {
10
10
  issue.parentSymbol && table.cell('parentSymbol', issue.parentSymbol);
11
11
  issue.symbolType && table.cell('symbolType', issue.symbolType);
12
12
  const pos = issue.line === undefined ? '' : `:${issue.line}${issue.col === undefined ? '' : `:${issue.col}`}`;
13
- const cell = `${relative(issue.filePath)}${pos}`;
13
+ const cell = issue.type === 'files' ? '' : `${relative(issue.filePath)}${pos}`;
14
14
  table.cell('filePath', cell);
15
15
  table.newRow();
16
16
  }
@@ -19,30 +19,17 @@ const logIssueRecord = (issues) => {
19
19
  export default ({ report, issues }) => {
20
20
  const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
21
21
  let totalIssues = 0;
22
- for (const [reportType, isReportType] of Object.entries(report)) {
23
- if (reportType === '_files')
24
- continue;
22
+ for (let [reportType, isReportType] of Object.entries(report)) {
23
+ if (reportType === 'files')
24
+ reportType = '_files';
25
25
  if (isReportType) {
26
26
  const title = reportMultipleGroups ? getTitle(reportType) : undefined;
27
- if (reportType === 'files') {
28
- const issuesForType = Array.from(issues._files);
29
- if (issuesForType.length > 0) {
30
- printHeader(issuesForType.length, title);
31
- const sortedIssues = issuesForType.sort((a, b) => a.filePath.localeCompare(b.filePath));
32
- for (const issue of sortedIssues)
33
- console.log(toRelative(issue.filePath));
34
- totalIssues = totalIssues + issuesForType.length;
35
- printFooter();
36
- }
37
- }
38
- else {
39
- const issuesForType = Object.values(issues[reportType]).flatMap(Object.values);
40
- if (issuesForType.length > 0) {
41
- printHeader(issuesForType.length, title);
42
- logIssueRecord(issuesForType);
43
- totalIssues = totalIssues + issuesForType.length;
44
- printFooter();
45
- }
27
+ const issuesForType = Object.values(issues[reportType]).flatMap(Object.values);
28
+ if (issuesForType.length > 0) {
29
+ printHeader(issuesForType.length, title);
30
+ logIssueRecord(issuesForType);
31
+ totalIssues = totalIssues + issuesForType.length;
32
+ printFooter();
46
33
  }
47
34
  }
48
35
  }
@@ -1,8 +1,9 @@
1
1
  declare const _default: {
2
- symbols: ({ report, issues, tagHints, configurationHints, noConfigHints, isShowProgress }: import("../index.js").ReporterOptions) => void;
2
+ symbols: ({ report, issues, tagHints, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, isShowProgress, }: 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;
6
+ codeclimate: ({ report, issues }: import("../index.js").ReporterOptions) => Promise<void>;
6
7
  json: ({ report, issues, options }: import("../index.js").ReporterOptions) => Promise<void>;
7
8
  markdown: ({ report, issues }: import("../index.js").ReporterOptions) => void;
8
9
  };
@@ -1,3 +1,4 @@
1
+ import codeclimate from './codeclimate.js';
1
2
  import codeowners from './codeowners.js';
2
3
  import compact from './compact.js';
3
4
  import disclosure from './disclosure.js';
@@ -9,6 +10,7 @@ export default {
9
10
  compact,
10
11
  codeowners,
11
12
  disclosure,
13
+ codeclimate,
12
14
  json,
13
15
  markdown,
14
16
  };
@@ -1,3 +1,3 @@
1
1
  import type { ReporterOptions } from '../types/issues.js';
2
- declare const _default: ({ report, issues, tagHints, configurationHints, noConfigHints, isShowProgress }: ReporterOptions) => void;
2
+ declare const _default: ({ report, issues, tagHints, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, isShowProgress, }: ReporterOptions) => void;
3
3
  export default _default;
@@ -33,56 +33,39 @@ const logIssueRecord = (issues) => {
33
33
  issue.parentSymbol && table.cell('parentSymbol', print(issue.parentSymbol));
34
34
  issue.symbolType && table.cell('symbolType', print(issue.symbolType));
35
35
  const pos = issue.line === undefined ? '' : `:${issue.line}${issue.col === undefined ? '' : `:${issue.col}`}`;
36
- const cell = `${relative(issue.filePath)}${pos}`;
36
+ const cell = issue.type === 'files' ? '' : `${relative(issue.filePath)}${pos}`;
37
37
  table.cell('filePath', print(cell));
38
38
  issue.isFixed && table.cell('fixed', print('(removed)'));
39
39
  table.newRow();
40
40
  }
41
41
  console.log(table.sort(sortByPos).print().trim());
42
42
  };
43
- export default ({ report, issues, tagHints, configurationHints, noConfigHints, isShowProgress }) => {
43
+ export default ({ report, issues, tagHints, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, isShowProgress, }) => {
44
44
  const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
45
45
  let totalIssues = 0;
46
- for (const [reportType, isReportType] of Object.entries(report)) {
47
- if (reportType === '_files')
48
- continue;
46
+ for (let [reportType, isReportType] of Object.entries(report)) {
47
+ if (reportType === 'files')
48
+ reportType = '_files';
49
49
  if (isReportType) {
50
50
  const title = reportMultipleGroups && getTitle(reportType);
51
- if (reportType === 'files') {
52
- const issuesForType = Array.from(issues._files);
53
- if (issuesForType.length > 0) {
54
- title && logTitle(title, issuesForType.length);
55
- const sortedIssues = issuesForType.sort((a, b) => a.filePath.localeCompare(b.filePath));
56
- for (const issue of sortedIssues) {
57
- const relPath = toRelative(issue.filePath);
58
- if (issue.isFixed)
59
- console.log(dim(`${relPath} (removed)`));
60
- else if (issue.severity === 'warn')
61
- console.log(dim(relPath));
62
- else
63
- console.log(relPath);
64
- }
65
- totalIssues = totalIssues + issuesForType.length;
66
- }
67
- }
68
- else {
69
- const issuesForType = Object.values(issues[reportType]).flatMap(Object.values);
70
- if (issuesForType.length > 0) {
71
- title && logTitle(title, issuesForType.length);
72
- logIssueRecord(issuesForType);
73
- totalIssues = totalIssues + issuesForType.length;
74
- }
51
+ const issuesForType = Object.values(issues[reportType]).flatMap(Object.values);
52
+ if (issuesForType.length > 0) {
53
+ title && logTitle(title, issuesForType.length);
54
+ logIssueRecord(issuesForType);
55
+ totalIssues = totalIssues + issuesForType.length;
75
56
  }
76
57
  }
77
58
  }
78
- if (!noConfigHints) {
59
+ if (!isDisableConfigHints) {
79
60
  if (configurationHints.size > 0) {
80
- logTitleDimmed('Configuration hints');
61
+ const _logTitle = isTreatConfigHintsAsErrors ? logTitle : logTitleDimmed;
62
+ const _color = isTreatConfigHintsAsErrors ? identity : dim;
63
+ _logTitle('Configuration hints', configurationHints.size);
81
64
  for (const hint of configurationHints) {
82
65
  const { type, workspaceName, identifier } = hint;
83
66
  const message = `Unused item in ${type}`;
84
67
  const workspace = workspaceName && workspaceName !== ROOT_WORKSPACE_NAME ? ` (workspace: ${workspaceName})` : '';
85
- console.warn(dim(`${message}${workspace}:`), identifier);
68
+ console.warn(_color(`${message}${workspace}:`), identifier);
86
69
  }
87
70
  }
88
71
  if (tagHints.size > 0) {
@@ -15,6 +15,7 @@ export declare const knipConfigurationSchema: z.ZodObject<z.objectUtil.extendSha
15
15
  compilers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodFunction<z.ZodTuple<[z.ZodString, z.ZodString], z.ZodUnknown>, z.ZodString>, z.ZodFunction<z.ZodTuple<[z.ZodString, z.ZodString], z.ZodUnknown>, z.ZodPromise<z.ZodString>>]>>>;
16
16
  syncCompilers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodFunction<z.ZodTuple<[z.ZodString, z.ZodString], z.ZodUnknown>, z.ZodString>>>;
17
17
  asyncCompilers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodFunction<z.ZodTuple<[z.ZodString, z.ZodString], z.ZodUnknown>, z.ZodPromise<z.ZodString>>>>;
18
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
18
19
  }, {
19
20
  include: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"files">, z.ZodLiteral<"dependencies">, z.ZodLiteral<"devDependencies">, z.ZodLiteral<"optionalPeerDependencies">, z.ZodLiteral<"unlisted">, z.ZodLiteral<"binaries">, z.ZodLiteral<"unresolved">, z.ZodLiteral<"exports">, z.ZodLiteral<"types">, z.ZodLiteral<"nsExports">, z.ZodLiteral<"nsTypes">, z.ZodLiteral<"duplicates">, z.ZodLiteral<"enumMembers">, z.ZodLiteral<"classMembers">]>, "many">>;
20
21
  exclude: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"files">, z.ZodLiteral<"dependencies">, z.ZodLiteral<"devDependencies">, z.ZodLiteral<"optionalPeerDependencies">, z.ZodLiteral<"unlisted">, z.ZodLiteral<"binaries">, z.ZodLiteral<"unresolved">, z.ZodLiteral<"exports">, z.ZodLiteral<"types">, z.ZodLiteral<"nsExports">, z.ZodLiteral<"nsTypes">, z.ZodLiteral<"duplicates">, z.ZodLiteral<"enumMembers">, z.ZodLiteral<"classMembers">]>, "many">>;
@@ -3330,6 +3331,7 @@ export declare const knipConfigurationSchema: z.ZodObject<z.objectUtil.extendSha
3330
3331
  }>]>>;
3331
3332
  }>, "strip", z.ZodTypeAny, {
3332
3333
  exclude?: ("dependencies" | "exports" | "files" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
3334
+ tags?: string[] | undefined;
3333
3335
  include?: ("dependencies" | "exports" | "files" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
3334
3336
  node?: string | boolean | string[] | {
3335
3337
  config?: string | string[] | undefined;
@@ -4269,6 +4271,7 @@ export declare const knipConfigurationSchema: z.ZodObject<z.objectUtil.extendSha
4269
4271
  }> | undefined;
4270
4272
  }, {
4271
4273
  exclude?: ("dependencies" | "exports" | "files" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
4274
+ tags?: string[] | undefined;
4272
4275
  include?: ("dependencies" | "exports" | "files" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
4273
4276
  node?: string | boolean | string[] | {
4274
4277
  config?: string | string[] | undefined;
@@ -50,6 +50,7 @@ const rootConfigurationSchema = z.object({
50
50
  compilers: compilersSchema.optional(),
51
51
  syncCompilers: z.record(z.string(), syncCompilerSchema).optional(),
52
52
  asyncCompilers: z.record(z.string(), asyncCompilerSchema).optional(),
53
+ tags: z.array(z.string()).optional(),
53
54
  });
54
55
  const reportConfigSchema = z.object({
55
56
  include: z.array(issueTypeSchema).optional(),
@@ -11,7 +11,7 @@ export interface CommandLineOptions {
11
11
  isExportsShorthand: boolean;
12
12
  isFilesShorthand: boolean;
13
13
  isFix: boolean;
14
- isHideConfigHints: boolean;
14
+ isDisableConfigHints: boolean;
15
15
  isIncludeEntryExports: boolean;
16
16
  isIncludeLibs: boolean;
17
17
  isIsolateWorkspaces: boolean;
@@ -47,6 +47,7 @@ export interface Configuration {
47
47
  syncCompilers: SyncCompilers;
48
48
  asyncCompilers: AsyncCompilers;
49
49
  rootPluginConfigs: Partial<PluginsConfiguration>;
50
+ tags: string[];
50
51
  }
51
52
  type NormalizedGlob = string[];
52
53
  export type EnsuredPluginConfiguration = {
@@ -32,7 +32,7 @@ export type IssueSet = Set<string>;
32
32
  export type IssueRecords = Record<string, Record<string, Issue>>;
33
33
  export type Issues = {
34
34
  files: IssueSet;
35
- _files: Set<Issue>;
35
+ _files: IssueRecords;
36
36
  dependencies: IssueRecords;
37
37
  devDependencies: IssueRecords;
38
38
  optionalPeerDependencies: IssueRecords;
@@ -48,7 +48,7 @@ export type Issues = {
48
48
  classMembers: IssueRecords;
49
49
  };
50
50
  export type IssueType = keyof Issues;
51
- export type SymbolIssueType = Exclude<IssueType, 'files' | '_files'>;
51
+ export type SymbolIssueType = Exclude<IssueType, 'files'>;
52
52
  export type Report = {
53
53
  [key in keyof Issues]: boolean;
54
54
  };
@@ -59,7 +59,8 @@ export type ReporterOptions = {
59
59
  counters: Counters;
60
60
  tagHints: TagHints;
61
61
  configurationHints: ConfigurationHints;
62
- noConfigHints: boolean;
62
+ isDisableConfigHints: boolean;
63
+ isTreatConfigHintsAsErrors: boolean;
63
64
  cwd: string;
64
65
  isProduction: boolean;
65
66
  isShowProgress: boolean;
@@ -27,7 +27,6 @@ type PragmaMap = {
27
27
  };
28
28
  export interface BoundSourceFile extends ts.SourceFile {
29
29
  symbol?: SymbolWithExports;
30
- resolvedModules?: ts.ModeAwareCache<ts.ResolvedModuleWithFailedLookupLocations>;
31
30
  locals?: SymbolTable;
32
31
  getNamedDeclarations?(): Map<string, readonly ts.Declaration[]>;
33
32
  scriptKind?: ts.ScriptKind;
@@ -1,6 +1,13 @@
1
1
  import ts from 'typescript';
2
2
  import { isIdChar } from '../util/regex.js';
3
3
  export const isType = (item) => item.type === 'type' || item.type === 'interface' || item.type === 'enum';
4
+ const findInFlow = (flowNode, targetSymbol) => {
5
+ if (!flowNode?.node)
6
+ return false;
7
+ if (flowNode.node.symbol === targetSymbol)
8
+ return true;
9
+ return findInFlow(flowNode.antecedent, targetSymbol);
10
+ };
4
11
  export const findInternalReferences = (item, sourceFile, typeChecker, referencedSymbolsInExport, isBindingElement) => {
5
12
  if (!item.symbol)
6
13
  return [0, false];
@@ -19,7 +26,7 @@ export const findInternalReferences = (item, sourceFile, typeChecker, referenced
19
26
  const isExportDeclaration = index === item.pos || index === item.pos + 1;
20
27
  if (!isExportDeclaration) {
21
28
  const symbol = typeChecker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, index));
22
- if (symbol) {
29
+ if (symbol && id === symbol.escapedName) {
23
30
  const isInExport = referencedSymbolsInExport.has(symbol);
24
31
  if (isInExport)
25
32
  isSymbolInExport = true;
@@ -30,7 +37,7 @@ export const findInternalReferences = (item, sourceFile, typeChecker, referenced
30
37
  }
31
38
  const declaration = symbol.declarations?.[0];
32
39
  if (declaration) {
33
- if (item.symbol === declaration.name?.flowNode?.node?.symbol) {
40
+ if (findInFlow(declaration.name?.flowNode, item.symbol)) {
34
41
  return [++refCount, isSymbolInExport];
35
42
  }
36
43
  if (ts.isImportSpecifier(declaration) && symbols.has(symbol)) {
@@ -1,4 +1,4 @@
1
- export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no test files, devDependencies)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n -W, --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)\n --directory [dir] Run process from a different directory (default: cwd)\n --cache Enable caching\n --cache-location Change cache location (default: node_modules/.cache/knip)\n --watch Watch mode\n --no-gitignore Don't use .gitignore\n --include Report only provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,binaries,unresolved\n --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates\n --files Shortcut for --include files\n --fix Fix issues\n --fix-type Fix only issues of type, can be comma-separated or repeated (2)\n --allow-remove-files Allow Knip to remove files (with --fix)\n --include-libs Include type definitions from external dependencies (default: false)\n --include-entry-exports Include entry files when reporting unused exports\n --isolate-workspaces Isolate workspaces into separate programs\n -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)\n --preprocessor Preprocess the results before providing it to the reporter(s), can be repeated\n --preprocessor-options Pass extra options to the preprocessor (as JSON string, see --reporter-options example)\n --reporter Select reporter: symbols, compact, codeowners, json, can be repeated (default: symbols)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --tags Include or exclude tagged exports\n --no-config-hints Suppress configuration hints\n --no-exit-code Always exit with code zero (0)\n --max-issues Maximum number of issues before non-zero exit code (default: 0)\n -d, --debug Show debug output\n --trace Show trace output\n --trace-export [name] Show trace output for named export(s)\n --trace-file [file] Show trace output for exports in file\n --performance Measure count and running time of expensive functions and display stats table\n -h, --help Print this help text\n -V, --version Print version\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, classMembers, types, nsTypes, enumMembers, duplicates\n(2) Fixable issue types: dependencies, exports, types\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --tags=-lintignore\n\nWebsite: https://knip.dev";
1
+ export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no test files, devDependencies)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n -W, --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)\n --directory [dir] Run process from a different directory (default: cwd)\n --cache Enable caching\n --cache-location Change cache location (default: node_modules/.cache/knip)\n --watch Watch mode\n --no-gitignore Don't use .gitignore\n --include Report only provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,binaries,unresolved\n --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates\n --files Shortcut for --include files\n --fix Fix issues\n --fix-type Fix only issues of type, can be comma-separated or repeated (2)\n --allow-remove-files Allow Knip to remove files (with --fix)\n --include-libs Include type definitions from external dependencies (default: false)\n --include-entry-exports Include entry files when reporting unused exports\n --isolate-workspaces Isolate workspaces into separate programs\n -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)\n --preprocessor Preprocess the results before providing it to the reporter(s), can be repeated\n --preprocessor-options Pass extra options to the preprocessor (as JSON string, see --reporter-options example)\n --reporter Select reporter: symbols, compact, codeowners, json, codeclimate, markdown, disclosure, can be repeated (default: symbols)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --tags Include or exclude tagged exports\n --no-config-hints Suppress configuration hints\n --treat-config-hints-as-errors Exit with non-zero code (1) if there are any configuration hints\n --no-exit-code Always exit with code zero (0)\n --max-issues Maximum number of issues before non-zero exit code (default: 0)\n -d, --debug Show debug output\n --trace Show trace output\n --trace-export [name] Show trace output for named export(s)\n --trace-file [file] Show trace output for exports in file\n --performance Measure count and running time of expensive functions and display stats table\n -h, --help Print this help text\n -V, --version Print version\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, classMembers, types, nsTypes, enumMembers, duplicates\n(2) Fixable issue types: dependencies, exports, types\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --tags=-lintignore\n\nWebsite: https://knip.dev";
2
2
  declare const _default: {
3
3
  cache?: boolean | undefined;
4
4
  'cache-location'?: string | undefined;
@@ -35,6 +35,7 @@ declare const _default: {
35
35
  trace?: boolean | undefined;
36
36
  'trace-export'?: string | undefined;
37
37
  'trace-file'?: string | undefined;
38
+ 'treat-config-hints-as-errors'?: boolean | undefined;
38
39
  tsConfig?: string | undefined;
39
40
  version?: boolean | undefined;
40
41
  watch?: boolean | undefined;
@@ -28,10 +28,11 @@ Options:
28
28
  -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)
29
29
  --preprocessor Preprocess the results before providing it to the reporter(s), can be repeated
30
30
  --preprocessor-options Pass extra options to the preprocessor (as JSON string, see --reporter-options example)
31
- --reporter Select reporter: symbols, compact, codeowners, json, can be repeated (default: symbols)
31
+ --reporter Select reporter: symbols, compact, codeowners, json, codeclimate, markdown, disclosure, can be repeated (default: symbols)
32
32
  --reporter-options Pass extra options to the reporter (as JSON string, see example)
33
33
  --tags Include or exclude tagged exports
34
34
  --no-config-hints Suppress configuration hints
35
+ --treat-config-hints-as-errors Exit with non-zero code (1) if there are any configuration hints
35
36
  --no-exit-code Always exit with code zero (0)
36
37
  --max-issues Maximum number of issues before non-zero exit code (default: 0)
37
38
  -d, --debug Show debug output
@@ -94,6 +95,7 @@ try {
94
95
  trace: { type: 'boolean' },
95
96
  'trace-export': { type: 'string' },
96
97
  'trace-file': { type: 'string' },
98
+ 'treat-config-hints-as-errors': { type: 'boolean' },
97
99
  tsConfig: { type: 'string', short: 't' },
98
100
  version: { type: 'boolean', short: 'V' },
99
101
  watch: { type: 'boolean' },
@@ -2,7 +2,7 @@ import { ISSUE_TYPES } from '../constants.js';
2
2
  export const initIssues = () => ({
3
3
  ...Object.fromEntries(ISSUE_TYPES.map(issueType => [issueType, {}])),
4
4
  files: new Set(),
5
- _files: new Set(),
5
+ _files: {},
6
6
  });
7
7
  export const initCounters = () => ({
8
8
  ...Object.fromEntries(ISSUE_TYPES.map(issueType => [issueType, 0])),
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.45.0";
1
+ export declare const version = "5.46.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.45.0';
1
+ export const version = '5.46.0';
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.45.0",
3
+ "version": "5.46.0",
4
4
  "description": "Find and fix unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/webpro-nl/knip",
8
+ "url": "git+https://github.com/webpro-nl/knip.git",
9
9
  "directory": "packages/knip"
10
10
  },
11
11
  "bugs": "https://github.com/webpro-nl/knip/issues",
@@ -30,8 +30,8 @@
30
30
  ],
31
31
  "main": "./dist/index.js",
32
32
  "bin": {
33
- "knip": "./bin/knip.js",
34
- "knip-bun": "./bin/knip-bun.js"
33
+ "knip": "bin/knip.js",
34
+ "knip-bun": "bin/knip-bun.js"
35
35
  },
36
36
  "type": "module",
37
37
  "types": "./dist/index.d.ts",
@@ -49,7 +49,7 @@
49
49
  "qa": "bun lint && bun run build && bun knip && bun knip:production && bun run test",
50
50
  "release": "release-it",
51
51
  "create-plugin": "bun ./scripts/create-new-plugin.ts",
52
- "postcreate-plugin": "bun run build && biome format --write schema.json schema-jsonc.json src/ConfigurationValidator.ts",
52
+ "postcreate-plugin": "bun run build && biome format --write schema.json schema-jsonc.json src/schema/plugins.ts",
53
53
  "generate-plugin-defs": "node ./scripts/generate-plugin-defs.js && biome check --write src/plugins/index.ts src/types/PluginNames.ts src/schema/plugins.ts"
54
54
  },
55
55
  "files": [
@@ -90,7 +90,7 @@
90
90
  "@types/webpack": "^5.28.5",
91
91
  "@wdio/types": "^9.5.0",
92
92
  "glob": "^10.4.2",
93
- "release-it": "^18.1.2",
93
+ "release-it": "^19.0.0-next.1",
94
94
  "type-fest": "^4.31.0",
95
95
  "typescript": "^5.5.2"
96
96
  },
package/schema.json CHANGED
@@ -102,6 +102,11 @@
102
102
  "title": "Include entry files when reporting unused exports",
103
103
  "type": "boolean"
104
104
  },
105
+ "tags": {
106
+ "title": "Exclude (-) or include (+) exports with the specified JSDoc/TSDoc tags",
107
+ "examples": ["+custom", "-lintignore", "-@internal"],
108
+ "$ref": "#/definitions/list"
109
+ },
105
110
  "workspaces": {
106
111
  "title": "Configuration for workspaces",
107
112
  "type": "object",