first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
# plugin/plugin — createContactsPlugin factory
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Returns the `PluginDescriptor<ContactsPluginConfig>` consumed by the
`@suaveplan/api` plugin host. Runs the 5-step `onInit` lifecycle:
1. Validate the supplied options through Zod (`INVALID_INPUT` on fail).
2. Resolve the host services (`app`, `db`, optional
`openAPIRegistry`, optional `migrationRunner`).
3. Apply the bundled SurrealQL schema unless
`applySchemaOnInit: false`.
4. Construct the three SurrealDB repositories and register them in
the `ServiceRegistry`.
5. Install a single mount-pattern middleware that injects repositories
+ `eventBus` into every request context, then register the 18
`/contacts` + `/groups` routes via `definePluginRoutes`.
The descriptor declares `dependencies: ["database", "auth"]` so the
host topo-sorts after `@suaveplan/api-plugin-database` and
`@suaveplan/api-plugin-auth`.
## Features
+ Single factory entry-point; idempotent within a process (re-calling
with the same options is safe — every `onInit` build is a fresh
bundle).
+ ServiceRegistry slot registration: `contactRepository`,
`groupRepository`, `membershipRepository`.
+ Hono ContextVariableMap injection: same three slots + `eventBus`.
+ Route-prefix collision detection raises
`ROUTE_PREFIX_COLLISION`.
+ Bare-mount fallback when `openAPIRegistry` is absent (routes
still work; the OpenAPI document just excludes them).
## Usage: Basic
```ts
import { createContactsPlugin } from "@suaveplan/api-plugin-contacts";
const plugin = createContactsPlugin();
// pluginManager.use(plugin);
```
## Usage: Advanced
```ts
import { createContactsPlugin } from "@suaveplan/api-plugin-contacts";
const plugin = createContactsPlugin({
routePrefix: "/api/v1",
maxImportBatchSize: 500,
maxGroupDepth: 5,
enforceGroupDepth: true,
applySchemaOnInit: false, // host has its own migration pipeline
});
```
## API Reference
+ `createContactsPlugin(options?: ContactsPluginOptions): PluginDescriptor<ContactsPluginConfig>`
+ `runOnInit(ctx, config): Promise<void>` — the lifecycle body; exported
for testability so tests can inject a hand-built `PluginContext`.
## Implementation Notes
+ The mount-pattern is computed as `*` when `routePrefix === "/"` and
`${prefix}/*` otherwise; this matches the convention used by the
user plugin and avoids the off-by-one Hono ignores trailing `/`.
+ ROUTE_PREFIX_COLLISION uses `${prefix}/contacts` as the probe so a
second mount of this plugin (even with a different prefix on the
same registry) trips the check.
+ The descriptor's `defaults` slot is the post-Zod-parse
`ContactsPluginConfig`, frozen by the schema's
`passthrough: false` semantics.