UNPKG

@fleye-me/ra-data-nest-crud

Version:
309 lines (259 loc) 9.22 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('ra-core'), require('@nestjsx/crud-request')) : typeof define === 'function' && define.amd ? define(['exports', 'ra-core', '@nestjsx/crud-request'], factory) : (global = global || self, factory(global.index = {}, global.raCore, global.crudRequest)); }(this, function (exports, raCore, crudRequest) { 'use strict'; const MAGIC_SEPARATOR = "_._._._"; const POSSIBLE_SINGLE_ACTIONS = ["GET_ONE", "GET_MANY", "CREATE", "UPDATE", "DELETE"]; function extractRealData(resource) { // Not encoded, return it if (resource.indexOf(MAGIC_SEPARATOR) === -1) { return { realResource: resource }; } const [realResource, paramsStr] = resource.split(MAGIC_SEPARATOR); try { const integratedParams = JSON.parse(paramsStr); return { realResource, integratedParams }; } catch (error) { console.warn("failed to parse params", { realResource, paramsStr, error }); return { realResource }; } } function httpParse(rawResponse, request) { const { json } = rawResponse; let toReturn = POSSIBLE_SINGLE_ACTIONS.includes(request.type) ? { data: json } : json; return toReturn; } function composeFilter(paramsFilter) { const flatFilter = raCore.fetchUtils.flattenObject(paramsFilter); if (paramsFilter["$search"]) { return { s: paramsFilter["$search"] }; } const filter = Object.keys(flatFilter).map(key => { const splitKey = key.split("||"); const operator = splitKey[1] || crudRequest.CondOperator.CONTAINS; let field = splitKey[0]; if (field.indexOf("_") === 0 && field.indexOf(".") !== -1) { field = field.split(/\.(.+)/)[1]; } return { field, operator, value: flatFilter[key] }; }); return filter; } /* eslint-disable @typescript-eslint/no-object-literal-type-assertion */ function dataRequestToHTTP(apiUrl, type, resource, params) { let url = ""; const options = {}; const parsedResource = extractRealData(resource); const { realResource } = parsedResource; const integratedParams = parsedResource.integratedParams || {}; switch (type) { case raCore.GET_LIST: { const { page, perPage } = params.pagination; const composedFilter = composeFilter(params.filter); let filter = {}; if (composedFilter["s"]) { filter = composedFilter["s"]; } else { filter = { filter: composedFilter }; } let query = crudRequest.RequestQueryBuilder.create({ ...filter }).setLimit(perPage).setPage(page).sortBy(params.sort).setOffset((page - 1) * perPage); if (integratedParams.join) { integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (integratedParams.fields) { query = query.select(integratedParams.fields); } url = `${apiUrl}/${realResource}?${query.query()}`; break; } case raCore.GET_ONE: { let query = crudRequest.RequestQueryBuilder.create(); if (integratedParams.join) { integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (integratedParams.fields) { query = query.select(integratedParams.fields); } url = `${apiUrl}/${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 (integratedParams.join) { integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (integratedParams.fields) { query = query.select(integratedParams.fields); } url = `${apiUrl}/${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.create({ filter }).sortBy(params.sort).setLimit(perPage).setOffset((page - 1) * perPage); if (integratedParams.join) { integratedParams.join.forEach(join => { query = query.setJoin(join); }); } if (integratedParams.fields) { query = query.select(integratedParams.fields); } url = `${apiUrl}/${realResource}?${query.query()}`; break; } case raCore.UPDATE: { url = `${apiUrl}/${realResource}/${params.id}`; options.method = "PATCH"; options.body = JSON.stringify(params.data); break; } case raCore.CREATE: { url = `${apiUrl}/${realResource}`; options.method = "POST"; options.body = JSON.stringify(params.data); break; } case raCore.DELETE: { url = `${apiUrl}/${realResource}/${params.id}`; options.method = "DELETE"; break; } default: throw new Error(`Unsupported fetch action type ${type}`); } return { url, options }; } /** * Experimental, not directly exposed * Will give us a hook to customize requets/responses */ async function makeRequest(apiUrl, httpClient = raCore.fetchUtils.fetchJson, configuration, type, resource, params) { let rawResponse; const parsedResource = extractRealData(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 } = dataRequestToHTTP(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); } let oneMoreIntermediateResponse = httpParse(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 makeRequest(apiUrl, httpClient, configuration, "GET_ONE", resource, { id: responseIntermediate.response.json.id }); default: return oneMoreIntermediateResponse; } } function createNestjsxCrudClient(apiUrl, httpClient = raCore.fetchUtils.fetchJson) { return makeRequest.bind(null, apiUrl, httpClient, {}); } /** * Not documented yet. Experimental. * Will give us a hook to customize requets/responses */ function createNestjsxCrudClientWithConfig(apiUrl, httpClient = raCore.fetchUtils.fetchJson, configuration = {}) { return makeRequest.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; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=index.js.map