@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
|
@@ -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/grafana/parameters.ts
|
|
57
|
+
init_parameter_definition();
|
|
46
58
|
var parameters = {
|
|
47
59
|
url: new ParameterDefinition({
|
|
48
60
|
slug: "url",
|
|
@@ -83,7 +95,7 @@ function createClient(params) {
|
|
|
83
95
|
headers.set("Accept", "application/json");
|
|
84
96
|
return fetch(url, { ...init, headers });
|
|
85
97
|
}
|
|
86
|
-
async function
|
|
98
|
+
async function listDatasources2() {
|
|
87
99
|
const response = await request("/api/datasources");
|
|
88
100
|
if (!response.ok) {
|
|
89
101
|
const body = await response.text();
|
|
@@ -155,7 +167,7 @@ function createClient(params) {
|
|
|
155
167
|
}
|
|
156
168
|
return {
|
|
157
169
|
request,
|
|
158
|
-
listDatasources,
|
|
170
|
+
listDatasources: listDatasources2,
|
|
159
171
|
getDatasource,
|
|
160
172
|
queryDatasource,
|
|
161
173
|
searchDashboards,
|
|
@@ -222,6 +234,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
222
234
|
tools;
|
|
223
235
|
query;
|
|
224
236
|
checkConnection;
|
|
237
|
+
/**
|
|
238
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
239
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
240
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
241
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
242
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
243
|
+
*/
|
|
244
|
+
setup;
|
|
245
|
+
/**
|
|
246
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
247
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
248
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
249
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
250
|
+
*
|
|
251
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
252
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
253
|
+
* connectionId, which doesn't exist until the row is saved
|
|
254
|
+
*
|
|
255
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
256
|
+
* the default verify-on-create behavior without opt-in.
|
|
257
|
+
*/
|
|
258
|
+
skipConnectionCheckOnCreate;
|
|
225
259
|
constructor(config) {
|
|
226
260
|
this.slug = config.slug;
|
|
227
261
|
this.authType = config.authType;
|
|
@@ -238,6 +272,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
238
272
|
this.tools = config.tools;
|
|
239
273
|
this.query = config.query;
|
|
240
274
|
this.checkConnection = config.checkConnection;
|
|
275
|
+
this.setup = config.setup;
|
|
276
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
241
277
|
}
|
|
242
278
|
get connectorKey() {
|
|
243
279
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -302,6 +338,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
302
338
|
}
|
|
303
339
|
};
|
|
304
340
|
|
|
341
|
+
// ../connectors/src/setup-flow.ts
|
|
342
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
343
|
+
const runtime = {
|
|
344
|
+
params,
|
|
345
|
+
language: ctx.language,
|
|
346
|
+
config
|
|
347
|
+
};
|
|
348
|
+
let state = flow.initialState();
|
|
349
|
+
let answerIdx = 0;
|
|
350
|
+
for (const step of flow.steps) {
|
|
351
|
+
const ans = ctx.answers[answerIdx];
|
|
352
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
353
|
+
state = step.applyAnswer(state, ans.answer);
|
|
354
|
+
answerIdx += 1;
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (step.type === "text") {
|
|
358
|
+
return {
|
|
359
|
+
type: "nextQuestion",
|
|
360
|
+
questionSlug: step.slug,
|
|
361
|
+
question: step.question[ctx.language],
|
|
362
|
+
questionType: "text"
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
366
|
+
if (options.length === 0) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
type: "nextQuestion",
|
|
371
|
+
questionSlug: step.slug,
|
|
372
|
+
question: step.question[ctx.language],
|
|
373
|
+
questionType: step.type,
|
|
374
|
+
options
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
378
|
+
return { type: "fulfilled", dataInvestigationResult };
|
|
379
|
+
}
|
|
380
|
+
async function resolveSetupSelection(params) {
|
|
381
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
382
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
383
|
+
return resolved.slice(0, limit);
|
|
384
|
+
}
|
|
385
|
+
|
|
305
386
|
// ../connectors/src/auth-types.ts
|
|
306
387
|
var AUTH_TYPES = {
|
|
307
388
|
OAUTH: "oauth",
|
|
@@ -324,6 +405,129 @@ var grafanaOnboarding = new ConnectorOnboarding({
|
|
|
324
405
|
}
|
|
325
406
|
});
|
|
326
407
|
|
|
408
|
+
// ../connectors/src/connectors/grafana/utils.ts
|
|
409
|
+
async function apiFetch(params, path2, init) {
|
|
410
|
+
const apiKey = params[parameters.apiKey.slug];
|
|
411
|
+
const rawUrl = params[parameters.url.slug];
|
|
412
|
+
if (!apiKey || !rawUrl) {
|
|
413
|
+
throw new Error("grafana: missing required parameters: url and api-key");
|
|
414
|
+
}
|
|
415
|
+
const baseUrl = rawUrl.replace(/\/+$/, "");
|
|
416
|
+
const url = `${baseUrl}${path2.startsWith("/") ? path2 : `/${path2}`}`;
|
|
417
|
+
const headers = new Headers(init?.headers);
|
|
418
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
419
|
+
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
420
|
+
return fetch(url, { ...init, headers });
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// ../connectors/src/connectors/grafana/setup-flow.ts
|
|
424
|
+
var ALL_DATASOURCES = "__ALL_DATASOURCES__";
|
|
425
|
+
var GRAFANA_SETUP_MAX_DATASOURCES = 10;
|
|
426
|
+
async function listOrgs(params) {
|
|
427
|
+
try {
|
|
428
|
+
const res = await apiFetch(params, "/api/orgs");
|
|
429
|
+
if (res.ok) {
|
|
430
|
+
const data = await res.json();
|
|
431
|
+
if (Array.isArray(data)) return data;
|
|
432
|
+
}
|
|
433
|
+
} catch {
|
|
434
|
+
}
|
|
435
|
+
try {
|
|
436
|
+
const res = await apiFetch(params, "/api/org");
|
|
437
|
+
if (!res.ok) return [];
|
|
438
|
+
const data = await res.json();
|
|
439
|
+
if (data && typeof data.id === "number" && typeof data.name === "string") {
|
|
440
|
+
return [data];
|
|
441
|
+
}
|
|
442
|
+
} catch {
|
|
443
|
+
}
|
|
444
|
+
return [];
|
|
445
|
+
}
|
|
446
|
+
async function listDatasources(params) {
|
|
447
|
+
const res = await apiFetch(params, "/api/datasources");
|
|
448
|
+
if (!res.ok) {
|
|
449
|
+
const body = await res.text().catch(() => res.statusText);
|
|
450
|
+
throw new Error(`grafana: listDatasources failed (${res.status}): ${body}`);
|
|
451
|
+
}
|
|
452
|
+
const data = await res.json();
|
|
453
|
+
return data ?? [];
|
|
454
|
+
}
|
|
455
|
+
var grafanaSetupFlow = {
|
|
456
|
+
initialState: () => ({}),
|
|
457
|
+
steps: [
|
|
458
|
+
{
|
|
459
|
+
slug: "organization",
|
|
460
|
+
type: "select",
|
|
461
|
+
question: {
|
|
462
|
+
ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u7D44\u7E54\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
|
|
463
|
+
en: "Select the organization to use for setup"
|
|
464
|
+
},
|
|
465
|
+
async fetchOptions(_state, rt) {
|
|
466
|
+
const orgs = await listOrgs(rt.params);
|
|
467
|
+
return orgs.map((o) => ({ value: String(o.id), label: o.name }));
|
|
468
|
+
},
|
|
469
|
+
applyAnswer: (state, answer) => ({ ...state, organization: answer[0] })
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
slug: "datasources",
|
|
473
|
+
type: "multiSelect",
|
|
474
|
+
question: {
|
|
475
|
+
ja: "\u5BFE\u8C61\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
476
|
+
en: "Select target datasources (multi-select allowed)"
|
|
477
|
+
},
|
|
478
|
+
async fetchOptions(_state, rt) {
|
|
479
|
+
const datasources = await listDatasources(rt.params);
|
|
480
|
+
const opts = datasources.filter((d) => d.uid && d.name).map((d) => ({
|
|
481
|
+
value: d.uid,
|
|
482
|
+
label: `${d.name} (${d.type})`
|
|
483
|
+
}));
|
|
484
|
+
if (opts.length === 0) return [];
|
|
485
|
+
return [
|
|
486
|
+
{
|
|
487
|
+
value: ALL_DATASOURCES,
|
|
488
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9" : "All datasources"
|
|
489
|
+
},
|
|
490
|
+
...opts
|
|
491
|
+
];
|
|
492
|
+
},
|
|
493
|
+
applyAnswer: (state, answer) => ({ ...state, datasources: answer })
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
async finalize(state, rt) {
|
|
497
|
+
if (!state.datasources) {
|
|
498
|
+
throw new Error("Grafana setup: incomplete state on finalize");
|
|
499
|
+
}
|
|
500
|
+
const datasources = await listDatasources(rt.params);
|
|
501
|
+
const byUid = new Map(datasources.map((d) => [d.uid, d]));
|
|
502
|
+
const targetUids = await resolveSetupSelection({
|
|
503
|
+
selected: state.datasources,
|
|
504
|
+
allSentinel: ALL_DATASOURCES,
|
|
505
|
+
fetchAll: async () => datasources.map((d) => d.uid).filter((u) => u),
|
|
506
|
+
limit: GRAFANA_SETUP_MAX_DATASOURCES
|
|
507
|
+
});
|
|
508
|
+
const sections = ["## Grafana", ""];
|
|
509
|
+
if (state.organization) {
|
|
510
|
+
sections.push(`### Organization: ${state.organization}`, "");
|
|
511
|
+
}
|
|
512
|
+
for (const uid of targetUids) {
|
|
513
|
+
const ds = byUid.get(uid);
|
|
514
|
+
if (!ds) {
|
|
515
|
+
sections.push(`#### Datasource: ${uid}`, "", "_Not found._", "");
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
sections.push(`#### Datasource: ${ds.name}`, "");
|
|
519
|
+
sections.push("| Field | Value |");
|
|
520
|
+
sections.push("|-------|-------|");
|
|
521
|
+
sections.push(`| UID | ${ds.uid} |`);
|
|
522
|
+
sections.push(`| Type | ${ds.type} |`);
|
|
523
|
+
sections.push(`| URL | ${ds.url ?? "-"} |`);
|
|
524
|
+
sections.push(`| Default | ${ds.isDefault ? "yes" : "no"} |`);
|
|
525
|
+
sections.push("");
|
|
526
|
+
}
|
|
527
|
+
return sections.join("\n");
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
|
|
327
531
|
// ../connectors/src/connectors/grafana/tools/request.ts
|
|
328
532
|
import { z } from "zod";
|
|
329
533
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
@@ -536,7 +740,41 @@ export default async function handler(c: Context) {
|
|
|
536
740
|
- \`GET /api/org\` \u2014 \u73FE\u5728\u306E\u7D44\u7E54\u3092\u53D6\u5F97
|
|
537
741
|
- \`GET /api/health\` \u2014 \u30D8\u30EB\u30B9\u30C1\u30A7\u30C3\u30AF`
|
|
538
742
|
},
|
|
539
|
-
tools
|
|
743
|
+
tools,
|
|
744
|
+
setup: (params, ctx, config) => runSetupFlow(grafanaSetupFlow, params, ctx, config),
|
|
745
|
+
async checkConnection(params, _config) {
|
|
746
|
+
const apiKey = params[parameters.apiKey.slug];
|
|
747
|
+
const rawUrl = params[parameters.url.slug];
|
|
748
|
+
if (!apiKey || !rawUrl) {
|
|
749
|
+
return {
|
|
750
|
+
success: false,
|
|
751
|
+
error: "Missing required parameters: url and api-key"
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
const baseUrl = rawUrl.replace(/\/+$/, "");
|
|
755
|
+
try {
|
|
756
|
+
const res = await fetch(`${baseUrl}/api/org`, {
|
|
757
|
+
method: "GET",
|
|
758
|
+
headers: {
|
|
759
|
+
Authorization: `Bearer ${apiKey}`,
|
|
760
|
+
Accept: "application/json"
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
if (!res.ok) {
|
|
764
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
765
|
+
return {
|
|
766
|
+
success: false,
|
|
767
|
+
error: `Grafana API failed: HTTP ${res.status} ${errorText}`
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
return { success: true };
|
|
771
|
+
} catch (error) {
|
|
772
|
+
return {
|
|
773
|
+
success: false,
|
|
774
|
+
error: error instanceof Error ? error.message : String(error)
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
}
|
|
540
778
|
});
|
|
541
779
|
|
|
542
780
|
// src/connectors/create-connector-sdk.ts
|
|
@@ -565,6 +803,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
565
803
|
import { getContext } from "hono/context-storage";
|
|
566
804
|
import { getCookie } from "hono/cookie";
|
|
567
805
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
806
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
568
807
|
function normalizeHeaders(input) {
|
|
569
808
|
const out = {};
|
|
570
809
|
if (!input) return out;
|
|
@@ -573,6 +812,11 @@ function normalizeHeaders(input) {
|
|
|
573
812
|
});
|
|
574
813
|
return out;
|
|
575
814
|
}
|
|
815
|
+
function extractInputUrl(input) {
|
|
816
|
+
if (typeof input === "string") return input;
|
|
817
|
+
if (input instanceof URL) return input.href;
|
|
818
|
+
return input.url;
|
|
819
|
+
}
|
|
576
820
|
function createSandboxProxyFetch(connectionId) {
|
|
577
821
|
return async (input, init) => {
|
|
578
822
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -582,10 +826,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
582
826
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
583
827
|
);
|
|
584
828
|
}
|
|
585
|
-
const originalUrl =
|
|
829
|
+
const originalUrl = extractInputUrl(input);
|
|
830
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
831
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
832
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
833
|
+
return fetch(sessionUrl, {
|
|
834
|
+
method: "POST",
|
|
835
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
836
|
+
});
|
|
837
|
+
}
|
|
586
838
|
const originalMethod = init?.method ?? "GET";
|
|
587
839
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
588
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
589
840
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
590
841
|
return fetch(proxyUrl, {
|
|
591
842
|
method: "POST",
|
|
@@ -611,10 +862,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
611
862
|
}
|
|
612
863
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
613
864
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
865
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
614
866
|
return async (input, init) => {
|
|
615
|
-
const originalUrl =
|
|
616
|
-
const originalMethod = init?.method ?? "GET";
|
|
617
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
867
|
+
const originalUrl = extractInputUrl(input);
|
|
618
868
|
const c = getContext();
|
|
619
869
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
620
870
|
if (!appSession) {
|
|
@@ -622,6 +872,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
622
872
|
"No authentication method available for connection proxy."
|
|
623
873
|
);
|
|
624
874
|
}
|
|
875
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
876
|
+
return fetch(sessionUrl, {
|
|
877
|
+
method: "POST",
|
|
878
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
const originalMethod = init?.method ?? "GET";
|
|
882
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
625
883
|
return fetch(proxyUrl, {
|
|
626
884
|
method: "POST",
|
|
627
885
|
headers: {
|