@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,875 @@
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/gmail/sdk/index.ts
46
+ import * as crypto from "crypto";
47
+
48
+ // ../connectors/src/connectors/gmail/parameters.ts
49
+ var parameters = {
50
+ serviceAccountKeyJsonBase64: new ParameterDefinition({
51
+ slug: "service-account-key-json-base64",
52
+ name: "Google Cloud Service Account JSON",
53
+ description: "The service account JSON key used to authenticate with Google Cloud Platform. The service account must have domain-wide delegation enabled and be granted the Gmail API scope in Google Workspace admin.",
54
+ envVarBaseKey: "GMAIL_SERVICE_ACCOUNT_JSON_BASE64",
55
+ type: "base64EncodedJson",
56
+ secret: true,
57
+ required: true
58
+ }),
59
+ delegatedUserEmail: new ParameterDefinition({
60
+ slug: "delegated-user-email",
61
+ name: "Delegated User Email",
62
+ description: "The email address of the Google Workspace user whose Gmail mailbox the service account will access via domain-wide delegation.",
63
+ envVarBaseKey: "GMAIL_DELEGATED_USER_EMAIL",
64
+ type: "text",
65
+ secret: false,
66
+ required: true
67
+ })
68
+ };
69
+
70
+ // ../connectors/src/connectors/gmail/sdk/index.ts
71
+ var TOKEN_URL = "https://oauth2.googleapis.com/token";
72
+ var BASE_URL = "https://gmail.googleapis.com/gmail/v1/users";
73
+ var SCOPE = "https://www.googleapis.com/auth/gmail.readonly";
74
+ function base64url(input) {
75
+ const buf = typeof input === "string" ? Buffer.from(input) : input;
76
+ return buf.toString("base64url");
77
+ }
78
+ function buildJwt(clientEmail, privateKey, subject, nowSec) {
79
+ const header = base64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
80
+ const payload = base64url(
81
+ JSON.stringify({
82
+ iss: clientEmail,
83
+ sub: subject,
84
+ scope: SCOPE,
85
+ aud: TOKEN_URL,
86
+ iat: nowSec,
87
+ exp: nowSec + 3600
88
+ })
89
+ );
90
+ const signingInput = `${header}.${payload}`;
91
+ const sign = crypto.createSign("RSA-SHA256");
92
+ sign.update(signingInput);
93
+ sign.end();
94
+ const signature = base64url(sign.sign(privateKey));
95
+ return `${signingInput}.${signature}`;
96
+ }
97
+ function createClient(params) {
98
+ const serviceAccountKeyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
99
+ const delegatedUserEmail = params[parameters.delegatedUserEmail.slug];
100
+ if (!serviceAccountKeyJsonBase64) {
101
+ throw new Error(
102
+ `gmail: missing required parameter: ${parameters.serviceAccountKeyJsonBase64.slug}`
103
+ );
104
+ }
105
+ if (!delegatedUserEmail) {
106
+ throw new Error(
107
+ `gmail: missing required parameter: ${parameters.delegatedUserEmail.slug}`
108
+ );
109
+ }
110
+ let serviceAccountKey;
111
+ try {
112
+ const decoded = Buffer.from(
113
+ serviceAccountKeyJsonBase64,
114
+ "base64"
115
+ ).toString("utf-8");
116
+ serviceAccountKey = JSON.parse(decoded);
117
+ } catch {
118
+ throw new Error(
119
+ "gmail: failed to decode service account key JSON from base64"
120
+ );
121
+ }
122
+ if (!serviceAccountKey.client_email || !serviceAccountKey.private_key) {
123
+ throw new Error(
124
+ "gmail: service account key JSON must contain client_email and private_key"
125
+ );
126
+ }
127
+ let cachedToken = null;
128
+ let tokenExpiresAt = 0;
129
+ async function getAccessToken() {
130
+ const nowSec = Math.floor(Date.now() / 1e3);
131
+ if (cachedToken && nowSec < tokenExpiresAt - 60) {
132
+ return cachedToken;
133
+ }
134
+ const jwt = buildJwt(
135
+ serviceAccountKey.client_email,
136
+ serviceAccountKey.private_key,
137
+ delegatedUserEmail,
138
+ nowSec
139
+ );
140
+ const response = await fetch(TOKEN_URL, {
141
+ method: "POST",
142
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
143
+ body: new URLSearchParams({
144
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
145
+ assertion: jwt
146
+ })
147
+ });
148
+ if (!response.ok) {
149
+ const text = await response.text();
150
+ throw new Error(
151
+ `gmail: token exchange failed (${response.status}): ${text}`
152
+ );
153
+ }
154
+ const data = await response.json();
155
+ cachedToken = data.access_token;
156
+ tokenExpiresAt = nowSec + data.expires_in;
157
+ return cachedToken;
158
+ }
159
+ async function request(path2, init) {
160
+ const accessToken = await getAccessToken();
161
+ const url = `${BASE_URL}${path2.startsWith("/") ? "" : "/"}${path2}`;
162
+ const headers = new Headers(init?.headers);
163
+ headers.set("Authorization", `Bearer ${accessToken}`);
164
+ return fetch(url, { ...init, headers });
165
+ }
166
+ async function getProfile() {
167
+ const response = await request("/me/profile");
168
+ if (!response.ok) {
169
+ const body = await response.text();
170
+ throw new Error(
171
+ `gmail: getProfile failed (${response.status}): ${body}`
172
+ );
173
+ }
174
+ return await response.json();
175
+ }
176
+ async function listLabels() {
177
+ const response = await request("/me/labels");
178
+ if (!response.ok) {
179
+ const body = await response.text();
180
+ throw new Error(
181
+ `gmail: listLabels failed (${response.status}): ${body}`
182
+ );
183
+ }
184
+ return await response.json();
185
+ }
186
+ async function listMessages(options) {
187
+ const params2 = new URLSearchParams();
188
+ if (options?.q) params2.set("q", options.q);
189
+ if (options?.maxResults) params2.set("maxResults", String(options.maxResults));
190
+ if (options?.pageToken) params2.set("pageToken", options.pageToken);
191
+ if (options?.labelIds) {
192
+ for (const labelId of options.labelIds) {
193
+ params2.append("labelIds", labelId);
194
+ }
195
+ }
196
+ const qs = params2.toString();
197
+ const response = await request(`/me/messages${qs ? `?${qs}` : ""}`);
198
+ if (!response.ok) {
199
+ const body = await response.text();
200
+ throw new Error(
201
+ `gmail: listMessages failed (${response.status}): ${body}`
202
+ );
203
+ }
204
+ return await response.json();
205
+ }
206
+ async function getMessage(messageId, format) {
207
+ const p = new URLSearchParams();
208
+ if (format) p.set("format", format);
209
+ const qs = p.toString();
210
+ const response = await request(
211
+ `/me/messages/${encodeURIComponent(messageId)}${qs ? `?${qs}` : ""}`
212
+ );
213
+ if (!response.ok) {
214
+ const body = await response.text();
215
+ throw new Error(
216
+ `gmail: getMessage failed (${response.status}): ${body}`
217
+ );
218
+ }
219
+ return await response.json();
220
+ }
221
+ async function listThreads(options) {
222
+ const params2 = new URLSearchParams();
223
+ if (options?.q) params2.set("q", options.q);
224
+ if (options?.maxResults) params2.set("maxResults", String(options.maxResults));
225
+ if (options?.pageToken) params2.set("pageToken", options.pageToken);
226
+ if (options?.labelIds) {
227
+ for (const labelId of options.labelIds) {
228
+ params2.append("labelIds", labelId);
229
+ }
230
+ }
231
+ const qs = params2.toString();
232
+ const response = await request(`/me/threads${qs ? `?${qs}` : ""}`);
233
+ if (!response.ok) {
234
+ const body = await response.text();
235
+ throw new Error(
236
+ `gmail: listThreads failed (${response.status}): ${body}`
237
+ );
238
+ }
239
+ return await response.json();
240
+ }
241
+ async function getThread(threadId, format) {
242
+ const p = new URLSearchParams();
243
+ if (format) p.set("format", format);
244
+ const qs = p.toString();
245
+ const response = await request(
246
+ `/me/threads/${encodeURIComponent(threadId)}${qs ? `?${qs}` : ""}`
247
+ );
248
+ if (!response.ok) {
249
+ const body = await response.text();
250
+ throw new Error(
251
+ `gmail: getThread failed (${response.status}): ${body}`
252
+ );
253
+ }
254
+ return await response.json();
255
+ }
256
+ return {
257
+ request,
258
+ getProfile,
259
+ listLabels,
260
+ listMessages,
261
+ getMessage,
262
+ listThreads,
263
+ getThread
264
+ };
265
+ }
266
+
267
+ // ../connectors/src/connector-onboarding.ts
268
+ var ConnectorOnboarding = class {
269
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
270
+ connectionSetupInstructions;
271
+ /** Phase 2: Data overview instructions */
272
+ dataOverviewInstructions;
273
+ constructor(config) {
274
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
275
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
276
+ }
277
+ getConnectionSetupPrompt(language) {
278
+ return this.connectionSetupInstructions?.[language] ?? null;
279
+ }
280
+ getDataOverviewInstructions(language) {
281
+ return this.dataOverviewInstructions[language];
282
+ }
283
+ };
284
+
285
+ // ../connectors/src/connector-tool.ts
286
+ var ConnectorTool = class {
287
+ name;
288
+ description;
289
+ inputSchema;
290
+ outputSchema;
291
+ _execute;
292
+ constructor(config) {
293
+ this.name = config.name;
294
+ this.description = config.description;
295
+ this.inputSchema = config.inputSchema;
296
+ this.outputSchema = config.outputSchema;
297
+ this._execute = config.execute;
298
+ }
299
+ createTool(connections, config) {
300
+ return {
301
+ description: this.description,
302
+ inputSchema: this.inputSchema,
303
+ outputSchema: this.outputSchema,
304
+ execute: (input) => this._execute(input, connections, config)
305
+ };
306
+ }
307
+ };
308
+
309
+ // ../connectors/src/connector-plugin.ts
310
+ var ConnectorPlugin = class _ConnectorPlugin {
311
+ slug;
312
+ authType;
313
+ name;
314
+ description;
315
+ iconUrl;
316
+ parameters;
317
+ releaseFlag;
318
+ proxyPolicy;
319
+ experimentalAttributes;
320
+ onboarding;
321
+ systemPrompt;
322
+ tools;
323
+ query;
324
+ checkConnection;
325
+ constructor(config) {
326
+ this.slug = config.slug;
327
+ this.authType = config.authType;
328
+ this.name = config.name;
329
+ this.description = config.description;
330
+ this.iconUrl = config.iconUrl;
331
+ this.parameters = config.parameters;
332
+ this.releaseFlag = config.releaseFlag;
333
+ this.proxyPolicy = config.proxyPolicy;
334
+ this.experimentalAttributes = config.experimentalAttributes;
335
+ this.onboarding = config.onboarding;
336
+ this.systemPrompt = config.systemPrompt;
337
+ this.tools = config.tools;
338
+ this.query = config.query;
339
+ this.checkConnection = config.checkConnection;
340
+ }
341
+ get connectorKey() {
342
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
343
+ }
344
+ /**
345
+ * Create tools for connections that belong to this connector.
346
+ * Filters connections by connectorKey internally.
347
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
348
+ */
349
+ createTools(connections, config) {
350
+ const myConnections = connections.filter(
351
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
352
+ );
353
+ const result = {};
354
+ for (const t of Object.values(this.tools)) {
355
+ result[`${this.connectorKey}_${t.name}`] = t.createTool(
356
+ myConnections,
357
+ config
358
+ );
359
+ }
360
+ return result;
361
+ }
362
+ static deriveKey(slug, authType) {
363
+ return authType ? `${slug}-${authType}` : slug;
364
+ }
365
+ };
366
+
367
+ // ../connectors/src/auth-types.ts
368
+ var AUTH_TYPES = {
369
+ OAUTH: "oauth",
370
+ API_KEY: "api-key",
371
+ JWT: "jwt",
372
+ SERVICE_ACCOUNT: "service-account",
373
+ PAT: "pat",
374
+ USER_PASSWORD: "user-password"
375
+ };
376
+
377
+ // ../connectors/src/connectors/gmail/tools/request.ts
378
+ import { z } from "zod";
379
+ var BASE_URL2 = "https://gmail.googleapis.com/gmail/v1/users";
380
+ var REQUEST_TIMEOUT_MS = 6e4;
381
+ var inputSchema = z.object({
382
+ toolUseIntent: z.string().optional().describe(
383
+ "Brief description of what you intend to accomplish with this tool call"
384
+ ),
385
+ connectionId: z.string().describe("ID of the Gmail service account connection to use"),
386
+ method: z.enum(["GET"]).describe("HTTP method (read-only, GET only)"),
387
+ path: z.string().describe(
388
+ "API path appended to https://gmail.googleapis.com/gmail/v1/users (e.g., '/me/messages', '/me/messages/{id}', '/me/labels'). Use '/me' as the userId."
389
+ ),
390
+ queryParams: z.record(z.string(), z.string()).optional().describe(
391
+ "Query parameters to append to the URL (e.g., { q: 'from:example@gmail.com', maxResults: '10' })"
392
+ )
393
+ });
394
+ var outputSchema = z.discriminatedUnion("success", [
395
+ z.object({
396
+ success: z.literal(true),
397
+ status: z.number(),
398
+ data: z.record(z.string(), z.unknown())
399
+ }),
400
+ z.object({
401
+ success: z.literal(false),
402
+ error: z.string()
403
+ })
404
+ ]);
405
+ var requestTool = new ConnectorTool({
406
+ name: "request",
407
+ description: `Send authenticated GET requests to the Gmail API v1.
408
+ Authentication is handled automatically using a service account with domain-wide delegation.
409
+ All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me' as the userId prefix (e.g., '/me/messages').`,
410
+ inputSchema,
411
+ outputSchema,
412
+ async execute({ connectionId, method, path: path2, queryParams }, connections) {
413
+ const connection2 = connections.find((c) => c.id === connectionId);
414
+ if (!connection2) {
415
+ return {
416
+ success: false,
417
+ error: `Connection ${connectionId} not found`
418
+ };
419
+ }
420
+ console.log(
421
+ `[connector-request] gmail/${connection2.name}: ${method} ${path2}`
422
+ );
423
+ try {
424
+ const { GoogleAuth } = await import("google-auth-library");
425
+ const keyJsonBase64 = parameters.serviceAccountKeyJsonBase64.getValue(connection2);
426
+ const delegatedUserEmail = parameters.delegatedUserEmail.getValue(connection2);
427
+ const credentials = JSON.parse(
428
+ Buffer.from(keyJsonBase64, "base64").toString("utf-8")
429
+ );
430
+ const auth = new GoogleAuth({
431
+ credentials,
432
+ scopes: ["https://www.googleapis.com/auth/gmail.readonly"],
433
+ clientOptions: {
434
+ subject: delegatedUserEmail
435
+ }
436
+ });
437
+ const token = await auth.getAccessToken();
438
+ if (!token) {
439
+ return {
440
+ success: false,
441
+ error: "Failed to obtain access token"
442
+ };
443
+ }
444
+ let url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
445
+ if (queryParams) {
446
+ const searchParams = new URLSearchParams(queryParams);
447
+ url += `?${searchParams.toString()}`;
448
+ }
449
+ const controller = new AbortController();
450
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
451
+ try {
452
+ const response = await fetch(url, {
453
+ method,
454
+ headers: {
455
+ Authorization: `Bearer ${token}`,
456
+ "Content-Type": "application/json"
457
+ },
458
+ signal: controller.signal
459
+ });
460
+ const data = await response.json();
461
+ if (!response.ok) {
462
+ const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
463
+ return { success: false, error: errorMessage };
464
+ }
465
+ return { success: true, status: response.status, data };
466
+ } finally {
467
+ clearTimeout(timeout);
468
+ }
469
+ } catch (err) {
470
+ const msg = err instanceof Error ? err.message : String(err);
471
+ return { success: false, error: msg };
472
+ }
473
+ }
474
+ });
475
+
476
+ // ../connectors/src/connectors/gmail/setup.ts
477
+ var requestToolName = `gmail_${requestTool.name}`;
478
+ var gmailOnboarding = new ConnectorOnboarding({
479
+ connectionSetupInstructions: {
480
+ ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Gmail\uFF08\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\uFF09\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
481
+
482
+ 1. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u53D6\u5F97\u3059\u308B:
483
+ - \`method\`: \`"GET"\`
484
+ - \`path\`: \`"/me/profile"\`
485
+ 2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u4EE5\u4E0B\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u30E6\u30FC\u30B6\u30FC\u306B\u4F1D\u3048\u308B:
486
+ - \u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u304C\u6709\u52B9\u304B
487
+ - Google Workspace\u7BA1\u7406\u30B3\u30F3\u30BD\u30FC\u30EB\u3067Gmail API\u30B9\u30B3\u30FC\u30D7\u304C\u8A31\u53EF\u3055\u308C\u3066\u3044\u308B\u304B
488
+ - \u59D4\u4EFB\u5BFE\u8C61\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u6B63\u3057\u3044\u304B
489
+ 3. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B:
490
+ - \`method\`: \`"GET"\`
491
+ - \`path\`: \`"/me/labels"\`
492
+ 4. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3059:
493
+ - \`email\`: \u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9
494
+ - \`labels\`: \u4E3B\u8981\u306A\u30E9\u30D9\u30EB\u540D\u4E00\u89A7\uFF08\u30AB\u30F3\u30DE\u533A\u5207\u308A\u3001INBOX, SENT, DRAFT, SPAM, TRASH\u7B49\u306E\u30B7\u30B9\u30C6\u30E0\u30E9\u30D9\u30EB\u3092\u542B\u3080\uFF09
495
+ - \`note\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5185\u5BB9\u306E\u7C21\u5358\u306A\u8AAC\u660E
496
+
497
+ #### \u5236\u7D04
498
+ - **\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u672C\u6587\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3053\u3068**\u3002\u5B9F\u884C\u3057\u3066\u3088\u3044\u306E\u306F\u4E0A\u8A18\u624B\u9806\u3067\u6307\u5B9A\u3055\u308C\u305F\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u53D6\u5F97\u3068\u30E9\u30D9\u30EB\u4E00\u89A7\u53D6\u5F97\u306E\u307F
499
+ - \u30C4\u30FC\u30EB\u9593\u306F1\u6587\u3060\u3051\u66F8\u3044\u3066\u5373\u6B21\u306E\u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057\u3002\u4E0D\u8981\u306A\u8AAC\u660E\u306F\u7701\u7565\u3057\u3001\u52B9\u7387\u7684\u306B\u9032\u3081\u308B`,
500
+ en: `Follow these steps to set up the Gmail (Service Account) connection.
501
+
502
+ 1. Call \`${requestToolName}\` to get the user's profile:
503
+ - \`method\`: \`"GET"\`
504
+ - \`path\`: \`"/me/profile"\`
505
+ 2. If an error is returned, ask the user to verify:
506
+ - Domain-wide delegation is enabled for the service account
507
+ - Gmail API scope is authorized in Google Workspace admin console
508
+ - The delegated user email address is correct
509
+ 3. Call \`${requestToolName}\` to get the label list:
510
+ - \`method\`: \`"GET"\`
511
+ - \`path\`: \`"/me/labels"\`
512
+ 4. Call \`updateConnectionContext\`:
513
+ - \`email\`: The user's email address
514
+ - \`labels\`: Key label names (comma-separated, including system labels like INBOX, SENT, DRAFT, SPAM, TRASH)
515
+ - \`note\`: Brief description of the setup
516
+
517
+ #### Constraints
518
+ - **Do NOT read message bodies during setup**. Only the profile and label list requests specified above are allowed
519
+ - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
520
+ },
521
+ dataOverviewInstructions: {
522
+ en: `1. Call gmail_request with GET /me/labels to list all labels
523
+ 2. Call gmail_request with GET /me/messages?maxResults=5 to get recent message IDs
524
+ 3. Call gmail_request with GET /me/messages/{id}?format=metadata for each message to see subjects and senders`,
525
+ ja: `1. gmail_request \u3067 GET /me/labels \u3092\u547C\u3073\u51FA\u3057\u3001\u5168\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97
526
+ 2. gmail_request \u3067 GET /me/messages?maxResults=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u65B0\u30E1\u30C3\u30BB\u30FC\u30B8ID\u3092\u53D6\u5F97
527
+ 3. \u5404\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3064\u3044\u3066 gmail_request \u3067 GET /me/messages/{id}?format=metadata \u3092\u547C\u3073\u51FA\u3057\u3001\u4EF6\u540D\u3068\u9001\u4FE1\u8005\u3092\u78BA\u8A8D`
528
+ }
529
+ });
530
+
531
+ // ../connectors/src/connectors/gmail/index.ts
532
+ var tools = { request: requestTool };
533
+ var gmailConnector = new ConnectorPlugin({
534
+ slug: "gmail",
535
+ authType: AUTH_TYPES.SERVICE_ACCOUNT,
536
+ name: "Gmail",
537
+ description: "Connect to Gmail for email data access using a service account with domain-wide delegation. Read-only access to messages, threads, and labels.",
538
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4V3rfaSc1ksFIt2eHBNIwJ/7f3be41a154a6d96dcf229ed0e5858c9/Gmail_icon__2020_.svg.png",
539
+ parameters,
540
+ releaseFlag: { dev1: true, dev2: false, prod: false },
541
+ onboarding: gmailOnboarding,
542
+ systemPrompt: {
543
+ en: `### Tools
544
+
545
+ - \`gmail_request\`: The only way to call the Gmail API (read-only). Use it to list messages, get message details, list labels, list threads, and get user profile. Authentication is handled automatically using a service account with domain-wide delegation.
546
+
547
+ ### Gmail API Reference
548
+
549
+ #### Available Endpoints
550
+ - GET \`/me/profile\` \u2014 Get the delegated user's profile (email address, total messages/threads)
551
+ - GET \`/me/labels\` \u2014 List all labels in the mailbox
552
+ - GET \`/me/labels/{id}\` \u2014 Get details for a specific label
553
+ - GET \`/me/messages\` \u2014 List messages (returns IDs only; use format param on individual messages)
554
+ - GET \`/me/messages/{id}\` \u2014 Get a specific message
555
+ - GET \`/me/threads\` \u2014 List threads
556
+ - GET \`/me/threads/{id}\` \u2014 Get a specific thread with all its messages
557
+
558
+ #### Key Query Parameters
559
+ - \`q\` \u2014 Gmail search query (same syntax as Gmail search box). Examples:
560
+ - \`from:user@example.com\` \u2014 Messages from a specific sender
561
+ - \`subject:meeting\` \u2014 Messages with "meeting" in the subject
562
+ - \`after:2025/01/01 before:2025/02/01\` \u2014 Messages within a date range
563
+ - \`label:INBOX is:unread\` \u2014 Unread messages in inbox
564
+ - \`has:attachment\` \u2014 Messages with attachments
565
+ - \`maxResults\` \u2014 Maximum number of results (default 100, max 500)
566
+ - \`pageToken\` \u2014 Token for pagination (from nextPageToken in response)
567
+ - \`labelIds\` \u2014 Filter by label IDs (e.g., \`INBOX\`, \`SENT\`, \`DRAFT\`)
568
+ - \`format\` \u2014 Message format for /messages/{id} and /threads/{id}:
569
+ - \`full\` \u2014 Complete message with parsed payload (default)
570
+ - \`metadata\` \u2014 Only headers (Subject, From, To, Date) without body
571
+ - \`minimal\` \u2014 Only IDs, labels, and snippet
572
+ - \`raw\` \u2014 Full RFC 2822 formatted message in base64url
573
+
574
+ #### Tips
575
+ - Always use \`/me\` as the userId \u2014 it refers to the delegated user
576
+ - List endpoints return only IDs; fetch individual resources for details
577
+ - Use \`format=metadata\` to efficiently get subject/sender without full body
578
+ - Message body content is base64url encoded in \`payload.body.data\` or nested \`payload.parts[].body.data\`
579
+ - Use \`q\` parameter for powerful search filtering (same as Gmail search syntax)
580
+ - System labels include: INBOX, SENT, DRAFT, SPAM, TRASH, UNREAD, STARRED, IMPORTANT, CATEGORY_PERSONAL, CATEGORY_SOCIAL, CATEGORY_PROMOTIONS, CATEGORY_UPDATES, CATEGORY_FORUMS
581
+
582
+ ### Business Logic
583
+
584
+ The business logic type for this connector is "typescript". Write handler code using the connector SDK shown below. Do NOT access credentials directly from environment variables.
585
+
586
+ #### Example
587
+
588
+ \`\`\`ts
589
+ import { connection } from "@squadbase/vite-server/connectors/gmail";
590
+
591
+ const gmail = connection("<connectionId>");
592
+
593
+ // Get user profile
594
+ const profile = await gmail.getProfile();
595
+ console.log(profile.emailAddress, profile.messagesTotal);
596
+
597
+ // List recent messages
598
+ const messages = await gmail.listMessages({ maxResults: 10 });
599
+ for (const msg of messages.messages) {
600
+ const detail = await gmail.getMessage(msg.id, "metadata");
601
+ const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
602
+ console.log(subject, detail.snippet);
603
+ }
604
+
605
+ // Search messages
606
+ const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
607
+
608
+ // List labels
609
+ const labels = await gmail.listLabels();
610
+ labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
611
+
612
+ // Get a thread
613
+ const thread = await gmail.getThread("<threadId>");
614
+ thread.messages.forEach(m => console.log(m.snippet));
615
+ \`\`\``,
616
+ ja: `### \u30C4\u30FC\u30EB
617
+
618
+ - \`gmail_request\`: Gmail API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\uFF08\u8AAD\u307F\u53D6\u308A\u5C02\u7528\uFF09\u3002\u30E1\u30C3\u30BB\u30FC\u30B8\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30E1\u30C3\u30BB\u30FC\u30B8\u8A73\u7D30\u306E\u53D6\u5F97\u3001\u30E9\u30D9\u30EB\u4E00\u89A7\u3001\u30B9\u30EC\u30C3\u30C9\u4E00\u89A7\u3001\u30E6\u30FC\u30B6\u30FC\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u306E\u53D6\u5F97\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u3092\u4F7F\u7528\u3057\u3066\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u51E6\u7406\u3055\u308C\u307E\u3059\u3002
619
+
620
+ ### Gmail API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
621
+
622
+ #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
623
+ - GET \`/me/profile\` \u2014 \u59D4\u4EFB\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u53D6\u5F97\uFF08\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3001\u30E1\u30C3\u30BB\u30FC\u30B8/\u30B9\u30EC\u30C3\u30C9\u7DCF\u6570\uFF09
624
+ - GET \`/me/labels\` \u2014 \u30E1\u30FC\u30EB\u30DC\u30C3\u30AF\u30B9\u306E\u5168\u30E9\u30D9\u30EB\u3092\u4E00\u89A7
625
+ - GET \`/me/labels/{id}\` \u2014 \u7279\u5B9A\u30E9\u30D9\u30EB\u306E\u8A73\u7D30\u3092\u53D6\u5F97
626
+ - GET \`/me/messages\` \u2014 \u30E1\u30C3\u30BB\u30FC\u30B8\u4E00\u89A7\uFF08ID\u306E\u307F\u8FD4\u5374\u3002\u500B\u5225\u30E1\u30C3\u30BB\u30FC\u30B8\u3067format\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528\uFF09
627
+ - GET \`/me/messages/{id}\` \u2014 \u7279\u5B9A\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
628
+ - GET \`/me/threads\` \u2014 \u30B9\u30EC\u30C3\u30C9\u4E00\u89A7
629
+ - GET \`/me/threads/{id}\` \u2014 \u7279\u5B9A\u30B9\u30EC\u30C3\u30C9\u306E\u5168\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
630
+
631
+ #### \u4E3B\u8981\u306A\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF
632
+ - \`q\` \u2014 Gmail\u691C\u7D22\u30AF\u30A8\u30EA\uFF08Gmail\u691C\u7D22\u30DC\u30C3\u30AF\u30B9\u3068\u540C\u3058\u69CB\u6587\uFF09\u3002\u4F8B\uFF1A
633
+ - \`from:user@example.com\` \u2014 \u7279\u5B9A\u306E\u9001\u4FE1\u8005\u304B\u3089\u306E\u30E1\u30C3\u30BB\u30FC\u30B8
634
+ - \`subject:meeting\` \u2014 \u4EF6\u540D\u306B\u300Cmeeting\u300D\u3092\u542B\u3080\u30E1\u30C3\u30BB\u30FC\u30B8
635
+ - \`after:2025/01/01 before:2025/02/01\` \u2014 \u65E5\u4ED8\u7BC4\u56F2\u5185\u306E\u30E1\u30C3\u30BB\u30FC\u30B8
636
+ - \`label:INBOX is:unread\` \u2014 \u53D7\u4FE1\u30C8\u30EC\u30A4\u306E\u672A\u8AAD\u30E1\u30C3\u30BB\u30FC\u30B8
637
+ - \`has:attachment\` \u2014 \u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u4ED8\u304D\u30E1\u30C3\u30BB\u30FC\u30B8
638
+ - \`maxResults\` \u2014 \u6700\u5927\u7D50\u679C\u6570\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8100\u3001\u6700\u5927500\uFF09
639
+ - \`pageToken\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u7528\u30C8\u30FC\u30AF\u30F3\uFF08\u30EC\u30B9\u30DD\u30F3\u30B9\u306EnextPageToken\u304B\u3089\u53D6\u5F97\uFF09
640
+ - \`labelIds\` \u2014 \u30E9\u30D9\u30EBID\u3067\u30D5\u30A3\u30EB\u30BF\uFF08\u4F8B\uFF1A\`INBOX\`, \`SENT\`, \`DRAFT\`\uFF09
641
+ - \`format\` \u2014 /messages/{id} \u3068 /threads/{id} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\uFF1A
642
+ - \`full\` \u2014 \u30D1\u30FC\u30B9\u6E08\u307F\u30DA\u30A4\u30ED\u30FC\u30C9\u4ED8\u304D\u306E\u5B8C\u5168\u306A\u30E1\u30C3\u30BB\u30FC\u30B8\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\uFF09
643
+ - \`metadata\` \u2014 \u30D8\u30C3\u30C0\u30FC\u306E\u307F\uFF08Subject, From, To, Date\uFF09\u3001\u672C\u6587\u306A\u3057
644
+ - \`minimal\` \u2014 ID\u3001\u30E9\u30D9\u30EB\u3001\u30B9\u30CB\u30DA\u30C3\u30C8\u306E\u307F
645
+ - \`raw\` \u2014 base64url\u30A8\u30F3\u30B3\u30FC\u30C9\u3055\u308C\u305F\u5B8C\u5168\u306ARFC 2822\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u30E1\u30C3\u30BB\u30FC\u30B8
646
+
647
+ #### \u30D2\u30F3\u30C8
648
+ - userId\u306B\u306F\u5E38\u306B \`/me\` \u3092\u4F7F\u7528 \u2014 \u59D4\u4EFB\u30E6\u30FC\u30B6\u30FC\u3092\u6307\u3057\u307E\u3059
649
+ - \u4E00\u89A7\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306FID\u306E\u307F\u8FD4\u5374\u3057\u307E\u3059\u3002\u8A73\u7D30\u306F\u500B\u5225\u30EA\u30BD\u30FC\u30B9\u3092\u53D6\u5F97\u3057\u3066\u304F\u3060\u3055\u3044
650
+ - \u4EF6\u540D/\u9001\u4FE1\u8005\u3092\u52B9\u7387\u7684\u306B\u53D6\u5F97\u3059\u308B\u306B\u306F \`format=metadata\` \u3092\u4F7F\u7528\u3057\u307E\u3059
651
+ - \u30E1\u30C3\u30BB\u30FC\u30B8\u672C\u6587\u306F \`payload.body.data\` \u307E\u305F\u306F\u30CD\u30B9\u30C8\u3055\u308C\u305F \`payload.parts[].body.data\` \u306Bbase64url\u30A8\u30F3\u30B3\u30FC\u30C9\u3067\u683C\u7D0D\u3055\u308C\u3066\u3044\u307E\u3059
652
+ - \u5F37\u529B\u306A\u691C\u7D22\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\u306B\u306F \`q\` \u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528\uFF08Gmail\u691C\u7D22\u3068\u540C\u3058\u69CB\u6587\uFF09
653
+ - \u30B7\u30B9\u30C6\u30E0\u30E9\u30D9\u30EB: INBOX, SENT, DRAFT, SPAM, TRASH, UNREAD, STARRED, IMPORTANT, CATEGORY_PERSONAL, CATEGORY_SOCIAL, CATEGORY_PROMOTIONS, CATEGORY_UPDATES, CATEGORY_FORUMS
654
+
655
+ ### Business Logic
656
+
657
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u4EE5\u4E0B\u306B\u793A\u3059\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u30CF\u30F3\u30C9\u30E9\u30B3\u30FC\u30C9\u3092\u8A18\u8FF0\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u76F4\u63A5\u8A8D\u8A3C\u60C5\u5831\u306B\u30A2\u30AF\u30BB\u30B9\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
658
+
659
+ #### Example
660
+
661
+ \`\`\`ts
662
+ import { connection } from "@squadbase/vite-server/connectors/gmail";
663
+
664
+ const gmail = connection("<connectionId>");
665
+
666
+ // Get user profile
667
+ const profile = await gmail.getProfile();
668
+ console.log(profile.emailAddress, profile.messagesTotal);
669
+
670
+ // List recent messages
671
+ const messages = await gmail.listMessages({ maxResults: 10 });
672
+ for (const msg of messages.messages) {
673
+ const detail = await gmail.getMessage(msg.id, "metadata");
674
+ const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
675
+ console.log(subject, detail.snippet);
676
+ }
677
+
678
+ // Search messages
679
+ const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
680
+
681
+ // List labels
682
+ const labels = await gmail.listLabels();
683
+ labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
684
+
685
+ // Get a thread
686
+ const thread = await gmail.getThread("<threadId>");
687
+ thread.messages.forEach(m => console.log(m.snippet));
688
+ \`\`\``
689
+ },
690
+ tools,
691
+ async checkConnection(params, _config) {
692
+ const { GoogleAuth } = await import("google-auth-library");
693
+ const credentials = JSON.parse(
694
+ Buffer.from(
695
+ params[parameters.serviceAccountKeyJsonBase64.slug],
696
+ "base64"
697
+ ).toString("utf-8")
698
+ );
699
+ const delegatedUserEmail = params[parameters.delegatedUserEmail.slug];
700
+ const auth = new GoogleAuth({
701
+ credentials,
702
+ scopes: ["https://www.googleapis.com/auth/gmail.readonly"],
703
+ clientOptions: {
704
+ subject: delegatedUserEmail
705
+ }
706
+ });
707
+ try {
708
+ const token = await auth.getAccessToken();
709
+ if (!token) {
710
+ return {
711
+ success: false,
712
+ error: "Failed to obtain access token"
713
+ };
714
+ }
715
+ const res = await fetch(
716
+ "https://gmail.googleapis.com/gmail/v1/users/me/profile",
717
+ {
718
+ method: "GET",
719
+ headers: { Authorization: `Bearer ${token}` }
720
+ }
721
+ );
722
+ if (!res.ok) {
723
+ const errorText = await res.text().catch(() => res.statusText);
724
+ return {
725
+ success: false,
726
+ error: `Gmail API failed: HTTP ${res.status} ${errorText}`
727
+ };
728
+ }
729
+ return { success: true };
730
+ } catch (error) {
731
+ return {
732
+ success: false,
733
+ error: error instanceof Error ? error.message : String(error)
734
+ };
735
+ }
736
+ }
737
+ });
738
+
739
+ // src/connectors/create-connector-sdk.ts
740
+ import { readFileSync } from "fs";
741
+ import path from "path";
742
+
743
+ // src/connector-client/env.ts
744
+ function resolveEnvVar(entry, key, connectionId) {
745
+ const envVarName = entry.envVars[key];
746
+ if (!envVarName) {
747
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
748
+ }
749
+ const value = process.env[envVarName];
750
+ if (!value) {
751
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
752
+ }
753
+ return value;
754
+ }
755
+ function resolveEnvVarOptional(entry, key) {
756
+ const envVarName = entry.envVars[key];
757
+ if (!envVarName) return void 0;
758
+ return process.env[envVarName] || void 0;
759
+ }
760
+
761
+ // src/connector-client/proxy-fetch.ts
762
+ import { getContext } from "hono/context-storage";
763
+ import { getCookie } from "hono/cookie";
764
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
765
+ function createSandboxProxyFetch(connectionId) {
766
+ return async (input, init) => {
767
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
768
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
769
+ if (!token || !sandboxId) {
770
+ throw new Error(
771
+ "Connection proxy is not configured. Please check your deployment settings."
772
+ );
773
+ }
774
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
775
+ const originalMethod = init?.method ?? "GET";
776
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
777
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
778
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
779
+ return fetch(proxyUrl, {
780
+ method: "POST",
781
+ headers: {
782
+ "Content-Type": "application/json",
783
+ Authorization: `Bearer ${token}`
784
+ },
785
+ body: JSON.stringify({
786
+ url: originalUrl,
787
+ method: originalMethod,
788
+ body: originalBody
789
+ })
790
+ });
791
+ };
792
+ }
793
+ function createDeployedAppProxyFetch(connectionId) {
794
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
795
+ if (!projectId) {
796
+ throw new Error(
797
+ "Connection proxy is not configured. Please check your deployment settings."
798
+ );
799
+ }
800
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
801
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
802
+ return async (input, init) => {
803
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
804
+ const originalMethod = init?.method ?? "GET";
805
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
806
+ const c = getContext();
807
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
808
+ if (!appSession) {
809
+ throw new Error(
810
+ "No authentication method available for connection proxy."
811
+ );
812
+ }
813
+ return fetch(proxyUrl, {
814
+ method: "POST",
815
+ headers: {
816
+ "Content-Type": "application/json",
817
+ Authorization: `Bearer ${appSession}`
818
+ },
819
+ body: JSON.stringify({
820
+ url: originalUrl,
821
+ method: originalMethod,
822
+ body: originalBody
823
+ })
824
+ });
825
+ };
826
+ }
827
+ function createProxyFetch(connectionId) {
828
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
829
+ return createSandboxProxyFetch(connectionId);
830
+ }
831
+ return createDeployedAppProxyFetch(connectionId);
832
+ }
833
+
834
+ // src/connectors/create-connector-sdk.ts
835
+ function loadConnectionsSync() {
836
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
837
+ try {
838
+ const raw = readFileSync(filePath, "utf-8");
839
+ return JSON.parse(raw);
840
+ } catch {
841
+ return {};
842
+ }
843
+ }
844
+ function createConnectorSdk(plugin, createClient2) {
845
+ return (connectionId) => {
846
+ const connections = loadConnectionsSync();
847
+ const entry = connections[connectionId];
848
+ if (!entry) {
849
+ throw new Error(
850
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
851
+ );
852
+ }
853
+ if (entry.connector.slug !== plugin.slug) {
854
+ throw new Error(
855
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
856
+ );
857
+ }
858
+ const params = {};
859
+ for (const param of Object.values(plugin.parameters)) {
860
+ if (param.required) {
861
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
862
+ } else {
863
+ const val = resolveEnvVarOptional(entry, param.slug);
864
+ if (val !== void 0) params[param.slug] = val;
865
+ }
866
+ }
867
+ return createClient2(params, createProxyFetch(connectionId));
868
+ };
869
+ }
870
+
871
+ // src/connectors/entries/gmail.ts
872
+ var connection = createConnectorSdk(gmailConnector, createClient);
873
+ export {
874
+ connection
875
+ };