96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
const urlOptional = z.string().url().optional();
|
|
const stringOptional = z.string().optional();
|
|
|
|
const publicEnvSchema = z.object({
|
|
NEXT_PUBLIC_GRIDPILOT_MODE: z.enum(['pre-launch', 'alpha']).optional(),
|
|
NEXT_PUBLIC_SITE_URL: urlOptional,
|
|
NEXT_PUBLIC_API_BASE_URL: urlOptional,
|
|
|
|
NEXT_PUBLIC_SITE_NAME: stringOptional,
|
|
NEXT_PUBLIC_SUPPORT_EMAIL: stringOptional,
|
|
NEXT_PUBLIC_SPONSOR_EMAIL: stringOptional,
|
|
|
|
NEXT_PUBLIC_LEGAL_COMPANY_NAME: stringOptional,
|
|
NEXT_PUBLIC_LEGAL_VAT_ID: stringOptional,
|
|
NEXT_PUBLIC_LEGAL_REGISTERED_COUNTRY: stringOptional,
|
|
NEXT_PUBLIC_LEGAL_REGISTERED_ADDRESS: stringOptional,
|
|
|
|
NEXT_PUBLIC_DISCORD_URL: stringOptional,
|
|
NEXT_PUBLIC_X_URL: stringOptional,
|
|
});
|
|
|
|
const serverEnvSchema = z.object({
|
|
API_BASE_URL: urlOptional,
|
|
KV_REST_API_URL: urlOptional,
|
|
KV_REST_API_TOKEN: stringOptional,
|
|
|
|
CI: stringOptional,
|
|
DOCKER: stringOptional,
|
|
NODE_ENV: z.enum(['development', 'production', 'test']).optional(),
|
|
});
|
|
|
|
export type WebsitePublicEnv = z.infer<typeof publicEnvSchema>;
|
|
export type WebsiteServerEnv = z.infer<typeof serverEnvSchema>;
|
|
|
|
function formatZodIssues(issues: z.ZodIssue[]): string {
|
|
return issues
|
|
.map((issue) => {
|
|
const path = issue.path.join('.') || '(root)';
|
|
return `${path}: ${issue.message}`;
|
|
})
|
|
.join('; ');
|
|
}
|
|
|
|
/**
|
|
* Parses Website env vars (server-side safe).
|
|
* Only validates the variables we explicitly support.
|
|
*/
|
|
export function getWebsiteServerEnv(): WebsiteServerEnv {
|
|
const result = serverEnvSchema.safeParse(process.env);
|
|
if (!result.success) {
|
|
throw new Error(`Invalid website server env: ${formatZodIssues(result.error.issues)}`);
|
|
}
|
|
return result.data;
|
|
}
|
|
|
|
/**
|
|
* Parses Website public env vars (safe on both server + client).
|
|
* Note: on the client, only `NEXT_PUBLIC_*` vars are actually present.
|
|
*/
|
|
export function getWebsitePublicEnv(): WebsitePublicEnv {
|
|
const result = publicEnvSchema.safeParse(process.env);
|
|
if (!result.success) {
|
|
throw new Error(`Invalid website public env: ${formatZodIssues(result.error.issues)}`);
|
|
}
|
|
return result.data;
|
|
}
|
|
|
|
export function isTruthyEnv(value: string | undefined): boolean {
|
|
if (!value) return false;
|
|
return value !== '0' && value.toLowerCase() !== 'false';
|
|
}
|
|
|
|
/**
|
|
* Matches the semantics used in [`getWebsiteApiBaseUrl()`](apps/website/lib/config/apiBaseUrl.ts:6).
|
|
*/
|
|
export function isTestLikeEnvironment(): boolean {
|
|
const { NODE_ENV, CI, DOCKER } = getWebsiteServerEnv();
|
|
return NODE_ENV === 'test' || CI === 'true' || DOCKER === 'true';
|
|
}
|
|
|
|
export function isProductionEnvironment(): boolean {
|
|
return getWebsiteServerEnv().NODE_ENV === 'production';
|
|
}
|
|
|
|
export function isKvConfigured(): boolean {
|
|
const { KV_REST_API_URL, KV_REST_API_TOKEN } = getWebsiteServerEnv();
|
|
return Boolean(KV_REST_API_URL && KV_REST_API_TOKEN);
|
|
}
|
|
|
|
export function assertKvConfiguredInProduction(): void {
|
|
if (isProductionEnvironment() && !isKvConfigured()) {
|
|
throw new Error('Missing KV_REST_API_URL/KV_REST_API_TOKEN in production environment');
|
|
}
|
|
} |