@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/sentry/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  organizationSlug: new ParameterDefinition({
48
60
  slug: "organization-slug",
@@ -94,7 +106,7 @@ function createClient(params) {
94
106
  const url = `${BASE_URL}${resolved.startsWith("/") ? "" : "/"}${resolved}`;
95
107
  return authenticatedFetch(url, init);
96
108
  }
97
- async function listProjects() {
109
+ async function listProjects2() {
98
110
  const url = `${BASE_URL}/organizations/${organizationSlug}/projects/`;
99
111
  const response = await authenticatedFetch(url);
100
112
  if (!response.ok) {
@@ -160,7 +172,7 @@ function createClient(params) {
160
172
  }
161
173
  return {
162
174
  request,
163
- listProjects,
175
+ listProjects: listProjects2,
164
176
  listIssues,
165
177
  getIssue,
166
178
  listIssueEvents,
@@ -227,6 +239,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
227
239
  tools;
228
240
  query;
229
241
  checkConnection;
242
+ /**
243
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
244
+ * implement this expose a step-by-step exploration flow (database/schema/
245
+ * table/etc. discovery) that the dashboard backend drives via the
246
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
247
+ * `runSetupFlow` from `setup-flow.ts`.
248
+ */
249
+ setup;
250
+ /**
251
+ * Opt-out of the default "verify before save" behavior on connection
252
+ * creation. The backend invokes `checkConnection` synchronously while
253
+ * creating the connection and aborts (no row inserted) if it fails — this
254
+ * flag disables that for connectors where the check cannot succeed pre-save:
255
+ *
256
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
257
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
258
+ * connectionId, which doesn't exist until the row is saved
259
+ *
260
+ * Exceptions are the explicit position; new credential-input connectors get
261
+ * the default verify-on-create behavior without opt-in.
262
+ */
263
+ skipConnectionCheckOnCreate;
230
264
  constructor(config) {
231
265
  this.slug = config.slug;
232
266
  this.authType = config.authType;
@@ -243,6 +277,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
243
277
  this.tools = config.tools;
244
278
  this.query = config.query;
245
279
  this.checkConnection = config.checkConnection;
280
+ this.setup = config.setup;
281
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
246
282
  }
247
283
  get connectorKey() {
248
284
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -307,6 +343,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
307
343
  }
308
344
  };
309
345
 
346
+ // ../connectors/src/setup-flow.ts
347
+ async function runSetupFlow(flow, params, ctx, config) {
348
+ const runtime = {
349
+ params,
350
+ language: ctx.language,
351
+ config
352
+ };
353
+ let state = flow.initialState();
354
+ let answerIdx = 0;
355
+ const pendingParameterUpdates = [];
356
+ for (const step of flow.steps) {
357
+ const ans = ctx.answers[answerIdx];
358
+ if (ans && ans.questionSlug === step.slug) {
359
+ state = step.applyAnswer(state, ans.answer);
360
+ if (step.toParameterUpdates) {
361
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
362
+ }
363
+ answerIdx += 1;
364
+ continue;
365
+ }
366
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
367
+ if (step.type === "text") {
368
+ if (step.fetchOptions) {
369
+ const options2 = await step.fetchOptions(state, runtime);
370
+ if (options2.length === 0) {
371
+ continue;
372
+ }
373
+ }
374
+ return {
375
+ type: "nextQuestion",
376
+ questionSlug: step.slug,
377
+ question: step.question[ctx.language],
378
+ questionType: "text",
379
+ allowFreeText: resolvedAllowFreeText,
380
+ ...pendingParameterUpdates.length > 0 && {
381
+ parameterUpdates: pendingParameterUpdates
382
+ }
383
+ };
384
+ }
385
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
386
+ if (options.length === 0) {
387
+ continue;
388
+ }
389
+ return {
390
+ type: "nextQuestion",
391
+ questionSlug: step.slug,
392
+ question: step.question[ctx.language],
393
+ questionType: step.type,
394
+ options,
395
+ allowFreeText: resolvedAllowFreeText,
396
+ ...pendingParameterUpdates.length > 0 && {
397
+ parameterUpdates: pendingParameterUpdates
398
+ }
399
+ };
400
+ }
401
+ const dataInvestigationResult = await flow.finalize(state, runtime);
402
+ return {
403
+ type: "fulfilled",
404
+ dataInvestigationResult,
405
+ ...pendingParameterUpdates.length > 0 && {
406
+ parameterUpdates: pendingParameterUpdates
407
+ }
408
+ };
409
+ }
410
+ async function resolveSetupSelection(params) {
411
+ const { selected, allSentinel, fetchAll, limit } = params;
412
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
413
+ return resolved.slice(0, limit);
414
+ }
415
+
310
416
  // ../connectors/src/auth-types.ts
311
417
  var AUTH_TYPES = {
312
418
  OAUTH: "oauth",
@@ -329,9 +435,121 @@ var sentryOnboarding = new ConnectorOnboarding({
329
435
  }
330
436
  });
331
437
 
438
+ // ../connectors/src/connectors/sentry/utils.ts
439
+ var BASE_URL2 = "https://sentry.io/api/0";
440
+ async function apiFetch(params, path2, init) {
441
+ const authToken = params[parameters.authToken.slug];
442
+ if (!authToken) {
443
+ throw new Error("sentry: missing required parameter: auth-token");
444
+ }
445
+ const url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
446
+ const headers = new Headers(init?.headers);
447
+ headers.set("Authorization", `Bearer ${authToken}`);
448
+ if (!headers.has("Accept")) headers.set("Accept", "application/json");
449
+ return fetch(url, { ...init, headers });
450
+ }
451
+
452
+ // ../connectors/src/connectors/sentry/setup-flow.ts
453
+ var ALL_PROJECTS = "__ALL_PROJECTS__";
454
+ var SENTRY_SETUP_MAX_PROJECTS = 20;
455
+ async function listOrganizations(params) {
456
+ const res = await apiFetch(params, "/organizations/");
457
+ if (!res.ok) {
458
+ const body = await res.text().catch(() => res.statusText);
459
+ throw new Error(`sentry: listOrganizations failed (${res.status}): ${body}`);
460
+ }
461
+ const data = await res.json();
462
+ return data ?? [];
463
+ }
464
+ async function listProjects(params, orgSlug) {
465
+ const res = await apiFetch(params, `/organizations/${orgSlug}/projects/`);
466
+ if (!res.ok) {
467
+ const body = await res.text().catch(() => res.statusText);
468
+ throw new Error(`sentry: listProjects failed (${res.status}): ${body}`);
469
+ }
470
+ const data = await res.json();
471
+ return data ?? [];
472
+ }
473
+ var sentrySetupFlow = {
474
+ initialState: () => ({}),
475
+ steps: [
476
+ {
477
+ slug: "organization",
478
+ type: "select",
479
+ question: {
480
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u7D44\u7E54\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
481
+ en: "Select the organization to use for setup"
482
+ },
483
+ async fetchOptions(_state, rt) {
484
+ const orgs = await listOrganizations(rt.params);
485
+ return orgs.filter((o) => o.slug).map((o) => ({ value: o.slug, label: o.name || o.slug }));
486
+ },
487
+ applyAnswer: (state, answer) => ({ ...state, organization: answer[0] })
488
+ },
489
+ {
490
+ slug: "projects",
491
+ type: "multiSelect",
492
+ question: {
493
+ ja: "\u5BFE\u8C61\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
494
+ en: "Select target projects (multi-select allowed)"
495
+ },
496
+ async fetchOptions(state, rt) {
497
+ if (!state.organization) return [];
498
+ const projects = await listProjects(rt.params, state.organization);
499
+ const opts = projects.filter((p) => p.slug).map((p) => ({ value: p.slug, label: p.name || p.slug }));
500
+ if (opts.length === 0) return [];
501
+ return [
502
+ {
503
+ value: ALL_PROJECTS,
504
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8" : "All projects"
505
+ },
506
+ ...opts
507
+ ];
508
+ },
509
+ applyAnswer: (state, answer) => ({ ...state, projects: answer })
510
+ }
511
+ ],
512
+ async finalize(state, rt) {
513
+ if (!state.organization || !state.projects) {
514
+ throw new Error("Sentry setup: incomplete state on finalize");
515
+ }
516
+ const orgSlug = state.organization;
517
+ const projects = await listProjects(rt.params, orgSlug);
518
+ const bySlug = new Map(projects.map((p) => [p.slug, p]));
519
+ const targetSlugs = await resolveSetupSelection({
520
+ selected: state.projects,
521
+ allSentinel: ALL_PROJECTS,
522
+ fetchAll: async () => projects.map((p) => p.slug).filter((s) => s),
523
+ limit: SENTRY_SETUP_MAX_PROJECTS
524
+ });
525
+ const sections = [
526
+ "## Sentry",
527
+ "",
528
+ `### Organization: ${orgSlug}`,
529
+ ""
530
+ ];
531
+ for (const slug of targetSlugs) {
532
+ const project = bySlug.get(slug);
533
+ if (!project) {
534
+ sections.push(`#### Project: ${slug}`, "", "_Not found._", "");
535
+ continue;
536
+ }
537
+ sections.push(`#### Project: ${project.name || project.slug}`, "");
538
+ sections.push("| Field | Value |");
539
+ sections.push("|-------|-------|");
540
+ sections.push(`| Slug | ${project.slug} |`);
541
+ sections.push(`| Platform | ${project.platform ?? "-"} |`);
542
+ sections.push(`| First event | ${project.firstEvent ?? "-"} |`);
543
+ sections.push(`| Created | ${project.dateCreated ?? "-"} |`);
544
+ sections.push("");
545
+ }
546
+ return sections.join("\n");
547
+ }
548
+ };
549
+
332
550
  // ../connectors/src/connectors/sentry/tools/request.ts
333
551
  import { z } from "zod";
334
- var BASE_URL2 = "https://sentry.io/api/0";
552
+ var BASE_URL3 = "https://sentry.io/api/0";
335
553
  var REQUEST_TIMEOUT_MS = 6e4;
336
554
  var inputSchema = z.object({
337
555
  toolUseIntent: z.string().optional().describe(
@@ -381,7 +599,7 @@ Authentication is handled automatically via Bearer token.
381
599
  /\{organizationSlug\}/g,
382
600
  organizationSlug
383
601
  );
384
- const url = `${BASE_URL2}${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
602
+ const url = `${BASE_URL3}${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
385
603
  const controller = new AbortController();
386
604
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
387
605
  try {
@@ -590,6 +808,7 @@ await sentry.updateIssue("12345", { status: "resolved" });
590
808
  \`\`\``
591
809
  },
592
810
  tools,
811
+ setup: (params, ctx, config) => runSetupFlow(sentrySetupFlow, params, ctx, config),
593
812
  async checkConnection(params) {
594
813
  const authToken = params[parameters.authToken.slug];
595
814
  const organizationSlug = params[parameters.organizationSlug.slug];
@@ -651,6 +870,7 @@ function resolveEnvVarOptional(entry, key) {
651
870
  import { getContext } from "hono/context-storage";
652
871
  import { getCookie } from "hono/cookie";
653
872
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
873
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
654
874
  function normalizeHeaders(input) {
655
875
  const out = {};
656
876
  if (!input) return out;
@@ -659,6 +879,11 @@ function normalizeHeaders(input) {
659
879
  });
660
880
  return out;
661
881
  }
882
+ function extractInputUrl(input) {
883
+ if (typeof input === "string") return input;
884
+ if (input instanceof URL) return input.href;
885
+ return input.url;
886
+ }
662
887
  function createSandboxProxyFetch(connectionId) {
663
888
  return async (input, init) => {
664
889
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -668,10 +893,17 @@ function createSandboxProxyFetch(connectionId) {
668
893
  "Connection proxy is not configured. Please check your deployment settings."
669
894
  );
670
895
  }
671
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
896
+ const originalUrl = extractInputUrl(input);
897
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
898
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
899
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
900
+ return fetch(sessionUrl, {
901
+ method: "POST",
902
+ headers: { Authorization: `Bearer ${token}` }
903
+ });
904
+ }
672
905
  const originalMethod = init?.method ?? "GET";
673
906
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
674
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
675
907
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
676
908
  return fetch(proxyUrl, {
677
909
  method: "POST",
@@ -697,10 +929,9 @@ function createDeployedAppProxyFetch(connectionId) {
697
929
  }
698
930
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
699
931
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
932
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
700
933
  return async (input, init) => {
701
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
702
- const originalMethod = init?.method ?? "GET";
703
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
934
+ const originalUrl = extractInputUrl(input);
704
935
  const c = getContext();
705
936
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
706
937
  if (!appSession) {
@@ -708,6 +939,14 @@ function createDeployedAppProxyFetch(connectionId) {
708
939
  "No authentication method available for connection proxy."
709
940
  );
710
941
  }
942
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
943
+ return fetch(sessionUrl, {
944
+ method: "POST",
945
+ headers: { Authorization: `Bearer ${appSession}` }
946
+ });
947
+ }
948
+ const originalMethod = init?.method ?? "GET";
949
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
711
950
  return fetch(proxyUrl, {
712
951
  method: "POST",
713
952
  headers: {