/** * This file can be directly run * * PACKAGE_DIR_TO_USE=(realpath .) bun test/cli/install/dummy.registry.ts */ import { file, Server } from "bun"; import { tmpdirSync } from "harness"; let expect: (typeof import("bun:test"))["expect"]; import { writeFile } from "fs/promises"; import { basename, join } from "path"; type Handler = (req: Request) => Response | Promise; type Pkg = { name: string; version: string; dist: { tarball: string; }; }; let handler: Handler; let server: Server; export let package_dir: string; export let requested: number; export let root_url: string; export let check_npm_auth_type = { check: true }; export async function write(path: string, content: string | object) { if (!package_dir) throw new Error("writeToPackageDir() must be called in a test"); await Bun.write(join(package_dir, path), typeof content === "string" ? content : JSON.stringify(content)); } export function read(path: string) { return Bun.file(join(package_dir, path)); } export function dummyRegistry(urls: string[], info: any = { "0.0.2": {} }, numberOfTimesTo500PerURL = 0) { let retryCountsByURL = new Map(); const _handler: Handler = async request => { urls.push(request.url); const url = request.url.replaceAll("%2f", "/"); let status = 200; if (numberOfTimesTo500PerURL > 0) { let currentCount = retryCountsByURL.get(request.url); if (currentCount === undefined) { retryCountsByURL.set(request.url, numberOfTimesTo500PerURL); status = 500; } else { retryCountsByURL.set(request.url, currentCount - 1); status = currentCount > 0 ? 500 : 200; } } expect(request.method).toBe("GET"); if (url.endsWith(".tgz")) { return new Response(file(join(import.meta.dir, basename(url).toLowerCase())), { status }); } expect(request.headers.get("accept")).toBe( "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*", ); if (check_npm_auth_type.check) { expect(request.headers.get("npm-auth-type")).toBe(null); } expect(await request.text()).toBe(""); const name = url.slice(url.indexOf("/", root_url.length) + 1); const versions: Record = {}; let version; for (version in info) { if (!/^[0-9]/.test(version)) continue; versions[version] = { name, version, dist: { tarball: `${url}-${info[version].as ?? version}.tgz`, }, ...info[version], }; } return new Response( JSON.stringify({ name, versions, "dist-tags": { latest: info.latest ?? version, }, }), { status }, ); }; return _handler; } export function setHandler(newHandler: Handler) { handler = newHandler; } function resetHandler() { setHandler(() => new Response("Tea Break~", { status: 418 })); } export function dummyBeforeAll() { server = Bun.serve({ async fetch(request) { requested++; return await handler(request); }, port: 0, }); root_url = `http://localhost:${server.port}`; } export function dummyAfterAll() { server.stop(); } export function getPort() { return server.port; } let packageDirGetter: () => string = () => { return tmpdirSync(); }; export async function dummyBeforeEach(opts?: { linker: "hoisted" | "isolated" }) { resetHandler(); requested = 0; package_dir = packageDirGetter(); await writeFile( join(package_dir, "bunfig.toml"), ` [install] cache = false registry = "http://localhost:${server.port}/" saveTextLockfile = false ${opts ? `linker = "${opts.linker}"` : ""} `, ); } export async function dummyAfterEach() { resetHandler(); } if (Bun.main === import.meta.path) { // @ts-expect-error expect = value => { return { toBe(expected) { if (value !== expected) { throw new Error(`Expected ${value} to be ${expected}`); } }, }; }; if (process.env.PACKAGE_DIR_TO_USE) { packageDirGetter = () => process.env.PACKAGE_DIR_TO_USE!; } await dummyBeforeAll(); await dummyBeforeEach(); setHandler(dummyRegistry([])); console.log("Running dummy registry!\n\n URL: ", root_url!, "\n", "DIR: ", package_dir!); } else { ({ expect } = Bun.jest(import.meta.path)); }