@squadbase/vite-server 0.1.3-dev.9 → 0.1.4-dev.0

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 (63) hide show
  1. package/dist/cli/index.js +14539 -29447
  2. package/dist/connectors/airtable-oauth.js +43 -6
  3. package/dist/connectors/airtable.js +43 -6
  4. package/dist/connectors/amplitude.js +43 -6
  5. package/dist/connectors/anthropic.js +43 -6
  6. package/dist/connectors/asana.js +43 -6
  7. package/dist/connectors/attio.js +522 -118
  8. package/dist/connectors/{google-ads-oauth.d.ts → backlog-api-key.d.ts} +1 -1
  9. package/dist/connectors/backlog-api-key.js +629 -0
  10. package/dist/connectors/customerio.js +43 -6
  11. package/dist/connectors/dbt.js +43 -6
  12. package/dist/connectors/{google-sheets-oauth.d.ts → gamma.d.ts} +1 -1
  13. package/dist/connectors/gamma.js +866 -0
  14. package/dist/connectors/gemini.js +43 -6
  15. package/dist/connectors/gmail-oauth.js +65 -8
  16. package/dist/connectors/gmail.js +104 -44
  17. package/dist/connectors/google-ads.d.ts +1 -1
  18. package/dist/connectors/google-ads.js +410 -332
  19. package/dist/connectors/google-analytics-oauth.js +61 -8
  20. package/dist/connectors/google-analytics.js +107 -292
  21. package/dist/connectors/google-calendar-oauth.js +61 -8
  22. package/dist/connectors/google-calendar.js +111 -58
  23. package/dist/connectors/{linkedin-ads-oauth.d.ts → google-docs.d.ts} +1 -1
  24. package/dist/connectors/google-docs.js +631 -0
  25. package/dist/connectors/google-drive.d.ts +5 -0
  26. package/dist/connectors/google-drive.js +875 -0
  27. package/dist/connectors/google-sheets.d.ts +1 -1
  28. package/dist/connectors/google-sheets.js +267 -285
  29. package/dist/connectors/google-slides.d.ts +5 -0
  30. package/dist/connectors/google-slides.js +663 -0
  31. package/dist/connectors/grafana.js +43 -6
  32. package/dist/connectors/hubspot-oauth.js +43 -6
  33. package/dist/connectors/hubspot.js +43 -6
  34. package/dist/connectors/intercom-oauth.js +43 -6
  35. package/dist/connectors/intercom.js +43 -6
  36. package/dist/connectors/jira-api-key.js +43 -6
  37. package/dist/connectors/kintone-api-token.js +256 -82
  38. package/dist/connectors/kintone.js +43 -6
  39. package/dist/connectors/linkedin-ads.js +188 -168
  40. package/dist/connectors/mailchimp-oauth.js +43 -6
  41. package/dist/connectors/mailchimp.js +43 -6
  42. package/dist/connectors/mixpanel.d.ts +5 -0
  43. package/dist/connectors/mixpanel.js +779 -0
  44. package/dist/connectors/notion-oauth.js +43 -6
  45. package/dist/connectors/notion.js +43 -6
  46. package/dist/connectors/openai.js +43 -6
  47. package/dist/connectors/sentry.d.ts +5 -0
  48. package/dist/connectors/sentry.js +761 -0
  49. package/dist/connectors/shopify-oauth.js +43 -6
  50. package/dist/connectors/shopify.js +43 -6
  51. package/dist/connectors/stripe-api-key.js +46 -7
  52. package/dist/connectors/stripe-oauth.js +43 -6
  53. package/dist/connectors/wix-store.js +43 -6
  54. package/dist/connectors/zendesk-oauth.js +43 -6
  55. package/dist/connectors/zendesk.js +43 -6
  56. package/dist/index.d.ts +1 -1
  57. package/dist/index.js +4574 -3863
  58. package/dist/main.js +4572 -3862
  59. package/dist/vite-plugin.js +4572 -3862
  60. package/package.json +30 -12
  61. package/dist/connectors/google-ads-oauth.js +0 -890
  62. package/dist/connectors/google-sheets-oauth.js +0 -718
  63. package/dist/connectors/linkedin-ads-oauth.js +0 -848
@@ -217,21 +217,58 @@ var ConnectorPlugin = class _ConnectorPlugin {
217
217
  * Filters connections by connectorKey internally.
218
218
  * Returns tools keyed as `${connectorKey}_${toolName}`.
219
219
  */
220
- createTools(connections, config) {
220
+ createTools(connections, config, opts) {
221
221
  const myConnections = connections.filter(
222
222
  (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
223
223
  );
224
224
  const result = {};
225
225
  for (const t of Object.values(this.tools)) {
226
- result[`${this.connectorKey}_${t.name}`] = t.createTool(
227
- myConnections,
228
- config
229
- );
226
+ const tool = t.createTool(myConnections, config);
227
+ const originalToModelOutput = tool.toModelOutput;
228
+ result[`${this.connectorKey}_${t.name}`] = {
229
+ ...tool,
230
+ toModelOutput: async (options) => {
231
+ if (!originalToModelOutput) {
232
+ return opts.truncateOutput(options.output);
233
+ }
234
+ const modelOutput = await originalToModelOutput(options);
235
+ if (modelOutput.type === "text" || modelOutput.type === "json") {
236
+ return opts.truncateOutput(modelOutput.value);
237
+ }
238
+ return modelOutput;
239
+ }
240
+ };
230
241
  }
231
242
  return result;
232
243
  }
233
244
  static deriveKey(slug, authType) {
234
- return authType ? `${slug}-${authType}` : slug;
245
+ if (authType) return `${slug}-${authType}`;
246
+ const LEGACY_NULL_AUTH_TYPE_MAP = {
247
+ // user-password
248
+ "postgresql": "user-password",
249
+ "mysql": "user-password",
250
+ "clickhouse": "user-password",
251
+ "kintone": "user-password",
252
+ "squadbase-db": "user-password",
253
+ // service-account
254
+ "snowflake": "service-account",
255
+ "bigquery": "service-account",
256
+ "google-analytics": "service-account",
257
+ "google-calendar": "service-account",
258
+ "aws-athena": "service-account",
259
+ "redshift": "service-account",
260
+ // api-key
261
+ "databricks": "api-key",
262
+ "dbt": "api-key",
263
+ "airtable": "api-key",
264
+ "openai": "api-key",
265
+ "gemini": "api-key",
266
+ "anthropic": "api-key",
267
+ "wix-store": "api-key"
268
+ };
269
+ const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
270
+ if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
271
+ return slug;
235
272
  }
236
273
  };
237
274
 
@@ -712,7 +749,15 @@ averageSessionDuration, conversions, totalRevenue
712
749
 
713
750
  ### Business Logic
714
751
 
715
- 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.
752
+ 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 and do NOT read \`INTERNAL_SQUADBASE_*\` env vars \u2014 the SDK takes care of OAuth.
753
+
754
+ SDK surface (client created via \`connection(connectionId)\`):
755
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch (\`path\` is appended to \`https://analyticsdata.googleapis.com/v1beta/\`).
756
+ - \`client.runReport(request)\` \u2014 run a GA4 report.
757
+ - \`client.runRealtimeReport(request)\` \u2014 run a realtime report.
758
+ - \`client.getMetadata()\` \u2014 fetch available dimensions and metrics.
759
+
760
+ If a handler test fails with \`Connection proxy is not configured\`, retry \u2014 the sandbox is still initializing. Do NOT abandon the SDK and construct OAuth proxy URLs manually.
716
761
 
717
762
  #### Example
718
763
 
@@ -776,7 +821,15 @@ averageSessionDuration, conversions, totalRevenue
776
821
 
777
822
  ### Business Logic
778
823
 
779
- \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
824
+ \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\u30BF SDK \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\`INTERNAL_SQUADBASE_*\` \u306E\u74B0\u5883\u5909\u6570\u3092\u4F7F\u3063\u3066\u624B\u52D5\u3067 OAuth \u30D7\u30ED\u30AD\u30B7\u3092\u53E9\u304F\u3053\u3068\u3082\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044 \u2014 SDK \u304C OAuth \u3092\u51E6\u7406\u3057\u307E\u3059\u3002
825
+
826
+ SDK\uFF08\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\uFF09:
827
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304D fetch\uFF08\`path\` \u306F \`https://analyticsdata.googleapis.com/v1beta/\` \u306B\u8FFD\u52A0\u3055\u308C\u307E\u3059\uFF09\u3002
828
+ - \`client.runReport(request)\` \u2014 GA4 \u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C\u3002
829
+ - \`client.runRealtimeReport(request)\` \u2014 \u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C\u3002
830
+ - \`client.getMetadata()\` \u2014 \u5229\u7528\u53EF\u80FD\u306A\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3\u3068\u30E1\u30C8\u30EA\u30AF\u30B9\u3092\u53D6\u5F97\u3002
831
+
832
+ \u30CF\u30F3\u30C9\u30E9\u306E\u30C6\u30B9\u30C8\u304C \`Connection proxy is not configured\` \u3067\u5931\u6557\u3059\u308B\u5834\u5408\u306F\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u901A\u5E38\u306F\u30B5\u30F3\u30C9\u30DC\u30C3\u30AF\u30B9\u306E\u521D\u671F\u5316\u4E2D\u306B\u8D77\u304D\u307E\u3059\u3002SDK \u3092\u8AE6\u3081\u3066 OAuth \u30D7\u30ED\u30AD\u30B7\u306E URL \u3092\u81EA\u5206\u3067\u7D44\u307F\u7ACB\u3066\u308B\u3053\u3068\u306F **\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044**\u3002
780
833
 
781
834
  #### Example
782
835
 
@@ -55,6 +55,15 @@ var parameters = {
55
55
  type: "base64EncodedJson",
56
56
  secret: true,
57
57
  required: true
58
+ }),
59
+ propertyId: new ParameterDefinition({
60
+ slug: "property-id",
61
+ name: "Google Analytics Property ID",
62
+ description: "The Google Analytics 4 property ID (e.g., 123456789).",
63
+ envVarBaseKey: "GA_PROPERTY_ID",
64
+ type: "text",
65
+ secret: false,
66
+ required: true
58
67
  })
59
68
  };
60
69
 
@@ -86,9 +95,15 @@ function buildJwt(clientEmail, privateKey, nowSec) {
86
95
  }
87
96
  function createClient(params) {
88
97
  const serviceAccountKeyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
89
- if (!serviceAccountKeyJsonBase64) {
98
+ const propertyId = params[parameters.propertyId.slug];
99
+ if (!serviceAccountKeyJsonBase64 || !propertyId) {
100
+ const required = [
101
+ parameters.serviceAccountKeyJsonBase64.slug,
102
+ parameters.propertyId.slug
103
+ ];
104
+ const missing = required.filter((s) => !params[s]);
90
105
  throw new Error(
91
- `google-analytics: missing required parameter: ${parameters.serviceAccountKeyJsonBase64.slug}`
106
+ `google-analytics: missing required parameters: ${missing.join(", ")}`
92
107
  );
93
108
  }
94
109
  let serviceAccountKey;
@@ -110,7 +125,7 @@ function createClient(params) {
110
125
  }
111
126
  let cachedToken = null;
112
127
  let tokenExpiresAt = 0;
113
- async function getAccessToken2() {
128
+ async function getAccessToken() {
114
129
  const nowSec = Math.floor(Date.now() / 1e3);
115
130
  if (cachedToken && nowSec < tokenExpiresAt - 60) {
116
131
  return cachedToken;
@@ -141,13 +156,14 @@ function createClient(params) {
141
156
  }
142
157
  return {
143
158
  async request(path2, init) {
144
- const accessToken = await getAccessToken2();
145
- const url = `${BASE_URL.replace(/\/+$/, "")}/${path2.replace(/^\/+/, "")}`;
159
+ const accessToken = await getAccessToken();
160
+ const resolvedPath = path2.replace(/\{propertyId\}/g, propertyId);
161
+ const url = `${BASE_URL.replace(/\/+$/, "")}/${resolvedPath.replace(/^\/+/, "")}`;
146
162
  const headers = new Headers(init?.headers);
147
163
  headers.set("Authorization", `Bearer ${accessToken}`);
148
164
  return fetch(url, { ...init, headers });
149
165
  },
150
- async runReport(propertyId, request) {
166
+ async runReport(request) {
151
167
  const response = await this.request(
152
168
  `properties/${propertyId}:runReport`,
153
169
  {
@@ -168,7 +184,7 @@ function createClient(params) {
168
184
  rowCount: data.rowCount ?? 0
169
185
  };
170
186
  },
171
- async getMetadata(propertyId) {
187
+ async getMetadata() {
172
188
  const response = await this.request(
173
189
  `properties/${propertyId}/metadata`,
174
190
  { method: "GET" }
@@ -181,7 +197,7 @@ function createClient(params) {
181
197
  }
182
198
  return await response.json();
183
199
  },
184
- async runRealtimeReport(propertyId, request) {
200
+ async runRealtimeReport(request) {
185
201
  const response = await this.request(
186
202
  `properties/${propertyId}:runRealtimeReport`,
187
203
  {
@@ -287,21 +303,58 @@ var ConnectorPlugin = class _ConnectorPlugin {
287
303
  * Filters connections by connectorKey internally.
288
304
  * Returns tools keyed as `${connectorKey}_${toolName}`.
289
305
  */
290
- createTools(connections, config) {
306
+ createTools(connections, config, opts) {
291
307
  const myConnections = connections.filter(
292
308
  (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
293
309
  );
294
310
  const result = {};
295
311
  for (const t of Object.values(this.tools)) {
296
- result[`${this.connectorKey}_${t.name}`] = t.createTool(
297
- myConnections,
298
- config
299
- );
312
+ const tool = t.createTool(myConnections, config);
313
+ const originalToModelOutput = tool.toModelOutput;
314
+ result[`${this.connectorKey}_${t.name}`] = {
315
+ ...tool,
316
+ toModelOutput: async (options) => {
317
+ if (!originalToModelOutput) {
318
+ return opts.truncateOutput(options.output);
319
+ }
320
+ const modelOutput = await originalToModelOutput(options);
321
+ if (modelOutput.type === "text" || modelOutput.type === "json") {
322
+ return opts.truncateOutput(modelOutput.value);
323
+ }
324
+ return modelOutput;
325
+ }
326
+ };
300
327
  }
301
328
  return result;
302
329
  }
303
330
  static deriveKey(slug, authType) {
304
- return authType ? `${slug}-${authType}` : slug;
331
+ if (authType) return `${slug}-${authType}`;
332
+ const LEGACY_NULL_AUTH_TYPE_MAP = {
333
+ // user-password
334
+ "postgresql": "user-password",
335
+ "mysql": "user-password",
336
+ "clickhouse": "user-password",
337
+ "kintone": "user-password",
338
+ "squadbase-db": "user-password",
339
+ // service-account
340
+ "snowflake": "service-account",
341
+ "bigquery": "service-account",
342
+ "google-analytics": "service-account",
343
+ "google-calendar": "service-account",
344
+ "aws-athena": "service-account",
345
+ "redshift": "service-account",
346
+ // api-key
347
+ "databricks": "api-key",
348
+ "dbt": "api-key",
349
+ "airtable": "api-key",
350
+ "openai": "api-key",
351
+ "gemini": "api-key",
352
+ "anthropic": "api-key",
353
+ "wix-store": "api-key"
354
+ };
355
+ const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
356
+ if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
357
+ return slug;
305
358
  }
306
359
  };
307
360
 
@@ -315,275 +368,45 @@ var AUTH_TYPES = {
315
368
  USER_PASSWORD: "user-password"
316
369
  };
317
370
 
318
- // ../connectors/src/connectors/google-analytics/tools/list-accounts.ts
319
- import { z } from "zod";
320
-
321
- // ../connectors/src/connectors/google-analytics/tools/auth.ts
322
- var SCOPES = [
323
- "https://www.googleapis.com/auth/analytics.readonly"
324
- ];
325
- async function getAccessToken(connection2) {
326
- const { GoogleAuth } = await import("google-auth-library");
327
- const keyJsonBase64 = parameters.serviceAccountKeyJsonBase64.getValue(connection2);
328
- const credentials = JSON.parse(
329
- Buffer.from(keyJsonBase64, "base64").toString("utf-8")
330
- );
331
- const auth = new GoogleAuth({
332
- credentials,
333
- scopes: SCOPES
334
- });
335
- const token = await auth.getAccessToken();
336
- if (!token) {
337
- throw new Error("Failed to obtain access token");
371
+ // ../connectors/src/connectors/google-analytics/setup.ts
372
+ var googleAnalyticsOnboarding = new ConnectorOnboarding({
373
+ dataOverviewInstructions: {
374
+ en: `1. Call google-analytics-service-account_request with GET properties/{propertyId}/metadata to list available dimensions and metrics
375
+ 2. Call google-analytics-service-account_request with POST properties/{propertyId}:runReport using a small date range and basic metrics to verify data availability`,
376
+ ja: `1. google-analytics-service-account_request \u3067 GET properties/{propertyId}/metadata \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3\u3068\u30E1\u30C8\u30EA\u30AF\u30B9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
377
+ 2. google-analytics-service-account_request \u3067 POST properties/{propertyId}:runReport \u3092\u77ED\u3044\u671F\u9593\u3068\u57FA\u672C\u30E1\u30C8\u30EA\u30AF\u30B9\u3067\u547C\u3073\u51FA\u3057\u3001\u30C7\u30FC\u30BF\u306E\u53EF\u7528\u6027\u3092\u78BA\u8A8D`
338
378
  }
339
- return token;
340
- }
379
+ });
341
380
 
342
- // ../connectors/src/connectors/google-analytics/tools/list-accounts.ts
343
- var ADMIN_BASE_URL = "https://analyticsadmin.googleapis.com/v1beta/";
381
+ // ../connectors/src/connectors/google-analytics/tools/request.ts
382
+ import { z } from "zod";
383
+ var BASE_URL2 = "https://analyticsdata.googleapis.com/v1beta/";
344
384
  var REQUEST_TIMEOUT_MS = 6e4;
345
385
  var inputSchema = z.object({
346
- toolUseIntent: z.string().optional().describe(
347
- "Brief description of what you intend to accomplish with this tool call"
348
- ),
349
- connectionId: z.string().describe("ID of the Google Analytics connection to use")
386
+ toolUseIntent: z.string().optional().describe("Brief description of what you intend to accomplish with this tool call"),
387
+ connectionId: z.string().describe("ID of the Google Analytics connection to use"),
388
+ method: z.enum(["GET", "POST"]).describe("HTTP method"),
389
+ path: z.string().describe("API path (e.g., 'properties/{propertyId}:runReport'). {propertyId} is automatically replaced."),
390
+ body: z.record(z.string(), z.unknown()).optional().describe("POST request body (JSON)")
350
391
  });
351
392
  var outputSchema = z.discriminatedUnion("success", [
352
393
  z.object({
353
394
  success: z.literal(true),
354
- accounts: z.array(
355
- z.object({
356
- name: z.string(),
357
- displayName: z.string()
358
- })
359
- )
395
+ status: z.number(),
396
+ data: z.record(z.string(), z.unknown())
360
397
  }),
361
398
  z.object({
362
399
  success: z.literal(false),
363
400
  error: z.string()
364
401
  })
365
402
  ]);
366
- var listAccountsTool = new ConnectorTool({
367
- name: "listAccounts",
368
- description: "List Google Analytics accounts accessible with the service account credentials. Returns account names and display names.",
369
- inputSchema,
370
- outputSchema,
371
- async execute({ connectionId }, connections) {
372
- const connection2 = connections.find((c) => c.id === connectionId);
373
- if (!connection2) {
374
- return {
375
- success: false,
376
- error: `Connection ${connectionId} not found`
377
- };
378
- }
379
- console.log(
380
- `[connector-request] google-analytics/${connection2.name}: listAccounts`
381
- );
382
- try {
383
- const token = await getAccessToken(connection2);
384
- const controller = new AbortController();
385
- const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
386
- try {
387
- const response = await fetch(`${ADMIN_BASE_URL}accounts`, {
388
- method: "GET",
389
- headers: {
390
- Authorization: `Bearer ${token}`
391
- },
392
- signal: controller.signal
393
- });
394
- const data = await response.json();
395
- if (!response.ok) {
396
- const errorMessage = data?.error?.message ?? `HTTP ${response.status} ${response.statusText}`;
397
- return { success: false, error: errorMessage };
398
- }
399
- const accounts = (data.accounts ?? []).map((a) => ({
400
- name: a.name ?? "",
401
- displayName: a.displayName ?? ""
402
- }));
403
- return { success: true, accounts };
404
- } finally {
405
- clearTimeout(timeout);
406
- }
407
- } catch (err) {
408
- const msg = err instanceof Error ? err.message : String(err);
409
- return { success: false, error: msg };
410
- }
411
- }
412
- });
413
-
414
- // ../connectors/src/connectors/google-analytics/tools/list-properties.ts
415
- import { z as z2 } from "zod";
416
- var ADMIN_BASE_URL2 = "https://analyticsadmin.googleapis.com/v1beta/";
417
- var REQUEST_TIMEOUT_MS2 = 6e4;
418
- var inputSchema2 = z2.object({
419
- toolUseIntent: z2.string().optional().describe(
420
- "Brief description of what you intend to accomplish with this tool call"
421
- ),
422
- connectionId: z2.string().describe("ID of the Google Analytics connection to use"),
423
- accountName: z2.string().describe(
424
- "The account resource name (e.g., 'accounts/123456'). Obtained from the listAccounts tool."
425
- )
426
- });
427
- var outputSchema2 = z2.discriminatedUnion("success", [
428
- z2.object({
429
- success: z2.literal(true),
430
- properties: z2.array(
431
- z2.object({
432
- name: z2.string(),
433
- displayName: z2.string(),
434
- propertyId: z2.string()
435
- })
436
- )
437
- }),
438
- z2.object({
439
- success: z2.literal(false),
440
- error: z2.string()
441
- })
442
- ]);
443
- var listPropertiesTool = new ConnectorTool({
444
- name: "listProperties",
445
- description: "List GA4 properties for a given Google Analytics account. Returns property names, display names, and property IDs.",
446
- inputSchema: inputSchema2,
447
- outputSchema: outputSchema2,
448
- async execute({ connectionId, accountName }, connections) {
449
- const connection2 = connections.find((c) => c.id === connectionId);
450
- if (!connection2) {
451
- return {
452
- success: false,
453
- error: `Connection ${connectionId} not found`
454
- };
455
- }
456
- console.log(
457
- `[connector-request] google-analytics/${connection2.name}: listProperties for ${accountName}`
458
- );
459
- try {
460
- const token = await getAccessToken(connection2);
461
- const controller = new AbortController();
462
- const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
463
- try {
464
- const filter = encodeURIComponent(`parent:${accountName}`);
465
- const response = await fetch(
466
- `${ADMIN_BASE_URL2}properties?filter=${filter}`,
467
- {
468
- method: "GET",
469
- headers: {
470
- Authorization: `Bearer ${token}`
471
- },
472
- signal: controller.signal
473
- }
474
- );
475
- const data = await response.json();
476
- if (!response.ok) {
477
- const errorMessage = data?.error?.message ?? `HTTP ${response.status} ${response.statusText}`;
478
- return { success: false, error: errorMessage };
479
- }
480
- const properties = (data.properties ?? []).map((p) => {
481
- const name = p.name ?? "";
482
- const propertyId = name.replace(/^properties\//, "");
483
- return {
484
- name,
485
- displayName: p.displayName ?? "",
486
- propertyId
487
- };
488
- });
489
- return { success: true, properties };
490
- } finally {
491
- clearTimeout(timeout);
492
- }
493
- } catch (err) {
494
- const msg = err instanceof Error ? err.message : String(err);
495
- return { success: false, error: msg };
496
- }
497
- }
498
- });
499
-
500
- // ../connectors/src/connectors/google-analytics/setup.ts
501
- var listAccountsToolName = `google-analytics_${listAccountsTool.name}`;
502
- var listPropertiesToolName = `google-analytics_${listPropertiesTool.name}`;
503
- var googleAnalyticsOnboarding = new ConnectorOnboarding({
504
- connectionSetupInstructions: {
505
- ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Google Analytics (Service Account) \u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
506
-
507
- 1. \`${listAccountsToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001Service Account\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGoogle Analytics\u30A2\u30AB\u30A6\u30F3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
508
- 2. \u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u9078\u629E:
509
- - \u30A2\u30AB\u30A6\u30F3\u30C8\u304C **2\u4EF6\u4EE5\u4E0A**: \u300C\u4F7F\u7528\u3059\u308B\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u300D\u3068\u30E6\u30FC\u30B6\u30FC\u306B\u4F1D\u3048\u305F\u4E0A\u3067\u3001\`askUserQuestion\` \u3092\u547C\u3073\u51FA\u3059\uFF08\`options\`: \u5404 option \u306E \`label\` \u306F \`\u8868\u793A\u540D (name)\` \u306E\u5F62\u5F0F\uFF09
510
- - \u30A2\u30AB\u30A6\u30F3\u30C8\u304C **1\u4EF6\u306E\u307F**: \`askUserQuestion\` \u306F\u30B9\u30AD\u30C3\u30D7\u3057\u3001\u305D\u306E\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u9078\u629E\u6E08\u307F\u3068\u3057\u3066\u6B21\u3078\u9032\u3080
511
- - \u30A2\u30AB\u30A6\u30F3\u30C8\u304C **0\u4EF6**: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u4E2D\u65AD\u3057\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30A2\u30AB\u30A6\u30F3\u30C8\u304C\u306A\u3044\u65E8\u3092\u4F1D\u3048\u308B
512
- 3. \`${listPropertiesToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u9078\u629E\u3055\u308C\u305F\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
513
- 4. \u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u9078\u629E:
514
- - \u30D7\u30ED\u30D1\u30C6\u30A3\u304C **2\u4EF6\u4EE5\u4E0A**: \u300C\u4F7F\u7528\u3059\u308B\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u300D\u3068\u30E6\u30FC\u30B6\u30FC\u306B\u4F1D\u3048\u305F\u4E0A\u3067\u3001\`askUserQuestion\` \u3092\u547C\u3073\u51FA\u3059\uFF08\`options\`: \u5404 option \u306E \`label\` \u306F \`\u8868\u793A\u540D (id: \u30D7\u30ED\u30D1\u30C6\u30A3ID)\` \u306E\u5F62\u5F0F\uFF09
515
- - \u30D7\u30ED\u30D1\u30C6\u30A3\u304C **1\u4EF6\u306E\u307F**: \`askUserQuestion\` \u306F\u30B9\u30AD\u30C3\u30D7\u3057\u3001\u305D\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u9078\u629E\u6E08\u307F\u3068\u3057\u3066\u6B21\u3078\u9032\u3080
516
- - \u30D7\u30ED\u30D1\u30C6\u30A3\u304C **0\u4EF6**: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u4E2D\u65AD\u3057\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30D7\u30ED\u30D1\u30C6\u30A3\u304C\u306A\u3044\u65E8\u3092\u4F1D\u3048\u308B
517
- 5. \u30E6\u30FC\u30B6\u30FC\u304C\u9078\u629E\u3057\u305F\uFF08\u3082\u3057\u304F\u306F\u81EA\u52D5\u9078\u629E\u3055\u308C\u305F\uFF09\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u60C5\u5831\u3092\u57FA\u306B\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u306B\u9032\u3080
518
- 6. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3059:
519
- - \`property\`: \u9078\u629E\u3055\u308C\u305F\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u8868\u793A\u540D
520
- - \`propertyId\`: \u9078\u629E\u3055\u308C\u305F\u30D7\u30ED\u30D1\u30C6\u30A3ID
521
- - \`note\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5185\u5BB9\u306E\u7C21\u5358\u306A\u8AAC\u660E
522
-
523
- #### \u5236\u7D04
524
- - **\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u30EC\u30DD\u30FC\u30C8\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3057\u306A\u3044\u3053\u3068**\u3002\u5B9F\u884C\u3057\u3066\u3088\u3044\u306E\u306F\u4E0A\u8A18\u624B\u9806\u3067\u6307\u5B9A\u3055\u308C\u305F\u30E1\u30BF\u30C7\u30FC\u30BF\u53D6\u5F97\u306E\u307F
525
- - \`askUserQuestion\` \u306E \`options\` \u306F\u6700\u4F4E2\u4EF6\u5FC5\u8981\u3002\u5019\u88DC\u304C1\u4EF6\u4EE5\u4E0B\u306E\u5834\u5408\u306F\u5FC5\u305A\u30B9\u30AD\u30C3\u30D7\u3059\u308B\u3053\u3068
526
- - \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`,
527
- en: `Follow these steps to set up the Google Analytics (Service Account) connection.
528
-
529
- 1. Call \`${listAccountsToolName}\` to get the list of Google Analytics accounts accessible with the service account credentials
530
- 2. Select an account:
531
- - **2 or more accounts**: Tell the user "Please select an account.", then call \`askUserQuestion\` (\`options\`: each option's \`label\` should be \`Display Name (name)\`)
532
- - **Only 1 account**: Skip \`askUserQuestion\` and proceed using that account as the selection
533
- - **0 accounts**: Abort setup and inform the user that no accessible accounts are available
534
- 3. Call \`${listPropertiesToolName}\` to get the list of properties for the selected account
535
- 4. Select a property:
536
- - **2 or more properties**: Tell the user "Please select a property.", then call \`askUserQuestion\` (\`options\`: each option's \`label\` should be \`Display Name (id: propertyId)\`)
537
- - **Only 1 property**: Skip \`askUserQuestion\` and proceed using that property as the selection
538
- - **0 properties**: Abort setup and inform the user that no accessible properties are available
539
- 5. Proceed to the next step using the user-selected (or auto-selected) property's information
540
- 6. Call \`updateConnectionContext\`:
541
- - \`property\`: The selected property's display name
542
- - \`propertyId\`: The selected property ID
543
- - \`note\`: Brief description of the setup
544
-
545
- #### Constraints
546
- - **Do NOT fetch report data during setup**. Only the metadata requests specified in the steps above are allowed
547
- - \`askUserQuestion\` requires at least 2 \`options\`. Always skip it when there is 1 or fewer candidates
548
- - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
549
- },
550
- dataOverviewInstructions: {
551
- en: `1. Call google-analytics_request with GET properties/{propertyId}/metadata to list available dimensions and metrics
552
- 2. Call google-analytics_request with POST properties/{propertyId}:runReport using a small date range and basic metrics to verify data availability`,
553
- ja: `1. google-analytics_request \u3067 GET properties/{propertyId}/metadata \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3\u3068\u30E1\u30C8\u30EA\u30AF\u30B9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
554
- 2. google-analytics_request \u3067 POST properties/{propertyId}:runReport \u3092\u77ED\u3044\u671F\u9593\u3068\u57FA\u672C\u30E1\u30C8\u30EA\u30AF\u30B9\u3067\u547C\u3073\u51FA\u3057\u3001\u30C7\u30FC\u30BF\u306E\u53EF\u7528\u6027\u3092\u78BA\u8A8D`
555
- }
556
- });
557
-
558
- // ../connectors/src/connectors/google-analytics/tools/request.ts
559
- import { z as z3 } from "zod";
560
- var BASE_URL2 = "https://analyticsdata.googleapis.com/v1beta/";
561
- var REQUEST_TIMEOUT_MS3 = 6e4;
562
- var inputSchema3 = z3.object({
563
- toolUseIntent: z3.string().optional().describe("Brief description of what you intend to accomplish with this tool call"),
564
- connectionId: z3.string().describe("ID of the Google Analytics connection to use"),
565
- method: z3.enum(["GET", "POST"]).describe("HTTP method"),
566
- path: z3.string().describe("API path including the property ID (e.g., 'properties/123456789:runReport')."),
567
- body: z3.record(z3.string(), z3.unknown()).optional().describe("POST request body (JSON)")
568
- });
569
- var outputSchema3 = z3.discriminatedUnion("success", [
570
- z3.object({
571
- success: z3.literal(true),
572
- status: z3.number(),
573
- data: z3.record(z3.string(), z3.unknown())
574
- }),
575
- z3.object({
576
- success: z3.literal(false),
577
- error: z3.string()
578
- })
579
- ]);
580
403
  var requestTool = new ConnectorTool({
581
404
  name: "request",
582
405
  description: `Send authenticated requests to the Google Analytics Data API.
583
406
  Authentication is handled automatically using a service account.
584
- Include the full property ID in the path (e.g., 'properties/123456789:runReport').`,
585
- inputSchema: inputSchema3,
586
- outputSchema: outputSchema3,
407
+ {propertyId} in the path is automatically replaced with the connection's property-id.`,
408
+ inputSchema,
409
+ outputSchema,
587
410
  async execute({ connectionId, method, path: path2, body }, connections) {
588
411
  const connection2 = connections.find((c) => c.id === connectionId);
589
412
  if (!connection2) {
@@ -593,6 +416,7 @@ Include the full property ID in the path (e.g., 'properties/123456789:runReport'
593
416
  try {
594
417
  const { GoogleAuth } = await import("google-auth-library");
595
418
  const keyJsonBase64 = parameters.serviceAccountKeyJsonBase64.getValue(connection2);
419
+ const propertyId = parameters.propertyId.getValue(connection2);
596
420
  const credentials = JSON.parse(
597
421
  Buffer.from(keyJsonBase64, "base64").toString("utf-8")
598
422
  );
@@ -604,9 +428,10 @@ Include the full property ID in the path (e.g., 'properties/123456789:runReport'
604
428
  if (!token) {
605
429
  return { success: false, error: "Failed to obtain access token" };
606
430
  }
607
- const url = `${BASE_URL2}${path2}`;
431
+ const resolvedPath = path2.replace(/\{propertyId\}/g, propertyId);
432
+ const url = `${BASE_URL2}${resolvedPath}`;
608
433
  const controller = new AbortController();
609
- const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS3);
434
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
610
435
  try {
611
436
  const response = await fetch(url, {
612
437
  method,
@@ -637,11 +462,7 @@ Include the full property ID in the path (e.g., 'properties/123456789:runReport'
637
462
  });
638
463
 
639
464
  // ../connectors/src/connectors/google-analytics/index.ts
640
- var tools = {
641
- request: requestTool,
642
- listAccounts: listAccountsTool,
643
- listProperties: listPropertiesTool
644
- };
465
+ var tools = { request: requestTool };
645
466
  var googleAnalyticsConnector = new ConnectorPlugin({
646
467
  slug: "google-analytics",
647
468
  authType: AUTH_TYPES.SERVICE_ACCOUNT,
@@ -654,26 +475,23 @@ var googleAnalyticsConnector = new ConnectorPlugin({
654
475
  systemPrompt: {
655
476
  en: `### Tools
656
477
 
657
- - \`google-analytics_request\`: The only way to call the GA4 Data API. Use it to fetch metadata, run reports, or run realtime reports. See the GA4 Data API Reference below for available endpoints and request bodies.
658
- - \`google-analytics_listAccounts\`: List accessible Google Analytics accounts. Use during setup to discover available accounts.
659
- - \`google-analytics_listProperties\`: List GA4 properties for a given account. Use during setup to select the target property.
478
+ - \`google-analytics-service-account_request\`: The only way to call the GA4 Data API. Use it to fetch metadata, run reports, or run realtime reports. See the GA4 Data API Reference below for available endpoints and request bodies.
660
479
 
661
480
  ### Business Logic
662
481
 
663
482
  The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
664
483
 
665
- SDK methods (client created via \`connection(connectionId)\`). The GA4 property ID is NOT stored as a connection parameter \u2014 pass it explicitly to each call. Use the \`propertyId\` recorded in the connection context during setup:
666
- - \`client.runReport(propertyId, request)\` \u2014 run a GA4 report
667
- - \`client.runRealtimeReport(propertyId, request)\` \u2014 run a realtime report
668
- - \`client.getMetadata(propertyId)\` \u2014 fetch available dimensions/metrics
669
- - \`client.request(path, init?)\` \u2014 low-level authenticated fetch (path must include the property ID)
484
+ SDK methods (client created via \`connection(connectionId)\`):
485
+ - \`client.runReport(request)\` \u2014 run a GA4 report
486
+ - \`client.runRealtimeReport(request)\` \u2014 run a realtime report
487
+ - \`client.getMetadata()\` \u2014 fetch available dimensions/metrics
488
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
670
489
 
671
490
  \`\`\`ts
672
491
  import type { Context } from "hono";
673
492
  import { connection } from "@squadbase/vite-server/connectors/google-analytics";
674
493
 
675
494
  const ga = connection("<connectionId>");
676
- const PROPERTY_ID = "<propertyId from connection context>";
677
495
 
678
496
  export default async function handler(c: Context) {
679
497
  const { startDate = "7daysAgo", endDate = "today" } = await c.req.json<{
@@ -681,7 +499,7 @@ export default async function handler(c: Context) {
681
499
  endDate?: string;
682
500
  }>();
683
501
 
684
- const { rows } = await ga.runReport(PROPERTY_ID, {
502
+ const { rows } = await ga.runReport({
685
503
  dateRanges: [{ startDate, endDate }],
686
504
  dimensions: [{ name: "date" }],
687
505
  metrics: [{ name: "activeUsers" }, { name: "sessions" }],
@@ -725,26 +543,23 @@ activeUsers, sessions, screenPageViews, bounceRate, averageSessionDuration, conv
725
543
  - Relative: \`"today"\`, \`"yesterday"\`, \`"7daysAgo"\`, \`"30daysAgo"\``,
726
544
  ja: `### \u30C4\u30FC\u30EB
727
545
 
728
- - \`google-analytics_request\`: GA4 Data API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30E1\u30BF\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u3001\u30EC\u30DD\u30FC\u30C8\u306E\u5B9F\u884C\u3001\u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30EC\u30DD\u30FC\u30C8\u306E\u5B9F\u884C\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3068\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3\u306F\u4E0B\u90E8\u306E\u300CGA4 Data API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
729
- - \`google-analytics_listAccounts\`: \u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGoogle Analytics\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u4E00\u89A7\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306B\u5229\u7528\u53EF\u80FD\u306A\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u78BA\u8A8D\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002
730
- - \`google-analytics_listProperties\`: \u6307\u5B9A\u30A2\u30AB\u30A6\u30F3\u30C8\u306EGA4\u30D7\u30ED\u30D1\u30C6\u30A3\u4E00\u89A7\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306B\u30BF\u30FC\u30B2\u30C3\u30C8\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u9078\u629E\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002
546
+ - \`google-analytics-service-account_request\`: GA4 Data API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30E1\u30BF\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u3001\u30EC\u30DD\u30FC\u30C8\u306E\u5B9F\u884C\u3001\u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30EC\u30DD\u30FC\u30C8\u306E\u5B9F\u884C\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3068\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3\u306F\u4E0B\u90E8\u306E\u300CGA4 Data API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
731
547
 
732
548
  ### Business Logic
733
549
 
734
550
  \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
735
551
 
736
- SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8)\u3002GA4 \u30D7\u30ED\u30D1\u30C6\u30A3ID\u306F\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u4FDD\u5B58\u3055\u308C\u307E\u305B\u3093\u3002\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306B connection context \u306B\u8A18\u9332\u3055\u308C\u305F \`propertyId\` \u3092\u5404\u547C\u3073\u51FA\u3057\u306B\u660E\u793A\u7684\u306B\u6E21\u3057\u3066\u304F\u3060\u3055\u3044:
737
- - \`client.runReport(propertyId, request)\` \u2014 GA4\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
738
- - \`client.runRealtimeReport(propertyId, request)\` \u2014 \u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
739
- - \`client.getMetadata(propertyId)\` \u2014 \u5229\u7528\u53EF\u80FD\u306A\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3/\u30E1\u30C8\u30EA\u30AF\u30B9\u3092\u53D6\u5F97
740
- - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch\uFF08path \u306B\u30D7\u30ED\u30D1\u30C6\u30A3ID\u3092\u542B\u3081\u308B\uFF09
552
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
553
+ - \`client.runReport(request)\` \u2014 GA4\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
554
+ - \`client.runRealtimeReport(request)\` \u2014 \u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
555
+ - \`client.getMetadata()\` \u2014 \u5229\u7528\u53EF\u80FD\u306A\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3/\u30E1\u30C8\u30EA\u30AF\u30B9\u3092\u53D6\u5F97
556
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
741
557
 
742
558
  \`\`\`ts
743
559
  import type { Context } from "hono";
744
560
  import { connection } from "@squadbase/vite-server/connectors/google-analytics";
745
561
 
746
562
  const ga = connection("<connectionId>");
747
- const PROPERTY_ID = "<connection context \u306E propertyId>";
748
563
 
749
564
  export default async function handler(c: Context) {
750
565
  const { startDate = "7daysAgo", endDate = "today" } = await c.req.json<{
@@ -752,7 +567,7 @@ export default async function handler(c: Context) {
752
567
  endDate?: string;
753
568
  }>();
754
569
 
755
- const { rows } = await ga.runReport(PROPERTY_ID, {
570
+ const { rows } = await ga.runReport({
756
571
  dateRanges: [{ startDate, endDate }],
757
572
  dimensions: [{ name: "date" }],
758
573
  metrics: [{ name: "activeUsers" }, { name: "sessions" }],