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
JavaScript
;
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;