Skip to content

Commit

Permalink
Merge pull request #28 from webzard-io/fix/http_error_handle
Browse files Browse the repository at this point in the history
fix: data api's get one throw error when get empty data and transform http error
  • Loading branch information
Yuyz0112 authored Nov 29, 2023
2 parents 5bb58e7 + 00a98ae commit 8b06fba
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 95 deletions.
56 changes: 56 additions & 0 deletions __tests__/utils/transform-http-error.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { transformHttpError } from '../../src/utils/transform-http-error';

describe('transformHttpError', () => {
it('should return an HttpError object with statusText and status code if error has response', () => {
const error = {
response: {
statusText: 'Not Found',
status: 404,
},
};

const expected = {
...error,
message: 'Not Found',
statusCode: 404,
};

expect(transformHttpError(error)).toEqual(expected);
});

it('should return an HttpError object with error message, undefined statusCode if error does not have response', () => {
const error = new Error('Internal Server Error');

const expected = {
error: error,
message: 'Internal Server Error',
statusCode: undefined,
};

expect(transformHttpError(error)).toEqual(expected);
});

it('should return an HttpError object with error message as JSON string if error is an object', () => {
const error = { message: 'Bad Request' };

const expected = {
error: error,
message: '{"message":"Bad Request"}',
statusCode: undefined,
};

expect(transformHttpError(error)).toEqual(expected);
});

it('should return an HttpError object with error message as string if error is not an object', () => {
const error = 'Unauthorized';

const expected = {
error: error,
message: 'Unauthorized',
statusCode: undefined,
};

expect(transformHttpError(error)).toEqual(expected);
});
});
219 changes: 124 additions & 95 deletions src/data-provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { filterData } from '../utils/filter-data';
import { sortData } from '../utils/sort-data';
import { paginateData } from '../utils/paginate-data';
import { GlobalStore } from '../global-store';
import { transformHttpError } from '../utils/transform-http-error';

export function getId(obj: Unstructured) {
if (!obj.metadata?.namespace) {
Expand All @@ -36,76 +37,90 @@ export const dataProvider = (
const getOne = async <TData extends BaseRecord = BaseRecord>(
params: Parameters<DataProvider['getOne']>['0']
): Promise<GetOneResponse<TData>> => {
const { resource, id, meta } = params;
const idParts = id.toString().split('/');
const [namespace, name] =
idParts.length === 1 ? [undefined, idParts[0]] : idParts;
const { items, kind, apiVersion } = await globalStore.get(resource, meta);
const data = items.find(
item =>
item.metadata.name === name && item.metadata.namespace === namespace
);
if (!data) {
console.error(`resource: ${resource} not include id: ${id}`);
return { data: null as unknown as TData };
try {
const { resource, id, meta } = params;
const idParts = id.toString().split('/');
const [namespace, name] =
idParts.length === 1 ? [undefined, idParts[0]] : idParts;
const { items, kind, apiVersion } = await globalStore.get(resource, meta);
const data = items.find(
item =>
item.metadata.name === name && item.metadata.namespace === namespace
);
if (!data) {
throw new Error(`resource: ${resource} not include id: ${id}`);
}
return {
data: {
...data,
id: getId(data),
kind: kind.replace(/List$/g, ''),
apiVersion: apiVersion,
} as unknown as TData,
};
} catch (e) {
const httpError = transformHttpError(e);
throw httpError;
}
return {
data: {
...data,
id: getId(data),
kind: kind.replace(/List$/g, ''),
apiVersion: apiVersion,
} as unknown as TData,
};
};

return {
getList: async <TData extends BaseRecord = BaseRecord>(
params: Parameters<DataProvider['getList']>['0']
): Promise<GetListResponse<TData>> => {
const { resource, pagination, filters, sorters, meta } = params;
let { items } = await globalStore.get<TData>(resource, meta);

if (filters) {
items = filterData(filters, items);
try {
const { resource, pagination, filters, sorters, meta } = params;
let { items } = await globalStore.get<TData>(resource, meta);

if (filters) {
items = filterData(filters, items);
}

if (sorters) {
items = sortData(sorters, items);
}
const _total = items.length;

if (pagination) {
items = paginateData(pagination, items);
}

return {
data: items.map((item: Unstructured) => ({
...item,
id: getId(item),
})),
total: _total,
};
} catch (e) {
const httpError = transformHttpError(e);
throw httpError;
}

if (sorters) {
items = sortData(sorters, items);
}
const _total = items.length

if (pagination) {
items = paginateData(pagination, items);
}

return {
data: items.map((item: Unstructured) => ({
...item,
id: getId(item),
})),
total: _total,
};
},

getMany: async <
TData extends BaseRecord = BaseRecord,
TVariables = unknown
TVariables = unknown,
>(params: {
resource: string;
ids: BaseKey[];
variables?: TVariables | undefined;
meta?: MetaQuery | undefined;
metaData?: MetaQuery | undefined;
}): Promise<GetManyResponse<TData>> => {
const { ids, ...rest } = params;
const data = await Promise.all(
ids.map(id => getOne({ id, ...rest }).then(v => v.data))
);

return {
data: data as unknown as TData[],
};
try {
const { ids, ...rest } = params;
const data = await Promise.all(
ids.map(id => getOne({ id, ...rest }).then(v => v.data))
);

return {
data: data as unknown as TData[],
};
} catch (e) {
const httpError = transformHttpError(e);
throw httpError;
}
},

create: async <TData extends BaseRecord = BaseRecord>({
Expand All @@ -118,18 +133,22 @@ export const dataProvider = (
basePath: globalStore.apiUrl,
fieldManager: globalStore.fieldManager,
});

const data = await sdk.createyYaml([
{
...(variables as unknown as Unstructured),
apiVersion: getApiVersion(meta?.resourceBasePath),
kind: meta?.kind,
},
]);

return {
data: data[0] as unknown as TData,
};
try {
const data = await sdk.createyYaml([
{
...(variables as unknown as Unstructured),
apiVersion: getApiVersion(meta?.resourceBasePath),
kind: meta?.kind,
},
]);

return {
data: data[0] as unknown as TData,
};
} catch (e) {
const httpError = transformHttpError(e);
throw httpError;
}
},

update: async <TData extends BaseRecord = BaseRecord>({
Expand All @@ -138,26 +157,31 @@ export const dataProvider = (
}: Parameters<DataProvider['update']>['0']): Promise<
UpdateResponse<TData>
> => {
const sdk = new KubeSdk({
basePath: globalStore.apiUrl,
fieldManager: globalStore.fieldManager,
});
const params = [
{
...(variables as unknown as Unstructured),
apiVersion: getApiVersion(meta?.resourceBasePath),
kind: meta?.kind,
},
];
const data = await sdk.applyYaml(
params,
meta?.strategy,
meta?.replacePaths
);

return {
data: data[0] as unknown as TData,
};
try {
const sdk = new KubeSdk({
basePath: globalStore.apiUrl,
fieldManager: globalStore.fieldManager,
});
const params = [
{
...(variables as unknown as Unstructured),
apiVersion: getApiVersion(meta?.resourceBasePath),
kind: meta?.kind,
},
];
const data = await sdk.applyYaml(
params,
meta?.strategy,
meta?.replacePaths
);

return {
data: data[0] as unknown as TData,
};
} catch (e) {
const httpError = transformHttpError(e);
throw httpError;
}
},

getOne,
Expand All @@ -170,18 +194,23 @@ export const dataProvider = (
}: Parameters<DataProvider['deleteOne']>['0']): Promise<
DeleteOneResponse<TData>
> => {
const sdk = new KubeSdk({
basePath: globalStore.apiUrl,
fieldManager: globalStore.fieldManager,
});

const { data: current } = await getOne({ id, resource, meta, ...rest });

const data = await sdk.deleteYaml([current as Unstructured]);

return {
data: data[0] as unknown as TData,
};
try {
const sdk = new KubeSdk({
basePath: globalStore.apiUrl,
fieldManager: globalStore.fieldManager,
});

const { data: current } = await getOne({ id, resource, meta, ...rest });

const data = await sdk.deleteYaml([current as Unstructured]);

return {
data: data[0] as unknown as TData,
};
} catch (e) {
const httpError = transformHttpError(e);
throw httpError;
}
},

getApiUrl: () => {
Expand Down
21 changes: 21 additions & 0 deletions src/utils/transform-http-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { HttpError } from '@refinedev/core';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const transformHttpError = (error: any): HttpError => {
if (error?.response) {
return {
...error,
message: error.response?.statusText,
statusCode: error.response?.status,
};
}
return {
error: error,
message:
typeof error === 'object'
? error instanceof Error
? error.message
: JSON.stringify(error)
: String(error),
statusCode: undefined as unknown as number,
};
};

0 comments on commit 8b06fba

Please sign in to comment.