@squadbase/vite-server 0.1.12-dev.93b8799 → 0.1.17-dev.24af54e

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 (77) hide show
  1. package/dist/cli/index.js +12128 -934
  2. package/dist/connectors/airtable-oauth.js +248 -46
  3. package/dist/connectors/airtable.js +285 -51
  4. package/dist/connectors/amplitude.js +288 -47
  5. package/dist/connectors/anthropic.js +126 -47
  6. package/dist/connectors/asana.js +293 -49
  7. package/dist/connectors/attio.js +268 -49
  8. package/dist/connectors/aws-billing.js +253 -46
  9. package/dist/connectors/azure-sql.js +387 -102
  10. package/dist/connectors/backlog-api-key.js +283 -47
  11. package/dist/connectors/clickup.js +304 -49
  12. package/dist/connectors/cosmosdb.js +271 -50
  13. package/dist/connectors/customerio.js +285 -47
  14. package/dist/connectors/dbt.js +306 -47
  15. package/dist/connectors/freshdesk.js +308 -53
  16. package/dist/connectors/freshsales.js +299 -52
  17. package/dist/connectors/freshservice.js +327 -53
  18. package/dist/connectors/gamma.js +293 -52
  19. package/dist/connectors/gemini.js +125 -47
  20. package/dist/connectors/github.js +352 -49
  21. package/dist/connectors/gmail-oauth.js +170 -7
  22. package/dist/connectors/gmail.js +316 -47
  23. package/dist/connectors/google-ads.js +254 -46
  24. package/dist/connectors/google-analytics-oauth.js +276 -46
  25. package/dist/connectors/google-analytics.js +378 -49
  26. package/dist/connectors/google-audit-log.js +404 -47
  27. package/dist/connectors/google-calendar-oauth.js +225 -46
  28. package/dist/connectors/google-calendar.js +325 -47
  29. package/dist/connectors/google-docs.js +186 -6
  30. package/dist/connectors/google-drive.js +228 -5
  31. package/dist/connectors/google-search-console-oauth.js +222 -46
  32. package/dist/connectors/google-sheets.js +238 -47
  33. package/dist/connectors/google-slides.js +171 -6
  34. package/dist/connectors/grafana.js +298 -49
  35. package/dist/connectors/hubspot-oauth.js +174 -5
  36. package/dist/connectors/hubspot.js +272 -49
  37. package/dist/connectors/influxdb.js +382 -51
  38. package/dist/connectors/intercom-oauth.js +176 -5
  39. package/dist/connectors/intercom.js +268 -49
  40. package/dist/connectors/jdbc.js +728 -110
  41. package/dist/connectors/jira-api-key.js +292 -47
  42. package/dist/connectors/kintone-api-token.js +247 -47
  43. package/dist/connectors/kintone.js +294 -47
  44. package/dist/connectors/linear.js +296 -49
  45. package/dist/connectors/linkedin-ads.js +234 -50
  46. package/dist/connectors/mailchimp-oauth.js +234 -46
  47. package/dist/connectors/mailchimp.js +286 -49
  48. package/dist/connectors/meta-ads-oauth.js +239 -48
  49. package/dist/connectors/meta-ads.js +251 -50
  50. package/dist/connectors/mixpanel.js +304 -47
  51. package/dist/connectors/monday.js +326 -49
  52. package/dist/connectors/mongodb.js +285 -57
  53. package/dist/connectors/notion-oauth.js +197 -5
  54. package/dist/connectors/notion.js +289 -51
  55. package/dist/connectors/openai.js +125 -47
  56. package/dist/connectors/oracle.js +405 -103
  57. package/dist/connectors/outlook-oauth.js +170 -5
  58. package/dist/connectors/powerbi-oauth.js +217 -5
  59. package/dist/connectors/salesforce.js +350 -49
  60. package/dist/connectors/semrush.js +280 -49
  61. package/dist/connectors/sentry.js +255 -50
  62. package/dist/connectors/shopify-oauth.js +153 -5
  63. package/dist/connectors/shopify.js +323 -47
  64. package/dist/connectors/sqlserver.js +381 -102
  65. package/dist/connectors/stripe-api-key.js +235 -46
  66. package/dist/connectors/stripe-oauth.js +168 -5
  67. package/dist/connectors/supabase.js +269 -48
  68. package/dist/connectors/tableau.js +337 -206
  69. package/dist/connectors/tiktok-ads.js +245 -48
  70. package/dist/connectors/wix-store.js +286 -49
  71. package/dist/connectors/zendesk-oauth.js +205 -5
  72. package/dist/connectors/zendesk.js +324 -47
  73. package/dist/index.d.ts +149 -1
  74. package/dist/index.js +18297 -6886
  75. package/dist/main.js +12785 -1382
  76. package/dist/vite-plugin.js +12140 -936
  77. package/package.json +1 -1
@@ -1,51 +1,63 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __esm = (fn, res) => function __init() {
3
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ };
5
+
1
6
  // ../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;
7
+ var ParameterDefinition;
8
+ var init_parameter_definition = __esm({
9
+ "../connectors/src/parameter-definition.ts"() {
10
+ "use strict";
11
+ ParameterDefinition = class {
12
+ slug;
13
+ name;
14
+ description;
15
+ envVarBaseKey;
16
+ type;
17
+ secret;
18
+ required;
19
+ constructor(config) {
20
+ this.slug = config.slug;
21
+ this.name = config.name;
22
+ this.description = config.description;
23
+ this.envVarBaseKey = config.envVarBaseKey;
24
+ this.type = config.type;
25
+ this.secret = config.secret;
26
+ this.required = config.required;
27
+ }
28
+ /**
29
+ * Get the parameter value from a ConnectorConnectionObject.
30
+ */
31
+ getValue(connection2) {
32
+ const param = connection2.parameters.find(
33
+ (p) => p.parameterSlug === this.slug
34
+ );
35
+ if (!param || param.value == null) {
36
+ throw new Error(
37
+ `Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
38
+ );
39
+ }
40
+ return param.value;
41
+ }
42
+ /**
43
+ * Try to get the parameter value. Returns undefined if not found (for optional params).
44
+ */
45
+ tryGetValue(connection2) {
46
+ const param = connection2.parameters.find(
47
+ (p) => p.parameterSlug === this.slug
48
+ );
49
+ if (!param || param.value == null) return void 0;
50
+ return param.value;
51
+ }
52
+ };
42
53
  }
43
- };
54
+ });
44
55
 
45
56
  // ../connectors/src/connectors/google-analytics/sdk/index.ts
46
57
  import * as crypto from "crypto";
47
58
 
48
59
  // ../connectors/src/connectors/google-analytics/parameters.ts
60
+ init_parameter_definition();
49
61
  var parameters = {
50
62
  serviceAccountKeyJsonBase64: new ParameterDefinition({
51
63
  slug: "service-account-key-json-base64",
@@ -125,7 +137,7 @@ function createClient(params) {
125
137
  }
126
138
  let cachedToken = null;
127
139
  let tokenExpiresAt = 0;
128
- async function getAccessToken() {
140
+ async function getAccessToken2() {
129
141
  const nowSec = Math.floor(Date.now() / 1e3);
130
142
  if (cachedToken && nowSec < tokenExpiresAt - 60) {
131
143
  return cachedToken;
@@ -156,7 +168,7 @@ function createClient(params) {
156
168
  }
157
169
  return {
158
170
  async request(path2, init) {
159
- const accessToken = await getAccessToken();
171
+ const accessToken = await getAccessToken2();
160
172
  const resolvedPath = path2.replace(/\{propertyId\}/g, propertyId);
161
173
  const url = `${BASE_URL.replace(/\/+$/, "")}/${resolvedPath.replace(/^\/+/, "")}`;
162
174
  const headers = new Headers(init?.headers);
@@ -288,6 +300,20 @@ var ConnectorPlugin = class _ConnectorPlugin {
288
300
  * `runSetupFlow` from `setup-flow.ts`.
289
301
  */
290
302
  setup;
303
+ /**
304
+ * Opt-out of the default "verify before save" behavior on connection
305
+ * creation. The backend invokes `checkConnection` synchronously while
306
+ * creating the connection and aborts (no row inserted) if it fails — this
307
+ * flag disables that for connectors where the check cannot succeed pre-save:
308
+ *
309
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
310
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
311
+ * connectionId, which doesn't exist until the row is saved
312
+ *
313
+ * Exceptions are the explicit position; new credential-input connectors get
314
+ * the default verify-on-create behavior without opt-in.
315
+ */
316
+ skipConnectionCheckOnCreate;
291
317
  constructor(config) {
292
318
  this.slug = config.slug;
293
319
  this.authType = config.authType;
@@ -305,6 +331,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
305
331
  this.query = config.query;
306
332
  this.checkConnection = config.checkConnection;
307
333
  this.setup = config.setup;
334
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
308
335
  }
309
336
  get connectorKey() {
310
337
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -369,6 +396,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
369
396
  }
370
397
  };
371
398
 
399
+ // ../connectors/src/setup-flow.ts
400
+ async function runSetupFlow(flow, params, ctx, config) {
401
+ const runtime = {
402
+ params,
403
+ language: ctx.language,
404
+ config
405
+ };
406
+ let state = flow.initialState();
407
+ let answerIdx = 0;
408
+ for (const step of flow.steps) {
409
+ const ans = ctx.answers[answerIdx];
410
+ if (ans && ans.questionSlug === step.slug) {
411
+ state = step.applyAnswer(state, ans.answer);
412
+ answerIdx += 1;
413
+ continue;
414
+ }
415
+ if (step.type === "text") {
416
+ return {
417
+ type: "nextQuestion",
418
+ questionSlug: step.slug,
419
+ question: step.question[ctx.language],
420
+ questionType: "text"
421
+ };
422
+ }
423
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
424
+ if (options.length === 0) {
425
+ continue;
426
+ }
427
+ return {
428
+ type: "nextQuestion",
429
+ questionSlug: step.slug,
430
+ question: step.question[ctx.language],
431
+ questionType: step.type,
432
+ options
433
+ };
434
+ }
435
+ const dataInvestigationResult = await flow.finalize(state, runtime);
436
+ return { type: "fulfilled", dataInvestigationResult };
437
+ }
438
+ async function resolveSetupSelection(params) {
439
+ const { selected, allSentinel, fetchAll, limit } = params;
440
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
441
+ return resolved.slice(0, limit);
442
+ }
443
+
372
444
  // ../connectors/src/auth-types.ts
373
445
  var AUTH_TYPES = {
374
446
  OAUTH: "oauth",
@@ -389,6 +461,219 @@ var googleAnalyticsOnboarding = new ConnectorOnboarding({
389
461
  }
390
462
  });
391
463
 
464
+ // ../connectors/src/connectors/google-analytics/utils.ts
465
+ import * as crypto2 from "crypto";
466
+ var TOKEN_URL2 = "https://oauth2.googleapis.com/token";
467
+ var ADMIN_BASE_URL = "https://analyticsadmin.googleapis.com/v1beta";
468
+ var SCOPE2 = "https://www.googleapis.com/auth/analytics.readonly";
469
+ function base64url2(input) {
470
+ const buf = typeof input === "string" ? Buffer.from(input) : input;
471
+ return buf.toString("base64url");
472
+ }
473
+ function buildJwt2(clientEmail, privateKey, nowSec) {
474
+ const header = base64url2(JSON.stringify({ alg: "RS256", typ: "JWT" }));
475
+ const payload = base64url2(
476
+ JSON.stringify({
477
+ iss: clientEmail,
478
+ scope: SCOPE2,
479
+ aud: TOKEN_URL2,
480
+ iat: nowSec,
481
+ exp: nowSec + 3600
482
+ })
483
+ );
484
+ const signingInput = `${header}.${payload}`;
485
+ const sign = crypto2.createSign("RSA-SHA256");
486
+ sign.update(signingInput);
487
+ sign.end();
488
+ const signature = base64url2(sign.sign(privateKey));
489
+ return `${signingInput}.${signature}`;
490
+ }
491
+ function decodeServiceAccount(serviceAccountKeyJsonBase64) {
492
+ let serviceAccountKey;
493
+ try {
494
+ const decoded = Buffer.from(
495
+ serviceAccountKeyJsonBase64,
496
+ "base64"
497
+ ).toString("utf-8");
498
+ serviceAccountKey = JSON.parse(decoded);
499
+ } catch {
500
+ throw new Error(
501
+ "google-analytics: failed to decode service account key JSON from base64"
502
+ );
503
+ }
504
+ if (!serviceAccountKey.client_email || !serviceAccountKey.private_key) {
505
+ throw new Error(
506
+ "google-analytics: service account key JSON must contain client_email and private_key"
507
+ );
508
+ }
509
+ return serviceAccountKey;
510
+ }
511
+ async function getAccessToken(serviceAccountKey) {
512
+ const nowSec = Math.floor(Date.now() / 1e3);
513
+ const jwt = buildJwt2(
514
+ serviceAccountKey.client_email,
515
+ serviceAccountKey.private_key,
516
+ nowSec
517
+ );
518
+ const response = await fetch(TOKEN_URL2, {
519
+ method: "POST",
520
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
521
+ body: new URLSearchParams({
522
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
523
+ assertion: jwt
524
+ })
525
+ });
526
+ if (!response.ok) {
527
+ const text = await response.text();
528
+ throw new Error(
529
+ `google-analytics: token exchange failed (${response.status}): ${text}`
530
+ );
531
+ }
532
+ const data = await response.json();
533
+ return data.access_token;
534
+ }
535
+ async function adminFetch(params, path2, init) {
536
+ const keyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
537
+ if (!keyJsonBase64) {
538
+ throw new Error(
539
+ "google-analytics: missing required parameter: service-account-key-json-base64"
540
+ );
541
+ }
542
+ const serviceAccountKey = decodeServiceAccount(keyJsonBase64);
543
+ const accessToken = await getAccessToken(serviceAccountKey);
544
+ const url = `${ADMIN_BASE_URL}${path2.startsWith("/") ? "" : "/"}${path2}`;
545
+ const headers = new Headers(init?.headers);
546
+ headers.set("Authorization", `Bearer ${accessToken}`);
547
+ return fetch(url, { ...init, headers });
548
+ }
549
+
550
+ // ../connectors/src/connectors/google-analytics/setup-flow.ts
551
+ var ALL_PROPERTIES = "__ALL_PROPERTIES__";
552
+ var GOOGLE_ANALYTICS_SETUP_MAX_PROPERTIES = 20;
553
+ async function listAccountSummaries(params) {
554
+ const summaries = [];
555
+ let pageToken;
556
+ do {
557
+ const path2 = pageToken ? `/accountSummaries?pageToken=${encodeURIComponent(pageToken)}` : `/accountSummaries`;
558
+ const res = await adminFetch(params, path2);
559
+ if (!res.ok) {
560
+ const body = await res.text().catch(() => res.statusText);
561
+ throw new Error(
562
+ `google-analytics: accountSummaries failed (${res.status}): ${body}`
563
+ );
564
+ }
565
+ const data = await res.json();
566
+ summaries.push(...data.accountSummaries ?? []);
567
+ pageToken = data.nextPageToken;
568
+ } while (pageToken);
569
+ return summaries;
570
+ }
571
+ function propertyIdFromResource(resource) {
572
+ return (resource ?? "").replace(/^properties\//, "");
573
+ }
574
+ async function getProperty(params, propertyId) {
575
+ const res = await adminFetch(params, `/properties/${propertyId}`);
576
+ if (!res.ok) return null;
577
+ return await res.json();
578
+ }
579
+ var googleAnalyticsSetupFlow = {
580
+ initialState: () => ({}),
581
+ steps: [
582
+ {
583
+ slug: "account",
584
+ type: "select",
585
+ question: {
586
+ ja: "Google Analytics \u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
587
+ en: "Select a Google Analytics account"
588
+ },
589
+ 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);
599
+ },
600
+ applyAnswer: (state, answer) => ({ ...state, account: answer[0] })
601
+ },
602
+ {
603
+ slug: "properties",
604
+ type: "multiSelect",
605
+ question: {
606
+ ja: "\u5BFE\u8C61\u306E GA4 \u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
607
+ en: "Select target GA4 properties (multi-select allowed)"
608
+ },
609
+ async fetchOptions(state, rt) {
610
+ 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
+ ];
631
+ },
632
+ applyAnswer: (state, answer) => ({ ...state, properties: answer })
633
+ }
634
+ ],
635
+ 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._", "");
658
+ return sections.join("\n");
659
+ }
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} |`
670
+ );
671
+ }
672
+ sections.push("");
673
+ return sections.join("\n");
674
+ }
675
+ };
676
+
392
677
  // ../connectors/src/connectors/google-analytics/tools/request.ts
393
678
  import { z } from "zod";
394
679
  var BASE_URL2 = "https://analyticsdata.googleapis.com/v1beta/";
@@ -622,7 +907,31 @@ activeUsers, sessions, screenPageViews, bounceRate, averageSessionDuration, conv
622
907
  - \u7D76\u5BFE\u5024: \`"2024-01-01"\`
623
908
  - \u76F8\u5BFE\u5024: \`"today"\`, \`"yesterday"\`, \`"7daysAgo"\`, \`"30daysAgo"\``
624
909
  },
625
- tools
910
+ tools,
911
+ setup: (params, ctx, config) => runSetupFlow(googleAnalyticsSetupFlow, params, ctx, config),
912
+ async checkConnection(params, _config) {
913
+ const keyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
914
+ if (!keyJsonBase64) {
915
+ return {
916
+ success: false,
917
+ error: "google-analytics: missing service account key"
918
+ };
919
+ }
920
+ try {
921
+ const res = await adminFetch(params, "/accountSummaries?pageSize=1");
922
+ if (!res.ok) {
923
+ const body = await res.text().catch(() => res.statusText);
924
+ return {
925
+ success: false,
926
+ error: `google-analytics: accountSummaries failed (${res.status}): ${body}`
927
+ };
928
+ }
929
+ return { success: true };
930
+ } catch (err) {
931
+ const msg = err instanceof Error ? err.message : String(err);
932
+ return { success: false, error: msg };
933
+ }
934
+ }
626
935
  });
627
936
 
628
937
  // src/connectors/create-connector-sdk.ts
@@ -651,6 +960,7 @@ function resolveEnvVarOptional(entry, key) {
651
960
  import { getContext } from "hono/context-storage";
652
961
  import { getCookie } from "hono/cookie";
653
962
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
963
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
654
964
  function normalizeHeaders(input) {
655
965
  const out = {};
656
966
  if (!input) return out;
@@ -659,6 +969,11 @@ function normalizeHeaders(input) {
659
969
  });
660
970
  return out;
661
971
  }
972
+ function extractInputUrl(input) {
973
+ if (typeof input === "string") return input;
974
+ if (input instanceof URL) return input.href;
975
+ return input.url;
976
+ }
662
977
  function createSandboxProxyFetch(connectionId) {
663
978
  return async (input, init) => {
664
979
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -668,10 +983,17 @@ function createSandboxProxyFetch(connectionId) {
668
983
  "Connection proxy is not configured. Please check your deployment settings."
669
984
  );
670
985
  }
671
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
986
+ const originalUrl = extractInputUrl(input);
987
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
988
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
989
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
990
+ return fetch(sessionUrl, {
991
+ method: "POST",
992
+ headers: { Authorization: `Bearer ${token}` }
993
+ });
994
+ }
672
995
  const originalMethod = init?.method ?? "GET";
673
996
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
674
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
675
997
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
676
998
  return fetch(proxyUrl, {
677
999
  method: "POST",
@@ -697,10 +1019,9 @@ function createDeployedAppProxyFetch(connectionId) {
697
1019
  }
698
1020
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
699
1021
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
1022
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
700
1023
  return async (input, init) => {
701
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
702
- const originalMethod = init?.method ?? "GET";
703
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
1024
+ const originalUrl = extractInputUrl(input);
704
1025
  const c = getContext();
705
1026
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
706
1027
  if (!appSession) {
@@ -708,6 +1029,14 @@ function createDeployedAppProxyFetch(connectionId) {
708
1029
  "No authentication method available for connection proxy."
709
1030
  );
710
1031
  }
1032
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1033
+ return fetch(sessionUrl, {
1034
+ method: "POST",
1035
+ headers: { Authorization: `Bearer ${appSession}` }
1036
+ });
1037
+ }
1038
+ const originalMethod = init?.method ?? "GET";
1039
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
711
1040
  return fetch(proxyUrl, {
712
1041
  method: "POST",
713
1042
  headers: {