first commit
This commit is contained in:
87
docs/api-stack/api/api-plugin-user/src/plugin/plugin.md
Normal file
87
docs/api-stack/api/api-plugin-user/src/plugin/plugin.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# plugin/plugin
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
The plugin module exports `createUserPlugin`, the public factory for
|
||||
the user plugin's `PluginDescriptor`. The factory validates the
|
||||
operator-supplied options against `UserPluginOptionsSchema`,
|
||||
constructs the resolved `UserPluginConfig`, and returns a descriptor
|
||||
that — when the host's `PluginRegistry` invokes `onInit(ctx)` —
|
||||
applies the bundled schema, registers the `userService` slot in the
|
||||
ServiceRegistry, installs `requireAuth()` on the route prefix, and
|
||||
mounts the three `/users/me` routes via `definePluginRoutes`.
|
||||
|
||||
## Features
|
||||
|
||||
- Zod-validated factory input — invalid options throw
|
||||
`UserError(USER_INVALID_INPUT)` carrying the `ZodError`.
|
||||
- Declares `dependencies: ["auth"]` so the registry topo-sorts after
|
||||
`api-plugin-auth` automatically.
|
||||
- Resolves the `app`, `authService`, and `db` services from the
|
||||
host's `ServiceRegistry`; raises `USER_SERVICE_NOT_AVAILABLE`
|
||||
listing missing slot names when any is absent.
|
||||
- Applies `USER_PROFILE_SCHEMA` via the `migrationRunner` when
|
||||
registered (so the migration is tracked) and falls back to a direct
|
||||
`db.execute` otherwise. Bypassed entirely when
|
||||
`applySchemaOnInit: false`.
|
||||
- Installs the auth plugin's `requireAuth()` middleware on the route
|
||||
prefix so every `/users/me` handler runs under an authenticated
|
||||
context.
|
||||
- Detects route-prefix collisions in the OpenAPI registry and raises
|
||||
`USER_ROUTE_PREFIX_COLLISION` rather than silently double-mounting.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { defineApp } from "@suaveplan/api";
|
||||
import { createAuthPlugin } from "@suaveplan/api-plugin-auth";
|
||||
import { createUserPlugin } from "@suaveplan/api-plugin-user";
|
||||
|
||||
await defineApp()
|
||||
.use(createAuthPlugin({ betterAuth: { /* … */ } }))
|
||||
.use(createUserPlugin({}))
|
||||
.start();
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Custom profile fields and the disabled self-delete path:
|
||||
|
||||
```ts
|
||||
const userPlugin = createUserPlugin({
|
||||
profileFields: ["displayName", "avatarUrl", "bio", "locale"],
|
||||
allowSelfDelete: false,
|
||||
applySchemaOnInit: true,
|
||||
});
|
||||
```
|
||||
|
||||
The resolved descriptor exposes `defaults` so a test harness can
|
||||
inspect the post-Zod config without booting the registry.
|
||||
|
||||
## API Reference
|
||||
|
||||
### `createUserPlugin(options?: UserPluginOptions): PluginDescriptor<UserPluginConfig>`
|
||||
|
||||
Returns the typed descriptor consumed by the host's
|
||||
`PluginRegistry`. `options` is fully optional — every field has a
|
||||
default in `UserPluginOptionsSchema`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The `onInit` closure captures the resolved config — the registry
|
||||
rebuilds the per-hook `PluginContext` each call, so capturing the
|
||||
config in the closure keeps the lifecycle stateless from the
|
||||
registry's perspective.
|
||||
- `requireAuth()` is installed via `app.use(prefix/*, ...)` so every
|
||||
route handler sees a non-null Principal; the handlers also
|
||||
defensively re-check the principal in case the operator changes the
|
||||
middleware ordering.
|
||||
- The route-prefix collision check compares the `/me` suffix
|
||||
specifically — registering siblings under the same base path (e.g.
|
||||
a future `/users/admin`) does NOT trigger the collision because
|
||||
the prefix-aware audit narrows to the exact route paths the plugin
|
||||
registers.
|
||||
Reference in New Issue
Block a user