knip 6.32.3 → 6.34.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.
- package/dist/DependencyDeputy.d.ts +1 -2
- package/dist/DependencyDeputy.js +1 -2
- package/dist/ProjectPrincipal.d.ts +6 -3
- package/dist/ProjectPrincipal.js +29 -6
- package/dist/cli.js +2 -2
- package/dist/config.d.ts +2 -0
- package/dist/config.js +1 -0
- package/dist/graph/analyze.js +4 -4
- package/dist/graph/build.js +1 -2
- package/dist/graph-explorer/explorer.d.ts +1 -0
- package/dist/graph-explorer/explorer.js +2 -0
- package/dist/graph-explorer/operations/is-enumerated.d.ts +2 -0
- package/dist/graph-explorer/operations/is-enumerated.js +33 -0
- package/dist/manifest/helpers.d.ts +2 -3
- package/dist/manifest/helpers.js +6 -42
- package/dist/manifest/index.d.ts +1 -2
- package/dist/manifest/index.js +2 -2
- package/dist/plugins/dotenv/index.js +1 -8
- package/dist/plugins/eslint/helpers.d.ts +2 -1
- package/dist/plugins/eslint/helpers.js +1 -0
- package/dist/plugins/eslint/resolveFromAST.d.ts +1 -0
- package/dist/plugins/eslint/resolveFromAST.js +5 -2
- package/dist/plugins/eslint/types.d.ts +1 -1
- package/dist/plugins/moonrepo/index.js +3 -3
- package/dist/plugins/node/index.js +5 -0
- package/dist/plugins/node/visitors/fsPromisesGlob.d.ts +2 -0
- package/dist/plugins/node/visitors/fsPromisesGlob.js +89 -0
- package/dist/plugins/nuxt/index.js +38 -13
- package/dist/plugins/nuxt/types.d.ts +5 -1
- package/dist/plugins/oxlint/index.js +6 -2
- package/dist/plugins/oxlint/types.d.ts +2 -0
- package/dist/plugins/typescript/index.js +22 -5
- package/dist/plugins/vitest/index.js +18 -11
- package/dist/plugins/vitest/types.d.ts +1 -1
- package/dist/plugins/vitest/visitors/mock.d.ts +2 -0
- package/dist/plugins/vitest/visitors/mock.js +50 -0
- package/dist/plugins/webpack/index.js +15 -14
- package/dist/run.js +1 -1
- package/dist/types/config.d.ts +2 -0
- package/dist/types/module-graph.d.ts +2 -0
- package/dist/types/tsconfig-json.d.ts +6 -0
- package/dist/typescript/get-imports-and-exports.js +7 -1
- package/dist/typescript/glob-imports.js +8 -3
- package/dist/typescript/visitors/calls.js +2 -2
- package/dist/typescript/visitors/members.js +56 -8
- package/dist/typescript/visitors/walk.d.ts +4 -1
- package/dist/typescript/visitors/walk.js +78 -14
- package/dist/util/cli-arguments.d.ts +1 -0
- package/dist/util/cli-arguments.js +9 -0
- package/dist/util/create-options.d.ts +2 -1
- package/dist/util/create-options.js +3 -1
- package/dist/util/load-config.js +6 -1
- package/dist/util/resolve.d.ts +1 -0
- package/dist/util/resolve.js +11 -0
- package/dist/util/scripts.d.ts +1 -0
- package/dist/util/scripts.js +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +16 -12
|
@@ -49,6 +49,26 @@ const resolveAlias = (specifier, srcDir, rootDir) => {
|
|
|
49
49
|
return join(srcDir, specifier.slice(2));
|
|
50
50
|
return specifier;
|
|
51
51
|
};
|
|
52
|
+
const remoteSourcePrefixes = ['gh:', 'github:', 'gitlab:', 'bitbucket:', 'https://', 'http://'];
|
|
53
|
+
const toLayerSource = (layer) => {
|
|
54
|
+
if (typeof layer === 'string')
|
|
55
|
+
return layer;
|
|
56
|
+
if (Array.isArray(layer))
|
|
57
|
+
return layer[0];
|
|
58
|
+
if (layer && typeof layer === 'object' && 'source' in layer)
|
|
59
|
+
return layer.source;
|
|
60
|
+
};
|
|
61
|
+
const toLayerSources = (extend) => {
|
|
62
|
+
const sources = [];
|
|
63
|
+
if (!extend)
|
|
64
|
+
return sources;
|
|
65
|
+
for (const layer of Array.isArray(extend) ? extend : [extend]) {
|
|
66
|
+
const source = toLayerSource(layer);
|
|
67
|
+
if (typeof source === 'string')
|
|
68
|
+
sources.push(source);
|
|
69
|
+
}
|
|
70
|
+
return sources;
|
|
71
|
+
};
|
|
52
72
|
const addAppEntries = (inputs, srcDir, serverDir, config, dir) => {
|
|
53
73
|
for (const id of entry)
|
|
54
74
|
inputs.push(toEntry(join(srcDir, id)));
|
|
@@ -67,18 +87,18 @@ const addAppEntries = (inputs, srcDir, serverDir, config, dir) => {
|
|
|
67
87
|
inputs.push(toDeferResolveProductionEntry(resolveAlias(id, srcDir, dir)));
|
|
68
88
|
};
|
|
69
89
|
const findLayerConfigs = (cwd) => _syncGlob({ cwd, patterns: [`layers/*/${config.at(0)}`] });
|
|
90
|
+
const definitionFiles = [
|
|
91
|
+
'.nuxt/imports.d.ts',
|
|
92
|
+
'.nuxt/components.d.ts',
|
|
93
|
+
'.nuxt/types/nitro-routes.d.ts',
|
|
94
|
+
'.nuxt/types/nitro-imports.d.ts',
|
|
95
|
+
];
|
|
70
96
|
const registerCompilers = async ({ cwd, hasDependency, registerCompiler }) => {
|
|
71
|
-
if (hasDependency('nuxt') || hasDependency('nuxt-nightly')) {
|
|
97
|
+
if (hasDependency('nuxt') || hasDependency('nuxt-nightly') || isDirectory(cwd, '.nuxt')) {
|
|
98
|
+
const paths = definitionFiles.map(file => join(cwd, file));
|
|
72
99
|
const maps = createAutoImportMaps();
|
|
73
|
-
const
|
|
74
|
-
'.
|
|
75
|
-
'.nuxt/components.d.ts',
|
|
76
|
-
'.nuxt/types/nitro-routes.d.ts',
|
|
77
|
-
'.nuxt/types/nitro-imports.d.ts',
|
|
78
|
-
];
|
|
79
|
-
for (const file of definitionFiles) {
|
|
80
|
-
const path = join(cwd, file);
|
|
81
|
-
buildAutoImportMap(path, readAndParseFile(path), maps, file.endsWith('components.d.ts'));
|
|
100
|
+
for (const path of paths) {
|
|
101
|
+
buildAutoImportMap(path, readAndParseFile(path), maps, path.endsWith('components.d.ts'));
|
|
82
102
|
}
|
|
83
103
|
registerCompiler({ extension: '.vue', compiler: createVueCompiler(maps, cwd) });
|
|
84
104
|
registerCompiler({ extension: '.ts', compiler: createTsCompiler(maps) });
|
|
@@ -101,6 +121,9 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
101
121
|
addModule(id);
|
|
102
122
|
}
|
|
103
123
|
addAppEntries(inputs, srcDir, serverDir, localConfig, cwd);
|
|
124
|
+
const sharedDir = toAbsolute(localConfig.dir?.shared ?? 'shared', cwd);
|
|
125
|
+
inputs.push(toAlias('#shared', sharedDir));
|
|
126
|
+
inputs.push(toAlias('#shared/*', join(sharedDir, '*'), { dir: cwd }));
|
|
104
127
|
const aliases = localConfig.alias;
|
|
105
128
|
if (aliases) {
|
|
106
129
|
for (const key in aliases) {
|
|
@@ -111,15 +134,17 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
111
134
|
}
|
|
112
135
|
}
|
|
113
136
|
}
|
|
114
|
-
for (const
|
|
115
|
-
|
|
137
|
+
for (const source of toLayerSources(localConfig.extends)) {
|
|
138
|
+
if (remoteSourcePrefixes.some(prefix => source.startsWith(prefix)))
|
|
139
|
+
continue;
|
|
140
|
+
const target = resolveAlias(source, srcDir, cwd);
|
|
116
141
|
const resolved = isInternal(target) ? toAbsolute(target, cwd) : target;
|
|
117
142
|
const configs = _syncGlob({ cwd: resolved, patterns: config });
|
|
118
143
|
if (configs.length > 0)
|
|
119
144
|
for (const cfg of configs)
|
|
120
145
|
inputs.push(toConfig('nuxt', cfg));
|
|
121
146
|
else
|
|
122
|
-
inputs.push(toDependency(
|
|
147
|
+
inputs.push(toDependency(source));
|
|
123
148
|
}
|
|
124
149
|
for (const layerConfig of findLayerConfigs(cwd)) {
|
|
125
150
|
inputs.push(toConfig('nuxt', layerConfig));
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
type NuxtLayer = string | [string, unknown?] | {
|
|
2
|
+
source: string;
|
|
3
|
+
};
|
|
1
4
|
export interface NuxtConfig {
|
|
2
5
|
srcDir?: string;
|
|
3
6
|
buildDir?: string;
|
|
@@ -14,7 +17,7 @@ export interface NuxtConfig {
|
|
|
14
17
|
autoImport?: boolean;
|
|
15
18
|
dirs?: string[];
|
|
16
19
|
};
|
|
17
|
-
extends?:
|
|
20
|
+
extends?: NuxtLayer | NuxtLayer[];
|
|
18
21
|
components?: Array<string | {
|
|
19
22
|
path: string;
|
|
20
23
|
}> | {
|
|
@@ -25,3 +28,4 @@ export interface NuxtConfig {
|
|
|
25
28
|
css?: string[];
|
|
26
29
|
alias?: Record<string, string>;
|
|
27
30
|
}
|
|
31
|
+
export {};
|
|
@@ -3,10 +3,12 @@ import { findProperty, getPropertyValues } from '../../typescript/ast-helpers.js
|
|
|
3
3
|
import { toDependency, toEntry } from '../../util/input.js';
|
|
4
4
|
import { isInternal } from '../../util/path.js';
|
|
5
5
|
import { hasDependency } from '../../util/plugin.js';
|
|
6
|
+
import { getInputsFromSettings } from '../eslint/helpers.js';
|
|
7
|
+
import { getInputsFromSettingsAST } from '../eslint/resolveFromAST.js';
|
|
6
8
|
const title = 'Oxlint';
|
|
7
9
|
const enablers = ['oxlint', 'vite-plus'];
|
|
8
10
|
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
9
|
-
const config = ['.oxlintrc.json', 'oxlint.config.{ts,mts}', 'vite.config.{js,mjs,ts,cjs,mts,cts}'];
|
|
11
|
+
const config = ['.oxlintrc.{json,jsonc}', 'oxlint.config.{ts,mts}', 'vite.config.{js,mjs,ts,cjs,mts,cts}'];
|
|
10
12
|
const isViteConfig = (configFileName) => configFileName.startsWith('vite.config.');
|
|
11
13
|
const args = {
|
|
12
14
|
config: true,
|
|
@@ -29,6 +31,8 @@ const resolveConfig = config => {
|
|
|
29
31
|
for (const input of resolveJsPlugins(override.jsPlugins))
|
|
30
32
|
inputs.push(input);
|
|
31
33
|
}
|
|
34
|
+
for (const input of getInputsFromSettings(config.settings))
|
|
35
|
+
inputs.push(input);
|
|
32
36
|
return inputs;
|
|
33
37
|
};
|
|
34
38
|
const resolveFromAST = (program, options) => {
|
|
@@ -51,7 +55,7 @@ const resolveFromAST = (program, options) => {
|
|
|
51
55
|
},
|
|
52
56
|
});
|
|
53
57
|
visitor.visit(program);
|
|
54
|
-
return resolveJsPlugins([...jsPlugins]);
|
|
58
|
+
return [...resolveJsPlugins([...jsPlugins]), ...getInputsFromSettingsAST(program)];
|
|
55
59
|
};
|
|
56
60
|
const plugin = {
|
|
57
61
|
title,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Settings } from '../eslint/types.ts';
|
|
1
2
|
type JsPlugin = string | {
|
|
2
3
|
name: string;
|
|
3
4
|
specifier: string;
|
|
@@ -8,5 +9,6 @@ type Override = {
|
|
|
8
9
|
export type OxlintConfig = {
|
|
9
10
|
jsPlugins?: JsPlugin[];
|
|
10
11
|
overrides?: Override[];
|
|
12
|
+
settings?: Settings;
|
|
11
13
|
};
|
|
12
14
|
export {};
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { compact } from '../../util/array.js';
|
|
2
|
-
import { toConfig, toDeferResolve, toProductionDependency } from '../../util/input.js';
|
|
2
|
+
import { toConfig, toDeferResolve, toDependency, toProductionDependency } from '../../util/input.js';
|
|
3
3
|
import { join } from '../../util/path.js';
|
|
4
4
|
import { hasDependency } from '../../util/plugin.js';
|
|
5
|
+
import { toShellCommand } from '../../util/scripts.js';
|
|
5
6
|
const title = 'TypeScript';
|
|
6
7
|
const enablers = ['typescript', '@typescript/native', '@typescript/native-preview'];
|
|
7
8
|
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
8
|
-
const config = ['tsconfig.json'];
|
|
9
|
-
const
|
|
9
|
+
const config = ['tsconfig.json', 'package.json'];
|
|
10
|
+
const packageJsonPath = 'typescript.contentMapper';
|
|
11
|
+
const resolveContentMapper = ({ exec }, options) => {
|
|
12
|
+
if (!Array.isArray(exec) || exec.some(arg => typeof arg !== 'string'))
|
|
13
|
+
return [];
|
|
14
|
+
return options
|
|
15
|
+
.getInputsFromScripts(toShellCommand(exec))
|
|
16
|
+
.map(input => input.type === 'entry' || input.type === 'deferResolveEntry' ? { ...input, production: true } : input);
|
|
17
|
+
};
|
|
18
|
+
const resolveTsConfig = (localConfig, options) => {
|
|
10
19
|
const { compilerOptions } = localConfig;
|
|
11
20
|
const extend = localConfig.extends
|
|
12
21
|
? [localConfig.extends]
|
|
@@ -16,8 +25,9 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
16
25
|
const references = localConfig.references
|
|
17
26
|
?.filter(reference => reference.path.endsWith('.json'))
|
|
18
27
|
.map(reference => toConfig('typescript', reference.path, { containingFilePath: options.configFilePath })) ?? [];
|
|
28
|
+
const contentMappers = localConfig.contentMappers?.map(contentMapper => toDependency(contentMapper.package)) ?? [];
|
|
19
29
|
if (!(compilerOptions && localConfig))
|
|
20
|
-
return compact([...extend, ...references]);
|
|
30
|
+
return compact([...contentMappers, ...extend, ...references]);
|
|
21
31
|
const jsx = (compilerOptions?.jsxImportSource ? [compilerOptions.jsxImportSource] : []).map(toProductionDependency);
|
|
22
32
|
const types = compilerOptions.types ?? [];
|
|
23
33
|
const plugins = Array.isArray(compilerOptions?.plugins)
|
|
@@ -25,6 +35,7 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
25
35
|
: [];
|
|
26
36
|
const importHelpers = compilerOptions?.importHelpers ? ['tslib'] : [];
|
|
27
37
|
return compact([
|
|
38
|
+
...contentMappers,
|
|
28
39
|
...extend,
|
|
29
40
|
...references,
|
|
30
41
|
...types.map(id => toDeferResolve(id, { isTypeOnly: true, dir: options.cwd })),
|
|
@@ -32,19 +43,25 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
32
43
|
...jsx,
|
|
33
44
|
]);
|
|
34
45
|
};
|
|
46
|
+
const resolveConfig = (localConfig, options) => options.configFileName === 'package.json'
|
|
47
|
+
? resolveContentMapper(localConfig, options)
|
|
48
|
+
: resolveTsConfig(localConfig, options);
|
|
35
49
|
const args = {
|
|
36
50
|
binaries: ['tsc', 'tsgo'],
|
|
37
51
|
string: ['project'],
|
|
38
52
|
alias: { project: ['p'] },
|
|
39
53
|
config: [['project', (p) => (p.endsWith('.json') ? p : join(p, 'tsconfig.json'))]],
|
|
40
54
|
};
|
|
41
|
-
const note =
|
|
55
|
+
const note = `[What's up with that configurable tsconfig.json location?](/reference/faq#whats-up-with-that-configurable-tsconfigjson-location)
|
|
56
|
+
|
|
57
|
+
In a content mapper package, the command in \`package.json#typescript.contentMapper.exec\` is resolved to a production entry.`;
|
|
42
58
|
export const docs = { note };
|
|
43
59
|
const plugin = {
|
|
44
60
|
title,
|
|
45
61
|
enablers,
|
|
46
62
|
isEnabled,
|
|
47
63
|
config,
|
|
64
|
+
packageJsonPath,
|
|
48
65
|
resolveConfig,
|
|
49
66
|
args,
|
|
50
67
|
};
|
|
@@ -6,6 +6,7 @@ import { isAbsolute, isInternal, join, toAbsolute } from '../../util/path.js';
|
|
|
6
6
|
import { hasDependency } from '../../util/plugin.js';
|
|
7
7
|
import { getIndexHtmlEntries } from '../vite/helpers.js';
|
|
8
8
|
import { getAliasInputs, getEnvSpecifier, getExternalReporters } from './helpers.js';
|
|
9
|
+
import { createVitestMockVisitor } from './visitors/mock.js';
|
|
9
10
|
const title = 'Vitest';
|
|
10
11
|
const enablers = ['vitest', 'vite-plus'];
|
|
11
12
|
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
@@ -15,7 +16,6 @@ const testEntry = ['**/*.{bench,test,test-d,spec,spec-d}.?(c|m)[jt]s?(x)'];
|
|
|
15
16
|
const entry = [...testEntry, ...mocks];
|
|
16
17
|
const benchmark = ['**/*.bench.?(c|m)[jt]s?(x)'];
|
|
17
18
|
const findConfigDependencies = (localConfig, options, vitestRoot) => {
|
|
18
|
-
const { configFileDir: dir } = options;
|
|
19
19
|
const testConfig = localConfig.test;
|
|
20
20
|
if (!testConfig)
|
|
21
21
|
return [];
|
|
@@ -37,7 +37,9 @@ const findConfigDependencies = (localConfig, options, vitestRoot) => {
|
|
|
37
37
|
...toDeferResolve(specifier),
|
|
38
38
|
dir: vitestRoot,
|
|
39
39
|
}));
|
|
40
|
-
const globalSetup = [testConfig.globalSetup ?? []]
|
|
40
|
+
const globalSetup = [testConfig.globalSetup ?? []]
|
|
41
|
+
.flat()
|
|
42
|
+
.map(specifier => ({ ...toDeferResolve(specifier), dir: vitestRoot }));
|
|
41
43
|
const workspaceDependencies = [];
|
|
42
44
|
if (testConfig.workspace !== undefined) {
|
|
43
45
|
for (const workspaceConfig of testConfig.workspace) {
|
|
@@ -75,12 +77,14 @@ const getConfigs = async (localConfig) => {
|
|
|
75
77
|
if (typeof config === 'function') {
|
|
76
78
|
for (const command of ['serve', 'build']) {
|
|
77
79
|
for (const mode of ['development', 'production']) {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
for (const ssrBuild of command === 'build' ? [undefined, false, true] : [undefined]) {
|
|
81
|
+
const cfg = await config({ command, mode, ssrBuild });
|
|
82
|
+
configs.push(cfg);
|
|
83
|
+
if (cfg.test?.projects) {
|
|
84
|
+
for (const project of cfg.test.projects) {
|
|
85
|
+
if (typeof project !== 'string') {
|
|
86
|
+
configs.push(project);
|
|
87
|
+
}
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
}
|
|
@@ -181,9 +185,8 @@ export const resolveConfig = async (localConfig, options) => {
|
|
|
181
185
|
for (const dependency of findConfigDependencies(cfg, options, vitestRoot))
|
|
182
186
|
inputs.add(dependency);
|
|
183
187
|
const _entry = cfg.build?.lib?.entry ?? [];
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
.map(id => toEntry(id));
|
|
188
|
+
const entries = typeof _entry === 'string' ? [_entry] : Array.isArray(_entry) ? _entry : Object.values(_entry).flat();
|
|
189
|
+
const deps = entries.map(specifier => join(vitestRoot, specifier)).map(id => toEntry(id));
|
|
187
190
|
for (const dependency of deps)
|
|
188
191
|
inputs.add(dependency);
|
|
189
192
|
}
|
|
@@ -215,6 +218,9 @@ const args = {
|
|
|
215
218
|
return inputs;
|
|
216
219
|
},
|
|
217
220
|
};
|
|
221
|
+
const registerVisitors = ({ ctx, registerVisitor }) => {
|
|
222
|
+
registerVisitor(createVitestMockVisitor(ctx));
|
|
223
|
+
};
|
|
218
224
|
const plugin = {
|
|
219
225
|
title,
|
|
220
226
|
enablers,
|
|
@@ -223,5 +229,6 @@ const plugin = {
|
|
|
223
229
|
entry,
|
|
224
230
|
resolveConfig,
|
|
225
231
|
args,
|
|
232
|
+
registerVisitors,
|
|
226
233
|
};
|
|
227
234
|
export default plugin;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { IMPORT_FLAGS } from '../../../constants.js';
|
|
2
|
+
import { getStringValue, isStringLiteral } from '../../../typescript/ast-nodes.js';
|
|
3
|
+
import { isShadowed } from '../../../typescript/visitors/walk.js';
|
|
4
|
+
export function createVitestMockVisitor(ctx) {
|
|
5
|
+
const viNames = new Set();
|
|
6
|
+
return {
|
|
7
|
+
Program(node) {
|
|
8
|
+
viNames.clear();
|
|
9
|
+
for (const statement of node.body) {
|
|
10
|
+
if (statement.type !== 'ImportDeclaration' ||
|
|
11
|
+
!isStringLiteral(statement.source) ||
|
|
12
|
+
getStringValue(statement.source) !== 'vitest')
|
|
13
|
+
continue;
|
|
14
|
+
for (const specifier of statement.specifiers ?? []) {
|
|
15
|
+
if (specifier.type === 'ImportSpecifier' &&
|
|
16
|
+
specifier.imported.type === 'Identifier' &&
|
|
17
|
+
specifier.imported.name === 'vi') {
|
|
18
|
+
viNames.add(specifier.local.name);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
CallExpression(node) {
|
|
24
|
+
const argument = node.arguments[0];
|
|
25
|
+
const factory = node.arguments[1];
|
|
26
|
+
const factoryBody = factory?.type === 'ArrowFunctionExpression' &&
|
|
27
|
+
factory.body.type === 'ParenthesizedExpression' &&
|
|
28
|
+
factory.body.expression.type === 'ObjectExpression'
|
|
29
|
+
? factory.body.expression
|
|
30
|
+
: undefined;
|
|
31
|
+
if (argument?.type !== 'ImportExpression' ||
|
|
32
|
+
!isStringLiteral(argument.source) ||
|
|
33
|
+
factory?.type !== 'ArrowFunctionExpression' ||
|
|
34
|
+
!factoryBody ||
|
|
35
|
+
factory.async ||
|
|
36
|
+
factory.params.length > 0 ||
|
|
37
|
+
factoryBody.properties.some(property => property.type === 'SpreadElement') ||
|
|
38
|
+
node.callee.type !== 'MemberExpression' ||
|
|
39
|
+
node.callee.computed ||
|
|
40
|
+
node.callee.object.type !== 'Identifier' ||
|
|
41
|
+
!viNames.has(node.callee.object.name) ||
|
|
42
|
+
isShadowed(node.callee.object.name, node.callee.object.start) ||
|
|
43
|
+
node.callee.property.type !== 'Identifier' ||
|
|
44
|
+
node.callee.property.name !== 'mock')
|
|
45
|
+
return;
|
|
46
|
+
ctx.markImportExpressionHandled(argument.start);
|
|
47
|
+
ctx.addImport(getStringValue(argument.source), argument.source.start, IMPORT_FLAGS.SIDE_EFFECTS);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -105,20 +105,21 @@ export const findWebpackDependenciesFromConfig = async (config, options) => {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
108
|
+
const entry = typeof opts.entry === 'function' ? await opts.entry() : opts.entry;
|
|
109
|
+
if (typeof entry === 'string')
|
|
110
|
+
entries.push(entry);
|
|
111
|
+
else if (Array.isArray(entry))
|
|
112
|
+
entries.push(...entry);
|
|
113
|
+
else if (typeof entry === 'object') {
|
|
114
|
+
for (const item of Object.values(entry)) {
|
|
115
|
+
if (typeof item === 'string')
|
|
116
|
+
entries.push(item);
|
|
117
|
+
else if (Array.isArray(item))
|
|
118
|
+
entries.push(...item);
|
|
119
|
+
else if (typeof item === 'function')
|
|
120
|
+
entries.push(item());
|
|
121
|
+
else if (item && typeof item === 'object' && 'import' in item)
|
|
122
|
+
entries.push(...[item.import].flat());
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
125
|
if (entries.length === 0 && opts.context)
|
package/dist/run.js
CHANGED
|
@@ -60,7 +60,7 @@ export const run = async (options) => {
|
|
|
60
60
|
const isGitIgnored = await getGitIgnoredHandler(options, new Set(workspaces.map(w => w.dir)));
|
|
61
61
|
const toSourceFilePath = getModuleSourcePathHandler(chief);
|
|
62
62
|
const findWorkspacePackageTarget = getWorkspacePackageTargetHandler(chief);
|
|
63
|
-
const principal = new ProjectPrincipal(options, toSourceFilePath, findWorkspacePackageTarget);
|
|
63
|
+
const principal = new ProjectPrincipal(options, toSourceFilePath, findWorkspacePackageTarget, filePath => chief.findWorkspaceByFilePath(filePath)?.name);
|
|
64
64
|
collector.setWorkspaceFilter(chief.workspaceFilePathFilter);
|
|
65
65
|
collector.setSelectedWorkspaces(chief.selectedWorkspaces);
|
|
66
66
|
collector.setIgnoreIssues(chief.getIgnoreIssues());
|
package/dist/types/config.d.ts
CHANGED
|
@@ -138,8 +138,10 @@ export type PluginVisitorContext = {
|
|
|
138
138
|
sourceText: string;
|
|
139
139
|
addScript: (script: string) => void;
|
|
140
140
|
addImport: (specifier: string, pos: number, modifiers: number) => void;
|
|
141
|
+
markImportExpressionHandled: (pos: number) => void;
|
|
141
142
|
addImportGlob: (patterns: string[], options?: {
|
|
142
143
|
base?: string;
|
|
144
|
+
cwd?: string;
|
|
143
145
|
filter?: RegExp;
|
|
144
146
|
}) => void;
|
|
145
147
|
markExportRegistered: (name: string) => void;
|
|
@@ -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;
|
|
@@ -76,6 +77,7 @@ export type FileNode = {
|
|
|
76
77
|
export interface ImportGlob {
|
|
77
78
|
patterns: string[];
|
|
78
79
|
base?: string;
|
|
80
|
+
cwd?: string;
|
|
79
81
|
filter?: RegExp;
|
|
80
82
|
}
|
|
81
83
|
export type ModuleGraph = Map<FilePath, FileNode>;
|
|
@@ -25,6 +25,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
25
25
|
const specifierExportNames = new Set();
|
|
26
26
|
const scripts = new Set();
|
|
27
27
|
const importGlobs = [];
|
|
28
|
+
const handledImportExpressions = new Set();
|
|
28
29
|
const importAliases = new Map();
|
|
29
30
|
const addImportAlias = (aliasName, id, importFilePath) => {
|
|
30
31
|
const aliases = importAliases.get(aliasName);
|
|
@@ -61,6 +62,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
61
62
|
col: opts.col,
|
|
62
63
|
isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
|
|
63
64
|
modifiers,
|
|
65
|
+
jsDocTags: undefined,
|
|
64
66
|
});
|
|
65
67
|
const file = internal.get(importFilePath);
|
|
66
68
|
const importMaps = file ?? createImports();
|
|
@@ -145,6 +147,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
145
147
|
col,
|
|
146
148
|
isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
|
|
147
149
|
modifiers,
|
|
150
|
+
jsDocTags,
|
|
148
151
|
});
|
|
149
152
|
}
|
|
150
153
|
}
|
|
@@ -170,6 +173,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
170
173
|
col,
|
|
171
174
|
isTypeOnly: isDts || !!(modifiers & IMPORT_FLAGS.TYPE_ONLY),
|
|
172
175
|
modifiers,
|
|
176
|
+
jsDocTags: undefined,
|
|
173
177
|
});
|
|
174
178
|
}
|
|
175
179
|
}
|
|
@@ -278,7 +282,8 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
278
282
|
pluginCtx.sourceText = sourceText;
|
|
279
283
|
pluginCtx.addScript = (s) => scripts.add(s);
|
|
280
284
|
pluginCtx.addImport = (spec, pos, mod) => addImport(spec, undefined, undefined, undefined, pos, mod);
|
|
281
|
-
pluginCtx.
|
|
285
|
+
pluginCtx.markImportExpressionHandled = (pos) => handledImportExpressions.add(pos);
|
|
286
|
+
pluginCtx.addImportGlob = (patterns, opts) => importGlobs.push({ patterns, base: opts?.base, cwd: opts?.cwd, filter: opts?.filter });
|
|
282
287
|
pluginCtx.markExportRegistered = (name) => registeredCustomElements.add(name);
|
|
283
288
|
}
|
|
284
289
|
const localRefs = _walkAST(result.program, sourceText, filePath, result.module.hasModuleSyntax, {
|
|
@@ -311,6 +316,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
311
316
|
resolveModule,
|
|
312
317
|
programFiles,
|
|
313
318
|
entryFiles,
|
|
319
|
+
handledImportExpressions,
|
|
314
320
|
visitor,
|
|
315
321
|
getJSDocTags,
|
|
316
322
|
});
|
|
@@ -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 (
|
|
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;
|
|
@@ -202,7 +202,7 @@ export function handleCallExpression(node, s) {
|
|
|
202
202
|
addValue(internalImport.import, OPAQUE, s.filePath);
|
|
203
203
|
else {
|
|
204
204
|
internalImport.refs.add(arg.name);
|
|
205
|
-
(internalImport.enumerated ??= new Set()).add(
|
|
205
|
+
(internalImport.enumerated ??= new Set()).add(_import.importedName);
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
}
|
|
@@ -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 &&
|
|
@@ -2,6 +2,12 @@ import { OPAQUE } from '../../constants.js';
|
|
|
2
2
|
import { addValue } from '../../util/module-graph.js';
|
|
3
3
|
import { getStringValue, isStringLiteral } from '../ast-nodes.js';
|
|
4
4
|
import { isShadowed } from './walk.js';
|
|
5
|
+
function markWholeObjectRead(internalImport, id) {
|
|
6
|
+
(internalImport.enumerated ??= new Set()).add(id);
|
|
7
|
+
}
|
|
8
|
+
function isNumericKey(value) {
|
|
9
|
+
return value != null && Number.isFinite(Number(value)) && String(Number(value)) === value;
|
|
10
|
+
}
|
|
5
11
|
export function handleMemberExpression(node, s) {
|
|
6
12
|
if (node.object.type === 'MemberExpression' && node.object.object.type === 'MemberExpression') {
|
|
7
13
|
s.chainedMemberExprs.add(node.object);
|
|
@@ -18,12 +24,21 @@ export function handleMemberExpression(node, s) {
|
|
|
18
24
|
memberName = node.property.name;
|
|
19
25
|
}
|
|
20
26
|
else if (node.computed && isStringLiteral(node.property)) {
|
|
21
|
-
|
|
27
|
+
const value = getStringValue(node.property);
|
|
28
|
+
if (!_import.isNamespace && isNumericKey(value)) {
|
|
29
|
+
markWholeObjectRead(internalImport, _import.importedName);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
memberName = value;
|
|
22
33
|
}
|
|
23
34
|
else if (node.computed && _import.isNamespace) {
|
|
24
35
|
addValue(internalImport.import, OPAQUE, s.filePath);
|
|
25
36
|
return;
|
|
26
37
|
}
|
|
38
|
+
else if (node.computed) {
|
|
39
|
+
markWholeObjectRead(internalImport, _import.importedName);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
27
42
|
if (memberName) {
|
|
28
43
|
if (_import.isDynamicImport) {
|
|
29
44
|
addValue(internalImport.import, memberName, s.filePath);
|
|
@@ -44,18 +59,51 @@ export function handleMemberExpression(node, s) {
|
|
|
44
59
|
if (aliases) {
|
|
45
60
|
s.accessedAliases.add(localName);
|
|
46
61
|
let memberName;
|
|
62
|
+
let isWholeRead = false;
|
|
47
63
|
if (node.computed === false && node.property.type === 'Identifier') {
|
|
48
64
|
memberName = node.property.name;
|
|
49
65
|
}
|
|
50
66
|
else if (node.computed && isStringLiteral(node.property)) {
|
|
51
|
-
|
|
67
|
+
const value = getStringValue(node.property);
|
|
68
|
+
if (isNumericKey(value))
|
|
69
|
+
isWholeRead = true;
|
|
70
|
+
else
|
|
71
|
+
memberName = value;
|
|
52
72
|
}
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
else if (node.computed) {
|
|
74
|
+
isWholeRead = true;
|
|
75
|
+
}
|
|
76
|
+
for (const alias of aliases) {
|
|
77
|
+
const internalImport = s.internal.get(alias.filePath);
|
|
78
|
+
if (!internalImport)
|
|
79
|
+
continue;
|
|
80
|
+
if (isWholeRead) {
|
|
81
|
+
const origin = s.localImportMap.get(alias.id);
|
|
82
|
+
markWholeObjectRead(internalImport, origin?.importedName ?? alias.id);
|
|
83
|
+
}
|
|
84
|
+
else if (memberName) {
|
|
85
|
+
s.addNsMemberRefs(internalImport, alias.id, memberName);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (node.computed &&
|
|
91
|
+
node.object.type === 'MemberExpression' &&
|
|
92
|
+
!node.object.computed &&
|
|
93
|
+
node.object.object.type === 'Identifier' &&
|
|
94
|
+
node.object.property.type === 'Identifier') {
|
|
95
|
+
const rootName = node.object.object.name;
|
|
96
|
+
if (!isShadowed(rootName, node.object.object.start)) {
|
|
97
|
+
const _import = s.localImportMap.get(rootName);
|
|
98
|
+
if (_import?.isNamespace) {
|
|
99
|
+
const internalImport = s.internal.get(_import.filePath);
|
|
100
|
+
if (internalImport) {
|
|
101
|
+
const mid = node.object.property.name;
|
|
102
|
+
const value = isStringLiteral(node.property) ? getStringValue(node.property) : undefined;
|
|
103
|
+
if (value !== undefined && !isNumericKey(value))
|
|
104
|
+
s.addNsMemberRefs(internalImport, rootName, `${mid}.${value}`);
|
|
105
|
+
else
|
|
106
|
+
markWholeObjectRead(internalImport, mid);
|
|
59
107
|
}
|
|
60
108
|
}
|
|
61
109
|
}
|