generated from ttipo/project-base
feat(backend): 반려동물 API — 등록·수정·삭제·순서·추억 보관함
앱의 우리 아이 기록(PetRepository)을 서버로 옮긴다.
- GET/POST /pets, PATCH/DELETE /pets/:id, PUT /pets/order, PUT/DELETE /pets/:id/archive
- 목록은 정한 순서(sort_order) 기준 커서 페이지네이션 — 공통 keysetPaginate 로 뽑았다
- 아이를 지우거나 보관할 때 일정·다이어리·명함이 따라 정리할 수 있게 PetLifecycleListener 를 두었다
(반려동물 모듈은 다른 도메인을 모르고, 정리는 같은 트랜잭션에서 한다)
- 사진을 바꾸면 쓰지 않는 파일만 지운다 — 다른 기록이 참조하면 FK 가 막는다
- 목록 응답 Swagger 를 실제 { items, pageInfo } 모양으로 그리는 ApiPaginatedResponse 추가
- e2e 에 목록 pageInfo 계약·미정의 쿼리 거부 검사를 되살렸다
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import { isValidIsoDate } from './iso-date';
|
||||
|
||||
describe('isValidIsoDate', () => {
|
||||
it('달력에 있는 날짜면 통과한다', () => {
|
||||
expect(isValidIsoDate('2026-10-11')).toBe(true);
|
||||
expect(isValidIsoDate('2024-02-29')).toBe(true);
|
||||
});
|
||||
|
||||
it('형식만 맞고 없는 날짜는 거절한다', () => {
|
||||
expect(isValidIsoDate('2026-02-30')).toBe(false);
|
||||
expect(isValidIsoDate('2025-02-29')).toBe(false);
|
||||
expect(isValidIsoDate('2026-13-01')).toBe(false);
|
||||
});
|
||||
|
||||
it('시각이 붙었거나 형식이 다르면 거절한다', () => {
|
||||
expect(isValidIsoDate('2026-10-11T00:00:00Z')).toBe(false);
|
||||
expect(isValidIsoDate('2026/10/11')).toBe(false);
|
||||
expect(isValidIsoDate('26-10-11')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
// 날짜 문자열(YYYY-MM-DD) 다루기 — 부수효과 없는 순수 함수
|
||||
|
||||
const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
||||
|
||||
/**
|
||||
* 달력에 있는 날짜인지 — `2026-02-30` 처럼 형식만 맞는 값은 거절한다.
|
||||
* 시각 없는 날짜(생일·일정 날짜)는 시간대 변환 없이 문자열 그대로 주고받는다.
|
||||
*/
|
||||
export function isValidIsoDate(value: string): boolean {
|
||||
const match = ISO_DATE_PATTERN.exec(value);
|
||||
if (!match) return false;
|
||||
|
||||
const [year, month, day] = match.slice(1).map(Number);
|
||||
const date = new Date(Date.UTC(year, month - 1, day));
|
||||
return (
|
||||
date.getUTCFullYear() === year &&
|
||||
date.getUTCMonth() === month - 1 &&
|
||||
date.getUTCDate() === day
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user