@squadbase/vite-server 0.1.3-dev.0 → 0.1.3-dev.10

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.
Files changed (70) hide show
  1. package/dist/cli/index.js +82859 -9645
  2. package/dist/connectors/airtable-oauth.js +77 -3
  3. package/dist/connectors/airtable.js +85 -2
  4. package/dist/connectors/amplitude.js +85 -2
  5. package/dist/connectors/anthropic.js +85 -2
  6. package/dist/connectors/{slack.d.ts → asana.d.ts} +1 -1
  7. package/dist/connectors/asana.js +744 -0
  8. package/dist/connectors/attio.js +85 -2
  9. package/dist/connectors/{microsoft-teams-oauth.d.ts → customerio.d.ts} +1 -1
  10. package/dist/connectors/customerio.js +716 -0
  11. package/dist/connectors/dbt.js +85 -2
  12. package/dist/connectors/gemini.js +86 -3
  13. package/dist/connectors/{microsoft-teams.d.ts → gmail-oauth.d.ts} +1 -1
  14. package/dist/connectors/gmail-oauth.js +713 -0
  15. package/dist/connectors/gmail.d.ts +5 -0
  16. package/dist/connectors/gmail.js +875 -0
  17. package/dist/connectors/google-ads-oauth.js +78 -4
  18. package/dist/connectors/google-ads.d.ts +5 -0
  19. package/dist/connectors/google-ads.js +867 -0
  20. package/dist/connectors/google-analytics-oauth.js +90 -8
  21. package/dist/connectors/google-analytics.js +85 -2
  22. package/dist/connectors/google-calendar-oauth.d.ts +5 -0
  23. package/dist/connectors/google-calendar-oauth.js +817 -0
  24. package/dist/connectors/google-calendar.d.ts +5 -0
  25. package/dist/connectors/google-calendar.js +991 -0
  26. package/dist/connectors/google-sheets-oauth.js +144 -33
  27. package/dist/connectors/google-sheets.d.ts +5 -0
  28. package/dist/connectors/google-sheets.js +707 -0
  29. package/dist/connectors/grafana.d.ts +5 -0
  30. package/dist/connectors/grafana.js +638 -0
  31. package/dist/connectors/hubspot-oauth.js +77 -3
  32. package/dist/connectors/hubspot.js +89 -6
  33. package/dist/connectors/intercom-oauth.d.ts +5 -0
  34. package/dist/connectors/intercom-oauth.js +584 -0
  35. package/dist/connectors/intercom.d.ts +5 -0
  36. package/dist/connectors/intercom.js +710 -0
  37. package/dist/connectors/jira-api-key.d.ts +5 -0
  38. package/dist/connectors/jira-api-key.js +598 -0
  39. package/dist/connectors/kintone-api-token.js +77 -3
  40. package/dist/connectors/kintone.js +86 -3
  41. package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
  42. package/dist/connectors/linkedin-ads-oauth.js +848 -0
  43. package/dist/connectors/linkedin-ads.d.ts +5 -0
  44. package/dist/connectors/linkedin-ads.js +865 -0
  45. package/dist/connectors/mailchimp-oauth.d.ts +5 -0
  46. package/dist/connectors/mailchimp-oauth.js +613 -0
  47. package/dist/connectors/mailchimp.d.ts +5 -0
  48. package/dist/connectors/mailchimp.js +729 -0
  49. package/dist/connectors/notion-oauth.d.ts +5 -0
  50. package/dist/connectors/notion-oauth.js +567 -0
  51. package/dist/connectors/notion.d.ts +5 -0
  52. package/dist/connectors/notion.js +663 -0
  53. package/dist/connectors/openai.js +85 -2
  54. package/dist/connectors/shopify-oauth.js +77 -3
  55. package/dist/connectors/shopify.js +85 -2
  56. package/dist/connectors/stripe-api-key.d.ts +5 -0
  57. package/dist/connectors/stripe-api-key.js +600 -0
  58. package/dist/connectors/stripe-oauth.js +77 -3
  59. package/dist/connectors/wix-store.js +85 -2
  60. package/dist/connectors/zendesk-oauth.d.ts +5 -0
  61. package/dist/connectors/zendesk-oauth.js +579 -0
  62. package/dist/connectors/zendesk.d.ts +5 -0
  63. package/dist/connectors/zendesk.js +714 -0
  64. package/dist/index.js +83024 -7099
  65. package/dist/main.js +82988 -7063
  66. package/dist/vite-plugin.js +82862 -6974
  67. package/package.json +86 -2
  68. package/dist/connectors/microsoft-teams-oauth.js +0 -479
  69. package/dist/connectors/microsoft-teams.js +0 -381
  70. package/dist/connectors/slack.js +0 -362
@@ -0,0 +1,716 @@
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/auth-types.ts
279
+ var AUTH_TYPES = {
280
+ OAUTH: "oauth",
281
+ API_KEY: "api-key",
282
+ JWT: "jwt",
283
+ SERVICE_ACCOUNT: "service-account",
284
+ PAT: "pat",
285
+ USER_PASSWORD: "user-password"
286
+ };
287
+
288
+ // ../connectors/src/connectors/customerio/setup.ts
289
+ var customerioOnboarding = new ConnectorOnboarding({
290
+ dataOverviewInstructions: {
291
+ en: `1. Call customerio_request with GET /v1/segments to list all segments
292
+ 2. Call customerio_request with GET /v1/campaigns to list all campaigns
293
+ 3. Pick a segment and call GET /v1/segments/{segment_id}/membership to view member IDs
294
+ 4. Pick a customer ID and call GET /v1/customers/{id}/attributes to view customer attributes`,
295
+ 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
296
+ 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
297
+ 3. \u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u9078\u629E\u3057 GET /v1/segments/{segment_id}/membership \u3067\u30E1\u30F3\u30D0\u30FCID\u3092\u78BA\u8A8D
298
+ 4. \u9867\u5BA2ID\u3092\u9078\u629E\u3057 GET /v1/customers/{id}/attributes \u3067\u9867\u5BA2\u5C5E\u6027\u3092\u78BA\u8A8D`
299
+ }
300
+ });
301
+
302
+ // ../connectors/src/connectors/customerio/tools/request.ts
303
+ import { z } from "zod";
304
+ var REQUEST_TIMEOUT_MS = 6e4;
305
+ function getBaseUrl2(region) {
306
+ return region === "eu" ? "https://api-eu.customer.io" : "https://api.customer.io";
307
+ }
308
+ var inputSchema = z.object({
309
+ toolUseIntent: z.string().optional().describe(
310
+ "Brief description of what you intend to accomplish with this tool call"
311
+ ),
312
+ connectionId: z.string().describe("ID of the Customer.io connection to use"),
313
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
314
+ path: z.string().describe(
315
+ "API path (e.g., '/v1/customers', '/v1/segments', '/v1/campaigns', '/v1/send/email')"
316
+ ),
317
+ queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters to append to the URL"),
318
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PUT/PATCH requests")
319
+ });
320
+ var outputSchema = z.discriminatedUnion("success", [
321
+ z.object({
322
+ success: z.literal(true),
323
+ status: z.number(),
324
+ data: z.record(z.string(), z.unknown())
325
+ }),
326
+ z.object({
327
+ success: z.literal(false),
328
+ error: z.string()
329
+ })
330
+ ]);
331
+ var requestTool = new ConnectorTool({
332
+ name: "request",
333
+ description: `Send authenticated requests to the Customer.io App API.
334
+ Authentication is handled automatically using the App API Key (Bearer token).
335
+ Use this tool for reading customer data, managing campaigns, segments, broadcasts, sending transactional messages, and retrieving delivery information.
336
+ The App API is the read and management path for Customer.io data.`,
337
+ inputSchema,
338
+ outputSchema,
339
+ async execute({ connectionId, method, path: path2, queryParams, body }, connections) {
340
+ const connection2 = connections.find((c) => c.id === connectionId);
341
+ if (!connection2) {
342
+ return {
343
+ success: false,
344
+ error: `Connection ${connectionId} not found`
345
+ };
346
+ }
347
+ console.log(
348
+ `[connector-request] customerio/${connection2.name}: ${method} ${path2}`
349
+ );
350
+ try {
351
+ const appApiKey = parameters.appApiKey.getValue(connection2);
352
+ const region = parameters.region.tryGetValue(connection2);
353
+ const baseUrl = getBaseUrl2(region);
354
+ let url = `${baseUrl}${path2.startsWith("/") ? "" : "/"}${path2}`;
355
+ if (queryParams) {
356
+ const searchParams = new URLSearchParams(queryParams);
357
+ url += `?${searchParams.toString()}`;
358
+ }
359
+ const controller = new AbortController();
360
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
361
+ try {
362
+ const response = await fetch(url, {
363
+ method,
364
+ headers: {
365
+ Authorization: `Bearer ${appApiKey}`,
366
+ "Content-Type": "application/json"
367
+ },
368
+ body: body ? JSON.stringify(body) : void 0,
369
+ signal: controller.signal
370
+ });
371
+ let data = {};
372
+ const text = await response.text();
373
+ if (text) {
374
+ try {
375
+ data = JSON.parse(text);
376
+ } catch {
377
+ data = { raw: text };
378
+ }
379
+ }
380
+ if (!response.ok) {
381
+ const meta = typeof data?.meta === "object" && data.meta !== null ? data.meta : null;
382
+ 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}`;
383
+ return { success: false, error: errorMessage };
384
+ }
385
+ return { success: true, status: response.status, data };
386
+ } finally {
387
+ clearTimeout(timeout);
388
+ }
389
+ } catch (err) {
390
+ const msg = err instanceof Error ? err.message : String(err);
391
+ return { success: false, error: msg };
392
+ }
393
+ }
394
+ });
395
+
396
+ // ../connectors/src/connectors/customerio/index.ts
397
+ var tools = { request: requestTool };
398
+ var customerioConnector = new ConnectorPlugin({
399
+ slug: "customerio",
400
+ authType: AUTH_TYPES.API_KEY,
401
+ name: "Customer.io",
402
+ description: "Connect to Customer.io App API for reading customer data, managing campaigns, segments, and sending transactional messages.",
403
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/nngohabT7oHDIgQYAVBpz/6f6c7662ef4692eb9869e3e69dd57114/customerio.png",
404
+ parameters,
405
+ releaseFlag: { dev1: true, dev2: false, prod: false },
406
+ onboarding: customerioOnboarding,
407
+ systemPrompt: {
408
+ en: `### Tools
409
+
410
+ - \`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.
411
+
412
+ ### Business Logic
413
+
414
+ The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
415
+
416
+ SDK methods (client created via \`connection(connectionId)\`):
417
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
418
+ - \`client.getCustomers(options?)\` \u2014 list customers
419
+ - \`client.getCustomer(identifier)\` \u2014 get customer attributes
420
+ - \`client.getSegments()\` \u2014 list all segments
421
+ - \`client.getSegmentMembership(segmentId)\` \u2014 get segment member IDs
422
+ - \`client.getCampaigns()\` \u2014 list all campaigns
423
+ - \`client.getCampaign(campaignId)\` \u2014 get campaign details
424
+ - \`client.sendEmail(params)\` \u2014 send a transactional email
425
+ - \`client.triggerBroadcast(broadcastId, params?)\` \u2014 trigger a broadcast
426
+
427
+ \`\`\`ts
428
+ import type { Context } from "hono";
429
+ import { connection } from "@squadbase/vite-server/connectors/customerio";
430
+
431
+ const cio = connection("<connectionId>");
432
+
433
+ export default async function handler(c: Context) {
434
+ const { segments } = await cio.getSegments();
435
+ const { campaigns } = await cio.getCampaigns();
436
+
437
+ return c.json({ segments, campaigns });
438
+ }
439
+ \`\`\`
440
+
441
+ ### Customer.io App API Reference
442
+
443
+ - Base URL: \`https://api.customer.io\` (US/Global) or \`https://api-eu.customer.io\` (EU)
444
+ - Authentication: Bearer token (\`Authorization: Bearer {app_api_key}\`)
445
+ - The App API is the read and management path \u2014 use it to retrieve data and trigger messages
446
+
447
+ #### Customers
448
+ - GET \`/v1/customers/{identifier}/attributes\` \u2014 Get customer attributes
449
+ - GET \`/v1/customers/{identifier}/segments\` \u2014 Get customer's segments
450
+ - GET \`/v1/customers/{identifier}/messages\` \u2014 Get customer's messages
451
+ - GET \`/v1/customers/{identifier}/activities\` \u2014 Get customer's activities
452
+
453
+ #### Segments
454
+ - GET \`/v1/segments\` \u2014 List all segments
455
+ - GET \`/v1/segments/{segment_id}\` \u2014 Get segment details
456
+ - GET \`/v1/segments/{segment_id}/membership\` \u2014 Get segment member IDs
457
+
458
+ #### Campaigns
459
+ - GET \`/v1/campaigns\` \u2014 List all campaigns
460
+ - GET \`/v1/campaigns/{campaign_id}\` \u2014 Get campaign details
461
+ - GET \`/v1/campaigns/{campaign_id}/actions\` \u2014 Get campaign actions
462
+ - GET \`/v1/campaigns/{campaign_id}/metrics\` \u2014 Get campaign metrics
463
+
464
+ #### Newsletters
465
+ - GET \`/v1/newsletters\` \u2014 List all newsletters
466
+ - GET \`/v1/newsletters/{newsletter_id}\` \u2014 Get newsletter details
467
+ - GET \`/v1/newsletters/{newsletter_id}/metrics\` \u2014 Get newsletter metrics
468
+
469
+ #### Broadcasts
470
+ - GET \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 List broadcast triggers
471
+ - POST \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 Trigger a broadcast
472
+
473
+ #### Transactional Messages
474
+ - POST \`/v1/send/email\` \u2014 Send a transactional email
475
+ - POST \`/v1/send/push\` \u2014 Send a transactional push notification
476
+
477
+ #### Message Info
478
+ - GET \`/v1/messages/{message_id}\` \u2014 Get message details
479
+ - GET \`/v1/messages/{message_id}/deliveries\` \u2014 Get delivery attempts
480
+
481
+ #### Exports
482
+ - POST \`/v1/exports/customers\` \u2014 Export customer data
483
+ - POST \`/v1/exports/deliveries\` \u2014 Export delivery data
484
+ - GET \`/v1/exports/{export_id}\` \u2014 Get export status
485
+ - GET \`/v1/exports/{export_id}/download\` \u2014 Download export
486
+
487
+ ### Tips
488
+ - App API keys are shown only once when created \u2014 store them securely
489
+ - Segment membership returns an array of customer IDs
490
+ - Use the exports endpoints for bulk data retrieval
491
+ - Pagination uses cursor-based \`start\` parameter for customer listing`,
492
+ ja: `### \u30C4\u30FC\u30EB
493
+
494
+ - \`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
495
+
496
+ ### Business Logic
497
+
498
+ \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
499
+
500
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
501
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
502
+ - \`client.getCustomers(options?)\` \u2014 \u9867\u5BA2\u4E00\u89A7
503
+ - \`client.getCustomer(identifier)\` \u2014 \u9867\u5BA2\u5C5E\u6027\u306E\u53D6\u5F97
504
+ - \`client.getSegments()\` \u2014 \u5168\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u4E00\u89A7
505
+ - \`client.getSegmentMembership(segmentId)\` \u2014 \u30BB\u30B0\u30E1\u30F3\u30C8\u30E1\u30F3\u30D0\u30FCID\u306E\u53D6\u5F97
506
+ - \`client.getCampaigns()\` \u2014 \u5168\u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u306E\u4E00\u89A7
507
+ - \`client.getCampaign(campaignId)\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u8A73\u7D30\u306E\u53D6\u5F97
508
+ - \`client.sendEmail(params)\` \u2014 \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30E1\u30FC\u30EB\u306E\u9001\u4FE1
509
+ - \`client.triggerBroadcast(broadcastId, params?)\` \u2014 \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8\u306E\u30C8\u30EA\u30AC\u30FC
510
+
511
+ \`\`\`ts
512
+ import type { Context } from "hono";
513
+ import { connection } from "@squadbase/vite-server/connectors/customerio";
514
+
515
+ const cio = connection("<connectionId>");
516
+
517
+ export default async function handler(c: Context) {
518
+ const { segments } = await cio.getSegments();
519
+ const { campaigns } = await cio.getCampaigns();
520
+
521
+ return c.json({ segments, campaigns });
522
+ }
523
+ \`\`\`
524
+
525
+ ### Customer.io App API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
526
+
527
+ - \u30D9\u30FC\u30B9URL: \`https://api.customer.io\`\uFF08US/Global\uFF09\u307E\u305F\u306F \`https://api-eu.customer.io\`\uFF08EU\uFF09
528
+ - \u8A8D\u8A3C: Bearer\u30C8\u30FC\u30AF\u30F3 (\`Authorization: Bearer {app_api_key}\`)
529
+ - 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
530
+
531
+ #### \u9867\u5BA2
532
+ - GET \`/v1/customers/{identifier}/attributes\` \u2014 \u9867\u5BA2\u5C5E\u6027\u306E\u53D6\u5F97
533
+ - GET \`/v1/customers/{identifier}/segments\` \u2014 \u9867\u5BA2\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u53D6\u5F97
534
+ - GET \`/v1/customers/{identifier}/messages\` \u2014 \u9867\u5BA2\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u53D6\u5F97
535
+ - GET \`/v1/customers/{identifier}/activities\` \u2014 \u9867\u5BA2\u306E\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u53D6\u5F97
536
+
537
+ #### \u30BB\u30B0\u30E1\u30F3\u30C8
538
+ - GET \`/v1/segments\` \u2014 \u5168\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u4E00\u89A7
539
+ - GET \`/v1/segments/{segment_id}\` \u2014 \u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u8A73\u7D30
540
+ - GET \`/v1/segments/{segment_id}/membership\` \u2014 \u30BB\u30B0\u30E1\u30F3\u30C8\u30E1\u30F3\u30D0\u30FCID\u306E\u53D6\u5F97
541
+
542
+ #### \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3
543
+ - GET \`/v1/campaigns\` \u2014 \u5168\u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u306E\u4E00\u89A7
544
+ - GET \`/v1/campaigns/{campaign_id}\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u306E\u8A73\u7D30
545
+ - GET \`/v1/campaigns/{campaign_id}/actions\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u30A2\u30AF\u30B7\u30E7\u30F3\u306E\u53D6\u5F97
546
+ - GET \`/v1/campaigns/{campaign_id}/metrics\` \u2014 \u30AD\u30E3\u30F3\u30DA\u30FC\u30F3\u30E1\u30C8\u30EA\u30AF\u30B9\u306E\u53D6\u5F97
547
+
548
+ #### \u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC
549
+ - GET \`/v1/newsletters\` \u2014 \u5168\u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC\u306E\u4E00\u89A7
550
+ - GET \`/v1/newsletters/{newsletter_id}\` \u2014 \u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC\u306E\u8A73\u7D30
551
+ - GET \`/v1/newsletters/{newsletter_id}/metrics\` \u2014 \u30CB\u30E5\u30FC\u30B9\u30EC\u30BF\u30FC\u30E1\u30C8\u30EA\u30AF\u30B9\u306E\u53D6\u5F97
552
+
553
+ #### \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8
554
+ - GET \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8\u30C8\u30EA\u30AC\u30FC\u4E00\u89A7
555
+ - POST \`/v1/campaigns/{broadcast_id}/triggers\` \u2014 \u30D6\u30ED\u30FC\u30C9\u30AD\u30E3\u30B9\u30C8\u306E\u30C8\u30EA\u30AC\u30FC
556
+
557
+ #### \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30E1\u30C3\u30BB\u30FC\u30B8
558
+ - POST \`/v1/send/email\` \u2014 \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30E1\u30FC\u30EB\u306E\u9001\u4FE1
559
+ - POST \`/v1/send/push\` \u2014 \u30C8\u30E9\u30F3\u30B6\u30AF\u30B7\u30E7\u30F3\u30D7\u30C3\u30B7\u30E5\u901A\u77E5\u306E\u9001\u4FE1
560
+
561
+ #### \u30E1\u30C3\u30BB\u30FC\u30B8\u60C5\u5831
562
+ - GET \`/v1/messages/{message_id}\` \u2014 \u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u8A73\u7D30
563
+ - GET \`/v1/messages/{message_id}/deliveries\` \u2014 \u914D\u4FE1\u8A66\u884C\u306E\u53D6\u5F97
564
+
565
+ #### \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
566
+ - POST \`/v1/exports/customers\` \u2014 \u9867\u5BA2\u30C7\u30FC\u30BF\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
567
+ - POST \`/v1/exports/deliveries\` \u2014 \u914D\u4FE1\u30C7\u30FC\u30BF\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
568
+ - GET \`/v1/exports/{export_id}\` \u2014 \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u72B6\u614B\u306E\u53D6\u5F97
569
+ - GET \`/v1/exports/{export_id}/download\` \u2014 \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306E\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9
570
+
571
+ ### \u30D2\u30F3\u30C8
572
+ - 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
573
+ - \u30BB\u30B0\u30E1\u30F3\u30C8\u30E1\u30F3\u30D0\u30FC\u30B7\u30C3\u30D7\u306F\u9867\u5BA2ID\u306E\u914D\u5217\u3092\u8FD4\u5374
574
+ - \u5927\u91CF\u30C7\u30FC\u30BF\u53D6\u5F97\u306B\u306Fexports\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528
575
+ - \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`
576
+ },
577
+ tools
578
+ });
579
+
580
+ // src/connectors/create-connector-sdk.ts
581
+ import { readFileSync } from "fs";
582
+ import path from "path";
583
+
584
+ // src/connector-client/env.ts
585
+ function resolveEnvVar(entry, key, connectionId) {
586
+ const envVarName = entry.envVars[key];
587
+ if (!envVarName) {
588
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
589
+ }
590
+ const value = process.env[envVarName];
591
+ if (!value) {
592
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
593
+ }
594
+ return value;
595
+ }
596
+ function resolveEnvVarOptional(entry, key) {
597
+ const envVarName = entry.envVars[key];
598
+ if (!envVarName) return void 0;
599
+ return process.env[envVarName] || void 0;
600
+ }
601
+
602
+ // src/connector-client/proxy-fetch.ts
603
+ import { getContext } from "hono/context-storage";
604
+ import { getCookie } from "hono/cookie";
605
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
606
+ function createSandboxProxyFetch(connectionId) {
607
+ return async (input, init) => {
608
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
609
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
610
+ if (!token || !sandboxId) {
611
+ throw new Error(
612
+ "Connection proxy is not configured. Please check your deployment settings."
613
+ );
614
+ }
615
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
616
+ const originalMethod = init?.method ?? "GET";
617
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
618
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
619
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
620
+ return fetch(proxyUrl, {
621
+ method: "POST",
622
+ headers: {
623
+ "Content-Type": "application/json",
624
+ Authorization: `Bearer ${token}`
625
+ },
626
+ body: JSON.stringify({
627
+ url: originalUrl,
628
+ method: originalMethod,
629
+ body: originalBody
630
+ })
631
+ });
632
+ };
633
+ }
634
+ function createDeployedAppProxyFetch(connectionId) {
635
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
636
+ if (!projectId) {
637
+ throw new Error(
638
+ "Connection proxy is not configured. Please check your deployment settings."
639
+ );
640
+ }
641
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
642
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
643
+ return async (input, init) => {
644
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
645
+ const originalMethod = init?.method ?? "GET";
646
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
647
+ const c = getContext();
648
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
649
+ if (!appSession) {
650
+ throw new Error(
651
+ "No authentication method available for connection proxy."
652
+ );
653
+ }
654
+ return fetch(proxyUrl, {
655
+ method: "POST",
656
+ headers: {
657
+ "Content-Type": "application/json",
658
+ Authorization: `Bearer ${appSession}`
659
+ },
660
+ body: JSON.stringify({
661
+ url: originalUrl,
662
+ method: originalMethod,
663
+ body: originalBody
664
+ })
665
+ });
666
+ };
667
+ }
668
+ function createProxyFetch(connectionId) {
669
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
670
+ return createSandboxProxyFetch(connectionId);
671
+ }
672
+ return createDeployedAppProxyFetch(connectionId);
673
+ }
674
+
675
+ // src/connectors/create-connector-sdk.ts
676
+ function loadConnectionsSync() {
677
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
678
+ try {
679
+ const raw = readFileSync(filePath, "utf-8");
680
+ return JSON.parse(raw);
681
+ } catch {
682
+ return {};
683
+ }
684
+ }
685
+ function createConnectorSdk(plugin, createClient2) {
686
+ return (connectionId) => {
687
+ const connections = loadConnectionsSync();
688
+ const entry = connections[connectionId];
689
+ if (!entry) {
690
+ throw new Error(
691
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
692
+ );
693
+ }
694
+ if (entry.connector.slug !== plugin.slug) {
695
+ throw new Error(
696
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
697
+ );
698
+ }
699
+ const params = {};
700
+ for (const param of Object.values(plugin.parameters)) {
701
+ if (param.required) {
702
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
703
+ } else {
704
+ const val = resolveEnvVarOptional(entry, param.slug);
705
+ if (val !== void 0) params[param.slug] = val;
706
+ }
707
+ }
708
+ return createClient2(params, createProxyFetch(connectionId));
709
+ };
710
+ }
711
+
712
+ // src/connectors/entries/customerio.ts
713
+ var connection = createConnectorSdk(customerioConnector, createClient);
714
+ export {
715
+ connection
716
+ };