|
4 | 4 | * Centralized configuration management with environment variable support. |
5 | 5 | */ |
6 | 6 |
|
7 | | -require('dotenv').config(); |
| 7 | +require("dotenv").config(); |
8 | 8 |
|
9 | 9 | const config = { |
10 | 10 | // Server configuration |
11 | 11 | server: { |
12 | | - nodeEnv: process.env.NODE_ENV || 'development', |
| 12 | + nodeEnv: process.env.NODE_ENV || "development", |
13 | 13 | port: parseInt(process.env.PORT, 10) || 3000, |
14 | | - host: process.env.HOST || '0.0.0.0', |
15 | | - baseUrl: process.env.API_BASE_URL || 'http://localhost:3000' |
| 14 | + host: process.env.HOST || "0.0.0.0", |
| 15 | + baseUrl: process.env.API_BASE_URL || "http://localhost:3000", |
16 | 16 | }, |
17 | 17 |
|
18 | 18 | // Database configuration |
19 | 19 | database: { |
20 | | - url: process.env.DATABASE_URL || 'mongodb://localhost:27017/openwallet', |
| 20 | + url: process.env.DATABASE_URL || "mongodb://localhost:27017/openwallet", |
21 | 21 | options: { |
22 | 22 | useNewUrlParser: true, |
23 | 23 | useUnifiedTopology: true, |
24 | 24 | serverSelectionTimeoutMS: 5000, |
25 | | - socketTimeoutMS: 45000 |
26 | | - } |
| 25 | + socketTimeoutMS: 45000, |
| 26 | + }, |
27 | 27 | }, |
28 | 28 |
|
29 | 29 | // Redis configuration (optional) |
30 | 30 | redis: { |
31 | | - url: process.env.REDIS_URL || 'redis://localhost:6379', |
32 | | - enabled: !!process.env.REDIS_URL |
| 31 | + url: process.env.REDIS_URL || "redis://localhost:6379", |
| 32 | + enabled: !!process.env.REDIS_URL, |
33 | 33 | }, |
34 | 34 |
|
35 | 35 | // Tokenization provider configuration |
36 | 36 | tokenization: { |
37 | 37 | apiKey: process.env.TOKENIZATION_API_KEY, |
38 | | - baseURL: process.env.TOKENIZATION_BASE_URL || 'https://api.basistheory.com', |
| 38 | + baseURL: process.env.TOKENIZATION_BASE_URL || "https://api.basistheory.com", |
39 | 39 | tenantId: process.env.TOKENIZATION_TENANT_ID, |
40 | | - timeout: 30000 |
| 40 | + timeout: 30000, |
41 | 41 | }, |
42 | 42 |
|
43 | 43 | // Security configuration |
44 | 44 | security: { |
45 | | - jwtSecret: process.env.JWT_SECRET || 'change-this-in-production', |
46 | | - jwtExpiresIn: '7d', |
| 45 | + jwtSecret: process.env.JWT_SECRET || "change-this-in-production", |
| 46 | + jwtExpiresIn: "7d", |
47 | 47 | encryptionKey: process.env.ENCRYPTION_KEY, |
48 | 48 | webhookSecret: process.env.WEBHOOK_SECRET, |
49 | | - bcryptRounds: 10 |
| 49 | + bcryptRounds: 10, |
50 | 50 | }, |
51 | 51 |
|
52 | 52 | // Rate limiting |
53 | 53 | rateLimit: { |
54 | 54 | windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS, 10) || 15 * 60 * 1000, |
55 | 55 | max: parseInt(process.env.RATE_LIMIT_MAX, 10) || 100, |
56 | 56 | standardHeaders: true, |
57 | | - legacyHeaders: false |
| 57 | + legacyHeaders: false, |
58 | 58 | }, |
59 | 59 |
|
60 | 60 | // CORS configuration |
61 | 61 | cors: { |
62 | | - origin: process.env.CORS_ORIGINS?.split(',') || ['http://localhost:3000'], |
63 | | - credentials: true |
| 62 | + origin: process.env.CORS_ORIGINS?.split(",") || ["http://localhost:3000"], |
| 63 | + credentials: true, |
64 | 64 | }, |
65 | 65 |
|
66 | 66 | // Wallet configuration |
67 | 67 | wallet: { |
68 | | - defaultCurrency: process.env.DEFAULT_CURRENCY || 'USD', |
| 68 | + defaultCurrency: process.env.DEFAULT_CURRENCY || "USD", |
69 | 69 | minBalance: parseFloat(process.env.MIN_BALANCE) || 0, |
70 | 70 | maxBalance: parseFloat(process.env.MAX_BALANCE) || 10000, |
71 | 71 | autoTopUp: { |
72 | | - enabled: process.env.AUTO_TOPUP_ENABLED === 'true', |
| 72 | + enabled: process.env.AUTO_TOPUP_ENABLED === "true", |
73 | 73 | threshold: parseFloat(process.env.AUTO_TOPUP_THRESHOLD) || 10, |
74 | | - amount: parseFloat(process.env.AUTO_TOPUP_AMOUNT) || 50 |
75 | | - } |
| 74 | + amount: parseFloat(process.env.AUTO_TOPUP_AMOUNT) || 50, |
| 75 | + }, |
76 | 76 | }, |
77 | 77 |
|
78 | 78 | // Payment providers |
79 | 79 | applePay: { |
80 | 80 | merchantId: process.env.APPLE_PAY_MERCHANT_ID, |
81 | | - merchantName: process.env.APPLE_PAY_MERCHANT_NAME || 'Open Commerce Initiative (OCI)', |
82 | | - countryCode: 'US', |
83 | | - supportedNetworks: ['visa', 'mastercard', 'amex', 'discover'] |
| 81 | + merchantName: |
| 82 | + process.env.APPLE_PAY_MERCHANT_NAME || "Open Commerce Initiative (OCI)", |
| 83 | + countryCode: "US", |
| 84 | + supportedNetworks: ["visa", "mastercard", "amex", "discover"], |
84 | 85 | }, |
85 | 86 |
|
86 | 87 | googlePay: { |
87 | 88 | merchantId: process.env.GOOGLE_PAY_MERCHANT_ID, |
88 | | - merchantName: process.env.GOOGLE_PAY_MERCHANT_NAME || 'Open Commerce Initiative (OCI)', |
89 | | - environment: process.env.GOOGLE_PAY_ENVIRONMENT || 'TEST' |
| 89 | + merchantName: |
| 90 | + process.env.GOOGLE_PAY_MERCHANT_NAME || "Open Commerce Initiative (OCI)", |
| 91 | + environment: process.env.GOOGLE_PAY_ENVIRONMENT || "TEST", |
90 | 92 | }, |
91 | 93 |
|
92 | 94 | // Logging configuration |
93 | 95 | logging: { |
94 | | - level: process.env.LOG_LEVEL || 'info', |
95 | | - file: process.env.LOG_FILE || 'logs/app.log', |
96 | | - console: process.env.NODE_ENV !== 'production' |
| 96 | + level: process.env.LOG_LEVEL || "info", |
| 97 | + file: process.env.LOG_FILE || "logs/app.log", |
| 98 | + console: process.env.NODE_ENV !== "production", |
97 | 99 | }, |
98 | 100 |
|
99 | 101 | // Monitoring |
100 | 102 | monitoring: { |
101 | 103 | sentryDsn: process.env.SENTRY_DSN, |
102 | | - newRelicKey: process.env.NEW_RELIC_LICENSE_KEY |
| 104 | + newRelicKey: process.env.NEW_RELIC_LICENSE_KEY, |
103 | 105 | }, |
104 | 106 |
|
105 | 107 | // Testing |
106 | 108 | testing: { |
107 | | - testMode: process.env.TEST_MODE === 'true' |
108 | | - } |
| 109 | + testMode: process.env.TEST_MODE === "true", |
| 110 | + }, |
109 | 111 | }; |
110 | 112 |
|
111 | 113 | // Validation |
112 | 114 | function validateConfig() { |
113 | 115 | const errors = []; |
114 | 116 |
|
115 | | - if (!config.tokenization.apiKey && config.server.nodeEnv === 'production') { |
116 | | - errors.push('TOKENIZATION_API_KEY is required in production'); |
| 117 | + if (!config.tokenization.apiKey && config.server.nodeEnv === "production") { |
| 118 | + errors.push("TOKENIZATION_API_KEY is required in production"); |
117 | 119 | } |
118 | 120 |
|
119 | | - if (config.security.jwtSecret === 'change-this-in-production' && |
120 | | - config.server.nodeEnv === 'production') { |
121 | | - errors.push('JWT_SECRET must be changed in production'); |
| 121 | + if ( |
| 122 | + config.security.jwtSecret === "change-this-in-production" && |
| 123 | + config.server.nodeEnv === "production" |
| 124 | + ) { |
| 125 | + errors.push("JWT_SECRET must be changed in production"); |
122 | 126 | } |
123 | 127 |
|
124 | | - if (!config.security.encryptionKey && config.server.nodeEnv === 'production') { |
125 | | - errors.push('ENCRYPTION_KEY is required in production'); |
| 128 | + if ( |
| 129 | + !config.security.encryptionKey && |
| 130 | + config.server.nodeEnv === "production" |
| 131 | + ) { |
| 132 | + errors.push("ENCRYPTION_KEY is required in production"); |
126 | 133 | } |
127 | 134 |
|
128 | 135 | // Database URL is always required |
129 | | - if (!process.env.DATABASE_URL && config.server.nodeEnv === 'production') { |
130 | | - errors.push('DATABASE_URL is required in production'); |
| 136 | + if (!process.env.DATABASE_URL && config.server.nodeEnv === "production") { |
| 137 | + errors.push("DATABASE_URL is required in production"); |
131 | 138 | } |
132 | 139 |
|
133 | 140 | if (errors.length > 0) { |
134 | | - throw new Error(`Configuration errors:\n${errors.join('\n')}`); |
| 141 | + throw new Error(`Configuration errors:\n${errors.join("\n")}`); |
135 | 142 | } |
136 | 143 | } |
137 | 144 |
|
138 | 145 | // Validate on load |
139 | | -if (process.env.NODE_ENV !== 'test') { |
| 146 | +if (process.env.NODE_ENV !== "test") { |
140 | 147 | validateConfig(); |
141 | 148 | } |
142 | 149 |
|
|
0 commit comments