Skip to content

Commit ee2ab9a

Browse files
committed
fix(plugins): install optional plugin dependencies
1 parent 54f4c45 commit ee2ab9a

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

src/plugins/install.test.ts

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,32 @@ function setupPluginInstallDirs() {
168168
return { tmpDir, pluginDir, extensionsDir };
169169
}
170170

171-
function setupInstallPluginFromDirFixture(params?: { devDependencies?: Record<string, string> }) {
171+
function setupInstallPluginFromDirFixture(params?: {
172+
devDependencies?: Record<string, string>;
173+
optionalDependencies?: Record<string, string>;
174+
omitDependencies?: boolean;
175+
}) {
172176
const caseDir = suiteTempRootTracker.makeTempDir();
173177
const stateDir = path.join(caseDir, "state");
174178
const pluginDir = path.join(caseDir, "plugin");
175179
fs.mkdirSync(stateDir, { recursive: true });
176180
fs.cpSync(installPluginFromDirTemplateDir, pluginDir, { recursive: true });
177-
if (params?.devDependencies) {
181+
if (params?.devDependencies || params?.optionalDependencies || params?.omitDependencies) {
178182
const packageJsonPath = path.join(pluginDir, "package.json");
179183
const manifest = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")) as {
184+
dependencies?: Record<string, string>;
180185
devDependencies?: Record<string, string>;
186+
optionalDependencies?: Record<string, string>;
181187
};
182-
manifest.devDependencies = params.devDependencies;
188+
if (params.omitDependencies) {
189+
delete manifest.dependencies;
190+
}
191+
if (params.devDependencies) {
192+
manifest.devDependencies = params.devDependencies;
193+
}
194+
if (params.optionalDependencies) {
195+
manifest.optionalDependencies = params.optionalDependencies;
196+
}
183197
fs.writeFileSync(packageJsonPath, JSON.stringify(manifest), "utf-8");
184198
}
185199
return { pluginDir, extensionsDir: path.join(stateDir, "extensions") };
@@ -2103,6 +2117,32 @@ describe("installPluginFromDir", () => {
21032117
});
21042118
});
21052119

2120+
it("runs npm install for optional-only dependencies", async () => {
2121+
const { pluginDir, extensionsDir } = setupInstallPluginFromDirFixture({
2122+
omitDependencies: true,
2123+
optionalDependencies: {
2124+
"left-pad": "1.3.0",
2125+
},
2126+
});
2127+
2128+
const run = vi.mocked(runCommandWithTimeout);
2129+
mockSuccessfulCommandRun(run);
2130+
2131+
const res = await installPluginFromDir({
2132+
dirPath: pluginDir,
2133+
extensionsDir,
2134+
});
2135+
2136+
expect(res.ok).toBe(true);
2137+
if (!res.ok) {
2138+
return;
2139+
}
2140+
expectSingleNpmInstallIgnoreScriptsCall({
2141+
calls: run.mock.calls as Array<[unknown, { cwd?: string } | undefined]>,
2142+
expectedTargetDir: res.targetDir,
2143+
});
2144+
});
2145+
21062146
it("strips workspace devDependencies before npm install", async () => {
21072147
const { pluginDir, extensionsDir } = setupInstallPluginFromDirFixture({
21082148
devDependencies: {

src/plugins/install.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type PluginInstallLogger = {
3232

3333
type PackageManifest = PluginPackageManifest & {
3434
dependencies?: Record<string, string>;
35+
optionalDependencies?: Record<string, string>;
3536
peerDependencies?: Record<string, string>;
3637
};
3738

@@ -797,7 +798,10 @@ async function installPluginFromPackageDir(
797798
return scanResult;
798799
}
799800

800-
const deps = manifest.dependencies ?? {};
801+
const deps = {
802+
...manifest.dependencies,
803+
...manifest.optionalDependencies,
804+
};
801805
const peerDeps = manifest.peerDependencies ?? {};
802806
return await installPluginDirectoryIntoExtensions({
803807
sourceDir: params.packageDir,

0 commit comments

Comments
 (0)