Skip to main content

elysia-api-routes

Create and update QuickStack Elysia REST API routes using the project's established /api/v1 route conventions. Use when adding or editing files under src/server/api/v1, defining Elysia query/params/body/response schemas, or handling REST API authorization and errors.

소스 정보

저장소
biersoeckli/quickstack
최근 소스 활동
2026년 8월 9일 17:04
감지된 SKILL.md 언어
영어
스타
361
포크
36

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
elysia-api-routes
description
Create and update QuickStack Elysia REST API routes using the project's established /api/v1 route conventions. Use when adding or editing files under src/server/api/v1, defining Elysia query/params/body/response schemas, or handling REST API authorization and errors.
# Elysia API Routes ## Quick Start For QuickStack REST routes under `src/server/api/v1`, follow the current examples in `app/route.ts` and `project/route.ts`: ```ts export const resourceRoutes = new Elysia() .derive(ApiUtils.deriveFunc) .get('/resources/:id', async ({ params, identity }) => { if (!identity) throw new ApiUnauthorizedException() const resource = await resourceService.getByIdOrUndefined(params.id); if (!resource) throw new ApiNotFoundException(); ensureReadResource(identity, resource.id); return resource; }, { params: z.object({ id: z.string(), }), response: ApiUtils.mapResponseModel(ResourceModel), detail: { summary: 'Get resource by id', security: [{ bearerAuth: [] }] } }); ``` ## Required Route Shape - Start each route module with `new Elysia().derive(ApiUtils.deriveFunc)` so handlers receive `identity`. - Import `ApiUtils` from `src/server/utils/api-response.utils`. - Import `ApiUnauthorizedException`, `ApiNotFoundException`, and `ServiceException` from `src/shared/model/service.exception.model` as needed. - Declare `query`, `params`, and `body` directly in route options with Zod schemas. - Declare `response` with `ApiUtils.mapResponseModel(successSchema)`. - Keep OpenAPI metadata in `detail`, with a short `summary` and `security: [{ bearerAuth: [] }]` for protected routes. ## Handler Rules - If `identity` is missing, throw `new ApiUnauthorizedException()`. - If a requested resource does not exist, throw `new ApiNotFoundException()`. - Use shared authorization helpers such as `ensureReadApp`, `ensureWriteApp`, `ensureCreateAppInProject`, `ensureDeleteAppInProject`, `ensureReadProject`, and `ensureAdmin`. - Let shared authorization helpers throw; do not duplicate permission checks inline except for simple admin/read filtering already established in list routes. - Throw `ServiceException` for expected domain validation errors, such as immutable `projectId` violations. - Return success payloads directly; do not wrap them in `{ data }`, `{ status }`, or error envelopes. - Do not return `ApiUtils.problem(...)`, raw `Response`, or Elysia `status(...)` for expected route errors. ## Schema Rules - Use inline Zod objects for simple route params and query inputs. - Use existing write schemas, such as `AppExtendedWriteZodModel` or a local `projectWriteSchema`, for bodies. - Do not parse `query`, `params`, or `body` inside the handler if the route option already declares the schema. - Do not use nested `schema: { query, params, body }` in these route modules. - For delete routes, return `undefined` and declare `response: ApiUtils.mapResponseModel(z.undefined())`. - For deployment request routes, return `{ deploymentId }` and declare `response: ApiUtils.mapResponseModel(z.object({ deploymentId: z.string() }))`. ## Write Route Pattern Use POST upsert semantics: ```ts .post('/projects', async ({ body, identity }) => { if (!identity) throw new ApiUnauthorizedException() ensureAdmin(identity); let existing: Project | null = null; if (body.id) { existing = await projectService.getByIdOrUndefined(body.id); if (!existing) throw new ApiNotFoundException(); } return projectService.save({ id: existing?.id, name: body.name }); }, { body: projectWriteSchema, response: ApiUtils.mapResponseModel(ProjectModel), detail: { summary: 'Create or update project', security: [{ bearerAuth: [] }] } }) ``` ## Validation Checklist - Run `yarn tsc --noEmit` after route changes. - Check that every accepted input has a route-level Zod schema. - Check that every route has `response: ApiUtils.mapResponseModel(...)`. - Check that expected failures are thrown as exceptions; route mounting maps them centrally with `ApiUtils.mapError(...)`. - Check `CONTEXT.md` for REST API domain terms and write semantics before changing behavior.
GitHub에서 보기