diff --git a/apps/api/src/modules/billing/env.ts b/apps/api/src/modules/billing/env.ts index b458081..27fdd1c 100644 --- a/apps/api/src/modules/billing/env.ts +++ b/apps/api/src/modules/billing/env.ts @@ -1,19 +1,27 @@ import { z } from 'zod'; /** - * ADR 0004 — env vars Stripe. Tutte opzionali: se mancano, i flussi di - * billing rispondono 503 (come abbiamo fatto per VAPID in ADR 0003). - * Questo permette al PO di sviluppare features non-billing senza dover - * configurare Stripe localmente. + * ADR 0004 — env vars Stripe. Tutte opzionali: se mancano (o sono stringhe + * vuote), i flussi di billing rispondono 503 (come per VAPID in ADR 0003). + * Questo permette al PO di sviluppare/deployare features non-billing senza + * configurare Stripe. + * + * `emptyAsUndefined`: una env file scritta come `STRIPE_SECRET_KEY=` viene + * letta da Node come stringa vuota; la trattiamo equivalente a `undefined`. */ +const emptyAsUndefined = z + .string() + .optional() + .transform((value) => (value && value.length > 0 ? value : undefined)); + const billingEnvSchema = z.object({ - STRIPE_SECRET_KEY: z.string().min(1).optional(), - STRIPE_WEBHOOK_SECRET: z.string().min(1).optional(), - STRIPE_PRICE_ID_MONTHLY: z.string().min(1).optional(), - STRIPE_PRICE_ID_YEARLY: z.string().min(1).optional(), + STRIPE_SECRET_KEY: emptyAsUndefined, + STRIPE_WEBHOOK_SECRET: emptyAsUndefined, + STRIPE_PRICE_ID_MONTHLY: emptyAsUndefined, + STRIPE_PRICE_ID_YEARLY: emptyAsUndefined, // URL di base usato per le redirect post-checkout. Deve coincidere col - // dominio del frontend (apps/web). - BILLING_RETURN_URL: z.string().url().optional(), + // dominio del frontend (apps/web). Non valida l'URL se è stringa vuota. + BILLING_RETURN_URL: emptyAsUndefined.pipe(z.string().url().optional()), }); export type BillingEnv = z.infer;