Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: TypedAxios 모듈 생성 #674

Merged
merged 8 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions api/endpoint/makers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { z } from 'zod';

import { createEndpoint } from '@/api/typedAxios';

export const getMakersProfile = createEndpoint({
request: {
method: 'GET',
url: `makers/profile`,
},
serverResponse: z.array(
z.object({
id: z.number(),
name: z.string(),
profileImage: z.string().nullable(),
activities: z.array(
z.object({
id: z.number(),
generation: z.number(),
}),
),
careers: z.array(
z.object({
id: z.number(),
companyName: z.string(),
title: z.string(),
isCurrent: z.boolean(),
}),
),
}),
),
});
23 changes: 23 additions & 0 deletions api/endpoint/members/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { z } from 'zod';

import { createEndpoint } from '@/api/typedAxios';

export const getMembersSearchByName = createEndpoint({
request: (name: string) => ({
method: 'GET',
url: `api/v1/members/search?name=${encodeURIComponent(name)}`,
}),
serverResponse: z.array(
z.object({
id: z.number(),
name: z.string(),
generation: z.number(),
hasProfile: z.boolean(),
profileImage: z
.string()
.optional()
.nullable()
.transform((str) => str ?? ''),
Tekiter marked this conversation as resolved.
Show resolved Hide resolved
}),
),
});
4 changes: 2 additions & 2 deletions api/endpoint_LEGACY/hooks/members.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useMutation, useQuery, UseQueryOptions } from '@tanstack/react-query';
import { AxiosError } from 'axios';

import { getMembersSearchByName } from '@/api/endpoint/members';
import {
getMemberOfMe,
getMemberProfileById,
getMemberProfileOfMe,
getMembersSearchByName,
postMemberCoffeeChat,
} from '@/api/endpoint_LEGACY/members';
import { PostMemberCoffeeChatVariables, ProfileDetail } from '@/api/endpoint_LEGACY/members/type';
Expand Down Expand Up @@ -74,7 +74,7 @@ export const useGetMembersSearchByName = (name: string) => {
return useQuery(
['getMembersSearchByName', name],
async () => {
const data = await getMembersSearchByName(name);
const data = await getMembersSearchByName.request(name);
return data;
},
{
Expand Down
46 changes: 46 additions & 0 deletions api/typedAxios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { AxiosRequestConfig } from 'axios';
import { z } from 'zod';

import { axiosInstance } from '@/api';

interface Endpoint<ServerResponse, Params extends unknown[]> {
request(...params: Params): Promise<ServerResponse>;
}

export function createEndpoint<
Validator extends z.ZodType,
Param extends unknown[] = [],
Transformed = z.infer<Validator>,
>(config: {
request: AxiosRequestConfig | ((...params: Param) => AxiosRequestConfig);
serverResponse: Validator;
Tekiter marked this conversation as resolved.
Show resolved Hide resolved
transformer?: (original: z.infer<Validator>) => Transformed;
}): Endpoint<Transformed, Param> {
return {
async request(...params) {
const getConfig = () => {
if (typeof config.request === 'function') {
return config.request(...params);
}
return config.request;
};

const axiosConfig = getConfig();

const { data } = await axiosInstance.request<unknown>(axiosConfig);

const res = config.serverResponse.safeParse(data);

if (!res.success) {
const zodError = String(res.error).slice(0, 1000) + '\n...';
const message = `서버 타입 검증에 실패했습니다. (${axiosConfig.method} ${axiosConfig.url})\n${zodError}`;
console.error(zodError);
throw new Error(message);
Comment on lines +35 to +38
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디버깅 하기에 정말 좋겠네요 👍👍👍

}

return res.data;
},
};
}

export type GetResponseType<T> = T extends Endpoint<infer R, never> ? R : never;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS 고수님 ,, 혹시 <infer R, never>에서 왜 never로 한 건지 알려주실 수 있나요? 🥺

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R 을 infer 해 오는것만 중요하고, 두번째 제너릭 인자는 필요가 없기 때문에 never를 줬어요! (사실 unknown[] 로 해도 작동해요.)

4 changes: 2 additions & 2 deletions components/projects/upload/hooks/useGetMembersByNameQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query';

import { getMembersSearchByName } from '@/api/endpoint_LEGACY/members';
import { getMembersSearchByName } from '@/api/endpoint/members';
interface GetMembersByNameQueryVariables {
name: string;
}
Expand All @@ -12,7 +12,7 @@ const useGetMembersByNameQuery = (variables: GetMembersByNameQueryVariables) =>
if (!name) {
return;
}
const data = await getMembersSearchByName(name);
const data = await getMembersSearchByName.request(name);
return data;
},
{
Expand Down
5 changes: 2 additions & 3 deletions pages/makers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { GetStaticProps } from 'next';
import { FC } from 'react';
import { RemoveScroll } from 'react-remove-scroll';

import { getMakersProfile } from '@/api/endpoint_LEGACY/makers';
import { getMakersProfile } from '@/api/endpoint/makers';
import Footer from '@/components/common/Footer';
import SwitchableHeader from '@/components/common/Header/SwitchableHeader';
import AboutMakers from '@/components/makers/AboutMakers';
Expand Down Expand Up @@ -32,11 +32,10 @@ const MakersPage: FC<MakersPageProps> = ({ memberMetadataList }) => {
};

export const getStaticProps: GetStaticProps<MakersPageProps> = async () => {
const memberList = await getMakersProfile();
const memberList = await getMakersProfile.request();

const memberMetadataList = memberList.map((member) => {
const sortedCareers = member.careers.filter((career) => career.isCurrent);
sortedCareers.sort((a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime());
const currentCompany = sortedCareers.length > 0 ? sortedCareers.at(-1)?.companyName ?? null : null;
const generations = member.activities.map((value) => value.generation).sort((a, b) => a - b);

Expand Down