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.
- package/README.md +1 -1
- package/dist/ConfigurationChief.d.ts +18 -0
- package/dist/WorkspaceWorker.js +1 -0
- package/dist/binaries/bash-parser.js +16 -39
- package/dist/binaries/resolvers/bun.js +1 -0
- package/dist/graph-explorer/operations/is-referenced.js +8 -2
- package/dist/manifest/index.js +2 -3
- package/dist/plugins/_component-style-urls/component-style-urls-visitor.d.ts +2 -0
- package/dist/plugins/_component-style-urls/component-style-urls-visitor.js +40 -0
- package/dist/plugins/angular/index.js +7 -1
- package/dist/plugins/biome/index.js +2 -2
- package/dist/plugins/commitlint/index.js +2 -2
- package/dist/plugins/eslint/helpers.js +1 -1
- package/dist/plugins/filesystem-routing/index.d.ts +3 -0
- package/dist/plugins/filesystem-routing/index.js +57 -0
- package/dist/plugins/github-actions/index.js +1 -1
- package/dist/plugins/index.d.ts +3 -0
- package/dist/plugins/index.js +6 -0
- package/dist/plugins/jest/index.js +5 -0
- package/dist/plugins/jest/visitors/mock.d.ts +2 -0
- package/dist/plugins/jest/visitors/mock.js +91 -0
- package/dist/plugins/mise/scripts.js +55 -97
- package/dist/plugins/next/index.js +33 -1
- package/dist/plugins/nx/index.js +46 -8
- package/dist/plugins/nx/types.d.ts +8 -0
- package/dist/plugins/oxlint/index.js +1 -1
- package/dist/plugins/react-router/index.d.ts +3 -0
- package/dist/plugins/react-router/index.js +3 -0
- package/dist/plugins/rstest/index.js +1 -1
- package/dist/plugins/solidjs-vite-plugin/index.d.ts +6 -0
- package/dist/plugins/solidjs-vite-plugin/index.js +17 -0
- package/dist/plugins/solidjs-vite-plugin/resolveFromAST.d.ts +3 -0
- package/dist/plugins/solidjs-vite-plugin/resolveFromAST.js +76 -0
- package/dist/plugins/sst/resolveFromAST.js +1 -1
- package/dist/plugins/stencil/index.js +2 -39
- package/dist/plugins/storybook/index.js +2 -4
- package/dist/plugins/sveltejs-package/helpers.js +2 -2
- package/dist/plugins/taskfile/index.js +3 -6
- package/dist/plugins/tsrs/index.d.ts +3 -0
- package/dist/plugins/tsrs/index.js +15 -0
- package/dist/plugins/typescript/index.d.ts +12 -1
- package/dist/plugins/typescript/index.js +5 -7
- package/dist/plugins/vite/helpers.d.ts +1 -0
- package/dist/plugins/vite/helpers.js +15 -1
- package/dist/plugins/vitest/index.js +2 -2
- package/dist/schema/configuration.d.ts +45 -0
- package/dist/schema/plugins.d.ts +15 -0
- package/dist/schema/plugins.js +3 -0
- package/dist/types/PluginNames.d.ts +2 -2
- package/dist/types/PluginNames.js +3 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/typescript/visitors/imports.js +11 -0
- package/dist/typescript/visitors/jsdoc.js +27 -22
- package/dist/util/create-options.d.ts +30 -0
- package/dist/util/create-options.js +2 -3
- package/dist/util/path.d.ts +1 -0
- package/dist/util/path.js +1 -0
- package/dist/util/scripts.d.ts +3 -2
- package/dist/util/scripts.js +32 -72
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -5
- package/schema.json +12 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parse } from 'unbash';
|
|
1
|
+
import { forEachChild, parse } from 'unbash';
|
|
2
2
|
import { getDependenciesFromCommand, getInputsFromNodeOptions } from '../../binaries/command.js';
|
|
3
3
|
import { spawningBinaries } from '../../binaries/fallback.js';
|
|
4
4
|
import { isWrapper } from '../../binaries/plugins.js';
|
|
@@ -7,121 +7,79 @@ import { toScript } from '../../binaries/util.js';
|
|
|
7
7
|
import { SCRIPT_INTERPOLATION } from '../../constants.js';
|
|
8
8
|
import { isBinary } from '../../util/input.js';
|
|
9
9
|
import { extractBinary, isRelativeNodeModulesBin } from '../../util/modules.js';
|
|
10
|
-
import {
|
|
10
|
+
import { isScriptExpansion, collectCommands } from '../../util/scripts.js';
|
|
11
11
|
export const getInputsFromMiseScript = (script, options, hasLocalBinPath) => {
|
|
12
12
|
const inputs = [];
|
|
13
13
|
const definedFunctions = new Set();
|
|
14
|
-
const
|
|
14
|
+
const readCommand = (command, source) => {
|
|
15
15
|
let text = '';
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
readScript(part.script);
|
|
22
|
-
text += SCRIPT_INTERPOLATION;
|
|
23
|
-
value += SCRIPT_INTERPOLATION;
|
|
24
|
-
hasExpansion = true;
|
|
16
|
+
let cursor = command.pos;
|
|
17
|
+
const visit = (node) => {
|
|
18
|
+
if (!isScriptExpansion(node)) {
|
|
19
|
+
forEachChild(node, visit);
|
|
20
|
+
return;
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
hasExpansion = true;
|
|
22
|
+
if (node.script)
|
|
23
|
+
readScript(node.script, node.script.source ?? source);
|
|
24
|
+
if (node.pos >= cursor && node.end <= command.end) {
|
|
25
|
+
text += source.slice(cursor, node.pos) + SCRIPT_INTERPOLATION;
|
|
26
|
+
cursor = node.end;
|
|
32
27
|
}
|
|
33
|
-
else {
|
|
34
|
-
text += part.text;
|
|
35
|
-
value += 'value' in part ? part.value : part.text;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return { text, value, hasExpansion };
|
|
39
|
-
};
|
|
40
|
-
const readWord = (word) => {
|
|
41
|
-
if (!word.parts)
|
|
42
|
-
return word;
|
|
43
|
-
const { text, value, hasExpansion } = readParts(word.parts);
|
|
44
|
-
return hasExpansion ? { type: 'Word', pos: word.pos, end: word.end, text, value } : word;
|
|
45
|
-
};
|
|
46
|
-
const readAssignment = (assignment) => {
|
|
47
|
-
const original = assignment.value;
|
|
48
|
-
const value = original.type === 'Word'
|
|
49
|
-
? readWord(original)
|
|
50
|
-
: { type: 'ArrayValue', pos: original.pos, end: original.end, elements: original.elements.map(readWord) };
|
|
51
|
-
if (value === original)
|
|
52
|
-
return assignment;
|
|
53
|
-
const text = value.type === 'Word' ? value.text : `(${value.elements.map(word => word.text).join(' ')})`;
|
|
54
|
-
return {
|
|
55
|
-
type: 'Assignment',
|
|
56
|
-
pos: assignment.pos,
|
|
57
|
-
end: assignment.end,
|
|
58
|
-
name: assignment.name,
|
|
59
|
-
index: assignment.index,
|
|
60
|
-
append: assignment.append,
|
|
61
|
-
value,
|
|
62
|
-
text: assignment.text.slice(0, original.pos - assignment.pos) + text,
|
|
63
28
|
};
|
|
29
|
+
forEachChild(command, visit);
|
|
30
|
+
return text + source.slice(cursor, command.end);
|
|
64
31
|
};
|
|
65
|
-
const readScript = (parsed) => {
|
|
32
|
+
const readScript = (parsed, source) => {
|
|
66
33
|
for (const statement of parsed.commands) {
|
|
67
34
|
if (statement.command.type === 'Function')
|
|
68
35
|
definedFunctions.add(statement.command.name.value);
|
|
69
36
|
}
|
|
70
|
-
for (const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
37
|
+
for (const command of collectCommands(parsed)) {
|
|
38
|
+
const text = readCommand(command, source);
|
|
39
|
+
const name = command.name?.value;
|
|
40
|
+
if (!name || definedFunctions.has(name))
|
|
41
|
+
continue;
|
|
42
|
+
const binary = extractBinary(name);
|
|
43
|
+
const isPackageCommand = isPackageManager(binary);
|
|
44
|
+
const isExplicit = isPackageCommand || name.startsWith('./') || isRelativeNodeModulesBin(name);
|
|
45
|
+
const hasPath = command.prefix.some(item => item.type === 'Assignment' && item.name === 'PATH');
|
|
46
|
+
const isLocal = hasLocalBinPath && !hasPath;
|
|
47
|
+
const isWrapperCommand = !isPackageCommand && isWrapper(binary);
|
|
48
|
+
if (!isExplicit && !isLocal && !isWrapperCommand && binary !== 'node' && binary !== 'find')
|
|
49
|
+
continue;
|
|
50
|
+
let commandInputs;
|
|
51
|
+
if (isWrapperCommand || binary === 'find') {
|
|
52
|
+
const [marked] = collectCommands(parse(text));
|
|
53
|
+
if (!marked)
|
|
85
54
|
continue;
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
55
|
+
const fromScript = (script) => {
|
|
56
|
+
inputs.push(...getInputsFromMiseScript(script, options, isLocal));
|
|
57
|
+
return [];
|
|
58
|
+
};
|
|
59
|
+
const fromArgs = args => fromScript(toScript(args));
|
|
60
|
+
commandInputs = getDependenciesFromCommand(marked, { ...options, fromArgs });
|
|
61
|
+
if (spawningBinaries.includes(binary))
|
|
62
|
+
commandInputs.push(...getInputsFromNodeOptions(marked.prefix));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
commandInputs = options.getInputsFromScripts(text, { cwd: options.cwd, manifest: options.manifest });
|
|
66
|
+
}
|
|
67
|
+
if (!isExplicit && !isLocal && binary !== 'node' && binary !== 'find')
|
|
68
|
+
continue;
|
|
69
|
+
const binaryInput = commandInputs.find(input => isBinary(input) && input.specifier === binary);
|
|
70
|
+
if (!isExplicit && isLocal && binaryInput)
|
|
71
|
+
binaryInput.optional = true;
|
|
72
|
+
for (const input of commandInputs) {
|
|
73
|
+
if (!input.specifier || input.specifier.includes(SCRIPT_INTERPOLATION))
|
|
92
74
|
continue;
|
|
93
|
-
|
|
94
|
-
if (isWrapperCommand || binary === 'find') {
|
|
95
|
-
const fromScript = (script) => {
|
|
96
|
-
inputs.push(...getInputsFromMiseScript(script, options, isLocal));
|
|
97
|
-
return [];
|
|
98
|
-
};
|
|
99
|
-
const fromArgs = args => fromScript(toScript(args));
|
|
100
|
-
commandInputs = getDependenciesFromCommand({ name: word, prefix, args: words }, { ...options, fromArgs });
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
commandInputs = options.getInputsFromScripts([...prefix.map(assignment => assignment.text), word.text, ...words.map(word => word.text)].join(' '), { cwd: options.cwd, manifest: options.manifest });
|
|
104
|
-
}
|
|
105
|
-
if (!isExplicit && !isLocal && binary !== 'node' && binary !== 'find')
|
|
75
|
+
if (!isExplicit && !isLocal && input === binaryInput)
|
|
106
76
|
continue;
|
|
107
|
-
|
|
108
|
-
commandInputs.push(...getInputsFromNodeOptions(prefix));
|
|
109
|
-
}
|
|
110
|
-
const binaryInput = commandInputs.find(input => isBinary(input) && input.specifier === binary);
|
|
111
|
-
if (!isExplicit && isLocal && binaryInput)
|
|
112
|
-
binaryInput.optional = true;
|
|
113
|
-
for (const input of commandInputs) {
|
|
114
|
-
if (!input.specifier || input.specifier.includes(SCRIPT_INTERPOLATION))
|
|
115
|
-
continue;
|
|
116
|
-
if (!isExplicit && !isLocal && input === binaryInput)
|
|
117
|
-
continue;
|
|
118
|
-
inputs.push(input);
|
|
119
|
-
}
|
|
77
|
+
inputs.push(input);
|
|
120
78
|
}
|
|
121
79
|
}
|
|
122
80
|
};
|
|
123
81
|
try {
|
|
124
|
-
readScript(parse(script));
|
|
82
|
+
readScript(parse(script), script);
|
|
125
83
|
}
|
|
126
84
|
catch {
|
|
127
85
|
return [];
|
|
@@ -42,6 +42,28 @@ const production = getEntryFilePatterns();
|
|
|
42
42
|
const resolveFromAST = (program, { configFileDir }) => {
|
|
43
43
|
const pageExtensions = new Set();
|
|
44
44
|
const loaders = new Set();
|
|
45
|
+
const aliasTargets = new Set();
|
|
46
|
+
const collectAliasTargets = (node) => {
|
|
47
|
+
const target = getStringValue(node);
|
|
48
|
+
if (target)
|
|
49
|
+
aliasTargets.add(target);
|
|
50
|
+
else if (node?.type === 'ArrayExpression') {
|
|
51
|
+
for (const element of node.elements)
|
|
52
|
+
collectAliasTargets(element);
|
|
53
|
+
}
|
|
54
|
+
else if (node?.type === 'ObjectExpression') {
|
|
55
|
+
collectAliasTargets(findProperty(node, 'browser'));
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const collectTurbopackAliases = (node) => {
|
|
59
|
+
const aliases = findProperty(node, 'resolveAlias');
|
|
60
|
+
if (aliases?.type !== 'ObjectExpression')
|
|
61
|
+
return;
|
|
62
|
+
for (const alias of aliases.properties) {
|
|
63
|
+
if (alias.type === 'Property')
|
|
64
|
+
collectAliasTargets(alias.value);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
45
67
|
const collectLoaders = (node) => {
|
|
46
68
|
if (node?.type === 'ArrayExpression') {
|
|
47
69
|
for (const element of node.elements)
|
|
@@ -60,7 +82,15 @@ const resolveFromAST = (program, { configFileDir }) => {
|
|
|
60
82
|
ObjectExpression(node) {
|
|
61
83
|
for (const extension of getPropertyValues(node, 'pageExtensions'))
|
|
62
84
|
pageExtensions.add(extension);
|
|
63
|
-
const
|
|
85
|
+
const turbopack = findProperty(node, 'turbopack');
|
|
86
|
+
if (turbopack?.type === 'ConditionalExpression') {
|
|
87
|
+
collectTurbopackAliases(turbopack.consequent);
|
|
88
|
+
collectTurbopackAliases(turbopack.alternate);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
collectTurbopackAliases(turbopack);
|
|
92
|
+
}
|
|
93
|
+
const rules = findProperty(turbopack, 'rules');
|
|
64
94
|
if (rules?.type !== 'ObjectExpression')
|
|
65
95
|
return;
|
|
66
96
|
for (const rule of rules.properties) {
|
|
@@ -75,6 +105,8 @@ const resolveFromAST = (program, { configFileDir }) => {
|
|
|
75
105
|
const inputs = patterns.map(id => toProductionEntry(join(configFileDir, id)));
|
|
76
106
|
for (const loader of loaders)
|
|
77
107
|
inputs.push(toDeferResolve(loader));
|
|
108
|
+
for (const target of aliasTargets)
|
|
109
|
+
inputs.push({ ...toDeferResolve(target, { dir: configFileDir }), production: true });
|
|
78
110
|
return inputs;
|
|
79
111
|
};
|
|
80
112
|
const commands = new Set(['dev', 'build', 'start']);
|
package/dist/plugins/nx/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { compact } from '../../util/array.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { isFile, loadJSON } from '../../util/fs.js';
|
|
3
|
+
import { toConfig, toDeferResolveEntry, toDependency } from '../../util/input.js';
|
|
4
|
+
import { get } from '../../util/object.js';
|
|
5
|
+
import { dirname, join, relative } from '../../util/path.js';
|
|
4
6
|
import { hasDependency } from '../../util/plugin.js';
|
|
5
7
|
import { substringBefore } from '../../util/string.js';
|
|
6
8
|
const title = 'Nx';
|
|
@@ -57,32 +59,67 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
57
59
|
const expandRelative = (command) => command
|
|
58
60
|
.replaceAll('{projectRoot}', relative(cwd, options.configFileDir))
|
|
59
61
|
.replaceAll('{workspaceRoot}', relative(cwd, options.rootCwd));
|
|
60
|
-
|
|
62
|
+
const scriptInputs = options.getInputsFromScripts(commands.map(expandRelative), { cwd });
|
|
63
|
+
for (const input of scriptInputs)
|
|
64
|
+
input.dir ??= cwd;
|
|
65
|
+
return scriptInputs;
|
|
61
66
|
});
|
|
67
|
+
const toTargetConfig = (pluginName, specifier) => toConfig(pluginName, expand(specifier), { dir: options.rootCwd });
|
|
62
68
|
const configInputs = targets.flatMap(target => {
|
|
63
69
|
const opts = target.options;
|
|
64
70
|
if (!opts)
|
|
65
71
|
return [];
|
|
66
72
|
const configs = [];
|
|
67
73
|
if ('eslintConfig' in opts && typeof opts.eslintConfig === 'string') {
|
|
68
|
-
configs.push(
|
|
74
|
+
configs.push(toTargetConfig('eslint', opts.eslintConfig));
|
|
69
75
|
}
|
|
70
76
|
if ('jestConfig' in opts && typeof opts.jestConfig === 'string') {
|
|
71
|
-
configs.push(
|
|
77
|
+
configs.push(toTargetConfig('jest', opts.jestConfig));
|
|
78
|
+
}
|
|
79
|
+
if ('karmaConfig' in opts && typeof opts.karmaConfig === 'string') {
|
|
80
|
+
configs.push(toTargetConfig('karma', opts.karmaConfig));
|
|
72
81
|
}
|
|
73
82
|
if ('tsConfig' in opts && typeof opts.tsConfig === 'string') {
|
|
74
|
-
configs.push(
|
|
83
|
+
configs.push(toTargetConfig('typescript', opts.tsConfig));
|
|
75
84
|
}
|
|
76
85
|
if ('vitestConfig' in opts && typeof opts.vitestConfig === 'string') {
|
|
77
|
-
configs.push(
|
|
86
|
+
configs.push(toTargetConfig('vitest', opts.vitestConfig));
|
|
78
87
|
}
|
|
79
88
|
if ('webpackConfig' in opts && typeof opts.webpackConfig === 'string') {
|
|
80
|
-
configs.push(
|
|
89
|
+
configs.push(toTargetConfig('webpack', opts.webpackConfig));
|
|
81
90
|
}
|
|
82
91
|
return configs;
|
|
83
92
|
});
|
|
84
93
|
return compact([...executors, ...inputs, ...configInputs]).map(id => typeof id === 'string' ? toDependency(id) : id);
|
|
85
94
|
};
|
|
95
|
+
const collections = [
|
|
96
|
+
['generators', 'schematics'],
|
|
97
|
+
['executors', 'builders'],
|
|
98
|
+
];
|
|
99
|
+
const resolve = async (options) => {
|
|
100
|
+
const inputs = [];
|
|
101
|
+
for (const [key, alias] of collections) {
|
|
102
|
+
const file = get(options.manifest, key) ?? get(options.manifest, alias);
|
|
103
|
+
if (typeof file !== 'string')
|
|
104
|
+
continue;
|
|
105
|
+
const filePath = join(options.cwd, file);
|
|
106
|
+
if (!isFile(filePath))
|
|
107
|
+
continue;
|
|
108
|
+
const collection = await loadJSON(filePath);
|
|
109
|
+
for (const entries of [collection[key], collection[alias]]) {
|
|
110
|
+
for (const entry of Object.values(entries ?? {})) {
|
|
111
|
+
if (!entry || typeof entry !== 'object')
|
|
112
|
+
continue;
|
|
113
|
+
for (const id of [entry.implementation || entry.factory, entry.batchImplementation]) {
|
|
114
|
+
if (typeof id === 'string' && id.length > 0) {
|
|
115
|
+
inputs.push(toDeferResolveEntry(join(dirname(filePath), substringBefore(id, '#'))));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return inputs;
|
|
122
|
+
};
|
|
86
123
|
const args = {
|
|
87
124
|
fromArgs: (parsed) => (parsed._[0] === 'exec' ? [...parsed._.slice(1), ...(parsed['--'] ?? [])] : []),
|
|
88
125
|
};
|
|
@@ -95,6 +132,7 @@ const plugin = {
|
|
|
95
132
|
isEnabled,
|
|
96
133
|
config,
|
|
97
134
|
resolveConfig,
|
|
135
|
+
resolve,
|
|
98
136
|
args,
|
|
99
137
|
};
|
|
100
138
|
export default plugin;
|
|
@@ -11,6 +11,7 @@ export interface NxProjectConfiguration {
|
|
|
11
11
|
cwd?: string;
|
|
12
12
|
eslintConfig?: string;
|
|
13
13
|
jestConfig?: string;
|
|
14
|
+
karmaConfig?: string;
|
|
14
15
|
tsConfig?: string;
|
|
15
16
|
vitestConfig?: string;
|
|
16
17
|
webpackConfig?: string;
|
|
@@ -18,6 +19,12 @@ export interface NxProjectConfiguration {
|
|
|
18
19
|
};
|
|
19
20
|
};
|
|
20
21
|
}
|
|
22
|
+
type NxCollectionEntry = string | {
|
|
23
|
+
factory?: string;
|
|
24
|
+
implementation?: string;
|
|
25
|
+
batchImplementation?: string;
|
|
26
|
+
};
|
|
27
|
+
export type NxCollection = Record<string, Record<string, NxCollectionEntry> | undefined>;
|
|
21
28
|
export interface NxConfigRoot {
|
|
22
29
|
plugins?: Array<string | {
|
|
23
30
|
plugin: string;
|
|
@@ -25,3 +32,4 @@ export interface NxConfigRoot {
|
|
|
25
32
|
generators?: Record<string, unknown>;
|
|
26
33
|
targetDefaults?: Record<string, unknown>;
|
|
27
34
|
}
|
|
35
|
+
export {};
|
|
@@ -26,7 +26,7 @@ export const resolveExtendedConfig = (config, configFilePath) => {
|
|
|
26
26
|
for (const entry of config.extends ?? []) {
|
|
27
27
|
if (typeof entry === 'string') {
|
|
28
28
|
const filePath = toAbsolute(entry, dirname(configFilePath));
|
|
29
|
-
inputs.push(toConfig('oxlint', filePath
|
|
29
|
+
inputs.push(toConfig('oxlint', filePath));
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
32
|
for (const input of resolveExtendedConfig(entry, configFilePath))
|
|
@@ -43,6 +43,9 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
43
43
|
}
|
|
44
44
|
return resolved;
|
|
45
45
|
};
|
|
46
|
+
const note = `Route modules import their types from \`./+types/<route>\`, which \`react-router typegen\` generates.
|
|
47
|
+
Run \`react-router typegen\` before Knip (e.g. in CI or a fresh checkout), or these imports are reported as unresolved.`;
|
|
48
|
+
export const docs = { note };
|
|
46
49
|
const plugin = {
|
|
47
50
|
title,
|
|
48
51
|
enablers,
|
|
@@ -91,7 +91,7 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
91
91
|
.catch(() => undefined)
|
|
92
92
|
: undefined;
|
|
93
93
|
if (!project) {
|
|
94
|
-
inputs.push(toConfig('rstest', filePath
|
|
94
|
+
inputs.push(toConfig('rstest', filePath));
|
|
95
95
|
continue;
|
|
96
96
|
}
|
|
97
97
|
inputs.push(toEntry(filePath));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { hasDependency } from '../../util/plugin.js';
|
|
2
|
+
import { config } from '../vite/index.js';
|
|
3
|
+
import { production, resolveFromAST } from './resolveFromAST.js';
|
|
4
|
+
const title = '@solidjs/vite-plugin';
|
|
5
|
+
const enablers = ['@solidjs/vite-plugin'];
|
|
6
|
+
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
7
|
+
const note = `Without a Vite config, the default entry patterns are used. With a config, start entries are only added when \`start\` is enabled. Paths like \`start.app\` replace the matching default, and the \`ssr\` option decides which files Solid loads. \`serverFunctions.configure\` is added with or without \`start\`.`;
|
|
8
|
+
export const docs = { note };
|
|
9
|
+
const plugin = {
|
|
10
|
+
title,
|
|
11
|
+
enablers,
|
|
12
|
+
isEnabled,
|
|
13
|
+
config,
|
|
14
|
+
production,
|
|
15
|
+
resolveFromAST,
|
|
16
|
+
};
|
|
17
|
+
export default plugin;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { findImportedCalls, findProperty } from '../../typescript/ast-helpers.js';
|
|
2
|
+
import { getStringValue } from '../../typescript/ast-nodes.js';
|
|
3
|
+
import { isFile } from '../../util/fs.js';
|
|
4
|
+
import { toProductionEntry } from '../../util/input.js';
|
|
5
|
+
import { join, toAbsolute } from '../../util/path.js';
|
|
6
|
+
import { getViteRoot } from '../vite/helpers.js';
|
|
7
|
+
const entryExtensions = ['tsx', 'jsx', 'ts', 'js', 'mjs', 'tsrx'];
|
|
8
|
+
const entryStems = {
|
|
9
|
+
entryServer: 'src/entry-server',
|
|
10
|
+
entryClient: 'src/entry-client',
|
|
11
|
+
};
|
|
12
|
+
const conventions = {
|
|
13
|
+
entryServer: `src/entry-server.{${entryExtensions.join(',')}}`,
|
|
14
|
+
entryClient: `src/entry-client.{${entryExtensions.join(',')}}`,
|
|
15
|
+
app: 'src/{App,app}.{tsx,jsx,ts,js,tsrx}',
|
|
16
|
+
document: 'src/Document.{tsx,jsx,tsrx}',
|
|
17
|
+
env: 'env.{ts,js}',
|
|
18
|
+
};
|
|
19
|
+
export const production = Object.values(conventions);
|
|
20
|
+
const startOptions = ['app', 'document', 'entryServer', 'entryClient', 'middleware', 'instrument', 'setup', 'env'];
|
|
21
|
+
const isBoolean = (node, value) => node?.type === 'Literal' && node.value === value;
|
|
22
|
+
const hasEntryFile = (root, stem) => {
|
|
23
|
+
for (const extension of entryExtensions)
|
|
24
|
+
if (isFile(root, `${stem}.${extension}`))
|
|
25
|
+
return true;
|
|
26
|
+
return false;
|
|
27
|
+
};
|
|
28
|
+
export const resolveFromAST = (program, options) => {
|
|
29
|
+
const root = getViteRoot(program, options.cwd);
|
|
30
|
+
const patterns = new Set();
|
|
31
|
+
const paths = new Set();
|
|
32
|
+
for (const call of findImportedCalls(program, '@solidjs/vite-plugin')) {
|
|
33
|
+
const arg = call.arguments[0];
|
|
34
|
+
if (arg?.type !== 'ObjectExpression')
|
|
35
|
+
continue;
|
|
36
|
+
const configure = getStringValue(findProperty(findProperty(arg, 'serverFunctions'), 'configure'));
|
|
37
|
+
if (configure)
|
|
38
|
+
paths.add(configure);
|
|
39
|
+
const start = findProperty(arg, 'start');
|
|
40
|
+
if (!start || isBoolean(start, false))
|
|
41
|
+
continue;
|
|
42
|
+
const values = {};
|
|
43
|
+
for (const name of startOptions) {
|
|
44
|
+
values[name] = start.type === 'ObjectExpression' ? findProperty(start, name) : undefined;
|
|
45
|
+
}
|
|
46
|
+
const isAuthored = (name) => Boolean(getStringValue(values[name])) || hasEntryFile(root, entryStems[name]);
|
|
47
|
+
const ssr = findProperty(arg, 'ssr');
|
|
48
|
+
const skip = new Set();
|
|
49
|
+
if (!ssr || isBoolean(ssr, false)) {
|
|
50
|
+
skip.add('entryServer');
|
|
51
|
+
skip.add('setup');
|
|
52
|
+
if (isAuthored('entryClient'))
|
|
53
|
+
skip.add('app');
|
|
54
|
+
}
|
|
55
|
+
else if (isBoolean(ssr, true) && isAuthored('entryServer') && isAuthored('entryClient')) {
|
|
56
|
+
skip.add('app');
|
|
57
|
+
skip.add('document');
|
|
58
|
+
}
|
|
59
|
+
for (const name of startOptions) {
|
|
60
|
+
if (skip.has(name))
|
|
61
|
+
continue;
|
|
62
|
+
const value = values[name];
|
|
63
|
+
const path = getStringValue(value);
|
|
64
|
+
if (path)
|
|
65
|
+
paths.add(path);
|
|
66
|
+
else if (name in conventions && !(name === 'env' && isBoolean(value, false)))
|
|
67
|
+
patterns.add(conventions[name]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const inputs = [];
|
|
71
|
+
for (const pattern of patterns)
|
|
72
|
+
inputs.push(toProductionEntry(join(root, pattern)));
|
|
73
|
+
for (const id of paths)
|
|
74
|
+
inputs.push(toProductionEntry(toAbsolute(id, root)));
|
|
75
|
+
return inputs;
|
|
76
|
+
};
|
|
@@ -44,5 +44,5 @@ export const resolveFromAST = (program, options) => {
|
|
|
44
44
|
visitor.visit(program);
|
|
45
45
|
}
|
|
46
46
|
catch { }
|
|
47
|
-
return Array.from(entries).map(specifier => toDeferResolveProductionEntry(specifier
|
|
47
|
+
return Array.from(entries).map(specifier => toDeferResolveProductionEntry(specifier));
|
|
48
48
|
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import scss from '../../compilers/scss.js';
|
|
2
|
-
import { IMPORT_FLAGS } from '../../constants.js';
|
|
3
|
-
import { getPropertyValues } from '../../typescript/ast-helpers.js';
|
|
4
|
-
import { dirname, join } from '../../util/path.js';
|
|
5
2
|
import { hasDependency } from '../../util/plugin.js';
|
|
3
|
+
import { createComponentStyleUrlsVisitor } from '../_component-style-urls/component-style-urls-visitor.js';
|
|
6
4
|
import { createCustomElementVisitor } from '../_custom-elements/custom-element-visitor.js';
|
|
7
5
|
import { entry, resolveFromAST } from './resolveFromAST.js';
|
|
8
6
|
const title = 'Stencil';
|
|
@@ -18,42 +16,7 @@ const registerCompilers = ({ hasDependency, registerCompiler }) => {
|
|
|
18
16
|
};
|
|
19
17
|
const registerVisitors = ({ ctx, registerVisitor }) => {
|
|
20
18
|
registerVisitor(createCustomElementVisitor(ctx, isStencilSpecifier, { decoratorName: 'Component' }));
|
|
21
|
-
|
|
22
|
-
registerVisitor({
|
|
23
|
-
Program() {
|
|
24
|
-
componentNames.clear();
|
|
25
|
-
},
|
|
26
|
-
ImportDeclaration(node) {
|
|
27
|
-
if (!isStencilSpecifier(node.source?.value))
|
|
28
|
-
return;
|
|
29
|
-
for (const spec of node.specifiers ?? []) {
|
|
30
|
-
if (spec.type === 'ImportSpecifier' &&
|
|
31
|
-
spec.imported.type === 'Identifier' &&
|
|
32
|
-
spec.imported.name === 'Component')
|
|
33
|
-
componentNames.add(spec.local.name);
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
ClassDeclaration(node) {
|
|
37
|
-
resolveStyleUrls(node);
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
function resolveStyleUrls(node) {
|
|
41
|
-
const dir = dirname(ctx.filePath);
|
|
42
|
-
for (const decorator of node.decorators ?? []) {
|
|
43
|
-
const expr = decorator.expression;
|
|
44
|
-
if (expr?.type !== 'CallExpression')
|
|
45
|
-
continue;
|
|
46
|
-
if (expr.callee?.type !== 'Identifier' || !componentNames.has(expr.callee.name))
|
|
47
|
-
continue;
|
|
48
|
-
const arg = expr.arguments?.[0];
|
|
49
|
-
if (arg?.type !== 'ObjectExpression')
|
|
50
|
-
continue;
|
|
51
|
-
for (const url of getPropertyValues(arg, 'styleUrl'))
|
|
52
|
-
ctx.addImport(join(dir, url), arg.start, IMPORT_FLAGS.NONE);
|
|
53
|
-
for (const url of getPropertyValues(arg, 'styleUrls'))
|
|
54
|
-
ctx.addImport(join(dir, url), arg.start, IMPORT_FLAGS.NONE);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
19
|
+
registerVisitor(createComponentStyleUrlsVisitor(ctx, isStencilSpecifier));
|
|
57
20
|
};
|
|
58
21
|
const plugin = {
|
|
59
22
|
title,
|
|
@@ -12,7 +12,7 @@ const restEntry = ['.{storybook,rnstorybook}/{manager,preview,index,vitest.setup
|
|
|
12
12
|
const entry = [...restEntry, ...stories];
|
|
13
13
|
const project = ['.{storybook,rnstorybook}/**/*.{js,jsx,ts,tsx,mts}'];
|
|
14
14
|
const resolveConfig = async (localConfig, options) => {
|
|
15
|
-
const { cwd, configFileDir
|
|
15
|
+
const { cwd, configFileDir } = options;
|
|
16
16
|
const strs = typeof localConfig?.stories === 'function' ? await localConfig.stories(stories) : localConfig?.stories;
|
|
17
17
|
const relativePatterns = strs?.map(pattern => {
|
|
18
18
|
if (typeof pattern === 'string')
|
|
@@ -37,9 +37,7 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
37
37
|
const viteConfigPath = typeof framework === 'object' &&
|
|
38
38
|
framework?.name === '@storybook/react-vite' &&
|
|
39
39
|
framework?.options?.builder?.viteConfigPath;
|
|
40
|
-
const configs = viteConfigPath
|
|
41
|
-
? [toConfig('vite', viteConfigPath, { dir: cwd, containingFilePath: configFilePath })]
|
|
42
|
-
: [];
|
|
40
|
+
const configs = viteConfigPath ? [toConfig('vite', viteConfigPath, { dir: cwd })] : [];
|
|
43
41
|
const hasVitestAddon = addons.some(addon => addon === '@storybook/addon-vitest');
|
|
44
42
|
const coverageDeps = hasVitestAddon
|
|
45
43
|
? [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import parseArgs from '../../util/parse-args.js';
|
|
2
2
|
import { parse } from 'unbash';
|
|
3
|
-
import { getCommandWords,
|
|
3
|
+
import { getCommandWords, collectCommands } from '../../util/scripts.js';
|
|
4
4
|
const BIN = 'svelte-package';
|
|
5
5
|
export const DEFAULT_INPUT = 'src/lib';
|
|
6
6
|
export const DEFAULT_OUTPUT = 'dist';
|
|
@@ -16,7 +16,7 @@ export const parseScripts = (scripts) => {
|
|
|
16
16
|
try {
|
|
17
17
|
const parsed = parse(script);
|
|
18
18
|
for (const statement of parsed.commands) {
|
|
19
|
-
for (const node of
|
|
19
|
+
for (const node of collectCommands(statement.command)) {
|
|
20
20
|
if (node.name?.value === BIN)
|
|
21
21
|
out.push(parseCommandIO(getCommandWords(node).map(word => word.value)));
|
|
22
22
|
}
|
|
@@ -78,7 +78,7 @@ const extractScriptsFromTask = (task) => {
|
|
|
78
78
|
const resolveConfig = async (localConfig, options) => {
|
|
79
79
|
if (!localConfig || !options.configFilePath)
|
|
80
80
|
return [];
|
|
81
|
-
const {
|
|
81
|
+
const { getInputsFromScripts, isProduction, configFileDir } = options;
|
|
82
82
|
const inputs = [];
|
|
83
83
|
if (localConfig.includes && typeof localConfig.includes === 'object') {
|
|
84
84
|
for (const includeValue of Object.values(localConfig.includes)) {
|
|
@@ -89,17 +89,14 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
89
89
|
: undefined;
|
|
90
90
|
if (includePath) {
|
|
91
91
|
const resolvedPath = join(configFileDir, includePath);
|
|
92
|
-
inputs.push(toConfig('taskfile', relative(configFileDir, resolvedPath)
|
|
92
|
+
inputs.push(toConfig('taskfile', relative(configFileDir, resolvedPath)));
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
if (localConfig.tasks && typeof localConfig.tasks === 'object') {
|
|
97
97
|
for (const task of Object.values(localConfig.tasks)) {
|
|
98
98
|
for (const script of extractScriptsFromTask(task)) {
|
|
99
|
-
for (const input of getInputsFromScripts([script], {
|
|
100
|
-
optionalBinaries: true,
|
|
101
|
-
containingFilePath: configFilePath,
|
|
102
|
-
})) {
|
|
99
|
+
for (const input of getInputsFromScripts([script], { optionalBinaries: true })) {
|
|
103
100
|
if (isProduction)
|
|
104
101
|
Object.assign(input, { optional: true });
|
|
105
102
|
inputs.push({ ...input, dir: configFileDir });
|