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,74 @@
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "@suaveplan/testing/runner";
const here = dirname(fileURLToPath(import.meta.url));
const pkgRoot = join(here, "..");
const srcRoot = join(pkgRoot, "src");
const pkgJson = JSON.parse(
readFileSync(join(pkgRoot, "package.json"), "utf8")
) as { exports: Record<string, unknown> };
function walk(dir: string, out: string[] = []): string[] {
if (!existsSync(dir)) return out;
for (const entry of readdirSync(dir)) {
const p = join(dir, entry);
if (statSync(p).isDirectory()) walk(p, out);
else if (p.endsWith(".test.ts")) out.push(p);
}
return out;
}
describe("exports", () => {
it("every feature module has a subpath export entry", {
timeout: 5000,
}, () => {
const required = [
".",
"./codec/ffmpeg-wasm-codec",
"./worker/worker-host",
"./core-loader/core-loader",
"./decode/decode-pipeline",
"./encode/encode-pipeline",
"./streaming/streaming-decoder",
"./streaming/streaming-encoder",
"./register/register",
"./error-codes",
];
for (const sub of required) {
expect(pkgJson.exports[sub]).toBeDefined();
}
});
it("no test file imports vitest or bun:test directly", {
timeout: 5000,
}, () => {
const tests = [...walk(srcRoot), ...walk(join(pkgRoot, "tests"))];
const offenders: string[] = [];
for (const f of tests) {
const text = readFileSync(f, "utf8");
if (/from\s+["'](vitest|bun:test)["']/.test(text)) {
offenders.push(f);
}
}
expect(offenders).toEqual([]);
});
it("package.json declares browser: true and sideEffects: false", {
timeout: 5000,
}, () => {
const raw = JSON.parse(
readFileSync(join(pkgRoot, "package.json"), "utf8")
) as { browser?: boolean; sideEffects?: boolean };
expect(raw.browser).toBe(true);
expect(raw.sideEffects).toBe(false);
});
it("each feature module is independently importable", {
timeout: 5000,
}, async () => {
const mod = await import("../src/register/register.js");
expect(typeof mod.register).toBe("function");
});
});

View File

@@ -0,0 +1,121 @@
import type {
WorkerLike,
WorkerRequest,
WorkerResponse,
} from "../../src/worker/worker-host.types.js";
type MessageListener = (ev: MessageEvent) => void;
type ErrorListener = (ev: ErrorEvent) => void;
/**
* Deterministic `Worker` shim. Tests script the response sequence via the
* `script` array; each posted request consumes the next handler. Out-of-script
* requests are echoed back as `ok: false` with a fixed stderr so the host
* surfaces the matching error code.
*/
export class FakeWorker implements WorkerLike {
public posted: WorkerRequest[] = [];
public terminated = 0;
public messageListeners: MessageListener[] = [];
public errorListeners: ErrorListener[] = [];
public script: Array<(req: WorkerRequest) => WorkerResponse | "drop"> = [];
public postMessage(message: unknown): void {
const req = message as WorkerRequest;
this.posted.push(req);
const handler = this.script.shift();
if (!handler) {
queueMicrotask(() => {
this.emitMessage({
id: req.id,
ok: false,
stderr: "no-handler",
});
});
return;
}
const result = handler(req);
if (result === "drop") return;
queueMicrotask(() => this.emitMessage(result));
}
public emitMessage(data: unknown): void {
const ev = { data } as MessageEvent;
for (const l of this.messageListeners) l(ev);
}
public emitError(message: string, error?: Error): void {
const ev = { message, error } as unknown as ErrorEvent;
for (const l of this.errorListeners) l(ev);
}
public addEventListener(
type: "message" | "error",
listener: MessageListener | ErrorListener
): void {
if (type === "message")
this.messageListeners.push(listener as MessageListener);
else this.errorListeners.push(listener as ErrorListener);
}
public removeEventListener(
type: "message" | "error",
listener: MessageListener | ErrorListener
): void {
if (type === "message")
this.messageListeners = this.messageListeners.filter(
(l) => l !== listener
);
else
this.errorListeners = this.errorListeners.filter(
(l) => l !== listener
);
}
public terminate(): void {
this.terminated++;
}
}
/**
* Standard success script: `load` resolves, `writeFile` resolves, `run`
* resolves with the provided output bytes and stderr, `readFile` resolves
* with those bytes, both `deleteFile` calls resolve. Drop into the worker's
* `script` array.
*/
export function successScript(
outputBytes: Uint8Array,
stderr = ""
): Array<(req: WorkerRequest) => WorkerResponse> {
return [
(req) => ({ id: req.id, ok: true }), // load
(req) => ({ id: req.id, ok: true }), // writeFile
(req) => ({ id: req.id, ok: true, value: { stderr } }), // run
(req) => ({ id: req.id, ok: true, value: outputBytes }), // readFile
(req) => ({ id: req.id, ok: true }), // deleteFile input
(req) => ({ id: req.id, ok: true }), // deleteFile output
];
}
/**
* Build a deterministic `Float32Array` interleaved into `Uint8Array` form
* for use as the `readFile` payload.
*/
export function buildPcmBytes(
frames: number,
channels: number,
pattern: (frame: number, channel: number) => number = (f, c) =>
Math.sin((f * (c + 1)) / 100) * 0.5
): Uint8Array {
const interleaved = new Float32Array(frames * channels);
for (let f = 0; f < frames; f++) {
for (let c = 0; c < channels; c++) {
interleaved[f * channels + c] = pattern(f, c);
}
}
return new Uint8Array(
interleaved.buffer,
interleaved.byteOffset,
interleaved.byteLength
);
}

View File

@@ -0,0 +1,47 @@
import { CodecRegistry } from "@suaveplan/audio-codecs/registry/registry";
import { describe, expect, it } from "@suaveplan/testing/runner";
import { FfmpegWasmCodec, register } from "../src/index.js";
import {
buildPcmBytes,
FakeWorker,
successScript,
} from "./fixtures/fake-worker.js";
describe("integration: codec wired through CodecRegistry", () => {
it("register installs and registry.detect finds the codec", {
timeout: 30000,
}, () => {
const registry = new CodecRegistry();
const codec = register(registry, {
coreLoader: () => Promise.resolve({}),
workerFactory: () => new FakeWorker() as unknown as Worker,
});
expect(codec).toBeInstanceOf(FfmpegWasmCodec);
const wav = new Uint8Array(44);
wav[0] = 0x52;
wav[1] = 0x49;
wav[2] = 0x46;
wav[3] = 0x46;
expect(registry.detect(wav)).toBe("ffmpeg-wasm");
});
it("registry.decode produces an AudioDocument", {
timeout: 30000,
}, async () => {
const registry = new CodecRegistry();
const worker = new FakeWorker();
worker.script.push(...successScript(buildPcmBytes(64, 2)));
register(registry, {
coreLoader: () => Promise.resolve({}),
workerFactory: () => worker as unknown as Worker,
});
const wav = new Uint8Array(44);
wav[0] = 0x52;
wav[1] = 0x49;
wav[2] = 0x46;
wav[3] = 0x46;
const doc = await registry.decode(wav);
expect(doc.channels).toBe(2);
expect(doc.sampleRate).toBeGreaterThan(0);
});
});

View File

@@ -0,0 +1,109 @@
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "@suaveplan/testing/runner";
const here = dirname(fileURLToPath(import.meta.url));
const srcRoot = join(here, "..", "src");
const distRoot = join(here, "..", "dist");
function walk(dir: string, out: string[] = []): string[] {
if (!existsSync(dir)) return out;
for (const entry of readdirSync(dir)) {
const p = join(dir, entry);
if (statSync(p).isDirectory()) walk(p, out);
else if (p.endsWith(".ts") || p.endsWith(".js")) out.push(p);
}
return out;
}
const FORBIDDEN_NODE_PATTERNS = [
/from\s+["']node:/,
/from\s+["']fs["']/,
/from\s+["']path["']/,
/from\s+["']crypto["']/,
];
describe("purity", () => {
it("source files do not import Node-only APIs at the top level", {
timeout: 5000,
}, () => {
const files = walk(srcRoot).filter(
(f) => !f.endsWith(".test.ts") && !f.endsWith(".d.ts")
);
const offenders: string[] = [];
for (const f of files) {
const text = readFileSync(f, "utf8");
for (const rx of FORBIDDEN_NODE_PATTERNS) {
if (rx.test(text)) offenders.push(`${f}: ${rx.source}`);
}
}
expect(offenders).toEqual([]);
});
it("@ffmpeg/core-mt is referenced only inside dynamic imports or comments", {
timeout: 5000,
}, () => {
const files = walk(srcRoot).filter(
(f) => !f.endsWith(".test.ts") && !f.endsWith(".d.ts")
);
for (const f of files) {
const text = readFileSync(f, "utf8");
const lines = text.split("\n");
for (const line of lines) {
if (!line.includes("@ffmpeg/core-mt")) continue;
const trimmed = line.trim();
if (trimmed.startsWith("//")) continue;
if (trimmed.startsWith("*")) continue;
if (line.includes("import(")) continue;
throw new Error(`disallowed reference in ${f}: ${line}`);
}
}
});
it("@ffmpeg/core is never reached via static import", {
timeout: 5000,
}, () => {
const files = walk(srcRoot).filter(
(f) => !f.endsWith(".test.ts") && !f.endsWith(".d.ts")
);
// Forbidden: `import … from "@ffmpeg/core"` / `import "@ffmpeg/core"`.
const STATIC_IMPORT =
/^\s*import\b[^;]*from\s+["']@ffmpeg\/core(?:-mt)?["']/;
for (const f of files) {
if (f.includes("ffmpeg-shim.d.ts")) continue;
const lines = readFileSync(f, "utf8").split("\n");
for (const line of lines) {
if (STATIC_IMPORT.test(line)) {
throw new Error(`static import in ${f}: ${line}`);
}
}
}
});
it("importing the root module mutates no global state", {
timeout: 5000,
}, async () => {
// The act of importing the module is the verification — no exception
// means no top-level throw, and no spec covers any mutation outside
// the module's own ESM closure.
const mod = await import("../src/index.js");
expect(mod.FfmpegWasmCodec).toBeDefined();
});
it("dist/ — when built — contains no node: references", {
timeout: 5000,
}, () => {
if (!existsSync(distRoot)) {
// pre-build environment — skip
return;
}
const files = walk(distRoot);
for (const f of files) {
const text = readFileSync(f, "utf8");
for (const rx of FORBIDDEN_NODE_PATTERNS) {
expect(rx.test(text)).toBe(false);
}
}
});
});