UNPKG

@baguskto/saham

Version:

MCP Server untuk data saham Indonesia (IDX) - Implementasi Node.js/TypeScript

211 lines 8.44 kB
"use strict"; /** * Configuration management for IDX MCP Server */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.config = exports.Config = void 0; const zod_1 = require("zod"); const path = __importStar(require("path")); const fs = __importStar(require("fs")); const ConfigSchema = zod_1.z.object({ server: zod_1.z.object({ name: zod_1.z.string().default('Baguskto Saham'), version: zod_1.z.string().default('1.0.0'), debug: zod_1.z.boolean().default(false) }), cache: zod_1.z.object({ type: zod_1.z.enum(['memory', 'redis']).default('memory'), url: zod_1.z.string().optional(), ttl: zod_1.z.object({ marketOverview: zod_1.z.number().default(60), stockInfo: zod_1.z.number().default(300), historical: zod_1.z.number().default(86400), sector: zod_1.z.number().default(300), static: zod_1.z.number().default(604800) }) }), dataSources: zod_1.z.object({ yahooFinance: zod_1.z.object({ timeout: zod_1.z.number().default(10000), maxRetries: zod_1.z.number().default(3), retryDelay: zod_1.z.number().default(1000) }), webScraping: zod_1.z.object({ timeout: zod_1.z.number().default(15000), maxRetries: zod_1.z.number().default(3), retryDelay: zod_1.z.number().default(1000) }), rateLimiting: zod_1.z.object({ requestsPerMinute: zod_1.z.number().default(60), burstLimit: zod_1.z.number().default(10) }) }), logging: zod_1.z.object({ level: zod_1.z.enum(['error', 'warn', 'info', 'debug']).default('info'), file: zod_1.z.string().optional() }), data: zod_1.z.object({ stockListFile: zod_1.z.string().default('data/idx_stocks.csv'), sectorMappingFile: zod_1.z.string().default('data/sector_mapping.csv') }) }); class Config { static instance; config; constructor() { this.config = this.loadConfig(); } static getInstance() { if (!Config.instance) { Config.instance = new Config(); } return Config.instance; } loadConfig() { // Default configuration const defaultConfig = { server: { name: process.env['IDX_MCP_SERVER_NAME'] || 'Baguskto Saham', version: process.env['IDX_MCP_SERVER_VERSION'] || '1.0.0', debug: process.env['IDX_MCP_DEBUG'] === 'true' || false }, cache: { type: process.env['IDX_MCP_CACHE_TYPE'] || 'memory', url: process.env['IDX_MCP_REDIS_URL'], ttl: { marketOverview: parseInt(process.env['IDX_MCP_CACHE_TTL_MARKET_OVERVIEW'] || '60'), stockInfo: parseInt(process.env['IDX_MCP_CACHE_TTL_STOCK_INFO'] || '300'), historical: parseInt(process.env['IDX_MCP_CACHE_TTL_HISTORICAL'] || '86400'), sector: parseInt(process.env['IDX_MCP_CACHE_TTL_SECTOR'] || '300'), static: parseInt(process.env['IDX_MCP_CACHE_TTL_STATIC'] || '604800') } }, dataSources: { yahooFinance: { timeout: parseInt(process.env['IDX_MCP_YAHOO_TIMEOUT'] || '10000'), maxRetries: parseInt(process.env['IDX_MCP_MAX_RETRIES'] || '3'), retryDelay: parseInt(process.env['IDX_MCP_RETRY_DELAY'] || '1000') }, webScraping: { timeout: parseInt(process.env['IDX_MCP_WEB_TIMEOUT'] || '15000'), maxRetries: parseInt(process.env['IDX_MCP_MAX_RETRIES'] || '3'), retryDelay: parseInt(process.env['IDX_MCP_RETRY_DELAY'] || '1000') }, rateLimiting: { requestsPerMinute: parseInt(process.env['IDX_MCP_REQUESTS_PER_MINUTE'] || '60'), burstLimit: parseInt(process.env['IDX_MCP_BURST_LIMIT'] || '10') } }, logging: { level: process.env['IDX_MCP_LOG_LEVEL'] || 'info', file: process.env['IDX_MCP_LOG_FILE'] }, data: { stockListFile: process.env['IDX_MCP_STOCK_LIST_FILE'] || 'data/idx_stocks.csv', sectorMappingFile: process.env['IDX_MCP_SECTOR_MAPPING_FILE'] || 'data/sector_mapping.csv' } }; // Validate configuration const result = ConfigSchema.safeParse(defaultConfig); if (!result.success) { throw new Error(`Configuration validation failed: ${result.error.message}`); } return result.data; } get() { return this.config; } getServer() { return this.config.server; } getCache() { return this.config.cache; } getDataSources() { return this.config.dataSources; } getLogging() { return this.config.logging; } getData() { return this.config.data; } getDataFilePath(relativePath) { // If it's already an absolute path, return as-is if (path.isAbsolute(relativePath)) { return relativePath; } // Try to resolve relative to package directory const packageDir = path.dirname(path.dirname(__dirname)); const packagePath = path.join(packageDir, relativePath); if (fs.existsSync(packagePath)) { return packagePath; } // Try to resolve relative to current working directory const cwdPath = path.join(process.cwd(), relativePath); if (fs.existsSync(cwdPath)) { return cwdPath; } // Return the package path as fallback (even if it doesn't exist) return packagePath; } ensureDirectories() { try { // Create user config directory in home folder for cache/logs const homeDir = process.env.HOME || process.env.USERPROFILE || process.cwd(); const configDir = path.join(homeDir, '.baguskto-saham'); if (!fs.existsSync(configDir)) { fs.mkdirSync(configDir, { recursive: true }); } // Only create log directory if log file is specified if (this.config.logging.file) { const logDir = path.dirname(this.config.logging.file.startsWith('/') ? this.config.logging.file : path.join(configDir, this.config.logging.file)); if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }); } } } catch (error) { // Silently fail - the app should work without creating directories // Data files are bundled with the package, logs are optional } } } exports.Config = Config; exports.config = Config.getInstance(); //# sourceMappingURL=index.js.map