@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
@@ -71,6 +71,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
71
71
  tools;
72
72
  query;
73
73
  checkConnection;
74
+ /**
75
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
76
+ * implement this expose a step-by-step exploration flow (database/schema/
77
+ * table/etc. discovery) that the dashboard backend drives via the
78
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
79
+ * `runSetupFlow` from `setup-flow.ts`.
80
+ */
81
+ setup;
82
+ /**
83
+ * Opt-out of the default "verify before save" behavior on connection
84
+ * creation. The backend invokes `checkConnection` synchronously while
85
+ * creating the connection and aborts (no row inserted) if it fails — this
86
+ * flag disables that for connectors where the check cannot succeed pre-save:
87
+ *
88
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
89
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
90
+ * connectionId, which doesn't exist until the row is saved
91
+ *
92
+ * Exceptions are the explicit position; new credential-input connectors get
93
+ * the default verify-on-create behavior without opt-in.
94
+ */
95
+ skipConnectionCheckOnCreate;
74
96
  constructor(config) {
75
97
  this.slug = config.slug;
76
98
  this.authType = config.authType;
@@ -87,6 +109,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
87
109
  this.tools = config.tools;
88
110
  this.query = config.query;
89
111
  this.checkConnection = config.checkConnection;
112
+ this.setup = config.setup;
113
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
90
114
  }
91
115
  get connectorKey() {
92
116
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -151,6 +175,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
151
175
  }
152
176
  };
153
177
 
178
+ // ../connectors/src/setup-flow.ts
179
+ async function runSetupFlow(flow, params, ctx, config) {
180
+ const runtime = {
181
+ params,
182
+ language: ctx.language,
183
+ config
184
+ };
185
+ let state = flow.initialState();
186
+ let answerIdx = 0;
187
+ const pendingParameterUpdates = [];
188
+ for (const step of flow.steps) {
189
+ const ans = ctx.answers[answerIdx];
190
+ if (ans && ans.questionSlug === step.slug) {
191
+ state = step.applyAnswer(state, ans.answer);
192
+ if (step.toParameterUpdates) {
193
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
194
+ }
195
+ answerIdx += 1;
196
+ continue;
197
+ }
198
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
199
+ if (step.type === "text") {
200
+ if (step.fetchOptions) {
201
+ const options2 = await step.fetchOptions(state, runtime);
202
+ if (options2.length === 0) {
203
+ continue;
204
+ }
205
+ }
206
+ return {
207
+ type: "nextQuestion",
208
+ questionSlug: step.slug,
209
+ question: step.question[ctx.language],
210
+ questionType: "text",
211
+ allowFreeText: resolvedAllowFreeText,
212
+ ...pendingParameterUpdates.length > 0 && {
213
+ parameterUpdates: pendingParameterUpdates
214
+ }
215
+ };
216
+ }
217
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
218
+ if (options.length === 0) {
219
+ continue;
220
+ }
221
+ return {
222
+ type: "nextQuestion",
223
+ questionSlug: step.slug,
224
+ question: step.question[ctx.language],
225
+ questionType: step.type,
226
+ options,
227
+ allowFreeText: resolvedAllowFreeText,
228
+ ...pendingParameterUpdates.length > 0 && {
229
+ parameterUpdates: pendingParameterUpdates
230
+ }
231
+ };
232
+ }
233
+ const dataInvestigationResult = await flow.finalize(state, runtime);
234
+ return {
235
+ type: "fulfilled",
236
+ dataInvestigationResult,
237
+ ...pendingParameterUpdates.length > 0 && {
238
+ parameterUpdates: pendingParameterUpdates
239
+ }
240
+ };
241
+ }
242
+ async function resolveSetupSelection(params) {
243
+ const { selected, allSentinel, fetchAll, limit } = params;
244
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
245
+ return resolved.slice(0, limit);
246
+ }
247
+
154
248
  // ../connectors/src/auth-types.ts
155
249
  var AUTH_TYPES = {
156
250
  OAUTH: "oauth",
@@ -315,11 +409,122 @@ var notionOauthOnboarding = new ConnectorOnboarding({
315
409
  // ../connectors/src/connectors/notion-oauth/parameters.ts
316
410
  var parameters = {};
317
411
 
412
+ // ../connectors/src/connectors/notion-oauth/utils.ts
413
+ var BASE_URL3 = "https://api.notion.com/v1";
414
+ var NOTION_VERSION3 = "2022-06-28";
415
+ function apiFetch(proxyFetch, path2, init) {
416
+ const url = `${BASE_URL3}${path2.startsWith("/") ? "" : "/"}${path2}`;
417
+ const headers = new Headers(init?.headers);
418
+ headers.set("Notion-Version", NOTION_VERSION3);
419
+ if (init?.body && !headers.has("Content-Type")) {
420
+ headers.set("Content-Type", "application/json");
421
+ }
422
+ return proxyFetch(url, { ...init, headers });
423
+ }
424
+
425
+ // ../connectors/src/connectors/notion-oauth/setup-flow.ts
426
+ var ALL_DATABASES = "__ALL_DATABASES__";
427
+ var NOTION_SETUP_MAX_DATABASES = 20;
428
+ function databaseTitle(db) {
429
+ const parts = (db.title ?? []).map((t) => t.plain_text ?? "").filter((s) => s);
430
+ return parts.join("").trim() || "(Untitled)";
431
+ }
432
+ async function searchDatabases(proxyFetch) {
433
+ const results = [];
434
+ let startCursor;
435
+ for (let i = 0; i < 20; i++) {
436
+ const body = {
437
+ filter: { property: "object", value: "database" },
438
+ page_size: 100
439
+ };
440
+ if (startCursor) body.start_cursor = startCursor;
441
+ const res = await apiFetch(proxyFetch, "/search", {
442
+ method: "POST",
443
+ body: JSON.stringify(body)
444
+ });
445
+ if (!res.ok) {
446
+ const text = await res.text().catch(() => res.statusText);
447
+ throw new Error(
448
+ `notion-oauth: search failed (${res.status}): ${text}`
449
+ );
450
+ }
451
+ const data = await res.json();
452
+ for (const r of data.results ?? []) results.push(r);
453
+ if (!data.has_more || !data.next_cursor) break;
454
+ startCursor = data.next_cursor;
455
+ }
456
+ return results;
457
+ }
458
+ async function getDatabase(proxyFetch, databaseId) {
459
+ const res = await apiFetch(proxyFetch, `/databases/${databaseId}`);
460
+ if (!res.ok) {
461
+ const text = await res.text().catch(() => res.statusText);
462
+ throw new Error(
463
+ `notion-oauth: getDatabase ${databaseId} failed (${res.status}): ${text}`
464
+ );
465
+ }
466
+ return await res.json();
467
+ }
468
+ var notionOauthSetupFlow = {
469
+ initialState: () => ({}),
470
+ steps: [
471
+ {
472
+ slug: "databases",
473
+ type: "multiSelect",
474
+ question: {
475
+ ja: "\u5BFE\u8C61\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
476
+ en: "Select target databases (multi-select allowed)"
477
+ },
478
+ async fetchOptions(_state, rt) {
479
+ const dbs = await searchDatabases(rt.config.proxyFetch);
480
+ const dbOptions = dbs.filter((db) => db.id).map((db) => ({ value: db.id, label: databaseTitle(db) }));
481
+ return [
482
+ {
483
+ value: ALL_DATABASES,
484
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9" : "All databases"
485
+ },
486
+ ...dbOptions
487
+ ];
488
+ },
489
+ applyAnswer: (state, answer) => ({ ...state, databases: answer })
490
+ }
491
+ ],
492
+ async finalize(state, rt) {
493
+ if (!state.databases) {
494
+ throw new Error("Notion setup: incomplete state on finalize");
495
+ }
496
+ const targetIds = await resolveSetupSelection({
497
+ selected: state.databases,
498
+ allSentinel: ALL_DATABASES,
499
+ fetchAll: async () => {
500
+ const dbs = await searchDatabases(rt.config.proxyFetch);
501
+ return dbs.map((db) => db.id).filter((id) => id);
502
+ },
503
+ limit: NOTION_SETUP_MAX_DATABASES
504
+ });
505
+ const sections = ["## Notion", ""];
506
+ for (const dbId of targetIds) {
507
+ const db = await getDatabase(rt.config.proxyFetch, dbId);
508
+ const title = databaseTitle(db);
509
+ sections.push(`### Database: ${title}`, "", `- id: \`${db.id}\``, "");
510
+ sections.push("| Property | Type |");
511
+ sections.push("|----------|------|");
512
+ for (const [name, def] of Object.entries(db.properties ?? {})) {
513
+ const escapedName = name.replace(/\|/g, "\\|");
514
+ sections.push(`| ${escapedName} | ${def?.type ?? "-"} |`);
515
+ }
516
+ sections.push("");
517
+ }
518
+ return sections.join("\n");
519
+ }
520
+ };
521
+
318
522
  // ../connectors/src/connectors/notion-oauth/index.ts
319
523
  var tools = { request: requestTool };
320
524
  var notionOauthConnector = new ConnectorPlugin({
321
525
  slug: "notion",
322
526
  authType: AUTH_TYPES.OAUTH,
527
+ skipConnectionCheckOnCreate: true,
323
528
  name: "Notion",
324
529
  description: "Connect to Notion to query databases, pages, and workspace content using OAuth.",
325
530
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/797V5GDDTA8bsfKUHBCoQO/290ec49b70b68ddb4acd3bf0a6ab8bda/notion-icon.webp",
@@ -438,6 +643,7 @@ const data = await res.json();
438
643
  \`\`\``
439
644
  },
440
645
  tools,
646
+ setup: (params, ctx, config) => runSetupFlow(notionOauthSetupFlow, params, ctx, config),
441
647
  async checkConnection(_params, config) {
442
648
  const { proxyFetch } = config;
443
649
  try {
@@ -488,6 +694,7 @@ function resolveEnvVarOptional(entry, key) {
488
694
  import { getContext } from "hono/context-storage";
489
695
  import { getCookie } from "hono/cookie";
490
696
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
697
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
491
698
  function normalizeHeaders(input) {
492
699
  const out = {};
493
700
  if (!input) return out;
@@ -496,6 +703,11 @@ function normalizeHeaders(input) {
496
703
  });
497
704
  return out;
498
705
  }
706
+ function extractInputUrl(input) {
707
+ if (typeof input === "string") return input;
708
+ if (input instanceof URL) return input.href;
709
+ return input.url;
710
+ }
499
711
  function createSandboxProxyFetch(connectionId) {
500
712
  return async (input, init) => {
501
713
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -505,10 +717,17 @@ function createSandboxProxyFetch(connectionId) {
505
717
  "Connection proxy is not configured. Please check your deployment settings."
506
718
  );
507
719
  }
508
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
720
+ const originalUrl = extractInputUrl(input);
721
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
722
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
723
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
724
+ return fetch(sessionUrl, {
725
+ method: "POST",
726
+ headers: { Authorization: `Bearer ${token}` }
727
+ });
728
+ }
509
729
  const originalMethod = init?.method ?? "GET";
510
730
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
511
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
512
731
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
513
732
  return fetch(proxyUrl, {
514
733
  method: "POST",
@@ -534,10 +753,9 @@ function createDeployedAppProxyFetch(connectionId) {
534
753
  }
535
754
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
536
755
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
756
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
537
757
  return async (input, init) => {
538
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
539
- const originalMethod = init?.method ?? "GET";
540
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
758
+ const originalUrl = extractInputUrl(input);
541
759
  const c = getContext();
542
760
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
543
761
  if (!appSession) {
@@ -545,6 +763,14 @@ function createDeployedAppProxyFetch(connectionId) {
545
763
  "No authentication method available for connection proxy."
546
764
  );
547
765
  }
766
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
767
+ return fetch(sessionUrl, {
768
+ method: "POST",
769
+ headers: { Authorization: `Bearer ${appSession}` }
770
+ });
771
+ }
772
+ const originalMethod = init?.method ?? "GET";
773
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
548
774
  return fetch(proxyUrl, {
549
775
  method: "POST",
550
776
  headers: {