@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
@@ -65,6 +65,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
65
65
  tools;
66
66
  query;
67
67
  checkConnection;
68
+ /**
69
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
70
+ * implement this expose a step-by-step exploration flow (database/schema/
71
+ * table/etc. discovery) that the dashboard backend drives via the
72
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
73
+ * `runSetupFlow` from `setup-flow.ts`.
74
+ */
75
+ setup;
76
+ /**
77
+ * Opt-out of the default "verify before save" behavior on connection
78
+ * creation. The backend invokes `checkConnection` synchronously while
79
+ * creating the connection and aborts (no row inserted) if it fails — this
80
+ * flag disables that for connectors where the check cannot succeed pre-save:
81
+ *
82
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
83
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
84
+ * connectionId, which doesn't exist until the row is saved
85
+ *
86
+ * Exceptions are the explicit position; new credential-input connectors get
87
+ * the default verify-on-create behavior without opt-in.
88
+ */
89
+ skipConnectionCheckOnCreate;
68
90
  constructor(config) {
69
91
  this.slug = config.slug;
70
92
  this.authType = config.authType;
@@ -81,6 +103,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
81
103
  this.tools = config.tools;
82
104
  this.query = config.query;
83
105
  this.checkConnection = config.checkConnection;
106
+ this.setup = config.setup;
107
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
84
108
  }
85
109
  get connectorKey() {
86
110
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -145,6 +169,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
145
169
  }
146
170
  };
147
171
 
172
+ // ../connectors/src/setup-flow.ts
173
+ async function runSetupFlow(flow, params, ctx, config) {
174
+ const runtime = {
175
+ params,
176
+ language: ctx.language,
177
+ config
178
+ };
179
+ let state = flow.initialState();
180
+ let answerIdx = 0;
181
+ const pendingParameterUpdates = [];
182
+ for (const step of flow.steps) {
183
+ const ans = ctx.answers[answerIdx];
184
+ if (ans && ans.questionSlug === step.slug) {
185
+ state = step.applyAnswer(state, ans.answer);
186
+ if (step.toParameterUpdates) {
187
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
188
+ }
189
+ answerIdx += 1;
190
+ continue;
191
+ }
192
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
193
+ if (step.type === "text") {
194
+ if (step.fetchOptions) {
195
+ const options2 = await step.fetchOptions(state, runtime);
196
+ if (options2.length === 0) {
197
+ continue;
198
+ }
199
+ }
200
+ return {
201
+ type: "nextQuestion",
202
+ questionSlug: step.slug,
203
+ question: step.question[ctx.language],
204
+ questionType: "text",
205
+ allowFreeText: resolvedAllowFreeText,
206
+ ...pendingParameterUpdates.length > 0 && {
207
+ parameterUpdates: pendingParameterUpdates
208
+ }
209
+ };
210
+ }
211
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
212
+ if (options.length === 0) {
213
+ continue;
214
+ }
215
+ return {
216
+ type: "nextQuestion",
217
+ questionSlug: step.slug,
218
+ question: step.question[ctx.language],
219
+ questionType: step.type,
220
+ options,
221
+ allowFreeText: resolvedAllowFreeText,
222
+ ...pendingParameterUpdates.length > 0 && {
223
+ parameterUpdates: pendingParameterUpdates
224
+ }
225
+ };
226
+ }
227
+ const dataInvestigationResult = await flow.finalize(state, runtime);
228
+ return {
229
+ type: "fulfilled",
230
+ dataInvestigationResult,
231
+ ...pendingParameterUpdates.length > 0 && {
232
+ parameterUpdates: pendingParameterUpdates
233
+ }
234
+ };
235
+ }
236
+ async function resolveSetupSelection(params) {
237
+ const { selected, allSentinel, fetchAll, limit } = params;
238
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
239
+ return resolved.slice(0, limit);
240
+ }
241
+
148
242
  // ../connectors/src/auth-types.ts
149
243
  var AUTH_TYPES = {
150
244
  OAUTH: "oauth",
@@ -309,6 +403,124 @@ var zendeskOauthOnboarding = new ConnectorOnboarding({
309
403
  }
310
404
  });
311
405
 
406
+ // ../connectors/src/connectors/zendesk-oauth/utils.ts
407
+ function apiFetch(proxyFetch, path2, init) {
408
+ const url = path2.startsWith("/") ? path2 : `/${path2}`;
409
+ const headers = new Headers(init?.headers);
410
+ headers.set("Accept", "application/json");
411
+ return proxyFetch(url, { ...init, headers });
412
+ }
413
+
414
+ // ../connectors/src/connectors/zendesk-oauth/setup-flow.ts
415
+ var ZENDESK_SETUP_MAX_ENTITIES = 5;
416
+ var ZENDESK_ENTITIES = [
417
+ {
418
+ value: "tickets",
419
+ label: "Tickets",
420
+ countPath: "/api/v2/tickets.json?page[size]=1"
421
+ },
422
+ {
423
+ value: "users",
424
+ label: "Users",
425
+ countPath: "/api/v2/users.json?page[size]=1"
426
+ },
427
+ {
428
+ value: "organizations",
429
+ label: "Organizations",
430
+ countPath: "/api/v2/organizations.json?page[size]=1"
431
+ },
432
+ {
433
+ value: "groups",
434
+ label: "Groups",
435
+ countPath: "/api/v2/groups.json?page[size]=1"
436
+ },
437
+ {
438
+ value: "articles",
439
+ label: "Help Center articles",
440
+ countPath: "/api/v2/help_center/articles.json?page[size]=1"
441
+ }
442
+ ];
443
+ async function listBrands(proxyFetch) {
444
+ const res = await apiFetch(proxyFetch, "/api/v2/brands.json");
445
+ if (!res.ok) return [];
446
+ const data = await res.json();
447
+ return data.brands ?? [];
448
+ }
449
+ async function fetchCount(proxyFetch, path2) {
450
+ const res = await apiFetch(proxyFetch, path2);
451
+ if (!res.ok) return null;
452
+ const data = await res.json();
453
+ if (typeof data["count"] === "number") return data["count"];
454
+ return null;
455
+ }
456
+ var zendeskOauthSetupFlow = {
457
+ initialState: () => ({}),
458
+ steps: [
459
+ {
460
+ slug: "brand",
461
+ type: "select",
462
+ question: {
463
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3067\u5BFE\u8C61\u3068\u3059\u308BZendesk\u30D6\u30E9\u30F3\u30C9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
464
+ en: "Select the Zendesk brand to use for setup"
465
+ },
466
+ async fetchOptions(_state, rt) {
467
+ const brands = await listBrands(rt.config.proxyFetch);
468
+ const active = brands.filter((b) => b.active !== false && b.name);
469
+ if (active.length < 2) return [];
470
+ return active.map((b) => ({
471
+ value: String(b.subdomain ?? b.id ?? b.name),
472
+ label: String(b.name)
473
+ }));
474
+ },
475
+ applyAnswer: (state, answer) => ({ ...state, brand: answer[0] })
476
+ },
477
+ {
478
+ slug: "entities",
479
+ type: "multiSelect",
480
+ question: {
481
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3067\u6982\u89B3\u3057\u305F\u3044\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
482
+ en: "Select the entities to include in setup (multi-select allowed)"
483
+ },
484
+ async fetchOptions(_state, _rt) {
485
+ return ZENDESK_ENTITIES.map((e) => ({ value: e.value, label: e.label }));
486
+ },
487
+ applyAnswer: (state, answer) => ({ ...state, entities: answer })
488
+ }
489
+ ],
490
+ async finalize(state, rt) {
491
+ if (!state.entities) {
492
+ throw new Error("Zendesk setup: incomplete state on finalize");
493
+ }
494
+ const targetEntities = await resolveSetupSelection({
495
+ selected: state.entities,
496
+ allSentinel: "__ALL__",
497
+ fetchAll: async () => ZENDESK_ENTITIES.map((e) => e.value),
498
+ limit: ZENDESK_SETUP_MAX_ENTITIES
499
+ });
500
+ const entityByValue = new Map(ZENDESK_ENTITIES.map((e) => [e.value, e]));
501
+ const sections = ["## Zendesk", ""];
502
+ if (state.brand) {
503
+ sections.push(`### Brand: ${state.brand}`, "");
504
+ }
505
+ sections.push("### Selected entities", "");
506
+ sections.push("| Entity | Count |");
507
+ sections.push("|--------|-------|");
508
+ for (const value of targetEntities) {
509
+ const entity = entityByValue.get(value);
510
+ if (!entity) {
511
+ sections.push(`| ${value} | _unknown_ |`);
512
+ continue;
513
+ }
514
+ const count = await fetchCount(rt.config.proxyFetch, entity.countPath);
515
+ sections.push(
516
+ `| ${entity.label} (${entity.value}) | ${count == null ? "-" : count} |`
517
+ );
518
+ }
519
+ sections.push("");
520
+ return sections.join("\n");
521
+ }
522
+ };
523
+
312
524
  // ../connectors/src/connectors/zendesk-oauth/parameters.ts
313
525
  var parameters = {};
314
526
 
@@ -317,6 +529,7 @@ var tools = { request: requestTool };
317
529
  var zendeskOauthConnector = new ConnectorPlugin({
318
530
  slug: "zendesk",
319
531
  authType: AUTH_TYPES.OAUTH,
532
+ skipConnectionCheckOnCreate: true,
320
533
  name: "Zendesk",
321
534
  description: "Connect to Zendesk Support for tickets, users, organizations, and customer service data using OAuth.",
322
535
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/7e9Q7PwV6MJRJMj543m2gl/55385fae903ccfa1599e35be9d3516aa/zendesk-icon.svg",
@@ -451,6 +664,7 @@ const data = await res.json();
451
664
  \`\`\``
452
665
  },
453
666
  tools,
667
+ setup: (params, ctx, config) => runSetupFlow(zendeskOauthSetupFlow, params, ctx, config),
454
668
  async checkConnection(_params, config) {
455
669
  const { proxyFetch } = config;
456
670
  try {
@@ -500,6 +714,7 @@ function resolveEnvVarOptional(entry, key) {
500
714
  import { getContext } from "hono/context-storage";
501
715
  import { getCookie } from "hono/cookie";
502
716
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
717
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
503
718
  function normalizeHeaders(input) {
504
719
  const out = {};
505
720
  if (!input) return out;
@@ -508,6 +723,11 @@ function normalizeHeaders(input) {
508
723
  });
509
724
  return out;
510
725
  }
726
+ function extractInputUrl(input) {
727
+ if (typeof input === "string") return input;
728
+ if (input instanceof URL) return input.href;
729
+ return input.url;
730
+ }
511
731
  function createSandboxProxyFetch(connectionId) {
512
732
  return async (input, init) => {
513
733
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -517,10 +737,17 @@ function createSandboxProxyFetch(connectionId) {
517
737
  "Connection proxy is not configured. Please check your deployment settings."
518
738
  );
519
739
  }
520
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
740
+ const originalUrl = extractInputUrl(input);
741
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
742
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
743
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
744
+ return fetch(sessionUrl, {
745
+ method: "POST",
746
+ headers: { Authorization: `Bearer ${token}` }
747
+ });
748
+ }
521
749
  const originalMethod = init?.method ?? "GET";
522
750
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
523
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
524
751
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
525
752
  return fetch(proxyUrl, {
526
753
  method: "POST",
@@ -546,10 +773,9 @@ function createDeployedAppProxyFetch(connectionId) {
546
773
  }
547
774
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
548
775
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
776
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
549
777
  return async (input, init) => {
550
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
551
- const originalMethod = init?.method ?? "GET";
552
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
778
+ const originalUrl = extractInputUrl(input);
553
779
  const c = getContext();
554
780
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
555
781
  if (!appSession) {
@@ -557,6 +783,14 @@ function createDeployedAppProxyFetch(connectionId) {
557
783
  "No authentication method available for connection proxy."
558
784
  );
559
785
  }
786
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
787
+ return fetch(sessionUrl, {
788
+ method: "POST",
789
+ headers: { Authorization: `Bearer ${appSession}` }
790
+ });
791
+ }
792
+ const originalMethod = init?.method ?? "GET";
793
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
560
794
  return fetch(proxyUrl, {
561
795
  method: "POST",
562
796
  headers: {