2.7 KiB
2.7 KiB
routes/build-routes — auth-gated import routes
Purpose
Constructs the OpenAPIHono router mounted by createImportPlugin at
the configured routePrefix. Five routes are registered — POST /preview, POST /, GET /, GET /{id}, DELETE /{id} — each gated
behind requireAuth() from @suaveplan/api-plugin-auth so anonymous
requests return 401 problem+json before they ever reach a handler.
Owner-scoped routes read c.get("user").id and pass it through to the
canonical ImportService, which raises IMPORT.NOT_FOUND (mapped to
404 problem+json) on foreign-owner lookups so the surface is
anti-enumeration-safe.
Features
- Five OpenAPI routes with full Zod request / response schemas.
- Per-route
app.use("/*", requireAuth())guard. progressToResponse()shape mapper so the response body always satisfiesImportJobResponseSchema.- Every handler funnels error paths through
respondProblemJsonso the response shape is uniform across success and failure.
Usage: Basic Example
import { createImportRoutes, ImportService } from "@suaveplan/api-plugin-import";
import { OpenAPIHono } from "@hono/zod-openapi";
const service = new ImportService();
const app = new OpenAPIHono();
app.route("/imports", createImportRoutes({ service }));
Usage: Advanced Example
import { createImportRoutes, ImportService, MemoryImportStore } from "@suaveplan/api-plugin-import";
import { OpenAPIHono } from "@hono/zod-openapi";
const store = new MemoryImportStore();
const service = new ImportService({ store });
service.bus.on("import.progress", (snap) => sse.broadcast(snap));
const app = new OpenAPIHono();
app.use("/imports/*", customRateLimit({ window: "1m", max: 10 }));
app.route("/imports", createImportRoutes({ service }));
API Reference
createImportRoutes(deps: ImportRoutesDeps): OpenAPIHonointerface ImportRoutesDeps { service: ImportService }
Implementation Notes
- The
requireAuth()middleware is mounted viaapp.use("/*", ...)so every route inherits the guard. Mounting per-route would duplicate the wiring and miss the OpenAPI catch-all. ownerOf(c)returns the empty string whenc.get("user")is null; the auth middleware throws BEFORE the handler runs, so the empty string is unreachable from production traffic — but it remains a safe default if a caller somehow bypasses the middleware in a test harness.- The list endpoint returns
{ items, total }rather than a raw array so clients can paginate; the schema enforcestotal >= 0. - The delete endpoint surfaces a
{ deleted: boolean }payload — a successful delete returns{ deleted: true }; a missing job throwsIMPORT.NOT_FOUNDfrom the service layer and is rendered as 404.