@open-apime/sdk 0.2.2
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 +22 -0
- package/README.md +44 -0
- package/dist/chunk-2BUPSB7O.js +0 -0
- package/dist/chunk-HS2RZ6SJ.js +93 -0
- package/dist/events-BV5UVoFu.d.cts +90 -0
- package/dist/events-BV5UVoFu.d.ts +90 -0
- package/dist/index-37ITjlwO.d.cts +83 -0
- package/dist/index-TqYrYke0.d.ts +83 -0
- package/dist/index.cjs +816 -0
- package/dist/index.d.cts +512 -0
- package/dist/index.d.ts +512 -0
- package/dist/index.js +719 -0
- package/dist/types/index.cjs +18 -0
- package/dist/types/index.d.cts +46 -0
- package/dist/types/index.d.ts +46 -0
- package/dist/types/index.js +1 -0
- package/dist/webhook/index.cjs +78 -0
- package/dist/webhook/index.d.cts +2 -0
- package/dist/webhook/index.d.ts +2 -0
- package/dist/webhook/index.js +12 -0
- package/package.json +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
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.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @open-apime/sdk
|
|
2
|
+
|
|
3
|
+
Cliente TypeScript da API do [apime](https://github.com/open-apime/apime): envio de WhatsApp,
|
|
4
|
+
gestão de instâncias e verificação de webhook.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm install @open-apime/sdk
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { Apime } from "@open-apime/sdk";
|
|
12
|
+
|
|
13
|
+
const conexao = Apime.withInstanceToken(
|
|
14
|
+
{ token: process.env.INSTANCE_TOKEN!, instanceId: "abc-123" },
|
|
15
|
+
{ baseUrl: "https://apime.example.com" },
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
await conexao.messages.sendText(
|
|
19
|
+
{ to: "5511999999999", text: "Olá" },
|
|
20
|
+
{ idempotencyKey: mensagem.id },
|
|
21
|
+
);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **Zero dependência de runtime.** `fetch` e `crypto` do próprio Node (18+).
|
|
25
|
+
- **Tipado por token:** o cliente que você constrói define o que compila, então token errado para a
|
|
26
|
+
rota vira erro de compilação, não `403` em produção.
|
|
27
|
+
- **Retry seguro:** leitura retenta sozinha, envio só com `Idempotency-Key`.
|
|
28
|
+
- **Webhook verificado** em tempo constante, sobre o corpo cru.
|
|
29
|
+
- Cobre as **66 operações** do contrato do apime.
|
|
30
|
+
|
|
31
|
+
## Documentação
|
|
32
|
+
|
|
33
|
+
| | |
|
|
34
|
+
|---|---|
|
|
35
|
+
| [Guia de uso](https://github.com/open-apime/sdk/blob/main/docs/guia.md) | clientes, envio, erros, retry, observabilidade e webhook |
|
|
36
|
+
| [Segurança](https://github.com/open-apime/sdk/blob/main/docs/seguranca.md) | o que o SDK protege, e como |
|
|
37
|
+
| [openapi.yaml](https://github.com/open-apime/apime/blob/main/openapi.yaml) | contrato da API |
|
|
38
|
+
| [webhook-payloads.md](https://github.com/open-apime/apime/blob/main/docs/webhook-payloads.md) | os 12 eventos |
|
|
39
|
+
|
|
40
|
+
Enquanto está em `0.x`, minor pode trazer mudança incompatível.
|
|
41
|
+
|
|
42
|
+
## Licença
|
|
43
|
+
|
|
44
|
+
MIT.
|
|
File without changes
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// src/webhook/index.ts
|
|
2
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
3
|
+
|
|
4
|
+
// src/errors/index.ts
|
|
5
|
+
var ApimeError = class extends Error {
|
|
6
|
+
status;
|
|
7
|
+
body;
|
|
8
|
+
/** Value of the request id header, when the response carried one. */
|
|
9
|
+
requestId;
|
|
10
|
+
constructor(message, options = {}) {
|
|
11
|
+
super(message, options.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
12
|
+
this.name = new.target.name;
|
|
13
|
+
this.status = options.status;
|
|
14
|
+
this.body = options.body;
|
|
15
|
+
this.requestId = options.requestId;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var AuthenticationError = class extends ApimeError {
|
|
19
|
+
};
|
|
20
|
+
var PermissionError = class extends ApimeError {
|
|
21
|
+
};
|
|
22
|
+
var NotFoundError = class extends ApimeError {
|
|
23
|
+
};
|
|
24
|
+
var ConflictError = class extends ApimeError {
|
|
25
|
+
};
|
|
26
|
+
var UnprocessableError = class extends ApimeError {
|
|
27
|
+
};
|
|
28
|
+
var RateLimitError = class extends ApimeError {
|
|
29
|
+
retryAfterMs;
|
|
30
|
+
constructor(message, options = {}) {
|
|
31
|
+
super(message, options);
|
|
32
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var InvalidRequestError = class extends ApimeError {
|
|
36
|
+
};
|
|
37
|
+
var ApiError = class extends ApimeError {
|
|
38
|
+
};
|
|
39
|
+
var SessionUnavailableError = class extends ApiError {
|
|
40
|
+
};
|
|
41
|
+
var ConnectionError = class extends ApimeError {
|
|
42
|
+
};
|
|
43
|
+
var TimeoutError = class extends ConnectionError {
|
|
44
|
+
};
|
|
45
|
+
var ConfigurationError = class extends ApimeError {
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/webhook/index.ts
|
|
49
|
+
var SIGNATURE_HEADER = "X-ApiMe-Signature";
|
|
50
|
+
var InvalidSignatureError = class extends ApimeError {
|
|
51
|
+
};
|
|
52
|
+
function verifyWebhookSignature(rawBody, signature, secret) {
|
|
53
|
+
if (!signature || !secret) return false;
|
|
54
|
+
const body = typeof rawBody === "string" ? Buffer.from(rawBody, "utf8") : rawBody;
|
|
55
|
+
const expected = `sha256=${createHmac("sha256", secret).update(body).digest("hex")}`;
|
|
56
|
+
const received = Buffer.from(signature, "utf8");
|
|
57
|
+
const digest = Buffer.from(expected, "utf8");
|
|
58
|
+
if (received.length !== digest.length) return false;
|
|
59
|
+
return timingSafeEqual(received, digest);
|
|
60
|
+
}
|
|
61
|
+
function constructEvent(rawBody, signature, secret) {
|
|
62
|
+
if (!verifyWebhookSignature(rawBody, signature, secret)) {
|
|
63
|
+
throw new InvalidSignatureError("assinatura do webhook n\xE3o confere");
|
|
64
|
+
}
|
|
65
|
+
const text = typeof rawBody === "string" ? rawBody : rawBody.toString("utf8");
|
|
66
|
+
let parsed;
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(text);
|
|
69
|
+
} catch (cause) {
|
|
70
|
+
throw new InvalidSignatureError("corpo do webhook n\xE3o \xE9 JSON v\xE1lido", { cause });
|
|
71
|
+
}
|
|
72
|
+
return parsed;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
ApimeError,
|
|
77
|
+
AuthenticationError,
|
|
78
|
+
PermissionError,
|
|
79
|
+
NotFoundError,
|
|
80
|
+
ConflictError,
|
|
81
|
+
UnprocessableError,
|
|
82
|
+
RateLimitError,
|
|
83
|
+
InvalidRequestError,
|
|
84
|
+
ApiError,
|
|
85
|
+
SessionUnavailableError,
|
|
86
|
+
ConnectionError,
|
|
87
|
+
TimeoutError,
|
|
88
|
+
ConfigurationError,
|
|
89
|
+
SIGNATURE_HEADER,
|
|
90
|
+
InvalidSignatureError,
|
|
91
|
+
verifyWebhookSignature,
|
|
92
|
+
constructEvent
|
|
93
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 12 event types the apime delivers. `ignore` is internal and never
|
|
3
|
+
* reaches a consumer, so it is not part of the union.
|
|
4
|
+
*/
|
|
5
|
+
type WebhookEventType = "message" | "receipt" | "presence" | "chat_presence" | "reaction" | "contact_update" | "connected" | "disconnected" | "temporary_ban" | "restriction_lifted" | "contact_reachout_locked" | "unknown";
|
|
6
|
+
interface WebhookEnvelope<T extends WebhookEventType = WebhookEventType, P = unknown> {
|
|
7
|
+
id: string;
|
|
8
|
+
instanceId: string;
|
|
9
|
+
type: T;
|
|
10
|
+
payload: P;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
/** Button of an interactive message. `call`, `copy`, `reply` and `url` are button kinds, not events. */
|
|
14
|
+
interface MessageButton {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
type: "reply" | "url" | "copy" | "call";
|
|
18
|
+
url?: string;
|
|
19
|
+
code?: string;
|
|
20
|
+
phone?: string;
|
|
21
|
+
}
|
|
22
|
+
interface MessagePayload {
|
|
23
|
+
from: string;
|
|
24
|
+
to: string;
|
|
25
|
+
isFromMe: boolean;
|
|
26
|
+
isGroup: boolean;
|
|
27
|
+
messageId: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
pushName?: string;
|
|
30
|
+
text?: string;
|
|
31
|
+
mediaType?: "image" | "video" | "audio" | "document" | "sticker" | "location" | "contact";
|
|
32
|
+
mediaUrl?: string;
|
|
33
|
+
mimetype?: string;
|
|
34
|
+
caption?: string;
|
|
35
|
+
buttons?: MessageButton[];
|
|
36
|
+
/**
|
|
37
|
+
* Present only when this event is an edit: the id of the message that was
|
|
38
|
+
* edited, and its new text. They always travel together, so checking one is
|
|
39
|
+
* enough to know it is an edit.
|
|
40
|
+
*/
|
|
41
|
+
editedMessageId?: string;
|
|
42
|
+
editedText?: string;
|
|
43
|
+
}
|
|
44
|
+
interface ReceiptPayload {
|
|
45
|
+
messageIds: string[];
|
|
46
|
+
timestamp: number;
|
|
47
|
+
chat: string;
|
|
48
|
+
status: "read" | "delivered" | "played";
|
|
49
|
+
}
|
|
50
|
+
interface PresencePayload {
|
|
51
|
+
from: string;
|
|
52
|
+
unavailable: boolean;
|
|
53
|
+
lastSeen?: number;
|
|
54
|
+
}
|
|
55
|
+
interface ChatPresencePayload {
|
|
56
|
+
from: string;
|
|
57
|
+
chatJID: string;
|
|
58
|
+
state: "composing" | "paused";
|
|
59
|
+
media?: "audio";
|
|
60
|
+
}
|
|
61
|
+
interface ContactUpdatePayload {
|
|
62
|
+
jid: string;
|
|
63
|
+
username: string;
|
|
64
|
+
}
|
|
65
|
+
interface DisconnectedPayload {
|
|
66
|
+
reason?: string;
|
|
67
|
+
}
|
|
68
|
+
/** Same shape for the account ban and for the reach-out timelock. */
|
|
69
|
+
interface TemporaryBanPayload {
|
|
70
|
+
reason?: string;
|
|
71
|
+
code?: number;
|
|
72
|
+
active: boolean;
|
|
73
|
+
restrictedUntil?: string;
|
|
74
|
+
enforcementType?: string;
|
|
75
|
+
}
|
|
76
|
+
interface RestrictionLiftedPayload {
|
|
77
|
+
active: false;
|
|
78
|
+
enforcementType?: string;
|
|
79
|
+
restrictedUntil?: string;
|
|
80
|
+
}
|
|
81
|
+
interface ContactReachoutLockedPayload {
|
|
82
|
+
to: string;
|
|
83
|
+
reason: string;
|
|
84
|
+
detail: string;
|
|
85
|
+
code: number;
|
|
86
|
+
}
|
|
87
|
+
/** Discriminated by `type`, so a switch narrows the payload. */
|
|
88
|
+
type WebhookEvent = WebhookEnvelope<"message", MessagePayload> | WebhookEnvelope<"receipt", ReceiptPayload> | WebhookEnvelope<"presence", PresencePayload> | WebhookEnvelope<"chat_presence", ChatPresencePayload> | WebhookEnvelope<"reaction", Record<string, unknown>> | WebhookEnvelope<"contact_update", ContactUpdatePayload> | WebhookEnvelope<"connected", Record<string, unknown>> | WebhookEnvelope<"disconnected", DisconnectedPayload> | WebhookEnvelope<"temporary_ban", TemporaryBanPayload> | WebhookEnvelope<"restriction_lifted", RestrictionLiftedPayload> | WebhookEnvelope<"contact_reachout_locked", ContactReachoutLockedPayload> | WebhookEnvelope<"unknown", Record<string, unknown>>;
|
|
89
|
+
|
|
90
|
+
export type { ChatPresencePayload as C, DisconnectedPayload as D, MessageButton as M, PresencePayload as P, ReceiptPayload as R, TemporaryBanPayload as T, WebhookEnvelope as W, ContactReachoutLockedPayload as a, ContactUpdatePayload as b, MessagePayload as c, RestrictionLiftedPayload as d, WebhookEvent as e, WebhookEventType as f };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 12 event types the apime delivers. `ignore` is internal and never
|
|
3
|
+
* reaches a consumer, so it is not part of the union.
|
|
4
|
+
*/
|
|
5
|
+
type WebhookEventType = "message" | "receipt" | "presence" | "chat_presence" | "reaction" | "contact_update" | "connected" | "disconnected" | "temporary_ban" | "restriction_lifted" | "contact_reachout_locked" | "unknown";
|
|
6
|
+
interface WebhookEnvelope<T extends WebhookEventType = WebhookEventType, P = unknown> {
|
|
7
|
+
id: string;
|
|
8
|
+
instanceId: string;
|
|
9
|
+
type: T;
|
|
10
|
+
payload: P;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
/** Button of an interactive message. `call`, `copy`, `reply` and `url` are button kinds, not events. */
|
|
14
|
+
interface MessageButton {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
type: "reply" | "url" | "copy" | "call";
|
|
18
|
+
url?: string;
|
|
19
|
+
code?: string;
|
|
20
|
+
phone?: string;
|
|
21
|
+
}
|
|
22
|
+
interface MessagePayload {
|
|
23
|
+
from: string;
|
|
24
|
+
to: string;
|
|
25
|
+
isFromMe: boolean;
|
|
26
|
+
isGroup: boolean;
|
|
27
|
+
messageId: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
pushName?: string;
|
|
30
|
+
text?: string;
|
|
31
|
+
mediaType?: "image" | "video" | "audio" | "document" | "sticker" | "location" | "contact";
|
|
32
|
+
mediaUrl?: string;
|
|
33
|
+
mimetype?: string;
|
|
34
|
+
caption?: string;
|
|
35
|
+
buttons?: MessageButton[];
|
|
36
|
+
/**
|
|
37
|
+
* Present only when this event is an edit: the id of the message that was
|
|
38
|
+
* edited, and its new text. They always travel together, so checking one is
|
|
39
|
+
* enough to know it is an edit.
|
|
40
|
+
*/
|
|
41
|
+
editedMessageId?: string;
|
|
42
|
+
editedText?: string;
|
|
43
|
+
}
|
|
44
|
+
interface ReceiptPayload {
|
|
45
|
+
messageIds: string[];
|
|
46
|
+
timestamp: number;
|
|
47
|
+
chat: string;
|
|
48
|
+
status: "read" | "delivered" | "played";
|
|
49
|
+
}
|
|
50
|
+
interface PresencePayload {
|
|
51
|
+
from: string;
|
|
52
|
+
unavailable: boolean;
|
|
53
|
+
lastSeen?: number;
|
|
54
|
+
}
|
|
55
|
+
interface ChatPresencePayload {
|
|
56
|
+
from: string;
|
|
57
|
+
chatJID: string;
|
|
58
|
+
state: "composing" | "paused";
|
|
59
|
+
media?: "audio";
|
|
60
|
+
}
|
|
61
|
+
interface ContactUpdatePayload {
|
|
62
|
+
jid: string;
|
|
63
|
+
username: string;
|
|
64
|
+
}
|
|
65
|
+
interface DisconnectedPayload {
|
|
66
|
+
reason?: string;
|
|
67
|
+
}
|
|
68
|
+
/** Same shape for the account ban and for the reach-out timelock. */
|
|
69
|
+
interface TemporaryBanPayload {
|
|
70
|
+
reason?: string;
|
|
71
|
+
code?: number;
|
|
72
|
+
active: boolean;
|
|
73
|
+
restrictedUntil?: string;
|
|
74
|
+
enforcementType?: string;
|
|
75
|
+
}
|
|
76
|
+
interface RestrictionLiftedPayload {
|
|
77
|
+
active: false;
|
|
78
|
+
enforcementType?: string;
|
|
79
|
+
restrictedUntil?: string;
|
|
80
|
+
}
|
|
81
|
+
interface ContactReachoutLockedPayload {
|
|
82
|
+
to: string;
|
|
83
|
+
reason: string;
|
|
84
|
+
detail: string;
|
|
85
|
+
code: number;
|
|
86
|
+
}
|
|
87
|
+
/** Discriminated by `type`, so a switch narrows the payload. */
|
|
88
|
+
type WebhookEvent = WebhookEnvelope<"message", MessagePayload> | WebhookEnvelope<"receipt", ReceiptPayload> | WebhookEnvelope<"presence", PresencePayload> | WebhookEnvelope<"chat_presence", ChatPresencePayload> | WebhookEnvelope<"reaction", Record<string, unknown>> | WebhookEnvelope<"contact_update", ContactUpdatePayload> | WebhookEnvelope<"connected", Record<string, unknown>> | WebhookEnvelope<"disconnected", DisconnectedPayload> | WebhookEnvelope<"temporary_ban", TemporaryBanPayload> | WebhookEnvelope<"restriction_lifted", RestrictionLiftedPayload> | WebhookEnvelope<"contact_reachout_locked", ContactReachoutLockedPayload> | WebhookEnvelope<"unknown", Record<string, unknown>>;
|
|
89
|
+
|
|
90
|
+
export type { ChatPresencePayload as C, DisconnectedPayload as D, MessageButton as M, PresencePayload as P, ReceiptPayload as R, TemporaryBanPayload as T, WebhookEnvelope as W, ContactReachoutLockedPayload as a, ContactUpdatePayload as b, MessagePayload as c, RestrictionLiftedPayload as d, WebhookEvent as e, WebhookEventType as f };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { e as WebhookEvent } from './events-BV5UVoFu.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One class per condition, so callers branch on the error instead of parsing
|
|
5
|
+
* status codes. Mirrors what the apime returns.
|
|
6
|
+
*/
|
|
7
|
+
declare class ApimeError extends Error {
|
|
8
|
+
readonly status: number | undefined;
|
|
9
|
+
readonly body: unknown;
|
|
10
|
+
/** Value of the request id header, when the response carried one. */
|
|
11
|
+
readonly requestId: string | undefined;
|
|
12
|
+
constructor(message: string, options?: {
|
|
13
|
+
status?: number;
|
|
14
|
+
body?: unknown;
|
|
15
|
+
requestId?: string;
|
|
16
|
+
cause?: unknown;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/** 401: token missing, malformed or unknown. */
|
|
20
|
+
declare class AuthenticationError extends ApimeError {
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 403: the token is valid but not for this. Most often an instance route
|
|
24
|
+
* reached with a user token, or a token from another instance.
|
|
25
|
+
*/
|
|
26
|
+
declare class PermissionError extends ApimeError {
|
|
27
|
+
}
|
|
28
|
+
/** 404. */
|
|
29
|
+
declare class NotFoundError extends ApimeError {
|
|
30
|
+
}
|
|
31
|
+
/** 409: another request with the same Idempotency-Key is still running. */
|
|
32
|
+
declare class ConflictError extends ApimeError {
|
|
33
|
+
}
|
|
34
|
+
/** 422: rejected payload, or an Idempotency-Key reused with different content. */
|
|
35
|
+
declare class UnprocessableError extends ApimeError {
|
|
36
|
+
}
|
|
37
|
+
/** 429: rate limited. `retryAfterMs` comes from the Retry-After header. */
|
|
38
|
+
declare class RateLimitError extends ApimeError {
|
|
39
|
+
readonly retryAfterMs: number | undefined;
|
|
40
|
+
constructor(message: string, options?: {
|
|
41
|
+
status?: number;
|
|
42
|
+
body?: unknown;
|
|
43
|
+
requestId?: string;
|
|
44
|
+
retryAfterMs?: number;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/** 400 and other client-side rejections. */
|
|
48
|
+
declare class InvalidRequestError extends ApimeError {
|
|
49
|
+
}
|
|
50
|
+
/** 5xx. */
|
|
51
|
+
declare class ApiError extends ApimeError {
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 503: the instance session is not ready. Nothing was sent, so this is safe to
|
|
55
|
+
* retry, including with the same Idempotency-Key.
|
|
56
|
+
*/
|
|
57
|
+
declare class SessionUnavailableError extends ApiError {
|
|
58
|
+
}
|
|
59
|
+
/** The request never got an answer: DNS, refused connection, socket reset. */
|
|
60
|
+
declare class ConnectionError extends ApimeError {
|
|
61
|
+
}
|
|
62
|
+
/** The request was aborted by the configured timeout. */
|
|
63
|
+
declare class TimeoutError extends ConnectionError {
|
|
64
|
+
}
|
|
65
|
+
/** Raised before any request when the configured base URL is unusable. */
|
|
66
|
+
declare class ConfigurationError extends ApimeError {
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
declare const SIGNATURE_HEADER = "X-ApiMe-Signature";
|
|
70
|
+
declare class InvalidSignatureError extends ApimeError {
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Verifies against the raw body, never a re-serialized object: JSON.stringify
|
|
74
|
+
* of a parsed payload reorders keys and the HMAC stops matching.
|
|
75
|
+
*/
|
|
76
|
+
declare function verifyWebhookSignature(rawBody: string | Buffer, signature: string | undefined, secret: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Checks the signature and returns the typed event, or throws. Same shape as
|
|
79
|
+
* the Stripe helper, so the raw-body requirement is the only thing to remember.
|
|
80
|
+
*/
|
|
81
|
+
declare function constructEvent(rawBody: string | Buffer, signature: string | undefined, secret: string): WebhookEvent;
|
|
82
|
+
|
|
83
|
+
export { ApimeError as A, ConfigurationError as C, InvalidRequestError as I, NotFoundError as N, PermissionError as P, RateLimitError as R, SessionUnavailableError as S, TimeoutError as T, UnprocessableError as U, ApiError as a, AuthenticationError as b, ConflictError as c, ConnectionError as d, InvalidSignatureError as e, constructEvent as f, SIGNATURE_HEADER as g, verifyWebhookSignature as v };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { e as WebhookEvent } from './events-BV5UVoFu.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One class per condition, so callers branch on the error instead of parsing
|
|
5
|
+
* status codes. Mirrors what the apime returns.
|
|
6
|
+
*/
|
|
7
|
+
declare class ApimeError extends Error {
|
|
8
|
+
readonly status: number | undefined;
|
|
9
|
+
readonly body: unknown;
|
|
10
|
+
/** Value of the request id header, when the response carried one. */
|
|
11
|
+
readonly requestId: string | undefined;
|
|
12
|
+
constructor(message: string, options?: {
|
|
13
|
+
status?: number;
|
|
14
|
+
body?: unknown;
|
|
15
|
+
requestId?: string;
|
|
16
|
+
cause?: unknown;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/** 401: token missing, malformed or unknown. */
|
|
20
|
+
declare class AuthenticationError extends ApimeError {
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 403: the token is valid but not for this. Most often an instance route
|
|
24
|
+
* reached with a user token, or a token from another instance.
|
|
25
|
+
*/
|
|
26
|
+
declare class PermissionError extends ApimeError {
|
|
27
|
+
}
|
|
28
|
+
/** 404. */
|
|
29
|
+
declare class NotFoundError extends ApimeError {
|
|
30
|
+
}
|
|
31
|
+
/** 409: another request with the same Idempotency-Key is still running. */
|
|
32
|
+
declare class ConflictError extends ApimeError {
|
|
33
|
+
}
|
|
34
|
+
/** 422: rejected payload, or an Idempotency-Key reused with different content. */
|
|
35
|
+
declare class UnprocessableError extends ApimeError {
|
|
36
|
+
}
|
|
37
|
+
/** 429: rate limited. `retryAfterMs` comes from the Retry-After header. */
|
|
38
|
+
declare class RateLimitError extends ApimeError {
|
|
39
|
+
readonly retryAfterMs: number | undefined;
|
|
40
|
+
constructor(message: string, options?: {
|
|
41
|
+
status?: number;
|
|
42
|
+
body?: unknown;
|
|
43
|
+
requestId?: string;
|
|
44
|
+
retryAfterMs?: number;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/** 400 and other client-side rejections. */
|
|
48
|
+
declare class InvalidRequestError extends ApimeError {
|
|
49
|
+
}
|
|
50
|
+
/** 5xx. */
|
|
51
|
+
declare class ApiError extends ApimeError {
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 503: the instance session is not ready. Nothing was sent, so this is safe to
|
|
55
|
+
* retry, including with the same Idempotency-Key.
|
|
56
|
+
*/
|
|
57
|
+
declare class SessionUnavailableError extends ApiError {
|
|
58
|
+
}
|
|
59
|
+
/** The request never got an answer: DNS, refused connection, socket reset. */
|
|
60
|
+
declare class ConnectionError extends ApimeError {
|
|
61
|
+
}
|
|
62
|
+
/** The request was aborted by the configured timeout. */
|
|
63
|
+
declare class TimeoutError extends ConnectionError {
|
|
64
|
+
}
|
|
65
|
+
/** Raised before any request when the configured base URL is unusable. */
|
|
66
|
+
declare class ConfigurationError extends ApimeError {
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
declare const SIGNATURE_HEADER = "X-ApiMe-Signature";
|
|
70
|
+
declare class InvalidSignatureError extends ApimeError {
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Verifies against the raw body, never a re-serialized object: JSON.stringify
|
|
74
|
+
* of a parsed payload reorders keys and the HMAC stops matching.
|
|
75
|
+
*/
|
|
76
|
+
declare function verifyWebhookSignature(rawBody: string | Buffer, signature: string | undefined, secret: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Checks the signature and returns the typed event, or throws. Same shape as
|
|
79
|
+
* the Stripe helper, so the raw-body requirement is the only thing to remember.
|
|
80
|
+
*/
|
|
81
|
+
declare function constructEvent(rawBody: string | Buffer, signature: string | undefined, secret: string): WebhookEvent;
|
|
82
|
+
|
|
83
|
+
export { ApimeError as A, ConfigurationError as C, InvalidRequestError as I, NotFoundError as N, PermissionError as P, RateLimitError as R, SessionUnavailableError as S, TimeoutError as T, UnprocessableError as U, ApiError as a, AuthenticationError as b, ConflictError as c, ConnectionError as d, InvalidSignatureError as e, constructEvent as f, SIGNATURE_HEADER as g, verifyWebhookSignature as v };
|