UNPKG

@gati-framework/runtime

Version:

Gati runtime execution engine for running handler-based applications

309 lines (231 loc) 7.85 kB
# @gati-framework/runtime > Runtime execution engine for Gati handler-based applications ## Installation ```bash npm install @gati-framework/runtime # or pnpm add @gati-framework/runtime # or yarn add @gati-framework/runtime ``` ## Usage ### Basic Setup ```typescript import { createApp } from '@gati-framework/runtime'; const app = createApp({ port: 3000, host: 'localhost', logging: true, }); // Register handlers manually app.get('/hello', (req, res) => { res.json({ message: 'Hello, World!' }); }); // Start the server await app.listen(); ``` ### Automatic Handler Discovery The runtime can automatically discover and register handlers from a directory: ```typescript import { createApp, loadHandlers } from '@gati-framework/runtime'; const app = createApp(); // Automatically load all handlers from ./src/handlers await loadHandlers(app, './src/handlers', { basePath: '/api', // Optional: prefix all routes verbose: true, // Optional: log registration }); await app.listen(); ``` ### Handler File Structure Handlers should export a `handler` function: ```typescript // src/handlers/hello.ts import type { Handler } from '@gati-framework/runtime'; export const handler: Handler = (req, res) => { const name = req.query.name || 'World'; res.json({ message: `Hello, ${name}!` }); }; // Optional: Export metadata for registration export const metadata = { method: 'GET', route: '/hello' }; ``` **File path routing:** - `src/handlers/hello.ts` → `GET /hello` - `src/handlers/users/create.ts` → `POST /users/create` - `src/handlers/api/v1/posts.ts` → `GET /api/v1/posts` ### Configuration ```typescript import { createApp } from '@gati-framework/runtime'; const app = createApp({ port: parseInt(process.env.PORT || '3000'), host: process.env.HOST || '0.0.0.0', timeout: 30000, // 30 seconds logging: process.env.NODE_ENV !== 'production', logger: { // Optional logger configuration level: 'info', // 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' pretty: process.env.NODE_ENV !== 'production', // Pretty print in dev }, }); ``` ### Structured Logging The runtime includes structured logging with pino for production observability: ```typescript import { createApp, logger, createLogger } from '@gati-framework/runtime'; // Use the default logger in your handlers app.get('/users', (req, res, gctx, lctx) => { logger.info({ requestId: lctx.requestId }, 'Fetching users'); // Your logic here const users = getUsersFromDB(); logger.info( { requestId: lctx.requestId, count: users.length }, 'Users fetched successfully' ); res.json({ users }); }); // Create a custom logger for specific modules const dbLogger = createLogger({ name: 'database', level: 'debug', pretty: false, // Force JSON output }); dbLogger.info({ query: 'SELECT * FROM users' }, 'Running query'); dbLogger.error({ error: err.message }, 'Database error'); ``` **Log Levels:** - `trace` - Very detailed debugging information - `debug` - Debugging information - `info` - Informational messages (default) - `warn` - Warning messages - `error` - Error messages - `fatal` - Critical errors **Output Formats:** - Development: Pretty-printed, human-readable logs - Production: JSON logs for aggregation tools (e.g., ELK, Datadog) ### Middleware ```typescript import { createApp, createCorsMiddleware } from '@gati-framework/runtime'; const app = createApp(); // Add custom middleware app.use(async (req, res, gctx, lctx, next) => { console.log(`${req.method} ${req.path}`); await next(); }); // Add CORS middleware (built-in helper) app.use(createCorsMiddleware({ origin: 'https://myapp.com', credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'], })); // Apply middleware to specific paths app.use(authMiddleware, { path: '/api/*' }); // Error handling middleware app.useError((error, req, res, gctx, lctx) => { console.error('Error:', error); res.status(500).json({ error: 'Internal Server Error' }); }); ``` ### CORS Configuration The built-in CORS middleware supports multiple configuration options: ```typescript import { createCorsMiddleware } from '@gati-framework/runtime'; // Allow all origins (default) app.use(createCorsMiddleware()); // Specific origin app.use(createCorsMiddleware({ origin: 'https://myapp.com' })); // Multiple origins app.use(createCorsMiddleware({ origin: ['https://app1.com', 'https://app2.com'] })); // Dynamic origin validation app.use(createCorsMiddleware({ origin: (origin) => origin.endsWith('.myapp.com'), credentials: true, exposedHeaders: ['X-Total-Count'], maxAge: 86400, // 24 hours })); ``` ### Graceful Shutdown The server supports graceful shutdown, waiting for active requests to complete: ```typescript const app = createApp({ port: 3000, timeout: 30000 // Request timeout: 30 seconds }); await app.listen(); // Handle shutdown signals process.on('SIGTERM', async () => { console.log('Shutting down gracefully...'); await app.close(); // Waits up to 10 seconds for active requests process.exit(0); }); process.on('SIGINT', async () => { console.log('Shutting down gracefully...'); await app.close(); process.exit(0); }); ``` ### Method-specific Routes ```typescript app.get('/users', getUsersHandler); app.post('/users', createUserHandler); app.put('/users/:id', updateUserHandler); app.patch('/users/:id', patchUserHandler); app.delete('/users/:id', deleteUserHandler); ``` ## API Reference ### `createApp(config?: AppConfig): GatiApp` Creates a new Gati application instance. **Config options:** - `port?: number` - Port to listen on (default: 3000) - `host?: string` - Host to bind to (default: 'localhost') - `timeout?: number` - Server timeout in ms (default: 30000) - `logging?: boolean` - Enable request logging (default: true) ### `loadHandlers(app, dir, options?): Promise<void>` Automatically discovers and registers handlers from a directory. **Parameters:** - `app: GatiApp` - Application instance - `dir: string` - Directory path (e.g., './src/handlers') - `options.basePath?: string` - Route prefix (default: '') - `options.verbose?: boolean` - Log registration (default: false) ### `GatiApp Methods` - `get(path, handler)` - Register GET route - `post(path, handler)` - Register POST route - `put(path, handler)` - Register PUT route - `patch(path, handler)` - Register PATCH route - `delete(path, handler)` - Register DELETE route - `use(middleware)` - Add middleware - `useError(errorMiddleware)` - Add error handler - `listen()` - Start HTTP server - `close()` - Stop HTTP server gracefully - `isRunning()` - Check if server is running - `getConfig()` - Get current configuration ## Type Definitions All TypeScript types are exported: ```typescript import type { Handler, Request, Response, GlobalContext, LocalContext, Middleware, ErrorMiddleware, AppConfig, } from '@gati-framework/runtime'; ``` ## Examples See the [examples directory](../../examples) for complete examples: - [hello-world](../../examples/hello-world) - Basic application - [scaffold-verify](../../examples/scaffold-verify) - Scaffolded project structure ## Requirements - Node.js >= 18.0.0 - TypeScript >= 5.3.0 (for development) ## License MIT © Krishna Paul ## Links - [Documentation](https://github.com/krishnapaul242/gati) - [GitHub Repository](https://github.com/krishnapaul242/gati) - [Report Issues](https://github.com/krishnapaul242/gati/issues)