knip 6.41.0 → 6.42.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 (63) hide show
  1. package/README.md +1 -1
  2. package/dist/ConfigurationChief.d.ts +18 -0
  3. package/dist/WorkspaceWorker.js +1 -0
  4. package/dist/binaries/bash-parser.js +16 -39
  5. package/dist/binaries/resolvers/bun.js +1 -0
  6. package/dist/graph-explorer/operations/is-referenced.js +8 -2
  7. package/dist/manifest/index.js +2 -3
  8. package/dist/plugins/_component-style-urls/component-style-urls-visitor.d.ts +2 -0
  9. package/dist/plugins/_component-style-urls/component-style-urls-visitor.js +40 -0
  10. package/dist/plugins/angular/index.js +7 -1
  11. package/dist/plugins/biome/index.js +2 -2
  12. package/dist/plugins/commitlint/index.js +2 -2
  13. package/dist/plugins/eslint/helpers.js +1 -1
  14. package/dist/plugins/filesystem-routing/index.d.ts +3 -0
  15. package/dist/plugins/filesystem-routing/index.js +57 -0
  16. package/dist/plugins/github-actions/index.js +1 -1
  17. package/dist/plugins/index.d.ts +3 -0
  18. package/dist/plugins/index.js +6 -0
  19. package/dist/plugins/jest/index.js +5 -0
  20. package/dist/plugins/jest/visitors/mock.d.ts +2 -0
  21. package/dist/plugins/jest/visitors/mock.js +91 -0
  22. package/dist/plugins/mise/scripts.js +55 -97
  23. package/dist/plugins/next/index.js +33 -1
  24. package/dist/plugins/nx/index.js +46 -8
  25. package/dist/plugins/nx/types.d.ts +8 -0
  26. package/dist/plugins/oxlint/index.js +1 -1
  27. package/dist/plugins/react-router/index.d.ts +3 -0
  28. package/dist/plugins/react-router/index.js +3 -0
  29. package/dist/plugins/rstest/index.js +1 -1
  30. package/dist/plugins/solidjs-vite-plugin/index.d.ts +6 -0
  31. package/dist/plugins/solidjs-vite-plugin/index.js +17 -0
  32. package/dist/plugins/solidjs-vite-plugin/resolveFromAST.d.ts +3 -0
  33. package/dist/plugins/solidjs-vite-plugin/resolveFromAST.js +76 -0
  34. package/dist/plugins/sst/resolveFromAST.js +1 -1
  35. package/dist/plugins/stencil/index.js +2 -39
  36. package/dist/plugins/storybook/index.js +2 -4
  37. package/dist/plugins/sveltejs-package/helpers.js +2 -2
  38. package/dist/plugins/taskfile/index.js +3 -6
  39. package/dist/plugins/tsrs/index.d.ts +3 -0
  40. package/dist/plugins/tsrs/index.js +15 -0
  41. package/dist/plugins/typescript/index.d.ts +12 -1
  42. package/dist/plugins/typescript/index.js +5 -7
  43. package/dist/plugins/vite/helpers.d.ts +1 -0
  44. package/dist/plugins/vite/helpers.js +15 -1
  45. package/dist/plugins/vitest/index.js +2 -2
  46. package/dist/schema/configuration.d.ts +45 -0
  47. package/dist/schema/plugins.d.ts +15 -0
  48. package/dist/schema/plugins.js +3 -0
  49. package/dist/types/PluginNames.d.ts +2 -2
  50. package/dist/types/PluginNames.js +3 -0
  51. package/dist/types/config.d.ts +1 -0
  52. package/dist/typescript/visitors/imports.js +11 -0
  53. package/dist/typescript/visitors/jsdoc.js +27 -22
  54. package/dist/util/create-options.d.ts +30 -0
  55. package/dist/util/create-options.js +2 -3
  56. package/dist/util/path.d.ts +1 -0
  57. package/dist/util/path.js +1 -0
  58. package/dist/util/scripts.d.ts +3 -2
  59. package/dist/util/scripts.js +32 -72
  60. package/dist/version.d.ts +1 -1
  61. package/dist/version.js +1 -1
  62. package/package.json +5 -5
  63. package/schema.json +12 -0
package/README.md CHANGED
@@ -48,7 +48,7 @@ following projects:
48
48
 
49
49
  [1]: https://www.npmx.dev/package/knip
50
50
  [2]: https://img.shields.io/npm/v/knip?color=f56e0f
51
- [3]: https://img.shields.io/npm/dm/knip?color=f56e0f
51
+ [3]: https://img.shields.io/badge/dynamic/json?url=https://npm-gapless.webpro.nl/downloads/range/last-month/knip&query=$.totalCompact&label=downloads&suffix=/month&color=f56e0f
52
52
  [4]: https://github.com/webpro-nl/knip
53
53
  [5]:
54
54
  https://img.shields.io/github/stars/webpro-nl/knip?style=flat&color=f56e0f
@@ -252,6 +252,11 @@ export declare class ConfigurationChief {
252
252
  entry?: string | string[] | undefined;
253
253
  project?: string | string[] | undefined;
254
254
  } | undefined;
255
+ 'filesystem-routing'?: string | boolean | string[] | {
256
+ config?: string | string[] | undefined;
257
+ entry?: string | string[] | undefined;
258
+ project?: string | string[] | undefined;
259
+ } | undefined;
255
260
  flue?: string | boolean | string[] | {
256
261
  config?: string | string[] | undefined;
257
262
  entry?: string | string[] | undefined;
@@ -722,6 +727,11 @@ export declare class ConfigurationChief {
722
727
  entry?: string | string[] | undefined;
723
728
  project?: string | string[] | undefined;
724
729
  } | undefined;
730
+ 'solidjs-vite-plugin'?: string | boolean | string[] | {
731
+ config?: string | string[] | undefined;
732
+ entry?: string | string[] | undefined;
733
+ project?: string | string[] | undefined;
734
+ } | undefined;
725
735
  sst?: string | boolean | string[] | {
726
736
  config?: string | string[] | undefined;
727
737
  entry?: string | string[] | undefined;
@@ -837,6 +847,11 @@ export declare class ConfigurationChief {
837
847
  entry?: string | string[] | undefined;
838
848
  project?: string | string[] | undefined;
839
849
  } | undefined;
850
+ tsrs?: string | boolean | string[] | {
851
+ config?: string | string[] | undefined;
852
+ entry?: string | string[] | undefined;
853
+ project?: string | string[] | undefined;
854
+ } | undefined;
840
855
  tsup?: string | boolean | string[] | {
841
856
  config?: string | string[] | undefined;
842
857
  entry?: string | string[] | undefined;
@@ -1089,6 +1104,7 @@ export declare class ConfigurationChief {
1089
1104
  "expo-router"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1090
1105
  "expressive-code"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1091
1106
  fast?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1107
+ "filesystem-routing"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1092
1108
  flue?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1093
1109
  fumadocs?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1094
1110
  gatsby?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -1183,6 +1199,7 @@ export declare class ConfigurationChief {
1183
1199
  "serverless-framework"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1184
1200
  "simple-git-hooks"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1185
1201
  "size-limit"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1202
+ "solidjs-vite-plugin"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1186
1203
  sst?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1187
1204
  starlight?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1188
1205
  stencil?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -1206,6 +1223,7 @@ export declare class ConfigurationChief {
1206
1223
  "ts-node"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1207
1224
  tsd?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1208
1225
  tsdown?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1226
+ tsrs?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1209
1227
  tsup?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1210
1228
  tsx?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
1211
1229
  turbo?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
@@ -294,6 +294,7 @@ export class WorkspaceWorker {
294
294
  }
295
295
  const options = {
296
296
  ...baseScriptOptions,
297
+ pluginName,
297
298
  config,
298
299
  configFilePath: containingFilePath,
299
300
  configFileDir: cwd,
@@ -1,31 +1,11 @@
1
- import { parse } from 'unbash';
1
+ import { forEachChild, parse } from 'unbash';
2
2
  import { debugLogObject } from '../util/debug.js';
3
3
  import { extractBinary, isValidBinary } from '../util/modules.js';
4
4
  import { relative } from '../util/path.js';
5
5
  import { substringBefore, truncate } from '../util/string.js';
6
- import { walkCommands } from '../util/scripts.js';
6
+ import { isScriptExpansion } from '../util/scripts.js';
7
7
  import { getDependenciesFromCommand } from './command.js';
8
8
  import { toScript } from './util.js';
9
- const collectExpansionScripts = (word, out) => {
10
- if (word.type === 'ArrayValue') {
11
- for (const element of word.elements)
12
- collectExpansionScripts(element, out);
13
- return;
14
- }
15
- if (!word.parts)
16
- return;
17
- for (const part of word.parts) {
18
- if ((part.type === 'CommandExpansion' || part.type === 'ProcessSubstitution') && part.script) {
19
- out.push(part.script);
20
- }
21
- else if (part.type === 'DoubleQuoted' || part.type === 'LocaleString') {
22
- for (const child of part.parts) {
23
- if (child.type === 'CommandExpansion' && child.script)
24
- out.push(child.script);
25
- }
26
- }
27
- }
28
- };
29
9
  export const getDependenciesFromScript = (script, options) => {
30
10
  if (!script)
31
11
  return [];
@@ -56,24 +36,21 @@ export const getDependenciesFromScript = (script, options) => {
56
36
  };
57
37
  const processScript = (s) => {
58
38
  collectFunctionNames(s.commands);
59
- const pending = [];
60
- const mainDeps = [];
61
- for (const statement of s.commands) {
62
- for (const command of walkCommands(statement.command))
63
- mainDeps.push(...processCommand(command, pending));
64
- }
65
- const expansionDeps = pending.flatMap(inner => processScript(inner));
66
- return [...mainDeps, ...expansionDeps];
39
+ const inputs = [];
40
+ const visit = (node) => {
41
+ if (node.type === 'Command')
42
+ inputs.push(...processCommand(node));
43
+ if (isScriptExpansion(node)) {
44
+ if (node.script)
45
+ inputs.push(...processScript(node.script));
46
+ }
47
+ else
48
+ forEachChild(node, visit);
49
+ };
50
+ visit(s);
51
+ return inputs;
67
52
  };
68
- const processCommand = (node, pending) => {
69
- if (node.name)
70
- collectExpansionScripts(node.name, pending);
71
- for (const prefix of node.prefix) {
72
- if (prefix.type === 'Assignment')
73
- collectExpansionScripts(prefix.value, pending);
74
- }
75
- for (const arg of node.args)
76
- collectExpansionScripts(arg.type === 'Assignment' ? arg.value : arg, pending);
53
+ const processCommand = (node) => {
77
54
  if (definedFunctions.size && node.name && definedFunctions.has(extractBinary(node.name.value)))
78
55
  return [];
79
56
  return getDependenciesFromCommand(node, { ...options, fromArgs }, fromWords);
@@ -10,6 +10,7 @@ const commands = new Set([
10
10
  'auth',
11
11
  'build',
12
12
  'c',
13
+ 'check',
13
14
  'ci',
14
15
  'cloud',
15
16
  'completions',
@@ -38,10 +38,16 @@ export const isReferenced = (graph, entryPaths, filePath, id, options) => {
38
38
  return hasCompleteResult();
39
39
  }
40
40
  const node = graph.get(path);
41
- const file = node?.importedBy;
42
- if (!identifier || !node || !file) {
41
+ if (!identifier || !node) {
43
42
  return false;
44
43
  }
44
+ if (isEntryFile && node.skipExports) {
45
+ isReferenced = true;
46
+ return hasCompleteResult();
47
+ }
48
+ const file = node.importedBy;
49
+ if (!file)
50
+ return false;
45
51
  const follow = (sources, nextId, nextViaStar = viaStar) => {
46
52
  for (const byFilePath of sources) {
47
53
  if (walkDown(byFilePath, nextId, nextViaStar))
@@ -16,10 +16,9 @@ const getMetaDataFromPackageJson = ({ dir, packageNames }) => {
16
16
  for (const packageName of packageNames) {
17
17
  const manifest = loadPackageManifest({ dir, packageName });
18
18
  if (manifest) {
19
- const defaultBinaryName = packageName.replace(/^@[^/]+\//, '');
20
- const binaries = typeof manifest.bin === 'string' ? [defaultBinaryName] : Object.keys(manifest.bin ?? {});
19
+ const binaries = typeof manifest.bin === 'string' ? [packageName] : Object.keys(manifest.bin ?? {});
21
20
  for (const binaryName of binaries)
22
- addBinary(binaryName, packageName);
21
+ addBinary(binaryName.replace(/^@[^/]+\//, ''), packageName);
23
22
  const packagePeerDependencies = Object.keys(manifest.peerDependencies ?? {});
24
23
  for (const packagePeerDependency of packagePeerDependencies) {
25
24
  const hostDependency = {
@@ -0,0 +1,2 @@
1
+ import type { PluginVisitorContext, PluginVisitorObject } from '../../types/config.ts';
2
+ export declare function createComponentStyleUrlsVisitor(ctx: PluginVisitorContext, isSpecifier: (specifier: string) => boolean): PluginVisitorObject;
@@ -0,0 +1,40 @@
1
+ import { IMPORT_FLAGS } from '../../constants.js';
2
+ import { getPropertyValues } from '../../typescript/ast-helpers.js';
3
+ import { dirname, join } from '../../util/path.js';
4
+ export function createComponentStyleUrlsVisitor(ctx, isSpecifier) {
5
+ const componentNames = new Set();
6
+ return {
7
+ Program() {
8
+ componentNames.clear();
9
+ },
10
+ ImportDeclaration(node) {
11
+ if (!isSpecifier(node.source?.value))
12
+ return;
13
+ for (const spec of node.specifiers ?? []) {
14
+ if (spec.type === 'ImportSpecifier' &&
15
+ spec.imported.type === 'Identifier' &&
16
+ spec.imported.name === 'Component')
17
+ componentNames.add(spec.local.name);
18
+ }
19
+ },
20
+ ClassDeclaration(node) {
21
+ if (componentNames.size === 0)
22
+ return;
23
+ const dir = dirname(ctx.filePath);
24
+ for (const decorator of node.decorators ?? []) {
25
+ const expr = decorator.expression;
26
+ if (expr?.type !== 'CallExpression')
27
+ continue;
28
+ if (expr.callee?.type !== 'Identifier' || !componentNames.has(expr.callee.name))
29
+ continue;
30
+ const arg = expr.arguments?.[0];
31
+ if (arg?.type !== 'ObjectExpression')
32
+ continue;
33
+ for (const url of getPropertyValues(arg, 'styleUrl'))
34
+ ctx.addImport(join(dir, url), arg.start, IMPORT_FLAGS.NONE);
35
+ for (const url of getPropertyValues(arg, 'styleUrls'))
36
+ ctx.addImport(join(dir, url), arg.start, IMPORT_FLAGS.NONE);
37
+ }
38
+ },
39
+ };
40
+ }
@@ -2,6 +2,7 @@ import { existsSync } from 'node:fs';
2
2
  import { toConfig, toDeferResolve, toDependency, toEntry, toProductionEntry } from '../../util/input.js';
3
3
  import { isInternal, join } from '../../util/path.js';
4
4
  import { hasDependency } from '../../util/plugin.js';
5
+ import { createComponentStyleUrlsVisitor } from '../_component-style-urls/component-style-urls-visitor.js';
5
6
  import * as karma from '../karma/helpers.js';
6
7
  const title = 'Angular';
7
8
  const enablers = ['@angular/cli'];
@@ -72,7 +73,7 @@ const resolveConfig = async (config, options) => {
72
73
  karma.inputsFromFrameworks(['jasmine']).forEach(inputs.add, inputs);
73
74
  }
74
75
  if (karmaConfig && !karma.configFiles.includes(karmaConfig)) {
75
- inputs.add(toConfig('karma', karmaConfig, { containingFilePath: options.configFilePath }));
76
+ inputs.add(toConfig('karma', karmaConfig));
76
77
  }
77
78
  }
78
79
  }
@@ -111,11 +112,16 @@ const isAngularBuilderRefWithName = ({ builderRef, name }) => {
111
112
  };
112
113
  const PRODUCTION_CONFIG_NAME = 'production';
113
114
  const BUILD_TARGET_NAME = 'build';
115
+ const isAngularSpecifier = (specifier) => specifier === '@angular/core';
116
+ const registerVisitors = ({ ctx, registerVisitor }) => {
117
+ registerVisitor(createComponentStyleUrlsVisitor(ctx, isAngularSpecifier));
118
+ };
114
119
  const plugin = {
115
120
  title,
116
121
  enablers,
117
122
  isEnabled,
118
123
  config,
119
124
  resolveConfig,
125
+ registerVisitors,
120
126
  };
121
127
  export default plugin;
@@ -10,9 +10,9 @@ const isRootConfigReference = (specifier) => specifier === '//';
10
10
  const resolveExtends = (extendsArray, options) => {
11
11
  return extendsArray.map(specifier => {
12
12
  if (isRootConfigReference(specifier)) {
13
- return toConfig('biome', join(options.rootCwd, 'biome'), { containingFilePath: options.configFilePath });
13
+ return toConfig('biome', join(options.rootCwd, 'biome'));
14
14
  }
15
- return toConfig('biome', specifier, { containingFilePath: options.configFilePath });
15
+ return toConfig('biome', specifier);
16
16
  });
17
17
  };
18
18
  const resolveConfig = (config, options) => {
@@ -25,12 +25,12 @@ const toPluginSpecifier = (id) => {
25
25
  return id;
26
26
  return id.replace('/', '/commitlint-plugin-');
27
27
  };
28
- const resolveConfig = async (config, options) => {
28
+ const resolveConfig = async (config) => {
29
29
  const inputs = [];
30
30
  const extendsConfigs = [];
31
31
  for (const id of config.extends ? [config.extends].flat() : []) {
32
32
  if (isInternal(id))
33
- inputs.push(toConfig('commitlint', id, { containingFilePath: options.configFilePath }));
33
+ inputs.push(toConfig('commitlint', id));
34
34
  else
35
35
  extendsConfigs.push(toExtendsSpecifier(id));
36
36
  }
@@ -20,7 +20,7 @@ const getInputsDeprecated = (config, options) => {
20
20
  const extendsSpecifiers = compact(extendsList.map(resolveExtendSpecifier));
21
21
  if (extendsSpecifiers.some(specifier => specifier?.startsWith('eslint-plugin-prettier')))
22
22
  extendsSpecifiers.push('eslint-config-prettier');
23
- const extendConfigs = [...extendsList.filter(isInternal), ...extendsSpecifiers].map(specifier => toConfig('eslint', specifier, { containingFilePath: options.configFilePath }));
23
+ const extendConfigs = [...extendsList.filter(isInternal), ...extendsSpecifiers].map(specifier => toConfig('eslint', specifier));
24
24
  const plugins = config.plugins ? config.plugins.map(resolvePluginSpecifier) : [];
25
25
  const parsers = getParsers(config);
26
26
  const babelDependencies = config.parserOptions?.babelOptions
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../../types/config.ts';
2
+ declare const plugin: Plugin;
3
+ export default plugin;
@@ -0,0 +1,57 @@
1
+ import { escapePath } from 'tinyglobby';
2
+ import { findImportedCalls, findProperty } from '../../typescript/ast-helpers.js';
3
+ import { getStringValue } from '../../typescript/ast-nodes.js';
4
+ import { toProductionEntry } from '../../util/input.js';
5
+ import { join, relative, toAbsolute } from '../../util/path.js';
6
+ import { hasDependency } from '../../util/plugin.js';
7
+ import { getViteRoot } from '../vite/helpers.js';
8
+ const title = 'filesystem-routing';
9
+ const enablers = ['filesystem-routing'];
10
+ const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
11
+ const config = ['vite.config.{js,mjs,ts,cjs,mts,cts}'];
12
+ const defaultDir = 'src/routes';
13
+ const defaultExtensions = ['js', 'jsx', 'ts', 'tsx', 'tsrx'];
14
+ const production = [`${defaultDir}/**/*.{${defaultExtensions.join(',')}}`];
15
+ const resolveFromAST = (program, { config, cwd }) => {
16
+ if (config.entry)
17
+ return [];
18
+ const root = getViteRoot(program, cwd);
19
+ const toEntry = (dir, pattern) => toProductionEntry(join(cwd, escapePath(relative(cwd, dir)), pattern));
20
+ const calls = findImportedCalls(program, 'filesystem-routing/vite');
21
+ if (calls.length === 0)
22
+ return production.map(pattern => toEntry(root, pattern));
23
+ const inputs = [];
24
+ for (const call of calls) {
25
+ const options = call.arguments[0];
26
+ const dir = getStringValue(findProperty(options, 'dir')) ?? defaultDir;
27
+ const value = findProperty(options, 'extensions');
28
+ const extensions = new Set();
29
+ let useDefaults = value?.type !== 'ArrayExpression';
30
+ if (value?.type === 'ArrayExpression') {
31
+ for (const element of value.elements) {
32
+ const extension = getStringValue(element);
33
+ if (extension === undefined)
34
+ useDefaults = true;
35
+ else
36
+ extensions.add(extension);
37
+ }
38
+ }
39
+ if (useDefaults)
40
+ for (const extension of defaultExtensions)
41
+ extensions.add(extension);
42
+ if (extensions.size === 0)
43
+ continue;
44
+ const suffix = extensions.size === 1 ? [...extensions][0] : `{${[...extensions].join(',')}}`;
45
+ inputs.push(toEntry(toAbsolute(dir, root), `**/*.${suffix}`));
46
+ }
47
+ return inputs;
48
+ };
49
+ const plugin = {
50
+ title,
51
+ enablers,
52
+ isEnabled,
53
+ config,
54
+ production,
55
+ resolveFromAST,
56
+ };
57
+ export default plugin;
@@ -29,7 +29,7 @@ const resolveConfig = async (config, options) => {
29
29
  const path = action?.with?.path;
30
30
  for (const step of steps.steps) {
31
31
  const workingDir = step['working-directory'];
32
- const dir = join(rootCwd, path && workingDir ? relative(workingDir, path) : workingDir ? workingDir : '.');
32
+ const dir = join(rootCwd, path && workingDir ? relative(path, workingDir) : workingDir ? workingDir : '.');
33
33
  if (step.run) {
34
34
  const manifest = getManifest(dir) ?? options.manifest;
35
35
  const actionPath = relative(dir, configFileDir);
@@ -43,6 +43,7 @@ export declare const Plugins: {
43
43
  config: string[];
44
44
  };
45
45
  fast: import("../types/config.ts").Plugin;
46
+ 'filesystem-routing': import("../types/config.ts").Plugin;
46
47
  flue: import("../types/config.ts").Plugin;
47
48
  fumadocs: import("../types/config.ts").Plugin;
48
49
  gatsby: import("../types/config.ts").Plugin;
@@ -137,6 +138,7 @@ export declare const Plugins: {
137
138
  'serverless-framework': import("../types/config.ts").Plugin;
138
139
  'simple-git-hooks': import("../types/config.ts").Plugin;
139
140
  'size-limit': import("../types/config.ts").Plugin;
141
+ 'solidjs-vite-plugin': import("../types/config.ts").Plugin;
140
142
  sst: import("../types/config.ts").Plugin;
141
143
  starlight: import("../types/config.ts").Plugin;
142
144
  stencil: import("../types/config.ts").Plugin;
@@ -160,6 +162,7 @@ export declare const Plugins: {
160
162
  'ts-node': import("../types/config.ts").Plugin;
161
163
  tsd: import("../types/config.ts").Plugin;
162
164
  tsdown: import("../types/config.ts").Plugin;
165
+ tsrs: import("../types/config.ts").Plugin;
163
166
  tsup: import("../types/config.ts").Plugin;
164
167
  tsx: import("../types/config.ts").Plugin;
165
168
  turbo: import("../types/config.ts").Plugin;
@@ -37,6 +37,7 @@ import { default as expo } from './expo/index.js';
37
37
  import { default as expoRouter } from './expo-router/index.js';
38
38
  import { default as expressiveCode } from './expressive-code/index.js';
39
39
  import { default as fast } from './fast/index.js';
40
+ import { default as filesystemRouting } from './filesystem-routing/index.js';
40
41
  import { default as flue } from './flue/index.js';
41
42
  import { default as fumadocs } from './fumadocs/index.js';
42
43
  import { default as gatsby } from './gatsby/index.js';
@@ -131,6 +132,7 @@ import { default as sentry } from './sentry/index.js';
131
132
  import { default as serverlessFramework } from './serverless-framework/index.js';
132
133
  import { default as simpleGitHooks } from './simple-git-hooks/index.js';
133
134
  import { default as sizeLimit } from './size-limit/index.js';
135
+ import { default as solidjsVitePlugin } from './solidjs-vite-plugin/index.js';
134
136
  import { default as sst } from './sst/index.js';
135
137
  import { default as starlight } from './starlight/index.js';
136
138
  import { default as stencil } from './stencil/index.js';
@@ -154,6 +156,7 @@ import { default as travis } from './travis/index.js';
154
156
  import { default as tsNode } from './ts-node/index.js';
155
157
  import { default as tsd } from './tsd/index.js';
156
158
  import { default as tsdown } from './tsdown/index.js';
159
+ import { default as tsrs } from './tsrs/index.js';
157
160
  import { default as tsup } from './tsup/index.js';
158
161
  import { default as tsx } from './tsx/index.js';
159
162
  import { default as turbo } from './turbo/index.js';
@@ -230,6 +233,7 @@ export const Plugins = {
230
233
  'expo-router': expoRouter,
231
234
  'expressive-code': expressiveCode,
232
235
  fast,
236
+ 'filesystem-routing': filesystemRouting,
233
237
  flue,
234
238
  fumadocs,
235
239
  gatsby,
@@ -324,6 +328,7 @@ export const Plugins = {
324
328
  'serverless-framework': serverlessFramework,
325
329
  'simple-git-hooks': simpleGitHooks,
326
330
  'size-limit': sizeLimit,
331
+ 'solidjs-vite-plugin': solidjsVitePlugin,
327
332
  sst,
328
333
  starlight,
329
334
  stencil,
@@ -347,6 +352,7 @@ export const Plugins = {
347
352
  'ts-node': tsNode,
348
353
  tsd,
349
354
  tsdown,
355
+ tsrs,
350
356
  tsup,
351
357
  tsx,
352
358
  turbo,
@@ -5,6 +5,7 @@ import { isInternal, join, normalize, toAbsolute } from '../../util/path.js';
5
5
  import { hasDependency } from '../../util/plugin.js';
6
6
  import { getDependenciesFromConfig } from '../babel/index.js';
7
7
  import { getReportersDependencies, resolveExtensibleConfig, resolveWithPrefix } from './helpers.js';
8
+ import { createJestMockVisitor } from './visitors/mock.js';
8
9
  const title = 'Jest';
9
10
  const enablers = ['jest'];
10
11
  const isEnabled = ({ dependencies, manifest }) => hasDependency(dependencies, enablers) || Boolean(manifest.name?.startsWith('jest-presets'));
@@ -127,6 +128,9 @@ const resolveConfig = async (localConfig, options) => {
127
128
  const args = {
128
129
  config: true,
129
130
  };
131
+ const registerVisitors = ({ ctx, registerVisitor }) => {
132
+ registerVisitor(createJestMockVisitor(ctx));
133
+ };
130
134
  const plugin = {
131
135
  title,
132
136
  enablers,
@@ -135,5 +139,6 @@ const plugin = {
135
139
  entry,
136
140
  resolveConfig,
137
141
  args,
142
+ registerVisitors,
138
143
  };
139
144
  export default plugin;
@@ -0,0 +1,2 @@
1
+ import type { PluginVisitorContext, PluginVisitorObject } from '../../../types/config.ts';
2
+ export declare function createJestMockVisitor(ctx: PluginVisitorContext): PluginVisitorObject;
@@ -0,0 +1,91 @@
1
+ import { IMPORT_FLAGS } from '../../../constants.js';
2
+ import { getPropertyKey } from '../../../typescript/ast-helpers.js';
3
+ import { getStringValue, isStringLiteral } from '../../../typescript/ast-nodes.js';
4
+ import { isShadowed } from '../../../typescript/visitors/walk.js';
5
+ const mockMethods = new Set([
6
+ 'mock',
7
+ 'doMock',
8
+ 'requireActual',
9
+ 'requireMock',
10
+ 'createMockFromModule',
11
+ 'unmock',
12
+ 'dontMock',
13
+ 'deepUnmock',
14
+ 'setMock',
15
+ 'unstable_mockModule',
16
+ 'unstable_unmockModule',
17
+ ]);
18
+ export function createJestMockVisitor(ctx) {
19
+ const jestNames = new Set();
20
+ const virtualMocks = new Set();
21
+ const virtualEsmMocks = new Set();
22
+ const mockLookups = [];
23
+ return {
24
+ Program(node) {
25
+ jestNames.clear();
26
+ virtualMocks.clear();
27
+ virtualEsmMocks.clear();
28
+ mockLookups.length = 0;
29
+ jestNames.add('jest');
30
+ for (const statement of node.body) {
31
+ if (statement.type !== 'ImportDeclaration' ||
32
+ !isStringLiteral(statement.source) ||
33
+ getStringValue(statement.source) !== '@jest/globals')
34
+ continue;
35
+ for (const specifier of statement.specifiers ?? []) {
36
+ if (specifier.type === 'ImportSpecifier' &&
37
+ specifier.imported.type === 'Identifier' &&
38
+ specifier.imported.name === 'jest') {
39
+ jestNames.add(specifier.local.name);
40
+ }
41
+ }
42
+ }
43
+ },
44
+ CallExpression(node) {
45
+ const argument = node.arguments[0];
46
+ const callee = node.callee;
47
+ if (!isStringLiteral(argument) ||
48
+ callee.type !== 'MemberExpression' ||
49
+ callee.computed ||
50
+ callee.object.type !== 'Identifier' ||
51
+ !jestNames.has(callee.object.name) ||
52
+ isShadowed(callee.object.name, callee.object.start) ||
53
+ callee.property.type !== 'Identifier' ||
54
+ !mockMethods.has(callee.property.name))
55
+ return;
56
+ const specifier = getStringValue(argument);
57
+ const method = callee.property.name;
58
+ const options = node.arguments[2];
59
+ if ((method === 'mock' || method === 'doMock' || method === 'unstable_mockModule') &&
60
+ options?.type === 'ObjectExpression') {
61
+ for (const property of options.properties) {
62
+ if (property.type === 'Property' &&
63
+ !property.computed &&
64
+ getPropertyKey(property) === 'virtual' &&
65
+ property.value.type === 'Literal' &&
66
+ property.value.value === true) {
67
+ (method === 'unstable_mockModule' ? virtualEsmMocks : virtualMocks).add(specifier);
68
+ return;
69
+ }
70
+ }
71
+ }
72
+ if (method === 'requireActual' || method === 'createMockFromModule') {
73
+ const flags = method === 'requireActual' ? IMPORT_FLAGS.OPAQUE : IMPORT_FLAGS.SIDE_EFFECTS;
74
+ ctx.addImport(specifier, argument.start, flags);
75
+ return;
76
+ }
77
+ mockLookups.push({
78
+ specifier,
79
+ pos: argument.start,
80
+ isEsm: method === 'unstable_mockModule' || method === 'unstable_unmockModule',
81
+ });
82
+ },
83
+ 'Program:exit'() {
84
+ for (const { specifier, pos, isEsm } of mockLookups) {
85
+ if ((isEsm ? virtualEsmMocks : virtualMocks).has(specifier))
86
+ continue;
87
+ ctx.addImport(specifier, pos, IMPORT_FLAGS.SIDE_EFFECTS);
88
+ }
89
+ },
90
+ };
91
+ }