UNPKG

@metis-w/api-client

Version:

Modern TypeScript HTTP API client with dynamic routes, parameterized endpoints, interceptors, and advanced features

196 lines 10.3 kB
import { CacheManager } from "../managers"; import { MethodResolver, RouteValidator, } from "../../utils"; /** * Manages the creation and building of dynamic routes for the DynamicClient. * Handles route creation, action handlers, and parameterized routes. */ export class RouteBuilder { /** * Creates a dynamic route for the specified controller. * If the route is already cached, it returns the cached version. * Otherwise, it creates a new route and caches it. * * @param controller - The controller name to create the route for * @param cacheManager - The cache manager instance to use for caching routes * @param requestMethod - The method to call for making HTTP requests * @param methodOptions - Options for HTTP method resolution * @returns A dynamic route function that can handle actions and parameterized routes */ static createRoute(controller, cacheManager, requestMethod, methodOptions = {}) { if (cacheManager.hasRoute(controller)) { return cacheManager.getRoute(controller); } const routeFunction = (id) => { return id !== undefined ? this.createParameterizedRoute(controller, id, cacheManager, requestMethod, methodOptions) : this.createActionRoute(controller, cacheManager, requestMethod, methodOptions); }; const cachedProxy = new Proxy(routeFunction, { get: (_, action) => RouteValidator.isValidAction(action) ? this.createActionHandler(controller, action, requestMethod, methodOptions) : undefined, }); cacheManager.setRoute(controller, cachedProxy); return cachedProxy; } /** * Creates a dynamic action route for the specified controller. * If the action route is already cached, it returns the cached version. * Otherwise, it creates a new action route and caches it. * * @param controller - The controller name to create the action route for * @param cacheManager - The cache manager instance to use for caching routes * @param requestMethod - The method to call for making HTTP requests * @param methodOptions - Options for HTTP method resolution * @returns A dynamic action route object */ static createActionRoute(controller, cacheManager, requestMethod, methodOptions = {}) { const cacheKey = CacheManager.generateActionCacheKey(controller); if (cacheManager.hasActionRoute(cacheKey)) { return cacheManager.getActionRoute(cacheKey); } const actionRoute = new Proxy({}, { get: (_, action) => RouteValidator.isValidAction(action) ? this.createActionHandler(controller, action, requestMethod, methodOptions) : undefined, }); cacheManager.setActionRoute(cacheKey, actionRoute); return actionRoute; } /** * Creates an action handler for the specified controller and action. * If the action handler is already cached, it returns the cached version. * Otherwise, it creates a new action handler and caches it. * * @param controller - The controller name to create the action handler for * @param action - The action name to create the handler for * @param requestMethod - The method to call for making HTTP requests * @param methodOptions - Options for HTTP method resolution * @returns A dynamic action handler function */ static createActionHandler(controller, action, requestMethod, methodOptions = {}) { const baseEndpoint = `/${controller}/${action}`; const mainHandler = (payload, queryParams) => { const explicitMethod = payload && typeof payload === "object" && "method" in payload ? payload.method : undefined; const httpMethod = MethodResolver.determineMethod(action, methodOptions, explicitMethod); const cleanPayload = payload && typeof payload === "object" && "method" in payload ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "method")) : payload; return requestMethod(baseEndpoint, cleanPayload, { params: queryParams, method: httpMethod, }); }; return new Proxy(mainHandler, { get: (_, subAction) => RouteValidator.isValidAction(subAction) ? this.createSubActionHandler(baseEndpoint, subAction, requestMethod, methodOptions) : undefined, }); } /** * Creates a parameterized route for the specified controller and ID. * If the parameterized route is already cached, it returns the cached version. * Otherwise, it creates a new parameterized route and caches it. * * @param controller - The controller name to create the parameterized route for * @param id - The ID to use in the parameterized route * @param cacheManager - The cache manager instance to use for caching routes * @param requestMethod - The method to call for making HTTP requests * @param methodOptions - Options for HTTP method resolution * @returns A dynamic parameterized route object */ static createParameterizedRoute(controller, id, cacheManager, requestMethod, methodOptions = {}) { const cacheKey = CacheManager.generateParameterizedCacheKey(controller, id); if (cacheManager.hasParameterizedRoute(cacheKey)) { return cacheManager.getParameterizedRoute(cacheKey); } // Створюємо функцію, яка може бути викликана безпосередньо const baseEndpoint = `/${controller}/${id}`; const paramFunction = (payload, queryParams) => { const explicitMethod = payload && typeof payload === "object" && "method" in payload ? payload.method : undefined; // Для прямого виклику використовуємо GET якщо немає payload, інакше PUT для оновлення const defaultAction = payload && Object.keys(payload).length > 0 ? "update" : "get"; const httpMethod = MethodResolver.determineMethod(defaultAction, methodOptions, explicitMethod); const cleanPayload = payload && typeof payload === "object" && "method" in payload ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "method")) : payload; return requestMethod(baseEndpoint, cleanPayload, { params: queryParams, method: httpMethod, }); }; const paramRoute = new Proxy(paramFunction, { get: (_, action) => { if (!RouteValidator.isValidAction(action)) return undefined; const endpoint = `/${controller}/${id}/${action}`; const paramHandler = this.createEndpointHandler(endpoint, requestMethod, methodOptions, action); return new Proxy(paramHandler, { get: (_, subAction) => RouteValidator.isValidAction(subAction) ? this.createSubActionHandler(endpoint, subAction, requestMethod, methodOptions) : undefined, }); }, }); cacheManager.setParameterizedRoute(cacheKey, paramRoute); return paramRoute; } /** * Creates a handler for a specific endpoint. * This is used for both main actions and sub-actions. * * @param endpoint - The endpoint to create the handler for * @param requestMethod - The method to call for making HTTP requests * @param methodOptions - Options for HTTP method resolution * @param actionName - The action name for method resolution * @returns A function that can be called with payload and query parameters */ static createEndpointHandler(endpoint, requestMethod, methodOptions = {}, actionName) { return (payload, queryParams) => { const explicitMethod = payload && typeof payload === "object" && "method" in payload ? payload.method : undefined; const action = actionName || endpoint.split("/").pop() || ""; const httpMethod = MethodResolver.determineMethod(action, methodOptions, explicitMethod); const cleanPayload = payload && typeof payload === "object" && "method" in payload ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "method")) : payload; return requestMethod(endpoint, cleanPayload, { params: queryParams, method: httpMethod, }); }; } /** * Creates a handler for sub-actions. * * @param baseEndpoint - The base endpoint for the sub-action * @param subAction - The sub-action name * @param requestMethod - The method to call for making HTTP requests * @param methodOptions - Options for HTTP method resolution * @returns A function that can be called with payload and query parameters */ static createSubActionHandler(baseEndpoint, subAction, requestMethod, methodOptions = {}) { const path = `${baseEndpoint}/${subAction}`; return (payload, queryParams) => { // Визначаємо HTTP метод для sub-action const explicitMethod = payload && typeof payload === "object" && "method" in payload ? payload.method : undefined; const httpMethod = MethodResolver.determineMethod(subAction, methodOptions, explicitMethod); // Видаляємо method з payload, якщо він там є const cleanPayload = payload && typeof payload === "object" && "method" in payload ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "method")) : payload; return requestMethod(path, cleanPayload, { params: queryParams, method: httpMethod, }); }; } } //# sourceMappingURL=route-builder.js.map