UNPKG

dreamstate

Version:

Store management library based on react context and observers

133 lines (130 loc) 5.39 kB
import { __values } from 'tslib'; import { DreamstateError } from '../error/DreamstateError.js'; import { QUERY_METADATA_SYMBOL } from '../internals.js'; import { EDreamstateErrorCode } from '../../types/error.js'; /** * Promisifies a query handler by wrapping it in a `Promise`. * * This function takes a query handler, and if it's asynchronous, it adds `.then` and `.catch` handlers to it. * If the query handler is synchronous, it directly returns the result or rejects the promise in case of an error. * It is useful for handling queries that may either return a promise or a direct result, ensuring consistent * promise-based handling. * * @template R - The type of the response expected from the query handler. * @template D - The type of data associated with the query request (optional). * @template T - The type of the query (defaults to `TQueryType`). * @param {TQueryListener<T, D, R>} callback - The query handler function that is called when the query is executed. * It can either be synchronous or asynchronous. * @param {IOptionalQueryRequest<D, T>} query - The query request containing necessary data for the query. * @param {TAnyContextManagerConstructor | null} answerer - The context manager class reference * that is handling the query. * @returns {Promise<TQueryResponse<R>>} A promise that resolves with the query response, either from the * synchronous result or the asynchronous operation. */ function promisifyQuery(callback, query, answerer) { return new Promise(function (resolve, reject) { try { var timestamp_1 = Date.now(); var result = callback(query); /* * Not all query responders are sync or async. * Here we expect it to be either sync or async and handle it in an async way. */ if (result instanceof Promise) { return result.then(function (data) { resolve({ answerer: answerer || callback, type: query.type, data: data, timestamp: timestamp_1 }); }).catch(reject); } else { return resolve({ answerer: answerer || callback, type: query.type, data: result, timestamp: timestamp_1 }); } } catch (error) { reject(error); } }); } /** * Finds the correct asynchronous listener or an array of listeners and returns the promise response or null. * * This function searches for a matching async listener based on the provided query type. If a listener is found, * it invokes the corresponding method and returns the result as a promise. If no matching listener is found, * the function returns `null`. It is useful for handling queries that require asynchronous processing and * responding with a promise. * * @template R - The type of the response expected from the query. * @template D - The type of the data associated with the query request. * @template T - The type of the query. * @template Q - The type of the query request (extends `IOptionalQueryRequest<D, T>`). * @param {Q} query - The query request containing the necessary data for the query. * @param {IRegistry} registry - An object containing registries for `CONTEXT_INSTANCES_REGISTRY` * and `QUERY_PROVIDERS_REGISTRY`, which store context instances and query providers for the respective queries. * @returns {Promise<TQueryResponse<R> | null>} A promise that resolves with the query response if a matching listener * is found, or `null` if no listener matches the query type. */ function queryDataAsync(query, _a) { var e_1, _b, e_2, _c; var CONTEXT_INSTANCES_REGISTRY = _a.CONTEXT_INSTANCES_REGISTRY, QUERY_PROVIDERS_REGISTRY = _a.QUERY_PROVIDERS_REGISTRY; if (!query || !query.type) { throw new DreamstateError(EDreamstateErrorCode.INCORRECT_PARAMETER, "Query must be an object with declared type or array of objects with type."); } try { /* * Managers classes are in priority over custom handlers. * Registered in order of creation. */ for (var _d = __values(CONTEXT_INSTANCES_REGISTRY.values()), _e = _d.next(); !_e.done; _e = _d.next()) { var service = _e.value; try { for (var _f = (e_2 = void 0, __values(service[QUERY_METADATA_SYMBOL])), _g = _f.next(); !_g.done; _g = _f.next()) { var entry = _g.value; if (query.type === entry[1]) { var method = entry[0]; return promisifyQuery(service[method].bind(service), query, service.constructor); } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_g && !_g.done && (_c = _f.return)) _c.call(_f); } finally { if (e_2) throw e_2.error; } } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_e && !_e.done && (_b = _d.return)) _b.call(_d); } finally { if (e_1) throw e_1.error; } } /* * From class providers fallback to manually listed query provider factories. */ if (QUERY_PROVIDERS_REGISTRY.has(query.type)) { var handlerFunction = QUERY_PROVIDERS_REGISTRY.get(query.type)[0]; return promisifyQuery(handlerFunction, query, null); } /* * Resolve null if nothing was found to handle request. */ return Promise.resolve(null); } export { queryDataAsync };