3.3 KiB
3.3 KiB
store
(no submodules)
Purpose
store.ts defines the SegmentStore interface that abstracts segment
persistence behind a six-method contract (create, getById, update,
delete, list, updateCache) and ships InMemorySegmentStore — a
single-process, map-backed implementation suitable for development, tests,
and lightweight production deployments. The in-memory store is built around
injectable Clock and IdGenerator primitives from @suaveplan/types, so
production paths never call Date.now() / new Date() directly or mutate a
module-scope counter.
Features
SegmentStoreinterface — six async methods, all returning the persistedSegment(orundefinedwhen the identifier does not exist).InMemorySegmentStore— single-process map-backed implementation.InMemorySegmentStoreOptions { clock?, idGenerator? }— both injection points are optional with sensible defaults.- Zod boundary on
createandupdate— invalid input raisesAudienceRulesErrorwith codeAUDIENCE_RULES.INVALID_INPUT(never a rawZodError). - Multi-tenant isolation on
list(tenantId)— segments owned by other tenants are invisible. updateCache(id, contactIds)updatescachedContactIds,cachedCount,lastRefreshedAt, andupdatedAtatomically.
Usage: Basic Example
import { InMemorySegmentStore } from "@suaveplan/audience-rules";
const store = new InMemorySegmentStore();
const segment = await store.create({
tenantId: "tenant-1",
name: "Active VIPs",
rules: [{ field: "tags", operator: "contains", value: "vip" }],
refreshMode: "manual",
});
Usage: Advanced Example
import { InMemorySegmentStore } from "@suaveplan/audience-rules";
// Deterministic store for tests: pinned clock + monotonic ID generator
let n = 0;
const store = new InMemorySegmentStore({
clock: () => 1_700_000_000_000,
idGenerator: () => {
n += 1;
return `test_seg_${n}`;
},
});
const a = await store.create({
tenantId: "t1",
name: "A",
rules: [],
refreshMode: "manual",
});
// a.id === "test_seg_1"; a.createdAt.getTime() === 1_700_000_000_000
API Reference
interface SegmentStore— see Features.interface InMemorySegmentStoreOptions—clock?: Clock,idGenerator?: IdGenerator(both from@suaveplan/types).class InMemorySegmentStore implements SegmentStore— constructor acceptsInMemorySegmentStoreOptions. ThrowsAudienceRulesErrorwithAUDIENCE_RULES.INVALID_INPUTon Zod failure increate/update, and onlistwith an emptytenantId.
Implementation Notes
- The default
IdGeneratoris a per-instance closure, so two separate stores in the same process produce independent ID sequences. This matches the@suaveplan/contactsInMemoryContactStoreconvention. createandupdatevalidate input withparseOrThrowbefore mutating the internal map — failure leaves the store untouched.listtakes anO(n)scan; the package is a development-tier store and multi-tenant filtering happens in-memory. Production stores backed by a database can index ontenantIddirectly.- Every mutation updates
updatedAtvia the injected clock, so OTel histograms and snapshot diffs in consumers stay deterministic underFakeClock.