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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/cli/index.js +12128 -934
  2. package/dist/connectors/airtable-oauth.js +248 -46
  3. package/dist/connectors/airtable.js +285 -51
  4. package/dist/connectors/amplitude.js +288 -47
  5. package/dist/connectors/anthropic.js +126 -47
  6. package/dist/connectors/asana.js +293 -49
  7. package/dist/connectors/attio.js +268 -49
  8. package/dist/connectors/aws-billing.js +253 -46
  9. package/dist/connectors/azure-sql.js +387 -102
  10. package/dist/connectors/backlog-api-key.js +283 -47
  11. package/dist/connectors/clickup.js +304 -49
  12. package/dist/connectors/cosmosdb.js +271 -50
  13. package/dist/connectors/customerio.js +285 -47
  14. package/dist/connectors/dbt.js +306 -47
  15. package/dist/connectors/freshdesk.js +308 -53
  16. package/dist/connectors/freshsales.js +299 -52
  17. package/dist/connectors/freshservice.js +327 -53
  18. package/dist/connectors/gamma.js +293 -52
  19. package/dist/connectors/gemini.js +125 -47
  20. package/dist/connectors/github.js +352 -49
  21. package/dist/connectors/gmail-oauth.js +170 -7
  22. package/dist/connectors/gmail.js +316 -47
  23. package/dist/connectors/google-ads.js +254 -46
  24. package/dist/connectors/google-analytics-oauth.js +276 -46
  25. package/dist/connectors/google-analytics.js +378 -49
  26. package/dist/connectors/google-audit-log.js +404 -47
  27. package/dist/connectors/google-calendar-oauth.js +225 -46
  28. package/dist/connectors/google-calendar.js +325 -47
  29. package/dist/connectors/google-docs.js +186 -6
  30. package/dist/connectors/google-drive.js +228 -5
  31. package/dist/connectors/google-search-console-oauth.js +222 -46
  32. package/dist/connectors/google-sheets.js +238 -47
  33. package/dist/connectors/google-slides.js +171 -6
  34. package/dist/connectors/grafana.js +298 -49
  35. package/dist/connectors/hubspot-oauth.js +174 -5
  36. package/dist/connectors/hubspot.js +272 -49
  37. package/dist/connectors/influxdb.js +382 -51
  38. package/dist/connectors/intercom-oauth.js +176 -5
  39. package/dist/connectors/intercom.js +268 -49
  40. package/dist/connectors/jdbc.js +728 -110
  41. package/dist/connectors/jira-api-key.js +292 -47
  42. package/dist/connectors/kintone-api-token.js +247 -47
  43. package/dist/connectors/kintone.js +294 -47
  44. package/dist/connectors/linear.js +296 -49
  45. package/dist/connectors/linkedin-ads.js +234 -50
  46. package/dist/connectors/mailchimp-oauth.js +234 -46
  47. package/dist/connectors/mailchimp.js +286 -49
  48. package/dist/connectors/meta-ads-oauth.js +239 -48
  49. package/dist/connectors/meta-ads.js +251 -50
  50. package/dist/connectors/mixpanel.js +304 -47
  51. package/dist/connectors/monday.js +326 -49
  52. package/dist/connectors/mongodb.js +285 -57
  53. package/dist/connectors/notion-oauth.js +197 -5
  54. package/dist/connectors/notion.js +289 -51
  55. package/dist/connectors/openai.js +125 -47
  56. package/dist/connectors/oracle.js +405 -103
  57. package/dist/connectors/outlook-oauth.js +170 -5
  58. package/dist/connectors/powerbi-oauth.js +217 -5
  59. package/dist/connectors/salesforce.js +350 -49
  60. package/dist/connectors/semrush.js +280 -49
  61. package/dist/connectors/sentry.js +255 -50
  62. package/dist/connectors/shopify-oauth.js +153 -5
  63. package/dist/connectors/shopify.js +323 -47
  64. package/dist/connectors/sqlserver.js +381 -102
  65. package/dist/connectors/stripe-api-key.js +235 -46
  66. package/dist/connectors/stripe-oauth.js +168 -5
  67. package/dist/connectors/supabase.js +269 -48
  68. package/dist/connectors/tableau.js +337 -206
  69. package/dist/connectors/tiktok-ads.js +245 -48
  70. package/dist/connectors/wix-store.js +286 -49
  71. package/dist/connectors/zendesk-oauth.js +205 -5
  72. package/dist/connectors/zendesk.js +324 -47
  73. package/dist/index.d.ts +149 -1
  74. package/dist/index.js +18297 -6886
  75. package/dist/main.js +12785 -1382
  76. package/dist/vite-plugin.js +12140 -936
  77. package/package.json +1 -1
@@ -193,6 +193,20 @@ var ConnectorPlugin = class _ConnectorPlugin {
193
193
  * `runSetupFlow` from `setup-flow.ts`.
194
194
  */
195
195
  setup;
196
+ /**
197
+ * Opt-out of the default "verify before save" behavior on connection
198
+ * creation. The backend invokes `checkConnection` synchronously while
199
+ * creating the connection and aborts (no row inserted) if it fails — this
200
+ * flag disables that for connectors where the check cannot succeed pre-save:
201
+ *
202
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
203
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
204
+ * connectionId, which doesn't exist until the row is saved
205
+ *
206
+ * Exceptions are the explicit position; new credential-input connectors get
207
+ * the default verify-on-create behavior without opt-in.
208
+ */
209
+ skipConnectionCheckOnCreate;
196
210
  constructor(config) {
197
211
  this.slug = config.slug;
198
212
  this.authType = config.authType;
@@ -210,6 +224,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
210
224
  this.query = config.query;
211
225
  this.checkConnection = config.checkConnection;
212
226
  this.setup = config.setup;
227
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
213
228
  }
214
229
  get connectorKey() {
215
230
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -274,6 +289,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
274
289
  }
275
290
  };
276
291
 
292
+ // ../connectors/src/setup-flow.ts
293
+ async function runSetupFlow(flow, params, ctx, config) {
294
+ const runtime = {
295
+ params,
296
+ language: ctx.language,
297
+ config
298
+ };
299
+ let state = flow.initialState();
300
+ let answerIdx = 0;
301
+ for (const step of flow.steps) {
302
+ const ans = ctx.answers[answerIdx];
303
+ if (ans && ans.questionSlug === step.slug) {
304
+ state = step.applyAnswer(state, ans.answer);
305
+ answerIdx += 1;
306
+ continue;
307
+ }
308
+ if (step.type === "text") {
309
+ return {
310
+ type: "nextQuestion",
311
+ questionSlug: step.slug,
312
+ question: step.question[ctx.language],
313
+ questionType: "text"
314
+ };
315
+ }
316
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
317
+ if (options.length === 0) {
318
+ continue;
319
+ }
320
+ return {
321
+ type: "nextQuestion",
322
+ questionSlug: step.slug,
323
+ question: step.question[ctx.language],
324
+ questionType: step.type,
325
+ options
326
+ };
327
+ }
328
+ const dataInvestigationResult = await flow.finalize(state, runtime);
329
+ return { type: "fulfilled", dataInvestigationResult };
330
+ }
331
+ async function resolveSetupSelection(params) {
332
+ const { selected, allSentinel, fetchAll, limit } = params;
333
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
334
+ return resolved.slice(0, limit);
335
+ }
336
+
277
337
  // ../connectors/src/auth-types.ts
278
338
  var AUTH_TYPES = {
279
339
  OAUTH: "oauth",
@@ -472,6 +532,89 @@ Calendar
472
532
  }
473
533
  });
474
534
 
535
+ // ../connectors/src/connectors/outlook-oauth/utils.ts
536
+ async function graphApiFetch(config, url) {
537
+ const res = await config.proxyFetch(url, { method: "GET" });
538
+ if (!res.ok) {
539
+ const text = await res.text().catch(() => res.statusText);
540
+ throw new Error(`Microsoft Graph ${url} failed: HTTP ${res.status} ${text}`);
541
+ }
542
+ return await res.json();
543
+ }
544
+
545
+ // ../connectors/src/connectors/outlook-oauth/setup-flow.ts
546
+ var ALL_FOLDERS = "__ALL_FOLDERS__";
547
+ var OUTLOOK_SETUP_MAX_FOLDERS = 20;
548
+ async function listMailFolders(config) {
549
+ const url = "https://graph.microsoft.com/v1.0/me/mailFolders?$top=100&$select=id,displayName,parentFolderId,childFolderCount,unreadItemCount,totalItemCount";
550
+ const data = await graphApiFetch(config, url);
551
+ return data.value ?? [];
552
+ }
553
+ var outlookOauthSetupFlow = {
554
+ initialState: () => ({}),
555
+ steps: [
556
+ {
557
+ slug: "folders",
558
+ type: "multiSelect",
559
+ question: {
560
+ ja: "\u5BFE\u8C61\u306E\u30E1\u30FC\u30EB\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
561
+ en: "Select target mail folders (multi-select allowed)"
562
+ },
563
+ async fetchOptions(_state, rt) {
564
+ const folders = await listMailFolders(rt.config);
565
+ return [
566
+ {
567
+ value: ALL_FOLDERS,
568
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30D5\u30A9\u30EB\u30C0" : "All folders"
569
+ },
570
+ ...folders.map((f) => ({
571
+ value: f.id,
572
+ label: f.displayName ?? f.id
573
+ }))
574
+ ];
575
+ },
576
+ applyAnswer: (state, answer) => ({ ...state, folders: answer })
577
+ }
578
+ ],
579
+ async finalize(state, rt) {
580
+ if (!state.folders) {
581
+ throw new Error("Outlook setup: incomplete state on finalize");
582
+ }
583
+ const folders = await listMailFolders(rt.config);
584
+ const byId = new Map(folders.map((f) => [f.id, f]));
585
+ const targetIds = await resolveSetupSelection({
586
+ selected: state.folders,
587
+ allSentinel: ALL_FOLDERS,
588
+ fetchAll: async () => folders.map((f) => f.id),
589
+ limit: OUTLOOK_SETUP_MAX_FOLDERS
590
+ });
591
+ const sections = ["## Outlook", ""];
592
+ if (targetIds.length === 0) {
593
+ sections.push(
594
+ rt.language === "ja" ? "\u5BFE\u8C61\u306E\u30D5\u30A9\u30EB\u30C0\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002" : "No folders selected."
595
+ );
596
+ return sections.join("\n");
597
+ }
598
+ sections.push("| Folder | Total | Unread | Sub-folders |");
599
+ sections.push("|--------|-------|--------|-------------|");
600
+ for (const id of targetIds) {
601
+ const f = byId.get(id);
602
+ if (!f) {
603
+ sections.push(`| ${id} | - | - | - |`);
604
+ continue;
605
+ }
606
+ const total = f.totalItemCount ?? "-";
607
+ const unread = f.unreadItemCount ?? "-";
608
+ const subs = f.childFolderCount ?? 0;
609
+ sections.push(
610
+ `| ${f.displayName ?? id} | ${total} | ${unread} | ${subs} |`
611
+ );
612
+ }
613
+ sections.push("");
614
+ return sections.join("\n");
615
+ }
616
+ };
617
+
475
618
  // ../connectors/src/connectors/outlook-oauth/parameters.ts
476
619
  var parameters = {};
477
620
 
@@ -480,6 +623,7 @@ var tools = { request: requestTool };
480
623
  var outlookOauthConnector = new ConnectorPlugin({
481
624
  slug: "outlook",
482
625
  authType: AUTH_TYPES.OAUTH,
626
+ skipConnectionCheckOnCreate: true,
483
627
  name: "Outlook",
484
628
  description: "Connect to Microsoft Outlook (Mail + Calendar) via Microsoft Graph using OAuth. Read-only access to the user's mailbox, mail folders, messages, attachments, calendars, and events.",
485
629
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/1J1FrRTYJjOh3CcSIqsz3I/6a467b4d926075ff99dc60820e0ae4b1/Microsoft_Outlook_Icon__2025%C3%A2__present_.svg",
@@ -764,6 +908,7 @@ events.value.forEach(e => console.log(e.start.dateTime, e.subject));
764
908
  \`\`\``
765
909
  },
766
910
  tools,
911
+ setup: (params, ctx, config) => runSetupFlow(outlookOauthSetupFlow, params, ctx, config),
767
912
  async checkConnection(_params, config) {
768
913
  const { proxyFetch } = config;
769
914
  const url = "https://graph.microsoft.com/v1.0/me";
@@ -812,6 +957,7 @@ function resolveEnvVarOptional(entry, key) {
812
957
  import { getContext } from "hono/context-storage";
813
958
  import { getCookie } from "hono/cookie";
814
959
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
960
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
815
961
  function normalizeHeaders(input) {
816
962
  const out = {};
817
963
  if (!input) return out;
@@ -820,6 +966,11 @@ function normalizeHeaders(input) {
820
966
  });
821
967
  return out;
822
968
  }
969
+ function extractInputUrl(input) {
970
+ if (typeof input === "string") return input;
971
+ if (input instanceof URL) return input.href;
972
+ return input.url;
973
+ }
823
974
  function createSandboxProxyFetch(connectionId) {
824
975
  return async (input, init) => {
825
976
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -829,10 +980,17 @@ function createSandboxProxyFetch(connectionId) {
829
980
  "Connection proxy is not configured. Please check your deployment settings."
830
981
  );
831
982
  }
832
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
983
+ const originalUrl = extractInputUrl(input);
984
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
985
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
986
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
987
+ return fetch(sessionUrl, {
988
+ method: "POST",
989
+ headers: { Authorization: `Bearer ${token}` }
990
+ });
991
+ }
833
992
  const originalMethod = init?.method ?? "GET";
834
993
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
835
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
836
994
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
837
995
  return fetch(proxyUrl, {
838
996
  method: "POST",
@@ -858,10 +1016,9 @@ function createDeployedAppProxyFetch(connectionId) {
858
1016
  }
859
1017
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
860
1018
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
1019
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
861
1020
  return async (input, init) => {
862
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
863
- const originalMethod = init?.method ?? "GET";
864
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
1021
+ const originalUrl = extractInputUrl(input);
865
1022
  const c = getContext();
866
1023
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
867
1024
  if (!appSession) {
@@ -869,6 +1026,14 @@ function createDeployedAppProxyFetch(connectionId) {
869
1026
  "No authentication method available for connection proxy."
870
1027
  );
871
1028
  }
1029
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1030
+ return fetch(sessionUrl, {
1031
+ method: "POST",
1032
+ headers: { Authorization: `Bearer ${appSession}` }
1033
+ });
1034
+ }
1035
+ const originalMethod = init?.method ?? "GET";
1036
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
872
1037
  return fetch(proxyUrl, {
873
1038
  method: "POST",
874
1039
  headers: {
@@ -151,6 +151,20 @@ var ConnectorPlugin = class _ConnectorPlugin {
151
151
  * `runSetupFlow` from `setup-flow.ts`.
152
152
  */
153
153
  setup;
154
+ /**
155
+ * Opt-out of the default "verify before save" behavior on connection
156
+ * creation. The backend invokes `checkConnection` synchronously while
157
+ * creating the connection and aborts (no row inserted) if it fails — this
158
+ * flag disables that for connectors where the check cannot succeed pre-save:
159
+ *
160
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
161
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
162
+ * connectionId, which doesn't exist until the row is saved
163
+ *
164
+ * Exceptions are the explicit position; new credential-input connectors get
165
+ * the default verify-on-create behavior without opt-in.
166
+ */
167
+ skipConnectionCheckOnCreate;
154
168
  constructor(config) {
155
169
  this.slug = config.slug;
156
170
  this.authType = config.authType;
@@ -168,6 +182,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
168
182
  this.query = config.query;
169
183
  this.checkConnection = config.checkConnection;
170
184
  this.setup = config.setup;
185
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
171
186
  }
172
187
  get connectorKey() {
173
188
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -232,6 +247,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
232
247
  }
233
248
  };
234
249
 
250
+ // ../connectors/src/setup-flow.ts
251
+ async function runSetupFlow(flow, params, ctx, config) {
252
+ const runtime = {
253
+ params,
254
+ language: ctx.language,
255
+ config
256
+ };
257
+ let state = flow.initialState();
258
+ let answerIdx = 0;
259
+ for (const step of flow.steps) {
260
+ const ans = ctx.answers[answerIdx];
261
+ if (ans && ans.questionSlug === step.slug) {
262
+ state = step.applyAnswer(state, ans.answer);
263
+ answerIdx += 1;
264
+ continue;
265
+ }
266
+ if (step.type === "text") {
267
+ return {
268
+ type: "nextQuestion",
269
+ questionSlug: step.slug,
270
+ question: step.question[ctx.language],
271
+ questionType: "text"
272
+ };
273
+ }
274
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
275
+ if (options.length === 0) {
276
+ continue;
277
+ }
278
+ return {
279
+ type: "nextQuestion",
280
+ questionSlug: step.slug,
281
+ question: step.question[ctx.language],
282
+ questionType: step.type,
283
+ options
284
+ };
285
+ }
286
+ const dataInvestigationResult = await flow.finalize(state, runtime);
287
+ return { type: "fulfilled", dataInvestigationResult };
288
+ }
289
+ async function resolveSetupSelection(params) {
290
+ const { selected, allSentinel, fetchAll, limit } = params;
291
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
292
+ return resolved.slice(0, limit);
293
+ }
294
+
235
295
  // ../connectors/src/auth-types.ts
236
296
  var AUTH_TYPES = {
237
297
  OAUTH: "oauth",
@@ -420,11 +480,142 @@ var powerbiOauthOnboarding = new ConnectorOnboarding({
420
480
  // ../connectors/src/connectors/powerbi-oauth/parameters.ts
421
481
  var parameters = {};
422
482
 
483
+ // ../connectors/src/connectors/powerbi-oauth/utils.ts
484
+ var BASE_URL3 = "https://api.powerbi.com/v1.0/myorg";
485
+ function apiFetch(proxyFetch, path2, init) {
486
+ const url = `${BASE_URL3}${path2.startsWith("/") ? "" : "/"}${path2}`;
487
+ return proxyFetch(url, init);
488
+ }
489
+
490
+ // ../connectors/src/connectors/powerbi-oauth/setup-flow.ts
491
+ var ALL_WORKSPACES = "__ALL_WORKSPACES__";
492
+ var POWERBI_SETUP_MAX_WORKSPACES = 10;
493
+ var RESOURCE_DISPLAY_LIMIT = 25;
494
+ var RESOURCE_DATASETS = "datasets";
495
+ var RESOURCE_REPORTS = "reports";
496
+ var RESOURCE_DASHBOARDS = "dashboards";
497
+ async function listGroups(proxyFetch) {
498
+ const res = await apiFetch(proxyFetch, "/groups");
499
+ if (!res.ok) {
500
+ const body = await res.text().catch(() => res.statusText);
501
+ throw new Error(`powerbi: listGroups failed (${res.status}): ${body}`);
502
+ }
503
+ const data = await res.json();
504
+ return data.value ?? [];
505
+ }
506
+ async function listResource(proxyFetch, groupId, resource) {
507
+ const res = await apiFetch(
508
+ proxyFetch,
509
+ `/groups/${encodeURIComponent(groupId)}/${resource}`
510
+ );
511
+ if (!res.ok) {
512
+ const body = await res.text().catch(() => res.statusText);
513
+ throw new Error(
514
+ `powerbi: list ${resource} for group ${groupId} failed (${res.status}): ${body}`
515
+ );
516
+ }
517
+ const data = await res.json();
518
+ return data.value ?? [];
519
+ }
520
+ function resourceLabel(r) {
521
+ return r.name ?? r.displayName ?? r.id ?? "(unknown)";
522
+ }
523
+ var powerbiOauthSetupFlow = {
524
+ initialState: () => ({}),
525
+ steps: [
526
+ {
527
+ slug: "workspaces",
528
+ type: "multiSelect",
529
+ question: {
530
+ ja: "\u5BFE\u8C61\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
531
+ en: "Select target workspaces (multi-select allowed)"
532
+ },
533
+ async fetchOptions(_state, rt) {
534
+ const groups = await listGroups(rt.config.proxyFetch);
535
+ const options = groups.filter((g) => g.id && g.name).map((g) => ({ value: g.id, label: g.name }));
536
+ return [
537
+ {
538
+ value: ALL_WORKSPACES,
539
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9" : "All workspaces"
540
+ },
541
+ ...options
542
+ ];
543
+ },
544
+ applyAnswer: (state, answer) => ({ ...state, workspaces: answer })
545
+ },
546
+ {
547
+ slug: "resources",
548
+ type: "multiSelect",
549
+ question: {
550
+ ja: "\u8981\u7D04\u306B\u542B\u3081\u308B\u30EA\u30BD\u30FC\u30B9\u7A2E\u5225\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
551
+ en: "Select which resource types to include in the summary"
552
+ },
553
+ async fetchOptions(state, rt) {
554
+ if (!state.workspaces?.length) return [];
555
+ const datasetsLabel = rt.language === "ja" ? "\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8" : "Datasets";
556
+ const reportsLabel = rt.language === "ja" ? "\u30EC\u30DD\u30FC\u30C8" : "Reports";
557
+ const dashboardsLabel = rt.language === "ja" ? "\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9" : "Dashboards";
558
+ return [
559
+ { value: RESOURCE_DATASETS, label: datasetsLabel },
560
+ { value: RESOURCE_REPORTS, label: reportsLabel },
561
+ { value: RESOURCE_DASHBOARDS, label: dashboardsLabel }
562
+ ];
563
+ },
564
+ applyAnswer: (state, answer) => ({ ...state, resources: answer })
565
+ }
566
+ ],
567
+ async finalize(state, rt) {
568
+ if (!state.workspaces || !state.resources) {
569
+ throw new Error("Power BI setup: incomplete state on finalize");
570
+ }
571
+ const allGroups = await listGroups(rt.config.proxyFetch);
572
+ const groupById = new Map(allGroups.map((g) => [g.id, g]));
573
+ const targetIds = await resolveSetupSelection({
574
+ selected: state.workspaces,
575
+ allSentinel: ALL_WORKSPACES,
576
+ fetchAll: async () => allGroups.map((g) => g.id).filter((id) => id),
577
+ limit: POWERBI_SETUP_MAX_WORKSPACES
578
+ });
579
+ const selectedResources = new Set(state.resources);
580
+ const sections = ["## Power BI", ""];
581
+ if (!targetIds.length) {
582
+ sections.push("_No workspaces selected._", "");
583
+ return sections.join("\n");
584
+ }
585
+ for (const id of targetIds) {
586
+ const group = groupById.get(id);
587
+ const name = group?.name ?? id;
588
+ sections.push(`### Workspace: ${name}`, "", `- id: \`${id}\``);
589
+ for (const resource of [
590
+ RESOURCE_DATASETS,
591
+ RESOURCE_REPORTS,
592
+ RESOURCE_DASHBOARDS
593
+ ]) {
594
+ if (!selectedResources.has(resource)) continue;
595
+ const items = await listResource(rt.config.proxyFetch, id, resource);
596
+ const heading = resource === RESOURCE_DATASETS ? "Datasets" : resource === RESOURCE_REPORTS ? "Reports" : "Dashboards";
597
+ sections.push(`- ${heading} (${items.length}):`);
598
+ for (const item of items.slice(0, RESOURCE_DISPLAY_LIMIT)) {
599
+ sections.push(` - ${resourceLabel(item)}`);
600
+ }
601
+ if (items.length > RESOURCE_DISPLAY_LIMIT) {
602
+ sections.push(
603
+ ` - \u2026and ${items.length - RESOURCE_DISPLAY_LIMIT} more`
604
+ );
605
+ }
606
+ }
607
+ sections.push("");
608
+ }
609
+ return sections.join("\n");
610
+ }
611
+ };
612
+
423
613
  // ../connectors/src/connectors/powerbi-oauth/index.ts
424
614
  var tools = { request: requestTool };
425
615
  var powerbiOauthConnector = new ConnectorPlugin({
426
616
  slug: "powerbi",
427
617
  authType: AUTH_TYPES.OAUTH,
618
+ skipConnectionCheckOnCreate: true,
428
619
  name: "Power BI",
429
620
  description: "Connect to Microsoft Power BI using OAuth (Microsoft Entra ID). Use it to enumerate workspaces, datasets, and reports the signed-in user has access to, and to run DAX queries.",
430
621
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2vXQCKGpMJ9kGSaqkZl9IS/cc5669c267fc5d11e7b1f8c01723e461/power-bi-icon.png",
@@ -555,6 +746,7 @@ export default async function handler(c: Context) {
555
746
  - \`executeQueries\` \u306F\u73FE\u72B6 1 \u30EA\u30AF\u30A8\u30B9\u30C8\u306B\u3064\u304D 1 \u30AF\u30A8\u30EA\u306E\u307F`
556
747
  },
557
748
  tools,
749
+ setup: (params, ctx, config) => runSetupFlow(powerbiOauthSetupFlow, params, ctx, config),
558
750
  async checkConnection(_params, config) {
559
751
  const { proxyFetch } = config;
560
752
  const url = "https://api.powerbi.com/v1.0/myorg/groups?$top=1";
@@ -603,6 +795,7 @@ function resolveEnvVarOptional(entry, key) {
603
795
  import { getContext } from "hono/context-storage";
604
796
  import { getCookie } from "hono/cookie";
605
797
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
798
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
606
799
  function normalizeHeaders(input) {
607
800
  const out = {};
608
801
  if (!input) return out;
@@ -611,6 +804,11 @@ function normalizeHeaders(input) {
611
804
  });
612
805
  return out;
613
806
  }
807
+ function extractInputUrl(input) {
808
+ if (typeof input === "string") return input;
809
+ if (input instanceof URL) return input.href;
810
+ return input.url;
811
+ }
614
812
  function createSandboxProxyFetch(connectionId) {
615
813
  return async (input, init) => {
616
814
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -620,10 +818,17 @@ function createSandboxProxyFetch(connectionId) {
620
818
  "Connection proxy is not configured. Please check your deployment settings."
621
819
  );
622
820
  }
623
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
821
+ const originalUrl = extractInputUrl(input);
822
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
823
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
824
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
825
+ return fetch(sessionUrl, {
826
+ method: "POST",
827
+ headers: { Authorization: `Bearer ${token}` }
828
+ });
829
+ }
624
830
  const originalMethod = init?.method ?? "GET";
625
831
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
626
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
627
832
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
628
833
  return fetch(proxyUrl, {
629
834
  method: "POST",
@@ -649,10 +854,9 @@ function createDeployedAppProxyFetch(connectionId) {
649
854
  }
650
855
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
651
856
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
857
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
652
858
  return async (input, init) => {
653
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
654
- const originalMethod = init?.method ?? "GET";
655
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
859
+ const originalUrl = extractInputUrl(input);
656
860
  const c = getContext();
657
861
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
658
862
  if (!appSession) {
@@ -660,6 +864,14 @@ function createDeployedAppProxyFetch(connectionId) {
660
864
  "No authentication method available for connection proxy."
661
865
  );
662
866
  }
867
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
868
+ return fetch(sessionUrl, {
869
+ method: "POST",
870
+ headers: { Authorization: `Bearer ${appSession}` }
871
+ });
872
+ }
873
+ const originalMethod = init?.method ?? "GET";
874
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
663
875
  return fetch(proxyUrl, {
664
876
  method: "POST",
665
877
  headers: {