mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-11 02:46:29 +00:00
feat(plugins): unify source installation and simplify plugin settings
This commit is contained in:
@@ -28,15 +28,15 @@ const getPluginLogs = vi.fn(async () => [
|
||||
message: "ready",
|
||||
},
|
||||
]);
|
||||
const installDirectoryPlugin = vi.fn(async () => ({
|
||||
const installPluginSource = vi.fn(async () => ({
|
||||
id: "trusted-plugin",
|
||||
path: "/plugins/trusted-plugin",
|
||||
enabled: true,
|
||||
status: "running" as const,
|
||||
}));
|
||||
const installPluginSource = vi.fn(async () => ({
|
||||
id: "trusted-plugin",
|
||||
path: "/plugins/trusted-plugin",
|
||||
const installDirectoryPlugin = vi.fn(async () => ({
|
||||
id: "legacy-plugin",
|
||||
path: "/plugins/legacy-plugin",
|
||||
enabled: true,
|
||||
status: "running" as const,
|
||||
}));
|
||||
@@ -59,7 +59,12 @@ vi.mock("../../utils/client.js", () => ({
|
||||
}));
|
||||
|
||||
import { render } from "../../output/index.js";
|
||||
import { createPluginCommand, runPluginListCommand, runPluginLogsCommand } from "./index.js";
|
||||
import {
|
||||
createPluginCommand,
|
||||
runPluginInstallCommand,
|
||||
runPluginListCommand,
|
||||
runPluginLogsCommand,
|
||||
} from "./index.js";
|
||||
|
||||
describe("plugin management commands", () => {
|
||||
beforeEach(() => {
|
||||
@@ -146,7 +151,7 @@ describe("plugin management commands", () => {
|
||||
});
|
||||
|
||||
it("prints the trust acknowledgement before installing", async () => {
|
||||
features.pluginManagement = true;
|
||||
features.pluginGitManagement = true;
|
||||
const stderr = vi.spyOn(process.stderr, "write").mockImplementation(() => true);
|
||||
const command = createPluginCommand();
|
||||
|
||||
@@ -155,7 +160,22 @@ describe("plugin management commands", () => {
|
||||
expect(stderr).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Git build commands run unsandboxed on the daemon host"),
|
||||
);
|
||||
expect(installDirectoryPlugin).toHaveBeenCalledWith("/plugins/trusted-plugin", undefined);
|
||||
expect(installPluginSource).toHaveBeenCalledWith({ source: "/plugins/trusted-plugin" });
|
||||
stderr.mockRestore();
|
||||
});
|
||||
|
||||
it("requires source support for directory installs without using the legacy RPC", async () => {
|
||||
features.pluginManagement = true;
|
||||
const stderr = vi.spyOn(process.stderr, "write").mockImplementation(() => true);
|
||||
|
||||
await expect(
|
||||
runPluginInstallCommand("/plugins/trusted-plugin", { daemonTarget }, {} as never),
|
||||
).rejects.toMatchObject({
|
||||
code: "DAEMON_UPDATE_REQUIRED",
|
||||
message: "Update the host to install or update plugins.",
|
||||
});
|
||||
expect(installPluginSource).not.toHaveBeenCalled();
|
||||
expect(installDirectoryPlugin).not.toHaveBeenCalled();
|
||||
stderr.mockRestore();
|
||||
});
|
||||
|
||||
@@ -184,7 +204,6 @@ describe("plugin management commands", () => {
|
||||
expect(installPluginSource).toHaveBeenCalledWith({
|
||||
source: "/plugins/monorepo:plugins/review",
|
||||
});
|
||||
expect(installDirectoryPlugin).not.toHaveBeenCalled();
|
||||
stderr.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { Command } from "commander";
|
||||
import path from "node:path";
|
||||
import type {
|
||||
PluginListItem,
|
||||
PluginLogEntry,
|
||||
PluginSourceUpdateItem,
|
||||
} from "@getpaseo/protocol/messages";
|
||||
import {
|
||||
formatPluginSourceReference,
|
||||
parsePluginSourceReference,
|
||||
} from "@getpaseo/protocol/plugin-source-reference";
|
||||
import { formatPluginSourceReference } from "@getpaseo/protocol/plugin-source-reference";
|
||||
import type { CommandOptions, ListResult, OutputSchema, SingleResult } from "../../output/index.js";
|
||||
import { withOutput } from "../../output/index.js";
|
||||
import { addJsonAndDaemonHostOptions, addJsonOption } from "../../utils/command-options.js";
|
||||
@@ -109,7 +105,7 @@ export async function runPluginLogsCommand(
|
||||
return { type: "list", data, schema: pluginLogsSchema };
|
||||
}
|
||||
|
||||
async function install(
|
||||
export async function runPluginInstallCommand(
|
||||
source: string,
|
||||
options: PluginOptions,
|
||||
_command: Command,
|
||||
@@ -117,29 +113,14 @@ async function install(
|
||||
process.stderr.write(
|
||||
"Trusting plugin code: server code and Git build commands run unsandboxed on the daemon host; client code runs inside Paseo. Dependencies and future updates are part of the codebase you trust.\n",
|
||||
);
|
||||
const isExplicitPath =
|
||||
path.isAbsolute(source) ||
|
||||
source === "." ||
|
||||
source === ".." ||
|
||||
source.startsWith("./") ||
|
||||
source.startsWith("../") ||
|
||||
source.startsWith(".\\") ||
|
||||
source.startsWith("..\\");
|
||||
const hasPluginPathSuffix = parsePluginSourceReference(source).pluginPath !== undefined;
|
||||
const canUseLegacyDirectoryInstall =
|
||||
isExplicitPath && !hasPluginPathSuffix && !options.ref && !options.path;
|
||||
const sourceReference = formatPluginSourceReference(source, options.path);
|
||||
const data = canUseLegacyDirectoryInstall
|
||||
? await withPluginManagementClient(options.daemonTarget, (client) =>
|
||||
client.installDirectoryPlugin(source, options.id),
|
||||
)
|
||||
: await withPluginSourceClient(options.daemonTarget, (client) =>
|
||||
client.installPluginSource({
|
||||
source: sourceReference,
|
||||
...(options.id ? { id: options.id } : {}),
|
||||
...(options.ref ? { ref: options.ref } : {}),
|
||||
}),
|
||||
);
|
||||
const data = await withPluginSourceClient(options.daemonTarget, (client) =>
|
||||
client.installPluginSource({
|
||||
source: sourceReference,
|
||||
...(options.id ? { id: options.id } : {}),
|
||||
...(options.ref ? { ref: options.ref } : {}),
|
||||
}),
|
||||
);
|
||||
return { type: "single", data, schema: pluginSchema };
|
||||
}
|
||||
|
||||
@@ -209,7 +190,7 @@ export function createPluginCommand(): Command {
|
||||
.option("--id <id>", "Runtime plugin ID (defaults to paseo-plugin.json id)")
|
||||
.option("--ref <ref>", "Git branch, tag, or commit")
|
||||
.option("--path <path>", "Legacy form of the :plugin/path source suffix"),
|
||||
).action(withOutput(install));
|
||||
).action(withOutput(runPluginInstallCommand));
|
||||
addJsonAndDaemonHostOptions(
|
||||
plugin
|
||||
.command("update")
|
||||
|
||||
@@ -55,7 +55,7 @@ export async function withPluginSourceClient<T>(
|
||||
return withPluginClient(
|
||||
target,
|
||||
"pluginGitManagement",
|
||||
"Update the host to install and update Git plugins.",
|
||||
"Update the host to install or update plugins.",
|
||||
run,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user