Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import z from "zod";
import { AbstractAudioFxPlugin } from "../base/audio-fx-plugin.js";
import {
AUDIO_FX_CODES,
type AudioFxError,
} from "../error-codes/error-codes.js";
import { PluginRegistry } from "./registry.js";
const SCHEMA = z.object({}).strict();
const STEREO_IO = {
inputs: [{ count: 2 as const }],
outputs: [{ count: "preserve" as const }],
};
class FixturePlugin extends AbstractAudioFxPlugin {
public constructor(id: string) {
super({
metadata: { id, name: id, version: "1.0.0", category: "utility" },
schema: SCHEMA,
io: STEREO_IO,
parameters: [],
supportedSchemaVersion: 1,
});
}
protected processBlock(
input: Float32Array[],
output: Float32Array[]
): void {
for (let ch = 0; ch < input.length; ch++) {
output[ch]!.set(input[ch]!);
}
}
}
describe("PluginRegistry: register + create", () => {
it("registers a factory and creates fresh instances", {
timeout: 5_000,
}, () => {
const r = new PluginRegistry();
r.register("fx-a", () => new FixturePlugin("fx-a"));
const a = r.create("fx-a");
const b = r.create("fx-a");
expect(a.metadata.id).toBe("fx-a");
expect(b.metadata.id).toBe("fx-a");
expect(a).not.toBe(b);
});
it("has(pluginType) reflects registration state", {
timeout: 5_000,
}, () => {
const r = new PluginRegistry();
expect(r.has("fx-a")).toBe(false);
r.register("fx-a", () => new FixturePlugin("fx-a"));
expect(r.has("fx-a")).toBe(true);
});
it("list() returns registered types in insertion order", {
timeout: 5_000,
}, () => {
const r = new PluginRegistry();
r.register("fx-b", () => new FixturePlugin("fx-b"));
r.register("fx-a", () => new FixturePlugin("fx-a"));
r.register("fx-c", () => new FixturePlugin("fx-c"));
expect(r.list()).toEqual(["fx-b", "fx-a", "fx-c"]);
});
it("re-registering a type overwrites the previous factory", {
timeout: 5_000,
}, () => {
const r = new PluginRegistry();
r.register("fx-a", () => new FixturePlugin("fx-a"));
r.register("fx-a", () => new FixturePlugin("fx-a-2"));
expect(r.create("fx-a").metadata.id).toBe("fx-a-2");
expect(r.list()).toEqual(["fx-a"]);
});
});
describe("PluginRegistry: missing factory rejection", () => {
it("create() rejects an unregistered type with CHAIN_SLOT_NOT_FOUND", {
timeout: 5_000,
}, () => {
const r = new PluginRegistry();
try {
r.create("fx-missing");
} catch (error) {
expect((error as AudioFxError).code).toBe(
AUDIO_FX_CODES.CHAIN_SLOT_NOT_FOUND
);
expect((error as AudioFxError).context).toEqual({
pluginType: "fx-missing",
});
return;
}
throw new Error("expected CHAIN_SLOT_NOT_FOUND");
});
});