@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.
- package/dist/cli/index.js +14375 -1652
- package/dist/connectors/airtable-oauth.js +282 -46
- package/dist/connectors/airtable.js +319 -51
- package/dist/connectors/amplitude.js +322 -47
- package/dist/connectors/anthropic.js +135 -47
- package/dist/connectors/asana.js +327 -49
- package/dist/connectors/attio.js +302 -49
- package/dist/connectors/aws-billing.js +287 -46
- package/dist/connectors/azure-sql.js +421 -102
- package/dist/connectors/backlog-api-key.js +317 -47
- package/dist/connectors/clickup.js +338 -49
- package/dist/connectors/cosmosdb.js +305 -50
- package/dist/connectors/customerio.js +319 -47
- package/dist/connectors/dbt.js +340 -47
- package/dist/connectors/freshdesk.js +342 -53
- package/dist/connectors/freshsales.js +333 -52
- package/dist/connectors/freshservice.js +361 -53
- package/dist/connectors/gamma.js +327 -52
- package/dist/connectors/gemini.js +134 -47
- package/dist/connectors/github.js +386 -49
- package/dist/connectors/gmail-oauth.js +204 -7
- package/dist/connectors/gmail.js +350 -47
- package/dist/connectors/google-ads.js +288 -46
- package/dist/connectors/google-analytics-oauth.js +310 -46
- package/dist/connectors/google-analytics.js +547 -87
- package/dist/connectors/google-audit-log.js +438 -47
- package/dist/connectors/google-calendar-oauth.js +259 -46
- package/dist/connectors/google-calendar.js +359 -47
- package/dist/connectors/google-docs.js +220 -6
- package/dist/connectors/google-drive.js +262 -5
- package/dist/connectors/google-search-console-oauth.js +256 -46
- package/dist/connectors/google-sheets.js +272 -47
- package/dist/connectors/google-slides.js +205 -6
- package/dist/connectors/grafana.js +332 -49
- package/dist/connectors/hubspot-oauth.js +208 -5
- package/dist/connectors/hubspot.js +306 -49
- package/dist/connectors/influxdb.js +416 -51
- package/dist/connectors/intercom-oauth.js +210 -5
- package/dist/connectors/intercom.js +302 -49
- package/dist/connectors/jdbc.js +762 -110
- package/dist/connectors/jira-api-key.js +326 -47
- package/dist/connectors/kintone-api-token.js +281 -47
- package/dist/connectors/kintone.js +328 -47
- package/dist/connectors/linear.js +330 -49
- package/dist/connectors/linkedin-ads.js +268 -50
- package/dist/connectors/mailchimp-oauth.js +268 -46
- package/dist/connectors/mailchimp.js +320 -49
- package/dist/connectors/meta-ads-oauth.js +273 -48
- package/dist/connectors/meta-ads.js +285 -50
- package/dist/connectors/mixpanel.js +338 -47
- package/dist/connectors/monday.js +360 -49
- package/dist/connectors/mongodb.js +319 -57
- package/dist/connectors/notion-oauth.js +231 -5
- package/dist/connectors/notion.js +323 -51
- package/dist/connectors/openai.js +134 -47
- package/dist/connectors/oracle.js +454 -103
- package/dist/connectors/outlook-oauth.js +204 -5
- package/dist/connectors/powerbi-oauth.js +498 -5
- package/dist/connectors/salesforce.js +384 -49
- package/dist/connectors/semrush.js +609 -49
- package/dist/connectors/sentry.js +289 -50
- package/dist/connectors/shopify-oauth.js +187 -5
- package/dist/connectors/shopify.js +357 -47
- package/dist/connectors/sqlserver.js +415 -102
- package/dist/connectors/stripe-api-key.js +269 -46
- package/dist/connectors/stripe-oauth.js +202 -5
- package/dist/connectors/supabase.js +303 -48
- package/dist/connectors/tableau.js +536 -163
- package/dist/connectors/tiktok-ads.js +279 -48
- package/dist/connectors/wix-store.js +320 -49
- package/dist/connectors/zendesk-oauth.js +239 -5
- package/dist/connectors/zendesk.js +358 -47
- package/dist/index.d.ts +149 -1
- package/dist/index.js +15057 -2117
- package/dist/main.js +15005 -2073
- package/dist/vite-plugin.js +14752 -2019
- package/package.json +1 -1
|
@@ -15,7 +15,7 @@ function createClient(_params, fetchFn = fetch) {
|
|
|
15
15
|
}
|
|
16
16
|
return await response.json();
|
|
17
17
|
}
|
|
18
|
-
async function
|
|
18
|
+
async function listLabels2() {
|
|
19
19
|
const response = await request("/me/labels");
|
|
20
20
|
if (!response.ok) {
|
|
21
21
|
const body = await response.text();
|
|
@@ -98,7 +98,7 @@ function createClient(_params, fetchFn = fetch) {
|
|
|
98
98
|
return {
|
|
99
99
|
request,
|
|
100
100
|
getProfile,
|
|
101
|
-
listLabels,
|
|
101
|
+
listLabels: listLabels2,
|
|
102
102
|
listMessages,
|
|
103
103
|
getMessage,
|
|
104
104
|
listThreads,
|
|
@@ -165,6 +165,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
165
165
|
tools;
|
|
166
166
|
query;
|
|
167
167
|
checkConnection;
|
|
168
|
+
/**
|
|
169
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
170
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
171
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
172
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
173
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
174
|
+
*/
|
|
175
|
+
setup;
|
|
176
|
+
/**
|
|
177
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
178
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
179
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
180
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
181
|
+
*
|
|
182
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
183
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
184
|
+
* connectionId, which doesn't exist until the row is saved
|
|
185
|
+
*
|
|
186
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
187
|
+
* the default verify-on-create behavior without opt-in.
|
|
188
|
+
*/
|
|
189
|
+
skipConnectionCheckOnCreate;
|
|
168
190
|
constructor(config) {
|
|
169
191
|
this.slug = config.slug;
|
|
170
192
|
this.authType = config.authType;
|
|
@@ -181,6 +203,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
181
203
|
this.tools = config.tools;
|
|
182
204
|
this.query = config.query;
|
|
183
205
|
this.checkConnection = config.checkConnection;
|
|
206
|
+
this.setup = config.setup;
|
|
207
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
184
208
|
}
|
|
185
209
|
get connectorKey() {
|
|
186
210
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -245,6 +269,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
245
269
|
}
|
|
246
270
|
};
|
|
247
271
|
|
|
272
|
+
// ../connectors/src/setup-flow.ts
|
|
273
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
274
|
+
const runtime = {
|
|
275
|
+
params,
|
|
276
|
+
language: ctx.language,
|
|
277
|
+
config
|
|
278
|
+
};
|
|
279
|
+
let state = flow.initialState();
|
|
280
|
+
let answerIdx = 0;
|
|
281
|
+
const pendingParameterUpdates = [];
|
|
282
|
+
for (const step of flow.steps) {
|
|
283
|
+
const ans = ctx.answers[answerIdx];
|
|
284
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
285
|
+
state = step.applyAnswer(state, ans.answer);
|
|
286
|
+
if (step.toParameterUpdates) {
|
|
287
|
+
pendingParameterUpdates.push(...step.toParameterUpdates(state));
|
|
288
|
+
}
|
|
289
|
+
answerIdx += 1;
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
|
|
293
|
+
if (step.type === "text") {
|
|
294
|
+
if (step.fetchOptions) {
|
|
295
|
+
const options2 = await step.fetchOptions(state, runtime);
|
|
296
|
+
if (options2.length === 0) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
type: "nextQuestion",
|
|
302
|
+
questionSlug: step.slug,
|
|
303
|
+
question: step.question[ctx.language],
|
|
304
|
+
questionType: "text",
|
|
305
|
+
allowFreeText: resolvedAllowFreeText,
|
|
306
|
+
...pendingParameterUpdates.length > 0 && {
|
|
307
|
+
parameterUpdates: pendingParameterUpdates
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
312
|
+
if (options.length === 0) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
type: "nextQuestion",
|
|
317
|
+
questionSlug: step.slug,
|
|
318
|
+
question: step.question[ctx.language],
|
|
319
|
+
questionType: step.type,
|
|
320
|
+
options,
|
|
321
|
+
allowFreeText: resolvedAllowFreeText,
|
|
322
|
+
...pendingParameterUpdates.length > 0 && {
|
|
323
|
+
parameterUpdates: pendingParameterUpdates
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
328
|
+
return {
|
|
329
|
+
type: "fulfilled",
|
|
330
|
+
dataInvestigationResult,
|
|
331
|
+
...pendingParameterUpdates.length > 0 && {
|
|
332
|
+
parameterUpdates: pendingParameterUpdates
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
async function resolveSetupSelection(params) {
|
|
337
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
338
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
339
|
+
return resolved.slice(0, limit);
|
|
340
|
+
}
|
|
341
|
+
|
|
248
342
|
// ../connectors/src/auth-types.ts
|
|
249
343
|
var AUTH_TYPES = {
|
|
250
344
|
OAUTH: "oauth",
|
|
@@ -425,6 +519,87 @@ var gmailOnboarding = new ConnectorOnboarding({
|
|
|
425
519
|
}
|
|
426
520
|
});
|
|
427
521
|
|
|
522
|
+
// ../connectors/src/connectors/gmail-oauth/utils.ts
|
|
523
|
+
async function gmailApiFetch(config, url) {
|
|
524
|
+
const res = await config.proxyFetch(url, { method: "GET" });
|
|
525
|
+
if (!res.ok) {
|
|
526
|
+
const text = await res.text().catch(() => res.statusText);
|
|
527
|
+
throw new Error(`Gmail API ${url} failed: HTTP ${res.status} ${text}`);
|
|
528
|
+
}
|
|
529
|
+
return await res.json();
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// ../connectors/src/connectors/gmail-oauth/setup-flow.ts
|
|
533
|
+
var ALL_LABELS = "__ALL_LABELS__";
|
|
534
|
+
var GMAIL_SETUP_MAX_LABELS = 20;
|
|
535
|
+
async function listLabels(config) {
|
|
536
|
+
const url = "https://gmail.googleapis.com/gmail/v1/users/me/labels";
|
|
537
|
+
const data = await gmailApiFetch(config, url);
|
|
538
|
+
return data.labels ?? [];
|
|
539
|
+
}
|
|
540
|
+
var gmailOauthSetupFlow = {
|
|
541
|
+
initialState: () => ({}),
|
|
542
|
+
steps: [
|
|
543
|
+
{
|
|
544
|
+
slug: "labels",
|
|
545
|
+
type: "multiSelect",
|
|
546
|
+
question: {
|
|
547
|
+
ja: "\u5BFE\u8C61\u306E\u30E9\u30D9\u30EB\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
548
|
+
en: "Select target labels (multi-select allowed)"
|
|
549
|
+
},
|
|
550
|
+
async fetchOptions(_state, rt) {
|
|
551
|
+
const labels = await listLabels(rt.config);
|
|
552
|
+
return [
|
|
553
|
+
{
|
|
554
|
+
value: ALL_LABELS,
|
|
555
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30E9\u30D9\u30EB" : "All labels"
|
|
556
|
+
},
|
|
557
|
+
...labels.map((l) => ({ value: l.id, label: l.name }))
|
|
558
|
+
];
|
|
559
|
+
},
|
|
560
|
+
applyAnswer: (state, answer) => ({ ...state, labels: answer })
|
|
561
|
+
}
|
|
562
|
+
],
|
|
563
|
+
async finalize(state, rt) {
|
|
564
|
+
if (!state.labels) {
|
|
565
|
+
throw new Error("Gmail setup: incomplete state on finalize");
|
|
566
|
+
}
|
|
567
|
+
const labels = await listLabels(rt.config);
|
|
568
|
+
const labelsById = new Map(labels.map((l) => [l.id, l]));
|
|
569
|
+
const targetIds = await resolveSetupSelection({
|
|
570
|
+
selected: state.labels,
|
|
571
|
+
allSentinel: ALL_LABELS,
|
|
572
|
+
fetchAll: async () => labels.map((l) => l.id),
|
|
573
|
+
limit: GMAIL_SETUP_MAX_LABELS
|
|
574
|
+
});
|
|
575
|
+
const sections = ["## Gmail", ""];
|
|
576
|
+
if (targetIds.length === 0) {
|
|
577
|
+
sections.push(
|
|
578
|
+
rt.language === "ja" ? "\u5BFE\u8C61\u306E\u30E9\u30D9\u30EB\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002" : "No labels selected."
|
|
579
|
+
);
|
|
580
|
+
return sections.join("\n");
|
|
581
|
+
}
|
|
582
|
+
sections.push("| Label | Visibility | Messages | Unread |");
|
|
583
|
+
sections.push("|-------|-----------|----------|--------|");
|
|
584
|
+
for (const id of targetIds) {
|
|
585
|
+
const url = `https://gmail.googleapis.com/gmail/v1/users/me/labels/${encodeURIComponent(
|
|
586
|
+
id
|
|
587
|
+
)}`;
|
|
588
|
+
const detail = await gmailApiFetch(
|
|
589
|
+
rt.config,
|
|
590
|
+
url
|
|
591
|
+
);
|
|
592
|
+
const name = detail.name ?? labelsById.get(id)?.name ?? id;
|
|
593
|
+
const vis = detail.labelListVisibility ?? "-";
|
|
594
|
+
const total = detail.messagesTotal ?? "-";
|
|
595
|
+
const unread = detail.messagesUnread ?? "-";
|
|
596
|
+
sections.push(`| ${name} | ${vis} | ${total} | ${unread} |`);
|
|
597
|
+
}
|
|
598
|
+
sections.push("");
|
|
599
|
+
return sections.join("\n");
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
|
|
428
603
|
// ../connectors/src/connectors/gmail-oauth/parameters.ts
|
|
429
604
|
var parameters = {};
|
|
430
605
|
|
|
@@ -433,6 +608,7 @@ var tools = { request: requestTool };
|
|
|
433
608
|
var gmailOauthConnector = new ConnectorPlugin({
|
|
434
609
|
slug: "gmail",
|
|
435
610
|
authType: AUTH_TYPES.OAUTH,
|
|
611
|
+
skipConnectionCheckOnCreate: true,
|
|
436
612
|
name: "Gmail",
|
|
437
613
|
description: "Connect to Gmail for email data access using OAuth. Read-only access to messages, threads, and labels.",
|
|
438
614
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4V3rfaSc1ksFIt2eHBNIwJ/7f3be41a154a6d96dcf229ed0e5858c9/Gmail_icon__2020_.svg.png",
|
|
@@ -617,6 +793,7 @@ thread.messages.forEach(m => console.log(m.snippet));
|
|
|
617
793
|
\`\`\``
|
|
618
794
|
},
|
|
619
795
|
tools,
|
|
796
|
+
setup: (params, ctx, config) => runSetupFlow(gmailOauthSetupFlow, params, ctx, config),
|
|
620
797
|
async checkConnection(_params, config) {
|
|
621
798
|
const { proxyFetch } = config;
|
|
622
799
|
const url = "https://gmail.googleapis.com/gmail/v1/users/me/profile";
|
|
@@ -665,6 +842,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
665
842
|
import { getContext } from "hono/context-storage";
|
|
666
843
|
import { getCookie } from "hono/cookie";
|
|
667
844
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
845
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
668
846
|
function normalizeHeaders(input) {
|
|
669
847
|
const out = {};
|
|
670
848
|
if (!input) return out;
|
|
@@ -673,6 +851,11 @@ function normalizeHeaders(input) {
|
|
|
673
851
|
});
|
|
674
852
|
return out;
|
|
675
853
|
}
|
|
854
|
+
function extractInputUrl(input) {
|
|
855
|
+
if (typeof input === "string") return input;
|
|
856
|
+
if (input instanceof URL) return input.href;
|
|
857
|
+
return input.url;
|
|
858
|
+
}
|
|
676
859
|
function createSandboxProxyFetch(connectionId) {
|
|
677
860
|
return async (input, init) => {
|
|
678
861
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -682,10 +865,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
682
865
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
683
866
|
);
|
|
684
867
|
}
|
|
685
|
-
const originalUrl =
|
|
868
|
+
const originalUrl = extractInputUrl(input);
|
|
869
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
870
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
871
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
872
|
+
return fetch(sessionUrl, {
|
|
873
|
+
method: "POST",
|
|
874
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
875
|
+
});
|
|
876
|
+
}
|
|
686
877
|
const originalMethod = init?.method ?? "GET";
|
|
687
878
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
688
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
689
879
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
690
880
|
return fetch(proxyUrl, {
|
|
691
881
|
method: "POST",
|
|
@@ -711,10 +901,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
711
901
|
}
|
|
712
902
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
713
903
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
904
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
714
905
|
return async (input, init) => {
|
|
715
|
-
const originalUrl =
|
|
716
|
-
const originalMethod = init?.method ?? "GET";
|
|
717
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
906
|
+
const originalUrl = extractInputUrl(input);
|
|
718
907
|
const c = getContext();
|
|
719
908
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
720
909
|
if (!appSession) {
|
|
@@ -722,6 +911,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
722
911
|
"No authentication method available for connection proxy."
|
|
723
912
|
);
|
|
724
913
|
}
|
|
914
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
915
|
+
return fetch(sessionUrl, {
|
|
916
|
+
method: "POST",
|
|
917
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
const originalMethod = init?.method ?? "GET";
|
|
921
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
725
922
|
return fetch(proxyUrl, {
|
|
726
923
|
method: "POST",
|
|
727
924
|
headers: {
|