Skip to content

Commit

Permalink
@gitanimals/api (#64)
Browse files Browse the repository at this point in the history
* chore: exceptions to exception

* chore: CustomException ์—๋Ÿฌ ํƒ€์ž… ์ถ”๊ฐ€

* feature: api ํŒจํ‚ค์ง€ ์ƒ์„ฑ

* feat: web์— ๋‚ด๋ถ€ ํŒจํ‚ค์ง€ ์ถ”๊ฐ€

* feat: instance

* feat: interceptor

* feat: getUser

* chore: lock

* chore: lock

* chore: directory name

* chore: zod to dev deps
  • Loading branch information
hyesungoh authored Jun 19, 2024
1 parent 8d7b2c8 commit 5828603
Show file tree
Hide file tree
Showing 17 changed files with 194 additions and 9 deletions.
3 changes: 2 additions & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
"build-storybook": "storybook build"
},
"dependencies": {
"@gitanimals/api": "workspace:*",
"@gitanimals/ui": "workspace:*",
"@gitanimals/exceptions": "workspace:*",
"@gitanimals/exception": "workspace:*",
"@tanstack/react-query": "^5.32.0",
"axios": "^1.6.8",
"framer-motion": "^11.1.7",
Expand Down
13 changes: 13 additions & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@gitanimals/api",
"version": "0.0.0",
"main": "./src/index.ts",
"devDependencies": {
"@gitanimals/exception": "workspace:*",
"@gitanimals/eslint-config": "workspace:*",
"@gitanimals/typescript-config": "workspace:*",
"axios": "^1.6.8",
"typescript": "*",
"zod": "^3.23.8"
}
}
31 changes: 31 additions & 0 deletions packages/api/src/_instance/default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import axios from 'axios';
import { setInterceptors } from '../_interceptor';

const API_URL = 'https://api.gitanimals.org';

const instance = setInterceptors(
axios.create({
baseURL: API_URL,
timeout: 15000,
}),
);

export const get = <T>(...args: Parameters<typeof instance.get>) => {
return instance.get<T, T>(...args);
};

export const post = <T>(...args: Parameters<typeof instance.post>) => {
return instance.post<T, T>(...args);
};

export const put = <T>(...args: Parameters<typeof instance.put>) => {
return instance.put<T, T>(...args);
};

export const patch = <T>(...args: Parameters<typeof instance.patch>) => {
return instance.patch<T, T>(...args);
};

export const del = <T>(...args: Parameters<typeof instance.delete>) => {
return instance.delete<T, T>(...args);
};
2 changes: 2 additions & 0 deletions packages/api/src/_instance/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './default';
export * from './render';
31 changes: 31 additions & 0 deletions packages/api/src/_instance/render.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import axios from 'axios';
import { setInterceptors } from '../_interceptor';

const API_URL = 'https://render.gitanimals.org';

const instance = setInterceptors(
axios.create({
baseURL: API_URL,
timeout: 15000,
}),
);

export const renderGet = <T>(...args: Parameters<typeof instance.get>) => {
return instance.get<T, T>(...args);
};

export const renderPost = <T>(...args: Parameters<typeof instance.post>) => {
return instance.post<T, T>(...args);
};

export const renderPut = <T>(...args: Parameters<typeof instance.put>) => {
return instance.put<T, T>(...args);
};

export const renderPatch = <T>(...args: Parameters<typeof instance.patch>) => {
return instance.patch<T, T>(...args);
};

export const renderDelete = <T>(...args: Parameters<typeof instance.delete>) => {
return instance.delete<T, T>(...args);
};
44 changes: 44 additions & 0 deletions packages/api/src/_interceptor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios';

import { ApiErrorScheme } from '../type';

const interceptorRequestFulfilled = (config: InternalAxiosRequestConfig) => {
if (typeof window === 'undefined') return config;

// TODO: cookie ์ฒ˜๋ฆฌ ์‹œ ๋ณ€๊ฒฝ ํ•„์š”
// const accessToken = getToken();
if (!config.headers) return config;
// if (!accessToken) return config;

// config.headers.Authorization = `Bearer ${accessToken}`;

return config;
};

// Response interceptor
const interceptorResponseFulfilled = (res: AxiosResponse) => {
if (200 <= res.status && res.status < 300) {
return res.data;
}

return Promise.reject(res.data);
};

// Response interceptor
const interceptorResponseRejected = (error: AxiosError<ApiErrorScheme>) => {
if (error.response?.status === 401) {
// TODO : logout and refresh login
// TODO : logout ์•ˆ๋‚ด
}

// 403 ์ฒ˜๋ฆฌ

return Promise.reject(error);
};

export const setInterceptors = (instance: AxiosInstance) => {
instance.interceptors.request.use(interceptorRequestFulfilled);
instance.interceptors.response.use(interceptorResponseFulfilled, interceptorResponseRejected);

return instance;
};
3 changes: 3 additions & 0 deletions packages/api/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './_instance';
export * from './type';
export * from './user';
3 changes: 3 additions & 0 deletions packages/api/src/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface ApiErrorScheme {
message: string;
}
21 changes: 21 additions & 0 deletions packages/api/src/user/getUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { z } from 'zod';
import { CustomException } from '@gitanimals/exception';
import { get } from '../_instance';

const UserSchema = z.object({
id: z.string(),
username: z.string(),
points: z.string(),
profileImage: z.string(),
});

type User = z.infer<typeof UserSchema>;

export const getUser = async () => {
const res = await get<User>(`/users`);

const parsed = UserSchema.safeParse(res);
if (parsed.error) throw new CustomException('API_TYPE_NOT_MATCH');

return res;
};
1 change: 1 addition & 0 deletions packages/api/src/user/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './getUser';
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@gitanimals/exceptions",
"name": "@gitanimals/exception",
"version": "0.0.0",
"main": "./src/index.ts",
"devDependencies": {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
type CustomErrorCode = 'NETWORK_ERROR' | 'NETWORK_TIMEOUT' | 'UNKNOWN_ERROR';
type CustomErrorCode = 'NETWORK_ERROR' | 'NETWORK_TIMEOUT' | 'UNKNOWN_ERROR' | 'API_TYPE_NOT_MATCH';

const ERROR_MESSAGE: Record<CustomErrorCode, string> = {
NETWORK_ERROR: 'Network error',
NETWORK_TIMEOUT: 'Network timeout',
UNKNOWN_ERROR: 'Unknown error',
NETWORK_ERROR: '๋„คํŠธ์›Œํฌ ์—๋Ÿฌ',
NETWORK_TIMEOUT: '๋„คํŠธ์›Œํฌ ํƒ€์ž„์•„์›ƒ',
UNKNOWN_ERROR: '์•Œ ์ˆ˜ ์—†๋Š” ์—๋Ÿฌ',
API_TYPE_NOT_MATCH: 'API ์‘๋‹ต ํƒ€์ž… ๋ถˆ์ผ์น˜',
};

export class CustomException extends Error {
Expand Down
File renamed without changes.
5 changes: 5 additions & 0 deletions packages/exception/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "@gitanimals/typescript-config/base.json",
"include": ["src"],
"exclude": ["node_modules"]
}
35 changes: 32 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5828603

Please sign in to comment.