@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/stripe-api-key/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  apiKey: new ParameterDefinition({
48
60
  slug: "api-key",
@@ -133,6 +145,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
133
145
  tools;
134
146
  query;
135
147
  checkConnection;
148
+ /**
149
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
150
+ * implement this expose a step-by-step exploration flow (database/schema/
151
+ * table/etc. discovery) that the dashboard backend drives via the
152
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
153
+ * `runSetupFlow` from `setup-flow.ts`.
154
+ */
155
+ setup;
156
+ /**
157
+ * Opt-out of the default "verify before save" behavior on connection
158
+ * creation. The backend invokes `checkConnection` synchronously while
159
+ * creating the connection and aborts (no row inserted) if it fails — this
160
+ * flag disables that for connectors where the check cannot succeed pre-save:
161
+ *
162
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
163
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
164
+ * connectionId, which doesn't exist until the row is saved
165
+ *
166
+ * Exceptions are the explicit position; new credential-input connectors get
167
+ * the default verify-on-create behavior without opt-in.
168
+ */
169
+ skipConnectionCheckOnCreate;
136
170
  constructor(config) {
137
171
  this.slug = config.slug;
138
172
  this.authType = config.authType;
@@ -149,6 +183,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
149
183
  this.tools = config.tools;
150
184
  this.query = config.query;
151
185
  this.checkConnection = config.checkConnection;
186
+ this.setup = config.setup;
187
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
152
188
  }
153
189
  get connectorKey() {
154
190
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -213,6 +249,71 @@ var ConnectorPlugin = class _ConnectorPlugin {
213
249
  }
214
250
  };
215
251
 
252
+ // ../connectors/src/setup-flow.ts
253
+ async function runSetupFlow(flow, params, ctx, config) {
254
+ const runtime = {
255
+ params,
256
+ language: ctx.language,
257
+ config
258
+ };
259
+ let state = flow.initialState();
260
+ let answerIdx = 0;
261
+ const pendingParameterUpdates = [];
262
+ for (const step of flow.steps) {
263
+ const ans = ctx.answers[answerIdx];
264
+ if (ans && ans.questionSlug === step.slug) {
265
+ state = step.applyAnswer(state, ans.answer);
266
+ if (step.toParameterUpdates) {
267
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
268
+ }
269
+ answerIdx += 1;
270
+ continue;
271
+ }
272
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
273
+ if (step.type === "text") {
274
+ if (step.fetchOptions) {
275
+ const options2 = await step.fetchOptions(state, runtime);
276
+ if (options2.length === 0) {
277
+ continue;
278
+ }
279
+ }
280
+ return {
281
+ type: "nextQuestion",
282
+ questionSlug: step.slug,
283
+ question: step.question[ctx.language],
284
+ questionType: "text",
285
+ allowFreeText: resolvedAllowFreeText,
286
+ ...pendingParameterUpdates.length > 0 && {
287
+ parameterUpdates: pendingParameterUpdates
288
+ }
289
+ };
290
+ }
291
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
292
+ if (options.length === 0) {
293
+ continue;
294
+ }
295
+ return {
296
+ type: "nextQuestion",
297
+ questionSlug: step.slug,
298
+ question: step.question[ctx.language],
299
+ questionType: step.type,
300
+ options,
301
+ allowFreeText: resolvedAllowFreeText,
302
+ ...pendingParameterUpdates.length > 0 && {
303
+ parameterUpdates: pendingParameterUpdates
304
+ }
305
+ };
306
+ }
307
+ const dataInvestigationResult = await flow.finalize(state, runtime);
308
+ return {
309
+ type: "fulfilled",
310
+ dataInvestigationResult,
311
+ ...pendingParameterUpdates.length > 0 && {
312
+ parameterUpdates: pendingParameterUpdates
313
+ }
314
+ };
315
+ }
316
+
216
317
  // ../connectors/src/auth-types.ts
217
318
  var AUTH_TYPES = {
218
319
  OAUTH: "oauth",
@@ -352,6 +453,107 @@ var stripeApiKeyOnboarding = new ConnectorOnboarding({
352
453
  }
353
454
  });
354
455
 
456
+ // ../connectors/src/connectors/stripe-api-key/utils.ts
457
+ var BASE_URL3 = "https://api.stripe.com";
458
+ async function apiFetch(params, path2, init) {
459
+ const apiKey = params[parameters.apiKey.slug];
460
+ if (!apiKey) {
461
+ throw new Error("stripe-api-key: missing required parameter: api-key");
462
+ }
463
+ const url = `${BASE_URL3}${path2.startsWith("/") ? "" : "/"}${path2}`;
464
+ const headers = new Headers(init?.headers);
465
+ headers.set("Authorization", `Bearer ${apiKey}`);
466
+ return fetch(url, { ...init, headers });
467
+ }
468
+
469
+ // ../connectors/src/connectors/stripe-api-key/setup-flow.ts
470
+ var STRIPE_SETUP_MAX_ENTITIES = 10;
471
+ var ENTITY_LABELS = {
472
+ customers: { en: "Customers", ja: "Customers (\u9867\u5BA2)" },
473
+ charges: { en: "Charges", ja: "Charges (\u652F\u6255\u3044)" },
474
+ invoices: { en: "Invoices", ja: "Invoices (\u8ACB\u6C42\u66F8)" },
475
+ subscriptions: {
476
+ en: "Subscriptions",
477
+ ja: "Subscriptions (\u30B5\u30D6\u30B9\u30AF\u30EA\u30D7\u30B7\u30E7\u30F3)"
478
+ },
479
+ products: { en: "Products", ja: "Products (\u5546\u54C1)" },
480
+ prices: { en: "Prices", ja: "Prices (\u4FA1\u683C)" },
481
+ payouts: { en: "Payouts", ja: "Payouts (\u652F\u6255\u3044)" },
482
+ refunds: { en: "Refunds", ja: "Refunds (\u8FD4\u91D1)" },
483
+ disputes: { en: "Disputes", ja: "Disputes (\u7570\u8B70)" },
484
+ paymentIntents: {
485
+ en: "Payment intents",
486
+ ja: "Payment intents (\u652F\u6255\u3044\u30A4\u30F3\u30C6\u30F3\u30C8)"
487
+ }
488
+ };
489
+ var ENTITY_PATHS = {
490
+ customers: "/v1/customers?limit=1",
491
+ charges: "/v1/charges?limit=1",
492
+ invoices: "/v1/invoices?limit=1",
493
+ subscriptions: "/v1/subscriptions?limit=1",
494
+ products: "/v1/products?limit=1",
495
+ prices: "/v1/prices?limit=1",
496
+ payouts: "/v1/payouts?limit=1",
497
+ refunds: "/v1/refunds?limit=1",
498
+ disputes: "/v1/disputes?limit=1",
499
+ paymentIntents: "/v1/payment_intents?limit=1"
500
+ };
501
+ var ENTITY_VALUES = Object.keys(ENTITY_PATHS);
502
+ async function defaultFetchEntity(params, path2) {
503
+ return apiFetch(params, path2);
504
+ }
505
+ function createStripeSetupFlow(fetchEntity = defaultFetchEntity, labelPrefix = "Stripe") {
506
+ return {
507
+ initialState: () => ({}),
508
+ steps: [
509
+ {
510
+ slug: "entities",
511
+ type: "multiSelect",
512
+ question: {
513
+ ja: "\u5BFE\u8C61\u306E\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
514
+ en: "Select target entities (multi-select allowed)"
515
+ },
516
+ async fetchOptions(_state, rt) {
517
+ return ENTITY_VALUES.map((value) => ({
518
+ value,
519
+ label: ENTITY_LABELS[value][rt.language]
520
+ }));
521
+ },
522
+ applyAnswer: (state, answer) => ({ ...state, entities: answer })
523
+ }
524
+ ],
525
+ async finalize(state, rt) {
526
+ if (!state.entities) {
527
+ throw new Error("Stripe setup: incomplete state on finalize");
528
+ }
529
+ const selected = state.entities.filter(
530
+ (e) => ENTITY_VALUES.includes(e)
531
+ ).slice(0, STRIPE_SETUP_MAX_ENTITIES);
532
+ const sections = [`## ${labelPrefix}`, ""];
533
+ for (const entity of selected) {
534
+ let count = "available";
535
+ const res = await fetchEntity(rt.params, ENTITY_PATHS[entity]);
536
+ if (res.ok) {
537
+ const data = await res.json();
538
+ if (Array.isArray(data.data) && data.data.length === 0) {
539
+ count = "0";
540
+ } else if (data.has_more === false) {
541
+ count = String(data.data?.length ?? 1);
542
+ } else if (Array.isArray(data.data)) {
543
+ count = "1+ (paginated)";
544
+ }
545
+ } else {
546
+ count = "unavailable";
547
+ }
548
+ sections.push(`### ${ENTITY_LABELS[entity].en}`, "");
549
+ sections.push(`Status: ${count}`, "");
550
+ }
551
+ return sections.join("\n");
552
+ }
553
+ };
554
+ }
555
+ var stripeApiKeySetupFlow = createStripeSetupFlow();
556
+
355
557
  // ../connectors/src/connectors/stripe-api-key/index.ts
356
558
  var tools = { request: requestTool };
357
559
  var stripeApiKeyConnector = new ConnectorPlugin({
@@ -469,6 +671,7 @@ const data = await res.json();
469
671
  \`\`\``
470
672
  },
471
673
  tools,
674
+ setup: (params, ctx, config) => runSetupFlow(stripeApiKeySetupFlow, params, ctx, config),
472
675
  async checkConnection(params) {
473
676
  try {
474
677
  const apiKey = params["api-key"];
@@ -525,6 +728,7 @@ function resolveEnvVarOptional(entry, key) {
525
728
  import { getContext } from "hono/context-storage";
526
729
  import { getCookie } from "hono/cookie";
527
730
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
731
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
528
732
  function normalizeHeaders(input) {
529
733
  const out = {};
530
734
  if (!input) return out;
@@ -533,6 +737,11 @@ function normalizeHeaders(input) {
533
737
  });
534
738
  return out;
535
739
  }
740
+ function extractInputUrl(input) {
741
+ if (typeof input === "string") return input;
742
+ if (input instanceof URL) return input.href;
743
+ return input.url;
744
+ }
536
745
  function createSandboxProxyFetch(connectionId) {
537
746
  return async (input, init) => {
538
747
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -542,10 +751,17 @@ function createSandboxProxyFetch(connectionId) {
542
751
  "Connection proxy is not configured. Please check your deployment settings."
543
752
  );
544
753
  }
545
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
754
+ const originalUrl = extractInputUrl(input);
755
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
756
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
757
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
758
+ return fetch(sessionUrl, {
759
+ method: "POST",
760
+ headers: { Authorization: `Bearer ${token}` }
761
+ });
762
+ }
546
763
  const originalMethod = init?.method ?? "GET";
547
764
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
548
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
549
765
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
550
766
  return fetch(proxyUrl, {
551
767
  method: "POST",
@@ -571,10 +787,9 @@ function createDeployedAppProxyFetch(connectionId) {
571
787
  }
572
788
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
573
789
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
790
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
574
791
  return async (input, init) => {
575
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
576
- const originalMethod = init?.method ?? "GET";
577
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
792
+ const originalUrl = extractInputUrl(input);
578
793
  const c = getContext();
579
794
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
580
795
  if (!appSession) {
@@ -582,6 +797,14 @@ function createDeployedAppProxyFetch(connectionId) {
582
797
  "No authentication method available for connection proxy."
583
798
  );
584
799
  }
800
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
801
+ return fetch(sessionUrl, {
802
+ method: "POST",
803
+ headers: { Authorization: `Bearer ${appSession}` }
804
+ });
805
+ }
806
+ const originalMethod = init?.method ?? "GET";
807
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
585
808
  return fetch(proxyUrl, {
586
809
  method: "POST",
587
810
  headers: {
@@ -67,6 +67,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
67
67
  tools;
68
68
  query;
69
69
  checkConnection;
70
+ /**
71
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
72
+ * implement this expose a step-by-step exploration flow (database/schema/
73
+ * table/etc. discovery) that the dashboard backend drives via the
74
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
75
+ * `runSetupFlow` from `setup-flow.ts`.
76
+ */
77
+ setup;
78
+ /**
79
+ * Opt-out of the default "verify before save" behavior on connection
80
+ * creation. The backend invokes `checkConnection` synchronously while
81
+ * creating the connection and aborts (no row inserted) if it fails — this
82
+ * flag disables that for connectors where the check cannot succeed pre-save:
83
+ *
84
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
85
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
86
+ * connectionId, which doesn't exist until the row is saved
87
+ *
88
+ * Exceptions are the explicit position; new credential-input connectors get
89
+ * the default verify-on-create behavior without opt-in.
90
+ */
91
+ skipConnectionCheckOnCreate;
70
92
  constructor(config) {
71
93
  this.slug = config.slug;
72
94
  this.authType = config.authType;
@@ -83,6 +105,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
83
105
  this.tools = config.tools;
84
106
  this.query = config.query;
85
107
  this.checkConnection = config.checkConnection;
108
+ this.setup = config.setup;
109
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
86
110
  }
87
111
  get connectorKey() {
88
112
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -147,6 +171,71 @@ var ConnectorPlugin = class _ConnectorPlugin {
147
171
  }
148
172
  };
149
173
 
174
+ // ../connectors/src/setup-flow.ts
175
+ async function runSetupFlow(flow, params, ctx, config) {
176
+ const runtime = {
177
+ params,
178
+ language: ctx.language,
179
+ config
180
+ };
181
+ let state = flow.initialState();
182
+ let answerIdx = 0;
183
+ const pendingParameterUpdates = [];
184
+ for (const step of flow.steps) {
185
+ const ans = ctx.answers[answerIdx];
186
+ if (ans && ans.questionSlug === step.slug) {
187
+ state = step.applyAnswer(state, ans.answer);
188
+ if (step.toParameterUpdates) {
189
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
190
+ }
191
+ answerIdx += 1;
192
+ continue;
193
+ }
194
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
195
+ if (step.type === "text") {
196
+ if (step.fetchOptions) {
197
+ const options2 = await step.fetchOptions(state, runtime);
198
+ if (options2.length === 0) {
199
+ continue;
200
+ }
201
+ }
202
+ return {
203
+ type: "nextQuestion",
204
+ questionSlug: step.slug,
205
+ question: step.question[ctx.language],
206
+ questionType: "text",
207
+ allowFreeText: resolvedAllowFreeText,
208
+ ...pendingParameterUpdates.length > 0 && {
209
+ parameterUpdates: pendingParameterUpdates
210
+ }
211
+ };
212
+ }
213
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
214
+ if (options.length === 0) {
215
+ continue;
216
+ }
217
+ return {
218
+ type: "nextQuestion",
219
+ questionSlug: step.slug,
220
+ question: step.question[ctx.language],
221
+ questionType: step.type,
222
+ options,
223
+ allowFreeText: resolvedAllowFreeText,
224
+ ...pendingParameterUpdates.length > 0 && {
225
+ parameterUpdates: pendingParameterUpdates
226
+ }
227
+ };
228
+ }
229
+ const dataInvestigationResult = await flow.finalize(state, runtime);
230
+ return {
231
+ type: "fulfilled",
232
+ dataInvestigationResult,
233
+ ...pendingParameterUpdates.length > 0 && {
234
+ parameterUpdates: pendingParameterUpdates
235
+ }
236
+ };
237
+ }
238
+
150
239
  // ../connectors/src/auth-types.ts
151
240
  var AUTH_TYPES = {
152
241
  OAUTH: "oauth",
@@ -310,11 +399,98 @@ var stripeOnboarding = new ConnectorOnboarding({
310
399
  // ../connectors/src/connectors/stripe-oauth/parameters.ts
311
400
  var parameters = {};
312
401
 
402
+ // ../connectors/src/connectors/stripe-oauth/setup-flow.ts
403
+ var BASE_URL3 = "https://api.stripe.com";
404
+ var STRIPE_OAUTH_SETUP_MAX_ENTITIES = 10;
405
+ var ENTITY_LABELS = {
406
+ customers: { en: "Customers", ja: "Customers (\u9867\u5BA2)" },
407
+ charges: { en: "Charges", ja: "Charges (\u652F\u6255\u3044)" },
408
+ invoices: { en: "Invoices", ja: "Invoices (\u8ACB\u6C42\u66F8)" },
409
+ subscriptions: {
410
+ en: "Subscriptions",
411
+ ja: "Subscriptions (\u30B5\u30D6\u30B9\u30AF\u30EA\u30D7\u30B7\u30E7\u30F3)"
412
+ },
413
+ products: { en: "Products", ja: "Products (\u5546\u54C1)" },
414
+ prices: { en: "Prices", ja: "Prices (\u4FA1\u683C)" },
415
+ payouts: { en: "Payouts", ja: "Payouts (\u652F\u6255\u3044)" },
416
+ refunds: { en: "Refunds", ja: "Refunds (\u8FD4\u91D1)" },
417
+ disputes: { en: "Disputes", ja: "Disputes (\u7570\u8B70)" },
418
+ paymentIntents: {
419
+ en: "Payment intents",
420
+ ja: "Payment intents (\u652F\u6255\u3044\u30A4\u30F3\u30C6\u30F3\u30C8)"
421
+ }
422
+ };
423
+ var ENTITY_PATHS = {
424
+ customers: "/v1/customers?limit=1",
425
+ charges: "/v1/charges?limit=1",
426
+ invoices: "/v1/invoices?limit=1",
427
+ subscriptions: "/v1/subscriptions?limit=1",
428
+ products: "/v1/products?limit=1",
429
+ prices: "/v1/prices?limit=1",
430
+ payouts: "/v1/payouts?limit=1",
431
+ refunds: "/v1/refunds?limit=1",
432
+ disputes: "/v1/disputes?limit=1",
433
+ paymentIntents: "/v1/payment_intents?limit=1"
434
+ };
435
+ var ENTITY_VALUES = Object.keys(ENTITY_PATHS);
436
+ var stripeOauthSetupFlow = {
437
+ initialState: () => ({}),
438
+ steps: [
439
+ {
440
+ slug: "entities",
441
+ type: "multiSelect",
442
+ question: {
443
+ ja: "\u5BFE\u8C61\u306E\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
444
+ en: "Select target entities (multi-select allowed)"
445
+ },
446
+ async fetchOptions(_state, rt) {
447
+ return ENTITY_VALUES.map((value) => ({
448
+ value,
449
+ label: ENTITY_LABELS[value][rt.language]
450
+ }));
451
+ },
452
+ applyAnswer: (state, answer) => ({ ...state, entities: answer })
453
+ }
454
+ ],
455
+ async finalize(state, rt) {
456
+ if (!state.entities) {
457
+ throw new Error("Stripe setup: incomplete state on finalize");
458
+ }
459
+ const selected = state.entities.filter(
460
+ (e) => ENTITY_VALUES.includes(e)
461
+ ).slice(0, STRIPE_OAUTH_SETUP_MAX_ENTITIES);
462
+ const sections = ["## Stripe", ""];
463
+ for (const entity of selected) {
464
+ let count = "available";
465
+ const res = await rt.config.proxyFetch(
466
+ `${BASE_URL3}${ENTITY_PATHS[entity]}`,
467
+ { method: "GET" }
468
+ );
469
+ if (res.ok) {
470
+ const data = await res.json();
471
+ if (Array.isArray(data.data) && data.data.length === 0) {
472
+ count = "0";
473
+ } else if (data.has_more === false) {
474
+ count = String(data.data?.length ?? 1);
475
+ } else if (Array.isArray(data.data)) {
476
+ count = "1+ (paginated)";
477
+ }
478
+ } else {
479
+ count = "unavailable";
480
+ }
481
+ sections.push(`### ${ENTITY_LABELS[entity].en}`, "");
482
+ sections.push(`Status: ${count}`, "");
483
+ }
484
+ return sections.join("\n");
485
+ }
486
+ };
487
+
313
488
  // ../connectors/src/connectors/stripe-oauth/index.ts
314
489
  var tools = { request: requestTool };
315
490
  var stripeOauthConnector = new ConnectorPlugin({
316
491
  slug: "stripe",
317
492
  authType: AUTH_TYPES.OAUTH,
493
+ skipConnectionCheckOnCreate: true,
318
494
  name: "Stripe",
319
495
  description: "Connect to Stripe for payment, customer, and subscription data using OAuth.",
320
496
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2QNK0u2doqp41uL0POS4Ks/7a92367e2388ec77c7f4ada143606f9a/stripe.jpeg",
@@ -431,6 +607,7 @@ const data = await res.json();
431
607
  \`\`\``
432
608
  },
433
609
  tools,
610
+ setup: (params, ctx, config) => runSetupFlow(stripeOauthSetupFlow, params, ctx, config),
434
611
  async checkConnection(_params, config) {
435
612
  const { proxyFetch } = config;
436
613
  try {
@@ -480,6 +657,7 @@ function resolveEnvVarOptional(entry, key) {
480
657
  import { getContext } from "hono/context-storage";
481
658
  import { getCookie } from "hono/cookie";
482
659
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
660
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
483
661
  function normalizeHeaders(input) {
484
662
  const out = {};
485
663
  if (!input) return out;
@@ -488,6 +666,11 @@ function normalizeHeaders(input) {
488
666
  });
489
667
  return out;
490
668
  }
669
+ function extractInputUrl(input) {
670
+ if (typeof input === "string") return input;
671
+ if (input instanceof URL) return input.href;
672
+ return input.url;
673
+ }
491
674
  function createSandboxProxyFetch(connectionId) {
492
675
  return async (input, init) => {
493
676
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -497,10 +680,17 @@ function createSandboxProxyFetch(connectionId) {
497
680
  "Connection proxy is not configured. Please check your deployment settings."
498
681
  );
499
682
  }
500
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
683
+ const originalUrl = extractInputUrl(input);
684
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
685
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
686
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
687
+ return fetch(sessionUrl, {
688
+ method: "POST",
689
+ headers: { Authorization: `Bearer ${token}` }
690
+ });
691
+ }
501
692
  const originalMethod = init?.method ?? "GET";
502
693
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
503
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
504
694
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
505
695
  return fetch(proxyUrl, {
506
696
  method: "POST",
@@ -526,10 +716,9 @@ function createDeployedAppProxyFetch(connectionId) {
526
716
  }
527
717
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
528
718
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
719
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
529
720
  return async (input, init) => {
530
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
531
- const originalMethod = init?.method ?? "GET";
532
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
721
+ const originalUrl = extractInputUrl(input);
533
722
  const c = getContext();
534
723
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
535
724
  if (!appSession) {
@@ -537,6 +726,14 @@ function createDeployedAppProxyFetch(connectionId) {
537
726
  "No authentication method available for connection proxy."
538
727
  );
539
728
  }
729
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
730
+ return fetch(sessionUrl, {
731
+ method: "POST",
732
+ headers: { Authorization: `Bearer ${appSession}` }
733
+ });
734
+ }
735
+ const originalMethod = init?.method ?? "GET";
736
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
540
737
  return fetch(proxyUrl, {
541
738
  method: "POST",
542
739
  headers: {