sadrazam 0.1.11 → 0.1.12
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/CHANGELOG.md +11 -0
- package/README.md +15 -0
- package/dist/cache.js +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/packageReader.d.ts +21 -0
- package/dist/packageReader.d.ts.map +1 -1
- package/dist/packageReader.js +1 -0
- package/dist/packageReader.js.map +1 -1
- package/dist/plugins.d.ts +18 -1
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +413 -153
- package/dist/plugins.js.map +1 -1
- package/dist/reporters.d.ts.map +1 -1
- package/dist/reporters.js +22 -0
- package/dist/reporters.js.map +1 -1
- package/dist/scan.d.ts +3 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +32 -2
- package/dist/scan.js.map +1 -1
- package/dist/scriptParser.d.ts.map +1 -1
- package/dist/scriptParser.js +2 -0
- package/dist/scriptParser.js.map +1 -1
- package/package.json +1 -1
package/dist/plugins.js
CHANGED
|
@@ -1,98 +1,76 @@
|
|
|
1
|
-
import { access } from "node:fs/promises";
|
|
1
|
+
import { access, readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import fg from "fast-glob";
|
|
3
4
|
const COMMAND_SPLIT_RE = /\s*(?:&&|\|\||;)\s*/;
|
|
4
5
|
const TOKEN_RE = /"[^"]*"|'[^']*'|`[^`]*`|[^\s]+/g;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
name,
|
|
8
|
-
supports(command) {
|
|
9
|
-
return commands.includes(command);
|
|
10
|
-
},
|
|
11
|
-
async resolve(tokens, packageDir) {
|
|
12
|
-
const fileEntries = new Set();
|
|
13
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
14
|
-
const token = stripQuotes(tokens[index] ?? "");
|
|
15
|
-
const next = stripQuotes(tokens[index + 1] ?? "");
|
|
16
|
-
if (!flags.includes(token) || !next) {
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
const configPath = path.resolve(packageDir, next);
|
|
20
|
-
if (await fileExists(configPath)) {
|
|
21
|
-
fileEntries.add(configPath);
|
|
22
|
-
}
|
|
23
|
-
index += 1;
|
|
24
|
-
}
|
|
25
|
-
return fileEntries.size > 0
|
|
26
|
-
? {
|
|
27
|
-
fileEntries: [...fileEntries],
|
|
28
|
-
}
|
|
29
|
-
: null;
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
6
|
+
const CONFIG_EXTENSIONS = "{js,cjs,mjs,ts,cts,mts,json,jsonc}";
|
|
7
|
+
const CONFIG_FLAG_ALIASES = ["--config", "-c"];
|
|
33
8
|
const PLUGINS = [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
9
|
+
createToolPlugin("vite", ["vite"], ["vite"], [`vite.config.${CONFIG_EXTENSIONS}`]),
|
|
10
|
+
createToolPlugin("vitest", ["vitest"], ["vitest"], [`vitest.config.${CONFIG_EXTENSIONS}`]),
|
|
11
|
+
createToolPlugin("jest", ["jest"], ["jest"], [
|
|
12
|
+
`jest.config.${CONFIG_EXTENSIONS}`,
|
|
13
|
+
"package.json",
|
|
14
|
+
]),
|
|
15
|
+
createToolPlugin("playwright", ["playwright"], ["@playwright/test", "playwright"], [
|
|
16
|
+
`playwright.config.${CONFIG_EXTENSIONS}`,
|
|
17
|
+
], ["tests/**", "e2e/**"]),
|
|
18
|
+
createToolPlugin("cypress", ["cypress"], ["cypress"], [
|
|
19
|
+
`cypress.config.${CONFIG_EXTENSIONS}`,
|
|
20
|
+
], ["cypress/**"]),
|
|
21
|
+
createToolPlugin("storybook", ["storybook", "start-storybook", "build-storybook"], ["storybook", "@storybook/cli"], [
|
|
22
|
+
".storybook/main.{js,cjs,mjs,ts,cts,mts}",
|
|
23
|
+
".storybook/preview.{js,cjs,mjs,ts,cts,mts}",
|
|
24
|
+
], [".storybook/**", "src/**/*.stories.{js,jsx,ts,tsx,mdx}"]),
|
|
25
|
+
createToolPlugin("next", ["next"], ["next"], [
|
|
26
|
+
"next.config.{js,cjs,mjs,ts}",
|
|
27
|
+
], ["pages/**/*.{js,jsx,ts,tsx}", "app/**/*.{js,jsx,ts,tsx}", "src/pages/**/*.{js,jsx,ts,tsx}", "src/app/**/*.{js,jsx,ts,tsx}"]),
|
|
28
|
+
createToolPlugin("astro", ["astro"], ["astro"], [
|
|
29
|
+
"astro.config.{js,cjs,mjs,ts}",
|
|
30
|
+
], ["src/pages/**/*.astro", "src/content/**/*.{md,mdx}"]),
|
|
31
|
+
createToolPlugin("sveltekit", ["svelte-kit"], ["@sveltejs/kit"], [
|
|
32
|
+
"svelte.config.{js,cjs,mjs,ts}",
|
|
33
|
+
"vite.config.{js,cjs,mjs,ts}",
|
|
34
|
+
], ["src/routes/**/*.{js,ts,svelte}", "src/hooks.{js,ts}"]),
|
|
35
|
+
createToolPlugin("webpack", ["webpack", "webpack-cli"], ["webpack", "webpack-cli"], [
|
|
36
|
+
`webpack.config.${CONFIG_EXTENSIONS}`,
|
|
37
|
+
]),
|
|
38
|
+
createToolPlugin("rollup", ["rollup"], ["rollup"], [
|
|
39
|
+
`rollup.config.${CONFIG_EXTENSIONS}`,
|
|
40
|
+
]),
|
|
37
41
|
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (token === "--plugin" && next) {
|
|
49
|
-
packages.add(next);
|
|
50
|
-
index += 1;
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
if (token === "--config" && next) {
|
|
54
|
-
const configPath = path.resolve(packageDir, next);
|
|
55
|
-
if (await fileExists(configPath)) {
|
|
56
|
-
fileEntries.add(configPath);
|
|
57
|
-
}
|
|
58
|
-
index += 1;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (packages.size === 0 && fileEntries.size === 0) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
packages: [...packages],
|
|
66
|
-
fileEntries: [...fileEntries],
|
|
67
|
-
};
|
|
68
|
-
},
|
|
42
|
+
...createToolPlugin("eslint", ["eslint"], ["eslint"], [
|
|
43
|
+
".eslintrc",
|
|
44
|
+
`.eslintrc.${CONFIG_EXTENSIONS}`,
|
|
45
|
+
`eslint.config.${CONFIG_EXTENSIONS}`,
|
|
46
|
+
]),
|
|
47
|
+
packageFlags: [
|
|
48
|
+
{ flag: "--parser" },
|
|
49
|
+
{ flag: "--plugin", normalize: normalizeEslintPlugin },
|
|
50
|
+
],
|
|
51
|
+
analyzeConfig: analyzeEslintConfig,
|
|
69
52
|
},
|
|
70
53
|
{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
? {
|
|
92
|
-
packages: [...packages],
|
|
93
|
-
}
|
|
94
|
-
: null;
|
|
95
|
-
},
|
|
54
|
+
...createToolPlugin("prettier", ["prettier"], ["prettier"], [
|
|
55
|
+
`.prettierrc.${CONFIG_EXTENSIONS}`,
|
|
56
|
+
"prettier.config.{js,cjs,mjs,ts,cts,mts}",
|
|
57
|
+
".prettierrc",
|
|
58
|
+
]),
|
|
59
|
+
packageFlags: [{ flag: "--plugin" }],
|
|
60
|
+
analyzePackageJson: analyzePrettierPackageJson,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
...createToolPlugin("tailwind", ["tailwindcss"], ["tailwindcss"], [
|
|
64
|
+
"tailwind.config.{js,cjs,mjs,ts}",
|
|
65
|
+
"postcss.config.{js,cjs,mjs,ts}",
|
|
66
|
+
]),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
...createToolPlugin("typescript", ["tsc", "tsserver"], ["typescript"], [
|
|
70
|
+
"tsconfig.json",
|
|
71
|
+
"tsconfig.*.json",
|
|
72
|
+
]),
|
|
73
|
+
analyzeConfig: analyzeTsConfig,
|
|
96
74
|
},
|
|
97
75
|
];
|
|
98
76
|
export async function analyzePlugins(context) {
|
|
@@ -100,63 +78,331 @@ export async function analyzePlugins(context) {
|
|
|
100
78
|
const commandPackages = new Set();
|
|
101
79
|
const fileEntries = new Set();
|
|
102
80
|
const commandUsage = new Map();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (!contribution) {
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
activePlugins.add(plugin.name);
|
|
123
|
-
for (const packageName of contribution.packages ?? []) {
|
|
124
|
-
commandPackages.add(packageName);
|
|
125
|
-
addUsage(commandUsage, packageName, `script:${scriptName}`);
|
|
126
|
-
}
|
|
127
|
-
for (const filePath of contribution.fileEntries ?? []) {
|
|
128
|
-
fileEntries.add(filePath);
|
|
129
|
-
}
|
|
130
|
-
for (const [packageName, sources] of Object.entries(contribution.packageUsage ?? {})) {
|
|
131
|
-
commandPackages.add(packageName);
|
|
132
|
-
for (const source of sources) {
|
|
133
|
-
addUsage(commandUsage, packageName, source);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
81
|
+
const details = [];
|
|
82
|
+
const scripts = collectScriptInvocations(context.scripts);
|
|
83
|
+
for (const plugin of PLUGINS) {
|
|
84
|
+
const override = context.config?.[plugin.name];
|
|
85
|
+
if (override === false) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const scriptInvocations = scripts.filter((script) => plugin.commands.includes(script.command));
|
|
89
|
+
const isForced = override === true || isPluginConfigObject(override);
|
|
90
|
+
const isDeclared = plugin.packages.some((packageName) => context.dependencyNames.has(packageName));
|
|
91
|
+
if (!isForced && !isDeclared && scriptInvocations.length === 0) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const contribution = await collectPluginContribution(plugin, context, scriptInvocations, override);
|
|
95
|
+
if (!hasContribution(contribution) && !isDeclared && !isForced) {
|
|
96
|
+
continue;
|
|
137
97
|
}
|
|
98
|
+
activePlugins.add(plugin.name);
|
|
99
|
+
mergeContribution(contribution, commandPackages, fileEntries, commandUsage);
|
|
100
|
+
details.push({
|
|
101
|
+
name: plugin.name,
|
|
102
|
+
activation: [
|
|
103
|
+
isDeclared ? "dependency" : null,
|
|
104
|
+
scriptInvocations.length > 0 ? "script" : null,
|
|
105
|
+
isForced ? "config" : null,
|
|
106
|
+
].filter((value) => Boolean(value)),
|
|
107
|
+
packages: contribution.packages ?? [],
|
|
108
|
+
fileEntries: contribution.fileEntries ?? [],
|
|
109
|
+
});
|
|
138
110
|
}
|
|
139
111
|
return {
|
|
140
112
|
activePlugins: [...activePlugins].sort(),
|
|
141
113
|
commandPackages: [...commandPackages].sort(),
|
|
142
114
|
fileEntries: [...fileEntries].sort(),
|
|
115
|
+
details: details.sort((left, right) => left.name.localeCompare(right.name)),
|
|
143
116
|
commandUsage: Object.fromEntries([...commandUsage.entries()]
|
|
144
117
|
.map(([packageName, sources]) => [packageName, [...sources].sort()])
|
|
145
118
|
.sort(([left], [right]) => left.localeCompare(right))),
|
|
146
119
|
};
|
|
147
120
|
}
|
|
121
|
+
export async function analyzePluginInputs(packageDir, config) {
|
|
122
|
+
const commandPackages = new Set();
|
|
123
|
+
const fileEntries = new Set();
|
|
124
|
+
const commandUsage = new Map();
|
|
125
|
+
for (const packageName of config?.packageNames ?? []) {
|
|
126
|
+
commandPackages.add(packageName);
|
|
127
|
+
addUsage(commandUsage, packageName, "config:inputs.packageNames");
|
|
128
|
+
}
|
|
129
|
+
for (const entry of config?.entryFiles ?? []) {
|
|
130
|
+
const filePath = path.resolve(packageDir, entry);
|
|
131
|
+
if (await fileExists(filePath)) {
|
|
132
|
+
fileEntries.add(filePath);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
activePlugins: commandPackages.size > 0 || fileEntries.size > 0 ? ["inputs"] : [],
|
|
137
|
+
commandPackages: [...commandPackages].sort(),
|
|
138
|
+
fileEntries: [...fileEntries].sort(),
|
|
139
|
+
details: commandPackages.size > 0 || fileEntries.size > 0
|
|
140
|
+
? [{
|
|
141
|
+
name: "inputs",
|
|
142
|
+
activation: ["config"],
|
|
143
|
+
packages: [...commandPackages].sort(),
|
|
144
|
+
fileEntries: [...fileEntries].sort(),
|
|
145
|
+
}]
|
|
146
|
+
: [],
|
|
147
|
+
commandUsage: Object.fromEntries([...commandUsage.entries()]
|
|
148
|
+
.map(([packageName, sources]) => [packageName, [...sources].sort()])
|
|
149
|
+
.sort(([left], [right]) => left.localeCompare(right))),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function createToolPlugin(name, commands, packages, configPatterns = [], entryPatterns = []) {
|
|
153
|
+
return {
|
|
154
|
+
name,
|
|
155
|
+
commands,
|
|
156
|
+
packages,
|
|
157
|
+
configPatterns,
|
|
158
|
+
entryPatterns,
|
|
159
|
+
configFlags: CONFIG_FLAG_ALIASES,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
async function collectPluginContribution(plugin, context, scriptInvocations, override) {
|
|
163
|
+
const packages = new Set();
|
|
164
|
+
const fileEntries = new Set();
|
|
165
|
+
const packageUsage = new Map();
|
|
166
|
+
for (const invocation of scriptInvocations) {
|
|
167
|
+
if (plugin.packages[0]) {
|
|
168
|
+
packages.add(plugin.packages[0]);
|
|
169
|
+
addUsage(packageUsage, plugin.packages[0], `script:${invocation.scriptName}`);
|
|
170
|
+
}
|
|
171
|
+
for (const packageName of collectPackagesFromFlags(invocation.tokens, plugin.packageFlags ?? [])) {
|
|
172
|
+
packages.add(packageName.name);
|
|
173
|
+
addUsage(packageUsage, packageName.name, `script:${invocation.scriptName}`);
|
|
174
|
+
}
|
|
175
|
+
for (const filePath of await collectFilesFromFlags(context.packageDir, invocation.tokens, plugin.configFlags ?? [])) {
|
|
176
|
+
fileEntries.add(filePath);
|
|
177
|
+
}
|
|
178
|
+
for (const filePath of await collectPositionalFiles(context.packageDir, invocation.tokens.slice(1))) {
|
|
179
|
+
fileEntries.add(filePath);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const configPatterns = isPluginConfigObject(override)
|
|
183
|
+
? toArray(override.config ?? plugin.configPatterns ?? [])
|
|
184
|
+
: plugin.configPatterns ?? [];
|
|
185
|
+
const entryPatterns = isPluginConfigObject(override)
|
|
186
|
+
? toArray(override.entry ?? plugin.entryPatterns ?? [])
|
|
187
|
+
: plugin.entryPatterns ?? [];
|
|
188
|
+
for (const filePath of await collectFilesFromPatterns(context.packageDir, configPatterns)) {
|
|
189
|
+
fileEntries.add(filePath);
|
|
190
|
+
const configContribution = plugin.analyzeConfig ? await plugin.analyzeConfig(filePath) : null;
|
|
191
|
+
mergeContribution(configContribution, packages, fileEntries, packageUsage);
|
|
192
|
+
}
|
|
193
|
+
for (const filePath of await collectFilesFromPatterns(context.packageDir, entryPatterns)) {
|
|
194
|
+
fileEntries.add(filePath);
|
|
195
|
+
}
|
|
196
|
+
mergeContribution(plugin.analyzePackageJson?.(context) ?? null, packages, fileEntries, packageUsage);
|
|
197
|
+
return {
|
|
198
|
+
packages: [...packages].sort(),
|
|
199
|
+
fileEntries: [...fileEntries].sort(),
|
|
200
|
+
packageUsage: Object.fromEntries([...packageUsage.entries()].map(([packageName, sources]) => [packageName, [...sources].sort()])),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function collectScriptInvocations(scripts) {
|
|
204
|
+
const invocations = [];
|
|
205
|
+
for (const [scriptName, script] of Object.entries(scripts)) {
|
|
206
|
+
for (const segment of script.split(COMMAND_SPLIT_RE)) {
|
|
207
|
+
const tokens = tokenize(segment);
|
|
208
|
+
const command = resolveCommandName(tokens);
|
|
209
|
+
if (command) {
|
|
210
|
+
invocations.push({ scriptName, command, tokens });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return invocations;
|
|
215
|
+
}
|
|
216
|
+
function collectPackagesFromFlags(tokens, flags) {
|
|
217
|
+
const packages = [];
|
|
218
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
219
|
+
const token = stripQuotes(tokens[index] ?? "");
|
|
220
|
+
const flag = flags.find((candidate) => candidate.flag === token);
|
|
221
|
+
const next = stripQuotes(tokens[index + 1] ?? "");
|
|
222
|
+
if (!flag || !next) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
packages.push({ name: flag.normalize ? flag.normalize(next) : next });
|
|
226
|
+
index += 1;
|
|
227
|
+
}
|
|
228
|
+
return packages;
|
|
229
|
+
}
|
|
230
|
+
async function collectFilesFromFlags(packageDir, tokens, flags) {
|
|
231
|
+
const fileEntries = new Set();
|
|
232
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
233
|
+
const token = stripQuotes(tokens[index] ?? "");
|
|
234
|
+
const next = stripQuotes(tokens[index + 1] ?? "");
|
|
235
|
+
if (!flags.includes(token) || !next) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
for (const filePath of await resolveEntryPattern(packageDir, next)) {
|
|
239
|
+
fileEntries.add(filePath);
|
|
240
|
+
}
|
|
241
|
+
index += 1;
|
|
242
|
+
}
|
|
243
|
+
return [...fileEntries];
|
|
244
|
+
}
|
|
245
|
+
async function collectPositionalFiles(packageDir, tokens) {
|
|
246
|
+
const entries = new Set();
|
|
247
|
+
for (const rawToken of tokens) {
|
|
248
|
+
const token = stripQuotes(rawToken);
|
|
249
|
+
if (!token || token.startsWith("-") || looksLikePackageSpecifier(token)) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
for (const filePath of await resolveEntryPattern(packageDir, token)) {
|
|
253
|
+
entries.add(filePath);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return [...entries];
|
|
257
|
+
}
|
|
258
|
+
async function collectFilesFromPatterns(packageDir, patterns) {
|
|
259
|
+
const entries = new Set();
|
|
260
|
+
for (const pattern of patterns) {
|
|
261
|
+
for (const filePath of await resolveEntryPattern(packageDir, pattern)) {
|
|
262
|
+
entries.add(filePath);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return [...entries];
|
|
266
|
+
}
|
|
267
|
+
async function resolveEntryPattern(packageDir, pattern) {
|
|
268
|
+
const cleanPattern = stripQuotes(pattern);
|
|
269
|
+
const absolutePath = path.resolve(packageDir, cleanPattern);
|
|
270
|
+
if (!hasGlobMagic(cleanPattern) && await fileExists(absolutePath)) {
|
|
271
|
+
return [absolutePath];
|
|
272
|
+
}
|
|
273
|
+
return fg(cleanPattern, {
|
|
274
|
+
cwd: packageDir,
|
|
275
|
+
absolute: true,
|
|
276
|
+
dot: true,
|
|
277
|
+
onlyFiles: true,
|
|
278
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.git/**"],
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async function analyzeEslintConfig(filePath) {
|
|
282
|
+
if (!filePath.endsWith(".json") && !filePath.endsWith(".eslintrc")) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
const config = await readJsonFile(filePath);
|
|
286
|
+
if (!isRecord(config)) {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
const packages = new Set();
|
|
290
|
+
for (const value of toArray(config.extends)) {
|
|
291
|
+
if (typeof value === "string" && !value.startsWith(".") && !path.isAbsolute(value)) {
|
|
292
|
+
packages.add(normalizeEslintConfig(value));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (typeof config.parser === "string") {
|
|
296
|
+
packages.add(config.parser);
|
|
297
|
+
}
|
|
298
|
+
for (const value of toArray(config.plugins)) {
|
|
299
|
+
if (typeof value === "string") {
|
|
300
|
+
packages.add(normalizeEslintPlugin(value));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return packages.size > 0 ? { packages: [...packages] } : null;
|
|
304
|
+
}
|
|
305
|
+
function analyzePrettierPackageJson(context) {
|
|
306
|
+
const prettierConfig = context.packageJson.prettier;
|
|
307
|
+
if (!prettierConfig) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
if (typeof prettierConfig === "string") {
|
|
311
|
+
return {
|
|
312
|
+
fileEntries: [path.resolve(context.packageDir, prettierConfig)],
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
packages: [...new Set(prettierConfig.plugins ?? [])],
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
async function analyzeTsConfig(filePath) {
|
|
320
|
+
const config = await readJsonFile(filePath);
|
|
321
|
+
if (!isRecord(config)) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
const fileEntries = new Set();
|
|
325
|
+
const packages = new Set();
|
|
326
|
+
const baseDir = path.dirname(filePath);
|
|
327
|
+
if (typeof config.extends === "string") {
|
|
328
|
+
if (config.extends.startsWith(".") || config.extends.startsWith("/")) {
|
|
329
|
+
const extendedPath = resolveTsConfigReference(baseDir, config.extends);
|
|
330
|
+
if (await fileExists(extendedPath)) {
|
|
331
|
+
fileEntries.add(extendedPath);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
packages.add(getPackageName(config.extends));
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
for (const reference of toUnknownArray(config.references)) {
|
|
339
|
+
if (!isRecord(reference) || typeof reference.path !== "string") {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const referencePath = resolveTsConfigReference(baseDir, reference.path);
|
|
343
|
+
if (await fileExists(referencePath)) {
|
|
344
|
+
fileEntries.add(referencePath);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
const compilerOptions = isRecord(config.compilerOptions) ? config.compilerOptions : {};
|
|
348
|
+
for (const plugin of toUnknownArray(compilerOptions.plugins)) {
|
|
349
|
+
if (isRecord(plugin) && typeof plugin.name === "string") {
|
|
350
|
+
packages.add(plugin.name);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return fileEntries.size > 0 || packages.size > 0
|
|
354
|
+
? { fileEntries: [...fileEntries], packages: [...packages] }
|
|
355
|
+
: null;
|
|
356
|
+
}
|
|
357
|
+
function resolveTsConfigReference(baseDir, value) {
|
|
358
|
+
const resolved = path.resolve(baseDir, value);
|
|
359
|
+
return path.extname(resolved) ? resolved : path.join(resolved, "tsconfig.json");
|
|
360
|
+
}
|
|
361
|
+
async function readJsonFile(filePath) {
|
|
362
|
+
try {
|
|
363
|
+
return JSON.parse(await readFile(filePath, "utf8"));
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function mergeContribution(contribution, packages, fileEntries, packageUsage) {
|
|
370
|
+
if (!contribution) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
for (const packageName of contribution.packages ?? []) {
|
|
374
|
+
packages.add(packageName);
|
|
375
|
+
}
|
|
376
|
+
for (const filePath of contribution.fileEntries ?? []) {
|
|
377
|
+
fileEntries.add(filePath);
|
|
378
|
+
}
|
|
379
|
+
for (const [packageName, sources] of Object.entries(contribution.packageUsage ?? {})) {
|
|
380
|
+
packages.add(packageName);
|
|
381
|
+
for (const source of sources) {
|
|
382
|
+
addUsage(packageUsage, packageName, source);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function hasContribution(contribution) {
|
|
387
|
+
return Boolean((contribution.packages?.length ?? 0) > 0
|
|
388
|
+
|| (contribution.fileEntries?.length ?? 0) > 0
|
|
389
|
+
|| Object.keys(contribution.packageUsage ?? {}).length > 0);
|
|
390
|
+
}
|
|
148
391
|
function tokenize(command) {
|
|
149
392
|
return command.match(TOKEN_RE)?.map((token) => token.trim()).filter(Boolean) ?? [];
|
|
150
393
|
}
|
|
151
394
|
function resolveCommandName(tokens) {
|
|
152
|
-
const [first, second] = tokens;
|
|
395
|
+
const [first, second, third] = tokens;
|
|
153
396
|
const command = stripQuotes(first ?? "");
|
|
154
397
|
if (!command) {
|
|
155
398
|
return null;
|
|
156
399
|
}
|
|
157
|
-
if (command === "npx" || command === "pnpx") {
|
|
400
|
+
if (command === "npx" || command === "pnpx" || command === "bunx") {
|
|
158
401
|
return stripQuotes(second ?? "") || null;
|
|
159
402
|
}
|
|
403
|
+
if ((command === "npm" || command === "pnpm" || command === "yarn") && stripQuotes(second ?? "") === "exec") {
|
|
404
|
+
return stripQuotes(third ?? "") || null;
|
|
405
|
+
}
|
|
160
406
|
return command;
|
|
161
407
|
}
|
|
162
408
|
function normalizeEslintPlugin(value) {
|
|
@@ -169,9 +415,52 @@ function normalizeEslintPlugin(value) {
|
|
|
169
415
|
}
|
|
170
416
|
return value.startsWith("eslint-plugin-") ? value : `eslint-plugin-${value}`;
|
|
171
417
|
}
|
|
418
|
+
function normalizeEslintConfig(value) {
|
|
419
|
+
if (value.startsWith("@")) {
|
|
420
|
+
if (value.includes("/eslint-config")) {
|
|
421
|
+
return value;
|
|
422
|
+
}
|
|
423
|
+
const [scope, name] = value.split("/");
|
|
424
|
+
return name ? `${scope}/eslint-config-${name}` : value;
|
|
425
|
+
}
|
|
426
|
+
return value.startsWith("eslint-config-") ? value : `eslint-config-${value}`;
|
|
427
|
+
}
|
|
428
|
+
function getPackageName(specifier) {
|
|
429
|
+
if (specifier.startsWith("@")) {
|
|
430
|
+
const [scope, name] = specifier.split("/");
|
|
431
|
+
return name ? `${scope}/${name}` : specifier;
|
|
432
|
+
}
|
|
433
|
+
return specifier.split("/")[0] ?? specifier;
|
|
434
|
+
}
|
|
435
|
+
function addUsage(usage, packageName, source) {
|
|
436
|
+
const sources = usage.get(packageName) ?? new Set();
|
|
437
|
+
sources.add(source);
|
|
438
|
+
usage.set(packageName, sources);
|
|
439
|
+
}
|
|
440
|
+
function isPluginConfigObject(value) {
|
|
441
|
+
return isRecord(value);
|
|
442
|
+
}
|
|
443
|
+
function isRecord(value) {
|
|
444
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
445
|
+
}
|
|
446
|
+
function toArray(value) {
|
|
447
|
+
if (Array.isArray(value)) {
|
|
448
|
+
return value.filter((item) => typeof item === "string");
|
|
449
|
+
}
|
|
450
|
+
return typeof value === "string" ? [value] : [];
|
|
451
|
+
}
|
|
452
|
+
function toUnknownArray(value) {
|
|
453
|
+
return Array.isArray(value) ? value : [];
|
|
454
|
+
}
|
|
172
455
|
function stripQuotes(value) {
|
|
173
456
|
return value.replace(/^['"`]|['"`]$/g, "");
|
|
174
457
|
}
|
|
458
|
+
function hasGlobMagic(value) {
|
|
459
|
+
return /[*?[\]{}()!+@]/.test(value);
|
|
460
|
+
}
|
|
461
|
+
function looksLikePackageSpecifier(value) {
|
|
462
|
+
return !value.startsWith(".") && !value.startsWith("/") && !value.includes("*") && !/\.[cm]?[jt]sx?$/.test(value);
|
|
463
|
+
}
|
|
175
464
|
async function fileExists(filePath) {
|
|
176
465
|
try {
|
|
177
466
|
await access(filePath);
|
|
@@ -181,33 +470,4 @@ async function fileExists(filePath) {
|
|
|
181
470
|
return false;
|
|
182
471
|
}
|
|
183
472
|
}
|
|
184
|
-
function addUsage(usageMap, packageName, source) {
|
|
185
|
-
const entries = usageMap.get(packageName) ?? new Set();
|
|
186
|
-
entries.add(source);
|
|
187
|
-
usageMap.set(packageName, entries);
|
|
188
|
-
}
|
|
189
|
-
export async function analyzePluginInputs(packageDir, inputs) {
|
|
190
|
-
const entryFiles = new Set();
|
|
191
|
-
const commandPackages = new Set();
|
|
192
|
-
const commandUsage = new Map();
|
|
193
|
-
for (const entryFile of inputs?.entryFiles ?? []) {
|
|
194
|
-
const absolutePath = path.resolve(packageDir, entryFile);
|
|
195
|
-
if (await fileExists(absolutePath)) {
|
|
196
|
-
entryFiles.add(absolutePath);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
for (const packageName of inputs?.packageNames ?? []) {
|
|
200
|
-
commandPackages.add(packageName);
|
|
201
|
-
addUsage(commandUsage, packageName, "input:config");
|
|
202
|
-
}
|
|
203
|
-
const activePlugins = entryFiles.size > 0 || commandPackages.size > 0 ? ["inputs"] : [];
|
|
204
|
-
return {
|
|
205
|
-
activePlugins,
|
|
206
|
-
commandPackages: [...commandPackages].sort(),
|
|
207
|
-
fileEntries: [...entryFiles].sort(),
|
|
208
|
-
commandUsage: Object.fromEntries([...commandUsage.entries()]
|
|
209
|
-
.map(([packageName, sources]) => [packageName, [...sources].sort()])
|
|
210
|
-
.sort(([left], [right]) => left.localeCompare(right))),
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
473
|
//# sourceMappingURL=plugins.js.map
|