Betterez HTTP Service Utilities
btrz-http-service is a JavaScript utility library designed to streamline API development within the Betterez ecosystem. Currently at version 1.47.0, it offers a suite of tools including a Swagger request handler formatter for defining API endpoints, specialized success and error response handlers for consistent API feedback, a collection of common Swagger schemas, and robust Swagger schema validation. It also introduces a custom `ValidationError` type to standardize error reporting within the application. The library appears to be actively maintained with a steady release cadence, evidenced by its significant minor version increments. Its key differentiators include its tight integration with Swagger for API definition and validation, a structured approach to middleware and error handling, and its focus on providing consistent API behavior for Betterez applications.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'paramTypes')
cause `this.swagger` or `this.swagger.paramTypes` is undefined within a `RequestHandler`'s `getSpec` method.fixEnsure that the `RequestHandler` class is properly constructed with a `swagger` object that provides the `paramTypes` utility, or mock it during testing. In typical usage, an integrating framework provides this context. -
ValidationError: WRONG_DATA - The 'field_name' field is required.
cause A request body failed validation against its defined Swagger schema, indicating missing or invalid data.fixCheck the API documentation for the endpoint's schema requirements. Adjust the request payload to include all required fields and ensure data types and formats match the schema definition. The `WRONG_DATA` log entry should specify the model path and field value. -
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
cause Multiple attempts were made to send a response (e.g., using `res.send`, `res.json`, or a response handler) within a single request-response cycle, likely due to incorrect promise chaining or conditional logic.fixReview the code to ensure that only one response is sent per request. Pay close attention to asynchronous operations and promise chains, especially when using `ResponseHandlers.success` and `ResponseHandlers.error`, which should be terminal operations.
Warnings
- gotcha Older versions (v1.6.5 and earlier) of `btrz-http-service` used `swagger-validation` in a way that could mutate the original Swagger `models` object passed for validation. This could lead to unexpected side effects in applications that reuse the models.
- gotcha The `ResponseHandlers.success` and `ResponseHandlers.error` utilities are designed to be used only once at the very end of a promise chain. Calling them multiple times or at intermediate steps in a chain can lead to unexpected behavior or errors in API responses.
- gotcha When defining `getSpec()` in a `RequestHandler` class, ensure that `this.swagger.paramTypes` or other `this.swagger` properties are correctly initialized and available. Improper setup of the `swagger` object passed to the `RequestHandler` constructor can lead to `TypeError: Cannot read properties of undefined (reading 'paramTypes')`.
Install
-
npm install btrz-http-service -
yarn add btrz-http-service -
pnpm add btrz-http-service
Imports
- swaggerRequestHandler
import { swaggerRequestHandler } from 'btrz-http-service';const swaggerRequestHandler = require('btrz-http-service').swaggerRequestHandler; - ResponseHandlers
import { ResponseHandlers } from 'btrz-http-service';const ResponseHandlers = require('btrz-http-service').ResponseHandlers; - validateSwaggerSchema
import { validateSwaggerSchema } from 'btrz-http-service';const validateSwaggerSchema = require('btrz-http-service').validateSwaggerSchema; - ValidationError
import { ValidationError } from 'btrz-http-service';const ValidationError = require('btrz-http-service').ValidationError;
Quickstart
const { swaggerRequestHandler, ResponseHandlers } = require('btrz-http-service');
// A mock request object for demonstration
const mockReq = { body: { items: ['item1', 'item2'] } };
// A mock response object with methods expected by ResponseHandlers
const mockRes = {
statusCode: 200,
data: null,
status(code) { this.statusCode = code; return this; },
send(data) { this.data = data; console.log(`Response Status: ${this.statusCode}, Data:`, this.data); },
json(data) { this.data = data; console.log(`Response Status: ${this.statusCode}, JSON:`, this.data); },
};
class RequestHandler {
constructor(swagger) {
this.swagger = swagger; // In a real app, this might be injected or provided
}
getSpec() {
return {
"description": "endpoint description",
"path": "/endpoint",
"summary": "endpoint summary",
"method": "POST",
"parameters": [
{
"name": "items",
"in": "body",
"description": "the items",
"schema": { "type": "array", "items": { "type": "string" } },
"required": true
}
],
"produces": ["application/json"],
"type": "Schema",
"errorResponses": [],
"nickname": "nick"
};
}
async handler(req, res) {
console.log('Handler received request body:', req.body);
try {
// Simulate an async operation
await new Promise(resolve => setTimeout(resolve, 100));
if (!req.body || !Array.isArray(req.body.items) || req.body.items.length === 0) {
throw new Error('No items provided');
}
const processedData = req.body.items.map(item => item.toUpperCase());
console.log('Processed data:', processedData);
// Use success handler
ResponseHandlers.success(res)(processedData);
} catch (error) {
console.error('Handler error:', error.message);
// Use error handler
ResponseHandlers.error(res)(error);
}
}
}
// Mock middleware for demonstration
function passportAuthenticate(req, res, next) {
console.log('Running passportAuthenticate middleware');
// Simulate authentication success
next();
}
function otherMiddleware(req, res, next) {
console.log('Running otherMiddleware');
// Simulate some other processing
next();
}
// Create a handler instance (mocking swagger object as it's not provided in context)
const handlerInstance = new RequestHandler({});
// Generate the swagger handler with middleware
const swaggerHandler = swaggerRequestHandler(passportAuthenticate, otherMiddleware, handlerInstance);
// Simulate calling the generated swaggerHandler
console.log('--- Simulating API Call ---');
swaggerHandler(mockReq, mockRes);