@squadbase/vite-server 0.1.12-dev.822582a → 0.1.12-dev.93b8799

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 (76) hide show
  1. package/dist/cli/index.js +343 -46
  2. package/dist/connectors/airtable-oauth.js +9 -0
  3. package/dist/connectors/airtable.js +9 -0
  4. package/dist/connectors/amplitude.js +9 -0
  5. package/dist/connectors/anthropic.js +9 -0
  6. package/dist/connectors/asana.js +9 -0
  7. package/dist/connectors/attio.js +9 -0
  8. package/dist/connectors/aws-billing.js +9 -0
  9. package/dist/connectors/azure-sql.js +9 -0
  10. package/dist/connectors/backlog-api-key.js +9 -0
  11. package/dist/connectors/clickup.js +9 -0
  12. package/dist/connectors/cosmosdb.js +9 -0
  13. package/dist/connectors/customerio.js +9 -0
  14. package/dist/connectors/dbt.js +9 -0
  15. package/dist/connectors/freshdesk.js +9 -0
  16. package/dist/connectors/freshsales.js +9 -0
  17. package/dist/connectors/freshservice.js +9 -0
  18. package/dist/connectors/gamma.js +9 -0
  19. package/dist/connectors/gemini.js +9 -0
  20. package/dist/connectors/github.js +9 -0
  21. package/dist/connectors/gmail-oauth.js +9 -0
  22. package/dist/connectors/gmail.js +9 -0
  23. package/dist/connectors/google-ads.js +9 -0
  24. package/dist/connectors/google-analytics-oauth.js +9 -0
  25. package/dist/connectors/google-analytics.js +9 -0
  26. package/dist/connectors/google-audit-log.js +9 -0
  27. package/dist/connectors/google-calendar-oauth.js +9 -0
  28. package/dist/connectors/google-calendar.js +9 -0
  29. package/dist/connectors/google-docs.js +9 -0
  30. package/dist/connectors/google-drive.js +9 -0
  31. package/dist/connectors/google-search-console-oauth.js +9 -0
  32. package/dist/connectors/google-sheets.js +9 -0
  33. package/dist/connectors/google-slides.js +9 -0
  34. package/dist/connectors/grafana.js +9 -0
  35. package/dist/connectors/hubspot-oauth.js +9 -0
  36. package/dist/connectors/hubspot.js +9 -0
  37. package/dist/connectors/influxdb.js +9 -0
  38. package/dist/connectors/intercom-oauth.js +9 -0
  39. package/dist/connectors/intercom.js +9 -0
  40. package/dist/connectors/jdbc.js +9 -0
  41. package/dist/connectors/jira-api-key.js +9 -0
  42. package/dist/connectors/kintone-api-token.js +9 -0
  43. package/dist/connectors/kintone.js +9 -0
  44. package/dist/connectors/linear.js +9 -0
  45. package/dist/connectors/linkedin-ads.js +9 -0
  46. package/dist/connectors/mailchimp-oauth.js +9 -0
  47. package/dist/connectors/mailchimp.js +9 -0
  48. package/dist/connectors/meta-ads-oauth.js +9 -0
  49. package/dist/connectors/meta-ads.js +9 -0
  50. package/dist/connectors/mixpanel.js +9 -0
  51. package/dist/connectors/monday.js +9 -0
  52. package/dist/connectors/mongodb.js +9 -0
  53. package/dist/connectors/notion-oauth.js +9 -0
  54. package/dist/connectors/notion.js +9 -0
  55. package/dist/connectors/openai.js +9 -0
  56. package/dist/connectors/oracle.js +9 -0
  57. package/dist/connectors/outlook-oauth.js +9 -0
  58. package/dist/connectors/powerbi-oauth.js +9 -0
  59. package/dist/connectors/salesforce.js +9 -0
  60. package/dist/connectors/semrush.js +9 -0
  61. package/dist/connectors/sentry.js +9 -0
  62. package/dist/connectors/shopify-oauth.js +9 -0
  63. package/dist/connectors/shopify.js +9 -0
  64. package/dist/connectors/sqlserver.js +9 -0
  65. package/dist/connectors/stripe-api-key.js +9 -0
  66. package/dist/connectors/stripe-oauth.js +9 -0
  67. package/dist/connectors/supabase.js +9 -0
  68. package/dist/connectors/tableau.js +129 -55
  69. package/dist/connectors/tiktok-ads.js +9 -0
  70. package/dist/connectors/wix-store.js +9 -0
  71. package/dist/connectors/zendesk-oauth.js +9 -0
  72. package/dist/connectors/zendesk.js +9 -0
  73. package/dist/index.js +343 -46
  74. package/dist/main.js +343 -46
  75. package/dist/vite-plugin.js +343 -46
  76. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -192,6 +192,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
192
192
  tools;
193
193
  query;
194
194
  checkConnection;
195
+ /**
196
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
197
+ * implement this expose a step-by-step exploration flow (database/schema/
198
+ * table/etc. discovery) that the dashboard backend drives via the
199
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
200
+ * `runSetupFlow` from `setup-flow.ts`.
201
+ */
202
+ setup;
195
203
  constructor(config) {
196
204
  this.slug = config.slug;
197
205
  this.authType = config.authType;
@@ -208,6 +216,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
208
216
  this.tools = config.tools;
209
217
  this.query = config.query;
210
218
  this.checkConnection = config.checkConnection;
219
+ this.setup = config.setup;
211
220
  }
212
221
  get connectorKey() {
213
222
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -272,6 +281,50 @@ var ConnectorPlugin = class _ConnectorPlugin {
272
281
  }
273
282
  };
274
283
 
284
+ // ../connectors/src/setup-flow.ts
285
+ async function runSetupFlow(flow, params, ctx, config) {
286
+ const runtime = {
287
+ params,
288
+ language: ctx.language,
289
+ config
290
+ };
291
+ let state = flow.initialState();
292
+ let answerIdx = 0;
293
+ for (const step of flow.steps) {
294
+ const ans = ctx.answers[answerIdx];
295
+ if (ans && ans.questionSlug === step.slug) {
296
+ state = step.applyAnswer(state, ans.answer);
297
+ answerIdx += 1;
298
+ continue;
299
+ }
300
+ if (step.type === "text") {
301
+ return {
302
+ type: "nextQuestion",
303
+ questionSlug: step.slug,
304
+ question: step.question[ctx.language],
305
+ questionType: "text"
306
+ };
307
+ }
308
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
309
+ if (options.length === 0) {
310
+ continue;
311
+ }
312
+ if (step.autoSelectIfSingle && options.length === 1) {
313
+ state = step.applyAnswer(state, [options[0].value]);
314
+ continue;
315
+ }
316
+ return {
317
+ type: "nextQuestion",
318
+ questionSlug: step.slug,
319
+ question: step.question[ctx.language],
320
+ questionType: "multiSelect",
321
+ options
322
+ };
323
+ }
324
+ const dataInvestigationResult = await flow.finalize(state, runtime);
325
+ return { type: "fulfilled", dataInvestigationResult };
326
+ }
327
+
275
328
  // ../connectors/src/auth-types.ts
276
329
  var AUTH_TYPES = {
277
330
  OAUTH: "oauth",
@@ -433,6 +486,125 @@ var parameters = {
433
486
  })
434
487
  };
435
488
 
489
+ // ../connectors/src/connectors/snowflake/setup-flow.ts
490
+ var ALL_TABLES = "__ALL_TABLES__";
491
+ var INTERNAL_SCHEMAS = /* @__PURE__ */ new Set([
492
+ "INFORMATION_SCHEMA",
493
+ "ACCOUNT_USAGE",
494
+ "READER_ACCOUNT_USAGE",
495
+ "DATA_SHARING_USAGE"
496
+ ]);
497
+ function createSnowflakeSetupFlow(runQuery3) {
498
+ return {
499
+ initialState: () => ({}),
500
+ steps: [
501
+ {
502
+ slug: "database",
503
+ type: "multiSelect",
504
+ autoSelectIfSingle: true,
505
+ question: {
506
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF081 \u4EF6\u306E\u307F\uFF09",
507
+ en: "Select the database to use for setup (pick one)"
508
+ },
509
+ async fetchOptions(_state, rt) {
510
+ const rows = await runQuery3(rt.params, "SHOW DATABASES");
511
+ return rows.map((r) => String(r["name"] ?? "")).filter((name) => name && !name.endsWith("_SHARE")).map((value) => ({ value }));
512
+ },
513
+ applyAnswer: (state, answer) => ({ ...state, database: answer[0] })
514
+ },
515
+ {
516
+ slug: "schema",
517
+ type: "multiSelect",
518
+ autoSelectIfSingle: true,
519
+ question: {
520
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u30B9\u30AD\u30FC\u30DE\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF081 \u4EF6\u306E\u307F\uFF09",
521
+ en: "Select the schema to use for setup (pick one)"
522
+ },
523
+ async fetchOptions(state, rt) {
524
+ if (!state.database) return [];
525
+ const rows = await runQuery3(
526
+ rt.params,
527
+ `SHOW SCHEMAS IN DATABASE "${state.database}"`
528
+ );
529
+ return rows.map((r) => String(r["name"] ?? "")).filter(
530
+ (name) => name && !INTERNAL_SCHEMAS.has(name.toUpperCase())
531
+ ).map((value) => ({ value }));
532
+ },
533
+ applyAnswer: (state, answer) => ({ ...state, schema: answer[0] })
534
+ },
535
+ {
536
+ slug: "tables",
537
+ type: "multiSelect",
538
+ question: {
539
+ ja: "\u5BFE\u8C61\u30C6\u30FC\u30D6\u30EB\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
540
+ en: "Select target tables (multi-select allowed)"
541
+ },
542
+ async fetchOptions(state, rt) {
543
+ if (!state.database || !state.schema) return [];
544
+ const rows = await runQuery3(
545
+ rt.params,
546
+ `SHOW TABLES IN SCHEMA "${state.database}"."${state.schema}"`
547
+ );
548
+ const tableOptions = rows.map((r) => String(r["name"] ?? "")).filter((name) => name).map((value) => ({ value }));
549
+ return [
550
+ {
551
+ value: ALL_TABLES,
552
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C6\u30FC\u30D6\u30EB" : "All tables"
553
+ },
554
+ ...tableOptions
555
+ ];
556
+ },
557
+ applyAnswer: (state, answer) => ({ ...state, tables: answer })
558
+ }
559
+ ],
560
+ async finalize(state, rt) {
561
+ if (!state.database || !state.schema || !state.tables) {
562
+ throw new Error("Snowflake setup: incomplete state on finalize");
563
+ }
564
+ const db = state.database;
565
+ const schema = state.schema;
566
+ let targetTables;
567
+ if (state.tables.includes(ALL_TABLES)) {
568
+ const rows = await runQuery3(
569
+ rt.params,
570
+ `SHOW TABLES IN SCHEMA "${db}"."${schema}"`
571
+ );
572
+ targetTables = rows.map((r) => String(r["name"] ?? "")).filter((name) => name);
573
+ } else {
574
+ targetTables = state.tables.filter((t) => t !== ALL_TABLES);
575
+ }
576
+ const sections = [
577
+ "## Snowflake",
578
+ "",
579
+ `### Database: ${db}`,
580
+ "",
581
+ `#### Schema: ${schema}`,
582
+ ""
583
+ ];
584
+ for (const table of targetTables) {
585
+ const cols = await runQuery3(
586
+ rt.params,
587
+ `DESCRIBE TABLE "${db}"."${schema}"."${table}"`
588
+ );
589
+ sections.push(`##### Table: ${table}`, "");
590
+ sections.push("| Column | Type | Nullable | Default |");
591
+ sections.push("|--------|------|----------|---------|");
592
+ for (const c of cols) {
593
+ const name = String(c["name"] ?? "");
594
+ const type = String(c["type"] ?? "");
595
+ const nullable = String(c["null?"] ?? "");
596
+ const defaultValue = c["default"] == null ? "-" : String(c["default"]);
597
+ sections.push(
598
+ `| ${name} | ${type} | ${nullable} | ${defaultValue} |`
599
+ );
600
+ }
601
+ sections.push("");
602
+ }
603
+ return sections.join("\n");
604
+ }
605
+ };
606
+ }
607
+
436
608
  // ../connectors/src/connectors/snowflake/tools/execute-query.ts
437
609
  import { z } from "zod";
438
610
 
@@ -477,6 +649,49 @@ function decryptPrivateKey(pem, passphrase) {
477
649
  passphrase
478
650
  }).export({ type: "pkcs8", format: "pem" });
479
651
  }
652
+ async function runQuery(params, sql) {
653
+ const snowflake = (await import("snowflake-sdk")).default;
654
+ snowflake.configure({ logLevel: "ERROR" });
655
+ const privateKeyPem = Buffer.from(
656
+ params[parameters.privateKeyBase64.slug],
657
+ "base64"
658
+ ).toString("utf-8");
659
+ const privateKeyPass = params[parameters.privateKeyPassphrase.slug] || void 0;
660
+ const privateKey = decryptPrivateKey(privateKeyPem, privateKeyPass);
661
+ const conn = snowflake.createConnection({
662
+ account: params[parameters.account.slug],
663
+ username: params[parameters.user.slug],
664
+ role: params[parameters.role.slug],
665
+ warehouse: params[parameters.warehouse.slug],
666
+ authenticator: "SNOWFLAKE_JWT",
667
+ privateKey
668
+ });
669
+ await new Promise((resolve, reject) => {
670
+ conn.connect((err) => {
671
+ if (err) reject(new Error(`Snowflake connect failed: ${err.message}`));
672
+ else resolve();
673
+ });
674
+ });
675
+ try {
676
+ return await new Promise((resolve, reject) => {
677
+ conn.execute({
678
+ sqlText: sql,
679
+ complete: (err, _stmt, rows) => {
680
+ if (err) reject(new Error(`Snowflake query failed: ${err.message}`));
681
+ else resolve(rows ?? []);
682
+ }
683
+ });
684
+ });
685
+ } finally {
686
+ conn.destroy((err) => {
687
+ if (err) {
688
+ console.warn(
689
+ `[connector-query] Snowflake destroy error: ${err.message}`
690
+ );
691
+ }
692
+ });
693
+ }
694
+ }
480
695
  async function executeWithSizeLimit(conn, sql, options) {
481
696
  const rows = [];
482
697
  let acc = 0;
@@ -631,6 +846,7 @@ Memory guidance:
631
846
  });
632
847
 
633
848
  // ../connectors/src/connectors/snowflake/index.ts
849
+ var snowflakeSetupFlow = createSnowflakeSetupFlow(runQuery);
634
850
  var tools = { executeQuery: executeQueryTool };
635
851
  var snowflakeConnector = new ConnectorPlugin({
636
852
  slug: "snowflake",
@@ -677,6 +893,7 @@ The business logic type for this connector is "sql".
677
893
  - INFORMATION_SCHEMA \u3082\u5229\u7528\u53EF\u80FD: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``
678
894
  },
679
895
  tools,
896
+ setup: (params, ctx, config) => runSetupFlow(snowflakeSetupFlow, params, ctx, config),
680
897
  async checkConnection(params, _config) {
681
898
  try {
682
899
  const snowflake = (await import("snowflake-sdk")).default;
@@ -809,6 +1026,47 @@ var parameters2 = {
809
1026
  })
810
1027
  };
811
1028
 
1029
+ // ../connectors/src/connectors/snowflake-pat/utils.ts
1030
+ async function runQuery2(params, sql) {
1031
+ const snowflake = (await import("snowflake-sdk")).default;
1032
+ snowflake.configure({ logLevel: "ERROR" });
1033
+ const conn = snowflake.createConnection({
1034
+ account: params[parameters2.account.slug],
1035
+ username: params[parameters2.user.slug],
1036
+ role: params[parameters2.role.slug],
1037
+ warehouse: params[parameters2.warehouse.slug],
1038
+ password: params[parameters2.pat.slug]
1039
+ });
1040
+ await new Promise((resolve, reject) => {
1041
+ conn.connect((err) => {
1042
+ if (err) reject(new Error(`Snowflake connect failed: ${err.message}`));
1043
+ else resolve();
1044
+ });
1045
+ });
1046
+ try {
1047
+ return await new Promise((resolve, reject) => {
1048
+ conn.execute({
1049
+ sqlText: sql,
1050
+ complete: (err, _stmt, rows) => {
1051
+ if (err) reject(new Error(`Snowflake query failed: ${err.message}`));
1052
+ else resolve(rows ?? []);
1053
+ }
1054
+ });
1055
+ });
1056
+ } finally {
1057
+ conn.destroy((err) => {
1058
+ if (err) {
1059
+ console.warn(
1060
+ `[connector-query] Snowflake destroy error: ${err.message}`
1061
+ );
1062
+ }
1063
+ });
1064
+ }
1065
+ }
1066
+
1067
+ // ../connectors/src/connectors/snowflake-pat/setup-flow.ts
1068
+ var snowflakePatSetupFlow = createSnowflakeSetupFlow(runQuery2);
1069
+
812
1070
  // ../connectors/src/connectors/snowflake-pat/tools/execute-query.ts
813
1071
  import { z as z2 } from "zod";
814
1072
  var MAX_ROWS = 500;
@@ -961,6 +1219,7 @@ The business logic type for this connector is "sql".
961
1219
  - INFORMATION_SCHEMA \u3082\u5229\u7528\u53EF\u80FD: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``
962
1220
  },
963
1221
  tools: tools2,
1222
+ setup: (params, ctx, config) => runSetupFlow(snowflakePatSetupFlow, params, ctx, config),
964
1223
  async checkConnection(params, _config) {
965
1224
  try {
966
1225
  const snowflake = (await import("snowflake-sdk")).default;
@@ -28036,6 +28295,10 @@ import { z as z98 } from "zod";
28036
28295
  var DEFAULT_API_VERSION = "3.28";
28037
28296
  var REQUEST_TIMEOUT_MS75 = 6e4;
28038
28297
  var sessionCache = /* @__PURE__ */ new Map();
28298
+ var inFlightSignIns = /* @__PURE__ */ new Map();
28299
+ function sessionCacheKey(serverUrl, siteContentUrl, patName) {
28300
+ return `${serverUrl}|${siteContentUrl}|${patName}`;
28301
+ }
28039
28302
  function buildBaseUrl4(serverUrl, apiVersion) {
28040
28303
  return `${serverUrl.replace(/\/$/, "")}/api/${apiVersion}`;
28041
28304
  }
@@ -28070,21 +28333,39 @@ async function signIn(serverUrl, apiVersion, siteContentUrl, patName, patSecret)
28070
28333
  expiresAt: Date.now() + 30 * 60 * 1e3
28071
28334
  };
28072
28335
  }
28073
- async function getSession(serverUrl, apiVersion, siteContentUrl, patName, patSecret) {
28074
- const cacheKey = `${serverUrl}|${siteContentUrl}|${patName}`;
28075
- const cached = sessionCache.get(cacheKey);
28076
- if (cached && cached.expiresAt > Date.now() + 6e4) {
28077
- return cached;
28336
+ async function getSession(serverUrl, apiVersion, siteContentUrl, patName, patSecret, { forceRefresh = false } = {}) {
28337
+ const cacheKey = sessionCacheKey(serverUrl, siteContentUrl, patName);
28338
+ if (forceRefresh) {
28339
+ sessionCache.delete(cacheKey);
28340
+ } else {
28341
+ const cached = sessionCache.get(cacheKey);
28342
+ if (cached && cached.expiresAt > Date.now() + 6e4) {
28343
+ return cached;
28344
+ }
28078
28345
  }
28079
- const session = await signIn(
28346
+ const existing = inFlightSignIns.get(cacheKey);
28347
+ if (existing) return existing;
28348
+ const promise = signIn(
28080
28349
  serverUrl,
28081
28350
  apiVersion,
28082
28351
  siteContentUrl,
28083
28352
  patName,
28084
28353
  patSecret
28085
- );
28086
- sessionCache.set(cacheKey, session);
28087
- return session;
28354
+ ).then((session) => {
28355
+ sessionCache.set(cacheKey, session);
28356
+ return session;
28357
+ }).finally(() => {
28358
+ inFlightSignIns.delete(cacheKey);
28359
+ });
28360
+ inFlightSignIns.set(cacheKey, promise);
28361
+ return promise;
28362
+ }
28363
+ function invalidateSession(serverUrl, siteContentUrl, patName, staleAuthToken) {
28364
+ const cacheKey = sessionCacheKey(serverUrl, siteContentUrl, patName);
28365
+ const current = sessionCache.get(cacheKey);
28366
+ if (current && current.authToken === staleAuthToken) {
28367
+ sessionCache.delete(cacheKey);
28368
+ }
28088
28369
  }
28089
28370
  var inputSchema98 = z98.object({
28090
28371
  toolUseIntent: z98.string().optional().describe(
@@ -28140,48 +28421,64 @@ Accept and Content-Type headers default to application/json so list responses co
28140
28421
  const patName = parameters81.patName.getValue(connection);
28141
28422
  const patSecret = parameters81.patSecret.getValue(connection);
28142
28423
  const apiVersion = parameters81.apiVersion.tryGetValue(connection) || DEFAULT_API_VERSION;
28143
- const session = await getSession(
28144
- serverUrl,
28145
- apiVersion,
28146
- siteContentUrl,
28147
- patName,
28148
- patSecret
28149
- );
28150
- const resolvedPath = path5.trim().replace(/\{siteId\}/g, session.siteId).replace(/^([^/])/, "/$1");
28151
- let url = `${buildBaseUrl4(serverUrl, apiVersion)}${resolvedPath}`;
28152
- if (queryParams) {
28153
- const searchParams = new URLSearchParams(queryParams);
28154
- url += `?${searchParams.toString()}`;
28155
- }
28424
+ const trimmedPath = path5.trim().replace(/^([^/])/, "/$1");
28425
+ const queryString = queryParams ? `?${new URLSearchParams(queryParams).toString()}` : "";
28426
+ const baseUrl = buildBaseUrl4(serverUrl, apiVersion);
28156
28427
  const controller = new AbortController();
28157
28428
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS75);
28158
28429
  try {
28159
- const init = {
28160
- method,
28161
- headers: {
28162
- "X-Tableau-Auth": session.authToken,
28163
- Accept: "application/json",
28164
- "Content-Type": "application/json"
28165
- },
28166
- signal: controller.signal
28167
- };
28168
- if (body !== void 0) {
28169
- init.body = JSON.stringify(body);
28170
- }
28171
- const response = await fetch(url, init);
28172
- const text = await response.text();
28173
- const data = text ? (() => {
28174
- try {
28175
- return JSON.parse(text);
28176
- } catch {
28177
- return text;
28430
+ let attempt = 0;
28431
+ while (true) {
28432
+ const session = await getSession(
28433
+ serverUrl,
28434
+ apiVersion,
28435
+ siteContentUrl,
28436
+ patName,
28437
+ patSecret,
28438
+ { forceRefresh: attempt > 0 }
28439
+ );
28440
+ const resolvedPath = trimmedPath.replace(
28441
+ /\{siteId\}/g,
28442
+ session.siteId
28443
+ );
28444
+ const url = `${baseUrl}${resolvedPath}${queryString}`;
28445
+ const init = {
28446
+ method,
28447
+ headers: {
28448
+ "X-Tableau-Auth": session.authToken,
28449
+ Accept: "application/json",
28450
+ "Content-Type": "application/json"
28451
+ },
28452
+ signal: controller.signal
28453
+ };
28454
+ if (body !== void 0) {
28455
+ init.body = JSON.stringify(body);
28178
28456
  }
28179
- })() : null;
28180
- if (!response.ok) {
28181
- const errorMessage = data && typeof data === "object" && "error" in data ? JSON.stringify(data.error) : typeof data === "string" && data ? data : `HTTP ${response.status} ${response.statusText}`;
28182
- return { success: false, error: errorMessage };
28457
+ const response = await fetch(url, init);
28458
+ const text = await response.text();
28459
+ const data = text ? (() => {
28460
+ try {
28461
+ return JSON.parse(text);
28462
+ } catch {
28463
+ return text;
28464
+ }
28465
+ })() : null;
28466
+ if (response.status === 401 && attempt === 0) {
28467
+ invalidateSession(
28468
+ serverUrl,
28469
+ siteContentUrl,
28470
+ patName,
28471
+ session.authToken
28472
+ );
28473
+ attempt++;
28474
+ continue;
28475
+ }
28476
+ if (!response.ok) {
28477
+ const errorMessage = data && typeof data === "object" && "error" in data ? JSON.stringify(data.error) : typeof data === "string" && data ? data : `HTTP ${response.status} ${response.statusText}`;
28478
+ return { success: false, error: errorMessage };
28479
+ }
28480
+ return { success: true, status: response.status, data };
28183
28481
  }
28184
- return { success: true, status: response.status, data };
28185
28482
  } finally {
28186
28483
  clearTimeout(timeout);
28187
28484
  }
@@ -126,6 +126,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
126
126
  tools;
127
127
  query;
128
128
  checkConnection;
129
+ /**
130
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
131
+ * implement this expose a step-by-step exploration flow (database/schema/
132
+ * table/etc. discovery) that the dashboard backend drives via the
133
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
134
+ * `runSetupFlow` from `setup-flow.ts`.
135
+ */
136
+ setup;
129
137
  constructor(config) {
130
138
  this.slug = config.slug;
131
139
  this.authType = config.authType;
@@ -142,6 +150,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
142
150
  this.tools = config.tools;
143
151
  this.query = config.query;
144
152
  this.checkConnection = config.checkConnection;
153
+ this.setup = config.setup;
145
154
  }
146
155
  get connectorKey() {
147
156
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -256,6 +256,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
256
256
  tools;
257
257
  query;
258
258
  checkConnection;
259
+ /**
260
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
261
+ * implement this expose a step-by-step exploration flow (database/schema/
262
+ * table/etc. discovery) that the dashboard backend drives via the
263
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
264
+ * `runSetupFlow` from `setup-flow.ts`.
265
+ */
266
+ setup;
259
267
  constructor(config) {
260
268
  this.slug = config.slug;
261
269
  this.authType = config.authType;
@@ -272,6 +280,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
272
280
  this.tools = config.tools;
273
281
  this.query = config.query;
274
282
  this.checkConnection = config.checkConnection;
283
+ this.setup = config.setup;
275
284
  }
276
285
  get connectorKey() {
277
286
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -216,6 +216,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
216
216
  tools;
217
217
  query;
218
218
  checkConnection;
219
+ /**
220
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
221
+ * implement this expose a step-by-step exploration flow (database/schema/
222
+ * table/etc. discovery) that the dashboard backend drives via the
223
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
224
+ * `runSetupFlow` from `setup-flow.ts`.
225
+ */
226
+ setup;
219
227
  constructor(config) {
220
228
  this.slug = config.slug;
221
229
  this.authType = config.authType;
@@ -232,6 +240,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
232
240
  this.tools = config.tools;
233
241
  this.query = config.query;
234
242
  this.checkConnection = config.checkConnection;
243
+ this.setup = config.setup;
235
244
  }
236
245
  get connectorKey() {
237
246
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -83,6 +83,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
83
83
  tools;
84
84
  query;
85
85
  checkConnection;
86
+ /**
87
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
88
+ * implement this expose a step-by-step exploration flow (database/schema/
89
+ * table/etc. discovery) that the dashboard backend drives via the
90
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
91
+ * `runSetupFlow` from `setup-flow.ts`.
92
+ */
93
+ setup;
86
94
  constructor(config) {
87
95
  this.slug = config.slug;
88
96
  this.authType = config.authType;
@@ -99,6 +107,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
99
107
  this.tools = config.tools;
100
108
  this.query = config.query;
101
109
  this.checkConnection = config.checkConnection;
110
+ this.setup = config.setup;
102
111
  }
103
112
  get connectorKey() {
104
113
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -253,6 +253,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
253
253
  tools;
254
254
  query;
255
255
  checkConnection;
256
+ /**
257
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
258
+ * implement this expose a step-by-step exploration flow (database/schema/
259
+ * table/etc. discovery) that the dashboard backend drives via the
260
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
261
+ * `runSetupFlow` from `setup-flow.ts`.
262
+ */
263
+ setup;
256
264
  constructor(config) {
257
265
  this.slug = config.slug;
258
266
  this.authType = config.authType;
@@ -269,6 +277,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
269
277
  this.tools = config.tools;
270
278
  this.query = config.query;
271
279
  this.checkConnection = config.checkConnection;
280
+ this.setup = config.setup;
272
281
  }
273
282
  get connectorKey() {
274
283
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -389,6 +389,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
389
389
  tools;
390
390
  query;
391
391
  checkConnection;
392
+ /**
393
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
394
+ * implement this expose a step-by-step exploration flow (database/schema/
395
+ * table/etc. discovery) that the dashboard backend drives via the
396
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
397
+ * `runSetupFlow` from `setup-flow.ts`.
398
+ */
399
+ setup;
392
400
  constructor(config) {
393
401
  this.slug = config.slug;
394
402
  this.authType = config.authType;
@@ -405,6 +413,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
405
413
  this.tools = config.tools;
406
414
  this.query = config.query;
407
415
  this.checkConnection = config.checkConnection;
416
+ this.setup = config.setup;
408
417
  }
409
418
  get connectorKey() {
410
419
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -155,6 +155,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
155
155
  tools;
156
156
  query;
157
157
  checkConnection;
158
+ /**
159
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
160
+ * implement this expose a step-by-step exploration flow (database/schema/
161
+ * table/etc. discovery) that the dashboard backend drives via the
162
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
163
+ * `runSetupFlow` from `setup-flow.ts`.
164
+ */
165
+ setup;
158
166
  constructor(config) {
159
167
  this.slug = config.slug;
160
168
  this.authType = config.authType;
@@ -171,6 +179,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
171
179
  this.tools = config.tools;
172
180
  this.query = config.query;
173
181
  this.checkConnection = config.checkConnection;
182
+ this.setup = config.setup;
174
183
  }
175
184
  get connectorKey() {
176
185
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -405,6 +405,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
405
405
  tools;
406
406
  query;
407
407
  checkConnection;
408
+ /**
409
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
410
+ * implement this expose a step-by-step exploration flow (database/schema/
411
+ * table/etc. discovery) that the dashboard backend drives via the
412
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
413
+ * `runSetupFlow` from `setup-flow.ts`.
414
+ */
415
+ setup;
408
416
  constructor(config) {
409
417
  this.slug = config.slug;
410
418
  this.authType = config.authType;
@@ -421,6 +429,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
421
429
  this.tools = config.tools;
422
430
  this.query = config.query;
423
431
  this.checkConnection = config.checkConnection;
432
+ this.setup = config.setup;
424
433
  }
425
434
  get connectorKey() {
426
435
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);