- Add Conceptos tab in CFDI page with column filters, sorting, pagination - Add GET /cfdi/conceptos endpoint with filters and orderBy - Backfill cfdi_conceptos from legacy XMLs (824k concepts inserted) - Fix CFDI delete button (bypass subscription check, add alerts) - Fix export to Excel (fetch all filtered results, limit 10k) - Fix facturacion page concepto delete bug (immutable updates, unique ids) - Add Facturapi live key auto-generation and caching - Fix SAT fechaPagoP parsing - Add metrics cache support for current year - Increase DB pool max to 15
65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
import { z } from 'zod';
|
|
import { config } from 'dotenv';
|
|
import { resolve } from 'path';
|
|
|
|
// Load .env file from the api package root
|
|
config({ path: resolve(process.cwd(), '.env') });
|
|
|
|
const envSchema = z.object({
|
|
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
PORT: z.string().default('4000'),
|
|
DATABASE_URL: z.string(),
|
|
JWT_SECRET: z.string().min(32),
|
|
JWT_EXPIRES_IN: z.string().default('15m'),
|
|
JWT_REFRESH_EXPIRES_IN: z.string().default('7d'),
|
|
CORS_ORIGIN: z.string().default('http://localhost:3000'),
|
|
|
|
// Frontend URL (for MercadoPago back_url, emails, etc.)
|
|
FRONTEND_URL: z.string().default('https://horuxfin.com'),
|
|
|
|
// FIEL encryption (separate from JWT to allow independent rotation)
|
|
FIEL_ENCRYPTION_KEY: z.string().min(32),
|
|
FIEL_STORAGE_PATH: z.string().default('/var/horux/fiel'),
|
|
|
|
// MercadoPago
|
|
MP_ACCESS_TOKEN: z.string().optional(),
|
|
MP_WEBHOOK_SECRET: z.string().optional(),
|
|
MP_NOTIFICATION_URL: z.string().optional(),
|
|
|
|
// SMTP (Gmail Workspace)
|
|
SMTP_HOST: z.string().default('smtp.gmail.com'),
|
|
SMTP_PORT: z.string().default('587'),
|
|
SMTP_USER: z.string().optional(),
|
|
SMTP_PASS: z.string().optional(),
|
|
SMTP_FROM: z.string().default('Horux360 <noreply@horuxfin.com>'),
|
|
|
|
// Admin notification email
|
|
ADMIN_EMAIL: z.string().default('carlos@horuxfin.com'),
|
|
|
|
// Facturapi
|
|
FACTURAPI_USER_KEY: z.string().optional(),
|
|
FACTURAPI_MODE: z.enum(['test', 'live']).optional(),
|
|
|
|
// Cloudflare Tunnel (connector BYO-DB)
|
|
CLOUDFLARE_API_TOKEN: z.string().optional(),
|
|
CLOUDFLARE_ACCOUNT_ID: z.string().optional(),
|
|
CLOUDFLARE_TUNNEL_DOMAIN: z.string().default('tunnel.horux.mx'),
|
|
|
|
// KMS for encrypting DB connection strings and connector tokens
|
|
CONNECTOR_ENCRYPTION_KEY: z.string().optional(),
|
|
});
|
|
|
|
const parsed = envSchema.safeParse(process.env);
|
|
|
|
if (!parsed.success) {
|
|
console.error('❌ Invalid environment variables:', parsed.error.flatten().fieldErrors);
|
|
process.exit(1);
|
|
}
|
|
|
|
export const env = parsed.data;
|
|
|
|
// Parse CORS origins (comma-separated) into array
|
|
export function getCorsOrigins(): string[] {
|
|
return env.CORS_ORIGIN.split(',').map(origin => origin.trim());
|
|
}
|