@squadbase/vite-server 0.1.12-dev.a9ac647 → 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 (77) hide show
  1. package/dist/cli/index.js +14375 -1652
  2. package/dist/connectors/airtable-oauth.js +282 -46
  3. package/dist/connectors/airtable.js +319 -51
  4. package/dist/connectors/amplitude.js +322 -47
  5. package/dist/connectors/anthropic.js +135 -47
  6. package/dist/connectors/asana.js +327 -49
  7. package/dist/connectors/attio.js +302 -49
  8. package/dist/connectors/aws-billing.js +287 -46
  9. package/dist/connectors/azure-sql.js +421 -102
  10. package/dist/connectors/backlog-api-key.js +317 -47
  11. package/dist/connectors/clickup.js +338 -49
  12. package/dist/connectors/cosmosdb.js +305 -50
  13. package/dist/connectors/customerio.js +319 -47
  14. package/dist/connectors/dbt.js +340 -47
  15. package/dist/connectors/freshdesk.js +342 -53
  16. package/dist/connectors/freshsales.js +333 -52
  17. package/dist/connectors/freshservice.js +361 -53
  18. package/dist/connectors/gamma.js +327 -52
  19. package/dist/connectors/gemini.js +134 -47
  20. package/dist/connectors/github.js +386 -49
  21. package/dist/connectors/gmail-oauth.js +204 -7
  22. package/dist/connectors/gmail.js +350 -47
  23. package/dist/connectors/google-ads.js +288 -46
  24. package/dist/connectors/google-analytics-oauth.js +310 -46
  25. package/dist/connectors/google-analytics.js +547 -87
  26. package/dist/connectors/google-audit-log.js +438 -47
  27. package/dist/connectors/google-calendar-oauth.js +259 -46
  28. package/dist/connectors/google-calendar.js +359 -47
  29. package/dist/connectors/google-docs.js +220 -6
  30. package/dist/connectors/google-drive.js +262 -5
  31. package/dist/connectors/google-search-console-oauth.js +256 -46
  32. package/dist/connectors/google-sheets.js +272 -47
  33. package/dist/connectors/google-slides.js +205 -6
  34. package/dist/connectors/grafana.js +332 -49
  35. package/dist/connectors/hubspot-oauth.js +208 -5
  36. package/dist/connectors/hubspot.js +306 -49
  37. package/dist/connectors/influxdb.js +416 -51
  38. package/dist/connectors/intercom-oauth.js +210 -5
  39. package/dist/connectors/intercom.js +302 -49
  40. package/dist/connectors/jdbc.js +762 -110
  41. package/dist/connectors/jira-api-key.js +326 -47
  42. package/dist/connectors/kintone-api-token.js +281 -47
  43. package/dist/connectors/kintone.js +328 -47
  44. package/dist/connectors/linear.js +330 -49
  45. package/dist/connectors/linkedin-ads.js +268 -50
  46. package/dist/connectors/mailchimp-oauth.js +268 -46
  47. package/dist/connectors/mailchimp.js +320 -49
  48. package/dist/connectors/meta-ads-oauth.js +273 -48
  49. package/dist/connectors/meta-ads.js +285 -50
  50. package/dist/connectors/mixpanel.js +338 -47
  51. package/dist/connectors/monday.js +360 -49
  52. package/dist/connectors/mongodb.js +319 -57
  53. package/dist/connectors/notion-oauth.js +231 -5
  54. package/dist/connectors/notion.js +323 -51
  55. package/dist/connectors/openai.js +134 -47
  56. package/dist/connectors/oracle.js +454 -103
  57. package/dist/connectors/outlook-oauth.js +204 -5
  58. package/dist/connectors/powerbi-oauth.js +498 -5
  59. package/dist/connectors/salesforce.js +384 -49
  60. package/dist/connectors/semrush.js +609 -49
  61. package/dist/connectors/sentry.js +289 -50
  62. package/dist/connectors/shopify-oauth.js +187 -5
  63. package/dist/connectors/shopify.js +357 -47
  64. package/dist/connectors/sqlserver.js +415 -102
  65. package/dist/connectors/stripe-api-key.js +269 -46
  66. package/dist/connectors/stripe-oauth.js +202 -5
  67. package/dist/connectors/supabase.js +303 -48
  68. package/dist/connectors/tableau.js +536 -163
  69. package/dist/connectors/tiktok-ads.js +279 -48
  70. package/dist/connectors/wix-store.js +320 -49
  71. package/dist/connectors/zendesk-oauth.js +239 -5
  72. package/dist/connectors/zendesk.js +358 -47
  73. package/dist/index.d.ts +149 -1
  74. package/dist/index.js +15057 -2117
  75. package/dist/main.js +15005 -2073
  76. package/dist/vite-plugin.js +14752 -2019
  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/gamma/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  apiKey: new ParameterDefinition({
48
60
  slug: "api-key",
@@ -210,6 +222,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
210
222
  tools;
211
223
  query;
212
224
  checkConnection;
225
+ /**
226
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
227
+ * implement this expose a step-by-step exploration flow (database/schema/
228
+ * table/etc. discovery) that the dashboard backend drives via the
229
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
230
+ * `runSetupFlow` from `setup-flow.ts`.
231
+ */
232
+ setup;
233
+ /**
234
+ * Opt-out of the default "verify before save" behavior on connection
235
+ * creation. The backend invokes `checkConnection` synchronously while
236
+ * creating the connection and aborts (no row inserted) if it fails — this
237
+ * flag disables that for connectors where the check cannot succeed pre-save:
238
+ *
239
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
240
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
241
+ * connectionId, which doesn't exist until the row is saved
242
+ *
243
+ * Exceptions are the explicit position; new credential-input connectors get
244
+ * the default verify-on-create behavior without opt-in.
245
+ */
246
+ skipConnectionCheckOnCreate;
213
247
  constructor(config) {
214
248
  this.slug = config.slug;
215
249
  this.authType = config.authType;
@@ -226,6 +260,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
226
260
  this.tools = config.tools;
227
261
  this.query = config.query;
228
262
  this.checkConnection = config.checkConnection;
263
+ this.setup = config.setup;
264
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
229
265
  }
230
266
  get connectorKey() {
231
267
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -290,6 +326,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
290
326
  }
291
327
  };
292
328
 
329
+ // ../connectors/src/setup-flow.ts
330
+ async function runSetupFlow(flow, params, ctx, config) {
331
+ const runtime = {
332
+ params,
333
+ language: ctx.language,
334
+ config
335
+ };
336
+ let state = flow.initialState();
337
+ let answerIdx = 0;
338
+ const pendingParameterUpdates = [];
339
+ for (const step of flow.steps) {
340
+ const ans = ctx.answers[answerIdx];
341
+ if (ans && ans.questionSlug === step.slug) {
342
+ state = step.applyAnswer(state, ans.answer);
343
+ if (step.toParameterUpdates) {
344
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
345
+ }
346
+ answerIdx += 1;
347
+ continue;
348
+ }
349
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
350
+ if (step.type === "text") {
351
+ if (step.fetchOptions) {
352
+ const options2 = await step.fetchOptions(state, runtime);
353
+ if (options2.length === 0) {
354
+ continue;
355
+ }
356
+ }
357
+ return {
358
+ type: "nextQuestion",
359
+ questionSlug: step.slug,
360
+ question: step.question[ctx.language],
361
+ questionType: "text",
362
+ allowFreeText: resolvedAllowFreeText,
363
+ ...pendingParameterUpdates.length > 0 && {
364
+ parameterUpdates: pendingParameterUpdates
365
+ }
366
+ };
367
+ }
368
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
369
+ if (options.length === 0) {
370
+ continue;
371
+ }
372
+ return {
373
+ type: "nextQuestion",
374
+ questionSlug: step.slug,
375
+ question: step.question[ctx.language],
376
+ questionType: step.type,
377
+ options,
378
+ allowFreeText: resolvedAllowFreeText,
379
+ ...pendingParameterUpdates.length > 0 && {
380
+ parameterUpdates: pendingParameterUpdates
381
+ }
382
+ };
383
+ }
384
+ const dataInvestigationResult = await flow.finalize(state, runtime);
385
+ return {
386
+ type: "fulfilled",
387
+ dataInvestigationResult,
388
+ ...pendingParameterUpdates.length > 0 && {
389
+ parameterUpdates: pendingParameterUpdates
390
+ }
391
+ };
392
+ }
393
+ async function resolveSetupSelection(params) {
394
+ const { selected, allSentinel, fetchAll, limit } = params;
395
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
396
+ return resolved.slice(0, limit);
397
+ }
398
+
293
399
  // ../connectors/src/auth-types.ts
294
400
  var AUTH_TYPES = {
295
401
  OAUTH: "oauth",
@@ -312,9 +418,122 @@ var gammaOnboarding = new ConnectorOnboarding({
312
418
  }
313
419
  });
314
420
 
421
+ // ../connectors/src/connectors/gamma/utils.ts
422
+ var BASE_URL2 = "https://public-api.gamma.app/v1.0";
423
+ function apiFetch(params, path2, init) {
424
+ const apiKey = params[parameters.apiKey.slug];
425
+ if (!apiKey) {
426
+ throw new Error(`gamma: missing required parameter: ${parameters.apiKey.slug}`);
427
+ }
428
+ const headers = new Headers(init?.headers);
429
+ headers.set("X-API-KEY", apiKey);
430
+ if (!headers.has("Content-Type")) headers.set("Content-Type", "application/json");
431
+ const trimmedPath = path2.startsWith("/") ? path2 : `/${path2}`;
432
+ return fetch(`${BASE_URL2}${trimmedPath}`, { ...init, headers });
433
+ }
434
+
435
+ // ../connectors/src/connectors/gamma/setup-flow.ts
436
+ var ALL_FOLDERS = "__ALL_FOLDERS__";
437
+ var GAMMA_SETUP_MAX_FOLDERS = 20;
438
+ var FOLDERS_PAGE_LIMIT = 50;
439
+ async function listAllFolders(params) {
440
+ const results = [];
441
+ let after;
442
+ for (let i = 0; i < 10; i++) {
443
+ const qs = new URLSearchParams();
444
+ qs.set("limit", String(FOLDERS_PAGE_LIMIT));
445
+ if (after) qs.set("after", after);
446
+ const res = await apiFetch(params, `/folders?${qs.toString()}`);
447
+ if (!res.ok) {
448
+ const body = await res.text().catch(() => res.statusText);
449
+ throw new Error(`gamma: listFolders failed (${res.status}): ${body}`);
450
+ }
451
+ const data = await res.json();
452
+ for (const item of data.data ?? []) results.push(item);
453
+ if (!data.hasMore || !data.nextCursor) break;
454
+ after = data.nextCursor;
455
+ }
456
+ return results;
457
+ }
458
+ async function listThemes(params) {
459
+ const res = await apiFetch(params, "/themes?limit=50");
460
+ if (!res.ok) {
461
+ return [];
462
+ }
463
+ const data = await res.json();
464
+ return data.data ?? [];
465
+ }
466
+ function folderLabel(f) {
467
+ return f.name ?? f.title ?? f.id ?? "(Untitled)";
468
+ }
469
+ var gammaSetupFlow = {
470
+ initialState: () => ({}),
471
+ steps: [
472
+ {
473
+ slug: "folders",
474
+ type: "multiSelect",
475
+ question: {
476
+ ja: "\u5BFE\u8C61\u306E\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
477
+ en: "Select target folders (multi-select allowed)"
478
+ },
479
+ async fetchOptions(_state, rt) {
480
+ const folders = await listAllFolders(rt.params);
481
+ const options = folders.filter((f) => f.id).map((f) => ({ value: f.id, label: folderLabel(f) }));
482
+ return [
483
+ {
484
+ value: ALL_FOLDERS,
485
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30D5\u30A9\u30EB\u30C0" : "All folders"
486
+ },
487
+ ...options
488
+ ];
489
+ },
490
+ applyAnswer: (state, answer) => ({ ...state, folders: answer })
491
+ }
492
+ ],
493
+ async finalize(state, rt) {
494
+ if (!state.folders) {
495
+ throw new Error("Gamma setup: incomplete state on finalize");
496
+ }
497
+ const allFolders = await listAllFolders(rt.params);
498
+ const folderById = new Map(
499
+ allFolders.filter((f) => f.id).map((f) => [f.id, f])
500
+ );
501
+ const targetIds = await resolveSetupSelection({
502
+ selected: state.folders,
503
+ allSentinel: ALL_FOLDERS,
504
+ fetchAll: async () => allFolders.map((f) => f.id ?? "").filter((id) => id),
505
+ limit: GAMMA_SETUP_MAX_FOLDERS
506
+ });
507
+ const sections = ["## Gamma", ""];
508
+ if (!targetIds.length) {
509
+ sections.push("_No folders selected._", "");
510
+ } else {
511
+ sections.push(`### Folders (${targetIds.length})`, "");
512
+ for (const id of targetIds) {
513
+ const folder = folderById.get(id);
514
+ sections.push(`- ${folderLabel(folder ?? { id })} (id: \`${id}\`)`);
515
+ }
516
+ sections.push("");
517
+ }
518
+ const themes = await listThemes(rt.params);
519
+ if (themes.length) {
520
+ sections.push(`### Available themes (${themes.length})`, "");
521
+ for (const theme of themes.slice(0, 20)) {
522
+ const label = theme.name ?? theme.id ?? "(unnamed)";
523
+ sections.push(`- ${label}`);
524
+ }
525
+ if (themes.length > 20) {
526
+ sections.push(`- \u2026and ${themes.length - 20} more`);
527
+ }
528
+ sections.push("");
529
+ }
530
+ return sections.join("\n");
531
+ }
532
+ };
533
+
315
534
  // ../connectors/src/connectors/gamma/tools/request.ts
316
535
  import { z } from "zod";
317
- var BASE_URL2 = "https://public-api.gamma.app/v1.0";
536
+ var BASE_URL3 = "https://public-api.gamma.app/v1.0";
318
537
  var REQUEST_TIMEOUT_MS = 6e4;
319
538
  var inputSchema = z.object({
320
539
  toolUseIntent: z.string().optional().describe(
@@ -359,7 +578,7 @@ For creating presentations/documents, prefer the gamma_generate tool instead.`,
359
578
  );
360
579
  try {
361
580
  const apiKey = parameters.apiKey.getValue(connection2);
362
- const url = `${BASE_URL2}${path2}`;
581
+ const url = `${BASE_URL3}${path2}`;
363
582
  const controller = new AbortController();
364
583
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
365
584
  try {
@@ -391,7 +610,7 @@ For creating presentations/documents, prefer the gamma_generate tool instead.`,
391
610
 
392
611
  // ../connectors/src/connectors/gamma/tools/generate.ts
393
612
  import { z as z2 } from "zod";
394
- var BASE_URL3 = "https://public-api.gamma.app/v1.0";
613
+ var BASE_URL4 = "https://public-api.gamma.app/v1.0";
395
614
  var POLL_INTERVAL_MS = 5e3;
396
615
  var MAX_POLL_DURATION_MS = 3e5;
397
616
  var inputSchema2 = z2.object({
@@ -508,7 +727,7 @@ Gamma does NOT support image uploads. To visualize data, embed raw numbers direc
508
727
  if (textAmount) textOptions.amount = textAmount;
509
728
  if (Object.keys(textOptions).length > 0) body.textOptions = textOptions;
510
729
  if (imageSource) body.imageOptions = { source: imageSource };
511
- const createRes = await fetch(`${BASE_URL3}/generations`, {
730
+ const createRes = await fetch(`${BASE_URL4}/generations`, {
512
731
  method: "POST",
513
732
  headers,
514
733
  body: JSON.stringify(body)
@@ -528,7 +747,7 @@ Gamma does NOT support image uploads. To visualize data, embed raw numbers direc
528
747
  const deadline = Date.now() + MAX_POLL_DURATION_MS;
529
748
  while (Date.now() < deadline) {
530
749
  await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
531
- const pollRes = await fetch(`${BASE_URL3}/generations/${generationId}`, {
750
+ const pollRes = await fetch(`${BASE_URL4}/generations/${generationId}`, {
532
751
  method: "GET",
533
752
  headers
534
753
  });
@@ -727,7 +946,43 @@ export default async function handler(c: Context) {
727
946
  #### \u30C7\u30FC\u30BF\u306E\u53EF\u8996\u5316
728
947
  Gamma\u306F\u753B\u50CF\u306E\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093\u3002\u30C7\u30FC\u30BF\u3092\u53EF\u8996\u5316\u3057\u305F\u3044\u5834\u5408\uFF08\u30C1\u30E3\u30FC\u30C8\u3001\u30B0\u30E9\u30D5\u3001\u30C6\u30FC\u30D6\u30EB\u306A\u3069\uFF09\u306F\u3001\`inputText\` \u306B\u6570\u5024\u3084\u30C7\u30FC\u30BF\u3092\u69CB\u9020\u5316\u30C6\u30AD\u30B9\u30C8\uFF08\u30DE\u30FC\u30AF\u30C0\u30A6\u30F3\u30C6\u30FC\u30D6\u30EB\u3001\u6570\u5024\u4ED8\u304D\u7B87\u6761\u66F8\u304D\u306A\u3069\uFF09\u3068\u3057\u3066\u76F4\u63A5\u57CB\u3081\u8FBC\u3093\u3067\u304F\u3060\u3055\u3044\u3002Gamma AI\u304C\u30C7\u30FC\u30BF\u304B\u3089\u9069\u5207\u306A\u30D3\u30B8\u30E5\u30A2\u30EB\u8981\u7D20\u3092\u751F\u6210\u3057\u307E\u3059\u3002\u30ED\u30FC\u30AB\u30EB\u3067\u30C1\u30E3\u30FC\u30C8\u753B\u50CF\u3092\u751F\u6210\u3057\u3066\u542B\u3081\u308B\u306E\u3067\u306F\u306A\u304F\u3001\u30C7\u30FC\u30BF\u306E\u5024\u3092\u30A4\u30F3\u30E9\u30A4\u30F3\u3067\u6E21\u3057\u3066Gamma\u306B\u53EF\u8996\u5316\u3055\u305B\u3066\u304F\u3060\u3055\u3044\u3002`
729
948
  },
730
- tools
949
+ tools,
950
+ setup: (params, ctx, config) => runSetupFlow(gammaSetupFlow, params, ctx, config),
951
+ async checkConnection(params, _config) {
952
+ const apiKey = params[parameters.apiKey.slug];
953
+ if (!apiKey) {
954
+ return {
955
+ success: false,
956
+ error: `Missing required parameter: ${parameters.apiKey.slug}`
957
+ };
958
+ }
959
+ try {
960
+ const res = await fetch(
961
+ "https://public-api.gamma.app/v1.0/folders?limit=1",
962
+ {
963
+ method: "GET",
964
+ headers: {
965
+ "X-API-KEY": apiKey,
966
+ Accept: "application/json"
967
+ }
968
+ }
969
+ );
970
+ if (!res.ok) {
971
+ const data = await res.json().catch(() => null);
972
+ const message = typeof data?.message === "string" && data.message || typeof data?.error === "string" && data.error || `HTTP ${res.status} ${res.statusText}`;
973
+ return {
974
+ success: false,
975
+ error: `Gamma API failed: ${message}`
976
+ };
977
+ }
978
+ return { success: true };
979
+ } catch (error) {
980
+ return {
981
+ success: false,
982
+ error: error instanceof Error ? error.message : String(error)
983
+ };
984
+ }
985
+ }
731
986
  });
732
987
 
733
988
  // src/connectors/create-connector-sdk.ts
@@ -756,6 +1011,7 @@ function resolveEnvVarOptional(entry, key) {
756
1011
  import { getContext } from "hono/context-storage";
757
1012
  import { getCookie } from "hono/cookie";
758
1013
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
1014
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
759
1015
  function normalizeHeaders(input) {
760
1016
  const out = {};
761
1017
  if (!input) return out;
@@ -764,6 +1020,11 @@ function normalizeHeaders(input) {
764
1020
  });
765
1021
  return out;
766
1022
  }
1023
+ function extractInputUrl(input) {
1024
+ if (typeof input === "string") return input;
1025
+ if (input instanceof URL) return input.href;
1026
+ return input.url;
1027
+ }
767
1028
  function createSandboxProxyFetch(connectionId) {
768
1029
  return async (input, init) => {
769
1030
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -773,10 +1034,17 @@ function createSandboxProxyFetch(connectionId) {
773
1034
  "Connection proxy is not configured. Please check your deployment settings."
774
1035
  );
775
1036
  }
776
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1037
+ const originalUrl = extractInputUrl(input);
1038
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
1039
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1040
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
1041
+ return fetch(sessionUrl, {
1042
+ method: "POST",
1043
+ headers: { Authorization: `Bearer ${token}` }
1044
+ });
1045
+ }
777
1046
  const originalMethod = init?.method ?? "GET";
778
1047
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
779
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
780
1048
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
781
1049
  return fetch(proxyUrl, {
782
1050
  method: "POST",
@@ -802,10 +1070,9 @@ function createDeployedAppProxyFetch(connectionId) {
802
1070
  }
803
1071
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
804
1072
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
1073
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
805
1074
  return async (input, init) => {
806
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
807
- const originalMethod = init?.method ?? "GET";
808
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
1075
+ const originalUrl = extractInputUrl(input);
809
1076
  const c = getContext();
810
1077
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
811
1078
  if (!appSession) {
@@ -813,6 +1080,14 @@ function createDeployedAppProxyFetch(connectionId) {
813
1080
  "No authentication method available for connection proxy."
814
1081
  );
815
1082
  }
1083
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1084
+ return fetch(sessionUrl, {
1085
+ method: "POST",
1086
+ headers: { Authorization: `Bearer ${appSession}` }
1087
+ });
1088
+ }
1089
+ const originalMethod = init?.method ?? "GET";
1090
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
816
1091
  return fetch(proxyUrl, {
817
1092
  method: "POST",
818
1093
  headers: {