@myko.pk/response
v1.0.1
Published
Shared response utilities, builders, and exception filters for MYKO services
Readme
📑 Table of Contents
- Description
- Key Features
- Use Cases
- Tech Stack
- Quick Start
- Available Scripts
- Project Structure
- Contributors
- Contributing
- License
📝 Description
@myko.pk/response provides a standardised response envelope (ApiResponse<T>) and a set of reusable NestJS exception filters for every MYKO service. The ResponseBuilder class offers a fluent API for constructing success, error, paginated, cursor-paginated, and specialised responses. Built-in exception filters handle HttpException, validation errors, database errors, and auth failures — all rendered into a consistent ApiResponse shape.
The package also includes a request context system (AsyncLocalStorage-based requestId tracking across the request lifecycle), decorators for fine-grained control over response wrapping, reusable pagination DTOs, a Swagger decorator to document the ApiResponse envelope, and a validation error formatter utility.
✨ Key Features
- 📦 Unified Response Envelope — Every response follows the
ApiResponse<T>shape:success,statusCode,message,data,error,timestamp,requestId. - 🏗️ Fluent Response Builder —
ResponseBuilder.success(),ResponseBuilder.error(),ResponseBuilder.paginated(),ResponseBuilder.cursorPaginated(),ResponseBuilder.ok(), and specialised methods for bulk, import/export, redirect, file download, and partial success. - 🛡️ Configurable Exception Filters — 5 NestJS exception filters covering global, validation, HTTP, database, and auth exceptions. Register all or pick specific ones via
ResponseModule.forRoot(). - 🔄 Response Interceptor — Automatically wraps controller returns into
ApiResponse. Respects@SkipResponseWrapper()and@ResponseMessage()decorators. - 🔗 Request Context —
RequestContextInterceptorcaptures or generates arequestId(viax-request-idheader orcrypto.randomUUID()) and stores it in AsyncLocalStorage. Access it anywhere withresponseContext.getStore(). - 📐 Reusable DTOs —
PaginatedQueryDtoandCursorPaginatedQueryDtowithclass-validatordecorators for consistent pagination parameters. - 📘 Swagger Integration —
@ApiResponseEnvelope(YourDto)decorator documents the fullApiResponse<T>wrapper shape in your OpenAPI spec. - 🔍 Validation Formatter —
formatValidationErrors()flattens NestJSValidationError[]into a structured{ field, constraints, children? }[]shape. - 📘 Fully Typed — Full TypeScript support with strict mode, typed response envelopes, and filter options.
🎯 Use Cases
- Standardising API response format across all MYKO NestJS microservices.
- Replacing ad-hoc error handling with consistent, typed exception filters.
- Automatically wrapping all controller responses in a uniform envelope.
- Tracking request IDs across the entire request lifecycle without manual parameter passing.
- Handling validation errors with structured field-level error messages.
- Documenting the
ApiResponseenvelope in Swagger/OpenAPI without manual schema definitions. - Building paginated endpoints with reusable, validated query DTOs.
- Rendering user-friendly error pages for browser-facing requests.
🛠️ Tech Stack
- 📘 TypeScript (strict mode)
- 🪺 NestJS (optional:
@nestjs/swaggerfor OpenAPI decorator) - 🚂 Express
⚡ Quick Start
Installation
npm install @myko.pk/response
# Optional — for paginated DTOs
npm install class-validator class-transformer
# Optional — for Swagger decorator
npm install @nestjs/swaggerResponse Builder
import { ResponseBuilder } from '@myko.pk/response';
// Success response
ResponseBuilder.success(data, 'User fetched', 200, requestId);
ResponseBuilder.created(newUser); // 201
ResponseBuilder.ok('Operation completed'); // 200, no data
ResponseBuilder.noContent('Item deleted'); // 204
// Error response
ResponseBuilder.error('User not found', 'USER_NOT_FOUND', 404, 'User ID: 123', requestId);
// Offset pagination
ResponseBuilder.paginated(items, total, page, limit);
// Cursor pagination (infinite scroll / load more)
ResponseBuilder.cursorPaginated(items, total, nextCursor, hasNextPage, limit);Module Registration
import { Module } from '@nestjs/common';
import { ResponseModule } from '@myko.pk/response';
@Module({
imports: [
ResponseModule.forRoot({
filters: ['GLOBAL', 'VALIDATION', 'HTTP', 'DATABASE', 'AUTH'],
enableResponseWrapper: true, // auto-wrap controller returns
enableRequestContext: true, // auto-track requestId via AsyncLocalStorage
}),
],
})
export class AppModule {}Decorators
import { SkipResponseWrapper, ResponseMessage } from '@myko.pk/response';
@SkipResponseWrapper() // skip auto-wrapping for this route
@ResponseMessage('Users fetched') // override default "Success" message
@Get('/users')
getUsers() { ... }Swagger
import { ApiResponseEnvelope } from '@myko.pk/response';
import { UserDto } from './user.dto';
@Get('/users')
@ApiResponseEnvelope(UserDto) // documents ApiResponse<UserDto> in OpenAPI
getUsers() { ... }Paginated DTOs
import { PaginatedQueryDto, CursorPaginatedQueryDto } from '@myko.pk/response';
@Get('/users')
async getUsers(@Query() query: PaginatedQueryDto) {
// query.page -> number (default 1)
// query.limit -> number (default 20, max 100)
}Request Context (AsyncLocalStorage)
import { responseContext } from '@myko.pk/response';
// Inside any service (after RequestContextInterceptor has run)
const ctx = responseContext.getStore();
console.log(ctx?.requestId); // "abc-123"
console.log(ctx?.path); // "/api/users"
console.log(ctx?.method); // "GET"🚀 Available Scripts
- build —
npm run build(tsup → CJS + ESM + DTS, copies views/) - dev —
npm run dev(tsup --watch) - typecheck —
npm run typecheck(tsc --noEmit)
📁 Project Structure
.
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── SECURITY.md
├── package.json
├── docs/
│ ├── README.md
│ └── QUICK-START.md
├── src
│ ├── builders
│ │ └── response.builder.ts
│ ├── decorators
│ │ ├── skip-response-wrapper.decorator.ts
│ │ └── response-message.decorator.ts
│ ├── dto
│ │ └── paginated-query.dto.ts
│ ├── filters
│ │ ├── auth.filter.ts
│ │ ├── database.filter.ts
│ │ ├── global-exception.filter.ts
│ │ ├── http-exception.filter.ts
│ │ └── validation.filter.ts
│ ├── interceptors
│ │ ├── response.interceptor.ts
│ ├── request-context
│ │ ├── request-context.interceptor.ts
│ ├── swagger
│ │ └── api-response-envelope.decorator.ts
│ ├── validation
│ │ └── validation-formatter.ts
│ ├── index.ts
│ ├── response.constants.ts
│ ├── response.context.ts
│ ├── response.module.ts
│ ├── types.ts
│ └── views-path.ts
├── tsconfig.json
├── tsup.config.mjs
└── views
└── error.hbs🛠️ Development Setup
- Install Node.js (v18+ recommended)
- Install dependencies:
npm install - Build:
npm run build
Note: This package does not currently have tests. Tests will be added in a future release.
👥 Contributors
See the full list of contributors →
👥 Contributing
Contributions are welcome! Here's the standard flow:
- Fork the repository
- Clone your fork:
git clone https://github.com/mykopk/response.git - Branch:
git checkout -b feature/your-feature - Commit:
git commit -m 'feat: add some feature' - Push:
git push origin feature/your-feature - Open a pull request
Please follow the existing code style and include tests for new behavior where applicable.
📜 License
This project is licensed under the MIT License.
MYKO Pakistan
Detail Information Website myko.pk Email [email protected] About Building digital infrastructure and super-app experiences for millions of users across Pakistan. Built with ❤️ in Pakistan 🇵🇰
