@drawbridge/drawbridge-utils 0.0.111 → 0.0.114
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/dist/connections/index.cjs +2286 -578
- package/dist/connections/index.d.cts +2012 -571
- package/dist/connections/index.d.ts +2012 -571
- package/dist/connections/index.js +2265 -572
- package/dist/connections/oauth.cjs +49 -50
- package/dist/connections/oauth.d.cts +83 -70
- package/dist/connections/oauth.d.ts +83 -70
- package/dist/connections/oauth.js +47 -47
- package/dist/safe-http.d.cts +1 -1
- package/dist/safe-http.d.ts +1 -1
- package/dist/sendgrid.cjs +168 -0
- package/dist/sendgrid.d.cts +185 -0
- package/dist/sendgrid.d.ts +185 -0
- package/dist/sendgrid.js +140 -0
- package/dist/twilio.cjs +112 -0
- package/dist/twilio.d.cts +64 -0
- package/dist/twilio.d.ts +64 -0
- package/dist/twilio.js +86 -0
- package/package.json +11 -1
package/dist/sendgrid.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// lib/http.js
|
|
2
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
3
|
+
var request = async ({
|
|
4
|
+
body,
|
|
5
|
+
headers = {},
|
|
6
|
+
method = "GET",
|
|
7
|
+
query,
|
|
8
|
+
timeout = DEFAULT_TIMEOUT_MS,
|
|
9
|
+
type = "json",
|
|
10
|
+
url
|
|
11
|
+
}) => {
|
|
12
|
+
const fullUrl = new URL(url);
|
|
13
|
+
if (query) {
|
|
14
|
+
Object.entries(query).forEach(([k, v]) => fullUrl.searchParams.set(k, v));
|
|
15
|
+
}
|
|
16
|
+
;
|
|
17
|
+
const isForm = type === "form";
|
|
18
|
+
const response = await fetch(fullUrl.toString(), {
|
|
19
|
+
method,
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": isForm ? "application/x-www-form-urlencoded" : "application/json",
|
|
22
|
+
...headers
|
|
23
|
+
},
|
|
24
|
+
signal: AbortSignal.timeout(timeout),
|
|
25
|
+
...body !== void 0 && {
|
|
26
|
+
body: isForm ? new URLSearchParams(body).toString() : JSON.stringify(body)
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const text2 = await response.text().catch(() => "");
|
|
31
|
+
const error = new Error(text2 || response.statusText);
|
|
32
|
+
error.status = response.status;
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
;
|
|
36
|
+
const text = await response.text();
|
|
37
|
+
try {
|
|
38
|
+
return text ? JSON.parse(text) : null;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// lib/sendgrid.js
|
|
45
|
+
import { createLogger } from "@drawbridge/drawbridge-telemetry";
|
|
46
|
+
var logger = createLogger();
|
|
47
|
+
var SENDGRID_BASE = "https://api.sendgrid.com";
|
|
48
|
+
var RETRYABLE_STATUSES = [429, 500, 502, 503];
|
|
49
|
+
var RETRY_DELAYS_MS = [1e3, 4e3];
|
|
50
|
+
var sendWithRetry = async (send, { delays = RETRY_DELAYS_MS } = {}) => {
|
|
51
|
+
for (let attempt = 0; ; attempt++) {
|
|
52
|
+
try {
|
|
53
|
+
return await send();
|
|
54
|
+
} catch (error) {
|
|
55
|
+
const status = Number(error == null ? void 0 : error.status);
|
|
56
|
+
const retryable = RETRYABLE_STATUSES.includes(status);
|
|
57
|
+
if (!retryable || attempt >= delays.length) {
|
|
58
|
+
if (!status) {
|
|
59
|
+
logger.warn("email.send.ambiguous-failure", {
|
|
60
|
+
name: error == null ? void 0 : error.name,
|
|
61
|
+
message: error == null ? void 0 : error.message
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
logger.info("email.send.retry", {
|
|
67
|
+
attempt: attempt + 1,
|
|
68
|
+
status,
|
|
69
|
+
delayMs: delays[attempt]
|
|
70
|
+
});
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var sendgridRequest = ({ apiKey, body, method, path, query, request: request2 = request }) => {
|
|
76
|
+
const key = apiKey || process.env.SENDGRID_API_KEY;
|
|
77
|
+
return request2({
|
|
78
|
+
body,
|
|
79
|
+
headers: {
|
|
80
|
+
"Authorization": "Bearer " + key
|
|
81
|
+
},
|
|
82
|
+
method,
|
|
83
|
+
query,
|
|
84
|
+
url: SENDGRID_BASE + path
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
var sendgrid = {
|
|
88
|
+
// `headers` (optional) carries the List-Unsubscribe pair on lead-facing
|
|
89
|
+
// commercial sends; omitted, the request body is byte-identical to the
|
|
90
|
+
// pre-opt-out-floor shape so system mail is untouched.
|
|
91
|
+
send: async ({ apiKey, from, headers, html, request: request2, subject, text, to }) => {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
try {
|
|
94
|
+
const sender = (from == null ? void 0 : from.email) ? from : {
|
|
95
|
+
email: process.env.SENDGRID_FROM_ADDRESS,
|
|
96
|
+
name: "Drawbridge"
|
|
97
|
+
};
|
|
98
|
+
await sendWithRetry(() => sendgridRequest({
|
|
99
|
+
apiKey,
|
|
100
|
+
...request2 && { request: request2 },
|
|
101
|
+
method: "POST",
|
|
102
|
+
path: "/v3/mail/send",
|
|
103
|
+
body: {
|
|
104
|
+
content: [
|
|
105
|
+
{
|
|
106
|
+
type: "text/plain",
|
|
107
|
+
value: text
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: "text/html",
|
|
111
|
+
value: html
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
from: sender,
|
|
115
|
+
...headers && { headers },
|
|
116
|
+
personalizations: [
|
|
117
|
+
{
|
|
118
|
+
to: [
|
|
119
|
+
{ email: to }
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
subject
|
|
124
|
+
}
|
|
125
|
+
}));
|
|
126
|
+
} catch (error) {
|
|
127
|
+
try {
|
|
128
|
+
const parsed = JSON.parse(error.message);
|
|
129
|
+
if ((_b = (_a = parsed == null ? void 0 : parsed.errors) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) error.message = parsed.errors[0].message;
|
|
130
|
+
} catch {
|
|
131
|
+
}
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
export {
|
|
137
|
+
sendWithRetry,
|
|
138
|
+
sendgrid,
|
|
139
|
+
sendgridRequest
|
|
140
|
+
};
|
package/dist/twilio.cjs
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// lib/twilio.js
|
|
20
|
+
var twilio_exports = {};
|
|
21
|
+
__export(twilio_exports, {
|
|
22
|
+
twilio: () => twilio
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(twilio_exports);
|
|
25
|
+
|
|
26
|
+
// lib/http.js
|
|
27
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
28
|
+
var request = async ({
|
|
29
|
+
body,
|
|
30
|
+
headers = {},
|
|
31
|
+
method = "GET",
|
|
32
|
+
query,
|
|
33
|
+
timeout = DEFAULT_TIMEOUT_MS,
|
|
34
|
+
type = "json",
|
|
35
|
+
url
|
|
36
|
+
}) => {
|
|
37
|
+
const fullUrl = new URL(url);
|
|
38
|
+
if (query) {
|
|
39
|
+
Object.entries(query).forEach(([k, v]) => fullUrl.searchParams.set(k, v));
|
|
40
|
+
}
|
|
41
|
+
;
|
|
42
|
+
const isForm = type === "form";
|
|
43
|
+
const response = await fetch(fullUrl.toString(), {
|
|
44
|
+
method,
|
|
45
|
+
headers: {
|
|
46
|
+
"Content-Type": isForm ? "application/x-www-form-urlencoded" : "application/json",
|
|
47
|
+
...headers
|
|
48
|
+
},
|
|
49
|
+
signal: AbortSignal.timeout(timeout),
|
|
50
|
+
...body !== void 0 && {
|
|
51
|
+
body: isForm ? new URLSearchParams(body).toString() : JSON.stringify(body)
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
const text2 = await response.text().catch(() => "");
|
|
56
|
+
const error = new Error(text2 || response.statusText);
|
|
57
|
+
error.status = response.status;
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
;
|
|
61
|
+
const text = await response.text();
|
|
62
|
+
try {
|
|
63
|
+
return text ? JSON.parse(text) : null;
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// lib/twilio.js
|
|
70
|
+
var twilio = {
|
|
71
|
+
sms: async ({
|
|
72
|
+
accountSid,
|
|
73
|
+
authToken,
|
|
74
|
+
from,
|
|
75
|
+
link,
|
|
76
|
+
message,
|
|
77
|
+
optOut = false,
|
|
78
|
+
prize,
|
|
79
|
+
// Injectable for the same reason sendgrid's is — see sendgrid.js.
|
|
80
|
+
request: request2 = request,
|
|
81
|
+
title,
|
|
82
|
+
to
|
|
83
|
+
}) => {
|
|
84
|
+
accountSid = accountSid || process.env.TWILIO_ACCOUNT_SID;
|
|
85
|
+
authToken = authToken || process.env.TWILIO_AUTH_TOKEN;
|
|
86
|
+
from = from || process.env.TWILIO_ACCOUNT_FROM;
|
|
87
|
+
const body = [
|
|
88
|
+
title,
|
|
89
|
+
message,
|
|
90
|
+
...prize ? [prize.title + " (" + prize.value + ")"] : [],
|
|
91
|
+
...link ? ["Verify here: " + link] : [],
|
|
92
|
+
...optOut ? ["Reply STOP to opt out"] : []
|
|
93
|
+
].filter(Boolean).join("\n");
|
|
94
|
+
return await request2({
|
|
95
|
+
method: "POST",
|
|
96
|
+
type: "form",
|
|
97
|
+
url: "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json",
|
|
98
|
+
headers: {
|
|
99
|
+
"Authorization": "Basic " + Buffer.from(accountSid + ":" + authToken).toString("base64")
|
|
100
|
+
},
|
|
101
|
+
body: {
|
|
102
|
+
Body: body,
|
|
103
|
+
From: from,
|
|
104
|
+
To: to
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
110
|
+
0 && (module.exports = {
|
|
111
|
+
twilio
|
|
112
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { request } from './http.cjs';
|
|
2
|
+
|
|
3
|
+
// TWILIO TRANSPORT. Vendor HTTP and nothing else, for the same reason SendGrid
|
|
4
|
+
// sits beside it — see sendgrid.js.
|
|
5
|
+
//
|
|
6
|
+
// The message COMPOSITION is here too, deliberately: the newline-separated
|
|
7
|
+
// shape, brand-first ordering and the absence of "Your prize is" / "Click here
|
|
8
|
+
// to verify" phrasing are carrier-filter avoidance that got these messages
|
|
9
|
+
// flagged once. That is a property of sending SMS, not of any one caller, and
|
|
10
|
+
// splitting it from the transport is how one caller quietly reverts it.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const twilio = {
|
|
14
|
+
|
|
15
|
+
sms : async ({
|
|
16
|
+
accountSid,
|
|
17
|
+
authToken,
|
|
18
|
+
from,
|
|
19
|
+
link,
|
|
20
|
+
message,
|
|
21
|
+
optOut = false,
|
|
22
|
+
prize,
|
|
23
|
+
// Injectable for the same reason sendgrid's is — see sendgrid.js.
|
|
24
|
+
request: request$1 = request,
|
|
25
|
+
title,
|
|
26
|
+
to
|
|
27
|
+
}) => {
|
|
28
|
+
|
|
29
|
+
accountSid = accountSid || process.env.TWILIO_ACCOUNT_SID;
|
|
30
|
+
authToken = authToken || process.env.TWILIO_AUTH_TOKEN;
|
|
31
|
+
from = from || process.env.TWILIO_ACCOUNT_FROM;
|
|
32
|
+
|
|
33
|
+
// Newline-separated, brand/title first, and no "Your prize is" /
|
|
34
|
+
// "Click here to verify your prize" phrasing — textbook carrier-filter
|
|
35
|
+
// bait that got these messages flagged. The opt-out line is appended
|
|
36
|
+
// on lead-facing sends (carrier compliance); OTC/auth sends pass
|
|
37
|
+
// nothing new and keep their exact copy.
|
|
38
|
+
const body = [
|
|
39
|
+
title,
|
|
40
|
+
message,
|
|
41
|
+
...( prize ? [ prize.title + ' (' + prize.value + ')' ] : [] ),
|
|
42
|
+
...( link ? [ 'Verify here: ' + link ] : [] ),
|
|
43
|
+
...( optOut ? [ 'Reply STOP to opt out' ] : [] )
|
|
44
|
+
].filter( Boolean ).join( '\n' );
|
|
45
|
+
|
|
46
|
+
return await request$1({
|
|
47
|
+
method : 'POST',
|
|
48
|
+
type : 'form',
|
|
49
|
+
url : 'https://api.twilio.com/2010-04-01/Accounts/' + accountSid + '/Messages.json',
|
|
50
|
+
headers : {
|
|
51
|
+
'Authorization' : 'Basic ' + Buffer.from( accountSid + ':' + authToken ).toString( 'base64' )
|
|
52
|
+
},
|
|
53
|
+
body : {
|
|
54
|
+
Body : body,
|
|
55
|
+
From : from,
|
|
56
|
+
To : to
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { twilio };
|
package/dist/twilio.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { request } from './http.js';
|
|
2
|
+
|
|
3
|
+
// TWILIO TRANSPORT. Vendor HTTP and nothing else, for the same reason SendGrid
|
|
4
|
+
// sits beside it — see sendgrid.js.
|
|
5
|
+
//
|
|
6
|
+
// The message COMPOSITION is here too, deliberately: the newline-separated
|
|
7
|
+
// shape, brand-first ordering and the absence of "Your prize is" / "Click here
|
|
8
|
+
// to verify" phrasing are carrier-filter avoidance that got these messages
|
|
9
|
+
// flagged once. That is a property of sending SMS, not of any one caller, and
|
|
10
|
+
// splitting it from the transport is how one caller quietly reverts it.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const twilio = {
|
|
14
|
+
|
|
15
|
+
sms : async ({
|
|
16
|
+
accountSid,
|
|
17
|
+
authToken,
|
|
18
|
+
from,
|
|
19
|
+
link,
|
|
20
|
+
message,
|
|
21
|
+
optOut = false,
|
|
22
|
+
prize,
|
|
23
|
+
// Injectable for the same reason sendgrid's is — see sendgrid.js.
|
|
24
|
+
request: request$1 = request,
|
|
25
|
+
title,
|
|
26
|
+
to
|
|
27
|
+
}) => {
|
|
28
|
+
|
|
29
|
+
accountSid = accountSid || process.env.TWILIO_ACCOUNT_SID;
|
|
30
|
+
authToken = authToken || process.env.TWILIO_AUTH_TOKEN;
|
|
31
|
+
from = from || process.env.TWILIO_ACCOUNT_FROM;
|
|
32
|
+
|
|
33
|
+
// Newline-separated, brand/title first, and no "Your prize is" /
|
|
34
|
+
// "Click here to verify your prize" phrasing — textbook carrier-filter
|
|
35
|
+
// bait that got these messages flagged. The opt-out line is appended
|
|
36
|
+
// on lead-facing sends (carrier compliance); OTC/auth sends pass
|
|
37
|
+
// nothing new and keep their exact copy.
|
|
38
|
+
const body = [
|
|
39
|
+
title,
|
|
40
|
+
message,
|
|
41
|
+
...( prize ? [ prize.title + ' (' + prize.value + ')' ] : [] ),
|
|
42
|
+
...( link ? [ 'Verify here: ' + link ] : [] ),
|
|
43
|
+
...( optOut ? [ 'Reply STOP to opt out' ] : [] )
|
|
44
|
+
].filter( Boolean ).join( '\n' );
|
|
45
|
+
|
|
46
|
+
return await request$1({
|
|
47
|
+
method : 'POST',
|
|
48
|
+
type : 'form',
|
|
49
|
+
url : 'https://api.twilio.com/2010-04-01/Accounts/' + accountSid + '/Messages.json',
|
|
50
|
+
headers : {
|
|
51
|
+
'Authorization' : 'Basic ' + Buffer.from( accountSid + ':' + authToken ).toString( 'base64' )
|
|
52
|
+
},
|
|
53
|
+
body : {
|
|
54
|
+
Body : body,
|
|
55
|
+
From : from,
|
|
56
|
+
To : to
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { twilio };
|
package/dist/twilio.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// lib/http.js
|
|
2
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
3
|
+
var request = async ({
|
|
4
|
+
body,
|
|
5
|
+
headers = {},
|
|
6
|
+
method = "GET",
|
|
7
|
+
query,
|
|
8
|
+
timeout = DEFAULT_TIMEOUT_MS,
|
|
9
|
+
type = "json",
|
|
10
|
+
url
|
|
11
|
+
}) => {
|
|
12
|
+
const fullUrl = new URL(url);
|
|
13
|
+
if (query) {
|
|
14
|
+
Object.entries(query).forEach(([k, v]) => fullUrl.searchParams.set(k, v));
|
|
15
|
+
}
|
|
16
|
+
;
|
|
17
|
+
const isForm = type === "form";
|
|
18
|
+
const response = await fetch(fullUrl.toString(), {
|
|
19
|
+
method,
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": isForm ? "application/x-www-form-urlencoded" : "application/json",
|
|
22
|
+
...headers
|
|
23
|
+
},
|
|
24
|
+
signal: AbortSignal.timeout(timeout),
|
|
25
|
+
...body !== void 0 && {
|
|
26
|
+
body: isForm ? new URLSearchParams(body).toString() : JSON.stringify(body)
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const text2 = await response.text().catch(() => "");
|
|
31
|
+
const error = new Error(text2 || response.statusText);
|
|
32
|
+
error.status = response.status;
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
;
|
|
36
|
+
const text = await response.text();
|
|
37
|
+
try {
|
|
38
|
+
return text ? JSON.parse(text) : null;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// lib/twilio.js
|
|
45
|
+
var twilio = {
|
|
46
|
+
sms: async ({
|
|
47
|
+
accountSid,
|
|
48
|
+
authToken,
|
|
49
|
+
from,
|
|
50
|
+
link,
|
|
51
|
+
message,
|
|
52
|
+
optOut = false,
|
|
53
|
+
prize,
|
|
54
|
+
// Injectable for the same reason sendgrid's is — see sendgrid.js.
|
|
55
|
+
request: request2 = request,
|
|
56
|
+
title,
|
|
57
|
+
to
|
|
58
|
+
}) => {
|
|
59
|
+
accountSid = accountSid || process.env.TWILIO_ACCOUNT_SID;
|
|
60
|
+
authToken = authToken || process.env.TWILIO_AUTH_TOKEN;
|
|
61
|
+
from = from || process.env.TWILIO_ACCOUNT_FROM;
|
|
62
|
+
const body = [
|
|
63
|
+
title,
|
|
64
|
+
message,
|
|
65
|
+
...prize ? [prize.title + " (" + prize.value + ")"] : [],
|
|
66
|
+
...link ? ["Verify here: " + link] : [],
|
|
67
|
+
...optOut ? ["Reply STOP to opt out"] : []
|
|
68
|
+
].filter(Boolean).join("\n");
|
|
69
|
+
return await request2({
|
|
70
|
+
method: "POST",
|
|
71
|
+
type: "form",
|
|
72
|
+
url: "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json",
|
|
73
|
+
headers: {
|
|
74
|
+
"Authorization": "Basic " + Buffer.from(accountSid + ":" + authToken).toString("base64")
|
|
75
|
+
},
|
|
76
|
+
body: {
|
|
77
|
+
Body: body,
|
|
78
|
+
From: from,
|
|
79
|
+
To: to
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
export {
|
|
85
|
+
twilio
|
|
86
|
+
};
|
package/package.json
CHANGED
|
@@ -133,6 +133,16 @@
|
|
|
133
133
|
"import": "./dist/fetch.js",
|
|
134
134
|
"require": "./dist/fetch.cjs"
|
|
135
135
|
},
|
|
136
|
+
"./sendgrid": {
|
|
137
|
+
"types": "./dist/sendgrid.d.ts",
|
|
138
|
+
"import": "./dist/sendgrid.js",
|
|
139
|
+
"require": "./dist/sendgrid.cjs"
|
|
140
|
+
},
|
|
141
|
+
"./twilio": {
|
|
142
|
+
"types": "./dist/twilio.d.ts",
|
|
143
|
+
"import": "./dist/twilio.js",
|
|
144
|
+
"require": "./dist/twilio.cjs"
|
|
145
|
+
},
|
|
136
146
|
"./http": {
|
|
137
147
|
"types": "./dist/http.d.ts",
|
|
138
148
|
"import": "./dist/http.js",
|
|
@@ -200,5 +210,5 @@
|
|
|
200
210
|
"test": ". \"$HOME/.nvm/nvm.sh\" && nvm use && node --test"
|
|
201
211
|
},
|
|
202
212
|
"types": "dist/index.d.ts",
|
|
203
|
-
"version": "0.0.
|
|
213
|
+
"version": "0.0.114"
|
|
204
214
|
}
|