Hono
@vperms/hono is the Hono counterpart of the
Express integration. It sets the ability on the Hono
context instead of the request object.
import { Hono } from "hono";import { vpermsMiddleware, hasPermission, type VPermsEnv,} from "@vperms/hono";import { VeguiPermsMemoryAdapter } from "vperms";
const app = new Hono<VPermsEnv>();
app.use( vpermsMiddleware({ adapter: new VeguiPermsMemoryAdapter(), workspace: "workspace", resolver: (c) => c.get("session")?.userId ?? null, }),);
app.get("/posts/:id", hasPermission("posts.read"), (c) => c.json({ allowed: true }),);Middleware options
Section titled “Middleware options”interface VpermsMiddlewareOptions { adapter: VeguiPermsAdapter; resolver: SubjectResolver; workspace: string | WorkspaceResolver; defaultParents?: DefaultParents; permissionsExport?: { path: string };}
type VPermsContext = Context<VPermsEnv>;type SubjectResolver = (c: VPermsContext) => SubjectId | Principal | null | Promise<...>;type WorkspaceResolver = (c: VPermsContext) => string | Promise<string>;The middleware stores three context variables:
interface VPermsVariables { ability: RequestAbility; subject: Subject | undefined; kind: SubjectType | undefined;}Use VPermsEnv as the app’s generic so c.get("ability") is typed.
Route guards
Section titled “Route guards”import { hasPermission, hasAnyPermission } from "@vperms/hono";
app.get("/posts/:id", hasPermission("posts.read"), handler);app.delete("/posts/:id", hasAnyPermission("admin", "posts.delete"), handler);hasPermission requires all inputs, hasAnyPermission at least one. Both
return a bare 403 response (c.body(null, 403)) when denied. Permissions can
be functions:
import type { PermissionBuilder } from "@vperms/hono";
const ownsPost: PermissionBuilder = (c) => `posts.${c.req.param("id")}.write`;
app.put("/posts/:id", hasPermission(ownsPost), handler);Permissions export
Section titled “Permissions export”With permissionsExport.path set, a matching GET is answered as JSON:
| Status | Body | Meaning |
|---|---|---|
200 |
ResolvedSubject |
Success |
403 |
empty | Caller cannot read the target |
404 |
empty | Subject does not exist |
400 |
{ "error": string } |
Invalid subject id |
Other requests continue through await next().
Exports
Section titled “Exports”RequestAbility, VPermsEnv, VPermsVariables, VPermsContext,
vpermsMiddleware, hasPermission, hasAnyPermission, PermissionBuilder,
PermissionInput, SubjectResolver, SubjectResolverResult,
WorkspaceResolver, PermissionsExportOptions, VpermsMiddlewareOptions,
ANONYMOUS_SUBJECT_ID.