feat(scripting): discover scoped @punktfunk/plugin-* packages
apple / swift (push) Successful in 1m24s
apple / screenshots (push) Successful in 6m27s
windows-host / package (push) Failing after 15m41s
ci / web (push) Successful in 1m33s
ci / docs-site (push) Successful in 1m26s
android / android (push) Successful in 14m3s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 16s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 15s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
ci / bench (push) Successful in 7m40s
deb / build-publish (push) Successful in 8m58s
deb / build-publish-host (push) Successful in 9m32s
arch / build-publish (push) Successful in 17m35s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m33s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m33s
ci / rust (push) Successful in 28m32s
docker / deploy-docs (push) Failing after 12s
apple / swift (push) Successful in 1m24s
apple / screenshots (push) Successful in 6m27s
windows-host / package (push) Failing after 15m41s
ci / web (push) Successful in 1m33s
ci / docs-site (push) Successful in 1m26s
android / android (push) Successful in 14m3s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 16s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 15s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
ci / bench (push) Successful in 7m40s
deb / build-publish (push) Successful in 8m58s
deb / build-publish-host (push) Successful in 9m32s
arch / build-publish (push) Successful in 17m35s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m33s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m33s
ci / rust (push) Successful in 28m32s
docker / deploy-docs (push) Failing after 12s
The runner only found unscoped `punktfunk-plugin-*` packages. An unscoped package can't be split across registries, which forced plugins to bundle their own copy of @punktfunk/host + effect (the plugin's Gitea registry has no `effect`; `--registry <gitea>` 404s it). Discovering the scoped `@punktfunk/plugin-*` convention lets a plugin resolve cleanly from one scope map and depend on @punktfunk/host + effect as SHARED (hoisted) deps instead of bundling — no per-plugin duplication. Additive: unscoped names still work. Bumps @punktfunk/host to 0.1.1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@punktfunk/host",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"description": "TypeScript SDK for the punktfunk streaming host: typed management-API client + lifecycle event stream, built on Effect.",
|
||||
"type": "module",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
|
||||
+29
-8
@@ -92,19 +92,40 @@ export const discoverUnits = (
|
||||
// no scripts dir — fine
|
||||
}
|
||||
const modules = path.join(pluginsDir, "node_modules");
|
||||
try {
|
||||
for (const pkg of fs.readdirSync(modules).sort()) {
|
||||
if (!pkg.startsWith("punktfunk-plugin-")) continue;
|
||||
// Read a plugin package's manifest (`module`/`main` entry) and add it as a unit.
|
||||
const addPlugin = (dir: string, name: string): void => {
|
||||
try {
|
||||
const manifest = JSON.parse(
|
||||
fs.readFileSync(path.join(modules, pkg, "package.json"), "utf8"),
|
||||
fs.readFileSync(path.join(dir, "package.json"), "utf8"),
|
||||
) as { main?: string; module?: string };
|
||||
const rel = manifest.module ?? manifest.main ?? "index.js";
|
||||
const file = path.join(modules, pkg, rel);
|
||||
if (!fileIsSafe(file, log)) continue;
|
||||
units.push({ name: pkg, file });
|
||||
const file = path.join(dir, rel);
|
||||
if (!fileIsSafe(file, log)) return;
|
||||
units.push({ name, file });
|
||||
} catch (e) {
|
||||
log(`[runner] skipping ${pkg}: unreadable package.json (${e})`);
|
||||
log(`[runner] skipping ${name}: unreadable package.json (${e})`);
|
||||
}
|
||||
};
|
||||
try {
|
||||
for (const pkg of fs.readdirSync(modules).sort()) {
|
||||
// Unscoped convention: `punktfunk-plugin-*`.
|
||||
if (pkg.startsWith("punktfunk-plugin-")) {
|
||||
addPlugin(path.join(modules, pkg), pkg);
|
||||
continue;
|
||||
}
|
||||
// Scoped convention: `@punktfunk/plugin-*` (first-party). A scoped name resolves cleanly
|
||||
// from a single registry scope-map, so a plugin can depend on `@punktfunk/host` + `effect`
|
||||
// as shared (hoisted) deps rather than bundling its own copy of each.
|
||||
if (pkg === "@punktfunk") {
|
||||
try {
|
||||
for (const scoped of fs.readdirSync(path.join(modules, pkg)).sort()) {
|
||||
if (scoped.startsWith("plugin-")) {
|
||||
addPlugin(path.join(modules, pkg, scoped), `${pkg}/${scoped}`);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// no @punktfunk scope dir — fine
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
||||
@@ -83,6 +83,25 @@ describe("discovery", () => {
|
||||
expect(logs.join("\n")).toContain("REFUSING");
|
||||
expect(logs.join("\n")).toContain("evil.ts");
|
||||
});
|
||||
|
||||
test("discovers scoped @punktfunk/plugin-* packages (not other scoped pkgs)", () => {
|
||||
const d = mkdirs("discover-scoped");
|
||||
write(
|
||||
path.join(d.pluginsDir, "node_modules", "@punktfunk", "plugin-y", "package.json"),
|
||||
JSON.stringify({ name: "@punktfunk/plugin-y", module: "dist/index.js" }),
|
||||
);
|
||||
write(
|
||||
path.join(d.pluginsDir, "node_modules", "@punktfunk", "plugin-y", "dist", "index.js"),
|
||||
"export default { name: 'y', main: async () => {} };",
|
||||
);
|
||||
// A non-plugin scoped package (e.g. the SDK itself) is ignored.
|
||||
write(
|
||||
path.join(d.pluginsDir, "node_modules", "@punktfunk", "host", "package.json"),
|
||||
JSON.stringify({ name: "@punktfunk/host" }),
|
||||
);
|
||||
const units = discoverUnits(d);
|
||||
expect(units.map((u) => u.name)).toEqual(["@punktfunk/plugin-y"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("supervision", () => {
|
||||
|
||||
Reference in New Issue
Block a user