UNPKG

bnaya_fork_ra-data-nest-crud

Version:

a data provider for react admin that handles request from nestjsx-crud server

325 lines (276 loc) 9.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var raCore = require('ra-core'); var crudRequest = require('@nestjsx/crud-request'); /** @internal */ async function makeNestjsxCrudRequest(apiUrl, httpClient = raCore.fetchUtils.fetchJson, /** * experimental, not directly exposed * Will give us a hook to customize requets/responses */ configuration, type, resource, params) { let rawResponse; const parsedResource = extractRealResourceAndParams(resource); let requestIntermediate = { type, resource: parsedResource.realResource, params, integratedParams: parsedResource.integratedParams }; if (configuration && configuration.requestMutator) { requestIntermediate = configuration.requestMutator(requestIntermediate); } if (requestIntermediate.type === raCore.UPDATE_MANY) { rawResponse = await Promise.all(requestIntermediate.params.ids.map(id => httpClient(`${apiUrl}/${parsedResource.realResource}/${id}`, { method: "PUT", body: JSON.stringify(requestIntermediate.params.data) }))); } else if (requestIntermediate.type === raCore.DELETE_MANY) { rawResponse = await Promise.all(requestIntermediate.params.ids.map(id => httpClient(`${apiUrl}/${parsedResource.realResource}/${id}`, { method: "DELETE" }))); } else { const { url, options } = convertDataRequestToHTTP(apiUrl, requestIntermediate.type, // Original and not intermediate here. resource, requestIntermediate.params); rawResponse = await httpClient(url, options); } // maybe pass here original and not intermediate values? let responseIntermediate = { response: rawResponse, type: requestIntermediate.type, resource: requestIntermediate.resource, params: requestIntermediate.params }; if (configuration && configuration.responseMutator) { responseIntermediate = configuration.responseMutator(responseIntermediate, requestIntermediate); } const oneMoreIntermediateResponse = convertHTTPResponse(responseIntermediate.response, requestIntermediate); // in some conditions, we want to fetch fresh copy of the data from nest/crud. switch (requestIntermediate.type) { case "CREATE": case "UPDATE": return makeNestjsxCrudRequest(apiUrl, httpClient, configuration, "GET_ONE", resource, { id: oneMoreIntermediateResponse.data.id }); case "UPDATE_MANY": return Promise.all(oneMoreIntermediateResponse.data.map(({ id }) => makeNestjsxCrudRequest(apiUrl, httpClient, configuration, "GET_ONE", resource, { id }))).then(all => ({ data: all })); default: return oneMoreIntermediateResponse; } } /** @internal */ function convertHTTPResponse(rawResponse, request) { let toReturn = Array.isArray(rawResponse) ? { data: rawResponse.map(entry => entry.json) } : { data: rawResponse.json }; switch (request.type) { case raCore.DELETE_MANY: toReturn = { data: request.params.ids }; break; case raCore.GET_LIST: case raCore.GET_MANY_REFERENCE: toReturn = { data: rawResponse.json.data, total: rawResponse.json.total }; } return toReturn; } /** @internal */ function composeFilter(paramsFilter) { const flatFilter = raCore.fetchUtils.flattenObject(paramsFilter); const filter = Object.keys(flatFilter).map(key => { const splitKey = key.split("||"); const ops = splitKey[1] ? splitKey[1] : crudRequest.CondOperator.CONTAINS; let field = splitKey[0]; if (field.indexOf("_") === 0 && field.indexOf(".") > -1) { field = field.split(/\.(.+)/)[1]; } return { field, operator: ops, value: flatFilter[key] }; }); return filter; } /** @internal */ const MAGIC_SEPARATOR = "_._._._"; /** @internal */ function extractRealResourceAndParams(resourceMaybeWithEncoded) { if (!resourceMaybeWithEncoded.includes(MAGIC_SEPARATOR)) { return { realResource: resourceMaybeWithEncoded }; } const [realResource, paramsStr] = resourceMaybeWithEncoded.split(MAGIC_SEPARATOR); try { const integratedParams = JSON.parse(paramsStr); return { realResource, integratedParams }; } catch (e) { // @ts-ignore console.warn("failed to parse params", { realResource, paramsStr }); return { realResource }; } } /** @internal */ function convertDataRequestToHTTP(apiUrl, type, resource, params) { let url = ""; const options = {}; const parsedResource = extractRealResourceAndParams(resource); switch (type) { case raCore.GET_LIST: { const { page, perPage } = params.pagination; let query = crudRequest.RequestQueryBuilder // @ts-ignore .create({ filter: composeFilter(params.filter) }).setLimit(perPage).setPage(page).sortBy(params.sort).setOffset((page - 1) * perPage); if (parsedResource.integratedParams) { if (parsedResource.integratedParams.join) { parsedResource.integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (parsedResource.integratedParams.fields) { query = query.select(parsedResource.integratedParams.fields); } } url = `${apiUrl}/${parsedResource.realResource}?${query.query()}`; break; } case raCore.GET_ONE: { let query = crudRequest.RequestQueryBuilder.create(); if (parsedResource.integratedParams) { if (parsedResource.integratedParams.join) { parsedResource.integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (parsedResource.integratedParams.fields) { query = query.select(parsedResource.integratedParams.fields); } } url = `${apiUrl}/${parsedResource.realResource}/${params.id}?${query.query()}`; break; } case raCore.GET_MANY: { let query = crudRequest.RequestQueryBuilder.create().setFilter({ field: "id", operator: crudRequest.CondOperator.IN, value: `${params.ids}` }); if (parsedResource.integratedParams) { if (parsedResource.integratedParams.join) { parsedResource.integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (parsedResource.integratedParams.fields) { query = query.select(parsedResource.integratedParams.fields); } } url = `${apiUrl}/${parsedResource.realResource}?${query.query()}`; break; } case raCore.GET_MANY_REFERENCE: { const { page, perPage } = params.pagination; const filter = composeFilter(params.filter); filter.push({ field: params.target, operator: crudRequest.CondOperator.EQUALS, value: params.id }); let query = crudRequest.RequestQueryBuilder // @ts-ignore .create({ filter }).sortBy(params.sort).setLimit(perPage).setOffset((page - 1) * perPage); if (parsedResource.integratedParams) { if (parsedResource.integratedParams.join) { parsedResource.integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (parsedResource.integratedParams.fields) { query = query.select(parsedResource.integratedParams.fields); } } url = `${apiUrl}/${parsedResource.realResource}?${query.query()}`; break; } case raCore.UPDATE: { url = `${apiUrl}/${parsedResource.realResource}/${params.id}`; options.method = "PATCH"; options.body = JSON.stringify(params.data); break; } case raCore.CREATE: { url = `${apiUrl}/${parsedResource.realResource}`; options.method = "POST"; options.body = JSON.stringify(params.data); break; } case raCore.DELETE: { url = `${apiUrl}/${parsedResource.realResource}/${params.id}`; options.method = "DELETE"; break; } default: throw new Error(`Unsupported fetch action type ${type}`); } return { url, options }; } function createNestjsxCrudClient(apiUrl, httpClient = raCore.fetchUtils.fetchJson) { return makeNestjsxCrudRequest.bind(null, apiUrl, httpClient, {}); } /** * Not documented yet. Experimental. */ function createNestjsxCrudClientWithConfig(apiUrl, httpClient = raCore.fetchUtils.fetchJson, /** * Not documented yet. Experimental. * Will give us a hook to customize requets/responses */ configuration = {}) { return makeNestjsxCrudRequest.bind(null, apiUrl, httpClient, configuration); } function encodeParamsInResource(resource, paramsToIntegrate) { return `${resource}${MAGIC_SEPARATOR}${JSON.stringify(paramsToIntegrate)}`; } exports.createNestjsxCrudClientWithConfig = createNestjsxCrudClientWithConfig; exports.default = createNestjsxCrudClient; exports.encodeParamsInResource = encodeParamsInResource;