Files
2026-06-09 21:06:27 +01:00

5.0 KiB

@suaveplan/campaigns - Universal campaign orchestration — engine, state machine, batch planner, workflow, and pluggable store with injectable Clock/IdGenerator/TimersLike/LoggerLike, CAMPAIGNS_CODES error registry, and OTel self-telemetry

Universal campaign orchestration.

Documentation tree

  • batch-planner — Deterministic batch-planning engine for campaign sends. Splits a contact list into sized batches with throttle-aware sc…
    • batch-planner — Deterministic batch-planning engine for campaign sends. Splits a contact list into sized batches with throttle-aware sc…
  • engine — Top-level orchestrator for campaign CRUD and lifecycle. CampaignEngine accepts an injectable CampaignStore and expo…
    • engine — Top-level orchestrator for campaign CRUD and lifecycle. CampaignEngine accepts an injectable CampaignStore and expo…
  • error-codes — Defines the stable, machine-readable error namespace for @suaveplan/campaigns. Every failure path in the package — fr…
    • error-codes — Defines the stable, machine-readable error namespace for @suaveplan/campaigns. Every failure path in the package — fr…
  • state-machine — Strictly typed lifecycle state machine for campaigns. Owns the set of nine legal transitions between the seven `Campaig…
    • state-machine — Strictly typed lifecycle state machine for campaigns. Owns the set of nine legal transitions between the seven `Campaig…
  • store — Defines the CampaignStore persistence contract and ships an InMemoryCampaignStore reference implementation. Every s…
    • store — Defines the CampaignStore persistence contract and ships an InMemoryCampaignStore reference implementation. Every s…
  • telemetry — OTel self-telemetry for @suaveplan/campaigns. Exposes a small set of counters and histograms that are emitted from ev…
    • telemetry — OTel self-telemetry for @suaveplan/campaigns. Exposes a small set of counters and histograms that are emitted from ev…
  • workflow — Composable multi-step send pipeline for campaigns. CampaignWorkflow.buildSendPipeline returns a canonical six-step pi…
    • workflow — Composable multi-step send pipeline for campaigns. CampaignWorkflow.buildSendPipeline returns a canonical six-step pi…

Modules

  • engine/ — CampaignEngine: CRUD + lifecycle methods over an injectable CampaignStore.
  • state-machine/ — CampaignStateMachine: nine canonical transitions, typed event union.
  • batch-planner/ — BatchPlanner: throttle-aware splitter + duration estimator.
  • workflow/ — CampaignWorkflow: composable 6-step send pipeline + sequential runner.
  • store/ — CampaignStore interface + InMemoryCampaignStore reference.
  • error-codes/ — CAMPAIGNS_CODES + CampaignsError.
  • telemetry/ — OTel meter, counters, histograms.
  • types/ — shared types.

Install

bun add @suaveplan/campaigns

Quick start

import { CampaignEngine, InMemoryCampaignStore } from "@suaveplan/campaigns";

const engine = new CampaignEngine(new InMemoryCampaignStore());

const campaign = await engine.create({
    tenantId: "tenant-1",
    name: "Spring Sale Announcement",
    type: "broadcast",
    channel: "email",
    audienceConfig: {
        groupIds: ["all-subscribers"],
        excludeGroupIds: ["unsubscribed"],
    },
    templateId: "spring-sale-v1",
});

await engine.schedule(campaign.id, {
    type: "scheduled",
    sendAt: new Date("2026-05-01T09:00:00Z"),
    timezone: "America/New_York",
});

await engine.send(campaign.id);

Throttle-aware batch planning

import { BatchPlanner, type ThrottleConfig } from "@suaveplan/campaigns";

const planner = new BatchPlanner();
const throttle: ThrottleConfig = { messagesPerSecond: 50 };
const batches = planner.planBatches(contactIds, { batchSize: 200 }, throttle);
const etaMs = planner.calculateTotalDuration(contactIds.length, { batchSize: 200 }, throttle);

Architecture

CampaignEngine ──┬── CampaignStateMachine  (validation)
                 ├── CampaignStore         (persistence)
                 ├── BatchPlanner          (throttle-aware planning)
                 └── CampaignWorkflow      (6-step pipeline)

All callers see CampaignsError with codes from CAMPAIGNS_CODES. All operations record OTel counters/histograms via the telemetry/ module.

License

MIT.