@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
package/dist/connectors/dbt.js
CHANGED
|
@@ -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/dbt/parameters.ts
|
|
57
|
+
init_parameter_definition();
|
|
46
58
|
var parameters = {
|
|
47
59
|
host: new ParameterDefinition({
|
|
48
60
|
slug: "host",
|
|
@@ -376,6 +388,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
376
388
|
tools;
|
|
377
389
|
query;
|
|
378
390
|
checkConnection;
|
|
391
|
+
/**
|
|
392
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
393
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
394
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
395
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
396
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
397
|
+
*/
|
|
398
|
+
setup;
|
|
399
|
+
/**
|
|
400
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
401
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
402
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
403
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
404
|
+
*
|
|
405
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
406
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
407
|
+
* connectionId, which doesn't exist until the row is saved
|
|
408
|
+
*
|
|
409
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
410
|
+
* the default verify-on-create behavior without opt-in.
|
|
411
|
+
*/
|
|
412
|
+
skipConnectionCheckOnCreate;
|
|
379
413
|
constructor(config) {
|
|
380
414
|
this.slug = config.slug;
|
|
381
415
|
this.authType = config.authType;
|
|
@@ -392,6 +426,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
392
426
|
this.tools = config.tools;
|
|
393
427
|
this.query = config.query;
|
|
394
428
|
this.checkConnection = config.checkConnection;
|
|
429
|
+
this.setup = config.setup;
|
|
430
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
395
431
|
}
|
|
396
432
|
get connectorKey() {
|
|
397
433
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -456,6 +492,76 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
456
492
|
}
|
|
457
493
|
};
|
|
458
494
|
|
|
495
|
+
// ../connectors/src/setup-flow.ts
|
|
496
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
497
|
+
const runtime = {
|
|
498
|
+
params,
|
|
499
|
+
language: ctx.language,
|
|
500
|
+
config
|
|
501
|
+
};
|
|
502
|
+
let state = flow.initialState();
|
|
503
|
+
let answerIdx = 0;
|
|
504
|
+
const pendingParameterUpdates = [];
|
|
505
|
+
for (const step of flow.steps) {
|
|
506
|
+
const ans = ctx.answers[answerIdx];
|
|
507
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
508
|
+
state = step.applyAnswer(state, ans.answer);
|
|
509
|
+
if (step.toParameterUpdates) {
|
|
510
|
+
pendingParameterUpdates.push(...step.toParameterUpdates(state));
|
|
511
|
+
}
|
|
512
|
+
answerIdx += 1;
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
|
|
516
|
+
if (step.type === "text") {
|
|
517
|
+
if (step.fetchOptions) {
|
|
518
|
+
const options2 = await step.fetchOptions(state, runtime);
|
|
519
|
+
if (options2.length === 0) {
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
type: "nextQuestion",
|
|
525
|
+
questionSlug: step.slug,
|
|
526
|
+
question: step.question[ctx.language],
|
|
527
|
+
questionType: "text",
|
|
528
|
+
allowFreeText: resolvedAllowFreeText,
|
|
529
|
+
...pendingParameterUpdates.length > 0 && {
|
|
530
|
+
parameterUpdates: pendingParameterUpdates
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
535
|
+
if (options.length === 0) {
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
type: "nextQuestion",
|
|
540
|
+
questionSlug: step.slug,
|
|
541
|
+
question: step.question[ctx.language],
|
|
542
|
+
questionType: step.type,
|
|
543
|
+
options,
|
|
544
|
+
allowFreeText: resolvedAllowFreeText,
|
|
545
|
+
...pendingParameterUpdates.length > 0 && {
|
|
546
|
+
parameterUpdates: pendingParameterUpdates
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
551
|
+
return {
|
|
552
|
+
type: "fulfilled",
|
|
553
|
+
dataInvestigationResult,
|
|
554
|
+
...pendingParameterUpdates.length > 0 && {
|
|
555
|
+
parameterUpdates: pendingParameterUpdates
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
async function resolveSetupSelection(params) {
|
|
560
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
561
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
562
|
+
return resolved.slice(0, limit);
|
|
563
|
+
}
|
|
564
|
+
|
|
459
565
|
// ../connectors/src/auth-types.ts
|
|
460
566
|
var AUTH_TYPES = {
|
|
461
567
|
OAUTH: "oauth",
|
|
@@ -478,6 +584,132 @@ var dbtOnboarding = new ConnectorOnboarding({
|
|
|
478
584
|
}
|
|
479
585
|
});
|
|
480
586
|
|
|
587
|
+
// ../connectors/src/connectors/dbt/utils.ts
|
|
588
|
+
function adminApiBase(host) {
|
|
589
|
+
const trimmed = host.replace(/\/+$/, "");
|
|
590
|
+
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
|
|
591
|
+
return trimmed;
|
|
592
|
+
}
|
|
593
|
+
return `https://${trimmed}`;
|
|
594
|
+
}
|
|
595
|
+
function adminApiFetch(params, path2, init) {
|
|
596
|
+
const host = params[parameters.host.slug];
|
|
597
|
+
const token = params[parameters.token.slug];
|
|
598
|
+
if (!host) {
|
|
599
|
+
throw new Error(`dbt: missing required parameter: ${parameters.host.slug}`);
|
|
600
|
+
}
|
|
601
|
+
if (!token) {
|
|
602
|
+
throw new Error(`dbt: missing required parameter: ${parameters.token.slug}`);
|
|
603
|
+
}
|
|
604
|
+
const trimmedPath = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
605
|
+
const headers = new Headers(init?.headers);
|
|
606
|
+
headers.set("Authorization", `Token ${token}`);
|
|
607
|
+
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
608
|
+
return fetch(`${adminApiBase(host)}${trimmedPath}`, { ...init, headers });
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// ../connectors/src/connectors/dbt/setup-flow.ts
|
|
612
|
+
var ALL_PROJECTS = "__ALL_PROJECTS__";
|
|
613
|
+
var DBT_SETUP_MAX_PROJECTS = 10;
|
|
614
|
+
async function listAllProjects(params) {
|
|
615
|
+
const accountId = params[parameters.accountId.slug];
|
|
616
|
+
if (!accountId) {
|
|
617
|
+
throw new Error(
|
|
618
|
+
`dbt: missing required parameter: ${parameters.accountId.slug}`
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
const all = [];
|
|
622
|
+
const limit = 100;
|
|
623
|
+
let offset = 0;
|
|
624
|
+
while (all.length < 500) {
|
|
625
|
+
const res = await adminApiFetch(
|
|
626
|
+
params,
|
|
627
|
+
`/api/v2/accounts/${encodeURIComponent(accountId)}/projects/?limit=${limit}&offset=${offset}`
|
|
628
|
+
);
|
|
629
|
+
if (!res.ok) {
|
|
630
|
+
const body = await res.text().catch(() => res.statusText);
|
|
631
|
+
throw new Error(`dbt: listProjects failed (${res.status}): ${body}`);
|
|
632
|
+
}
|
|
633
|
+
const data = await res.json();
|
|
634
|
+
const batch = data.data ?? [];
|
|
635
|
+
all.push(...batch);
|
|
636
|
+
const total = data.extra?.pagination?.total_count ?? all.length;
|
|
637
|
+
if (!batch.length || all.length >= total) break;
|
|
638
|
+
offset += batch.length;
|
|
639
|
+
}
|
|
640
|
+
return all;
|
|
641
|
+
}
|
|
642
|
+
function repoLabel(p) {
|
|
643
|
+
const repo = p.repository;
|
|
644
|
+
if (!repo) return "-";
|
|
645
|
+
if (repo.remote_url) return repo.remote_url;
|
|
646
|
+
if (repo.name) return repo.name;
|
|
647
|
+
return "-";
|
|
648
|
+
}
|
|
649
|
+
var dbtSetupFlow = {
|
|
650
|
+
initialState: () => ({}),
|
|
651
|
+
steps: [
|
|
652
|
+
{
|
|
653
|
+
slug: "projects",
|
|
654
|
+
type: "multiSelect",
|
|
655
|
+
question: {
|
|
656
|
+
ja: "\u5BFE\u8C61\u306E dbt \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
657
|
+
en: "Select target dbt projects (multi-select allowed)"
|
|
658
|
+
},
|
|
659
|
+
async fetchOptions(_state, rt) {
|
|
660
|
+
const projects = await listAllProjects(rt.params);
|
|
661
|
+
const options = projects.filter((p) => p.id != null && p.name).map((p) => ({ value: String(p.id), label: p.name }));
|
|
662
|
+
if (options.length === 0) return [];
|
|
663
|
+
return [
|
|
664
|
+
{
|
|
665
|
+
value: ALL_PROJECTS,
|
|
666
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8" : "All projects"
|
|
667
|
+
},
|
|
668
|
+
...options
|
|
669
|
+
];
|
|
670
|
+
},
|
|
671
|
+
applyAnswer: (state, answer) => ({ ...state, projects: answer })
|
|
672
|
+
}
|
|
673
|
+
],
|
|
674
|
+
async finalize(state, rt) {
|
|
675
|
+
if (!state.projects) {
|
|
676
|
+
throw new Error("dbt setup: incomplete state on finalize");
|
|
677
|
+
}
|
|
678
|
+
const allProjects = await listAllProjects(rt.params);
|
|
679
|
+
const byId = new Map(allProjects.map((p) => [String(p.id), p]));
|
|
680
|
+
const targetIds = await resolveSetupSelection({
|
|
681
|
+
selected: state.projects,
|
|
682
|
+
allSentinel: ALL_PROJECTS,
|
|
683
|
+
fetchAll: async () => allProjects.map((p) => String(p.id)).filter((id) => id),
|
|
684
|
+
limit: DBT_SETUP_MAX_PROJECTS
|
|
685
|
+
});
|
|
686
|
+
const sections = ["## dbt Cloud", ""];
|
|
687
|
+
const accountId = rt.params[parameters.accountId.slug];
|
|
688
|
+
const prodEnvId = rt.params[parameters.prodEnvId.slug];
|
|
689
|
+
if (accountId) sections.push(`- Account: \`${accountId}\``);
|
|
690
|
+
if (prodEnvId) sections.push(`- Prod environment: \`${prodEnvId}\``);
|
|
691
|
+
sections.push("");
|
|
692
|
+
if (!targetIds.length) {
|
|
693
|
+
sections.push("_No projects selected._", "");
|
|
694
|
+
return sections.join("\n");
|
|
695
|
+
}
|
|
696
|
+
sections.push("| Project | Repository |");
|
|
697
|
+
sections.push("|---------|------------|");
|
|
698
|
+
for (const id of targetIds) {
|
|
699
|
+
const p = byId.get(id);
|
|
700
|
+
if (!p) {
|
|
701
|
+
sections.push(`| ${id} | - |`);
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
const name = (p.name ?? String(p.id)).replace(/\|/g, "\\|");
|
|
705
|
+
const repo = repoLabel(p).replace(/\|/g, "\\|");
|
|
706
|
+
sections.push(`| ${name} | ${repo} |`);
|
|
707
|
+
}
|
|
708
|
+
sections.push("");
|
|
709
|
+
return sections.join("\n");
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
|
|
481
713
|
// ../connectors/src/connectors/dbt/tools/request.ts
|
|
482
714
|
import { z } from "zod";
|
|
483
715
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
@@ -795,7 +1027,48 @@ query($environmentId: BigInt!, $uniqueIds: [String!]!) {
|
|
|
795
1027
|
- \`ancestors\` / \`children\` \u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u4F7F\u7528\u3057\u3066\u95A2\u4FC2\u3092\u30C8\u30E9\u30D0\u30FC\u30B9\u3057\u307E\u3059
|
|
796
1028
|
- node\u5185\u3067 \`ancestors { uniqueId name }\` \u307E\u305F\u306F \`children { uniqueId name }\` \u3092\u53D6\u5F97\u3057\u307E\u3059`
|
|
797
1029
|
},
|
|
798
|
-
tools
|
|
1030
|
+
tools,
|
|
1031
|
+
setup: (params, ctx, config) => runSetupFlow(dbtSetupFlow, params, ctx, config),
|
|
1032
|
+
async checkConnection(params, _config) {
|
|
1033
|
+
const host = params[parameters.host.slug];
|
|
1034
|
+
const token = params[parameters.token.slug];
|
|
1035
|
+
if (!host || !token) {
|
|
1036
|
+
return {
|
|
1037
|
+
success: false,
|
|
1038
|
+
error: `Missing required parameters: ${parameters.host.slug} and ${parameters.token.slug}`
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
const normalizedHost = host.trim().replace(/\/+$/, "");
|
|
1042
|
+
const hostWithScheme = /^https?:\/\//i.test(normalizedHost) ? normalizedHost : `https://${normalizedHost}`;
|
|
1043
|
+
try {
|
|
1044
|
+
const res = await fetch(`${hostWithScheme}/api/v2/accounts/`, {
|
|
1045
|
+
method: "GET",
|
|
1046
|
+
headers: {
|
|
1047
|
+
Authorization: `Token ${token}`,
|
|
1048
|
+
Accept: "application/json"
|
|
1049
|
+
}
|
|
1050
|
+
});
|
|
1051
|
+
if (!res.ok) {
|
|
1052
|
+
if (res.status === 401) {
|
|
1053
|
+
return {
|
|
1054
|
+
success: false,
|
|
1055
|
+
error: "dbt Cloud API failed: HTTP 401 Unauthorized \u2014 invalid token"
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
1059
|
+
return {
|
|
1060
|
+
success: false,
|
|
1061
|
+
error: `dbt Cloud API failed: HTTP ${res.status} ${errorText}`
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
return { success: true };
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
return {
|
|
1067
|
+
success: false,
|
|
1068
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
799
1072
|
});
|
|
800
1073
|
|
|
801
1074
|
// src/connectors/create-connector-sdk.ts
|
|
@@ -824,6 +1097,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
824
1097
|
import { getContext } from "hono/context-storage";
|
|
825
1098
|
import { getCookie } from "hono/cookie";
|
|
826
1099
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
1100
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
827
1101
|
function normalizeHeaders(input) {
|
|
828
1102
|
const out = {};
|
|
829
1103
|
if (!input) return out;
|
|
@@ -832,6 +1106,11 @@ function normalizeHeaders(input) {
|
|
|
832
1106
|
});
|
|
833
1107
|
return out;
|
|
834
1108
|
}
|
|
1109
|
+
function extractInputUrl(input) {
|
|
1110
|
+
if (typeof input === "string") return input;
|
|
1111
|
+
if (input instanceof URL) return input.href;
|
|
1112
|
+
return input.url;
|
|
1113
|
+
}
|
|
835
1114
|
function createSandboxProxyFetch(connectionId) {
|
|
836
1115
|
return async (input, init) => {
|
|
837
1116
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -841,10 +1120,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
841
1120
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
842
1121
|
);
|
|
843
1122
|
}
|
|
844
|
-
const originalUrl =
|
|
1123
|
+
const originalUrl = extractInputUrl(input);
|
|
1124
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
1125
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1126
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
1127
|
+
return fetch(sessionUrl, {
|
|
1128
|
+
method: "POST",
|
|
1129
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
845
1132
|
const originalMethod = init?.method ?? "GET";
|
|
846
1133
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
847
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
848
1134
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
849
1135
|
return fetch(proxyUrl, {
|
|
850
1136
|
method: "POST",
|
|
@@ -870,10 +1156,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
870
1156
|
}
|
|
871
1157
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
872
1158
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1159
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
873
1160
|
return async (input, init) => {
|
|
874
|
-
const originalUrl =
|
|
875
|
-
const originalMethod = init?.method ?? "GET";
|
|
876
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
1161
|
+
const originalUrl = extractInputUrl(input);
|
|
877
1162
|
const c = getContext();
|
|
878
1163
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
879
1164
|
if (!appSession) {
|
|
@@ -881,6 +1166,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
881
1166
|
"No authentication method available for connection proxy."
|
|
882
1167
|
);
|
|
883
1168
|
}
|
|
1169
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1170
|
+
return fetch(sessionUrl, {
|
|
1171
|
+
method: "POST",
|
|
1172
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
const originalMethod = init?.method ?? "GET";
|
|
1176
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
884
1177
|
return fetch(proxyUrl, {
|
|
885
1178
|
method: "POST",
|
|
886
1179
|
headers: {
|