@sendora/sdk 1.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/README.md +364 -0
- package/dist/base64.d.ts +3 -0
- package/dist/base64.d.ts.map +1 -0
- package/dist/base64.js +17 -0
- package/dist/base64.js.map +1 -0
- package/dist/broadcasts.d.ts +60 -0
- package/dist/broadcasts.d.ts.map +1 -0
- package/dist/broadcasts.js +98 -0
- package/dist/broadcasts.js.map +1 -0
- package/dist/client.d.ts +51 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +69 -0
- package/dist/client.js.map +1 -0
- package/dist/domains.d.ts +34 -0
- package/dist/domains.d.ts.map +1 -0
- package/dist/domains.js +70 -0
- package/dist/domains.js.map +1 -0
- package/dist/email.d.ts +40 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +68 -0
- package/dist/email.js.map +1 -0
- package/dist/error.d.ts +67 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +173 -0
- package/dist/error.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/messages.d.ts +37 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +68 -0
- package/dist/messages.js.map +1 -0
- package/dist/pagination.d.ts +3 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +14 -0
- package/dist/pagination.js.map +1 -0
- package/dist/retry.d.ts +6 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +14 -0
- package/dist/retry.js.map +1 -0
- package/dist/streams.d.ts +45 -0
- package/dist/streams.d.ts.map +1 -0
- package/dist/streams.js +82 -0
- package/dist/streams.js.map +1 -0
- package/dist/suppressions.d.ts +37 -0
- package/dist/suppressions.d.ts.map +1 -0
- package/dist/suppressions.js +56 -0
- package/dist/suppressions.js.map +1 -0
- package/dist/tokens.d.ts +28 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +57 -0
- package/dist/tokens.js.map +1 -0
- package/dist/transport.d.ts +34 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +146 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +802 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/webhook-verify.d.ts +33 -0
- package/dist/webhook-verify.d.ts.map +1 -0
- package/dist/webhook-verify.js +115 -0
- package/dist/webhook-verify.js.map +1 -0
- package/dist/webhooks.d.ts +63 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +118 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +49 -0
- package/skills/sendora/SKILL.md +86 -0
- package/src/base64.ts +17 -0
- package/src/broadcasts.ts +115 -0
- package/src/client.ts +88 -0
- package/src/domains.ts +84 -0
- package/src/email.ts +83 -0
- package/src/error.ts +252 -0
- package/src/index.ts +16 -0
- package/src/messages.ts +88 -0
- package/src/pagination.ts +18 -0
- package/src/retry.ts +20 -0
- package/src/streams.ts +100 -0
- package/src/suppressions.ts +73 -0
- package/src/tokens.ts +70 -0
- package/src/transport.ts +179 -0
- package/src/types.ts +848 -0
- package/src/version.ts +2 -0
- package/src/webhook-verify.ts +147 -0
- package/src/webhooks.ts +157 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { DomainsResource } from "./domains.js";
|
|
2
|
+
import { BroadcastsResource } from "./broadcasts.js";
|
|
3
|
+
import { EmailResource } from "./email.js";
|
|
4
|
+
import { MessagesResource } from "./messages.js";
|
|
5
|
+
import { DEFAULT_MAX_RETRIES } from "./retry.js";
|
|
6
|
+
import { StreamsResource } from "./streams.js";
|
|
7
|
+
import { SuppressionsResource } from "./suppressions.js";
|
|
8
|
+
import { TokensResource } from "./tokens.js";
|
|
9
|
+
import { Transport } from "./transport.js";
|
|
10
|
+
import { SDK_VERSION } from "./version.js";
|
|
11
|
+
import { WebhooksResource } from "./webhooks.js";
|
|
12
|
+
export const DEFAULT_BASE_URL = 'https://api.sendora.se';
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
14
|
+
/**
|
|
15
|
+
* The client. One instance per server token; every resource hangs off it.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* import { Sendora } from '@sendora/sdk';
|
|
19
|
+
*
|
|
20
|
+
* const sendora = new Sendora({ token: process.env.SENDORA_API_TOKEN });
|
|
21
|
+
* const { messageId } = await sendora.email.send({
|
|
22
|
+
* from: 'no-reply@example.se',
|
|
23
|
+
* to: ['anna@example.com'],
|
|
24
|
+
* subject: 'Välkommen',
|
|
25
|
+
* text: 'Hej Anna!',
|
|
26
|
+
* });
|
|
27
|
+
*/
|
|
28
|
+
export class Sendora {
|
|
29
|
+
email;
|
|
30
|
+
broadcasts;
|
|
31
|
+
messages;
|
|
32
|
+
streams;
|
|
33
|
+
suppressions;
|
|
34
|
+
tokens;
|
|
35
|
+
webhooks;
|
|
36
|
+
domains;
|
|
37
|
+
constructor(options) {
|
|
38
|
+
if (options.token === undefined || options.token.trim() === '') {
|
|
39
|
+
throw new TypeError('Sendora needs a server API token; create one in the dashboard.');
|
|
40
|
+
}
|
|
41
|
+
const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
42
|
+
new URL(baseUrl);
|
|
43
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
44
|
+
if (!(timeoutMs > 0)) {
|
|
45
|
+
throw new TypeError('timeoutMs must be a positive number of milliseconds.');
|
|
46
|
+
}
|
|
47
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
48
|
+
if (!Number.isInteger(maxRetries) || maxRetries < 0) {
|
|
49
|
+
throw new TypeError('maxRetries must be a whole number of zero or more.');
|
|
50
|
+
}
|
|
51
|
+
const transport = new Transport({
|
|
52
|
+
baseUrl,
|
|
53
|
+
token: options.token,
|
|
54
|
+
fetch: options.fetch ?? fetch,
|
|
55
|
+
timeoutMs,
|
|
56
|
+
maxRetries,
|
|
57
|
+
userAgent: `sendora-sdk/${SDK_VERSION}`,
|
|
58
|
+
});
|
|
59
|
+
this.email = new EmailResource(transport);
|
|
60
|
+
this.broadcasts = new BroadcastsResource(transport);
|
|
61
|
+
this.messages = new MessagesResource(transport);
|
|
62
|
+
this.streams = new StreamsResource(transport);
|
|
63
|
+
this.suppressions = new SuppressionsResource(transport);
|
|
64
|
+
this.tokens = new TokensResource(transport);
|
|
65
|
+
this.webhooks = new WebhooksResource(transport);
|
|
66
|
+
this.domains = new DomainsResource(transport);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,CAAC,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AACzD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAmBlC;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,OAAO;IACT,KAAK,CAAgB;IACrB,UAAU,CAAqB;IAC/B,QAAQ,CAAmB;IAC3B,OAAO,CAAkB;IACzB,YAAY,CAAuB;IACnC,MAAM,CAAiB;IACvB,QAAQ,CAAmB;IAC3B,OAAO,CAAkB;IAElC,YAAY,OAAuB;QACjC,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/D,MAAM,IAAI,SAAS,CAAC,gEAAgE,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;QACpD,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QACjB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;QAC1D,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,sDAAsD,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAC;QAC5E,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;YAC9B,OAAO;YACP,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;YAC7B,SAAS;YACT,UAAU;YACV,SAAS,EAAE,eAAe,WAAW,EAAE;SACxC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,IAAI,cAAc,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Transport } from './transport.ts';
|
|
2
|
+
import type { CreateDomainRequest, DomainList, RequestOptions, SendingDomain, VerifiedDomain } from './types.ts';
|
|
3
|
+
/** The account's sending domains and the two DNS records each one needs. Any server's token manages them. */
|
|
4
|
+
export declare class DomainsResource {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(transport: Transport);
|
|
7
|
+
/**
|
|
8
|
+
* Adds a domain with its own DKIM key and answers the two records to
|
|
9
|
+
* create: a CNAME for the return path and a TXT record for the DKIM key.
|
|
10
|
+
* Mail may go out once both are seen. `domain_exists` carries the id of
|
|
11
|
+
* the domain the account already has as `existingId`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const domain = await sendora.domains.create({ domain: 'example.se' });
|
|
15
|
+
* console.log(domain.returnPath.host, domain.returnPath.value);
|
|
16
|
+
* console.log(domain.dkim.host, domain.dkim.value);
|
|
17
|
+
*/
|
|
18
|
+
create(request: CreateDomainRequest, options?: RequestOptions): Promise<SendingDomain>;
|
|
19
|
+
/** Every sending domain of the account. */
|
|
20
|
+
list(options?: RequestOptions): Promise<DomainList>;
|
|
21
|
+
/** One domain by id, with the state of its records. */
|
|
22
|
+
get(domainId: string, options?: RequestOptions): Promise<SendingDomain>;
|
|
23
|
+
/**
|
|
24
|
+
* Looks both records up now and answers the domain as it stands plus
|
|
25
|
+
* what each lookup found: `ok`, `missing`, `mismatch` or `dns_error`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* const { verified, check } = await sendora.domains.verify(domainId);
|
|
29
|
+
*/
|
|
30
|
+
verify(domainId: string, options?: RequestOptions): Promise<VerifiedDomain>;
|
|
31
|
+
/** Removes the domain; mail from it is refused from then on and its DKIM key is gone. */
|
|
32
|
+
delete(domainId: string, options?: RequestOptions): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=domains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.d.ts","sourceRoot":"","sources":["../src/domains.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,aAAa,EACb,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,6GAA6G;AAC7G,qBAAa,eAAe;;gBAGd,SAAS,EAAE,SAAS;IAIhC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAU1F,2CAA2C;IAC3C,IAAI,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,UAAU,CAAC;IASvD,uDAAuD;IACvD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAS3E;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAS/E,yFAAyF;IACzF,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;CAQtE"}
|
package/dist/domains.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** The account's sending domains and the two DNS records each one needs. Any server's token manages them. */
|
|
2
|
+
export class DomainsResource {
|
|
3
|
+
#transport;
|
|
4
|
+
constructor(transport) {
|
|
5
|
+
this.#transport = transport;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Adds a domain with its own DKIM key and answers the two records to
|
|
9
|
+
* create: a CNAME for the return path and a TXT record for the DKIM key.
|
|
10
|
+
* Mail may go out once both are seen. `domain_exists` carries the id of
|
|
11
|
+
* the domain the account already has as `existingId`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const domain = await sendora.domains.create({ domain: 'example.se' });
|
|
15
|
+
* console.log(domain.returnPath.host, domain.returnPath.value);
|
|
16
|
+
* console.log(domain.dkim.host, domain.dkim.value);
|
|
17
|
+
*/
|
|
18
|
+
create(request, options = {}) {
|
|
19
|
+
return this.#transport.request({
|
|
20
|
+
method: 'POST',
|
|
21
|
+
path: '/v1/domains',
|
|
22
|
+
body: request,
|
|
23
|
+
idempotent: false,
|
|
24
|
+
signal: options.signal,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Every sending domain of the account. */
|
|
28
|
+
list(options = {}) {
|
|
29
|
+
return this.#transport.request({
|
|
30
|
+
method: 'GET',
|
|
31
|
+
path: '/v1/domains',
|
|
32
|
+
idempotent: true,
|
|
33
|
+
signal: options.signal,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** One domain by id, with the state of its records. */
|
|
37
|
+
get(domainId, options = {}) {
|
|
38
|
+
return this.#transport.request({
|
|
39
|
+
method: 'GET',
|
|
40
|
+
path: `/v1/domains/${encodeURIComponent(domainId)}`,
|
|
41
|
+
idempotent: true,
|
|
42
|
+
signal: options.signal,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Looks both records up now and answers the domain as it stands plus
|
|
47
|
+
* what each lookup found: `ok`, `missing`, `mismatch` or `dns_error`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* const { verified, check } = await sendora.domains.verify(domainId);
|
|
51
|
+
*/
|
|
52
|
+
verify(domainId, options = {}) {
|
|
53
|
+
return this.#transport.request({
|
|
54
|
+
method: 'POST',
|
|
55
|
+
path: `/v1/domains/${encodeURIComponent(domainId)}/verify`,
|
|
56
|
+
idempotent: true,
|
|
57
|
+
signal: options.signal,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/** Removes the domain; mail from it is refused from then on and its DKIM key is gone. */
|
|
61
|
+
delete(domainId, options = {}) {
|
|
62
|
+
return this.#transport.request({
|
|
63
|
+
method: 'DELETE',
|
|
64
|
+
path: `/v1/domains/${encodeURIComponent(domainId)}`,
|
|
65
|
+
idempotent: true,
|
|
66
|
+
signal: options.signal,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.js","sourceRoot":"","sources":["../src/domains.ts"],"names":[],"mappings":"AASA,6GAA6G;AAC7G,MAAM,OAAO,eAAe;IACjB,UAAU,CAAY;IAE/B,YAAY,SAAoB;QAC9B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;OAUG;IACH,MAAM,CAAC,OAA4B,EAAE,UAA0B,EAAE;QAC/D,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAgB;YAC5C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED,2CAA2C;IAC3C,IAAI,CAAC,UAA0B,EAAE;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAa;YACzC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,aAAa;YACnB,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED,uDAAuD;IACvD,GAAG,CAAC,QAAgB,EAAE,UAA0B,EAAE;QAChD,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAgB;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,eAAe,kBAAkB,CAAC,QAAQ,CAAC,EAAE;YACnD,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,QAAgB,EAAE,UAA0B,EAAE;QACnD,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAiB;YAC7C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,eAAe,kBAAkB,CAAC,QAAQ,CAAC,SAAS;YAC1D,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED,yFAAyF;IACzF,MAAM,CAAC,QAAgB,EAAE,UAA0B,EAAE;QACnD,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAY;YACxC,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,eAAe,kBAAkB,CAAC,QAAQ,CAAC,EAAE;YACnD,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/dist/email.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Transport } from './transport.ts';
|
|
2
|
+
import type { AcceptedEmail, Attachment, BatchResult, EncodedAttachment, SendEmailBody, SendEmailRequest, SendOptions } from './types.ts';
|
|
3
|
+
/** Hands messages over for delivery, one at a time or up to 100 in a batch. */
|
|
4
|
+
export declare class EmailResource {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(transport: Transport);
|
|
7
|
+
/**
|
|
8
|
+
* Sends one message and answers at once with its id. Delivery, deferral,
|
|
9
|
+
* bounce and complaint arrive later as events on the message and as
|
|
10
|
+
* webhooks. Every send carries an idempotency key, yours or a random one,
|
|
11
|
+
* so the SDK's retries can never send twice.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const { messageId } = await sendora.email.send({
|
|
15
|
+
* from: { email: 'no-reply@example.se', name: 'Example AB' },
|
|
16
|
+
* to: ['anna@example.com'],
|
|
17
|
+
* subject: 'Din faktura för september',
|
|
18
|
+
* text: 'Hej Anna, fakturan finns bifogad.',
|
|
19
|
+
* attachments: [{ name: 'faktura.pdf', content: pdfBytes, contentType: 'application/pdf' }],
|
|
20
|
+
* tag: 'invoice',
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
send(request: SendEmailRequest, options?: SendOptions): Promise<AcceptedEmail>;
|
|
24
|
+
/**
|
|
25
|
+
* Sends up to 100 messages and answers one result per message, in order:
|
|
26
|
+
* accepted with its id, or refused with the same error a single send
|
|
27
|
+
* would give. The batch as a whole never fails halfway, so read
|
|
28
|
+
* `results[i].status`. A retry under the same key sends nothing twice:
|
|
29
|
+
* items accepted before come back with `replayed` set.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const { results } = await sendora.email.sendBatch(messages, { idempotencyKey: 'invoices-2026-09' });
|
|
33
|
+
* const refused = results.filter((result) => result.status === 'error');
|
|
34
|
+
*/
|
|
35
|
+
sendBatch(messages: SendEmailRequest[], options?: SendOptions): Promise<BatchResult>;
|
|
36
|
+
}
|
|
37
|
+
/** The body as the API takes it: attachment bytes become base64, everything else is passed through. */
|
|
38
|
+
export declare function encodeSendRequest(request: SendEmailRequest): SendEmailBody;
|
|
39
|
+
export declare function encodeAttachment(attachment: Attachment): EncodedAttachment;
|
|
40
|
+
//# sourceMappingURL=email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,+EAA+E;AAC/E,qBAAa,aAAa;;gBAGZ,SAAS,EAAE,SAAS;IAIhC;;;;;;;;;;;;;;;OAeG;IACH,IAAI,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,aAAa,CAAC;IAWlF;;;;;;;;;;OAUG;IACH,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;CAUzF;AAED,uGAAuG;AACvG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAM1E;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,iBAAiB,CAG1E"}
|
package/dist/email.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { toBase64 } from "./base64.js";
|
|
2
|
+
/** Hands messages over for delivery, one at a time or up to 100 in a batch. */
|
|
3
|
+
export class EmailResource {
|
|
4
|
+
#transport;
|
|
5
|
+
constructor(transport) {
|
|
6
|
+
this.#transport = transport;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Sends one message and answers at once with its id. Delivery, deferral,
|
|
10
|
+
* bounce and complaint arrive later as events on the message and as
|
|
11
|
+
* webhooks. Every send carries an idempotency key, yours or a random one,
|
|
12
|
+
* so the SDK's retries can never send twice.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const { messageId } = await sendora.email.send({
|
|
16
|
+
* from: { email: 'no-reply@example.se', name: 'Example AB' },
|
|
17
|
+
* to: ['anna@example.com'],
|
|
18
|
+
* subject: 'Din faktura för september',
|
|
19
|
+
* text: 'Hej Anna, fakturan finns bifogad.',
|
|
20
|
+
* attachments: [{ name: 'faktura.pdf', content: pdfBytes, contentType: 'application/pdf' }],
|
|
21
|
+
* tag: 'invoice',
|
|
22
|
+
* });
|
|
23
|
+
*/
|
|
24
|
+
send(request, options = {}) {
|
|
25
|
+
return this.#transport.request({
|
|
26
|
+
method: 'POST',
|
|
27
|
+
path: '/v1/email',
|
|
28
|
+
body: encodeSendRequest(request),
|
|
29
|
+
headers: { 'idempotency-key': options.idempotencyKey ?? crypto.randomUUID() },
|
|
30
|
+
idempotent: true,
|
|
31
|
+
signal: options.signal,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sends up to 100 messages and answers one result per message, in order:
|
|
36
|
+
* accepted with its id, or refused with the same error a single send
|
|
37
|
+
* would give. The batch as a whole never fails halfway, so read
|
|
38
|
+
* `results[i].status`. A retry under the same key sends nothing twice:
|
|
39
|
+
* items accepted before come back with `replayed` set.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const { results } = await sendora.email.sendBatch(messages, { idempotencyKey: 'invoices-2026-09' });
|
|
43
|
+
* const refused = results.filter((result) => result.status === 'error');
|
|
44
|
+
*/
|
|
45
|
+
sendBatch(messages, options = {}) {
|
|
46
|
+
return this.#transport.request({
|
|
47
|
+
method: 'POST',
|
|
48
|
+
path: '/v1/email/batch',
|
|
49
|
+
body: messages.map(encodeSendRequest),
|
|
50
|
+
headers: { 'idempotency-key': options.idempotencyKey ?? crypto.randomUUID() },
|
|
51
|
+
idempotent: true,
|
|
52
|
+
signal: options.signal,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** The body as the API takes it: attachment bytes become base64, everything else is passed through. */
|
|
57
|
+
export function encodeSendRequest(request) {
|
|
58
|
+
const { attachments, ...fields } = request;
|
|
59
|
+
if (attachments === undefined) {
|
|
60
|
+
return fields;
|
|
61
|
+
}
|
|
62
|
+
return { ...fields, attachments: attachments.map(encodeAttachment) };
|
|
63
|
+
}
|
|
64
|
+
export function encodeAttachment(attachment) {
|
|
65
|
+
const { content, ...fields } = attachment;
|
|
66
|
+
return { ...fields, content: typeof content === 'string' ? content : toBase64(content) };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.js","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAYvC,+EAA+E;AAC/E,MAAM,OAAO,aAAa;IACf,UAAU,CAAY;IAE/B,YAAY,SAAoB;QAC9B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,IAAI,CAAC,OAAyB,EAAE,UAAuB,EAAE;QACvD,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAgB;YAC5C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC;YAChC,OAAO,EAAE,EAAE,iBAAiB,EAAE,OAAO,CAAC,cAAc,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE;YAC7E,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;OAUG;IACH,SAAS,CAAC,QAA4B,EAAE,UAAuB,EAAE;QAC/D,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAc;YAC1C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,iBAAiB;YACvB,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC;YACrC,OAAO,EAAE,EAAE,iBAAiB,EAAE,OAAO,CAAC,cAAc,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE;YAC7E,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;CACF;AAED,uGAAuG;AACvG,MAAM,UAAU,iBAAiB,CAAC,OAAyB;IACzD,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAAsB;IACrD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC;IAC1C,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;AAC3F,CAAC"}
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { LimitScope, SuppressedRecipient, ValidationIssue } from './types.ts';
|
|
2
|
+
/** Every code the API answers, the three the SDK raises when it never got a proper answer, and the two of the webhook verifier. */
|
|
3
|
+
export type SendoraErrorCode = 'invalid_request' | 'unauthorized' | 'payment_required' | 'tenant_paused' | 'tenant_not_active' | 'spam_complaint_locked' | 'unsubscribe_locked' | 'not_found' | 'domain_exists' | 'webhook_exists' | 'stream_exists' | 'inbound_stream_exists' | 'default_stream' | 'last_token' | 'request_too_large' | 'from_domain_not_verified' | 'stream_not_found' | 'stream_archived' | 'stream_paused' | 'stream_not_sendable' | 'stream_not_broadcast' | 'broadcast_not_enabled' | 'broadcast_not_open' | 'substitution_missing' | 'unsubscribe_placeholder_missing' | 'list_unsubscribe_reserved' | 'recipient_suppressed' | 'idempotency_key_mismatch' | 'idempotency_key_required' | 'rate_limited' | 'monthly_cap_reached' | 'sending_disabled' | 'connection_failed' | 'timeout' | 'unexpected_response' | 'invalid_signature' | 'stale_signature';
|
|
4
|
+
export interface SendoraErrorFields {
|
|
5
|
+
code: SendoraErrorCode;
|
|
6
|
+
message: string;
|
|
7
|
+
status: number | null;
|
|
8
|
+
retryAfter?: number | null;
|
|
9
|
+
scope?: LimitScope | null;
|
|
10
|
+
limit?: number | null;
|
|
11
|
+
cap?: number | null;
|
|
12
|
+
used?: number | null;
|
|
13
|
+
resetsAt?: string | null;
|
|
14
|
+
issues?: ValidationIssue[];
|
|
15
|
+
suppressed?: SuppressedRecipient[];
|
|
16
|
+
streamId?: string | null;
|
|
17
|
+
existingId?: string | null;
|
|
18
|
+
cause?: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* What every failed call throws. Narrow on `code`; the other fields are
|
|
22
|
+
* filled where the API gives them and null or empty otherwise. Neither the
|
|
23
|
+
* token nor the request body is ever part of it.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* try {
|
|
27
|
+
* await sendora.email.send(message);
|
|
28
|
+
* } catch (error) {
|
|
29
|
+
* if (error instanceof SendoraError && error.code === 'recipient_suppressed') {
|
|
30
|
+
* console.log(error.suppressed.map((entry) => entry.address));
|
|
31
|
+
* } else {
|
|
32
|
+
* throw error;
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
*/
|
|
36
|
+
export declare class SendoraError extends Error {
|
|
37
|
+
readonly name = "SendoraError";
|
|
38
|
+
readonly code: SendoraErrorCode;
|
|
39
|
+
/** The HTTP status, or null when no answer arrived. */
|
|
40
|
+
readonly status: number | null;
|
|
41
|
+
/** Seconds to wait before trying again, when the API said so. */
|
|
42
|
+
readonly retryAfter: number | null;
|
|
43
|
+
/** Whose limit or cap it is, on rate_limited and monthly_cap_reached. */
|
|
44
|
+
readonly scope: LimitScope | null;
|
|
45
|
+
/** Emails per minute allowed for that scope, on rate_limited. */
|
|
46
|
+
readonly limit: number | null;
|
|
47
|
+
/** The monthly cap and what was used of it, on monthly_cap_reached. */
|
|
48
|
+
readonly cap: number | null;
|
|
49
|
+
readonly used: number | null;
|
|
50
|
+
/** When the month counter resets, on monthly_cap_reached. */
|
|
51
|
+
readonly resetsAt: string | null;
|
|
52
|
+
/** One entry per invalid field, on invalid_request. */
|
|
53
|
+
readonly issues: ValidationIssue[];
|
|
54
|
+
/** The recipients the server refused, on recipient_suppressed. */
|
|
55
|
+
readonly suppressed: SuppressedRecipient[];
|
|
56
|
+
/** The stream whose suppression list refused the send, on recipient_suppressed. */
|
|
57
|
+
readonly streamId: string | null;
|
|
58
|
+
/** The id of the domain, webhook or stream that already exists, on domain_exists, webhook_exists and stream_exists. */
|
|
59
|
+
readonly existingId: string | null;
|
|
60
|
+
constructor(fields: SendoraErrorFields);
|
|
61
|
+
/** True when waiting and calling again could succeed: a rate limit, sending paused for everyone, a lost connection, a timeout, or a server-side failure. */
|
|
62
|
+
get retryable(): boolean;
|
|
63
|
+
toJSON(): Record<string, unknown>;
|
|
64
|
+
}
|
|
65
|
+
/** The error a non-2xx answer amounts to; an answer without a known code is `unexpected_response`. */
|
|
66
|
+
export declare function errorFromAnswer(status: number, body: unknown, retryAfterHeader: string | null): SendoraError;
|
|
67
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEnF,mIAAmI;AACnI,MAAM,MAAM,gBAAgB,GACxB,iBAAiB,GACjB,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,uBAAuB,GACvB,oBAAoB,GACpB,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,uBAAuB,GACvB,gBAAgB,GAChB,YAAY,GACZ,mBAAmB,GACnB,0BAA0B,GAC1B,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,GACf,qBAAqB,GACrB,sBAAsB,GACtB,uBAAuB,GACvB,oBAAoB,GACpB,sBAAsB,GACtB,iCAAiC,GACjC,2BAA2B,GAC3B,sBAAsB,GACtB,0BAA0B,GAC1B,0BAA0B,GAC1B,cAAc,GACd,qBAAqB,GACrB,kBAAkB,GAClB,mBAAmB,GACnB,SAAS,GACT,qBAAqB,GACrB,mBAAmB,GACnB,iBAAiB,CAAC;AAqCtB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAkB,IAAI,kBAAkB;IACxC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAClC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;IACnC,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uHAAuH;IACvH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;gBAEvB,MAAM,EAAE,kBAAkB;IAgBtC,4JAA4J;IAC5J,IAAI,SAAS,IAAI,OAAO,CAQvB;IAED,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAkBlC;AAED,sGAAsG;AACtG,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAC9B,YAAY,CA0Bd"}
|
package/dist/error.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
const apiCodes = new Set([
|
|
2
|
+
'invalid_request',
|
|
3
|
+
'unauthorized',
|
|
4
|
+
'payment_required',
|
|
5
|
+
'tenant_paused',
|
|
6
|
+
'tenant_not_active',
|
|
7
|
+
'spam_complaint_locked',
|
|
8
|
+
'unsubscribe_locked',
|
|
9
|
+
'not_found',
|
|
10
|
+
'domain_exists',
|
|
11
|
+
'webhook_exists',
|
|
12
|
+
'stream_exists',
|
|
13
|
+
'inbound_stream_exists',
|
|
14
|
+
'default_stream',
|
|
15
|
+
'last_token',
|
|
16
|
+
'request_too_large',
|
|
17
|
+
'from_domain_not_verified',
|
|
18
|
+
'stream_not_found',
|
|
19
|
+
'stream_archived',
|
|
20
|
+
'stream_paused',
|
|
21
|
+
'stream_not_sendable',
|
|
22
|
+
'stream_not_broadcast',
|
|
23
|
+
'broadcast_not_enabled',
|
|
24
|
+
'broadcast_not_open',
|
|
25
|
+
'substitution_missing',
|
|
26
|
+
'unsubscribe_placeholder_missing',
|
|
27
|
+
'list_unsubscribe_reserved',
|
|
28
|
+
'recipient_suppressed',
|
|
29
|
+
'idempotency_key_mismatch',
|
|
30
|
+
'idempotency_key_required',
|
|
31
|
+
'rate_limited',
|
|
32
|
+
'monthly_cap_reached',
|
|
33
|
+
'sending_disabled',
|
|
34
|
+
]);
|
|
35
|
+
/**
|
|
36
|
+
* What every failed call throws. Narrow on `code`; the other fields are
|
|
37
|
+
* filled where the API gives them and null or empty otherwise. Neither the
|
|
38
|
+
* token nor the request body is ever part of it.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* try {
|
|
42
|
+
* await sendora.email.send(message);
|
|
43
|
+
* } catch (error) {
|
|
44
|
+
* if (error instanceof SendoraError && error.code === 'recipient_suppressed') {
|
|
45
|
+
* console.log(error.suppressed.map((entry) => entry.address));
|
|
46
|
+
* } else {
|
|
47
|
+
* throw error;
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
*/
|
|
51
|
+
export class SendoraError extends Error {
|
|
52
|
+
name = 'SendoraError';
|
|
53
|
+
code;
|
|
54
|
+
/** The HTTP status, or null when no answer arrived. */
|
|
55
|
+
status;
|
|
56
|
+
/** Seconds to wait before trying again, when the API said so. */
|
|
57
|
+
retryAfter;
|
|
58
|
+
/** Whose limit or cap it is, on rate_limited and monthly_cap_reached. */
|
|
59
|
+
scope;
|
|
60
|
+
/** Emails per minute allowed for that scope, on rate_limited. */
|
|
61
|
+
limit;
|
|
62
|
+
/** The monthly cap and what was used of it, on monthly_cap_reached. */
|
|
63
|
+
cap;
|
|
64
|
+
used;
|
|
65
|
+
/** When the month counter resets, on monthly_cap_reached. */
|
|
66
|
+
resetsAt;
|
|
67
|
+
/** One entry per invalid field, on invalid_request. */
|
|
68
|
+
issues;
|
|
69
|
+
/** The recipients the server refused, on recipient_suppressed. */
|
|
70
|
+
suppressed;
|
|
71
|
+
/** The stream whose suppression list refused the send, on recipient_suppressed. */
|
|
72
|
+
streamId;
|
|
73
|
+
/** The id of the domain, webhook or stream that already exists, on domain_exists, webhook_exists and stream_exists. */
|
|
74
|
+
existingId;
|
|
75
|
+
constructor(fields) {
|
|
76
|
+
super(fields.message, { cause: fields.cause });
|
|
77
|
+
this.code = fields.code;
|
|
78
|
+
this.status = fields.status;
|
|
79
|
+
this.retryAfter = fields.retryAfter ?? null;
|
|
80
|
+
this.scope = fields.scope ?? null;
|
|
81
|
+
this.limit = fields.limit ?? null;
|
|
82
|
+
this.cap = fields.cap ?? null;
|
|
83
|
+
this.used = fields.used ?? null;
|
|
84
|
+
this.resetsAt = fields.resetsAt ?? null;
|
|
85
|
+
this.issues = fields.issues ?? [];
|
|
86
|
+
this.suppressed = fields.suppressed ?? [];
|
|
87
|
+
this.streamId = fields.streamId ?? null;
|
|
88
|
+
this.existingId = fields.existingId ?? null;
|
|
89
|
+
}
|
|
90
|
+
/** True when waiting and calling again could succeed: a rate limit, sending paused for everyone, a lost connection, a timeout, or a server-side failure. */
|
|
91
|
+
get retryable() {
|
|
92
|
+
return (this.code === 'rate_limited' ||
|
|
93
|
+
this.code === 'sending_disabled' ||
|
|
94
|
+
this.code === 'connection_failed' ||
|
|
95
|
+
this.code === 'timeout' ||
|
|
96
|
+
(this.status !== null && this.status >= 500));
|
|
97
|
+
}
|
|
98
|
+
toJSON() {
|
|
99
|
+
return {
|
|
100
|
+
name: this.name,
|
|
101
|
+
code: this.code,
|
|
102
|
+
status: this.status,
|
|
103
|
+
message: this.message,
|
|
104
|
+
retryAfter: this.retryAfter,
|
|
105
|
+
scope: this.scope,
|
|
106
|
+
limit: this.limit,
|
|
107
|
+
cap: this.cap,
|
|
108
|
+
used: this.used,
|
|
109
|
+
resetsAt: this.resetsAt,
|
|
110
|
+
issues: this.issues,
|
|
111
|
+
suppressed: this.suppressed,
|
|
112
|
+
streamId: this.streamId,
|
|
113
|
+
existingId: this.existingId,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** The error a non-2xx answer amounts to; an answer without a known code is `unexpected_response`. */
|
|
118
|
+
export function errorFromAnswer(status, body, retryAfterHeader) {
|
|
119
|
+
const answer = isRecord(body) ? body : {};
|
|
120
|
+
const code = knownCode(answer.error);
|
|
121
|
+
const issues = Array.isArray(answer.issues) ? answer.issues.filter(isIssue) : [];
|
|
122
|
+
const message = typeof answer.message === 'string'
|
|
123
|
+
? answer.message
|
|
124
|
+
: code === 'invalid_request'
|
|
125
|
+
? `The request is invalid: ${issues.map((issue) => `${issue.path}: ${issue.message}`).join('; ')}`
|
|
126
|
+
: `The API answered ${String(status)} without an error body.`;
|
|
127
|
+
return new SendoraError({
|
|
128
|
+
code,
|
|
129
|
+
message,
|
|
130
|
+
status,
|
|
131
|
+
retryAfter: integerOf(answer.retryAfter) ?? integerOf(retryAfterHeader),
|
|
132
|
+
scope: answer.scope === 'tenant' || answer.scope === 'server' ? answer.scope : null,
|
|
133
|
+
limit: integerOf(answer.limit),
|
|
134
|
+
cap: integerOf(answer.cap),
|
|
135
|
+
used: integerOf(answer.used),
|
|
136
|
+
resetsAt: typeof answer.resetsAt === 'string' ? answer.resetsAt : null,
|
|
137
|
+
issues,
|
|
138
|
+
suppressed: Array.isArray(answer.suppressed) ? answer.suppressed.filter(isSuppressed) : [],
|
|
139
|
+
streamId: code === 'recipient_suppressed' ? stringOf(answer.streamId) : null,
|
|
140
|
+
existingId: stringOf(answer.domainId) ?? stringOf(answer.webhookId) ?? stringOf(answer.streamId),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
function stringOf(value) {
|
|
144
|
+
return typeof value === 'string' ? value : null;
|
|
145
|
+
}
|
|
146
|
+
function knownCode(value) {
|
|
147
|
+
return typeof value === 'string' && apiCodes.has(value)
|
|
148
|
+
? value
|
|
149
|
+
: 'unexpected_response';
|
|
150
|
+
}
|
|
151
|
+
function isRecord(value) {
|
|
152
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
153
|
+
}
|
|
154
|
+
function isIssue(value) {
|
|
155
|
+
return isRecord(value) && typeof value.path === 'string' && typeof value.message === 'string';
|
|
156
|
+
}
|
|
157
|
+
function isSuppressed(value) {
|
|
158
|
+
return (isRecord(value) &&
|
|
159
|
+
typeof value.address === 'string' &&
|
|
160
|
+
(value.reason === 'hard_bounce' ||
|
|
161
|
+
value.reason === 'spam_complaint' ||
|
|
162
|
+
value.reason === 'manual'));
|
|
163
|
+
}
|
|
164
|
+
function integerOf(value) {
|
|
165
|
+
if (typeof value === 'number' && Number.isInteger(value)) {
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
if (typeof value === 'string' && /^\d+$/.test(value)) {
|
|
169
|
+
return Number(value);
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { DEFAULT_BASE_URL, Sendora } from './client.ts';
|
|
2
|
+
export type { SendoraOptions } from './client.ts';
|
|
3
|
+
export type { BroadcastsResource } from './broadcasts.ts';
|
|
4
|
+
export type { DomainsResource } from './domains.ts';
|
|
5
|
+
export type { EmailResource } from './email.ts';
|
|
6
|
+
export { SendoraError } from './error.ts';
|
|
7
|
+
export type { SendoraErrorCode } from './error.ts';
|
|
8
|
+
export type { MessagesResource } from './messages.ts';
|
|
9
|
+
export type { StreamsResource } from './streams.ts';
|
|
10
|
+
export type { SuppressionsResource } from './suppressions.ts';
|
|
11
|
+
export type { TokensResource } from './tokens.ts';
|
|
12
|
+
export type * from './types.ts';
|
|
13
|
+
export { SDK_VERSION } from './version.ts';
|
|
14
|
+
export { verifyWebhook } from './webhook-verify.ts';
|
|
15
|
+
export type { VerifyWebhookInput } from './webhook-verify.ts';
|
|
16
|
+
export type { WebhooksResource } from './webhooks.ts';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Transport } from './transport.ts';
|
|
2
|
+
import type { Message, MessageDetail, MessagePage, MessageSearch, MessageSearchBody, RequestOptions } from './types.ts';
|
|
3
|
+
/** The message log of the token's server and each message's timeline. */
|
|
4
|
+
export declare class MessagesResource {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(transport: Transport);
|
|
7
|
+
/**
|
|
8
|
+
* One message as the log holds it: its recipients with their state, its
|
|
9
|
+
* attachments described, and every event on its timeline. Bodies are
|
|
10
|
+
* never returned.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const message = await sendora.messages.get(messageId);
|
|
14
|
+
* const delivered = message.recipients.every((recipient) => recipient.status === 'delivered');
|
|
15
|
+
*/
|
|
16
|
+
get(messageId: string, options?: RequestOptions): Promise<MessageDetail>;
|
|
17
|
+
/**
|
|
18
|
+
* One page of the log, newest first. Every filter is optional; pass the
|
|
19
|
+
* page's `next` as `after` for the following page, or use `searchAll`.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const page = await sendora.messages.search({ tag: 'invoice', status: 'bounced', limit: 20 });
|
|
23
|
+
*/
|
|
24
|
+
search(search?: MessageSearch, options?: RequestOptions): Promise<MessagePage>;
|
|
25
|
+
/**
|
|
26
|
+
* Every message the filters match, page by page, for `for await`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* for await (const message of sendora.messages.searchAll({ recipient: 'anna@example.com' })) {
|
|
30
|
+
* console.log(message.messageId, message.subject);
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
searchAll(search?: MessageSearch, options?: RequestOptions): AsyncIterable<Message>;
|
|
34
|
+
}
|
|
35
|
+
/** The body as the API takes it: times as ISO 8601 strings. */
|
|
36
|
+
export declare function encodeSearch(search: MessageSearch): MessageSearchBody;
|
|
37
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,OAAO,EACP,aAAa,EACb,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,yEAAyE;AACzE,qBAAa,gBAAgB;;gBAGf,SAAS,EAAE,SAAS;IAIhC;;;;;;;;OAQG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAS5E;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,GAAE,aAAkB,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IAUtF;;;;;;;OAOG;IACH,SAAS,CAAC,MAAM,GAAE,aAAkB,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CAAC,OAAO,CAAC;CAQ5F;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,iBAAiB,CAUrE"}
|