feat(plugins): load workspace packages in dev

This commit is contained in:
Federico Jaramillo Martinez
2026-05-21 09:41:46 +02:00
parent 3cce6d20d1
commit 698a89948b
7 changed files with 140 additions and 12 deletions
+17
View File
@@ -54,6 +54,23 @@ describe("PiWebPluginService", () => {
expect(manifest.plugins[0]?.module).toMatch(/^\/pi-web-plugins\/review\/dist\/review\.js\?v=\d+$/u);
});
it("discovers source checkout plugin packages without symlinks", async () => {
await mkdir(join(tempDir, "src", "server"), { recursive: true });
await writeFile(join(tempDir, "src", "server", "index.ts"), "export {};\n");
await writePlugin(join(tempDir, "plugins", "source-dev"), {
packageJson: { piWeb: { plugins: [{ id: "source-dev", module: "dist/pi-web-plugin.js" }] } },
files: { "dist/pi-web-plugin.js": "export default { apiVersion: 1, name: 'Source Dev', activate: () => ({ contributions: {} }) };" },
});
const service = new PiWebPluginService({ cwd: tempDir, packageProvider: false });
const manifest = await service.manifest();
expect(manifest.plugins).toEqual(expect.arrayContaining([
expect.objectContaining({ id: "source-dev", source: "dev", scope: "local" }),
]));
await expect(service.readAsset("source-dev", "dist/pi-web-plugin.js")).resolves.toBeDefined();
});
it("discovers local plugins through symlinks for development", async () => {
const pluginDir = join(tempDir, "dev-plugin");
await writePlugin(pluginDir, {
+9 -2
View File
@@ -84,7 +84,7 @@ export class PiWebPluginService {
constructor(options: PiWebPluginServiceOptions = {}) {
const cwd = options.cwd ?? process.cwd();
const agentDir = options.agentDir ?? getAgentDir();
this.roots = options.roots ?? defaultPluginRoots();
this.roots = options.roots ?? defaultPluginRoots(cwd);
this.packageProvider = options.packageProvider === false ? undefined : options.packageProvider ?? new DefaultPiPackageProvider(cwd, agentDir);
}
@@ -148,11 +148,12 @@ export class PiWebPluginService {
}
}
function defaultPluginRoots(): LocalPluginRoot[] {
function defaultPluginRoots(cwd: string): LocalPluginRoot[] {
const moduleDir = dirname(fileURLToPath(import.meta.url));
const packageRoot = join(moduleDir, "..", "..");
return [
{ path: bundledPluginRoot(packageRoot), source: "bundled", scope: "bundled" },
...sourceCheckoutPluginRoots(cwd),
{ path: join(piWebDataDir(), "plugins"), source: "local", scope: "local" },
];
}
@@ -161,6 +162,12 @@ function bundledPluginRoot(packageRoot: string): string {
return join(packageRoot, "dist", "pi-web-plugins");
}
function sourceCheckoutPluginRoots(cwd: string): LocalPluginRoot[] {
const pluginsRoot = join(cwd, "plugins");
if (!existsSync(join(cwd, "src", "server", "index.ts")) || !existsSync(pluginsRoot)) return [];
return [{ path: pluginsRoot, source: "dev", scope: "local" }];
}
async function discoverLocalRoot(root: LocalPluginRoot): Promise<PluginRecord[]> {
if (!existsSync(root.path)) return [];
const entries = await readdir(root.path, { withFileTypes: true }).catch(() => []);