Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121// buildIdealTree's port (src/kernel/npm/resolve.ts), checked in Node against the trees// real npm 11.7.0 wrote from the same recorded registries, and against hand cases whose// expected trees came from real npm too.import { readFileSync } from "node:fs";import { test, expect } from "@playwright/test";import { resolve, ResolveError } from "../src/kernel/npm/resolve";import { loadTree, type Tree } from "../src/kernel/npm/tree";import { fakeRegistry, recordingRegistry, type FakePackages } from "./npm-registry";
type LockEntry = { version?: string; name?: string; dev?: boolean; optional?: boolean; peer?: boolean; devOptional?: boolean };type Shape = Record<string, LockEntry>;
const fixture = (name: string, file: string): string => readFileSync(new URL(`./fixtures/registry/${name}/${file}`, import.meta.url), "utf8");
/** What the oracle compares: each placed node's version, alias name and dependency flags. */function shapeOf(tree: Tree): Shape { const out: Shape = {}; for (const [location, node] of [...tree.nodes].sort(([a], [b]) => a.localeCompare(b, "en"))) { out[location] = { version: node.version, ...(node.packageName !== node.name && { name: node.packageName }), ...(node.dev && { dev: true }), ...(node.optional && { optional: true }), ...(node.devOptional && { devOptional: true }), ...(node.peer && { peer: true }), }; } return out;}
function lockShape(name: string): Shape { const lock = JSON.parse(fixture(name, "package-lock.json")) as { packages: Record<string, LockEntry> }; return packagesShape(lock.packages);}
function packagesShape(packages: Record<string, LockEntry>): Shape { const out: Shape = {}; for (const [location, e] of Object.entries(packages).sort(([a], [b]) => a.localeCompare(b, "en"))) { if (location === "") continue; out[location] = { version: e.version, ...(e.name && { name: e.name }), ...(e.dev && { dev: true }), ...(e.optional && { optional: true }), ...(e.devOptional && { devOptional: true }), ...(e.peer && { peer: true }), }; } return out;}
for (const name of ["hono", "express", "conflict"]) { test(`${name}: package.json alone resolves to the tree npm locked`, async () => { const registry = recordingRegistry(name); const tree = loadTree({ text: fixture(name, "package.json"), path: "package.json" }); const { warnings } = await resolve(tree, registry); console.log(`${name}: ${tree.nodes.size} nodes, ${registry.calls.length} manifest() calls, ${warnings.length} warnings`); expect(shapeOf(tree)).toEqual(lockShape(name)); expect(warnings).toEqual([]); });
test(`${name}: the lockfile as seed resolves nothing and stands`, async () => { const registry = recordingRegistry(name); const tree = loadTree({ text: fixture(name, "package.json"), path: "package.json" }, { text: fixture(name, "package-lock.json"), path: "package-lock.json" }); await resolve(tree, registry); expect(registry.calls).toEqual([]); expect(shapeOf(tree)).toEqual(lockShape(name)); });}
// Hand cases: tests/fixtures/fake/<case>.json holds a package.json and an in-memory// registry, and under `npm` what real npm 11.7.0 did with exactly those inputs// (`node scripts/npm-oracle.mjs fake <case>` refreshes it).interface FakeCase { description: string; package: Record<string, unknown>; seed?: Record<string, unknown>; registry: FakePackages; npm: { version: string; status: number; packages?: Record<string, LockEntry>; seedLock?: unknown; stderr: string };}
const fakeCase = (name: string): FakeCase => JSON.parse(readFileSync(new URL(`./fixtures/fake/${name}.json`, import.meta.url), "utf8"));const source = (json: unknown, path: string) => ({ text: JSON.stringify(json), path });
for (const name of ["replace", "override-ref"]) { test(`${name}: ${fakeCase(name).description}`, async () => { const c = fakeCase(name); const tree = loadTree(source(c.package, "package.json")); const { warnings } = await resolve(tree, fakeRegistry(c.registry)); expect(shapeOf(tree)).toEqual(packagesShape(c.npm.packages!)); expect(warnings).toEqual([]); });}
test(`bump: ${fakeCase("bump").description}`, async () => { const c = fakeCase("bump"); const tree = loadTree(source(c.package, "package.json"), source(c.npm.seedLock, "package-lock.json")); const registry = fakeRegistry(c.registry); const { warnings } = await resolve(tree, registry); expect(registry.calls).toEqual(["a@^1.4.0"]); expect(shapeOf(tree)).toEqual(packagesShape(c.npm.packages!)); expect(warnings).toEqual([]);});
test(`eresolve: ${fakeCase("eresolve").description}`, async () => { const c = fakeCase("eresolve"); const tree = loadTree(source(c.package, "package.json")); const error = await resolve(tree, fakeRegistry(c.registry)).then(() => null, (e: unknown) => e); expect(error).toBeInstanceOf(ResolveError); expect((error as ResolveError).code).toBe("ERESOLVE"); expect(`code ERESOLVE\nERESOLVE ${(error as ResolveError).message}`).toBe(c.npm.stderr);});
test(`peer-warn: ${fakeCase("peer-warn").description}`, async () => { const c = fakeCase("peer-warn"); const tree = loadTree(source(c.package, "package.json")); const { warnings } = await resolve(tree, fakeRegistry(c.registry)); expect(shapeOf(tree)).toEqual(packagesShape(c.npm.packages!)); expect(warnings.join("\n")).toBe(c.npm.stderr);});