{"version":3,"sources":["../src/http/create-http-errors.ts","../src/http/create-api-wrapper.ts","../src/http/create-auth-wrapper.ts","../src/http/error-catalog.ts","../src/http/index.ts"],"names":["throwHttpError","createHttpError","errorHandler","_a","apiWrapper"],"mappings":"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","file":"http.mjs","sourcesContent":["/**\n * createHttpErrors — 프로젝트별 ErrorCatalog를 주입해 에러 유틸을 생성하는 팩토리\n *\n * 프로젝트마다 ErrorCatalog가 다르기 때문에 팩토리 패턴으로 분리한다.\n * 반환된 함수들은 카탈로그 키에 대한 타입 자동완성을 지원한다.\n *\n * @example\n * // shared/errors.ts (프로젝트 내 1회 설정)\n * import { createHttpErrors } from \"@linkup/http\";\n * import { ErrorCatalog } from \"./errorCatalog\";\n *\n * export const { throwHttpError, createHttpError, errorHandler } =\n *   createHttpErrors(ErrorCatalog, {\n *     onMysqlDupEntry: (sqlMessage) => {\n *       if (sqlMessage?.includes(\"product_domae_tb_unique\")) return \"이미 등록된 도매사 상품입니다.\";\n *     },\n *   });\n *\n * @example\n * // route 에서 사용\n * import { throwHttpError } from \"@/shared/errors\";\n * throwHttpError(\"NOT_FOUND\", \"회원을 찾을 수 없습니다.\");\n */\n\nimport { NextResponse } from \"next/server\";\nimport { ZodError } from \"zod\";\n\n/** ErrorCatalog 각 항목의 형태 */\nexport interface ErrorEntry {\n    status: number;\n    message: string;\n}\n\n/** AppError — throwHttpError / createHttpError 가 만드는 에러 객체 */\nexport interface AppError extends Error {\n    status: number;\n    code: string;\n    detail?: string;\n}\n\nexport interface HttpErrorsOptions {\n    /**\n     * MySQL ER_DUP_ENTRY 발생 시 호출된다.\n     * 프로젝트 고유 유니크 키 이름으로 detail 메시지를 분기할 때 사용.\n     * undefined를 반환하면 기본 메시지(\"이미 등록된 데이터입니다.\")를 사용한다.\n     */\n    onMysqlDupEntry?: (sqlMessage?: string) => string | undefined;\n    /**\n     * 에러 로깅 핸들러.\n     * 기본: development 환경에서만 console.error.\n     */\n    onLog?: (err: unknown) => void;\n}\n\nexport function createHttpErrors<\n    TCatalog extends Record<string, ErrorEntry>\n>(catalog: TCatalog, options: HttpErrorsOptions = {}) {\n    type ErrorKey = keyof TCatalog & string;\n\n    const log =\n        options.onLog ??\n        ((err: unknown) => {\n            if (process.env.NODE_ENV === \"development\") {\n                console.error(\"[http] error:\", err);\n            }\n        });\n\n    /** 에러를 throw한다. never 타입이므로 이후 코드가 실행되지 않는다. */\n    function throwHttpError(code: ErrorKey, detail?: string): never {\n        const entry = catalog[code];\n        const error = new Error(entry.message) as AppError;\n        error.status = entry.status;\n        error.code = code;\n        if (detail) error.detail = detail;\n        throw error;\n    }\n\n    /** 에러 객체를 생성만 하고 throw하지 않는다. */\n    function createHttpError(code: ErrorKey, detail?: string): AppError {\n        const entry = catalog[code];\n        const error = new Error(entry.message) as AppError;\n        error.status = entry.status;\n        error.code = code;\n        if (detail) error.detail = detail;\n        return error;\n    }\n\n    /** catch 블록에서 받은 unknown 에러를 NextResponse로 변환한다. */\n    function errorHandler(err: unknown): NextResponse {\n        log(err);\n\n        // AppError (throwHttpError / createHttpError 로 만든 에러)\n        const isAppError = (e: unknown): e is AppError =>\n            typeof e === \"object\" &&\n            e !== null &&\n            \"code\" in e &&\n            \"status\" in e;\n\n        // mysql2 에러 — errno(number)가 있으면 mysql 에러로 판별\n        const isMysqlError = (\n            e: unknown\n        ): e is { code?: string; errno?: number; sqlMessage?: string; message?: string } =>\n            typeof e === \"object\" &&\n            e !== null &&\n            \"errno\" in e &&\n            typeof (e as any).errno === \"number\";\n\n        let code: string = \"INTERNAL_ERROR\";\n        let status = 500;\n        let message = \"Internal Server Error\";\n        let detail = \"알 수 없는 오류\";\n        let fieldErrors: { path: string; message: string }[] | undefined;\n\n        if (isAppError(err)) {\n            code = err.code;\n            status = err.status;\n            message = err.message || catalog[code]?.message || message;\n            detail = err.detail || err.message || detail;\n        } else if (err instanceof ZodError) {\n            fieldErrors = err.issues.map((issue) => ({\n                path: issue.path.join(\".\"),\n                message: issue.message,\n            }));\n            code = \"BAD_REQUEST\";\n            status = 400;\n            // \"입력값이 올바르지 않습니다\" 뒤에 필드명(마지막 path 세그먼트) + zod 원본 메시지를 힌트로 붙여준다.\n            message = `입력값이 올바르지 않습니다: ${fieldErrors\n                .map((e) => {\n                    const word = e.path.split(\".\").pop();\n                    return word ? `${word}: ${e.message}` : e.message;\n                })\n                .join(\", \")}`;\n            detail = fieldErrors\n                .map((e) => (e.path ? `${e.path}: ${e.message}` : e.message))\n                .join(\", \");\n        } else if (isMysqlError(err)) {\n            if (err.code === \"ER_DUP_ENTRY\") {\n                code = \"BAD_REQUEST\";\n                status = 400;\n                message = \"중복된 데이터입니다.\";\n                detail =\n                    options.onMysqlDupEntry?.(err.sqlMessage) ??\n                    \"이미 등록된 데이터입니다.\";\n            } else {\n                message = err.message || message;\n                detail = err.sqlMessage || err.message || detail;\n            }\n        } else if (err instanceof Error) {\n            message = err.message || message;\n            detail = err.message || detail;\n        }\n\n        return NextResponse.json(\n            {\n                success: false,\n                status,\n                code,\n                message,\n                detail,\n                fieldErrors,\n                error: process.env.NODE_ENV === \"development\" ? message : undefined,\n            },\n            { status }\n        );\n    }\n\n    return { throwHttpError, createHttpError, errorHandler };\n}\n","/**\n * createApiWrapper — Next.js Route Handler try/catch 래퍼 생성 팩토리\n *\n * createHttpErrors()로 만든 errorHandler를 주입해 apiWrapper를 생성한다.\n * 모든 Route Handler에서 try/catch를 제거하고 에러 처리를 한 곳으로 모을 수 있다.\n *\n * @example\n * // shared/errors.ts\n * import { createHttpErrors, createApiWrapper } from \"@linkup/http\";\n * import { ErrorCatalog } from \"./errorCatalog\";\n *\n * export const { throwHttpError, errorHandler } = createHttpErrors(ErrorCatalog);\n * export const apiWrapper = createApiWrapper(errorHandler);\n *\n * @example\n * // app/api/members/route.ts\n * import { apiWrapper, throwHttpError } from \"@/shared/errors\";\n *\n * export const GET = apiWrapper(async (req) => {\n *   const user = await queryOne<User>(\"SELECT ...\", []);\n *   if (!user) throwHttpError(\"NOT_FOUND\");\n *   return NextResponse.json({ data: user });\n * });\n *\n * @example\n * // params가 있는 동적 라우트\n * export const DELETE = apiWrapper<{ params: Promise<{ id: string }> }>(\n *   async (req, { params }) => {\n *     const { id } = await params;\n *     await remove(\"users\", { id });\n *     return NextResponse.json({ success: true });\n *   }\n * );\n */\n\nimport { NextRequest } from \"next/server\";\n\ntype RouteHandler<TContext = any> = (\n    req: NextRequest,\n    context: TContext\n) => Promise<Response>;\n\nexport function createApiWrapper(errorHandler: (err: unknown) => Response) {\n    return function apiWrapper<TContext = any>(handler: RouteHandler<TContext>) {\n        return async (req: NextRequest, context: TContext): Promise<Response> => {\n            try {\n                return await handler(req, context);\n            } catch (error) {\n                return errorHandler(error);\n            }\n        };\n    };\n}\n","/**\n * createAuthWrapper — 인증 체크가 포함된 Route Handler 래퍼 생성 팩토리\n *\n * getUser 함수를 주입받아 authWrapper를 생성한다.\n * getUser는 인증 실패 시 throwHttpError(\"UNAUTHORIZED\")를 throw해야 한다.\n * (throw된 에러는 errorHandler가 처리하므로 route에서 별도 try/catch 불필요)\n *\n * @example\n * // shared/errors.ts (프로젝트 내 1회 설정)\n * import { createHttpErrors, createApiWrapper, createAuthWrapper } from \"@linkup/http\";\n * import { ErrorCatalog } from \"./errorCatalog\";\n * import { getUserSession } from \"./auth\";\n *\n * export const { throwHttpError, errorHandler } = createHttpErrors(ErrorCatalog);\n * export const apiWrapper = createApiWrapper(errorHandler);\n * export const authWrapper = createAuthWrapper(errorHandler, getUserSession);\n *\n * @example\n * // shared/auth.ts (프로젝트에서 직접 구현)\n * import { getToken } from \"next-auth/jwt\";\n * import { throwHttpError } from \"./errors\";\n *\n * export async function getUserSession(req: NextRequest) {\n *   const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });\n *   if (!token?.user?.userKey) throwHttpError(\"UNAUTHORIZED\", \"다시 로그인 해주세요\");\n *   return token.user;\n * }\n *\n * @example\n * // route 에서 사용 — user가 3번째 인자로 자동 주입됨\n * import { authWrapper } from \"@/shared/errors\";\n *\n * export const GET = authWrapper(async (req, _ctx, user) => {\n *   return NextResponse.json({ userKey: user.userKey });\n * });\n *\n * // 동적 라우트 params + 인증\n * export const DELETE = authWrapper<{ params: Promise<{ id: string }> }>(\n *   async (req, { params }, user) => {\n *     const { id } = await params;\n *     return NextResponse.json({ id, deletedBy: user.userKey });\n *   }\n * );\n */\n\nimport { NextRequest } from \"next/server\";\n\ntype AuthRouteHandler<TUser, TContext = any> = (\n    req: NextRequest,\n    context: TContext,\n    user: TUser\n) => Promise<Response>;\n\nexport function createAuthWrapper<TUser>(\n    errorHandler: (err: unknown) => Response,\n    getUser: (req: NextRequest) => Promise<TUser>\n) {\n    return function authWrapper<TContext = any>(\n        handler: AuthRouteHandler<TUser, TContext>\n    ) {\n        return async (req: NextRequest, context: TContext): Promise<Response> => {\n            try {\n                const user = await getUser(req);\n                return await handler(req, context, user);\n            } catch (error) {\n                return errorHandler(error);\n            }\n        };\n    };\n}\n","/**\n * 공통 HTTP 에러 카탈로그\n *\n * 프로젝트 고유 에러 코드가 필요하면 spread로 확장한다.\n *\n * @example\n * // 그대로 사용\n * import { throwHttpError } from \"@sunkim4638/admin-modules/http\";\n * throwHttpError(\"NOT_FOUND\", \"회원을 찾을 수 없습니다.\");\n *\n * @example\n * // 확장해서 사용\n * import { createHttpErrors, createApiWrapper, ErrorCatalog } from \"@sunkim4638/admin-modules/http\";\n *\n * const MyErrorCatalog = {\n *   ...ErrorCatalog,\n *   PAYMENT_FAILED: { status: 402, message: \"결제에 실패했습니다.\" },\n * } as const;\n *\n * export const { throwHttpError, errorHandler } = createHttpErrors(MyErrorCatalog);\n * export const apiWrapper = createApiWrapper(errorHandler);\n */\n\nexport const ErrorCatalog = {\n    BAD_REQUEST:        { status: 400, message: \"잘못된 요청입니다.\" },\n    UNAUTHORIZED:       { status: 401, message: \"인증이 필요합니다.\" },\n    FORBIDDEN:          { status: 403, message: \"권한이 없습니다.\" },\n    NOT_FOUND:          { status: 404, message: \"데이터를 찾을 수 없습니다.\" },\n    CONFLICT:           { status: 409, message: \"이미 존재하는 데이터입니다.\" },\n    UNPROCESSABLE:      { status: 422, message: \"처리할 수 없는 요청입니다.\" },\n    INTERNAL_ERROR:     { status: 500, message: \"서버 오류가 발생했습니다.\" },\n    SERVICE_UNAVAILABLE:{ status: 503, message: \"서비스를 일시적으로 사용할 수 없습니다.\" },\n} as const;\n\nexport type ErrorKey = keyof typeof ErrorCatalog;\n","export { createHttpErrors, type AppError, type ErrorEntry, type HttpErrorsOptions } from \"./create-http-errors\";\nexport { createApiWrapper } from \"./create-api-wrapper\";\nexport { createAuthWrapper } from \"./create-auth-wrapper\";\nexport { ErrorCatalog, type ErrorKey } from \"./error-catalog\";\n\n// 공통 카탈로그로 미리 빌드된 버전 — 커스텀 없이 바로 사용 가능\nimport { createHttpErrors } from \"./create-http-errors\";\nimport { createApiWrapper } from \"./create-api-wrapper\";\nimport { ErrorCatalog } from \"./error-catalog\";\n\nconst _http = createHttpErrors(ErrorCatalog, {\n    onMysqlDupEntry: () => \"이미 등록된 데이터입니다.\",\n});\n\nexport const throwHttpError = _http.throwHttpError;\nexport const createHttpError = _http.createHttpError;\nexport const errorHandler = _http.errorHandler;\nexport const apiWrapper = createApiWrapper(_http.errorHandler);\n"]}