@baguskto/saham
Version:
MCP Server untuk data saham Indonesia (IDX) - Implementasi Node.js/TypeScript
211 lines • 8.44 kB
JavaScript
;
/**
* 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