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 语言
英语
星标
362
分支
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 查看