feat: add public plugin workspace capabilities

This commit is contained in:
Federico Jaramillo Martinez
2026-06-04 13:00:25 +02:00
parent 93b50e61af
commit e3533ebf1f
28 changed files with 584 additions and 531 deletions
+38
View File
@@ -0,0 +1,38 @@
import { readdir, readFile } from "node:fs/promises";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
const pluginRoot = "pi-web-plugins";
const forbiddenPatterns = [
{ pattern: /\bfetch\s*\(/u, message: "direct browser fetch" },
{ pattern: /["'`][^"'`]*\/api\//u, message: "direct PI WEB /api URL" },
{ pattern: /piWebInternal/u, message: "legacy internal plugin context" },
{ pattern: /(?:\.\.\/)+src\//u, message: "imports from PI WEB source internals" },
];
describe("bundled PI WEB plugins", () => {
it("use public plugin APIs instead of direct PI WEB internals", async () => {
const violations: string[] = [];
for (const file of await pluginSourceFiles(pluginRoot)) {
const content = await readFile(file, "utf8");
for (const { pattern, message } of forbiddenPatterns) {
if (pattern.test(content)) violations.push(`${file}: ${message}`);
}
if (content.includes("piWebUnstable") && !content.includes("@jmfederico/pi-web/plugin-api/unstable")) {
violations.push(`${file}: piWebUnstable use without explicit unstable type import`);
}
}
expect(violations).toEqual([]);
});
});
async function pluginSourceFiles(root: string): Promise<string[]> {
const files: string[] = [];
for (const entry of await readdir(root, { withFileTypes: true })) {
const path = join(root, entry.name);
if (entry.isDirectory()) files.push(...await pluginSourceFiles(path));
else if (entry.isFile() && entry.name.endsWith(".ts") && !entry.name.endsWith(".test.ts")) files.push(path);
}
return files;
}