3.0 KiB
repositories/suppression/suppression-internals
Purpose
This module owns the validation and mapping primitives shared by the two
CampaignSuppressionStore implementations — ReasonSchema,
CreateInputSchema, QuerySchema, the requireTenant guard, the
rowToEntry row mapper, and the validateCreate wrapper. Keeping these
helpers in a dedicated sibling module is what allows both the SurrealDB
implementation (./suppression.ts) and the in-memory reference
(./suppression-memory.ts) to stay under the 300-line hard cap without
duplicating their entry-validation logic.
Features
ReasonSchema— Zod enum guard over the five canonicalCampaignSuppressionReasonvalues (unsubscribe,bounce,complaint,manual,compliance).CreateInputSchema/QuerySchema— strict Zod object guards for the two public input shapes.requireTenant(tenantId)— boundary check that throwsCAMPAIGNS_API.TENANT_REQUIREDfor an empty string.validateCreate(input)— parses withCreateInputSchemaand throwsCAMPAIGNS_API.INVALID_INPUTon failure with the underlyingZodErrorattached ascause.rowToEntry(row)— mapsCampaignSuppressionRow↔CampaignSuppressionEntrywithDatenormalisation andnull→undefinedcollapsing.
Usage: Basic
import { validateCreate, requireTenant } from "./suppression-internals.js";
requireTenant("tenant-1");
const data = validateCreate({
tenantId: "tenant-1",
channel: "email",
channelValue: "user@example.com",
reason: "unsubscribe",
});
Usage: Advanced
import { QuerySchema, rowToEntry } from "./suppression-internals.js";
const parsed = QuerySchema.safeParse({
tenantId: "t1",
channel: "sms",
limit: 25,
});
if (!parsed.success) {
// handle ZodError without going through the repository
}
const entry = rowToEntry({
id: "s1",
tenant_id: "t1",
channel: "sms",
channel_value: "+15551234567",
reason: "complaint",
metadata: null,
created_at: "2026-05-24T00:00:00.000Z",
});
API Reference
const ReasonSchema: z.ZodEnumconst CreateInputSchema: z.ZodObjectconst QuerySchema: z.ZodObjectfunction requireTenant(tenantId: string): void— throws on empty.function rowToEntry(row: CampaignSuppressionRow): CampaignSuppressionEntryfunction validateCreate(input: CreateCampaignSuppressionInput): CreateCampaignSuppressionInput
Implementation Notes
CreateInputSchema and QuerySchema use .strict() so unknown keys
fail validation rather than silently flowing through to SurrealDB —
this keeps the repository contract honest against evolving HTTP payloads
and stops typos from becoming silent feature requests.
The schemas live here (not in ../../schemas/) because they are
implementation details of the suppression repository, not part of the
plugin's public option surface. The plugin's options schema in
../../schemas/options.ts is the user-facing configuration contract; the
repository schemas are private guards at a different boundary.