@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.
Files changed (34) hide show
  1. package/dist/cli/index.js +13282 -4299
  2. package/dist/connectors/asana.d.ts +5 -0
  3. package/dist/connectors/asana.js +661 -0
  4. package/dist/connectors/customerio.d.ts +5 -0
  5. package/dist/connectors/customerio.js +633 -0
  6. package/dist/connectors/gmail-oauth.d.ts +5 -0
  7. package/dist/connectors/gmail-oauth.js +639 -0
  8. package/dist/connectors/google-ads.d.ts +5 -0
  9. package/dist/connectors/google-ads.js +784 -0
  10. package/dist/connectors/google-sheets.d.ts +5 -0
  11. package/dist/connectors/google-sheets.js +598 -0
  12. package/dist/connectors/hubspot.js +14 -5
  13. package/dist/connectors/intercom-oauth.d.ts +5 -0
  14. package/dist/connectors/intercom-oauth.js +510 -0
  15. package/dist/connectors/intercom.d.ts +5 -0
  16. package/dist/connectors/intercom.js +627 -0
  17. package/dist/connectors/jira-api-key.d.ts +5 -0
  18. package/dist/connectors/jira-api-key.js +523 -0
  19. package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
  20. package/dist/connectors/linkedin-ads-oauth.js +774 -0
  21. package/dist/connectors/linkedin-ads.d.ts +5 -0
  22. package/dist/connectors/linkedin-ads.js +782 -0
  23. package/dist/connectors/mailchimp-oauth.d.ts +5 -0
  24. package/dist/connectors/mailchimp-oauth.js +539 -0
  25. package/dist/connectors/mailchimp.d.ts +5 -0
  26. package/dist/connectors/mailchimp.js +646 -0
  27. package/dist/connectors/zendesk-oauth.d.ts +5 -0
  28. package/dist/connectors/zendesk-oauth.js +505 -0
  29. package/dist/connectors/zendesk.d.ts +5 -0
  30. package/dist/connectors/zendesk.js +631 -0
  31. package/dist/index.js +13238 -4255
  32. package/dist/main.js +13240 -4257
  33. package/dist/vite-plugin.js +13240 -4257
  34. package/package.json +42 -2
@@ -0,0 +1,639 @@
1
+ // ../connectors/src/connectors/gmail-oauth/sdk/index.ts
2
+ var BASE_URL = "https://gmail.googleapis.com/gmail/v1/users";
3
+ function createClient(_params, fetchFn = fetch) {
4
+ function request(path2, init) {
5
+ const url = `${BASE_URL}${path2.startsWith("/") ? "" : "/"}${path2}`;
6
+ return fetchFn(url, init);
7
+ }
8
+ async function getProfile() {
9
+ const response = await request("/me/profile");
10
+ if (!response.ok) {
11
+ const body = await response.text();
12
+ throw new Error(
13
+ `gmail: getProfile failed (${response.status}): ${body}`
14
+ );
15
+ }
16
+ return await response.json();
17
+ }
18
+ async function listLabels() {
19
+ const response = await request("/me/labels");
20
+ if (!response.ok) {
21
+ const body = await response.text();
22
+ throw new Error(
23
+ `gmail: listLabels failed (${response.status}): ${body}`
24
+ );
25
+ }
26
+ return await response.json();
27
+ }
28
+ async function listMessages(options) {
29
+ const params = new URLSearchParams();
30
+ if (options?.q) params.set("q", options.q);
31
+ if (options?.maxResults) params.set("maxResults", String(options.maxResults));
32
+ if (options?.pageToken) params.set("pageToken", options.pageToken);
33
+ if (options?.labelIds) {
34
+ for (const labelId of options.labelIds) {
35
+ params.append("labelIds", labelId);
36
+ }
37
+ }
38
+ const qs = params.toString();
39
+ const response = await request(`/me/messages${qs ? `?${qs}` : ""}`);
40
+ if (!response.ok) {
41
+ const body = await response.text();
42
+ throw new Error(
43
+ `gmail: listMessages failed (${response.status}): ${body}`
44
+ );
45
+ }
46
+ return await response.json();
47
+ }
48
+ async function getMessage(messageId, format) {
49
+ const params = new URLSearchParams();
50
+ if (format) params.set("format", format);
51
+ const qs = params.toString();
52
+ const response = await request(
53
+ `/me/messages/${encodeURIComponent(messageId)}${qs ? `?${qs}` : ""}`
54
+ );
55
+ if (!response.ok) {
56
+ const body = await response.text();
57
+ throw new Error(
58
+ `gmail: getMessage failed (${response.status}): ${body}`
59
+ );
60
+ }
61
+ return await response.json();
62
+ }
63
+ async function listThreads(options) {
64
+ const params = new URLSearchParams();
65
+ if (options?.q) params.set("q", options.q);
66
+ if (options?.maxResults) params.set("maxResults", String(options.maxResults));
67
+ if (options?.pageToken) params.set("pageToken", options.pageToken);
68
+ if (options?.labelIds) {
69
+ for (const labelId of options.labelIds) {
70
+ params.append("labelIds", labelId);
71
+ }
72
+ }
73
+ const qs = params.toString();
74
+ const response = await request(`/me/threads${qs ? `?${qs}` : ""}`);
75
+ if (!response.ok) {
76
+ const body = await response.text();
77
+ throw new Error(
78
+ `gmail: listThreads failed (${response.status}): ${body}`
79
+ );
80
+ }
81
+ return await response.json();
82
+ }
83
+ async function getThread(threadId, format) {
84
+ const params = new URLSearchParams();
85
+ if (format) params.set("format", format);
86
+ const qs = params.toString();
87
+ const response = await request(
88
+ `/me/threads/${encodeURIComponent(threadId)}${qs ? `?${qs}` : ""}`
89
+ );
90
+ if (!response.ok) {
91
+ const body = await response.text();
92
+ throw new Error(
93
+ `gmail: getThread failed (${response.status}): ${body}`
94
+ );
95
+ }
96
+ return await response.json();
97
+ }
98
+ return {
99
+ request,
100
+ getProfile,
101
+ listLabels,
102
+ listMessages,
103
+ getMessage,
104
+ listThreads,
105
+ getThread
106
+ };
107
+ }
108
+
109
+ // ../connectors/src/connector-onboarding.ts
110
+ var ConnectorOnboarding = class {
111
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
112
+ connectionSetupInstructions;
113
+ /** Phase 2: Data overview instructions */
114
+ dataOverviewInstructions;
115
+ constructor(config) {
116
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
117
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
118
+ }
119
+ getConnectionSetupPrompt(language) {
120
+ return this.connectionSetupInstructions?.[language] ?? null;
121
+ }
122
+ getDataOverviewInstructions(language) {
123
+ return this.dataOverviewInstructions[language];
124
+ }
125
+ };
126
+
127
+ // ../connectors/src/connector-tool.ts
128
+ var ConnectorTool = class {
129
+ name;
130
+ description;
131
+ inputSchema;
132
+ outputSchema;
133
+ _execute;
134
+ constructor(config) {
135
+ this.name = config.name;
136
+ this.description = config.description;
137
+ this.inputSchema = config.inputSchema;
138
+ this.outputSchema = config.outputSchema;
139
+ this._execute = config.execute;
140
+ }
141
+ createTool(connections, config) {
142
+ return {
143
+ description: this.description,
144
+ inputSchema: this.inputSchema,
145
+ outputSchema: this.outputSchema,
146
+ execute: (input) => this._execute(input, connections, config)
147
+ };
148
+ }
149
+ };
150
+
151
+ // ../connectors/src/connector-plugin.ts
152
+ var ConnectorPlugin = class _ConnectorPlugin {
153
+ slug;
154
+ authType;
155
+ name;
156
+ description;
157
+ iconUrl;
158
+ parameters;
159
+ releaseFlag;
160
+ proxyPolicy;
161
+ experimentalAttributes;
162
+ onboarding;
163
+ systemPrompt;
164
+ tools;
165
+ query;
166
+ checkConnection;
167
+ constructor(config) {
168
+ this.slug = config.slug;
169
+ this.authType = config.authType;
170
+ this.name = config.name;
171
+ this.description = config.description;
172
+ this.iconUrl = config.iconUrl;
173
+ this.parameters = config.parameters;
174
+ this.releaseFlag = config.releaseFlag;
175
+ this.proxyPolicy = config.proxyPolicy;
176
+ this.experimentalAttributes = config.experimentalAttributes;
177
+ this.onboarding = config.onboarding;
178
+ this.systemPrompt = config.systemPrompt;
179
+ this.tools = config.tools;
180
+ this.query = config.query;
181
+ this.checkConnection = config.checkConnection;
182
+ }
183
+ get connectorKey() {
184
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
185
+ }
186
+ /**
187
+ * Create tools for connections that belong to this connector.
188
+ * Filters connections by connectorKey internally.
189
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
190
+ */
191
+ createTools(connections, config) {
192
+ const myConnections = connections.filter(
193
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
194
+ );
195
+ const result = {};
196
+ for (const t of Object.values(this.tools)) {
197
+ result[`${this.connectorKey}_${t.name}`] = t.createTool(
198
+ myConnections,
199
+ config
200
+ );
201
+ }
202
+ return result;
203
+ }
204
+ static deriveKey(slug, authType) {
205
+ return authType ? `${slug}-${authType}` : slug;
206
+ }
207
+ };
208
+
209
+ // ../connectors/src/auth-types.ts
210
+ var AUTH_TYPES = {
211
+ OAUTH: "oauth",
212
+ API_KEY: "api-key",
213
+ JWT: "jwt",
214
+ SERVICE_ACCOUNT: "service-account",
215
+ PAT: "pat"
216
+ };
217
+
218
+ // ../connectors/src/connectors/gmail-oauth/tools/request.ts
219
+ import { z } from "zod";
220
+ var BASE_URL2 = "https://gmail.googleapis.com/gmail/v1/users";
221
+ var REQUEST_TIMEOUT_MS = 6e4;
222
+ var cachedToken = null;
223
+ async function getProxyToken(config) {
224
+ if (cachedToken && cachedToken.expiresAt > Date.now() + 6e4) {
225
+ return cachedToken.token;
226
+ }
227
+ const url = `${config.appApiBaseUrl}/v0/database/${config.projectId}/environment/${config.environmentId}/oauth-request-proxy-token`;
228
+ const res = await fetch(url, {
229
+ method: "POST",
230
+ headers: {
231
+ "Content-Type": "application/json",
232
+ "x-api-key": config.appApiKey,
233
+ "project-id": config.projectId
234
+ },
235
+ body: JSON.stringify({
236
+ sandboxId: config.sandboxId,
237
+ issuedBy: "coding-agent"
238
+ })
239
+ });
240
+ if (!res.ok) {
241
+ const errorText = await res.text().catch(() => res.statusText);
242
+ throw new Error(
243
+ `Failed to get proxy token: HTTP ${res.status} ${errorText}`
244
+ );
245
+ }
246
+ const data = await res.json();
247
+ cachedToken = {
248
+ token: data.token,
249
+ expiresAt: new Date(data.expiresAt).getTime()
250
+ };
251
+ return data.token;
252
+ }
253
+ var inputSchema = z.object({
254
+ toolUseIntent: z.string().optional().describe(
255
+ "Brief description of what you intend to accomplish with this tool call"
256
+ ),
257
+ connectionId: z.string().describe("ID of the Gmail OAuth connection to use"),
258
+ method: z.enum(["GET"]).describe("HTTP method (read-only, GET only)"),
259
+ path: z.string().describe(
260
+ "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."
261
+ ),
262
+ queryParams: z.record(z.string(), z.string()).optional().describe(
263
+ "Query parameters to append to the URL (e.g., { q: 'from:example@gmail.com', maxResults: '10' })"
264
+ )
265
+ });
266
+ var outputSchema = z.discriminatedUnion("success", [
267
+ z.object({
268
+ success: z.literal(true),
269
+ status: z.number(),
270
+ data: z.record(z.string(), z.unknown())
271
+ }),
272
+ z.object({
273
+ success: z.literal(false),
274
+ error: z.string()
275
+ })
276
+ ]);
277
+ var requestTool = new ConnectorTool({
278
+ name: "request",
279
+ description: `Send authenticated GET requests to the Gmail API v1.
280
+ Authentication is handled automatically via OAuth proxy.
281
+ All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me' as the userId prefix (e.g., '/me/messages').`,
282
+ inputSchema,
283
+ outputSchema,
284
+ async execute({ connectionId, method, path: path2, queryParams }, connections, config) {
285
+ const connection2 = connections.find((c) => c.id === connectionId);
286
+ if (!connection2) {
287
+ return {
288
+ success: false,
289
+ error: `Connection ${connectionId} not found`
290
+ };
291
+ }
292
+ console.log(
293
+ `[connector-request] gmail-oauth/${connection2.name}: ${method} ${path2}`
294
+ );
295
+ try {
296
+ let url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
297
+ if (queryParams) {
298
+ const searchParams = new URLSearchParams(queryParams);
299
+ url += `?${searchParams.toString()}`;
300
+ }
301
+ const token = await getProxyToken(config.oauthProxy);
302
+ const proxyUrl = `https://${config.oauthProxy.sandboxId}.${config.oauthProxy.previewBaseDomain}/_sqcore/connections/${connectionId}/request`;
303
+ const controller = new AbortController();
304
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
305
+ try {
306
+ const response = await fetch(proxyUrl, {
307
+ method: "POST",
308
+ headers: {
309
+ "Content-Type": "application/json",
310
+ Authorization: `Bearer ${token}`
311
+ },
312
+ body: JSON.stringify({
313
+ url,
314
+ method
315
+ }),
316
+ signal: controller.signal
317
+ });
318
+ const data = await response.json();
319
+ if (!response.ok) {
320
+ const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
321
+ return { success: false, error: errorMessage };
322
+ }
323
+ return { success: true, status: response.status, data };
324
+ } finally {
325
+ clearTimeout(timeout);
326
+ }
327
+ } catch (err) {
328
+ const msg = err instanceof Error ? err.message : String(err);
329
+ return { success: false, error: msg };
330
+ }
331
+ }
332
+ });
333
+
334
+ // ../connectors/src/connectors/gmail-oauth/setup.ts
335
+ var requestToolName = `gmail-oauth_${requestTool.name}`;
336
+ var gmailOnboarding = new ConnectorOnboarding({
337
+ connectionSetupInstructions: {
338
+ ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Gmail\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
339
+
340
+ 1. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u53D6\u5F97\u3059\u308B:
341
+ - \`method\`: \`"GET"\`
342
+ - \`path\`: \`"/me/profile"\`
343
+ 2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001OAuth\u306E\u8A8D\u8A3C\u304C\u6B63\u3057\u304F\u5B8C\u4E86\u3057\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3059\u308B\u3088\u3046\u30E6\u30FC\u30B6\u30FC\u306B\u4F1D\u3048\u308B
344
+ 3. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B:
345
+ - \`method\`: \`"GET"\`
346
+ - \`path\`: \`"/me/labels"\`
347
+ 4. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3059:
348
+ - \`email\`: \u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9
349
+ - \`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
350
+ - \`note\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5185\u5BB9\u306E\u7C21\u5358\u306A\u8AAC\u660E
351
+
352
+ #### \u5236\u7D04
353
+ - **\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
354
+ - \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`,
355
+ en: `Follow these steps to set up the Gmail connection.
356
+
357
+ 1. Call \`${requestToolName}\` to get the user's profile:
358
+ - \`method\`: \`"GET"\`
359
+ - \`path\`: \`"/me/profile"\`
360
+ 2. If an error is returned, ask the user to verify that OAuth authentication completed correctly
361
+ 3. Call \`${requestToolName}\` to get the label list:
362
+ - \`method\`: \`"GET"\`
363
+ - \`path\`: \`"/me/labels"\`
364
+ 4. Call \`updateConnectionContext\`:
365
+ - \`email\`: The user's email address
366
+ - \`labels\`: Key label names (comma-separated, including system labels like INBOX, SENT, DRAFT, SPAM, TRASH)
367
+ - \`note\`: Brief description of the setup
368
+
369
+ #### Constraints
370
+ - **Do NOT read message bodies during setup**. Only the profile and label list requests specified above are allowed
371
+ - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
372
+ },
373
+ dataOverviewInstructions: {
374
+ en: `1. Call gmail-oauth_request with GET /me/labels to list all labels
375
+ 2. Call gmail-oauth_request with GET /me/messages?maxResults=5 to get recent message IDs
376
+ 3. Call gmail-oauth_request with GET /me/messages/{id}?format=metadata for each message to see subjects and senders`,
377
+ ja: `1. gmail-oauth_request \u3067 GET /me/labels \u3092\u547C\u3073\u51FA\u3057\u3001\u5168\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97
378
+ 2. gmail-oauth_request \u3067 GET /me/messages?maxResults=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u65B0\u30E1\u30C3\u30BB\u30FC\u30B8ID\u3092\u53D6\u5F97
379
+ 3. \u5404\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3064\u3044\u3066 gmail-oauth_request \u3067 GET /me/messages/{id}?format=metadata \u3092\u547C\u3073\u51FA\u3057\u3001\u4EF6\u540D\u3068\u9001\u4FE1\u8005\u3092\u78BA\u8A8D`
380
+ }
381
+ });
382
+
383
+ // ../connectors/src/connectors/gmail-oauth/parameters.ts
384
+ var parameters = {};
385
+
386
+ // ../connectors/src/connectors/gmail-oauth/index.ts
387
+ var tools = { request: requestTool };
388
+ var gmailOauthConnector = new ConnectorPlugin({
389
+ slug: "gmail",
390
+ authType: AUTH_TYPES.OAUTH,
391
+ name: "Gmail (OAuth)",
392
+ description: "Connect to Gmail for email data access using OAuth. Read-only access to messages, threads, and labels.",
393
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5rPCSZnB5SHqb4fTXnLXHH/7ba8ca52a3c36c6a18ac7a2f92ac4c5b/gmail.svg",
394
+ parameters,
395
+ releaseFlag: { dev1: true, dev2: false, prod: false },
396
+ onboarding: gmailOnboarding,
397
+ proxyPolicy: {
398
+ allowlist: [
399
+ {
400
+ host: "gmail.googleapis.com",
401
+ methods: ["GET"]
402
+ }
403
+ ]
404
+ },
405
+ systemPrompt: {
406
+ en: `### Tools
407
+
408
+ - \`gmail-oauth_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 configured automatically via OAuth.
409
+
410
+ ### Gmail API Reference
411
+
412
+ #### Available Endpoints
413
+ - GET \`/me/profile\` \u2014 Get the authenticated user's profile (email address, total messages/threads)
414
+ - GET \`/me/labels\` \u2014 List all labels in the mailbox
415
+ - GET \`/me/labels/{id}\` \u2014 Get details for a specific label
416
+ - GET \`/me/messages\` \u2014 List messages (returns IDs only; use format param on individual messages)
417
+ - GET \`/me/messages/{id}\` \u2014 Get a specific message
418
+ - GET \`/me/threads\` \u2014 List threads
419
+ - GET \`/me/threads/{id}\` \u2014 Get a specific thread with all its messages
420
+
421
+ #### Key Query Parameters
422
+ - \`q\` \u2014 Gmail search query (same syntax as Gmail search box). Examples:
423
+ - \`from:user@example.com\` \u2014 Messages from a specific sender
424
+ - \`subject:meeting\` \u2014 Messages with "meeting" in the subject
425
+ - \`after:2025/01/01 before:2025/02/01\` \u2014 Messages within a date range
426
+ - \`label:INBOX is:unread\` \u2014 Unread messages in inbox
427
+ - \`has:attachment\` \u2014 Messages with attachments
428
+ - \`maxResults\` \u2014 Maximum number of results (default 100, max 500)
429
+ - \`pageToken\` \u2014 Token for pagination (from nextPageToken in response)
430
+ - \`labelIds\` \u2014 Filter by label IDs (e.g., \`INBOX\`, \`SENT\`, \`DRAFT\`)
431
+ - \`format\` \u2014 Message format for /messages/{id} and /threads/{id}:
432
+ - \`full\` \u2014 Complete message with parsed payload (default)
433
+ - \`metadata\` \u2014 Only headers (Subject, From, To, Date) without body
434
+ - \`minimal\` \u2014 Only IDs, labels, and snippet
435
+ - \`raw\` \u2014 Full RFC 2822 formatted message in base64url
436
+
437
+ #### Tips
438
+ - Always use \`/me\` as the userId \u2014 it refers to the authenticated user
439
+ - List endpoints return only IDs; fetch individual resources for details
440
+ - Use \`format=metadata\` to efficiently get subject/sender without full body
441
+ - Message body content is base64url encoded in \`payload.body.data\` or nested \`payload.parts[].body.data\`
442
+ - Use \`q\` parameter for powerful search filtering (same as Gmail search syntax)
443
+ - System labels include: INBOX, SENT, DRAFT, SPAM, TRASH, UNREAD, STARRED, IMPORTANT, CATEGORY_PERSONAL, CATEGORY_SOCIAL, CATEGORY_PROMOTIONS, CATEGORY_UPDATES, CATEGORY_FORUMS
444
+
445
+ ### Business Logic
446
+
447
+ 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.
448
+
449
+ #### Example
450
+
451
+ \`\`\`ts
452
+ import { connection } from "@squadbase/vite-server/connectors/gmail-oauth";
453
+
454
+ const gmail = connection("<connectionId>");
455
+
456
+ // Get user profile
457
+ const profile = await gmail.getProfile();
458
+ console.log(profile.emailAddress, profile.messagesTotal);
459
+
460
+ // List recent messages
461
+ const messages = await gmail.listMessages({ maxResults: 10 });
462
+ for (const msg of messages.messages) {
463
+ const detail = await gmail.getMessage(msg.id, "metadata");
464
+ const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
465
+ console.log(subject, detail.snippet);
466
+ }
467
+
468
+ // Search messages
469
+ const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
470
+
471
+ // List labels
472
+ const labels = await gmail.listLabels();
473
+ labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
474
+
475
+ // Get a thread
476
+ const thread = await gmail.getThread("<threadId>");
477
+ thread.messages.forEach(m => console.log(m.snippet));
478
+ \`\`\``,
479
+ ja: `### \u30C4\u30FC\u30EB
480
+
481
+ - \`gmail-oauth_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\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
482
+
483
+ ### Gmail API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
484
+
485
+ #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
486
+ - GET \`/me/profile\` \u2014 \u8A8D\u8A3C\u6E08\u307F\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
487
+ - GET \`/me/labels\` \u2014 \u30E1\u30FC\u30EB\u30DC\u30C3\u30AF\u30B9\u306E\u5168\u30E9\u30D9\u30EB\u3092\u4E00\u89A7
488
+ - GET \`/me/labels/{id}\` \u2014 \u7279\u5B9A\u30E9\u30D9\u30EB\u306E\u8A73\u7D30\u3092\u53D6\u5F97
489
+ - 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
490
+ - GET \`/me/messages/{id}\` \u2014 \u7279\u5B9A\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
491
+ - GET \`/me/threads\` \u2014 \u30B9\u30EC\u30C3\u30C9\u4E00\u89A7
492
+ - GET \`/me/threads/{id}\` \u2014 \u7279\u5B9A\u30B9\u30EC\u30C3\u30C9\u306E\u5168\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
493
+
494
+ #### \u4E3B\u8981\u306A\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF
495
+ - \`q\` \u2014 Gmail\u691C\u7D22\u30AF\u30A8\u30EA\uFF08Gmail\u691C\u7D22\u30DC\u30C3\u30AF\u30B9\u3068\u540C\u3058\u69CB\u6587\uFF09\u3002\u4F8B\uFF1A
496
+ - \`from:user@example.com\` \u2014 \u7279\u5B9A\u306E\u9001\u4FE1\u8005\u304B\u3089\u306E\u30E1\u30C3\u30BB\u30FC\u30B8
497
+ - \`subject:meeting\` \u2014 \u4EF6\u540D\u306B\u300Cmeeting\u300D\u3092\u542B\u3080\u30E1\u30C3\u30BB\u30FC\u30B8
498
+ - \`after:2025/01/01 before:2025/02/01\` \u2014 \u65E5\u4ED8\u7BC4\u56F2\u5185\u306E\u30E1\u30C3\u30BB\u30FC\u30B8
499
+ - \`label:INBOX is:unread\` \u2014 \u53D7\u4FE1\u30C8\u30EC\u30A4\u306E\u672A\u8AAD\u30E1\u30C3\u30BB\u30FC\u30B8
500
+ - \`has:attachment\` \u2014 \u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u4ED8\u304D\u30E1\u30C3\u30BB\u30FC\u30B8
501
+ - \`maxResults\` \u2014 \u6700\u5927\u7D50\u679C\u6570\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8100\u3001\u6700\u5927500\uFF09
502
+ - \`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
503
+ - \`labelIds\` \u2014 \u30E9\u30D9\u30EBID\u3067\u30D5\u30A3\u30EB\u30BF\uFF08\u4F8B\uFF1A\`INBOX\`, \`SENT\`, \`DRAFT\`\uFF09
504
+ - \`format\` \u2014 /messages/{id} \u3068 /threads/{id} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\uFF1A
505
+ - \`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
506
+ - \`metadata\` \u2014 \u30D8\u30C3\u30C0\u30FC\u306E\u307F\uFF08Subject, From, To, Date\uFF09\u3001\u672C\u6587\u306A\u3057
507
+ - \`minimal\` \u2014 ID\u3001\u30E9\u30D9\u30EB\u3001\u30B9\u30CB\u30DA\u30C3\u30C8\u306E\u307F
508
+ - \`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
509
+
510
+ #### \u30D2\u30F3\u30C8
511
+ - userId\u306B\u306F\u5E38\u306B \`/me\` \u3092\u4F7F\u7528 \u2014 \u8A8D\u8A3C\u6E08\u307F\u30E6\u30FC\u30B6\u30FC\u3092\u6307\u3057\u307E\u3059
512
+ - \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
513
+ - \u4EF6\u540D/\u9001\u4FE1\u8005\u3092\u52B9\u7387\u7684\u306B\u53D6\u5F97\u3059\u308B\u306B\u306F \`format=metadata\` \u3092\u4F7F\u7528\u3057\u307E\u3059
514
+ - \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
515
+ - \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
516
+ - \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
517
+
518
+ ### Business Logic
519
+
520
+ \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
521
+
522
+ #### Example
523
+
524
+ \`\`\`ts
525
+ import { connection } from "@squadbase/vite-server/connectors/gmail-oauth";
526
+
527
+ const gmail = connection("<connectionId>");
528
+
529
+ // Get user profile
530
+ const profile = await gmail.getProfile();
531
+ console.log(profile.emailAddress, profile.messagesTotal);
532
+
533
+ // List recent messages
534
+ const messages = await gmail.listMessages({ maxResults: 10 });
535
+ for (const msg of messages.messages) {
536
+ const detail = await gmail.getMessage(msg.id, "metadata");
537
+ const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
538
+ console.log(subject, detail.snippet);
539
+ }
540
+
541
+ // Search messages
542
+ const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
543
+
544
+ // List labels
545
+ const labels = await gmail.listLabels();
546
+ labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
547
+
548
+ // Get a thread
549
+ const thread = await gmail.getThread("<threadId>");
550
+ thread.messages.forEach(m => console.log(m.snippet));
551
+ \`\`\``
552
+ },
553
+ tools,
554
+ async checkConnection(_params, config) {
555
+ const { proxyFetch } = config;
556
+ const url = "https://gmail.googleapis.com/gmail/v1/users/me/profile";
557
+ try {
558
+ const res = await proxyFetch(url, { method: "GET" });
559
+ if (!res.ok) {
560
+ const errorText = await res.text().catch(() => res.statusText);
561
+ return {
562
+ success: false,
563
+ error: `Gmail API failed: HTTP ${res.status} ${errorText}`
564
+ };
565
+ }
566
+ return { success: true };
567
+ } catch (error) {
568
+ return {
569
+ success: false,
570
+ error: error instanceof Error ? error.message : String(error)
571
+ };
572
+ }
573
+ }
574
+ });
575
+
576
+ // src/connectors/create-connector-sdk.ts
577
+ import { readFileSync } from "fs";
578
+ import path from "path";
579
+
580
+ // src/connector-client/env.ts
581
+ function resolveEnvVar(entry, key, connectionId) {
582
+ const envVarName = entry.envVars[key];
583
+ if (!envVarName) {
584
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
585
+ }
586
+ const value = process.env[envVarName];
587
+ if (!value) {
588
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
589
+ }
590
+ return value;
591
+ }
592
+ function resolveEnvVarOptional(entry, key) {
593
+ const envVarName = entry.envVars[key];
594
+ if (!envVarName) return void 0;
595
+ return process.env[envVarName] || void 0;
596
+ }
597
+
598
+ // src/connectors/create-connector-sdk.ts
599
+ function loadConnectionsSync() {
600
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
601
+ try {
602
+ const raw = readFileSync(filePath, "utf-8");
603
+ return JSON.parse(raw);
604
+ } catch {
605
+ return {};
606
+ }
607
+ }
608
+ function createConnectorSdk(plugin, createClient2) {
609
+ return (connectionId) => {
610
+ const connections = loadConnectionsSync();
611
+ const entry = connections[connectionId];
612
+ if (!entry) {
613
+ throw new Error(
614
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
615
+ );
616
+ }
617
+ if (entry.connector.slug !== plugin.slug) {
618
+ throw new Error(
619
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
620
+ );
621
+ }
622
+ const params = {};
623
+ for (const param of Object.values(plugin.parameters)) {
624
+ if (param.required) {
625
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
626
+ } else {
627
+ const val = resolveEnvVarOptional(entry, param.slug);
628
+ if (val !== void 0) params[param.slug] = val;
629
+ }
630
+ }
631
+ return createClient2(params);
632
+ };
633
+ }
634
+
635
+ // src/connectors/entries/gmail-oauth.ts
636
+ var connection = createConnectorSdk(gmailOauthConnector, createClient);
637
+ export {
638
+ connection
639
+ };
@@ -0,0 +1,5 @@
1
+ import * as _squadbase_connectors_sdk from '@squadbase/connectors/sdk';
2
+
3
+ declare const connection: (connectionId: string) => _squadbase_connectors_sdk.GoogleAdsServiceAccountConnectorSdk;
4
+
5
+ export { connection };