Files
skills/docs/api-stack/api/api-plugin-vault/src/plugin/plugin.md
2026-05-29 08:20:56 +01:00

3.6 KiB

plugin/plugin

(no submodules)

Purpose

createVaultPlugin(options) is the factory that returns a typed PluginDescriptor<VaultPluginConfig> ready to register with the host's PluginRegistry. Third instance of the 3-way plug-and-play contract: the plugin owns its .surql DDL, its Zod schemas, and its OpenAPI routes, and applies all three during onInit. Depends on api-plugin-auth so every route's principal scoping has a typed upstream supplier.

Features

  • Zod-validated options via VaultPluginOptionsSchema — invalid input raises VaultPluginError(VAULT_PLUGIN_INVALID_INPUT) carrying the ZodError.
  • Declares dependencies: ["auth"] so the registry refuses to load the plugin without api-plugin-auth registered upstream.
  • 6-step onInit lifecycle: resolve services → apply schema → construct vaultService → register vaultService → register routes → (no global middleware — requireAuth() is per-route).
  • routePrefix-aware route mounting — paths are rebuilt at the prefix the operator chose, both in the served Hono app and in the OpenAPIRegistry snapshot. Default /vault.
  • Collision detection — pre-existing routes under the configured prefix raise VAULT_PLUGIN_ROUTE_PREFIX_COLLISION.
  • Graceful degradation — when openAPIRegistry is absent, routes mount on the Hono app directly (no doc); when neither migrationRunner nor db is available with applySchemaOnInit: true, init fails fast with VAULT_PLUGIN_SERVICE_NOT_AVAILABLE.

Usage: Basic

import { defineApp } from "@suaveplan/api";
import { createAuthPlugin } from "@suaveplan/api-plugin-auth";
import { createVaultPlugin } from "@suaveplan/api-plugin-vault";

const app = await defineApp()
    .name("my-api")
    .use(createAuthPlugin({ betterAuth: { /* ... */ } }))
    .use(createVaultPlugin({ storage: driveAdapter }))
    .start();

Usage: Advanced

const plugin = createVaultPlugin({
    storage: driveAdapter,
    routePrefix: "/v1/vault",
    maxItemSizeBytes: 4 * 1024 * 1024,
    serverPepper: process.env["VAULT_SERVER_PEPPER"]!,
    unlockExtractor: (c) =>
        c.req.header("X-Custom-Vault-Unlock") ?? null,
    applySchemaOnInit: false, // operator runs migrations externally
});

API Reference

createVaultPlugin(options: VaultPluginOptions): PluginDescriptor<VaultPluginConfig>

Returns a definePlugin descriptor. name: "vault", version: "0.1.0", dependencies: ["auth"].

The defaults field carries every resolved option after Zod validation — the registry passes that to onInit via ctx.getOwnConfig().

onInit(ctx) resolves services, applies the schema, constructs the service, registers it, and registers the 5 routes.

Implementation Notes

  • The plugin DOES NOT install global middleware. requireAuth() from api-plugin-auth is applied per-route inside buildVaultRoutes so the public /openapi.json doc only carries vault routes for the authenticated scope and operators can leave the vault prefix out of public-facing API documentation tooling.
  • The rewritePath helper preserves {id} segments verbatim — when the operator chooses /v1/vault, the route path /vault/items/{id} becomes /v1/vault/items/{id}.
  • The collision check inspects every previously registered route whose path starts with the configured prefix — operators wiring multiple vault plugin instances under different prefixes are unaffected.
  • The plugin does not provide an onClose hook because the vaultService is stateless across requests — every handle is opened + closed within a single request lifecycle.