@applica-software-guru/crud-client
Version:
Libreria per l'accesso ai servizi REST di Applica.
351 lines (329 loc) • 10.5 kB
text/typescript
import { ApplicaDataProviderConfig, AttachmentParserResult, IApplicaDataProvider } from './types';
import { createFormData, createGetQuery, fetchJson } from './utils';
import { stringify } from 'query-string';
import {
CreateParams,
CreateResult,
DeleteManyParams,
DeleteManyResult,
DeleteParams,
DeleteResult,
GetListParams,
GetListResult,
GetManyParams,
GetManyReferenceParams,
GetManyReferenceResult,
GetManyResult,
GetOneParams,
GetOneResult,
Identifier,
UpdateManyParams,
UpdateManyResult,
UpdateParams,
UpdateResult
} from 'ra-core';
class ApplicaDataProvider implements IApplicaDataProvider {
config: ApplicaDataProviderConfig;
prepareData: (data: any, resource?: string, params?: CreateParams | UpdateParams | any) => any;
prepareAttachments: (data: any) => Promise<AttachmentParserResult>;
constructor(config: ApplicaDataProviderConfig) {
this.config = config;
this.prepareData = config.prepareData || ((data: any) => data);
this.prepareAttachments = config.attachmentsParser;
}
/**
* @inheritdoc
*/
getApiUrl(): string {
return this.config.apiUrl;
}
/**
* @inheritdoc
*/
async getFile(resource: string): Promise<string> {
const headers = await this.config.getHeaders();
return fetch(`${this.config.apiUrl}${resource}`, { headers })
.then((response) => response.blob())
.then((blob) => URL.createObjectURL(blob));
}
/**
* @inheritdoc
*/
async getList(resource: string, params: GetListParams | any): Promise<GetListResult | any> {
const query = createGetQuery(params);
const url = `${this.config.apiUrl}/${resource}/find`;
const headers = await this.config.getHeaders();
const options = {
headers,
body: JSON.stringify(query),
method: 'POST'
};
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: json?.value?.rows,
total: parseInt(json?.value?.totalRows)
}));
}
/**
* @inheritdoc
*/
async getOne(resource: string, params: GetOneParams | any): Promise<GetOneResult | any> {
const url = `${this.config.apiUrl}/${resource}` + (params.id ? `/${params.id}` : '');
const headers = await this.config.getHeaders();
const options = { headers };
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: json.value
}));
}
/**
* @inheritdoc
*/
async getMany(resource: string, params: GetManyParams | any): Promise<GetManyResult | any> {
const url = `${this.config.apiUrl}/${resource}/find`;
const headers = await this.config.getHeaders();
const options = {
headers,
body: JSON.stringify({
filters: [
{
property: 'id',
value: params.ids,
type: 'in'
}
]
}),
method: 'POST'
};
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: json?.value?.rows,
total: parseInt(json?.value?.totalRows)
}));
}
/**
* @inheritdoc
*/
async getManyReference(resource: string, params: GetManyReferenceParams): Promise<GetManyReferenceResult> {
const query = createGetQuery(params);
const url = `${this.config.apiUrl}/${resource}/find`;
const headers = await this.config.getHeaders();
query.filters.push({
property: params.target,
value: params.id,
type: 'eq'
});
const options = {
headers,
body: JSON.stringify(query),
method: 'POST'
};
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: json?.value?.rows,
total: parseInt(json?.value?.totalRows)
}));
}
/**
* @inheritdoc
*/
async create(resource: string, params: CreateParams): Promise<CreateResult> {
return this.prepareAttachments(params.data).then(async ({ data, parts }) => {
const url = `${this.config.apiUrl}/${resource}`;
const token = await this.config.getToken();
let body: any = null;
let headers: any = {};
if (this.config.mobile === true) {
body = this.prepareData(data, resource, params);
body = JSON.stringify(body);
headers = {
'Content-Type': 'application/json'
};
} else {
body = new FormData();
const jsonData = JSON.stringify(this.prepareData(data, resource, params));
const entity = new Blob([jsonData], { type: 'application/json' });
body.append('entity', entity);
parts.forEach((p) => body.append(p.id, p.file));
}
const options = this.createOptions(
{
method: 'POST',
body,
headers
},
token
);
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: { ...(json?.value || params.data), id: json?.value.id }
}));
});
}
/**
* @inheritdoc
*/
async update(resource: string, params: UpdateParams): Promise<UpdateResult> {
return this.prepareAttachments(params.data).then(async ({ data, parts }) => {
const url = `${this.config.apiUrl}/${resource}`;
const token = await this.config.getToken();
let body: any = null;
let headers: any = {};
if (this.config.mobile === true) {
body = this.prepareData(data, resource, params);
body = JSON.stringify(body);
headers = {
'Content-Type': 'application/json'
};
} else {
body = new FormData();
const jsonData = JSON.stringify(this.prepareData(data, resource, params));
const entity = new Blob([jsonData], { type: 'application/json' });
body.append('entity', entity);
parts.forEach((p) => body.append(p.id, p.file));
}
const options = this.createOptions(
{
method: 'POST',
body,
headers
},
token
);
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: { ...(json?.value || params.data), id: json?.value.id }
}));
});
}
/**
* @inheritdoc
*/
async updateMany(
resource: string,
params: UpdateManyParams & {
rows?: any[];
}
): Promise<UpdateManyResult> {
const token = await this.config.getToken();
return Promise.all(
params.ids.map((id: Identifier) =>
fetchJson(
`${this.config.apiUrl}/${resource}`,
{
method: 'POST',
body: (() => {
if (this.config.mobile === true) {
const row = params?.rows?.[id as number] || params?.rows?.find((r: any) => r.id === id);
const entity = JSON.stringify(this.prepareData({ ...row, ...params.data, id }));
return entity;
} else {
const row = params?.rows?.[id as number] || params?.rows?.find((r: any) => r.id === id);
const jsonData = JSON.stringify(this.prepareData({ ...row, ...params.data, id }));
const entity = new Blob([jsonData], { type: 'application/json' });
const formData = new FormData();
formData.append('entity', entity);
return formData;
}
})(),
headers: (() =>
this.config.mobile === true
? this.createHeaders(
{
'Content-Type': 'application/json'
},
token
)
: this.createHeaders({}, token))()
},
this.config.HttpErrorClass
).then(({ json }) => ({
data: { ...(json?.value || params.data), id: json?.value.id }
}))
)
).then((responses) => ({
data: responses.map((response) => response.data)
}));
}
/**
* @inheritdoc
*/
async delete(resource: string, params: DeleteParams | any): Promise<DeleteResult | any> {
const url = `${this.config.apiUrl}/${resource}/delete`;
const token = await this.config.getToken();
const body = createFormData({ ids: params.id });
const options = this.createOptions(
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Accept: 'application/json'
},
body
},
token
);
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: json
}));
}
/**
* @inheritdoc
*/
async deleteMany(resource: string, params: DeleteManyParams | any): Promise<DeleteManyResult | any> {
const token = await this.config.getToken();
const url = `${this.config.apiUrl}/${resource}/delete`;
const options = this.createOptions(
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Accept: 'application/json'
},
body: createFormData({ ids: params.ids })
},
token
);
return fetchJson(url, options, this.config.HttpErrorClass).then(() => ({
data: params.ids
}));
}
private async _call(method: string, resource: string, params: any): Promise<any> {
let url = `${this.config.apiUrl}/${resource}`;
if (method === 'GET' && params) {
const queryString = stringify(params);
url = `${this.config.apiUrl}/${resource}?${queryString}`;
}
const headers = await this.config.getHeaders();
const options = {
method,
headers,
body: method !== 'GET' ? JSON.stringify(params) : undefined
};
return fetchJson(url, options, this.config.HttpErrorClass).then(({ json }) => ({
data: json
}));
}
/**
* @inheritdoc
*/
async post(resource: string, params: object): Promise<any> {
return this._call('POST', resource, params);
}
/**
* @inheritdoc
*/
async get(resource: string, params: object): Promise<any> {
return this._call('GET', resource, params);
}
private createHeaders(headers: any, token?: string) {
const authHeaders =
typeof token === 'string' && token !== undefined && token !== null ? { Authorization: `Bearer ${token}` } : {};
return {
...headers,
...authHeaders
};
}
private createOptions(options: any, token?: string): any {
const headers = this.createHeaders(options?.headers, token);
return {
...options,
headers
};
}
}
export { ApplicaDataProvider };