@squadbase/vite-server 0.1.12-dev.a9ac647 → 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 +12374 -883
  2. package/dist/connectors/airtable-oauth.js +257 -46
  3. package/dist/connectors/airtable.js +294 -51
  4. package/dist/connectors/amplitude.js +297 -47
  5. package/dist/connectors/anthropic.js +135 -47
  6. package/dist/connectors/asana.js +302 -49
  7. package/dist/connectors/attio.js +277 -49
  8. package/dist/connectors/aws-billing.js +262 -46
  9. package/dist/connectors/azure-sql.js +396 -102
  10. package/dist/connectors/backlog-api-key.js +292 -47
  11. package/dist/connectors/clickup.js +313 -49
  12. package/dist/connectors/cosmosdb.js +280 -50
  13. package/dist/connectors/customerio.js +294 -47
  14. package/dist/connectors/dbt.js +315 -47
  15. package/dist/connectors/freshdesk.js +317 -53
  16. package/dist/connectors/freshsales.js +308 -52
  17. package/dist/connectors/freshservice.js +336 -53
  18. package/dist/connectors/gamma.js +302 -52
  19. package/dist/connectors/gemini.js +134 -47
  20. package/dist/connectors/github.js +361 -49
  21. package/dist/connectors/gmail-oauth.js +179 -7
  22. package/dist/connectors/gmail.js +325 -47
  23. package/dist/connectors/google-ads.js +263 -46
  24. package/dist/connectors/google-analytics-oauth.js +285 -46
  25. package/dist/connectors/google-analytics.js +387 -49
  26. package/dist/connectors/google-audit-log.js +413 -47
  27. package/dist/connectors/google-calendar-oauth.js +234 -46
  28. package/dist/connectors/google-calendar.js +334 -47
  29. package/dist/connectors/google-docs.js +195 -6
  30. package/dist/connectors/google-drive.js +237 -5
  31. package/dist/connectors/google-search-console-oauth.js +231 -46
  32. package/dist/connectors/google-sheets.js +247 -47
  33. package/dist/connectors/google-slides.js +180 -6
  34. package/dist/connectors/grafana.js +307 -49
  35. package/dist/connectors/hubspot-oauth.js +183 -5
  36. package/dist/connectors/hubspot.js +281 -49
  37. package/dist/connectors/influxdb.js +391 -51
  38. package/dist/connectors/intercom-oauth.js +185 -5
  39. package/dist/connectors/intercom.js +277 -49
  40. package/dist/connectors/jdbc.js +737 -110
  41. package/dist/connectors/jira-api-key.js +301 -47
  42. package/dist/connectors/kintone-api-token.js +256 -47
  43. package/dist/connectors/kintone.js +303 -47
  44. package/dist/connectors/linear.js +305 -49
  45. package/dist/connectors/linkedin-ads.js +243 -50
  46. package/dist/connectors/mailchimp-oauth.js +243 -46
  47. package/dist/connectors/mailchimp.js +295 -49
  48. package/dist/connectors/meta-ads-oauth.js +248 -48
  49. package/dist/connectors/meta-ads.js +260 -50
  50. package/dist/connectors/mixpanel.js +313 -47
  51. package/dist/connectors/monday.js +335 -49
  52. package/dist/connectors/mongodb.js +294 -57
  53. package/dist/connectors/notion-oauth.js +206 -5
  54. package/dist/connectors/notion.js +298 -51
  55. package/dist/connectors/openai.js +134 -47
  56. package/dist/connectors/oracle.js +414 -103
  57. package/dist/connectors/outlook-oauth.js +179 -5
  58. package/dist/connectors/powerbi-oauth.js +226 -5
  59. package/dist/connectors/salesforce.js +359 -49
  60. package/dist/connectors/semrush.js +289 -49
  61. package/dist/connectors/sentry.js +264 -50
  62. package/dist/connectors/shopify-oauth.js +162 -5
  63. package/dist/connectors/shopify.js +332 -47
  64. package/dist/connectors/sqlserver.js +390 -102
  65. package/dist/connectors/stripe-api-key.js +244 -46
  66. package/dist/connectors/stripe-oauth.js +177 -5
  67. package/dist/connectors/supabase.js +278 -48
  68. package/dist/connectors/tableau.js +389 -184
  69. package/dist/connectors/tiktok-ads.js +254 -48
  70. package/dist/connectors/wix-store.js +295 -49
  71. package/dist/connectors/zendesk-oauth.js +214 -5
  72. package/dist/connectors/zendesk.js +333 -47
  73. package/dist/index.d.ts +149 -1
  74. package/dist/index.js +13677 -1969
  75. package/dist/main.js +13627 -1927
  76. package/dist/vite-plugin.js +12391 -890
  77. package/package.json +1 -1
@@ -1,48 +1,60 @@
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/salesforce/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  instanceUrl: new ParameterDefinition({
48
60
  slug: "instance-url",
@@ -272,6 +284,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
272
284
  tools;
273
285
  query;
274
286
  checkConnection;
287
+ /**
288
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
289
+ * implement this expose a step-by-step exploration flow (database/schema/
290
+ * table/etc. discovery) that the dashboard backend drives via the
291
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
292
+ * `runSetupFlow` from `setup-flow.ts`.
293
+ */
294
+ setup;
295
+ /**
296
+ * Opt-out of the default "verify before save" behavior on connection
297
+ * creation. The backend invokes `checkConnection` synchronously while
298
+ * creating the connection and aborts (no row inserted) if it fails — this
299
+ * flag disables that for connectors where the check cannot succeed pre-save:
300
+ *
301
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
302
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
303
+ * connectionId, which doesn't exist until the row is saved
304
+ *
305
+ * Exceptions are the explicit position; new credential-input connectors get
306
+ * the default verify-on-create behavior without opt-in.
307
+ */
308
+ skipConnectionCheckOnCreate;
275
309
  constructor(config) {
276
310
  this.slug = config.slug;
277
311
  this.authType = config.authType;
@@ -288,6 +322,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
288
322
  this.tools = config.tools;
289
323
  this.query = config.query;
290
324
  this.checkConnection = config.checkConnection;
325
+ this.setup = config.setup;
326
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
291
327
  }
292
328
  get connectorKey() {
293
329
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -352,6 +388,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
352
388
  }
353
389
  };
354
390
 
391
+ // ../connectors/src/setup-flow.ts
392
+ async function runSetupFlow(flow, params, ctx, config) {
393
+ const runtime = {
394
+ params,
395
+ language: ctx.language,
396
+ config
397
+ };
398
+ let state = flow.initialState();
399
+ let answerIdx = 0;
400
+ for (const step of flow.steps) {
401
+ const ans = ctx.answers[answerIdx];
402
+ if (ans && ans.questionSlug === step.slug) {
403
+ state = step.applyAnswer(state, ans.answer);
404
+ answerIdx += 1;
405
+ continue;
406
+ }
407
+ if (step.type === "text") {
408
+ return {
409
+ type: "nextQuestion",
410
+ questionSlug: step.slug,
411
+ question: step.question[ctx.language],
412
+ questionType: "text"
413
+ };
414
+ }
415
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
416
+ if (options.length === 0) {
417
+ continue;
418
+ }
419
+ return {
420
+ type: "nextQuestion",
421
+ questionSlug: step.slug,
422
+ question: step.question[ctx.language],
423
+ questionType: step.type,
424
+ options
425
+ };
426
+ }
427
+ const dataInvestigationResult = await flow.finalize(state, runtime);
428
+ return { type: "fulfilled", dataInvestigationResult };
429
+ }
430
+ async function resolveSetupSelection(params) {
431
+ const { selected, allSentinel, fetchAll, limit } = params;
432
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
433
+ return resolved.slice(0, limit);
434
+ }
435
+
355
436
  // ../connectors/src/auth-types.ts
356
437
  var AUTH_TYPES = {
357
438
  OAUTH: "oauth",
@@ -374,6 +455,151 @@ var salesforceOnboarding = new ConnectorOnboarding({
374
455
  }
375
456
  });
376
457
 
458
+ // ../connectors/src/connectors/salesforce/utils.ts
459
+ var API_VERSION = "v60.0";
460
+ function normalizeInstanceUrl2(raw) {
461
+ const trimmed = raw.trim().replace(/\/+$/, "");
462
+ if (!/^https?:\/\//i.test(trimmed)) {
463
+ return `https://${trimmed}`;
464
+ }
465
+ return trimmed;
466
+ }
467
+ async function getAccessToken(params) {
468
+ const instanceUrlParam = params[parameters.instanceUrl.slug];
469
+ const clientId = params[parameters.clientId.slug];
470
+ const clientSecret = params[parameters.clientSecret.slug];
471
+ if (!instanceUrlParam || !clientId || !clientSecret) {
472
+ throw new Error(
473
+ "salesforce: missing required parameter(s) (instance-url, client-id, client-secret)"
474
+ );
475
+ }
476
+ const instanceUrl = normalizeInstanceUrl2(instanceUrlParam);
477
+ const tokenBody = new URLSearchParams({
478
+ grant_type: "client_credentials",
479
+ client_id: clientId,
480
+ client_secret: clientSecret
481
+ });
482
+ const tokenRes = await fetch(`${instanceUrl}/services/oauth2/token`, {
483
+ method: "POST",
484
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
485
+ body: tokenBody.toString()
486
+ });
487
+ if (!tokenRes.ok) {
488
+ const errText = await tokenRes.text().catch(() => tokenRes.statusText);
489
+ throw new Error(
490
+ `salesforce: token request failed (${tokenRes.status}): ${errText}`
491
+ );
492
+ }
493
+ const tokenJson = await tokenRes.json();
494
+ if (!tokenJson.access_token) {
495
+ throw new Error("salesforce: access_token missing in token response");
496
+ }
497
+ return {
498
+ accessToken: tokenJson.access_token,
499
+ instanceUrl: tokenJson.instance_url ?? instanceUrl
500
+ };
501
+ }
502
+ async function apiFetch(params, path2, init) {
503
+ const token = await getAccessToken(params);
504
+ const url = `${token.instanceUrl}${path2.startsWith("/") ? "" : "/"}${path2}`;
505
+ const headers = new Headers(init?.headers);
506
+ headers.set("Authorization", `Bearer ${token.accessToken}`);
507
+ headers.set("Accept", "application/json");
508
+ return fetch(url, { ...init, headers });
509
+ }
510
+ var SALESFORCE_API_VERSION = API_VERSION;
511
+
512
+ // ../connectors/src/connectors/salesforce/setup-flow.ts
513
+ var SALESFORCE_SETUP_MAX_OBJECTS = 10;
514
+ var SALESFORCE_SETUP_MAX_FIELDS = 50;
515
+ async function listSObjects(params) {
516
+ const res = await apiFetch(
517
+ params,
518
+ `/services/data/${SALESFORCE_API_VERSION}/sobjects/`
519
+ );
520
+ if (!res.ok) {
521
+ const body = await res.text().catch(() => res.statusText);
522
+ throw new Error(
523
+ `salesforce: listSObjects failed (${res.status}): ${body}`
524
+ );
525
+ }
526
+ const data = await res.json();
527
+ return data.sobjects ?? [];
528
+ }
529
+ async function describeSObject(params, name) {
530
+ const res = await apiFetch(
531
+ params,
532
+ `/services/data/${SALESFORCE_API_VERSION}/sobjects/${name}/describe`
533
+ );
534
+ if (!res.ok) {
535
+ const body = await res.text().catch(() => res.statusText);
536
+ throw new Error(
537
+ `salesforce: describeSObject(${name}) failed (${res.status}): ${body}`
538
+ );
539
+ }
540
+ const data = await res.json();
541
+ return data.fields ?? [];
542
+ }
543
+ var salesforceSetupFlow = {
544
+ initialState: () => ({}),
545
+ steps: [
546
+ {
547
+ slug: "objects",
548
+ type: "multiSelect",
549
+ question: {
550
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3067\u6982\u89B3\u3057\u305F\u3044Salesforce\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
551
+ en: "Select the Salesforce sObjects to include in setup (multi-select allowed)"
552
+ },
553
+ async fetchOptions(_state, rt) {
554
+ const all = await listSObjects(rt.params);
555
+ return all.filter((s) => s.queryable !== false && s.name).map((s) => ({
556
+ value: String(s.name),
557
+ label: s.label ? `${s.label} (${s.name})` : String(s.name)
558
+ }));
559
+ },
560
+ applyAnswer: (state, answer) => ({ ...state, objects: answer })
561
+ }
562
+ ],
563
+ async finalize(state, rt) {
564
+ if (!state.objects) {
565
+ throw new Error("Salesforce setup: incomplete state on finalize");
566
+ }
567
+ const targetObjects = await resolveSetupSelection({
568
+ selected: state.objects,
569
+ allSentinel: "__ALL__",
570
+ fetchAll: async () => {
571
+ const all = await listSObjects(rt.params);
572
+ return all.filter((s) => s.queryable !== false && s.name).map((s) => String(s.name));
573
+ },
574
+ limit: SALESFORCE_SETUP_MAX_OBJECTS
575
+ });
576
+ const sections = ["## Salesforce", ""];
577
+ for (const objectName of targetObjects) {
578
+ sections.push(`### sObject: ${objectName}`, "");
579
+ const fields = await describeSObject(rt.params, objectName);
580
+ const limited = fields.slice(0, SALESFORCE_SETUP_MAX_FIELDS);
581
+ sections.push("| Field | Type | Label | Custom |");
582
+ sections.push("|-------|------|-------|--------|");
583
+ for (const f of limited) {
584
+ const name = (f.name ?? "").replace(/\|/g, "\\|");
585
+ const type = (f.type ?? "").replace(/\|/g, "\\|");
586
+ const label = (f.label ?? "").replace(/\|/g, "\\|");
587
+ sections.push(
588
+ `| ${name} | ${type} | ${label || "-"} | ${f.custom ? "yes" : "no"} |`
589
+ );
590
+ }
591
+ if (fields.length > SALESFORCE_SETUP_MAX_FIELDS) {
592
+ sections.push(
593
+ "",
594
+ `_Showing first ${SALESFORCE_SETUP_MAX_FIELDS} of ${fields.length} fields._`
595
+ );
596
+ }
597
+ sections.push("");
598
+ }
599
+ return sections.join("\n");
600
+ }
601
+ };
602
+
377
603
  // ../connectors/src/connectors/salesforce/tools/request.ts
378
604
  import { z } from "zod";
379
605
  var REQUEST_TIMEOUT_MS = 6e4;
@@ -401,7 +627,7 @@ var outputSchema = z.discriminatedUnion("success", [
401
627
  error: z.string()
402
628
  })
403
629
  ]);
404
- function normalizeInstanceUrl2(raw) {
630
+ function normalizeInstanceUrl3(raw) {
405
631
  const trimmed = raw.trim().replace(/\/+$/, "");
406
632
  if (!/^https?:\/\//i.test(trimmed)) {
407
633
  return `https://${trimmed}`;
@@ -431,7 +657,7 @@ Prefer SOQL via the /query endpoint for filtered, joined, or aggregated reads ra
431
657
  const instanceUrlParam = parameters.instanceUrl.getValue(connection2);
432
658
  const clientId = parameters.clientId.getValue(connection2);
433
659
  const clientSecret = parameters.clientSecret.getValue(connection2);
434
- const instanceUrl = normalizeInstanceUrl2(instanceUrlParam);
660
+ const instanceUrl = normalizeInstanceUrl3(instanceUrlParam);
435
661
  const tokenBody = new URLSearchParams({
436
662
  grant_type: "client_credentials",
437
663
  client_id: clientId,
@@ -660,7 +886,71 @@ export default async function handler(c: Context) {
660
886
  - \u96C6\u8A08: \`GROUP BY\`, \`HAVING\`, \`COUNT()\`, \`SUM()\`, \`AVG()\`, \`MIN()\`, \`MAX()\`
661
887
  - \u89AA\u2192\u5B50\u30B5\u30D6\u30AF\u30A8\u30EA: \`SELECT Id, Name, (SELECT Id, Email FROM Contacts) FROM Account\``
662
888
  },
663
- tools
889
+ tools,
890
+ setup: (params, ctx, config) => runSetupFlow(salesforceSetupFlow, params, ctx, config),
891
+ async checkConnection(params, _config) {
892
+ const instanceUrlParam = params[parameters.instanceUrl.slug];
893
+ const clientId = params[parameters.clientId.slug];
894
+ const clientSecret = params[parameters.clientSecret.slug];
895
+ if (!instanceUrlParam || !clientId || !clientSecret) {
896
+ return {
897
+ success: false,
898
+ error: `Missing required parameter(s): ${parameters.instanceUrl.slug}, ${parameters.clientId.slug}, ${parameters.clientSecret.slug}`
899
+ };
900
+ }
901
+ const trimmed = instanceUrlParam.trim().replace(/\/+$/, "");
902
+ const instanceUrl = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
903
+ try {
904
+ const tokenBody = new URLSearchParams({
905
+ grant_type: "client_credentials",
906
+ client_id: clientId,
907
+ client_secret: clientSecret
908
+ });
909
+ const tokenRes = await fetch(`${instanceUrl}/services/oauth2/token`, {
910
+ method: "POST",
911
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
912
+ body: tokenBody.toString()
913
+ });
914
+ if (!tokenRes.ok) {
915
+ const errText = await tokenRes.text().catch(() => tokenRes.statusText);
916
+ return {
917
+ success: false,
918
+ error: `Salesforce token request failed: HTTP ${tokenRes.status} ${errText}`
919
+ };
920
+ }
921
+ const tokenJson = await tokenRes.json();
922
+ if (!tokenJson.access_token) {
923
+ return {
924
+ success: false,
925
+ error: "Salesforce: access_token missing in token response"
926
+ };
927
+ }
928
+ const resolvedInstanceUrl = tokenJson.instance_url ?? instanceUrl;
929
+ const res = await fetch(
930
+ `${resolvedInstanceUrl}/services/data/v60.0/limits`,
931
+ {
932
+ method: "GET",
933
+ headers: {
934
+ Authorization: `Bearer ${tokenJson.access_token}`,
935
+ Accept: "application/json"
936
+ }
937
+ }
938
+ );
939
+ if (!res.ok) {
940
+ const errText = await res.text().catch(() => res.statusText);
941
+ return {
942
+ success: false,
943
+ error: `Salesforce API failed: HTTP ${res.status} ${errText}`
944
+ };
945
+ }
946
+ return { success: true };
947
+ } catch (error) {
948
+ return {
949
+ success: false,
950
+ error: error instanceof Error ? error.message : String(error)
951
+ };
952
+ }
953
+ }
664
954
  });
665
955
 
666
956
  // src/connectors/create-connector-sdk.ts
@@ -689,6 +979,7 @@ function resolveEnvVarOptional(entry, key) {
689
979
  import { getContext } from "hono/context-storage";
690
980
  import { getCookie } from "hono/cookie";
691
981
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
982
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
692
983
  function normalizeHeaders(input) {
693
984
  const out = {};
694
985
  if (!input) return out;
@@ -697,6 +988,11 @@ function normalizeHeaders(input) {
697
988
  });
698
989
  return out;
699
990
  }
991
+ function extractInputUrl(input) {
992
+ if (typeof input === "string") return input;
993
+ if (input instanceof URL) return input.href;
994
+ return input.url;
995
+ }
700
996
  function createSandboxProxyFetch(connectionId) {
701
997
  return async (input, init) => {
702
998
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -706,10 +1002,17 @@ function createSandboxProxyFetch(connectionId) {
706
1002
  "Connection proxy is not configured. Please check your deployment settings."
707
1003
  );
708
1004
  }
709
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1005
+ const originalUrl = extractInputUrl(input);
1006
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
1007
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1008
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
1009
+ return fetch(sessionUrl, {
1010
+ method: "POST",
1011
+ headers: { Authorization: `Bearer ${token}` }
1012
+ });
1013
+ }
710
1014
  const originalMethod = init?.method ?? "GET";
711
1015
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
712
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
713
1016
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
714
1017
  return fetch(proxyUrl, {
715
1018
  method: "POST",
@@ -735,10 +1038,9 @@ function createDeployedAppProxyFetch(connectionId) {
735
1038
  }
736
1039
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
737
1040
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
1041
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
738
1042
  return async (input, init) => {
739
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
740
- const originalMethod = init?.method ?? "GET";
741
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
1043
+ const originalUrl = extractInputUrl(input);
742
1044
  const c = getContext();
743
1045
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
744
1046
  if (!appSession) {
@@ -746,6 +1048,14 @@ function createDeployedAppProxyFetch(connectionId) {
746
1048
  "No authentication method available for connection proxy."
747
1049
  );
748
1050
  }
1051
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1052
+ return fetch(sessionUrl, {
1053
+ method: "POST",
1054
+ headers: { Authorization: `Bearer ${appSession}` }
1055
+ });
1056
+ }
1057
+ const originalMethod = init?.method ?? "GET";
1058
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
749
1059
  return fetch(proxyUrl, {
750
1060
  method: "POST",
751
1061
  headers: {