@squadbase/vite-server 0.1.12-dev.a9ac647 → 0.1.17-dev.24af54e

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 +12374 -883
  2. package/dist/connectors/airtable-oauth.js +257 -46
  3. package/dist/connectors/airtable.js +294 -51
  4. package/dist/connectors/amplitude.js +297 -47
  5. package/dist/connectors/anthropic.js +135 -47
  6. package/dist/connectors/asana.js +302 -49
  7. package/dist/connectors/attio.js +277 -49
  8. package/dist/connectors/aws-billing.js +262 -46
  9. package/dist/connectors/azure-sql.js +396 -102
  10. package/dist/connectors/backlog-api-key.js +292 -47
  11. package/dist/connectors/clickup.js +313 -49
  12. package/dist/connectors/cosmosdb.js +280 -50
  13. package/dist/connectors/customerio.js +294 -47
  14. package/dist/connectors/dbt.js +315 -47
  15. package/dist/connectors/freshdesk.js +317 -53
  16. package/dist/connectors/freshsales.js +308 -52
  17. package/dist/connectors/freshservice.js +336 -53
  18. package/dist/connectors/gamma.js +302 -52
  19. package/dist/connectors/gemini.js +134 -47
  20. package/dist/connectors/github.js +361 -49
  21. package/dist/connectors/gmail-oauth.js +179 -7
  22. package/dist/connectors/gmail.js +325 -47
  23. package/dist/connectors/google-ads.js +263 -46
  24. package/dist/connectors/google-analytics-oauth.js +285 -46
  25. package/dist/connectors/google-analytics.js +387 -49
  26. package/dist/connectors/google-audit-log.js +413 -47
  27. package/dist/connectors/google-calendar-oauth.js +234 -46
  28. package/dist/connectors/google-calendar.js +334 -47
  29. package/dist/connectors/google-docs.js +195 -6
  30. package/dist/connectors/google-drive.js +237 -5
  31. package/dist/connectors/google-search-console-oauth.js +231 -46
  32. package/dist/connectors/google-sheets.js +247 -47
  33. package/dist/connectors/google-slides.js +180 -6
  34. package/dist/connectors/grafana.js +307 -49
  35. package/dist/connectors/hubspot-oauth.js +183 -5
  36. package/dist/connectors/hubspot.js +281 -49
  37. package/dist/connectors/influxdb.js +391 -51
  38. package/dist/connectors/intercom-oauth.js +185 -5
  39. package/dist/connectors/intercom.js +277 -49
  40. package/dist/connectors/jdbc.js +737 -110
  41. package/dist/connectors/jira-api-key.js +301 -47
  42. package/dist/connectors/kintone-api-token.js +256 -47
  43. package/dist/connectors/kintone.js +303 -47
  44. package/dist/connectors/linear.js +305 -49
  45. package/dist/connectors/linkedin-ads.js +243 -50
  46. package/dist/connectors/mailchimp-oauth.js +243 -46
  47. package/dist/connectors/mailchimp.js +295 -49
  48. package/dist/connectors/meta-ads-oauth.js +248 -48
  49. package/dist/connectors/meta-ads.js +260 -50
  50. package/dist/connectors/mixpanel.js +313 -47
  51. package/dist/connectors/monday.js +335 -49
  52. package/dist/connectors/mongodb.js +294 -57
  53. package/dist/connectors/notion-oauth.js +206 -5
  54. package/dist/connectors/notion.js +298 -51
  55. package/dist/connectors/openai.js +134 -47
  56. package/dist/connectors/oracle.js +414 -103
  57. package/dist/connectors/outlook-oauth.js +179 -5
  58. package/dist/connectors/powerbi-oauth.js +226 -5
  59. package/dist/connectors/salesforce.js +359 -49
  60. package/dist/connectors/semrush.js +289 -49
  61. package/dist/connectors/sentry.js +264 -50
  62. package/dist/connectors/shopify-oauth.js +162 -5
  63. package/dist/connectors/shopify.js +332 -47
  64. package/dist/connectors/sqlserver.js +390 -102
  65. package/dist/connectors/stripe-api-key.js +244 -46
  66. package/dist/connectors/stripe-oauth.js +177 -5
  67. package/dist/connectors/supabase.js +278 -48
  68. package/dist/connectors/tableau.js +389 -184
  69. package/dist/connectors/tiktok-ads.js +254 -48
  70. package/dist/connectors/wix-store.js +295 -49
  71. package/dist/connectors/zendesk-oauth.js +214 -5
  72. package/dist/connectors/zendesk.js +333 -47
  73. package/dist/index.d.ts +149 -1
  74. package/dist/index.js +13677 -1969
  75. package/dist/main.js +13627 -1927
  76. package/dist/vite-plugin.js +12391 -890
  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/airtable/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  baseId: new ParameterDefinition({
48
60
  slug: "base-id",
@@ -176,7 +188,7 @@ function createClient(params) {
176
188
  }
177
189
  return await response.json();
178
190
  }
179
- async function listTables() {
191
+ async function listTables2() {
180
192
  const path2 = `/meta/bases/${baseId}/tables`;
181
193
  const response = await request(path2);
182
194
  if (!response.ok) {
@@ -193,7 +205,7 @@ function createClient(params) {
193
205
  getRecord,
194
206
  createRecords,
195
207
  updateRecords,
196
- listTables
208
+ listTables: listTables2
197
209
  };
198
210
  }
199
211
 
@@ -256,6 +268,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
256
268
  tools;
257
269
  query;
258
270
  checkConnection;
271
+ /**
272
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
273
+ * implement this expose a step-by-step exploration flow (database/schema/
274
+ * table/etc. discovery) that the dashboard backend drives via the
275
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
276
+ * `runSetupFlow` from `setup-flow.ts`.
277
+ */
278
+ setup;
279
+ /**
280
+ * Opt-out of the default "verify before save" behavior on connection
281
+ * creation. The backend invokes `checkConnection` synchronously while
282
+ * creating the connection and aborts (no row inserted) if it fails — this
283
+ * flag disables that for connectors where the check cannot succeed pre-save:
284
+ *
285
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
286
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
287
+ * connectionId, which doesn't exist until the row is saved
288
+ *
289
+ * Exceptions are the explicit position; new credential-input connectors get
290
+ * the default verify-on-create behavior without opt-in.
291
+ */
292
+ skipConnectionCheckOnCreate;
259
293
  constructor(config) {
260
294
  this.slug = config.slug;
261
295
  this.authType = config.authType;
@@ -272,6 +306,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
272
306
  this.tools = config.tools;
273
307
  this.query = config.query;
274
308
  this.checkConnection = config.checkConnection;
309
+ this.setup = config.setup;
310
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
275
311
  }
276
312
  get connectorKey() {
277
313
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -336,6 +372,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
336
372
  }
337
373
  };
338
374
 
375
+ // ../connectors/src/setup-flow.ts
376
+ async function runSetupFlow(flow, params, ctx, config) {
377
+ const runtime = {
378
+ params,
379
+ language: ctx.language,
380
+ config
381
+ };
382
+ let state = flow.initialState();
383
+ let answerIdx = 0;
384
+ for (const step of flow.steps) {
385
+ const ans = ctx.answers[answerIdx];
386
+ if (ans && ans.questionSlug === step.slug) {
387
+ state = step.applyAnswer(state, ans.answer);
388
+ answerIdx += 1;
389
+ continue;
390
+ }
391
+ if (step.type === "text") {
392
+ return {
393
+ type: "nextQuestion",
394
+ questionSlug: step.slug,
395
+ question: step.question[ctx.language],
396
+ questionType: "text"
397
+ };
398
+ }
399
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
400
+ if (options.length === 0) {
401
+ continue;
402
+ }
403
+ return {
404
+ type: "nextQuestion",
405
+ questionSlug: step.slug,
406
+ question: step.question[ctx.language],
407
+ questionType: step.type,
408
+ options
409
+ };
410
+ }
411
+ const dataInvestigationResult = await flow.finalize(state, runtime);
412
+ return { type: "fulfilled", dataInvestigationResult };
413
+ }
414
+ async function resolveSetupSelection(params) {
415
+ const { selected, allSentinel, fetchAll, limit } = params;
416
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
417
+ return resolved.slice(0, limit);
418
+ }
419
+
339
420
  // ../connectors/src/auth-types.ts
340
421
  var AUTH_TYPES = {
341
422
  OAUTH: "oauth",
@@ -356,9 +437,119 @@ var airtableOnboarding = new ConnectorOnboarding({
356
437
  }
357
438
  });
358
439
 
440
+ // ../connectors/src/connectors/airtable/utils.ts
441
+ var BASE_URL2 = "https://api.airtable.com/v0";
442
+ async function apiFetch(params, path2, init) {
443
+ const apiKey = params[parameters.apiKey.slug];
444
+ if (!apiKey) {
445
+ throw new Error("airtable: missing required parameter: api-key");
446
+ }
447
+ const url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
448
+ const headers = new Headers(init?.headers);
449
+ headers.set("Authorization", `Bearer ${apiKey}`);
450
+ return fetch(url, { ...init, headers });
451
+ }
452
+
453
+ // ../connectors/src/connectors/airtable/setup-flow.ts
454
+ var ALL_TABLES = "__ALL_TABLES__";
455
+ var AIRTABLE_SETUP_MAX_TABLES = 20;
456
+ async function listBases(params) {
457
+ const res = await apiFetch(params, "/meta/bases");
458
+ if (!res.ok) {
459
+ const body = await res.text().catch(() => res.statusText);
460
+ throw new Error(`airtable: listBases failed (${res.status}): ${body}`);
461
+ }
462
+ const data = await res.json();
463
+ return data.bases ?? [];
464
+ }
465
+ async function listTables(params, baseId) {
466
+ const res = await apiFetch(params, `/meta/bases/${baseId}/tables`);
467
+ if (!res.ok) {
468
+ const body = await res.text().catch(() => res.statusText);
469
+ throw new Error(`airtable: listTables failed (${res.status}): ${body}`);
470
+ }
471
+ const data = await res.json();
472
+ return data.tables ?? [];
473
+ }
474
+ var airtableSetupFlow = {
475
+ initialState: () => ({}),
476
+ steps: [
477
+ {
478
+ slug: "base",
479
+ type: "select",
480
+ question: {
481
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
482
+ en: "Select the base to use for setup"
483
+ },
484
+ async fetchOptions(_state, rt) {
485
+ const bases = await listBases(rt.params);
486
+ return bases.filter((b) => b.id && b.name).map((b) => ({ value: b.id, label: b.name }));
487
+ },
488
+ applyAnswer: (state, answer) => ({ ...state, base: answer[0] })
489
+ },
490
+ {
491
+ slug: "tables",
492
+ type: "multiSelect",
493
+ question: {
494
+ ja: "\u5BFE\u8C61\u30C6\u30FC\u30D6\u30EB\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
495
+ en: "Select target tables (multi-select allowed)"
496
+ },
497
+ async fetchOptions(state, rt) {
498
+ if (!state.base) return [];
499
+ const tables = await listTables(rt.params, state.base);
500
+ const tableOptions = tables.filter((t) => t.name).map((t) => ({ value: t.name }));
501
+ return [
502
+ {
503
+ value: ALL_TABLES,
504
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C6\u30FC\u30D6\u30EB" : "All tables"
505
+ },
506
+ ...tableOptions
507
+ ];
508
+ },
509
+ applyAnswer: (state, answer) => ({ ...state, tables: answer })
510
+ }
511
+ ],
512
+ async finalize(state, rt) {
513
+ if (!state.base || !state.tables) {
514
+ throw new Error("Airtable setup: incomplete state on finalize");
515
+ }
516
+ const baseId = state.base;
517
+ const tables = await listTables(rt.params, baseId);
518
+ const tableByName = new Map(tables.map((t) => [t.name, t]));
519
+ const targetTableNames = await resolveSetupSelection({
520
+ selected: state.tables,
521
+ allSentinel: ALL_TABLES,
522
+ fetchAll: async () => tables.map((t) => t.name).filter((n) => n),
523
+ limit: AIRTABLE_SETUP_MAX_TABLES
524
+ });
525
+ const sections = [
526
+ "## Airtable",
527
+ "",
528
+ `### Base: ${baseId}`,
529
+ ""
530
+ ];
531
+ for (const tableName of targetTableNames) {
532
+ const table = tableByName.get(tableName);
533
+ if (!table) {
534
+ sections.push(`#### Table: ${tableName}`, "", "_Not found._", "");
535
+ continue;
536
+ }
537
+ sections.push(`#### Table: ${table.name}`, "");
538
+ sections.push("| Field | Type | Description |");
539
+ sections.push("|-------|------|-------------|");
540
+ for (const f of table.fields ?? []) {
541
+ const description = (f.description ?? "").replace(/\|/g, "\\|");
542
+ sections.push(`| ${f.name} | ${f.type} | ${description || "-"} |`);
543
+ }
544
+ sections.push("");
545
+ }
546
+ return sections.join("\n");
547
+ }
548
+ };
549
+
359
550
  // ../connectors/src/connectors/airtable/tools/request.ts
360
551
  import { z } from "zod";
361
- var BASE_URL2 = "https://api.airtable.com/v0/";
552
+ var BASE_URL3 = "https://api.airtable.com/v0/";
362
553
  var REQUEST_TIMEOUT_MS = 6e4;
363
554
  var inputSchema = z.object({
364
555
  toolUseIntent: z.string().optional().describe("Brief description of what you intend to accomplish with this tool call"),
@@ -395,7 +586,7 @@ Authentication is handled automatically using the API Key.
395
586
  const apiKey = parameters.apiKey.getValue(connection2);
396
587
  const baseId = parameters.baseId.getValue(connection2);
397
588
  const resolvedPath = path2.replace(/\{baseId\}/g, baseId);
398
- const url = `${BASE_URL2}${resolvedPath}`;
589
+ const url = `${BASE_URL3}${resolvedPath}`;
399
590
  const controller = new AbortController();
400
591
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
401
592
  try {
@@ -559,7 +750,39 @@ export default async function handler(c: Context) {
559
750
  #### \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3
560
751
  - \u30EC\u30B9\u30DD\u30F3\u30B9\u306B \`offset\` \u304C\u542B\u307E\u308C\u308B\u5834\u5408\u3001\u6B21\u306E\u30EA\u30AF\u30A8\u30B9\u30C8\u306B \`?offset={offset}\` \u3092\u8FFD\u52A0\u3057\u3066\u6B21\u306E\u30DA\u30FC\u30B8\u3092\u53D6\u5F97\u3057\u307E\u3059`
561
752
  },
562
- tools
753
+ tools,
754
+ setup: (params, ctx, config) => runSetupFlow(airtableSetupFlow, params, ctx, config),
755
+ async checkConnection(params, _config) {
756
+ const apiKey = params[parameters.apiKey.slug];
757
+ if (!apiKey) {
758
+ return {
759
+ success: false,
760
+ error: `Missing required parameter: ${parameters.apiKey.slug}`
761
+ };
762
+ }
763
+ try {
764
+ const res = await fetch("https://api.airtable.com/v0/meta/whoami", {
765
+ method: "GET",
766
+ headers: {
767
+ Authorization: `Bearer ${apiKey}`,
768
+ Accept: "application/json"
769
+ }
770
+ });
771
+ if (!res.ok) {
772
+ const errorText = await res.text().catch(() => res.statusText);
773
+ return {
774
+ success: false,
775
+ error: `Airtable API failed: HTTP ${res.status} ${errorText}`
776
+ };
777
+ }
778
+ return { success: true };
779
+ } catch (error) {
780
+ return {
781
+ success: false,
782
+ error: error instanceof Error ? error.message : String(error)
783
+ };
784
+ }
785
+ }
563
786
  });
564
787
 
565
788
  // src/connectors/create-connector-sdk.ts
@@ -588,6 +811,7 @@ function resolveEnvVarOptional(entry, key) {
588
811
  import { getContext } from "hono/context-storage";
589
812
  import { getCookie } from "hono/cookie";
590
813
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
814
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
591
815
  function normalizeHeaders(input) {
592
816
  const out = {};
593
817
  if (!input) return out;
@@ -596,6 +820,11 @@ function normalizeHeaders(input) {
596
820
  });
597
821
  return out;
598
822
  }
823
+ function extractInputUrl(input) {
824
+ if (typeof input === "string") return input;
825
+ if (input instanceof URL) return input.href;
826
+ return input.url;
827
+ }
599
828
  function createSandboxProxyFetch(connectionId) {
600
829
  return async (input, init) => {
601
830
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -605,10 +834,17 @@ function createSandboxProxyFetch(connectionId) {
605
834
  "Connection proxy is not configured. Please check your deployment settings."
606
835
  );
607
836
  }
608
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
837
+ const originalUrl = extractInputUrl(input);
838
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
839
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
840
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
841
+ return fetch(sessionUrl, {
842
+ method: "POST",
843
+ headers: { Authorization: `Bearer ${token}` }
844
+ });
845
+ }
609
846
  const originalMethod = init?.method ?? "GET";
610
847
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
611
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
612
848
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
613
849
  return fetch(proxyUrl, {
614
850
  method: "POST",
@@ -634,10 +870,9 @@ function createDeployedAppProxyFetch(connectionId) {
634
870
  }
635
871
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
636
872
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
873
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
637
874
  return async (input, init) => {
638
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
639
- const originalMethod = init?.method ?? "GET";
640
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
875
+ const originalUrl = extractInputUrl(input);
641
876
  const c = getContext();
642
877
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
643
878
  if (!appSession) {
@@ -645,6 +880,14 @@ function createDeployedAppProxyFetch(connectionId) {
645
880
  "No authentication method available for connection proxy."
646
881
  );
647
882
  }
883
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
884
+ return fetch(sessionUrl, {
885
+ method: "POST",
886
+ headers: { Authorization: `Bearer ${appSession}` }
887
+ });
888
+ }
889
+ const originalMethod = init?.method ?? "GET";
890
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
648
891
  return fetch(proxyUrl, {
649
892
  method: "POST",
650
893
  headers: {