@syncafricabs/shared-kernel-core
v1.0.0
Published
Uniform API responses, robust validation, zero boilerplate — for Node.js.
Downloads
109
Maintainers
Readme
@syncafricabs/shared-kernel-core
Uniform API responses, robust validation, zero boilerplate — for Node.js and TypeScript. Available from npm.
Overview
This library provides a complete solution for building consistent RESTful APIs with:
- Standardized API Responses - Consistent JSON envelope format across your application
- Validation Utilities - Comprehensive field validation helpers
- Custom Exceptions - Pre-defined exception types for common scenarios
- Global Exception Handling - Automatic HTTP status code mapping for Express
- Utility Classes - Common helpers (slugify, truncate, currency formatting, etc.)
Installation
Package: @syncafricabs/shared-kernel-core
npm install @syncafricabs/shared-kernel-coreyarn add @syncafricabs/shared-kernel-corepnpm add @syncafricabs/shared-kernel-coreAPI Response Format
All responses follow this standardized JSON envelope:
{
"code": 200,
"message": "Operation successful",
"success": true,
"data": { ... }
}| Field | Type | Description |
|-------|------|-------------|
| code | number | HTTP status code (200, 201, 400, 401, 403, 404, 409, 500, etc.) |
| message | string | Human-readable message |
| success | boolean | true for successful operations, false for failures |
| data | any | Response payload (null for error responses) |
Response Examples
Success Responses
// 200 OK - Resource retrieved
{
"code": 200,
"message": "User retrieved successfully",
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "[email protected]"
}
}// 201 Created - Resource created
{
"code": 201,
"message": "User created successfully",
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Jane Doe",
"email": "[email protected]"
}
}// 204 No Content - Deleted successfully
{
"code": 204,
"message": "User deleted successfully",
"success": true,
"data": null
}Client Error Responses
// 400 Bad Request - Validation failed
{
"code": 400,
"message": "Validation failed",
"success": false,
"data": {
"email": "Email is required",
"password": "Password must be at least 8 characters long"
}
}// 401 Unauthorized - Invalid credentials
{
"code": 401,
"message": "Invalid credentials",
"success": false,
"data": null
}// 403 Forbidden - Access denied
{
"code": 403,
"message": "Access denied",
"success": false,
"data": null
}// 404 Not Found - Resource not found
{
"code": 404,
"message": "User not found",
"success": false,
"data": null
}// 409 Conflict - Resource already exists
{
"code": 409,
"message": "User already exists",
"success": false,
"data": null
}// 410 Gone - Expired resource or link
{
"code": 410,
"message": "Invitation link has expired",
"success": false,
"data": null
}// 422 Unprocessable Entity - Business rule violation
{
"code": 422,
"message": "Insufficient funds",
"success": false,
"data": null
}// 429 Too Many Requests - Rate limit exceeded
{
"code": 429,
"message": "Too many login attempts. Please try again later.",
"success": false,
"data": null
}// 423 Locked - Account or resource locked
{
"code": 423,
"message": "Account is locked due to suspicious activity",
"success": false,
"data": null
}// 402 Payment Required - Subscription or payment needed
{
"code": 402,
"message": "Subscription payment is required to access this feature",
"success": false,
"data": null
}// 501 Not Implemented - Feature not yet available
{
"code": 501,
"message": "This feature is not yet available in your region",
"success": false,
"data": null
}// 502 Bad Gateway - Upstream service failure
{
"code": 502,
"message": "Payment gateway is currently unavailable",
"success": false,
"data": null
}// 503 Service Unavailable - Maintenance or overloaded
{
"code": 503,
"message": "System is under maintenance. Please try again later.",
"success": false,
"data": null
}// 504 Gateway Timeout - Upstream timeout
{
"code": 504,
"message": "External reporting service timed out",
"success": false,
"data": null
}Server Error Responses
// 500 Internal Server Error
{
"code": 500,
"message": "An unexpected error occurred. Please try again later.",
"success": false,
"data": null
}Quick Start
Build API Responses
import { ApiEnvelope, ApiEnvelopeFactory, ResponseEntityBuilder } from '@syncafricabs/shared-kernel-core';
// Create a success response
const response: ApiEnvelope<User> = ApiEnvelopeFactory.success('User retrieved', user);
// Or use ResponseEntityBuilder for Express-compatible responses
const result = ResponseEntityBuilder.ok('User retrieved', user);
res.status(result.status).json(result.body);Validate Input Fields
import { GlobalFieldValidator } from '@syncafricabs/shared-kernel-core';
// Validate strings
GlobalFieldValidator.validateString(name, 'Name', 2, 100);
// Validate email
GlobalFieldValidator.validateEmail(email, 'Email');
// Validate phone
GlobalFieldValidator.validatePhone(phone, 'Phone');
// Validate URL
GlobalFieldValidator.validateUrl(website, 'Website');
// Validate UUID
GlobalFieldValidator.validateUUID(id, 'Id');
// Validate positive Long ID
GlobalFieldValidator.validatePositiveLong(userId, 'UserId');
// Validate integer
GlobalFieldValidator.validateInteger(count, 'Count');
// Validate period (days, 0-365)
GlobalFieldValidator.validatePeriod(days, 'Days');
// Validate size limit (1-1,000,000)
GlobalFieldValidator.validateSizeLimit(limit, 'Limit');Handle Exceptions
The library includes pre-defined exception types and an Express middleware for automatic HTTP mapping:
import {
ValidationException,
AlreadyExistsException,
NotFoundException,
MissingFieldsException,
UnauthorizedException,
NotAllowedException,
InvalidException,
RequestFailedException,
InsufficientFundsException,
TooManyRequestsException,
PaymentRequiredException,
TokenExpiredException,
SessionExpiredException,
AccountSuspendedException,
LockedException,
ConflictException,
QuotaExceededException,
ExternalServiceException,
DataIntegrityException,
ExpiredException,
ServiceUnavailableException,
InvalidTokenException,
PermissionDeniedException,
FeatureNotAvailableException,
BadGatewayException,
GatewayTimeoutException,
NotImplementedException,
MaintenanceModeException,
DoesNotExistException,
} from '@syncafricabs/shared-kernel-core';
import { GlobalExceptionHandler } from '@syncafricabs/shared-kernel-core';
// Throw these in your service layer
throw new ValidationException('Invalid input');
throw new AlreadyExistsException('User already exists');
throw new NotFoundException('User not found');
throw new MissingFieldsException('Email and password are required');
throw new UnauthorizedException('Invalid credentials');
throw new NotAllowedException('Access denied');
throw new InvalidException('Invalid state transition');
throw new RequestFailedException('Operation failed');
throw new InsufficientFundsException('Insufficient balance');
throw new TooManyRequestsException('Too many requests. Please try again later.');
throw new PaymentRequiredException('Subscription payment is required');
throw new TokenExpiredException('Token has expired');
throw new SessionExpiredException('Session has expired');
throw new AccountSuspendedException('Account is suspended');
throw new LockedException('Account is locked');
throw new ConflictException('Resource conflict detected');
throw new QuotaExceededException('Storage quota exceeded');
throw new ExternalServiceException('Payment gateway is unavailable');
throw new DataIntegrityException('Database constraint violation');
throw new ExpiredException('Link has expired');
throw new ServiceUnavailableException('Service is under maintenance');
throw new InvalidTokenException('Invalid token format');
throw new PermissionDeniedException('Permission denied');
throw new FeatureNotAvailableException('Feature not available in your region');
throw new BadGatewayException('Upstream service error');
throw new GatewayTimeoutException('Upstream service timeout');
throw new NotImplementedException('Feature not implemented');
throw new MaintenanceModeException('System is under maintenance');
throw new DoesNotExistException('Resource does not exist');Exception-to-HTTP Mapping:
| Exception | HTTP Status | Use Case |
|-----------|-------------|----------|
| ValidationException | 400 | Validation errors, invalid input |
| MissingFieldsException | 400 | Required fields missing |
| AlreadyExistsException / ConflictException | 409 | Resource already exists or business conflict |
| NotFoundException / DoesNotExistException | 404 | Resource not found |
| UnauthorizedException / TokenExpiredException / SessionExpiredException / InvalidTokenException | 401 | Authentication required, token/session expired, invalid token |
| NotAllowedException / InvalidException / AccountSuspendedException / LockedException / PermissionDeniedException | 403 | Access denied, account locked, permission denied |
| RequestFailedException | 500 | Server-side request failure |
| InsufficientFundsException / PaymentRequiredException | 400 | Insufficient funds or payment required |
| TooManyRequestsException / QuotaExceededException | 429 | Rate limit or quota exceeded |
| ExternalServiceException / BadGatewayException | 502 | Third-party API or upstream service failure |
| DataIntegrityException | 422 | Database constraint violation |
| ExpiredException | 410 | Expired links, offers, or resources |
| ServiceUnavailableException / MaintenanceModeException | 503 | System under maintenance or overloaded |
| GatewayTimeoutException | 504 | Upstream service timeout |
| NotImplementedException / FeatureNotAvailableException | 501 | Feature not yet implemented or unavailable |
| Generic Error | 500 | Unhandled server errors |
Express Integration
import express from 'express';
import { GlobalExceptionHandler, ApiEnvelopeFactory } from '@syncafricabs/shared-kernel-core';
const app = express();
app.use(express.json());
// Global exception handler
app.use(GlobalExceptionHandler.middleware());
app.use(GlobalExceptionHandler.validationErrorsMiddleware());
app.get('/api/users/:id', (req, res) => {
const { id } = req.params;
GlobalFieldValidator.validatePositiveLong(Number(id), 'Id');
const user = userService.findById(Number(id));
const result = ResponseEntityBuilder.ok('User retrieved', user);
res.status(result.status).json(result.body);
});
app.listen(3000);Controller Example
import express from 'express';
import { ResponseEntityBuilder, GlobalFieldValidator } from '@syncafricabs/shared-kernel-core';
const app = express();
app.use(express.json());
app.post('/api/users', (req, res) => {
const { name, email, age } = req.body;
GlobalFieldValidator.validateString(name, 'Name', 2, 100);
GlobalFieldValidator.validateEmail(email, 'Email');
GlobalFieldValidator.validatePositiveLong(age, 'Age');
const user = userService.create(req.body);
const result = ResponseEntityBuilder.created('User created successfully', user);
res.status(result.status).json(result.body);
});
app.get('/api/users/:id', (req, res) => {
const { id } = req.params;
GlobalFieldValidator.validatePositiveLong(Number(id), 'Id');
const user = userService.findById(Number(id));
const result = ResponseEntityBuilder.ok('User retrieved', user);
res.status(result.status).json(result.body);
});
app.delete('/api/users/:id', (req, res) => {
const { id } = req.params;
userService.delete(Number(id));
const result = ResponseEntityBuilder.noContent('User deleted');
res.status(result.status).json(result.body);
});
app.listen(3000);Utility Classes
import { BaseUtils } from '@syncafricabs/shared-kernel-core';
BaseUtils.formatCurrency(99.99, 'USD'); // $99.99
BaseUtils.formatPercentage(0.1567); // 15.67%
BaseUtils.generateSlug('Hello World'); // hello-world
BaseUtils.truncate('Some long text...', 10); // Some long ...
BaseUtils.maskString('1234567890'); // ******7890
BaseUtils.sanitizeHtml('<script>alert("xss")</script>'); // <script>alert("xss")</script>Project Structure
shared-kernel/
├── src/
│ ├── ApiEnvelope.ts # Generic API response envelope
│ ├── ApiEnvelopeFactory.ts # Factory for creating envelopes
│ ├── ResponseEntityBuilder.ts # Express-compatible response builder
│ ├── validation/
│ │ ├── GlobalFieldValidator.ts # Validators + custom annotations
│ │ └── index.ts
│ ├── exception/
│ │ ├── GlobalExceptionHandler.ts # Express error middleware
│ │ ├── ErrorResponse.ts # Error response DTO
│ │ └── [custom exceptions].ts # Custom exception types
│ └── configs/
│ ├── BaseUtils.ts # Utility classes
│ └── index.ts
├── package.json
├── tsconfig.json
└── README.mdLicense
Apache License, Version 2.0
Author
Providence Chikukwa
- Email: [email protected]
- GitHub: https://github.com/iamprovy-dev
- LinkedIn: https://www.linkedin.com/in/provychikukwa
- Organization: SyncAfrica Business Solutions (https://www.syncafricabs.com)