@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.
- package/dist/cli/index.js +12374 -883
- package/dist/connectors/airtable-oauth.js +257 -46
- package/dist/connectors/airtable.js +294 -51
- package/dist/connectors/amplitude.js +297 -47
- package/dist/connectors/anthropic.js +135 -47
- package/dist/connectors/asana.js +302 -49
- package/dist/connectors/attio.js +277 -49
- package/dist/connectors/aws-billing.js +262 -46
- package/dist/connectors/azure-sql.js +396 -102
- package/dist/connectors/backlog-api-key.js +292 -47
- package/dist/connectors/clickup.js +313 -49
- package/dist/connectors/cosmosdb.js +280 -50
- package/dist/connectors/customerio.js +294 -47
- package/dist/connectors/dbt.js +315 -47
- package/dist/connectors/freshdesk.js +317 -53
- package/dist/connectors/freshsales.js +308 -52
- package/dist/connectors/freshservice.js +336 -53
- package/dist/connectors/gamma.js +302 -52
- package/dist/connectors/gemini.js +134 -47
- package/dist/connectors/github.js +361 -49
- package/dist/connectors/gmail-oauth.js +179 -7
- package/dist/connectors/gmail.js +325 -47
- package/dist/connectors/google-ads.js +263 -46
- package/dist/connectors/google-analytics-oauth.js +285 -46
- package/dist/connectors/google-analytics.js +387 -49
- package/dist/connectors/google-audit-log.js +413 -47
- package/dist/connectors/google-calendar-oauth.js +234 -46
- package/dist/connectors/google-calendar.js +334 -47
- package/dist/connectors/google-docs.js +195 -6
- package/dist/connectors/google-drive.js +237 -5
- package/dist/connectors/google-search-console-oauth.js +231 -46
- package/dist/connectors/google-sheets.js +247 -47
- package/dist/connectors/google-slides.js +180 -6
- package/dist/connectors/grafana.js +307 -49
- package/dist/connectors/hubspot-oauth.js +183 -5
- package/dist/connectors/hubspot.js +281 -49
- package/dist/connectors/influxdb.js +391 -51
- package/dist/connectors/intercom-oauth.js +185 -5
- package/dist/connectors/intercom.js +277 -49
- package/dist/connectors/jdbc.js +737 -110
- package/dist/connectors/jira-api-key.js +301 -47
- package/dist/connectors/kintone-api-token.js +256 -47
- package/dist/connectors/kintone.js +303 -47
- package/dist/connectors/linear.js +305 -49
- package/dist/connectors/linkedin-ads.js +243 -50
- package/dist/connectors/mailchimp-oauth.js +243 -46
- package/dist/connectors/mailchimp.js +295 -49
- package/dist/connectors/meta-ads-oauth.js +248 -48
- package/dist/connectors/meta-ads.js +260 -50
- package/dist/connectors/mixpanel.js +313 -47
- package/dist/connectors/monday.js +335 -49
- package/dist/connectors/mongodb.js +294 -57
- package/dist/connectors/notion-oauth.js +206 -5
- package/dist/connectors/notion.js +298 -51
- package/dist/connectors/openai.js +134 -47
- package/dist/connectors/oracle.js +414 -103
- package/dist/connectors/outlook-oauth.js +179 -5
- package/dist/connectors/powerbi-oauth.js +226 -5
- package/dist/connectors/salesforce.js +359 -49
- package/dist/connectors/semrush.js +289 -49
- package/dist/connectors/sentry.js +264 -50
- package/dist/connectors/shopify-oauth.js +162 -5
- package/dist/connectors/shopify.js +332 -47
- package/dist/connectors/sqlserver.js +390 -102
- package/dist/connectors/stripe-api-key.js +244 -46
- package/dist/connectors/stripe-oauth.js +177 -5
- package/dist/connectors/supabase.js +278 -48
- package/dist/connectors/tableau.js +389 -184
- package/dist/connectors/tiktok-ads.js +254 -48
- package/dist/connectors/wix-store.js +295 -49
- package/dist/connectors/zendesk-oauth.js +214 -5
- package/dist/connectors/zendesk.js +333 -47
- package/dist/index.d.ts +149 -1
- package/dist/index.js +13677 -1969
- package/dist/main.js +13627 -1927
- package/dist/vite-plugin.js +12391 -890
- 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,51 @@ 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
|
+
for (const step of flow.steps) {
|
|
182
|
+
const ans = ctx.answers[answerIdx];
|
|
183
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
184
|
+
state = step.applyAnswer(state, ans.answer);
|
|
185
|
+
answerIdx += 1;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (step.type === "text") {
|
|
189
|
+
return {
|
|
190
|
+
type: "nextQuestion",
|
|
191
|
+
questionSlug: step.slug,
|
|
192
|
+
question: step.question[ctx.language],
|
|
193
|
+
questionType: "text"
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
197
|
+
if (options.length === 0) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
type: "nextQuestion",
|
|
202
|
+
questionSlug: step.slug,
|
|
203
|
+
question: step.question[ctx.language],
|
|
204
|
+
questionType: step.type,
|
|
205
|
+
options
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
209
|
+
return { type: "fulfilled", dataInvestigationResult };
|
|
210
|
+
}
|
|
211
|
+
async function resolveSetupSelection(params) {
|
|
212
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
213
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
214
|
+
return resolved.slice(0, limit);
|
|
215
|
+
}
|
|
216
|
+
|
|
148
217
|
// ../connectors/src/auth-types.ts
|
|
149
218
|
var AUTH_TYPES = {
|
|
150
219
|
OAUTH: "oauth",
|
|
@@ -309,6 +378,124 @@ var zendeskOauthOnboarding = new ConnectorOnboarding({
|
|
|
309
378
|
}
|
|
310
379
|
});
|
|
311
380
|
|
|
381
|
+
// ../connectors/src/connectors/zendesk-oauth/utils.ts
|
|
382
|
+
function apiFetch(proxyFetch, path2, init) {
|
|
383
|
+
const url = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
384
|
+
const headers = new Headers(init?.headers);
|
|
385
|
+
headers.set("Accept", "application/json");
|
|
386
|
+
return proxyFetch(url, { ...init, headers });
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// ../connectors/src/connectors/zendesk-oauth/setup-flow.ts
|
|
390
|
+
var ZENDESK_SETUP_MAX_ENTITIES = 5;
|
|
391
|
+
var ZENDESK_ENTITIES = [
|
|
392
|
+
{
|
|
393
|
+
value: "tickets",
|
|
394
|
+
label: "Tickets",
|
|
395
|
+
countPath: "/api/v2/tickets.json?page[size]=1"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
value: "users",
|
|
399
|
+
label: "Users",
|
|
400
|
+
countPath: "/api/v2/users.json?page[size]=1"
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
value: "organizations",
|
|
404
|
+
label: "Organizations",
|
|
405
|
+
countPath: "/api/v2/organizations.json?page[size]=1"
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
value: "groups",
|
|
409
|
+
label: "Groups",
|
|
410
|
+
countPath: "/api/v2/groups.json?page[size]=1"
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
value: "articles",
|
|
414
|
+
label: "Help Center articles",
|
|
415
|
+
countPath: "/api/v2/help_center/articles.json?page[size]=1"
|
|
416
|
+
}
|
|
417
|
+
];
|
|
418
|
+
async function listBrands(proxyFetch) {
|
|
419
|
+
const res = await apiFetch(proxyFetch, "/api/v2/brands.json");
|
|
420
|
+
if (!res.ok) return [];
|
|
421
|
+
const data = await res.json();
|
|
422
|
+
return data.brands ?? [];
|
|
423
|
+
}
|
|
424
|
+
async function fetchCount(proxyFetch, path2) {
|
|
425
|
+
const res = await apiFetch(proxyFetch, path2);
|
|
426
|
+
if (!res.ok) return null;
|
|
427
|
+
const data = await res.json();
|
|
428
|
+
if (typeof data["count"] === "number") return data["count"];
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
var zendeskOauthSetupFlow = {
|
|
432
|
+
initialState: () => ({}),
|
|
433
|
+
steps: [
|
|
434
|
+
{
|
|
435
|
+
slug: "brand",
|
|
436
|
+
type: "select",
|
|
437
|
+
question: {
|
|
438
|
+
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",
|
|
439
|
+
en: "Select the Zendesk brand to use for setup"
|
|
440
|
+
},
|
|
441
|
+
async fetchOptions(_state, rt) {
|
|
442
|
+
const brands = await listBrands(rt.config.proxyFetch);
|
|
443
|
+
const active = brands.filter((b) => b.active !== false && b.name);
|
|
444
|
+
if (active.length < 2) return [];
|
|
445
|
+
return active.map((b) => ({
|
|
446
|
+
value: String(b.subdomain ?? b.id ?? b.name),
|
|
447
|
+
label: String(b.name)
|
|
448
|
+
}));
|
|
449
|
+
},
|
|
450
|
+
applyAnswer: (state, answer) => ({ ...state, brand: answer[0] })
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
slug: "entities",
|
|
454
|
+
type: "multiSelect",
|
|
455
|
+
question: {
|
|
456
|
+
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",
|
|
457
|
+
en: "Select the entities to include in setup (multi-select allowed)"
|
|
458
|
+
},
|
|
459
|
+
async fetchOptions(_state, _rt) {
|
|
460
|
+
return ZENDESK_ENTITIES.map((e) => ({ value: e.value, label: e.label }));
|
|
461
|
+
},
|
|
462
|
+
applyAnswer: (state, answer) => ({ ...state, entities: answer })
|
|
463
|
+
}
|
|
464
|
+
],
|
|
465
|
+
async finalize(state, rt) {
|
|
466
|
+
if (!state.entities) {
|
|
467
|
+
throw new Error("Zendesk setup: incomplete state on finalize");
|
|
468
|
+
}
|
|
469
|
+
const targetEntities = await resolveSetupSelection({
|
|
470
|
+
selected: state.entities,
|
|
471
|
+
allSentinel: "__ALL__",
|
|
472
|
+
fetchAll: async () => ZENDESK_ENTITIES.map((e) => e.value),
|
|
473
|
+
limit: ZENDESK_SETUP_MAX_ENTITIES
|
|
474
|
+
});
|
|
475
|
+
const entityByValue = new Map(ZENDESK_ENTITIES.map((e) => [e.value, e]));
|
|
476
|
+
const sections = ["## Zendesk", ""];
|
|
477
|
+
if (state.brand) {
|
|
478
|
+
sections.push(`### Brand: ${state.brand}`, "");
|
|
479
|
+
}
|
|
480
|
+
sections.push("### Selected entities", "");
|
|
481
|
+
sections.push("| Entity | Count |");
|
|
482
|
+
sections.push("|--------|-------|");
|
|
483
|
+
for (const value of targetEntities) {
|
|
484
|
+
const entity = entityByValue.get(value);
|
|
485
|
+
if (!entity) {
|
|
486
|
+
sections.push(`| ${value} | _unknown_ |`);
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
const count = await fetchCount(rt.config.proxyFetch, entity.countPath);
|
|
490
|
+
sections.push(
|
|
491
|
+
`| ${entity.label} (${entity.value}) | ${count == null ? "-" : count} |`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
sections.push("");
|
|
495
|
+
return sections.join("\n");
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
|
|
312
499
|
// ../connectors/src/connectors/zendesk-oauth/parameters.ts
|
|
313
500
|
var parameters = {};
|
|
314
501
|
|
|
@@ -317,6 +504,7 @@ var tools = { request: requestTool };
|
|
|
317
504
|
var zendeskOauthConnector = new ConnectorPlugin({
|
|
318
505
|
slug: "zendesk",
|
|
319
506
|
authType: AUTH_TYPES.OAUTH,
|
|
507
|
+
skipConnectionCheckOnCreate: true,
|
|
320
508
|
name: "Zendesk",
|
|
321
509
|
description: "Connect to Zendesk Support for tickets, users, organizations, and customer service data using OAuth.",
|
|
322
510
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/7e9Q7PwV6MJRJMj543m2gl/55385fae903ccfa1599e35be9d3516aa/zendesk-icon.svg",
|
|
@@ -451,6 +639,7 @@ const data = await res.json();
|
|
|
451
639
|
\`\`\``
|
|
452
640
|
},
|
|
453
641
|
tools,
|
|
642
|
+
setup: (params, ctx, config) => runSetupFlow(zendeskOauthSetupFlow, params, ctx, config),
|
|
454
643
|
async checkConnection(_params, config) {
|
|
455
644
|
const { proxyFetch } = config;
|
|
456
645
|
try {
|
|
@@ -500,6 +689,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
500
689
|
import { getContext } from "hono/context-storage";
|
|
501
690
|
import { getCookie } from "hono/cookie";
|
|
502
691
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
692
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
503
693
|
function normalizeHeaders(input) {
|
|
504
694
|
const out = {};
|
|
505
695
|
if (!input) return out;
|
|
@@ -508,6 +698,11 @@ function normalizeHeaders(input) {
|
|
|
508
698
|
});
|
|
509
699
|
return out;
|
|
510
700
|
}
|
|
701
|
+
function extractInputUrl(input) {
|
|
702
|
+
if (typeof input === "string") return input;
|
|
703
|
+
if (input instanceof URL) return input.href;
|
|
704
|
+
return input.url;
|
|
705
|
+
}
|
|
511
706
|
function createSandboxProxyFetch(connectionId) {
|
|
512
707
|
return async (input, init) => {
|
|
513
708
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -517,10 +712,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
517
712
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
518
713
|
);
|
|
519
714
|
}
|
|
520
|
-
const originalUrl =
|
|
715
|
+
const originalUrl = extractInputUrl(input);
|
|
716
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
717
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
718
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
719
|
+
return fetch(sessionUrl, {
|
|
720
|
+
method: "POST",
|
|
721
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
722
|
+
});
|
|
723
|
+
}
|
|
521
724
|
const originalMethod = init?.method ?? "GET";
|
|
522
725
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
523
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
524
726
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
525
727
|
return fetch(proxyUrl, {
|
|
526
728
|
method: "POST",
|
|
@@ -546,10 +748,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
546
748
|
}
|
|
547
749
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
548
750
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
751
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
549
752
|
return async (input, init) => {
|
|
550
|
-
const originalUrl =
|
|
551
|
-
const originalMethod = init?.method ?? "GET";
|
|
552
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
753
|
+
const originalUrl = extractInputUrl(input);
|
|
553
754
|
const c = getContext();
|
|
554
755
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
555
756
|
if (!appSession) {
|
|
@@ -557,6 +758,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
557
758
|
"No authentication method available for connection proxy."
|
|
558
759
|
);
|
|
559
760
|
}
|
|
761
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
762
|
+
return fetch(sessionUrl, {
|
|
763
|
+
method: "POST",
|
|
764
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
const originalMethod = init?.method ?? "GET";
|
|
768
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
560
769
|
return fetch(proxyUrl, {
|
|
561
770
|
method: "POST",
|
|
562
771
|
headers: {
|