144 lines
4.7 KiB
TypeScript
144 lines
4.7 KiB
TypeScript
import { readFile, stat } from "node:fs/promises";
|
|
import { fileURLToPath } from "node:url";
|
|
import { decodeWav } from "@suaveplan/audio-decode-wav";
|
|
import {
|
|
createIrRegistry,
|
|
createUriPluginCollector,
|
|
} from "@suaveplan/audio-ir-core";
|
|
import { createIrLoader } from "@suaveplan/audio-ir-loader";
|
|
import {
|
|
createStorageUriResolver,
|
|
STORAGE_URI_CODES,
|
|
StorageUriError,
|
|
type UriPlugin,
|
|
} from "@suaveplan/storage-uri";
|
|
import { fallbackUriPlugin } from "@suaveplan/storage-uri-plugin-fallback";
|
|
import type { FetchLike } from "@suaveplan/types";
|
|
|
|
/**
|
|
* Minimal `file://` `FetchLike` for Node — Node's `globalThis.fetch` rejects
|
|
* `file://` URLs, so we substitute one that round-trips via `node:fs`. Lives
|
|
* in the test file by design (no new package introduced).
|
|
*/
|
|
const nodeFileFetch: FetchLike = async (input, init) => {
|
|
const url =
|
|
typeof input === "string"
|
|
? new URL(input)
|
|
: input instanceof URL
|
|
? input
|
|
: new URL((input as Request).url);
|
|
if (url.protocol !== "file:") {
|
|
return globalThis.fetch(
|
|
input as Parameters<typeof globalThis.fetch>[0],
|
|
init
|
|
);
|
|
}
|
|
const path = fileURLToPath(url);
|
|
try {
|
|
const bytes = await readFile(path);
|
|
const meta = await stat(path);
|
|
return new Response(bytes, {
|
|
status: 200,
|
|
headers: {
|
|
"content-length": String(meta.size),
|
|
"content-type": "application/octet-stream",
|
|
},
|
|
});
|
|
} catch (err) {
|
|
const code = (err as NodeJS.ErrnoException).code;
|
|
if (code === "ENOENT") {
|
|
return new Response(null, { status: 404 });
|
|
}
|
|
throw err;
|
|
}
|
|
};
|
|
|
|
import { describe, expect, it } from "@suaveplan/testing/runner";
|
|
import { ENTRY_ID, manifest } from "../../src/manifest/manifest.js";
|
|
import { register } from "../../src/register/register.js";
|
|
|
|
/**
|
|
* Minimal in-test https `UriPlugin` wrapping `globalThis.fetch`. Lives in
|
|
* the test file by design — there is no shipped storage-uri plugin for
|
|
* https today, and the integration test must not introduce a new package.
|
|
*/
|
|
function makeHttpsPlugin(spy: { calls: number }): UriPlugin {
|
|
return {
|
|
scheme: "https",
|
|
adapter: {
|
|
async get(key: string) {
|
|
spy.calls += 1;
|
|
const url = `https://${key}`;
|
|
const res = await fetch(url);
|
|
if (res.status === 404) return undefined;
|
|
if (!res.ok) {
|
|
throw new StorageUriError(
|
|
STORAGE_URI_CODES.ADAPTER_ERROR,
|
|
`HTTP ${res.status} from ${url}`,
|
|
{ uri: url, scheme: "https" }
|
|
);
|
|
}
|
|
return new Uint8Array(await res.arrayBuffer());
|
|
},
|
|
async set() {
|
|
return;
|
|
},
|
|
async delete() {
|
|
return true;
|
|
},
|
|
async exists() {
|
|
spy.calls += 1;
|
|
return false;
|
|
},
|
|
async list() {
|
|
return { keys: [], total: 0, hasMore: false };
|
|
},
|
|
async clear() {
|
|
return;
|
|
},
|
|
},
|
|
parse(uri: string) {
|
|
const noScheme = uri.replace(/^https:\/\//, "");
|
|
return { key: noScheme };
|
|
},
|
|
};
|
|
}
|
|
|
|
describe("integration: bundle-only", () => {
|
|
it("bundle candidate wins without fetching HTTPS via foundation collector", {
|
|
timeout: 30000,
|
|
}, async () => {
|
|
const collector = createUriPluginCollector();
|
|
const registry = createIrRegistry();
|
|
register(registry, collector, { fetch: nodeFileFetch });
|
|
|
|
const spy = { calls: 0 };
|
|
const httpsPlugin = makeHttpsPlugin(spy);
|
|
collector.use(httpsPlugin);
|
|
|
|
const plugins: readonly UriPlugin[] = collector.plugins;
|
|
const innerResolver = createStorageUriResolver([...plugins]);
|
|
const fb = fallbackUriPlugin({
|
|
resolver: innerResolver,
|
|
policy: { errorClass: "any" },
|
|
});
|
|
const outerResolver = createStorageUriResolver([...plugins, fb]);
|
|
|
|
const loader = createIrLoader({
|
|
registry,
|
|
resolver: outerResolver,
|
|
decoders: { wav: decodeWav },
|
|
});
|
|
|
|
const ir = await loader.load(ENTRY_ID);
|
|
expect(ir.id).toBe(ENTRY_ID);
|
|
expect(ir.family).toBe("room");
|
|
expect(ir.channels).toBe(manifest.entries[0]?.channels);
|
|
expect(ir.sampleRate).toBe(manifest.entries[0]?.sampleRate);
|
|
expect(Object.isFrozen(ir)).toBe(true);
|
|
|
|
// Critical assertion: HTTPS adapter was never invoked.
|
|
expect(spy.calls).toBe(0);
|
|
});
|
|
});
|