@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
|
@@ -65,6 +65,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
65
65
|
tools;
|
|
66
66
|
query;
|
|
67
67
|
checkConnection;
|
|
68
|
+
/**
|
|
69
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
70
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
71
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
72
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
73
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
74
|
+
*/
|
|
75
|
+
setup;
|
|
76
|
+
/**
|
|
77
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
78
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
79
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
80
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
81
|
+
*
|
|
82
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
83
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
84
|
+
* connectionId, which doesn't exist until the row is saved
|
|
85
|
+
*
|
|
86
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
87
|
+
* the default verify-on-create behavior without opt-in.
|
|
88
|
+
*/
|
|
89
|
+
skipConnectionCheckOnCreate;
|
|
68
90
|
constructor(config) {
|
|
69
91
|
this.slug = config.slug;
|
|
70
92
|
this.authType = config.authType;
|
|
@@ -81,6 +103,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
81
103
|
this.tools = config.tools;
|
|
82
104
|
this.query = config.query;
|
|
83
105
|
this.checkConnection = config.checkConnection;
|
|
106
|
+
this.setup = config.setup;
|
|
107
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
84
108
|
}
|
|
85
109
|
get connectorKey() {
|
|
86
110
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -145,6 +169,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
145
169
|
}
|
|
146
170
|
};
|
|
147
171
|
|
|
172
|
+
// ../connectors/src/setup-flow.ts
|
|
173
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
174
|
+
const runtime = {
|
|
175
|
+
params,
|
|
176
|
+
language: ctx.language,
|
|
177
|
+
config
|
|
178
|
+
};
|
|
179
|
+
let state = flow.initialState();
|
|
180
|
+
let answerIdx = 0;
|
|
181
|
+
const pendingParameterUpdates = [];
|
|
182
|
+
for (const step of flow.steps) {
|
|
183
|
+
const ans = ctx.answers[answerIdx];
|
|
184
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
185
|
+
state = step.applyAnswer(state, ans.answer);
|
|
186
|
+
if (step.toParameterUpdates) {
|
|
187
|
+
pendingParameterUpdates.push(...step.toParameterUpdates(state));
|
|
188
|
+
}
|
|
189
|
+
answerIdx += 1;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
|
|
193
|
+
if (step.type === "text") {
|
|
194
|
+
if (step.fetchOptions) {
|
|
195
|
+
const options2 = await step.fetchOptions(state, runtime);
|
|
196
|
+
if (options2.length === 0) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
type: "nextQuestion",
|
|
202
|
+
questionSlug: step.slug,
|
|
203
|
+
question: step.question[ctx.language],
|
|
204
|
+
questionType: "text",
|
|
205
|
+
allowFreeText: resolvedAllowFreeText,
|
|
206
|
+
...pendingParameterUpdates.length > 0 && {
|
|
207
|
+
parameterUpdates: pendingParameterUpdates
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
212
|
+
if (options.length === 0) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
type: "nextQuestion",
|
|
217
|
+
questionSlug: step.slug,
|
|
218
|
+
question: step.question[ctx.language],
|
|
219
|
+
questionType: step.type,
|
|
220
|
+
options,
|
|
221
|
+
allowFreeText: resolvedAllowFreeText,
|
|
222
|
+
...pendingParameterUpdates.length > 0 && {
|
|
223
|
+
parameterUpdates: pendingParameterUpdates
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
228
|
+
return {
|
|
229
|
+
type: "fulfilled",
|
|
230
|
+
dataInvestigationResult,
|
|
231
|
+
...pendingParameterUpdates.length > 0 && {
|
|
232
|
+
parameterUpdates: pendingParameterUpdates
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
async function resolveSetupSelection(params) {
|
|
237
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
238
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
239
|
+
return resolved.slice(0, limit);
|
|
240
|
+
}
|
|
241
|
+
|
|
148
242
|
// ../connectors/src/auth-types.ts
|
|
149
243
|
var AUTH_TYPES = {
|
|
150
244
|
OAUTH: "oauth",
|
|
@@ -309,6 +403,124 @@ var zendeskOauthOnboarding = new ConnectorOnboarding({
|
|
|
309
403
|
}
|
|
310
404
|
});
|
|
311
405
|
|
|
406
|
+
// ../connectors/src/connectors/zendesk-oauth/utils.ts
|
|
407
|
+
function apiFetch(proxyFetch, path2, init) {
|
|
408
|
+
const url = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
409
|
+
const headers = new Headers(init?.headers);
|
|
410
|
+
headers.set("Accept", "application/json");
|
|
411
|
+
return proxyFetch(url, { ...init, headers });
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// ../connectors/src/connectors/zendesk-oauth/setup-flow.ts
|
|
415
|
+
var ZENDESK_SETUP_MAX_ENTITIES = 5;
|
|
416
|
+
var ZENDESK_ENTITIES = [
|
|
417
|
+
{
|
|
418
|
+
value: "tickets",
|
|
419
|
+
label: "Tickets",
|
|
420
|
+
countPath: "/api/v2/tickets.json?page[size]=1"
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
value: "users",
|
|
424
|
+
label: "Users",
|
|
425
|
+
countPath: "/api/v2/users.json?page[size]=1"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
value: "organizations",
|
|
429
|
+
label: "Organizations",
|
|
430
|
+
countPath: "/api/v2/organizations.json?page[size]=1"
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
value: "groups",
|
|
434
|
+
label: "Groups",
|
|
435
|
+
countPath: "/api/v2/groups.json?page[size]=1"
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
value: "articles",
|
|
439
|
+
label: "Help Center articles",
|
|
440
|
+
countPath: "/api/v2/help_center/articles.json?page[size]=1"
|
|
441
|
+
}
|
|
442
|
+
];
|
|
443
|
+
async function listBrands(proxyFetch) {
|
|
444
|
+
const res = await apiFetch(proxyFetch, "/api/v2/brands.json");
|
|
445
|
+
if (!res.ok) return [];
|
|
446
|
+
const data = await res.json();
|
|
447
|
+
return data.brands ?? [];
|
|
448
|
+
}
|
|
449
|
+
async function fetchCount(proxyFetch, path2) {
|
|
450
|
+
const res = await apiFetch(proxyFetch, path2);
|
|
451
|
+
if (!res.ok) return null;
|
|
452
|
+
const data = await res.json();
|
|
453
|
+
if (typeof data["count"] === "number") return data["count"];
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
var zendeskOauthSetupFlow = {
|
|
457
|
+
initialState: () => ({}),
|
|
458
|
+
steps: [
|
|
459
|
+
{
|
|
460
|
+
slug: "brand",
|
|
461
|
+
type: "select",
|
|
462
|
+
question: {
|
|
463
|
+
ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3067\u5BFE\u8C61\u3068\u3059\u308BZendesk\u30D6\u30E9\u30F3\u30C9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
|
|
464
|
+
en: "Select the Zendesk brand to use for setup"
|
|
465
|
+
},
|
|
466
|
+
async fetchOptions(_state, rt) {
|
|
467
|
+
const brands = await listBrands(rt.config.proxyFetch);
|
|
468
|
+
const active = brands.filter((b) => b.active !== false && b.name);
|
|
469
|
+
if (active.length < 2) return [];
|
|
470
|
+
return active.map((b) => ({
|
|
471
|
+
value: String(b.subdomain ?? b.id ?? b.name),
|
|
472
|
+
label: String(b.name)
|
|
473
|
+
}));
|
|
474
|
+
},
|
|
475
|
+
applyAnswer: (state, answer) => ({ ...state, brand: answer[0] })
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
slug: "entities",
|
|
479
|
+
type: "multiSelect",
|
|
480
|
+
question: {
|
|
481
|
+
ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3067\u6982\u89B3\u3057\u305F\u3044\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
482
|
+
en: "Select the entities to include in setup (multi-select allowed)"
|
|
483
|
+
},
|
|
484
|
+
async fetchOptions(_state, _rt) {
|
|
485
|
+
return ZENDESK_ENTITIES.map((e) => ({ value: e.value, label: e.label }));
|
|
486
|
+
},
|
|
487
|
+
applyAnswer: (state, answer) => ({ ...state, entities: answer })
|
|
488
|
+
}
|
|
489
|
+
],
|
|
490
|
+
async finalize(state, rt) {
|
|
491
|
+
if (!state.entities) {
|
|
492
|
+
throw new Error("Zendesk setup: incomplete state on finalize");
|
|
493
|
+
}
|
|
494
|
+
const targetEntities = await resolveSetupSelection({
|
|
495
|
+
selected: state.entities,
|
|
496
|
+
allSentinel: "__ALL__",
|
|
497
|
+
fetchAll: async () => ZENDESK_ENTITIES.map((e) => e.value),
|
|
498
|
+
limit: ZENDESK_SETUP_MAX_ENTITIES
|
|
499
|
+
});
|
|
500
|
+
const entityByValue = new Map(ZENDESK_ENTITIES.map((e) => [e.value, e]));
|
|
501
|
+
const sections = ["## Zendesk", ""];
|
|
502
|
+
if (state.brand) {
|
|
503
|
+
sections.push(`### Brand: ${state.brand}`, "");
|
|
504
|
+
}
|
|
505
|
+
sections.push("### Selected entities", "");
|
|
506
|
+
sections.push("| Entity | Count |");
|
|
507
|
+
sections.push("|--------|-------|");
|
|
508
|
+
for (const value of targetEntities) {
|
|
509
|
+
const entity = entityByValue.get(value);
|
|
510
|
+
if (!entity) {
|
|
511
|
+
sections.push(`| ${value} | _unknown_ |`);
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
const count = await fetchCount(rt.config.proxyFetch, entity.countPath);
|
|
515
|
+
sections.push(
|
|
516
|
+
`| ${entity.label} (${entity.value}) | ${count == null ? "-" : count} |`
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
sections.push("");
|
|
520
|
+
return sections.join("\n");
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
312
524
|
// ../connectors/src/connectors/zendesk-oauth/parameters.ts
|
|
313
525
|
var parameters = {};
|
|
314
526
|
|
|
@@ -317,6 +529,7 @@ var tools = { request: requestTool };
|
|
|
317
529
|
var zendeskOauthConnector = new ConnectorPlugin({
|
|
318
530
|
slug: "zendesk",
|
|
319
531
|
authType: AUTH_TYPES.OAUTH,
|
|
532
|
+
skipConnectionCheckOnCreate: true,
|
|
320
533
|
name: "Zendesk",
|
|
321
534
|
description: "Connect to Zendesk Support for tickets, users, organizations, and customer service data using OAuth.",
|
|
322
535
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/7e9Q7PwV6MJRJMj543m2gl/55385fae903ccfa1599e35be9d3516aa/zendesk-icon.svg",
|
|
@@ -451,6 +664,7 @@ const data = await res.json();
|
|
|
451
664
|
\`\`\``
|
|
452
665
|
},
|
|
453
666
|
tools,
|
|
667
|
+
setup: (params, ctx, config) => runSetupFlow(zendeskOauthSetupFlow, params, ctx, config),
|
|
454
668
|
async checkConnection(_params, config) {
|
|
455
669
|
const { proxyFetch } = config;
|
|
456
670
|
try {
|
|
@@ -500,6 +714,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
500
714
|
import { getContext } from "hono/context-storage";
|
|
501
715
|
import { getCookie } from "hono/cookie";
|
|
502
716
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
717
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
503
718
|
function normalizeHeaders(input) {
|
|
504
719
|
const out = {};
|
|
505
720
|
if (!input) return out;
|
|
@@ -508,6 +723,11 @@ function normalizeHeaders(input) {
|
|
|
508
723
|
});
|
|
509
724
|
return out;
|
|
510
725
|
}
|
|
726
|
+
function extractInputUrl(input) {
|
|
727
|
+
if (typeof input === "string") return input;
|
|
728
|
+
if (input instanceof URL) return input.href;
|
|
729
|
+
return input.url;
|
|
730
|
+
}
|
|
511
731
|
function createSandboxProxyFetch(connectionId) {
|
|
512
732
|
return async (input, init) => {
|
|
513
733
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -517,10 +737,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
517
737
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
518
738
|
);
|
|
519
739
|
}
|
|
520
|
-
const originalUrl =
|
|
740
|
+
const originalUrl = extractInputUrl(input);
|
|
741
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
742
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
743
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
744
|
+
return fetch(sessionUrl, {
|
|
745
|
+
method: "POST",
|
|
746
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
747
|
+
});
|
|
748
|
+
}
|
|
521
749
|
const originalMethod = init?.method ?? "GET";
|
|
522
750
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
523
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
524
751
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
525
752
|
return fetch(proxyUrl, {
|
|
526
753
|
method: "POST",
|
|
@@ -546,10 +773,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
546
773
|
}
|
|
547
774
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
548
775
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
776
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
549
777
|
return async (input, init) => {
|
|
550
|
-
const originalUrl =
|
|
551
|
-
const originalMethod = init?.method ?? "GET";
|
|
552
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
778
|
+
const originalUrl = extractInputUrl(input);
|
|
553
779
|
const c = getContext();
|
|
554
780
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
555
781
|
if (!appSession) {
|
|
@@ -557,6 +783,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
557
783
|
"No authentication method available for connection proxy."
|
|
558
784
|
);
|
|
559
785
|
}
|
|
786
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
787
|
+
return fetch(sessionUrl, {
|
|
788
|
+
method: "POST",
|
|
789
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
const originalMethod = init?.method ?? "GET";
|
|
793
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
560
794
|
return fetch(proxyUrl, {
|
|
561
795
|
method: "POST",
|
|
562
796
|
headers: {
|