paperclip / packages /db /src /embedded-postgres-runtime-installer.test.ts
cjovs's picture
Deploy Paperclip CN to Hugging Face Space
96e86e5
Raw
History Blame Contribute Delete
9.42 kB
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import {
EmbeddedPostgresRuntimeInstaller,
ensureEmbeddedPostgresPlatformPackageReady,
type EmbeddedPostgresRuntimeIssue,
type EmbeddedPostgresRuntimeRepairResult,
} from "./embedded-postgres-runtime-installer.js";
function createMissingPlatformPackageError(specifier: string): Error & { code: string } {
return Object.assign(
new Error(`Cannot find package '${specifier}' imported from /tmp/embedded-postgres/binary.js`),
{ code: "ERR_MODULE_NOT_FOUND" },
);
}
function createEligibleInstaller(
overrides: Partial<ConstructorParameters<typeof EmbeddedPostgresRuntimeInstaller>[0]> = {},
): EmbeddedPostgresRuntimeInstaller {
return new EmbeddedPostgresRuntimeInstaller({
platform: "win32",
arch: "x64",
env: {
npm_command: "exec",
npm_config_cache: "/tmp/npm-cache",
npm_execpath: "/usr/lib/node_modules/npm/bin/npm-cli.js",
},
resolveModule: () => "/tmp/npm-cache/_npx/run-123/node_modules/embedded-postgres/package.json",
resolveModuleFrom: (_fromPath, specifier) => {
throw createMissingPlatformPackageError(specifier);
},
readTextFile: async () => JSON.stringify({ version: "18.1.0-beta.16" }),
isWritable: async () => true,
...overrides,
});
}
describe("EmbeddedPostgresRuntimeInstaller", () => {
it("maps supported platforms and architectures to the expected package name", () => {
expect(new EmbeddedPostgresRuntimeInstaller({ platform: "win32", arch: "x64" }).getExpectedPlatformPackageName())
.toBe("@embedded-postgres/windows-x64");
expect(new EmbeddedPostgresRuntimeInstaller({ platform: "darwin", arch: "arm64" }).getExpectedPlatformPackageName())
.toBe("@embedded-postgres/darwin-arm64");
expect(new EmbeddedPostgresRuntimeInstaller({ platform: "darwin", arch: "x64" }).getExpectedPlatformPackageName())
.toBe("@embedded-postgres/darwin-x64");
expect(new EmbeddedPostgresRuntimeInstaller({ platform: "linux", arch: "arm64" }).getExpectedPlatformPackageName())
.toBe("@embedded-postgres/linux-arm64");
expect(new EmbeddedPostgresRuntimeInstaller({ platform: "linux", arch: "ppc64" }).getExpectedPlatformPackageName())
.toBe("@embedded-postgres/linux-ppc64");
expect(new EmbeddedPostgresRuntimeInstaller({ platform: "win32", arch: "arm64" }).getExpectedPlatformPackageName())
.toBeNull();
});
it("returns null when the current platform package is already installed", async () => {
const installer = createEligibleInstaller({
resolveModuleFrom: () => "/tmp/npm-cache/_npx/run-123/node_modules/@embedded-postgres/windows-x64/index.js",
});
await expect(installer.inspectRuntime()).resolves.toBeNull();
});
it("detects a missing current-platform package and enables auto-repair inside npm exec cache", async () => {
const installer = createEligibleInstaller();
const installRoot = path.resolve("/tmp/npm-cache/_npx/run-123");
const issue = await installer.inspectRuntime();
expect(issue).toEqual({
packageName: "@embedded-postgres/windows-x64",
packageSpecifier: "@embedded-postgres/windows-x64",
packageVersion: "18.1.0-beta.16",
installRoot,
eligibleForAutoRepair: true,
});
});
it("keeps manual repair mode when the install root is outside the npm exec cache", async () => {
const installer = createEligibleInstaller({
resolveModule: () => "/tmp/local-install/node_modules/embedded-postgres/package.json",
});
const issue = await installer.inspectRuntime();
expect(issue).not.toBeNull();
expect(issue?.eligibleForAutoRepair).toBe(false);
expect(issue?.reason).toContain("temporary npx/npm exec environments");
});
it("returns null when embedded-postgres itself is not installed", async () => {
const installer = createEligibleInstaller({
resolveModule: () => {
throw createMissingPlatformPackageError("embedded-postgres/package.json");
},
});
await expect(installer.inspectRuntime()).resolves.toBeNull();
});
it("builds the expected npm install command and only attempts the repair once per process", async () => {
const installRoot = path.resolve("/tmp/npm-cache/_npx/run-123");
const runCommand = vi.fn(async () => ({
exitCode: 0,
stdout: "",
stderr: "",
signal: null,
}));
const installer = createEligibleInstaller({ runCommand });
const issue = await installer.inspectRuntime();
expect(issue).not.toBeNull();
await expect(installer.attemptRepair(issue!)).resolves.toEqual({ kind: "repaired" });
await expect(installer.attemptRepair(issue!)).resolves.toEqual({
kind: "skipped",
reason: "Automatic repair already ran once in this process.",
});
expect(runCommand).toHaveBeenCalledTimes(1);
expect(runCommand).toHaveBeenCalledWith(
process.execPath,
[
"/usr/lib/node_modules/npm/bin/npm-cli.js",
"install",
"--prefix",
installRoot,
"--no-save",
"--no-package-lock",
"--no-audit",
"--fund=false",
"@embedded-postgres/windows-x64@18.1.0-beta.16",
],
expect.objectContaining({
cwd: installRoot,
env: expect.objectContaining({
npm_command: "exec",
npm_execpath: "/usr/lib/node_modules/npm/bin/npm-cli.js",
}),
}),
);
});
it("surfaces a clearer manual-repair message when automatic repair is unavailable", async () => {
const installer = createEligibleInstaller({
env: {
npm_command: "install",
npm_config_cache: "/tmp/npm-cache",
npm_execpath: "/usr/lib/node_modules/npm/bin/npm-cli.js",
},
});
const issue = await installer.inspectRuntime();
expect(issue).not.toBeNull();
const enhancedError = installer.createManualRepairError(issue!);
expect(enhancedError.message).toContain("Missing embedded-postgres platform package @embedded-postgres/windows-x64@18.1.0-beta.16.");
expect(enhancedError.message).toContain("temporary npx/npm exec environments");
expect(enhancedError.message).toContain("Install the missing package into the same runtime environment and retry.");
});
});
describe("ensureEmbeddedPostgresPlatformPackageReady", () => {
it("does nothing when the runtime is already ready", async () => {
const inspectRuntime = vi.fn(async () => null);
const attemptRepair = vi.fn();
const createManualRepairError = vi.fn();
await expect(
ensureEmbeddedPostgresPlatformPackageReady({
installer: {
inspectRuntime,
attemptRepair,
createManualRepairError,
},
}),
).resolves.toBeUndefined();
expect(inspectRuntime).toHaveBeenCalledTimes(1);
expect(attemptRepair).not.toHaveBeenCalled();
expect(createManualRepairError).not.toHaveBeenCalled();
});
it("repairs the missing platform package before embedded-postgres loads", async () => {
const issue: EmbeddedPostgresRuntimeIssue = {
packageName: "@embedded-postgres/windows-x64",
packageSpecifier: "@embedded-postgres/windows-x64",
packageVersion: "18.1.0-beta.16",
installRoot: "/tmp/npm-cache/_npx/run-123",
eligibleForAutoRepair: true,
};
const inspectRuntime = vi.fn(async () => issue);
const attemptRepair = vi.fn(async (): Promise<EmbeddedPostgresRuntimeRepairResult> => ({ kind: "repaired" }));
const createManualRepairError = vi.fn();
const logger = { info: vi.fn(), warn: vi.fn() };
await expect(
ensureEmbeddedPostgresPlatformPackageReady({
installer: {
inspectRuntime,
attemptRepair,
createManualRepairError,
},
logger,
}),
).resolves.toBeUndefined();
expect(attemptRepair).toHaveBeenCalledTimes(1);
expect(logger.info).toHaveBeenCalledWith(
"Installed @embedded-postgres/windows-x64@18.1.0-beta.16 before loading embedded PostgreSQL.",
);
expect(createManualRepairError).not.toHaveBeenCalled();
});
it("throws an enhanced error when the repair cannot run", async () => {
const issue: EmbeddedPostgresRuntimeIssue = {
packageName: "@embedded-postgres/windows-x64",
packageSpecifier: "@embedded-postgres/windows-x64",
packageVersion: "18.1.0-beta.16",
installRoot: null,
eligibleForAutoRepair: false,
reason: "Automatic repair only runs inside temporary npx/npm exec environments.",
};
const inspectRuntime = vi.fn(async () => issue);
const attemptRepair = vi.fn(async () => ({
kind: "skipped" as const,
reason: "Automatic repair only runs inside temporary npx/npm exec environments.",
}));
const createManualRepairError = vi.fn(
(targetIssue: EmbeddedPostgresRuntimeIssue, repairResult?: EmbeddedPostgresRuntimeRepairResult) =>
new Error(`${targetIssue.packageName} | ${repairResult?.kind ?? "none"}`),
);
await expect(
ensureEmbeddedPostgresPlatformPackageReady({
installer: {
inspectRuntime,
attemptRepair,
createManualRepairError,
},
}),
).rejects.toThrow("@embedded-postgres/windows-x64 | skipped");
expect(attemptRepair).toHaveBeenCalledTimes(1);
expect(createManualRepairError).toHaveBeenCalledTimes(1);
});
});