UNPKG

@simpleapps-com/augur-api

Version:

TypeScript client library for Augur microservices API endpoints

198 lines 6.97 kB
import { z } from 'zod'; /** * Custom Zod schema for MySQL datetime format * Matches format: YYYY-MM-DD HH:mm:ss */ export const mysqlDatetimeSchema = () => z .string() .regex(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, 'Invalid MySQL datetime format. Expected: YYYY-MM-DD HH:mm:ss'); /** * Standard error response data structure * Matches the BaseResponse pattern but for error scenarios */ export const ErrorResponseDataSchema = z.object({ /** Error code identifier */ code: z.string(), /** Human-readable error message */ message: z.string(), /** Optional error details for debugging */ details: z.record(z.unknown()).optional(), /** Timestamp of when the error occurred */ timestamp: z.string().optional(), /** Request ID for tracking */ requestId: z.string().optional(), }); /** * Validation error details schema * Used when request parameters or body fail validation */ export const ValidationErrorDetailSchema = z.object({ /** Field path that failed validation */ field: z.string(), /** Validation error message */ message: z.string(), /** Error code (e.g., 'required', 'invalid_type', 'too_small') */ code: z.string(), /** Value that was received */ received: z.unknown().optional(), /** Value that was expected */ expected: z.unknown().optional(), }); /** * Validation error response data schema * Extends the base error response with validation-specific details */ export const ValidationErrorResponseDataSchema = ErrorResponseDataSchema.extend({ /** Array of validation errors */ validationErrors: z.array(ValidationErrorDetailSchema), }); /** * Standard error response schema following BaseResponse pattern * All error responses MUST use this 8-field structure */ export const ErrorResponseSchema = z.object({ count: z.literal(0), // Always 0 for error responses data: ErrorResponseDataSchema, message: z.string(), // High-level error message options: z.record(z.unknown()).default({}), params: z.record(z.unknown()).default({}), status: z.number().int().min(400).max(599), // HTTP error status codes only total: z.literal(0), // Always 0 for error responses totalResults: z.literal(0), // Always 0 for error responses }); /** * Validation error response schema following BaseResponse pattern * Used specifically for request validation failures (HTTP 400) */ export const ValidationErrorResponseSchema = z.object({ count: z.literal(0), data: ValidationErrorResponseDataSchema, message: z.string(), options: z.record(z.unknown()).default({}), params: z.record(z.unknown()).default({}), status: z.literal(400), // Always 400 for validation errors total: z.literal(0), totalResults: z.literal(0), }); /** * Common HTTP error response schemas * These provide standardized error responses for common HTTP status codes */ export const CommonErrorSchemas = { /** HTTP 400 - Bad Request (validation errors) */ 400: ValidationErrorResponseSchema, /** HTTP 401 - Unauthorized (authentication required) */ 401: ErrorResponseSchema.extend({ status: z.literal(401), data: ErrorResponseDataSchema.extend({ code: z.literal('AUTHENTICATION_REQUIRED'), }), }), /** HTTP 403 - Forbidden (insufficient permissions) */ 403: ErrorResponseSchema.extend({ status: z.literal(403), data: ErrorResponseDataSchema.extend({ code: z.literal('INSUFFICIENT_PERMISSIONS'), }), }), /** HTTP 404 - Not Found (resource not found) */ 404: ErrorResponseSchema.extend({ status: z.literal(404), data: ErrorResponseDataSchema.extend({ code: z.literal('RESOURCE_NOT_FOUND'), }), }), /** HTTP 409 - Conflict (resource already exists or conflict) */ 409: ErrorResponseSchema.extend({ status: z.literal(409), data: ErrorResponseDataSchema.extend({ code: z.literal('RESOURCE_CONFLICT'), }), }), /** HTTP 422 - Unprocessable Entity (business logic errors) */ 422: ErrorResponseSchema.extend({ status: z.literal(422), data: ErrorResponseDataSchema.extend({ code: z.literal('BUSINESS_LOGIC_ERROR'), }), }), /** HTTP 429 - Too Many Requests (rate limiting) */ 429: ErrorResponseSchema.extend({ status: z.literal(429), data: ErrorResponseDataSchema.extend({ code: z.literal('RATE_LIMIT_EXCEEDED'), details: z .object({ retryAfter: z.number().optional(), limit: z.number().optional(), remaining: z.number().optional(), resetTime: z.string().optional(), }) .optional(), }), }), /** HTTP 500 - Internal Server Error */ 500: ErrorResponseSchema.extend({ status: z.literal(500), data: ErrorResponseDataSchema.extend({ code: z.literal('INTERNAL_SERVER_ERROR'), }), }), /** HTTP 502 - Bad Gateway (upstream service error) */ 502: ErrorResponseSchema.extend({ status: z.literal(502), data: ErrorResponseDataSchema.extend({ code: z.literal('UPSTREAM_SERVICE_ERROR'), }), }), /** HTTP 503 - Service Unavailable (temporary outage) */ 503: ErrorResponseSchema.extend({ status: z.literal(503), data: ErrorResponseDataSchema.extend({ code: z.literal('SERVICE_UNAVAILABLE'), details: z .object({ retryAfter: z.number().optional(), maintenanceWindow: z.string().optional(), }) .optional(), }), }), /** HTTP 504 - Gateway Timeout (upstream timeout) */ 504: ErrorResponseSchema.extend({ status: z.literal(504), data: ErrorResponseDataSchema.extend({ code: z.literal('UPSTREAM_TIMEOUT'), }), }), }; /** * Simple schema utilities for common patterns */ export class SchemaUtils { /** * Create pagination parameters schema */ static createPaginatedParamsSchema(additionalFields, defaultLimit = 20) { const baseFields = { limit: z.coerce.number().int().min(1).max(1000).optional().default(defaultLimit), offset: z.coerce.number().int().min(0).optional().default(0), orderBy: z.string().optional(), q: z.string().optional(), }; return z.object({ ...baseFields, ...additionalFields, }); } /** * Create search parameters schema */ static createSearchParamsSchema(additionalFields) { return this.createPaginatedParamsSchema({ searchType: z.enum(['query', 'category', 'brand']).optional().default('query'), ...additionalFields, }); } } //# sourceMappingURL=schema-utils.js.map