@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
@@ -15,7 +15,7 @@ function createClient(_params, fetchFn = fetch) {
15
15
  }
16
16
  return await response.json();
17
17
  }
18
- async function listLabels() {
18
+ async function listLabels2() {
19
19
  const response = await request("/me/labels");
20
20
  if (!response.ok) {
21
21
  const body = await response.text();
@@ -98,7 +98,7 @@ function createClient(_params, fetchFn = fetch) {
98
98
  return {
99
99
  request,
100
100
  getProfile,
101
- listLabels,
101
+ listLabels: listLabels2,
102
102
  listMessages,
103
103
  getMessage,
104
104
  listThreads,
@@ -165,6 +165,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
165
165
  tools;
166
166
  query;
167
167
  checkConnection;
168
+ /**
169
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
170
+ * implement this expose a step-by-step exploration flow (database/schema/
171
+ * table/etc. discovery) that the dashboard backend drives via the
172
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
173
+ * `runSetupFlow` from `setup-flow.ts`.
174
+ */
175
+ setup;
176
+ /**
177
+ * Opt-out of the default "verify before save" behavior on connection
178
+ * creation. The backend invokes `checkConnection` synchronously while
179
+ * creating the connection and aborts (no row inserted) if it fails — this
180
+ * flag disables that for connectors where the check cannot succeed pre-save:
181
+ *
182
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
183
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
184
+ * connectionId, which doesn't exist until the row is saved
185
+ *
186
+ * Exceptions are the explicit position; new credential-input connectors get
187
+ * the default verify-on-create behavior without opt-in.
188
+ */
189
+ skipConnectionCheckOnCreate;
168
190
  constructor(config) {
169
191
  this.slug = config.slug;
170
192
  this.authType = config.authType;
@@ -181,6 +203,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
181
203
  this.tools = config.tools;
182
204
  this.query = config.query;
183
205
  this.checkConnection = config.checkConnection;
206
+ this.setup = config.setup;
207
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
184
208
  }
185
209
  get connectorKey() {
186
210
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -245,6 +269,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
245
269
  }
246
270
  };
247
271
 
272
+ // ../connectors/src/setup-flow.ts
273
+ async function runSetupFlow(flow, params, ctx, config) {
274
+ const runtime = {
275
+ params,
276
+ language: ctx.language,
277
+ config
278
+ };
279
+ let state = flow.initialState();
280
+ let answerIdx = 0;
281
+ const pendingParameterUpdates = [];
282
+ for (const step of flow.steps) {
283
+ const ans = ctx.answers[answerIdx];
284
+ if (ans && ans.questionSlug === step.slug) {
285
+ state = step.applyAnswer(state, ans.answer);
286
+ if (step.toParameterUpdates) {
287
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
288
+ }
289
+ answerIdx += 1;
290
+ continue;
291
+ }
292
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
293
+ if (step.type === "text") {
294
+ if (step.fetchOptions) {
295
+ const options2 = await step.fetchOptions(state, runtime);
296
+ if (options2.length === 0) {
297
+ continue;
298
+ }
299
+ }
300
+ return {
301
+ type: "nextQuestion",
302
+ questionSlug: step.slug,
303
+ question: step.question[ctx.language],
304
+ questionType: "text",
305
+ allowFreeText: resolvedAllowFreeText,
306
+ ...pendingParameterUpdates.length > 0 && {
307
+ parameterUpdates: pendingParameterUpdates
308
+ }
309
+ };
310
+ }
311
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
312
+ if (options.length === 0) {
313
+ continue;
314
+ }
315
+ return {
316
+ type: "nextQuestion",
317
+ questionSlug: step.slug,
318
+ question: step.question[ctx.language],
319
+ questionType: step.type,
320
+ options,
321
+ allowFreeText: resolvedAllowFreeText,
322
+ ...pendingParameterUpdates.length > 0 && {
323
+ parameterUpdates: pendingParameterUpdates
324
+ }
325
+ };
326
+ }
327
+ const dataInvestigationResult = await flow.finalize(state, runtime);
328
+ return {
329
+ type: "fulfilled",
330
+ dataInvestigationResult,
331
+ ...pendingParameterUpdates.length > 0 && {
332
+ parameterUpdates: pendingParameterUpdates
333
+ }
334
+ };
335
+ }
336
+ async function resolveSetupSelection(params) {
337
+ const { selected, allSentinel, fetchAll, limit } = params;
338
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
339
+ return resolved.slice(0, limit);
340
+ }
341
+
248
342
  // ../connectors/src/auth-types.ts
249
343
  var AUTH_TYPES = {
250
344
  OAUTH: "oauth",
@@ -425,6 +519,87 @@ var gmailOnboarding = new ConnectorOnboarding({
425
519
  }
426
520
  });
427
521
 
522
+ // ../connectors/src/connectors/gmail-oauth/utils.ts
523
+ async function gmailApiFetch(config, url) {
524
+ const res = await config.proxyFetch(url, { method: "GET" });
525
+ if (!res.ok) {
526
+ const text = await res.text().catch(() => res.statusText);
527
+ throw new Error(`Gmail API ${url} failed: HTTP ${res.status} ${text}`);
528
+ }
529
+ return await res.json();
530
+ }
531
+
532
+ // ../connectors/src/connectors/gmail-oauth/setup-flow.ts
533
+ var ALL_LABELS = "__ALL_LABELS__";
534
+ var GMAIL_SETUP_MAX_LABELS = 20;
535
+ async function listLabels(config) {
536
+ const url = "https://gmail.googleapis.com/gmail/v1/users/me/labels";
537
+ const data = await gmailApiFetch(config, url);
538
+ return data.labels ?? [];
539
+ }
540
+ var gmailOauthSetupFlow = {
541
+ initialState: () => ({}),
542
+ steps: [
543
+ {
544
+ slug: "labels",
545
+ type: "multiSelect",
546
+ question: {
547
+ ja: "\u5BFE\u8C61\u306E\u30E9\u30D9\u30EB\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
548
+ en: "Select target labels (multi-select allowed)"
549
+ },
550
+ async fetchOptions(_state, rt) {
551
+ const labels = await listLabels(rt.config);
552
+ return [
553
+ {
554
+ value: ALL_LABELS,
555
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30E9\u30D9\u30EB" : "All labels"
556
+ },
557
+ ...labels.map((l) => ({ value: l.id, label: l.name }))
558
+ ];
559
+ },
560
+ applyAnswer: (state, answer) => ({ ...state, labels: answer })
561
+ }
562
+ ],
563
+ async finalize(state, rt) {
564
+ if (!state.labels) {
565
+ throw new Error("Gmail setup: incomplete state on finalize");
566
+ }
567
+ const labels = await listLabels(rt.config);
568
+ const labelsById = new Map(labels.map((l) => [l.id, l]));
569
+ const targetIds = await resolveSetupSelection({
570
+ selected: state.labels,
571
+ allSentinel: ALL_LABELS,
572
+ fetchAll: async () => labels.map((l) => l.id),
573
+ limit: GMAIL_SETUP_MAX_LABELS
574
+ });
575
+ const sections = ["## Gmail", ""];
576
+ if (targetIds.length === 0) {
577
+ sections.push(
578
+ rt.language === "ja" ? "\u5BFE\u8C61\u306E\u30E9\u30D9\u30EB\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002" : "No labels selected."
579
+ );
580
+ return sections.join("\n");
581
+ }
582
+ sections.push("| Label | Visibility | Messages | Unread |");
583
+ sections.push("|-------|-----------|----------|--------|");
584
+ for (const id of targetIds) {
585
+ const url = `https://gmail.googleapis.com/gmail/v1/users/me/labels/${encodeURIComponent(
586
+ id
587
+ )}`;
588
+ const detail = await gmailApiFetch(
589
+ rt.config,
590
+ url
591
+ );
592
+ const name = detail.name ?? labelsById.get(id)?.name ?? id;
593
+ const vis = detail.labelListVisibility ?? "-";
594
+ const total = detail.messagesTotal ?? "-";
595
+ const unread = detail.messagesUnread ?? "-";
596
+ sections.push(`| ${name} | ${vis} | ${total} | ${unread} |`);
597
+ }
598
+ sections.push("");
599
+ return sections.join("\n");
600
+ }
601
+ };
602
+
428
603
  // ../connectors/src/connectors/gmail-oauth/parameters.ts
429
604
  var parameters = {};
430
605
 
@@ -433,6 +608,7 @@ var tools = { request: requestTool };
433
608
  var gmailOauthConnector = new ConnectorPlugin({
434
609
  slug: "gmail",
435
610
  authType: AUTH_TYPES.OAUTH,
611
+ skipConnectionCheckOnCreate: true,
436
612
  name: "Gmail",
437
613
  description: "Connect to Gmail for email data access using OAuth. Read-only access to messages, threads, and labels.",
438
614
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4V3rfaSc1ksFIt2eHBNIwJ/7f3be41a154a6d96dcf229ed0e5858c9/Gmail_icon__2020_.svg.png",
@@ -617,6 +793,7 @@ thread.messages.forEach(m => console.log(m.snippet));
617
793
  \`\`\``
618
794
  },
619
795
  tools,
796
+ setup: (params, ctx, config) => runSetupFlow(gmailOauthSetupFlow, params, ctx, config),
620
797
  async checkConnection(_params, config) {
621
798
  const { proxyFetch } = config;
622
799
  const url = "https://gmail.googleapis.com/gmail/v1/users/me/profile";
@@ -665,6 +842,7 @@ function resolveEnvVarOptional(entry, key) {
665
842
  import { getContext } from "hono/context-storage";
666
843
  import { getCookie } from "hono/cookie";
667
844
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
845
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
668
846
  function normalizeHeaders(input) {
669
847
  const out = {};
670
848
  if (!input) return out;
@@ -673,6 +851,11 @@ function normalizeHeaders(input) {
673
851
  });
674
852
  return out;
675
853
  }
854
+ function extractInputUrl(input) {
855
+ if (typeof input === "string") return input;
856
+ if (input instanceof URL) return input.href;
857
+ return input.url;
858
+ }
676
859
  function createSandboxProxyFetch(connectionId) {
677
860
  return async (input, init) => {
678
861
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -682,10 +865,17 @@ function createSandboxProxyFetch(connectionId) {
682
865
  "Connection proxy is not configured. Please check your deployment settings."
683
866
  );
684
867
  }
685
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
868
+ const originalUrl = extractInputUrl(input);
869
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
870
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
871
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
872
+ return fetch(sessionUrl, {
873
+ method: "POST",
874
+ headers: { Authorization: `Bearer ${token}` }
875
+ });
876
+ }
686
877
  const originalMethod = init?.method ?? "GET";
687
878
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
688
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
689
879
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
690
880
  return fetch(proxyUrl, {
691
881
  method: "POST",
@@ -711,10 +901,9 @@ function createDeployedAppProxyFetch(connectionId) {
711
901
  }
712
902
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
713
903
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
904
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
714
905
  return async (input, init) => {
715
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
716
- const originalMethod = init?.method ?? "GET";
717
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
906
+ const originalUrl = extractInputUrl(input);
718
907
  const c = getContext();
719
908
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
720
909
  if (!appSession) {
@@ -722,6 +911,14 @@ function createDeployedAppProxyFetch(connectionId) {
722
911
  "No authentication method available for connection proxy."
723
912
  );
724
913
  }
914
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
915
+ return fetch(sessionUrl, {
916
+ method: "POST",
917
+ headers: { Authorization: `Bearer ${appSession}` }
918
+ });
919
+ }
920
+ const originalMethod = init?.method ?? "GET";
921
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
725
922
  return fetch(proxyUrl, {
726
923
  method: "POST",
727
924
  headers: {