Files
skills/docs/api-stack/api/api-plugin-campaigns/src/routes/campaigns/build-routes.md
2026-05-29 08:20:56 +01:00

2.4 KiB

build-routes (campaigns)

Purpose

buildCampaignRoutes is the single aggregator that materialises every /campaigns/* PluginRouteEntry in a canonical order. The plugin's onInit consumes the array verbatim — there is no per-route opt-in or configuration knob — so the OpenAPI spec generated for the campaigns tree is deterministic across deployments and across reloads. Tests assert the canonical order so accidental reordering during refactors surfaces immediately rather than as silent spec drift.

The aggregator is intentionally a flat function returning a readonly array (rather than a class or builder). The cost of describing 12 routes inline is small, the structure is obvious, and downstream consumers can array.map(toPrefixed) cheaply when they need to mount under a non-root prefix.

Features

  • Returns 12 entries in a documented canonical order.
  • Pure: no I/O, no side effects, no captured registry.
  • Each entry exposes route: RouteConfig + handler: RouteHandler so it can be mounted either via definePluginRoutes (production) or directly on a bare Hono app (tests).

Usage: Basic

import { buildCampaignRoutes } from "@suaveplan/api-plugin-campaigns";

const entries = buildCampaignRoutes();
for (const e of entries) {
    app[e.route.method as "get" | "post" | "patch" | "delete"](
        e.route.path,
        (c) => e.handler(c)
    );
}

Usage: Advanced

import {
    buildCampaignRoutes,
    definePluginRoutes,
} from "@suaveplan/api-plugin-campaigns";

const prefix = "/api/v1";
const prefixed = buildCampaignRoutes().map((e) => ({
    ...e,
    route: { ...e.route, path: `${prefix}${e.route.path}` },
}));
definePluginRoutes(prefixed, { app, registry, pluginName: "campaigns" });

API Reference

  • buildCampaignRoutes(): readonly PluginRouteEntry[] — returns the 12 canonical campaign route entries.

Implementation Notes

The canonical order — list, create, get, update, delete, send, pause, cancel, duplicate, test, stats, events — places the read endpoints before write/action endpoints (so OpenAPI consumers naturally see the read surface first) and groups the lifecycle action routes together. The events route comes last because it depends on the deliveryEventStore slot being populated, which is the only non-trivial dependency in the bundle; co-locating it with stats makes the dependency footprint visible at a glance.