Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions services/api/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import type { AppConfig } from "./types.js";
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "../../..");
loadDotenv({ path: join(repoRoot, ".env"), quiet: true });

const OptionalUrl = z.preprocess(
(value) => (typeof value === "string" && value.trim() === "" ? undefined : value),
z.string().url().optional(),
);
// .env templates ship optional keys as blank assignments (KEY=), which dotenv
// delivers as empty strings; every optional field must read those as unset.
const blankToUndefined = (value: unknown) =>
typeof value === "string" && value.trim() === "" ? undefined : value;

const OptionalUrl = z.preprocess(blankToUndefined, z.string().url().optional());

const OptionalGithubOrganization = z.preprocess(
(value) => (typeof value === "string" && value.trim() === "" ? undefined : value),
blankToUndefined,
z
.string()
.trim()
Expand All @@ -23,13 +25,8 @@ const OptionalGithubOrganization = z.preprocess(
.optional(),
);

// .env templates ship optional keys as blank assignments (KEY=), which dotenv
// delivers as empty strings — those must parse as unset, while a value that is
// actually set must still be non-empty.
const OptionalNonEmpty = z.preprocess(
(value) => (typeof value === "string" && value.trim() === "" ? undefined : value),
z.string().trim().min(1).optional(),
);
// A value that is actually set must still be non-empty after trimming.
const OptionalNonEmpty = z.preprocess(blankToUndefined, z.string().trim().min(1).optional());

const EnvSchema = z
.object({
Expand All @@ -40,7 +37,7 @@ const EnvSchema = z
WEB_URL: z.string().url().optional(),
FACILITY_PREVIEW_URL: OptionalUrl,
FACILITY_PREVIEW_SURFACE_TOKEN: z.preprocess(
(value) => (typeof value === "string" && value.trim() === "" ? undefined : value),
blankToUndefined,
z.string().min(32).max(128).optional(),
),
SANDBOX_API_URL: z.string().url().optional(),
Expand Down