knip 5.65.0 → 5.66.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.
@@ -147,6 +147,11 @@ export declare class ConfigurationChief {
147
147
  entry?: string | string[] | undefined;
148
148
  project?: string | string[] | undefined;
149
149
  } | undefined;
150
+ danger?: string | boolean | string[] | {
151
+ config?: string | string[] | undefined;
152
+ entry?: string | string[] | undefined;
153
+ project?: string | string[] | undefined;
154
+ } | undefined;
150
155
  'dependency-cruiser'?: string | boolean | string[] | {
151
156
  config?: string | string[] | undefined;
152
157
  entry?: string | string[] | undefined;
@@ -658,6 +663,7 @@ export declare class ConfigurationChief {
658
663
  cspell?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
659
664
  cucumber?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
660
665
  cypress?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
666
+ danger?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
661
667
  "dependency-cruiser"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
662
668
  docusaurus?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
663
669
  dotenv?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -98,6 +98,7 @@ export class ConfigurationChief {
98
98
  const ignoreMembers = rawConfig.ignoreMembers ?? [];
99
99
  const ignoreUnresolved = rawConfig.ignoreUnresolved ?? [];
100
100
  const ignoreExportsUsedInFile = rawConfig.ignoreExportsUsedInFile ?? false;
101
+ const ignoreIssues = rawConfig.ignoreIssues;
101
102
  const ignoreWorkspaces = rawConfig.ignoreWorkspaces ?? defaultConfig.ignoreWorkspaces;
102
103
  const isIncludeEntryExports = rawConfig.includeEntryExports ?? this.isIncludeEntryExports;
103
104
  const { syncCompilers, asyncCompilers } = rawConfig;
@@ -115,6 +116,7 @@ export class ConfigurationChief {
115
116
  ignoreMembers,
116
117
  ignoreUnresolved,
117
118
  ignoreExportsUsedInFile,
119
+ ignoreIssues,
118
120
  ignoreWorkspaces,
119
121
  isIncludeEntryExports,
120
122
  syncCompilers: new Map(Object.entries(syncCompilers ?? {})),
@@ -1,3 +1,4 @@
1
+ import type { IgnoreIssues } from './types/config.js';
1
2
  import type { ConfigurationHint, Issue, TagHint } from './types/issues.js';
2
3
  import type { MainOptions } from './util/create-options.js';
3
4
  export declare class IssueCollector {
@@ -13,9 +14,12 @@ export declare class IssueCollector {
13
14
  private ignoreFilesPatterns;
14
15
  private isMatch;
15
16
  private isFileMatch;
17
+ private issueMatchers;
16
18
  constructor(options: MainOptions);
17
19
  addIgnorePatterns(patterns: string[]): void;
18
20
  addIgnoreFilesPatterns(patterns: string[]): void;
21
+ setIgnoreIssues(ignoreIssues?: IgnoreIssues): void;
22
+ private shouldIgnoreIssue;
19
23
  addFileCounts({ processed, unused }: {
20
24
  processed: number;
21
25
  unused: number;
@@ -16,6 +16,7 @@ export class IssueCollector {
16
16
  ignoreFilesPatterns = new Set();
17
17
  isMatch;
18
18
  isFileMatch;
19
+ issueMatchers = new Map();
19
20
  constructor(options) {
20
21
  this.cwd = options.cwd;
21
22
  this.rules = options.rules;
@@ -26,14 +27,37 @@ export class IssueCollector {
26
27
  addIgnorePatterns(patterns) {
27
28
  for (const pattern of patterns)
28
29
  this.ignorePatterns.add(pattern);
29
- const _patterns = Array.from(this.ignorePatterns);
30
- this.isMatch = (filePath) => isMatch(filePath, _patterns, { dot: true });
30
+ const p = [...this.ignorePatterns];
31
+ this.isMatch = (filePath) => isMatch(filePath, p, { dot: true });
31
32
  }
32
33
  addIgnoreFilesPatterns(patterns) {
33
34
  for (const pattern of patterns)
34
35
  this.ignoreFilesPatterns.add(pattern);
35
- const _patterns = Array.from(this.ignoreFilesPatterns);
36
- this.isFileMatch = (filePath) => isMatch(filePath, _patterns, { dot: true });
36
+ const p = [...this.ignoreFilesPatterns];
37
+ this.isFileMatch = (filePath) => isMatch(filePath, p, { dot: true });
38
+ }
39
+ setIgnoreIssues(ignoreIssues) {
40
+ if (!ignoreIssues)
41
+ return;
42
+ const issueTypePatterns = new Map();
43
+ for (const [pattern, issueTypes] of Object.entries(ignoreIssues)) {
44
+ for (const issueType of issueTypes) {
45
+ if (!issueTypePatterns.has(issueType)) {
46
+ issueTypePatterns.set(issueType, []);
47
+ }
48
+ issueTypePatterns.get(issueType)?.push(pattern);
49
+ }
50
+ }
51
+ for (const [issueType, patterns] of issueTypePatterns) {
52
+ this.issueMatchers.set(issueType, (filePath) => isMatch(filePath, patterns, { dot: true }));
53
+ }
54
+ }
55
+ shouldIgnoreIssue(filePath, issueType) {
56
+ const matcher = this.issueMatchers.get(issueType);
57
+ if (!matcher)
58
+ return false;
59
+ const relativePath = relative(this.cwd, filePath);
60
+ return matcher(relativePath);
37
61
  }
38
62
  addFileCounts({ processed, unused }) {
39
63
  this.counters.processed += processed;
@@ -49,6 +73,8 @@ export class IssueCollector {
49
73
  continue;
50
74
  if (this.isFileMatch(filePath))
51
75
  continue;
76
+ if (this.shouldIgnoreIssue(filePath, 'files'))
77
+ continue;
52
78
  this.issues.files.add(filePath);
53
79
  const symbol = relative(this.cwd, filePath);
54
80
  this.issues._files[symbol] = [{ type: 'files', filePath, symbol, severity: this.rules.files }];
@@ -61,6 +87,8 @@ export class IssueCollector {
61
87
  return;
62
88
  if (this.isMatch(issue.filePath))
63
89
  return;
90
+ if (this.shouldIgnoreIssue(issue.filePath, issue.type))
91
+ return;
64
92
  const key = relative(this.cwd, issue.filePath);
65
93
  const { type } = issue;
66
94
  issue.severity = this.rules[type];
@@ -99,6 +99,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
99
99
  entry?: string | string[] | undefined;
100
100
  project?: string | string[] | undefined;
101
101
  } | undefined;
102
+ danger?: string | boolean | string[] | {
103
+ config?: string | string[] | undefined;
104
+ entry?: string | string[] | undefined;
105
+ project?: string | string[] | undefined;
106
+ } | undefined;
102
107
  'dependency-cruiser'?: string | boolean | string[] | {
103
108
  config?: string | string[] | undefined;
104
109
  entry?: string | string[] | undefined;
@@ -670,6 +675,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
670
675
  entry?: string | string[] | undefined;
671
676
  project?: string | string[] | undefined;
672
677
  } | undefined;
678
+ danger?: string | boolean | string[] | {
679
+ config?: string | string[] | undefined;
680
+ entry?: string | string[] | undefined;
681
+ project?: string | string[] | undefined;
682
+ } | undefined;
673
683
  'dependency-cruiser'?: string | boolean | string[] | {
674
684
  config?: string | string[] | undefined;
675
685
  entry?: string | string[] | undefined;
@@ -1177,6 +1187,7 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
1177
1187
  member?: boolean | undefined;
1178
1188
  type?: boolean | undefined;
1179
1189
  } | undefined;
1190
+ ignoreIssues?: Record<string, ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[]> | undefined;
1180
1191
  ignoreWorkspaces?: string[] | undefined;
1181
1192
  includeEntryExports?: boolean | undefined;
1182
1193
  compilers?: Record<string, true | ((filename: string, contents: string) => string) | ((filename: string, contents: string) => Promise<string>)> | undefined;
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ export const main = async (options) => {
24
24
  streamer.cast('Reading workspace configuration');
25
25
  const workspaces = await chief.getWorkspaces();
26
26
  const isGitIgnored = await getGitIgnoredHandler(options);
27
+ collector.setIgnoreIssues(chief.config.ignoreIssues);
27
28
  debugLogObject('*', 'Included workspaces', () => workspaces.map(w => w.pkgName));
28
29
  debugLogObject('*', 'Included workspace configs', () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors })));
29
30
  const { graph, entryPaths, analyzedFiles, unreferencedFiles, analyzeSourceFile } = await build({
@@ -0,0 +1,8 @@
1
+ import type { IsPluginEnabled } from '../../types/config.js';
2
+ declare const _default: {
3
+ title: string;
4
+ enablers: string[];
5
+ isEnabled: IsPluginEnabled;
6
+ entry: string[];
7
+ };
8
+ export default _default;
@@ -0,0 +1,11 @@
1
+ import { hasDependency } from '../../util/plugin.js';
2
+ const title = 'Danger';
3
+ const enablers = ['danger'];
4
+ const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
+ const entry = ['dangerfile.{js,cjs,mjs,ts}'];
6
+ export default {
7
+ title,
8
+ enablers,
9
+ isEnabled,
10
+ entry,
11
+ };
@@ -82,6 +82,7 @@ export declare class DummyEleventyConfig {
82
82
  setLayoutsDirectory(): void;
83
83
  setFreezeReservedData(): void;
84
84
  addDateParsing(): void;
85
+ addBundle(): void;
85
86
  _uniqueId: {};
86
87
  events: {};
87
88
  benchmarkManager: {};
@@ -91,6 +91,7 @@ export class DummyEleventyConfig {
91
91
  setLayoutsDirectory() { }
92
92
  setFreezeReservedData() { }
93
93
  addDateParsing() { }
94
+ addBundle() { }
94
95
  _uniqueId = {};
95
96
  events = {};
96
97
  benchmarkManager = {};
@@ -141,6 +141,12 @@ export declare const Plugins: {
141
141
  entry: string[];
142
142
  resolveConfig: import("../types/config.js").ResolveConfig<import("./cypress/types.js").CypressConfig>;
143
143
  };
144
+ danger: {
145
+ title: string;
146
+ enablers: string[];
147
+ isEnabled: import("../types/config.js").IsPluginEnabled;
148
+ entry: string[];
149
+ };
144
150
  'dependency-cruiser': {
145
151
  title: string;
146
152
  enablers: string[];
@@ -17,6 +17,7 @@ import { default as createTypescriptApp } from './create-typescript-app/index.js
17
17
  import { default as cspell } from './cspell/index.js';
18
18
  import { default as cucumber } from './cucumber/index.js';
19
19
  import { default as cypress } from './cypress/index.js';
20
+ import { default as danger } from './danger/index.js';
20
21
  import { default as dependencyCruiser } from './dependency-cruiser/index.js';
21
22
  import { default as docusaurus } from './docusaurus/index.js';
22
23
  import { default as dotenv } from './dotenv/index.js';
@@ -132,6 +133,7 @@ export const Plugins = {
132
133
  cspell,
133
134
  cucumber,
134
135
  cypress,
136
+ danger,
135
137
  'dependency-cruiser': dependencyCruiser,
136
138
  docusaurus,
137
139
  dotenv,
@@ -97,6 +97,11 @@ export declare const knipConfigurationSchema: z.ZodMiniObject<{
97
97
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
98
98
  project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
99
99
  }, z.core.$strip>]>>;
100
+ danger: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
101
+ config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
102
+ entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
103
+ project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
104
+ }, z.core.$strip>]>>;
100
105
  'dependency-cruiser': z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
101
106
  config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
102
107
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
@@ -668,6 +673,11 @@ export declare const knipConfigurationSchema: z.ZodMiniObject<{
668
673
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
669
674
  project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
670
675
  }, z.core.$strip>]>>;
676
+ danger: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
677
+ config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
678
+ entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
679
+ project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
680
+ }, z.core.$strip>]>>;
671
681
  'dependency-cruiser': z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
672
682
  config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
673
683
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
@@ -1179,6 +1189,7 @@ export declare const knipConfigurationSchema: z.ZodMiniObject<{
1179
1189
  member: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1180
1190
  type: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1181
1191
  }, z.core.$strict>]>>;
1192
+ ignoreIssues: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniUnion<readonly [z.ZodMiniLiteral<"files">, z.ZodMiniLiteral<"dependencies">, z.ZodMiniLiteral<"devDependencies">, z.ZodMiniLiteral<"optionalPeerDependencies">, z.ZodMiniLiteral<"unlisted">, z.ZodMiniLiteral<"binaries">, z.ZodMiniLiteral<"unresolved">, z.ZodMiniLiteral<"exports">, z.ZodMiniLiteral<"types">, z.ZodMiniLiteral<"nsExports">, z.ZodMiniLiteral<"nsTypes">, z.ZodMiniLiteral<"duplicates">, z.ZodMiniLiteral<"enumMembers">, z.ZodMiniLiteral<"classMembers">]>>>>;
1182
1193
  ignoreWorkspaces: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
1183
1194
  includeEntryExports: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1184
1195
  compilers: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniUnion<readonly [z.ZodMiniLiteral<true>, z.ZodMiniCustom<SyncCompiler, SyncCompiler>]>, z.ZodMiniCustom<AsyncCompiler, AsyncCompiler>]>>>;
@@ -32,6 +32,7 @@ const ignoreExportsUsedInFileObjectSchema = z.strictObject({
32
32
  type: z.optional(z.boolean()),
33
33
  });
34
34
  const ignoreExportsUsedInFileSchema = z.union([z.boolean(), ignoreExportsUsedInFileObjectSchema]);
35
+ const ignoreIssuesSchema = z.record(z.string(), z.array(issueTypeSchema));
35
36
  const rootConfigurationSchema = z.object({
36
37
  $schema: z.optional(z.string()),
37
38
  rules: z.optional(rulesSchema),
@@ -45,6 +46,7 @@ const rootConfigurationSchema = z.object({
45
46
  ignoreMembers: z.optional(stringOrRegexSchema),
46
47
  ignoreUnresolved: z.optional(stringOrRegexSchema),
47
48
  ignoreExportsUsedInFile: z.optional(ignoreExportsUsedInFileSchema),
49
+ ignoreIssues: z.optional(ignoreIssuesSchema),
48
50
  ignoreWorkspaces: z.optional(z.array(z.string())),
49
51
  includeEntryExports: z.optional(z.boolean()),
50
52
  compilers: z.optional(compilersSchema),
@@ -101,6 +101,11 @@ export declare const pluginsSchema: z.ZodMiniObject<{
101
101
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
102
102
  project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
103
103
  }, z.core.$strip>]>;
104
+ danger: z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
105
+ config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
106
+ entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
107
+ project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
108
+ }, z.core.$strip>]>;
104
109
  'dependency-cruiser': z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
105
110
  config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
106
111
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
@@ -29,6 +29,7 @@ export const pluginsSchema = z.object({
29
29
  cspell: pluginSchema,
30
30
  cucumber: pluginSchema,
31
31
  cypress: pluginSchema,
32
+ danger: pluginSchema,
32
33
  'dependency-cruiser': pluginSchema,
33
34
  docusaurus: pluginSchema,
34
35
  dotenv: pluginSchema,
@@ -1,2 +1,2 @@
1
- export type PluginName = 'angular' | 'astro' | 'ava' | 'babel' | 'biome' | 'bumpp' | 'bun' | 'c8' | 'capacitor' | 'changelogen' | 'changelogithub' | 'changesets' | 'commitizen' | 'commitlint' | 'convex' | 'create-typescript-app' | 'cspell' | 'cucumber' | 'cypress' | 'dependency-cruiser' | 'docusaurus' | 'dotenv' | 'drizzle' | 'eleventy' | 'eslint' | 'expo' | 'gatsby' | 'github-action' | 'github-actions' | 'glob' | 'graphql-codegen' | 'hardhat' | 'husky' | 'i18next-parser' | 'jest' | 'karma' | 'ladle' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lockfile-lint' | 'lost-pixel' | 'markdownlint' | 'metro' | 'mocha' | 'moonrepo' | 'msw' | 'nano-staged' | 'nest' | 'netlify' | 'next' | 'node' | 'node-modules-inspector' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nx' | 'nyc' | 'oclif' | 'oxlint' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'pnpm' | 'postcss' | 'preconstruct' | 'prettier' | 'prisma' | 'react-cosmos' | 'react-router' | 'relay' | 'release-it' | 'remark' | 'remix' | 'rollup' | 'rsbuild' | 'rslib' | 'rspack' | 'rstest' | 'semantic-release' | 'sentry' | 'simple-git-hooks' | 'size-limit' | 'sst' | 'starlight' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'svgo' | 'syncpack' | 'tailwind' | 'travis' | 'ts-node' | 'tsdown' | 'tsup' | 'tsx' | 'typedoc' | 'typescript' | 'unbuild' | 'unocss' | 'vercel-og' | 'vike' | 'vite' | 'vitest' | 'vue' | 'webdriver-io' | 'webpack' | 'wireit' | 'wrangler' | 'xo' | 'yarn' | 'yorkie';
2
- export declare const pluginNames: readonly ["angular", "astro", "ava", "babel", "biome", "bumpp", "bun", "c8", "capacitor", "changelogen", "changelogithub", "changesets", "commitizen", "commitlint", "convex", "create-typescript-app", "cspell", "cucumber", "cypress", "dependency-cruiser", "docusaurus", "dotenv", "drizzle", "eleventy", "eslint", "expo", "gatsby", "github-action", "github-actions", "glob", "graphql-codegen", "hardhat", "husky", "i18next-parser", "jest", "karma", "ladle", "lefthook", "lint-staged", "linthtml", "lockfile-lint", "lost-pixel", "markdownlint", "metro", "mocha", "moonrepo", "msw", "nano-staged", "nest", "netlify", "next", "node", "node-modules-inspector", "nodemon", "npm-package-json-lint", "nuxt", "nx", "nyc", "oclif", "oxlint", "playwright", "playwright-ct", "playwright-test", "plop", "pnpm", "postcss", "preconstruct", "prettier", "prisma", "react-cosmos", "react-router", "relay", "release-it", "remark", "remix", "rollup", "rsbuild", "rslib", "rspack", "rstest", "semantic-release", "sentry", "simple-git-hooks", "size-limit", "sst", "starlight", "storybook", "stryker", "stylelint", "svelte", "svgo", "syncpack", "tailwind", "travis", "ts-node", "tsdown", "tsup", "tsx", "typedoc", "typescript", "unbuild", "unocss", "vercel-og", "vike", "vite", "vitest", "vue", "webdriver-io", "webpack", "wireit", "wrangler", "xo", "yarn", "yorkie"];
1
+ export type PluginName = 'angular' | 'astro' | 'ava' | 'babel' | 'biome' | 'bumpp' | 'bun' | 'c8' | 'capacitor' | 'changelogen' | 'changelogithub' | 'changesets' | 'commitizen' | 'commitlint' | 'convex' | 'create-typescript-app' | 'cspell' | 'cucumber' | 'cypress' | 'danger' | 'dependency-cruiser' | 'docusaurus' | 'dotenv' | 'drizzle' | 'eleventy' | 'eslint' | 'expo' | 'gatsby' | 'github-action' | 'github-actions' | 'glob' | 'graphql-codegen' | 'hardhat' | 'husky' | 'i18next-parser' | 'jest' | 'karma' | 'ladle' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lockfile-lint' | 'lost-pixel' | 'markdownlint' | 'metro' | 'mocha' | 'moonrepo' | 'msw' | 'nano-staged' | 'nest' | 'netlify' | 'next' | 'node' | 'node-modules-inspector' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nx' | 'nyc' | 'oclif' | 'oxlint' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'pnpm' | 'postcss' | 'preconstruct' | 'prettier' | 'prisma' | 'react-cosmos' | 'react-router' | 'relay' | 'release-it' | 'remark' | 'remix' | 'rollup' | 'rsbuild' | 'rslib' | 'rspack' | 'rstest' | 'semantic-release' | 'sentry' | 'simple-git-hooks' | 'size-limit' | 'sst' | 'starlight' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'svgo' | 'syncpack' | 'tailwind' | 'travis' | 'ts-node' | 'tsdown' | 'tsup' | 'tsx' | 'typedoc' | 'typescript' | 'unbuild' | 'unocss' | 'vercel-og' | 'vike' | 'vite' | 'vitest' | 'vue' | 'webdriver-io' | 'webpack' | 'wireit' | 'wrangler' | 'xo' | 'yarn' | 'yorkie';
2
+ export declare const pluginNames: readonly ["angular", "astro", "ava", "babel", "biome", "bumpp", "bun", "c8", "capacitor", "changelogen", "changelogithub", "changesets", "commitizen", "commitlint", "convex", "create-typescript-app", "cspell", "cucumber", "cypress", "danger", "dependency-cruiser", "docusaurus", "dotenv", "drizzle", "eleventy", "eslint", "expo", "gatsby", "github-action", "github-actions", "glob", "graphql-codegen", "hardhat", "husky", "i18next-parser", "jest", "karma", "ladle", "lefthook", "lint-staged", "linthtml", "lockfile-lint", "lost-pixel", "markdownlint", "metro", "mocha", "moonrepo", "msw", "nano-staged", "nest", "netlify", "next", "node", "node-modules-inspector", "nodemon", "npm-package-json-lint", "nuxt", "nx", "nyc", "oclif", "oxlint", "playwright", "playwright-ct", "playwright-test", "plop", "pnpm", "postcss", "preconstruct", "prettier", "prisma", "react-cosmos", "react-router", "relay", "release-it", "remark", "remix", "rollup", "rsbuild", "rslib", "rspack", "rstest", "semantic-release", "sentry", "simple-git-hooks", "size-limit", "sst", "starlight", "storybook", "stryker", "stylelint", "svelte", "svgo", "syncpack", "tailwind", "travis", "ts-node", "tsdown", "tsup", "tsx", "typedoc", "typescript", "unbuild", "unocss", "vercel-og", "vike", "vite", "vitest", "vue", "webdriver-io", "webpack", "wireit", "wrangler", "xo", "yarn", "yorkie"];
@@ -18,6 +18,7 @@ export const pluginNames = [
18
18
  'cspell',
19
19
  'cucumber',
20
20
  'cypress',
21
+ 'danger',
21
22
  'dependency-cruiser',
22
23
  'docusaurus',
23
24
  'dotenv',
@@ -5,7 +5,7 @@ import type { knipConfigurationSchema } from '../schema/configuration.js';
5
5
  import type { pluginSchema } from '../schema/plugins.js';
6
6
  import type { Input } from '../util/input.js';
7
7
  import type { Args } from './args.js';
8
- import type { SymbolType } from './issues.js';
8
+ import type { IssueType, SymbolType } from './issues.js';
9
9
  import type { Tags } from './options.js';
10
10
  import type { PluginName } from './PluginNames.js';
11
11
  import type { PackageJson } from './package-json.js';
@@ -25,6 +25,7 @@ export type RawPluginConfiguration = z.infer<typeof pluginSchema>;
25
25
  export type IgnorePatterns = (string | RegExp)[];
26
26
  type IgnorableExport = Exclude<SymbolType, SymbolType.UNKNOWN>;
27
27
  export type IgnoreExportsUsedInFile = boolean | Partial<Record<IgnorableExport, boolean>>;
28
+ export type IgnoreIssues = Record<string, IssueType[]>;
28
29
  export type GetImportsAndExportsOptions = {
29
30
  skipTypeOnly: boolean;
30
31
  isFixExports: boolean;
@@ -38,6 +39,7 @@ export interface Configuration {
38
39
  ignoreBinaries: IgnorePatterns;
39
40
  ignoreDependencies: IgnorePatterns;
40
41
  ignoreExportsUsedInFile: IgnoreExportsUsedInFile;
42
+ ignoreIssues?: IgnoreIssues;
41
43
  ignoreMembers: IgnorePatterns;
42
44
  ignoreUnresolved: IgnorePatterns;
43
45
  ignoreWorkspaces: string[];
@@ -133,6 +133,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
133
133
  entry?: string | string[] | undefined;
134
134
  project?: string | string[] | undefined;
135
135
  } | undefined;
136
+ danger?: string | boolean | string[] | {
137
+ config?: string | string[] | undefined;
138
+ entry?: string | string[] | undefined;
139
+ project?: string | string[] | undefined;
140
+ } | undefined;
136
141
  'dependency-cruiser'?: string | boolean | string[] | {
137
142
  config?: string | string[] | undefined;
138
143
  entry?: string | string[] | undefined;
@@ -704,6 +709,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
704
709
  entry?: string | string[] | undefined;
705
710
  project?: string | string[] | undefined;
706
711
  } | undefined;
712
+ danger?: string | boolean | string[] | {
713
+ config?: string | string[] | undefined;
714
+ entry?: string | string[] | undefined;
715
+ project?: string | string[] | undefined;
716
+ } | undefined;
707
717
  'dependency-cruiser'?: string | boolean | string[] | {
708
718
  config?: string | string[] | undefined;
709
719
  entry?: string | string[] | undefined;
@@ -1211,6 +1221,7 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1211
1221
  member?: boolean | undefined;
1212
1222
  type?: boolean | undefined;
1213
1223
  } | undefined;
1224
+ ignoreIssues?: Record<string, ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[]> | undefined;
1214
1225
  ignoreWorkspaces?: string[] | undefined;
1215
1226
  includeEntryExports?: boolean | undefined;
1216
1227
  compilers?: Record<string, true | ((filename: string, contents: string) => string) | ((filename: string, contents: string) => Promise<string>)> | undefined;
package/dist/util/fs.d.ts CHANGED
@@ -3,7 +3,8 @@ export declare const isFile: (filePath: string) => boolean;
3
3
  export declare const findFile: (workingDir: string, fileName: string) => string | undefined;
4
4
  export declare const loadFile: (filePath: string) => Promise<string>;
5
5
  export declare const loadJSON: (filePath: string) => Promise<any>;
6
+ export declare const loadJSONC: (filePath: string) => Promise<any>;
6
7
  export declare const loadYAML: (filePath: string) => Promise<unknown>;
7
8
  export declare const loadTOML: (filePath: string) => Promise<import("smol-toml").TomlTable>;
8
- export declare const parseJSON: (filePath: string, contents: string) => Promise<any>;
9
+ export declare const parseJSONC: (filePath: string, contents: string) => Promise<any>;
9
10
  export declare const parseYAML: (contents: string) => unknown;
package/dist/util/fs.js CHANGED
@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
4
4
  import { parse as parseTOML } from 'smol-toml';
5
5
  import stripJsonComments from 'strip-json-comments';
6
6
  import { LoaderError } from './errors.js';
7
- import { join } from './path.js';
7
+ import { extname, join } from './path.js';
8
8
  export const isDirectory = (filePath) => {
9
9
  try {
10
10
  return statSync(filePath).isDirectory();
@@ -36,7 +36,16 @@ export const loadFile = async (filePath) => {
36
36
  };
37
37
  export const loadJSON = async (filePath) => {
38
38
  const contents = await loadFile(filePath);
39
- return parseJSON(filePath, contents);
39
+ try {
40
+ return JSON.parse(contents);
41
+ }
42
+ catch {
43
+ return parseJSONC(filePath, contents);
44
+ }
45
+ };
46
+ export const loadJSONC = async (filePath) => {
47
+ const contents = await loadFile(filePath);
48
+ return parseJSONC(filePath, contents);
40
49
  };
41
50
  export const loadYAML = async (filePath) => {
42
51
  const contents = await loadFile(filePath);
@@ -46,12 +55,13 @@ export const loadTOML = async (filePath) => {
46
55
  const contents = await loadFile(filePath);
47
56
  return parseTOML(contents);
48
57
  };
49
- export const parseJSON = async (filePath, contents) => {
58
+ export const parseJSONC = async (filePath, contents) => {
50
59
  try {
51
60
  return JSON.parse(stripJsonComments(contents, { trailingCommas: true, whitespace: false }));
52
61
  }
53
62
  catch (error) {
54
- throw new LoaderError(`Error parsing ${filePath}`, { cause: error });
63
+ const message = `Error parsing ${filePath} ${extname(filePath) === '.json5' ? 'JSON5 features beyond comments and trailing commas are not fully supported. Consider converting to .jsonc format.' : ''}`;
64
+ throw new LoaderError(message, { cause: error });
55
65
  }
56
66
  };
57
67
  export const parseYAML = (contents) => {
@@ -1,5 +1,5 @@
1
1
  import { LoaderError } from './errors.js';
2
- import { loadFile, loadJSON, loadTOML, loadYAML, parseJSON, parseYAML } from './fs.js';
2
+ import { loadFile, loadJSON, loadJSONC, loadTOML, loadYAML, parseJSONC, parseYAML } from './fs.js';
3
3
  import { jiti } from './jiti.js';
4
4
  import { timerify } from './Performance.js';
5
5
  import { extname, isInternal } from './path.js';
@@ -12,7 +12,7 @@ const load = async (filePath) => {
12
12
  return parseYAML(contents);
13
13
  }
14
14
  catch {
15
- return parseJSON(filePath, contents);
15
+ return parseJSONC(filePath, contents);
16
16
  }
17
17
  }
18
18
  if (ext === '.yaml' || ext === '.yml') {
@@ -21,9 +21,12 @@ const load = async (filePath) => {
21
21
  if (ext === '' && isInternal(filePath)) {
22
22
  return await loadFile(filePath);
23
23
  }
24
- if (ext === '.json' || ext === '.jsonc' || ext === '.json5') {
24
+ if (ext === '.json') {
25
25
  return await loadJSON(filePath);
26
26
  }
27
+ if (ext === '.jsonc' || ext === '.json5') {
28
+ return await loadJSONC(filePath);
29
+ }
27
30
  if (typeof Bun !== 'undefined') {
28
31
  const imported = await import(filePath);
29
32
  return imported.default ?? imported;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.65.0";
1
+ export declare const version = "5.66.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.65.0';
1
+ export const version = '5.66.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.65.0",
3
+ "version": "5.66.0",
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": {
package/schema.json CHANGED
@@ -103,6 +103,19 @@
103
103
  }
104
104
  ]
105
105
  },
106
+ "ignoreIssues": {
107
+ "title": " Ignore specific issue types for specific file patterns",
108
+ "examples": [
109
+ {
110
+ "src/generated/**": ["exports", "types"],
111
+ "**/*.generated.ts": ["exports", "classMembers"]
112
+ }
113
+ ],
114
+ "type": "object",
115
+ "additionalProperties": {
116
+ "$ref": "#/definitions/issueTypes"
117
+ }
118
+ },
106
119
  "includeEntryExports": {
107
120
  "title": "Include entry files when reporting unused exports",
108
121
  "type": "boolean"
@@ -386,6 +399,10 @@
386
399
  "title": "Cypress plugin configuration (https://knip.dev/reference/plugins/cypress)",
387
400
  "$ref": "#/definitions/plugin"
388
401
  },
402
+ "danger": {
403
+ "title": "danger plugin configuration (https://knip.dev/reference/plugins/danger)",
404
+ "$ref": "#/definitions/plugin"
405
+ },
389
406
  "dependency-cruiser": {
390
407
  "title": "dependency-cruiser plugin configuration (https://knip.dev/reference/plugins/dependency-cruiser)",
391
408
  "$ref": "#/definitions/plugin"