Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# @suaveplan/api-plugin-tenant - Multi-tenancy plugin for @suaveplan/api. Exposes @suaveplan/api-tenant's resolver chain (header / subdomain / domain / path / JWT / query / cookie) as a first-class definePlugin slot, wires TenantCache, installs the per-request resolving middleware, registers a typed tenantService in the ServiceRegistry, and (when a TenantStore is configured) mounts admin-gated CRUD routes. Server-tier. Composes with @suaveplan/api-plugin-auth's requireRole when present for RBAC on the management routes.
|
||||
|
||||
Multi-tenancy plugin for `@suaveplan/api`. Wraps
|
||||
`@suaveplan/api-tenant`'s resolver chain (header / subdomain / domain /
|
||||
path / JWT / query / cookie) as a first-class `definePlugin` slot,
|
||||
wires `TenantCache`, installs the per-request resolving middleware,
|
||||
registers a typed `tenantService` in the host `ServiceRegistry`, and
|
||||
(when a `TenantStore` is configured) mounts admin-gated CRUD routes
|
||||
under a configurable prefix.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry for `@suaveplan/api-plugin-tenant` and the concrete `TenantPluginError` class th…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry for `@suaveplan/api-plugin-tenant` and the concrete `TenantPluginError` class th…
|
||||
- [middleware](./src/middleware/tenant.md) — Provides `buildTenantPluginMiddleware`, the Hono middleware factory the plugin installs on `ctx.app` during `onInit`. T…
|
||||
- [tenant](./src/middleware/tenant.md) — Provides `buildTenantPluginMiddleware`, the Hono middleware factory the plugin installs on `ctx.app` during `onInit`. T…
|
||||
- [otel](./src/otel/instruments.md) — Lazily resolves the OpenTelemetry instruments (`Counter`, `Histogram`) the plugin emits from its production paths. The…
|
||||
- [instruments](./src/otel/instruments.md) — Lazily resolves the OpenTelemetry instruments (`Counter`, `Histogram`) the plugin emits from its production paths. The…
|
||||
- [plugin](./src/plugin/plugin.md) — Exposes `createTenantPlugin`, the factory that returns a typed `PluginDescriptor` consumable by the `@suaveplan/api` or…
|
||||
- [build-resolver](./src/plugin/build-resolver.md) — Composes the strategy specs from the plugin's options into a single `TenantResolver` chain, optionally wrapped with `Te…
|
||||
- [plugin](./src/plugin/plugin.md) — Exposes `createTenantPlugin`, the factory that returns a typed `PluginDescriptor` consumable by the `@suaveplan/api` or…
|
||||
- [routes](./src/routes/routes.md) — Builds the five OpenAPI route entries `createTenantPlugin` mounts when a `TenantStore` is configured: `GET /`, `POST /`…
|
||||
- [routes](./src/routes/routes.md) — Builds the five OpenAPI route entries `createTenantPlugin` mounts when a `TenantStore` is configured: `GET /`, `POST /`…
|
||||
- [options](./src/schemas/options.md) — Defines the Zod schema validated at the `createTenantPlugin` boundary plus the strategy-spec discriminated-union schema…
|
||||
- [routes](./src/schemas/routes.md) — Defines the Zod request/response schemas the five management routes mount when the plugin is configured with a `TenantS…
|
||||
- [registry-augmentation](./src/services/registry-augmentation.md) — Side-effect module that declares the `tenantService` slot on `@suaveplan/api-plugin`'s `ServiceRegistry` interface so c…
|
||||
- [tenant-service](./src/services/tenant-service.md) — Defines the `TenantService` interface registered into the host `ServiceRegistry` by `createTenantPlugin` and the factor…
|
||||
- [store](./src/store/store.md) — Defines the canonical `TenantStore` persistence contract every `@suaveplan/api-plugin-tenant` backend honours. The inte…
|
||||
- [memory](./src/store/memory.md) — Ships the default `MemoryTenantStore` — a synchronous in-memory implementation of the `TenantStore` interface suitable…
|
||||
- [store](./src/store/store.md) — Defines the canonical `TenantStore` persistence contract every `@suaveplan/api-plugin-tenant` backend honours. The inte…
|
||||
- [types](./src/types/types.md) — Defines the public option shapes accepted by `createTenantPlugin` and the resolved-config shape stored on the returned…
|
||||
- [types](./src/types/types.md) — Defines the public option shapes accepted by `createTenantPlugin` and the resolved-config shape stored on the returned…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/api-plugin-tenant
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import { defineApp } from "@suaveplan/api";
|
||||
import { createAuthPlugin } from "@suaveplan/api-plugin-auth";
|
||||
import { createTenantPlugin, MemoryTenantStore } from "@suaveplan/api-plugin-tenant";
|
||||
|
||||
const app = defineApp({
|
||||
plugins: [
|
||||
createAuthPlugin({ betterAuth: { /* ... */ } }),
|
||||
createTenantPlugin({
|
||||
strategies: [
|
||||
{ type: "header", headerName: "x-tenant-id" },
|
||||
{ type: "cookie", cookieName: "tenant" },
|
||||
{ type: "subdomain", baseDomain: "app.example.com" },
|
||||
{ type: "jwt", claimName: "tenantId" },
|
||||
{ type: "path", prefix: "/t/" },
|
||||
{ type: "query", paramName: "tenant" },
|
||||
],
|
||||
cache: { ttlMs: 60_000, negativeTtlMs: 5_000, maxEntries: 10_000 },
|
||||
required: false,
|
||||
store: new MemoryTenantStore(),
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## What you get
|
||||
|
||||
- **Seven resolver strategies** composed in priority order — first
|
||||
non-null wins. The chain is wrapped with `TenantCache` when a
|
||||
`cache` config is supplied.
|
||||
- **Per-request `c.set("tenant", tenant)`** via the inner
|
||||
`createTenantMiddleware` from `@suaveplan/api-tenant`. Status gating
|
||||
(`deleted` / `suspended` / `pending`) is enforced before the handler
|
||||
runs.
|
||||
- **`tenantService` registry slot** — `resolveFrom`, `requireFrom`,
|
||||
`current`, `getById`, `listAll`, `createTenant`, `updateTenant`,
|
||||
`deleteTenant`, `getResolver`.
|
||||
- **Five CRUD routes** mounted when `store` is supplied:
|
||||
`GET /tenants`, `POST /tenants`, `GET /tenants/:id`,
|
||||
`PATCH /tenants/:id`, `DELETE /tenants/:id`. Every body and query
|
||||
flows through a strict Zod schema, so the unified OpenAPI 3.1 doc
|
||||
matches the runtime surface.
|
||||
- **Optional admin RBAC** — when `@suaveplan/api-plugin-auth` is
|
||||
loaded, the CRUD routes are gated by `requireRole("admin")`. Without
|
||||
it, the plugin logs a warning so operators do not silently expose
|
||||
admin endpoints.
|
||||
- **OpenTelemetry instruments** — `tenant_plugin.resolutions_total`,
|
||||
`tenant_plugin.resolution_duration_ms`, `tenant_plugin.cache_total`,
|
||||
`tenant_plugin.management_ops_total`.
|
||||
- **Seven stable `TENANT_PLUGIN.*` error codes** — surfaced via
|
||||
`TenantPluginError extends SuaveplanError`.
|
||||
|
||||
## Modules
|
||||
|
||||
- [`error-codes/error-codes.md`](./src/error-codes/error-codes.md)
|
||||
- [`types/types.md`](./src/types/types.md)
|
||||
- [`store/store.md`](./src/store/store.md)
|
||||
- [`store/memory.md`](./src/store/memory.md)
|
||||
- [`schemas/options.md`](./src/schemas/options.md)
|
||||
- [`schemas/routes.md`](./src/schemas/routes.md)
|
||||
- [`services/tenant-service.md`](./src/services/tenant-service.md)
|
||||
- [`services/registry-augmentation.md`](./src/services/registry-augmentation.md)
|
||||
- [`middleware/tenant.md`](./src/middleware/tenant.md)
|
||||
- [`otel/instruments.md`](./src/otel/instruments.md)
|
||||
- [`plugin/build-resolver.md`](./src/plugin/build-resolver.md)
|
||||
- [`plugin/plugin.md`](./src/plugin/plugin.md)
|
||||
- [`routes/routes.md`](./src/routes/routes.md)
|
||||
|
||||
## Error codes
|
||||
|
||||
`TENANT_PLUGIN.INVALID_INPUT`, `STORE_NOT_CONFIGURED`,
|
||||
`SERVICE_NOT_AVAILABLE`, `ROUTE_PREFIX_COLLISION`, `TENANT_NOT_FOUND`,
|
||||
`TENANT_SLUG_TAKEN`, `RESOLVER_BUILD_FAILED`.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user