@squadbase/vite-server 0.1.3-dev.4 → 0.1.3-dev.6

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 (52) hide show
  1. package/dist/cli/index.js +3104 -2679
  2. package/dist/connectors/airtable-oauth.js +3 -2
  3. package/dist/connectors/airtable.js +11 -1
  4. package/dist/connectors/amplitude.js +11 -1
  5. package/dist/connectors/anthropic.js +11 -1
  6. package/dist/connectors/asana.js +11 -1
  7. package/dist/connectors/attio.js +11 -1
  8. package/dist/connectors/customerio.js +11 -1
  9. package/dist/connectors/dbt.js +11 -1
  10. package/dist/connectors/gemini.js +11 -1
  11. package/dist/connectors/gmail-oauth.js +3 -2
  12. package/dist/connectors/{microsoft-teams-oauth.d.ts → gmail.d.ts} +1 -1
  13. package/dist/connectors/gmail.js +802 -0
  14. package/dist/connectors/google-ads-oauth.js +4 -3
  15. package/dist/connectors/google-ads.js +11 -1
  16. package/dist/connectors/google-analytics-oauth.js +3 -2
  17. package/dist/connectors/google-analytics.js +267 -27
  18. package/dist/connectors/{slack.d.ts → google-calendar-oauth.d.ts} +1 -1
  19. package/dist/connectors/google-calendar-oauth.js +744 -0
  20. package/dist/connectors/google-calendar.d.ts +12 -0
  21. package/dist/connectors/google-calendar.js +688 -0
  22. package/dist/connectors/google-sheets-oauth.js +3 -2
  23. package/dist/connectors/google-sheets.js +11 -1
  24. package/dist/connectors/hubspot-oauth.js +2 -1
  25. package/dist/connectors/hubspot.js +11 -1
  26. package/dist/connectors/intercom-oauth.js +3 -2
  27. package/dist/connectors/intercom.js +11 -1
  28. package/dist/connectors/jira-api-key.js +3 -2
  29. package/dist/connectors/kintone-api-token.js +3 -2
  30. package/dist/connectors/kintone.js +12 -2
  31. package/dist/connectors/linkedin-ads-oauth.js +3 -2
  32. package/dist/connectors/linkedin-ads.js +11 -1
  33. package/dist/connectors/mailchimp-oauth.js +2 -1
  34. package/dist/connectors/mailchimp.js +11 -1
  35. package/dist/connectors/notion-oauth.js +3 -2
  36. package/dist/connectors/notion.js +11 -1
  37. package/dist/connectors/openai.js +11 -1
  38. package/dist/connectors/shopify-oauth.js +3 -2
  39. package/dist/connectors/shopify.js +11 -1
  40. package/dist/connectors/stripe-api-key.js +3 -2
  41. package/dist/connectors/stripe-oauth.js +3 -2
  42. package/dist/connectors/wix-store.js +11 -1
  43. package/dist/connectors/zendesk-oauth.js +3 -2
  44. package/dist/connectors/zendesk.js +11 -1
  45. package/dist/index.js +3099 -2674
  46. package/dist/main.js +3099 -2674
  47. package/dist/vite-plugin.js +3099 -2674
  48. package/package.json +13 -1
  49. package/dist/connectors/microsoft-teams-oauth.js +0 -479
  50. package/dist/connectors/microsoft-teams.d.ts +0 -5
  51. package/dist/connectors/microsoft-teams.js +0 -381
  52. package/dist/connectors/slack.js +0 -362
@@ -0,0 +1,688 @@
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/google-calendar/sdk/index.ts
46
+ import * as crypto from "crypto";
47
+
48
+ // ../connectors/src/connectors/google-calendar/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. Ensure that the service account has the necessary permissions to access Google Calendar, and that calendars are shared with the service account email.",
54
+ envVarBaseKey: "GOOGLE_CALENDAR_SERVICE_ACCOUNT_JSON_BASE64",
55
+ type: "base64EncodedJson",
56
+ secret: true,
57
+ required: true
58
+ }),
59
+ calendarId: new ParameterDefinition({
60
+ slug: "calendar-id",
61
+ name: "Default Calendar ID",
62
+ description: "The default Google Calendar ID to use (e.g., 'primary' or an email address like 'user@example.com'). If not set, 'primary' is used.",
63
+ envVarBaseKey: "GOOGLE_CALENDAR_CALENDAR_ID",
64
+ type: "text",
65
+ secret: false,
66
+ required: false
67
+ })
68
+ };
69
+
70
+ // ../connectors/src/connectors/google-calendar/sdk/index.ts
71
+ var TOKEN_URL = "https://oauth2.googleapis.com/token";
72
+ var BASE_URL = "https://www.googleapis.com/calendar/v3";
73
+ var SCOPE = "https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/calendar.events.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, nowSec, subject) {
79
+ const header = base64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
80
+ const claims = {
81
+ iss: clientEmail,
82
+ scope: SCOPE,
83
+ aud: TOKEN_URL,
84
+ iat: nowSec,
85
+ exp: nowSec + 3600
86
+ };
87
+ if (subject) {
88
+ claims.sub = subject;
89
+ }
90
+ const payload = base64url(JSON.stringify(claims));
91
+ const signingInput = `${header}.${payload}`;
92
+ const sign = crypto.createSign("RSA-SHA256");
93
+ sign.update(signingInput);
94
+ sign.end();
95
+ const signature = base64url(sign.sign(privateKey));
96
+ return `${signingInput}.${signature}`;
97
+ }
98
+ function createClient(params, options) {
99
+ const serviceAccountKeyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
100
+ const defaultCalendarId = params[parameters.calendarId.slug] ?? "primary";
101
+ if (!serviceAccountKeyJsonBase64) {
102
+ throw new Error(
103
+ `google-calendar: missing required parameter: ${parameters.serviceAccountKeyJsonBase64.slug}`
104
+ );
105
+ }
106
+ let serviceAccountKey;
107
+ try {
108
+ const decoded = Buffer.from(
109
+ serviceAccountKeyJsonBase64,
110
+ "base64"
111
+ ).toString("utf-8");
112
+ serviceAccountKey = JSON.parse(decoded);
113
+ } catch {
114
+ throw new Error(
115
+ "google-calendar: failed to decode service account key JSON from base64"
116
+ );
117
+ }
118
+ if (!serviceAccountKey.client_email || !serviceAccountKey.private_key) {
119
+ throw new Error(
120
+ "google-calendar: service account key JSON must contain client_email and private_key"
121
+ );
122
+ }
123
+ const subject = options?.subject;
124
+ let cachedToken = null;
125
+ let tokenExpiresAt = 0;
126
+ async function getAccessToken() {
127
+ const nowSec = Math.floor(Date.now() / 1e3);
128
+ if (cachedToken && nowSec < tokenExpiresAt - 60) {
129
+ return cachedToken;
130
+ }
131
+ const jwt = buildJwt(
132
+ serviceAccountKey.client_email,
133
+ serviceAccountKey.private_key,
134
+ nowSec,
135
+ subject
136
+ );
137
+ const response = await fetch(TOKEN_URL, {
138
+ method: "POST",
139
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
140
+ body: new URLSearchParams({
141
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
142
+ assertion: jwt
143
+ })
144
+ });
145
+ if (!response.ok) {
146
+ const text = await response.text();
147
+ throw new Error(
148
+ `google-calendar: token exchange failed (${response.status}): ${text}`
149
+ );
150
+ }
151
+ const data = await response.json();
152
+ cachedToken = data.access_token;
153
+ tokenExpiresAt = nowSec + data.expires_in;
154
+ return cachedToken;
155
+ }
156
+ function resolveCalendarId(override) {
157
+ return override ?? defaultCalendarId;
158
+ }
159
+ return {
160
+ async request(path2, init) {
161
+ const accessToken = await getAccessToken();
162
+ const resolvedPath = path2.replace(
163
+ /\{calendarId\}/g,
164
+ defaultCalendarId
165
+ );
166
+ const url = `${BASE_URL}${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
167
+ const headers = new Headers(init?.headers);
168
+ headers.set("Authorization", `Bearer ${accessToken}`);
169
+ return fetch(url, { ...init, headers });
170
+ },
171
+ async listCalendars() {
172
+ const response = await this.request("/users/me/calendarList", {
173
+ method: "GET"
174
+ });
175
+ if (!response.ok) {
176
+ const text = await response.text();
177
+ throw new Error(
178
+ `google-calendar: listCalendars failed (${response.status}): ${text}`
179
+ );
180
+ }
181
+ const data = await response.json();
182
+ return data.items ?? [];
183
+ },
184
+ async listEvents(options2, calendarId) {
185
+ const cid = resolveCalendarId(calendarId);
186
+ const searchParams = new URLSearchParams();
187
+ if (options2?.timeMin) searchParams.set("timeMin", options2.timeMin);
188
+ if (options2?.timeMax) searchParams.set("timeMax", options2.timeMax);
189
+ if (options2?.maxResults)
190
+ searchParams.set("maxResults", String(options2.maxResults));
191
+ if (options2?.q) searchParams.set("q", options2.q);
192
+ if (options2?.singleEvents != null)
193
+ searchParams.set("singleEvents", String(options2.singleEvents));
194
+ if (options2?.orderBy) searchParams.set("orderBy", options2.orderBy);
195
+ if (options2?.pageToken) searchParams.set("pageToken", options2.pageToken);
196
+ const qs = searchParams.toString();
197
+ const path2 = `/calendars/${encodeURIComponent(cid)}/events${qs ? `?${qs}` : ""}`;
198
+ const response = await this.request(path2, { method: "GET" });
199
+ if (!response.ok) {
200
+ const text = await response.text();
201
+ throw new Error(
202
+ `google-calendar: listEvents failed (${response.status}): ${text}`
203
+ );
204
+ }
205
+ return await response.json();
206
+ },
207
+ async getEvent(eventId, calendarId) {
208
+ const cid = resolveCalendarId(calendarId);
209
+ const path2 = `/calendars/${encodeURIComponent(cid)}/events/${encodeURIComponent(eventId)}`;
210
+ const response = await this.request(path2, { method: "GET" });
211
+ if (!response.ok) {
212
+ const text = await response.text();
213
+ throw new Error(
214
+ `google-calendar: getEvent failed (${response.status}): ${text}`
215
+ );
216
+ }
217
+ return await response.json();
218
+ }
219
+ };
220
+ }
221
+
222
+ // ../connectors/src/connector-onboarding.ts
223
+ var ConnectorOnboarding = class {
224
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
225
+ connectionSetupInstructions;
226
+ /** Phase 2: Data overview instructions */
227
+ dataOverviewInstructions;
228
+ constructor(config) {
229
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
230
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
231
+ }
232
+ getConnectionSetupPrompt(language) {
233
+ return this.connectionSetupInstructions?.[language] ?? null;
234
+ }
235
+ getDataOverviewInstructions(language) {
236
+ return this.dataOverviewInstructions[language];
237
+ }
238
+ };
239
+
240
+ // ../connectors/src/connector-tool.ts
241
+ var ConnectorTool = class {
242
+ name;
243
+ description;
244
+ inputSchema;
245
+ outputSchema;
246
+ _execute;
247
+ constructor(config) {
248
+ this.name = config.name;
249
+ this.description = config.description;
250
+ this.inputSchema = config.inputSchema;
251
+ this.outputSchema = config.outputSchema;
252
+ this._execute = config.execute;
253
+ }
254
+ createTool(connections, config) {
255
+ return {
256
+ description: this.description,
257
+ inputSchema: this.inputSchema,
258
+ outputSchema: this.outputSchema,
259
+ execute: (input) => this._execute(input, connections, config)
260
+ };
261
+ }
262
+ };
263
+
264
+ // ../connectors/src/connector-plugin.ts
265
+ var ConnectorPlugin = class _ConnectorPlugin {
266
+ slug;
267
+ authType;
268
+ name;
269
+ description;
270
+ iconUrl;
271
+ parameters;
272
+ releaseFlag;
273
+ proxyPolicy;
274
+ experimentalAttributes;
275
+ onboarding;
276
+ systemPrompt;
277
+ tools;
278
+ query;
279
+ checkConnection;
280
+ constructor(config) {
281
+ this.slug = config.slug;
282
+ this.authType = config.authType;
283
+ this.name = config.name;
284
+ this.description = config.description;
285
+ this.iconUrl = config.iconUrl;
286
+ this.parameters = config.parameters;
287
+ this.releaseFlag = config.releaseFlag;
288
+ this.proxyPolicy = config.proxyPolicy;
289
+ this.experimentalAttributes = config.experimentalAttributes;
290
+ this.onboarding = config.onboarding;
291
+ this.systemPrompt = config.systemPrompt;
292
+ this.tools = config.tools;
293
+ this.query = config.query;
294
+ this.checkConnection = config.checkConnection;
295
+ }
296
+ get connectorKey() {
297
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
298
+ }
299
+ /**
300
+ * Create tools for connections that belong to this connector.
301
+ * Filters connections by connectorKey internally.
302
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
303
+ */
304
+ createTools(connections, config) {
305
+ const myConnections = connections.filter(
306
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
307
+ );
308
+ const result = {};
309
+ for (const t of Object.values(this.tools)) {
310
+ result[`${this.connectorKey}_${t.name}`] = t.createTool(
311
+ myConnections,
312
+ config
313
+ );
314
+ }
315
+ return result;
316
+ }
317
+ static deriveKey(slug, authType) {
318
+ return authType ? `${slug}-${authType}` : slug;
319
+ }
320
+ };
321
+
322
+ // ../connectors/src/auth-types.ts
323
+ var AUTH_TYPES = {
324
+ OAUTH: "oauth",
325
+ API_KEY: "api-key",
326
+ JWT: "jwt",
327
+ SERVICE_ACCOUNT: "service-account",
328
+ PAT: "pat",
329
+ USER_PASSWORD: "user-password"
330
+ };
331
+
332
+ // ../connectors/src/connectors/google-calendar/setup.ts
333
+ var googleCalendarOnboarding = new ConnectorOnboarding({
334
+ dataOverviewInstructions: {
335
+ en: `1. Call google-calendar_request with GET /calendars/{calendarId} to get the default calendar's metadata
336
+ 2. Call google-calendar_request with GET /users/me/calendarList to list all accessible calendars
337
+ 3. Call google-calendar_request with GET /calendars/{calendarId}/events with query params timeMin (RFC3339) and maxResults=10 to sample upcoming events`,
338
+ ja: `1. google-calendar_request \u3067 GET /calendars/{calendarId} \u3092\u547C\u3073\u51FA\u3057\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
339
+ 2. google-calendar_request \u3067 GET /users/me/calendarList \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u5168\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7\u3092\u53D6\u5F97
340
+ 3. google-calendar_request \u3067 GET /calendars/{calendarId}/events \u3092\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF timeMin\uFF08RFC3339\u5F62\u5F0F\uFF09\u3068 maxResults=10 \u3067\u547C\u3073\u51FA\u3057\u3001\u76F4\u8FD1\u306E\u30A4\u30D9\u30F3\u30C8\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
341
+ }
342
+ });
343
+
344
+ // ../connectors/src/connectors/google-calendar/tools/request.ts
345
+ import { z } from "zod";
346
+ var BASE_URL2 = "https://www.googleapis.com/calendar/v3";
347
+ var REQUEST_TIMEOUT_MS = 6e4;
348
+ var inputSchema = z.object({
349
+ toolUseIntent: z.string().optional().describe(
350
+ "Brief description of what you intend to accomplish with this tool call"
351
+ ),
352
+ connectionId: z.string().describe("ID of the Google Calendar connection to use"),
353
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
354
+ path: z.string().describe(
355
+ "API path appended to https://www.googleapis.com/calendar/v3 (e.g., '/calendars/{calendarId}/events'). {calendarId} is automatically replaced."
356
+ ),
357
+ queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters to append to the URL"),
358
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PUT/PATCH methods"),
359
+ subject: z.string().optional().describe(
360
+ "Email address of the user to impersonate via Domain-wide Delegation. When set, the service account acts on behalf of this user."
361
+ )
362
+ });
363
+ var outputSchema = z.discriminatedUnion("success", [
364
+ z.object({
365
+ success: z.literal(true),
366
+ status: z.number(),
367
+ data: z.record(z.string(), z.unknown())
368
+ }),
369
+ z.object({
370
+ success: z.literal(false),
371
+ error: z.string()
372
+ })
373
+ ]);
374
+ var requestTool = new ConnectorTool({
375
+ name: "request",
376
+ description: `Send authenticated requests to the Google Calendar API v3.
377
+ Authentication is handled automatically using a service account.
378
+ {calendarId} in the path is automatically replaced with the connection's default calendar ID.`,
379
+ inputSchema,
380
+ outputSchema,
381
+ async execute({ connectionId, method, path: path2, queryParams, body, subject }, connections) {
382
+ const connection2 = connections.find((c) => c.id === connectionId);
383
+ if (!connection2) {
384
+ return {
385
+ success: false,
386
+ error: `Connection ${connectionId} not found`
387
+ };
388
+ }
389
+ console.log(
390
+ `[connector-request] google-calendar/${connection2.name}: ${method} ${path2}`
391
+ );
392
+ try {
393
+ const { GoogleAuth } = await import("google-auth-library");
394
+ const keyJsonBase64 = parameters.serviceAccountKeyJsonBase64.getValue(connection2);
395
+ const calendarId = parameters.calendarId.tryGetValue(connection2) ?? "primary";
396
+ const credentials = JSON.parse(
397
+ Buffer.from(keyJsonBase64, "base64").toString("utf-8")
398
+ );
399
+ const auth = new GoogleAuth({
400
+ credentials,
401
+ scopes: [
402
+ "https://www.googleapis.com/auth/calendar.readonly",
403
+ "https://www.googleapis.com/auth/calendar.events.readonly"
404
+ ],
405
+ ...subject ? { clientOptions: { subject } } : {}
406
+ });
407
+ const token = await auth.getAccessToken();
408
+ if (!token) {
409
+ return {
410
+ success: false,
411
+ error: "Failed to obtain access token"
412
+ };
413
+ }
414
+ const resolvedPath = path2.replace(/\{calendarId\}/g, calendarId);
415
+ let url = `${BASE_URL2}${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
416
+ if (queryParams) {
417
+ const searchParams = new URLSearchParams(queryParams);
418
+ url += `?${searchParams.toString()}`;
419
+ }
420
+ const controller = new AbortController();
421
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
422
+ try {
423
+ const response = await fetch(url, {
424
+ method,
425
+ headers: {
426
+ Authorization: `Bearer ${token}`,
427
+ "Content-Type": "application/json"
428
+ },
429
+ body: body && ["POST", "PUT", "PATCH"].includes(method) ? JSON.stringify(body) : void 0,
430
+ signal: controller.signal
431
+ });
432
+ if (method === "DELETE" && response.status === 204) {
433
+ return {
434
+ success: true,
435
+ status: 204,
436
+ data: { message: "Deleted successfully" }
437
+ };
438
+ }
439
+ const data = await response.json();
440
+ if (!response.ok) {
441
+ const errorObj = data?.error;
442
+ return {
443
+ success: false,
444
+ error: errorObj?.message ?? `HTTP ${response.status} ${response.statusText}`
445
+ };
446
+ }
447
+ return { success: true, status: response.status, data };
448
+ } finally {
449
+ clearTimeout(timeout);
450
+ }
451
+ } catch (err) {
452
+ const msg = err instanceof Error ? err.message : String(err);
453
+ return { success: false, error: msg };
454
+ }
455
+ }
456
+ });
457
+
458
+ // ../connectors/src/connectors/google-calendar/index.ts
459
+ var tools = { request: requestTool };
460
+ var googleCalendarConnector = new ConnectorPlugin({
461
+ slug: "google-calendar",
462
+ authType: AUTH_TYPES.SERVICE_ACCOUNT,
463
+ name: "Google Calendar",
464
+ description: "Connect to Google Calendar for calendar and event data access using a service account.",
465
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5D9eTiMxiL7MaezWXyAaLG/dbcf25e1d51ab877548b3d77e4b02c6d/google-calendar.svg",
466
+ parameters,
467
+ releaseFlag: { dev1: true, dev2: true, prod: true },
468
+ onboarding: googleCalendarOnboarding,
469
+ systemPrompt: {
470
+ en: `### Tools
471
+
472
+ - \`google-calendar_request\`: The only way to call the Google Calendar API. Use it to list calendars, get events, and manage calendar data. Authentication is handled automatically using a service account. The {calendarId} placeholder in paths is automatically replaced with the configured default calendar ID. Supports Domain-wide Delegation via the optional \`subject\` parameter to impersonate a user.
473
+
474
+ ### Business Logic
475
+
476
+ The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
477
+
478
+ SDK methods (client created via \`connection(connectionId)\` or \`connection(connectionId, { subject })\`):
479
+ - \`client.listCalendars()\` \u2014 list all accessible calendars
480
+ - \`client.listEvents(options?, calendarId?)\` \u2014 list events with optional filters
481
+ - \`client.getEvent(eventId, calendarId?)\` \u2014 get a single event by ID
482
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
483
+
484
+ #### Domain-wide Delegation
485
+
486
+ To access a user's calendar via Domain-wide Delegation, pass \`subject\` (the user's email) as the second argument to \`connection()\`:
487
+
488
+ \`\`\`ts
489
+ const calendar = connection("<connectionId>", { subject: "user@example.com" });
490
+ \`\`\`
491
+
492
+ \`\`\`ts
493
+ import type { Context } from "hono";
494
+ import { connection } from "@squadbase/vite-server/connectors/google-calendar";
495
+
496
+ const calendar = connection("<connectionId>");
497
+
498
+ export default async function handler(c: Context) {
499
+ const now = new Date().toISOString();
500
+ const { items } = await calendar.listEvents({
501
+ timeMin: now,
502
+ maxResults: 10,
503
+ singleEvents: true,
504
+ orderBy: "startTime",
505
+ });
506
+
507
+ return c.json(
508
+ items.map((event) => ({
509
+ id: event.id,
510
+ summary: event.summary,
511
+ start: event.start.dateTime ?? event.start.date,
512
+ end: event.end.dateTime ?? event.end.date,
513
+ location: event.location,
514
+ })),
515
+ );
516
+ }
517
+ \`\`\`
518
+
519
+ ### Google Calendar API v3 Reference
520
+
521
+ #### Available Endpoints
522
+ - GET \`/calendars/{calendarId}\` \u2014 Get calendar metadata
523
+ - GET \`/users/me/calendarList\` \u2014 List all calendars accessible by the authenticated user
524
+ - GET \`/calendars/{calendarId}/events\` \u2014 List events on a calendar
525
+ - GET \`/calendars/{calendarId}/events/{eventId}\` \u2014 Get a single event
526
+
527
+ #### Common Query Parameters for Event Listing
528
+ - \`timeMin\` \u2014 Lower bound (RFC3339 timestamp, e.g., "2024-01-01T00:00:00Z")
529
+ - \`timeMax\` \u2014 Upper bound (RFC3339 timestamp)
530
+ - \`maxResults\` \u2014 Maximum number of events (default 250, max 2500)
531
+ - \`singleEvents=true\` \u2014 Expand recurring events into individual instances
532
+ - \`orderBy=startTime\` \u2014 Order by start time (requires singleEvents=true)
533
+ - \`q\` \u2014 Free text search terms
534
+
535
+ #### Tips
536
+ - Use \`{calendarId}\` placeholder in paths \u2014 it is automatically replaced with the configured default calendar ID
537
+ - Set \`singleEvents=true\` to expand recurring events into individual instances
538
+ - When using \`orderBy=startTime\`, you must also set \`singleEvents=true\`
539
+ - Use RFC3339 format for time parameters (e.g., "2024-01-15T09:00:00Z" or "2024-01-15T09:00:00+09:00")
540
+ - The default calendar ID is "primary" if not configured`,
541
+ ja: `### \u30C4\u30FC\u30EB
542
+
543
+ - \`google-calendar_request\`: Google Calendar API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7\u53D6\u5F97\u3001\u30A4\u30D9\u30F3\u30C8\u306E\u53D6\u5F97\u3001\u30AB\u30EC\u30F3\u30C0\u30FC\u30C7\u30FC\u30BF\u306E\u7BA1\u7406\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u3066\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u51E6\u7406\u3055\u308C\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{calendarId}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FCID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002Domain-wide Delegation\u3092\u4F7F\u7528\u3059\u308B\u5834\u5408\u3001\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\`subject\`\u30D1\u30E9\u30E1\u30FC\u30BF\u3067\u30E6\u30FC\u30B6\u30FC\u3092\u507D\u88C5\u3067\u304D\u307E\u3059\u3002
544
+
545
+ ### Business Logic
546
+
547
+ \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
548
+
549
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u307E\u305F\u306F \`connection(connectionId, { subject })\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
550
+ - \`client.listCalendars()\` \u2014 \u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u5168\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7\u53D6\u5F97
551
+ - \`client.listEvents(options?, calendarId?)\` \u2014 \u30D5\u30A3\u30EB\u30BF\u30FC\u4ED8\u304D\u30A4\u30D9\u30F3\u30C8\u4E00\u89A7\u53D6\u5F97
552
+ - \`client.getEvent(eventId, calendarId?)\` \u2014 ID\u306B\u3088\u308B\u5358\u4E00\u30A4\u30D9\u30F3\u30C8\u53D6\u5F97
553
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
554
+
555
+ #### Domain-wide Delegation
556
+
557
+ Domain-wide Delegation\u3067\u30E6\u30FC\u30B6\u30FC\u306E\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u3059\u308B\u306B\u306F\u3001\`connection()\`\u306E\u7B2C2\u5F15\u6570\u306B\`subject\`\uFF08\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\uFF09\u3092\u6E21\u3057\u307E\u3059\uFF1A
558
+
559
+ \`\`\`ts
560
+ const calendar = connection("<connectionId>", { subject: "user@example.com" });
561
+ \`\`\`
562
+
563
+ \`\`\`ts
564
+ import type { Context } from "hono";
565
+ import { connection } from "@squadbase/vite-server/connectors/google-calendar";
566
+
567
+ const calendar = connection("<connectionId>");
568
+
569
+ export default async function handler(c: Context) {
570
+ const now = new Date().toISOString();
571
+ const { items } = await calendar.listEvents({
572
+ timeMin: now,
573
+ maxResults: 10,
574
+ singleEvents: true,
575
+ orderBy: "startTime",
576
+ });
577
+
578
+ return c.json(
579
+ items.map((event) => ({
580
+ id: event.id,
581
+ summary: event.summary,
582
+ start: event.start.dateTime ?? event.start.date,
583
+ end: event.end.dateTime ?? event.end.date,
584
+ location: event.location,
585
+ })),
586
+ );
587
+ }
588
+ \`\`\`
589
+
590
+ ### Google Calendar API v3 \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
591
+
592
+ #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
593
+ - GET \`/calendars/{calendarId}\` \u2014 \u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
594
+ - GET \`/users/me/calendarList\` \u2014 \u8A8D\u8A3C\u30E6\u30FC\u30B6\u30FC\u304C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u5168\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7
595
+ - GET \`/calendars/{calendarId}/events\` \u2014 \u30AB\u30EC\u30F3\u30C0\u30FC\u4E0A\u306E\u30A4\u30D9\u30F3\u30C8\u4E00\u89A7
596
+ - GET \`/calendars/{calendarId}/events/{eventId}\` \u2014 \u5358\u4E00\u30A4\u30D9\u30F3\u30C8\u306E\u53D6\u5F97
597
+
598
+ #### \u30A4\u30D9\u30F3\u30C8\u4E00\u89A7\u306E\u4E3B\u8981\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF
599
+ - \`timeMin\` \u2014 \u4E0B\u9650\uFF08RFC3339\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u3001\u4F8B: "2024-01-01T00:00:00Z"\uFF09
600
+ - \`timeMax\` \u2014 \u4E0A\u9650\uFF08RFC3339\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\uFF09
601
+ - \`maxResults\` \u2014 \u6700\u5927\u30A4\u30D9\u30F3\u30C8\u6570\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8250\u3001\u6700\u59272500\uFF09
602
+ - \`singleEvents=true\` \u2014 \u7E70\u308A\u8FD4\u3057\u30A4\u30D9\u30F3\u30C8\u3092\u500B\u5225\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u306B\u5C55\u958B
603
+ - \`orderBy=startTime\` \u2014 \u958B\u59CB\u6642\u9593\u9806\u306B\u4E26\u3079\u66FF\u3048\uFF08singleEvents=true\u304C\u5FC5\u8981\uFF09
604
+ - \`q\` \u2014 \u30D5\u30EA\u30FC\u30C6\u30AD\u30B9\u30C8\u691C\u7D22\u8A9E
605
+
606
+ #### \u30D2\u30F3\u30C8
607
+ - \u30D1\u30B9\u306B \`{calendarId}\` \u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u3092\u4F7F\u7528 \u2014 \u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FCID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059
608
+ - \`singleEvents=true\` \u3092\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u7E70\u308A\u8FD4\u3057\u30A4\u30D9\u30F3\u30C8\u304C\u500B\u5225\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u306B\u5C55\u958B\u3055\u308C\u307E\u3059
609
+ - \`orderBy=startTime\` \u3092\u4F7F\u7528\u3059\u308B\u5834\u5408\u3001\`singleEvents=true\` \u3082\u8A2D\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
610
+ - \u6642\u9593\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u306FRFC3339\u5F62\u5F0F\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: "2024-01-15T09:00:00Z" \u3084 "2024-01-15T09:00:00+09:00"\uFF09
611
+ - \u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FCID\u306F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408 "primary" \u304C\u4F7F\u7528\u3055\u308C\u307E\u3059`
612
+ },
613
+ tools
614
+ });
615
+
616
+ // src/connectors/create-connector-sdk.ts
617
+ import { readFileSync } from "fs";
618
+ import path from "path";
619
+
620
+ // src/connector-client/env.ts
621
+ function resolveEnvVar(entry, key, connectionId) {
622
+ const envVarName = entry.envVars[key];
623
+ if (!envVarName) {
624
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
625
+ }
626
+ const value = process.env[envVarName];
627
+ if (!value) {
628
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
629
+ }
630
+ return value;
631
+ }
632
+ function resolveEnvVarOptional(entry, key) {
633
+ const envVarName = entry.envVars[key];
634
+ if (!envVarName) return void 0;
635
+ return process.env[envVarName] || void 0;
636
+ }
637
+
638
+ // src/connectors/create-connector-sdk.ts
639
+ function loadConnectionsSync() {
640
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
641
+ try {
642
+ const raw = readFileSync(filePath, "utf-8");
643
+ return JSON.parse(raw);
644
+ } catch {
645
+ return {};
646
+ }
647
+ }
648
+ function createConnectorSdk(plugin, createClient2) {
649
+ return (connectionId) => {
650
+ const connections = loadConnectionsSync();
651
+ const entry = connections[connectionId];
652
+ if (!entry) {
653
+ throw new Error(
654
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
655
+ );
656
+ }
657
+ if (entry.connector.slug !== plugin.slug) {
658
+ throw new Error(
659
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
660
+ );
661
+ }
662
+ const params = {};
663
+ for (const param of Object.values(plugin.parameters)) {
664
+ if (param.required) {
665
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
666
+ } else {
667
+ const val = resolveEnvVarOptional(entry, param.slug);
668
+ if (val !== void 0) params[param.slug] = val;
669
+ }
670
+ }
671
+ return createClient2(params);
672
+ };
673
+ }
674
+
675
+ // src/connectors/entries/google-calendar.ts
676
+ var baseConnection = createConnectorSdk(googleCalendarConnector, createClient);
677
+ var connection = (connectionId, options) => {
678
+ if (options) {
679
+ return createConnectorSdk(
680
+ googleCalendarConnector,
681
+ (params) => createClient(params, options)
682
+ )(connectionId);
683
+ }
684
+ return baseConnection(connectionId);
685
+ };
686
+ export {
687
+ connection
688
+ };