knip 6.13.0 → 6.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,7 +28,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
28
28
  }
29
29
  if (inExport.hasRefsInFile)
30
30
  return true;
31
- if (explorer.isReferenced(filePath, containingExport, { includeEntryExports })[0])
31
+ if (explorer.isReferenced(filePath, containingExport, { traverseEntries: includeEntryExports })[0])
32
32
  return true;
33
33
  if (inExport.referencedIn) {
34
34
  const v = visited ?? new Set();
@@ -63,7 +63,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
63
63
  const isIgnored = shouldIgnoreTags(exportedItem.jsDocTags) || isInternalProd;
64
64
  if (importsForExport) {
65
65
  const [isReferenced, reExportingEntryFile] = explorer.isReferenced(filePath, identifier, {
66
- includeEntryExports: isIncludeEntryExports,
66
+ traverseEntries: isIncludeEntryExports,
67
67
  });
68
68
  if (isIgnored &&
69
69
  (isReferenced || isReferencedInUsedExport(exportedItem, filePath, isIncludeEntryExports))) {
@@ -104,7 +104,8 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
104
104
  if (!member.hasRefsInFile) {
105
105
  const id = `${identifier}.${member.identifier}`;
106
106
  const [isMemberReferenced] = explorer.isReferenced(filePath, id, {
107
- includeEntryExports: true,
107
+ traverseEntries: true,
108
+ treatStarAtEntryAsReferenced: true,
108
109
  });
109
110
  const isIgnored = shouldIgnoreTags(member.jsDocTags);
110
111
  if (!isMemberReferenced) {
@@ -1,7 +1,8 @@
1
1
  import type { ModuleGraph } from '../types/module-graph.ts';
2
2
  export declare const createGraphExplorer: (graph: ModuleGraph, entryPaths: Set<string>) => {
3
3
  isReferenced: (filePath: string, identifier: string, options: {
4
- includeEntryExports: boolean;
4
+ traverseEntries: boolean;
5
+ treatStarAtEntryAsReferenced?: boolean;
5
6
  }) => [boolean, string | undefined];
6
7
  hasStrictlyNsReferences: (filePath: string, identifier: string) => [boolean, (string | undefined)?];
7
8
  buildExportsTree: (options: {
@@ -1,4 +1,5 @@
1
1
  import type { Identifier, ModuleGraph } from '../../types/module-graph.ts';
2
2
  export declare const isReferenced: (graph: ModuleGraph, entryPaths: Set<string>, filePath: string, id: Identifier, options: {
3
- includeEntryExports: boolean;
3
+ traverseEntries: boolean;
4
+ treatStarAtEntryAsReferenced?: boolean;
4
5
  }) => [boolean, string | undefined];
@@ -23,9 +23,12 @@ export const isReferenced = (graph, entryPaths, filePath, id, options) => {
23
23
  seen.add(path);
24
24
  const restIds = id.split('.');
25
25
  const identifier = restIds.shift();
26
+ if (options.treatStarAtEntryAsReferenced && isEntryFile && viaStar && restIds.length > 0) {
27
+ return [true, reExportingEntryFile];
28
+ }
26
29
  const file = graph.get(path)?.importedBy;
27
30
  if (!identifier || !file) {
28
- return [isEntryFile && viaStar && restIds.length > 0, reExportingEntryFile];
31
+ return [false, reExportingEntryFile];
29
32
  }
30
33
  const follow = (sources, nextId, nextViaStar = viaStar) => {
31
34
  for (const byFilePath of sources) {
@@ -71,7 +74,7 @@ export const isReferenced = (graph, entryPaths, filePath, id, options) => {
71
74
  return [true, reExportingEntryFile];
72
75
  }
73
76
  }
74
- if (isEntryFile && !options.includeEntryExports)
77
+ if (isEntryFile && !options.traverseEntries)
75
78
  return [false, reExportingEntryFile];
76
79
  const aliasMap = getAliasReExportMap(file, identifier);
77
80
  if (aliasMap) {
@@ -91,7 +94,7 @@ export const isReferenced = (graph, entryPaths, filePath, id, options) => {
91
94
  return [true, reExportingEntryFile];
92
95
  }
93
96
  for (const [namespace, sources] of file.reExportNs) {
94
- if (follow(sources, `${namespace}.${id}`)) {
97
+ if (follow(sources, `${namespace}.${id}`, true)) {
95
98
  return [true, reExportingEntryFile];
96
99
  }
97
100
  }
@@ -1,5 +1,7 @@
1
1
  import { toDeferResolve, toProductionEntry } from '../../util/input.js';
2
+ import { join } from '../../util/path.js';
2
3
  import { findWebpackDependenciesFromConfig } from '../webpack/index.js';
4
+ const isLocalPath = (name) => name.startsWith('.') || name.startsWith('/');
3
5
  const FIRST_PARTY_MODULES = new Set([
4
6
  'content-docs',
5
7
  'content-blog',
@@ -55,12 +57,14 @@ const resolveSidebarPath = (config) => {
55
57
  const path = config?.sidebarPath ?? config?.docs?.sidebarPath;
56
58
  return typeof path === 'string' ? path : undefined;
57
59
  };
58
- const resolveArrayConfig = ([name, config], type) => {
60
+ const resolveArrayConfig = ([name, config], type, cwd) => {
59
61
  if (typeof name !== 'string')
60
62
  return [];
61
- const resolvedName = resolveModuleName(name, type);
62
63
  const sidebarPath = type !== 'theme' ? resolveSidebarPath(config) : undefined;
63
- return [toDeferResolve(resolvedName), ...(sidebarPath ? [toProductionEntry(sidebarPath)] : [])];
64
+ const sidebar = sidebarPath ? [toProductionEntry(sidebarPath)] : [];
65
+ if (isLocalPath(name))
66
+ return [toProductionEntry(join(cwd, name)), ...sidebar];
67
+ return [toDeferResolve(resolveModuleName(name, type)), ...sidebar];
64
68
  };
65
69
  export const resolveConfigItems = async (items, type, options) => {
66
70
  const inputs = new Set();
@@ -70,10 +74,13 @@ export const resolveConfigItems = async (items, type, options) => {
70
74
  if (!item)
71
75
  continue;
72
76
  if (typeof item === 'string') {
73
- inputs.add(toDeferResolve(resolveModuleName(item, type)));
77
+ if (isLocalPath(item))
78
+ inputs.add(toProductionEntry(join(options.cwd, item)));
79
+ else
80
+ inputs.add(toDeferResolve(resolveModuleName(item, type)));
74
81
  }
75
82
  else if (Array.isArray(item)) {
76
- for (const input of resolveArrayConfig(item, type))
83
+ for (const input of resolveArrayConfig(item, type, options.cwd))
77
84
  inputs.add(input);
78
85
  }
79
86
  else if (typeof item.configureWebpack === 'function') {
@@ -5,7 +5,7 @@ import { CORE_CLIENT_API, resolveConfigItems } from './helpers.js';
5
5
  const title = 'Docusaurus';
6
6
  const enablers = ['@docusaurus/core'];
7
7
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
8
- const config = ['docusaurus.config.{js,mjs,ts}'];
8
+ const config = ['docusaurus.config.{js,cjs,mjs,ts,cts,mts}'];
9
9
  const production = ['src/pages/**/*.{js,ts,jsx,tsx}', '{blog,docs}/**/*.mdx', 'versioned_docs/**/*.{mdx,jsx,tsx}'];
10
10
  const entry = ['babel.config.{js,cjs,mjs,cts}'];
11
11
  const resolveStaticAssets = (items, cwd) => {
@@ -30,6 +30,7 @@ const resolveConfig = async (config, options) => {
30
30
  toDependency('@docusaurus/module-type-aliases', { optional: true }),
31
31
  ...(hasClassicTheme ? [toIgnore('(@theme|@theme-init|@theme-original)/*', 'dependencies')] : []),
32
32
  toIgnore(`@docusaurus/(${CORE_CLIENT_API.join('|')})`, 'dependencies'),
33
+ toIgnore('@generated/.*', 'dependencies'),
33
34
  ...(config.future?.experimental_faster ? [toDependency('@docusaurus/faster')] : []),
34
35
  ...production.map(id => toProductionEntry(id)),
35
36
  ...entry.map(id => toEntry(id)),
@@ -3,7 +3,7 @@ import { hasDependency } from '../../util/plugin.js';
3
3
  const title = 'Hardhat';
4
4
  const enablers = ['hardhat'];
5
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
- const entry = ['hardhat.config.{js,cjs,mjs,ts}'];
6
+ const entry = ['hardhat.config.{js,cjs,mjs,ts,cts,mts}'];
7
7
  const resolve = async () => {
8
8
  return [toDependency('hardhat')];
9
9
  };
@@ -6,7 +6,7 @@ import { getReportersDependencies, resolveExtensibleConfig } from './helpers.js'
6
6
  const title = 'Jest';
7
7
  const enablers = ['jest'];
8
8
  const isEnabled = ({ dependencies, manifest }) => hasDependency(dependencies, enablers) || Boolean(manifest.name?.startsWith('jest-presets'));
9
- const config = ['jest.config.{js,ts,mjs,cjs,json}', 'package.json'];
9
+ const config = ['jest.config.{js,ts,mjs,cjs,mts,cts,json}', 'package.json'];
10
10
  const mocks = ['**/__mocks__/**/*.[jt]s?(x)'];
11
11
  const entry = ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)', ...mocks];
12
12
  const rootDirRe = /<rootDir>/;
@@ -4,7 +4,7 @@ import { hasDependency } from '../../util/plugin.js';
4
4
  const title = 'Nitro';
5
5
  const enablers = ['nitropack', 'nitro'];
6
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
7
- const config = ['nitro.config.{js,mjs,ts}'];
7
+ const config = ['nitro.config.{js,cjs,mjs,ts,cts,mts}'];
8
8
  const production = [
9
9
  'server.{js,mjs,ts}',
10
10
  'api/**/*.ts',
@@ -8,7 +8,7 @@ import { buildAutoImportMap, collectIdentifiers, collectLocalImportPaths, collec
8
8
  const title = 'Nuxt';
9
9
  const enablers = ['nuxt', 'nuxt-nightly'];
10
10
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
11
- const config = ['nuxt.config.{js,mjs,ts}'];
11
+ const config = ['nuxt.config.{js,cjs,mjs,ts,cts,mts}'];
12
12
  const entry = ['app.config.ts', '**/*.d.vue.ts'];
13
13
  const app = ['app.{vue,jsx,tsx}', 'error.{vue,jsx,tsx}', 'router.options.ts'];
14
14
  const layout = (dir = 'layouts') => join(dir, '**/*.{vue,jsx,tsx}');
@@ -35,6 +35,15 @@ const resolveConfig = async (localConfig, options) => {
35
35
  .map(target => target?.executor)
36
36
  .filter(executor => executor && !executor.startsWith('.'))
37
37
  .map(executor => executor?.split(':')[0]);
38
+ const expand = (value) => value
39
+ .replaceAll('{projectRoot}', options.configFileDir)
40
+ .replaceAll('{workspaceRoot}', options.rootCwd);
41
+ const resolveTargetCwd = (targetCwd) => {
42
+ if (!targetCwd)
43
+ return options.cwd;
44
+ const expanded = expand(targetCwd);
45
+ return expanded === targetCwd ? join(options.cwd, targetCwd) : expanded;
46
+ };
38
47
  const inputs = targets
39
48
  .filter(target => target.executor === 'nx:run-commands' || target.command)
40
49
  .flatMap(target => {
@@ -45,8 +54,7 @@ const resolveConfig = async (localConfig, options) => {
45
54
  commands = [target.options.command];
46
55
  else if (target.options?.commands)
47
56
  commands = target.options.commands.map(commandConfig => typeof commandConfig === 'string' ? commandConfig : commandConfig.command);
48
- const cwd = target.options?.cwd ? join(options.cwd, target.options.cwd) : options.cwd;
49
- return options.getInputsFromScripts(commands, { cwd });
57
+ return options.getInputsFromScripts(commands.map(expand), { cwd: resolveTargetCwd(target.options?.cwd) });
50
58
  });
51
59
  const configInputs = targets.flatMap(target => {
52
60
  const opts = target.options;
@@ -3,7 +3,7 @@ import compiler from './compiler.js';
3
3
  const title = 'Tailwind';
4
4
  const enablers = ['tailwindcss', '@tailwindcss/vite', '@tailwindcss/postcss', '@tailwindcss/cli'];
5
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
- const entry = ['tailwind.config.{js,cjs,mjs,ts}'];
6
+ const entry = ['tailwind.config.{js,cjs,mjs,ts,cts,mts}'];
7
7
  const registerCompilers = ({ registerCompiler, hasDependency }) => {
8
8
  if (enablers.some(enabler => hasDependency(enabler)))
9
9
  registerCompiler({ extension: '.css', compiler });
@@ -3,7 +3,7 @@ import { hasDependency } from '../../util/plugin.js';
3
3
  const title = 'WXT';
4
4
  const enablers = ['wxt'];
5
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
- const config = ['wxt.config.{js,mjs,ts}'];
6
+ const config = ['wxt.config.{js,cjs,mjs,ts,cts,mts}'];
7
7
  const production = ['entrypoints/**/*'];
8
8
  const resolveConfig = async (localConfig) => {
9
9
  const inputs = [];
@@ -35,7 +35,7 @@ export default ({ graph, explorer, options, workspaceFilePathFilter }) => {
35
35
  nodes.sort((a, b) => a.filePath.localeCompare(b.filePath) || a.identifier.localeCompare(b.identifier));
36
36
  const toRel = (path) => toRelative(path, options.cwd);
37
37
  const isReferenced = (node) => {
38
- if (explorer.isReferenced(node.filePath, node.identifier, { includeEntryExports: false })[0])
38
+ if (explorer.isReferenced(node.filePath, node.identifier, { traverseEntries: false })[0])
39
39
  return true;
40
40
  if (explorer.hasStrictlyNsReferences(node.filePath, node.identifier)[0])
41
41
  return true;
@@ -48,7 +48,11 @@ export default ({ graph, explorer, options, workspaceFilePathFilter }) => {
48
48
  memberStatuses = [];
49
49
  for (const m of exp.members) {
50
50
  const id = `${node.identifier}.${m.identifier}`;
51
- const referenced = m.hasRefsInFile || explorer.isReferenced(node.filePath, id, { includeEntryExports: true })[0];
51
+ const referenced = m.hasRefsInFile ||
52
+ explorer.isReferenced(node.filePath, id, {
53
+ traverseEntries: true,
54
+ treatStarAtEntryAsReferenced: true,
55
+ })[0];
52
56
  memberStatuses.push({ identifier: m.identifier, referenced });
53
57
  }
54
58
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "6.13.0";
1
+ export declare const version = "6.13.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '6.13.0';
1
+ export const version = '6.13.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "6.13.0",
3
+ "version": "6.13.1",
4
4
  "description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
5
5
  "keywords": [
6
6
  "analysis",