knip 6.34.0 → 6.35.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.
Files changed (79) hide show
  1. package/dist/CatalogCounselor.d.ts +2 -0
  2. package/dist/CatalogCounselor.js +30 -7
  3. package/dist/ConfigurationChief.d.ts +6 -0
  4. package/dist/ConfigurationChief.js +3 -5
  5. package/dist/ProjectPrincipal.d.ts +9 -10
  6. package/dist/ProjectPrincipal.js +45 -52
  7. package/dist/WorkspaceWorker.d.ts +3 -3
  8. package/dist/WorkspaceWorker.js +6 -6
  9. package/dist/YamlCatalogPeeker.d.ts +4 -0
  10. package/dist/YamlCatalogPeeker.js +17 -0
  11. package/dist/binaries/bash-parser.d.ts +1 -1
  12. package/dist/binaries/bash-parser.js +12 -58
  13. package/dist/binaries/command.d.ts +5 -0
  14. package/dist/binaries/command.js +47 -0
  15. package/dist/binaries/fallback.d.ts +2 -0
  16. package/dist/binaries/fallback.js +2 -0
  17. package/dist/binaries/plugins.d.ts +1 -0
  18. package/dist/binaries/plugins.js +2 -1
  19. package/dist/binaries/resolvers/pnpm.js +1 -0
  20. package/dist/binaries/util.d.ts +1 -0
  21. package/dist/binaries/util.js +12 -0
  22. package/dist/cli.js +8 -26
  23. package/dist/compilers/index.d.ts +3 -1866
  24. package/dist/compilers/index.js +17 -27
  25. package/dist/compilers/types.d.ts +4 -5
  26. package/dist/graph/analyze.js +71 -53
  27. package/dist/graph/build.d.ts +3 -3
  28. package/dist/graph/build.js +63 -31
  29. package/dist/plugins/_vue/auto-import.js +28 -4
  30. package/dist/plugins/index.d.ts +1 -0
  31. package/dist/plugins/index.js +2 -0
  32. package/dist/plugins/mise/index.d.ts +3 -0
  33. package/dist/plugins/mise/index.js +82 -0
  34. package/dist/plugins/mise/scripts.d.ts +7 -0
  35. package/dist/plugins/mise/scripts.js +108 -0
  36. package/dist/plugins/mise/types.d.ts +26 -0
  37. package/dist/plugins/mise/types.js +1 -0
  38. package/dist/plugins/rstest/index.js +3 -2
  39. package/dist/plugins/rstest/types.d.ts +3 -1
  40. package/dist/plugins/vite/helpers.d.ts +2 -2
  41. package/dist/plugins/vite/helpers.js +18 -11
  42. package/dist/plugins/vite/visitors/importMetaGlob.js +12 -0
  43. package/dist/plugins/vitest/index.js +5 -2
  44. package/dist/plugins/vitest/types.d.ts +1 -0
  45. package/dist/schema/configuration.d.ts +20 -4
  46. package/dist/schema/configuration.js +5 -6
  47. package/dist/schema/plugins.d.ts +5 -0
  48. package/dist/schema/plugins.js +1 -0
  49. package/dist/session/index.d.ts +1 -1
  50. package/dist/session/index.js +1 -1
  51. package/dist/session/session.js +22 -4
  52. package/dist/types/PluginNames.d.ts +2 -2
  53. package/dist/types/PluginNames.js +1 -0
  54. package/dist/types/config.d.ts +4 -4
  55. package/dist/types/module-graph.d.ts +2 -0
  56. package/dist/types.d.ts +1 -0
  57. package/dist/typescript/SourceFileManager.d.ts +13 -9
  58. package/dist/typescript/SourceFileManager.js +58 -22
  59. package/dist/typescript/get-imports-and-exports.js +2 -1
  60. package/dist/typescript/visitors/exports.js +8 -4
  61. package/dist/util/catalog.d.ts +5 -0
  62. package/dist/util/catalog.js +37 -17
  63. package/dist/util/create-options.d.ts +17 -3
  64. package/dist/util/create-options.js +14 -3
  65. package/dist/util/errors.d.ts +3 -1
  66. package/dist/util/errors.js +6 -1
  67. package/dist/util/file-entry-cache.js +2 -2
  68. package/dist/util/module-graph.js +1 -0
  69. package/dist/util/package-json.d.ts +1 -0
  70. package/dist/util/preprocessor.d.ts +6 -0
  71. package/dist/util/preprocessor.js +24 -0
  72. package/dist/util/reporter.d.ts +0 -1
  73. package/dist/util/reporter.js +0 -7
  74. package/dist/util/watch.d.ts +1 -1
  75. package/dist/util/watch.js +33 -15
  76. package/dist/version.d.ts +1 -1
  77. package/dist/version.js +1 -1
  78. package/package.json +7 -7
  79. package/schema.json +12 -0
@@ -1,7 +1,7 @@
1
1
  import type { Program, VisitorObject } from 'oxc-parser';
2
2
  import type { Word } from 'unbash';
3
3
  import type { z } from 'zod/mini';
4
- import type { AsyncCompilers, CompilerSync, HasDependency, SyncCompilers } from '../compilers/types.ts';
4
+ import type { Compiler, HasDependency, RawCompilers } from '../compilers/types.ts';
5
5
  import type { knipConfigurationSchema, workspaceConfigurationSchema } from '../schema/configuration.ts';
6
6
  import type { pluginSchema } from '../schema/plugins.ts';
7
7
  import type { ParsedCLIArgs } from '../util/cli-arguments.ts';
@@ -56,8 +56,7 @@ export interface Configuration {
56
56
  ignoreUnresolved: IgnorePatterns;
57
57
  ignoreWorkspaces: string[];
58
58
  isIncludeEntryExports: boolean;
59
- syncCompilers: SyncCompilers;
60
- asyncCompilers: AsyncCompilers;
59
+ compilers: RawCompilers;
61
60
  rootPluginConfigs: Partial<PluginsConfiguration>;
62
61
  }
63
62
  type NormalizedGlob = string[];
@@ -121,7 +120,7 @@ export type ResolveSourceMap = (options: ResolveSourceMapOptions) => Promise<Sou
121
120
  export type HandleInput = (input: Input) => string | undefined;
122
121
  type RegisterCompilerInput = {
123
122
  extension: string;
124
- compiler: CompilerSync;
123
+ compiler: Compiler;
125
124
  };
126
125
  export type RegisterCompiler = (input: RegisterCompilerInput) => void;
127
126
  export type ResolveFromAST = (program: Program, options: PluginOptions & {
@@ -143,6 +142,7 @@ export type PluginVisitorContext = {
143
142
  base?: string;
144
143
  cwd?: string;
145
144
  filter?: RegExp;
145
+ analyzeExports?: boolean;
146
146
  }) => void;
147
147
  markExportRegistered: (name: string) => void;
148
148
  };
@@ -58,6 +58,7 @@ export interface ExportMember extends Position {
58
58
  type ExportMap = Map<Identifier, Export>;
59
59
  export type Imports = Set<Import>;
60
60
  export type FileNode = {
61
+ skipExports: boolean;
61
62
  imports: {
62
63
  readonly internal: ImportMap;
63
64
  readonly external: Set<Import>;
@@ -79,6 +80,7 @@ export interface ImportGlob {
79
80
  base?: string;
80
81
  cwd?: string;
81
82
  filter?: RegExp;
83
+ analyzeExports?: boolean;
82
84
  }
83
85
  export type ModuleGraph = Map<FilePath, FileNode>;
84
86
  export {};
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type { Compiler, CompilerResult } from './compilers/types.ts';
1
2
  export type { RawConfigurationOrFn as KnipConfig, RawConfiguration as KnipConfiguration, WorkspaceProjectConfig, } from './types/config.ts';
2
3
  export type { Issue, IssueRecords, IssueType, Preprocessor, Reporter, ReporterOptions } from './types/issues.ts';
3
4
  export type { JSONReport, JSONReportEntry, JSONReportItem, JSONReportNamedItem } from './reporters/json.ts';
@@ -1,15 +1,19 @@
1
- import type { AsyncCompilers, SyncCompilers } from '../compilers/types.ts';
1
+ import type { Compilers } from '../compilers/types.ts';
2
2
  interface SourceFileManagerOptions {
3
- compilers: [SyncCompilers, AsyncCompilers];
3
+ compilers: Compilers;
4
+ isSession?: boolean;
4
5
  }
5
6
  export declare class SourceFileManager {
6
- sourceTextCache: Map<string, string>;
7
- syncCompilers: SyncCompilers;
8
- asyncCompilers: AsyncCompilers;
9
- constructor({ compilers }: SourceFileManagerOptions);
10
- readFile(filePath: string): string;
7
+ sourceTextCache: Map<string, string | Promise<string>>;
8
+ compilers: Compilers;
9
+ private rawContentHashes;
10
+ private isSession;
11
+ constructor({ compilers, isSession }: SourceFileManagerOptions);
12
+ loadSourceText(filePath: string): string | Promise<string>;
11
13
  invalidate(filePath: string): void;
12
- compileAndAddSourceFile(filePath: string): Promise<void>;
13
- private readRawFile;
14
+ hasChanged(filePath: string): boolean;
15
+ readRawFile(filePath: string): string | undefined;
16
+ private cacheSourceText;
17
+ private validateCompilerResult;
14
18
  }
15
19
  export {};
@@ -1,21 +1,24 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { readFileSync } from 'node:fs';
2
3
  import { FOREIGN_FILE_EXTENSIONS } from '../constants.js';
3
4
  import { debugLog } from '../util/debug.js';
5
+ import { CompilerError, ConfigurationError } from '../util/errors.js';
4
6
  import { extname, isInternal } from '../util/path.js';
5
7
  export class SourceFileManager {
6
8
  sourceTextCache = new Map();
7
- syncCompilers;
8
- asyncCompilers;
9
- constructor({ compilers }) {
10
- this.syncCompilers = compilers[0];
11
- this.asyncCompilers = compilers[1];
9
+ compilers;
10
+ rawContentHashes = new Map();
11
+ isSession;
12
+ constructor({ compilers, isSession = false }) {
13
+ this.compilers = compilers;
14
+ this.isSession = isSession;
12
15
  }
13
- readFile(filePath) {
16
+ loadSourceText(filePath) {
14
17
  const cachedSourceText = this.sourceTextCache.get(filePath);
15
18
  if (cachedSourceText !== undefined)
16
19
  return cachedSourceText;
17
20
  const ext = extname(filePath);
18
- const compiler = this.syncCompilers.get(ext);
21
+ const compiler = this.compilers.get(ext);
19
22
  if (FOREIGN_FILE_EXTENSIONS.has(ext) && !compiler) {
20
23
  this.sourceTextCache.set(filePath, '');
21
24
  return '';
@@ -27,26 +30,47 @@ export class SourceFileManager {
27
30
  this.sourceTextCache.set(filePath, '');
28
31
  return '';
29
32
  }
30
- const compiled = compiler ? compiler(contents, filePath) : contents;
31
- if (compiler)
32
- debugLog('*', `Compiled ${filePath}`);
33
- this.sourceTextCache.set(filePath, compiled);
34
- return compiled;
33
+ if (!compiler)
34
+ return this.cacheSourceText(filePath, contents, contents);
35
+ let result;
36
+ try {
37
+ result = compiler(contents, filePath);
38
+ if (result !== null && (typeof result === 'object' || typeof result === 'function')) {
39
+ const pending = Promise.resolve(result).then(result => {
40
+ const isCurrent = this.sourceTextCache.get(filePath) === pending;
41
+ if (isCurrent)
42
+ this.sourceTextCache.delete(filePath);
43
+ const sourceText = this.validateCompilerResult(result, filePath, ext);
44
+ if (isCurrent)
45
+ this.cacheSourceText(filePath, sourceText, contents);
46
+ debugLog('*', `Compiled ${filePath}`);
47
+ return sourceText;
48
+ }, cause => {
49
+ if (this.sourceTextCache.get(filePath) === pending)
50
+ this.sourceTextCache.delete(filePath);
51
+ throw new CompilerError(`Compiler for ${ext} failed (${filePath})`, { cause });
52
+ });
53
+ this.sourceTextCache.set(filePath, pending);
54
+ return pending;
55
+ }
56
+ }
57
+ catch (cause) {
58
+ throw new CompilerError(`Compiler for ${ext} failed (${filePath})`, { cause });
59
+ }
60
+ const sourceText = this.validateCompilerResult(result, filePath, ext);
61
+ debugLog('*', `Compiled ${filePath}`);
62
+ return this.cacheSourceText(filePath, sourceText, contents);
35
63
  }
36
64
  invalidate(filePath) {
37
65
  this.sourceTextCache.delete(filePath);
66
+ this.rawContentHashes.delete(filePath);
38
67
  }
39
- async compileAndAddSourceFile(filePath) {
68
+ hasChanged(filePath) {
69
+ const previousHash = this.rawContentHashes.get(filePath);
70
+ if (previousHash === undefined)
71
+ return true;
40
72
  const contents = this.readRawFile(filePath);
41
- if (contents === undefined)
42
- throw new Error(`Unable to read ${filePath}`);
43
- const ext = extname(filePath);
44
- const compiler = this.asyncCompilers.get(ext);
45
- if (compiler) {
46
- const compiled = await compiler(contents, filePath);
47
- debugLog('*', `Compiled ${filePath}`);
48
- this.sourceTextCache.set(filePath, compiled);
49
- }
73
+ return contents === undefined || createHash('sha1').update(contents).digest('hex') !== previousHash;
50
74
  }
51
75
  readRawFile(filePath) {
52
76
  try {
@@ -56,4 +80,16 @@ export class SourceFileManager {
56
80
  return undefined;
57
81
  }
58
82
  }
83
+ cacheSourceText(filePath, sourceText, contents) {
84
+ this.sourceTextCache.set(filePath, sourceText);
85
+ if (this.isSession)
86
+ this.rawContentHashes.set(filePath, createHash('sha1').update(contents).digest('hex'));
87
+ return sourceText;
88
+ }
89
+ validateCompilerResult(result, filePath, ext) {
90
+ if (typeof result === 'string')
91
+ return result;
92
+ const category = result === null ? 'null' : typeof result;
93
+ throw new ConfigurationError(`Compiler for ${ext} returned ${category} for ${filePath}; expected a string or PromiseLike<string>`);
94
+ }
59
95
  }
@@ -283,7 +283,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
283
283
  pluginCtx.addScript = (s) => scripts.add(s);
284
284
  pluginCtx.addImport = (spec, pos, mod) => addImport(spec, undefined, undefined, undefined, pos, mod);
285
285
  pluginCtx.markImportExpressionHandled = (pos) => handledImportExpressions.add(pos);
286
- pluginCtx.addImportGlob = (patterns, opts) => importGlobs.push({ patterns, base: opts?.base, cwd: opts?.cwd, filter: opts?.filter });
286
+ pluginCtx.addImportGlob = (patterns, opts) => importGlobs.push({ patterns, ...opts });
287
287
  pluginCtx.markExportRegistered = (name) => registeredCustomElements.add(name);
288
288
  }
289
289
  const localRefs = _walkAST(result.program, sourceText, filePath, result.module.hasModuleSyntax, {
@@ -329,6 +329,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
329
329
  }
330
330
  }
331
331
  return {
332
+ skipExports,
332
333
  imports: { internal, external, externalRefs: new Set(), programFiles, entryFiles, imports, unresolved },
333
334
  exports,
334
335
  duplicates: [...aliasedExports.values()],
@@ -123,10 +123,14 @@ export function handleExportNamed(node, s) {
123
123
  s.accessedAliases.add(name);
124
124
  }
125
125
  }
126
- else if (prop.type === 'Property' &&
127
- prop.value?.type === 'ObjectExpression' &&
128
- prop.key?.type === 'Identifier') {
129
- findSpreads(prop.value, [...path, prop.key.name]);
126
+ else if (prop.type === 'Property' && prop.value?.type === 'ObjectExpression') {
127
+ const key = prop.key?.type === 'Identifier'
128
+ ? prop.key.name
129
+ : prop.key?.type === 'Literal' && typeof prop.key.value === 'string'
130
+ ? prop.key.value
131
+ : undefined;
132
+ if (key)
133
+ findSpreads(prop.value, [...path, key]);
130
134
  }
131
135
  }
132
136
  };
@@ -4,8 +4,13 @@ export declare const DEFAULT_CATALOG = "default";
4
4
  export type CatalogReference = {
5
5
  catalogName: string;
6
6
  packageName: string;
7
+ selector?: string;
8
+ };
9
+ export type OverrideCatalogReference = CatalogReference & {
10
+ selector: string;
7
11
  };
8
12
  export declare const getCatalogReference: (specifier: string) => CatalogReference | undefined;
9
13
  export declare const getCatalogContainer: (cwd: string, manifest: PackageJson, manifestPath: string, pnpmWorkspacePath?: string, pnpmWorkspace?: any) => Promise<CatalogContainer>;
10
14
  export declare const parseCatalog: (container: CatalogContainer) => Set<string>;
15
+ export declare const getOverrideCatalogReferences: (overrides: Record<string, string> | undefined) => OverrideCatalogReference[];
11
16
  export declare const extractCatalogReferences: (manifest: PackageJson) => CatalogReference[];
@@ -27,7 +27,7 @@ export const getCatalogContainer = async (cwd, manifest, manifestPath, pnpmWorks
27
27
  yarnWorkspace?.catalogs ??
28
28
  manifest.catalogs ??
29
29
  ((!Array.isArray(manifest.workspaces) && manifest.workspaces?.catalogs) || {});
30
- return { filePath, catalog, catalogs };
30
+ return { filePath, catalog, catalogs, overrides: pnpmWorkspace?.overrides };
31
31
  };
32
32
  const extractEntries = (catalog) => {
33
33
  if (catalog && typeof catalog === 'object')
@@ -56,23 +56,43 @@ export const parseCatalog = (container) => {
56
56
  entries.add(id);
57
57
  return entries;
58
58
  };
59
+ const OVERRIDE_DELIMITER = /[^ |@]>/;
60
+ const toCatalogReference = (packageName, version) => {
61
+ if (typeof version !== 'string' || !version.startsWith('catalog:'))
62
+ return;
63
+ return { catalogName: version.slice('catalog:'.length) || DEFAULT_CATALOG, packageName };
64
+ };
65
+ const collectCatalogReferences = (dependencies, catalogReferences) => {
66
+ if (!dependencies)
67
+ return;
68
+ for (const [packageName, version] of Object.entries(dependencies)) {
69
+ const reference = toCatalogReference(packageName, version);
70
+ if (reference)
71
+ catalogReferences.push(reference);
72
+ }
73
+ };
74
+ export const getOverrideCatalogReferences = (overrides) => {
75
+ const catalogReferences = [];
76
+ if (!overrides)
77
+ return catalogReferences;
78
+ for (const [selector, version] of Object.entries(overrides)) {
79
+ const delimiterIndex = selector.search(OVERRIDE_DELIMITER);
80
+ const target = delimiterIndex === -1 ? selector : selector.slice(delimiterIndex + 2);
81
+ const packageName = getPackageNameFromModuleSpecifier(target);
82
+ if (!packageName)
83
+ continue;
84
+ const reference = toCatalogReference(packageName, version);
85
+ if (reference)
86
+ catalogReferences.push({ ...reference, selector });
87
+ }
88
+ return catalogReferences;
89
+ };
59
90
  export const extractCatalogReferences = (manifest) => {
60
91
  const catalogReferences = [];
61
- const checkDependencies = (dependencies) => {
62
- if (!dependencies)
63
- return;
64
- for (const [name, version] of Object.entries(dependencies)) {
65
- if (typeof version === 'string' && version.startsWith('catalog:')) {
66
- const catalogName = version.slice('catalog:'.length) || DEFAULT_CATALOG;
67
- catalogReferences.push({ catalogName, packageName: name });
68
- }
69
- }
70
- };
71
- checkDependencies(manifest.dependencies);
72
- checkDependencies(manifest.devDependencies);
73
- checkDependencies(manifest.peerDependencies);
74
- checkDependencies(manifest.optionalDependencies);
75
- checkDependencies(manifest.resolutions);
76
- checkDependencies(manifest.pnpm?.overrides);
92
+ collectCatalogReferences(manifest.dependencies, catalogReferences);
93
+ collectCatalogReferences(manifest.devDependencies, catalogReferences);
94
+ collectCatalogReferences(manifest.peerDependencies, catalogReferences);
95
+ collectCatalogReferences(manifest.optionalDependencies, catalogReferences);
96
+ collectCatalogReferences(manifest.resolutions, catalogReferences);
77
97
  return catalogReferences;
78
98
  };
@@ -366,6 +366,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
366
366
  entry?: string | string[] | undefined;
367
367
  project?: string | string[] | undefined;
368
368
  } | undefined;
369
+ mise?: string | boolean | string[] | {
370
+ config?: string | string[] | undefined;
371
+ entry?: string | string[] | undefined;
372
+ project?: string | string[] | undefined;
373
+ } | undefined;
369
374
  mocha?: string | boolean | string[] | {
370
375
  config?: string | string[] | undefined;
371
376
  entry?: string | string[] | undefined;
@@ -975,12 +980,13 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
975
980
  } | undefined;
976
981
  ignoreWorkspaces?: string[] | undefined;
977
982
  includeEntryExports?: boolean | undefined;
978
- compilers?: Record<string, true | import("../compilers/types.ts").CompilerAsync | import("../compilers/types.ts").CompilerSync> | undefined;
979
- syncCompilers?: Record<string, true | import("../compilers/types.ts").CompilerSync> | undefined;
980
- asyncCompilers?: Record<string, import("../compilers/types.ts").CompilerAsync> | undefined;
983
+ compilers?: Record<string, true | import("../types.ts").Compiler> | undefined;
984
+ asyncCompilers?: Record<string, import("../types.ts").Compiler> | undefined;
981
985
  tags?: string[] | undefined;
982
986
  treatConfigHintsAsErrors?: boolean | undefined;
983
987
  treatTagHintsAsErrors?: boolean | undefined;
988
+ preprocessor?: string | string[] | undefined;
989
+ preprocessorOptions?: Record<string, unknown> | undefined;
984
990
  include?: ("binaries" | "catalog" | "catalogReferences" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
985
991
  exclude?: ("binaries" | "catalog" | "catalogReferences" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
986
992
  workspaces?: Record<string, {
@@ -1304,6 +1310,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1304
1310
  entry?: string | string[] | undefined;
1305
1311
  project?: string | string[] | undefined;
1306
1312
  } | undefined;
1313
+ mise?: string | boolean | string[] | {
1314
+ config?: string | string[] | undefined;
1315
+ entry?: string | string[] | undefined;
1316
+ project?: string | string[] | undefined;
1317
+ } | undefined;
1307
1318
  mocha?: string | boolean | string[] | {
1308
1319
  config?: string | string[] | undefined;
1309
1320
  entry?: string | string[] | undefined;
@@ -1908,6 +1919,9 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1908
1919
  includeEntryExports?: boolean | undefined;
1909
1920
  }> | undefined;
1910
1921
  };
1922
+ preprocessor: string[];
1923
+ preprocessorInputs: string[];
1924
+ preprocessorOptions: string;
1911
1925
  rules: {
1912
1926
  binaries: import("../types/issues.ts").IssueSeverity;
1913
1927
  catalog: import("../types/issues.ts").IssueSeverity;
@@ -1,6 +1,6 @@
1
- import { partitionCompilers } from '../compilers/index.js';
2
1
  import { ISSUE_TYPES, KNIP_CONFIG_LOCATIONS } from '../constants.js';
3
2
  import { knipConfigurationSchema } from '../schema/configuration.js';
3
+ import { arrayify } from './array.js';
4
4
  import { getCatalogContainer } from './catalog.js';
5
5
  import { parseNumericOption } from './cli-arguments.js';
6
6
  import { ConfigurationError } from './errors.js';
@@ -11,7 +11,7 @@ import { loadResolvedConfigFile } from './load-config.js';
11
11
  import { _load } from './loader.js';
12
12
  import { logWarning } from './log.js';
13
13
  import { getKeysByValue } from './object.js';
14
- import { isAbsolute, join, normalize, toAbsolute, toPosix } from './path.js';
14
+ import { isAbsolute, isInternal, join, normalize, toAbsolute, toPosix } from './path.js';
15
15
  import { splitTags } from './tag.js';
16
16
  export const createOptions = async (options) => {
17
17
  const { args = {} } = options;
@@ -56,7 +56,7 @@ export const createOptions = async (options) => {
56
56
  }
57
57
  }
58
58
  }
59
- const parsedConfig = knipConfigurationSchema.parse(partitionCompilers(loadedConfig));
59
+ const parsedConfig = knipConfigurationSchema.parse(loadedConfig);
60
60
  if (!configFilePath && manifest.knip)
61
61
  configFilePath = manifestPath;
62
62
  const pnpmWorkspacePath = findFile(cwd, 'pnpm-workspace.yaml');
@@ -94,6 +94,14 @@ export const createOptions = async (options) => {
94
94
  const isFixFiles = args['allow-remove-files'] && (fixTypes.length === 0 || fixTypes.includes('files'));
95
95
  const tags = splitTags(args.tags ?? options.tags ?? parsedConfig.tags ?? []);
96
96
  const workspace = options.workspace ?? args.workspace;
97
+ const toPreprocessor = (specifier) => (isInternal(specifier) ? toAbsolute(specifier, cwd) : specifier);
98
+ const configuredPreprocessor = arrayify(parsedConfig.preprocessor).map(toPreprocessor);
99
+ const preprocessor = args.preprocessor ? args.preprocessor.map(toPreprocessor) : configuredPreprocessor;
100
+ const preprocessorInputs = args.preprocessor
101
+ ? [...new Set([...configuredPreprocessor, ...preprocessor])]
102
+ : preprocessor;
103
+ const preprocessorOptions = args['preprocessor-options'] ??
104
+ (parsedConfig.preprocessorOptions ? JSON.stringify(parsedConfig.preprocessorOptions) : '');
97
105
  return {
98
106
  cacheLocation: args['cache-location'] ?? join(cwd, 'node_modules', '.cache', 'knip'),
99
107
  catalog: await getCatalogContainer(cwd, manifest, manifestPath, pnpmWorkspacePath, pnpmWorkspace),
@@ -154,6 +162,9 @@ export const createOptions = async (options) => {
154
162
  maxIssues: parseNumericOption(args['max-issues'], 'max-issues') ?? 0,
155
163
  maxShowIssues: parseNumericOption(args['max-show-issues'], 'max-show-issues'),
156
164
  parsedConfig,
165
+ preprocessor,
166
+ preprocessorInputs,
167
+ preprocessorOptions,
157
168
  rules,
158
169
  tags,
159
170
  traceDependency: args['trace-dependency'],
@@ -4,9 +4,11 @@ interface ErrorWithCause extends Error {
4
4
  }
5
5
  export declare class ConfigurationError extends Error {
6
6
  }
7
+ export declare class CompilerError extends Error {
8
+ }
7
9
  export declare class LoaderError extends Error {
8
10
  }
9
- export declare const isKnownError: (error: Error) => error is core.$ZodError<any> | ConfigurationError | LoaderError;
11
+ export declare const isKnownError: (error: Error) => error is core.$ZodError<any> | CompilerError | ConfigurationError | LoaderError;
10
12
  export declare const hasErrorCause: (error: Error) => error is ErrorWithCause;
11
13
  export declare const isConfigurationError: (error: Error) => error is ConfigurationError;
12
14
  export declare const isModuleNotFoundError: (error: Error) => boolean;
@@ -3,9 +3,14 @@ import { substringBefore } from './string.js';
3
3
  const isZodErrorLike = (error) => error instanceof core.$ZodError;
4
4
  export class ConfigurationError extends Error {
5
5
  }
6
+ export class CompilerError extends Error {
7
+ }
6
8
  export class LoaderError extends Error {
7
9
  }
8
- export const isKnownError = (error) => error instanceof ConfigurationError || error instanceof LoaderError || isZodErrorLike(error);
10
+ export const isKnownError = (error) => error instanceof ConfigurationError ||
11
+ error instanceof CompilerError ||
12
+ error instanceof LoaderError ||
13
+ isZodErrorLike(error);
9
14
  export const hasErrorCause = (error) => !isZodErrorLike(error) && error.cause instanceof Error;
10
15
  export const isConfigurationError = (error) => error instanceof ConfigurationError;
11
16
  export const isModuleNotFoundError = (error) => 'code' in error && error.code === 'MODULE_NOT_FOUND';
@@ -4,7 +4,7 @@ import { deserialize, serialize } from 'node:v8';
4
4
  import { debugLog } from './debug.js';
5
5
  import { isDirectory, isFile } from './fs.js';
6
6
  import { timerify } from './Performance.js';
7
- import { dirname, isAbsolute, resolve } from './path.js';
7
+ import { isAbsolute, resolve } from './path.js';
8
8
  const createCache = (filePath) => {
9
9
  try {
10
10
  return deserialize(fs.readFileSync(filePath));
@@ -70,7 +70,7 @@ export class FileEntryCache {
70
70
  }
71
71
  reconcile() {
72
72
  try {
73
- const dir = dirname(this.filePath);
73
+ const dir = path.dirname(this.filePath);
74
74
  if (!isDirectory(dir))
75
75
  fs.mkdirSync(dir, { recursive: true });
76
76
  fs.writeFileSync(this.filePath, serialize(this.cache));
@@ -35,6 +35,7 @@ export const updateImportMap = (file, importMap, graph) => {
35
35
  }
36
36
  };
37
37
  export const createFileNode = () => ({
38
+ skipExports: false,
38
39
  imports: {
39
40
  internal: new Map(),
40
41
  external: new Set(),
@@ -231,6 +231,7 @@ export declare const getPublishedTypeManifest: (manifest: PackageJson) => {
231
231
  mdx: unknown;
232
232
  mdxlint: unknown;
233
233
  metro: unknown;
234
+ mise: unknown;
234
235
  mocha: unknown;
235
236
  moonrepo: unknown;
236
237
  msw: unknown;
@@ -0,0 +1,6 @@
1
+ import type { Results } from '../run.ts';
2
+ import type { ReporterOptions } from '../types/issues.ts';
3
+ import type { ParsedCLIArgs } from './cli-arguments.ts';
4
+ import type { MainOptions } from './create-options.ts';
5
+ export declare const toReporterOptions: (options: MainOptions, results: Results, args?: ParsedCLIArgs) => ReporterOptions;
6
+ export declare const createPreprocessor: (processors: string[]) => Promise<(data: ReporterOptions) => Promise<ReporterOptions>>;
@@ -0,0 +1,24 @@
1
+ import { _load } from './loader.js';
2
+ export const toReporterOptions = (options, results, args) => ({
3
+ ...results,
4
+ report: options.includedIssueTypes,
5
+ cwd: options.cwd,
6
+ configFilePath: options.configFilePath,
7
+ isDisableConfigHints: options.isDisableConfigHints,
8
+ isDisableTagHints: options.isDisableTagHints,
9
+ isProduction: options.isProduction,
10
+ isShowProgress: options.isShowProgress,
11
+ isTreatConfigHintsAsErrors: options.isTreatConfigHintsAsErrors,
12
+ isTreatTagHintsAsErrors: options.isTreatTagHintsAsErrors,
13
+ maxShowIssues: options.maxShowIssues,
14
+ options: args?.['reporter-options'] ?? '',
15
+ preprocessorOptions: options.preprocessorOptions,
16
+ });
17
+ export const createPreprocessor = async (processors) => {
18
+ const preprocessors = await Promise.all(processors.map(_load));
19
+ return async (data) => {
20
+ for (const preprocessor of preprocessors)
21
+ data = await preprocessor(data);
22
+ return data;
23
+ };
24
+ };
@@ -1,3 +1,2 @@
1
1
  import type { ReporterOptions } from '../types/issues.ts';
2
- export declare const runPreprocessors: (processors: string[], data: ReporterOptions) => Promise<ReporterOptions>;
3
2
  export declare const runReporters: (reporter: string[], options: ReporterOptions) => Promise<void>;
@@ -1,13 +1,6 @@
1
1
  import internalReporters from '../reporters/index.js';
2
2
  import { _load } from './loader.js';
3
3
  import { isAbsolute, isInternal, resolve } from './path.js';
4
- export const runPreprocessors = async (processors, data) => {
5
- const preprocessors = await Promise.all(processors.map(proc => _load(isInternal(proc) && !isAbsolute(proc) ? resolve(proc) : proc)));
6
- let result = data;
7
- for (const preprocessor of preprocessors)
8
- result = await preprocessor(result);
9
- return result;
10
- };
11
4
  export const runReporters = async (reporter, options) => {
12
5
  const reporters = await Promise.all(reporter.map(async (reporter) => {
13
6
  return reporter in internalReporters
@@ -17,7 +17,7 @@ export type WatchChange = {
17
17
  export type SessionHandler = Awaited<ReturnType<typeof getSessionHandler>>;
18
18
  type WatchOptions = {
19
19
  analyzedFiles: Set<string>;
20
- analyzeSourceFile: (filePath: string, principal: ProjectPrincipal) => void;
20
+ analyzeSourceFile: (filePath: string) => Promise<void>;
21
21
  chief: ConfigurationChief;
22
22
  collector: IssueCollector;
23
23
  analyze: () => Promise<void>;