@squadbase/vite-server 0.1.17-dev.24af54e → 0.1.17-dev.3b633bb

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 (73) hide show
  1. package/dist/cli/index.js +1681 -449
  2. package/dist/connectors/airtable-oauth.js +28 -3
  3. package/dist/connectors/airtable.js +28 -3
  4. package/dist/connectors/amplitude.js +28 -3
  5. package/dist/connectors/asana.js +28 -3
  6. package/dist/connectors/attio.js +28 -3
  7. package/dist/connectors/aws-billing.js +28 -3
  8. package/dist/connectors/azure-sql.js +31 -6
  9. package/dist/connectors/backlog-api-key.js +28 -3
  10. package/dist/connectors/clickup.js +28 -3
  11. package/dist/connectors/cosmosdb.js +28 -3
  12. package/dist/connectors/customerio.js +29 -4
  13. package/dist/connectors/dbt.js +28 -3
  14. package/dist/connectors/freshdesk.js +28 -3
  15. package/dist/connectors/freshsales.js +28 -3
  16. package/dist/connectors/freshservice.js +28 -3
  17. package/dist/connectors/gamma.js +30 -5
  18. package/dist/connectors/github.js +28 -3
  19. package/dist/connectors/gmail-oauth.js +28 -3
  20. package/dist/connectors/gmail.js +28 -3
  21. package/dist/connectors/google-ads.js +28 -3
  22. package/dist/connectors/google-analytics-oauth.js +28 -3
  23. package/dist/connectors/google-analytics.js +227 -105
  24. package/dist/connectors/google-audit-log.js +28 -3
  25. package/dist/connectors/google-calendar-oauth.js +28 -3
  26. package/dist/connectors/google-calendar.js +28 -3
  27. package/dist/connectors/google-docs.js +28 -3
  28. package/dist/connectors/google-drive.js +28 -3
  29. package/dist/connectors/google-search-console-oauth.js +28 -3
  30. package/dist/connectors/google-sheets.js +28 -3
  31. package/dist/connectors/google-slides.js +28 -3
  32. package/dist/connectors/grafana.js +28 -3
  33. package/dist/connectors/hubspot-oauth.js +28 -3
  34. package/dist/connectors/hubspot.js +28 -3
  35. package/dist/connectors/influxdb.js +28 -3
  36. package/dist/connectors/intercom-oauth.js +28 -3
  37. package/dist/connectors/intercom.js +28 -3
  38. package/dist/connectors/jdbc.js +28 -3
  39. package/dist/connectors/jira-api-key.js +28 -3
  40. package/dist/connectors/kintone-api-token.js +28 -3
  41. package/dist/connectors/kintone.js +28 -3
  42. package/dist/connectors/linear.js +28 -3
  43. package/dist/connectors/linkedin-ads.js +28 -3
  44. package/dist/connectors/mailchimp-oauth.js +28 -3
  45. package/dist/connectors/mailchimp.js +28 -3
  46. package/dist/connectors/meta-ads-oauth.js +28 -3
  47. package/dist/connectors/meta-ads.js +28 -3
  48. package/dist/connectors/mixpanel.js +28 -3
  49. package/dist/connectors/monday.js +28 -3
  50. package/dist/connectors/mongodb.js +28 -3
  51. package/dist/connectors/notion-oauth.js +28 -3
  52. package/dist/connectors/notion.js +28 -3
  53. package/dist/connectors/oracle.js +54 -14
  54. package/dist/connectors/outlook-oauth.js +28 -3
  55. package/dist/connectors/powerbi-oauth.js +309 -37
  56. package/dist/connectors/salesforce.js +28 -3
  57. package/dist/connectors/semrush.js +366 -46
  58. package/dist/connectors/sentry.js +28 -3
  59. package/dist/connectors/shopify-oauth.js +28 -3
  60. package/dist/connectors/shopify.js +28 -3
  61. package/dist/connectors/sqlserver.js +31 -6
  62. package/dist/connectors/stripe-api-key.js +28 -3
  63. package/dist/connectors/stripe-oauth.js +28 -3
  64. package/dist/connectors/supabase.js +31 -6
  65. package/dist/connectors/tableau.js +246 -78
  66. package/dist/connectors/tiktok-ads.js +28 -3
  67. package/dist/connectors/wix-store.js +28 -3
  68. package/dist/connectors/zendesk-oauth.js +28 -3
  69. package/dist/connectors/zendesk.js +28 -3
  70. package/dist/index.js +1681 -449
  71. package/dist/main.js +1681 -449
  72. package/dist/vite-plugin.js +1681 -449
  73. package/package.json +1 -1
@@ -67,15 +67,6 @@ var parameters = {
67
67
  type: "base64EncodedJson",
68
68
  secret: true,
69
69
  required: true
70
- }),
71
- propertyId: new ParameterDefinition({
72
- slug: "property-id",
73
- name: "Google Analytics Property ID",
74
- description: "The Google Analytics 4 property ID (e.g., 123456789).",
75
- envVarBaseKey: "GA_PROPERTY_ID",
76
- type: "text",
77
- secret: false,
78
- required: true
79
70
  })
80
71
  };
81
72
 
@@ -107,15 +98,9 @@ function buildJwt(clientEmail, privateKey, nowSec) {
107
98
  }
108
99
  function createClient(params) {
109
100
  const serviceAccountKeyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
110
- const propertyId = params[parameters.propertyId.slug];
111
- if (!serviceAccountKeyJsonBase64 || !propertyId) {
112
- const required = [
113
- parameters.serviceAccountKeyJsonBase64.slug,
114
- parameters.propertyId.slug
115
- ];
116
- const missing = required.filter((s) => !params[s]);
101
+ if (!serviceAccountKeyJsonBase64) {
117
102
  throw new Error(
118
- `google-analytics: missing required parameters: ${missing.join(", ")}`
103
+ `google-analytics: missing required parameters: ${parameters.serviceAccountKeyJsonBase64.slug}`
119
104
  );
120
105
  }
121
106
  let serviceAccountKey;
@@ -169,13 +154,12 @@ function createClient(params) {
169
154
  return {
170
155
  async request(path2, init) {
171
156
  const accessToken = await getAccessToken2();
172
- const resolvedPath = path2.replace(/\{propertyId\}/g, propertyId);
173
- const url = `${BASE_URL.replace(/\/+$/, "")}/${resolvedPath.replace(/^\/+/, "")}`;
157
+ const url = `${BASE_URL.replace(/\/+$/, "")}/${path2.replace(/^\/+/, "")}`;
174
158
  const headers = new Headers(init?.headers);
175
159
  headers.set("Authorization", `Bearer ${accessToken}`);
176
160
  return fetch(url, { ...init, headers });
177
161
  },
178
- async runReport(request) {
162
+ async runReport(propertyId, request) {
179
163
  const response = await this.request(
180
164
  `properties/${propertyId}:runReport`,
181
165
  {
@@ -196,7 +180,7 @@ function createClient(params) {
196
180
  rowCount: data.rowCount ?? 0
197
181
  };
198
182
  },
199
- async getMetadata() {
183
+ async getMetadata(propertyId) {
200
184
  const response = await this.request(
201
185
  `properties/${propertyId}/metadata`,
202
186
  { method: "GET" }
@@ -209,7 +193,7 @@ function createClient(params) {
209
193
  }
210
194
  return await response.json();
211
195
  },
212
- async runRealtimeReport(request) {
196
+ async runRealtimeReport(propertyId, request) {
213
197
  const response = await this.request(
214
198
  `properties/${propertyId}:runRealtimeReport`,
215
199
  {
@@ -405,19 +389,34 @@ async function runSetupFlow(flow, params, ctx, config) {
405
389
  };
406
390
  let state = flow.initialState();
407
391
  let answerIdx = 0;
392
+ const pendingParameterUpdates = [];
408
393
  for (const step of flow.steps) {
409
394
  const ans = ctx.answers[answerIdx];
410
395
  if (ans && ans.questionSlug === step.slug) {
411
396
  state = step.applyAnswer(state, ans.answer);
397
+ if (step.toParameterUpdates) {
398
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
399
+ }
412
400
  answerIdx += 1;
413
401
  continue;
414
402
  }
403
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
415
404
  if (step.type === "text") {
405
+ if (step.fetchOptions) {
406
+ const options2 = await step.fetchOptions(state, runtime);
407
+ if (options2.length === 0) {
408
+ continue;
409
+ }
410
+ }
416
411
  return {
417
412
  type: "nextQuestion",
418
413
  questionSlug: step.slug,
419
414
  question: step.question[ctx.language],
420
- questionType: "text"
415
+ questionType: "text",
416
+ allowFreeText: resolvedAllowFreeText,
417
+ ...pendingParameterUpdates.length > 0 && {
418
+ parameterUpdates: pendingParameterUpdates
419
+ }
421
420
  };
422
421
  }
423
422
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -429,11 +428,21 @@ async function runSetupFlow(flow, params, ctx, config) {
429
428
  questionSlug: step.slug,
430
429
  question: step.question[ctx.language],
431
430
  questionType: step.type,
432
- options
431
+ options,
432
+ allowFreeText: resolvedAllowFreeText,
433
+ ...pendingParameterUpdates.length > 0 && {
434
+ parameterUpdates: pendingParameterUpdates
435
+ }
433
436
  };
434
437
  }
435
438
  const dataInvestigationResult = await flow.finalize(state, runtime);
436
- return { type: "fulfilled", dataInvestigationResult };
439
+ return {
440
+ type: "fulfilled",
441
+ dataInvestigationResult,
442
+ ...pendingParameterUpdates.length > 0 && {
443
+ parameterUpdates: pendingParameterUpdates
444
+ }
445
+ };
437
446
  }
438
447
  async function resolveSetupSelection(params) {
439
448
  const { selected, allSentinel, fetchAll, limit } = params;
@@ -465,6 +474,7 @@ var googleAnalyticsOnboarding = new ConnectorOnboarding({
465
474
  import * as crypto2 from "crypto";
466
475
  var TOKEN_URL2 = "https://oauth2.googleapis.com/token";
467
476
  var ADMIN_BASE_URL = "https://analyticsadmin.googleapis.com/v1beta";
477
+ var DATA_BASE_URL = "https://analyticsdata.googleapis.com/v1beta";
468
478
  var SCOPE2 = "https://www.googleapis.com/auth/analytics.readonly";
469
479
  function base64url2(input) {
470
480
  const buf = typeof input === "string" ? Buffer.from(input) : input;
@@ -546,10 +556,25 @@ async function adminFetch(params, path2, init) {
546
556
  headers.set("Authorization", `Bearer ${accessToken}`);
547
557
  return fetch(url, { ...init, headers });
548
558
  }
559
+ async function dataFetch(params, path2, init) {
560
+ const keyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
561
+ if (!keyJsonBase64) {
562
+ throw new Error(
563
+ "google-analytics: missing required parameter: service-account-key-json-base64"
564
+ );
565
+ }
566
+ const serviceAccountKey = decodeServiceAccount(keyJsonBase64);
567
+ const accessToken = await getAccessToken(serviceAccountKey);
568
+ const url = `${DATA_BASE_URL}${path2.startsWith("/") ? "" : "/"}${path2}`;
569
+ const headers = new Headers(init?.headers);
570
+ headers.set("Authorization", `Bearer ${accessToken}`);
571
+ return fetch(url, { ...init, headers });
572
+ }
549
573
 
550
574
  // ../connectors/src/connectors/google-analytics/setup-flow.ts
551
575
  var ALL_PROPERTIES = "__ALL_PROPERTIES__";
552
576
  var GOOGLE_ANALYTICS_SETUP_MAX_PROPERTIES = 20;
577
+ var METADATA_DISPLAY_LIMIT = 30;
553
578
  async function listAccountSummaries(params) {
554
579
  const summaries = [];
555
580
  let pageToken;
@@ -576,6 +601,48 @@ async function getProperty(params, propertyId) {
576
601
  if (!res.ok) return null;
577
602
  return await res.json();
578
603
  }
604
+ async function getMetadata(params, propertyId) {
605
+ try {
606
+ const res = await dataFetch(
607
+ params,
608
+ `/properties/${propertyId}/metadata`
609
+ );
610
+ if (!res.ok) return { dimensions: [], metrics: [] };
611
+ const data = await res.json();
612
+ return {
613
+ dimensions: data.dimensions ?? [],
614
+ metrics: data.metrics ?? []
615
+ };
616
+ } catch {
617
+ return { dimensions: [], metrics: [] };
618
+ }
619
+ }
620
+ function appendMetadataSection(sections, dimensions, metrics) {
621
+ if (dimensions.length > 0) {
622
+ sections.push(`#### Dimensions (${dimensions.length})`, "");
623
+ for (const d of dimensions.slice(0, METADATA_DISPLAY_LIMIT)) {
624
+ sections.push(`- ${d.apiName ?? d.uiName ?? "(unknown)"}`);
625
+ }
626
+ if (dimensions.length > METADATA_DISPLAY_LIMIT) {
627
+ sections.push(
628
+ `- \u2026and ${dimensions.length - METADATA_DISPLAY_LIMIT} more`
629
+ );
630
+ }
631
+ sections.push("");
632
+ }
633
+ if (metrics.length > 0) {
634
+ sections.push(`#### Metrics (${metrics.length})`, "");
635
+ for (const m of metrics.slice(0, METADATA_DISPLAY_LIMIT)) {
636
+ sections.push(`- ${m.apiName ?? m.uiName ?? "(unknown)"}`);
637
+ }
638
+ if (metrics.length > METADATA_DISPLAY_LIMIT) {
639
+ sections.push(
640
+ `- \u2026and ${metrics.length - METADATA_DISPLAY_LIMIT} more`
641
+ );
642
+ }
643
+ sections.push("");
644
+ }
645
+ }
579
646
  var googleAnalyticsSetupFlow = {
580
647
  initialState: () => ({}),
581
648
  steps: [
@@ -587,15 +654,19 @@ var googleAnalyticsSetupFlow = {
587
654
  en: "Select a Google Analytics account"
588
655
  },
589
656
  async fetchOptions(_state, rt) {
590
- const summaries = await listAccountSummaries(rt.params);
591
- return summaries.map((s) => {
592
- const accountResource = s.account ?? s.name ?? "";
593
- if (!accountResource) return null;
594
- return {
595
- value: accountResource,
596
- label: s.displayName ?? accountResource
597
- };
598
- }).filter((v) => v != null);
657
+ try {
658
+ const summaries = await listAccountSummaries(rt.params);
659
+ return summaries.map((s) => {
660
+ const accountResource = s.account ?? s.name ?? "";
661
+ if (!accountResource) return null;
662
+ return {
663
+ value: accountResource,
664
+ label: s.displayName ?? accountResource
665
+ };
666
+ }).filter((v) => v != null);
667
+ } catch {
668
+ return [];
669
+ }
599
670
  },
600
671
  applyAnswer: (state, answer) => ({ ...state, account: answer[0] })
601
672
  },
@@ -608,68 +679,117 @@ var googleAnalyticsSetupFlow = {
608
679
  },
609
680
  async fetchOptions(state, rt) {
610
681
  if (!state.account) return [];
611
- const summaries = await listAccountSummaries(rt.params);
612
- const account = summaries.find(
613
- (s) => (s.account ?? s.name) === state.account
614
- );
615
- const props = (account?.propertySummaries ?? []).map((p) => {
616
- const id = propertyIdFromResource(p.property);
617
- if (!id) return null;
618
- return {
619
- value: id,
620
- label: p.displayName ? `${p.displayName} (${id})` : id
621
- };
622
- }).filter((v) => v != null);
623
- if (props.length === 0) return [];
624
- return [
625
- {
626
- value: ALL_PROPERTIES,
627
- label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30D7\u30ED\u30D1\u30C6\u30A3" : "All properties"
628
- },
629
- ...props
630
- ];
682
+ try {
683
+ const summaries = await listAccountSummaries(rt.params);
684
+ const account = summaries.find(
685
+ (s) => (s.account ?? s.name) === state.account
686
+ );
687
+ const props = (account?.propertySummaries ?? []).map((p) => {
688
+ const id = propertyIdFromResource(p.property);
689
+ if (!id) return null;
690
+ return {
691
+ value: id,
692
+ label: p.displayName ? `${p.displayName} (${id})` : id
693
+ };
694
+ }).filter((v) => v != null);
695
+ if (props.length === 0) return [];
696
+ return [
697
+ {
698
+ value: ALL_PROPERTIES,
699
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30D7\u30ED\u30D1\u30C6\u30A3" : "All properties"
700
+ },
701
+ ...props
702
+ ];
703
+ } catch {
704
+ return [];
705
+ }
631
706
  },
632
707
  applyAnswer: (state, answer) => ({ ...state, properties: answer })
708
+ },
709
+ {
710
+ slug: "manualPropertyId",
711
+ type: "text",
712
+ question: {
713
+ ja: "GA4 \u30D7\u30ED\u30D1\u30C6\u30A3 ID \u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: 123456789\uFF09\u3002GA4 \u7BA1\u7406\u753B\u9762 > \u30D7\u30ED\u30D1\u30C6\u30A3\u8A2D\u5B9A\u3067\u78BA\u8A8D\u3067\u304D\u307E\u3059\u3002",
714
+ en: "Enter your GA4 Property ID (e.g., 123456789). Found in GA4 Admin > Property Settings."
715
+ },
716
+ async fetchOptions(state) {
717
+ if (state.properties?.length) return [];
718
+ return [{ value: "_show", label: "" }];
719
+ },
720
+ applyAnswer: (state, answer) => ({
721
+ ...state,
722
+ manualPropertyId: answer[0]
723
+ })
633
724
  }
634
725
  ],
635
726
  async finalize(state, rt) {
636
- if (!state.account || !state.properties) {
637
- throw new Error("Google Analytics setup: incomplete state on finalize");
638
- }
639
- const summaries = await listAccountSummaries(rt.params);
640
- const account = summaries.find(
641
- (s) => (s.account ?? s.name) === state.account
642
- );
643
- const accountLabel = account?.displayName ?? state.account.replace(/^accounts\//, "");
644
- const targetPropertyIds = await resolveSetupSelection({
645
- selected: state.properties,
646
- allSentinel: ALL_PROPERTIES,
647
- fetchAll: async () => (account?.propertySummaries ?? []).map((p) => propertyIdFromResource(p.property)).filter((v) => v),
648
- limit: GOOGLE_ANALYTICS_SETUP_MAX_PROPERTIES
649
- });
650
- const sections = [
651
- "## Google Analytics",
652
- "",
653
- `### Account: ${accountLabel}`,
654
- ""
655
- ];
656
- if (targetPropertyIds.length === 0) {
657
- sections.push("_No properties selected._", "");
727
+ const sections = ["## Google Analytics", ""];
728
+ if (state.account && state.properties) {
729
+ let summaries = [];
730
+ try {
731
+ summaries = await listAccountSummaries(rt.params);
732
+ } catch {
733
+ }
734
+ const account = summaries.find(
735
+ (s) => (s.account ?? s.name) === state.account
736
+ );
737
+ const accountLabel = account?.displayName ?? state.account.replace(/^accounts\//, "");
738
+ const targetPropertyIds = await resolveSetupSelection({
739
+ selected: state.properties,
740
+ allSentinel: ALL_PROPERTIES,
741
+ fetchAll: async () => (account?.propertySummaries ?? []).map((p) => propertyIdFromResource(p.property)).filter((v) => v),
742
+ limit: GOOGLE_ANALYTICS_SETUP_MAX_PROPERTIES
743
+ });
744
+ sections.push(`### Account: ${accountLabel}`, "");
745
+ if (targetPropertyIds.length === 0) {
746
+ sections.push("_No properties selected._", "");
747
+ return sections.join("\n");
748
+ }
749
+ sections.push(
750
+ "| Property ID | Display Name | Time Zone | Currency | Industry |"
751
+ );
752
+ sections.push(
753
+ "|-------------|--------------|-----------|----------|----------|"
754
+ );
755
+ for (const pid of targetPropertyIds) {
756
+ const prop = await getProperty(rt.params, pid).catch(() => null);
757
+ const displayName = (prop?.displayName ?? "-").replace(/\|/g, "\\|");
758
+ const timeZone = prop?.timeZone ?? "-";
759
+ const currency = prop?.currencyCode ?? "-";
760
+ const industry = (prop?.industryCategory ?? "-").replace(
761
+ /\|/g,
762
+ "\\|"
763
+ );
764
+ sections.push(
765
+ `| ${pid} | ${displayName} | ${timeZone} | ${currency} | ${industry} |`
766
+ );
767
+ }
768
+ sections.push("");
769
+ const firstPropertyId = targetPropertyIds[0];
770
+ if (firstPropertyId) {
771
+ const { dimensions, metrics } = await getMetadata(
772
+ rt.params,
773
+ firstPropertyId
774
+ );
775
+ appendMetadataSection(sections, dimensions, metrics);
776
+ }
658
777
  return sections.join("\n");
659
778
  }
660
- sections.push("| Property ID | Display Name | Time Zone | Currency | Industry |");
661
- sections.push("|-------------|--------------|-----------|----------|----------|");
662
- for (const propertyId of targetPropertyIds) {
663
- const prop = await getProperty(rt.params, propertyId);
664
- const displayName = (prop?.displayName ?? "-").replace(/\|/g, "\\|");
665
- const timeZone = prop?.timeZone ?? "-";
666
- const currency = prop?.currencyCode ?? "-";
667
- const industry = (prop?.industryCategory ?? "-").replace(/\|/g, "\\|");
668
- sections.push(
669
- `| ${propertyId} | ${displayName} | ${timeZone} | ${currency} | ${industry} |`
779
+ const propertyId = state.manualPropertyId;
780
+ if (propertyId) {
781
+ sections.push(`### Property: ${propertyId}`, "");
782
+ const { dimensions, metrics } = await getMetadata(
783
+ rt.params,
784
+ propertyId
670
785
  );
786
+ appendMetadataSection(sections, dimensions, metrics);
787
+ return sections.join("\n");
671
788
  }
672
- sections.push("");
789
+ sections.push(
790
+ "_Could not list GA4 accounts. Please enable the Google Analytics Admin API in your GCP project. Property ID can be specified per request at runtime._",
791
+ ""
792
+ );
673
793
  return sections.join("\n");
674
794
  }
675
795
  };
@@ -681,8 +801,9 @@ var REQUEST_TIMEOUT_MS = 6e4;
681
801
  var inputSchema = z.object({
682
802
  toolUseIntent: z.string().optional().describe("Brief description of what you intend to accomplish with this tool call"),
683
803
  connectionId: z.string().describe("ID of the Google Analytics connection to use"),
804
+ propertyId: z.string().describe("GA4 property ID (e.g., '123456789')"),
684
805
  method: z.enum(["GET", "POST"]).describe("HTTP method"),
685
- path: z.string().describe("API path (e.g., 'properties/{propertyId}:runReport'). {propertyId} is automatically replaced."),
806
+ path: z.string().describe("API path (e.g., 'properties/{propertyId}:runReport'). {propertyId} is replaced with the propertyId parameter."),
686
807
  body: z.record(z.string(), z.unknown()).optional().describe("POST request body (JSON)")
687
808
  });
688
809
  var outputSchema = z.discriminatedUnion("success", [
@@ -700,10 +821,10 @@ var requestTool = new ConnectorTool({
700
821
  name: "request",
701
822
  description: `Send authenticated requests to the Google Analytics Data API.
702
823
  Authentication is handled automatically using a service account.
703
- {propertyId} in the path is automatically replaced with the connection's property-id.`,
824
+ {propertyId} in the path is automatically replaced with the propertyId parameter.`,
704
825
  inputSchema,
705
826
  outputSchema,
706
- async execute({ connectionId, method, path: path2, body }, connections) {
827
+ async execute({ connectionId, propertyId, method, path: path2, body }, connections) {
707
828
  const connection2 = connections.find((c) => c.id === connectionId);
708
829
  if (!connection2) {
709
830
  return { success: false, error: `Connection ${connectionId} not found` };
@@ -712,7 +833,6 @@ Authentication is handled automatically using a service account.
712
833
  try {
713
834
  const { GoogleAuth } = await import("google-auth-library");
714
835
  const keyJsonBase64 = parameters.serviceAccountKeyJsonBase64.getValue(connection2);
715
- const propertyId = parameters.propertyId.getValue(connection2);
716
836
  const credentials = JSON.parse(
717
837
  Buffer.from(keyJsonBase64, "base64").toString("utf-8")
718
838
  );
@@ -772,16 +892,16 @@ var googleAnalyticsConnector = new ConnectorPlugin({
772
892
  systemPrompt: {
773
893
  en: `### Tools
774
894
 
775
- - \`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.
895
+ - \`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. Requires a \`propertyId\` parameter. See the GA4 Data API Reference below for available endpoints and request bodies.
776
896
 
777
897
  ### Business Logic
778
898
 
779
899
  The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
780
900
 
781
901
  SDK methods (client created via \`connection(connectionId)\`):
782
- - \`client.runReport(request)\` \u2014 run a GA4 report
783
- - \`client.runRealtimeReport(request)\` \u2014 run a realtime report
784
- - \`client.getMetadata()\` \u2014 fetch available dimensions/metrics
902
+ - \`client.runReport(propertyId, request)\` \u2014 run a GA4 report
903
+ - \`client.runRealtimeReport(propertyId, request)\` \u2014 run a realtime report
904
+ - \`client.getMetadata(propertyId)\` \u2014 fetch available dimensions/metrics
785
905
  - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
786
906
 
787
907
  \`\`\`ts
@@ -791,12 +911,13 @@ import { connection } from "@squadbase/vite-server/connectors/google-analytics";
791
911
  const ga = connection("<connectionId>");
792
912
 
793
913
  export default async function handler(c: Context) {
794
- const { startDate = "7daysAgo", endDate = "today" } = await c.req.json<{
914
+ const { propertyId, startDate = "7daysAgo", endDate = "today" } = await c.req.json<{
915
+ propertyId: string;
795
916
  startDate?: string;
796
917
  endDate?: string;
797
918
  }>();
798
919
 
799
- const { rows } = await ga.runReport({
920
+ const { rows } = await ga.runReport(propertyId, {
800
921
  dateRanges: [{ startDate, endDate }],
801
922
  dimensions: [{ name: "date" }],
802
923
  metrics: [{ name: "activeUsers" }, { name: "sessions" }],
@@ -840,16 +961,16 @@ activeUsers, sessions, screenPageViews, bounceRate, averageSessionDuration, conv
840
961
  - Relative: \`"today"\`, \`"yesterday"\`, \`"7daysAgo"\`, \`"30daysAgo"\``,
841
962
  ja: `### \u30C4\u30FC\u30EB
842
963
 
843
- - \`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
964
+ - \`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\`propertyId\` \u30D1\u30E9\u30E1\u30FC\u30BF\u30FC\u304C\u5FC5\u8981\u3067\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
844
965
 
845
966
  ### Business Logic
846
967
 
847
968
  \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
848
969
 
849
970
  SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
850
- - \`client.runReport(request)\` \u2014 GA4\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
851
- - \`client.runRealtimeReport(request)\` \u2014 \u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
852
- - \`client.getMetadata()\` \u2014 \u5229\u7528\u53EF\u80FD\u306A\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3/\u30E1\u30C8\u30EA\u30AF\u30B9\u3092\u53D6\u5F97
971
+ - \`client.runReport(propertyId, request)\` \u2014 GA4\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
972
+ - \`client.runRealtimeReport(propertyId, request)\` \u2014 \u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C
973
+ - \`client.getMetadata(propertyId)\` \u2014 \u5229\u7528\u53EF\u80FD\u306A\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3/\u30E1\u30C8\u30EA\u30AF\u30B9\u3092\u53D6\u5F97
853
974
  - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
854
975
 
855
976
  \`\`\`ts
@@ -859,12 +980,13 @@ import { connection } from "@squadbase/vite-server/connectors/google-analytics";
859
980
  const ga = connection("<connectionId>");
860
981
 
861
982
  export default async function handler(c: Context) {
862
- const { startDate = "7daysAgo", endDate = "today" } = await c.req.json<{
983
+ const { propertyId, startDate = "7daysAgo", endDate = "today" } = await c.req.json<{
984
+ propertyId: string;
863
985
  startDate?: string;
864
986
  endDate?: string;
865
987
  }>();
866
988
 
867
- const { rows } = await ga.runReport({
989
+ const { rows } = await ga.runReport(propertyId, {
868
990
  dateRanges: [{ startDate, endDate }],
869
991
  dimensions: [{ name: "date" }],
870
992
  metrics: [{ name: "activeUsers" }, { name: "sessions" }],
@@ -918,12 +1040,12 @@ activeUsers, sessions, screenPageViews, bounceRate, averageSessionDuration, conv
918
1040
  };
919
1041
  }
920
1042
  try {
921
- const res = await adminFetch(params, "/accountSummaries?pageSize=1");
1043
+ const res = await dataFetch(params, `/metadata`);
922
1044
  if (!res.ok) {
923
1045
  const body = await res.text().catch(() => res.statusText);
924
1046
  return {
925
1047
  success: false,
926
- error: `google-analytics: accountSummaries failed (${res.status}): ${body}`
1048
+ error: `Google Analytics API failed: HTTP ${res.status} ${body}`
927
1049
  };
928
1050
  }
929
1051
  return { success: true };
@@ -290,19 +290,34 @@ async function runSetupFlow(flow, params, ctx, config) {
290
290
  };
291
291
  let state = flow.initialState();
292
292
  let answerIdx = 0;
293
+ const pendingParameterUpdates = [];
293
294
  for (const step of flow.steps) {
294
295
  const ans = ctx.answers[answerIdx];
295
296
  if (ans && ans.questionSlug === step.slug) {
296
297
  state = step.applyAnswer(state, ans.answer);
298
+ if (step.toParameterUpdates) {
299
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
300
+ }
297
301
  answerIdx += 1;
298
302
  continue;
299
303
  }
304
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
300
305
  if (step.type === "text") {
306
+ if (step.fetchOptions) {
307
+ const options2 = await step.fetchOptions(state, runtime);
308
+ if (options2.length === 0) {
309
+ continue;
310
+ }
311
+ }
301
312
  return {
302
313
  type: "nextQuestion",
303
314
  questionSlug: step.slug,
304
315
  question: step.question[ctx.language],
305
- questionType: "text"
316
+ questionType: "text",
317
+ allowFreeText: resolvedAllowFreeText,
318
+ ...pendingParameterUpdates.length > 0 && {
319
+ parameterUpdates: pendingParameterUpdates
320
+ }
306
321
  };
307
322
  }
308
323
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -314,11 +329,21 @@ async function runSetupFlow(flow, params, ctx, config) {
314
329
  questionSlug: step.slug,
315
330
  question: step.question[ctx.language],
316
331
  questionType: step.type,
317
- options
332
+ options,
333
+ allowFreeText: resolvedAllowFreeText,
334
+ ...pendingParameterUpdates.length > 0 && {
335
+ parameterUpdates: pendingParameterUpdates
336
+ }
318
337
  };
319
338
  }
320
339
  const dataInvestigationResult = await flow.finalize(state, runtime);
321
- return { type: "fulfilled", dataInvestigationResult };
340
+ return {
341
+ type: "fulfilled",
342
+ dataInvestigationResult,
343
+ ...pendingParameterUpdates.length > 0 && {
344
+ parameterUpdates: pendingParameterUpdates
345
+ }
346
+ };
322
347
  }
323
348
  async function resolveSetupSelection(params) {
324
349
  const { selected, allSentinel, fetchAll, limit } = params;
@@ -306,19 +306,34 @@ async function runSetupFlow(flow, params, ctx, config) {
306
306
  };
307
307
  let state = flow.initialState();
308
308
  let answerIdx = 0;
309
+ const pendingParameterUpdates = [];
309
310
  for (const step of flow.steps) {
310
311
  const ans = ctx.answers[answerIdx];
311
312
  if (ans && ans.questionSlug === step.slug) {
312
313
  state = step.applyAnswer(state, ans.answer);
314
+ if (step.toParameterUpdates) {
315
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
316
+ }
313
317
  answerIdx += 1;
314
318
  continue;
315
319
  }
320
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
316
321
  if (step.type === "text") {
322
+ if (step.fetchOptions) {
323
+ const options2 = await step.fetchOptions(state, runtime);
324
+ if (options2.length === 0) {
325
+ continue;
326
+ }
327
+ }
317
328
  return {
318
329
  type: "nextQuestion",
319
330
  questionSlug: step.slug,
320
331
  question: step.question[ctx.language],
321
- questionType: "text"
332
+ questionType: "text",
333
+ allowFreeText: resolvedAllowFreeText,
334
+ ...pendingParameterUpdates.length > 0 && {
335
+ parameterUpdates: pendingParameterUpdates
336
+ }
322
337
  };
323
338
  }
324
339
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -330,11 +345,21 @@ async function runSetupFlow(flow, params, ctx, config) {
330
345
  questionSlug: step.slug,
331
346
  question: step.question[ctx.language],
332
347
  questionType: step.type,
333
- options
348
+ options,
349
+ allowFreeText: resolvedAllowFreeText,
350
+ ...pendingParameterUpdates.length > 0 && {
351
+ parameterUpdates: pendingParameterUpdates
352
+ }
334
353
  };
335
354
  }
336
355
  const dataInvestigationResult = await flow.finalize(state, runtime);
337
- return { type: "fulfilled", dataInvestigationResult };
356
+ return {
357
+ type: "fulfilled",
358
+ dataInvestigationResult,
359
+ ...pendingParameterUpdates.length > 0 && {
360
+ parameterUpdates: pendingParameterUpdates
361
+ }
362
+ };
338
363
  }
339
364
  async function resolveSetupSelection(params) {
340
365
  const { selected, allSentinel, fetchAll, limit } = params;