@dojocoding/whatsapp-sdk 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +402 -0
- package/LICENSE +21 -0
- package/README.md +286 -0
- package/dist/adapters/express/index.cjs +114 -0
- package/dist/adapters/express/index.d.cts +42 -0
- package/dist/adapters/express/index.d.ts +42 -0
- package/dist/adapters/express/index.js +108 -0
- package/dist/adapters/hono/index.cjs +52 -0
- package/dist/adapters/hono/index.d.cts +38 -0
- package/dist/adapters/hono/index.d.ts +38 -0
- package/dist/adapters/hono/index.js +50 -0
- package/dist/adapters/web/index.cjs +46 -0
- package/dist/adapters/web/index.d.cts +40 -0
- package/dist/adapters/web/index.d.ts +40 -0
- package/dist/adapters/web/index.js +44 -0
- package/dist/index-CDfzGvQJ.d.cts +42 -0
- package/dist/index-CDfzGvQJ.d.ts +42 -0
- package/dist/index.cjs +2242 -0
- package/dist/index.d.cts +1262 -0
- package/dist/index.d.ts +1262 -0
- package/dist/index.js +2183 -0
- package/dist/receiver-C_yfwg6g.d.ts +167 -0
- package/dist/receiver-DWJm571Z.d.cts +167 -0
- package/dist/storage/postgres.cjs +66 -0
- package/dist/storage/postgres.d.cts +38 -0
- package/dist/storage/postgres.d.ts +38 -0
- package/dist/storage/postgres.js +63 -0
- package/dist/storage/redis.cjs +32 -0
- package/dist/storage/redis.d.cts +38 -0
- package/dist/storage/redis.d.ts +38 -0
- package/dist/storage/redis.js +30 -0
- package/package.json +181 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@dojocoding/whatsapp-sdk` (formerly
|
|
4
|
+
`@dojocoding/whatsapp`) are documented in this file.
|
|
5
|
+
|
|
6
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
7
|
+
and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
|
+
Pre-1.0 minor versions may contain breaking changes — see
|
|
9
|
+
[`CONTRIBUTING.md`](../../CONTRIBUTING.md) § Releases.
|
|
10
|
+
|
|
11
|
+
## [0.8.0] — 2026-05-10
|
|
12
|
+
|
|
13
|
+
### Renamed: `@dojocoding/whatsapp` → `@dojocoding/whatsapp-sdk`
|
|
14
|
+
|
|
15
|
+
This release renames the package to match the new two-package
|
|
16
|
+
architecture (`@dojocoding/whatsapp-sdk` + the new sibling
|
|
17
|
+
[`@dojocoding/whatsapp-mcp`](../whatsapp-mcp/CHANGELOG.md), which
|
|
18
|
+
exposes the SDK's outbound surface as a Model Context Protocol
|
|
19
|
+
server for LLM agents).
|
|
20
|
+
|
|
21
|
+
**Zero runtime change.** The 572-test suite passes verbatim
|
|
22
|
+
against `0.7.4`'s public surface. No symbol renames, no type
|
|
23
|
+
changes, no behaviour change.
|
|
24
|
+
|
|
25
|
+
**Migration — one line of `package.json`:**
|
|
26
|
+
|
|
27
|
+
```diff
|
|
28
|
+
"dependencies": {
|
|
29
|
+
- "@dojocoding/whatsapp": "^0.7.0"
|
|
30
|
+
+ "@dojocoding/whatsapp-sdk": "^0.8.0"
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
…plus a project-wide find-and-replace on import statements:
|
|
35
|
+
|
|
36
|
+
```diff
|
|
37
|
+
- import { WhatsAppClient } from "@dojocoding/whatsapp";
|
|
38
|
+
+ import { WhatsAppClient } from "@dojocoding/whatsapp-sdk";
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
…and equivalent updates for subpath imports (`/express`,
|
|
42
|
+
`/web`, `/hono`, `/storage/redis`, `/storage/postgres`).
|
|
43
|
+
|
|
44
|
+
The old `@dojocoding/whatsapp` package is `npm deprecate`-d with
|
|
45
|
+
a redirect message; the 13 published versions (0.1.0–0.7.4)
|
|
46
|
+
stay installable for pinned consumers.
|
|
47
|
+
|
|
48
|
+
### Repo structure (no consumer-visible change)
|
|
49
|
+
|
|
50
|
+
- The repo is now a `pnpm` workspace. SDK code lives under
|
|
51
|
+
`packages/whatsapp-sdk/`; the new MCP server lives under
|
|
52
|
+
`packages/whatsapp-mcp/`.
|
|
53
|
+
- Tag prefixes disambiguate release targets in CI:
|
|
54
|
+
`sdk-v0.x.x` for this package, `mcp-v0.x.x` for the MCP
|
|
55
|
+
sibling. The legacy `v0.x.x` prefix retires with this
|
|
56
|
+
release.
|
|
57
|
+
- Docs reorganise under repo-root `docs/` with `sdk/`, `mcp/`,
|
|
58
|
+
and `cookbook/{sdk,mcp,hybrid}/` subtrees. The
|
|
59
|
+
[`hybrid/`](../../docs/cookbook/hybrid/) cookbook (lands in
|
|
60
|
+
Phase C3) is the showcase for using both packages together.
|
|
61
|
+
|
|
62
|
+
See OpenSpec change
|
|
63
|
+
[`2026-05-10-add-mcp-server`](../../openspec/changes/2026-05-10-add-mcp-server/)
|
|
64
|
+
for the full rationale.
|
|
65
|
+
|
|
66
|
+
## [0.7.4] — 2026-05-10
|
|
67
|
+
|
|
68
|
+
### Tooling (no SDK behaviour change)
|
|
69
|
+
|
|
70
|
+
Phase 4 of the Track F + test-coverage audit hardening pass. The
|
|
71
|
+
published artefact is functionally identical to 0.7.3; only the
|
|
72
|
+
build / CI tooling and CHANGELOG differ.
|
|
73
|
+
|
|
74
|
+
- **Bundle-size budgets (F6).** `size-limit` is wired into CI with
|
|
75
|
+
per-entry-point budgets defined in `package.json`:
|
|
76
|
+
|
|
77
|
+
| Entry point | Budget |
|
|
78
|
+
| --------------------------------------- | ------ |
|
|
79
|
+
| `@dojocoding/whatsapp` (root, ESM/CJS) | 100 KB |
|
|
80
|
+
| `@dojocoding/whatsapp/express` | 6 KB |
|
|
81
|
+
| `@dojocoding/whatsapp/web` | 3 KB |
|
|
82
|
+
| `@dojocoding/whatsapp/hono` | 3 KB |
|
|
83
|
+
| `@dojocoding/whatsapp/storage/redis` | 2 KB |
|
|
84
|
+
| `@dojocoding/whatsapp/storage/postgres` | 4 KB |
|
|
85
|
+
|
|
86
|
+
Limits are roughly 1.5× the current measured sizes, so a single PR
|
|
87
|
+
cannot double a bundle by accident (e.g. an accidental
|
|
88
|
+
`import "lodash"`). Run `pnpm size` locally to see the same
|
|
89
|
+
budget report CI runs.
|
|
90
|
+
|
|
91
|
+
## [0.7.3] — 2026-05-10
|
|
92
|
+
|
|
93
|
+
### Tests (no SDK behaviour change)
|
|
94
|
+
|
|
95
|
+
Phase 3 of the Track F + test-coverage audit hardening pass.
|
|
96
|
+
572 tests pass (was 524 — +48 across the seven audit items below).
|
|
97
|
+
The published artefact is functionally identical to 0.7.2; only the
|
|
98
|
+
test suite and CHANGELOG differ.
|
|
99
|
+
|
|
100
|
+
- **Property-based assertions** with `fast-check` for three
|
|
101
|
+
high-leverage modules:
|
|
102
|
+
- `webhooks/signature.ts` — HMAC verifier invariants across
|
|
103
|
+
random body / secret / header inputs.
|
|
104
|
+
- `webhooks/dedupe.ts` — dedupe-key identity + Unicode handling.
|
|
105
|
+
- `client/retry.ts` — `fullJitterDelay` math bounded by
|
|
106
|
+
`[floorMs, min(maxDelayMs, expCap)]` for any RNG output.
|
|
107
|
+
- **Concurrent dedupe race test** — 100 parallel `handlePayload`
|
|
108
|
+
calls with the same wamid invoke the handler exactly once;
|
|
109
|
+
validates the single-flight semantics under Meta's aggressive
|
|
110
|
+
retry pattern.
|
|
111
|
+
- **Storage failure propagation** — explicit assertions that
|
|
112
|
+
`WebhookDeduper`, `WindowTracker`, and `WebhookReceiver`
|
|
113
|
+
surface storage errors rather than swallowing them silently.
|
|
114
|
+
- **`sendReply` template-path coverage** — the window-exempt path
|
|
115
|
+
for template + reaction payloads through `sendReply`, plus the
|
|
116
|
+
window-gated path for free-form payloads, all asserted against
|
|
117
|
+
captured wire bodies.
|
|
118
|
+
- **Local pack-contents smoke** — `test/contract/pack-contents.test.ts`
|
|
119
|
+
mirrors the CI "Verify pack contents (dry-run)" assertion so
|
|
120
|
+
`pnpm test` catches a `files` allowlist regression before CI.
|
|
121
|
+
|
|
122
|
+
## [0.7.2] — 2026-05-11
|
|
123
|
+
|
|
124
|
+
### Changed (CI / repo hygiene only — no SDK behaviour change)
|
|
125
|
+
|
|
126
|
+
- Dependabot now opens grouped weekly PRs for npm + GitHub Actions
|
|
127
|
+
updates. `@types/*`, lint/format tooling, vitest/msw, and the
|
|
128
|
+
`@opentelemetry/*` family ship as batched sweeps. Major-version
|
|
129
|
+
bumps to peer-dep ecosystems (express, hono, ioredis, pg) are
|
|
130
|
+
ignored — those need an explicit decision about widening the
|
|
131
|
+
supported range.
|
|
132
|
+
- CodeQL static-analysis workflow added (`.github/workflows/codeql.yml`)
|
|
133
|
+
with the `security-extended` query suite. Runs on push, PR, and
|
|
134
|
+
a weekly Monday schedule. Findings appear in the Security tab.
|
|
135
|
+
- `pnpm audit --prod --audit-level=moderate` runs on every CI build
|
|
136
|
+
(continue-on-error initially, so advisories surface in the run
|
|
137
|
+
log without blocking PRs).
|
|
138
|
+
- PR template + three issue templates (bug, feature, compliance
|
|
139
|
+
drift) shipped. `.github/CODEOWNERS` pins compliance-relevant
|
|
140
|
+
files and the release pipeline.
|
|
141
|
+
|
|
142
|
+
No npm-published artefact changes from 0.7.1.
|
|
143
|
+
|
|
144
|
+
## [0.7.1] — 2026-05-11
|
|
145
|
+
|
|
146
|
+
### Added
|
|
147
|
+
|
|
148
|
+
- **`verifySignatureOrThrow(input)`** — throwing variant of
|
|
149
|
+
`verifySignature` exported from the root entry. Resolves silently
|
|
150
|
+
on a valid signature; throws `WebhookSignatureError` on bad HMAC,
|
|
151
|
+
missing header, malformed hex, or wrong byte length. Use this when
|
|
152
|
+
wiring your own HTTP layer (not the SDK's Express / web / Hono
|
|
153
|
+
adapters) and you want a typed error rather than a boolean.
|
|
154
|
+
|
|
155
|
+
### Changed
|
|
156
|
+
|
|
157
|
+
- **CI: bumped GitHub Actions to Node 24-compatible versions** —
|
|
158
|
+
`actions/checkout@v5`, `actions/setup-node@v6`,
|
|
159
|
+
`pnpm/action-setup@v6`, `actions/upload-artifact@v7`,
|
|
160
|
+
`softprops/action-gh-release@v3`. Removes the deprecation banner
|
|
161
|
+
on every CI run; ready for Meta's 2026-06-02 Node 20 default
|
|
162
|
+
removal.
|
|
163
|
+
|
|
164
|
+
### Tests
|
|
165
|
+
|
|
166
|
+
- Added `test/contract/public-surface.test.ts` — a drift detector
|
|
167
|
+
asserting every documented value/class/factory across the root
|
|
168
|
+
entry and all five subpaths (`/express`, `/web`, `/hono`,
|
|
169
|
+
`/storage/redis`, `/storage/postgres`) is reachable at runtime.
|
|
170
|
+
If a sub-module export is added without being plumbed through, or
|
|
171
|
+
a documented export is accidentally renamed/removed, this test
|
|
172
|
+
fails before consumers do.
|
|
173
|
+
- Added negative-path coverage for `WebhookSignatureError` (5 new
|
|
174
|
+
tests via `verifySignatureOrThrow`) and `MockModeError` (4 new
|
|
175
|
+
contract tests pinning the public shape).
|
|
176
|
+
- Re-shimmed `test/integration/express/middleware.test.ts` to use a
|
|
177
|
+
Promise-resolved-by-handler pattern instead of 5 ms `setTimeout`
|
|
178
|
+
waits and wall-clock ack-timing windows — mirrors the
|
|
179
|
+
determinism fix already applied to the web adapter test in 0.2.0.
|
|
180
|
+
|
|
181
|
+
524 tests pass (was 447).
|
|
182
|
+
|
|
183
|
+
## [0.7.0] — 2026-05-11
|
|
184
|
+
|
|
185
|
+
### Added
|
|
186
|
+
|
|
187
|
+
- **Authentication template (OTP) builder.** `buildAuthTemplate({
|
|
188
|
+
to, name, language, otp, otpButtonIndex? })` and the matching
|
|
189
|
+
`client.sendAuthTemplate(...)` produce the documented copy-code /
|
|
190
|
+
one-tap / zero-tap wire payload with the OTP code duplicated into
|
|
191
|
+
both the body and URL-button parameters (the canonical footgun
|
|
192
|
+
this builder exists to remove). OTP length validated against
|
|
193
|
+
Meta's 15-char ceiling.
|
|
194
|
+
- **Voice-note builder.** `buildVoice({ to, id|link })` and
|
|
195
|
+
`client.sendVoice(...)` produce audio messages with `voice: true`,
|
|
196
|
+
triggering transcription support, auto-download, and the "played"
|
|
197
|
+
delivery status.
|
|
198
|
+
- **Carousel-template builder.** `buildCarouselTemplate({ to, name,
|
|
199
|
+
language, bodyParameters?, cards })` and
|
|
200
|
+
`client.sendCarouselTemplate(...)` produce media-card carousel
|
|
201
|
+
template sends with 1–10 cards. Each card's `card_index` is
|
|
202
|
+
computed from iteration order; consumers can't misorder it.
|
|
203
|
+
- **Limited-time-offer template support.** Three new
|
|
204
|
+
`TemplateParameter` union variants:
|
|
205
|
+
`TemplateParameterLimitedTimeOffer`,
|
|
206
|
+
`TemplateParameterCouponCode`, and `TemplateParameterPayload`.
|
|
207
|
+
`TemplateComponent.type` widens to accept `"carousel"` and
|
|
208
|
+
`"limited_time_offer"`. Use via the existing `buildTemplate(...)`
|
|
209
|
+
/
|
|
210
|
+
`client.sendTemplate(...)`.
|
|
211
|
+
- New `CarouselCardComponent` exported type. `AudioMessage.audio`
|
|
212
|
+
gains an optional `voice?: boolean` field.
|
|
213
|
+
|
|
214
|
+
Every wire shape is grounded in a Meta doc URL referenced in
|
|
215
|
+
source-file JSDoc and pinned via byte-for-byte snapshot tests:
|
|
216
|
+
|
|
217
|
+
- https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/authentication-templates/copy-code-button-authentication-templates/
|
|
218
|
+
- https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/audio-messages
|
|
219
|
+
- https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/marketing-templates/media-card-carousel-templates/
|
|
220
|
+
- https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/marketing-templates/limited-time-offer-templates/
|
|
221
|
+
|
|
222
|
+
## [0.6.0] — 2026-05-11
|
|
223
|
+
|
|
224
|
+
### Added
|
|
225
|
+
|
|
226
|
+
- **Redis and Postgres `Storage` adapters at subpath exports.**
|
|
227
|
+
- `@dojocoding/whatsapp/storage/redis` exports
|
|
228
|
+
`createRedisStorage(client, options?)`. Takes an
|
|
229
|
+
`ioredis`-compatible client; uses native `SET PX` / `SET NX`
|
|
230
|
+
for TTL and atomicity. `ioredis` is an optional peer
|
|
231
|
+
dependency on `^5.0.0`.
|
|
232
|
+
- `@dojocoding/whatsapp/storage/postgres` exports
|
|
233
|
+
`createPostgresStorage(client, options?)` and
|
|
234
|
+
`POSTGRES_STORAGE_SCHEMA: string`. Takes a `pg`-compatible
|
|
235
|
+
client; runs four SQL statements (`SELECT`, two `INSERT ... ON
|
|
236
|
+
CONFLICT`, `DELETE`). `pg` is an optional peer dependency on
|
|
237
|
+
`^8.0.0`.
|
|
238
|
+
- Both adapters use minimal structural interfaces (`RedisLike`,
|
|
239
|
+
`PgLike`) so the SDK doesn't import either library at runtime;
|
|
240
|
+
consumers pass any compatible client (including test fakes).
|
|
241
|
+
- See [`docs/storage.md`](./docs/storage.md).
|
|
242
|
+
- Shared `Storage` contract test:
|
|
243
|
+
`test/unit/storage/contract.ts` exports a parametrised suite
|
|
244
|
+
that every implementation (`InMemoryStorage`,
|
|
245
|
+
`createRedisStorage`, `createPostgresStorage`) runs against —
|
|
246
|
+
drift between implementations is impossible-to-not-notice.
|
|
247
|
+
|
|
248
|
+
## [0.5.0] — 2026-05-11
|
|
249
|
+
|
|
250
|
+
### Added
|
|
251
|
+
|
|
252
|
+
- **`withRateLimit(client, options?)` decorator + `TokenBucket` /
|
|
253
|
+
`BucketMap` primitives.** Wraps any `WhatsAppLikeClient` and
|
|
254
|
+
throttles `send*` calls at a per-pair bucket (default 1 msg per
|
|
255
|
+
6 s) and a per-WABA bucket (default 80 MPS) before delegating to
|
|
256
|
+
the wrapped client. Caller surface unchanged — the queue is
|
|
257
|
+
invisible. Lower-level `TokenBucket` and `BucketMap` are exported
|
|
258
|
+
for non-WhatsApp use cases. See [`docs/queue.md`](./docs/queue.md).
|
|
259
|
+
- New OTel span `whatsapp.queue.acquire` exposes queue latency
|
|
260
|
+
separately from network latency, with PII-redacted recipient /
|
|
261
|
+
WABA attributes.
|
|
262
|
+
|
|
263
|
+
## [0.4.0] — 2026-05-10
|
|
264
|
+
|
|
265
|
+
### Added
|
|
266
|
+
|
|
267
|
+
- **`TokenProvider` callback for `WhatsAppClient`.**
|
|
268
|
+
`WhatsAppClientOptions.token` now accepts
|
|
269
|
+
`string | (() => string | Promise<string>)`. The SDK resolves the
|
|
270
|
+
callback once per outer request — all retries within a single
|
|
271
|
+
request reuse the same resolved value. Closes the race window in
|
|
272
|
+
the previous "swap the client instance per tenant on
|
|
273
|
+
`AuthenticationError`" rotation pattern. The `TokenProvider` type
|
|
274
|
+
is exported from the root entry. See
|
|
275
|
+
[`docs/client.md`](./docs/client.md) and
|
|
276
|
+
[`docs/patterns.md`](./docs/patterns.md) § 5.
|
|
277
|
+
- Provider errors (throw, empty string, non-string return) surface
|
|
278
|
+
as `AuthenticationError` before the HTTP request is made, with
|
|
279
|
+
the underlying error attached as `cause`.
|
|
280
|
+
|
|
281
|
+
### Changed
|
|
282
|
+
|
|
283
|
+
- **BREAKING (pre-1.0 minor):** the `@internal`
|
|
284
|
+
`WhatsAppClient._getBearerToken(): string` is removed and replaced
|
|
285
|
+
with `WhatsAppClient._resolveBearerToken(): Promise<string>`.
|
|
286
|
+
External callers MUST NOT depend on internal accessors; the legacy
|
|
287
|
+
helper is gone.
|
|
288
|
+
|
|
289
|
+
## [0.3.0] — 2026-05-10
|
|
290
|
+
|
|
291
|
+
### Added
|
|
292
|
+
|
|
293
|
+
- **`@dojocoding/whatsapp/hono` subpath** — typed Hono `Handler`
|
|
294
|
+
wrapper around the web-standard core. Mount with
|
|
295
|
+
`app.all(path, whatsappHandler(receiver))`. See
|
|
296
|
+
[`docs/hono.md`](./docs/hono.md) and
|
|
297
|
+
[`docs/cookbook/hono.md`](./docs/cookbook/hono.md). Hono is an
|
|
298
|
+
optional peer dependency on `^4.0.0`.
|
|
299
|
+
|
|
300
|
+
## [0.2.0] — 2026-05-10
|
|
301
|
+
|
|
302
|
+
### Added
|
|
303
|
+
|
|
304
|
+
- **`@dojocoding/whatsapp/web` subpath** — Fetch-API
|
|
305
|
+
(`Request → Response`) handler usable on Cloudflare Workers, Bun,
|
|
306
|
+
Deno, Hono, Next.js App Router, and any WinterCG runtime. See
|
|
307
|
+
[`docs/web.md`](./docs/web.md) and
|
|
308
|
+
[`docs/cookbook/cloudflare-workers.md`](./docs/cookbook/cloudflare-workers.md).
|
|
309
|
+
- WebCrypto migration of `verifySignature`, `verifyHandshake`, and
|
|
310
|
+
`hashPhoneNumberId` — these now run unmodified on any WinterCG
|
|
311
|
+
runtime in addition to Node. Byte-identical output to the previous
|
|
312
|
+
`node:crypto` implementations, verified by parity tests.
|
|
313
|
+
|
|
314
|
+
### Changed
|
|
315
|
+
|
|
316
|
+
- **BREAKING (pre-1.0 minor):** `verifySignature`, `computeSignature`,
|
|
317
|
+
and `hashPhoneNumberId` are now `async`. Internal call sites are
|
|
318
|
+
updated; external callers must `await` the return value.
|
|
319
|
+
- **BREAKING (pre-1.0 minor):** `WebhookReceiver.verify` and
|
|
320
|
+
`WebhookReceiver.handlePayload` are now `async`. The return shape
|
|
321
|
+
(`{ status, dispatchPromise }`) is unchanged; the receiver now
|
|
322
|
+
resolves to it via a Promise.
|
|
323
|
+
- The Express adapter is now a thin shim over the web-standard core
|
|
324
|
+
(`createWhatsAppHandler`). Externally observable behaviour is
|
|
325
|
+
unchanged; the integration suite passes without modification.
|
|
326
|
+
|
|
327
|
+
## [0.1.0] — 2026-05-10
|
|
328
|
+
|
|
329
|
+
First public release. Eight capability slices, all proposed and merged through
|
|
330
|
+
OpenSpec; see `openspec/changes/archive/` for the per-capability proposal,
|
|
331
|
+
design, spec deltas, and tasks.
|
|
332
|
+
|
|
333
|
+
### Added
|
|
334
|
+
|
|
335
|
+
- **Cloud API client** (`WhatsAppClient`) — HTTP transport with bearer-token
|
|
336
|
+
auth, exponential-backoff retry with full jitter on 408/429/5xx and Meta
|
|
337
|
+
recoverable codes (130429 / 131048 / 131053 / 131056), `Retry-After`
|
|
338
|
+
honouring, token-debug health check, per-instance Graph API version pin.
|
|
339
|
+
- **Message builders** — typed builders and `client.send*` convenience methods
|
|
340
|
+
for text, image, video, audio, document, sticker, location, contacts,
|
|
341
|
+
interactive (button / list / cta_url), template, reaction, and reply
|
|
342
|
+
messages.
|
|
343
|
+
- **Webhook receiver** (`WebhookReceiver`) — GET-handshake verify-token check,
|
|
344
|
+
raw-body HMAC-SHA256 signature verification with `crypto.timingSafeEqual`,
|
|
345
|
+
polymorphic event parsing (`message`, `status`, `template_status`,
|
|
346
|
+
`template_quality_update`, `template_category_update`,
|
|
347
|
+
`phone_number_quality_update`, `account_alert`, `account_review`,
|
|
348
|
+
`unknown`), `wamid` dedupe through a pluggable `Storage`, and 30-second-ack
|
|
349
|
+
async dispatch.
|
|
350
|
+
- **24-hour window tracker** (`WindowTracker`) — pluggable `Storage`-backed
|
|
351
|
+
customer-service window state; `client.send*` throws `WindowClosedError`
|
|
352
|
+
pre-flight when the window is closed. Templates and reactions are
|
|
353
|
+
window-exempt.
|
|
354
|
+
- **Template management** — list / get approved templates; 1-indexed
|
|
355
|
+
contiguous `{{N}}` placeholder validation; cross-validation of template
|
|
356
|
+
components against placeholder counts before send.
|
|
357
|
+
- **Mock mode** (`MockWhatsAppClient`, `pickWhatsAppClient`) — shared
|
|
358
|
+
`WhatsAppLikeClient` interface with the real client, parity-tested across a
|
|
359
|
+
cross-client matrix. Records sends in memory; optional in-memory template
|
|
360
|
+
registry. No Meta credentials required.
|
|
361
|
+
- **Observability** — OpenTelemetry spans on every Graph API request and
|
|
362
|
+
every webhook-handler invocation, with PII-redacting `hashPhoneNumberId`
|
|
363
|
+
(configurable salt via `setRedactSalt`). `@opentelemetry/api` is an
|
|
364
|
+
optional peer dependency.
|
|
365
|
+
- **Express adapter** (`@dojocoding/whatsapp/express`) — middleware that
|
|
366
|
+
captures raw bytes before any JSON parser, handles `GET`/`POST` method
|
|
367
|
+
routing, and acks within 30 seconds.
|
|
368
|
+
- **Typed error classes** — `WhatsAppError`, `RateLimitError`,
|
|
369
|
+
`WindowClosedError`, `WebhookSignatureError`, `TemplateError`,
|
|
370
|
+
`MissingCredentialsError`, `MockModeError`, `AuthenticationError`,
|
|
371
|
+
`PermissionError`, `CapabilityError`. Branch with `instanceof`, not
|
|
372
|
+
string matching.
|
|
373
|
+
- **Storage interface** — `Storage` with TTL semantics and `InMemoryStorage`
|
|
374
|
+
reference implementation. Shared by `WindowTracker` and the webhook
|
|
375
|
+
deduper.
|
|
376
|
+
|
|
377
|
+
### Compliance
|
|
378
|
+
|
|
379
|
+
- Graph API pin: `v25.0`.
|
|
380
|
+
- Webhook dedupe TTL: 24 hours (covers Meta's up-to-7-day delivery retries
|
|
381
|
+
practically; full 7-day TTL is opt-in via `Storage` config).
|
|
382
|
+
- Webhook ack deadline: 30 seconds.
|
|
383
|
+
|
|
384
|
+
### Project
|
|
385
|
+
|
|
386
|
+
- Spec-driven via [OpenSpec](https://github.com/openspec-dev/openspec); eight
|
|
387
|
+
stable specs under `openspec/specs/`.
|
|
388
|
+
- Dual ESM + CJS build via `tsup`; `Node >= 20` LTS.
|
|
389
|
+
- Test layers: unit, contract, integration, parity. Coverage thresholds
|
|
390
|
+
enforced in CI (line ≥ 90 %, branch ≥ 85 %).
|
|
391
|
+
- Licensed under [MIT](./LICENSE).
|
|
392
|
+
|
|
393
|
+
[0.7.3]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.7.3
|
|
394
|
+
[0.7.2]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.7.2
|
|
395
|
+
[0.7.1]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.7.1
|
|
396
|
+
[0.7.0]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.7.0
|
|
397
|
+
[0.6.0]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.6.0
|
|
398
|
+
[0.5.0]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.5.0
|
|
399
|
+
[0.4.0]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.4.0
|
|
400
|
+
[0.3.0]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.3.0
|
|
401
|
+
[0.2.0]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.2.0
|
|
402
|
+
[0.1.0]: https://github.com/DojoCodingLabs/whatsapp-adapter/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dojo Coding LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|