Skip to content

Commit

Permalink
🚧(frontend) implement joanie generated api client
Browse files Browse the repository at this point in the history
  • Loading branch information
rlecellier committed Feb 20, 2023
1 parent 2aca269 commit 54ee0d7
Show file tree
Hide file tree
Showing 18 changed files with 1,437 additions and 17 deletions.
34 changes: 34 additions & 0 deletions src/frontend/js/api/joanie/__specs__/ApiClientTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BaseHttpRequest } from '../gen/core/BaseHttpRequest';
import type { OpenAPIConfig } from '../gen/core/OpenAPI';
import { FetchHttpRequest } from '../gen/core/FetchHttpRequest';

import { TodoService } from './TodoService';

type HttpRequestConstructor = new (config: OpenAPIConfig) => BaseHttpRequest;

export class ApiClientTest {

public readonly todo: TodoService;
public readonly request: BaseHttpRequest;

constructor(config?: Partial<OpenAPIConfig>, HttpRequest: HttpRequestConstructor = FetchHttpRequest) {
this.request = new HttpRequest({
BASE: config?.BASE ?? 'http://localhost:8071/api/v1.0',
VERSION: config?.VERSION ?? '1.0',
WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
CREDENTIALS: config?.CREDENTIALS ?? 'include',
TOKEN: config?.TOKEN,
USERNAME: config?.USERNAME,
PASSWORD: config?.PASSWORD,
HEADERS: config?.HEADERS,
ENCODE_PATH: config?.ENCODE_PATH,
});

this.todo = new TodoService(this.request);

}
}

54 changes: 54 additions & 0 deletions src/frontend/js/api/joanie/__specs__/TodoService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { CancelablePromise } from '../gen/core/CancelablePromise';
import type { BaseHttpRequest } from '../gen/core/BaseHttpRequest';

export interface Todo {
id: string;
name: string;
}

export class TodoService {
constructor(readonly httpRequest: BaseHttpRequest) {}

todoList(): CancelablePromise<Array<Todo>> {
return this.httpRequest.request({
method: 'GET',
url: '/todo/',
});
}
todoCreate({ data }: { data: Todo }): CancelablePromise<Todo> {
return this.httpRequest.request({
method: 'POST',
url: '/todo/',
body: data,
});
}
todoRead({ id }: { id: string }): CancelablePromise<Todo> {
console.log('api.joanie.__specs__.TodoService::totoRead');
return this.httpRequest.request({
method: 'GET',
url: '/todo/{id}/',
path: {
id,
},
});
}
todoUpdate({ id, data }: { id: string; data: Todo }): CancelablePromise<Todo> {
return this.httpRequest.request({
method: 'PUT',
url: '/todo/{id}/',
path: {
id,
},
body: data,
});
}
todoDelete({ id }: { id: string }): CancelablePromise<void> {
return this.httpRequest.request({
method: 'DELETE',
url: '/todo/{id}/',
path: {
id,
},
});
}
}
35 changes: 35 additions & 0 deletions src/frontend/js/api/joanie/__specs__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import fetchMock from 'fetch-mock';
import * as mockFactories from 'utils/test/factories';
import { RICHIE_USER_TOKEN } from 'settings';

import { joanieApi } from '..';

jest.mock('utils/context', () => ({
__esModule: true,
default: mockFactories
.ContextFactory({
joanie_backend: { endpoint: 'https://joanie.endpoint' },
})
.generate(),
}));

describe('joanieApi', () => {
it('test', async () => {
fetchMock.get('https://joanie.endpoint/api/v1.0/addresses/addressId/', []);
await joanieApi.addresses.addressesRead({ id: 'addressId' });

let lastCall = fetchMock.lastCall();
const visitorHeader = lastCall && lastCall[1]?.headers;
// TS see visitorHeader has HeadersInit instead of Headers and
// didn't accept get() as a possible function.
// @ts-ignore
expect(visitorHeader?.get('Authorization')).toBeNull();

sessionStorage.setItem(RICHIE_USER_TOKEN, 'TEST_TOKEN');
await joanieApi.addresses.addressesRead({ id: 'addressId' });
lastCall = fetchMock.lastCall();
const userHeader = lastCall && lastCall[1]?.headers;
// @ts-ignore
expect(userHeader?.get('Authorization')).toBe('Bearer TEST_TOKEN');
});
});
30 changes: 30 additions & 0 deletions src/frontend/js/api/joanie/__specs__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// import context from 'utils/context';
// import { JOANIE_API_VERSION } from 'settings';
import { OpenAPIConfig } from '../gen';
import { ApiClientTest } from './ApiClientTest';

/**
* Build Joanie API Routes interface.
*/
// const getAPIEndpoint = () => {
// const endpoint = context?.joanie_backend?.endpoint;
// const version = JOANIE_API_VERSION;

// if (!endpoint) {
// throw new Error('[JOANIE] - Joanie API endpoint is not defined.');
// }

// return `${endpoint}/api/${version}`;
// };

// // TODO add auth with jwt
// export const config: OpenAPIConfig = {
// BASE: getAPIEndpoint(),
// VERSION: '1',
// WITH_CREDENTIALS: true,
// CREDENTIALS: 'include',
// // TOKEN:
// };
export { TodoService } from './TodoService';
export type { Todo } from './TodoService';
export const getJoanieApiTest = (config: OpenAPIConfig) => new ApiClientTest(config);
11 changes: 1 addition & 10 deletions src/frontend/js/api/joanie/gen/core/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export const sendRequest = async (
}

onCancel(() => controller.abort());
console.log('joanie.gen.sendRequest::await fetch', await fetch(url, request))

return await fetch(url, request);
};

Expand All @@ -227,8 +227,6 @@ const getResponseHeader = (response: Response, responseHeader?: string): string
};

const getResponseBody = async (response: Response): Promise<any> => {
console.log('joanie.gen.getResponseBody::response.status', response.status)
console.log('joanie.gen.getResponseBody::response', response)
if (response.status !== 204) {
try {
const contentType = response.headers.get('Content-Type');
Expand Down Expand Up @@ -260,9 +258,6 @@ const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void =>
}

const error = errors[result.status];
console.log('api.joanie.gen.request.catchErrorCodes::options', options)
console.log('api.joanie.gen.request.catchErrorCodes::result', result)
console.log('api.joanie.gen.request.catchErrorCodes::error', error)
if (error) {
throw new ApiError(options, result, error);
}
Expand All @@ -282,7 +277,6 @@ const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void =>
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> => {
return new CancelablePromise(async (resolve, reject, onCancel) => {
try {
console.log('api.joanie.gen.request')
const url = getUrl(config, options);
const formData = getFormData(options);
const body = getRequestBody(options);
Expand All @@ -293,8 +287,6 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
const responseBody = await getResponseBody(response);
const responseHeader = getResponseHeader(response, options.responseHeader);

console.log('api.joanie.gen.request::response', response)

const result: ApiResult = {
url,
ok: response.ok,
Expand All @@ -308,7 +300,6 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C
resolve(result.body);
}
} catch (error) {
console.log('api.joanie.gen.throw', error)
reject(error);
}
});
Expand Down
1 change: 1 addition & 0 deletions src/frontend/js/api/joanie/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as useJoanieApiAddresses } from './useJoanieAddresses';
1 change: 1 addition & 0 deletions src/frontend/js/api/joanie/hooks/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ApiFn<TData> = (data?: any) => TData | TData[] | void;
82 changes: 82 additions & 0 deletions src/frontend/js/api/joanie/hooks/useJoanieAddresses/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { defineMessages } from 'react-intl';
import { joanieApi } from 'api/joanie';

import { AutogenApiResourceListInterface, AutogenApiResourceReadInterface } from 'types/Joanie';
import { ResourcesQuery, UseResourceListProps, UseResourceReadProps } from 'hooks/useResources';

import { Address } from 'api/joanie/gen';
import { useResourceReadRoot } from 'hooks/useJoanieResources/useResourceReadRoot';
import { useResourceListRoot } from 'hooks/useJoanieResources/useResourceListRoot';

const messages = defineMessages({
errorUpdate: {
id: 'hooks.useAddresses.errorUpdate',
description: 'Error message shown to the user when address update request fails.',
defaultMessage: 'An error occurred while updating the address. Please retry later.',
},
errorDelete: {
id: 'hooks.useAddresses.errorDelete',
description: 'Error message shown to the user when address deletion request fails.',
defaultMessage: 'An error occurred while deleting the address. Please retry later.',
},
errorCreate: {
id: 'hooks.useAddresses.errorCreate',
description: 'Error message shown to the user when address creation request fails.',
defaultMessage: 'An error occurred while creating the address. Please retry later.',
},
errorGet: {
id: 'hooks.useAddresses.errorSelect',
description: 'Error message shown to the user when addresses fetch request fails.',
defaultMessage: 'An error occurred while fetching addresses. Please retry later.',
},
errorNotFound: {
id: 'hooks.useAddresses.errorNotFound',
description: 'Error message shown to the user when not address matches.',
defaultMessage: 'Cannot find the address',
},
});

const readProps: UseResourceReadProps<Address, AutogenApiResourceReadInterface<Address>> = {
queryKey: ['addresses'],
session: true,
messages,
apiInterface: () => ({
get: (id?: string) => (id ? joanieApi.addresses.addressesRead(id) : Promise.resolve(undefined)),
create: joanieApi.addresses.addressesCreate,
update: joanieApi.addresses.addressesUpdate,
delete: joanieApi.addresses.addressesDelete,
}),
};
export const useAddresses = useResourceReadRoot(readProps);

// export const useAddressesList = () => {
// const readProps: UseResourceReadProps<Address, AutogenApiResourceReadInterface<Address>> = {
// queryKey: ['addresses'],
// session: true,
// messages,
// apiInterface: () => ({
// get: (id?: string) => (id ? joanieApi.addresses.addressesRead(id) : Promise.resolve(undefined)),
// // create: joanieApi.addresses.addressesCreate,
// // update: joanieApi.addresses.addressesUpdate,
// // delete: joanieApi.addresses.addressesDelete,
// }),
// };
// useResourceReadRoot(readProps);
// }

const listProps: UseResourceListProps<
Address,
ResourcesQuery,
AutogenApiResourceListInterface<Address>
> = {
queryKey: ['addresses'],
session: true,
messages,
apiInterface: () => ({
list: joanieApi.addresses.addressesList,
create: joanieApi.addresses.addressesCreate,
update: joanieApi.addresses.addressesUpdate,
delete: joanieApi.addresses.addressesDelete,
}),
};
export const useAddress = () => useResourceListRoot(listProps);
Loading

0 comments on commit 54ee0d7

Please sign in to comment.