@kenniy/godeye-data-contracts
Version:
Enterprise-grade base repository architecture for GOD-EYE microservices with zero overhead and maximum code reuse
618 lines (617 loc) • 24 kB
JavaScript
"use strict";
/**
* Unified Swagger Documentation System
* Standardized API documentation across all services
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.optimizeDescription = optimizeDescription;
exports.ApiResponseWithOptimizedDescription = ApiResponseWithOptimizedDescription;
exports.ApiResponse = ApiResponse;
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
/**
* Default description configuration
*/
const DEFAULT_DESCRIPTION_CONFIG = {
maxLength: 500,
truncateAt: 450,
addEllipsis: true,
preserveFormatting: false,
};
/**
* Truncate and optimize description text for Swagger UI
* Handles large descriptions by truncating them and preserving important information
*/
function optimizeDescription(description, config = {}) {
const finalConfig = { ...DEFAULT_DESCRIPTION_CONFIG, ...config };
const originalLength = description.length;
if (originalLength <= finalConfig.maxLength) {
return {
description,
isTruncated: false,
originalLength,
};
}
// Find a good truncation point (prefer end of sentence)
let truncateAt = finalConfig.truncateAt;
const truncationZone = description.substring(truncateAt - 50, truncateAt + 50);
const sentenceEnd = truncationZone.match(/[.!?]\s/);
if (sentenceEnd) {
const sentenceEndIndex = truncationZone.indexOf(sentenceEnd[0]) + (truncateAt - 50);
if (sentenceEndIndex > 0 && sentenceEndIndex < finalConfig.maxLength) {
truncateAt = sentenceEndIndex + 1;
}
}
let truncatedDescription = description.substring(0, truncateAt).trim();
if (finalConfig.addEllipsis) {
truncatedDescription += "...";
}
// Add truncation notice
const remainingChars = originalLength - truncateAt;
truncatedDescription += `\n\n*[Truncated: ${remainingChars} more characters. See external documentation for full details.]*`;
return {
description: truncatedDescription,
isTruncated: true,
originalLength,
};
}
/**
* Enhanced API decorator with description optimization
*/
function ApiResponseWithOptimizedDescription(dataType, options) {
const optimizedDesc = optimizeDescription(options.description, options.descriptionConfig);
return ApiResponse(dataType, {
...options,
description: optimizedDesc.description,
});
}
/**
* Unified API Response Decorator
* Replaces @ApiSuccessResponse, @ApiPaginatedResponse, @CommonApiErrorResponses
*/
function ApiResponse(dataType, options) {
const decorators = [];
// Add the data type to extra models
decorators.push((0, swagger_1.ApiExtraModels)(dataType));
// Success response schema
const successSchema = options.paginated
? createPaginatedResponseSchema(dataType, options.description)
: createSuccessResponseSchema(dataType, options.description);
decorators.push((0, swagger_1.ApiResponse)({
status: options.status_code || common_1.HttpStatus.OK,
description: options.description,
schema: successSchema,
}));
// Add error responses
if (options.errors) {
options.errors.forEach((errorType) => {
decorators.push(createErrorResponseDecorator(errorType));
});
}
return (0, common_1.applyDecorators)(...decorators);
}
/**
* Create success response schema with enhanced support for deeply populated responses
*/
function createSuccessResponseSchema(dataType, description) {
return {
type: "object",
required: [
"success",
"message",
"data",
"status_code",
"time_ms",
"timestamp",
"trace_id",
],
properties: {
success: {
type: "boolean",
example: true,
description: "Indicates if the operation was successful",
},
message: {
type: "string",
example: description,
description: "Human-readable message describing the result",
},
data: {
$ref: (0, swagger_1.getSchemaPath)(dataType),
description: "Response data payload",
},
status_code: {
type: "number",
example: 200,
description: "HTTP status code",
},
time_ms: {
type: "number",
example: 45,
description: "Request processing time in milliseconds",
},
timestamp: {
type: "string",
example: "2025-08-01T10:30:00.000Z",
description: "ISO 8601 timestamp of the response",
},
trace_id: {
type: "string",
example: "trace_1725182200000_abc123def",
description: "Unique trace identifier for request tracking",
},
metadata: {
type: "object",
description: "BLAZING FAST enhanced metadata with comprehensive query and performance info",
nullable: true,
properties: {
queryTime: {
type: "string",
example: "45ms",
description: "Query execution time with unit",
},
searchAlgorithms: {
type: "array",
items: { type: "string" },
example: ["exact", "fuzzy"],
description: "Search algorithms used in query processing",
},
backendConditions: {
type: "array",
items: { type: "string" },
example: ["status", "isDeleted"],
description: "Backend conditions applied to the query",
},
relationsLoaded: {
type: "array",
items: { type: "string" },
example: ["profile", "permissions"],
description: "Relations that were loaded/populated",
},
relationErrors: {
type: "array",
items: { type: "string" },
example: [],
description: "Any relation loading errors encountered",
},
filters: {
type: "object",
properties: {
appliedFilters: {
type: "array",
items: { type: "string" },
example: ["status"],
description: "Currently applied filters",
},
availableFilters: {
type: "array",
items: { type: "string" },
example: ["status", "role", "business_type"],
description: "Available filter options",
},
},
description: "Filter metadata",
},
sorting: {
type: "object",
properties: {
sortBy: {
type: "string",
example: "created_at",
description: "Current sort field",
},
sortOrder: {
type: "string",
enum: ["asc", "desc"],
example: "desc",
description: "Sort direction",
},
availableSorts: {
type: "array",
items: { type: "string" },
example: ["created_at", "updated_at", "name"],
description: "Available sort fields",
},
},
description: "Sorting metadata",
},
ms_speed: {
type: "number",
example: 45,
description: "Processing speed in milliseconds (legacy)",
},
cpu_usage_percent: {
type: "number",
example: 23.5,
description: "CPU usage percentage",
},
memory_used_mb: {
type: "number",
example: 128.4,
description: "Memory usage in MB",
},
heap_used_mb: {
type: "number",
example: 64.2,
description: "Heap memory usage in MB",
},
cache_hit: {
type: "boolean",
example: true,
description: "Whether cache was hit (legacy)",
},
cacheStatus: {
type: "string",
enum: ["hit", "miss", "bypass"],
example: "hit",
description: "Cache status",
},
lastUpdated: {
type: "string",
example: "2025-08-01T10:30:00.000Z",
description: "Last update timestamp",
},
},
},
},
};
}
/**
* Create BLAZING FAST paginated response schema with standardized structure
*/
function createPaginatedResponseSchema(dataType, description) {
return {
type: "object",
required: [
"success",
"message",
"data",
"status_code",
"time_ms",
"timestamp",
"trace_id",
],
properties: {
success: {
type: "boolean",
example: true,
description: "Indicates if the operation was successful",
},
message: {
type: "string",
example: description,
description: "Human-readable message describing the result",
},
data: {
type: "object",
required: [
"items",
"total",
"page",
"limit",
"totalPages",
"hasNext",
"hasPrev",
],
properties: {
items: {
type: "array",
items: { $ref: (0, swagger_1.getSchemaPath)(dataType) },
description: "Array of data items",
},
total: {
type: "number",
example: 25,
description: "Total number of items available",
},
page: {
type: "number",
example: 1,
description: "Current page number (1-based)",
},
limit: {
type: "number",
example: 10,
description: "Number of items per page",
},
totalPages: {
type: "number",
example: 3,
description: "Total number of pages (camelCase)",
},
hasNext: {
type: "boolean",
example: true,
description: "Whether there is a next page (camelCase)",
},
hasPrev: {
type: "boolean",
example: false,
description: "Whether there is a previous page (camelCase)",
},
},
description: "BLAZING FAST paginated data container with items and pagination info",
},
status_code: {
type: "number",
example: 200,
description: "HTTP status code",
},
time_ms: {
type: "number",
example: 150,
description: "Request processing time in milliseconds",
},
timestamp: {
type: "string",
example: "2025-07-29T10:30:00.000Z",
description: "ISO 8601 timestamp of the response",
},
trace_id: {
type: "string",
example: "trace_1722164200000_abc123def",
description: "Unique trace identifier for request tracking",
},
metadata: {
type: "object",
description: "BLAZING FAST enhanced metadata with comprehensive query and performance info",
nullable: true,
properties: {
queryTime: {
type: "string",
example: "120ms",
description: "Query execution time with unit",
},
searchAlgorithms: {
type: "array",
items: { type: "string" },
example: ["fuzzy", "exact", "contains"],
description: "Search algorithms used in query processing",
},
backendConditions: {
type: "array",
items: { type: "string" },
example: ["status", "isDeleted", "isVerified"],
description: "Backend conditions applied to the query",
},
relationsLoaded: {
type: "array",
items: { type: "string" },
example: ["business", "profile", "permissions"],
description: "Relations that were loaded/populated",
},
relationErrors: {
type: "array",
items: { type: "string" },
example: [],
description: "Any relation loading errors encountered",
},
activeCount: {
type: "number",
example: 8,
description: "Number of active items",
},
pendingCount: {
type: "number",
example: 3,
description: "Number of pending items",
},
suspendedCount: {
type: "number",
example: 1,
description: "Number of suspended items",
},
filters: {
type: "object",
properties: {
appliedFilters: {
type: "array",
items: { type: "string" },
example: ["role", "status", "business_type"],
description: "Currently applied filters",
},
availableFilters: {
type: "array",
items: { type: "string" },
example: [
"role",
"status",
"job_title",
"business_type",
"permissions",
],
description: "Available filter options",
},
},
description: "Filter metadata",
},
sorting: {
type: "object",
properties: {
sortBy: {
type: "string",
example: "invited_at",
description: "Current sort field",
},
sortOrder: {
type: "string",
enum: ["asc", "desc"],
example: "desc",
description: "Sort direction",
},
availableSorts: {
type: "array",
items: { type: "string" },
example: [
"invited_at",
"activated_at",
"first_name",
"last_name",
"status",
],
description: "Available sort fields",
},
},
description: "Sorting metadata",
},
ms_speed: {
type: "number",
example: 85,
description: "Processing speed in milliseconds (legacy)",
},
cpu_usage_percent: {
type: "number",
example: 34.2,
description: "CPU usage percentage",
},
memory_used_mb: {
type: "number",
example: 156.7,
description: "Memory usage in MB",
},
heap_used_mb: {
type: "number",
example: 78.3,
description: "Heap memory usage in MB",
},
cache_hit: {
type: "boolean",
example: false,
description: "Whether cache was hit (legacy)",
},
cacheStatus: {
type: "string",
enum: ["hit", "miss", "bypass"],
example: "hit",
description: "Cache status",
},
lastUpdated: {
type: "string",
example: "2025-07-15T14:30:00.000Z",
description: "Last update timestamp",
},
},
},
},
};
}
/**
* Create error response decorator
*/
function createErrorResponseDecorator(errorType) {
const errorConfig = getErrorConfig(errorType);
return (0, swagger_1.ApiResponse)({
status: errorConfig.status,
description: errorConfig.description,
schema: {
type: "object",
required: [
"success",
"error",
"message",
"status_code",
"time_ms",
"timestamp",
"trace_id",
],
properties: {
success: {
type: "boolean",
example: false,
description: "Indicates if the operation was successful",
},
error: {
type: "string",
example: errorConfig.error,
description: "Error code or type",
},
message: {
type: "string",
example: errorConfig.message,
description: "Human-readable error message",
},
status_code: {
type: "number",
example: errorConfig.status,
description: "HTTP status code",
},
time_ms: {
type: "number",
example: 25,
description: "Request processing time in milliseconds",
},
timestamp: {
type: "string",
example: "2025-07-29T10:30:00.000Z",
description: "ISO 8601 timestamp of the response",
},
trace_id: {
type: "string",
example: "trace_1722164200000_abc123def",
description: "Unique trace identifier for request tracking",
},
metadata: {
type: "object",
description: "Additional error metadata",
nullable: true,
},
},
},
});
}
/**
* Get error configuration
*/
function getErrorConfig(errorType) {
const configs = {
BadRequest: {
status: common_1.HttpStatus.BAD_REQUEST,
error: "Bad Request",
message: "Invalid input data provided",
description: "Validation failed - Invalid input data",
},
Unauthorized: {
status: common_1.HttpStatus.UNAUTHORIZED,
error: "Unauthorized",
message: "Authentication required",
description: "Authentication failed - Invalid credentials or missing token",
},
Forbidden: {
status: common_1.HttpStatus.FORBIDDEN,
error: "Forbidden",
message: "Access denied",
description: "Access denied - Insufficient permissions",
},
NotFound: {
status: common_1.HttpStatus.NOT_FOUND,
error: "Not Found",
message: "Resource not found",
description: "Resource not found",
},
Conflict: {
status: common_1.HttpStatus.CONFLICT,
error: "Conflict",
message: "Resource already exists",
description: "Resource conflict - Data already exists",
},
UnprocessableEntity: {
status: common_1.HttpStatus.UNPROCESSABLE_ENTITY,
error: "Unprocessable Entity",
message: "Business logic validation failed",
description: "Business logic validation failed",
},
TooManyRequests: {
status: common_1.HttpStatus.TOO_MANY_REQUESTS,
error: "Too Many Requests",
message: "Rate limit exceeded",
description: "Rate limit exceeded",
},
InternalServerError: {
status: common_1.HttpStatus.INTERNAL_SERVER_ERROR,
error: "Internal Server Error",
message: "An unexpected error occurred",
description: "Internal server error",
},
};
return (configs[errorType] || configs.InternalServerError);
}