### Install and Check Project Source: https://github.com/ecube-labs/koa-x-router/blob/main/codemods/v0.1-adaptor-imports/README.md Install project dependencies and run checks. This is a standard development setup command. ```bash npm install npm run check ``` -------------------------------- ### Install koa-x-router Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/quick-start.md Install the necessary packages for koa-x-router, koa, and @koa/router. ```bash npm install koa @koa/router koa-x-router ``` -------------------------------- ### Full TypeScript Example with Koa-X-Router Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/examples.md This example shows a complete setup for a Koa application using Koa-X-Router with TypeScript. It defines interfaces for user data, validation schemas using Joi, and a typed route handler for creating new users. The `createRoute` factory function ensures type safety for route specifications. ```typescript import Koa, { Context } from 'koa'; import bodyParser from 'koa-bodyparser'; import Joi from 'joi'; import { Router, RouteLayerSpec } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; // Type definitions for domain models interface User { id: number; name: string; email: string; role: 'admin' | 'user'; createdAt: Date; } interface CreateUserRequest { name: string; email: string; role?: 'admin' | 'user'; } interface UserResponse { id: number; name: string; email: string; role: string; createdAt: Date; } // Validation schemas const schemas = { createUser: Joi.object({ name: Joi.string().min(1).max(100).required(), email: Joi.string().email().required(), role: Joi.string().valid('admin', 'user').default('user') }), userResponse: Joi.object({ id: Joi.number().required(), name: Joi.string().required(), email: Joi.string().required(), role: Joi.string().required(), createdAt: Joi.date().required() }) }; // Typed route handler factory function createRoute( spec: Omit, 'handler'> & { handler: (ctx: Context) => Promise; } ): RouteLayerSpec { return spec as RouteLayerSpec; } const app = new Koa(); const router = new Router({ adaptors: [JoiAdaptor] }); // Database mock const users: Record = {}; let nextId = 1; // Typed route router.add( createRoute({ method: 'post', path: '/users', validate: { body: schemas.createUser, output: { 201: { body: schemas.userResponse } } }, handler: async (ctx) => { const userData = ctx.request.body as CreateUserRequest; const user: User = { id: nextId++, ...userData, role: userData.role || 'user', createdAt: new Date() }; users[user.id] = user; ctx.status = 201; ctx.body = user as UserResponse; } }) ); app.use(bodyParser()); app.use(router.routes()); app.listen(3000); ``` -------------------------------- ### Install Joi for Validation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/quick-start.md Install the Joi library if you plan to use it for request validation with koa-x-router. ```bash npm install joi ``` -------------------------------- ### Simple GET Endpoint with Koa-x-router Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/examples.md Demonstrates setting up a basic GET endpoint for health checks using koa-x-router. Ensure Koa and koa-x-router are installed. ```typescript import Koa from 'koa'; import { Router } from 'koa-x-router'; const app = new Koa(); const router = new Router(); router.add({ method: 'get', path: '/health', handler: async (ctx) => { ctx.body = { status: 'healthy' }; } }); app.use(router.routes()); app.listen(3000); // Test: GET /health → { status: 'healthy' } ``` -------------------------------- ### Basic Koa-X-Router Setup with Joi Validation Source: https://github.com/ecube-labs/koa-x-router/blob/main/README.md Demonstrates initializing Koa-X-Router with the JoiAdaptor for request validation. This setup is essential for defining routes with schema-based input and output validation. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import Joi from 'joi'; import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; // import { ZodAdaptor } from "koa-x-router/zod"; const app = new Koa(); const router = new Router({ adaptors: [JoiAdaptor], // <== Important! // adaptors: [ZodAdaptor], // If you want to use with Zod // adaptors: [JoiAdaptor, ZodAdaptor], // or both }); const docRouter = new Router(); // Define a route with validation router.add({ method: 'get', path: '/users', validate: { query: Joi.object({ name: Joi.string(), }), output: { 200: { body: Joi.array().items( Joi.object({ name: Joi.string().required(), age: Joi.number().positive().required(), }), ), }, }, }, handler: async (ctx) => { // code... }, }); docRouter.get('/', (ctx) => { ctx.body = ` API Documentation `; }); docRouter.get('/openapi.json', (ctx) => { ctx.body = router.generateOpenApiSpecJson({ info: { title: 'koa-x-router Demo API Docs', version: '1.0.0', }, }); }); app.use(docRouter.routes()); app.use(bodyParser()); app.use(router.routes()); app.listen(3000, () => { console.log('Server listening on port 3000'); }); ``` -------------------------------- ### Install koa-x-router with Joi Source: https://github.com/ecube-labs/koa-x-router/blob/main/README.md Install the necessary packages for koa-x-router when using Joi for validation. ```shell npm install koa @koa/router koa-x-router joi ``` -------------------------------- ### Complete Koa Application with Zod Validation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/ZodAdaptor.md A full example demonstrating Koa application setup with koa-x-router and ZodAdaptor. It includes defining schemas for request bodies and responses, registering routes with validation, and generating an OpenAPI specification. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import { z } from 'zod'; import { Router } from 'koa-x-router'; import { ZodAdaptor } from 'koa-x-router/zod'; const app = new Koa(); const router = new Router({ adaptors: [ZodAdaptor] }); // Define schemas as Zod types const createUserSchema = z.object({ name: z.string().min(2).max(100), email: z.string().email(), age: z.number().int().min(18).optional() }); const userResponseSchema = z.object({ id: z.number().int(), name: z.string(), email: z.string(), createdAt: z.string().datetime() }); // Register routes with Zod validation router.add({ method: 'post', path: '/users', meta: { document: { summary: 'Create a new user', tags: ['Users'] } }, validate: { body: createUserSchema, output: { 201: { body: userResponseSchema }, 400: { body: z.object({ error: z.string() }) } } }, handler: async (ctx) => { const { name, email, age } = ctx.request.body; // Validated data is ready to use ctx.status = 201; ctx.body = { id: 1, name, email, createdAt: new Date().toISOString() }; } }); router.add({ method: 'get', path: '/users/:id', meta: { document: { summary: 'Get user by ID', tags: ['Users'] } }, validate: { params: z.object({ id: z.coerce.number().int().positive() }), output: { 200: { body: userResponseSchema }, 404: { body: z.object({ message: z.string() }) } } }, handler: async (ctx) => { const { id } = ctx.params; // id is validated as positive integer ctx.body = { id, name: 'John', email: 'john@example.com', createdAt: new Date().toISOString() }; } }); // Generate OpenAPI spec const docRouter = new Router(); docRouter.get('/openapi.json', (ctx) => { ctx.body = router.generateOpenApiSpecJson({ info: { title: 'User API', version: '1.0.0' } }); }); app.use(bodyParser()); app.use(router.routes()); app.use(docRouter.routes()); app.listen(3000); ``` -------------------------------- ### Catch-all Route Example Source: https://github.com/ecube-labs/koa-x-router/blob/main/README.md Illustrates how to use `method: 'all'` to create a catch-all route that handles any HTTP verb for a given path. This is useful for proxying or fallback scenarios. ```typescript router.add({ method: 'all', path: '/hubspot/:path(.*)', handler: async (ctx) => { // handles GET, POST, PUT, PATCH, DELETE, ... on /hubspot/* }, }); ``` -------------------------------- ### Complete Koa Application with Joi Validation and OpenAPI Spec Generation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/JoiAdaptor.md A full example demonstrating Koa setup with JoiAdaptor for route validation, including request body validation and output schema definition. It also shows how to generate an OpenAPI specification. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import Joi from 'joi'; import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; const app = new Koa(); const router = new Router({ adaptors: [JoiAdaptor] }); // Register routes with Joi validation router.add({ method: 'post', path: '/users', meta: { document: { summary: 'Create a new user', tags: ['Users'] } }, validate: { body: Joi.object({ name: Joi.string().min(2).max(100).required(), email: Joi.string().email().required(), age: Joi.number().min(18).optional() }), output: { 201: { body: Joi.object({ id: Joi.number().required(), name: Joi.string().required(), email: Joi.string().required(), createdAt: Joi.date().required() }) }, 400: { body: Joi.object({ error: Joi.string().required() }) } } }, handler: async (ctx) => { const { name, email, age } = ctx.request.body; // Validated data is ready to use ctx.status = 201; ctx.body = { id: 1, name, email, createdAt: new Date() }; } }); // Generate OpenAPI spec const docRouter = new Router(); docRouter.get('/openapi.json', (ctx) => { ctx.body = router.generateOpenApiSpecJson({ info: { title: 'User API', version: '1.0.0' } }); }); app.use(bodyParser()); app.use(router.routes()); app.use(docRouter.routes()); app.listen(3000); ``` -------------------------------- ### Install Zod for Validation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/quick-start.md Install the Zod library if you plan to use it for request validation with koa-x-router. ```bash npm install zod ``` -------------------------------- ### RouteLayerSpec Example for User Creation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/types.md An example of defining a POST route for user creation using RouteLayerSpec, including request body validation with Joi and OpenAPI metadata. ```typescript import { Router, RouteLayerSpec } from 'koa-x-router'; import Joi from 'joi'; const userRoute: RouteLayerSpec = { method: 'post', path: '/api/users', meta: { document: { summary: 'Create user', description: 'Creates a new user in the system', tags: ['Users'] } }, validate: { body: Joi.object({ name: Joi.string().required(), email: Joi.string().email().required() }) }, handler: async (ctx) => { ctx.body = { id: 1, name: ctx.request.body.name }; } }; const router = new Router({ adaptors: [JoiAdaptor] }); router.add(userRoute); ``` -------------------------------- ### Complete API Documentation Setup with Koa-x-router Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/examples.md This snippet sets up a Koa application with koa-x-router to handle API routes, validate requests and responses using Joi, and generate OpenAPI documentation. It includes routes for listing and creating products, along with a documentation route that serves an HTML page with Redoc and an OpenAPI JSON specification. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import Joi from 'joi'; import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; const app = new Koa(); // Main API router with metadata const apiRouter = new Router({ adaptors: [JoiAdaptor], prefix: '/api' }); apiRouter.add({ method: 'get', path: '/products', meta: { document: { summary: 'List all products', description: 'Returns a paginated list of products', tags: ['Products'], deprecated: false } }, validate: { query: Joi.object({ page: Joi.number().min(1).default(1), limit: Joi.number().min(1).max(100).default(20), sort: Joi.string().valid('name', 'price', '-price') }), output: { 200: { body: Joi.object({ data: Joi.array().items( Joi.object({ id: Joi.number(), name: Joi.string(), price: Joi.number() }) ), pagination: Joi.object({ page: Joi.number(), limit: Joi.number(), total: Joi.number() }) }) } } }, handler: async (ctx) => { ctx.body = { data: [ { id: 1, name: 'Product 1', price: 29.99 }, { id: 2, name: 'Product 2', price: 39.99 } ], pagination: { page: 1, limit: 20, total: 2 } }; } }); apiRouter.add({ method: 'post', path: '/products', meta: { document: { summary: 'Create a product', tags: ['Products'] } }, validate: { body: Joi.object({ name: Joi.string().required(), price: Joi.number().positive().required(), description: Joi.string() }), output: { 201: { body: Joi.object({ id: Joi.number(), name: Joi.string(), price: Joi.number(), createdAt: Joi.date() }) } } }, handler: async (ctx) => { ctx.status = 201; ctx.body = { id: 1, ...ctx.request.body, createdAt: new Date() }; } }); // Documentation router const docRouter = new Router(); docRouter.get('/', (ctx) => { ctx.type = 'text/html'; ctx.body = ` Product API Documentation

Product API Documentation

View the API specification at /docs/openapi.json


`; }); docRouter.get('/openapi.json', (ctx) => { ctx.body = apiRouter.generateOpenApiSpecJson({ info: { title: 'Product API', version: '1.0.0', description: 'Complete product management API', contact: { name: 'API Support', email: 'support@example.com' } }, servers: [ { url: 'https://api.example.com', description: 'Production' }, { url: 'http://localhost:3000', description: 'Development' } ], tags: [ { name: 'Products', description: 'Product management operations' } ], externalDocs: { url: 'https://docs.example.com', description: 'Extended documentation' } }); }); app.use(bodyParser()); app.use(docRouter.routes()); app.use(apiRouter.routes()); app.listen(3000, () => { console.log('API running on http://localhost:3000'); console.log('Documentation: http://localhost:3000/docs/'); }); ``` -------------------------------- ### Basic Setup with Zod Validation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/quick-start.md Set up a Koa application with koa-x-router and Zod for validating POST request bodies. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import { z } from 'zod'; import { Router } from 'koa-x-router'; import { ZodAdaptor } from 'koa-x-router/zod'; const app = new Koa(); const router = new Router({ adaptors: [ZodAdaptor] }); router.add({ method: 'post', path: '/users', validate: { body: z.object({ name: z.string().min(1), email: z.string().email() }) }, handler: async (ctx) => { ctx.status = 201; ctx.body = { id: 1, ...ctx.request.body }; } }); app.use(bodyParser()); app.use(router.routes()); app.listen(3000); ``` -------------------------------- ### SchemaLike Example with Joi Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/types.md Demonstrates how to use the SchemaLike type with the Joi validation library to define a schema for an object. ```typescript import { Router } from 'koa-x-router'; import Joi from 'joi'; const mySchema: SchemaLike = Joi.object({ name: Joi.string() }); ``` -------------------------------- ### Install koa-x-router with Zod Source: https://github.com/ecube-labs/koa-x-router/blob/main/README.md Install the necessary packages for koa-x-router when using Zod for validation. ```shell npm install koa @koa/router koa-x-router zod ``` -------------------------------- ### Add Route with Validation Example Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/types.md Example of adding a POST route to '/users' with request body validation using Joi and output validation for different status codes. ```typescript router.add({ method: 'post', path: '/users', validate: { body: Joi.object({ name: Joi.string().required(), email: Joi.string().email().required() }), output: { 201: { body: Joi.object({ id: Joi.number().required(), name: Joi.string().required(), email: Joi.string().required() }) }, 400: { body: Joi.object({ error: Joi.string().required() }) }, '500-599': { body: Joi.object({ message: Joi.string() }) } } }, handler: async (ctx) => { try { const user = await createUser(ctx.request.body); ctx.status = 201; ctx.body = user; } catch (error) { ctx.status = 400; ctx.body = { error: error.message }; } } }); ``` -------------------------------- ### Install TypeScript Types Source: https://github.com/ecube-labs/koa-x-router/blob/main/README.md Install TypeScript types for Koa and Koa Router when using TypeScript. ```shell npm install @types/koa @types/koa__router -D ``` -------------------------------- ### Example Validation Flow with Koa-X-Router Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/Router.md Demonstrates how to configure a route with validation for parameters, query, body, and output. This example shows type coercion, such as string '123' to number 123. ```typescript router.add({ method: 'post', path: '/users/:id', validate: { params: Joi.object({ id: Joi.number().required() // "123" → 123 }), query: Joi.object({ notify: Joi.boolean() // "true" → true }), body: Joi.object({ age: Joi.number() // "30" → 30 }), output: { 200: { body: Joi.object({ id: Joi.number().required(), createdAt: Joi.date() }) }, '400-499': { body: Joi.object({ error: Joi.string().required() }) } } }, handler: async (ctx) => { // ctx.params.id is a number // ctx.query.notify is a boolean // ctx.request.body.age is a number ctx.body = { id: ctx.params.id, createdAt: new Date() }; } }); ``` -------------------------------- ### Router Configuration with Custom Adapter Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/XRouterAdaptor.md This example shows how to configure a Koa router with the custom 'SimpleAdaptor' and define a POST endpoint that uses the adapter for request body validation. ```APIDOC ## POST /users Endpoint with SimpleAdaptor Validation ### Description This endpoint accepts user data in the request body, validates it using the `SimpleAdaptor`, and returns the created user with an ID. ### Method POST ### Endpoint /users ### Parameters #### Request Body - **userSchema** (SimpleSchema) - Required - The schema for the user data. ### Request Example ```json { "name": "John Doe", "age": 30 } ``` ### Response #### Success Response (201) - **id** (number) - The ID of the created user. - **name** (string) - The name of the user. - **age** (number) - The age of the user. #### Response Example ```json { "id": 1, "name": "John Doe", "age": 30 } ``` ### Usage Example ```typescript import { Router } from 'koa-x-router'; // Assuming SimpleAdaptor is defined as shown in the previous snippet // import { SimpleAdaptor } from './SimpleAdaptor'; const userSchema: SimpleSchema = { fields: { name: { type: 'string', required: true, description: 'User name' }, age: { type: 'number', description: 'User age' } }, validate: async (data) => { // Custom validation logic if needed return data; } }; const router = new Router({ adaptors: [SimpleAdaptor] }); router.add({ method: 'post', path: '/users', validate: { body: userSchema }, handler: async (ctx) => { ctx.status = 201; ctx.body = { id: 1, ...ctx.request.body }; } }); ``` ``` -------------------------------- ### Example Usage of SchemaMetadata Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/types.md Demonstrates how to attach SchemaMetadata to a route definition using the 'meta.document' property. This includes setting summary, description, tags, deprecation, and custom operationId. ```typescript router.add({ method: 'get', path: '/users/:id', meta: { document: { summary: 'Get user by ID', description: 'Retrieves a single user by their unique identifier', tags: ['Users', 'Public'], deprecated: false, operationId: 'getUserById' // Custom property } }, handler: async (ctx) => { // ... } }); ``` -------------------------------- ### Testing Custom Adapters with Koa and Supertest Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/XRouterAdaptor.md This example demonstrates how to test a custom XRouter adapter by setting up a Koa application, defining a route with validation, and using supertest to send requests and assert responses for both successful and failed validation scenarios. ```typescript import { Router } from 'koa-x-router'; import request from 'supertest'; import Koa from 'koa'; const app = new Koa(); const router = new Router({ adaptors: [MyAdaptor] }); router.add({ method: 'post', path: '/test', validate: { body: new MySchema(...) }, handler: async (ctx) => { ctx.body = { received: ctx.request.body }; } }); app.use(router.routes()); // Test successful validation const response1 = await request(app).post('/test').send({ name: 'John', age: 30 }); expect(response1.status).toBe(200); expect(response1.body).toEqual({ received: { name: 'John', age: 30 } }); // Test failed validation const response2 = await request(app).post('/test').send({ age: 'invalid' }); expect(response2.status).toBe(400); ``` -------------------------------- ### Configure Router with Environment Variable Prefix Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/configuration.md Example of passing configuration options to the Router constructor, using an environment variable for the API prefix. Ensure environment variables are handled in your application code. ```typescript const router = new Router({ adaptors: [JoiAdaptor], prefix: process.env.API_PREFIX || '/api' }); ``` -------------------------------- ### Implementing a Custom XRouterAdaptor Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/types.md Example of creating a custom adapter for a hypothetical validation library. This adapter needs to be registered with the Router. ```typescript import type { XRouterAdaptor, SchemaLike } from 'koa-x-router'; import type { SchemaObject } from 'openapi3-ts/oas31'; // Example: Custom adapter for a hypothetical validation library const CustomAdaptor: XRouterAdaptor = { name: 'custom', isCompatibleSchema(schemaLike: SchemaLike): boolean { return schemaLike instanceof CustomSchema; }, async validate(schemaLike: SchemaLike, data: any): Promise { const schema = schemaLike as CustomSchema; const result = await schema.validate(data); if (!result.valid) { throw new Error(result.errors.join(', ')); } return result.data; }, schemaToOpenApiSchema(schemaLike: SchemaLike): SchemaObject { const schema = schemaLike as CustomSchema; return schema.toOpenApiSchema(); } }; // Use in router const router = new Router({ adaptors: [CustomAdaptor] }); ``` -------------------------------- ### Complete Koa Application with koa-x-router Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/configuration.md This snippet shows a full Koa application setup. It includes defining API routes with validation, a documentation route using Redoc, and middleware configuration. The application listens on port 3000. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import Joi from 'joi'; import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; const app = new Koa(); // API Router const apiRouter = new Router({ adaptors: [JoiAdaptor], prefix: '/api' }); apiRouter.add({ method: 'get', path: '/health', meta: { document: { summary: 'Health Check', tags: ['System'] } }, validate: { output: { 200: { body: Joi.object({ status: Joi.string().valid('ok').required() }) } } }, handler: async (ctx) => { ctx.body = { status: 'ok' }; } }); apiRouter.add({ method: 'post', path: '/users', meta: { document: { summary: 'Create User', description: 'Creates a new user', tags: ['Users'] } }, validate: { body: Joi.object({ name: Joi.string().required(), email: Joi.string().email().required() }), output: { 201: { body: Joi.object({ id: Joi.number().required(), name: Joi.string().required(), email: Joi.string().required() }) }, 400: { body: Joi.object({ error: Joi.string().required() }) } } }, handler: async (ctx) => { ctx.status = 201; ctx.body = { id: Math.random(), name: ctx.request.body.name, email: ctx.request.body.email }; } }); // Documentation Router const docRouter = new Router(); docRouter.get('/', (ctx) => { ctx.type = 'text/html'; ctx.body = ` API Documentation `; }); docRouter.get('/openapi.json', (ctx) => { ctx.body = apiRouter.generateOpenApiSpecJson({ info: { title: 'My API', version: '1.0.0', description: 'Production API documentation' }, servers: [ { url: 'http://localhost:3000', description: 'Development' } ], tags: [ { name: 'System', description: 'System endpoints' }, { name: 'Users', description: 'User management' } ] }); }); // Middleware app.use(bodyParser()); // Routes app.use(docRouter.routes()); app.use(apiRouter.routes()); app.listen(3000, () => { console.log('Server listening on http://localhost:3000'); console.log('API docs available at http://localhost:3000/'); }); ``` -------------------------------- ### Complete User CRUD API with Koa-x-router Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/examples.md This snippet implements a full CRUD API for users. It sets up Koa, koa-x-router, and Joi for validation. Define schemas for user data, validation rules, and API responses. Includes routes for listing, getting, creating, updating, and deleting users, with a mock in-memory database. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import Joi from 'joi'; import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; const app = new Koa(); const router = new Router({ adaptors: [JoiAdaptor], prefix: '/api/users' }); // Validation schemas const userIdSchema = Joi.object({ id: Joi.number().required() }); const createUserSchema = Joi.object({ name: Joi.string().min(1).max(100).required(), email: Joi.string().email().required(), role: Joi.string().valid('admin', 'user').default('user') }); const updateUserSchema = Joi.object({ name: Joi.string().min(1).max(100), email: Joi.string().email(), role: Joi.string().valid('admin', 'user') }).min(1); // At least one field required const userResponseSchema = Joi.object({ id: Joi.number().required(), name: Joi.string().required(), email: Joi.string().required(), role: Joi.string().required(), createdAt: Joi.date().required() }); const errorSchema = Joi.object({ error: Joi.string().required() }); // Database mock const users: Record = { 1: { id: 1, name: 'John Doe', email: 'john@example.com', role: 'admin', createdAt: new Date() } }; let nextId = 2; // Routes // GET /api/users - List users router.add({ method: 'get', path: '/', meta: { document: { summary: 'List all users', tags: ['Users'] } }, validate: { output: { 200: { body: Joi.array().items(userResponseSchema) } } }, handler: async (ctx) => { ctx.body = Object.values(users); } }); // GET /api/users/:id - Get user by ID router.add({ method: 'get', path: '/:id', meta: { document: { summary: 'Get user by ID', tags: ['Users'] } }, validate: { params: userIdSchema, output: { 200: { body: userResponseSchema }, 404: { body: errorSchema } } }, handler: async (ctx) => { const user = users[ctx.params.id]; if (!user) { ctx.status = 404; ctx.body = { error: 'User not found' }; return; } ctx.body = user; } }); // POST /api/users - Create user router.add({ method: 'post', path: '/', meta: { document: { summary: 'Create a new user', tags: ['Users'] } }, validate: { body: createUserSchema, output: { 201: { body: userResponseSchema }, 400: { body: errorSchema } } }, handler: async (ctx) => { const id = nextId++; const user = { id, ...ctx.request.body, createdAt: new Date() }; users[id] = user; ctx.status = 201; ctx.body = user; } }); // PUT /api/users/:id - Update user router.add({ method: 'put', path: '/:id', meta: { document: { summary: 'Update user', tags: ['Users'] } }, validate: { params: userIdSchema, body: updateUserSchema, output: { 200: { body: userResponseSchema }, 404: { body: errorSchema } } }, handler: async (ctx) => { const user = users[ctx.params.id]; if (!user) { ctx.status = 404; ctx.body = { error: 'User not found' }; return; } Object.assign(user, ctx.request.body); ctx.body = user; } }); // DELETE /api/users/:id - Delete user router.add({ method: 'delete', path: '/:id', meta: { document: { summary: 'Delete user', tags: ['Users'] } }, validate: { params: userIdSchema, output: { 204: { body: Joi.any() }, 404: { body: errorSchema } } }, handler: async (ctx) => { if (!users[ctx.params.id]) { ctx.status = 404; ctx.body = { error: 'User not found' }; return; } delete users[ctx.params.id]; ctx.status = 204; } }); app.use(bodyParser()); app.use(router.routes()); app.listen(3000); ``` -------------------------------- ### Create a product Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/examples.md Creates a new product with the provided details. ```APIDOC ## POST /api/products ### Description Creates a new product. ### Method POST ### Endpoint /api/products ### Parameters #### Request Body - **name** (string) - Required - The name of the product. - **price** (number) - Required - The price of the product. Must be positive. - **description** (string) - Optional - A description of the product. ### Response #### Success Response (201) - **id** (number) - The ID of the newly created product. - **name** (string) - The name of the product. - **price** (number) - The price of the product. - **createdAt** (date) - The timestamp when the product was created. ### Response Example { "id": 1, "name": "New Product", "price": 49.99, "createdAt": "2023-10-27T10:00:00.000Z" } ``` -------------------------------- ### GET Endpoint with Query Validation using JoiAdaptor Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/examples.md Shows how to add query parameter validation to a GET endpoint using koa-x-router with the JoiAdaptor. Requires Joi and koa-x-router to be installed. The validation schema defines required fields, number ranges, and default values. ```typescript import Koa from 'koa'; import Joi from 'joi'; import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; const app = new Koa(); const router = new Router({ adaptors: [JoiAdaptor] }); router.add({ method: 'get', path: '/search', validate: { query: Joi.object({ q: Joi.string().required(), limit: Joi.number().min(1).max(100).default(10), offset: Joi.number().min(0).default(0) }) }, handler: async (ctx) => { const { q, limit, offset } = ctx.query; ctx.body = { query: q, limit, offset, results: [ { id: 1, title: 'Result 1' }, { id: 2, title: 'Result 2' } ] }; } }); app.use(router.routes()); app.listen(3000); // Test: GET /search?q=test&limit=5 // Response: { query: 'test', limit: 5, offset: 0, results: [...] } // Missing 'q': HTTP 400 - '"q" is required' ``` -------------------------------- ### Instantiate Router with Multiple Adapters and Prefix Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/Router.md Shows how to initialize a Router with multiple validation adapters (Joi and Zod) and a specific path prefix '/api/v1'. ```typescript import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; import { ZodAdaptor } from 'koa-x-router/zod'; // Create router with prefix and multiple adapters const multiRouter = new Router({ adaptors: [JoiAdaptor, ZodAdaptor], prefix: '/api/v1' }); ``` -------------------------------- ### Initialize Router with CommonJS and JoiAdaptor Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/quick-start.md Set up a Koa-X-Router instance using CommonJS syntax and configuring it with the JoiAdaptor for validation. ```javascript const { Router } = require('koa-x-router'); const { JoiAdaptor } = require('koa-x-router/joi'); const { ZodAdaptor } = require('koa-x-router/zod'); const router = new Router({ adaptors: [JoiAdaptor] }); ``` -------------------------------- ### Multiple Koa-X-Routers with Different Configurations Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/configuration.md Demonstrates setting up multiple routers with distinct configurations, including different validation adaptors (Joi and Zod), prefixes, and advanced options like 'strict' and 'sensitive' for an admin router. Note the case-sensitive path '/Dashboard'. ```typescript import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; import { ZodAdaptor } from 'koa-x-router/zod'; import Joi from 'joi'; import { z } from 'zod'; const app = new Koa(); // V1 API with Joi validation const v1Router = new Router({ adaptors: [JoiAdaptor], prefix: '/api/v1' }); v1Router.add({ method: 'get', path: '/items', validate: { query: Joi.object({ limit: Joi.number().default(10) }) }, handler: async (ctx) => { ctx.body = []; } }); // V2 API with Zod validation const v2Router = new Router({ adaptors: [ZodAdaptor], prefix: '/api/v2' }); v2Router.add({ method: 'get', path: '/items', validate: { query: z.object({ limit: z.coerce.number().default(10) }) }, handler: async (ctx) => { ctx.body = []; } }); // Admin API with stricter configuration const adminRouter = new Router({ adaptors: [JoiAdaptor], prefix: '/admin', strict: true, sensitive: true }); adminRouter.add({ method: 'get', path: '/Dashboard', // Case-sensitive handler: async (ctx) => { ctx.body = { data: 'admin dashboard' }; } }); app.use(bodyParser()); app.use(v1Router.routes()); app.use(v2Router.routes()); app.use(adminRouter.routes()); app.listen(3000); // Endpoints: // GET /api/v1/items?limit=20 // GET /api/v2/items?limit=20 // GET /admin/Dashboard (case-sensitive, no trailing slashes) ``` -------------------------------- ### Initialize Router with Adaptors Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/Router.md Demonstrates how to initialize a new Router instance with a specific adaptor, such as JoiAdaptor. The 'adaptors' property will be populated with the provided adaptor instances, keyed by their names. ```typescript const router = new Router({ adaptors: [JoiAdaptor] }); console.log(router.adaptors); // { joi: JoiAdaptor } ``` -------------------------------- ### GET Route with Parameter and Response Validation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/README.md Defines a GET route to retrieve a user by ID, validating the ID parameter and the expected successful response structure. ```typescript router.add({ method: 'get', path: '/users/:id', validate: { params: Joi.object({ id: Joi.number().required() }), output: { 200: { body: Joi.object({ id: Joi.number().required(), name: Joi.string().required() }) }, 404: { body: Joi.object({ message: Joi.string().required() }) } } }, handler: async (ctx) => { ctx.body = { id: ctx.params.id, name: 'John' }; } }); ``` -------------------------------- ### Instantiate Router with Joi Validation Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/Router.md Demonstrates creating a Router instance with the Joi validation adapter and setting a '/api' prefix. Ensure JoiAdaptor and Joi are imported. ```typescript import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; import Joi from 'joi'; // Create router without validation const router = new Router(); // Create router with Joi validation const joiRouter = new Router({ adaptors: [JoiAdaptor], prefix: '/api' }); ``` -------------------------------- ### Router Constructor Source: https://github.com/ecube-labs/koa-x-router/blob/main/_autodocs/api-reference/Router.md Initializes a new Router instance. It can be configured with options including validation adapters, a path prefix, custom HTTP methods, and a router context path. ```APIDOC ## Constructor Router ### Description Initializes a new Router instance. It can be configured with options including validation adapters, a path prefix, custom HTTP methods, and a router context path. ### Parameters #### Options - **options** (object) - Optional - Router configuration object. Can include `KoaRouter.RouterOptions` and `adaptors`. - **options.adaptors** (XRouterAdaptor[]) - Optional - Array of validation adapters to use (e.g., `[JoiAdaptor]` or `[ZodAdaptor]`). - **options.prefix** (string) - Optional - Path prefix for all routes. - **options.methods** (string[]) - Optional - Custom HTTP methods to support. - **options.routerPath** (string) - Optional - Router context path. ### Returns - **Router** instance ### Example ```typescript import { Router } from 'koa-x-router'; import { JoiAdaptor } from 'koa-x-router/joi'; import Joi from 'joi'; // Create router without validation const router = new Router(); // Create router with Joi validation const joiRouter = new Router({ adaptors: [JoiAdaptor], prefix: '/api' }); // Create router with prefix and multiple adapters const multiRouter = new Router({ adaptors: [JoiAdaptor, ZodAdaptor], prefix: '/api/v1' }); ``` ``` -------------------------------- ### Run Codemod Source: https://github.com/ecube-labs/koa-x-router/blob/main/codemods/v0.1-adaptor-imports/README.md Execute the codemod to migrate adaptor imports. Review the changes and run tests before committing. ```bash npx codemod @ecube-labs/koa-x-router-v0-1-adaptor-imports ``` ```bash npx codemod @ecube-labs/koa-x-router-v0-1-adaptor-imports@0.1.0 ```