UNPKG

markmv

Version:

TypeScript CLI for markdown file operations with intelligent link refactoring

145 lines 5.14 kB
/** * Native Node.js REST API server for markmv * * Provides a lightweight HTTP API using only Node.js built-in modules. Uses auto-generated route * definitions from JSON Schema-first approach. Exposes markmv functionality via RESTful endpoints * for language-agnostic access. */ import * as http from 'node:http'; import * as url from 'node:url'; import { createMarkMv } from './index.js'; import { autoGeneratedApiRoutes, getApiRoutePaths } from './generated/api-routes.js'; const markmv = createMarkMv(); const startTime = Date.now(); /** Type guard to check if an object is a valid API route */ function isApiRoute(obj) { return (typeof obj === 'object' && obj !== null && 'method' in obj && 'path' in obj && 'handler' in obj && typeof obj.method === 'string' && typeof obj.path === 'string' && typeof obj.handler === 'function'); } /** Send JSON response with proper headers */ function sendJSON(response, statusCode, data) { response.writeHead(statusCode, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }); response.end(JSON.stringify(data)); } /** Create a standardized API response */ function createApiResponse(success, data, error, details) { const response = { success, timestamp: new Date().toISOString(), }; if (data !== undefined) { response.data = data; } if (error !== undefined) { response.error = error; } if (details !== undefined) { response.details = details; } return response; } /** Create an error response */ function createErrorResponse(statusCode, error, message, details) { const response = { error, message, statusCode, }; if (details !== undefined) { response.details = details; } return response; } /** Handle CORS preflight requests */ function handleCORS(request, response) { if (request.method === 'OPTIONS') { response.writeHead(200, { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }); response.end(); return true; } return false; } /** Handle health check endpoint */ async function handleHealth(response) { const healthResponse = { status: 'ok', version: '1.0.0', uptime: Date.now() - startTime, info: { service: 'markmv-api', description: 'Markdown file operations API', }, }; const apiResponse = createApiResponse(true, healthResponse); sendJSON(response, 200, apiResponse); } /** Main request handler */ async function handleRequest(request, response) { // Handle CORS preflight if (handleCORS(request, response)) { return; } const { method, url: reqUrl } = request; const parsedUrl = url.parse(reqUrl || '', true); const path = parsedUrl.pathname; try { // Handle health endpoint if (method === 'GET' && path === '/health') { await handleHealth(response); return; } // Handle auto-generated API routes const autoRoute = autoGeneratedApiRoutes.find((route) => { return isApiRoute(route) && route.method === method && route.path === path; }); if (autoRoute && isApiRoute(autoRoute)) { // Call the auto-generated handler with the markmv instance await autoRoute.handler(request, response, markmv); return; } // Route not found const availableRoutes = ['GET /health', ...getApiRoutePaths().map((p) => `POST ${p}`)]; const errorResponse = createErrorResponse(404, 'NotFound', `Route ${method} ${path} not found`, [`Available routes: ${availableRoutes.join(', ')}`]); sendJSON(response, 404, errorResponse); } catch (error) { console.error('Unhandled error:', error); const errorResponse = createErrorResponse(500, 'InternalServerError', 'An unexpected error occurred'); sendJSON(response, 500, errorResponse); } } /** Create and start the HTTP server */ export function createApiServer(port = 3000) { const server = http.createServer(handleRequest); server.listen(port, () => { console.log(`markmv API server running on port ${port}`); console.log(`Health check: http://localhost:${port}/health`); console.log(`API endpoints: http://localhost:${port}/api/*`); }); return server; } /** Start the API server with environment-based configuration */ export function startApiServer() { const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000; return createApiServer(port); } // For direct execution if (process.argv[1] && process.argv[1].endsWith('api-server.js')) { startApiServer(); } //# sourceMappingURL=api-server.js.map