integreat
Version:
Node.js integration layer
82 lines • 3.79 kB
JavaScript
import debugLib from 'debug';
import pLimit from 'p-limit';
import { createErrorResponse, createUnknownServiceError, combineResponses, setOrigin, } from '../utils/response.js';
import mutateAndSend from '../utils/mutateAndSend.js';
import { isObject } from '../utils/is.js';
const debug = debugLib('great');
const isErrorResponse = (response) => isObject(response) &&
response.status !== 'ok' &&
response.status !== 'notfound' &&
response.status !== 'noaction';
const hasId = ({ payload: { id } }) => !!id;
const getIdFromAction = ({ payload: { id } }) => Array.isArray(id) && id.length === 1 ? id[0] : id;
function combineIndividualResponses(action, responses) {
const errorResponses = responses.filter(isErrorResponse);
if (errorResponses.length > 0) {
const combinedResponse = combineResponses(errorResponses);
return setOrigin({
...combinedResponse,
error: `One or more of the requests for ids ${getIdFromAction(action)} failed with the following error(s): ${combinedResponse.error}`,
}, 'handler:GET');
}
else {
return {
...action.response,
status: 'ok',
data: responses.map((response) => Array.isArray(response.data) ? response.data[0] : response.data),
};
}
}
const setIdOnActionPayload = (action, id) => ({
...action,
payload: { ...action.payload, id },
});
const createNoEndpointError = (action, serviceId) => createErrorResponse(`No endpoint matching ${action.type} request to service '${serviceId}'.`, 'handler:GET', 'badrequest');
async function runAsIndividualActions(action, service, dispatch) {
const actions = action.payload.id.map((individualId) => setIdOnActionPayload(action, individualId));
const representativeAction = actions.find(hasId);
if (!representativeAction) {
return combineIndividualResponses(action, actions.map(() => ({ status: 'noaction', data: null })));
}
const endpoint = await service.endpointFromAction(representativeAction);
if (!endpoint) {
return createNoEndpointError(action, service.id);
}
const responses = await Promise.all(actions.map((individualAction) => hasId(individualAction)
? pLimit(1)(() => mutateAndSend(service, endpoint, individualAction, dispatch))
: { status: 'noaction', data: null }));
return combineIndividualResponses(action, responses);
}
const isMembersAction = (action) => Array.isArray(action.payload.id);
async function runOneOrMany(action, service, dispatch) {
const endpoint = await service.endpointFromAction(action);
if (!endpoint) {
if (isMembersAction(action)) {
return runAsIndividualActions(action, service, dispatch);
}
else {
return createNoEndpointError(action, service.id);
}
}
else {
return mutateAndSend(service, endpoint, action, dispatch);
}
}
export default async function get(action, { getService, dispatch }) {
const { type, targetService: serviceId, endpoint: endpointId, } = action.payload;
const id = getIdFromAction(action);
if (Array.isArray(id) && id.length === 0) {
return createErrorResponse('GET action was dispatched with empty array of ids', 'handler:GET', 'noaction');
}
const service = getService(type, serviceId);
if (!service) {
return createUnknownServiceError(type, serviceId, 'GET');
}
const endpointDebug = endpointId
? `endpoint '${endpointId}'`
: `endpoint matching type '${type}' and id '${id}'`;
debug('GET: Fetch from service %s at %s', service.id, endpointDebug);
const nextAction = setIdOnActionPayload(action, id);
return await runOneOrMany(nextAction, service, dispatch);
}
//# sourceMappingURL=get.js.map