UNPKG

@kya-os/mcp-i

Version:

The TypeScript MCP framework with identity features built-in

161 lines (160 loc) 5.44 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getConfig = getConfig; exports.readConfig = readConfig; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const webpack_1 = require("webpack"); const memfs_1 = require("memfs"); const compiler_context_1 = require("./compiler-context"); const config_1 = require("./config"); const constants_1 = require("./config/constants"); function validateConfig(config) { return config_1.configSchema.parse(config); } // read if exists function readConfigFile(pathToConfig) { const configPath = path_1.default.resolve(process.cwd(), pathToConfig); if (!fs_1.default.existsSync(configPath)) { return null; } return fs_1.default.readFileSync(configPath, "utf8"); } const configPaths = { ts: "xmcp.config.ts", json: "xmcp.config.json", }; /** * Parse and validate xmcp config file */ async function getConfig() { const config = await readConfig(); const { platforms } = compiler_context_1.compilerContext.getContext(); if (platforms.vercel) { // Remove stdio to deploy on vercel delete config.stdio; } return config; } /** * Read config from file or return default */ async function readConfig() { // Simple json config const jsonFile = readConfigFile(configPaths.json); if (jsonFile) { return validateConfig(JSON.parse(jsonFile)); } // TypeScript config, compile it const tsFile = readConfigFile(configPaths.ts); if (tsFile) { try { return await compileConfig(); } catch (error) { throw new Error(`Failed to compile xmcp.config.ts:\n${error}`); } } // Default config return { stdio: true, http: true, paths: constants_1.DEFAULT_PATHS_CONFIG, }; } /** * If the user is using a typescript config file, * we need to bundle it, run it and return its copiled code * */ async function compileConfig() { const configPath = path_1.default.resolve(process.cwd(), configPaths.ts); // Create memory filesystem const memoryFs = (0, memfs_1.createFsFromVolume)(new memfs_1.Volume()); // Webpack configuration const webpackConfig = { mode: "production", entry: configPath, target: "node", output: { path: "/", filename: "config.js", library: { type: "commonjs2", }, }, resolve: { extensions: [".ts", ".js"], }, module: { rules: [ { test: /\.ts$/, use: { loader: "swc-loader", options: { jsc: { parser: { syntax: "typescript", }, target: "es2020", }, module: { type: "commonjs", }, }, }, exclude: /node_modules/, }, ], }, externals: { webpack: "commonjs2 webpack", }, }; return new Promise((resolve, reject) => { const compiler = (0, webpack_1.webpack)(webpackConfig); // Webpack returns null if config is invalid if (!compiler) { reject(new Error("Failed to create webpack compiler - invalid config")); return; } // Use memory filesystem for output compiler.outputFileSystem = memoryFs; compiler.run((err, stats) => { if (err) { reject(err); return; } if (stats?.hasErrors()) { reject(new Error(stats.toString({ colors: false, errors: true }))); return; } try { // Read the bundled code from memory const bundledCode = memoryFs.readFileSync("/config.js", "utf8"); // Create a temporary module to evaluate the bundled code const module = { exports: {} }; const require = (id) => { // Handle webpack require if (id === "webpack") { return webpack_1.webpack; } throw new Error(`Cannot resolve module: ${id}`); }; // Evaluate the bundled code const func = new Function("module", "exports", "require", "__filename", "__dirname", bundledCode); func(module, module.exports, require, configPath, path_1.default.dirname(configPath)); // Extract the config - it could be default export or direct export const configExport = module.exports.default || module.exports; const config = typeof configExport === "function" ? configExport() : configExport; resolve(validateConfig(config)); } catch (evalError) { reject(evalError); } }); }); }