moved to zod, packages messed up still
This commit is contained in:
parent
15dd03c0ec
commit
a8ee4022bf
35 changed files with 3245 additions and 691 deletions
|
|
@ -1,29 +1,31 @@
|
|||
/**
|
||||
* Admin interfaces configuration using envalid
|
||||
* Admin interfaces configuration using Zod
|
||||
* PgAdmin, Mongo Express, Redis Insight for database management
|
||||
*/
|
||||
import { cleanEnv, str, port, bool } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, port, bool, strWithChoices } = envValidators;
|
||||
|
||||
/**
|
||||
* PgAdmin configuration with validation and defaults
|
||||
*/
|
||||
export const pgAdminConfig = cleanEnv(process.env, {
|
||||
// PgAdmin Server
|
||||
PGADMIN_HOST: str({ default: 'localhost', desc: 'PgAdmin host' }),
|
||||
PGADMIN_PORT: port({ default: 8080, desc: 'PgAdmin port' }),
|
||||
PGADMIN_HOST: str('localhost', 'PgAdmin host'),
|
||||
PGADMIN_PORT: port(8080, 'PgAdmin port'),
|
||||
|
||||
// Authentication
|
||||
PGADMIN_DEFAULT_EMAIL: str({ default: 'admin@tradingbot.local', desc: 'PgAdmin default admin email' }),
|
||||
PGADMIN_DEFAULT_PASSWORD: str({ default: 'admin123', desc: 'PgAdmin default admin password' }),
|
||||
PGADMIN_DEFAULT_EMAIL: str('admin@tradingbot.local', 'PgAdmin default admin email'),
|
||||
PGADMIN_DEFAULT_PASSWORD: str('admin123', 'PgAdmin default admin password'),
|
||||
|
||||
// Configuration
|
||||
PGADMIN_SERVER_MODE: bool({ default: false, desc: 'Enable server mode (multi-user)' }),
|
||||
PGADMIN_DISABLE_POSTFIX: bool({ default: true, desc: 'Disable postfix for email' }),
|
||||
PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION: bool({ default: true, desc: 'Enhanced cookie protection' }),
|
||||
PGADMIN_SERVER_MODE: bool(false, 'Enable server mode (multi-user)'),
|
||||
PGADMIN_DISABLE_POSTFIX: bool(true, 'Disable postfix for email'),
|
||||
PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION: bool(true, 'Enhanced cookie protection'),
|
||||
|
||||
// Security
|
||||
PGADMIN_MASTER_PASSWORD_REQUIRED: bool({ default: false, desc: 'Require master password' }),
|
||||
PGADMIN_SESSION_TIMEOUT: str({ default: '60', desc: 'Session timeout in minutes' }),
|
||||
PGADMIN_MASTER_PASSWORD_REQUIRED: bool(false, 'Require master password'),
|
||||
PGADMIN_SESSION_TIMEOUT: str('60', 'Session timeout in minutes'),
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -31,26 +33,23 @@ export const pgAdminConfig = cleanEnv(process.env, {
|
|||
*/
|
||||
export const mongoExpressConfig = cleanEnv(process.env, {
|
||||
// Mongo Express Server
|
||||
MONGO_EXPRESS_HOST: str({ default: 'localhost', desc: 'Mongo Express host' }),
|
||||
MONGO_EXPRESS_PORT: port({ default: 8081, desc: 'Mongo Express port' }),
|
||||
MONGO_EXPRESS_HOST: str('localhost', 'Mongo Express host'),
|
||||
MONGO_EXPRESS_PORT: port(8081, 'Mongo Express port'),
|
||||
|
||||
// MongoDB Connection
|
||||
MONGO_EXPRESS_MONGODB_SERVER: str({ default: 'mongodb', desc: 'MongoDB server name/host' }),
|
||||
MONGO_EXPRESS_MONGODB_PORT: port({ default: 27017, desc: 'MongoDB port' }),
|
||||
MONGO_EXPRESS_MONGODB_ADMINUSERNAME: str({ default: 'trading_admin', desc: 'MongoDB admin username' }),
|
||||
MONGO_EXPRESS_MONGODB_ADMINPASSWORD: str({ default: '', desc: 'MongoDB admin password' }),
|
||||
MONGO_EXPRESS_MONGODB_SERVER: str('mongodb', 'MongoDB server name/host'),
|
||||
MONGO_EXPRESS_MONGODB_PORT: port(27017, 'MongoDB port'),
|
||||
MONGO_EXPRESS_MONGODB_ADMINUSERNAME: str('trading_admin', 'MongoDB admin username'),
|
||||
MONGO_EXPRESS_MONGODB_ADMINPASSWORD: str('', 'MongoDB admin password'),
|
||||
|
||||
// Basic Authentication for Mongo Express
|
||||
MONGO_EXPRESS_BASICAUTH_USERNAME: str({ default: 'admin', desc: 'Basic auth username for Mongo Express' }),
|
||||
MONGO_EXPRESS_BASICAUTH_PASSWORD: str({ default: 'admin123', desc: 'Basic auth password for Mongo Express' }),
|
||||
MONGO_EXPRESS_BASICAUTH_USERNAME: str('admin', 'Basic auth username for Mongo Express'),
|
||||
MONGO_EXPRESS_BASICAUTH_PASSWORD: str('admin123', 'Basic auth password for Mongo Express'),
|
||||
|
||||
// Configuration
|
||||
MONGO_EXPRESS_ENABLE_ADMIN: bool({ default: true, desc: 'Enable admin features' }),
|
||||
MONGO_EXPRESS_OPTIONS_EDITOR_THEME: str({
|
||||
default: 'rubyblue',
|
||||
desc: 'Editor theme (rubyblue, 3024-night, etc.)'
|
||||
}),
|
||||
MONGO_EXPRESS_REQUEST_SIZE: str({ default: '100kb', desc: 'Maximum request size' }),
|
||||
MONGO_EXPRESS_ENABLE_ADMIN: bool(true, 'Enable admin features'),
|
||||
MONGO_EXPRESS_OPTIONS_EDITOR_THEME: str('rubyblue', 'Editor theme (rubyblue, 3024-night, etc.)'),
|
||||
MONGO_EXPRESS_REQUEST_SIZE: str('100kb', 'Maximum request size'),
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -58,23 +57,16 @@ export const mongoExpressConfig = cleanEnv(process.env, {
|
|||
*/
|
||||
export const redisInsightConfig = cleanEnv(process.env, {
|
||||
// Redis Insight Server
|
||||
REDIS_INSIGHT_HOST: str({ default: 'localhost', desc: 'Redis Insight host' }),
|
||||
REDIS_INSIGHT_PORT: port({ default: 8001, desc: 'Redis Insight port' }),
|
||||
REDIS_INSIGHT_HOST: str('localhost', 'Redis Insight host'),
|
||||
REDIS_INSIGHT_PORT: port(8001, 'Redis Insight port'),
|
||||
|
||||
// Redis Connection Settings
|
||||
REDIS_INSIGHT_REDIS_HOSTS: str({
|
||||
default: 'local:dragonfly:6379',
|
||||
desc: 'Redis hosts in format name:host:port,name:host:port'
|
||||
}),
|
||||
REDIS_INSIGHT_REDIS_HOSTS: str('local:dragonfly:6379', 'Redis hosts in format name:host:port,name:host:port'),
|
||||
|
||||
// Configuration
|
||||
REDIS_INSIGHT_LOG_LEVEL: str({
|
||||
default: 'info',
|
||||
choices: ['error', 'warn', 'info', 'verbose', 'debug'],
|
||||
desc: 'Redis Insight log level'
|
||||
}),
|
||||
REDIS_INSIGHT_DISABLE_ANALYTICS: bool({ default: true, desc: 'Disable analytics collection' }),
|
||||
REDIS_INSIGHT_BUILD_TYPE: str({ default: 'DOCKER', desc: 'Build type identifier' }),
|
||||
REDIS_INSIGHT_LOG_LEVEL: strWithChoices(['error', 'warn', 'info', 'verbose', 'debug'], 'info', 'Redis Insight log level'),
|
||||
REDIS_INSIGHT_DISABLE_ANALYTICS: bool(true, 'Disable analytics collection'),
|
||||
REDIS_INSIGHT_BUILD_TYPE: str('DOCKER', 'Build type identifier'),
|
||||
});
|
||||
|
||||
// Export typed configuration objects
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Core configuration module for the Stock Bot platform using envalid
|
||||
* Core configuration module for the Stock Bot platform using Zod
|
||||
*/
|
||||
import { config as dotenvConfig } from 'dotenv';
|
||||
import path from 'node:path';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/**
|
||||
* Data provider configurations using envalid
|
||||
* Data provider configurations using Zod
|
||||
*/
|
||||
import { cleanEnv, str, num, bool } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, num, bool, strWithChoices } = envValidators;
|
||||
|
||||
export interface ProviderConfig {
|
||||
name: string;
|
||||
|
|
@ -21,45 +23,41 @@ export interface ProviderConfig {
|
|||
*/
|
||||
export const dataProvidersConfig = cleanEnv(process.env, {
|
||||
// Default Provider
|
||||
DEFAULT_DATA_PROVIDER: str({
|
||||
choices: ['alpaca', 'polygon', 'yahoo', 'iex'],
|
||||
default: 'alpaca',
|
||||
desc: 'Default data provider'
|
||||
}),
|
||||
DEFAULT_DATA_PROVIDER: strWithChoices(['alpaca', 'polygon', 'yahoo', 'iex'], 'alpaca', 'Default data provider'),
|
||||
|
||||
// Alpaca Configuration
|
||||
ALPACA_API_KEY: str({ default: '', desc: 'Alpaca API key' }),
|
||||
ALPACA_API_SECRET: str({ default: '', desc: 'Alpaca API secret' }),
|
||||
ALPACA_BASE_URL: str({ default: 'https://data.alpaca.markets/v1beta1', desc: 'Alpaca base URL' }),
|
||||
ALPACA_RATE_LIMIT: num({ default: 200, desc: 'Alpaca rate limit per minute' }),
|
||||
ALPACA_ENABLED: bool({ default: true, desc: 'Enable Alpaca provider' }),
|
||||
ALPACA_API_KEY: str('', 'Alpaca API key'),
|
||||
ALPACA_API_SECRET: str('', 'Alpaca API secret'),
|
||||
ALPACA_BASE_URL: str('https://data.alpaca.markets/v1beta1', 'Alpaca base URL'),
|
||||
ALPACA_RATE_LIMIT: num(200, 'Alpaca rate limit per minute'),
|
||||
ALPACA_ENABLED: bool(true, 'Enable Alpaca provider'),
|
||||
|
||||
// Polygon Configuration
|
||||
POLYGON_API_KEY: str({ default: '', desc: 'Polygon API key' }),
|
||||
POLYGON_BASE_URL: str({ default: 'https://api.polygon.io', desc: 'Polygon base URL' }),
|
||||
POLYGON_RATE_LIMIT: num({ default: 5, desc: 'Polygon rate limit per minute' }),
|
||||
POLYGON_ENABLED: bool({ default: false, desc: 'Enable Polygon provider' }),
|
||||
POLYGON_API_KEY: str('', 'Polygon API key'),
|
||||
POLYGON_BASE_URL: str('https://api.polygon.io', 'Polygon base URL'),
|
||||
POLYGON_RATE_LIMIT: num(5, 'Polygon rate limit per minute'),
|
||||
POLYGON_ENABLED: bool(false, 'Enable Polygon provider'),
|
||||
|
||||
// Yahoo Finance Configuration
|
||||
YAHOO_BASE_URL: str({ default: 'https://query1.finance.yahoo.com', desc: 'Yahoo Finance base URL' }),
|
||||
YAHOO_RATE_LIMIT: num({ default: 2000, desc: 'Yahoo Finance rate limit per hour' }),
|
||||
YAHOO_ENABLED: bool({ default: true, desc: 'Enable Yahoo Finance provider' }),
|
||||
YAHOO_BASE_URL: str('https://query1.finance.yahoo.com', 'Yahoo Finance base URL'),
|
||||
YAHOO_RATE_LIMIT: num(2000, 'Yahoo Finance rate limit per hour'),
|
||||
YAHOO_ENABLED: bool(true, 'Enable Yahoo Finance provider'),
|
||||
|
||||
// IEX Cloud Configuration
|
||||
IEX_API_KEY: str({ default: '', desc: 'IEX Cloud API key' }),
|
||||
IEX_BASE_URL: str({ default: 'https://cloud.iexapis.com/stable', desc: 'IEX Cloud base URL' }),
|
||||
IEX_RATE_LIMIT: num({ default: 100, desc: 'IEX Cloud rate limit per second' }),
|
||||
IEX_ENABLED: bool({ default: false, desc: 'Enable IEX Cloud provider' }),
|
||||
IEX_API_KEY: str('', 'IEX Cloud API key'),
|
||||
IEX_BASE_URL: str('https://cloud.iexapis.com/stable', 'IEX Cloud base URL'),
|
||||
IEX_RATE_LIMIT: num(100, 'IEX Cloud rate limit per second'),
|
||||
IEX_ENABLED: bool(false, 'Enable IEX Cloud provider'),
|
||||
|
||||
// Connection Settings
|
||||
DATA_PROVIDER_TIMEOUT: num({ default: 30000, desc: 'Request timeout in milliseconds' }),
|
||||
DATA_PROVIDER_RETRIES: num({ default: 3, desc: 'Number of retry attempts' }),
|
||||
DATA_PROVIDER_RETRY_DELAY: num({ default: 1000, desc: 'Retry delay in milliseconds' }),
|
||||
DATA_PROVIDER_TIMEOUT: num(30000, 'Request timeout in milliseconds'),
|
||||
DATA_PROVIDER_RETRIES: num(3, 'Number of retry attempts'),
|
||||
DATA_PROVIDER_RETRY_DELAY: num(1000, 'Retry delay in milliseconds'),
|
||||
|
||||
// Cache Settings
|
||||
DATA_CACHE_ENABLED: bool({ default: true, desc: 'Enable data caching' }),
|
||||
DATA_CACHE_TTL: num({ default: 300000, desc: 'Cache TTL in milliseconds' }),
|
||||
DATA_CACHE_MAX_SIZE: num({ default: 1000, desc: 'Maximum cache entries' }),
|
||||
DATA_CACHE_ENABLED: bool(true, 'Enable data caching'),
|
||||
DATA_CACHE_TTL: num(300000, 'Cache TTL in milliseconds'),
|
||||
DATA_CACHE_MAX_SIZE: num(1000, 'Maximum cache entries'),
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,34 +1,36 @@
|
|||
/**
|
||||
* Database configuration using envalid
|
||||
* Database configuration using Zod
|
||||
*/
|
||||
import { cleanEnv, str, port, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils.js';
|
||||
|
||||
const { str, port, num, bool } = envValidators;
|
||||
|
||||
/**
|
||||
* Database configuration with validation and defaults
|
||||
*/
|
||||
export const databaseConfig = cleanEnv(process.env, {
|
||||
// PostgreSQL Configuration
|
||||
DB_HOST: str({ default: 'localhost', desc: 'Database host' }),
|
||||
DB_PORT: port({ default: 5432, desc: 'Database port' }),
|
||||
DB_NAME: str({ default: 'stockbot', desc: 'Database name' }),
|
||||
DB_USER: str({ default: 'stockbot', desc: 'Database user' }),
|
||||
DB_PASSWORD: str({ default: '', desc: 'Database password' }),
|
||||
DB_HOST: str('localhost', 'Database host'),
|
||||
DB_PORT: port(5432, 'Database port'),
|
||||
DB_NAME: str('stockbot', 'Database name'),
|
||||
DB_USER: str('stockbot', 'Database user'),
|
||||
DB_PASSWORD: str('', 'Database password'),
|
||||
|
||||
// Connection Pool Settings
|
||||
DB_POOL_MIN: num({ default: 2, desc: 'Minimum pool connections' }),
|
||||
DB_POOL_MAX: num({ default: 10, desc: 'Maximum pool connections' }),
|
||||
DB_POOL_IDLE_TIMEOUT: num({ default: 30000, desc: 'Pool idle timeout in ms' }),
|
||||
DB_POOL_MIN: num(2, 'Minimum pool connections'),
|
||||
DB_POOL_MAX: num(10, 'Maximum pool connections'),
|
||||
DB_POOL_IDLE_TIMEOUT: num(30000, 'Pool idle timeout in ms'),
|
||||
|
||||
// SSL Configuration
|
||||
DB_SSL: bool({ default: false, desc: 'Enable SSL for database connection' }),
|
||||
DB_SSL_REJECT_UNAUTHORIZED: bool({ default: true, desc: 'Reject unauthorized SSL certificates' }),
|
||||
DB_SSL: bool(false, 'Enable SSL for database connection'),
|
||||
DB_SSL_REJECT_UNAUTHORIZED: bool(true, 'Reject unauthorized SSL certificates'),
|
||||
|
||||
// Additional Settings
|
||||
DB_QUERY_TIMEOUT: num({ default: 30000, desc: 'Query timeout in ms' }),
|
||||
DB_CONNECTION_TIMEOUT: num({ default: 5000, desc: 'Connection timeout in ms' }),
|
||||
DB_STATEMENT_TIMEOUT: num({ default: 30000, desc: 'Statement timeout in ms' }),
|
||||
DB_LOCK_TIMEOUT: num({ default: 10000, desc: 'Lock timeout in ms' }),
|
||||
DB_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: num({ default: 60000, desc: 'Idle in transaction timeout in ms' }),
|
||||
DB_QUERY_TIMEOUT: num(30000, 'Query timeout in ms'),
|
||||
DB_CONNECTION_TIMEOUT: num(5000, 'Connection timeout in ms'),
|
||||
DB_STATEMENT_TIMEOUT: num(30000, 'Statement timeout in ms'),
|
||||
DB_LOCK_TIMEOUT: num(10000, 'Lock timeout in ms'),
|
||||
DB_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: num(60000, 'Idle in transaction timeout in ms'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
|
|
@ -1,51 +1,53 @@
|
|||
/**
|
||||
* Dragonfly (Redis replacement) configuration using envalid
|
||||
* Dragonfly (Redis replacement) configuration using Zod
|
||||
* High-performance caching and event streaming
|
||||
*/
|
||||
import { cleanEnv, str, port, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils.js';
|
||||
|
||||
const { str, port, num, bool } = envValidators;
|
||||
|
||||
/**
|
||||
* Dragonfly configuration with validation and defaults
|
||||
*/
|
||||
export const dragonflyConfig = cleanEnv(process.env, {
|
||||
// Dragonfly Connection
|
||||
DRAGONFLY_HOST: str({ default: 'localhost', desc: 'Dragonfly host' }),
|
||||
DRAGONFLY_PORT: port({ default: 6379, desc: 'Dragonfly port' }),
|
||||
DRAGONFLY_PASSWORD: str({ default: '', desc: 'Dragonfly password (if auth enabled)' }),
|
||||
DRAGONFLY_USERNAME: str({ default: '', desc: 'Dragonfly username (if ACL enabled)' }),
|
||||
DRAGONFLY_HOST: str('localhost', 'Dragonfly host'),
|
||||
DRAGONFLY_PORT: port(6379, 'Dragonfly port'),
|
||||
DRAGONFLY_PASSWORD: str('', 'Dragonfly password (if auth enabled)'),
|
||||
DRAGONFLY_USERNAME: str('', 'Dragonfly username (if ACL enabled)'),
|
||||
|
||||
// Database Selection
|
||||
DRAGONFLY_DATABASE: num({ default: 0, desc: 'Dragonfly database number (0-15)' }),
|
||||
DRAGONFLY_DATABASE: num(0, 'Dragonfly database number (0-15)'),
|
||||
|
||||
// Connection Pool Settings
|
||||
DRAGONFLY_MAX_RETRIES: num({ default: 3, desc: 'Maximum retry attempts' }),
|
||||
DRAGONFLY_RETRY_DELAY: num({ default: 50, desc: 'Retry delay in ms' }),
|
||||
DRAGONFLY_CONNECT_TIMEOUT: num({ default: 10000, desc: 'Connection timeout in ms' }),
|
||||
DRAGONFLY_COMMAND_TIMEOUT: num({ default: 5000, desc: 'Command timeout in ms' }),
|
||||
DRAGONFLY_MAX_RETRIES: num(3, 'Maximum retry attempts'),
|
||||
DRAGONFLY_RETRY_DELAY: num(50, 'Retry delay in ms'),
|
||||
DRAGONFLY_CONNECT_TIMEOUT: num(10000, 'Connection timeout in ms'),
|
||||
DRAGONFLY_COMMAND_TIMEOUT: num(5000, 'Command timeout in ms'),
|
||||
|
||||
// Pool Configuration
|
||||
DRAGONFLY_POOL_SIZE: num({ default: 10, desc: 'Connection pool size' }),
|
||||
DRAGONFLY_POOL_MIN: num({ default: 1, desc: 'Minimum pool connections' }),
|
||||
DRAGONFLY_POOL_MAX: num({ default: 20, desc: 'Maximum pool connections' }),
|
||||
DRAGONFLY_POOL_SIZE: num(10, 'Connection pool size'),
|
||||
DRAGONFLY_POOL_MIN: num(1, 'Minimum pool connections'),
|
||||
DRAGONFLY_POOL_MAX: num(20, 'Maximum pool connections'),
|
||||
|
||||
// TLS Settings
|
||||
DRAGONFLY_TLS: bool({ default: false, desc: 'Enable TLS for Dragonfly connection' }),
|
||||
DRAGONFLY_TLS_CERT_FILE: str({ default: '', desc: 'Path to TLS certificate file' }),
|
||||
DRAGONFLY_TLS_KEY_FILE: str({ default: '', desc: 'Path to TLS key file' }),
|
||||
DRAGONFLY_TLS_CA_FILE: str({ default: '', desc: 'Path to TLS CA certificate file' }),
|
||||
DRAGONFLY_TLS_SKIP_VERIFY: bool({ default: false, desc: 'Skip TLS certificate verification' }),
|
||||
DRAGONFLY_TLS: bool(false, 'Enable TLS for Dragonfly connection'),
|
||||
DRAGONFLY_TLS_CERT_FILE: str('', 'Path to TLS certificate file'),
|
||||
DRAGONFLY_TLS_KEY_FILE: str('', 'Path to TLS key file'),
|
||||
DRAGONFLY_TLS_CA_FILE: str('', 'Path to TLS CA certificate file'),
|
||||
DRAGONFLY_TLS_SKIP_VERIFY: bool(false, 'Skip TLS certificate verification'),
|
||||
|
||||
// Performance Settings
|
||||
DRAGONFLY_ENABLE_KEEPALIVE: bool({ default: true, desc: 'Enable TCP keepalive' }),
|
||||
DRAGONFLY_KEEPALIVE_INTERVAL: num({ default: 60, desc: 'Keepalive interval in seconds' }),
|
||||
DRAGONFLY_ENABLE_KEEPALIVE: bool(true, 'Enable TCP keepalive'),
|
||||
DRAGONFLY_KEEPALIVE_INTERVAL: num(60, 'Keepalive interval in seconds'),
|
||||
|
||||
// Clustering (if using cluster mode)
|
||||
DRAGONFLY_CLUSTER_MODE: bool({ default: false, desc: 'Enable cluster mode' }),
|
||||
DRAGONFLY_CLUSTER_NODES: str({ default: '', desc: 'Comma-separated list of cluster nodes (host:port)' }),
|
||||
DRAGONFLY_CLUSTER_MODE: bool(false, 'Enable cluster mode'),
|
||||
DRAGONFLY_CLUSTER_NODES: str('', 'Comma-separated list of cluster nodes (host:port)'),
|
||||
|
||||
// Memory and Cache Settings
|
||||
DRAGONFLY_MAX_MEMORY: str({ default: '2gb', desc: 'Maximum memory usage' }),
|
||||
DRAGONFLY_CACHE_MODE: bool({ default: true, desc: 'Enable cache mode' }),
|
||||
DRAGONFLY_MAX_MEMORY: str('2gb', 'Maximum memory usage'),
|
||||
DRAGONFLY_CACHE_MODE: bool(true, 'Enable cache mode'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
91
libs/config/src/env-utils.ts
Normal file
91
libs/config/src/env-utils.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Environment validation utilities using Zod
|
||||
*/
|
||||
import { z } from 'zod';
|
||||
import { config } from 'dotenv';
|
||||
|
||||
// Load environment variables
|
||||
config();
|
||||
|
||||
/**
|
||||
* Creates a Zod schema for environment variable validation
|
||||
*/
|
||||
export function createEnvSchema<T extends z.ZodRawShape>(shape: T) {
|
||||
return z.object(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates environment variables against a Zod schema
|
||||
*/
|
||||
export function validateEnv<T extends z.ZodRawShape>(
|
||||
schema: z.ZodObject<T>,
|
||||
env = process.env
|
||||
): z.infer<z.ZodObject<T>> {
|
||||
const result = schema.safeParse(env);
|
||||
|
||||
if (!result.success) {
|
||||
console.error('❌ Invalid environment variables:');
|
||||
result.error.issues.forEach((issue: any) => {
|
||||
console.error(` ${issue.path.join('.')}: ${issue.message}`);
|
||||
});
|
||||
throw new Error('Environment validation failed');
|
||||
}
|
||||
|
||||
return result.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper functions for common validation patterns
|
||||
*/
|
||||
export const envValidators = { // String with default
|
||||
str: (defaultValue?: string, description?: string) =>
|
||||
z.string().default(defaultValue || '').describe(description || ''),
|
||||
|
||||
// String with choices (enum)
|
||||
strWithChoices: (choices: string[], defaultValue?: string, description?: string) =>
|
||||
z.enum(choices as [string, ...string[]])
|
||||
.default((defaultValue || choices[0]) as any)
|
||||
.describe(description || ''),
|
||||
|
||||
// Required string
|
||||
requiredStr: (description?: string) =>
|
||||
z.string().min(1, 'Required').describe(description || ''),
|
||||
// Port number
|
||||
port: (defaultValue?: number, description?: string) =>
|
||||
z.string().transform((val: string) => parseInt(val, 10))
|
||||
.pipe(z.number().int().min(1).max(65535))
|
||||
.default(defaultValue?.toString() || '3000')
|
||||
.describe(description || ''),
|
||||
// Number with default
|
||||
num: (defaultValue?: number, description?: string) =>
|
||||
z.string().transform((val: string) => parseInt(val, 10))
|
||||
.pipe(z.number())
|
||||
.default(defaultValue?.toString() || '0')
|
||||
.describe(description || ''),
|
||||
|
||||
// Boolean with default
|
||||
bool: (defaultValue?: boolean, description?: string) =>
|
||||
z.string().transform((val: string) => val === 'true' || val === '1')
|
||||
.default(defaultValue?.toString() || 'false')
|
||||
.describe(description || ''),
|
||||
|
||||
// URL validation
|
||||
url: (defaultValue?: string, description?: string) =>
|
||||
z.string().url().default(defaultValue || 'http://localhost')
|
||||
.describe(description || ''),
|
||||
|
||||
// Email validation
|
||||
email: (description?: string) =>
|
||||
z.string().email().describe(description || ''),
|
||||
};
|
||||
|
||||
/**
|
||||
* Legacy compatibility - creates a cleanEnv-like function
|
||||
*/
|
||||
export function cleanEnv<T extends z.ZodRawShape>(
|
||||
env: Record<string, string | undefined>,
|
||||
validators: T
|
||||
): z.infer<z.ZodObject<T>> {
|
||||
const schema = createEnvSchema(validators);
|
||||
return validateEnv(schema, env);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Example usage of the Stock Bot configuration library
|
||||
*
|
||||
* This file demonstrates how to use the envalid-based configuration
|
||||
* This file demonstrates how to use the Zod-based configuration
|
||||
* system for various services in the Stock Bot platform.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,20 @@
|
|||
/**
|
||||
* @stock-bot/config
|
||||
*
|
||||
* Configuration management library for Stock Bot platform using envalid
|
||||
* Configuration management library for Stock Bot platform using Zod
|
||||
*/
|
||||
|
||||
// Core configuration functionality
|
||||
// Re-export everything from all modules
|
||||
export * from './env-utils';
|
||||
export * from './core';
|
||||
|
||||
// Database configurations
|
||||
export * from './admin-interfaces';
|
||||
export * from './database';
|
||||
export * from './dragonfly';
|
||||
export * from './postgres';
|
||||
export * from './questdb';
|
||||
export * from './mongodb';
|
||||
export * from './dragonfly';
|
||||
|
||||
// Logging and monitoring configurations
|
||||
export * from './logging';
|
||||
export * from './loki';
|
||||
export * from './monitoring';
|
||||
|
||||
// Data provider configurations
|
||||
export * from './data-providers';
|
||||
|
||||
// Risk management configurations
|
||||
export * from './risk';
|
||||
|
|
|
|||
|
|
@ -1,55 +1,48 @@
|
|||
/**
|
||||
* Logging configuration using envalid
|
||||
* Logging configuration using Zod
|
||||
* Application logging settings without Loki (Loki config is in monitoring.ts)
|
||||
*/
|
||||
import { cleanEnv, str, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, bool, num, strWithChoices } = envValidators;
|
||||
|
||||
/**
|
||||
* Logging configuration with validation and defaults
|
||||
*/
|
||||
export const loggingConfig = cleanEnv(process.env, {
|
||||
// Basic Logging Settings
|
||||
LOG_LEVEL: str({
|
||||
default: 'info',
|
||||
choices: ['debug' , 'info' , 'warn' , 'error'],
|
||||
desc: 'Logging level'
|
||||
}),
|
||||
LOG_FORMAT: str({
|
||||
default: 'json',
|
||||
choices: ['json', 'simple', 'combined'],
|
||||
desc: 'Log output format'
|
||||
}),
|
||||
LOG_CONSOLE: bool({ default: true, desc: 'Enable console logging' }),
|
||||
LOG_FILE: bool({ default: false, desc: 'Enable file logging' }),
|
||||
LOG_LEVEL: strWithChoices(['debug', 'info', 'warn', 'error'], 'info', 'Logging level'),
|
||||
LOG_FORMAT: strWithChoices(['json', 'simple', 'combined'], 'json', 'Log output format'),
|
||||
LOG_CONSOLE: bool(true, 'Enable console logging'),
|
||||
LOG_FILE: bool(false, 'Enable file logging'),
|
||||
|
||||
// File Logging Settings
|
||||
LOG_FILE_PATH: str({ default: 'logs', desc: 'Log file directory path' }),
|
||||
LOG_FILE_MAX_SIZE: str({ default: '20m', desc: 'Maximum log file size' }),
|
||||
LOG_FILE_MAX_FILES: num({ default: 14, desc: 'Maximum number of log files to keep' }),
|
||||
LOG_FILE_DATE_PATTERN: str({ default: 'YYYY-MM-DD', desc: 'Log file date pattern' }),
|
||||
LOG_FILE_PATH: str('logs', 'Log file directory path'),
|
||||
LOG_FILE_MAX_SIZE: str('20m', 'Maximum log file size'),
|
||||
LOG_FILE_MAX_FILES: num(14, 'Maximum number of log files to keep'),
|
||||
LOG_FILE_DATE_PATTERN: str('YYYY-MM-DD', 'Log file date pattern'),
|
||||
|
||||
// Error Logging
|
||||
LOG_ERROR_FILE: bool({ default: true, desc: 'Enable separate error log file' }),
|
||||
LOG_ERROR_STACK: bool({ default: true, desc: 'Include stack traces in error logs' }),
|
||||
LOG_ERROR_FILE: bool(true, 'Enable separate error log file'),
|
||||
LOG_ERROR_STACK: bool(true, 'Include stack traces in error logs'),
|
||||
|
||||
// Performance Logging
|
||||
LOG_PERFORMANCE: bool({ default: false, desc: 'Enable performance logging' }),
|
||||
LOG_SQL_QUERIES: bool({ default: false, desc: 'Log SQL queries' }),
|
||||
LOG_HTTP_REQUESTS: bool({ default: true, desc: 'Log HTTP requests' }),
|
||||
LOG_PERFORMANCE: bool(false, 'Enable performance logging'),
|
||||
LOG_SQL_QUERIES: bool(false, 'Log SQL queries'),
|
||||
LOG_HTTP_REQUESTS: bool(true, 'Log HTTP requests'),
|
||||
|
||||
// Structured Logging
|
||||
LOG_STRUCTURED: bool({ default: true, desc: 'Use structured logging format' }),
|
||||
LOG_TIMESTAMP: bool({ default: true, desc: 'Include timestamps in logs' }),
|
||||
LOG_CALLER_INFO: bool({ default: false, desc: 'Include caller information in logs' }),
|
||||
|
||||
// Log Filtering
|
||||
LOG_SILENT_MODULES: str({ default: '', desc: 'Comma-separated list of modules to silence' }),
|
||||
LOG_VERBOSE_MODULES: str({ default: '', desc: 'Comma-separated list of modules for verbose logging' }),
|
||||
LOG_STRUCTURED: bool(true, 'Use structured logging format'),
|
||||
LOG_TIMESTAMP: bool(true, 'Include timestamps in logs'),
|
||||
LOG_CALLER_INFO: bool(false, 'Include caller information in logs'),
|
||||
// Log Filtering
|
||||
LOG_SILENT_MODULES: str('', 'Comma-separated list of modules to silence'),
|
||||
LOG_VERBOSE_MODULES: str('', 'Comma-separated list of modules for verbose logging'),
|
||||
|
||||
// Application Context
|
||||
LOG_SERVICE_NAME: str({ default: 'stock-bot', desc: 'Service name for log context' }),
|
||||
LOG_SERVICE_VERSION: str({ default: '1.0.0', desc: 'Service version for log context' }),
|
||||
LOG_ENVIRONMENT: str({ default: 'development', desc: 'Environment for log context' }),
|
||||
LOG_SERVICE_NAME: str('stock-bot', 'Service name for log context'),
|
||||
LOG_SERVICE_VERSION: str('1.0.0', 'Service version for log context'),
|
||||
LOG_ENVIRONMENT: str('development', 'Environment for log context'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
|
|
@ -1,40 +1,42 @@
|
|||
/**
|
||||
* Loki log aggregation configuration using envalid
|
||||
* Loki log aggregation configuration using Zod
|
||||
* Centralized logging configuration for the Stock Bot platform
|
||||
*/
|
||||
import { cleanEnv, str, port, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, port, bool, num } = envValidators;
|
||||
|
||||
/**
|
||||
* Loki configuration with validation and defaults
|
||||
*/
|
||||
export const lokiConfig = cleanEnv(process.env, {
|
||||
// Loki Server
|
||||
LOKI_HOST: str({ default: 'localhost', desc: 'Loki host' }),
|
||||
LOKI_PORT: port({ default: 3100, desc: 'Loki port' }),
|
||||
LOKI_URL: str({ default: '', desc: 'Complete Loki URL (overrides host/port)' }),
|
||||
LOKI_HOST: str('localhost', 'Loki host'),
|
||||
LOKI_PORT: port(3100, 'Loki port'),
|
||||
LOKI_URL: str('', 'Complete Loki URL (overrides host/port)'),
|
||||
|
||||
// Authentication
|
||||
LOKI_USERNAME: str({ default: '', desc: 'Loki username (if auth enabled)' }),
|
||||
LOKI_PASSWORD: str({ default: '', desc: 'Loki password (if auth enabled)' }),
|
||||
LOKI_TENANT_ID: str({ default: '', desc: 'Loki tenant ID (for multi-tenancy)' }),
|
||||
LOKI_USERNAME: str('', 'Loki username (if auth enabled)'),
|
||||
LOKI_PASSWORD: str('', 'Loki password (if auth enabled)'),
|
||||
LOKI_TENANT_ID: str('', 'Loki tenant ID (for multi-tenancy)'),
|
||||
|
||||
// Push Configuration
|
||||
LOKI_PUSH_TIMEOUT: num({ default: 10000, desc: 'Push timeout in ms' }),
|
||||
LOKI_BATCH_SIZE: num({ default: 1024, desc: 'Batch size for log entries' }),
|
||||
LOKI_BATCH_WAIT: num({ default: 5, desc: 'Batch wait time in ms' }),
|
||||
LOKI_PUSH_TIMEOUT: num(10000, 'Push timeout in ms'),
|
||||
LOKI_BATCH_SIZE: num(1024, 'Batch size for log entries'),
|
||||
LOKI_BATCH_WAIT: num(5, 'Batch wait time in ms'),
|
||||
|
||||
// Retention Settings
|
||||
LOKI_RETENTION_PERIOD: str({ default: '30d', desc: 'Log retention period' }),
|
||||
LOKI_MAX_CHUNK_AGE: str({ default: '1h', desc: 'Maximum chunk age' }),
|
||||
LOKI_RETENTION_PERIOD: str('30d', 'Log retention period'),
|
||||
LOKI_MAX_CHUNK_AGE: str('1h', 'Maximum chunk age'),
|
||||
|
||||
// TLS Settings
|
||||
LOKI_TLS_ENABLED: bool({ default: false, desc: 'Enable TLS for Loki' }),
|
||||
LOKI_TLS_INSECURE: bool({ default: false, desc: 'Skip TLS verification' }),
|
||||
LOKI_TLS_ENABLED: bool(false, 'Enable TLS for Loki'),
|
||||
LOKI_TLS_INSECURE: bool(false, 'Skip TLS verification'),
|
||||
|
||||
// Log Labels
|
||||
LOKI_DEFAULT_LABELS: str({ default: '', desc: 'Default labels for all log entries (JSON format)' }),
|
||||
LOKI_SERVICE_LABEL: str({ default: 'stock-bot', desc: 'Service label for log entries' }),
|
||||
LOKI_ENVIRONMENT_LABEL: str({ default: 'development', desc: 'Environment label for log entries' }),
|
||||
LOKI_DEFAULT_LABELS: str('', 'Default labels for all log entries (JSON format)'),
|
||||
LOKI_SERVICE_LABEL: str('stock-bot', 'Service label for log entries'),
|
||||
LOKI_ENVIRONMENT_LABEL: str('development', 'Environment label for log entries'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
|
|
@ -1,50 +1,48 @@
|
|||
/**
|
||||
* MongoDB configuration using envalid
|
||||
* MongoDB configuration using Zod
|
||||
* Document storage for sentiment data, raw documents, and unstructured data
|
||||
*/
|
||||
import { cleanEnv, str, port, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, port, bool, num, strWithChoices } = envValidators;
|
||||
|
||||
/**
|
||||
* MongoDB configuration with validation and defaults
|
||||
*/
|
||||
export const mongodbConfig = cleanEnv(process.env, {
|
||||
// MongoDB Connection
|
||||
MONGODB_HOST: str({ default: 'localhost', desc: 'MongoDB host' }),
|
||||
MONGODB_PORT: port({ default: 27017, desc: 'MongoDB port' }),
|
||||
MONGODB_DATABASE: str({ default: 'trading_documents', desc: 'MongoDB database name' }),
|
||||
MONGODB_HOST: str('localhost', 'MongoDB host'),
|
||||
MONGODB_PORT: port(27017, 'MongoDB port'),
|
||||
MONGODB_DATABASE: str('trading_documents', 'MongoDB database name'),
|
||||
|
||||
// Authentication
|
||||
MONGODB_USERNAME: str({ default: 'trading_admin', desc: 'MongoDB username' }),
|
||||
MONGODB_PASSWORD: str({ default: '', desc: 'MongoDB password' }),
|
||||
MONGODB_AUTH_SOURCE: str({ default: 'admin', desc: 'MongoDB authentication database' }),
|
||||
MONGODB_USERNAME: str('trading_admin', 'MongoDB username'),
|
||||
MONGODB_PASSWORD: str('', 'MongoDB password'),
|
||||
MONGODB_AUTH_SOURCE: str('admin', 'MongoDB authentication database'),
|
||||
|
||||
// Connection URI (alternative to individual settings)
|
||||
MONGODB_URI: str({ default: '', desc: 'Complete MongoDB connection URI (overrides individual settings)' }),
|
||||
MONGODB_URI: str('', 'Complete MongoDB connection URI (overrides individual settings)'),
|
||||
|
||||
// Connection Pool Settings
|
||||
MONGODB_MAX_POOL_SIZE: num({ default: 10, desc: 'Maximum connection pool size' }),
|
||||
MONGODB_MIN_POOL_SIZE: num({ default: 0, desc: 'Minimum connection pool size' }),
|
||||
MONGODB_MAX_IDLE_TIME: num({ default: 30000, desc: 'Maximum idle time for connections in ms' }),
|
||||
MONGODB_MAX_POOL_SIZE: num(10, 'Maximum connection pool size'),
|
||||
MONGODB_MIN_POOL_SIZE: num(0, 'Minimum connection pool size'),
|
||||
MONGODB_MAX_IDLE_TIME: num(30000, 'Maximum idle time for connections in ms'),
|
||||
|
||||
// Timeouts
|
||||
MONGODB_CONNECT_TIMEOUT: num({ default: 10000, desc: 'Connection timeout in ms' }),
|
||||
MONGODB_SOCKET_TIMEOUT: num({ default: 30000, desc: 'Socket timeout in ms' }),
|
||||
MONGODB_SERVER_SELECTION_TIMEOUT: num({ default: 5000, desc: 'Server selection timeout in ms' }),
|
||||
MONGODB_CONNECT_TIMEOUT: num(10000, 'Connection timeout in ms'),
|
||||
MONGODB_SOCKET_TIMEOUT: num(30000, 'Socket timeout in ms'),
|
||||
MONGODB_SERVER_SELECTION_TIMEOUT: num(5000, 'Server selection timeout in ms'),
|
||||
|
||||
// SSL/TLS Settings
|
||||
MONGODB_TLS: bool({ default: false, desc: 'Enable TLS for MongoDB connection' }),
|
||||
MONGODB_TLS_INSECURE: bool({ default: false, desc: 'Allow invalid certificates in TLS mode' }),
|
||||
MONGODB_TLS_CA_FILE: str({ default: '', desc: 'Path to TLS CA certificate file' }),
|
||||
MONGODB_TLS: bool(false, 'Enable TLS for MongoDB connection'),
|
||||
MONGODB_TLS_INSECURE: bool(false, 'Allow invalid certificates in TLS mode'),
|
||||
MONGODB_TLS_CA_FILE: str('', 'Path to TLS CA certificate file'),
|
||||
|
||||
// Additional Settings
|
||||
MONGODB_RETRY_WRITES: bool({ default: true, desc: 'Enable retryable writes' }),
|
||||
MONGODB_JOURNAL: bool({ default: true, desc: 'Enable write concern journal' }),
|
||||
MONGODB_READ_PREFERENCE: str({
|
||||
default: 'primary',
|
||||
choices: ['primary', 'primaryPreferred', 'secondary', 'secondaryPreferred', 'nearest'],
|
||||
desc: 'MongoDB read preference'
|
||||
}),
|
||||
MONGODB_WRITE_CONCERN: str({ default: 'majority', desc: 'Write concern level' }),
|
||||
MONGODB_RETRY_WRITES: bool(true, 'Enable retryable writes'),
|
||||
MONGODB_JOURNAL: bool(true, 'Enable write concern journal'),
|
||||
MONGODB_READ_PREFERENCE: strWithChoices(['primary', 'primaryPreferred', 'secondary', 'secondaryPreferred', 'nearest'], 'primary', 'MongoDB read preference'),
|
||||
MONGODB_WRITE_CONCERN: str('majority', 'Write concern level'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
|
|
@ -1,30 +1,32 @@
|
|||
/**
|
||||
* Monitoring configuration using envalid
|
||||
* Monitoring configuration using Zod
|
||||
* Prometheus metrics, Grafana visualization, and Loki logging
|
||||
*/
|
||||
import { cleanEnv, str, port, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, port, bool, num, strWithChoices } = envValidators;
|
||||
|
||||
/**
|
||||
* Prometheus configuration with validation and defaults
|
||||
*/
|
||||
export const prometheusConfig = cleanEnv(process.env, {
|
||||
// Prometheus Server
|
||||
PROMETHEUS_HOST: str({ default: 'localhost', desc: 'Prometheus host' }),
|
||||
PROMETHEUS_PORT: port({ default: 9090, desc: 'Prometheus port' }),
|
||||
PROMETHEUS_URL: str({ default: '', desc: 'Complete Prometheus URL (overrides host/port)' }),
|
||||
PROMETHEUS_HOST: str('localhost', 'Prometheus host'),
|
||||
PROMETHEUS_PORT: port(9090, 'Prometheus port'),
|
||||
PROMETHEUS_URL: str('', 'Complete Prometheus URL (overrides host/port)'),
|
||||
|
||||
// Authentication
|
||||
PROMETHEUS_USERNAME: str({ default: '', desc: 'Prometheus username (if auth enabled)' }),
|
||||
PROMETHEUS_PASSWORD: str({ default: '', desc: 'Prometheus password (if auth enabled)' }),
|
||||
PROMETHEUS_USERNAME: str('', 'Prometheus username (if auth enabled)'),
|
||||
PROMETHEUS_PASSWORD: str('', 'Prometheus password (if auth enabled)'),
|
||||
|
||||
// Metrics Collection
|
||||
PROMETHEUS_SCRAPE_INTERVAL: str({ default: '15s', desc: 'Default scrape interval' }),
|
||||
PROMETHEUS_EVALUATION_INTERVAL: str({ default: '15s', desc: 'Rule evaluation interval' }),
|
||||
PROMETHEUS_RETENTION_TIME: str({ default: '15d', desc: 'Data retention time' }),
|
||||
PROMETHEUS_SCRAPE_INTERVAL: str('15s', 'Default scrape interval'),
|
||||
PROMETHEUS_EVALUATION_INTERVAL: str('15s', 'Rule evaluation interval'),
|
||||
PROMETHEUS_RETENTION_TIME: str('15d', 'Data retention time'),
|
||||
|
||||
// TLS Settings
|
||||
PROMETHEUS_TLS_ENABLED: bool({ default: false, desc: 'Enable TLS for Prometheus' }),
|
||||
PROMETHEUS_TLS_INSECURE: bool({ default: false, desc: 'Skip TLS verification' }),
|
||||
PROMETHEUS_TLS_ENABLED: bool(false, 'Enable TLS for Prometheus'),
|
||||
PROMETHEUS_TLS_INSECURE: bool(false, 'Skip TLS verification'),
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -32,29 +34,25 @@ export const prometheusConfig = cleanEnv(process.env, {
|
|||
*/
|
||||
export const grafanaConfig = cleanEnv(process.env, {
|
||||
// Grafana Server
|
||||
GRAFANA_HOST: str({ default: 'localhost', desc: 'Grafana host' }),
|
||||
GRAFANA_PORT: port({ default: 3000, desc: 'Grafana port' }),
|
||||
GRAFANA_URL: str({ default: '', desc: 'Complete Grafana URL (overrides host/port)' }),
|
||||
GRAFANA_HOST: str('localhost', 'Grafana host'),
|
||||
GRAFANA_PORT: port(3000, 'Grafana port'),
|
||||
GRAFANA_URL: str('', 'Complete Grafana URL (overrides host/port)'),
|
||||
|
||||
// Authentication
|
||||
GRAFANA_ADMIN_USER: str({ default: 'admin', desc: 'Grafana admin username' }),
|
||||
GRAFANA_ADMIN_PASSWORD: str({ default: 'admin', desc: 'Grafana admin password' }),
|
||||
GRAFANA_ADMIN_USER: str('admin', 'Grafana admin username'),
|
||||
GRAFANA_ADMIN_PASSWORD: str('admin', 'Grafana admin password'),
|
||||
|
||||
// Security Settings
|
||||
GRAFANA_ALLOW_SIGN_UP: bool({ default: false, desc: 'Allow user sign up' }),
|
||||
GRAFANA_SECRET_KEY: str({ default: '', desc: 'Grafana secret key for encryption' }),
|
||||
GRAFANA_ALLOW_SIGN_UP: bool(false, 'Allow user sign up'),
|
||||
GRAFANA_SECRET_KEY: str('', 'Grafana secret key for encryption'),
|
||||
|
||||
// Database Settings
|
||||
GRAFANA_DATABASE_TYPE: str({
|
||||
default: 'sqlite3',
|
||||
choices: ['mysql', 'postgres', 'sqlite3'],
|
||||
desc: 'Grafana database type'
|
||||
}),
|
||||
GRAFANA_DATABASE_URL: str({ default: '', desc: 'Grafana database URL' }),
|
||||
GRAFANA_DATABASE_TYPE: strWithChoices(['mysql', 'postgres', 'sqlite3'], 'sqlite3', 'Grafana database type'),
|
||||
GRAFANA_DATABASE_URL: str('', 'Grafana database URL'),
|
||||
|
||||
// Feature Flags
|
||||
GRAFANA_DISABLE_GRAVATAR: bool({ default: true, desc: 'Disable Gravatar avatars' }),
|
||||
GRAFANA_ENABLE_GZIP: bool({ default: true, desc: 'Enable gzip compression' }),
|
||||
GRAFANA_DISABLE_GRAVATAR: bool(true, 'Disable Gravatar avatars'),
|
||||
GRAFANA_ENABLE_GZIP: bool(true, 'Enable gzip compression'),
|
||||
});
|
||||
|
||||
// Export typed configuration objects
|
||||
|
|
|
|||
|
|
@ -1,34 +1,36 @@
|
|||
/**
|
||||
* PostgreSQL configuration using envalid
|
||||
* PostgreSQL configuration using Zod
|
||||
*/
|
||||
import { cleanEnv, str, port, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, port, bool, num } = envValidators;
|
||||
|
||||
/**
|
||||
* PostgreSQL configuration with validation and defaults
|
||||
*/
|
||||
export const postgresConfig = cleanEnv(process.env, {
|
||||
// PostgreSQL Connection Settings
|
||||
POSTGRES_HOST: str({ default: 'localhost', desc: 'PostgreSQL host' }),
|
||||
POSTGRES_PORT: port({ default: 5432, desc: 'PostgreSQL port' }),
|
||||
POSTGRES_DATABASE: str({ default: 'stockbot', desc: 'PostgreSQL database name' }),
|
||||
POSTGRES_USERNAME: str({ default: 'stockbot', desc: 'PostgreSQL username' }),
|
||||
POSTGRES_PASSWORD: str({ default: '', desc: 'PostgreSQL password' }),
|
||||
POSTGRES_HOST: str('localhost', 'PostgreSQL host'),
|
||||
POSTGRES_PORT: port(5432, 'PostgreSQL port'),
|
||||
POSTGRES_DATABASE: str('stockbot', 'PostgreSQL database name'),
|
||||
POSTGRES_USERNAME: str('stockbot', 'PostgreSQL username'),
|
||||
POSTGRES_PASSWORD: str('', 'PostgreSQL password'),
|
||||
|
||||
// Connection Pool Settings
|
||||
POSTGRES_POOL_MIN: num({ default: 2, desc: 'Minimum pool connections' }),
|
||||
POSTGRES_POOL_MAX: num({ default: 10, desc: 'Maximum pool connections' }),
|
||||
POSTGRES_POOL_IDLE_TIMEOUT: num({ default: 30000, desc: 'Pool idle timeout in ms' }),
|
||||
POSTGRES_POOL_MIN: num(2, 'Minimum pool connections'),
|
||||
POSTGRES_POOL_MAX: num(10, 'Maximum pool connections'),
|
||||
POSTGRES_POOL_IDLE_TIMEOUT: num(30000, 'Pool idle timeout in ms'),
|
||||
|
||||
// SSL Configuration
|
||||
POSTGRES_SSL: bool({ default: false, desc: 'Enable SSL for PostgreSQL connection' }),
|
||||
POSTGRES_SSL_REJECT_UNAUTHORIZED: bool({ default: true, desc: 'Reject unauthorized SSL certificates' }),
|
||||
POSTGRES_SSL: bool(false, 'Enable SSL for PostgreSQL connection'),
|
||||
POSTGRES_SSL_REJECT_UNAUTHORIZED: bool(true, 'Reject unauthorized SSL certificates'),
|
||||
|
||||
// Additional Settings
|
||||
POSTGRES_QUERY_TIMEOUT: num({ default: 30000, desc: 'Query timeout in ms' }),
|
||||
POSTGRES_CONNECTION_TIMEOUT: num({ default: 5000, desc: 'Connection timeout in ms' }),
|
||||
POSTGRES_STATEMENT_TIMEOUT: num({ default: 30000, desc: 'Statement timeout in ms' }),
|
||||
POSTGRES_LOCK_TIMEOUT: num({ default: 10000, desc: 'Lock timeout in ms' }),
|
||||
POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: num({ default: 60000, desc: 'Idle in transaction timeout in ms' }),
|
||||
POSTGRES_QUERY_TIMEOUT: num(30000, 'Query timeout in ms'),
|
||||
POSTGRES_CONNECTION_TIMEOUT: num(5000, 'Connection timeout in ms'),
|
||||
POSTGRES_STATEMENT_TIMEOUT: num(30000, 'Statement timeout in ms'),
|
||||
POSTGRES_LOCK_TIMEOUT: num(10000, 'Lock timeout in ms'),
|
||||
POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: num(60000, 'Idle in transaction timeout in ms'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
|
|
@ -1,35 +1,37 @@
|
|||
/**
|
||||
* QuestDB configuration using envalid
|
||||
* QuestDB configuration using Zod
|
||||
* Time-series database for OHLCV data, indicators, and performance metrics
|
||||
*/
|
||||
import { cleanEnv, str, port, bool, num } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, port, bool, num } = envValidators;
|
||||
|
||||
/**
|
||||
* QuestDB configuration with validation and defaults
|
||||
*/
|
||||
export const questdbConfig = cleanEnv(process.env, {
|
||||
// QuestDB Connection
|
||||
QUESTDB_HOST: str({ default: 'localhost', desc: 'QuestDB host' }),
|
||||
QUESTDB_HTTP_PORT: port({ default: 9000, desc: 'QuestDB HTTP port (web console)' }),
|
||||
QUESTDB_PG_PORT: port({ default: 8812, desc: 'QuestDB PostgreSQL wire protocol port' }),
|
||||
QUESTDB_INFLUX_PORT: port({ default: 9009, desc: 'QuestDB InfluxDB line protocol port' }),
|
||||
QUESTDB_HOST: str('localhost', 'QuestDB host'),
|
||||
QUESTDB_HTTP_PORT: port(9000, 'QuestDB HTTP port (web console)'),
|
||||
QUESTDB_PG_PORT: port(8812, 'QuestDB PostgreSQL wire protocol port'),
|
||||
QUESTDB_INFLUX_PORT: port(9009, 'QuestDB InfluxDB line protocol port'),
|
||||
|
||||
// Authentication (if enabled)
|
||||
QUESTDB_USER: str({ default: '', desc: 'QuestDB username (if auth enabled)' }),
|
||||
QUESTDB_PASSWORD: str({ default: '', desc: 'QuestDB password (if auth enabled)' }),
|
||||
QUESTDB_USER: str('', 'QuestDB username (if auth enabled)'),
|
||||
QUESTDB_PASSWORD: str('', 'QuestDB password (if auth enabled)'),
|
||||
|
||||
// Connection Settings
|
||||
QUESTDB_CONNECTION_TIMEOUT: num({ default: 5000, desc: 'Connection timeout in ms' }),
|
||||
QUESTDB_REQUEST_TIMEOUT: num({ default: 30000, desc: 'Request timeout in ms' }),
|
||||
QUESTDB_RETRY_ATTEMPTS: num({ default: 3, desc: 'Number of retry attempts' }),
|
||||
QUESTDB_CONNECTION_TIMEOUT: num(5000, 'Connection timeout in ms'),
|
||||
QUESTDB_REQUEST_TIMEOUT: num(30000, 'Request timeout in ms'),
|
||||
QUESTDB_RETRY_ATTEMPTS: num(3, 'Number of retry attempts'),
|
||||
|
||||
// TLS Settings
|
||||
QUESTDB_TLS_ENABLED: bool({ default: false, desc: 'Enable TLS for QuestDB connection' }),
|
||||
QUESTDB_TLS_VERIFY_SERVER_CERT: bool({ default: true, desc: 'Verify server certificate' }),
|
||||
QUESTDB_TLS_ENABLED: bool(false, 'Enable TLS for QuestDB connection'),
|
||||
QUESTDB_TLS_VERIFY_SERVER_CERT: bool(true, 'Verify server certificate'),
|
||||
|
||||
// Database Settings
|
||||
QUESTDB_DEFAULT_DATABASE: str({ default: 'qdb', desc: 'Default database name' }),
|
||||
QUESTDB_TELEMETRY_ENABLED: bool({ default: false, desc: 'Enable telemetry' }),
|
||||
QUESTDB_DEFAULT_DATABASE: str('qdb', 'Default database name'),
|
||||
QUESTDB_TELEMETRY_ENABLED: bool(false, 'Enable telemetry'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
|
|
@ -1,54 +1,52 @@
|
|||
/**
|
||||
* Risk management configuration using envalid
|
||||
* Risk management configuration using Zod
|
||||
*/
|
||||
import { cleanEnv, str, num, bool } from 'envalid';
|
||||
import { cleanEnv, envValidators } from './env-utils';
|
||||
|
||||
const { str, num, bool, strWithChoices } = envValidators;
|
||||
|
||||
/**
|
||||
* Risk configuration with validation and defaults
|
||||
*/
|
||||
export const riskConfig = cleanEnv(process.env, {
|
||||
// Position Sizing
|
||||
RISK_MAX_POSITION_SIZE: num({ default: 0.1, desc: 'Maximum position size as percentage of portfolio' }),
|
||||
RISK_MAX_PORTFOLIO_EXPOSURE: num({ default: 0.8, desc: 'Maximum portfolio exposure percentage' }),
|
||||
RISK_MAX_SINGLE_ASSET_EXPOSURE: num({ default: 0.2, desc: 'Maximum exposure to single asset' }),
|
||||
RISK_MAX_SECTOR_EXPOSURE: num({ default: 0.3, desc: 'Maximum exposure to single sector' }),
|
||||
RISK_MAX_POSITION_SIZE: num(0.1, 'Maximum position size as percentage of portfolio'),
|
||||
RISK_MAX_PORTFOLIO_EXPOSURE: num(0.8, 'Maximum portfolio exposure percentage'),
|
||||
RISK_MAX_SINGLE_ASSET_EXPOSURE: num(0.2, 'Maximum exposure to single asset'),
|
||||
RISK_MAX_SECTOR_EXPOSURE: num(0.3, 'Maximum exposure to single sector'),
|
||||
|
||||
// Stop Loss and Take Profit
|
||||
RISK_DEFAULT_STOP_LOSS: num({ default: 0.05, desc: 'Default stop loss percentage' }),
|
||||
RISK_DEFAULT_TAKE_PROFIT: num({ default: 0.15, desc: 'Default take profit percentage' }),
|
||||
RISK_TRAILING_STOP_ENABLED: bool({ default: true, desc: 'Enable trailing stop losses' }),
|
||||
RISK_TRAILING_STOP_DISTANCE: num({ default: 0.03, desc: 'Trailing stop distance percentage' }),
|
||||
RISK_DEFAULT_STOP_LOSS: num(0.05, 'Default stop loss percentage'),
|
||||
RISK_DEFAULT_TAKE_PROFIT: num(0.15, 'Default take profit percentage'),
|
||||
RISK_TRAILING_STOP_ENABLED: bool(true, 'Enable trailing stop losses'),
|
||||
RISK_TRAILING_STOP_DISTANCE: num(0.03, 'Trailing stop distance percentage'),
|
||||
|
||||
// Risk Limits
|
||||
RISK_MAX_DAILY_LOSS: num({ default: 0.05, desc: 'Maximum daily loss percentage' }),
|
||||
RISK_MAX_WEEKLY_LOSS: num({ default: 0.1, desc: 'Maximum weekly loss percentage' }),
|
||||
RISK_MAX_MONTHLY_LOSS: num({ default: 0.2, desc: 'Maximum monthly loss percentage' }),
|
||||
RISK_MAX_DAILY_LOSS: num(0.05, 'Maximum daily loss percentage'),
|
||||
RISK_MAX_WEEKLY_LOSS: num(0.1, 'Maximum weekly loss percentage'),
|
||||
RISK_MAX_MONTHLY_LOSS: num(0.2, 'Maximum monthly loss percentage'),
|
||||
|
||||
// Volatility Controls
|
||||
RISK_MAX_VOLATILITY_THRESHOLD: num({ default: 0.4, desc: 'Maximum volatility threshold' }),
|
||||
RISK_VOLATILITY_LOOKBACK_DAYS: num({ default: 20, desc: 'Volatility calculation lookback period' }),
|
||||
RISK_MAX_VOLATILITY_THRESHOLD: num(0.4, 'Maximum volatility threshold'),
|
||||
RISK_VOLATILITY_LOOKBACK_DAYS: num(20, 'Volatility calculation lookback period'),
|
||||
|
||||
// Correlation Controls
|
||||
RISK_MAX_CORRELATION_THRESHOLD: num({ default: 0.7, desc: 'Maximum correlation between positions' }),
|
||||
RISK_CORRELATION_LOOKBACK_DAYS: num({ default: 60, desc: 'Correlation calculation lookback period' }),
|
||||
RISK_MAX_CORRELATION_THRESHOLD: num(0.7, 'Maximum correlation between positions'),
|
||||
RISK_CORRELATION_LOOKBACK_DAYS: num(60, 'Correlation calculation lookback period'),
|
||||
|
||||
// Leverage Controls
|
||||
RISK_MAX_LEVERAGE: num({ default: 2.0, desc: 'Maximum leverage allowed' }),
|
||||
RISK_MARGIN_CALL_THRESHOLD: num({ default: 0.3, desc: 'Margin call threshold' }),
|
||||
RISK_MAX_LEVERAGE: num(2.0, 'Maximum leverage allowed'),
|
||||
RISK_MARGIN_CALL_THRESHOLD: num(0.3, 'Margin call threshold'),
|
||||
|
||||
// Circuit Breakers
|
||||
RISK_CIRCUIT_BREAKER_ENABLED: bool({ default: true, desc: 'Enable circuit breakers' }),
|
||||
RISK_CIRCUIT_BREAKER_LOSS_THRESHOLD: num({ default: 0.1, desc: 'Circuit breaker loss threshold' }),
|
||||
RISK_CIRCUIT_BREAKER_COOLDOWN_MINUTES: num({ default: 60, desc: 'Circuit breaker cooldown period' }),
|
||||
RISK_CIRCUIT_BREAKER_ENABLED: bool(true, 'Enable circuit breakers'),
|
||||
RISK_CIRCUIT_BREAKER_LOSS_THRESHOLD: num(0.1, 'Circuit breaker loss threshold'),
|
||||
RISK_CIRCUIT_BREAKER_COOLDOWN_MINUTES: num(60, 'Circuit breaker cooldown period'),
|
||||
|
||||
// Risk Model
|
||||
RISK_MODEL_TYPE: str({
|
||||
choices: ['var', 'cvar', 'expected_shortfall'],
|
||||
default: 'var',
|
||||
desc: 'Risk model type'
|
||||
}),
|
||||
RISK_CONFIDENCE_LEVEL: num({ default: 0.95, desc: 'Risk model confidence level' }),
|
||||
RISK_TIME_HORIZON_DAYS: num({ default: 1, desc: 'Risk time horizon in days' }),
|
||||
RISK_MODEL_TYPE: strWithChoices(['var', 'cvar', 'expected_shortfall'], 'var', 'Risk model type'),
|
||||
RISK_CONFIDENCE_LEVEL: num(0.95, 'Risk model confidence level'),
|
||||
RISK_TIME_HORIZON_DAYS: num(1, 'Risk time horizon in days'),
|
||||
});
|
||||
|
||||
// Export typed configuration object
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue