Files
bun.sh/test/cli/install/dummy.registry.ts
Alistair Smith efdbe3b54f bun install Security Scanner API (#21183)
### What does this PR do?

Fixes #22014

todo:
- [x] not spawn sync
- [x] better comm to subprocess (not stderr)
- [x] tty
- [x] more tests (also include some tests for the actual implementation
of a provider)
- [x] disable autoinstall?

Scanner template: https://github.com/oven-sh/security-scanner-template

<!-- **Please explain what your changes do**, example: -->

<!--

This adds a new flag --bail to bun test. When set, it will stop running
tests after the first failure. This is useful for CI environments where
you want to fail fast.

-->

---

- [x] Documentation or TypeScript types (it's okay to leave the rest
blank in this case)
- [x] Code changes

### How did you verify your code works?

<!-- **For code changes, please include automated tests**. Feel free to
uncomment the line below -->

<!-- I wrote automated tests -->

<!-- If JavaScript/TypeScript modules or builtins changed:

- [ ] I included a test for the new code, or existing tests cover it
- [ ] I ran my tests locally and they pass (`bun-debug test
test-file-name.test`)

-->

<!-- If Zig files changed:

- [ ] I checked the lifetime of memory allocated to verify it's (1)
freed and (2) only freed when it should be
- [ ] I included a test for the new code, or an existing test covers it
- [ ] JSValue used outside of the stack is either wrapped in a
JSC.Strong or is JSValueProtect'ed
- [ ] I wrote TypeScript/JavaScript tests and they pass locally
(`bun-debug test test-file-name.test`)
-->

<!-- If new methods, getters, or setters were added to a publicly
exposed class:

- [ ] I added TypeScript types for the new methods, getters, or setters
-->

<!-- If dependencies in tests changed:

- [ ] I made sure that specific versions of dependencies are used
instead of ranged or tagged versions
-->

<!-- If a new builtin ESM/CJS module was added:

- [ ] I updated Aliases in `module_loader.zig` to include the new module
- [ ] I added a test that imports the module
- [ ] I added a test that require() the module
-->


tests (bad currently)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan-conway@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-08-21 14:53:50 -07:00

171 lines
4.2 KiB
TypeScript

/**
* 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<Response>;
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<string, number>();
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<string, Pkg> = {};
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() {
resetHandler();
requested = 0;
package_dir = packageDirGetter();
await writeFile(
join(package_dir, "bunfig.toml"),
`
[install]
cache = false
registry = "http://localhost:${server.port}/"
saveTextLockfile = false
`,
);
}
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 {
// @ts-expect-error
({ expect } = Bun.jest(import.meta.path));
}