@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
|
@@ -185,6 +185,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
185
185
|
tools;
|
|
186
186
|
query;
|
|
187
187
|
checkConnection;
|
|
188
|
+
/**
|
|
189
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
190
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
191
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
192
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
193
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
194
|
+
*/
|
|
195
|
+
setup;
|
|
196
|
+
/**
|
|
197
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
198
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
199
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
200
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
201
|
+
*
|
|
202
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
203
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
204
|
+
* connectionId, which doesn't exist until the row is saved
|
|
205
|
+
*
|
|
206
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
207
|
+
* the default verify-on-create behavior without opt-in.
|
|
208
|
+
*/
|
|
209
|
+
skipConnectionCheckOnCreate;
|
|
188
210
|
constructor(config) {
|
|
189
211
|
this.slug = config.slug;
|
|
190
212
|
this.authType = config.authType;
|
|
@@ -201,6 +223,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
201
223
|
this.tools = config.tools;
|
|
202
224
|
this.query = config.query;
|
|
203
225
|
this.checkConnection = config.checkConnection;
|
|
226
|
+
this.setup = config.setup;
|
|
227
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
204
228
|
}
|
|
205
229
|
get connectorKey() {
|
|
206
230
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -265,6 +289,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
265
289
|
}
|
|
266
290
|
};
|
|
267
291
|
|
|
292
|
+
// ../connectors/src/setup-flow.ts
|
|
293
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
294
|
+
const runtime = {
|
|
295
|
+
params,
|
|
296
|
+
language: ctx.language,
|
|
297
|
+
config
|
|
298
|
+
};
|
|
299
|
+
let state = flow.initialState();
|
|
300
|
+
let answerIdx = 0;
|
|
301
|
+
const pendingParameterUpdates = [];
|
|
302
|
+
for (const step of flow.steps) {
|
|
303
|
+
const ans = ctx.answers[answerIdx];
|
|
304
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
305
|
+
state = step.applyAnswer(state, ans.answer);
|
|
306
|
+
if (step.toParameterUpdates) {
|
|
307
|
+
pendingParameterUpdates.push(...step.toParameterUpdates(state));
|
|
308
|
+
}
|
|
309
|
+
answerIdx += 1;
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
|
|
313
|
+
if (step.type === "text") {
|
|
314
|
+
if (step.fetchOptions) {
|
|
315
|
+
const options2 = await step.fetchOptions(state, runtime);
|
|
316
|
+
if (options2.length === 0) {
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return {
|
|
321
|
+
type: "nextQuestion",
|
|
322
|
+
questionSlug: step.slug,
|
|
323
|
+
question: step.question[ctx.language],
|
|
324
|
+
questionType: "text",
|
|
325
|
+
allowFreeText: resolvedAllowFreeText,
|
|
326
|
+
...pendingParameterUpdates.length > 0 && {
|
|
327
|
+
parameterUpdates: pendingParameterUpdates
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
332
|
+
if (options.length === 0) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
type: "nextQuestion",
|
|
337
|
+
questionSlug: step.slug,
|
|
338
|
+
question: step.question[ctx.language],
|
|
339
|
+
questionType: step.type,
|
|
340
|
+
options,
|
|
341
|
+
allowFreeText: resolvedAllowFreeText,
|
|
342
|
+
...pendingParameterUpdates.length > 0 && {
|
|
343
|
+
parameterUpdates: pendingParameterUpdates
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
348
|
+
return {
|
|
349
|
+
type: "fulfilled",
|
|
350
|
+
dataInvestigationResult,
|
|
351
|
+
...pendingParameterUpdates.length > 0 && {
|
|
352
|
+
parameterUpdates: pendingParameterUpdates
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
async function resolveSetupSelection(params) {
|
|
357
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
358
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
359
|
+
return resolved.slice(0, limit);
|
|
360
|
+
}
|
|
361
|
+
|
|
268
362
|
// ../connectors/src/auth-types.ts
|
|
269
363
|
var AUTH_TYPES = {
|
|
270
364
|
OAUTH: "oauth",
|
|
@@ -463,6 +557,89 @@ Calendar
|
|
|
463
557
|
}
|
|
464
558
|
});
|
|
465
559
|
|
|
560
|
+
// ../connectors/src/connectors/outlook-oauth/utils.ts
|
|
561
|
+
async function graphApiFetch(config, url) {
|
|
562
|
+
const res = await config.proxyFetch(url, { method: "GET" });
|
|
563
|
+
if (!res.ok) {
|
|
564
|
+
const text = await res.text().catch(() => res.statusText);
|
|
565
|
+
throw new Error(`Microsoft Graph ${url} failed: HTTP ${res.status} ${text}`);
|
|
566
|
+
}
|
|
567
|
+
return await res.json();
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// ../connectors/src/connectors/outlook-oauth/setup-flow.ts
|
|
571
|
+
var ALL_FOLDERS = "__ALL_FOLDERS__";
|
|
572
|
+
var OUTLOOK_SETUP_MAX_FOLDERS = 20;
|
|
573
|
+
async function listMailFolders(config) {
|
|
574
|
+
const url = "https://graph.microsoft.com/v1.0/me/mailFolders?$top=100&$select=id,displayName,parentFolderId,childFolderCount,unreadItemCount,totalItemCount";
|
|
575
|
+
const data = await graphApiFetch(config, url);
|
|
576
|
+
return data.value ?? [];
|
|
577
|
+
}
|
|
578
|
+
var outlookOauthSetupFlow = {
|
|
579
|
+
initialState: () => ({}),
|
|
580
|
+
steps: [
|
|
581
|
+
{
|
|
582
|
+
slug: "folders",
|
|
583
|
+
type: "multiSelect",
|
|
584
|
+
question: {
|
|
585
|
+
ja: "\u5BFE\u8C61\u306E\u30E1\u30FC\u30EB\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
586
|
+
en: "Select target mail folders (multi-select allowed)"
|
|
587
|
+
},
|
|
588
|
+
async fetchOptions(_state, rt) {
|
|
589
|
+
const folders = await listMailFolders(rt.config);
|
|
590
|
+
return [
|
|
591
|
+
{
|
|
592
|
+
value: ALL_FOLDERS,
|
|
593
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30D5\u30A9\u30EB\u30C0" : "All folders"
|
|
594
|
+
},
|
|
595
|
+
...folders.map((f) => ({
|
|
596
|
+
value: f.id,
|
|
597
|
+
label: f.displayName ?? f.id
|
|
598
|
+
}))
|
|
599
|
+
];
|
|
600
|
+
},
|
|
601
|
+
applyAnswer: (state, answer) => ({ ...state, folders: answer })
|
|
602
|
+
}
|
|
603
|
+
],
|
|
604
|
+
async finalize(state, rt) {
|
|
605
|
+
if (!state.folders) {
|
|
606
|
+
throw new Error("Outlook setup: incomplete state on finalize");
|
|
607
|
+
}
|
|
608
|
+
const folders = await listMailFolders(rt.config);
|
|
609
|
+
const byId = new Map(folders.map((f) => [f.id, f]));
|
|
610
|
+
const targetIds = await resolveSetupSelection({
|
|
611
|
+
selected: state.folders,
|
|
612
|
+
allSentinel: ALL_FOLDERS,
|
|
613
|
+
fetchAll: async () => folders.map((f) => f.id),
|
|
614
|
+
limit: OUTLOOK_SETUP_MAX_FOLDERS
|
|
615
|
+
});
|
|
616
|
+
const sections = ["## Outlook", ""];
|
|
617
|
+
if (targetIds.length === 0) {
|
|
618
|
+
sections.push(
|
|
619
|
+
rt.language === "ja" ? "\u5BFE\u8C61\u306E\u30D5\u30A9\u30EB\u30C0\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002" : "No folders selected."
|
|
620
|
+
);
|
|
621
|
+
return sections.join("\n");
|
|
622
|
+
}
|
|
623
|
+
sections.push("| Folder | Total | Unread | Sub-folders |");
|
|
624
|
+
sections.push("|--------|-------|--------|-------------|");
|
|
625
|
+
for (const id of targetIds) {
|
|
626
|
+
const f = byId.get(id);
|
|
627
|
+
if (!f) {
|
|
628
|
+
sections.push(`| ${id} | - | - | - |`);
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
const total = f.totalItemCount ?? "-";
|
|
632
|
+
const unread = f.unreadItemCount ?? "-";
|
|
633
|
+
const subs = f.childFolderCount ?? 0;
|
|
634
|
+
sections.push(
|
|
635
|
+
`| ${f.displayName ?? id} | ${total} | ${unread} | ${subs} |`
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
sections.push("");
|
|
639
|
+
return sections.join("\n");
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
|
|
466
643
|
// ../connectors/src/connectors/outlook-oauth/parameters.ts
|
|
467
644
|
var parameters = {};
|
|
468
645
|
|
|
@@ -471,6 +648,7 @@ var tools = { request: requestTool };
|
|
|
471
648
|
var outlookOauthConnector = new ConnectorPlugin({
|
|
472
649
|
slug: "outlook",
|
|
473
650
|
authType: AUTH_TYPES.OAUTH,
|
|
651
|
+
skipConnectionCheckOnCreate: true,
|
|
474
652
|
name: "Outlook",
|
|
475
653
|
description: "Connect to Microsoft Outlook (Mail + Calendar) via Microsoft Graph using OAuth. Read-only access to the user's mailbox, mail folders, messages, attachments, calendars, and events.",
|
|
476
654
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/1J1FrRTYJjOh3CcSIqsz3I/6a467b4d926075ff99dc60820e0ae4b1/Microsoft_Outlook_Icon__2025%C3%A2__present_.svg",
|
|
@@ -755,6 +933,7 @@ events.value.forEach(e => console.log(e.start.dateTime, e.subject));
|
|
|
755
933
|
\`\`\``
|
|
756
934
|
},
|
|
757
935
|
tools,
|
|
936
|
+
setup: (params, ctx, config) => runSetupFlow(outlookOauthSetupFlow, params, ctx, config),
|
|
758
937
|
async checkConnection(_params, config) {
|
|
759
938
|
const { proxyFetch } = config;
|
|
760
939
|
const url = "https://graph.microsoft.com/v1.0/me";
|
|
@@ -803,6 +982,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
803
982
|
import { getContext } from "hono/context-storage";
|
|
804
983
|
import { getCookie } from "hono/cookie";
|
|
805
984
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
985
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
806
986
|
function normalizeHeaders(input) {
|
|
807
987
|
const out = {};
|
|
808
988
|
if (!input) return out;
|
|
@@ -811,6 +991,11 @@ function normalizeHeaders(input) {
|
|
|
811
991
|
});
|
|
812
992
|
return out;
|
|
813
993
|
}
|
|
994
|
+
function extractInputUrl(input) {
|
|
995
|
+
if (typeof input === "string") return input;
|
|
996
|
+
if (input instanceof URL) return input.href;
|
|
997
|
+
return input.url;
|
|
998
|
+
}
|
|
814
999
|
function createSandboxProxyFetch(connectionId) {
|
|
815
1000
|
return async (input, init) => {
|
|
816
1001
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -820,10 +1005,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
820
1005
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
821
1006
|
);
|
|
822
1007
|
}
|
|
823
|
-
const originalUrl =
|
|
1008
|
+
const originalUrl = extractInputUrl(input);
|
|
1009
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
1010
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1011
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
1012
|
+
return fetch(sessionUrl, {
|
|
1013
|
+
method: "POST",
|
|
1014
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
824
1017
|
const originalMethod = init?.method ?? "GET";
|
|
825
1018
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
826
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
827
1019
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
828
1020
|
return fetch(proxyUrl, {
|
|
829
1021
|
method: "POST",
|
|
@@ -849,10 +1041,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
849
1041
|
}
|
|
850
1042
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
851
1043
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1044
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
852
1045
|
return async (input, init) => {
|
|
853
|
-
const originalUrl =
|
|
854
|
-
const originalMethod = init?.method ?? "GET";
|
|
855
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
1046
|
+
const originalUrl = extractInputUrl(input);
|
|
856
1047
|
const c = getContext();
|
|
857
1048
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
858
1049
|
if (!appSession) {
|
|
@@ -860,6 +1051,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
860
1051
|
"No authentication method available for connection proxy."
|
|
861
1052
|
);
|
|
862
1053
|
}
|
|
1054
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1055
|
+
return fetch(sessionUrl, {
|
|
1056
|
+
method: "POST",
|
|
1057
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
const originalMethod = init?.method ?? "GET";
|
|
1061
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
863
1062
|
return fetch(proxyUrl, {
|
|
864
1063
|
method: "POST",
|
|
865
1064
|
headers: {
|