knip 6.33.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 (90) 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 +12 -10
  6. package/dist/ProjectPrincipal.js +56 -41
  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 +9 -27
  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 +74 -56
  27. package/dist/graph/build.d.ts +3 -3
  28. package/dist/graph/build.js +64 -32
  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/node/index.js +5 -0
  39. package/dist/plugins/node/visitors/fsPromisesGlob.d.ts +2 -0
  40. package/dist/plugins/node/visitors/fsPromisesGlob.js +89 -0
  41. package/dist/plugins/nuxt/index.js +13 -10
  42. package/dist/plugins/rstest/index.js +3 -2
  43. package/dist/plugins/rstest/types.d.ts +3 -1
  44. package/dist/plugins/vite/helpers.d.ts +2 -2
  45. package/dist/plugins/vite/helpers.js +18 -11
  46. package/dist/plugins/vite/visitors/importMetaGlob.js +12 -0
  47. package/dist/plugins/vitest/index.js +5 -2
  48. package/dist/plugins/vitest/types.d.ts +1 -0
  49. package/dist/run.js +1 -1
  50. package/dist/schema/configuration.d.ts +20 -4
  51. package/dist/schema/configuration.js +5 -6
  52. package/dist/schema/plugins.d.ts +5 -0
  53. package/dist/schema/plugins.js +1 -0
  54. package/dist/session/index.d.ts +1 -1
  55. package/dist/session/index.js +1 -1
  56. package/dist/session/session.js +22 -4
  57. package/dist/types/PluginNames.d.ts +2 -2
  58. package/dist/types/PluginNames.js +1 -0
  59. package/dist/types/config.d.ts +5 -4
  60. package/dist/types/module-graph.d.ts +4 -0
  61. package/dist/types.d.ts +1 -0
  62. package/dist/typescript/SourceFileManager.d.ts +13 -9
  63. package/dist/typescript/SourceFileManager.js +58 -22
  64. package/dist/typescript/get-imports-and-exports.js +5 -1
  65. package/dist/typescript/glob-imports.js +8 -3
  66. package/dist/typescript/visitors/calls.js +1 -1
  67. package/dist/typescript/visitors/exports.js +8 -4
  68. package/dist/typescript/visitors/walk.d.ts +3 -1
  69. package/dist/typescript/visitors/walk.js +78 -13
  70. package/dist/util/catalog.d.ts +5 -0
  71. package/dist/util/catalog.js +37 -17
  72. package/dist/util/cli-arguments.d.ts +1 -0
  73. package/dist/util/cli-arguments.js +9 -0
  74. package/dist/util/create-options.d.ts +19 -4
  75. package/dist/util/create-options.js +17 -4
  76. package/dist/util/errors.d.ts +3 -1
  77. package/dist/util/errors.js +6 -1
  78. package/dist/util/file-entry-cache.js +2 -2
  79. package/dist/util/module-graph.js +1 -0
  80. package/dist/util/package-json.d.ts +1 -0
  81. package/dist/util/preprocessor.d.ts +6 -0
  82. package/dist/util/preprocessor.js +24 -0
  83. package/dist/util/reporter.d.ts +0 -1
  84. package/dist/util/reporter.js +0 -7
  85. package/dist/util/watch.d.ts +1 -1
  86. package/dist/util/watch.js +33 -15
  87. package/dist/version.d.ts +1 -1
  88. package/dist/version.js +1 -1
  89. package/package.json +8 -8
  90. package/schema.json +12 -0
@@ -326,6 +326,11 @@ export declare const pluginsSchema: z.ZodMiniObject<{
326
326
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
327
327
  project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
328
328
  }, z.core.$strip>]>;
329
+ mise: z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
330
+ config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
331
+ entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
332
+ project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
333
+ }, z.core.$strip>]>;
329
334
  mocha: z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
330
335
  config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
331
336
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
@@ -74,6 +74,7 @@ export const pluginsSchema = z.object({
74
74
  mdx: pluginSchema,
75
75
  mdxlint: pluginSchema,
76
76
  metro: pluginSchema,
77
+ mise: pluginSchema,
77
78
  mocha: pluginSchema,
78
79
  moonrepo: pluginSchema,
79
80
  msw: pluginSchema,
@@ -1,4 +1,4 @@
1
- export { IMPORT_STAR, KNIP_CONFIG_LOCATIONS, SIDE_EFFECTS } from '../constants.ts';
1
+ export { IMPORT_STAR, ISSUE_TYPES, KNIP_CONFIG_LOCATIONS, SIDE_EFFECTS } from '../constants.ts';
2
2
  export type { DependencyNode, DependencyNodes } from '../graph-explorer/operations/get-dependency-usage.ts';
3
3
  export { finalizeConfigurationHints } from '../reporters/util/configuration-hints.ts';
4
4
  export { getIssuePrefix } from '../reporters/util/util.ts';
@@ -1,4 +1,4 @@
1
- export { IMPORT_STAR, KNIP_CONFIG_LOCATIONS, SIDE_EFFECTS } from '../constants.js';
1
+ export { IMPORT_STAR, ISSUE_TYPES, KNIP_CONFIG_LOCATIONS, SIDE_EFFECTS } from '../constants.js';
2
2
  export { finalizeConfigurationHints } from '../reporters/util/configuration-hints.js';
3
3
  export { getIssuePrefix } from '../reporters/util/util.js';
4
4
  export { createOptions } from '../util/create-options.js';
@@ -1,18 +1,36 @@
1
1
  import { run } from '../run.js';
2
+ import { createPreprocessor, toReporterOptions } from '../util/preprocessor.js';
2
3
  import { buildFileDescriptor } from './file-descriptor.js';
3
4
  import { buildPackageJsonDescriptor } from './package-json-descriptor.js';
4
5
  export const createSession = async (options) => {
5
6
  const { session, results } = await run(options);
6
7
  if (!session)
7
8
  throw new Error('Unable to initialize watch session');
8
- return createSessionAdapter(session, results, options);
9
- };
10
- const createSessionAdapter = (session, results, options) => {
11
- return {
9
+ const adapter = {
12
10
  handleFileChanges: session.handleFileChanges,
13
11
  getIssues: session.getIssues,
14
12
  getResults: () => results,
15
13
  describeFile: (filePath, opts) => buildFileDescriptor(filePath, options.cwd, session.getGraph(), session.getEntryPaths(), opts),
16
14
  describePackageJson: () => buildPackageJsonDescriptor(session.getGraph(), session.getEntryPaths()),
17
15
  };
16
+ if (options.preprocessor.length === 0)
17
+ return adapter;
18
+ const input = toReporterOptions(options, results);
19
+ const preprocess = await createPreprocessor(options.preprocessor);
20
+ const updateResults = async () => {
21
+ const data = await preprocess({ ...input, ...structuredClone(session.getIssues()) });
22
+ results.issues = data.issues;
23
+ results.counters = data.counters;
24
+ results.tagHints = data.tagHints;
25
+ results.configurationHints = data.configurationHints;
26
+ };
27
+ await updateResults();
28
+ adapter.handleFileChanges = async (changes) => {
29
+ const update = await session.handleFileChanges(changes);
30
+ if (update)
31
+ await updateResults();
32
+ return update;
33
+ };
34
+ adapter.getIssues = () => results;
35
+ return adapter;
18
36
  };
@@ -1,2 +1,2 @@
1
- export type PluginName = 'angular' | 'astro' | 'astro-db' | 'astro-markdoc' | 'astro-og-canvas' | 'ava' | 'babel' | 'biome' | 'borp' | 'bumpp' | 'bun' | 'c8' | 'capacitor' | 'catalyst' | 'changelogen' | 'changelogithub' | 'changesets' | 'commitizen' | 'commitlint' | 'convex' | 'create-typescript-app' | 'cspell' | 'cucumber' | 'cypress' | 'danger' | 'dependency-cruiser' | 'docusaurus' | 'dotenv' | 'drizzle' | 'electron-vite' | 'eleventy' | 'esbuild' | 'eslint' | 'eve' | 'execa' | 'expo' | 'expressive-code' | 'fast' | 'fumadocs' | 'gatsby' | 'github-action' | 'github-actions' | 'glob' | 'graphql-codegen' | 'hardhat' | 'husky' | 'i18next-parser' | 'jest' | 'karma' | 'knex' | 'ladle' | 'laravel-vite-plugin' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lit' | 'lockfile-lint' | 'lost-pixel' | 'lunaria' | 'markdownlint' | 'marko' | 'mdx' | 'mdxlint' | 'metro' | 'mocha' | 'moonrepo' | 'msw' | 'nano-spawn' | 'nano-staged' | 'nest' | 'netlify' | 'next' | 'next-intl' | 'next-mdx' | 'nitro' | 'node' | 'node-modules-inspector' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nuxtjs-i18n' | 'nx' | 'nyc' | 'oclif' | 'openapi-ts' | 'openclaw' | 'orval' | 'oxfmt' | 'oxlint' | 'panda-css' | 'parcel' | 'payload' | 'pino' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'pm2' | 'pnpm' | 'postcss' | 'pre-commit' | 'preconstruct' | 'prettier' | 'prisma' | 'quasar' | 'qwik' | 'raycast' | 'react-cosmos' | 'react-email' | 'react-native' | 'react-router' | 'relay' | 'release-it' | 'remark' | 'remix' | 'rolldown' | 'rollup' | 'rsbuild' | 'rslib' | 'rspack' | 'rstest' | 'sanity' | 'semantic-release' | 'sentry' | 'serverless-framework' | 'simple-git-hooks' | 'size-limit' | 'sst' | 'starlight' | 'stencil' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'sveltejs-package' | 'sveltekit' | 'svgo' | 'svgr' | 'swc' | 'syncpack' | 'tailwind' | 'tanstack-router' | 'taskfile' | 'tauri' | 'temporal' | 'travis' | 'ts-node' | 'tsd' | 'tsdown' | 'tsup' | 'tsx' | 'typedoc' | 'typescript' | 'unbuild' | 'unocss' | 'unplugin-auto-import' | 'unplugin-icons' | 'unplugin-vue-components' | 'unplugin-vue-i18n' | 'unplugin-vue-markdown' | 'unplugin-vue-router' | 'vercel' | 'vercel-og' | 'vike' | 'vite' | 'vite-plugin-pages' | 'vite-plugin-pwa' | 'vite-plugin-vue-layouts-next' | 'vite-plus' | 'vite-pwa-assets-generator' | 'vitepress' | 'vitest' | 'vue' | 'webdriver-io' | 'webpack' | 'wireit' | 'wrangler' | 'wxt' | 'xo' | 'yarn' | 'yorkie' | 'zx';
2
- export declare const pluginNames: readonly ['angular', 'astro', 'astro-db', 'astro-markdoc', 'astro-og-canvas', 'ava', 'babel', 'biome', 'borp', 'bumpp', 'bun', 'c8', 'capacitor', 'catalyst', 'changelogen', 'changelogithub', 'changesets', 'commitizen', 'commitlint', 'convex', 'create-typescript-app', 'cspell', 'cucumber', 'cypress', 'danger', 'dependency-cruiser', 'docusaurus', 'dotenv', 'drizzle', 'electron-vite', 'eleventy', 'esbuild', 'eslint', 'eve', 'execa', 'expo', 'expressive-code', 'fast', 'fumadocs', 'gatsby', 'github-action', 'github-actions', 'glob', 'graphql-codegen', 'hardhat', 'husky', 'i18next-parser', 'jest', 'karma', 'knex', 'ladle', 'laravel-vite-plugin', 'lefthook', 'lint-staged', 'linthtml', 'lit', 'lockfile-lint', 'lost-pixel', 'lunaria', 'markdownlint', 'marko', 'mdx', 'mdxlint', 'metro', 'mocha', 'moonrepo', 'msw', 'nano-spawn', 'nano-staged', 'nest', 'netlify', 'next', 'next-intl', 'next-mdx', 'nitro', 'node', 'node-modules-inspector', 'nodemon', 'npm-package-json-lint', 'nuxt', 'nuxtjs-i18n', 'nx', 'nyc', 'oclif', 'openapi-ts', 'openclaw', 'orval', 'oxfmt', 'oxlint', 'panda-css', 'parcel', 'payload', 'pino', 'playwright', 'playwright-ct', 'playwright-test', 'plop', 'pm2', 'pnpm', 'postcss', 'pre-commit', 'preconstruct', 'prettier', 'prisma', 'quasar', 'qwik', 'raycast', 'react-cosmos', 'react-email', 'react-native', 'react-router', 'relay', 'release-it', 'remark', 'remix', 'rolldown', 'rollup', 'rsbuild', 'rslib', 'rspack', 'rstest', 'sanity', 'semantic-release', 'sentry', 'serverless-framework', 'simple-git-hooks', 'size-limit', 'sst', 'starlight', 'stencil', 'storybook', 'stryker', 'stylelint', 'svelte', 'sveltejs-package', 'sveltekit', 'svgo', 'svgr', 'swc', 'syncpack', 'tailwind', 'tanstack-router', 'taskfile', 'tauri', 'temporal', 'travis', 'ts-node', 'tsd', 'tsdown', 'tsup', 'tsx', 'typedoc', 'typescript', 'unbuild', 'unocss', 'unplugin-auto-import', 'unplugin-icons', 'unplugin-vue-components', 'unplugin-vue-i18n', 'unplugin-vue-markdown', 'unplugin-vue-router', 'vercel', 'vercel-og', 'vike', 'vite', 'vite-plugin-pages', 'vite-plugin-pwa', 'vite-plugin-vue-layouts-next', 'vite-plus', 'vite-pwa-assets-generator', 'vitepress', 'vitest', 'vue', 'webdriver-io', 'webpack', 'wireit', 'wrangler', 'wxt', 'xo', 'yarn', 'yorkie', 'zx'];
1
+ export type PluginName = 'angular' | 'astro' | 'astro-db' | 'astro-markdoc' | 'astro-og-canvas' | 'ava' | 'babel' | 'biome' | 'borp' | 'bumpp' | 'bun' | 'c8' | 'capacitor' | 'catalyst' | 'changelogen' | 'changelogithub' | 'changesets' | 'commitizen' | 'commitlint' | 'convex' | 'create-typescript-app' | 'cspell' | 'cucumber' | 'cypress' | 'danger' | 'dependency-cruiser' | 'docusaurus' | 'dotenv' | 'drizzle' | 'electron-vite' | 'eleventy' | 'esbuild' | 'eslint' | 'eve' | 'execa' | 'expo' | 'expressive-code' | 'fast' | 'fumadocs' | 'gatsby' | 'github-action' | 'github-actions' | 'glob' | 'graphql-codegen' | 'hardhat' | 'husky' | 'i18next-parser' | 'jest' | 'karma' | 'knex' | 'ladle' | 'laravel-vite-plugin' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lit' | 'lockfile-lint' | 'lost-pixel' | 'lunaria' | 'markdownlint' | 'marko' | 'mdx' | 'mdxlint' | 'metro' | 'mise' | 'mocha' | 'moonrepo' | 'msw' | 'nano-spawn' | 'nano-staged' | 'nest' | 'netlify' | 'next' | 'next-intl' | 'next-mdx' | 'nitro' | 'node' | 'node-modules-inspector' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nuxtjs-i18n' | 'nx' | 'nyc' | 'oclif' | 'openapi-ts' | 'openclaw' | 'orval' | 'oxfmt' | 'oxlint' | 'panda-css' | 'parcel' | 'payload' | 'pino' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'pm2' | 'pnpm' | 'postcss' | 'pre-commit' | 'preconstruct' | 'prettier' | 'prisma' | 'quasar' | 'qwik' | 'raycast' | 'react-cosmos' | 'react-email' | 'react-native' | 'react-router' | 'relay' | 'release-it' | 'remark' | 'remix' | 'rolldown' | 'rollup' | 'rsbuild' | 'rslib' | 'rspack' | 'rstest' | 'sanity' | 'semantic-release' | 'sentry' | 'serverless-framework' | 'simple-git-hooks' | 'size-limit' | 'sst' | 'starlight' | 'stencil' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'sveltejs-package' | 'sveltekit' | 'svgo' | 'svgr' | 'swc' | 'syncpack' | 'tailwind' | 'tanstack-router' | 'taskfile' | 'tauri' | 'temporal' | 'travis' | 'ts-node' | 'tsd' | 'tsdown' | 'tsup' | 'tsx' | 'typedoc' | 'typescript' | 'unbuild' | 'unocss' | 'unplugin-auto-import' | 'unplugin-icons' | 'unplugin-vue-components' | 'unplugin-vue-i18n' | 'unplugin-vue-markdown' | 'unplugin-vue-router' | 'vercel' | 'vercel-og' | 'vike' | 'vite' | 'vite-plugin-pages' | 'vite-plugin-pwa' | 'vite-plugin-vue-layouts-next' | 'vite-plus' | 'vite-pwa-assets-generator' | 'vitepress' | 'vitest' | 'vue' | 'webdriver-io' | 'webpack' | 'wireit' | 'wrangler' | 'wxt' | 'xo' | 'yarn' | 'yorkie' | 'zx';
2
+ export declare const pluginNames: readonly ['angular', 'astro', 'astro-db', 'astro-markdoc', 'astro-og-canvas', 'ava', 'babel', 'biome', 'borp', 'bumpp', 'bun', 'c8', 'capacitor', 'catalyst', 'changelogen', 'changelogithub', 'changesets', 'commitizen', 'commitlint', 'convex', 'create-typescript-app', 'cspell', 'cucumber', 'cypress', 'danger', 'dependency-cruiser', 'docusaurus', 'dotenv', 'drizzle', 'electron-vite', 'eleventy', 'esbuild', 'eslint', 'eve', 'execa', 'expo', 'expressive-code', 'fast', 'fumadocs', 'gatsby', 'github-action', 'github-actions', 'glob', 'graphql-codegen', 'hardhat', 'husky', 'i18next-parser', 'jest', 'karma', 'knex', 'ladle', 'laravel-vite-plugin', 'lefthook', 'lint-staged', 'linthtml', 'lit', 'lockfile-lint', 'lost-pixel', 'lunaria', 'markdownlint', 'marko', 'mdx', 'mdxlint', 'metro', 'mise', 'mocha', 'moonrepo', 'msw', 'nano-spawn', 'nano-staged', 'nest', 'netlify', 'next', 'next-intl', 'next-mdx', 'nitro', 'node', 'node-modules-inspector', 'nodemon', 'npm-package-json-lint', 'nuxt', 'nuxtjs-i18n', 'nx', 'nyc', 'oclif', 'openapi-ts', 'openclaw', 'orval', 'oxfmt', 'oxlint', 'panda-css', 'parcel', 'payload', 'pino', 'playwright', 'playwright-ct', 'playwright-test', 'plop', 'pm2', 'pnpm', 'postcss', 'pre-commit', 'preconstruct', 'prettier', 'prisma', 'quasar', 'qwik', 'raycast', 'react-cosmos', 'react-email', 'react-native', 'react-router', 'relay', 'release-it', 'remark', 'remix', 'rolldown', 'rollup', 'rsbuild', 'rslib', 'rspack', 'rstest', 'sanity', 'semantic-release', 'sentry', 'serverless-framework', 'simple-git-hooks', 'size-limit', 'sst', 'starlight', 'stencil', 'storybook', 'stryker', 'stylelint', 'svelte', 'sveltejs-package', 'sveltekit', 'svgo', 'svgr', 'swc', 'syncpack', 'tailwind', 'tanstack-router', 'taskfile', 'tauri', 'temporal', 'travis', 'ts-node', 'tsd', 'tsdown', 'tsup', 'tsx', 'typedoc', 'typescript', 'unbuild', 'unocss', 'unplugin-auto-import', 'unplugin-icons', 'unplugin-vue-components', 'unplugin-vue-i18n', 'unplugin-vue-markdown', 'unplugin-vue-router', 'vercel', 'vercel-og', 'vike', 'vite', 'vite-plugin-pages', 'vite-plugin-pwa', 'vite-plugin-vue-layouts-next', 'vite-plus', 'vite-pwa-assets-generator', 'vitepress', 'vitest', 'vue', 'webdriver-io', 'webpack', 'wireit', 'wrangler', 'wxt', 'xo', 'yarn', 'yorkie', 'zx'];
@@ -63,6 +63,7 @@ export const pluginNames = [
63
63
  'mdx',
64
64
  'mdxlint',
65
65
  'metro',
66
+ 'mise',
66
67
  'mocha',
67
68
  'moonrepo',
68
69
  'msw',
@@ -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 & {
@@ -141,7 +140,9 @@ export type PluginVisitorContext = {
141
140
  markImportExpressionHandled: (pos: number) => void;
142
141
  addImportGlob: (patterns: string[], options?: {
143
142
  base?: string;
143
+ cwd?: string;
144
144
  filter?: RegExp;
145
+ analyzeExports?: boolean;
145
146
  }) => void;
146
147
  markExportRegistered: (name: string) => void;
147
148
  };
@@ -30,6 +30,7 @@ export interface Import extends Position {
30
30
  readonly identifier: string | undefined;
31
31
  readonly isTypeOnly: boolean;
32
32
  readonly modifiers: number;
33
+ readonly jsDocTags: Tags | undefined;
33
34
  }
34
35
  export interface ExternalRef {
35
36
  readonly specifier: string;
@@ -57,6 +58,7 @@ export interface ExportMember extends Position {
57
58
  type ExportMap = Map<Identifier, Export>;
58
59
  export type Imports = Set<Import>;
59
60
  export type FileNode = {
61
+ skipExports: boolean;
60
62
  imports: {
61
63
  readonly internal: ImportMap;
62
64
  readonly external: Set<Import>;
@@ -76,7 +78,9 @@ export type FileNode = {
76
78
  export interface ImportGlob {
77
79
  patterns: string[];
78
80
  base?: string;
81
+ cwd?: string;
79
82
  filter?: RegExp;
83
+ analyzeExports?: boolean;
80
84
  }
81
85
  export type ModuleGraph = Map<FilePath, FileNode>;
82
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
  }
@@ -62,6 +62,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
62
62
  col: opts.col,
63
63
  isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
64
64
  modifiers,
65
+ jsDocTags: undefined,
65
66
  });
66
67
  const file = internal.get(importFilePath);
67
68
  const importMaps = file ?? createImports();
@@ -146,6 +147,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
146
147
  col,
147
148
  isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
148
149
  modifiers,
150
+ jsDocTags,
149
151
  });
150
152
  }
151
153
  }
@@ -171,6 +173,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
171
173
  col,
172
174
  isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
173
175
  modifiers,
176
+ jsDocTags: undefined,
174
177
  });
175
178
  }
176
179
  }
@@ -280,7 +283,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
280
283
  pluginCtx.addScript = (s) => scripts.add(s);
281
284
  pluginCtx.addImport = (spec, pos, mod) => addImport(spec, undefined, undefined, undefined, pos, mod);
282
285
  pluginCtx.markImportExpressionHandled = (pos) => handledImportExpressions.add(pos);
283
- pluginCtx.addImportGlob = (patterns, opts) => importGlobs.push({ patterns, base: opts?.base, filter: opts?.filter });
286
+ pluginCtx.addImportGlob = (patterns, opts) => importGlobs.push({ patterns, ...opts });
284
287
  pluginCtx.markExportRegistered = (name) => registeredCustomElements.add(name);
285
288
  }
286
289
  const localRefs = _walkAST(result.program, sourceText, filePath, result.module.hasModuleSyntax, {
@@ -326,6 +329,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
326
329
  }
327
330
  }
328
331
  return {
332
+ skipExports,
329
333
  imports: { internal, external, externalRefs: new Set(), programFiles, entryFiles, imports, unresolved },
330
334
  exports,
331
335
  duplicates: [...aliasedExports.values()],
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { _syncGlob } from '../util/glob.js';
3
- import { dirname, isAbsolute, join, toRelative } from '../util/path.js';
3
+ import { dirname, isAbsolute, join, toAbsolute, toRelative } from '../util/path.js';
4
4
  function resolveBaseDir(base, dir, resolveGlobPattern) {
5
5
  if (base.startsWith('.'))
6
6
  return join(dir, base);
@@ -15,8 +15,13 @@ function resolveBaseDir(base, dir, resolveGlobPattern) {
15
15
  export function resolveImportGlobs(items, containingFile, resolveGlobPattern, workspaceRoot) {
16
16
  const filePaths = [];
17
17
  const dir = dirname(containingFile);
18
- for (const { patterns, base, filter } of items) {
19
- if (base !== undefined) {
18
+ for (const { patterns, base, cwd, filter } of items) {
19
+ if (cwd !== undefined) {
20
+ for (const filePath of _syncGlob({ patterns, cwd: toAbsolute(cwd, workspaceRoot) })) {
21
+ filePaths.push(filePath);
22
+ }
23
+ }
24
+ else if (base !== undefined) {
20
25
  const cwd = resolveBaseDir(base, dir, resolveGlobPattern);
21
26
  if (!cwd)
22
27
  continue;
@@ -256,7 +256,7 @@ export function handleNewExpression(node, s) {
256
256
  node.arguments[1].property.name === 'url') {
257
257
  const specifier = getStringValue(node.arguments[0]);
258
258
  if (specifier)
259
- s.addImport(specifier, undefined, undefined, undefined, node.arguments[0].start, IMPORT_FLAGS.ENTRY | IMPORT_FLAGS.OPTIONAL);
259
+ s.addImport(specifier, undefined, undefined, undefined, node.arguments[0].start, IMPORT_FLAGS.ENTRY | IMPORT_FLAGS.OPTIONAL, undefined, s.getJSDocTags(node.start));
260
260
  return;
261
261
  }
262
262
  if (s.hasWorkerThreadsImport &&
@@ -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
  };
@@ -1,4 +1,4 @@
1
- import { Visitor, type Class, type Function as FunctionNode, type Program, type Span, type VariableDeclarator } from 'oxc-parser';
1
+ import { Visitor, type Class, type Function as FunctionNode, type Program, type Span, type TSInterfaceDeclaration, type VariableDeclarator } from 'oxc-parser';
2
2
  import type { PluginVisitorObject } from '../../types/config.ts';
3
3
  import type { GetImportsAndExportsOptions } from '../../types/config.ts';
4
4
  import type { Fix } from '../../types/exports.ts';
@@ -67,10 +67,12 @@ export interface WalkState extends WalkContext {
67
67
  scopeEnds: number[];
68
68
  shadowScopes: Map<string, [number, number][]>;
69
69
  localDeclarations: Map<string, FunctionNode | Class | VariableDeclarator>;
70
+ localInterfaces: Map<string, TSInterfaceDeclaration | null>;
70
71
  pendingCallRefs: Array<{
71
72
  name: string;
72
73
  exportName: string;
73
74
  seen: Set<string>;
75
+ kind: 'callee' | 'argument';
74
76
  }>;
75
77
  pendingMemberCallRefs: Array<{
76
78
  objectName: string;
@@ -49,7 +49,7 @@ const _addExport = (identifier, type, pos, members, fix, isReExport, jsDocTags)
49
49
  });
50
50
  }
51
51
  };
52
- const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), inBody = false) => {
52
+ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), inBody = false, thisType) => {
53
53
  if (!node)
54
54
  return;
55
55
  const type = node.type;
@@ -64,10 +64,14 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
64
64
  if (node.typeName?.type === 'Identifier')
65
65
  _addRefInExport(node.typeName.name, exportName);
66
66
  break;
67
+ case 'TSThisType':
68
+ if (thisType)
69
+ _addRefInExport(thisType, exportName);
70
+ return;
67
71
  case 'CallExpression': {
68
72
  const callee = node.callee;
69
73
  if (callee?.type === 'Identifier') {
70
- state.pendingCallRefs.push({ name: callee.name, exportName, seen });
74
+ state.pendingCallRefs.push({ name: callee.name, exportName, seen, kind: 'callee' });
71
75
  }
72
76
  else if (callee?.type === 'MemberExpression' &&
73
77
  !callee.computed &&
@@ -84,8 +88,9 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
84
88
  const args = node.arguments;
85
89
  if (args) {
86
90
  for (const arg of args) {
87
- if (arg?.type === 'Identifier')
88
- state.pendingCallRefs.push({ name: arg.name, exportName, seen });
91
+ if (arg?.type === 'Identifier') {
92
+ state.pendingCallRefs.push({ name: arg.name, exportName, seen, kind: 'argument' });
93
+ }
89
94
  }
90
95
  }
91
96
  }
@@ -101,14 +106,14 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
101
106
  case 'TSSatisfiesExpression':
102
107
  if (inBody) {
103
108
  if (node.expression)
104
- _collectRefsInType(node.expression, exportName, signatureOnly, seen, inBody);
109
+ _collectRefsInType(node.expression, exportName, signatureOnly, seen, inBody, thisType);
105
110
  return;
106
111
  }
107
112
  break;
108
113
  case 'VariableDeclarator':
109
114
  if (inBody) {
110
115
  if (node.init)
111
- _collectRefsInType(node.init, exportName, signatureOnly, seen, inBody);
116
+ _collectRefsInType(node.init, exportName, signatureOnly, seen, inBody, thisType);
112
117
  return;
113
118
  }
114
119
  break;
@@ -124,14 +129,63 @@ const _collectRefsInType = (node, exportName, signatureOnly, seen = new Set(), i
124
129
  if (Array.isArray(val)) {
125
130
  for (const item of val) {
126
131
  if (item)
127
- _collectRefsInType(item, exportName, signatureOnly, seen, childInBody);
132
+ _collectRefsInType(item, exportName, signatureOnly, seen, childInBody, thisType);
128
133
  }
129
134
  }
130
135
  else {
131
- _collectRefsInType(val, exportName, signatureOnly, seen, childInBody);
136
+ _collectRefsInType(val, exportName, signatureOnly, seen, childInBody, thisType);
132
137
  }
133
138
  }
134
139
  };
140
+ const _collectRefsInDirectMemberResult = (fn, exportName, seen) => {
141
+ const body = fn.body;
142
+ if (body?.type !== 'MemberExpression' ||
143
+ body.computed ||
144
+ body.object?.type !== 'Identifier' ||
145
+ body.property?.type !== 'Identifier') {
146
+ return false;
147
+ }
148
+ const params = Array.isArray(fn.params) ? fn.params : (fn.params?.items ?? []);
149
+ const param = params.find((param) => param.type === 'Identifier' && param.name === body.object.name);
150
+ const paramType = param?.typeAnnotation?.typeAnnotation;
151
+ if (paramType?.type !== 'TSTypeReference' || paramType.typeName?.type !== 'Identifier' || paramType.typeArguments) {
152
+ return false;
153
+ }
154
+ const declaration = state.localInterfaces.get(paramType.typeName.name);
155
+ if (!declaration || declaration.typeParameters)
156
+ return false;
157
+ const members = declaration.body.body.filter((member) => member.type === 'TSPropertySignature' &&
158
+ !member.computed &&
159
+ member.key?.type === 'Identifier' &&
160
+ member.key.name === body.property.name &&
161
+ Boolean(member.typeAnnotation));
162
+ if (members.length !== 1)
163
+ return false;
164
+ _collectRefsInType(members[0].typeAnnotation, exportName, true, seen, false, paramType.typeName.name);
165
+ return true;
166
+ };
167
+ const _collectRefsInCallResult = (node, exportName, seen) => {
168
+ const annotatedType = node.type === 'VariableDeclarator' ? node.id.typeAnnotation?.typeAnnotation : undefined;
169
+ if (annotatedType?.type === 'TSFunctionType') {
170
+ _collectRefsInType(annotatedType.typeParameters, exportName, true, seen);
171
+ return _collectRefsInType(annotatedType.returnType, exportName, true, seen);
172
+ }
173
+ if (annotatedType)
174
+ return _collectRefsInType(annotatedType, exportName, true, seen);
175
+ const fn = node.type === 'VariableDeclarator' ? node.init : node;
176
+ if (fn?.type !== 'ArrowFunctionExpression' &&
177
+ fn?.type !== 'FunctionDeclaration' &&
178
+ fn?.type !== 'FunctionExpression') {
179
+ return _collectRefsInType(node, exportName, true, seen);
180
+ }
181
+ if (fn.returnType) {
182
+ _collectRefsInType(fn.typeParameters, exportName, true, seen);
183
+ return _collectRefsInType(fn.returnType, exportName, true, seen);
184
+ }
185
+ if (_collectRefsInDirectMemberResult(fn, exportName, seen))
186
+ return;
187
+ _collectRefsInType(fn, exportName, true, seen);
188
+ };
135
189
  const _addRefInExport = (name, exportName) => {
136
190
  const refs = state.referencedInExport.get(name);
137
191
  if (refs)
@@ -221,6 +275,12 @@ const coreVisitorObject = {
221
275
  state.addImport(specifier, name, undefined, undefined, node.id.start, IMPORT_FLAGS.TYPE_ONLY | IMPORT_FLAGS.AUGMENT);
222
276
  }
223
277
  },
278
+ TSInterfaceDeclaration(node) {
279
+ if (state.scopeDepth > 0 || state.isInNamespace(node))
280
+ return;
281
+ const name = node.id.name;
282
+ state.localInterfaces.set(name, state.localInterfaces.has(name) ? null : node);
283
+ },
224
284
  ClassDeclaration(node) {
225
285
  state.classNameStack.push(node.id?.name ?? '');
226
286
  if (node.id?.name) {
@@ -740,6 +800,7 @@ function walkAST(program, sourceText, filePath, hasModuleSyntax, ctx) {
740
800
  scopeEnds: [],
741
801
  shadowScopes: new Map(),
742
802
  localDeclarations: new Map(),
803
+ localInterfaces: new Map(),
743
804
  pendingCallRefs: [],
744
805
  pendingMemberCallRefs: [],
745
806
  localToExports: new Map(),
@@ -756,14 +817,18 @@ function walkAST(program, sourceText, filePath, hasModuleSyntax, ctx) {
756
817
  ctx.visitor.visit(program);
757
818
  while (state.pendingCallRefs.length > 0 || state.pendingMemberCallRefs.length > 0) {
758
819
  while (state.pendingCallRefs.length > 0) {
759
- const { name, exportName, seen } = state.pendingCallRefs.pop();
760
- if (seen.has(name))
820
+ const { name, exportName, seen, kind } = state.pendingCallRefs.pop();
821
+ const key = `${kind}:${name}`;
822
+ if (seen.has(key))
761
823
  continue;
762
824
  const decl = state.localDeclarations.get(name);
763
825
  if (!decl)
764
826
  continue;
765
- seen.add(name);
766
- _collectRefsInType(decl, exportName, true, seen);
827
+ seen.add(key);
828
+ if (kind === 'callee')
829
+ _collectRefsInCallResult(decl, exportName, seen);
830
+ else
831
+ _collectRefsInType(decl, exportName, true, seen);
767
832
  }
768
833
  while (state.pendingMemberCallRefs.length > 0) {
769
834
  const { objectName, propertyName, exportName, seen } = state.pendingMemberCallRefs.pop();
@@ -780,7 +845,7 @@ function walkAST(program, sourceText, filePath, hasModuleSyntax, ctx) {
780
845
  if (fn.type !== 'ArrowFunctionExpression' && fn.type !== 'FunctionExpression')
781
846
  continue;
782
847
  seen.add(key);
783
- _collectRefsInType(fn, exportName, true, seen);
848
+ _collectRefsInCallResult(fn, exportName, seen);
784
849
  }
785
850
  }
786
851
  for (let i = 0; i < state.memberRefsInFile.length; i += 2) {
@@ -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[];