knip 5.41.1 → 5.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +1 -1
  2. package/dist/ConfigurationChief.d.ts +2 -0
  3. package/dist/ConfigurationValidator.d.ts +112 -0
  4. package/dist/IssueCollector.js +6 -4
  5. package/dist/ProjectPrincipal.js +2 -14
  6. package/dist/WorkspaceWorker.js +2 -3
  7. package/dist/binaries/package-manager/bun.js +8 -2
  8. package/dist/binaries/package-manager/bunx.d.ts +3 -0
  9. package/dist/binaries/package-manager/bunx.js +18 -0
  10. package/dist/binaries/package-manager/index.d.ts +2 -0
  11. package/dist/binaries/package-manager/index.js +4 -0
  12. package/dist/binaries/package-manager/npm.js +1 -2
  13. package/dist/binaries/package-manager/npx.js +7 -2
  14. package/dist/binaries/package-manager/pnpm.js +7 -1
  15. package/dist/binaries/package-manager/pnpx.d.ts +3 -0
  16. package/dist/binaries/package-manager/pnpx.js +18 -0
  17. package/dist/binaries/package-manager/yarn.js +4 -3
  18. package/dist/binaries/plugins.js +7 -2
  19. package/dist/compilers/index.d.ts +20 -0
  20. package/dist/constants.js +2 -0
  21. package/dist/index.js +27 -17
  22. package/dist/plugins/_template/index.js +1 -1
  23. package/dist/plugins/angular/index.js +59 -27
  24. package/dist/plugins/angular/types.d.ts +2 -2
  25. package/dist/plugins/capacitor/index.js +1 -1
  26. package/dist/plugins/changesets/index.js +1 -1
  27. package/dist/plugins/commitlint/index.js +1 -1
  28. package/dist/plugins/dependency-cruiser/index.d.ts +12 -0
  29. package/dist/plugins/dependency-cruiser/index.js +16 -0
  30. package/dist/plugins/expo/helpers.js +1 -1
  31. package/dist/plugins/expo/index.d.ts +3 -0
  32. package/dist/plugins/expo/index.js +6 -4
  33. package/dist/plugins/gatsby/index.js +1 -1
  34. package/dist/plugins/graphql-codegen/index.js +1 -1
  35. package/dist/plugins/index.d.ts +29 -11
  36. package/dist/plugins/index.js +4 -0
  37. package/dist/plugins/jest/index.d.ts +3 -0
  38. package/dist/plugins/jest/index.js +4 -0
  39. package/dist/plugins/karma/helpers.d.ts +7 -0
  40. package/dist/plugins/karma/helpers.js +32 -0
  41. package/dist/plugins/karma/index.d.ts +1 -2
  42. package/dist/plugins/karma/index.js +10 -36
  43. package/dist/plugins/lefthook/index.js +2 -2
  44. package/dist/plugins/linthtml/index.d.ts +2 -2
  45. package/dist/plugins/linthtml/types.d.ts +1 -1
  46. package/dist/plugins/markdownlint/index.js +1 -1
  47. package/dist/plugins/metro/index.d.ts +15 -0
  48. package/dist/plugins/metro/index.js +47 -0
  49. package/dist/plugins/metro/types.d.ts +13 -0
  50. package/dist/plugins/metro/types.js +1 -0
  51. package/dist/plugins/nest/index.js +1 -1
  52. package/dist/plugins/netlify/index.js +2 -2
  53. package/dist/plugins/npm-package-json-lint/index.js +1 -1
  54. package/dist/plugins/nuxt/index.d.ts +3 -1
  55. package/dist/plugins/nuxt/index.js +3 -3
  56. package/dist/plugins/nx/index.js +11 -3
  57. package/dist/plugins/nx/types.d.ts +1 -0
  58. package/dist/plugins/oclif/index.js +1 -1
  59. package/dist/plugins/prettier/index.js +1 -1
  60. package/dist/plugins/release-it/index.d.ts +0 -1
  61. package/dist/plugins/release-it/index.js +1 -3
  62. package/dist/plugins/semantic-release/index.js +7 -1
  63. package/dist/plugins/simple-git-hooks/index.d.ts +2 -3
  64. package/dist/plugins/simple-git-hooks/index.js +1 -9
  65. package/dist/plugins/simple-git-hooks/types.d.ts +1 -1
  66. package/dist/plugins/storybook/index.js +5 -1
  67. package/dist/plugins/typescript/index.d.ts +3 -1
  68. package/dist/plugins/typescript/index.js +2 -2
  69. package/dist/plugins/vite/index.d.ts +0 -1
  70. package/dist/plugins/vite/index.js +0 -2
  71. package/dist/plugins/vitest/index.js +1 -1
  72. package/dist/plugins/webdriver-io/index.js +1 -1
  73. package/dist/plugins/webpack/index.d.ts +4 -1
  74. package/dist/plugins/webpack/index.js +5 -2
  75. package/dist/plugins/wireit/index.d.ts +0 -1
  76. package/dist/plugins/wireit/index.js +0 -2
  77. package/dist/reporters/symbols.js +12 -3
  78. package/dist/schema/plugins.d.ts +46 -0
  79. package/dist/schema/plugins.js +2 -0
  80. package/dist/types/PluginNames.d.ts +2 -2
  81. package/dist/types/PluginNames.js +2 -0
  82. package/dist/types/config.d.ts +1 -2
  83. package/dist/types/dependency-graph.d.ts +2 -4
  84. package/dist/typescript/ast-helpers.d.ts +1 -0
  85. package/dist/typescript/ast-helpers.js +1 -0
  86. package/dist/typescript/get-imports-and-exports.d.ts +2 -4
  87. package/dist/typescript/get-imports-and-exports.js +18 -23
  88. package/dist/typescript/visitors/exports/exportAssignment.js +2 -1
  89. package/dist/typescript/visitors/exports/exportDeclaration.js +2 -1
  90. package/dist/typescript/visitors/exports/exportKeyword.js +3 -4
  91. package/dist/typescript/visitors/helpers.d.ts +2 -1
  92. package/dist/typescript/visitors/helpers.js +3 -2
  93. package/dist/typescript/visitors/scripts/bun.js +1 -1
  94. package/dist/typescript/visitors/scripts/execa.js +24 -1
  95. package/dist/util/dependency-graph.js +2 -4
  96. package/dist/util/file-entry-cache.js +2 -6
  97. package/dist/util/get-referenced-inputs.js +4 -2
  98. package/dist/util/input.d.ts +3 -1
  99. package/dist/util/input.js +5 -1
  100. package/dist/util/modules.js +1 -1
  101. package/dist/version.d.ts +1 -1
  102. package/dist/version.js +1 -1
  103. package/package.json +13 -12
  104. package/schema.json +8 -0
@@ -170,6 +170,19 @@ export declare const pluginsSchema: z.ZodObject<{
170
170
  entry?: string | string[] | undefined;
171
171
  project?: string | string[] | undefined;
172
172
  }>]>;
173
+ 'dependency-cruiser': z.ZodUnion<[z.ZodBoolean, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
174
+ config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
175
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
176
+ project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
177
+ }, "strip", z.ZodTypeAny, {
178
+ config?: string | string[] | undefined;
179
+ entry?: string | string[] | undefined;
180
+ project?: string | string[] | undefined;
181
+ }, {
182
+ config?: string | string[] | undefined;
183
+ entry?: string | string[] | undefined;
184
+ project?: string | string[] | undefined;
185
+ }>]>;
173
186
  dotenv: z.ZodUnion<[z.ZodBoolean, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
174
187
  config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
175
188
  entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
@@ -417,6 +430,19 @@ export declare const pluginsSchema: z.ZodObject<{
417
430
  entry?: string | string[] | undefined;
418
431
  project?: string | string[] | undefined;
419
432
  }>]>;
433
+ metro: z.ZodUnion<[z.ZodBoolean, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
434
+ config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
435
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
436
+ project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
437
+ }, "strip", z.ZodTypeAny, {
438
+ config?: string | string[] | undefined;
439
+ entry?: string | string[] | undefined;
440
+ project?: string | string[] | undefined;
441
+ }, {
442
+ config?: string | string[] | undefined;
443
+ entry?: string | string[] | undefined;
444
+ project?: string | string[] | undefined;
445
+ }>]>;
420
446
  mocha: z.ZodUnion<[z.ZodBoolean, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
421
447
  config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
422
448
  entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
@@ -1237,6 +1263,11 @@ export declare const pluginsSchema: z.ZodObject<{
1237
1263
  entry?: string | string[] | undefined;
1238
1264
  project?: string | string[] | undefined;
1239
1265
  };
1266
+ 'dependency-cruiser': string | boolean | string[] | {
1267
+ config?: string | string[] | undefined;
1268
+ entry?: string | string[] | undefined;
1269
+ project?: string | string[] | undefined;
1270
+ };
1240
1271
  dotenv: string | boolean | string[] | {
1241
1272
  config?: string | string[] | undefined;
1242
1273
  entry?: string | string[] | undefined;
@@ -1332,6 +1363,11 @@ export declare const pluginsSchema: z.ZodObject<{
1332
1363
  entry?: string | string[] | undefined;
1333
1364
  project?: string | string[] | undefined;
1334
1365
  };
1366
+ metro: string | boolean | string[] | {
1367
+ config?: string | string[] | undefined;
1368
+ entry?: string | string[] | undefined;
1369
+ project?: string | string[] | undefined;
1370
+ };
1335
1371
  mocha: string | boolean | string[] | {
1336
1372
  config?: string | string[] | undefined;
1337
1373
  entry?: string | string[] | undefined;
@@ -1683,6 +1719,11 @@ export declare const pluginsSchema: z.ZodObject<{
1683
1719
  entry?: string | string[] | undefined;
1684
1720
  project?: string | string[] | undefined;
1685
1721
  };
1722
+ 'dependency-cruiser': string | boolean | string[] | {
1723
+ config?: string | string[] | undefined;
1724
+ entry?: string | string[] | undefined;
1725
+ project?: string | string[] | undefined;
1726
+ };
1686
1727
  dotenv: string | boolean | string[] | {
1687
1728
  config?: string | string[] | undefined;
1688
1729
  entry?: string | string[] | undefined;
@@ -1778,6 +1819,11 @@ export declare const pluginsSchema: z.ZodObject<{
1778
1819
  entry?: string | string[] | undefined;
1779
1820
  project?: string | string[] | undefined;
1780
1821
  };
1822
+ metro: string | boolean | string[] | {
1823
+ config?: string | string[] | undefined;
1824
+ entry?: string | string[] | undefined;
1825
+ project?: string | string[] | undefined;
1826
+ };
1781
1827
  mocha: string | boolean | string[] | {
1782
1828
  config?: string | string[] | undefined;
1783
1829
  entry?: string | string[] | undefined;
@@ -22,6 +22,7 @@ export const pluginsSchema = z.object({
22
22
  cspell: pluginSchema,
23
23
  cucumber: pluginSchema,
24
24
  cypress: pluginSchema,
25
+ 'dependency-cruiser': pluginSchema,
25
26
  dotenv: pluginSchema,
26
27
  drizzle: pluginSchema,
27
28
  eleventy: pluginSchema,
@@ -41,6 +42,7 @@ export const pluginsSchema = z.object({
41
42
  'lockfile-lint': pluginSchema,
42
43
  'lost-pixel': pluginSchema,
43
44
  markdownlint: pluginSchema,
45
+ metro: pluginSchema,
44
46
  mocha: pluginSchema,
45
47
  moonrepo: pluginSchema,
46
48
  msw: pluginSchema,
@@ -1,2 +1,2 @@
1
- export type PluginName = 'angular' | 'astro' | 'ava' | 'babel' | 'c8' | 'capacitor' | 'changesets' | 'commitizen' | 'commitlint' | 'cspell' | 'cucumber' | 'cypress' | 'dotenv' | 'drizzle' | 'eleventy' | 'eslint' | 'expo' | 'gatsby' | 'github-actions' | 'glob' | 'graphql-codegen' | 'husky' | 'jest' | 'karma' | 'ladle' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lockfile-lint' | 'lost-pixel' | 'markdownlint' | 'mocha' | 'moonrepo' | 'msw' | 'nest' | 'netlify' | 'next' | 'node' | 'node-test-runner' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nx' | 'nyc' | 'oclif' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'postcss' | 'preconstruct' | 'prettier' | 'react-cosmos' | 'release-it' | 'remark' | 'remix' | 'rollup' | 'rsbuild' | 'rspack' | 'semantic-release' | 'sentry' | 'simple-git-hooks' | 'size-limit' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'syncpack' | 'tailwind' | 'travis' | 'ts-node' | '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", "c8", "capacitor", "changesets", "commitizen", "commitlint", "cspell", "cucumber", "cypress", "dotenv", "drizzle", "eleventy", "eslint", "expo", "gatsby", "github-actions", "glob", "graphql-codegen", "husky", "jest", "karma", "ladle", "lefthook", "lint-staged", "linthtml", "lockfile-lint", "lost-pixel", "markdownlint", "mocha", "moonrepo", "msw", "nest", "netlify", "next", "node", "node-test-runner", "nodemon", "npm-package-json-lint", "nuxt", "nx", "nyc", "oclif", "playwright", "playwright-ct", "playwright-test", "plop", "postcss", "preconstruct", "prettier", "react-cosmos", "release-it", "remark", "remix", "rollup", "rsbuild", "rspack", "semantic-release", "sentry", "simple-git-hooks", "size-limit", "storybook", "stryker", "stylelint", "svelte", "syncpack", "tailwind", "travis", "ts-node", "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' | 'c8' | 'capacitor' | 'changesets' | 'commitizen' | 'commitlint' | 'cspell' | 'cucumber' | 'cypress' | 'dependency-cruiser' | 'dotenv' | 'drizzle' | 'eleventy' | 'eslint' | 'expo' | 'gatsby' | 'github-actions' | 'glob' | 'graphql-codegen' | 'husky' | 'jest' | 'karma' | 'ladle' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lockfile-lint' | 'lost-pixel' | 'markdownlint' | 'metro' | 'mocha' | 'moonrepo' | 'msw' | 'nest' | 'netlify' | 'next' | 'node' | 'node-test-runner' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nx' | 'nyc' | 'oclif' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'postcss' | 'preconstruct' | 'prettier' | 'react-cosmos' | 'release-it' | 'remark' | 'remix' | 'rollup' | 'rsbuild' | 'rspack' | 'semantic-release' | 'sentry' | 'simple-git-hooks' | 'size-limit' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'syncpack' | 'tailwind' | 'travis' | 'ts-node' | '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", "c8", "capacitor", "changesets", "commitizen", "commitlint", "cspell", "cucumber", "cypress", "dependency-cruiser", "dotenv", "drizzle", "eleventy", "eslint", "expo", "gatsby", "github-actions", "glob", "graphql-codegen", "husky", "jest", "karma", "ladle", "lefthook", "lint-staged", "linthtml", "lockfile-lint", "lost-pixel", "markdownlint", "metro", "mocha", "moonrepo", "msw", "nest", "netlify", "next", "node", "node-test-runner", "nodemon", "npm-package-json-lint", "nuxt", "nx", "nyc", "oclif", "playwright", "playwright-ct", "playwright-test", "plop", "postcss", "preconstruct", "prettier", "react-cosmos", "release-it", "remark", "remix", "rollup", "rsbuild", "rspack", "semantic-release", "sentry", "simple-git-hooks", "size-limit", "storybook", "stryker", "stylelint", "svelte", "syncpack", "tailwind", "travis", "ts-node", "tsup", "tsx", "typedoc", "typescript", "unbuild", "unocss", "vercel-og", "vike", "vite", "vitest", "vue", "webdriver-io", "webpack", "wireit", "wrangler", "xo", "yarn", "yorkie"];
@@ -11,6 +11,7 @@ export const pluginNames = [
11
11
  'cspell',
12
12
  'cucumber',
13
13
  'cypress',
14
+ 'dependency-cruiser',
14
15
  'dotenv',
15
16
  'drizzle',
16
17
  'eleventy',
@@ -30,6 +31,7 @@ export const pluginNames = [
30
31
  'lockfile-lint',
31
32
  'lost-pixel',
32
33
  'markdownlint',
34
+ 'metro',
33
35
  'mocha',
34
36
  'moonrepo',
35
37
  'msw',
@@ -15,7 +15,7 @@ export interface GetInputsFromScriptsOptions extends BaseOptions {
15
15
  export type GetInputsFromScripts<T = GetInputsFromScriptsOptions> = (npmScripts: string | string[] | Set<string>, options: T) => Input[];
16
16
  export type GetInputsFromScriptsPartial = (npmScripts: string | string[] | Set<string>, options?: Partial<GetInputsFromScriptsOptions>) => Input[];
17
17
  type FromArgs = (args: string[]) => Input[];
18
- interface BinaryResolverOptions extends GetInputsFromScriptsOptions {
18
+ export interface BinaryResolverOptions extends GetInputsFromScriptsOptions {
19
19
  fromArgs: FromArgs;
20
20
  }
21
21
  export type BinaryResolver = (binary: string, args: string[], options: BinaryResolverOptions) => Input[];
@@ -92,7 +92,6 @@ export type ResolveConfig<T = any> = (config: T, options: PluginOptions) => Prom
92
92
  export type Resolve = (options: PluginOptions) => Promise<Input[]> | Input[];
93
93
  export interface Plugin {
94
94
  title: string;
95
- note?: string;
96
95
  args?: Args;
97
96
  packageJsonPath?: string | ((manifest: PackageJson) => string);
98
97
  enablers?: IgnorePatterns | string;
@@ -56,10 +56,8 @@ export type FileNode = {
56
56
  external: Set<string>;
57
57
  unresolved: Set<UnresolvedImport>;
58
58
  };
59
- exports: {
60
- exported: ExportMap;
61
- duplicate: Iterable<Array<IssueSymbol>>;
62
- };
59
+ exports: ExportMap;
60
+ duplicates: Iterable<Array<IssueSymbol>>;
63
61
  scripts: Set<string>;
64
62
  imported?: ImportDetails;
65
63
  internalImportCache?: ImportMap;
@@ -21,6 +21,7 @@ export declare const isDestructuring: (node: ts.Node) => boolean;
21
21
  export declare const getDestructuredIds: (name: ts.ObjectBindingPattern) => string[];
22
22
  export declare const isConsiderReferencedNS: (node: ts.Identifier) => boolean;
23
23
  export declare const isObjectEnumerationCallExpressionArgument: (node: ts.Identifier) => boolean;
24
+ export declare const isInForIteration: (node: ts.Node) => boolean;
24
25
  export declare const isTopLevel: (node: ts.Node) => boolean;
25
26
  export declare const getTypeName: (node: ts.Identifier) => ts.QualifiedName | undefined;
26
27
  export declare const isImportSpecifier: (node: ts.Node) => boolean;
@@ -148,6 +148,7 @@ export const isObjectEnumerationCallExpressionArgument = (node) => ts.isCallExpr
148
148
  ts.isIdentifier(node.parent.expression.expression) &&
149
149
  node.parent.expression.expression.escapedText === 'Object' &&
150
150
  objectEnumerationMethods.has(String(node.parent.expression.name.escapedText));
151
+ export const isInForIteration = (node) => node.parent && (ts.isForInStatement(node.parent) || ts.isForOfStatement(node.parent));
151
152
  export const isTopLevel = (node) => ts.isSourceFile(node.parent) || (node.parent && ts.isSourceFile(node.parent.parent));
152
153
  export const getTypeName = (node) => {
153
154
  if (!node.parent?.parent)
@@ -11,10 +11,8 @@ export declare const _getImportsAndExports: (sourceFile: BoundSourceFile, resolv
11
11
  specifiers: Set<[string, string]>;
12
12
  unresolved: Set<UnresolvedImport>;
13
13
  };
14
- exports: {
15
- exported: ExportMap;
16
- duplicate: IssueSymbol[][];
17
- };
14
+ exports: ExportMap;
15
+ duplicates: IssueSymbol[][];
18
16
  scripts: Set<string>;
19
17
  traceRefs: Set<string>;
20
18
  };
@@ -6,7 +6,7 @@ import { addNsValue, addValue, createImports } from '../util/dependency-graph.js
6
6
  import { getPackageNameFromFilePath, isStartsLikePackageName, sanitizeSpecifier } from '../util/modules.js';
7
7
  import { isInNodeModules } from '../util/path.js';
8
8
  import { shouldIgnore } from '../util/tag.js';
9
- import { getAccessMembers, getDestructuredIds, getJSDocTags, getLineAndCharacterOfPosition, getTypeName, isAccessExpression, isConsiderReferencedNS, isDestructuring, isImportSpecifier, isObjectEnumerationCallExpressionArgument, isReferencedInExport, } from './ast-helpers.js';
9
+ import { getAccessMembers, getDestructuredIds, getJSDocTags, getLineAndCharacterOfPosition, getTypeName, isAccessExpression, isConsiderReferencedNS, isDestructuring, isImportSpecifier, isInForIteration, isObjectEnumerationCallExpressionArgument, isReferencedInExport, } from './ast-helpers.js';
10
10
  import { findInternalReferences, isType } from './find-internal-references.js';
11
11
  import getDynamicImportVisitors from './visitors/dynamic-imports/index.js';
12
12
  import getExportVisitors from './visitors/exports/index.js';
@@ -35,9 +35,9 @@ const createMember = (node, member, pos) => {
35
35
  };
36
36
  const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) => {
37
37
  const { skipTypeOnly, tags, ignoreExportsUsedInFile } = options;
38
- const internalImports = new Map();
39
- const externalImports = new Set();
40
- const unresolvedImports = new Set();
38
+ const internal = new Map();
39
+ const external = new Set();
40
+ const unresolved = new Set();
41
41
  const resolved = new Set();
42
42
  const specifiers = new Set();
43
43
  const exports = new Map();
@@ -80,10 +80,10 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
80
80
  const { identifier, symbol, filePath, namespace, alias, specifier, isReExport } = options;
81
81
  const isStar = identifier === IMPORT_STAR;
82
82
  specifiers.add([specifier, filePath]);
83
- const file = internalImports.get(filePath);
83
+ const file = internal.get(filePath);
84
84
  const imports = file ?? createImports();
85
85
  if (!file)
86
- internalImports.set(filePath, imports);
86
+ internal.set(filePath, imports);
87
87
  const nsOrAlias = symbol ? String(symbol.escapedName) : alias;
88
88
  if (isReExport) {
89
89
  if (isStar && namespace) {
@@ -134,7 +134,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
134
134
  if (!isStartsLikePackageName(sanitizedSpecifier)) {
135
135
  return;
136
136
  }
137
- externalImports.add(sanitizedSpecifier);
137
+ external.add(sanitizedSpecifier);
138
138
  }
139
139
  }
140
140
  }
@@ -147,10 +147,10 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
147
147
  return;
148
148
  if (typeof pos === 'number') {
149
149
  const { line, character } = sourceFile.getLineAndCharacterOfPosition(pos);
150
- unresolvedImports.add({ specifier, pos, line: line + 1, col: character + 1 });
150
+ unresolved.add({ specifier, pos, line: line + 1, col: character + 1 });
151
151
  }
152
152
  else {
153
- unresolvedImports.add({ specifier });
153
+ unresolved.add({ specifier });
154
154
  }
155
155
  }
156
156
  };
@@ -161,7 +161,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
161
161
  const importedSymbolFilePath = importedInternalSymbols.get(symbol);
162
162
  if (importedSymbolFilePath) {
163
163
  const importId = String(symbol.escapedName);
164
- const internalImport = internalImports.get(importedSymbolFilePath);
164
+ const internalImport = internal.get(importedSymbolFilePath);
165
165
  if (internalImport) {
166
166
  if (importId !== identifier) {
167
167
  addNsValue(internalImport.reExportedAs, importId, identifier, sourceFile.fileName);
@@ -242,7 +242,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
242
242
  if (symbol) {
243
243
  if (filePath) {
244
244
  if (!isImportSpecifier(node)) {
245
- const imports = internalImports.get(filePath);
245
+ const imports = internal.get(filePath);
246
246
  if (imports) {
247
247
  traceRefs.add(id);
248
248
  if (isAccessExpression(node.parent)) {
@@ -277,6 +277,9 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
277
277
  else if (isObjectEnumerationCallExpressionArgument(node)) {
278
278
  imports.refs.add(id);
279
279
  }
280
+ else if (isInForIteration(node)) {
281
+ imports.refs.add(id);
282
+ }
280
283
  }
281
284
  }
282
285
  }
@@ -294,7 +297,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
294
297
  const namespace = left.text;
295
298
  const { filePath } = getImport(namespace, node);
296
299
  if (filePath) {
297
- const internalImport = internalImports.get(filePath);
300
+ const internalImport = internal.get(filePath);
298
301
  if (internalImport)
299
302
  addNsMemberRefs(internalImport, namespace, right.text);
300
303
  }
@@ -327,17 +330,9 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options) =
327
330
  item.symbol = undefined;
328
331
  }
329
332
  return {
330
- imports: {
331
- internal: internalImports,
332
- external: externalImports,
333
- resolved,
334
- specifiers,
335
- unresolved: unresolvedImports,
336
- },
337
- exports: {
338
- exported: exports,
339
- duplicate: [...aliasedExports.values()],
340
- },
333
+ imports: { internal, external, resolved, specifiers, unresolved },
334
+ exports,
335
+ duplicates: [...aliasedExports.values()],
341
336
  scripts,
342
337
  traceRefs,
343
338
  };
@@ -1,8 +1,9 @@
1
1
  import ts from 'typescript';
2
2
  import { FIX_FLAGS } from '../../../constants.js';
3
3
  import { SymbolType } from '../../../types/issues.js';
4
+ import { isModule } from '../helpers.js';
4
5
  import { exportVisitor as visit } from '../index.js';
5
- export default visit(() => true, (node, { isFixExports }) => {
6
+ export default visit(isModule, (node, { isFixExports }) => {
6
7
  if (ts.isExportAssignment(node)) {
7
8
  const pos = node.getChildAt(1).getStart();
8
9
  const fix = isFixExports ? [node.getStart(), node.getEnd() + 1, FIX_FLAGS.NONE] : undefined;
@@ -1,8 +1,9 @@
1
1
  import ts from 'typescript';
2
2
  import { FIX_FLAGS } from '../../../constants.js';
3
3
  import { SymbolType } from '../../../types/issues.js';
4
+ import { isModule } from '../helpers.js';
4
5
  import { exportVisitor as visit } from '../index.js';
5
- export default visit(() => true, (node, { isFixExports, isFixTypes }) => {
6
+ export default visit(isModule, (node, { isFixExports, isFixTypes }) => {
6
7
  if (ts.isExportDeclaration(node)) {
7
8
  if (node.exportClause && ts.isNamedExports(node.exportClause)) {
8
9
  const nodeType = node.isTypeOnly ? SymbolType.TYPE : SymbolType.UNKNOWN;
@@ -3,8 +3,9 @@ import { FIX_FLAGS } from '../../../constants.js';
3
3
  import { SymbolType } from '../../../types/issues.js';
4
4
  import { compact } from '../../../util/array.js';
5
5
  import { getDefaultKeywordNode, getExportKeywordNode, isGetOrSetAccessorDeclaration, isPrivateMember, stripQuotes, } from '../../ast-helpers.js';
6
+ import { isModule } from '../helpers.js';
6
7
  import { exportVisitor as visit } from '../index.js';
7
- export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClassMembers }) => {
8
+ export default visit(isModule, (node, { isFixExports, isFixTypes, isReportClassMembers }) => {
8
9
  const exportKeyword = getExportKeywordNode(node);
9
10
  if (exportKeyword) {
10
11
  const getFix = (node, defaultKeyword) => isFixExports ? [node.getStart(), (defaultKeyword ?? node).getEnd() + 1, FIX_FLAGS.NONE] : undefined;
@@ -14,9 +15,7 @@ export default visit(() => true, (node, { isFixExports, isFixTypes, isReportClas
14
15
  if (ts.isObjectBindingPattern(declaration.name)) {
15
16
  return compact(declaration.name.elements.map(element => {
16
17
  if (ts.isIdentifier(element.name)) {
17
- const fix = isFixExports
18
- ? [element.getStart(), element.getEnd(), FIX_FLAGS.OBJECT_BINDING]
19
- : undefined;
18
+ const fix = isFixExports ? [element.getStart(), element.getEnd(), FIX_FLAGS.OBJECT_BINDING] : undefined;
20
19
  return {
21
20
  node: element,
22
21
  symbol: element.symbol,
@@ -3,5 +3,6 @@ import type { ImportNode } from '../../types/imports.js';
3
3
  import type { BoundSourceFile } from '../SourceFile.js';
4
4
  export declare const isNotJS: (sourceFile: BoundSourceFile) => boolean;
5
5
  export declare const isJS: (sourceFile: BoundSourceFile) => boolean;
6
+ export declare const isModule: (sourceFile: BoundSourceFile) => boolean;
6
7
  export declare function getImportsFromPragmas(sourceFile: BoundSourceFile): ImportNode[];
7
- export declare function hasImportSpecifier(node: ts.Statement, name: string): boolean;
8
+ export declare function hasImportSpecifier(node: ts.Statement, name: string, id?: string): boolean;
@@ -1,6 +1,7 @@
1
1
  import ts from 'typescript';
2
2
  export const isNotJS = (sourceFile) => !isJS(sourceFile);
3
3
  export const isJS = (sourceFile) => sourceFile.scriptKind === ts.ScriptKind.JS || sourceFile.scriptKind === ts.ScriptKind.JSX;
4
+ export const isModule = (sourceFile) => ts.isExternalModule(sourceFile);
4
5
  export function getImportsFromPragmas(sourceFile) {
5
6
  const importNodes = [];
6
7
  if (sourceFile.pragmas) {
@@ -28,11 +29,11 @@ export function getImportsFromPragmas(sourceFile) {
28
29
  }
29
30
  return importNodes;
30
31
  }
31
- export function hasImportSpecifier(node, name) {
32
+ export function hasImportSpecifier(node, name, id) {
32
33
  return (ts.isImportDeclaration(node) &&
33
34
  ts.isStringLiteral(node.moduleSpecifier) &&
34
35
  node.moduleSpecifier.text === name &&
35
36
  !!node.importClause?.namedBindings &&
36
37
  ts.isNamedImports(node.importClause.namedBindings) &&
37
- node.importClause.namedBindings.elements.some(element => element.name.text === '$'));
38
+ (!id || node.importClause.namedBindings.elements.some(element => element.name.text === id)));
38
39
  }
@@ -2,7 +2,7 @@ import ts from 'typescript';
2
2
  import { stripQuotes } from '../../ast-helpers.js';
3
3
  import { hasImportSpecifier } from '../helpers.js';
4
4
  import { scriptVisitor as visit } from '../index.js';
5
- export default visit(sourceFile => sourceFile.statements.some(node => hasImportSpecifier(node, 'bun')), node => {
5
+ export default visit(sourceFile => sourceFile.statements.some(node => hasImportSpecifier(node, 'bun', '$')), node => {
6
6
  if (ts.isTaggedTemplateExpression(node) && node.tag.getText() === '$') {
7
7
  return stripQuotes(node.template.getText());
8
8
  }
@@ -2,10 +2,33 @@ import ts from 'typescript';
2
2
  import { stripQuotes } from '../../ast-helpers.js';
3
3
  import { hasImportSpecifier } from '../helpers.js';
4
4
  import { scriptVisitor as visit } from '../index.js';
5
+ const tags = new Set(['$', '$sync']);
6
+ const methods = new Set(['execa', 'execaSync', 'execaCommand', 'execaCommandSync', '$sync']);
5
7
  export default visit(sourceFile => sourceFile.statements.some(node => hasImportSpecifier(node, 'execa')), node => {
6
8
  if (ts.isTaggedTemplateExpression(node)) {
7
- if (node.tag.getText() === '$' || (ts.isCallExpression(node.tag) && node.tag.expression.getText() === '$')) {
9
+ if (tags.has(node.tag.getText()) || (ts.isCallExpression(node.tag) && tags.has(node.tag.expression.getText()))) {
8
10
  return stripQuotes(node.template.getText());
9
11
  }
10
12
  }
13
+ if (ts.isCallExpression(node)) {
14
+ const functionName = node.expression.getText();
15
+ if (methods.has(functionName)) {
16
+ if (functionName.startsWith('execaCommand')) {
17
+ if (node.arguments[0] && ts.isStringLiteral(node.arguments[0])) {
18
+ return stripQuotes(node.arguments[0].getText());
19
+ }
20
+ }
21
+ else {
22
+ const [executable, args] = node.arguments;
23
+ if (executable && ts.isStringLiteral(executable)) {
24
+ const executableStr = stripQuotes(executable.getText());
25
+ if (args && ts.isArrayLiteralExpression(args)) {
26
+ const argStrings = args.elements.filter(ts.isStringLiteral).map(arg => stripQuotes(arg.getText()));
27
+ return [executableStr, ...argStrings].join(' ');
28
+ }
29
+ return executableStr;
30
+ }
31
+ }
32
+ }
33
+ }
11
34
  });
@@ -36,10 +36,8 @@ const createFileNode = () => ({
36
36
  external: new Set(),
37
37
  unresolved: new Set(),
38
38
  },
39
- exports: {
40
- exported: new Map(),
41
- duplicate: new Set(),
42
- },
39
+ exports: new Map(),
40
+ duplicates: new Set(),
43
41
  scripts: new Set(),
44
42
  traceRefs: new Set(),
45
43
  });
@@ -1,12 +1,10 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { timerify } from './Performance.js';
4
- import parsedArgValues from './cli-arguments.js';
5
4
  import { debugLog } from './debug.js';
6
5
  import { isDirectory, isFile } from './fs.js';
7
- import { dirname, isAbsolute, resolve } from './path.js';
6
+ import { cwd, dirname, isAbsolute, resolve } from './path.js';
8
7
  import { deserialize, serialize } from './serialize.js';
9
- const cwd = process.cwd();
10
8
  const createCache = (filePath) => {
11
9
  try {
12
10
  return deserialize(fs.readFileSync(filePath));
@@ -21,9 +19,7 @@ export class FileEntryCache {
21
19
  cache = new Map();
22
20
  normalizedEntries = new Map();
23
21
  constructor(cacheId, _path) {
24
- const { 'cache-location': cacheLocation } = parsedArgValues;
25
- const currentPath = cacheLocation ? path.resolve(cacheLocation) : path.resolve(cwd);
26
- this.filePath = isAbsolute(currentPath) ? path.join(currentPath, cacheId) : path.join(currentPath, _path, cacheId);
22
+ this.filePath = isAbsolute(_path) ? path.resolve(_path, cacheId) : path.resolve(cwd, _path, cacheId);
27
23
  if (isFile(this.filePath))
28
24
  this.cache = create(this.filePath);
29
25
  this.removeNotFoundFiles();
@@ -35,7 +35,7 @@ export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnore
35
35
  const isHandled = deputy.maybeAddReferencedExternalDependency(inputWorkspace, packageName);
36
36
  if (isWorkspace || isDependency(input)) {
37
37
  if (!isHandled) {
38
- if ((deputy.isProduction && input.production) || !deputy.isProduction) {
38
+ if (!input.optional && ((deputy.isProduction && input.production) || !deputy.isProduction)) {
39
39
  collector.addIssue({
40
40
  type: 'unlisted',
41
41
  filePath: containingFilePath,
@@ -47,7 +47,7 @@ export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnore
47
47
  return;
48
48
  }
49
49
  const ref = _resolveSync(specifier, dirname(containingFilePath));
50
- if (ref && !isGitIgnored(ref))
50
+ if (ref && isInternal(ref) && !isGitIgnored(ref))
51
51
  return ref;
52
52
  }
53
53
  if (isHandled)
@@ -63,6 +63,8 @@ export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnore
63
63
  if (resolvedFilePath && isInternal(resolvedFilePath)) {
64
64
  return isGitIgnored(resolvedFilePath) ? undefined : resolvedFilePath;
65
65
  }
66
+ if (input.optional)
67
+ return;
66
68
  if (!isInternal(filePath)) {
67
69
  collector.addIssue({
68
70
  type: 'unlisted',
@@ -4,6 +4,7 @@ export interface Input {
4
4
  type: InputType;
5
5
  specifier: string;
6
6
  production?: boolean;
7
+ optional?: boolean;
7
8
  dir?: string;
8
9
  containingFilePath?: string;
9
10
  }
@@ -14,6 +15,7 @@ export interface ConfigInput extends Input {
14
15
  }
15
16
  type Options = {
16
17
  production?: boolean;
18
+ optional?: boolean;
17
19
  dir?: string;
18
20
  containingFilePath?: string;
19
21
  };
@@ -26,7 +28,7 @@ export declare const toProductionEntry: (specifier: string, options?: Options) =
26
28
  export declare const isProductionEntry: (input: Input) => boolean;
27
29
  export declare const toConfig: (pluginName: PluginName, specifier: string, containingFilePath: string) => ConfigInput;
28
30
  export declare const isConfigPattern: (input: Input) => input is ConfigInput;
29
- export declare const toDependency: (specifier: string) => Input;
31
+ export declare const toDependency: (specifier: string, options?: Options) => Input;
30
32
  export declare const isDependency: (input: Input) => boolean;
31
33
  export declare const toProductionDependency: (specifier: string) => Input;
32
34
  export declare const toDevDependency: (specifier: string) => Input;
@@ -22,7 +22,11 @@ export const toConfig = (pluginName, specifier, containingFilePath) => ({
22
22
  containingFilePath,
23
23
  });
24
24
  export const isConfigPattern = (input) => input.type === 'config';
25
- export const toDependency = (specifier) => ({ type: 'dependency', specifier });
25
+ export const toDependency = (specifier, options = {}) => ({
26
+ type: 'dependency',
27
+ specifier,
28
+ ...options,
29
+ });
26
30
  export const isDependency = (input) => input.type === 'dependency';
27
31
  export const toProductionDependency = (specifier) => ({
28
32
  type: 'dependency',
@@ -19,7 +19,7 @@ export const getPackageNameFromFilePath = (value) => {
19
19
  export const getPackageNameFromSpecifier = (specifier) => isInNodeModules(specifier) ? getPackageNameFromFilePath(specifier) : getPackageNameFromModuleSpecifier(specifier);
20
20
  export const isStartsLikePackageName = (specifier) => /^(@[a-z0-9._]|[a-z0-9])/i.test(specifier);
21
21
  export const stripVersionFromSpecifier = (specifier) => specifier.replace(/(\S+)@.*/, '$1');
22
- const stripNodeModulesFromPath = (command) => command.replace(/^(\.\/)?node_modules\//, '');
22
+ const stripNodeModulesFromPath = (command) => command.replace(/(?:\.{0,2}\/)*node_modules\//, '');
23
23
  export const extractBinary = (command) => stripVersionFromSpecifier(stripNodeModulesFromPath(command)
24
24
  .replace(/^(\.bin\/)/, '')
25
25
  .replace(/\$\(npm bin\)\/(\w+)/, '$1'));
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.41.1";
1
+ export declare const version = "5.42.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.41.1';
1
+ export const version = '5.42.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.41.1",
3
+ "version": "5.42.1",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {
@@ -41,6 +41,7 @@
41
41
  "lint": "biome lint ../..",
42
42
  "format": "biome format --write .",
43
43
  "test": "bun test test/*.test.ts test/**/*.test.ts",
44
+ "test:watch": "bun test test/*.test.ts test/**/*.test.ts --reporter=junit --reporter-outfile=junit.xml || bun test --watch $(grep -o 'name=\"[^\"]*\".*failures=\"[^0]' junit.xml | grep -v 'name=\"bun test\"' | grep -o 'name=\"[^\"]*\"' | cut -d'\"' -f2)",
44
45
  "test:node": "glob -c \"npx -y tsx --test --import ./transform-test.js\" \"test/**/*.test.ts\"",
45
46
  "watch": "npm link && tsc --watch",
46
47
  "prebuild": "npm run generate-plugin-defs && node rmdir.js dist",
@@ -48,7 +49,7 @@
48
49
  "qa": "bun lint && bun run build && bun knip && bun knip:production && bun run test",
49
50
  "release": "release-it",
50
51
  "create-plugin": "bun ./scripts/create-new-plugin.ts",
51
- "postcreate-plugin": "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/ConfigurationValidator.ts",
52
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"
53
54
  },
54
55
  "files": [
@@ -58,12 +59,12 @@
58
59
  "schema-jsonc.json"
59
60
  ],
60
61
  "dependencies": {
61
- "@nodelib/fs.walk": "1.2.8",
62
+ "@nodelib/fs.walk": "3.0.1",
62
63
  "@snyk/github-codeowners": "1.1.0",
63
64
  "easy-table": "1.2.0",
64
- "enhanced-resolve": "^5.17.1",
65
- "fast-glob": "^3.3.2",
66
- "jiti": "^2.4.0",
65
+ "enhanced-resolve": "^5.18.0",
66
+ "fast-glob": "^3.3.3",
67
+ "jiti": "^2.4.2",
67
68
  "js-yaml": "^4.1.0",
68
69
  "minimist": "^1.2.8",
69
70
  "picocolors": "^1.1.0",
@@ -81,20 +82,20 @@
81
82
  },
82
83
  "devDependencies": {
83
84
  "@jest/types": "^29.6.3",
84
- "@release-it/bumper": "^6.0.1",
85
- "@types/bun": "^1.1.13",
85
+ "@release-it/bumper": "^7.0.0",
86
+ "@types/bun": "^1.1.16",
86
87
  "@types/js-yaml": "^4.0.9",
87
88
  "@types/minimist": "^1.2.5",
88
89
  "@types/picomatch": "3.0.1",
89
90
  "@types/webpack": "^5.28.5",
90
- "@wdio/types": "^9.2.2",
91
+ "@wdio/types": "^9.5.0",
91
92
  "glob": "^10.4.2",
92
- "release-it": "^17.10.0",
93
- "type-fest": "^4.26.1",
93
+ "release-it": "^18.1.1",
94
+ "type-fest": "^4.31.0",
94
95
  "typescript": "^5.5.2"
95
96
  },
96
97
  "engines": {
97
- "node": ">=18.6.0"
98
+ "node": ">=18.18.0"
98
99
  },
99
100
  "engineStrict": true,
100
101
  "keywords": [