fix(tsc): ensure appSecret is set in type system
This commit is contained in:
parent
0e56ce395a
commit
cf19881d4f
2 changed files with 8 additions and 93 deletions
|
|
@ -1,5 +1,4 @@
|
|||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
import os from "node:os";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { parseConfig } from "../config";
|
||||
|
||||
|
|
@ -8,45 +7,6 @@ const fileAppSecret = "b".repeat(32);
|
|||
const appSecretFixturePath = fileURLToPath(new URL("./fixtures/app-secret.txt", import.meta.url));
|
||||
const shortAppSecretFixturePath = fileURLToPath(new URL("./fixtures/short-app-secret.txt", import.meta.url));
|
||||
|
||||
const loadParseConfigWithSystemMocks = async ({
|
||||
mountinfo,
|
||||
hostname,
|
||||
}: {
|
||||
mountinfo: string | Error;
|
||||
hostname?: string;
|
||||
}) => {
|
||||
vi.resetModules();
|
||||
vi.doMock("node:fs", async () => {
|
||||
const actual = await vi.importActual<typeof import("node:fs")>("node:fs");
|
||||
|
||||
return {
|
||||
...actual,
|
||||
readFileSync: vi.fn(() => {
|
||||
if (mountinfo instanceof Error) {
|
||||
throw mountinfo;
|
||||
}
|
||||
|
||||
return mountinfo;
|
||||
}),
|
||||
};
|
||||
});
|
||||
vi.doMock("node:os", async () => {
|
||||
const actual = await vi.importActual<typeof import("node:os")>("node:os");
|
||||
const hostnameMock = vi.fn(() => hostname ?? actual.hostname());
|
||||
|
||||
return {
|
||||
...actual,
|
||||
default: {
|
||||
...actual,
|
||||
hostname: hostnameMock,
|
||||
},
|
||||
hostname: hostnameMock,
|
||||
};
|
||||
});
|
||||
|
||||
return (await import("../config")).parseConfig;
|
||||
};
|
||||
|
||||
const createEnv = (overrides: Record<string, string | undefined> = {}) => {
|
||||
const env = {
|
||||
APP_SECRET: validAppSecret,
|
||||
|
|
@ -72,9 +32,6 @@ const expectParseConfigToExit = (env: Record<string, string | undefined>, messag
|
|||
describe("parseConfig", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.doUnmock("node:fs");
|
||||
vi.doUnmock("node:os");
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
test("parses quoted origins and derives runtime flags", () => {
|
||||
|
|
@ -117,8 +74,6 @@ describe("parseConfig", () => {
|
|||
});
|
||||
|
||||
test("uses the configured RESTIC_HOSTNAME when present", () => {
|
||||
const hostnameSpy = vi.spyOn(os, "hostname");
|
||||
|
||||
const config = parseConfig(
|
||||
createEnv({
|
||||
RESTIC_HOSTNAME: "manual-restic-host",
|
||||
|
|
@ -126,53 +81,6 @@ describe("parseConfig", () => {
|
|||
);
|
||||
|
||||
expect(config.resticHostname).toBe("manual-restic-host");
|
||||
expect(hostnameSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("falls back to zerobyte when the mountinfo hostname lookup fails", async () => {
|
||||
const mockedParseConfig = await loadParseConfigWithSystemMocks({
|
||||
mountinfo: new Error("mountinfo unavailable"),
|
||||
});
|
||||
|
||||
const config = mockedParseConfig(
|
||||
createEnv({
|
||||
RESTIC_HOSTNAME: undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(config.resticHostname).toBe("zerobyte");
|
||||
});
|
||||
|
||||
test("uses the OS hostname when mountinfo resolves to a different container id", async () => {
|
||||
const mockedParseConfig = await loadParseConfigWithSystemMocks({
|
||||
mountinfo:
|
||||
"36 25 0:32 /hostname /etc/hostname rw,relatime - ext4 /dev/root rw 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n",
|
||||
hostname: "hostbox",
|
||||
});
|
||||
|
||||
const config = mockedParseConfig(
|
||||
createEnv({
|
||||
RESTIC_HOSTNAME: undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(config.resticHostname).toBe("hostbox");
|
||||
});
|
||||
|
||||
test("collapses container-derived hostnames back to zerobyte", async () => {
|
||||
const containerHostname = "abc123";
|
||||
const mockedParseConfig = await loadParseConfigWithSystemMocks({
|
||||
mountinfo: `36 25 0:32 /hostname /etc/hostname rw,relatime - ext4 /dev/root rw ${containerHostname}${"0".repeat(58)}\n`,
|
||||
hostname: containerHostname,
|
||||
});
|
||||
|
||||
const config = mockedParseConfig(
|
||||
createEnv({
|
||||
RESTIC_HOSTNAME: undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(config.resticHostname).toBe("zerobyte");
|
||||
});
|
||||
|
||||
test("reads APP_SECRET from APP_SECRET_FILE", () => {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ const envSchema = z
|
|||
trustedOrigins: trustedOrigins,
|
||||
trustProxy: s.TRUST_PROXY === "true",
|
||||
disableRateLimiting: s.DISABLE_RATE_LIMITING === "true" || s.NODE_ENV === "test",
|
||||
appSecret,
|
||||
appSecret: appSecret ?? "",
|
||||
baseUrl,
|
||||
isSecure: baseUrl.startsWith("https://"),
|
||||
enableDevPanel: s.ENABLE_DEV_PANEL === "true",
|
||||
|
|
@ -143,6 +143,13 @@ export const parseConfig = (env: unknown) => {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!result.data.appSecret) {
|
||||
console.error(
|
||||
"APP_SECRET is required but was not provided. Please set the APP_SECRET environment variable or provide a file with APP_SECRET_FILE.",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return result.data;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue