@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
|
@@ -71,6 +71,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
71
71
|
tools;
|
|
72
72
|
query;
|
|
73
73
|
checkConnection;
|
|
74
|
+
/**
|
|
75
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
76
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
77
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
78
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
79
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
80
|
+
*/
|
|
81
|
+
setup;
|
|
82
|
+
/**
|
|
83
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
84
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
85
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
86
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
87
|
+
*
|
|
88
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
89
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
90
|
+
* connectionId, which doesn't exist until the row is saved
|
|
91
|
+
*
|
|
92
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
93
|
+
* the default verify-on-create behavior without opt-in.
|
|
94
|
+
*/
|
|
95
|
+
skipConnectionCheckOnCreate;
|
|
74
96
|
constructor(config) {
|
|
75
97
|
this.slug = config.slug;
|
|
76
98
|
this.authType = config.authType;
|
|
@@ -87,6 +109,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
87
109
|
this.tools = config.tools;
|
|
88
110
|
this.query = config.query;
|
|
89
111
|
this.checkConnection = config.checkConnection;
|
|
112
|
+
this.setup = config.setup;
|
|
113
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
90
114
|
}
|
|
91
115
|
get connectorKey() {
|
|
92
116
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -151,6 +175,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
151
175
|
}
|
|
152
176
|
};
|
|
153
177
|
|
|
178
|
+
// ../connectors/src/setup-flow.ts
|
|
179
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
180
|
+
const runtime = {
|
|
181
|
+
params,
|
|
182
|
+
language: ctx.language,
|
|
183
|
+
config
|
|
184
|
+
};
|
|
185
|
+
let state = flow.initialState();
|
|
186
|
+
let answerIdx = 0;
|
|
187
|
+
const pendingParameterUpdates = [];
|
|
188
|
+
for (const step of flow.steps) {
|
|
189
|
+
const ans = ctx.answers[answerIdx];
|
|
190
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
191
|
+
state = step.applyAnswer(state, ans.answer);
|
|
192
|
+
if (step.toParameterUpdates) {
|
|
193
|
+
pendingParameterUpdates.push(...step.toParameterUpdates(state));
|
|
194
|
+
}
|
|
195
|
+
answerIdx += 1;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
|
|
199
|
+
if (step.type === "text") {
|
|
200
|
+
if (step.fetchOptions) {
|
|
201
|
+
const options2 = await step.fetchOptions(state, runtime);
|
|
202
|
+
if (options2.length === 0) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
type: "nextQuestion",
|
|
208
|
+
questionSlug: step.slug,
|
|
209
|
+
question: step.question[ctx.language],
|
|
210
|
+
questionType: "text",
|
|
211
|
+
allowFreeText: resolvedAllowFreeText,
|
|
212
|
+
...pendingParameterUpdates.length > 0 && {
|
|
213
|
+
parameterUpdates: pendingParameterUpdates
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
218
|
+
if (options.length === 0) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
type: "nextQuestion",
|
|
223
|
+
questionSlug: step.slug,
|
|
224
|
+
question: step.question[ctx.language],
|
|
225
|
+
questionType: step.type,
|
|
226
|
+
options,
|
|
227
|
+
allowFreeText: resolvedAllowFreeText,
|
|
228
|
+
...pendingParameterUpdates.length > 0 && {
|
|
229
|
+
parameterUpdates: pendingParameterUpdates
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
234
|
+
return {
|
|
235
|
+
type: "fulfilled",
|
|
236
|
+
dataInvestigationResult,
|
|
237
|
+
...pendingParameterUpdates.length > 0 && {
|
|
238
|
+
parameterUpdates: pendingParameterUpdates
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
async function resolveSetupSelection(params) {
|
|
243
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
244
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
245
|
+
return resolved.slice(0, limit);
|
|
246
|
+
}
|
|
247
|
+
|
|
154
248
|
// ../connectors/src/auth-types.ts
|
|
155
249
|
var AUTH_TYPES = {
|
|
156
250
|
OAUTH: "oauth",
|
|
@@ -315,11 +409,122 @@ var notionOauthOnboarding = new ConnectorOnboarding({
|
|
|
315
409
|
// ../connectors/src/connectors/notion-oauth/parameters.ts
|
|
316
410
|
var parameters = {};
|
|
317
411
|
|
|
412
|
+
// ../connectors/src/connectors/notion-oauth/utils.ts
|
|
413
|
+
var BASE_URL3 = "https://api.notion.com/v1";
|
|
414
|
+
var NOTION_VERSION3 = "2022-06-28";
|
|
415
|
+
function apiFetch(proxyFetch, path2, init) {
|
|
416
|
+
const url = `${BASE_URL3}${path2.startsWith("/") ? "" : "/"}${path2}`;
|
|
417
|
+
const headers = new Headers(init?.headers);
|
|
418
|
+
headers.set("Notion-Version", NOTION_VERSION3);
|
|
419
|
+
if (init?.body && !headers.has("Content-Type")) {
|
|
420
|
+
headers.set("Content-Type", "application/json");
|
|
421
|
+
}
|
|
422
|
+
return proxyFetch(url, { ...init, headers });
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// ../connectors/src/connectors/notion-oauth/setup-flow.ts
|
|
426
|
+
var ALL_DATABASES = "__ALL_DATABASES__";
|
|
427
|
+
var NOTION_SETUP_MAX_DATABASES = 20;
|
|
428
|
+
function databaseTitle(db) {
|
|
429
|
+
const parts = (db.title ?? []).map((t) => t.plain_text ?? "").filter((s) => s);
|
|
430
|
+
return parts.join("").trim() || "(Untitled)";
|
|
431
|
+
}
|
|
432
|
+
async function searchDatabases(proxyFetch) {
|
|
433
|
+
const results = [];
|
|
434
|
+
let startCursor;
|
|
435
|
+
for (let i = 0; i < 20; i++) {
|
|
436
|
+
const body = {
|
|
437
|
+
filter: { property: "object", value: "database" },
|
|
438
|
+
page_size: 100
|
|
439
|
+
};
|
|
440
|
+
if (startCursor) body.start_cursor = startCursor;
|
|
441
|
+
const res = await apiFetch(proxyFetch, "/search", {
|
|
442
|
+
method: "POST",
|
|
443
|
+
body: JSON.stringify(body)
|
|
444
|
+
});
|
|
445
|
+
if (!res.ok) {
|
|
446
|
+
const text = await res.text().catch(() => res.statusText);
|
|
447
|
+
throw new Error(
|
|
448
|
+
`notion-oauth: search failed (${res.status}): ${text}`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
const data = await res.json();
|
|
452
|
+
for (const r of data.results ?? []) results.push(r);
|
|
453
|
+
if (!data.has_more || !data.next_cursor) break;
|
|
454
|
+
startCursor = data.next_cursor;
|
|
455
|
+
}
|
|
456
|
+
return results;
|
|
457
|
+
}
|
|
458
|
+
async function getDatabase(proxyFetch, databaseId) {
|
|
459
|
+
const res = await apiFetch(proxyFetch, `/databases/${databaseId}`);
|
|
460
|
+
if (!res.ok) {
|
|
461
|
+
const text = await res.text().catch(() => res.statusText);
|
|
462
|
+
throw new Error(
|
|
463
|
+
`notion-oauth: getDatabase ${databaseId} failed (${res.status}): ${text}`
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
return await res.json();
|
|
467
|
+
}
|
|
468
|
+
var notionOauthSetupFlow = {
|
|
469
|
+
initialState: () => ({}),
|
|
470
|
+
steps: [
|
|
471
|
+
{
|
|
472
|
+
slug: "databases",
|
|
473
|
+
type: "multiSelect",
|
|
474
|
+
question: {
|
|
475
|
+
ja: "\u5BFE\u8C61\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
476
|
+
en: "Select target databases (multi-select allowed)"
|
|
477
|
+
},
|
|
478
|
+
async fetchOptions(_state, rt) {
|
|
479
|
+
const dbs = await searchDatabases(rt.config.proxyFetch);
|
|
480
|
+
const dbOptions = dbs.filter((db) => db.id).map((db) => ({ value: db.id, label: databaseTitle(db) }));
|
|
481
|
+
return [
|
|
482
|
+
{
|
|
483
|
+
value: ALL_DATABASES,
|
|
484
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9" : "All databases"
|
|
485
|
+
},
|
|
486
|
+
...dbOptions
|
|
487
|
+
];
|
|
488
|
+
},
|
|
489
|
+
applyAnswer: (state, answer) => ({ ...state, databases: answer })
|
|
490
|
+
}
|
|
491
|
+
],
|
|
492
|
+
async finalize(state, rt) {
|
|
493
|
+
if (!state.databases) {
|
|
494
|
+
throw new Error("Notion setup: incomplete state on finalize");
|
|
495
|
+
}
|
|
496
|
+
const targetIds = await resolveSetupSelection({
|
|
497
|
+
selected: state.databases,
|
|
498
|
+
allSentinel: ALL_DATABASES,
|
|
499
|
+
fetchAll: async () => {
|
|
500
|
+
const dbs = await searchDatabases(rt.config.proxyFetch);
|
|
501
|
+
return dbs.map((db) => db.id).filter((id) => id);
|
|
502
|
+
},
|
|
503
|
+
limit: NOTION_SETUP_MAX_DATABASES
|
|
504
|
+
});
|
|
505
|
+
const sections = ["## Notion", ""];
|
|
506
|
+
for (const dbId of targetIds) {
|
|
507
|
+
const db = await getDatabase(rt.config.proxyFetch, dbId);
|
|
508
|
+
const title = databaseTitle(db);
|
|
509
|
+
sections.push(`### Database: ${title}`, "", `- id: \`${db.id}\``, "");
|
|
510
|
+
sections.push("| Property | Type |");
|
|
511
|
+
sections.push("|----------|------|");
|
|
512
|
+
for (const [name, def] of Object.entries(db.properties ?? {})) {
|
|
513
|
+
const escapedName = name.replace(/\|/g, "\\|");
|
|
514
|
+
sections.push(`| ${escapedName} | ${def?.type ?? "-"} |`);
|
|
515
|
+
}
|
|
516
|
+
sections.push("");
|
|
517
|
+
}
|
|
518
|
+
return sections.join("\n");
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
|
|
318
522
|
// ../connectors/src/connectors/notion-oauth/index.ts
|
|
319
523
|
var tools = { request: requestTool };
|
|
320
524
|
var notionOauthConnector = new ConnectorPlugin({
|
|
321
525
|
slug: "notion",
|
|
322
526
|
authType: AUTH_TYPES.OAUTH,
|
|
527
|
+
skipConnectionCheckOnCreate: true,
|
|
323
528
|
name: "Notion",
|
|
324
529
|
description: "Connect to Notion to query databases, pages, and workspace content using OAuth.",
|
|
325
530
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/797V5GDDTA8bsfKUHBCoQO/290ec49b70b68ddb4acd3bf0a6ab8bda/notion-icon.webp",
|
|
@@ -438,6 +643,7 @@ const data = await res.json();
|
|
|
438
643
|
\`\`\``
|
|
439
644
|
},
|
|
440
645
|
tools,
|
|
646
|
+
setup: (params, ctx, config) => runSetupFlow(notionOauthSetupFlow, params, ctx, config),
|
|
441
647
|
async checkConnection(_params, config) {
|
|
442
648
|
const { proxyFetch } = config;
|
|
443
649
|
try {
|
|
@@ -488,6 +694,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
488
694
|
import { getContext } from "hono/context-storage";
|
|
489
695
|
import { getCookie } from "hono/cookie";
|
|
490
696
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
697
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
491
698
|
function normalizeHeaders(input) {
|
|
492
699
|
const out = {};
|
|
493
700
|
if (!input) return out;
|
|
@@ -496,6 +703,11 @@ function normalizeHeaders(input) {
|
|
|
496
703
|
});
|
|
497
704
|
return out;
|
|
498
705
|
}
|
|
706
|
+
function extractInputUrl(input) {
|
|
707
|
+
if (typeof input === "string") return input;
|
|
708
|
+
if (input instanceof URL) return input.href;
|
|
709
|
+
return input.url;
|
|
710
|
+
}
|
|
499
711
|
function createSandboxProxyFetch(connectionId) {
|
|
500
712
|
return async (input, init) => {
|
|
501
713
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -505,10 +717,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
505
717
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
506
718
|
);
|
|
507
719
|
}
|
|
508
|
-
const originalUrl =
|
|
720
|
+
const originalUrl = extractInputUrl(input);
|
|
721
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
722
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
723
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
724
|
+
return fetch(sessionUrl, {
|
|
725
|
+
method: "POST",
|
|
726
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
727
|
+
});
|
|
728
|
+
}
|
|
509
729
|
const originalMethod = init?.method ?? "GET";
|
|
510
730
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
511
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
512
731
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
513
732
|
return fetch(proxyUrl, {
|
|
514
733
|
method: "POST",
|
|
@@ -534,10 +753,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
534
753
|
}
|
|
535
754
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
536
755
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
756
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
537
757
|
return async (input, init) => {
|
|
538
|
-
const originalUrl =
|
|
539
|
-
const originalMethod = init?.method ?? "GET";
|
|
540
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
758
|
+
const originalUrl = extractInputUrl(input);
|
|
541
759
|
const c = getContext();
|
|
542
760
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
543
761
|
if (!appSession) {
|
|
@@ -545,6 +763,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
545
763
|
"No authentication method available for connection proxy."
|
|
546
764
|
);
|
|
547
765
|
}
|
|
766
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
767
|
+
return fetch(sessionUrl, {
|
|
768
|
+
method: "POST",
|
|
769
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
const originalMethod = init?.method ?? "GET";
|
|
773
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
548
774
|
return fetch(proxyUrl, {
|
|
549
775
|
method: "POST",
|
|
550
776
|
headers: {
|