@squadbase/vite-server 0.1.12-dev.93b8799 → 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 +12128 -934
- package/dist/connectors/airtable-oauth.js +248 -46
- package/dist/connectors/airtable.js +285 -51
- package/dist/connectors/amplitude.js +288 -47
- package/dist/connectors/anthropic.js +126 -47
- package/dist/connectors/asana.js +293 -49
- package/dist/connectors/attio.js +268 -49
- package/dist/connectors/aws-billing.js +253 -46
- package/dist/connectors/azure-sql.js +387 -102
- package/dist/connectors/backlog-api-key.js +283 -47
- package/dist/connectors/clickup.js +304 -49
- package/dist/connectors/cosmosdb.js +271 -50
- package/dist/connectors/customerio.js +285 -47
- package/dist/connectors/dbt.js +306 -47
- package/dist/connectors/freshdesk.js +308 -53
- package/dist/connectors/freshsales.js +299 -52
- package/dist/connectors/freshservice.js +327 -53
- package/dist/connectors/gamma.js +293 -52
- package/dist/connectors/gemini.js +125 -47
- package/dist/connectors/github.js +352 -49
- package/dist/connectors/gmail-oauth.js +170 -7
- package/dist/connectors/gmail.js +316 -47
- package/dist/connectors/google-ads.js +254 -46
- package/dist/connectors/google-analytics-oauth.js +276 -46
- package/dist/connectors/google-analytics.js +378 -49
- package/dist/connectors/google-audit-log.js +404 -47
- package/dist/connectors/google-calendar-oauth.js +225 -46
- package/dist/connectors/google-calendar.js +325 -47
- package/dist/connectors/google-docs.js +186 -6
- package/dist/connectors/google-drive.js +228 -5
- package/dist/connectors/google-search-console-oauth.js +222 -46
- package/dist/connectors/google-sheets.js +238 -47
- package/dist/connectors/google-slides.js +171 -6
- package/dist/connectors/grafana.js +298 -49
- package/dist/connectors/hubspot-oauth.js +174 -5
- package/dist/connectors/hubspot.js +272 -49
- package/dist/connectors/influxdb.js +382 -51
- package/dist/connectors/intercom-oauth.js +176 -5
- package/dist/connectors/intercom.js +268 -49
- package/dist/connectors/jdbc.js +728 -110
- package/dist/connectors/jira-api-key.js +292 -47
- package/dist/connectors/kintone-api-token.js +247 -47
- package/dist/connectors/kintone.js +294 -47
- package/dist/connectors/linear.js +296 -49
- package/dist/connectors/linkedin-ads.js +234 -50
- package/dist/connectors/mailchimp-oauth.js +234 -46
- package/dist/connectors/mailchimp.js +286 -49
- package/dist/connectors/meta-ads-oauth.js +239 -48
- package/dist/connectors/meta-ads.js +251 -50
- package/dist/connectors/mixpanel.js +304 -47
- package/dist/connectors/monday.js +326 -49
- package/dist/connectors/mongodb.js +285 -57
- package/dist/connectors/notion-oauth.js +197 -5
- package/dist/connectors/notion.js +289 -51
- package/dist/connectors/openai.js +125 -47
- package/dist/connectors/oracle.js +405 -103
- package/dist/connectors/outlook-oauth.js +170 -5
- package/dist/connectors/powerbi-oauth.js +217 -5
- package/dist/connectors/salesforce.js +350 -49
- package/dist/connectors/semrush.js +280 -49
- package/dist/connectors/sentry.js +255 -50
- package/dist/connectors/shopify-oauth.js +153 -5
- package/dist/connectors/shopify.js +323 -47
- package/dist/connectors/sqlserver.js +381 -102
- package/dist/connectors/stripe-api-key.js +235 -46
- package/dist/connectors/stripe-oauth.js +168 -5
- package/dist/connectors/supabase.js +269 -48
- package/dist/connectors/tableau.js +337 -206
- package/dist/connectors/tiktok-ads.js +245 -48
- package/dist/connectors/wix-store.js +286 -49
- package/dist/connectors/zendesk-oauth.js +205 -5
- package/dist/connectors/zendesk.js +324 -47
- package/dist/index.d.ts +149 -1
- package/dist/index.js +18297 -6886
- package/dist/main.js +12785 -1382
- package/dist/vite-plugin.js +12140 -936
- 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/influxdb/parameters.ts
|
|
57
|
+
init_parameter_definition();
|
|
46
58
|
var parameters = {
|
|
47
59
|
url: new ParameterDefinition({
|
|
48
60
|
slug: "url",
|
|
@@ -103,7 +115,7 @@ function createClient(params) {
|
|
|
103
115
|
`influxdb: missing required parameter: ${parameters.database.slug}`
|
|
104
116
|
);
|
|
105
117
|
}
|
|
106
|
-
function
|
|
118
|
+
function authHeaders2(extra) {
|
|
107
119
|
const headers = new Headers(extra);
|
|
108
120
|
headers.set("Authorization", `Token ${token}`);
|
|
109
121
|
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
@@ -139,7 +151,7 @@ function createClient(params) {
|
|
|
139
151
|
async querySql(sql, options) {
|
|
140
152
|
const res = await fetch(`${url}/api/v3/query_sql`, {
|
|
141
153
|
method: "POST",
|
|
142
|
-
headers:
|
|
154
|
+
headers: authHeaders2({ "Content-Type": "application/json" }),
|
|
143
155
|
body: JSON.stringify({
|
|
144
156
|
db: options?.database ?? database,
|
|
145
157
|
q: sql
|
|
@@ -151,7 +163,7 @@ function createClient(params) {
|
|
|
151
163
|
async queryInfluxql(influxql, options) {
|
|
152
164
|
const res = await fetch(`${url}/api/v3/query_influxql`, {
|
|
153
165
|
method: "POST",
|
|
154
|
-
headers:
|
|
166
|
+
headers: authHeaders2({ "Content-Type": "application/json" }),
|
|
155
167
|
body: JSON.stringify({
|
|
156
168
|
db: options?.database ?? database,
|
|
157
169
|
q: influxql
|
|
@@ -171,7 +183,7 @@ function createClient(params) {
|
|
|
171
183
|
`${url}/api/v2/query?org=${encodeURIComponent(resolvedOrg)}`,
|
|
172
184
|
{
|
|
173
185
|
method: "POST",
|
|
174
|
-
headers:
|
|
186
|
+
headers: authHeaders2({
|
|
175
187
|
"Content-Type": "application/vnd.flux",
|
|
176
188
|
Accept: "application/csv"
|
|
177
189
|
}),
|
|
@@ -188,7 +200,7 @@ function createClient(params) {
|
|
|
188
200
|
const endpoint = resolvedOrg ? `${url}/api/v2/write?org=${encodeURIComponent(resolvedOrg)}&bucket=${encodeURIComponent(resolvedDatabase)}&precision=${precision}` : `${url}/api/v3/write_lp?db=${encodeURIComponent(resolvedDatabase)}&precision=${precision}`;
|
|
189
201
|
const res = await fetch(endpoint, {
|
|
190
202
|
method: "POST",
|
|
191
|
-
headers:
|
|
203
|
+
headers: authHeaders2({ "Content-Type": "text/plain; charset=utf-8" }),
|
|
192
204
|
body: lineProtocol
|
|
193
205
|
});
|
|
194
206
|
await assertOk(res, "writeLineProtocol");
|
|
@@ -263,6 +275,20 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
263
275
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
264
276
|
*/
|
|
265
277
|
setup;
|
|
278
|
+
/**
|
|
279
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
280
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
281
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
282
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
283
|
+
*
|
|
284
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
285
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
286
|
+
* connectionId, which doesn't exist until the row is saved
|
|
287
|
+
*
|
|
288
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
289
|
+
* the default verify-on-create behavior without opt-in.
|
|
290
|
+
*/
|
|
291
|
+
skipConnectionCheckOnCreate;
|
|
266
292
|
constructor(config) {
|
|
267
293
|
this.slug = config.slug;
|
|
268
294
|
this.authType = config.authType;
|
|
@@ -280,6 +306,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
280
306
|
this.query = config.query;
|
|
281
307
|
this.checkConnection = config.checkConnection;
|
|
282
308
|
this.setup = config.setup;
|
|
309
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
283
310
|
}
|
|
284
311
|
get connectorKey() {
|
|
285
312
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -344,6 +371,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
344
371
|
}
|
|
345
372
|
};
|
|
346
373
|
|
|
374
|
+
// ../connectors/src/setup-flow.ts
|
|
375
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
376
|
+
const runtime = {
|
|
377
|
+
params,
|
|
378
|
+
language: ctx.language,
|
|
379
|
+
config
|
|
380
|
+
};
|
|
381
|
+
let state = flow.initialState();
|
|
382
|
+
let answerIdx = 0;
|
|
383
|
+
for (const step of flow.steps) {
|
|
384
|
+
const ans = ctx.answers[answerIdx];
|
|
385
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
386
|
+
state = step.applyAnswer(state, ans.answer);
|
|
387
|
+
answerIdx += 1;
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (step.type === "text") {
|
|
391
|
+
return {
|
|
392
|
+
type: "nextQuestion",
|
|
393
|
+
questionSlug: step.slug,
|
|
394
|
+
question: step.question[ctx.language],
|
|
395
|
+
questionType: "text"
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
399
|
+
if (options.length === 0) {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
type: "nextQuestion",
|
|
404
|
+
questionSlug: step.slug,
|
|
405
|
+
question: step.question[ctx.language],
|
|
406
|
+
questionType: step.type,
|
|
407
|
+
options
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
411
|
+
return { type: "fulfilled", dataInvestigationResult };
|
|
412
|
+
}
|
|
413
|
+
async function resolveSetupSelection(params) {
|
|
414
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
415
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
416
|
+
return resolved.slice(0, limit);
|
|
417
|
+
}
|
|
418
|
+
|
|
347
419
|
// ../connectors/src/auth-types.ts
|
|
348
420
|
var AUTH_TYPES = {
|
|
349
421
|
OAUTH: "oauth",
|
|
@@ -412,6 +484,244 @@ var influxdbOnboarding = new ConnectorOnboarding({
|
|
|
412
484
|
}
|
|
413
485
|
});
|
|
414
486
|
|
|
487
|
+
// ../connectors/src/connectors/influxdb/utils.ts
|
|
488
|
+
function authHeaders(token, extra) {
|
|
489
|
+
const headers = new Headers(extra);
|
|
490
|
+
headers.set("Authorization", `Token ${token}`);
|
|
491
|
+
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
492
|
+
return headers;
|
|
493
|
+
}
|
|
494
|
+
async function detectVariant(params) {
|
|
495
|
+
const url = (params[parameters.url.slug] ?? "").replace(/\/$/, "");
|
|
496
|
+
const token = params[parameters.token.slug];
|
|
497
|
+
const database = params[parameters.database.slug];
|
|
498
|
+
const res = await fetch(`${url}/api/v3/query_sql`, {
|
|
499
|
+
method: "POST",
|
|
500
|
+
headers: authHeaders(token, { "Content-Type": "application/json" }),
|
|
501
|
+
body: JSON.stringify({ db: database, q: "SELECT 1" })
|
|
502
|
+
});
|
|
503
|
+
if (res.ok) {
|
|
504
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
505
|
+
if (contentType.includes("application/json")) return "v3";
|
|
506
|
+
}
|
|
507
|
+
return "v2";
|
|
508
|
+
}
|
|
509
|
+
async function runSql(params, sql) {
|
|
510
|
+
const url = (params[parameters.url.slug] ?? "").replace(/\/$/, "");
|
|
511
|
+
const token = params[parameters.token.slug];
|
|
512
|
+
const database = params[parameters.database.slug];
|
|
513
|
+
const res = await fetch(`${url}/api/v3/query_sql`, {
|
|
514
|
+
method: "POST",
|
|
515
|
+
headers: authHeaders(token, { "Content-Type": "application/json" }),
|
|
516
|
+
body: JSON.stringify({ db: database, q: sql })
|
|
517
|
+
});
|
|
518
|
+
if (!res.ok) {
|
|
519
|
+
const body = await res.text().catch(() => res.statusText);
|
|
520
|
+
throw new Error(
|
|
521
|
+
`InfluxDB SQL query failed: HTTP ${res.status} \u2014 ${body.slice(0, 200)}`
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
return await res.json();
|
|
525
|
+
}
|
|
526
|
+
async function runFlux(params, flux) {
|
|
527
|
+
const url = (params[parameters.url.slug] ?? "").replace(/\/$/, "");
|
|
528
|
+
const token = params[parameters.token.slug];
|
|
529
|
+
const org = params[parameters.org.slug];
|
|
530
|
+
if (!org) {
|
|
531
|
+
throw new Error(
|
|
532
|
+
"InfluxDB 2 Flux queries require the 'org' connection parameter, which is not configured"
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
const res = await fetch(
|
|
536
|
+
`${url}/api/v2/query?org=${encodeURIComponent(org)}`,
|
|
537
|
+
{
|
|
538
|
+
method: "POST",
|
|
539
|
+
headers: authHeaders(token, {
|
|
540
|
+
"Content-Type": "application/vnd.flux",
|
|
541
|
+
Accept: "application/csv"
|
|
542
|
+
}),
|
|
543
|
+
body: flux
|
|
544
|
+
}
|
|
545
|
+
);
|
|
546
|
+
if (!res.ok) {
|
|
547
|
+
const body = await res.text().catch(() => res.statusText);
|
|
548
|
+
throw new Error(
|
|
549
|
+
`InfluxDB Flux query failed: HTTP ${res.status} \u2014 ${body.slice(0, 200)}`
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
return await res.text();
|
|
553
|
+
}
|
|
554
|
+
function parseAnnotatedCsv(csv) {
|
|
555
|
+
const lines = csv.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
556
|
+
const rows = [];
|
|
557
|
+
let headers = null;
|
|
558
|
+
for (const line of lines) {
|
|
559
|
+
if (line.startsWith("#")) {
|
|
560
|
+
headers = null;
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
const fields = splitCsvLine(line);
|
|
564
|
+
if (headers === null) {
|
|
565
|
+
headers = fields;
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
const row = {};
|
|
569
|
+
headers.forEach((h, i) => {
|
|
570
|
+
row[h] = fields[i] ?? "";
|
|
571
|
+
});
|
|
572
|
+
rows.push(row);
|
|
573
|
+
}
|
|
574
|
+
return { columns: headers ?? [], rows };
|
|
575
|
+
}
|
|
576
|
+
function splitCsvLine(line) {
|
|
577
|
+
const out = [];
|
|
578
|
+
let cur = "";
|
|
579
|
+
let inQuotes = false;
|
|
580
|
+
for (let i = 0; i < line.length; i++) {
|
|
581
|
+
const c = line[i];
|
|
582
|
+
if (inQuotes) {
|
|
583
|
+
if (c === '"' && line[i + 1] === '"') {
|
|
584
|
+
cur += '"';
|
|
585
|
+
i += 1;
|
|
586
|
+
} else if (c === '"') {
|
|
587
|
+
inQuotes = false;
|
|
588
|
+
} else {
|
|
589
|
+
cur += c;
|
|
590
|
+
}
|
|
591
|
+
} else if (c === '"') {
|
|
592
|
+
inQuotes = true;
|
|
593
|
+
} else if (c === ",") {
|
|
594
|
+
out.push(cur);
|
|
595
|
+
cur = "";
|
|
596
|
+
} else {
|
|
597
|
+
cur += c;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
out.push(cur);
|
|
601
|
+
return out;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// ../connectors/src/connectors/influxdb/setup-flow.ts
|
|
605
|
+
var ALL_MEASUREMENTS = "__ALL_MEASUREMENTS__";
|
|
606
|
+
var INFLUXDB_SETUP_MAX_MEASUREMENTS = 20;
|
|
607
|
+
async function listMeasurements(params, variant) {
|
|
608
|
+
if (variant === "v3") {
|
|
609
|
+
const rows2 = await runSql(params, "SHOW TABLES");
|
|
610
|
+
return rows2.map((r) => String(r["table_name"] ?? r["name"] ?? "")).filter((name) => name).filter((name) => !name.includes("::"));
|
|
611
|
+
}
|
|
612
|
+
const bucket = params[parameters.database.slug];
|
|
613
|
+
if (!bucket) {
|
|
614
|
+
throw new Error(
|
|
615
|
+
"InfluxDB 2 setup: 'database' (bucket) parameter is required to list measurements"
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
const flux = [
|
|
619
|
+
`import "influxdata/influxdb/schema"`,
|
|
620
|
+
`schema.measurements(bucket: ${JSON.stringify(bucket)})`
|
|
621
|
+
].join("\n");
|
|
622
|
+
const csv = await runFlux(params, flux);
|
|
623
|
+
const { rows } = parseAnnotatedCsv(csv);
|
|
624
|
+
return rows.map((r) => r["_value"] ?? "").filter((name) => name);
|
|
625
|
+
}
|
|
626
|
+
async function listMeasurementColumns(params, variant, measurement) {
|
|
627
|
+
if (variant === "v3") {
|
|
628
|
+
const safeName2 = measurement.replace(/"/g, '""');
|
|
629
|
+
const rows = await runSql(params, `SHOW COLUMNS FROM "${safeName2}"`);
|
|
630
|
+
return rows.map((r) => ({
|
|
631
|
+
name: String(r["column_name"] ?? r["name"] ?? ""),
|
|
632
|
+
kind: String(r["data_type"] ?? r["type"] ?? "")
|
|
633
|
+
}));
|
|
634
|
+
}
|
|
635
|
+
const bucket = params[parameters.database.slug];
|
|
636
|
+
const safeName = measurement.replace(/"/g, '\\"');
|
|
637
|
+
const fieldsFlux = [
|
|
638
|
+
`import "influxdata/influxdb/schema"`,
|
|
639
|
+
`schema.measurementFieldKeys(bucket: ${JSON.stringify(bucket)}, measurement: "${safeName}")`
|
|
640
|
+
].join("\n");
|
|
641
|
+
const tagsFlux = [
|
|
642
|
+
`import "influxdata/influxdb/schema"`,
|
|
643
|
+
`schema.measurementTagKeys(bucket: ${JSON.stringify(bucket)}, measurement: "${safeName}")`
|
|
644
|
+
].join("\n");
|
|
645
|
+
const [fieldsCsv, tagsCsv] = await Promise.all([
|
|
646
|
+
runFlux(params, fieldsFlux),
|
|
647
|
+
runFlux(params, tagsFlux)
|
|
648
|
+
]);
|
|
649
|
+
const fields = parseAnnotatedCsv(fieldsCsv).rows.map((r) => ({
|
|
650
|
+
name: r["_value"] ?? "",
|
|
651
|
+
kind: "field"
|
|
652
|
+
}));
|
|
653
|
+
const tags = parseAnnotatedCsv(tagsCsv).rows.map((r) => ({
|
|
654
|
+
name: r["_value"] ?? "",
|
|
655
|
+
kind: "tag"
|
|
656
|
+
}));
|
|
657
|
+
return [...tags, ...fields].filter((c) => c.name);
|
|
658
|
+
}
|
|
659
|
+
var influxdbSetupFlow = {
|
|
660
|
+
initialState: () => ({}),
|
|
661
|
+
steps: [
|
|
662
|
+
{
|
|
663
|
+
slug: "measurements",
|
|
664
|
+
type: "multiSelect",
|
|
665
|
+
question: {
|
|
666
|
+
ja: "\u5BFE\u8C61 measurement \u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
667
|
+
en: "Select target measurements (multi-select allowed)"
|
|
668
|
+
},
|
|
669
|
+
async fetchOptions(_state, rt) {
|
|
670
|
+
const variant = await detectVariant(rt.params);
|
|
671
|
+
const ms = await listMeasurements(rt.params, variant);
|
|
672
|
+
const options = ms.map((value) => ({ value }));
|
|
673
|
+
return [
|
|
674
|
+
{
|
|
675
|
+
value: ALL_MEASUREMENTS,
|
|
676
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E measurement" : "All measurements"
|
|
677
|
+
},
|
|
678
|
+
...options
|
|
679
|
+
];
|
|
680
|
+
},
|
|
681
|
+
applyAnswer: (state, answer) => ({ ...state, measurements: answer })
|
|
682
|
+
}
|
|
683
|
+
],
|
|
684
|
+
async finalize(state, rt) {
|
|
685
|
+
if (!state.measurements) {
|
|
686
|
+
throw new Error("InfluxDB setup: incomplete state on finalize");
|
|
687
|
+
}
|
|
688
|
+
const variant = await detectVariant(rt.params);
|
|
689
|
+
const database = rt.params[parameters.database.slug];
|
|
690
|
+
const org = rt.params[parameters.org.slug];
|
|
691
|
+
const targetMeasurements = await resolveSetupSelection({
|
|
692
|
+
selected: state.measurements,
|
|
693
|
+
allSentinel: ALL_MEASUREMENTS,
|
|
694
|
+
fetchAll: () => listMeasurements(rt.params, variant),
|
|
695
|
+
limit: INFLUXDB_SETUP_MAX_MEASUREMENTS
|
|
696
|
+
});
|
|
697
|
+
const sections = [
|
|
698
|
+
"## InfluxDB",
|
|
699
|
+
"",
|
|
700
|
+
`### Variant: ${variant === "v3" ? "InfluxDB 3 (SQL)" : "InfluxDB 2 (Flux)"}`,
|
|
701
|
+
`### ${variant === "v3" ? "Database" : "Bucket"}: ${database}`
|
|
702
|
+
];
|
|
703
|
+
if (variant === "v2" && org) {
|
|
704
|
+
sections.push(`### Organization: ${org}`);
|
|
705
|
+
}
|
|
706
|
+
sections.push("");
|
|
707
|
+
for (const measurement of targetMeasurements) {
|
|
708
|
+
const cols = await listMeasurementColumns(rt.params, variant, measurement);
|
|
709
|
+
sections.push(`#### Measurement: ${measurement}`, "");
|
|
710
|
+
if (cols.length === 0) {
|
|
711
|
+
sections.push("_(no fields or tags found)_", "");
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
sections.push("| Column | Kind |");
|
|
715
|
+
sections.push("|--------|------|");
|
|
716
|
+
for (const c of cols) {
|
|
717
|
+
sections.push(`| ${c.name} | ${c.kind || "-"} |`);
|
|
718
|
+
}
|
|
719
|
+
sections.push("");
|
|
720
|
+
}
|
|
721
|
+
return sections.join("\n");
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
|
|
415
725
|
// ../connectors/src/connectors/influxdb/tools/request.ts
|
|
416
726
|
import { z } from "zod";
|
|
417
727
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
@@ -678,6 +988,7 @@ export default async function handler(c: Context) {
|
|
|
678
988
|
- measurement \u4E00\u89A7: \`SHOW TABLES\`\u3001\u5217\u4E00\u89A7: \`SHOW COLUMNS FROM <measurement>\``
|
|
679
989
|
},
|
|
680
990
|
tools,
|
|
991
|
+
setup: (params, ctx, config) => runSetupFlow(influxdbSetupFlow, params, ctx, config),
|
|
681
992
|
async checkConnection(params) {
|
|
682
993
|
const url = (params.url ?? "").replace(/\/$/, "");
|
|
683
994
|
const token = params.token;
|
|
@@ -746,6 +1057,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
746
1057
|
import { getContext } from "hono/context-storage";
|
|
747
1058
|
import { getCookie } from "hono/cookie";
|
|
748
1059
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
1060
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
749
1061
|
function normalizeHeaders(input) {
|
|
750
1062
|
const out = {};
|
|
751
1063
|
if (!input) return out;
|
|
@@ -754,6 +1066,11 @@ function normalizeHeaders(input) {
|
|
|
754
1066
|
});
|
|
755
1067
|
return out;
|
|
756
1068
|
}
|
|
1069
|
+
function extractInputUrl(input) {
|
|
1070
|
+
if (typeof input === "string") return input;
|
|
1071
|
+
if (input instanceof URL) return input.href;
|
|
1072
|
+
return input.url;
|
|
1073
|
+
}
|
|
757
1074
|
function createSandboxProxyFetch(connectionId) {
|
|
758
1075
|
return async (input, init) => {
|
|
759
1076
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -763,10 +1080,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
763
1080
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
764
1081
|
);
|
|
765
1082
|
}
|
|
766
|
-
const originalUrl =
|
|
1083
|
+
const originalUrl = extractInputUrl(input);
|
|
1084
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
1085
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1086
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
1087
|
+
return fetch(sessionUrl, {
|
|
1088
|
+
method: "POST",
|
|
1089
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
767
1092
|
const originalMethod = init?.method ?? "GET";
|
|
768
1093
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
769
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
770
1094
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
771
1095
|
return fetch(proxyUrl, {
|
|
772
1096
|
method: "POST",
|
|
@@ -792,10 +1116,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
792
1116
|
}
|
|
793
1117
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
794
1118
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1119
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
795
1120
|
return async (input, init) => {
|
|
796
|
-
const originalUrl =
|
|
797
|
-
const originalMethod = init?.method ?? "GET";
|
|
798
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
1121
|
+
const originalUrl = extractInputUrl(input);
|
|
799
1122
|
const c = getContext();
|
|
800
1123
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
801
1124
|
if (!appSession) {
|
|
@@ -803,6 +1126,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
803
1126
|
"No authentication method available for connection proxy."
|
|
804
1127
|
);
|
|
805
1128
|
}
|
|
1129
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1130
|
+
return fetch(sessionUrl, {
|
|
1131
|
+
method: "POST",
|
|
1132
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
const originalMethod = init?.method ?? "GET";
|
|
1136
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
806
1137
|
return fetch(proxyUrl, {
|
|
807
1138
|
method: "POST",
|
|
808
1139
|
headers: {
|