# All files / config env.config.ts

0% Statements 0/5
0% Branches 0/60
0% Functions 0/1
0% Lines 0/3

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105

     import * as Joi from 'joi';

    export const envConfig = () => ({
      nodeEnv: process.env.NODE_ENV || 'development',
      port: parseInt(process.env.PORT || '3001', 10),

      database: {
        host: process.env.DB_HOST || 'localhost',
        port: parseInt(process.env.DB_PORT || '5432', 10),
        name: process.env.DB_NAME || 'template_saas_dev',
        user: process.env.DB_USER || 'template_saas_user',
        password: process.env.DB_PASSWORD || 'template_saas_dev_2026',
      },

      jwt: {
        secret: process.env.JWT_SECRET || 'dev-jwt-secret-change-in-production',
        expiresIn: process.env.JWT_EXPIRES_IN || '15m',
        refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN || '7d',
      },

      cors: {
        origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
      },

      stripe: {
        secretKey: process.env.STRIPE_SECRET_KEY || '',
        webhookSecret: process.env.STRIPE_WEBHOOK_SECRET || '',
        publishableKey: process.env.STRIPE_PUBLISHABLE_KEY || '',
      },

      ai: {
        openrouterApiKey: process.env.OPENROUTER_API_KEY || '',
        defaultModel: process.env.AI_DEFAULT_MODEL || 'anthropic/claude-3-haiku',
        fallbackModel: process.env.AI_FALLBACK_MODEL || 'openai/gpt-3.5-turbo',
        timeoutMs: parseInt(process.env.AI_TIMEOUT_MS || '30000', 10),
      },

      email: {
        provider: process.env.EMAIL_PROVIDER || 'sendgrid', // 'sendgrid' | 'ses' | 'smtp'
        from: process.env.EMAIL_FROM || 'noreply@example.com',
        fromName: process.env.EMAIL_FROM_NAME || 'Template SaaS',
        replyTo: process.env.EMAIL_REPLY_TO || '',
        // SendGrid
        sendgridApiKey: process.env.SENDGRID_API_KEY || '',
        // AWS SES
        sesRegion: process.env.AWS_SES_REGION || 'us-east-1',
        sesAccessKeyId: process.env.AWS_SES_ACCESS_KEY_ID || '',
        sesSecretAccessKey: process.env.AWS_SES_SECRET_ACCESS_KEY || '',
        // SMTP (fallback)
        smtpHost: process.env.SMTP_HOST || '',
        smtpPort: parseInt(process.env.SMTP_PORT || '587', 10),
        smtpUser: process.env.SMTP_USER || '',
        smtpPassword: process.env.SMTP_PASSWORD || '',
        smtpSecure: process.env.SMTP_SECURE === 'true',
      },
    });

    export const validationSchema = Joi.object({
      NODE_ENV: Joi.string()
        .valid('development', 'production', 'test')
        .default('development'),
      PORT: Joi.number().default(3001),

      DB_HOST: Joi.string().default('localhost'),
      DB_PORT: Joi.number().default(5432),
      DB_NAME: Joi.string().default('template_saas_dev'),
      DB_USER: Joi.string().default('template_saas_user'),
      DB_PASSWORD: Joi.string().default('template_saas_dev_2026'),

      JWT_SECRET: Joi.string().default('dev-jwt-secret-change-in-production'),
      JWT_EXPIRES_IN: Joi.string().default('15m'),
      JWT_REFRESH_EXPIRES_IN: Joi.string().default('7d'),

      CORS_ORIGIN: Joi.string().default('http://localhost:3000'),

      // Stripe (optional - integration disabled if not set)
      STRIPE_SECRET_KEY: Joi.string().allow('').default(''),
      STRIPE_WEBHOOK_SECRET: Joi.string().allow('').default(''),
      STRIPE_PUBLISHABLE_KEY: Joi.string().allow('').default(''),

      // AI (optional - integration disabled if not set)
      OPENROUTER_API_KEY: Joi.string().allow('').default(''),
      AI_DEFAULT_MODEL: Joi.string().default('anthropic/claude-3-haiku'),
      AI_FALLBACK_MODEL: Joi.string().default('openai/gpt-3.5-turbo'),
      AI_TIMEOUT_MS: Joi.number().default(30000),

      // Email (optional - integration disabled if not set)
      EMAIL_PROVIDER: Joi.string().valid('sendgrid', 'ses', 'smtp').default('sendgrid'),
      EMAIL_FROM: Joi.string().email().default('noreply@example.com'),
      EMAIL_FROM_NAME: Joi.string().default('Template SaaS'),
      EMAIL_REPLY_TO: Joi.string().allow('').default(''),
      // SendGrid
      SENDGRID_API_KEY: Joi.string().allow('').default(''),
      // AWS SES
      AWS_SES_REGION: Joi.string().default('us-east-1'),
      AWS_SES_ACCESS_KEY_ID: Joi.string().allow('').default(''),
      AWS_SES_SECRET_ACCESS_KEY: Joi.string().allow('').default(''),
      // SMTP
      SMTP_HOST: Joi.string().allow('').default(''),
      SMTP_PORT: Joi.number().default(587),
      SMTP_USER: Joi.string().allow('').default(''),
      SMTP_PASSWORD: Joi.string().allow('').default(''),
      SMTP_SECURE: Joi.boolean().default(false),
    });