knip 1.0.0-beta.1 → 1.0.0-beta.3

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.
package/README.md CHANGED
@@ -61,14 +61,14 @@ Create a configuration file, let's give it the default name `knip.json` with the
61
61
 
62
62
  ```json
63
63
  {
64
- "$schema": "https://unpkg.com/knip@alpha/schema.json",
64
+ "$schema": "https://unpkg.com/knip@next/schema.json",
65
65
  "entry": ["src/index.ts"],
66
66
  "project": ["src/**/*.ts"]
67
67
  }
68
68
  ```
69
69
 
70
- The `entry` files target the starting point(s) to resolve code dependencies. The `project` files should contain all
71
- files it should match them against, including potentially unused files.
70
+ The `entry` files target the starting point(s) to resolve the rest of the imported code. The `project` files should
71
+ contain all files to match against the files resolved from the entry files, including potentially unused files.
72
72
 
73
73
  Then run the checks:
74
74
 
@@ -184,7 +184,7 @@ be part of the analysis. Here's a simple example:
184
184
  ```jsonc
185
185
  {
186
186
  "ignore": "**/fixtures/**",
187
- "ignoreBinaries": ["deno", "git"],
187
+ "ignoreBinaries": ["rm", "docker-compose"],
188
188
  "ignoreWorkspaces": ["packages/ignore-me"],
189
189
  "workspaces": {
190
190
  "packages/*": {
@@ -262,7 +262,7 @@ idea of how they work and why they are needed:
262
262
  - Static configuration files such as JSON and YAML always require a custom dependency resolver.
263
263
 
264
264
  Custom dependency resolvers return all referenced dependencies for the configuration files it is given. Knip handles the
265
- rest.
265
+ rest to find which of those dependencies are unused or missing.
266
266
 
267
267
  ### `entry`
268
268
 
@@ -15,6 +15,7 @@ export default class ConfigurationChief {
15
15
  config: Configuration;
16
16
  manifestPath: undefined | string;
17
17
  manifest: undefined | PackageJson;
18
+ manifestWorkspaces: undefined | string[];
18
19
  constructor({ cwd, isStrict, isProduction }: ConfigurationManagerOptions);
19
20
  loadLocalConfig(): Promise<void>;
20
21
  normalize(rawLocalConfig: z.infer<typeof ConfigurationValidator>): {
@@ -35,7 +36,8 @@ export default class ConfigurationChief {
35
36
  config: WorkspaceConfiguration;
36
37
  ancestors: string[];
37
38
  }[]>;
38
- getNegatedWorkspacePatterns(): Promise<string[]>;
39
+ getDescendentWorkspaces(name: string): Promise<string[]>;
40
+ getNegatedWorkspacePatterns(name: string): Promise<string[]>;
39
41
  private getConfigKeyForWorkspace;
40
42
  private hasConfigForWorkspace;
41
43
  getConfigForWorkspace(workspaceName: string): WorkspaceConfiguration;
@@ -8,12 +8,12 @@ import { arrayify } from './util/array.js';
8
8
  import { ConfigurationError } from './util/errors.js';
9
9
  import { findFile, loadJSON } from './util/fs.js';
10
10
  import parsedArgs from './util/parseArgs.js';
11
- import { resolveIncludedIssueTypes } from './util/resolveIncludedIssueTypes.js';
11
+ import { resolveIncludedIssueTypes } from './util/resolve-included-issue-types.js';
12
12
  import { byPathDepth } from './util/workspace.js';
13
13
  const { values: { config: rawConfigArg, workspace: rawWorkspaceArg, include = [], exclude = [] }, } = parsedArgs;
14
14
  const defaultWorkspaceConfig = {
15
- entry: ['index.{js,ts,tsx}', 'src/index.{js,ts,tsx}'],
16
- project: ['**/*.{js,ts,tsx}'],
15
+ entry: ['index.{js,ts,tsx}!', 'src/index.{js,ts,tsx}!'],
16
+ project: ['**/*.{js,ts,tsx}!'],
17
17
  ignore: [],
18
18
  };
19
19
  const defaultConfig = {
@@ -35,6 +35,7 @@ export default class ConfigurationChief {
35
35
  config;
36
36
  manifestPath;
37
37
  manifest;
38
+ manifestWorkspaces;
38
39
  constructor({ cwd, isStrict, isProduction }) {
39
40
  this.cwd = cwd ?? this.cwd;
40
41
  this.isStrict = isStrict;
@@ -99,8 +100,8 @@ export default class ConfigurationChief {
99
100
  }
100
101
  else {
101
102
  const isObject = typeof pluginConfig !== 'string' && !Array.isArray(pluginConfig);
102
- const config = isObject ? arrayify(pluginConfig.config) : arrayify(pluginConfig);
103
- const entry = isObject && 'entry' in pluginConfig ? arrayify(pluginConfig.entry) : [];
103
+ const config = typeof pluginConfig === 'string' ? [pluginConfig] : isObject ? arrayify(pluginConfig.config) : null;
104
+ const entry = isObject && 'entry' in pluginConfig ? arrayify(pluginConfig.entry) : null;
104
105
  const project = isObject && 'project' in pluginConfig ? arrayify(pluginConfig.project) : entry;
105
106
  workspaces[workspaceName][pluginName] = {
106
107
  config,
@@ -115,6 +116,8 @@ export default class ConfigurationChief {
115
116
  };
116
117
  }
117
118
  async getManifestWorkspaces() {
119
+ if (this.manifestWorkspaces)
120
+ return this.manifestWorkspaces;
118
121
  if (this.manifest) {
119
122
  const workspaces = await mapWorkspaces({
120
123
  pkg: this.manifest,
@@ -122,7 +125,8 @@ export default class ConfigurationChief {
122
125
  ignore: this.config.ignoreWorkspaces,
123
126
  absolute: false,
124
127
  });
125
- return Array.from(workspaces.values()).map(workspaceDir => path.relative(this.cwd, workspaceDir));
128
+ this.manifestWorkspaces = Array.from(workspaces.values()).map(dir => path.relative(this.cwd, dir));
129
+ return this.manifestWorkspaces;
126
130
  }
127
131
  return [];
128
132
  }
@@ -172,11 +176,17 @@ export default class ConfigurationChief {
172
176
  }, []),
173
177
  }));
174
178
  }
175
- async getNegatedWorkspacePatterns() {
179
+ async getDescendentWorkspaces(name) {
176
180
  const manifestWorkspaces = await this.getManifestWorkspaces();
177
181
  const additionalWorkspaces = this.getAdditionalWorkspaces(manifestWorkspaces);
178
182
  return [...manifestWorkspaces, ...additionalWorkspaces]
179
- .filter(workspaceName => workspaceName !== ROOT_WORKSPACE_NAME)
183
+ .filter(workspaceName => workspaceName !== name)
184
+ .filter(workspaceName => name === ROOT_WORKSPACE_NAME || workspaceName.startsWith(name));
185
+ }
186
+ async getNegatedWorkspacePatterns(name) {
187
+ const descendentWorkspaces = await this.getDescendentWorkspaces(name);
188
+ return descendentWorkspaces
189
+ .map(workspaceName => path.relative(path.join(this.cwd, name), workspaceName))
180
190
  .map(workspaceName => `!${workspaceName}`);
181
191
  }
182
192
  getConfigKeyForWorkspace(workspaceName) {
@@ -191,9 +201,8 @@ export default class ConfigurationChief {
191
201
  }
192
202
  getConfigForWorkspace(workspaceName) {
193
203
  const key = this.getConfigKeyForWorkspace(workspaceName);
194
- if (key) {
195
- return this.config?.workspaces?.[key] ?? { entry: [], project: [], ignore: [] };
196
- }
204
+ if (key && this.config?.workspaces?.[key])
205
+ return this.config.workspaces[key];
197
206
  return { entry: [], project: [], ignore: [] };
198
207
  }
199
208
  resolveIncludedIssueTypes() {
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import ProjectPrincipal from './project-principal.js';
7
7
  import SourceLab from './source-lab.js';
8
8
  import { compact } from './util/array.js';
9
9
  import { debugLogObject, debugLogFiles } from './util/debug.js';
10
- import { _findImportModuleSpecifiers } from './util/externalImports.js';
10
+ import { _findImportModuleSpecifiers } from './util/find-import-specifiers.js';
11
11
  import { findFile, loadJSON } from './util/fs.js';
12
12
  import { _glob } from './util/glob.js';
13
13
  import { getPackageNameFromModuleSpecifier } from './util/modules.js';
@@ -24,7 +24,6 @@ export const main = async (unresolvedConfiguration) => {
24
24
  await chief.loadLocalConfig();
25
25
  const deputy = new DependencyDeputy({ ignoreDependencies: chief.config.ignoreDependencies });
26
26
  const workspaces = await chief.getActiveWorkspaces();
27
- const negatedWorkspacePatterns = await chief.getNegatedWorkspacePatterns();
28
27
  debugLogObject('Included workspaces', workspaces);
29
28
  const report = chief.resolveIncludedIssueTypes();
30
29
  const workspaceDirs = Object.values(workspaces)
@@ -54,6 +53,7 @@ export const main = async (unresolvedConfiguration) => {
54
53
  const workspaceManifest = deputy.getWorkspaceManifest(name);
55
54
  if (!workspaceManifest)
56
55
  continue;
56
+ const negatedWorkspacePatterns = await chief.getNegatedWorkspacePatterns(name);
57
57
  const worker = new WorkspaceWorker({
58
58
  name,
59
59
  dir,
@@ -0,0 +1,7 @@
1
+ import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ export declare const CONFIG_FILE_PATTERNS: never[];
3
+ export declare const ENTRY_FILE_PATTERNS: never[];
4
+ export declare const PRODUCTION_ENTRY_FILE_PATTERNS: never[];
5
+ export declare const PROJECT_FILE_PATTERNS: never[];
6
+ export declare const isEnabled: IsPluginEnabledCallback;
7
+ export declare const findDependencies: GenericPluginCallback;
@@ -0,0 +1,14 @@
1
+ import { _load } from '../../util/loader.js';
2
+ import { timerify } from '../../util/performance.js';
3
+ export const CONFIG_FILE_PATTERNS = [];
4
+ export const ENTRY_FILE_PATTERNS = [];
5
+ export const PRODUCTION_ENTRY_FILE_PATTERNS = [];
6
+ export const PROJECT_FILE_PATTERNS = [];
7
+ export const isEnabled = ({ dependencies }) => {
8
+ return dependencies.has('[pkg]');
9
+ };
10
+ const findPluginDependencies = async (configFilePath, { manifest }) => {
11
+ const config = configFilePath.endsWith('package.json') ? manifest.plugin : await _load(configFilePath);
12
+ return config?.plugins ?? [];
13
+ };
14
+ export const findDependencies = timerify(findPluginDependencies);
@@ -0,0 +1,3 @@
1
+ export type PluginConfig = {
2
+ plugins?: string[];
3
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,5 @@
1
1
  import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
2
  export declare const isEnabled: IsPluginEnabledCallback;
3
3
  export declare const CONFIG_FILE_PATTERNS: string[];
4
+ export declare const ENTRY_FILE_PATTERNS: string[];
4
5
  export declare const findDependencies: GenericPluginCallback;
@@ -3,12 +3,15 @@ import { getPackageName } from '../../util/modules.js';
3
3
  import { timerify } from '../../util/performance.js';
4
4
  export const isEnabled = ({ dependencies }) => dependencies.has('postcss');
5
5
  export const CONFIG_FILE_PATTERNS = ['postcss.config.js', 'package.json'];
6
+ export const ENTRY_FILE_PATTERNS = ['postcss.config.js'];
6
7
  const findPostCSSDependencies = async (configFilePath, { manifest }) => {
7
8
  const config = configFilePath.endsWith('package.json')
8
9
  ? manifest?.postcss
9
10
  : await _load(configFilePath);
10
11
  return config?.plugins
11
- ? (Array.isArray(config.plugins) ? config.plugins : Object.keys(config.plugins)).map(getPackageName)
12
+ ? (Array.isArray(config.plugins) ? config.plugins : Object.keys(config.plugins))
13
+ .filter(plugin => typeof plugin === 'string')
14
+ .map(getPackageName)
12
15
  : [];
13
16
  };
14
17
  export const findDependencies = timerify(findPostCSSDependencies);
@@ -1,34 +1,12 @@
1
+ import * as Plugins from '../plugins/index.js';
1
2
  type NormalizedGlob = string[];
3
+ export type PluginName = keyof typeof Plugins;
2
4
  export type PluginConfiguration = {
3
- config: NormalizedGlob;
4
- entry: NormalizedGlob;
5
- project: NormalizedGlob;
5
+ config: NormalizedGlob | null;
6
+ entry: NormalizedGlob | null;
7
+ project: NormalizedGlob | null;
6
8
  } | false;
7
- interface PluginsConfiguration {
8
- babel: PluginConfiguration;
9
- capacitor: PluginConfiguration;
10
- changesets: PluginConfiguration;
11
- commitlint: PluginConfiguration;
12
- cypress: PluginConfiguration;
13
- eslint: PluginConfiguration;
14
- gatsby: PluginConfiguration;
15
- jest: PluginConfiguration;
16
- mocha: PluginConfiguration;
17
- next: PluginConfiguration;
18
- nx: PluginConfiguration;
19
- nyc: PluginConfiguration;
20
- playwright: PluginConfiguration;
21
- postcss: PluginConfiguration;
22
- prettier: PluginConfiguration;
23
- remark: PluginConfiguration;
24
- remix: PluginConfiguration;
25
- rollup: PluginConfiguration;
26
- sentry: PluginConfiguration;
27
- storybook: PluginConfiguration;
28
- stryker: PluginConfiguration;
29
- typescript: PluginConfiguration;
30
- webpack: PluginConfiguration;
31
- }
9
+ type PluginsConfiguration = Record<PluginName, PluginConfiguration>;
32
10
  interface BaseWorkspaceConfiguration {
33
11
  entry: NormalizedGlob;
34
12
  project: NormalizedGlob;
@@ -36,7 +14,6 @@ interface BaseWorkspaceConfiguration {
36
14
  }
37
15
  export interface WorkspaceConfiguration extends BaseWorkspaceConfiguration, Partial<PluginsConfiguration> {
38
16
  }
39
- export type PluginName = keyof PluginsConfiguration;
40
17
  export interface Configuration {
41
18
  include: string[];
42
19
  exclude: string[];
@@ -30,8 +30,12 @@ const findImportModuleSpecifiers = (sourceFile, options = { skipInternal: false
30
30
  const moduleSpecifiers = compact([...importLiterals, ...requireCallExpressions].map(importLiteral => {
31
31
  if (!importLiteral)
32
32
  return;
33
- if (importLiteral.isKind(ts.SyntaxKind.TemplateExpression))
34
- return importLiteral.getFullText().slice(1, -1);
33
+ if (importLiteral.isKind(ts.SyntaxKind.TemplateExpression)) {
34
+ const literalText = importLiteral.getFullText();
35
+ if (literalText.includes('${'))
36
+ return;
37
+ return literalText.slice(1, -1);
38
+ }
35
39
  return importLiteral?.getLiteralText();
36
40
  }));
37
41
  const internalModuleSpecifiers = options.skipInternal ? [] : resolveInternal(filePath, moduleSpecifiers);
@@ -37,7 +37,7 @@ export default class WorkspaceWorker {
37
37
  this.enabled = Object.keys(plugins).reduce((enabled, pluginName) => ({ ...enabled, [pluginName]: false }), {});
38
38
  }
39
39
  getConfigForPlugin(pluginName) {
40
- return this.config[pluginName] ?? { config: [], entry: [], project: [] };
40
+ return this.config[pluginName] ?? { config: null, entry: null, project: null };
41
41
  }
42
42
  async init() {
43
43
  this.setEnabledPlugins();
@@ -76,7 +76,7 @@ export default class WorkspaceWorker {
76
76
  const { entry } = this.config;
77
77
  if (entry.length === 0)
78
78
  return [];
79
- return [entry, TEST_FILE_PATTERNS, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
79
+ return [entry, TEST_FILE_PATTERNS, this.negatedWorkspacePatterns].flat();
80
80
  }
81
81
  getProjectFilePatterns() {
82
82
  const { project } = this.config;
@@ -91,7 +91,7 @@ export default class WorkspaceWorker {
91
91
  negatedPluginEntryFilePatterns,
92
92
  negatedPluginProjectFilePatterns,
93
93
  TEST_FILE_PATTERNS,
94
- this.isRoot ? this.negatedWorkspacePatterns : [],
94
+ this.negatedWorkspacePatterns,
95
95
  ].flat();
96
96
  }
97
97
  getPluginEntryFilePatterns(isIncludeProductionEntryFiles = true) {
@@ -101,14 +101,14 @@ export default class WorkspaceWorker {
101
101
  if (this.enabled[pluginName] && pluginConfig) {
102
102
  const { entry } = pluginConfig;
103
103
  const defaultEntryFiles = 'ENTRY_FILE_PATTERNS' in plugin ? plugin.ENTRY_FILE_PATTERNS : [];
104
- patterns.push(...(entry.length > 0 ? entry : defaultEntryFiles));
104
+ patterns.push(...(entry ?? defaultEntryFiles));
105
105
  if (isIncludeProductionEntryFiles) {
106
106
  const entry = 'PRODUCTION_ENTRY_FILE_PATTERNS' in plugin ? plugin.PRODUCTION_ENTRY_FILE_PATTERNS : [];
107
107
  patterns.push(...entry);
108
108
  }
109
109
  }
110
110
  }
111
- return [patterns, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
111
+ return [patterns, this.negatedWorkspacePatterns].flat();
112
112
  }
113
113
  getPluginProjectFilePatterns() {
114
114
  const patterns = [];
@@ -116,18 +116,16 @@ export default class WorkspaceWorker {
116
116
  const pluginConfig = this.getConfigForPlugin(pluginName);
117
117
  if (this.enabled[pluginName] && pluginConfig) {
118
118
  const { entry, project } = pluginConfig;
119
- const defaultEntryFiles = 'ENTRY_FILE_PATTERNS' in plugin ? plugin.ENTRY_FILE_PATTERNS : [];
120
- const defaultProjectFiles = 'PROJECT_FILE_PATTERNS' in plugin ? plugin.PROJECT_FILE_PATTERNS : defaultEntryFiles;
121
- patterns.push(...(project.length > 0
122
- ? project
123
- : defaultProjectFiles.length > 0
124
- ? defaultProjectFiles
125
- : entry.length > 0
126
- ? entry
127
- : defaultEntryFiles));
119
+ patterns.push(...(project ??
120
+ entry ??
121
+ ('PROJECT_FILE_PATTERNS' in plugin
122
+ ? plugin.PROJECT_FILE_PATTERNS
123
+ : 'ENTRY_FILE_PATTERNS' in plugin
124
+ ? plugin.ENTRY_FILE_PATTERNS
125
+ : [])));
128
126
  }
129
127
  }
130
- return [patterns, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
128
+ return [patterns, this.negatedWorkspacePatterns].flat();
131
129
  }
132
130
  getPluginConfigPatterns() {
133
131
  const patterns = [];
@@ -136,7 +134,7 @@ export default class WorkspaceWorker {
136
134
  if (this.enabled[pluginName] && pluginConfig) {
137
135
  const { config } = pluginConfig;
138
136
  const defaultConfigFiles = 'CONFIG_FILE_PATTERNS' in plugin ? plugin.CONFIG_FILE_PATTERNS : [];
139
- patterns.push(...(config.length > 0 ? config : defaultConfigFiles));
137
+ patterns.push(...(config ?? defaultConfigFiles));
140
138
  }
141
139
  }
142
140
  return patterns;
@@ -146,7 +144,7 @@ export default class WorkspaceWorker {
146
144
  if (entry.length === 0)
147
145
  return [];
148
146
  const negatedEntryFiles = this.config.entry.filter(hasNoProductionSuffix).map(negate);
149
- return [entry, negatedEntryFiles, negatedTestFilePatterns, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
147
+ return [entry, negatedEntryFiles, negatedTestFilePatterns, this.negatedWorkspacePatterns].flat();
150
148
  }
151
149
  getProductionProjectFilePatterns() {
152
150
  const project = this.config.project;
@@ -168,7 +166,7 @@ export default class WorkspaceWorker {
168
166
  negatedPluginEntryFilePatterns,
169
167
  negatedPluginProjectFilePatterns,
170
168
  negatedTestFilePatterns,
171
- this.isRoot ? this.negatedWorkspacePatterns : [],
169
+ this.negatedWorkspacePatterns,
172
170
  ].flat();
173
171
  }
174
172
  getProductionPluginEntryFilePatterns() {
@@ -177,9 +175,7 @@ export default class WorkspaceWorker {
177
175
  const pluginConfig = this.getConfigForPlugin(pluginName);
178
176
  if (this.enabled[pluginName] && pluginConfig) {
179
177
  if ('PRODUCTION_ENTRY_FILE_PATTERNS' in plugin) {
180
- const { entry } = pluginConfig;
181
- const defaultEntryFiles = plugin.PRODUCTION_ENTRY_FILE_PATTERNS;
182
- patterns.push(...(entry.length > 0 ? entry : defaultEntryFiles));
178
+ patterns.push(...(pluginConfig.entry ?? plugin.PRODUCTION_ENTRY_FILE_PATTERNS));
183
179
  }
184
180
  }
185
181
  }
@@ -191,9 +187,8 @@ export default class WorkspaceWorker {
191
187
  const plugin = plugins[pluginName];
192
188
  const pluginConfig = this.getConfigForPlugin(pluginName);
193
189
  if (pluginConfig) {
194
- const { config } = pluginConfig;
195
190
  const defaultConfig = 'CONFIG_FILE_PATTERNS' in plugin ? plugin.CONFIG_FILE_PATTERNS : [];
196
- return config.length > 0 ? config : defaultConfig;
191
+ return pluginConfig.config ?? defaultConfig;
197
192
  }
198
193
  return [];
199
194
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.3",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript project",
5
5
  "keywords": [
6
6
  "find",
@@ -42,7 +42,9 @@
42
42
  "prepublishOnly": "npm test && npm run build && npm run knip",
43
43
  "format": "remark README.md -o",
44
44
  "release": "release-it",
45
- "postinstall": "patch-package"
45
+ "postinstall": "patch-package",
46
+ "add-plugin:help": "echo 'Usage: npm run add-plugin --name=[name] (and update README.md and schema.json)'",
47
+ "add-plugin": "cp -R src/plugins/_template src/plugins/$npm_config_name && echo \"export * as $npm_config_name from \\\"./$npm_config_name/index.js\\\";\" >> src/plugins/index.ts"
46
48
  },
47
49
  "files": [
48
50
  "dist",
@@ -59,7 +61,7 @@
59
61
  "@snyk/github-codeowners": "1.1.0",
60
62
  "chalk": "5.2.0",
61
63
  "easy-table": "1.2.0",
62
- "esbuild": "0.16.10",
64
+ "esbuild": "0.16.11",
63
65
  "esbuild-register": "3.4.2",
64
66
  "eslint": "8.30.0",
65
67
  "fast-glob": "3.2.12",
@@ -81,11 +83,11 @@
81
83
  "@types/eslint": "8.4.10",
82
84
  "@types/js-yaml": "4.0.5",
83
85
  "@types/micromatch": "4.0.2",
84
- "@types/node": "18.11.17",
86
+ "@types/node": "18.11.18",
85
87
  "@types/npmcli__map-workspaces": "3.0.0",
86
88
  "@types/webpack": "5.28.0",
87
- "@typescript-eslint/eslint-plugin": "5.47.0",
88
- "@typescript-eslint/parser": "5.47.0",
89
+ "@typescript-eslint/eslint-plugin": "5.47.1",
90
+ "@typescript-eslint/parser": "5.47.1",
89
91
  "eslint-import-resolver-typescript": "3.5.2",
90
92
  "eslint-plugin-import": "2.26.0",
91
93
  "globstar": "1.0.0",
@@ -93,7 +95,7 @@
93
95
  "remark-cli": "11.0.0",
94
96
  "remark-preset-webpro": "0.0.1",
95
97
  "tsx": "3.12.1",
96
- "type-fest": "3.4.0",
98
+ "type-fest": "3.5.0",
97
99
  "typescript": "4.9.4"
98
100
  },
99
101
  "release-it": {
package/schema.json CHANGED
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Knip configuration",
4
+ "description": "See https://github.com/webpro/knip",
3
5
  "type": "object",
4
6
  "allOf": [
5
7
  {
@@ -7,25 +9,45 @@
7
9
  },
8
10
  {
9
11
  "$ref": "#/definitions/plugins"
12
+ },
13
+ {
14
+ "properties": {
15
+ "$schema": {
16
+ "type": "string",
17
+ "title": "JSON Schema",
18
+ "description": "Pointer to the schema against which this document should be validated."
19
+ }
20
+ }
10
21
  }
11
22
  ],
12
23
  "properties": {
13
24
  "ignoreBinaries": {
25
+ "title": "Binaries to ignore",
26
+ "examples": ["rm", "docker-compose", "eslint"],
14
27
  "$ref": "#/definitions/list"
15
28
  },
16
29
  "ignoreDependencies": {
30
+ "title": "Dependencies from package.json to ignore",
31
+ "examples": ["husky", "lint-staged"],
17
32
  "$ref": "#/definitions/list"
18
33
  },
19
34
  "ignoreWorkspaces": {
35
+ "title": "Workspaces to ignore",
36
+ "examples": ["packages/ignore-me"],
20
37
  "$ref": "#/definitions/list"
21
38
  },
22
39
  "include": {
23
- "$ref": "#/definitions/list"
40
+ "title": "Include issue types in the report",
41
+ "examples": ["files", "dependencies"],
42
+ "$ref": "#/definitions/issueTypes"
24
43
  },
25
44
  "exclude": {
26
- "$ref": "#/definitions/list"
45
+ "title": "Exclude issue types from the report",
46
+ "examples": ["classMembers", "enumMembers"],
47
+ "$ref": "#/definitions/issueTypes"
27
48
  },
28
49
  "workspaces": {
50
+ "title": "Configuration for workspaces",
29
51
  "type": "object",
30
52
  "additionalProperties": {
31
53
  "allOf": [
@@ -48,7 +70,26 @@
48
70
  "type": "string"
49
71
  }
50
72
  },
73
+ "issueTypes": {
74
+ "type": "array",
75
+ "items": {
76
+ "type": "string",
77
+ "enum": [
78
+ "files",
79
+ "dependencies",
80
+ "unlisted",
81
+ "exports",
82
+ "nsExports",
83
+ "classMembers",
84
+ "types",
85
+ "nsTypes",
86
+ "enumMembers",
87
+ "duplicates"
88
+ ]
89
+ }
90
+ },
51
91
  "globPatterns": {
92
+ "description": "Use file paths and glob patterns to match files. Knip uses fast-glob and and minimatch (https://github.com/micromatch/micromatch#matching-features)",
52
93
  "anyOf": [
53
94
  {
54
95
  "type": "string"
@@ -62,22 +103,30 @@
62
103
  ]
63
104
  },
64
105
  "workspace": {
65
- "description": "Workspace configuration.",
66
106
  "type": "object",
67
107
  "properties": {
68
108
  "entry": {
109
+ "title": "The entry files target the starting point(s) to resolve the rest of the imported code.",
110
+ "example": ["lib/index.ts"],
111
+ "default": ["index.{js,ts,tsx}", "src/index.{js,ts,tsx}"],
69
112
  "$ref": "#/definitions/globPatterns"
70
113
  },
71
114
  "project": {
115
+ "title": "The project files should contain all files to match against the files resolved from the entry files, including potentially unused files.",
116
+ "example": ["lib/**/*.ts"],
117
+ "default": ["**/*.{js,ts,tsx}"],
72
118
  "$ref": "#/definitions/globPatterns"
73
119
  },
74
120
  "ignore": {
121
+ "title": "Files to ignore in the analysis.",
122
+ "example": ["**/fixtures", "mocks"],
123
+ "default": [],
75
124
  "$ref": "#/definitions/globPatterns"
76
125
  }
77
126
  }
78
127
  },
79
128
  "plugin": {
80
- "description": "Knip plugin configuration. See https://github.com/webpro/knip#plugins",
129
+ "description": "Knip plugin configuration. See https://github.com/webpro/knip/blob/next/README.md#plugins",
81
130
  "anyOf": [
82
131
  { "const": false },
83
132
  {
@@ -87,12 +136,17 @@
87
136
  "type": "object",
88
137
  "properties": {
89
138
  "config": {
139
+ "title": "The custom dependency resolver of this plugin is applied to the files listed here. Also see https://github.com/webpro/knip/blob/next/README.md#config",
140
+ "examples": [".eslintrc.json"],
90
141
  "$ref": "#/definitions/globPatterns"
91
142
  },
92
143
  "entry": {
144
+ "title": "The entry files target the starting point(s) to resolve its imported dependencies, like regular source code.",
145
+ "examples": ["**/*.story.ts", "**/*.spec.ts"],
93
146
  "$ref": "#/definitions/globPatterns"
94
147
  },
95
148
  "project": {
149
+ "title": "The project files should contain all files to match against the files resolved from the entry files for this plugin, including potentially unused files.",
96
150
  "$ref": "#/definitions/globPatterns"
97
151
  }
98
152
  },
@@ -103,72 +157,95 @@
103
157
  "plugins": {
104
158
  "properties": {
105
159
  "babel": {
160
+ "title": "Babel plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/babel/README.md)",
106
161
  "$ref": "#/definitions/plugin"
107
162
  },
108
163
  "capacitor": {
164
+ "title": "Capacitor plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/capacitor/README.md)",
109
165
  "$ref": "#/definitions/plugin"
110
166
  },
111
167
  "changesets": {
168
+ "title": "Changesets plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/changesets/README.md)",
112
169
  "$ref": "#/definitions/plugin"
113
170
  },
114
171
  "commitlint": {
172
+ "title": "commitlint plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/commitlint/README.md)",
115
173
  "$ref": "#/definitions/plugin"
116
174
  },
117
175
  "cypress": {
176
+ "title": "Cypress plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/cypress/README.md)",
118
177
  "$ref": "#/definitions/plugin"
119
178
  },
120
179
  "eslint": {
180
+ "title": "ESLint plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/eslint/README.md)",
121
181
  "$ref": "#/definitions/plugin"
122
182
  },
123
183
  "gatsby": {
184
+ "title": "Gatsby plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/gatsby/README.md)",
124
185
  "$ref": "#/definitions/plugin"
125
186
  },
126
187
  "jest": {
188
+ "title": "Jest plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/jest/README.md)",
127
189
  "$ref": "#/definitions/plugin"
128
190
  },
129
191
  "mocha": {
192
+ "title": "Mocha plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/mocha/README.md)",
130
193
  "$ref": "#/definitions/plugin"
131
194
  },
132
195
  "next": {
196
+ "title": "Next.js plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/next/README.md)",
133
197
  "$ref": "#/definitions/plugin"
134
198
  },
135
199
  "nx": {
200
+ "title": "Nx plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/nx/README.md)",
136
201
  "$ref": "#/definitions/plugin"
137
202
  },
138
203
  "nyc": {
204
+ "title": "nyc plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/nyc/README.md)",
139
205
  "$ref": "#/definitions/plugin"
140
206
  },
141
207
  "playwright": {
208
+ "title": "Playwright plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/playwright/README.md)",
142
209
  "$ref": "#/definitions/plugin"
143
210
  },
144
211
  "postcss": {
212
+ "title": "PostCSS plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/postcss/README.md)",
145
213
  "$ref": "#/definitions/plugin"
146
214
  },
147
215
  "prettier": {
216
+ "title": "Prettier plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/prettier/README.md)",
148
217
  "$ref": "#/definitions/plugin"
149
218
  },
150
219
  "remark": {
220
+ "title": "Remark plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/remark/README.md)",
151
221
  "$ref": "#/definitions/plugin"
152
222
  },
153
223
  "remix": {
224
+ "title": "Remix plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/remix/README.md)",
154
225
  "$ref": "#/definitions/plugin"
155
226
  },
156
227
  "rollup": {
228
+ "title": "Rollup plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/rollup/README.md)",
157
229
  "$ref": "#/definitions/plugin"
158
230
  },
159
231
  "sentry": {
232
+ "title": "Sentry plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/sentry/README.md)",
160
233
  "$ref": "#/definitions/plugin"
161
234
  },
162
235
  "storybook": {
236
+ "title": "Storybook plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/storybook/README.md)",
163
237
  "$ref": "#/definitions/plugin"
164
238
  },
165
239
  "stryker": {
240
+ "title": "Stryker plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/stryker/README.md)",
166
241
  "$ref": "#/definitions/plugin"
167
242
  },
168
243
  "typescript": {
244
+ "title": "TypeScript plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/typescript/README.md)",
169
245
  "$ref": "#/definitions/plugin"
170
246
  },
171
247
  "webpack": {
248
+ "title": "Webpack plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/webpack/README.md)",
172
249
  "$ref": "#/definitions/plugin"
173
250
  }
174
251
  }