Files
immich-folio/lib/env.ts

67 lines
1.9 KiB
TypeScript
Raw Normal View History

/**
* Zod-validated environment variables.
* Parsed once at startup — all env access should go through this module.
*/
import { z } from 'zod';
const envSchema = z.object({
/** Base URL of your Immich instance, e.g. https://immich.example.com */
IMMICH_API_URL: z
.string()
.url('IMMICH_API_URL must be a valid URL')
.transform((url) => url.replace(/\/+$/, '')),
/** Immich API key (from Admin → API Keys) */
IMMICH_API_KEY: z.string().min(1, 'IMMICH_API_KEY is required'),
/** Public site title shown in the header */
SITE_TITLE: z.string().default('Gallery'),
/** Subtitle displayed below the title */
SITE_SUBTITLE: z.string().default(''),
/** Cache TTL in seconds */
CACHE_TTL: z.coerce.number().int().min(0).default(300),
/** Rate limit: max requests per minute per IP */
RATE_LIMIT_RPM: z.coerce.number().int().min(1).default(120),
/**
* Secret used for signing auth cookies and encrypting asset tokens.
*/
AUTH_SECRET: z.string().min(16, 'AUTH_SECRET should be at least 16 characters').optional(),
}).refine(
(data) => {
// Only require AUTH_SECRET in production at runtime, not during build
if (
process.env.NODE_ENV === 'production' &&
!process.env.NEXT_PHASE?.includes('build') &&
!data.AUTH_SECRET
) {
return false;
}
return true;
},
{
message: 'AUTH_SECRET is required in production',
path: ['AUTH_SECRET'],
},
);
export type Env = z.infer<typeof envSchema>;
function parseEnv(): Env {
const result = envSchema.safeParse(process.env);
if (!result.success) {
const formatted = result.error.issues
.map((issue) => ` ✗ ${issue.path.join('.')}: ${issue.message}`)
.join('\n');
throw new Error(`\n❌ Environment validation failed:\n${formatted}\n`);
}
return result.data;
}
/** Validated, typed environment variables. */
export const env = parseEnv();