Skip to content

Commit

Permalink
feat(client-axios): remove axios instance in argument
Browse files Browse the repository at this point in the history
  • Loading branch information
anymaniax committed Nov 29, 2020
1 parent 1dcbc87 commit f3631fa
Show file tree
Hide file tree
Showing 24 changed files with 187 additions and 221 deletions.
@@ -1,10 +1,10 @@
import Axios, { AxiosRequestConfig } from 'axios';

const instance = Axios.create({ baseURL: 'test' });
export const AXIOS_INSTANCE = Axios.create({ baseURL: '' });

export const customInstance = <T>(config: AxiosRequestConfig): Promise<T> => {
const source = Axios.CancelToken.source();
const promise = instance({ ...config, cancelToken: source.token }).then(
const promise = AXIOS_INSTANCE({ ...config, cancelToken: source.token }).then(
({ data }) => data,
);

Expand Down
30 changes: 11 additions & 19 deletions samples/react-app-with-react-query/src/auth.context.tsx
@@ -1,11 +1,11 @@
import axios from 'axios';
import React, {
createContext,
ReactNode,
useContext,
useEffect,
useState,
} from 'react';
import { AXIOS_INSTANCE } from './api/mutator/custom-instance';
type Dispatch = (Auth: string) => void;

type AuthProviderProps = { children: ReactNode; initialState?: string | null };
Expand All @@ -18,26 +18,18 @@ const AuthProvider = ({ children, initialState = null }: AuthProviderProps) => {
const [token, setToken] = useState(initialState);

useEffect(() => {
const interceptorId = axios.interceptors.request.use(
(config) => {
return {
...config,
baseURL: '', // use an env or your api url
headers: token
? {
...config.headers,
Authorization: `Bearer ${token}`,
}
: config.headers,
};
},
(error) => {
Promise.reject(error);
},
);
const interceptorId = AXIOS_INSTANCE.interceptors.request.use((config) => ({
...config,
headers: token
? {
...config.headers,
Authorization: `Bearer ${token}`,
}
: config.headers,
}));

return () => {
axios.interceptors.request.eject(interceptorId);
AXIOS_INSTANCE.interceptors.request.eject(interceptorId);
};
}, [token]);

Expand Down
5 changes: 4 additions & 1 deletion samples/react-app/orval.config.js
Expand Up @@ -11,9 +11,12 @@ module.exports = {
schemas: 'src/api/model',
mock: true,
override: {
mutator: {
path: 'src/api/mutator/custom-instance.ts',
name: 'customInstance',
},
operations: {
listPets: {
mutator: 'src/api/mutator/response-type.ts',
mock: {
properties: () => {
return {
Expand Down
26 changes: 19 additions & 7 deletions samples/react-app/src/App.tsx
@@ -1,20 +1,32 @@
import React from 'react';
import { useQuery } from 'react-query';
import React, { useEffect, useState } from 'react';
import { Pets } from './api/model';
import { useApi } from './api/useApi';
import './App.css';
import { useAuthDispatch } from './auth.context';
import logo from './logo.png';

function App() {
const { petstore } = useApi();
const { data: pets } = useQuery('pets', () => petstore.listPets());
const dispatch = useAuthDispatch();
const { listPets } = useApi();
const [pets, setPets] = useState<Pets>([]);

useEffect(() => {
dispatch('token');

setTimeout(() => {
listPets().then(setPets);
}, 1000);
}, []);

return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
{pets?.data.map((pet) => (
<p key={pet.id}>{pet.name}</p>
))}
{!!pets.length ? (
pets.map((pet) => <p key={pet.id}>{pet.name}</p>)
) : (
<div>...loading</div>
)}
</header>
</div>
);
Expand Down
34 changes: 0 additions & 34 deletions samples/react-app/src/api/config.ts

This file was deleted.

Expand Up @@ -4,20 +4,27 @@
* Swagger Petstore
* OpenAPI spec version: 1.0.0
*/
import { AxiosInstance } from 'axios';
import { CreatePetsBody, ListPetsParams, Pet, Pets } from '../model';
import listPetsMutator from './../../../src/api/mutator/response-type';
export const getSwaggerPetstore = (axios: AxiosInstance) => ({
import { customInstance } from '../mutator/custom-instance';
export const getSwaggerPetstore = () => ({
listPets(params?: ListPetsParams, version: number = 1) {
return listPetsMutator<Pets>(
{ url: `/v${version}/pets`, method: 'get', params },
axios,
);
return customInstance<Pets>({
url: `/v${version}/pets`,
method: 'get',
params,
});
},
createPets(createPetsBody: CreatePetsBody, version: number = 1) {
return axios.post<unknown>(`/v${version}/pets`, createPetsBody);
return customInstance<unknown>({
url: `/v${version}/pets`,
method: 'post',
data: createPetsBody,
});
},
showPetById(petId: string, version: number = 1) {
return axios.get<Pet>(`/v${version}/pets/${petId}`);
return customInstance<Pet>({
url: `/v${version}/pets/${petId}`,
method: 'get',
});
},
});
9 changes: 9 additions & 0 deletions samples/react-app/src/api/mutator/custom-instance.ts
@@ -0,0 +1,9 @@
import Axios, { AxiosRequestConfig } from 'axios';

export const AXIOS_INSTANCE = Axios.create({ baseURL: '' });

export const customInstance = <T>(config: AxiosRequestConfig): Promise<T> => {
return AXIOS_INSTANCE(config).then(({ data }) => data);
};

export default customInstance;
10 changes: 0 additions & 10 deletions samples/react-app/src/api/mutator/response-type.ts

This file was deleted.

39 changes: 2 additions & 37 deletions samples/react-app/src/api/useApi.ts
@@ -1,38 +1,3 @@
import { AxiosError } from 'axios';
import { useMemo } from 'react';
import { getApi } from './config';
import { getAuthHeader } from './headers';
import { createApiError } from './utilities';
import { getSwaggerPetstore } from './endpoints/petstoreFromFileSpecWithTransformer';

export const useApi = () => {
const token = 'xxxxxxxx'; // get your token

const headers = useMemo(
() => ({
...getAuthHeader(token),
}),
[token],
);

const unauthorizedAndErrorInterceptor = useMemo(
() => ({
response: {
onRejected(error: AxiosError): Promise<unknown> | void {
//do your check
return Promise.reject(createApiError());
},
},
}),
[],
);

return useMemo(
() =>
getApi({
headers,
interceptor: unauthorizedAndErrorInterceptor,
baseUrl: '', // use an env or your api url
}),
[headers, unauthorizedAndErrorInterceptor],
);
};
export const useApi = () => getSwaggerPetstore();
58 changes: 58 additions & 0 deletions samples/react-app/src/auth.context.tsx
@@ -0,0 +1,58 @@
import React, {
createContext,
ReactNode,
useContext,
useEffect,
useState,
} from 'react';
import { AXIOS_INSTANCE } from './api/mutator/custom-instance';
type Dispatch = (Auth: string) => void;

type AuthProviderProps = { children: ReactNode; initialState?: string | null };

const AuthContext = createContext<string | null>(null);
const AuthDispatchContext = createContext<Dispatch | null>(null);

const AuthProvider = ({ children, initialState = null }: AuthProviderProps) => {
// it's a quick demo with useState but you can also have a more complexe state with a useReducer
const [token, setToken] = useState(initialState);

useEffect(() => {
const interceptorId = AXIOS_INSTANCE.interceptors.request.use((config) => ({
...config,
headers: token
? {
...config.headers,
Authorization: `Bearer ${token}`,
}
: config.headers,
}));

return () => {
AXIOS_INSTANCE.interceptors.request.eject(interceptorId);
};
}, [token]);

return (
<AuthContext.Provider value={token}>
<AuthDispatchContext.Provider value={setToken}>
{children}
</AuthDispatchContext.Provider>
</AuthContext.Provider>
);
};

const useAuth = (): string | null => {
return useContext<string | null>(AuthContext);
};

const useAuthDispatch = (): Dispatch => {
const context = useContext<Dispatch | null>(AuthDispatchContext);

if (context === null) {
throw new Error('useAuthDispatch must be used within a AuthProvider');
}
return context;
};

export { AuthProvider, useAuth, useAuthDispatch };
5 changes: 4 additions & 1 deletion samples/react-app/src/index.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { AuthProvider } from './auth.context';
import './index.css';
import * as serviceWorker from './serviceWorker';

Expand All @@ -10,7 +11,9 @@ if (process.env.NODE_ENV === 'development') {

ReactDOM.render(
<React.StrictMode>
<App />
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>,
document.getElementById('root'),
);
Expand Down
37 changes: 13 additions & 24 deletions src/core/generators/angular.ts
Expand Up @@ -4,38 +4,27 @@ import {
GeneratorVerbOptions,
} from '../../types/generator';
import { pascal } from '../../utils/case';
import { toObjectString } from '../../utils/string';
import { sanitize, toObjectString } from '../../utils/string';
import { generateFormData } from './formData';
import { generateAxiosConfig, generateOptions } from './options';

export const generateAngularImports = () => ({
implementation: `import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';\n`,
});
export const generateAngularImports = () => `import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';\n`;

export const generateAngularTitle = (title: string) => {
return {
implementation: `${pascal(title)}Service`,
};
const sanTitle = sanitize(title);
return `${pascal(sanTitle)}Service`;
};

export const generateAngularHeader = (titles: { implementation: string }) => {
return {
implementation: `
@Injectable()
export class ${titles.implementation} {
constructor(
private http: HttpClient,
) {}`,
};
};
export const generateAngularHeader = (title: string) => `
@Injectable()
export class ${title} {
constructor(
private http: HttpClient,
) {}`;

export const generateAngularFooter = () => {
return {
implementation: '};\n',
};
};
export const generateAngularFooter = () => '};\n';

const generateImports = ({
response,
Expand Down

0 comments on commit f3631fa

Please sign in to comment.