first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
# Keywords — `@suaveplan/sms-providers`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Universal classifier mapping an inbound SMS body to the canonical `OptOutAction` enum used by `@suaveplan/sms`'s `OptOutRegistry`. CTIA's Short Code Monitoring Handbook (and the parallel TCPA / GDPR opt-out frameworks) mandate that outbound SMS programs recognise STOP / STOPALL / UNSUBSCRIBE / CANCEL / END / QUIT as opt-out, START / YES / UNSTOP as opt-in, and HELP / INFO as help-info requests, in every market. Every provider's `parseInbound` runs the raw body through this classifier so the higher-level service layer never has to re-implement the vocabulary.
## Features
- Canonical six-keyword opt-out set: `STOP`, `STOPALL`, `UNSUBSCRIBE`, `CANCEL`, `END`, `QUIT`.
- Canonical three-keyword opt-in set: `START`, `YES`, `UNSTOP`.
- Canonical two-keyword help set: `HELP`, `INFO`.
- Recognition is case-insensitive and ignores surrounding whitespace — `" Stop "`, `"STOP\n"`, `"stop"` all match.
- Multi-word bodies do not match (the canonical CTIA contract is single-keyword); they fall through to `"none"`.
## Usage: Basic
```ts
import { parseOptOutKeyword } from "@suaveplan/sms-providers";
const action = parseOptOutKeyword(" Stop ");
// action === "opt_out"
```
## Usage: Advanced
```ts
import {
parseOptOutKeyword,
type OptOutAction,
} from "@suaveplan/sms-providers";
function handleInbound(from: string, body: string): void {
const action: OptOutAction = parseOptOutKeyword(body);
switch (action) {
case "opt_out":
// optOutRegistry.recordOptOut({ phoneNumber: from, optedOutAt: new Date() });
return;
case "opt_in":
// optOutRegistry.recordOptIn({ phoneNumber: from });
return;
case "help":
// outbound auto-reply with HELP text required by CTIA
return;
case "none":
// forward to the conversational handler
return;
}
}
```
## API Reference
| Symbol | Kind | Notes |
|---|---|---|
| `OptOutAction` | union | `"opt_out" \| "opt_in" \| "help" \| "none"`. |
| `parseOptOutKeyword(body)` | function | Returns the classification. |
## Implementation Notes
The keyword sets are frozen `Set<string>` instances at module load so lookup is O(1). Trim + upper-case the input once and compare against all three sets in sequence — short-circuiting on the first match means an opt-out check beats opt-in beats help (no overlap exists in the canonical vocabulary; sequencing is for stability rather than correctness).