121 lines
9.7 KiB
Markdown
121 lines
9.7 KiB
Markdown
# @suaveplan/contacts - Universal contact and group management: hierarchical n-level groups (adjacency + materialized path), channel-agnostic contacts with dedup, many-to-many memberships with ancestor count propagation, audience resolution with descendant walk + dedup + filters, contact merger, CSV/JSON import-export, injectable Clock + IdGenerator, Zod input boundaries, six OTel counters and three histograms, and typed ContactsError hierarchy with stable CONTACTS.* code registry.
|
|
|
|
Universal contact and group management with hierarchical nesting, audience resolution, contact merger, and CSV/JSON import-export. Multi-tenant, channel-agnostic, deterministic (injectable `Clock` + `IdGenerator`), Zod-validated at every public boundary, OTel-instrumented via `@suaveplan/opentelemetry`, and ships a typed `ContactsError` hierarchy with a stable `CONTACTS.*` code registry.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## Documentation tree
|
|
|
|
- [audience-resolver](./src/core/audience-resolver/audience-resolver.md) — `AudienceResolver` flattens a set of groups into a deduplicated, filtered contact list — the typical "send this campaig…
|
|
- [audience-resolver](./src/core/audience-resolver/audience-resolver.md) — `AudienceResolver` flattens a set of groups into a deduplicated, filtered contact list — the typical "send this campaig…
|
|
- [contact-manager](./src/core/contact-manager/contact-manager.md) — `ContactManager` is the public CRUD surface for contacts. It validates inputs against the corresponding Zod schemas (`c…
|
|
- [contact-manager](./src/core/contact-manager/contact-manager.md) — `ContactManager` is the public CRUD surface for contacts. It validates inputs against the corresponding Zod schemas (`c…
|
|
- [contact-merger](./src/core/contact-merger/contact-merger.md) — `ContactMerger` consolidates duplicate contacts into a single primary record. It merges channels (dedup-by-`type:value`…
|
|
- [contact-merger](./src/core/contact-merger/contact-merger.md) — `ContactMerger` consolidates duplicate contacts into a single primary record. It merges channels (dedup-by-`type:value`…
|
|
- [group-manager](./src/core/group-manager/group-manager.md) — `GroupManager` is the public surface for hierarchical groups. It manages n-level nesting via a hybrid adjacency-list +…
|
|
- [group-manager](./src/core/group-manager/group-manager.md) — `GroupManager` is the public surface for hierarchical groups. It manages n-level nesting via a hybrid adjacency-list +…
|
|
- [membership-manager](./src/core/membership-manager/membership-manager.md) — `MembershipManager` orchestrates many-to-many contact-group memberships. It owns the integrity guarantee that `Group.co…
|
|
- [membership-manager](./src/core/membership-manager/membership-manager.md) — `MembershipManager` orchestrates many-to-many contact-group memberships. It owns the integrity guarantee that `Group.co…
|
|
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry and typed `ContactsError` class for `@suaveplan/contacts`. Every failure path th…
|
|
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable error-code registry and typed `ContactsError` class for `@suaveplan/contacts`. Every failure path th…
|
|
- [contact-exporter](./src/import-export/contact-exporter/contact-exporter.md) — `ContactExporter` serializes contacts to JSON or CSV with optional field inclusion flags. CSV output follows RFC 4180 q…
|
|
- [contact-exporter](./src/import-export/contact-exporter/contact-exporter.md) — `ContactExporter` serializes contacts to JSON or CSV with optional field inclusion flags. CSV output follows RFC 4180 q…
|
|
- [contact-importer](./src/import-export/contact-importer/contact-importer.md) — `ContactImporter` ingests contacts from already-parsed record arrays or raw CSV content. It applies caller-supplied fie…
|
|
- [contact-importer](./src/import-export/contact-importer/contact-importer.md) — `ContactImporter` ingests contacts from already-parsed record arrays or raw CSV content. It applies caller-supplied fie…
|
|
- [otel](./src/otel/instruments.md) — Exposes the bundle of OpenTelemetry metric instruments emitted by `@suaveplan/contacts`. The bundle binds lazily agains…
|
|
- [instruments](./src/otel/instruments.md) — Exposes the bundle of OpenTelemetry metric instruments emitted by `@suaveplan/contacts`. The bundle binds lazily agains…
|
|
- [schemas](./src/schemas/schemas.md) — Zod schemas for every public input boundary of `@suaveplan/contacts` plus the `parseOrThrow` helper that converts Zod v…
|
|
- [schemas](./src/schemas/schemas.md) — Zod schemas for every public input boundary of `@suaveplan/contacts` plus the `parseOrThrow` helper that converts Zod v…
|
|
- [contact-store](./src/stores/contact-store/contact-store.md) — Defines the `ContactStore` storage interface that `ContactManager` and `AudienceResolver` consume, plus the `InMemoryCo…
|
|
- [contact-store](./src/stores/contact-store/contact-store.md) — Defines the `ContactStore` storage interface that `ContactManager` and `AudienceResolver` consume, plus the `InMemoryCo…
|
|
- [group-store](./src/stores/group-store/group-store.md) — Defines the `GroupStore` storage interface that `GroupManager` and `AudienceResolver` consume, plus the `InMemoryGroupS…
|
|
- [group-store](./src/stores/group-store/group-store.md) — Defines the `GroupStore` storage interface that `GroupManager` and `AudienceResolver` consume, plus the `InMemoryGroupS…
|
|
- [membership-store](./src/stores/membership-store/membership-store.md) — Defines the `MembershipStore` storage interface that `MembershipManager`, `ContactMerger`, and `AudienceResolver` consu…
|
|
- [membership-store](./src/stores/membership-store/membership-store.md) — Defines the `MembershipStore` storage interface that `MembershipManager`, `ContactMerger`, and `AudienceResolver` consu…
|
|
- [tree](./src/tree/tree-utils.md) — Pure tree utilities for building, flattening, traversing, and inspecting `GroupTreeNode<TMeta>` hierarchies. None of th…
|
|
- [tree-utils](./src/tree/tree-utils.md) — Pure tree utilities for building, flattening, traversing, and inspecting `GroupTreeNode<TMeta>` hierarchies. None of th…
|
|
<!-- end:auto-docs -->
|
|
|
|
## Install
|
|
|
|
```bash
|
|
bun add @suaveplan/contacts
|
|
```
|
|
|
|
## Quick start
|
|
|
|
```ts
|
|
import {
|
|
AudienceResolver,
|
|
ContactManager,
|
|
GroupManager,
|
|
InMemoryContactStore,
|
|
InMemoryGroupStore,
|
|
InMemoryMembershipStore,
|
|
MembershipManager,
|
|
} from "@suaveplan/contacts";
|
|
|
|
const contactStore = new InMemoryContactStore();
|
|
const groupStore = new InMemoryGroupStore();
|
|
const membershipStore = new InMemoryMembershipStore();
|
|
|
|
const contacts = new ContactManager({ store: contactStore });
|
|
const groups = new GroupManager({ store: groupStore });
|
|
const memberships = new MembershipManager({
|
|
contactStore,
|
|
groupStore,
|
|
membershipStore,
|
|
});
|
|
const resolver = new AudienceResolver({
|
|
contactStore,
|
|
groupStore,
|
|
membershipStore,
|
|
});
|
|
|
|
const vip = await groups.create({ tenantId: "acme", name: "VIP Customers" });
|
|
const alice = await contacts.create({
|
|
tenantId: "acme",
|
|
displayName: "Alice",
|
|
channels: [
|
|
{ type: "email", value: "alice@example.com", primary: true, verified: true },
|
|
],
|
|
});
|
|
await memberships.addContactToGroup(vip.id, alice.id);
|
|
const audience = await resolver.resolve({ groupIds: [vip.id] });
|
|
console.log(audience.totalCount); // 1
|
|
```
|
|
|
|
## Architecture
|
|
|
|
```text
|
|
ContactStore GroupStore MembershipStore <- pluggable storage
|
|
│ │ │
|
|
└─── ContactManager / GroupManager / MembershipManager <- CRUD + validation + OTel
|
|
│
|
|
┌─────────────┴─────────────┐
|
|
│ │
|
|
AudienceResolver ContactMerger / ContactImporter / ContactExporter
|
|
(group walk + dedup) (data ops + import/export pipelines)
|
|
```
|
|
|
|
Every public mutating method validates via Zod, raises a typed `ContactsError` (never a bare `Error`), and emits on at least one OTel instrument. All temporal and id-generating paths accept injectable `Clock` and `IdGenerator` from `@suaveplan/types`.
|
|
|
|
## Modules
|
|
|
|
| Module | Documentation |
|
|
|---|---|
|
|
| Error codes (`CONTACTS_CODES`, `ContactsError`) | [src/error-codes/error-codes.md](src/error-codes/error-codes.md) |
|
|
| OTel instruments (`getContactsInstruments`) | [src/otel/instruments.md](src/otel/instruments.md) |
|
|
| Zod schemas (`createContactInputSchema`, …, `parseOrThrow`) | [src/schemas/schemas.md](src/schemas/schemas.md) |
|
|
| Contact store (`InMemoryContactStore`) | [src/stores/contact-store/contact-store.md](src/stores/contact-store/contact-store.md) |
|
|
| Group store (`InMemoryGroupStore`) | [src/stores/group-store/group-store.md](src/stores/group-store/group-store.md) |
|
|
| Membership store (`InMemoryMembershipStore`) | [src/stores/membership-store/membership-store.md](src/stores/membership-store/membership-store.md) |
|
|
| `ContactManager` | [src/core/contact-manager/contact-manager.md](src/core/contact-manager/contact-manager.md) |
|
|
| `GroupManager` | [src/core/group-manager/group-manager.md](src/core/group-manager/group-manager.md) |
|
|
| `MembershipManager` | [src/core/membership-manager/membership-manager.md](src/core/membership-manager/membership-manager.md) |
|
|
| `ContactMerger` | [src/core/contact-merger/contact-merger.md](src/core/contact-merger/contact-merger.md) |
|
|
| `AudienceResolver` | [src/core/audience-resolver/audience-resolver.md](src/core/audience-resolver/audience-resolver.md) |
|
|
| `ContactExporter` | [src/import-export/contact-exporter/contact-exporter.md](src/import-export/contact-exporter/contact-exporter.md) |
|
|
| `ContactImporter` | [src/import-export/contact-importer/contact-importer.md](src/import-export/contact-importer/contact-importer.md) |
|
|
| Tree utilities (`buildGroupTree`, …) | [src/tree/tree-utils.md](src/tree/tree-utils.md) |
|
|
|