Files
skills/docs/commerce/contacts/api-plugin-contacts/src/plugin/plugin.md
2026-05-29 08:20:56 +01:00

2.7 KiB

plugin/plugin — createContactsPlugin factory

(no submodules)

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

import { createContactsPlugin } from "@suaveplan/api-plugin-contacts";

const plugin = createContactsPlugin();
// pluginManager.use(plugin);

Usage: Advanced

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.