@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
|
@@ -1,48 +1,60 @@
|
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
+
var __esm = (fn, res) => function __init() {
|
|
3
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
4
|
+
};
|
|
5
|
+
|
|
1
6
|
// ../connectors/src/parameter-definition.ts
|
|
2
|
-
var ParameterDefinition
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
7
|
+
var ParameterDefinition;
|
|
8
|
+
var init_parameter_definition = __esm({
|
|
9
|
+
"../connectors/src/parameter-definition.ts"() {
|
|
10
|
+
"use strict";
|
|
11
|
+
ParameterDefinition = class {
|
|
12
|
+
slug;
|
|
13
|
+
name;
|
|
14
|
+
description;
|
|
15
|
+
envVarBaseKey;
|
|
16
|
+
type;
|
|
17
|
+
secret;
|
|
18
|
+
required;
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.slug = config.slug;
|
|
21
|
+
this.name = config.name;
|
|
22
|
+
this.description = config.description;
|
|
23
|
+
this.envVarBaseKey = config.envVarBaseKey;
|
|
24
|
+
this.type = config.type;
|
|
25
|
+
this.secret = config.secret;
|
|
26
|
+
this.required = config.required;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the parameter value from a ConnectorConnectionObject.
|
|
30
|
+
*/
|
|
31
|
+
getValue(connection2) {
|
|
32
|
+
const param = connection2.parameters.find(
|
|
33
|
+
(p) => p.parameterSlug === this.slug
|
|
34
|
+
);
|
|
35
|
+
if (!param || param.value == null) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return param.value;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Try to get the parameter value. Returns undefined if not found (for optional params).
|
|
44
|
+
*/
|
|
45
|
+
tryGetValue(connection2) {
|
|
46
|
+
const param = connection2.parameters.find(
|
|
47
|
+
(p) => p.parameterSlug === this.slug
|
|
48
|
+
);
|
|
49
|
+
if (!param || param.value == null) return void 0;
|
|
50
|
+
return param.value;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
42
53
|
}
|
|
43
|
-
};
|
|
54
|
+
});
|
|
44
55
|
|
|
45
56
|
// ../connectors/src/connectors/mixpanel/parameters.ts
|
|
57
|
+
init_parameter_definition();
|
|
46
58
|
var parameters = {
|
|
47
59
|
serviceAccountUsername: new ParameterDefinition({
|
|
48
60
|
slug: "service-account-username",
|
|
@@ -273,6 +285,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
273
285
|
tools;
|
|
274
286
|
query;
|
|
275
287
|
checkConnection;
|
|
288
|
+
/**
|
|
289
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
290
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
291
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
292
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
293
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
294
|
+
*/
|
|
295
|
+
setup;
|
|
296
|
+
/**
|
|
297
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
298
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
299
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
300
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
301
|
+
*
|
|
302
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
303
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
304
|
+
* connectionId, which doesn't exist until the row is saved
|
|
305
|
+
*
|
|
306
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
307
|
+
* the default verify-on-create behavior without opt-in.
|
|
308
|
+
*/
|
|
309
|
+
skipConnectionCheckOnCreate;
|
|
276
310
|
constructor(config) {
|
|
277
311
|
this.slug = config.slug;
|
|
278
312
|
this.authType = config.authType;
|
|
@@ -289,6 +323,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
289
323
|
this.tools = config.tools;
|
|
290
324
|
this.query = config.query;
|
|
291
325
|
this.checkConnection = config.checkConnection;
|
|
326
|
+
this.setup = config.setup;
|
|
327
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
292
328
|
}
|
|
293
329
|
get connectorKey() {
|
|
294
330
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -353,6 +389,71 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
353
389
|
}
|
|
354
390
|
};
|
|
355
391
|
|
|
392
|
+
// ../connectors/src/setup-flow.ts
|
|
393
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
394
|
+
const runtime = {
|
|
395
|
+
params,
|
|
396
|
+
language: ctx.language,
|
|
397
|
+
config
|
|
398
|
+
};
|
|
399
|
+
let state = flow.initialState();
|
|
400
|
+
let answerIdx = 0;
|
|
401
|
+
const pendingParameterUpdates = [];
|
|
402
|
+
for (const step of flow.steps) {
|
|
403
|
+
const ans = ctx.answers[answerIdx];
|
|
404
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
405
|
+
state = step.applyAnswer(state, ans.answer);
|
|
406
|
+
if (step.toParameterUpdates) {
|
|
407
|
+
pendingParameterUpdates.push(...step.toParameterUpdates(state));
|
|
408
|
+
}
|
|
409
|
+
answerIdx += 1;
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
|
|
413
|
+
if (step.type === "text") {
|
|
414
|
+
if (step.fetchOptions) {
|
|
415
|
+
const options2 = await step.fetchOptions(state, runtime);
|
|
416
|
+
if (options2.length === 0) {
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return {
|
|
421
|
+
type: "nextQuestion",
|
|
422
|
+
questionSlug: step.slug,
|
|
423
|
+
question: step.question[ctx.language],
|
|
424
|
+
questionType: "text",
|
|
425
|
+
allowFreeText: resolvedAllowFreeText,
|
|
426
|
+
...pendingParameterUpdates.length > 0 && {
|
|
427
|
+
parameterUpdates: pendingParameterUpdates
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
432
|
+
if (options.length === 0) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
type: "nextQuestion",
|
|
437
|
+
questionSlug: step.slug,
|
|
438
|
+
question: step.question[ctx.language],
|
|
439
|
+
questionType: step.type,
|
|
440
|
+
options,
|
|
441
|
+
allowFreeText: resolvedAllowFreeText,
|
|
442
|
+
...pendingParameterUpdates.length > 0 && {
|
|
443
|
+
parameterUpdates: pendingParameterUpdates
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
448
|
+
return {
|
|
449
|
+
type: "fulfilled",
|
|
450
|
+
dataInvestigationResult,
|
|
451
|
+
...pendingParameterUpdates.length > 0 && {
|
|
452
|
+
parameterUpdates: pendingParameterUpdates
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
356
457
|
// ../connectors/src/auth-types.ts
|
|
357
458
|
var AUTH_TYPES = {
|
|
358
459
|
OAUTH: "oauth",
|
|
@@ -383,6 +484,137 @@ NOTE: The Query API endpoints (insights, funnels, retention) require a bookmark_
|
|
|
383
484
|
}
|
|
384
485
|
});
|
|
385
486
|
|
|
487
|
+
// ../connectors/src/connectors/mixpanel/utils.ts
|
|
488
|
+
function getQueryBaseUrl(params) {
|
|
489
|
+
const region = params[parameters.region.slug];
|
|
490
|
+
if (region === "eu") return "https://eu.mixpanel.com/api";
|
|
491
|
+
if (region === "in") return "https://in.mixpanel.com/api";
|
|
492
|
+
return "https://mixpanel.com/api";
|
|
493
|
+
}
|
|
494
|
+
async function apiFetch(params, path2, init) {
|
|
495
|
+
const username = params[parameters.serviceAccountUsername.slug];
|
|
496
|
+
const secret = params[parameters.serviceAccountSecret.slug];
|
|
497
|
+
const projectId = params[parameters.projectId.slug];
|
|
498
|
+
if (!username || !secret || !projectId) {
|
|
499
|
+
throw new Error(
|
|
500
|
+
"mixpanel: missing required parameters: service-account-username, service-account-secret, project-id"
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
const base = getQueryBaseUrl(params);
|
|
504
|
+
const url = new URL(`${base}${path2.startsWith("/") ? "" : "/"}${path2}`);
|
|
505
|
+
if (!url.searchParams.has("project_id")) {
|
|
506
|
+
url.searchParams.set("project_id", projectId);
|
|
507
|
+
}
|
|
508
|
+
const headers = new Headers(init?.headers);
|
|
509
|
+
headers.set("Authorization", `Basic ${btoa(`${username}:${secret}`)}`);
|
|
510
|
+
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
511
|
+
return fetch(url.toString(), { ...init, headers });
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// ../connectors/src/connectors/mixpanel/setup-flow.ts
|
|
515
|
+
var MIXPANEL_SETUP_MAX_ENTITIES = 10;
|
|
516
|
+
var MIXPANEL_SETUP_MAX_EVENTS = 50;
|
|
517
|
+
var ENTITY_LABELS = {
|
|
518
|
+
events: { en: "Events", ja: "Events (\u30A4\u30D9\u30F3\u30C8)" },
|
|
519
|
+
userProperties: {
|
|
520
|
+
en: "User properties",
|
|
521
|
+
ja: "User properties (\u30E6\u30FC\u30B6\u30FC\u30D7\u30ED\u30D1\u30C6\u30A3)"
|
|
522
|
+
},
|
|
523
|
+
cohorts: { en: "Cohorts", ja: "Cohorts (\u30B3\u30DB\u30FC\u30C8)" },
|
|
524
|
+
funnels: { en: "Funnels", ja: "Funnels (\u30D5\u30A1\u30CD\u30EB)" },
|
|
525
|
+
retentionReports: {
|
|
526
|
+
en: "Retention reports",
|
|
527
|
+
ja: "Retention reports (\u30EA\u30C6\u30F3\u30B7\u30E7\u30F3\u30EC\u30DD\u30FC\u30C8)"
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
var ENTITY_DESCRIPTIONS = {
|
|
531
|
+
events: {
|
|
532
|
+
en: "Tracked event names.",
|
|
533
|
+
ja: "\u8FFD\u8DE1\u3055\u308C\u3066\u3044\u308B\u30A4\u30D9\u30F3\u30C8\u540D\u3002"
|
|
534
|
+
},
|
|
535
|
+
userProperties: {
|
|
536
|
+
en: "User-level properties available for segmentation.",
|
|
537
|
+
ja: "\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u4F7F\u3048\u308B\u30E6\u30FC\u30B6\u30FC\u30EC\u30D9\u30EB\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3002"
|
|
538
|
+
},
|
|
539
|
+
cohorts: {
|
|
540
|
+
en: "Saved user cohorts.",
|
|
541
|
+
ja: "\u4FDD\u5B58\u6E08\u307F\u306E\u30E6\u30FC\u30B6\u30FC\u30B3\u30DB\u30FC\u30C8\u3002"
|
|
542
|
+
},
|
|
543
|
+
funnels: {
|
|
544
|
+
en: "Saved funnel definitions.",
|
|
545
|
+
ja: "\u4FDD\u5B58\u6E08\u307F\u306E\u30D5\u30A1\u30CD\u30EB\u5B9A\u7FA9\u3002"
|
|
546
|
+
},
|
|
547
|
+
retentionReports: {
|
|
548
|
+
en: "Saved retention reports.",
|
|
549
|
+
ja: "\u4FDD\u5B58\u6E08\u307F\u306E\u30EA\u30C6\u30F3\u30B7\u30E7\u30F3\u30EC\u30DD\u30FC\u30C8\u3002"
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
var ENTITY_VALUES = [
|
|
553
|
+
"events",
|
|
554
|
+
"userProperties",
|
|
555
|
+
"cohorts",
|
|
556
|
+
"funnels",
|
|
557
|
+
"retentionReports"
|
|
558
|
+
];
|
|
559
|
+
async function fetchEventNames(params) {
|
|
560
|
+
try {
|
|
561
|
+
const res = await apiFetch(params, "/2.0/events/names?type=general");
|
|
562
|
+
if (!res.ok) return [];
|
|
563
|
+
const data = await res.json();
|
|
564
|
+
if (!Array.isArray(data)) return [];
|
|
565
|
+
return data.filter((v) => typeof v === "string");
|
|
566
|
+
} catch {
|
|
567
|
+
return [];
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
var mixpanelSetupFlow = {
|
|
571
|
+
initialState: () => ({}),
|
|
572
|
+
steps: [
|
|
573
|
+
{
|
|
574
|
+
slug: "entities",
|
|
575
|
+
type: "multiSelect",
|
|
576
|
+
question: {
|
|
577
|
+
ja: "\u5BFE\u8C61\u306E\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
578
|
+
en: "Select target entities (multi-select allowed)"
|
|
579
|
+
},
|
|
580
|
+
async fetchOptions(_state, rt) {
|
|
581
|
+
return ENTITY_VALUES.map((value) => ({
|
|
582
|
+
value,
|
|
583
|
+
label: ENTITY_LABELS[value][rt.language]
|
|
584
|
+
}));
|
|
585
|
+
},
|
|
586
|
+
applyAnswer: (state, answer) => ({ ...state, entities: answer })
|
|
587
|
+
}
|
|
588
|
+
],
|
|
589
|
+
async finalize(state, rt) {
|
|
590
|
+
if (!state.entities) {
|
|
591
|
+
throw new Error("Mixpanel setup: incomplete state on finalize");
|
|
592
|
+
}
|
|
593
|
+
const selected = state.entities.filter(
|
|
594
|
+
(e) => ENTITY_VALUES.includes(e)
|
|
595
|
+
).slice(0, MIXPANEL_SETUP_MAX_ENTITIES);
|
|
596
|
+
const sections = ["## Mixpanel", ""];
|
|
597
|
+
for (const entity of selected) {
|
|
598
|
+
sections.push(`### ${ENTITY_LABELS[entity].en}`, "");
|
|
599
|
+
sections.push(ENTITY_DESCRIPTIONS[entity][rt.language], "");
|
|
600
|
+
if (entity === "events") {
|
|
601
|
+
const names = (await fetchEventNames(rt.params)).slice(
|
|
602
|
+
0,
|
|
603
|
+
MIXPANEL_SETUP_MAX_EVENTS
|
|
604
|
+
);
|
|
605
|
+
if (names.length > 0) {
|
|
606
|
+
sections.push("Event names:", "");
|
|
607
|
+
for (const name of names) {
|
|
608
|
+
sections.push(`- ${name}`);
|
|
609
|
+
}
|
|
610
|
+
sections.push("");
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return sections.join("\n");
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
|
|
386
618
|
// ../connectors/src/connectors/mixpanel/tools/request.ts
|
|
387
619
|
import { z } from "zod";
|
|
388
620
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
@@ -640,7 +872,46 @@ export default async function handler(c: Context) {
|
|
|
640
872
|
|
|
641
873
|
\u91CD\u8981: Insights\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306F\u3001Mixpanel UI\u306E\u65E2\u5B58\u30EC\u30DD\u30FC\u30C8\u306Ebookmark_id\u304C\u5FC5\u8981\u3067\u3059\u3002\u30A2\u30C9\u30DB\u30C3\u30AF\u306A\u30A4\u30D9\u30F3\u30C8\u5206\u6790\u306B\u306F\u3001Export API\u3067\u751F\u30A4\u30D9\u30F3\u30C8\u3092\u53D6\u5F97\u3057\u3001\u30B3\u30FC\u30C9\u4E0A\u3067\u96C6\u8A08\u3057\u3066\u304F\u3060\u3055\u3044\u3002Export API\u304C\u6700\u3082\u67D4\u8EDF\u3067\u5E83\u304F\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3067\u3059\u3002`
|
|
642
874
|
},
|
|
643
|
-
tools
|
|
875
|
+
tools,
|
|
876
|
+
setup: (params, ctx, config) => runSetupFlow(mixpanelSetupFlow, params, ctx, config),
|
|
877
|
+
async checkConnection(params, _config) {
|
|
878
|
+
const username = params[parameters.serviceAccountUsername.slug];
|
|
879
|
+
const secret = params[parameters.serviceAccountSecret.slug];
|
|
880
|
+
const projectId = params[parameters.projectId.slug];
|
|
881
|
+
if (!username || !secret || !projectId) {
|
|
882
|
+
return {
|
|
883
|
+
success: false,
|
|
884
|
+
error: "Missing required parameters: service-account-username, service-account-secret, and project-id"
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
const region = params[parameters.region.slug];
|
|
888
|
+
const queryBase = region === "eu" ? "https://eu.mixpanel.com/api/query" : region === "in" ? "https://in.mixpanel.com/api/query" : "https://mixpanel.com/api/query";
|
|
889
|
+
try {
|
|
890
|
+
const res = await fetch(
|
|
891
|
+
`${queryBase}/events/names?project_id=${encodeURIComponent(projectId)}&type=general&limit=1`,
|
|
892
|
+
{
|
|
893
|
+
method: "GET",
|
|
894
|
+
headers: {
|
|
895
|
+
Authorization: `Basic ${btoa(`${username}:${secret}`)}`,
|
|
896
|
+
Accept: "application/json"
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
);
|
|
900
|
+
if (!res.ok) {
|
|
901
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
902
|
+
return {
|
|
903
|
+
success: false,
|
|
904
|
+
error: `Mixpanel API failed: HTTP ${res.status} ${errorText}`
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
return { success: true };
|
|
908
|
+
} catch (error) {
|
|
909
|
+
return {
|
|
910
|
+
success: false,
|
|
911
|
+
error: error instanceof Error ? error.message : String(error)
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
}
|
|
644
915
|
});
|
|
645
916
|
|
|
646
917
|
// src/connectors/create-connector-sdk.ts
|
|
@@ -669,6 +940,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
669
940
|
import { getContext } from "hono/context-storage";
|
|
670
941
|
import { getCookie } from "hono/cookie";
|
|
671
942
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
943
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
672
944
|
function normalizeHeaders(input) {
|
|
673
945
|
const out = {};
|
|
674
946
|
if (!input) return out;
|
|
@@ -677,6 +949,11 @@ function normalizeHeaders(input) {
|
|
|
677
949
|
});
|
|
678
950
|
return out;
|
|
679
951
|
}
|
|
952
|
+
function extractInputUrl(input) {
|
|
953
|
+
if (typeof input === "string") return input;
|
|
954
|
+
if (input instanceof URL) return input.href;
|
|
955
|
+
return input.url;
|
|
956
|
+
}
|
|
680
957
|
function createSandboxProxyFetch(connectionId) {
|
|
681
958
|
return async (input, init) => {
|
|
682
959
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -686,10 +963,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
686
963
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
687
964
|
);
|
|
688
965
|
}
|
|
689
|
-
const originalUrl =
|
|
966
|
+
const originalUrl = extractInputUrl(input);
|
|
967
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
968
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
969
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
970
|
+
return fetch(sessionUrl, {
|
|
971
|
+
method: "POST",
|
|
972
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
973
|
+
});
|
|
974
|
+
}
|
|
690
975
|
const originalMethod = init?.method ?? "GET";
|
|
691
976
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
692
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
693
977
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
694
978
|
return fetch(proxyUrl, {
|
|
695
979
|
method: "POST",
|
|
@@ -715,10 +999,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
715
999
|
}
|
|
716
1000
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
717
1001
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1002
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
718
1003
|
return async (input, init) => {
|
|
719
|
-
const originalUrl =
|
|
720
|
-
const originalMethod = init?.method ?? "GET";
|
|
721
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
1004
|
+
const originalUrl = extractInputUrl(input);
|
|
722
1005
|
const c = getContext();
|
|
723
1006
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
724
1007
|
if (!appSession) {
|
|
@@ -726,6 +1009,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
726
1009
|
"No authentication method available for connection proxy."
|
|
727
1010
|
);
|
|
728
1011
|
}
|
|
1012
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1013
|
+
return fetch(sessionUrl, {
|
|
1014
|
+
method: "POST",
|
|
1015
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
const originalMethod = init?.method ?? "GET";
|
|
1019
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
729
1020
|
return fetch(proxyUrl, {
|
|
730
1021
|
method: "POST",
|
|
731
1022
|
headers: {
|