@squadbase/vite-server 0.1.3-dev.0 → 0.1.3-dev.1
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/cli/index.js +13282 -4299
- package/dist/connectors/asana.d.ts +5 -0
- package/dist/connectors/asana.js +661 -0
- package/dist/connectors/customerio.d.ts +5 -0
- package/dist/connectors/customerio.js +633 -0
- package/dist/connectors/gmail-oauth.d.ts +5 -0
- package/dist/connectors/gmail-oauth.js +639 -0
- package/dist/connectors/google-ads.d.ts +5 -0
- package/dist/connectors/google-ads.js +784 -0
- package/dist/connectors/google-sheets.d.ts +5 -0
- package/dist/connectors/google-sheets.js +598 -0
- package/dist/connectors/hubspot.js +14 -5
- package/dist/connectors/intercom-oauth.d.ts +5 -0
- package/dist/connectors/intercom-oauth.js +510 -0
- package/dist/connectors/intercom.d.ts +5 -0
- package/dist/connectors/intercom.js +627 -0
- package/dist/connectors/jira-api-key.d.ts +5 -0
- package/dist/connectors/jira-api-key.js +523 -0
- package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
- package/dist/connectors/linkedin-ads-oauth.js +774 -0
- package/dist/connectors/linkedin-ads.d.ts +5 -0
- package/dist/connectors/linkedin-ads.js +782 -0
- package/dist/connectors/mailchimp-oauth.d.ts +5 -0
- package/dist/connectors/mailchimp-oauth.js +539 -0
- package/dist/connectors/mailchimp.d.ts +5 -0
- package/dist/connectors/mailchimp.js +646 -0
- package/dist/connectors/zendesk-oauth.d.ts +5 -0
- package/dist/connectors/zendesk-oauth.js +505 -0
- package/dist/connectors/zendesk.d.ts +5 -0
- package/dist/connectors/zendesk.js +631 -0
- package/dist/index.js +13238 -4255
- package/dist/main.js +13240 -4257
- package/dist/vite-plugin.js +13240 -4257
- package/package.json +42 -2
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
// ../connectors/src/parameter-definition.ts
|
|
2
|
+
var ParameterDefinition = class {
|
|
3
|
+
slug;
|
|
4
|
+
name;
|
|
5
|
+
description;
|
|
6
|
+
envVarBaseKey;
|
|
7
|
+
type;
|
|
8
|
+
secret;
|
|
9
|
+
required;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.slug = config.slug;
|
|
12
|
+
this.name = config.name;
|
|
13
|
+
this.description = config.description;
|
|
14
|
+
this.envVarBaseKey = config.envVarBaseKey;
|
|
15
|
+
this.type = config.type;
|
|
16
|
+
this.secret = config.secret;
|
|
17
|
+
this.required = config.required;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get the parameter value from a ConnectorConnectionObject.
|
|
21
|
+
*/
|
|
22
|
+
getValue(connection2) {
|
|
23
|
+
const param = connection2.parameters.find(
|
|
24
|
+
(p) => p.parameterSlug === this.slug
|
|
25
|
+
);
|
|
26
|
+
if (!param || param.value == null) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return param.value;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Try to get the parameter value. Returns undefined if not found (for optional params).
|
|
35
|
+
*/
|
|
36
|
+
tryGetValue(connection2) {
|
|
37
|
+
const param = connection2.parameters.find(
|
|
38
|
+
(p) => p.parameterSlug === this.slug
|
|
39
|
+
);
|
|
40
|
+
if (!param || param.value == null) return void 0;
|
|
41
|
+
return param.value;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ../connectors/src/connectors/customerio/parameters.ts
|
|
46
|
+
var parameters = {
|
|
47
|
+
appApiKey: new ParameterDefinition({
|
|
48
|
+
slug: "app-api-key",
|
|
49
|
+
name: "App API Key",
|
|
50
|
+
description: "Your Customer.io App API Key. Used for Bearer authentication. Found under Settings > API Credentials. Note: shown only once when created.",
|
|
51
|
+
envVarBaseKey: "CUSTOMERIO_API_KEY",
|
|
52
|
+
type: "text",
|
|
53
|
+
secret: true,
|
|
54
|
+
required: true
|
|
55
|
+
}),
|
|
56
|
+
region: new ParameterDefinition({
|
|
57
|
+
slug: "region",
|
|
58
|
+
name: "Region",
|
|
59
|
+
description: 'Set to "eu" for EU region. Leave empty for US/Global region (default).',
|
|
60
|
+
envVarBaseKey: "CUSTOMERIO_REGION",
|
|
61
|
+
type: "text",
|
|
62
|
+
secret: false,
|
|
63
|
+
required: false
|
|
64
|
+
})
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// ../connectors/src/connectors/customerio/sdk/index.ts
|
|
68
|
+
function getBaseUrl(region) {
|
|
69
|
+
return region === "eu" ? "https://api-eu.customer.io" : "https://api.customer.io";
|
|
70
|
+
}
|
|
71
|
+
function createClient(params) {
|
|
72
|
+
const appApiKey = params[parameters.appApiKey.slug];
|
|
73
|
+
const region = params[parameters.region.slug];
|
|
74
|
+
if (!appApiKey) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`customerio: missing required parameter: ${parameters.appApiKey.slug}`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
const baseUrl = getBaseUrl(region);
|
|
80
|
+
function authHeaders(extra) {
|
|
81
|
+
const headers = new Headers(extra);
|
|
82
|
+
headers.set("Authorization", `Bearer ${appApiKey}`);
|
|
83
|
+
headers.set("Content-Type", "application/json");
|
|
84
|
+
return headers;
|
|
85
|
+
}
|
|
86
|
+
async function assertOk(res, label) {
|
|
87
|
+
if (!res.ok) {
|
|
88
|
+
const body = await res.text().catch(() => "(unreadable body)");
|
|
89
|
+
throw new Error(
|
|
90
|
+
`customerio ${label}: ${res.status} ${res.statusText} \u2014 ${body}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
request(path2, init) {
|
|
96
|
+
const url = `${baseUrl}${path2.startsWith("/") ? "" : "/"}${path2}`;
|
|
97
|
+
const headers = new Headers(init?.headers);
|
|
98
|
+
headers.set("Authorization", `Bearer ${appApiKey}`);
|
|
99
|
+
headers.set("Content-Type", "application/json");
|
|
100
|
+
return fetch(url, { ...init, headers });
|
|
101
|
+
},
|
|
102
|
+
async getCustomers(options) {
|
|
103
|
+
const sp = new URLSearchParams();
|
|
104
|
+
if (options?.start) sp.set("start", options.start);
|
|
105
|
+
if (options?.limit) sp.set("limit", String(options.limit));
|
|
106
|
+
const qs = sp.toString() ? `?${sp.toString()}` : "";
|
|
107
|
+
const res = await fetch(`${baseUrl}/v1/customers${qs}`, {
|
|
108
|
+
method: "GET",
|
|
109
|
+
headers: authHeaders()
|
|
110
|
+
});
|
|
111
|
+
await assertOk(res, "getCustomers");
|
|
112
|
+
return await res.json();
|
|
113
|
+
},
|
|
114
|
+
async getCustomer(identifier) {
|
|
115
|
+
const res = await fetch(
|
|
116
|
+
`${baseUrl}/v1/customers/${encodeURIComponent(identifier)}/attributes`,
|
|
117
|
+
{ method: "GET", headers: authHeaders() }
|
|
118
|
+
);
|
|
119
|
+
await assertOk(res, "getCustomer");
|
|
120
|
+
return await res.json();
|
|
121
|
+
},
|
|
122
|
+
async getSegments() {
|
|
123
|
+
const res = await fetch(`${baseUrl}/v1/segments`, {
|
|
124
|
+
method: "GET",
|
|
125
|
+
headers: authHeaders()
|
|
126
|
+
});
|
|
127
|
+
await assertOk(res, "getSegments");
|
|
128
|
+
return await res.json();
|
|
129
|
+
},
|
|
130
|
+
async getSegmentMembership(segmentId) {
|
|
131
|
+
const res = await fetch(
|
|
132
|
+
`${baseUrl}/v1/segments/${segmentId}/membership`,
|
|
133
|
+
{ method: "GET", headers: authHeaders() }
|
|
134
|
+
);
|
|
135
|
+
await assertOk(res, "getSegmentMembership");
|
|
136
|
+
return await res.json();
|
|
137
|
+
},
|
|
138
|
+
async getCampaigns() {
|
|
139
|
+
const res = await fetch(`${baseUrl}/v1/campaigns`, {
|
|
140
|
+
method: "GET",
|
|
141
|
+
headers: authHeaders()
|
|
142
|
+
});
|
|
143
|
+
await assertOk(res, "getCampaigns");
|
|
144
|
+
return await res.json();
|
|
145
|
+
},
|
|
146
|
+
async getCampaign(campaignId) {
|
|
147
|
+
const res = await fetch(`${baseUrl}/v1/campaigns/${campaignId}`, {
|
|
148
|
+
method: "GET",
|
|
149
|
+
headers: authHeaders()
|
|
150
|
+
});
|
|
151
|
+
await assertOk(res, "getCampaign");
|
|
152
|
+
return await res.json();
|
|
153
|
+
},
|
|
154
|
+
async sendEmail(emailParams) {
|
|
155
|
+
const res = await fetch(`${baseUrl}/v1/send/email`, {
|
|
156
|
+
method: "POST",
|
|
157
|
+
headers: authHeaders(),
|
|
158
|
+
body: JSON.stringify(emailParams)
|
|
159
|
+
});
|
|
160
|
+
await assertOk(res, "sendEmail");
|
|
161
|
+
return await res.json();
|
|
162
|
+
},
|
|
163
|
+
async triggerBroadcast(broadcastId, broadcastParams) {
|
|
164
|
+
const res = await fetch(
|
|
165
|
+
`${baseUrl}/v1/campaigns/${broadcastId}/triggers`,
|
|
166
|
+
{
|
|
167
|
+
method: "POST",
|
|
168
|
+
headers: authHeaders(),
|
|
169
|
+
body: JSON.stringify(broadcastParams ?? {})
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
await assertOk(res, "triggerBroadcast");
|
|
173
|
+
return await res.json();
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ../connectors/src/connector-onboarding.ts
|
|
179
|
+
var ConnectorOnboarding = class {
|
|
180
|
+
/** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
|
|
181
|
+
connectionSetupInstructions;
|
|
182
|
+
/** Phase 2: Data overview instructions */
|
|
183
|
+
dataOverviewInstructions;
|
|
184
|
+
constructor(config) {
|
|
185
|
+
this.connectionSetupInstructions = config.connectionSetupInstructions;
|
|
186
|
+
this.dataOverviewInstructions = config.dataOverviewInstructions;
|
|
187
|
+
}
|
|
188
|
+
getConnectionSetupPrompt(language) {
|
|
189
|
+
return this.connectionSetupInstructions?.[language] ?? null;
|
|
190
|
+
}
|
|
191
|
+
getDataOverviewInstructions(language) {
|
|
192
|
+
return this.dataOverviewInstructions[language];
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// ../connectors/src/connector-tool.ts
|
|
197
|
+
var ConnectorTool = class {
|
|
198
|
+
name;
|
|
199
|
+
description;
|
|
200
|
+
inputSchema;
|
|
201
|
+
outputSchema;
|
|
202
|
+
_execute;
|
|
203
|
+
constructor(config) {
|
|
204
|
+
this.name = config.name;
|
|
205
|
+
this.description = config.description;
|
|
206
|
+
this.inputSchema = config.inputSchema;
|
|
207
|
+
this.outputSchema = config.outputSchema;
|
|
208
|
+
this._execute = config.execute;
|
|
209
|
+
}
|
|
210
|
+
createTool(connections, config) {
|
|
211
|
+
return {
|
|
212
|
+
description: this.description,
|
|
213
|
+
inputSchema: this.inputSchema,
|
|
214
|
+
outputSchema: this.outputSchema,
|
|
215
|
+
execute: (input) => this._execute(input, connections, config)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// ../connectors/src/connector-plugin.ts
|
|
221
|
+
var ConnectorPlugin = class _ConnectorPlugin {
|
|
222
|
+
slug;
|
|
223
|
+
authType;
|
|
224
|
+
name;
|
|
225
|
+
description;
|
|
226
|
+
iconUrl;
|
|
227
|
+
parameters;
|
|
228
|
+
releaseFlag;
|
|
229
|
+
proxyPolicy;
|
|
230
|
+
experimentalAttributes;
|
|
231
|
+
onboarding;
|
|
232
|
+
systemPrompt;
|
|
233
|
+
tools;
|
|
234
|
+
query;
|
|
235
|
+
checkConnection;
|
|
236
|
+
constructor(config) {
|
|
237
|
+
this.slug = config.slug;
|
|
238
|
+
this.authType = config.authType;
|
|
239
|
+
this.name = config.name;
|
|
240
|
+
this.description = config.description;
|
|
241
|
+
this.iconUrl = config.iconUrl;
|
|
242
|
+
this.parameters = config.parameters;
|
|
243
|
+
this.releaseFlag = config.releaseFlag;
|
|
244
|
+
this.proxyPolicy = config.proxyPolicy;
|
|
245
|
+
this.experimentalAttributes = config.experimentalAttributes;
|
|
246
|
+
this.onboarding = config.onboarding;
|
|
247
|
+
this.systemPrompt = config.systemPrompt;
|
|
248
|
+
this.tools = config.tools;
|
|
249
|
+
this.query = config.query;
|
|
250
|
+
this.checkConnection = config.checkConnection;
|
|
251
|
+
}
|
|
252
|
+
get connectorKey() {
|
|
253
|
+
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Create tools for connections that belong to this connector.
|
|
257
|
+
* Filters connections by connectorKey internally.
|
|
258
|
+
* Returns tools keyed as `${connectorKey}_${toolName}`.
|
|
259
|
+
*/
|
|
260
|
+
createTools(connections, config) {
|
|
261
|
+
const myConnections = connections.filter(
|
|
262
|
+
(c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
|
|
263
|
+
);
|
|
264
|
+
const result = {};
|
|
265
|
+
for (const t of Object.values(this.tools)) {
|
|
266
|
+
result[`${this.connectorKey}_${t.name}`] = t.createTool(
|
|
267
|
+
myConnections,
|
|
268
|
+
config
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
static deriveKey(slug, authType) {
|
|
274
|
+
return authType ? `${slug}-${authType}` : slug;
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// ../connectors/src/connectors/customerio/setup.ts
|
|
279
|
+
var customerioOnboarding = new ConnectorOnboarding({
|
|
280
|
+
dataOverviewInstructions: {
|
|
281
|
+
en: `1. Call customerio_request with GET /v1/segments to list all segments
|
|
282
|
+
2. Call customerio_request with GET /v1/campaigns to list all campaigns
|
|
283
|
+
3. Pick a segment and call GET /v1/segments/{segment_id}/membership to view member IDs
|
|
284
|
+
4. Pick a customer ID and call GET /v1/customers/{id}/attributes to view customer attributes`,
|
|
285
|
+
ja: `1. customerio_request \u3067 GET /v1/segments \u3092\u547C\u3073\u51FA\u3057\u3001\u5168\u30BB\u30B0\u30E1\u30F3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
|
|
286
|
+
2. customerio_request \u3067 GET /v1/campaigns \u3092\u547C\u3073\u51FA\u3057\u3001\u5168\u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u4E00\u89A7\u3092\u53D6\u5F97
|
|
287
|
+
3. \u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u9078\u629E\u3057 GET /v1/segments/{segment_id}/membership \u3067\u30E1\u30F3\u30D0\u30FCID\u3092\u78BA\u8A8D
|
|
288
|
+
4. \u9867\u5BA2ID\u3092\u9078\u629E\u3057 GET /v1/customers/{id}/attributes \u3067\u9867\u5BA2\u5C5E\u6027\u3092\u78BA\u8A8D`
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// ../connectors/src/connectors/customerio/tools/request.ts
|
|
293
|
+
import { z } from "zod";
|
|
294
|
+
var REQUEST_TIMEOUT_MS = 6e4;
|
|
295
|
+
function getBaseUrl2(region) {
|
|
296
|
+
return region === "eu" ? "https://api-eu.customer.io" : "https://api.customer.io";
|
|
297
|
+
}
|
|
298
|
+
var inputSchema = z.object({
|
|
299
|
+
toolUseIntent: z.string().optional().describe(
|
|
300
|
+
"Brief description of what you intend to accomplish with this tool call"
|
|
301
|
+
),
|
|
302
|
+
connectionId: z.string().describe("ID of the Customer.io connection to use"),
|
|
303
|
+
method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
|
|
304
|
+
path: z.string().describe(
|
|
305
|
+
"API path (e.g., '/v1/customers', '/v1/segments', '/v1/campaigns', '/v1/send/email')"
|
|
306
|
+
),
|
|
307
|
+
queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters to append to the URL"),
|
|
308
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PUT/PATCH requests")
|
|
309
|
+
});
|
|
310
|
+
var outputSchema = z.discriminatedUnion("success", [
|
|
311
|
+
z.object({
|
|
312
|
+
success: z.literal(true),
|
|
313
|
+
status: z.number(),
|
|
314
|
+
data: z.record(z.string(), z.unknown())
|
|
315
|
+
}),
|
|
316
|
+
z.object({
|
|
317
|
+
success: z.literal(false),
|
|
318
|
+
error: z.string()
|
|
319
|
+
})
|
|
320
|
+
]);
|
|
321
|
+
var requestTool = new ConnectorTool({
|
|
322
|
+
name: "request",
|
|
323
|
+
description: `Send authenticated requests to the Customer.io App API.
|
|
324
|
+
Authentication is handled automatically using the App API Key (Bearer token).
|
|
325
|
+
Use this tool for reading customer data, managing campaigns, segments, broadcasts, sending transactional messages, and retrieving delivery information.
|
|
326
|
+
The App API is the read and management path for Customer.io data.`,
|
|
327
|
+
inputSchema,
|
|
328
|
+
outputSchema,
|
|
329
|
+
async execute({ connectionId, method, path: path2, queryParams, body }, connections) {
|
|
330
|
+
const connection2 = connections.find((c) => c.id === connectionId);
|
|
331
|
+
if (!connection2) {
|
|
332
|
+
return {
|
|
333
|
+
success: false,
|
|
334
|
+
error: `Connection ${connectionId} not found`
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
console.log(
|
|
338
|
+
`[connector-request] customerio/${connection2.name}: ${method} ${path2}`
|
|
339
|
+
);
|
|
340
|
+
try {
|
|
341
|
+
const appApiKey = parameters.appApiKey.getValue(connection2);
|
|
342
|
+
const region = parameters.region.tryGetValue(connection2);
|
|
343
|
+
const baseUrl = getBaseUrl2(region);
|
|
344
|
+
let url = `${baseUrl}${path2.startsWith("/") ? "" : "/"}${path2}`;
|
|
345
|
+
if (queryParams) {
|
|
346
|
+
const searchParams = new URLSearchParams(queryParams);
|
|
347
|
+
url += `?${searchParams.toString()}`;
|
|
348
|
+
}
|
|
349
|
+
const controller = new AbortController();
|
|
350
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
351
|
+
try {
|
|
352
|
+
const response = await fetch(url, {
|
|
353
|
+
method,
|
|
354
|
+
headers: {
|
|
355
|
+
Authorization: `Bearer ${appApiKey}`,
|
|
356
|
+
"Content-Type": "application/json"
|
|
357
|
+
},
|
|
358
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
359
|
+
signal: controller.signal
|
|
360
|
+
});
|
|
361
|
+
let data = {};
|
|
362
|
+
const text = await response.text();
|
|
363
|
+
if (text) {
|
|
364
|
+
try {
|
|
365
|
+
data = JSON.parse(text);
|
|
366
|
+
} catch {
|
|
367
|
+
data = { raw: text };
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (!response.ok) {
|
|
371
|
+
const meta = typeof data?.meta === "object" && data.meta !== null ? data.meta : null;
|
|
372
|
+
const errorMessage = typeof meta?.error === "string" ? meta.error : typeof data?.errors === "object" ? JSON.stringify(data.errors) : typeof data?.error === "string" ? data.error : `HTTP ${response.status} ${response.statusText}`;
|
|
373
|
+
return { success: false, error: errorMessage };
|
|
374
|
+
}
|
|
375
|
+
return { success: true, status: response.status, data };
|
|
376
|
+
} finally {
|
|
377
|
+
clearTimeout(timeout);
|
|
378
|
+
}
|
|
379
|
+
} catch (err) {
|
|
380
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
381
|
+
return { success: false, error: msg };
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// ../connectors/src/connectors/customerio/index.ts
|
|
387
|
+
var tools = { request: requestTool };
|
|
388
|
+
var customerioConnector = new ConnectorPlugin({
|
|
389
|
+
slug: "customerio",
|
|
390
|
+
authType: null,
|
|
391
|
+
name: "Customer.io",
|
|
392
|
+
description: "Connect to Customer.io App API for reading customer data, managing campaigns, segments, and sending transactional messages.",
|
|
393
|
+
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/6VPGKA8I2MqzaBgULLj4WQ/a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4/customerio.svg",
|
|
394
|
+
parameters,
|
|
395
|
+
releaseFlag: { dev1: true, dev2: false, prod: false },
|
|
396
|
+
onboarding: customerioOnboarding,
|
|
397
|
+
systemPrompt: {
|
|
398
|
+
en: `### Tools
|
|
399
|
+
|
|
400
|
+
- \`customerio_request\`: The only way to call the Customer.io App API. Use it to read customer data, manage campaigns and segments, send transactional messages, and trigger broadcasts. Authentication (Bearer token with App API Key) is configured automatically.
|
|
401
|
+
|
|
402
|
+
### Business Logic
|
|
403
|
+
|
|
404
|
+
The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
|
|
405
|
+
|
|
406
|
+
SDK methods (client created via \`connection(connectionId)\`):
|
|
407
|
+
- \`client.request(path, init?)\` \u2014 low-level authenticated fetch
|
|
408
|
+
- \`client.getCustomers(options?)\` \u2014 list customers
|
|
409
|
+
- \`client.getCustomer(identifier)\` \u2014 get customer attributes
|
|
410
|
+
- \`client.getSegments()\` \u2014 list all segments
|
|
411
|
+
- \`client.getSegmentMembership(segmentId)\` \u2014 get segment member IDs
|
|
412
|
+
- \`client.getCampaigns()\` \u2014 list all campaigns
|
|
413
|
+
- \`client.getCampaign(campaignId)\` \u2014 get campaign details
|
|
414
|
+
- \`client.sendEmail(params)\` \u2014 send a transactional email
|
|
415
|
+
- \`client.triggerBroadcast(broadcastId, params?)\` \u2014 trigger a broadcast
|
|
416
|
+
|
|
417
|
+
\`\`\`ts
|
|
418
|
+
import type { Context } from "hono";
|
|
419
|
+
import { connection } from "@squadbase/vite-server/connectors/customerio";
|
|
420
|
+
|
|
421
|
+
const cio = connection("<connectionId>");
|
|
422
|
+
|
|
423
|
+
export default async function handler(c: Context) {
|
|
424
|
+
const { segments } = await cio.getSegments();
|
|
425
|
+
const { campaigns } = await cio.getCampaigns();
|
|
426
|
+
|
|
427
|
+
return c.json({ segments, campaigns });
|
|
428
|
+
}
|
|
429
|
+
\`\`\`
|
|
430
|
+
|
|
431
|
+
### Customer.io App API Reference
|
|
432
|
+
|
|
433
|
+
- Base URL: \`https://api.customer.io\` (US/Global) or \`https://api-eu.customer.io\` (EU)
|
|
434
|
+
- Authentication: Bearer token (\`Authorization: Bearer {app_api_key}\`)
|
|
435
|
+
- The App API is the read and management path \u2014 use it to retrieve data and trigger messages
|
|
436
|
+
|
|
437
|
+
#### Customers
|
|
438
|
+
- GET \`/v1/customers/{identifier}/attributes\` \u2014 Get customer attributes
|
|
439
|
+
- GET \`/v1/customers/{identifier}/segments\` \u2014 Get customer's segments
|
|
440
|
+
- GET \`/v1/customers/{identifier}/messages\` \u2014 Get customer's messages
|
|
441
|
+
- GET \`/v1/customers/{identifier}/activities\` \u2014 Get customer's activities
|
|
442
|
+
|
|
443
|
+
#### Segments
|
|
444
|
+
- GET \`/v1/segments\` \u2014 List all segments
|
|
445
|
+
- GET \`/v1/segments/{segment_id}\` \u2014 Get segment details
|
|
446
|
+
- GET \`/v1/segments/{segment_id}/membership\` \u2014 Get segment member IDs
|
|
447
|
+
|
|
448
|
+
#### Campaigns
|
|
449
|
+
- GET \`/v1/campaigns\` \u2014 List all campaigns
|
|
450
|
+
- GET \`/v1/campaigns/{campaign_id}\` \u2014 Get campaign details
|
|
451
|
+
- GET \`/v1/campaigns/{campaign_id}/actions\` \u2014 Get campaign actions
|
|
452
|
+
- GET \`/v1/campaigns/{campaign_id}/metrics\` \u2014 Get campaign metrics
|
|
453
|
+
|
|
454
|
+
#### Newsletters
|
|
455
|
+
- GET \`/v1/newsletters\` \u2014 List all newsletters
|
|
456
|
+
- GET \`/v1/newsletters/{newsletter_id}\` \u2014 Get newsletter details
|
|
457
|
+
- GET \`/v1/newsletters/{newsletter_id}/metrics\` \u2014 Get newsletter metrics
|
|
458
|
+
|
|
459
|
+
#### Broadcasts
|
|
460
|
+
- GET \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 List broadcast triggers
|
|
461
|
+
- POST \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 Trigger a broadcast
|
|
462
|
+
|
|
463
|
+
#### Transactional Messages
|
|
464
|
+
- POST \`/v1/send/email\` \u2014 Send a transactional email
|
|
465
|
+
- POST \`/v1/send/push\` \u2014 Send a transactional push notification
|
|
466
|
+
|
|
467
|
+
#### Message Info
|
|
468
|
+
- GET \`/v1/messages/{message_id}\` \u2014 Get message details
|
|
469
|
+
- GET \`/v1/messages/{message_id}/deliveries\` \u2014 Get delivery attempts
|
|
470
|
+
|
|
471
|
+
#### Exports
|
|
472
|
+
- POST \`/v1/exports/customers\` \u2014 Export customer data
|
|
473
|
+
- POST \`/v1/exports/deliveries\` \u2014 Export delivery data
|
|
474
|
+
- GET \`/v1/exports/{export_id}\` \u2014 Get export status
|
|
475
|
+
- GET \`/v1/exports/{export_id}/download\` \u2014 Download export
|
|
476
|
+
|
|
477
|
+
### Tips
|
|
478
|
+
- App API keys are shown only once when created \u2014 store them securely
|
|
479
|
+
- Segment membership returns an array of customer IDs
|
|
480
|
+
- Use the exports endpoints for bulk data retrieval
|
|
481
|
+
- Pagination uses cursor-based \`start\` parameter for customer listing`,
|
|
482
|
+
ja: `### \u30C4\u30FC\u30EB
|
|
483
|
+
|
|
484
|
+
- \`customerio_request\`: Customer.io App API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u9867\u5BA2\u30C7\u30FC\u30BF\u306E\u8AAD\u307F\u53D6\u308A\u3001\u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u3084\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u7BA1\u7406\u3001\u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u9001\u4FE1\u3001\u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8\u306E\u30C8\u30EA\u30AC\u30FC\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08App API\u30AD\u30FC\u306B\u3088\u308BBearer\u30C8\u30FC\u30AF\u30F3\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
|
|
485
|
+
|
|
486
|
+
### Business Logic
|
|
487
|
+
|
|
488
|
+
\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u8A8D\u8A3C\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
489
|
+
|
|
490
|
+
SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
|
|
491
|
+
- \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
|
|
492
|
+
- \`client.getCustomers(options?)\` \u2014 \u9867\u5BA2\u4E00\u89A7
|
|
493
|
+
- \`client.getCustomer(identifier)\` \u2014 \u9867\u5BA2\u5C5E\u6027\u306E\u53D6\u5F97
|
|
494
|
+
- \`client.getSegments()\` \u2014 \u5168\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u4E00\u89A7
|
|
495
|
+
- \`client.getSegmentMembership(segmentId)\` \u2014 \u30BB\u30B0\u30E1\u30F3\u30C8\u30E1\u30F3\u30D0\u30FCID\u306E\u53D6\u5F97
|
|
496
|
+
- \`client.getCampaigns()\` \u2014 \u5168\u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u306E\u4E00\u89A7
|
|
497
|
+
- \`client.getCampaign(campaignId)\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u8A73\u7D30\u306E\u53D6\u5F97
|
|
498
|
+
- \`client.sendEmail(params)\` \u2014 \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30E1\u30FC\u30EB\u306E\u9001\u4FE1
|
|
499
|
+
- \`client.triggerBroadcast(broadcastId, params?)\` \u2014 \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8\u306E\u30C8\u30EA\u30AC\u30FC
|
|
500
|
+
|
|
501
|
+
\`\`\`ts
|
|
502
|
+
import type { Context } from "hono";
|
|
503
|
+
import { connection } from "@squadbase/vite-server/connectors/customerio";
|
|
504
|
+
|
|
505
|
+
const cio = connection("<connectionId>");
|
|
506
|
+
|
|
507
|
+
export default async function handler(c: Context) {
|
|
508
|
+
const { segments } = await cio.getSegments();
|
|
509
|
+
const { campaigns } = await cio.getCampaigns();
|
|
510
|
+
|
|
511
|
+
return c.json({ segments, campaigns });
|
|
512
|
+
}
|
|
513
|
+
\`\`\`
|
|
514
|
+
|
|
515
|
+
### Customer.io App API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
516
|
+
|
|
517
|
+
- \u30D9\u30FC\u30B9URL: \`https://api.customer.io\`\uFF08US/Global\uFF09\u307E\u305F\u306F \`https://api-eu.customer.io\`\uFF08EU\uFF09
|
|
518
|
+
- \u8A8D\u8A3C: Bearer\u30C8\u30FC\u30AF\u30F3 (\`Authorization: Bearer {app_api_key}\`)
|
|
519
|
+
- App API\u306F\u8AAD\u307F\u53D6\u308A\u3068\u7BA1\u7406\u30D1\u30B9\u3067\u3059 \u2014 \u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u3068\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u30C8\u30EA\u30AC\u30FC\u306B\u4F7F\u7528\u3057\u307E\u3059
|
|
520
|
+
|
|
521
|
+
#### \u9867\u5BA2
|
|
522
|
+
- GET \`/v1/customers/{identifier}/attributes\` \u2014 \u9867\u5BA2\u5C5E\u6027\u306E\u53D6\u5F97
|
|
523
|
+
- GET \`/v1/customers/{identifier}/segments\` \u2014 \u9867\u5BA2\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u53D6\u5F97
|
|
524
|
+
- GET \`/v1/customers/{identifier}/messages\` \u2014 \u9867\u5BA2\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u53D6\u5F97
|
|
525
|
+
- GET \`/v1/customers/{identifier}/activities\` \u2014 \u9867\u5BA2\u306E\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u53D6\u5F97
|
|
526
|
+
|
|
527
|
+
#### \u30BB\u30B0\u30E1\u30F3\u30C8
|
|
528
|
+
- GET \`/v1/segments\` \u2014 \u5168\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u4E00\u89A7
|
|
529
|
+
- GET \`/v1/segments/{segment_id}\` \u2014 \u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u8A73\u7D30
|
|
530
|
+
- GET \`/v1/segments/{segment_id}/membership\` \u2014 \u30BB\u30B0\u30E1\u30F3\u30C8\u30E1\u30F3\u30D0\u30FCID\u306E\u53D6\u5F97
|
|
531
|
+
|
|
532
|
+
#### \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3
|
|
533
|
+
- GET \`/v1/campaigns\` \u2014 \u5168\u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u306E\u4E00\u89A7
|
|
534
|
+
- GET \`/v1/campaigns/{campaign_id}\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u306E\u8A73\u7D30
|
|
535
|
+
- GET \`/v1/campaigns/{campaign_id}/actions\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u30A2\u30AF\u30B7\u30E7\u30F3\u306E\u53D6\u5F97
|
|
536
|
+
- GET \`/v1/campaigns/{campaign_id}/metrics\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u30E1\u30C8\u30EA\u30AF\u30B9\u306E\u53D6\u5F97
|
|
537
|
+
|
|
538
|
+
#### \u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC
|
|
539
|
+
- GET \`/v1/newsletters\` \u2014 \u5168\u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC\u306E\u4E00\u89A7
|
|
540
|
+
- GET \`/v1/newsletters/{newsletter_id}\` \u2014 \u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC\u306E\u8A73\u7D30
|
|
541
|
+
- GET \`/v1/newsletters/{newsletter_id}/metrics\` \u2014 \u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC\u30E1\u30C8\u30EA\u30AF\u30B9\u306E\u53D6\u5F97
|
|
542
|
+
|
|
543
|
+
#### \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8
|
|
544
|
+
- GET \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8\u30C8\u30EA\u30AC\u30FC\u4E00\u89A7
|
|
545
|
+
- POST \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8\u306E\u30C8\u30EA\u30AC\u30FC
|
|
546
|
+
|
|
547
|
+
#### \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30E1\u30C3\u30BB\u30FC\u30B8
|
|
548
|
+
- POST \`/v1/send/email\` \u2014 \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30E1\u30FC\u30EB\u306E\u9001\u4FE1
|
|
549
|
+
- POST \`/v1/send/push\` \u2014 \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30D7\u30C3\u30B7\u30E5\u901A\u77E5\u306E\u9001\u4FE1
|
|
550
|
+
|
|
551
|
+
#### \u30E1\u30C3\u30BB\u30FC\u30B8\u60C5\u5831
|
|
552
|
+
- GET \`/v1/messages/{message_id}\` \u2014 \u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u8A73\u7D30
|
|
553
|
+
- GET \`/v1/messages/{message_id}/deliveries\` \u2014 \u914D\u4FE1\u8A66\u884C\u306E\u53D6\u5F97
|
|
554
|
+
|
|
555
|
+
#### \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
|
|
556
|
+
- POST \`/v1/exports/customers\` \u2014 \u9867\u5BA2\u30C7\u30FC\u30BF\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
|
|
557
|
+
- POST \`/v1/exports/deliveries\` \u2014 \u914D\u4FE1\u30C7\u30FC\u30BF\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
|
|
558
|
+
- GET \`/v1/exports/{export_id}\` \u2014 \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u72B6\u614B\u306E\u53D6\u5F97
|
|
559
|
+
- GET \`/v1/exports/{export_id}/download\` \u2014 \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306E\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9
|
|
560
|
+
|
|
561
|
+
### \u30D2\u30F3\u30C8
|
|
562
|
+
- App API\u30AD\u30FC\u306F\u4F5C\u6210\u6642\u306B\u4E00\u5EA6\u3060\u3051\u8868\u793A\u3055\u308C\u308B \u2014 \u5B89\u5168\u306B\u4FDD\u7BA1\u3059\u308B\u3053\u3068
|
|
563
|
+
- \u30BB\u30B0\u30E1\u30F3\u30C8\u30E1\u30F3\u30D0\u30FC\u30B7\u30C3\u30D7\u306F\u9867\u5BA2ID\u306E\u914D\u5217\u3092\u8FD4\u5374
|
|
564
|
+
- \u5927\u91CF\u30C7\u30FC\u30BF\u53D6\u5F97\u306B\u306Fexports\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528
|
|
565
|
+
- \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u306F\u9867\u5BA2\u4E00\u89A7\u3067\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\`start\`\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528`
|
|
566
|
+
},
|
|
567
|
+
tools
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
// src/connectors/create-connector-sdk.ts
|
|
571
|
+
import { readFileSync } from "fs";
|
|
572
|
+
import path from "path";
|
|
573
|
+
|
|
574
|
+
// src/connector-client/env.ts
|
|
575
|
+
function resolveEnvVar(entry, key, connectionId) {
|
|
576
|
+
const envVarName = entry.envVars[key];
|
|
577
|
+
if (!envVarName) {
|
|
578
|
+
throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
|
|
579
|
+
}
|
|
580
|
+
const value = process.env[envVarName];
|
|
581
|
+
if (!value) {
|
|
582
|
+
throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
|
|
583
|
+
}
|
|
584
|
+
return value;
|
|
585
|
+
}
|
|
586
|
+
function resolveEnvVarOptional(entry, key) {
|
|
587
|
+
const envVarName = entry.envVars[key];
|
|
588
|
+
if (!envVarName) return void 0;
|
|
589
|
+
return process.env[envVarName] || void 0;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// src/connectors/create-connector-sdk.ts
|
|
593
|
+
function loadConnectionsSync() {
|
|
594
|
+
const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
|
|
595
|
+
try {
|
|
596
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
597
|
+
return JSON.parse(raw);
|
|
598
|
+
} catch {
|
|
599
|
+
return {};
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
function createConnectorSdk(plugin, createClient2) {
|
|
603
|
+
return (connectionId) => {
|
|
604
|
+
const connections = loadConnectionsSync();
|
|
605
|
+
const entry = connections[connectionId];
|
|
606
|
+
if (!entry) {
|
|
607
|
+
throw new Error(
|
|
608
|
+
`Connection "${connectionId}" not found in .squadbase/connections.json`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
if (entry.connector.slug !== plugin.slug) {
|
|
612
|
+
throw new Error(
|
|
613
|
+
`Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
const params = {};
|
|
617
|
+
for (const param of Object.values(plugin.parameters)) {
|
|
618
|
+
if (param.required) {
|
|
619
|
+
params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
|
|
620
|
+
} else {
|
|
621
|
+
const val = resolveEnvVarOptional(entry, param.slug);
|
|
622
|
+
if (val !== void 0) params[param.slug] = val;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return createClient2(params);
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// src/connectors/entries/customerio.ts
|
|
630
|
+
var connection = createConnectorSdk(customerioConnector, createClient);
|
|
631
|
+
export {
|
|
632
|
+
connection
|
|
633
|
+
};
|