@whatsapi.sh/sdk 0.1.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/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/client.d.ts +35 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +169 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +40 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +42 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/contract.d.ts +318 -0
- package/dist/generated/contract.d.ts.map +1 -0
- package/dist/generated/contract.js +32 -0
- package/dist/generated/contract.js.map +1 -0
- package/dist/generated/operations.d.ts +240 -0
- package/dist/generated/operations.d.ts.map +1 -0
- package/dist/generated/operations.js +285 -0
- package/dist/generated/operations.js.map +1 -0
- package/dist/generated/params.d.ts +177 -0
- package/dist/generated/params.d.ts.map +1 -0
- package/dist/generated/params.js +7 -0
- package/dist/generated/params.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/webhooks.d.ts +28 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +73 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +47 -0
- package/src/client.ts +204 -0
- package/src/errors.ts +71 -0
- package/src/generated/contract.ts +402 -0
- package/src/generated/operations.ts +371 -0
- package/src/generated/params.ts +203 -0
- package/src/index.ts +11 -0
- package/src/webhooks.ts +96 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 whatsapi.sh
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @whatsapi.sh/sdk
|
|
2
|
+
|
|
3
|
+
The official TypeScript client for [whatsapi.sh](https://whatsapi.sh) — send WhatsApp
|
|
4
|
+
messages, media and one-time codes through numbers you pair yourself, and receive
|
|
5
|
+
signed events back.
|
|
6
|
+
|
|
7
|
+
Every method, type and doc comment in this package is generated from the API's own
|
|
8
|
+
operation definitions, so what TypeScript tells you here is what the server actually
|
|
9
|
+
does.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @whatsapi.sh/sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Send a message
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { Whatsapi } from "@whatsapi.sh/sdk";
|
|
19
|
+
|
|
20
|
+
const wa = new Whatsapi({ apiKey: process.env.WHATSAPI_KEY! });
|
|
21
|
+
|
|
22
|
+
const message = await wa.sendMessage({
|
|
23
|
+
to: "+5511988887777",
|
|
24
|
+
text: "Your table is ready.",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
console.log(message.id, message.quotaRemaining);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The key comes from [the dashboard](https://app.whatsapi.sh/keys). With a single
|
|
31
|
+
connected number you never name a sender; with several, pass `from`.
|
|
32
|
+
|
|
33
|
+
## Pair a number
|
|
34
|
+
|
|
35
|
+
A number is a slot on your account plus a real WhatsApp session linked to it. Create
|
|
36
|
+
the slot, then pair it by QR (scan from **WhatsApp → Linked devices**) or by an
|
|
37
|
+
8-character code typed into the phone:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const number = await wa.createNumber({ name: "Support" });
|
|
41
|
+
|
|
42
|
+
const pairing = await wa.pairNumber({ numberId: number.id, mode: "qr" });
|
|
43
|
+
if (pairing.qrCode) showToUser(pairing.qrCode); // base64 PNG, good for ~90s
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`pairNumber` is also the poll: call it again while `state` is `"pairing"` and no code
|
|
47
|
+
has been minted yet. A fresh QR can only be generated every few minutes, so reuse the
|
|
48
|
+
one you have (`isCached`, `generatedAt`, `remainingCooldown` all say where you stand).
|
|
49
|
+
|
|
50
|
+
## One-time codes
|
|
51
|
+
|
|
52
|
+
`sendOtp` generates the code, sends it, and hands it back — verify it yourself, or let
|
|
53
|
+
us do it and keep nothing:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
const otp = await wa.sendOtp({ to: "+5511988887777" });
|
|
57
|
+
// …later, with what the user typed:
|
|
58
|
+
await wa.checkOtp({ to: "+5511988887777", code: "123456" });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
A wrong or expired code throws `OTP_INVALID` rather than answering "not verified" — a
|
|
62
|
+
check you forget to read can never look like a pass.
|
|
63
|
+
|
|
64
|
+
## Receive events
|
|
65
|
+
|
|
66
|
+
One endpoint per account receives all five events, signed. Verify before you trust:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { verifyWebhook, WebhookSignatureError } from "@whatsapi.sh/sdk";
|
|
70
|
+
|
|
71
|
+
app.post("/webhooks/whatsapp", express.raw({ type: "application/json" }), async (req, res) => {
|
|
72
|
+
try {
|
|
73
|
+
const event = await verifyWebhook({
|
|
74
|
+
payload: req.body, // the RAW body, not the parsed one
|
|
75
|
+
signature: req.header("x-whatsapi-signature"),
|
|
76
|
+
secret: process.env.WHATSAPI_WEBHOOK_SECRET!,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (event.type === "message.created") {
|
|
80
|
+
await reply(event.data.number.id, event.data.message.text ?? "");
|
|
81
|
+
}
|
|
82
|
+
res.sendStatus(200);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
res.sendStatus(error instanceof WebhookSignatureError ? 400 : 500);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`event.type` narrows `event.data`, so the compiler knows a `message.status` event has
|
|
90
|
+
`messageIds` and a `number.logged_out` event does not. Deliveries retry, so the same
|
|
91
|
+
`event.id` can arrive twice — record it and drop repeats.
|
|
92
|
+
|
|
93
|
+
## Errors
|
|
94
|
+
|
|
95
|
+
Every failure is a `WhatsapiError` carrying the API's own `code`, plus `status`,
|
|
96
|
+
`retryAfter` and the `requestId` to quote at support.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { WhatsapiError } from "@whatsapi.sh/sdk";
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
await wa.sendMessage({ to, text });
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (!(error instanceof WhatsapiError)) throw error;
|
|
105
|
+
|
|
106
|
+
if (error.code === "PAYMENT_REQUIRED") return askThemToUpgrade();
|
|
107
|
+
if (error.code === "NUMBER_NOT_CONNECTED") return askThemToPairAgain();
|
|
108
|
+
if (error.code === "GATEWAY_TIMEOUT") return watchFor(error.messageId); // see below
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Two rules worth knowing before you write a retry loop of your own:
|
|
114
|
+
|
|
115
|
+
- **`GATEWAY_TIMEOUT` is not a failure.** WhatsApp did not confirm in time, but the
|
|
116
|
+
send was accepted and most likely delivered. Sending again sends twice. Watch for
|
|
117
|
+
`error.messageId` on the `message.status` webhook instead.
|
|
118
|
+
- **`PAYMENT_REQUIRED` never clears by waiting**, unlike `RATE_LIMIT_EXCEEDED` and
|
|
119
|
+
`QUOTA_EXCEEDED`, which carry a `retryAfter`.
|
|
120
|
+
|
|
121
|
+
This client retries **reads** (a failed `GET`, twice by default, honoring
|
|
122
|
+
`Retry-After`) and never retries a write. There is no idempotency key on the API yet,
|
|
123
|
+
so an automatic retry of a send would be a second real message to a real person — that
|
|
124
|
+
call is yours to make, deliberately.
|
|
125
|
+
|
|
126
|
+
## Agents
|
|
127
|
+
|
|
128
|
+
If you are wiring up an LLM rather than an app, you probably want the MCP server
|
|
129
|
+
instead of this package: the same operations, as tools, at
|
|
130
|
+
`https://api.whatsapi.sh/mcp` with the same `wa_` key. See
|
|
131
|
+
[the MCP reference](https://docs.whatsapi.sh/mcp).
|
|
132
|
+
|
|
133
|
+
## Before you ship
|
|
134
|
+
|
|
135
|
+
whatsapi.sh runs on the **unofficial** WhatsApp protocol — the same one WhatsApp Web
|
|
136
|
+
uses. It is not the WhatsApp Business API, there is no Meta approval, and WhatsApp can
|
|
137
|
+
restrict or ban a number that behaves like a broadcaster. Cold outreach, identical
|
|
138
|
+
messages at speed and large recipient lists are what gets numbers banned. Pace your
|
|
139
|
+
sends, message people who expect you, and do not put a number you cannot afford to
|
|
140
|
+
lose on it. We tell you this before you pair, not after.
|
|
141
|
+
|
|
142
|
+
## Requirements
|
|
143
|
+
|
|
144
|
+
Node 20+, or any runtime with `fetch` and Web Crypto (Bun, Deno, Cloudflare Workers,
|
|
145
|
+
the browser — though a `wa_` key does not belong in a browser). ESM only; on Node
|
|
146
|
+
22.12+ `require("@whatsapi.sh/sdk")` works too.
|
|
147
|
+
|
|
148
|
+
- Docs: [docs.whatsapi.sh](https://docs.whatsapi.sh)
|
|
149
|
+
- REST reference: [docs.whatsapi.sh/reference](https://docs.whatsapi.sh/reference)
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { GeneratedOperations } from "./generated/operations.ts";
|
|
2
|
+
export interface WhatsapiOptions {
|
|
3
|
+
/** A `wa_` key from the dashboard. */
|
|
4
|
+
apiKey: string;
|
|
5
|
+
/** Defaults to the hosted API; point it at a self-hosted deployment if you run one. */
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
/** Per-attempt timeout in ms. Default 30000. */
|
|
8
|
+
timeout?: number;
|
|
9
|
+
/** Extra attempts for READ calls only. Default 2, 0 disables. */
|
|
10
|
+
maxRetries?: number;
|
|
11
|
+
/** Swap the fetch implementation (tests, proxies, a custom agent). */
|
|
12
|
+
fetch?: typeof globalThis.fetch;
|
|
13
|
+
}
|
|
14
|
+
/** What a generated method hands the transport. */
|
|
15
|
+
export interface RequestSpec {
|
|
16
|
+
method: "GET" | "POST" | "PUT" | "DELETE";
|
|
17
|
+
/** Template with `:name` placeholders naming the params that fill them. */
|
|
18
|
+
path: string;
|
|
19
|
+
pathParams?: readonly string[];
|
|
20
|
+
/** Values the ROUTE fixes rather than the caller. */
|
|
21
|
+
fixed?: Readonly<Record<string, unknown>>;
|
|
22
|
+
}
|
|
23
|
+
export declare class Whatsapi extends GeneratedOperations {
|
|
24
|
+
private readonly apiKey;
|
|
25
|
+
private readonly baseUrl;
|
|
26
|
+
private readonly timeout;
|
|
27
|
+
private readonly maxRetries;
|
|
28
|
+
private readonly fetchImpl;
|
|
29
|
+
constructor(options: WhatsapiOptions | string);
|
|
30
|
+
protected request<T>(spec: RequestSpec, params?: object): Promise<T>;
|
|
31
|
+
/** How long to wait before repeating a read, or undefined to give up now. */
|
|
32
|
+
private retryDelay;
|
|
33
|
+
private attempt;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAUA,OAAO,EAAoB,mBAAmB,EAAe,MAAM,2BAA2B,CAAC;AAE/F,MAAM,WAAW,eAAe;IAC5B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACnC;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,qDAAqD;IACrD,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC7C;AA6BD,qBAAa,QAAS,SAAQ,mBAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;gBAExC,OAAO,EAAE,eAAe,GAAG,MAAM;cAqB7B,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAE,MAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAgB9E,6EAA6E;IAC7E,OAAO,CAAC,UAAU;YAkBJ,OAAO;CA8ExB"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// The transport under every generated method: one request, one `{ data }`
|
|
2
|
+
// unwrap, one error taxonomy.
|
|
3
|
+
//
|
|
4
|
+
// The retry policy is the opinionated part, and it is deliberately narrow:
|
|
5
|
+
// READS retry, WRITES never do. There is no idempotency key on /v1, so a
|
|
6
|
+
// retried send is a second WhatsApp message to a real person and a second unit
|
|
7
|
+
// off the quota — worse than the failure it was papering over. Writes come back
|
|
8
|
+
// as a WhatsapiError carrying `code` and `retryAfter`, and the caller decides.
|
|
9
|
+
import { WhatsapiError } from "./errors.js";
|
|
10
|
+
import { DEFAULT_BASE_URL, GeneratedOperations, SDK_VERSION } from "./generated/operations.js";
|
|
11
|
+
/** A Retry-After we would honor beyond this is not a retry, it is a hang — the
|
|
12
|
+
* caller gets the error (with `retryAfter` on it) and schedules it themselves. */
|
|
13
|
+
const MAX_RETRY_DELAY_MS = 10_000;
|
|
14
|
+
/** How the API answers when it never got to answer at all. */
|
|
15
|
+
function statusCode(status) {
|
|
16
|
+
if (status === 503)
|
|
17
|
+
return "SERVICE_UNAVAILABLE";
|
|
18
|
+
if (status === 404)
|
|
19
|
+
return "NOT_FOUND";
|
|
20
|
+
if (status === 401)
|
|
21
|
+
return "UNAUTHORIZED";
|
|
22
|
+
return "INTERNAL_ERROR";
|
|
23
|
+
}
|
|
24
|
+
/** Seconds from `Retry-After` (delta form) or the error's own details. */
|
|
25
|
+
function retryAfterOf(header, details) {
|
|
26
|
+
const fromDetails = typeof details === "object" && details !== null
|
|
27
|
+
? details.retryAfterSecs
|
|
28
|
+
: undefined;
|
|
29
|
+
if (typeof fromDetails === "number" && Number.isFinite(fromDetails))
|
|
30
|
+
return fromDetails;
|
|
31
|
+
const seconds = header === null ? NaN : Number(header);
|
|
32
|
+
return Number.isFinite(seconds) ? seconds : undefined;
|
|
33
|
+
}
|
|
34
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
35
|
+
export class Whatsapi extends GeneratedOperations {
|
|
36
|
+
apiKey;
|
|
37
|
+
baseUrl;
|
|
38
|
+
timeout;
|
|
39
|
+
maxRetries;
|
|
40
|
+
fetchImpl;
|
|
41
|
+
constructor(options) {
|
|
42
|
+
super();
|
|
43
|
+
const opts = typeof options === "string" ? { apiKey: options } : options;
|
|
44
|
+
if (!opts.apiKey)
|
|
45
|
+
throw new TypeError("whatsapi: an API key is required — create one at https://app.whatsapi.sh/keys");
|
|
46
|
+
this.apiKey = opts.apiKey;
|
|
47
|
+
// Trailing slashes would double up against the leading slash of a path.
|
|
48
|
+
this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
49
|
+
this.timeout = opts.timeout ?? 30_000;
|
|
50
|
+
this.maxRetries = opts.maxRetries ?? 2;
|
|
51
|
+
const impl = opts.fetch ?? globalThis.fetch;
|
|
52
|
+
if (typeof impl !== "function")
|
|
53
|
+
throw new TypeError("whatsapi: no global fetch — use Node 20+, or pass `fetch` in the options.");
|
|
54
|
+
// Bound: an unbound global fetch throws "Illegal invocation" in browsers.
|
|
55
|
+
this.fetchImpl = opts.fetch ?? impl.bind(globalThis);
|
|
56
|
+
}
|
|
57
|
+
async request(spec, params = {}) {
|
|
58
|
+
// Reads are the only calls we may repeat: a re-sent message is a second
|
|
59
|
+
// message to a real person, and no header on /v1 makes it idempotent.
|
|
60
|
+
const retries = spec.method === "GET" ? this.maxRetries : 0;
|
|
61
|
+
for (let attempt = 0;; attempt++) {
|
|
62
|
+
try {
|
|
63
|
+
return await this.attempt(spec, params);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (!(error instanceof WhatsapiError) || attempt >= retries)
|
|
67
|
+
throw error;
|
|
68
|
+
const delay = this.retryDelay(error, attempt);
|
|
69
|
+
if (delay === undefined)
|
|
70
|
+
throw error;
|
|
71
|
+
await sleep(delay);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** How long to wait before repeating a read, or undefined to give up now. */
|
|
76
|
+
retryDelay(error, attempt) {
|
|
77
|
+
const worthRepeating = error.code === "NETWORK_ERROR" ||
|
|
78
|
+
error.code === "TIMEOUT" ||
|
|
79
|
+
error.code === "RATE_LIMIT_EXCEEDED" ||
|
|
80
|
+
// A quota clears when the month rolls over and a pairing cooldown
|
|
81
|
+
// runs for minutes: both are answers, not hiccups.
|
|
82
|
+
(error.status >= 500 && error.code !== "GATEWAY_TIMEOUT");
|
|
83
|
+
if (!worthRepeating)
|
|
84
|
+
return undefined;
|
|
85
|
+
if (error.retryAfter !== undefined) {
|
|
86
|
+
const ms = error.retryAfter * 1000;
|
|
87
|
+
return ms > MAX_RETRY_DELAY_MS ? undefined : ms;
|
|
88
|
+
}
|
|
89
|
+
// Exponential with jitter, so a fleet of clients does not resynchronize
|
|
90
|
+
// onto the same second after an outage.
|
|
91
|
+
return Math.min(250 * 2 ** attempt, 4_000) * (0.5 + Math.random());
|
|
92
|
+
}
|
|
93
|
+
async attempt(spec, params) {
|
|
94
|
+
const rest = { ...params };
|
|
95
|
+
let path = spec.path;
|
|
96
|
+
for (const name of spec.pathParams ?? []) {
|
|
97
|
+
const value = rest[name];
|
|
98
|
+
if (value === undefined || value === null || value === "")
|
|
99
|
+
throw new TypeError(`whatsapi: \`${name}\` is required`);
|
|
100
|
+
delete rest[name];
|
|
101
|
+
path = path.replace(`:${name}`, encodeURIComponent(String(value)));
|
|
102
|
+
}
|
|
103
|
+
const url = new URL(this.baseUrl + path);
|
|
104
|
+
const hasBody = spec.method === "POST" || spec.method === "PUT";
|
|
105
|
+
if (!hasBody)
|
|
106
|
+
for (const [key, value] of Object.entries(rest))
|
|
107
|
+
if (value !== undefined && value !== null)
|
|
108
|
+
url.searchParams.set(key, String(value));
|
|
109
|
+
const headers = {
|
|
110
|
+
authorization: `Bearer ${this.apiKey}`,
|
|
111
|
+
accept: "application/json",
|
|
112
|
+
"x-whatsapi-client": `whatsapi-js/${SDK_VERSION}`,
|
|
113
|
+
};
|
|
114
|
+
if (hasBody)
|
|
115
|
+
headers["content-type"] = "application/json";
|
|
116
|
+
let response;
|
|
117
|
+
try {
|
|
118
|
+
response = await this.fetchImpl(url.toString(), {
|
|
119
|
+
method: spec.method,
|
|
120
|
+
headers,
|
|
121
|
+
...(hasBody
|
|
122
|
+
? { body: JSON.stringify({ ...rest, ...(spec.fixed ?? {}) }) }
|
|
123
|
+
: undefined),
|
|
124
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch (cause) {
|
|
128
|
+
const timedOut = cause instanceof Error && cause.name === "TimeoutError";
|
|
129
|
+
throw new WhatsapiError({
|
|
130
|
+
code: (timedOut ? "TIMEOUT" : "NETWORK_ERROR"),
|
|
131
|
+
status: 0,
|
|
132
|
+
message: timedOut
|
|
133
|
+
? `whatsapi: no answer within ${this.timeout}ms — the call may still have gone through.`
|
|
134
|
+
: `whatsapi: could not reach ${url.host}.`,
|
|
135
|
+
cause,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const requestId = response.headers.get("x-request-id") ?? undefined;
|
|
139
|
+
const text = await response.text();
|
|
140
|
+
let payload;
|
|
141
|
+
try {
|
|
142
|
+
payload = text ? JSON.parse(text) : undefined;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
payload = undefined;
|
|
146
|
+
}
|
|
147
|
+
if (response.ok)
|
|
148
|
+
return payload.data;
|
|
149
|
+
const envelope = typeof payload === "object" && payload !== null
|
|
150
|
+
? payload.error
|
|
151
|
+
: undefined;
|
|
152
|
+
const details = envelope?.details;
|
|
153
|
+
throw new WhatsapiError({
|
|
154
|
+
code: envelope?.code ?? statusCode(response.status),
|
|
155
|
+
status: response.status,
|
|
156
|
+
// A proxy or a cold start can answer HTML; say what actually came back
|
|
157
|
+
// rather than pretending the body was ours.
|
|
158
|
+
message: typeof envelope?.message === "string"
|
|
159
|
+
? envelope.message
|
|
160
|
+
: `whatsapi: ${spec.method} ${path} failed with ${response.status}.`,
|
|
161
|
+
messageKey: typeof envelope?.messageKey === "string" ? envelope.messageKey : undefined,
|
|
162
|
+
params: envelope?.params,
|
|
163
|
+
details: envelope ? details : text.slice(0, 500) || undefined,
|
|
164
|
+
retryAfter: retryAfterOf(response.headers.get("retry-after"), details),
|
|
165
|
+
requestId,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ErrorCode } from "./generated/contract.ts";
|
|
2
|
+
/** Failures that never reached the API, so they carry no server code. */
|
|
3
|
+
export type ClientErrorCode = "NETWORK_ERROR" | "TIMEOUT";
|
|
4
|
+
export interface WhatsapiErrorInit {
|
|
5
|
+
code: ErrorCode | ClientErrorCode;
|
|
6
|
+
message: string;
|
|
7
|
+
/** HTTP status, or 0 when no answer arrived. */
|
|
8
|
+
status: number;
|
|
9
|
+
messageKey?: string;
|
|
10
|
+
params?: Record<string, string | number>;
|
|
11
|
+
details?: unknown;
|
|
12
|
+
/** Seconds until the call is worth making again, when the API said. */
|
|
13
|
+
retryAfter?: number;
|
|
14
|
+
/** `X-Request-ID` — quote it in a support request and we can find the call. */
|
|
15
|
+
requestId?: string;
|
|
16
|
+
cause?: unknown;
|
|
17
|
+
}
|
|
18
|
+
export declare class WhatsapiError extends Error {
|
|
19
|
+
readonly code: ErrorCode | ClientErrorCode;
|
|
20
|
+
readonly status: number;
|
|
21
|
+
readonly messageKey?: string;
|
|
22
|
+
readonly params?: Record<string, string | number>;
|
|
23
|
+
readonly details?: unknown;
|
|
24
|
+
readonly retryAfter?: number;
|
|
25
|
+
readonly requestId?: string;
|
|
26
|
+
constructor(init: WhatsapiErrorInit);
|
|
27
|
+
/** The id a timed-out send went out with.
|
|
28
|
+
*
|
|
29
|
+
* `GATEWAY_TIMEOUT` means WhatsApp did not confirm in time — NOT that the
|
|
30
|
+
* message failed. It was accepted upstream and most likely delivered, so
|
|
31
|
+
* sending it again sends it twice. Watch for this id on the
|
|
32
|
+
* `message.status` webhook instead. */
|
|
33
|
+
get messageId(): string | undefined;
|
|
34
|
+
}
|
|
35
|
+
/** A delivery whose signature did not check out — treat the body as hostile and
|
|
36
|
+
* answer 400. Never a WhatsapiError: nothing here came from a call we made. */
|
|
37
|
+
export declare class WebhookSignatureError extends Error {
|
|
38
|
+
constructor(message: string);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,yEAAyE;AACzE,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG,SAAS,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,SAAS,GAAG,eAAe,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;gBAEhB,IAAI,EAAE,iBAAiB;IAYnC;;;;;4CAKwC;IACxC,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAMlC;CACJ;AAED;gFACgF;AAChF,qBAAa,qBAAsB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI9B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export class WhatsapiError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
messageKey;
|
|
5
|
+
params;
|
|
6
|
+
details;
|
|
7
|
+
retryAfter;
|
|
8
|
+
requestId;
|
|
9
|
+
constructor(init) {
|
|
10
|
+
super(init.message, init.cause !== undefined ? { cause: init.cause } : undefined);
|
|
11
|
+
this.name = "WhatsapiError";
|
|
12
|
+
this.code = init.code;
|
|
13
|
+
this.status = init.status;
|
|
14
|
+
this.messageKey = init.messageKey;
|
|
15
|
+
this.params = init.params;
|
|
16
|
+
this.details = init.details;
|
|
17
|
+
this.retryAfter = init.retryAfter;
|
|
18
|
+
this.requestId = init.requestId;
|
|
19
|
+
}
|
|
20
|
+
/** The id a timed-out send went out with.
|
|
21
|
+
*
|
|
22
|
+
* `GATEWAY_TIMEOUT` means WhatsApp did not confirm in time — NOT that the
|
|
23
|
+
* message failed. It was accepted upstream and most likely delivered, so
|
|
24
|
+
* sending it again sends it twice. Watch for this id on the
|
|
25
|
+
* `message.status` webhook instead. */
|
|
26
|
+
get messageId() {
|
|
27
|
+
const details = this.details;
|
|
28
|
+
if (this.code !== "GATEWAY_TIMEOUT" || typeof details !== "object" || details === null)
|
|
29
|
+
return undefined;
|
|
30
|
+
const id = details.messageId;
|
|
31
|
+
return typeof id === "string" ? id : undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** A delivery whose signature did not check out — treat the body as hostile and
|
|
35
|
+
* answer 400. Never a WhatsapiError: nothing here came from a call we made. */
|
|
36
|
+
export class WebhookSignatureError extends Error {
|
|
37
|
+
constructor(message) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "WebhookSignatureError";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AA2BA,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC3B,IAAI,CAA8B;IAClC,MAAM,CAAS;IACf,UAAU,CAAU;IACpB,MAAM,CAAmC;IACzC,OAAO,CAAW;IAClB,UAAU,CAAU;IACpB,SAAS,CAAU;IAE5B,YAAY,IAAuB;QAC/B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAClF,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACpC,CAAC;IAED;;;;;4CAKwC;IACxC,IAAI,SAAS;QACT,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;YAClF,OAAO,SAAS,CAAC;QACrB,MAAM,EAAE,GAAI,OAAmC,CAAC,SAAS,CAAC;QAC1D,OAAO,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACnD,CAAC;CACJ;AAED;gFACgF;AAChF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACxC,CAAC;CACJ"}
|