Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
# @suaveplan/sms - Universal SMS core: provider-agnostic send pipeline with E.164 validation, Zod boundaries, template rendering, opt-out registry, token-bucket rate limiter, exponential-backoff retry, message scheduler, bounded delivery-tracker LRU cache, typed EventBus, legacy on/off mirror, in-memory test provider, four OTel instruments, thirteen SMS.* error codes via defineCodes, and back-compat for upstream SmsError + SMS_ERROR_METADATA.
|
||||
|
||||
Universal SMS core: provider-agnostic send pipeline with strict
|
||||
E.164 validation, Zod boundaries, template rendering, opt-out
|
||||
registry, token-bucket rate limiter, exponential-backoff retry with
|
||||
abort propagation, message scheduling, bounded LRU delivery tracker,
|
||||
typed `EventBus` + legacy `on/off/emit` mirror, an in-memory test
|
||||
provider, four OpenTelemetry instruments, thirteen `SMS.*` error
|
||||
codes via `defineCodes`, and full back-compat for the upstream
|
||||
`SmsError` class and `SMS_ERROR_METADATA` table.
|
||||
|
||||
This package is the SMS core. Concrete provider integrations
|
||||
(Twilio, Vonage, AWS SNS, etc.) ship in `@suaveplan/sms-providers`.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [delivery-tracker](./src/delivery-tracker/delivery-tracker.md) — `delivery-tracker` is the bounded LRU cache of `SmsDeliveryReport` records that `SmsService` consults for delivery stat…
|
||||
- [delivery-tracker](./src/delivery-tracker/delivery-tracker.md) — `delivery-tracker` is the bounded LRU cache of `SmsDeliveryReport` records that `SmsService` consults for delivery stat…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — The error-codes module owns the canonical `SMS.*` registry for `@suaveplan/sms`. Every error surfaced by the package —…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — The error-codes module owns the canonical `SMS.*` registry for `@suaveplan/sms`. Every error surfaced by the package —…
|
||||
- [in-memory-provider](./src/in-memory-provider/in-memory-provider.md) — `InMemorySmsProvider` is the production-quality in-process `SmsProvider` implementation that ships with `@suaveplan/sms…
|
||||
- [in-memory-provider](./src/in-memory-provider/in-memory-provider.md) — `InMemorySmsProvider` is the production-quality in-process `SmsProvider` implementation that ships with `@suaveplan/sms…
|
||||
- [legacy-errors](./src/legacy-errors/legacy-errors.md) — `legacy-errors` preserves the upstream `@suaveplan/sms` v1 public surface — the `SmsError` class, the `SmsErrorCode` st…
|
||||
- [legacy-errors](./src/legacy-errors/legacy-errors.md) — `legacy-errors` preserves the upstream `@suaveplan/sms` v1 public surface — the `SmsError` class, the `SmsErrorCode` st…
|
||||
- [legacy-metadata](./src/legacy-metadata/legacy-metadata.md) — `legacy-metadata` preserves the upstream `SMS_ERROR_METADATA` table — the per-code mapping of `httpStatus`, `severity`,…
|
||||
- [legacy-metadata](./src/legacy-metadata/legacy-metadata.md) — `legacy-metadata` preserves the upstream `SMS_ERROR_METADATA` table — the per-code mapping of `httpStatus`, `severity`,…
|
||||
- [opt-out](./src/opt-out/opt-out.md) — `opt-out` is the in-memory opt-out registry that `SmsService` consults before every outbound message. Recipients on the…
|
||||
- [opt-out](./src/opt-out/opt-out.md) — `opt-out` is the in-memory opt-out registry that `SmsService` consults before every outbound message. Recipients on the…
|
||||
- [otel](./src/otel/metrics.md) — `otel/metrics` is the OpenTelemetry instrumentation layer for `@suaveplan/sms`. It owns four meter instruments — three…
|
||||
- [metrics](./src/otel/metrics.md) — `otel/metrics` is the OpenTelemetry instrumentation layer for `@suaveplan/sms`. It owns four meter instruments — three…
|
||||
- [rate-limiter](./src/rate-limiter/rate-limiter.md) — `rate-limiter` is the token-bucket throttle that `SmsService` consults before every outbound send. The limiter is keyed…
|
||||
- [rate-limiter](./src/rate-limiter/rate-limiter.md) — `rate-limiter` is the token-bucket throttle that `SmsService` consults before every outbound send. The limiter is keyed…
|
||||
- [retry](./src/retry/retry.md) — `retry` is the exponential-backoff retry policy used by `SmsService.send` to absorb transient provider failures. The po…
|
||||
- [retry](./src/retry/retry.md) — `retry` is the exponential-backoff retry policy used by `SmsService.send` to absorb transient provider failures. The po…
|
||||
- [routes](./src/routes/problem-json.md) — `routes/problem-json` is the RFC 7807 `application/problem+json` response helper for hosts wiring `@suaveplan/sms` erro…
|
||||
- [problem-json](./src/routes/problem-json.md) — `routes/problem-json` is the RFC 7807 `application/problem+json` response helper for hosts wiring `@suaveplan/sms` erro…
|
||||
- [scheduler](./src/scheduler/scheduler.md) — `scheduler` provides `MessageScheduler` — the minimal timer seam that `SmsService.scheduleAt` uses to fire a delayed de…
|
||||
- [scheduler](./src/scheduler/scheduler.md) — `scheduler` provides `MessageScheduler` — the minimal timer seam that `SmsService.scheduleAt` uses to fire a delayed de…
|
||||
- [schemas](./src/schemas/schemas.md) — `schemas` is the Zod boundary for every public input that `@suaveplan/sms` exposes. The schemas mirror the public type…
|
||||
- [schemas](./src/schemas/schemas.md) — `schemas` is the Zod boundary for every public input that `@suaveplan/sms` exposes. The schemas mirror the public type…
|
||||
- [bus-map](./src/service/bus-map.md) — `bus-map` declares `SmsBusMap` — the single-payload topic contract used by `SmsService.bus` (an `EventBus<SmsBusMap>`).…
|
||||
- [legacy-emitter](./src/service/legacy-emitter.md) — `LegacyEmitter` is the back-compat shim that preserves the upstream `@suaveplan/sms` v1 `on/off/emit` listener API on t…
|
||||
- [sms-service](./src/service/sms-service.md) — `SmsService` is the provider-agnostic orchestrator that ties together every primitive in `@suaveplan/sms`. A single `se…
|
||||
- [templates](./src/templates/templates.md) — `templates` is the in-process template registry and renderer used by `SmsService` to expand `{{variable}}` placeholders…
|
||||
- [templates](./src/templates/templates.md) — `templates` is the in-process template registry and renderer used by `SmsService` to expand `{{variable}}` placeholders…
|
||||
- [validation](./src/validation/phone.md) — `validation/phone` is the strict-E.164 phone number validator used by every public input boundary in `@suaveplan/sms`.…
|
||||
- [phone](./src/validation/phone.md) — `validation/phone` is the strict-E.164 phone number validator used by every public input boundary in `@suaveplan/sms`.…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Highlights
|
||||
|
||||
- **`SmsService`** — orchestrates the full send pipeline: abort
|
||||
check → provider check → E.164 validation → opt-out check →
|
||||
rate-limit → template render → retry → provider send → delivery
|
||||
tracker ingest → OTel + bus emit.
|
||||
- **`InMemorySmsProvider`** — production-quality in-process
|
||||
`SmsProvider` for tests and demos; records every sent message,
|
||||
supports configurable failure predicates and status transitions.
|
||||
- **`TemplateRegistry`** + `renderTemplate` — `{{var}}` substitution
|
||||
with template-level and call-level `defaults` maps.
|
||||
- **`OptOutRegistry`** — channel-scoped opt-out / opt-in with bulk
|
||||
import/export.
|
||||
- **`RateLimiter`** — token bucket per `(channel, recipient)` key
|
||||
with injectable `Clock`.
|
||||
- **`RetryPolicy`** — exponential backoff with full jitter,
|
||||
AbortSignal-aware, injectable `Timers` seam.
|
||||
- **`MessageScheduler`** — `scheduleAt(date, fn)` with cancel
|
||||
handle, injectable timers + clock.
|
||||
- **`DeliveryTracker`** — bounded LRU receipt cache with provider
|
||||
fall-back via `lookupOrFetch`.
|
||||
- **Typed `EventBus`** on `service.bus` plus the upstream
|
||||
`on/off/emit` API mirroring against it.
|
||||
- **Four OTel instruments**: `sms.sent_total`, `sms.failed_total`,
|
||||
`sms.retry_total`, `sms.send_duration_ms`.
|
||||
- **Thirteen `SMS.*` error codes** via `defineCodes("SMS", [...])`
|
||||
plus the upstream `SmsError` legacy class preserved verbatim for
|
||||
back-compat.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/sms
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import {
|
||||
InMemorySmsProvider,
|
||||
SmsService,
|
||||
} from "@suaveplan/sms";
|
||||
|
||||
const provider = new InMemorySmsProvider();
|
||||
const service = new SmsService({ provider });
|
||||
|
||||
service.registerTemplate({
|
||||
id: "welcome",
|
||||
body: "Hi {{name}}!",
|
||||
variables: ["name"],
|
||||
});
|
||||
|
||||
service.bus.on("sms.sent", (report) => {
|
||||
console.log("delivered", report.messageId, "→", report.to);
|
||||
});
|
||||
|
||||
await service.send({
|
||||
to: "+15551234567",
|
||||
body: "ignored when templateId is set",
|
||||
templateId: "welcome",
|
||||
templateVars: { name: "Alice" },
|
||||
});
|
||||
```
|
||||
|
||||
## Modules
|
||||
|
||||
- [`error-codes/error-codes.md`](./src/error-codes/error-codes.md) — `defineCodes("SMS", [...])`, leaf classes
|
||||
- [`legacy-errors/legacy-errors.md`](./src/legacy-errors/legacy-errors.md) — upstream `SmsError` back-compat
|
||||
- [`legacy-metadata/legacy-metadata.md`](./src/legacy-metadata/legacy-metadata.md) — `SMS_ERROR_METADATA` table
|
||||
- [`schemas/schemas.md`](./src/schemas/schemas.md) — Zod boundary parsers
|
||||
- [`validation/phone.md`](./src/validation/phone.md) — strict E.164 validator
|
||||
- [`templates/templates.md`](./src/templates/templates.md) — `TemplateRegistry`, `renderTemplate`
|
||||
- [`opt-out/opt-out.md`](./src/opt-out/opt-out.md) — `OptOutRegistry`
|
||||
- [`rate-limiter/rate-limiter.md`](./src/rate-limiter/rate-limiter.md) — token-bucket limiter
|
||||
- [`retry/retry.md`](./src/retry/retry.md) — `RetryPolicy`
|
||||
- [`scheduler/scheduler.md`](./src/scheduler/scheduler.md) — `MessageScheduler`
|
||||
- [`delivery-tracker/delivery-tracker.md`](./src/delivery-tracker/delivery-tracker.md) — bounded LRU receipt cache
|
||||
- [`in-memory-provider/in-memory-provider.md`](./src/in-memory-provider/in-memory-provider.md) — `InMemorySmsProvider`
|
||||
- [`service/sms-service.md`](./src/service/sms-service.md) — orchestrator
|
||||
- [`service/legacy-emitter.md`](./src/service/legacy-emitter.md) — legacy `on/off/emit` mirror
|
||||
- [`routes/problem-json.md`](./src/routes/problem-json.md) — RFC 7807 Hono helper
|
||||
- [`otel/metrics.md`](./src/otel/metrics.md) — OpenTelemetry instruments
|
||||
|
||||
Reference in New Issue
Block a user