patchwork-os 0.2.0-beta.6.canary.21 → 0.2.0-beta.6.canary.23
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/connectorRoutes.js +384 -0
- package/dist/connectorRoutes.js.map +1 -1
- package/dist/connectors/airtable.d.ts +108 -0
- package/dist/connectors/airtable.js +396 -0
- package/dist/connectors/airtable.js.map +1 -0
- package/dist/connectors/connectorRegistry.js +63 -0
- package/dist/connectors/connectorRegistry.js.map +1 -1
- package/dist/connectors/elasticsearch.d.ts +141 -0
- package/dist/connectors/elasticsearch.js +601 -0
- package/dist/connectors/elasticsearch.js.map +1 -0
- package/dist/connectors/figma.d.ts +130 -0
- package/dist/connectors/figma.js +387 -0
- package/dist/connectors/figma.js.map +1 -0
- package/dist/connectors/gmail.js +9 -0
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleDrive.d.ts +12 -0
- package/dist/connectors/googleDrive.js +27 -0
- package/dist/connectors/googleDrive.js.map +1 -1
- package/dist/connectors/mongodb.d.ts +139 -0
- package/dist/connectors/mongodb.js +455 -0
- package/dist/connectors/mongodb.js.map +1 -0
- package/dist/connectors/postgres.d.ts +127 -0
- package/dist/connectors/postgres.js +512 -0
- package/dist/connectors/postgres.js.map +1 -0
- package/dist/connectors/redis.d.ts +140 -0
- package/dist/connectors/redis.js +571 -0
- package/dist/connectors/redis.js.map +1 -0
- package/dist/connectors/sendgrid.d.ts +102 -0
- package/dist/connectors/sendgrid.js +423 -0
- package/dist/connectors/sendgrid.js.map +1 -0
- package/dist/connectors/twilio.d.ts +118 -0
- package/dist/connectors/twilio.js +475 -0
- package/dist/connectors/twilio.js.map +1 -0
- package/dist/connectors/webflow.d.ts +118 -0
- package/dist/connectors/webflow.js +393 -0
- package/dist/connectors/webflow.js.map +1 -0
- package/dist/recipes/tools/gmail.js +27 -5
- package/dist/recipes/tools/gmail.js.map +1 -1
- package/dist/recipes/tools/googleDrive.js +64 -0
- package/dist/recipes/tools/googleDrive.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Twilio connector — SMS + account access via the Twilio REST API (2010-04-01).
|
|
3
|
+
*
|
|
4
|
+
* Auth: HTTP Basic where username=Account SID (AC...), password=Auth Token.
|
|
5
|
+
* - Env vars: TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN (+ optional TWILIO_DEFAULT_FROM)
|
|
6
|
+
* - Stored: getSecretJsonSync("twilio") → TwilioTokens
|
|
7
|
+
*
|
|
8
|
+
* Tools: sendSms, listMessages, getMessage, listPhoneNumbers, getAccountBalance
|
|
9
|
+
*
|
|
10
|
+
* Extends BaseConnector for unified auth, retry, rate-limit, error handling.
|
|
11
|
+
*/
|
|
12
|
+
import { type AuthContext, BaseConnector, type ConnectorError, type ConnectorStatus } from "./baseConnector.js";
|
|
13
|
+
export interface TwilioTokens {
|
|
14
|
+
accountSid: string;
|
|
15
|
+
authToken: string;
|
|
16
|
+
defaultFrom?: string;
|
|
17
|
+
friendlyName?: string;
|
|
18
|
+
connected_at: string;
|
|
19
|
+
}
|
|
20
|
+
export interface TwilioMessage {
|
|
21
|
+
sid: string;
|
|
22
|
+
account_sid: string;
|
|
23
|
+
to: string;
|
|
24
|
+
from: string;
|
|
25
|
+
body: string;
|
|
26
|
+
status: string;
|
|
27
|
+
direction: string;
|
|
28
|
+
date_sent: string | null;
|
|
29
|
+
date_created: string;
|
|
30
|
+
date_updated: string;
|
|
31
|
+
price: string | null;
|
|
32
|
+
price_unit: string | null;
|
|
33
|
+
error_code: number | null;
|
|
34
|
+
error_message: string | null;
|
|
35
|
+
num_segments: string;
|
|
36
|
+
num_media: string;
|
|
37
|
+
uri: string;
|
|
38
|
+
}
|
|
39
|
+
export interface TwilioMessageListResult {
|
|
40
|
+
messages: TwilioMessage[];
|
|
41
|
+
page: number;
|
|
42
|
+
page_size: number;
|
|
43
|
+
next_page_uri: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface TwilioPhoneNumber {
|
|
46
|
+
sid: string;
|
|
47
|
+
account_sid: string;
|
|
48
|
+
phone_number: string;
|
|
49
|
+
friendly_name: string;
|
|
50
|
+
capabilities: {
|
|
51
|
+
voice?: boolean;
|
|
52
|
+
sms?: boolean;
|
|
53
|
+
mms?: boolean;
|
|
54
|
+
};
|
|
55
|
+
date_created: string;
|
|
56
|
+
}
|
|
57
|
+
export interface TwilioPhoneNumberListResult {
|
|
58
|
+
incoming_phone_numbers: TwilioPhoneNumber[];
|
|
59
|
+
page: number;
|
|
60
|
+
page_size: number;
|
|
61
|
+
next_page_uri: string | null;
|
|
62
|
+
}
|
|
63
|
+
export interface TwilioBalance {
|
|
64
|
+
account_sid: string;
|
|
65
|
+
balance: string;
|
|
66
|
+
currency: string;
|
|
67
|
+
}
|
|
68
|
+
export declare class TwilioConnector extends BaseConnector {
|
|
69
|
+
readonly providerName = "twilio";
|
|
70
|
+
private tokens;
|
|
71
|
+
protected getOAuthConfig(): null;
|
|
72
|
+
authenticate(): Promise<AuthContext>;
|
|
73
|
+
healthCheck(): Promise<{
|
|
74
|
+
ok: boolean;
|
|
75
|
+
error?: ConnectorError;
|
|
76
|
+
}>;
|
|
77
|
+
normalizeError(error: unknown): ConnectorError;
|
|
78
|
+
getStatus(): ConnectorStatus;
|
|
79
|
+
sendSms(params: {
|
|
80
|
+
to: string;
|
|
81
|
+
body: string;
|
|
82
|
+
from?: string;
|
|
83
|
+
}): Promise<TwilioMessage>;
|
|
84
|
+
listMessages(params?: {
|
|
85
|
+
to?: string;
|
|
86
|
+
from?: string;
|
|
87
|
+
dateSent?: string;
|
|
88
|
+
limit?: number;
|
|
89
|
+
}): Promise<TwilioMessageListResult>;
|
|
90
|
+
getMessage(messageSid: string): Promise<TwilioMessage>;
|
|
91
|
+
listPhoneNumbers(params?: {
|
|
92
|
+
limit?: number;
|
|
93
|
+
}): Promise<TwilioPhoneNumberListResult>;
|
|
94
|
+
getAccountBalance(): Promise<TwilioBalance>;
|
|
95
|
+
private buildHeaders;
|
|
96
|
+
}
|
|
97
|
+
export declare function loadTokens(): TwilioTokens | null;
|
|
98
|
+
export declare function saveTokens(tokens: TwilioTokens): void;
|
|
99
|
+
export declare function clearTokens(): void;
|
|
100
|
+
export declare function getTwilioConnector(): TwilioConnector;
|
|
101
|
+
export { getTwilioConnector as twilio };
|
|
102
|
+
export interface ConnectorHandlerResult {
|
|
103
|
+
status: number;
|
|
104
|
+
body: string;
|
|
105
|
+
contentType?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* POST /connections/twilio/connect { accountSid, authToken, defaultFrom? }
|
|
109
|
+
*/
|
|
110
|
+
export declare function handleTwilioConnect(body: string): Promise<ConnectorHandlerResult>;
|
|
111
|
+
/**
|
|
112
|
+
* POST /connections/twilio/test
|
|
113
|
+
*/
|
|
114
|
+
export declare function handleTwilioTest(): Promise<ConnectorHandlerResult>;
|
|
115
|
+
/**
|
|
116
|
+
* DELETE /connections/twilio
|
|
117
|
+
*/
|
|
118
|
+
export declare function handleTwilioDisconnect(): ConnectorHandlerResult;
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Twilio connector — SMS + account access via the Twilio REST API (2010-04-01).
|
|
3
|
+
*
|
|
4
|
+
* Auth: HTTP Basic where username=Account SID (AC...), password=Auth Token.
|
|
5
|
+
* - Env vars: TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN (+ optional TWILIO_DEFAULT_FROM)
|
|
6
|
+
* - Stored: getSecretJsonSync("twilio") → TwilioTokens
|
|
7
|
+
*
|
|
8
|
+
* Tools: sendSms, listMessages, getMessage, listPhoneNumbers, getAccountBalance
|
|
9
|
+
*
|
|
10
|
+
* Extends BaseConnector for unified auth, retry, rate-limit, error handling.
|
|
11
|
+
*/
|
|
12
|
+
import { BaseConnector, } from "./baseConnector.js";
|
|
13
|
+
import { deleteSecretJsonSync, getSecretJsonSync, storeSecretJsonSync, } from "./tokenStorage.js";
|
|
14
|
+
const BASE_URL = "https://api.twilio.com";
|
|
15
|
+
const E164_RE = /^\+\d{8,15}$/;
|
|
16
|
+
export class TwilioConnector extends BaseConnector {
|
|
17
|
+
providerName = "twilio";
|
|
18
|
+
tokens = null;
|
|
19
|
+
getOAuthConfig() {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
async authenticate() {
|
|
23
|
+
const tokens = loadTokens();
|
|
24
|
+
if (!tokens) {
|
|
25
|
+
throw new Error("Twilio not connected. Run: patchwork-os connect twilio or set TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN");
|
|
26
|
+
}
|
|
27
|
+
this.tokens = tokens;
|
|
28
|
+
return {
|
|
29
|
+
token: tokens.authToken,
|
|
30
|
+
scopes: ["read", "write"],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async healthCheck() {
|
|
34
|
+
try {
|
|
35
|
+
const tokens = this.tokens ?? loadTokens();
|
|
36
|
+
if (!tokens) {
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
error: {
|
|
40
|
+
code: "auth_expired",
|
|
41
|
+
message: "Twilio not connected",
|
|
42
|
+
retryable: false,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
this.tokens = tokens;
|
|
47
|
+
const result = await this.apiCall(async () => {
|
|
48
|
+
const res = await fetch(`${BASE_URL}/2010-04-01/Accounts/${tokens.accountSid}.json`, { headers: this.buildHeaders() });
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
throw res;
|
|
51
|
+
return res.json();
|
|
52
|
+
});
|
|
53
|
+
if ("error" in result)
|
|
54
|
+
return { ok: false, error: result.error };
|
|
55
|
+
return { ok: true };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return { ok: false, error: this.normalizeError(err) };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
normalizeError(error) {
|
|
62
|
+
if (error instanceof Response) {
|
|
63
|
+
const s = error.status;
|
|
64
|
+
if (s === 401)
|
|
65
|
+
return {
|
|
66
|
+
code: "auth_expired",
|
|
67
|
+
message: "Twilio authentication expired — reconnect",
|
|
68
|
+
retryable: false,
|
|
69
|
+
suggestedAction: "patchwork-os connect twilio",
|
|
70
|
+
};
|
|
71
|
+
if (s === 403)
|
|
72
|
+
return {
|
|
73
|
+
code: "permission_denied",
|
|
74
|
+
message: "Insufficient Twilio permissions",
|
|
75
|
+
retryable: false,
|
|
76
|
+
};
|
|
77
|
+
if (s === 404)
|
|
78
|
+
return {
|
|
79
|
+
code: "not_found",
|
|
80
|
+
message: "Twilio resource not found",
|
|
81
|
+
retryable: false,
|
|
82
|
+
};
|
|
83
|
+
if (s === 429)
|
|
84
|
+
return {
|
|
85
|
+
code: "rate_limited",
|
|
86
|
+
message: "Twilio API rate limit exceeded",
|
|
87
|
+
retryable: true,
|
|
88
|
+
suggestedAction: "Wait and retry",
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
code: "provider_error",
|
|
92
|
+
message: `Twilio API error: HTTP ${s}`,
|
|
93
|
+
retryable: s >= 500,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (error &&
|
|
97
|
+
typeof error === "object" &&
|
|
98
|
+
"code" in error &&
|
|
99
|
+
"message" in error &&
|
|
100
|
+
typeof error.message === "string") {
|
|
101
|
+
// Twilio JSON error shape: { code, message, status, more_info }
|
|
102
|
+
const e = error;
|
|
103
|
+
const s = typeof e.status === "number" ? e.status : 0;
|
|
104
|
+
if (s === 401)
|
|
105
|
+
return {
|
|
106
|
+
code: "auth_expired",
|
|
107
|
+
message: `Twilio auth failed: ${e.message}`,
|
|
108
|
+
retryable: false,
|
|
109
|
+
suggestedAction: "patchwork-os connect twilio",
|
|
110
|
+
};
|
|
111
|
+
if (s === 403)
|
|
112
|
+
return {
|
|
113
|
+
code: "permission_denied",
|
|
114
|
+
message: `Twilio: ${e.message}`,
|
|
115
|
+
retryable: false,
|
|
116
|
+
};
|
|
117
|
+
if (s === 404)
|
|
118
|
+
return {
|
|
119
|
+
code: "not_found",
|
|
120
|
+
message: `Twilio: ${e.message}`,
|
|
121
|
+
retryable: false,
|
|
122
|
+
};
|
|
123
|
+
if (s === 429)
|
|
124
|
+
return {
|
|
125
|
+
code: "rate_limited",
|
|
126
|
+
message: `Twilio: ${e.message}`,
|
|
127
|
+
retryable: true,
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
code: "provider_error",
|
|
131
|
+
message: `Twilio [${e.code}]: ${e.message}`,
|
|
132
|
+
retryable: s >= 500,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (error instanceof Error) {
|
|
136
|
+
if (error.message.includes("ENOTFOUND") ||
|
|
137
|
+
error.message.includes("ECONNREFUSED")) {
|
|
138
|
+
return {
|
|
139
|
+
code: "network_error",
|
|
140
|
+
message: `Cannot connect to Twilio: ${error.message}`,
|
|
141
|
+
retryable: true,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
code: "provider_error",
|
|
147
|
+
message: error instanceof Error ? error.message : String(error),
|
|
148
|
+
retryable: false,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
getStatus() {
|
|
152
|
+
const tokens = loadTokens();
|
|
153
|
+
return {
|
|
154
|
+
id: "twilio",
|
|
155
|
+
status: tokens ? "connected" : "disconnected",
|
|
156
|
+
lastSync: tokens?.connected_at,
|
|
157
|
+
workspace: tokens?.friendlyName
|
|
158
|
+
? `Twilio: ${tokens.friendlyName}`
|
|
159
|
+
: tokens?.accountSid
|
|
160
|
+
? `Twilio account ${tokens.accountSid}`
|
|
161
|
+
: undefined,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
// ── API Methods ────────────────────────────────────────────────────────────
|
|
165
|
+
async sendSms(params) {
|
|
166
|
+
if (!params.to || !E164_RE.test(params.to)) {
|
|
167
|
+
throw new Error(`Invalid 'to' phone number: must be E.164 format (e.g. +14155551234), got: ${params.to}`);
|
|
168
|
+
}
|
|
169
|
+
if (!params.body) {
|
|
170
|
+
throw new Error("sendSms: 'body' is required");
|
|
171
|
+
}
|
|
172
|
+
const tokens = this.tokens ?? loadTokens();
|
|
173
|
+
if (!tokens)
|
|
174
|
+
throw new Error("Twilio not connected");
|
|
175
|
+
this.tokens = tokens;
|
|
176
|
+
const from = params.from ?? tokens.defaultFrom;
|
|
177
|
+
if (!from) {
|
|
178
|
+
throw new Error("sendSms: no 'from' number provided and no defaultFrom configured");
|
|
179
|
+
}
|
|
180
|
+
if (!E164_RE.test(from)) {
|
|
181
|
+
throw new Error(`Invalid 'from' phone number: must be E.164 format, got: ${from}`);
|
|
182
|
+
}
|
|
183
|
+
const formBody = new URLSearchParams();
|
|
184
|
+
formBody.set("To", params.to);
|
|
185
|
+
formBody.set("From", from);
|
|
186
|
+
formBody.set("Body", params.body);
|
|
187
|
+
const result = await this.apiCall(async () => {
|
|
188
|
+
const res = await fetch(`${BASE_URL}/2010-04-01/Accounts/${tokens.accountSid}/Messages.json`, {
|
|
189
|
+
method: "POST",
|
|
190
|
+
headers: {
|
|
191
|
+
...this.buildHeaders(),
|
|
192
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
193
|
+
},
|
|
194
|
+
body: formBody.toString(),
|
|
195
|
+
});
|
|
196
|
+
if (!res.ok)
|
|
197
|
+
throw res;
|
|
198
|
+
return res.json();
|
|
199
|
+
});
|
|
200
|
+
if ("error" in result)
|
|
201
|
+
throw new Error(result.error.message);
|
|
202
|
+
return result.data;
|
|
203
|
+
}
|
|
204
|
+
async listMessages(params = {}) {
|
|
205
|
+
const tokens = this.tokens ?? loadTokens();
|
|
206
|
+
if (!tokens)
|
|
207
|
+
throw new Error("Twilio not connected");
|
|
208
|
+
this.tokens = tokens;
|
|
209
|
+
const qs = new URLSearchParams();
|
|
210
|
+
qs.set("PageSize", String(params.limit ?? 20));
|
|
211
|
+
if (params.to)
|
|
212
|
+
qs.set("To", params.to);
|
|
213
|
+
if (params.from)
|
|
214
|
+
qs.set("From", params.from);
|
|
215
|
+
if (params.dateSent)
|
|
216
|
+
qs.set("DateSent", params.dateSent);
|
|
217
|
+
const result = await this.apiCall(async () => {
|
|
218
|
+
const res = await fetch(`${BASE_URL}/2010-04-01/Accounts/${tokens.accountSid}/Messages.json?${qs}`, { headers: this.buildHeaders() });
|
|
219
|
+
if (!res.ok)
|
|
220
|
+
throw res;
|
|
221
|
+
return res.json();
|
|
222
|
+
});
|
|
223
|
+
if ("error" in result)
|
|
224
|
+
throw new Error(result.error.message);
|
|
225
|
+
return result.data;
|
|
226
|
+
}
|
|
227
|
+
async getMessage(messageSid) {
|
|
228
|
+
const tokens = this.tokens ?? loadTokens();
|
|
229
|
+
if (!tokens)
|
|
230
|
+
throw new Error("Twilio not connected");
|
|
231
|
+
this.tokens = tokens;
|
|
232
|
+
const result = await this.apiCall(async () => {
|
|
233
|
+
const res = await fetch(`${BASE_URL}/2010-04-01/Accounts/${tokens.accountSid}/Messages/${messageSid}.json`, { headers: this.buildHeaders() });
|
|
234
|
+
if (!res.ok)
|
|
235
|
+
throw res;
|
|
236
|
+
return res.json();
|
|
237
|
+
});
|
|
238
|
+
if ("error" in result)
|
|
239
|
+
throw new Error(result.error.message);
|
|
240
|
+
return result.data;
|
|
241
|
+
}
|
|
242
|
+
async listPhoneNumbers(params = {}) {
|
|
243
|
+
const tokens = this.tokens ?? loadTokens();
|
|
244
|
+
if (!tokens)
|
|
245
|
+
throw new Error("Twilio not connected");
|
|
246
|
+
this.tokens = tokens;
|
|
247
|
+
const qs = new URLSearchParams();
|
|
248
|
+
qs.set("PageSize", String(params.limit ?? 20));
|
|
249
|
+
const result = await this.apiCall(async () => {
|
|
250
|
+
const res = await fetch(`${BASE_URL}/2010-04-01/Accounts/${tokens.accountSid}/IncomingPhoneNumbers.json?${qs}`, { headers: this.buildHeaders() });
|
|
251
|
+
if (!res.ok)
|
|
252
|
+
throw res;
|
|
253
|
+
return res.json();
|
|
254
|
+
});
|
|
255
|
+
if ("error" in result)
|
|
256
|
+
throw new Error(result.error.message);
|
|
257
|
+
return result.data;
|
|
258
|
+
}
|
|
259
|
+
async getAccountBalance() {
|
|
260
|
+
const tokens = this.tokens ?? loadTokens();
|
|
261
|
+
if (!tokens)
|
|
262
|
+
throw new Error("Twilio not connected");
|
|
263
|
+
this.tokens = tokens;
|
|
264
|
+
const result = await this.apiCall(async () => {
|
|
265
|
+
const res = await fetch(`${BASE_URL}/2010-04-01/Accounts/${tokens.accountSid}/Balance.json`, { headers: this.buildHeaders() });
|
|
266
|
+
if (!res.ok)
|
|
267
|
+
throw res;
|
|
268
|
+
return res.json();
|
|
269
|
+
});
|
|
270
|
+
if ("error" in result)
|
|
271
|
+
throw new Error(result.error.message);
|
|
272
|
+
return result.data;
|
|
273
|
+
}
|
|
274
|
+
// ── Helpers ────────────────────────────────────────────────────────────────
|
|
275
|
+
buildHeaders() {
|
|
276
|
+
const sid = this.tokens?.accountSid ?? "";
|
|
277
|
+
const tok = this.tokens?.authToken ?? "";
|
|
278
|
+
const basic = Buffer.from(`${sid}:${tok}`).toString("base64");
|
|
279
|
+
return {
|
|
280
|
+
Authorization: `Basic ${basic}`,
|
|
281
|
+
Accept: "application/json",
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// ── Token persistence ────────────────────────────────────────────────────────
|
|
286
|
+
export function loadTokens() {
|
|
287
|
+
const envSid = process.env.TWILIO_ACCOUNT_SID;
|
|
288
|
+
const envTok = process.env.TWILIO_AUTH_TOKEN;
|
|
289
|
+
if (envSid && envTok) {
|
|
290
|
+
return {
|
|
291
|
+
accountSid: envSid,
|
|
292
|
+
authToken: envTok,
|
|
293
|
+
defaultFrom: process.env.TWILIO_DEFAULT_FROM,
|
|
294
|
+
connected_at: new Date().toISOString(),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return getSecretJsonSync("twilio");
|
|
298
|
+
}
|
|
299
|
+
export function saveTokens(tokens) {
|
|
300
|
+
storeSecretJsonSync("twilio", tokens);
|
|
301
|
+
}
|
|
302
|
+
export function clearTokens() {
|
|
303
|
+
try {
|
|
304
|
+
deleteSecretJsonSync("twilio");
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
// ignore
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// ── Singleton instance ───────────────────────────────────────────────────────
|
|
311
|
+
let _instance = null;
|
|
312
|
+
function resetTwilioConnector() {
|
|
313
|
+
_instance = null;
|
|
314
|
+
}
|
|
315
|
+
export function getTwilioConnector() {
|
|
316
|
+
if (!_instance) {
|
|
317
|
+
_instance = new TwilioConnector();
|
|
318
|
+
}
|
|
319
|
+
return _instance;
|
|
320
|
+
}
|
|
321
|
+
export { getTwilioConnector as twilio };
|
|
322
|
+
/**
|
|
323
|
+
* POST /connections/twilio/connect { accountSid, authToken, defaultFrom? }
|
|
324
|
+
*/
|
|
325
|
+
export async function handleTwilioConnect(body) {
|
|
326
|
+
let accountSid;
|
|
327
|
+
let authToken;
|
|
328
|
+
let defaultFrom;
|
|
329
|
+
try {
|
|
330
|
+
const parsed = JSON.parse(body);
|
|
331
|
+
if (typeof parsed.accountSid !== "string" || !parsed.accountSid) {
|
|
332
|
+
return {
|
|
333
|
+
status: 400,
|
|
334
|
+
contentType: "application/json",
|
|
335
|
+
body: JSON.stringify({ ok: false, error: "accountSid is required" }),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
if (typeof parsed.authToken !== "string" || !parsed.authToken) {
|
|
339
|
+
return {
|
|
340
|
+
status: 400,
|
|
341
|
+
contentType: "application/json",
|
|
342
|
+
body: JSON.stringify({ ok: false, error: "authToken is required" }),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
if (!parsed.accountSid.startsWith("AC")) {
|
|
346
|
+
return {
|
|
347
|
+
status: 400,
|
|
348
|
+
contentType: "application/json",
|
|
349
|
+
body: JSON.stringify({
|
|
350
|
+
ok: false,
|
|
351
|
+
error: "accountSid must start with 'AC'",
|
|
352
|
+
}),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
accountSid = parsed.accountSid;
|
|
356
|
+
authToken = parsed.authToken;
|
|
357
|
+
if (typeof parsed.defaultFrom === "string" && parsed.defaultFrom) {
|
|
358
|
+
if (!E164_RE.test(parsed.defaultFrom)) {
|
|
359
|
+
return {
|
|
360
|
+
status: 400,
|
|
361
|
+
contentType: "application/json",
|
|
362
|
+
body: JSON.stringify({
|
|
363
|
+
ok: false,
|
|
364
|
+
error: "defaultFrom must be E.164 format (e.g. +14155551234)",
|
|
365
|
+
}),
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
defaultFrom = parsed.defaultFrom;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
return {
|
|
373
|
+
status: 400,
|
|
374
|
+
contentType: "application/json",
|
|
375
|
+
body: JSON.stringify({ ok: false, error: "Invalid JSON body" }),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
const basic = Buffer.from(`${accountSid}:${authToken}`).toString("base64");
|
|
380
|
+
const res = await fetch(`${BASE_URL}/2010-04-01/Accounts/${accountSid}.json`, {
|
|
381
|
+
headers: {
|
|
382
|
+
Authorization: `Basic ${basic}`,
|
|
383
|
+
Accept: "application/json",
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
if (!res.ok) {
|
|
387
|
+
return {
|
|
388
|
+
status: 401,
|
|
389
|
+
contentType: "application/json",
|
|
390
|
+
body: JSON.stringify({
|
|
391
|
+
ok: false,
|
|
392
|
+
error: `Credentials rejected by Twilio (HTTP ${res.status}) — check accountSid + authToken`,
|
|
393
|
+
}),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
const account = (await res.json());
|
|
397
|
+
const friendlyName = account.friendly_name ?? undefined;
|
|
398
|
+
const sid = account.sid ?? accountSid;
|
|
399
|
+
const tokens = {
|
|
400
|
+
accountSid: sid,
|
|
401
|
+
authToken,
|
|
402
|
+
defaultFrom,
|
|
403
|
+
friendlyName,
|
|
404
|
+
connected_at: new Date().toISOString(),
|
|
405
|
+
};
|
|
406
|
+
saveTokens(tokens);
|
|
407
|
+
resetTwilioConnector();
|
|
408
|
+
return {
|
|
409
|
+
status: 200,
|
|
410
|
+
contentType: "application/json",
|
|
411
|
+
body: JSON.stringify({
|
|
412
|
+
ok: true,
|
|
413
|
+
accountSid: sid,
|
|
414
|
+
friendlyName,
|
|
415
|
+
defaultFrom,
|
|
416
|
+
connectedAt: tokens.connected_at,
|
|
417
|
+
}),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
return {
|
|
422
|
+
status: 500,
|
|
423
|
+
contentType: "application/json",
|
|
424
|
+
body: JSON.stringify({
|
|
425
|
+
ok: false,
|
|
426
|
+
error: err instanceof Error ? err.message : String(err),
|
|
427
|
+
}),
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* POST /connections/twilio/test
|
|
433
|
+
*/
|
|
434
|
+
export async function handleTwilioTest() {
|
|
435
|
+
const tokens = loadTokens();
|
|
436
|
+
if (!tokens) {
|
|
437
|
+
return {
|
|
438
|
+
status: 400,
|
|
439
|
+
contentType: "application/json",
|
|
440
|
+
body: JSON.stringify({ ok: false, error: "Twilio not connected" }),
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
try {
|
|
444
|
+
const connector = getTwilioConnector();
|
|
445
|
+
const check = await connector.healthCheck();
|
|
446
|
+
return {
|
|
447
|
+
status: check.ok ? 200 : 401,
|
|
448
|
+
contentType: "application/json",
|
|
449
|
+
body: JSON.stringify(check.ok ? { ok: true } : { ok: false, error: check.error?.message }),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
catch (err) {
|
|
453
|
+
return {
|
|
454
|
+
status: 500,
|
|
455
|
+
contentType: "application/json",
|
|
456
|
+
body: JSON.stringify({
|
|
457
|
+
ok: false,
|
|
458
|
+
error: err instanceof Error ? err.message : String(err),
|
|
459
|
+
}),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* DELETE /connections/twilio
|
|
465
|
+
*/
|
|
466
|
+
export function handleTwilioDisconnect() {
|
|
467
|
+
clearTokens();
|
|
468
|
+
resetTwilioConnector();
|
|
469
|
+
return {
|
|
470
|
+
status: 200,
|
|
471
|
+
contentType: "application/json",
|
|
472
|
+
body: JSON.stringify({ ok: true }),
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=twilio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"twilio.js","sourceRoot":"","sources":["../../src/connectors/twilio.ts"],"names":[],"mappings":"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"}
|