3.2 KiB
plugin/plugin
(no submodules)
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 theZodError. - Declares
dependencies: ["auth"]so the registry topo-sorts afterapi-plugin-authautomatically. - Resolves the
app,authService, anddbservices from the host'sServiceRegistry; raisesUSER_SERVICE_NOT_AVAILABLElisting missing slot names when any is absent. - Applies
USER_PROFILE_SCHEMAvia themigrationRunnerwhen registered (so the migration is tracked) and falls back to a directdb.executeotherwise. Bypassed entirely whenapplySchemaOnInit: false. - Installs the auth plugin's
requireAuth()middleware on the route prefix so every/users/mehandler runs under an authenticated context. - Detects route-prefix collisions in the OpenAPI registry and raises
USER_ROUTE_PREFIX_COLLISIONrather than silently double-mounting.
Usage: Basic
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:
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
onInitclosure captures the resolved config — the registry rebuilds the per-hookPluginContexteach call, so capturing the config in the closure keeps the lifecycle stateless from the registry's perspective. requireAuth()is installed viaapp.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
/mesuffix 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.