@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/influxdb/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  url: new ParameterDefinition({
48
60
  slug: "url",
@@ -103,7 +115,7 @@ function createClient(params) {
103
115
  `influxdb: missing required parameter: ${parameters.database.slug}`
104
116
  );
105
117
  }
106
- function authHeaders(extra) {
118
+ function authHeaders2(extra) {
107
119
  const headers = new Headers(extra);
108
120
  headers.set("Authorization", `Token ${token}`);
109
121
  if (!headers.has("Accept")) headers.set("Accept", "application/json");
@@ -139,7 +151,7 @@ function createClient(params) {
139
151
  async querySql(sql, options) {
140
152
  const res = await fetch(`${url}/api/v3/query_sql`, {
141
153
  method: "POST",
142
- headers: authHeaders({ "Content-Type": "application/json" }),
154
+ headers: authHeaders2({ "Content-Type": "application/json" }),
143
155
  body: JSON.stringify({
144
156
  db: options?.database ?? database,
145
157
  q: sql
@@ -151,7 +163,7 @@ function createClient(params) {
151
163
  async queryInfluxql(influxql, options) {
152
164
  const res = await fetch(`${url}/api/v3/query_influxql`, {
153
165
  method: "POST",
154
- headers: authHeaders({ "Content-Type": "application/json" }),
166
+ headers: authHeaders2({ "Content-Type": "application/json" }),
155
167
  body: JSON.stringify({
156
168
  db: options?.database ?? database,
157
169
  q: influxql
@@ -171,7 +183,7 @@ function createClient(params) {
171
183
  `${url}/api/v2/query?org=${encodeURIComponent(resolvedOrg)}`,
172
184
  {
173
185
  method: "POST",
174
- headers: authHeaders({
186
+ headers: authHeaders2({
175
187
  "Content-Type": "application/vnd.flux",
176
188
  Accept: "application/csv"
177
189
  }),
@@ -188,7 +200,7 @@ function createClient(params) {
188
200
  const endpoint = resolvedOrg ? `${url}/api/v2/write?org=${encodeURIComponent(resolvedOrg)}&bucket=${encodeURIComponent(resolvedDatabase)}&precision=${precision}` : `${url}/api/v3/write_lp?db=${encodeURIComponent(resolvedDatabase)}&precision=${precision}`;
189
201
  const res = await fetch(endpoint, {
190
202
  method: "POST",
191
- headers: authHeaders({ "Content-Type": "text/plain; charset=utf-8" }),
203
+ headers: authHeaders2({ "Content-Type": "text/plain; charset=utf-8" }),
192
204
  body: lineProtocol
193
205
  });
194
206
  await assertOk(res, "writeLineProtocol");
@@ -255,6 +267,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
255
267
  tools;
256
268
  query;
257
269
  checkConnection;
270
+ /**
271
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
272
+ * implement this expose a step-by-step exploration flow (database/schema/
273
+ * table/etc. discovery) that the dashboard backend drives via the
274
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
275
+ * `runSetupFlow` from `setup-flow.ts`.
276
+ */
277
+ setup;
278
+ /**
279
+ * Opt-out of the default "verify before save" behavior on connection
280
+ * creation. The backend invokes `checkConnection` synchronously while
281
+ * creating the connection and aborts (no row inserted) if it fails — this
282
+ * flag disables that for connectors where the check cannot succeed pre-save:
283
+ *
284
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
285
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
286
+ * connectionId, which doesn't exist until the row is saved
287
+ *
288
+ * Exceptions are the explicit position; new credential-input connectors get
289
+ * the default verify-on-create behavior without opt-in.
290
+ */
291
+ skipConnectionCheckOnCreate;
258
292
  constructor(config) {
259
293
  this.slug = config.slug;
260
294
  this.authType = config.authType;
@@ -271,6 +305,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
271
305
  this.tools = config.tools;
272
306
  this.query = config.query;
273
307
  this.checkConnection = config.checkConnection;
308
+ this.setup = config.setup;
309
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
274
310
  }
275
311
  get connectorKey() {
276
312
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -335,6 +371,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
335
371
  }
336
372
  };
337
373
 
374
+ // ../connectors/src/setup-flow.ts
375
+ async function runSetupFlow(flow, params, ctx, config) {
376
+ const runtime = {
377
+ params,
378
+ language: ctx.language,
379
+ config
380
+ };
381
+ let state = flow.initialState();
382
+ let answerIdx = 0;
383
+ for (const step of flow.steps) {
384
+ const ans = ctx.answers[answerIdx];
385
+ if (ans && ans.questionSlug === step.slug) {
386
+ state = step.applyAnswer(state, ans.answer);
387
+ answerIdx += 1;
388
+ continue;
389
+ }
390
+ if (step.type === "text") {
391
+ return {
392
+ type: "nextQuestion",
393
+ questionSlug: step.slug,
394
+ question: step.question[ctx.language],
395
+ questionType: "text"
396
+ };
397
+ }
398
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
399
+ if (options.length === 0) {
400
+ continue;
401
+ }
402
+ return {
403
+ type: "nextQuestion",
404
+ questionSlug: step.slug,
405
+ question: step.question[ctx.language],
406
+ questionType: step.type,
407
+ options
408
+ };
409
+ }
410
+ const dataInvestigationResult = await flow.finalize(state, runtime);
411
+ return { type: "fulfilled", dataInvestigationResult };
412
+ }
413
+ async function resolveSetupSelection(params) {
414
+ const { selected, allSentinel, fetchAll, limit } = params;
415
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
416
+ return resolved.slice(0, limit);
417
+ }
418
+
338
419
  // ../connectors/src/auth-types.ts
339
420
  var AUTH_TYPES = {
340
421
  OAUTH: "oauth",
@@ -403,6 +484,244 @@ var influxdbOnboarding = new ConnectorOnboarding({
403
484
  }
404
485
  });
405
486
 
487
+ // ../connectors/src/connectors/influxdb/utils.ts
488
+ function authHeaders(token, extra) {
489
+ const headers = new Headers(extra);
490
+ headers.set("Authorization", `Token ${token}`);
491
+ if (!headers.has("Accept")) headers.set("Accept", "application/json");
492
+ return headers;
493
+ }
494
+ async function detectVariant(params) {
495
+ const url = (params[parameters.url.slug] ?? "").replace(/\/$/, "");
496
+ const token = params[parameters.token.slug];
497
+ const database = params[parameters.database.slug];
498
+ const res = await fetch(`${url}/api/v3/query_sql`, {
499
+ method: "POST",
500
+ headers: authHeaders(token, { "Content-Type": "application/json" }),
501
+ body: JSON.stringify({ db: database, q: "SELECT 1" })
502
+ });
503
+ if (res.ok) {
504
+ const contentType = res.headers.get("content-type") ?? "";
505
+ if (contentType.includes("application/json")) return "v3";
506
+ }
507
+ return "v2";
508
+ }
509
+ async function runSql(params, sql) {
510
+ const url = (params[parameters.url.slug] ?? "").replace(/\/$/, "");
511
+ const token = params[parameters.token.slug];
512
+ const database = params[parameters.database.slug];
513
+ const res = await fetch(`${url}/api/v3/query_sql`, {
514
+ method: "POST",
515
+ headers: authHeaders(token, { "Content-Type": "application/json" }),
516
+ body: JSON.stringify({ db: database, q: sql })
517
+ });
518
+ if (!res.ok) {
519
+ const body = await res.text().catch(() => res.statusText);
520
+ throw new Error(
521
+ `InfluxDB SQL query failed: HTTP ${res.status} \u2014 ${body.slice(0, 200)}`
522
+ );
523
+ }
524
+ return await res.json();
525
+ }
526
+ async function runFlux(params, flux) {
527
+ const url = (params[parameters.url.slug] ?? "").replace(/\/$/, "");
528
+ const token = params[parameters.token.slug];
529
+ const org = params[parameters.org.slug];
530
+ if (!org) {
531
+ throw new Error(
532
+ "InfluxDB 2 Flux queries require the 'org' connection parameter, which is not configured"
533
+ );
534
+ }
535
+ const res = await fetch(
536
+ `${url}/api/v2/query?org=${encodeURIComponent(org)}`,
537
+ {
538
+ method: "POST",
539
+ headers: authHeaders(token, {
540
+ "Content-Type": "application/vnd.flux",
541
+ Accept: "application/csv"
542
+ }),
543
+ body: flux
544
+ }
545
+ );
546
+ if (!res.ok) {
547
+ const body = await res.text().catch(() => res.statusText);
548
+ throw new Error(
549
+ `InfluxDB Flux query failed: HTTP ${res.status} \u2014 ${body.slice(0, 200)}`
550
+ );
551
+ }
552
+ return await res.text();
553
+ }
554
+ function parseAnnotatedCsv(csv) {
555
+ const lines = csv.split(/\r?\n/).filter((line) => line.trim().length > 0);
556
+ const rows = [];
557
+ let headers = null;
558
+ for (const line of lines) {
559
+ if (line.startsWith("#")) {
560
+ headers = null;
561
+ continue;
562
+ }
563
+ const fields = splitCsvLine(line);
564
+ if (headers === null) {
565
+ headers = fields;
566
+ continue;
567
+ }
568
+ const row = {};
569
+ headers.forEach((h, i) => {
570
+ row[h] = fields[i] ?? "";
571
+ });
572
+ rows.push(row);
573
+ }
574
+ return { columns: headers ?? [], rows };
575
+ }
576
+ function splitCsvLine(line) {
577
+ const out = [];
578
+ let cur = "";
579
+ let inQuotes = false;
580
+ for (let i = 0; i < line.length; i++) {
581
+ const c = line[i];
582
+ if (inQuotes) {
583
+ if (c === '"' && line[i + 1] === '"') {
584
+ cur += '"';
585
+ i += 1;
586
+ } else if (c === '"') {
587
+ inQuotes = false;
588
+ } else {
589
+ cur += c;
590
+ }
591
+ } else if (c === '"') {
592
+ inQuotes = true;
593
+ } else if (c === ",") {
594
+ out.push(cur);
595
+ cur = "";
596
+ } else {
597
+ cur += c;
598
+ }
599
+ }
600
+ out.push(cur);
601
+ return out;
602
+ }
603
+
604
+ // ../connectors/src/connectors/influxdb/setup-flow.ts
605
+ var ALL_MEASUREMENTS = "__ALL_MEASUREMENTS__";
606
+ var INFLUXDB_SETUP_MAX_MEASUREMENTS = 20;
607
+ async function listMeasurements(params, variant) {
608
+ if (variant === "v3") {
609
+ const rows2 = await runSql(params, "SHOW TABLES");
610
+ return rows2.map((r) => String(r["table_name"] ?? r["name"] ?? "")).filter((name) => name).filter((name) => !name.includes("::"));
611
+ }
612
+ const bucket = params[parameters.database.slug];
613
+ if (!bucket) {
614
+ throw new Error(
615
+ "InfluxDB 2 setup: 'database' (bucket) parameter is required to list measurements"
616
+ );
617
+ }
618
+ const flux = [
619
+ `import "influxdata/influxdb/schema"`,
620
+ `schema.measurements(bucket: ${JSON.stringify(bucket)})`
621
+ ].join("\n");
622
+ const csv = await runFlux(params, flux);
623
+ const { rows } = parseAnnotatedCsv(csv);
624
+ return rows.map((r) => r["_value"] ?? "").filter((name) => name);
625
+ }
626
+ async function listMeasurementColumns(params, variant, measurement) {
627
+ if (variant === "v3") {
628
+ const safeName2 = measurement.replace(/"/g, '""');
629
+ const rows = await runSql(params, `SHOW COLUMNS FROM "${safeName2}"`);
630
+ return rows.map((r) => ({
631
+ name: String(r["column_name"] ?? r["name"] ?? ""),
632
+ kind: String(r["data_type"] ?? r["type"] ?? "")
633
+ }));
634
+ }
635
+ const bucket = params[parameters.database.slug];
636
+ const safeName = measurement.replace(/"/g, '\\"');
637
+ const fieldsFlux = [
638
+ `import "influxdata/influxdb/schema"`,
639
+ `schema.measurementFieldKeys(bucket: ${JSON.stringify(bucket)}, measurement: "${safeName}")`
640
+ ].join("\n");
641
+ const tagsFlux = [
642
+ `import "influxdata/influxdb/schema"`,
643
+ `schema.measurementTagKeys(bucket: ${JSON.stringify(bucket)}, measurement: "${safeName}")`
644
+ ].join("\n");
645
+ const [fieldsCsv, tagsCsv] = await Promise.all([
646
+ runFlux(params, fieldsFlux),
647
+ runFlux(params, tagsFlux)
648
+ ]);
649
+ const fields = parseAnnotatedCsv(fieldsCsv).rows.map((r) => ({
650
+ name: r["_value"] ?? "",
651
+ kind: "field"
652
+ }));
653
+ const tags = parseAnnotatedCsv(tagsCsv).rows.map((r) => ({
654
+ name: r["_value"] ?? "",
655
+ kind: "tag"
656
+ }));
657
+ return [...tags, ...fields].filter((c) => c.name);
658
+ }
659
+ var influxdbSetupFlow = {
660
+ initialState: () => ({}),
661
+ steps: [
662
+ {
663
+ slug: "measurements",
664
+ type: "multiSelect",
665
+ question: {
666
+ ja: "\u5BFE\u8C61 measurement \u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
667
+ en: "Select target measurements (multi-select allowed)"
668
+ },
669
+ async fetchOptions(_state, rt) {
670
+ const variant = await detectVariant(rt.params);
671
+ const ms = await listMeasurements(rt.params, variant);
672
+ const options = ms.map((value) => ({ value }));
673
+ return [
674
+ {
675
+ value: ALL_MEASUREMENTS,
676
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E measurement" : "All measurements"
677
+ },
678
+ ...options
679
+ ];
680
+ },
681
+ applyAnswer: (state, answer) => ({ ...state, measurements: answer })
682
+ }
683
+ ],
684
+ async finalize(state, rt) {
685
+ if (!state.measurements) {
686
+ throw new Error("InfluxDB setup: incomplete state on finalize");
687
+ }
688
+ const variant = await detectVariant(rt.params);
689
+ const database = rt.params[parameters.database.slug];
690
+ const org = rt.params[parameters.org.slug];
691
+ const targetMeasurements = await resolveSetupSelection({
692
+ selected: state.measurements,
693
+ allSentinel: ALL_MEASUREMENTS,
694
+ fetchAll: () => listMeasurements(rt.params, variant),
695
+ limit: INFLUXDB_SETUP_MAX_MEASUREMENTS
696
+ });
697
+ const sections = [
698
+ "## InfluxDB",
699
+ "",
700
+ `### Variant: ${variant === "v3" ? "InfluxDB 3 (SQL)" : "InfluxDB 2 (Flux)"}`,
701
+ `### ${variant === "v3" ? "Database" : "Bucket"}: ${database}`
702
+ ];
703
+ if (variant === "v2" && org) {
704
+ sections.push(`### Organization: ${org}`);
705
+ }
706
+ sections.push("");
707
+ for (const measurement of targetMeasurements) {
708
+ const cols = await listMeasurementColumns(rt.params, variant, measurement);
709
+ sections.push(`#### Measurement: ${measurement}`, "");
710
+ if (cols.length === 0) {
711
+ sections.push("_(no fields or tags found)_", "");
712
+ continue;
713
+ }
714
+ sections.push("| Column | Kind |");
715
+ sections.push("|--------|------|");
716
+ for (const c of cols) {
717
+ sections.push(`| ${c.name} | ${c.kind || "-"} |`);
718
+ }
719
+ sections.push("");
720
+ }
721
+ return sections.join("\n");
722
+ }
723
+ };
724
+
406
725
  // ../connectors/src/connectors/influxdb/tools/request.ts
407
726
  import { z } from "zod";
408
727
  var REQUEST_TIMEOUT_MS = 6e4;
@@ -669,6 +988,7 @@ export default async function handler(c: Context) {
669
988
  - measurement \u4E00\u89A7: \`SHOW TABLES\`\u3001\u5217\u4E00\u89A7: \`SHOW COLUMNS FROM <measurement>\``
670
989
  },
671
990
  tools,
991
+ setup: (params, ctx, config) => runSetupFlow(influxdbSetupFlow, params, ctx, config),
672
992
  async checkConnection(params) {
673
993
  const url = (params.url ?? "").replace(/\/$/, "");
674
994
  const token = params.token;
@@ -737,6 +1057,7 @@ function resolveEnvVarOptional(entry, key) {
737
1057
  import { getContext } from "hono/context-storage";
738
1058
  import { getCookie } from "hono/cookie";
739
1059
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
1060
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
740
1061
  function normalizeHeaders(input) {
741
1062
  const out = {};
742
1063
  if (!input) return out;
@@ -745,6 +1066,11 @@ function normalizeHeaders(input) {
745
1066
  });
746
1067
  return out;
747
1068
  }
1069
+ function extractInputUrl(input) {
1070
+ if (typeof input === "string") return input;
1071
+ if (input instanceof URL) return input.href;
1072
+ return input.url;
1073
+ }
748
1074
  function createSandboxProxyFetch(connectionId) {
749
1075
  return async (input, init) => {
750
1076
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -754,10 +1080,17 @@ function createSandboxProxyFetch(connectionId) {
754
1080
  "Connection proxy is not configured. Please check your deployment settings."
755
1081
  );
756
1082
  }
757
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1083
+ const originalUrl = extractInputUrl(input);
1084
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
1085
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1086
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
1087
+ return fetch(sessionUrl, {
1088
+ method: "POST",
1089
+ headers: { Authorization: `Bearer ${token}` }
1090
+ });
1091
+ }
758
1092
  const originalMethod = init?.method ?? "GET";
759
1093
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
760
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
761
1094
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
762
1095
  return fetch(proxyUrl, {
763
1096
  method: "POST",
@@ -783,10 +1116,9 @@ function createDeployedAppProxyFetch(connectionId) {
783
1116
  }
784
1117
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
785
1118
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
1119
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
786
1120
  return async (input, init) => {
787
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
788
- const originalMethod = init?.method ?? "GET";
789
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
1121
+ const originalUrl = extractInputUrl(input);
790
1122
  const c = getContext();
791
1123
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
792
1124
  if (!appSession) {
@@ -794,6 +1126,14 @@ function createDeployedAppProxyFetch(connectionId) {
794
1126
  "No authentication method available for connection proxy."
795
1127
  );
796
1128
  }
1129
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1130
+ return fetch(sessionUrl, {
1131
+ method: "POST",
1132
+ headers: { Authorization: `Bearer ${appSession}` }
1133
+ });
1134
+ }
1135
+ const originalMethod = init?.method ?? "GET";
1136
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
797
1137
  return fetch(proxyUrl, {
798
1138
  method: "POST",
799
1139
  headers: {