@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,46 +1,57 @@
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/google-ads/constants.ts
46
57
  var VERSION_FALLBACK_ORDER = ["v22", "v23", "v24"];
@@ -76,6 +87,7 @@ async function fetchGoogleAdsWithVersionFallback(attempt) {
76
87
  }
77
88
 
78
89
  // ../connectors/src/connectors/google-ads/parameters.ts
90
+ init_parameter_definition();
79
91
  var parameters = {
80
92
  customerId: new ParameterDefinition({
81
93
  slug: "customer-id",
@@ -213,6 +225,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
213
225
  tools;
214
226
  query;
215
227
  checkConnection;
228
+ /**
229
+ * SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
230
+ * implement this expose a step-by-step exploration flow (database/schema/
231
+ * table/etc. discovery) that the dashboard backend drives via the
232
+ * `/connections/:connectionId/setup` endpoint. Implement by delegating to
233
+ * `runSetupFlow` from `setup-flow.ts`.
234
+ */
235
+ setup;
236
+ /**
237
+ * Opt-out of the default "verify before save" behavior on connection
238
+ * creation. The backend invokes `checkConnection` synchronously while
239
+ * creating the connection and aborts (no row inserted) if it fails — this
240
+ * flag disables that for connectors where the check cannot succeed pre-save:
241
+ *
242
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
243
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
244
+ * connectionId, which doesn't exist until the row is saved
245
+ *
246
+ * Exceptions are the explicit position; new credential-input connectors get
247
+ * the default verify-on-create behavior without opt-in.
248
+ */
249
+ skipConnectionCheckOnCreate;
216
250
  constructor(config) {
217
251
  this.slug = config.slug;
218
252
  this.authType = config.authType;
@@ -229,6 +263,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
229
263
  this.tools = config.tools;
230
264
  this.query = config.query;
231
265
  this.checkConnection = config.checkConnection;
266
+ this.setup = config.setup;
267
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
232
268
  }
233
269
  get connectorKey() {
234
270
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -293,6 +329,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
293
329
  }
294
330
  };
295
331
 
332
+ // ../connectors/src/setup-flow.ts
333
+ async function runSetupFlow(flow, params, ctx, config) {
334
+ const runtime = {
335
+ params,
336
+ language: ctx.language,
337
+ config
338
+ };
339
+ let state = flow.initialState();
340
+ let answerIdx = 0;
341
+ for (const step of flow.steps) {
342
+ const ans = ctx.answers[answerIdx];
343
+ if (ans && ans.questionSlug === step.slug) {
344
+ state = step.applyAnswer(state, ans.answer);
345
+ answerIdx += 1;
346
+ continue;
347
+ }
348
+ if (step.type === "text") {
349
+ return {
350
+ type: "nextQuestion",
351
+ questionSlug: step.slug,
352
+ question: step.question[ctx.language],
353
+ questionType: "text"
354
+ };
355
+ }
356
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
357
+ if (options.length === 0) {
358
+ continue;
359
+ }
360
+ return {
361
+ type: "nextQuestion",
362
+ questionSlug: step.slug,
363
+ question: step.question[ctx.language],
364
+ questionType: step.type,
365
+ options
366
+ };
367
+ }
368
+ const dataInvestigationResult = await flow.finalize(state, runtime);
369
+ return { type: "fulfilled", dataInvestigationResult };
370
+ }
371
+ async function resolveSetupSelection(params) {
372
+ const { selected, allSentinel, fetchAll, limit } = params;
373
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
374
+ return resolved.slice(0, limit);
375
+ }
376
+
296
377
  // ../connectors/src/auth-types.ts
297
378
  var AUTH_TYPES = {
298
379
  OAUTH: "oauth",
@@ -561,6 +642,120 @@ var googleAdsOnboarding = new ConnectorOnboarding({
561
642
  }
562
643
  });
563
644
 
645
+ // ../connectors/src/connectors/google-ads/setup-flow.ts
646
+ var ALL_CUSTOMERS = "__ALL_CUSTOMERS__";
647
+ var GOOGLE_ADS_SETUP_MAX_CUSTOMERS = 10;
648
+ async function listAccessibleCustomerIds(proxyFetch) {
649
+ const res = await fetchGoogleAdsWithVersionFallback(
650
+ (baseUrl) => proxyFetch(`${baseUrl}customers:listAccessibleCustomers`, {
651
+ method: "GET"
652
+ })
653
+ );
654
+ if (!res.ok) {
655
+ const body = await res.text().catch(() => res.statusText);
656
+ throw new Error(
657
+ `google-ads: listAccessibleCustomers failed (${res.status}): ${body}`
658
+ );
659
+ }
660
+ const data = await res.json();
661
+ return (data.resourceNames ?? []).map(
662
+ (rn) => rn.replace(/^customers\//, "")
663
+ );
664
+ }
665
+ async function fetchCustomerInfo(proxyFetch, customerId) {
666
+ try {
667
+ const res = await fetchGoogleAdsWithVersionFallback(
668
+ (baseUrl) => proxyFetch(`${baseUrl}customers/${customerId}/googleAds:searchStream`, {
669
+ method: "POST",
670
+ headers: {
671
+ "Content-Type": "application/json",
672
+ "login-customer-id": customerId
673
+ },
674
+ body: JSON.stringify({
675
+ query: "SELECT customer.id, customer.descriptive_name, customer.currency_code, customer.time_zone FROM customer LIMIT 1"
676
+ })
677
+ })
678
+ );
679
+ if (!res.ok) {
680
+ return {
681
+ customerId,
682
+ descriptiveName: customerId,
683
+ currencyCode: "-",
684
+ timeZone: "-"
685
+ };
686
+ }
687
+ const data = await res.json();
688
+ const customer = data?.[0]?.results?.[0]?.customer;
689
+ return {
690
+ customerId,
691
+ descriptiveName: customer?.descriptiveName ?? customerId,
692
+ currencyCode: customer?.currencyCode ?? "-",
693
+ timeZone: customer?.timeZone ?? "-"
694
+ };
695
+ } catch {
696
+ return {
697
+ customerId,
698
+ descriptiveName: customerId,
699
+ currencyCode: "-",
700
+ timeZone: "-"
701
+ };
702
+ }
703
+ }
704
+ var googleAdsSetupFlow = {
705
+ initialState: () => ({}),
706
+ steps: [
707
+ {
708
+ slug: "customers",
709
+ type: "multiSelect",
710
+ question: {
711
+ ja: "\u5BFE\u8C61\u306E Google Ads \u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
712
+ en: "Select target Google Ads accounts (multi-select allowed)"
713
+ },
714
+ async fetchOptions(_state, rt) {
715
+ const customerIds = await listAccessibleCustomerIds(
716
+ rt.config.proxyFetch
717
+ );
718
+ if (customerIds.length === 0) return [];
719
+ return [
720
+ {
721
+ value: ALL_CUSTOMERS,
722
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30A2\u30AB\u30A6\u30F3\u30C8" : "All accounts"
723
+ },
724
+ ...customerIds.map((id) => ({ value: id }))
725
+ ];
726
+ },
727
+ applyAnswer: (state, answer) => ({ ...state, customers: answer })
728
+ }
729
+ ],
730
+ async finalize(state, rt) {
731
+ if (!state.customers) {
732
+ throw new Error("Google Ads setup: incomplete state on finalize");
733
+ }
734
+ const targetCustomerIds = await resolveSetupSelection({
735
+ selected: state.customers,
736
+ allSentinel: ALL_CUSTOMERS,
737
+ fetchAll: async () => listAccessibleCustomerIds(rt.config.proxyFetch),
738
+ limit: GOOGLE_ADS_SETUP_MAX_CUSTOMERS
739
+ });
740
+ const sections = ["## Google Ads", ""];
741
+ if (targetCustomerIds.length === 0) {
742
+ sections.push("_No customer accounts selected._", "");
743
+ return sections.join("\n");
744
+ }
745
+ sections.push("| Customer ID | Name | Currency | Time Zone |");
746
+ sections.push("|-------------|------|----------|-----------|");
747
+ for (const customerId of targetCustomerIds) {
748
+ const info = await fetchCustomerInfo(rt.config.proxyFetch, customerId);
749
+ const name = info.descriptiveName.replace(/\|/g, "\\|");
750
+ sections.push(
751
+ `| ${info.customerId} | ${name} | ${info.currencyCode} | ${info.timeZone} |`
752
+ );
753
+ }
754
+ sections.push("");
755
+ return sections.join("\n");
756
+ }
757
+ };
758
+
564
759
  // ../connectors/src/connectors/google-ads/tools/request.ts
565
760
  import { z as z2 } from "zod";
566
761
  var REQUEST_TIMEOUT_MS2 = 6e4;
@@ -695,6 +890,7 @@ var tools = {
695
890
  var googleAdsConnector = new ConnectorPlugin({
696
891
  slug: "google-ads",
697
892
  authType: AUTH_TYPES.OAUTH,
893
+ skipConnectionCheckOnCreate: true,
698
894
  name: "Google Ads",
699
895
  description: "Connect to Google Ads for advertising campaign data and reporting using OAuth.",
700
896
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/1NGvmgvCxX7Tn11EST2N3N/a745fe7c63d360ed40a27ddaad3af168/google-ads.svg",
@@ -837,6 +1033,7 @@ const customerIds = await ads.listAccessibleCustomers();
837
1033
  \`\`\``
838
1034
  },
839
1035
  tools,
1036
+ setup: (params, ctx, config) => runSetupFlow(googleAdsSetupFlow, params, ctx, config),
840
1037
  async checkConnection(params, config) {
841
1038
  const { proxyFetch } = config;
842
1039
  const rawCustomerId = params[parameters.customerId.slug];
@@ -903,6 +1100,7 @@ function resolveEnvVarOptional(entry, key) {
903
1100
  import { getContext } from "hono/context-storage";
904
1101
  import { getCookie } from "hono/cookie";
905
1102
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
1103
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
906
1104
  function normalizeHeaders(input) {
907
1105
  const out = {};
908
1106
  if (!input) return out;
@@ -911,6 +1109,11 @@ function normalizeHeaders(input) {
911
1109
  });
912
1110
  return out;
913
1111
  }
1112
+ function extractInputUrl(input) {
1113
+ if (typeof input === "string") return input;
1114
+ if (input instanceof URL) return input.href;
1115
+ return input.url;
1116
+ }
914
1117
  function createSandboxProxyFetch(connectionId) {
915
1118
  return async (input, init) => {
916
1119
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -920,10 +1123,17 @@ function createSandboxProxyFetch(connectionId) {
920
1123
  "Connection proxy is not configured. Please check your deployment settings."
921
1124
  );
922
1125
  }
923
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1126
+ const originalUrl = extractInputUrl(input);
1127
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
1128
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1129
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
1130
+ return fetch(sessionUrl, {
1131
+ method: "POST",
1132
+ headers: { Authorization: `Bearer ${token}` }
1133
+ });
1134
+ }
924
1135
  const originalMethod = init?.method ?? "GET";
925
1136
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
926
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
927
1137
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
928
1138
  return fetch(proxyUrl, {
929
1139
  method: "POST",
@@ -949,10 +1159,9 @@ function createDeployedAppProxyFetch(connectionId) {
949
1159
  }
950
1160
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
951
1161
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
1162
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
952
1163
  return async (input, init) => {
953
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
954
- const originalMethod = init?.method ?? "GET";
955
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
1164
+ const originalUrl = extractInputUrl(input);
956
1165
  const c = getContext();
957
1166
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
958
1167
  if (!appSession) {
@@ -960,6 +1169,14 @@ function createDeployedAppProxyFetch(connectionId) {
960
1169
  "No authentication method available for connection proxy."
961
1170
  );
962
1171
  }
1172
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
1173
+ return fetch(sessionUrl, {
1174
+ method: "POST",
1175
+ headers: { Authorization: `Bearer ${appSession}` }
1176
+ });
1177
+ }
1178
+ const originalMethod = init?.method ?? "GET";
1179
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
963
1180
  return fetch(proxyUrl, {
964
1181
  method: "POST",
965
1182
  headers: {