UNPKG

recoder-code

Version:

Complete AI-powered development platform with ML model training, plugin registry, real-time collaboration, monitoring, infrastructure automation, and enterprise deployment capabilities

252 lines 10.4 kB
"use strict"; /** * Recoder Code Plugin Registry Service * NPM-compatible registry for Recoder Code plugins */ 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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); require("reflect-metadata"); const express_1 = __importDefault(require("express")); const cors_1 = __importDefault(require("cors")); const helmet_1 = __importDefault(require("helmet")); const compression_1 = __importDefault(require("compression")); const express_rate_limit_1 = __importDefault(require("express-rate-limit")); const winston_1 = __importDefault(require("winston")); const dotenv_1 = __importDefault(require("dotenv")); const config_1 = __importDefault(require("./config")); const database_1 = require("./database"); // import { getQueues } from './queues'; const container_1 = require("./container"); const error_1 = require("./middleware/error"); const logger_1 = require("./middleware/logger"); // Routes const auth_1 = __importDefault(require("./routes/auth")); const packages_1 = __importDefault(require("./routes/packages")); const users_1 = __importDefault(require("./routes/users")); const admin_1 = __importDefault(require("./routes/admin")); const search_1 = __importDefault(require("./routes/search")); const download_1 = __importDefault(require("./routes/download")); const webhooks_1 = __importDefault(require("./routes/webhooks")); // Load environment variables dotenv_1.default.config(); // Setup logger const logger = winston_1.default.createLogger({ level: 'info', format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.errors({ stack: true }), winston_1.default.format.json()), transports: [ new winston_1.default.transports.Console(), new winston_1.default.transports.File({ filename: 'error.log', level: 'error' }), new winston_1.default.transports.File({ filename: 'combined.log' }) ] }); class PluginRegistryServer { constructor() { this.app = (0, express_1.default)(); this.setupMiddleware(); this.setupRoutes(); this.setupErrorHandling(); } setupMiddleware() { // Security middleware this.app.use((0, helmet_1.default)({ contentSecurityPolicy: false, crossOriginEmbedderPolicy: false })); // CORS this.app.use((0, cors_1.default)({ origin: true, credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], allowedHeaders: ['Content-Type', 'Authorization', 'X-Registry-Token'] })); // Compression this.app.use((0, compression_1.default)()); // Rate limiting const limiter = (0, express_rate_limit_1.default)({ windowMs: 15 * 60 * 1000, max: 1000, message: 'Too many requests from this IP, please try again later.', standardHeaders: true, legacyHeaders: false, }); this.app.use('/api/', limiter); // Strict rate limiting for package publishing const publishLimiter = (0, express_rate_limit_1.default)({ windowMs: 60 * 60 * 1000, max: 20, message: 'Too many package publishes, please try again later.', }); this.app.use('/api/packages/:packageName', publishLimiter); // Body parsing this.app.use(express_1.default.json({ limit: '50mb' })); this.app.use(express_1.default.urlencoded({ extended: true, limit: '50mb' })); // Request logging this.app.use(logger_1.requestLogger); // Authentication middleware would go here if needed } setupRoutes() { // Health check this.app.get('/health', (req, res) => { res.json({ status: 'healthy', service: 'recoder-code-plugin-registry', version: '1.0.0', timestamp: new Date().toISOString() }); }); // NPM-compatible endpoints this.app.get('/', (req, res) => { res.json({ registry: 'Recoder Code Plugin Registry', version: '1.0.0', description: 'NPM-compatible registry for Recoder Code plugins', endpoints: { package: '/api/packages/:packageName', search: '/api/search', download: '/api/download/:packageName/:version', publish: '/api/packages/:packageName', user: '/api/users/:username' } }); }); // API routes this.app.use('/api/auth', auth_1.default); this.app.use('/api/packages', packages_1.default); this.app.use('/api/users', users_1.default); this.app.use('/api/admin', admin_1.default); this.app.use('/api/search', search_1.default); this.app.use('/api/download', download_1.default); this.app.use('/api/webhooks', webhooks_1.default); // NPM CLI compatibility routes this.app.get('/:packageName', packages_1.default); this.app.put('/:packageName', packages_1.default); this.app.get('/:packageName/-/:filename', download_1.default); // Registry metadata endpoint (NPM compatibility) this.app.get('/-/ping', (req, res) => { res.json({ ok: true }); }); this.app.get('/-/whoami', (req, res) => { if (req.user) { res.json({ username: req.user.username }); } else { res.status(401).json({ error: 'Not authenticated' }); } }); } setupErrorHandling() { // 404 handler this.app.use(error_1.notFound); // Error handler this.app.use(error_1.errorHandler); // Unhandled promise rejections process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled Rejection at:', promise, 'reason:', reason); }); // Uncaught exceptions process.on('uncaughtException', (error) => { logger.error('Uncaught Exception:', error); process.exit(1); }); } async start() { try { logger.info('Starting Recoder Code Plugin Registry...'); // Setup database await (0, database_1.initializeDatabase)(); logger.info('Database connected'); // Setup Redis const { initializeRedis } = await Promise.resolve().then(() => __importStar(require('./redis'))); await initializeRedis(); logger.info('Redis connected'); // Initialize container (0, container_1.initializeContainer)(); logger.info('Dependency injection container initialized'); // Setup job queues // await getQueues(); // logger.info('Job queues initialized'); // Start server this.server = this.app.listen(config_1.default.port, config_1.default.host, () => { logger.info(`Server running on ${config_1.default.host}:${config_1.default.port}`); logger.info(`Environment: ${config_1.default.environment}`); }); // Graceful shutdown this.setupGracefulShutdown(); } catch (error) { logger.error('Failed to start server:', error); process.exit(1); } } setupGracefulShutdown() { const shutdown = async (signal) => { logger.info(`Received ${signal}, shutting down gracefully...`); if (this.server) { this.server.close(() => { logger.info('HTTP server closed'); }); } // Close database connections try { const connection = (await Promise.resolve().then(() => __importStar(require('typeorm')))).getConnection(); if (connection.isConnected) { await connection.close(); logger.info('Database connection closed'); } } catch (error) { logger.error('Error closing database:', error); } // Close Redis connections try { const { getRedis } = await Promise.resolve().then(() => __importStar(require('./redis'))); const redis = getRedis(); if (redis) { await redis.quit(); logger.info('Redis connection closed'); } } catch (error) { logger.error('Error closing Redis:', error); } process.exit(0); }; process.on('SIGTERM', () => shutdown('SIGTERM')); process.on('SIGINT', () => shutdown('SIGINT')); } } // Start server if this file is run directly if (require.main === module) { const server = new PluginRegistryServer(); server.start().catch((error) => { logger.error('Failed to start server:', error); process.exit(1); }); } exports.default = PluginRegistryServer; //# sourceMappingURL=index.js.map