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.

Quellinformationen

Repository
biersoeckli/quickstack
Letzte Quellaktivität
9. August 2026 um 17:04
Erkannte Sprache von SKILL.md
Englisch
Sterne
362
Forks
36

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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.
Auf GitHub ansehen