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
JavaScript
/**
* 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
;