# schemas/options ## Purpose `UserPluginOptionsSchema` is the Zod boundary contract for the operator-supplied options accepted by `createUserPlugin`. It enforces defaults, validates the route prefix shape, gates profile-field names through the SurrealQL identifier grammar so they can be interpolated into DDL without quoting, and structurally validates the optional logger override. Invalid input causes the factory to throw `UserError(USER_INVALID_INPUT)` carrying the `ZodError` as `cause`. ## Features - Defaults `routePrefix` to `/users`, `allowSelfDelete` to `true`, `applySchemaOnInit` to `true`, and `profileFields` to `["displayName", "avatarUrl", "locale", "timezone"]`. - `routePrefix` is regex-checked: starts with `/`, ends without a trailing `/` (root `/` is the single allowed exception). - `profileFields` is regex-checked against `[A-Za-z_][A-Za-z0-9_]*` so the schema-apply step can drop each name straight into DDL. - `logger` is structurally validated via `z.custom` so operators can pass any object that satisfies `LoggerLike` without nominal typing. - Two type aliases — `UserPluginOptionsInput` (pre-parse) and `UserPluginOptionsResolved` (post-parse) — are exported so callers can pick the variant that matches their lifecycle stage. ## Usage: Basic ```ts import { UserPluginOptionsSchema } from "@suaveplan/api-plugin-user/schemas/options"; const resolved = UserPluginOptionsSchema.parse({}); // resolved.routePrefix === "/users" ``` ## Usage: Advanced When wiring the plugin into a custom factory, validate the operator input separately so the error surface is explicit: ```ts import { UserPluginOptionsSchema } from "@suaveplan/api-plugin-user/schemas/options"; const parsed = UserPluginOptionsSchema.safeParse(input); if (!parsed.success) { return Result.err({ code: "USER.INVALID_INPUT", issues: parsed.error }); } const resolved = parsed.data; ``` ## API Reference ### `UserPluginOptionsSchema: z.ZodObject` Schema with five entries — `routePrefix`, `allowSelfDelete`, `profileFields`, `applySchemaOnInit`, and `logger`. Defaults are applied during parse. ### `UserPluginOptionsInput` `z.input` of the schema — the pre-parse shape, every field optional. ### `UserPluginOptionsResolved` `z.output` of the schema — defaults applied. The plugin's `defaults` field on the descriptor types to this shape. ## Implementation Notes - The `profileFields` regex deliberately rejects digits-at-position-0 and dashes; SurrealQL identifiers that contain those characters would need backtick-quoting which the bundled schema does not emit. - `.readonly()` on `profileFields` flows through to the runtime config so the array is shared without defensive copies. - The `logger` predicate only checks `info`; the other three methods are inferred from the `LoggerLike` cast for downstream consumers.