@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/airtable-oauth/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  baseId: new ParameterDefinition({
48
60
  slug: "base-id",
@@ -126,6 +138,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
126
138
  tools;
127
139
  query;
128
140
  checkConnection;
141
+ /**
142
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
143
+ * implement this expose a step-by-step exploration flow (database/schema/
144
+ * table/etc. discovery) that the dashboard backend drives via the
145
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
146
+ * `runSetupFlow` from `setup-flow.ts`.
147
+ */
148
+ setup;
149
+ /**
150
+ * Opt-out of the default "verify before save" behavior on connection
151
+ * creation. The backend invokes `checkConnection` synchronously while
152
+ * creating the connection and aborts (no row inserted) if it fails — this
153
+ * flag disables that for connectors where the check cannot succeed pre-save:
154
+ *
155
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
156
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
157
+ * connectionId, which doesn't exist until the row is saved
158
+ *
159
+ * Exceptions are the explicit position; new credential-input connectors get
160
+ * the default verify-on-create behavior without opt-in.
161
+ */
162
+ skipConnectionCheckOnCreate;
129
163
  constructor(config) {
130
164
  this.slug = config.slug;
131
165
  this.authType = config.authType;
@@ -142,6 +176,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
142
176
  this.tools = config.tools;
143
177
  this.query = config.query;
144
178
  this.checkConnection = config.checkConnection;
179
+ this.setup = config.setup;
180
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
145
181
  }
146
182
  get connectorKey() {
147
183
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -206,6 +242,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
206
242
  }
207
243
  };
208
244
 
245
+ // ../connectors/src/setup-flow.ts
246
+ async function runSetupFlow(flow, params, ctx, config) {
247
+ const runtime = {
248
+ params,
249
+ language: ctx.language,
250
+ config
251
+ };
252
+ let state = flow.initialState();
253
+ let answerIdx = 0;
254
+ const pendingParameterUpdates = [];
255
+ for (const step of flow.steps) {
256
+ const ans = ctx.answers[answerIdx];
257
+ if (ans && ans.questionSlug === step.slug) {
258
+ state = step.applyAnswer(state, ans.answer);
259
+ if (step.toParameterUpdates) {
260
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
261
+ }
262
+ answerIdx += 1;
263
+ continue;
264
+ }
265
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
266
+ if (step.type === "text") {
267
+ if (step.fetchOptions) {
268
+ const options2 = await step.fetchOptions(state, runtime);
269
+ if (options2.length === 0) {
270
+ continue;
271
+ }
272
+ }
273
+ return {
274
+ type: "nextQuestion",
275
+ questionSlug: step.slug,
276
+ question: step.question[ctx.language],
277
+ questionType: "text",
278
+ allowFreeText: resolvedAllowFreeText,
279
+ ...pendingParameterUpdates.length > 0 && {
280
+ parameterUpdates: pendingParameterUpdates
281
+ }
282
+ };
283
+ }
284
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
285
+ if (options.length === 0) {
286
+ continue;
287
+ }
288
+ return {
289
+ type: "nextQuestion",
290
+ questionSlug: step.slug,
291
+ question: step.question[ctx.language],
292
+ questionType: step.type,
293
+ options,
294
+ allowFreeText: resolvedAllowFreeText,
295
+ ...pendingParameterUpdates.length > 0 && {
296
+ parameterUpdates: pendingParameterUpdates
297
+ }
298
+ };
299
+ }
300
+ const dataInvestigationResult = await flow.finalize(state, runtime);
301
+ return {
302
+ type: "fulfilled",
303
+ dataInvestigationResult,
304
+ ...pendingParameterUpdates.length > 0 && {
305
+ parameterUpdates: pendingParameterUpdates
306
+ }
307
+ };
308
+ }
309
+ async function resolveSetupSelection(params) {
310
+ const { selected, allSentinel, fetchAll, limit } = params;
311
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
312
+ return resolved.slice(0, limit);
313
+ }
314
+
209
315
  // ../connectors/src/auth-types.ts
210
316
  var AUTH_TYPES = {
211
317
  OAUTH: "oauth",
@@ -377,11 +483,120 @@ var airtableOauthOnboarding = new ConnectorOnboarding({
377
483
  }
378
484
  });
379
485
 
486
+ // ../connectors/src/connectors/airtable-oauth/utils.ts
487
+ var BASE_URL3 = "https://api.airtable.com/v0";
488
+ function apiFetch(proxyFetch, path2, init) {
489
+ const url = `${BASE_URL3}${path2.startsWith("/") ? "" : "/"}${path2}`;
490
+ return proxyFetch(url, init);
491
+ }
492
+
493
+ // ../connectors/src/connectors/airtable-oauth/setup-flow.ts
494
+ var ALL_TABLES = "__ALL_TABLES__";
495
+ var AIRTABLE_SETUP_MAX_TABLES = 20;
496
+ async function listBases(proxyFetch) {
497
+ const res = await apiFetch(proxyFetch, "/meta/bases");
498
+ if (!res.ok) {
499
+ const body = await res.text().catch(() => res.statusText);
500
+ throw new Error(
501
+ `airtable-oauth: listBases failed (${res.status}): ${body}`
502
+ );
503
+ }
504
+ const data = await res.json();
505
+ return data.bases ?? [];
506
+ }
507
+ async function listTables(proxyFetch, baseId) {
508
+ const res = await apiFetch(proxyFetch, `/meta/bases/${baseId}/tables`);
509
+ if (!res.ok) {
510
+ const body = await res.text().catch(() => res.statusText);
511
+ throw new Error(
512
+ `airtable-oauth: listTables failed (${res.status}): ${body}`
513
+ );
514
+ }
515
+ const data = await res.json();
516
+ return data.tables ?? [];
517
+ }
518
+ var airtableOauthSetupFlow = {
519
+ initialState: () => ({}),
520
+ steps: [
521
+ {
522
+ slug: "base",
523
+ type: "select",
524
+ question: {
525
+ ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
526
+ en: "Select the base to use for setup"
527
+ },
528
+ async fetchOptions(_state, rt) {
529
+ const bases = await listBases(rt.config.proxyFetch);
530
+ return bases.filter((b) => b.id && b.name).map((b) => ({ value: b.id, label: b.name }));
531
+ },
532
+ applyAnswer: (state, answer) => ({ ...state, base: answer[0] })
533
+ },
534
+ {
535
+ slug: "tables",
536
+ type: "multiSelect",
537
+ question: {
538
+ ja: "\u5BFE\u8C61\u30C6\u30FC\u30D6\u30EB\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
539
+ en: "Select target tables (multi-select allowed)"
540
+ },
541
+ async fetchOptions(state, rt) {
542
+ if (!state.base) return [];
543
+ const tables = await listTables(rt.config.proxyFetch, state.base);
544
+ const tableOptions = tables.filter((t) => t.name).map((t) => ({ value: t.name }));
545
+ return [
546
+ {
547
+ value: ALL_TABLES,
548
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C6\u30FC\u30D6\u30EB" : "All tables"
549
+ },
550
+ ...tableOptions
551
+ ];
552
+ },
553
+ applyAnswer: (state, answer) => ({ ...state, tables: answer })
554
+ }
555
+ ],
556
+ async finalize(state, rt) {
557
+ if (!state.base || !state.tables) {
558
+ throw new Error("Airtable setup: incomplete state on finalize");
559
+ }
560
+ const baseId = state.base;
561
+ const tables = await listTables(rt.config.proxyFetch, baseId);
562
+ const tableByName = new Map(tables.map((t) => [t.name, t]));
563
+ const targetTableNames = await resolveSetupSelection({
564
+ selected: state.tables,
565
+ allSentinel: ALL_TABLES,
566
+ fetchAll: async () => tables.map((t) => t.name).filter((n) => n),
567
+ limit: AIRTABLE_SETUP_MAX_TABLES
568
+ });
569
+ const sections = [
570
+ "## Airtable",
571
+ "",
572
+ `### Base: ${baseId}`,
573
+ ""
574
+ ];
575
+ for (const tableName of targetTableNames) {
576
+ const table = tableByName.get(tableName);
577
+ if (!table) {
578
+ sections.push(`#### Table: ${tableName}`, "", "_Not found._", "");
579
+ continue;
580
+ }
581
+ sections.push(`#### Table: ${table.name}`, "");
582
+ sections.push("| Field | Type | Description |");
583
+ sections.push("|-------|------|-------------|");
584
+ for (const f of table.fields ?? []) {
585
+ const description = (f.description ?? "").replace(/\|/g, "\\|");
586
+ sections.push(`| ${f.name} | ${f.type} | ${description || "-"} |`);
587
+ }
588
+ sections.push("");
589
+ }
590
+ return sections.join("\n");
591
+ }
592
+ };
593
+
380
594
  // ../connectors/src/connectors/airtable-oauth/index.ts
381
595
  var tools = { request: requestTool };
382
596
  var airtableOauthConnector = new ConnectorPlugin({
383
597
  slug: "airtable",
384
598
  authType: AUTH_TYPES.OAUTH,
599
+ skipConnectionCheckOnCreate: true,
385
600
  name: "Airtable",
386
601
  description: "Connect to Airtable for spreadsheet-database hybrid data management using OAuth.",
387
602
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/19JUphfOZjyjTK6Zg4NGCf/8c56227b088cada52d3a2d9385a3be97/airtable.svg",
@@ -496,6 +711,7 @@ const recordsData = await records.json();
496
711
  \`\`\``
497
712
  },
498
713
  tools,
714
+ setup: (params, ctx, config) => runSetupFlow(airtableOauthSetupFlow, params, ctx, config),
499
715
  async checkConnection(params, config) {
500
716
  const { proxyFetch } = config;
501
717
  const baseId = params[parameters.baseId.slug];
@@ -550,6 +766,7 @@ function resolveEnvVarOptional(entry, key) {
550
766
  import { getContext } from "hono/context-storage";
551
767
  import { getCookie } from "hono/cookie";
552
768
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
769
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
553
770
  function normalizeHeaders(input) {
554
771
  const out = {};
555
772
  if (!input) return out;
@@ -558,6 +775,11 @@ function normalizeHeaders(input) {
558
775
  });
559
776
  return out;
560
777
  }
778
+ function extractInputUrl(input) {
779
+ if (typeof input === "string") return input;
780
+ if (input instanceof URL) return input.href;
781
+ return input.url;
782
+ }
561
783
  function createSandboxProxyFetch(connectionId) {
562
784
  return async (input, init) => {
563
785
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -567,10 +789,17 @@ function createSandboxProxyFetch(connectionId) {
567
789
  "Connection proxy is not configured. Please check your deployment settings."
568
790
  );
569
791
  }
570
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
792
+ const originalUrl = extractInputUrl(input);
793
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
794
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
795
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
796
+ return fetch(sessionUrl, {
797
+ method: "POST",
798
+ headers: { Authorization: `Bearer ${token}` }
799
+ });
800
+ }
571
801
  const originalMethod = init?.method ?? "GET";
572
802
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
573
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
574
803
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
575
804
  return fetch(proxyUrl, {
576
805
  method: "POST",
@@ -596,10 +825,9 @@ function createDeployedAppProxyFetch(connectionId) {
596
825
  }
597
826
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
598
827
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
828
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
599
829
  return async (input, init) => {
600
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
601
- const originalMethod = init?.method ?? "GET";
602
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
830
+ const originalUrl = extractInputUrl(input);
603
831
  const c = getContext();
604
832
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
605
833
  if (!appSession) {
@@ -607,6 +835,14 @@ function createDeployedAppProxyFetch(connectionId) {
607
835
  "No authentication method available for connection proxy."
608
836
  );
609
837
  }
838
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
839
+ return fetch(sessionUrl, {
840
+ method: "POST",
841
+ headers: { Authorization: `Bearer ${appSession}` }
842
+ });
843
+ }
844
+ const originalMethod = init?.method ?? "GET";
845
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
610
846
  return fetch(proxyUrl, {
611
847
  method: "POST",
612
848
  headers: {