-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: histories 라우터에 추가 histories 라우터에 추가 * feat: histories controller 추가 histories controller 추가 * feat: impl 추가 impl 추가 * feat: histories 전용 type 파일 추가 histories 전용 type 파일 추가 * feat: histories service 추가 histories service 추가 * feat: 권한 없음 에러 추가 권한 없음 에러 추가 * feat: 권한 없음 에러 오브젝트 추가 권한 없음 에러 오브젝트 추가 * feat: meta 스키마 추가 meta 스키마 추가 * style: eslint comma 추가 eslint comma 추가 * feat: contract에 histories 추가 contract에 histories 추가 * feat: contract에 histories 명세 추가 contract에 histories 명세 추가 * feat: contract에 histories에서 사용하는 query string 스키마 추가 contract에 histories에서 사용하는 GET 메서드들의 query string 스키마 추가 * feat: contract에 공용으로 사용할 권한 없음 에러 스키마 추가 contract에 공용으로 사용할 권한 없음 에러 스키마 추가 * feat(histories): histories controller 추가 - 전체 대출 기록 조회하는 controller 추가 - 나의 대출 기록 조회하는 controller 추가 * feat(histories): histories service 추가 - 전체 대출 기록 조회하는 service 추가 - 나의 대출 기록 조회하는 service 추가 * feat(histories): histories 조회 시의 query string schema 변경 histories 조회 시의 query string schema 구조 변경 * feat(histories): 라우터 분기 자세하게 나눔 - histories의 라우터 분기를 '나의 기록 조회', '전체 기록 조회'로 나눔 * feat(histories): histories service index.ts 추가 histories service index.ts 추가 * fix: 쿼리 파라미터를 json으로 파싱 참고: https://ts-rest.com/docs/core/#query-parameters https://ts-rest.com/docs/express/#options * feat(histories): 결과 반환 시, literal이 아닌 아이템 리스트 반환 결과 반환 시, z.literal 조회 성공 문구 대신 데이터베이스 조회한 결과 반환하게 함 * style(histories): import 형식 변경 VHistories 가져올 때 중괄호 이용 * feat(histories): histories 조회 결과 200 시, 스키마 추가 histories를 조회하여 200 스테이터스 일 때 반환하는 스키마 추가 * feat(histories): 검색 조건 callsign 추가 callsign으로도 검색할 수 있도록 조건 추가 및 query undefined 체크 추가 * feat(histories): meta 스키마 추가 meta 스키마 공용 스키마로 추가 * feat(histories): id 타입 변경 id 타입을 string -> number로 변경 * feat(histories): meta 스키마 positiveInt로 변경 z.number()...를 positiveInt로 변경 * feat(histories): 서비스 함수 반환 타입 변경 서비스 함수 반환 타입 오브젝트 형식으로 변경 * feat(histories): getMyHistories 반환값 변경 getMyHistories 반환값 데이터베이스 조회 결과로 변경 * feat(histories): 서비스 함수 반환 타입 변경 서비스 함수들 반환 타입 변경 * chore(histories): 서비스 파일 분리 및 컨트롤러 파일 분리 서비스 파일과 서비스 구현 파일, 컨트롤러 파일과 컨트롤러 구현 파일 분리 * fix: 스키마에서 date와 string 모두 허용 * fix: 패턴 매칭에서 타입이 좁혀지지 않던 문제 * fix: users 경로 숨김 * fix: stocks 타입 오류 수정 --------- Co-authored-by: scarf <greenscarf005@gmail.com>
- Loading branch information
Showing
19 changed files
with
291 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { contract } from '@jiphyeonjeon-42/contracts'; | ||
import { P, match } from 'ts-pattern'; | ||
import { | ||
UnauthorizedError, | ||
HandlerFor, | ||
unauthorized, | ||
} from '../../shared'; | ||
import { HistoriesService } from '../service'; | ||
|
||
// mkGetMyHistories | ||
type GetMyDeps = Pick<HistoriesService, 'searchMyHistories'>; | ||
type MkGetMy = (services: GetMyDeps) => HandlerFor<typeof contract.histories.getMyHistories>; | ||
export const mkGetMyHistories: MkGetMy = ({ searchMyHistories }) => | ||
async ({ query }) => { | ||
const result = await searchMyHistories(query); | ||
|
||
return match(result) | ||
.with(P.instanceOf(UnauthorizedError), () => unauthorized) | ||
.otherwise((body) => ({ status: 200, body } as const)); | ||
}; | ||
|
||
// mkGetAllHistories | ||
type GetAllDeps = Pick<HistoriesService, 'searchAllHistories'>; | ||
type MkGetAll = (services: GetAllDeps) => HandlerFor<typeof contract.histories.getAllHistories>; | ||
export const mkGetAllHistories: MkGetAll = ({ searchAllHistories }) => async ({ query }) => { | ||
const result = await searchAllHistories(query); | ||
return match(result) | ||
.with(P.instanceOf(UnauthorizedError), () => unauthorized) | ||
.otherwise((body) => ({ status: 200, body } as const)); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { mkGetMyHistories, mkGetAllHistories } from './controller'; | ||
import { | ||
HistoriesService, | ||
} from '../service'; | ||
|
||
export const implHistoriesController = (service: HistoriesService) => ({ | ||
getMyHistories: mkGetMyHistories(service), | ||
getAllHistories: mkGetAllHistories(service), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './controller'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { contract } from '@jiphyeonjeon-42/contracts'; | ||
import { initServer } from '@ts-rest/express'; | ||
import jipDataSource from '~/app-data-source'; | ||
import { roleSet } from '~/v1/auth/auth.type'; | ||
import authValidate from '~/v1/auth/auth.validate'; | ||
import { VHistories } from '~/entity/entities/VHistories'; | ||
import { implHistoriesService } from '~/v2/histories/service/impl'; | ||
import { implHistoriesController } from '~/v2/histories/controller/impl'; | ||
|
||
const service = implHistoriesService({ | ||
historiesRepo: jipDataSource.getRepository(VHistories), | ||
}); | ||
|
||
const handler = implHistoriesController(service); | ||
|
||
const s = initServer(); | ||
export const histories = s.router(contract.histories, { | ||
getMyHistories: { | ||
middleware: [authValidate(roleSet.all)], | ||
handler: handler.getMyHistories, | ||
}, | ||
getAllHistories: { | ||
middleware: [authValidate(roleSet.librarian)], | ||
handler: handler.getAllHistories, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Repository } from 'typeorm'; | ||
import { VHistories } from '~/entity/entities/VHistories'; | ||
|
||
import { | ||
mkSearchHistories, | ||
} from './service'; | ||
|
||
export const implHistoriesService = (repos: { | ||
historiesRepo: Repository<VHistories>; | ||
}) => ({ | ||
searchMyHistories: mkSearchHistories(repos), | ||
searchAllHistories: mkSearchHistories(repos), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { VHistories } from '~/entity/entities/VHistories'; | ||
import { Meta, UnauthorizedError } from '~/v2/shared'; | ||
|
||
type Args = { | ||
query?: string | undefined; | ||
page: number; | ||
limit: number; | ||
type?: 'title' | 'user' | 'callsign' | undefined; | ||
}; | ||
|
||
export type HistoriesService = { | ||
searchMyHistories: ( | ||
args: Args, | ||
) => Promise<UnauthorizedError | { items: VHistories[], meta: Meta }>; | ||
searchAllHistories: ( | ||
args: Args, | ||
) => Promise<UnauthorizedError | { items: VHistories[], meta: Meta }>; | ||
} | ||
|
||
export * from './service'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
import { match } from 'ts-pattern'; | ||
|
||
import { FindOperator, Like, type Repository } from 'typeorm'; | ||
import { VHistories } from '~/entity/entities/VHistories'; | ||
|
||
import { Meta } from '~/v2/shared'; | ||
import type { HistoriesService } from '.'; | ||
|
||
// HistoriesService | ||
|
||
type Repos = { historiesRepo: Repository<VHistories> }; | ||
|
||
type MkSearchHistories = ( | ||
repos: Repos | ||
) => HistoriesService['searchAllHistories']; | ||
|
||
type whereCondition = { | ||
login: FindOperator<string>, | ||
title: FindOperator<string>, | ||
callSign: FindOperator<string>, | ||
} | [ | ||
{ login: FindOperator<string> }, | ||
{ title: FindOperator<string> }, | ||
{ callSign: FindOperator<string> }, | ||
]; | ||
|
||
export const mkSearchHistories: MkSearchHistories = ({ historiesRepo }) => async ({ | ||
query, type, page, limit, | ||
}): Promise<{ items: VHistories[], meta: Meta }> => { | ||
let filterQuery: whereCondition = { | ||
login: Like('%%'), | ||
title: Like('%%'), | ||
callSign: Like('%%'), | ||
}; | ||
if (query !== undefined) { | ||
if (type === 'user') { | ||
filterQuery.login = Like(`%${query}%`); | ||
} else if (type === 'title') { | ||
filterQuery.title = Like(`%${query}%`); | ||
} else if (type === 'callsign') { | ||
filterQuery.callSign = Like(`%${query}%`); | ||
} else { | ||
filterQuery = [ | ||
{ login: Like(`%${query}%`) }, | ||
{ title: Like(`%${query}%`) }, | ||
{ callSign: Like(`%${query}%`) }, | ||
]; | ||
} | ||
} | ||
const [items, count] = await historiesRepo.findAndCount({ | ||
where: filterQuery, | ||
take: limit, | ||
skip: limit * page, | ||
}); | ||
const meta: Meta = { | ||
totalItems: count, | ||
itemCount: items.length, | ||
itemsPerPage: limit, | ||
totalPages: Math.ceil(count / limit), | ||
currentPage: page + 1, | ||
}; | ||
const returnObject = { | ||
items, | ||
meta, | ||
}; | ||
return returnObject; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { z } from 'zod'; | ||
import { positiveInt } from '~/v1/reviews/controller/reviews.type'; | ||
|
||
export type ParsedHistoriesSearchCondition = z.infer<typeof getHistoriesSearchCondition>; | ||
export const getHistoriesSearchCondition = z.object({ | ||
query: z.string().optional(), | ||
type: z.enum(['user', 'title', 'callsign']).optional(), | ||
page: z.number().nonnegative().default(0), | ||
limit: z.number().nonnegative().default(10), | ||
}); | ||
|
||
export type ParsedHistoriesUserInfo = z.infer<typeof getHistoriesUserInfo>; | ||
export const getHistoriesUserInfo = z.object({ | ||
userId: positiveInt, | ||
userRole: positiveInt.max(3), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { initContract } from '@ts-rest/core'; | ||
import { z } from 'zod'; | ||
import { | ||
historiesGetQuerySchema, historiesGetResponseSchema, | ||
} from './schema'; | ||
import { unauthorizedSchema } from '../shared'; | ||
|
||
export * from './schema'; | ||
|
||
// contract 를 생성할 때, router 함수를 사용하여 api 를 생성 | ||
const c = initContract(); | ||
|
||
export const historiesContract = c.router( | ||
{ | ||
getMyHistories: { | ||
method: 'GET', | ||
path: '/mypage/histories', | ||
description: '마이페이지에서 본인의 대출 기록을 가져온다.', | ||
query: historiesGetQuerySchema, | ||
responses: { | ||
200: historiesGetResponseSchema, | ||
401: unauthorizedSchema, | ||
}, | ||
}, | ||
getAllHistories: { | ||
method: 'GET', | ||
path: '/histories', | ||
description: '사서가 전체 대출 기록을 가져온다.', | ||
query: historiesGetQuerySchema, | ||
responses: { | ||
200: historiesGetResponseSchema, | ||
401: unauthorizedSchema, | ||
}, | ||
}, | ||
|
||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { dateLike, metaSchema, positiveInt } from '../shared'; | ||
import { z } from '../zodWithOpenapi'; | ||
|
||
export const historiesGetQuerySchema = z.object({ | ||
query: z.string().optional(), | ||
type: z.enum(['user', 'title', 'callsign']).optional(), | ||
page: z.number().int().nonnegative().default(0), | ||
limit: z.number().int().nonnegative().default(10), | ||
}); | ||
|
||
export const historiesGetResponseSchema = z.object({ | ||
items: z.array( | ||
z.object({ | ||
id: positiveInt, | ||
lendingCondition: z.string(), | ||
login: z.string(), | ||
returningCondition: z.string(), | ||
penaltyDays: z.number().int().nonnegative(), | ||
callSign: z.string(), | ||
title: z.string(), | ||
bookInfoId: positiveInt, | ||
image: z.string(), | ||
createdAt: dateLike, | ||
returnedAt: dateLike, | ||
updatedAt: dateLike, | ||
dueDate: dateLike, | ||
lendingLibrarianNickName: z.string(), | ||
returningLibrarianNickname: z.string(), | ||
}), | ||
), | ||
meta: metaSchema, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.