@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/amplitude/parameters.ts
|
|
57
|
+
init_parameter_definition();
|
|
46
58
|
var parameters = {
|
|
47
59
|
apiKey: new ParameterDefinition({
|
|
48
60
|
slug: "api-key",
|
|
@@ -216,6 +228,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
216
228
|
tools;
|
|
217
229
|
query;
|
|
218
230
|
checkConnection;
|
|
231
|
+
/**
|
|
232
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
233
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
234
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
235
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
236
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
237
|
+
*/
|
|
238
|
+
setup;
|
|
239
|
+
/**
|
|
240
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
241
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
242
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
243
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
244
|
+
*
|
|
245
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
246
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
247
|
+
* connectionId, which doesn't exist until the row is saved
|
|
248
|
+
*
|
|
249
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
250
|
+
* the default verify-on-create behavior without opt-in.
|
|
251
|
+
*/
|
|
252
|
+
skipConnectionCheckOnCreate;
|
|
219
253
|
constructor(config) {
|
|
220
254
|
this.slug = config.slug;
|
|
221
255
|
this.authType = config.authType;
|
|
@@ -232,6 +266,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
232
266
|
this.tools = config.tools;
|
|
233
267
|
this.query = config.query;
|
|
234
268
|
this.checkConnection = config.checkConnection;
|
|
269
|
+
this.setup = config.setup;
|
|
270
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
235
271
|
}
|
|
236
272
|
get connectorKey() {
|
|
237
273
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -296,6 +332,71 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
296
332
|
}
|
|
297
333
|
};
|
|
298
334
|
|
|
335
|
+
// ../connectors/src/setup-flow.ts
|
|
336
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
337
|
+
const runtime = {
|
|
338
|
+
params,
|
|
339
|
+
language: ctx.language,
|
|
340
|
+
config
|
|
341
|
+
};
|
|
342
|
+
let state = flow.initialState();
|
|
343
|
+
let answerIdx = 0;
|
|
344
|
+
const pendingParameterUpdates = [];
|
|
345
|
+
for (const step of flow.steps) {
|
|
346
|
+
const ans = ctx.answers[answerIdx];
|
|
347
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
348
|
+
state = step.applyAnswer(state, ans.answer);
|
|
349
|
+
if (step.toParameterUpdates) {
|
|
350
|
+
pendingParameterUpdates.push(...step.toParameterUpdates(state));
|
|
351
|
+
}
|
|
352
|
+
answerIdx += 1;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
|
|
356
|
+
if (step.type === "text") {
|
|
357
|
+
if (step.fetchOptions) {
|
|
358
|
+
const options2 = await step.fetchOptions(state, runtime);
|
|
359
|
+
if (options2.length === 0) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
type: "nextQuestion",
|
|
365
|
+
questionSlug: step.slug,
|
|
366
|
+
question: step.question[ctx.language],
|
|
367
|
+
questionType: "text",
|
|
368
|
+
allowFreeText: resolvedAllowFreeText,
|
|
369
|
+
...pendingParameterUpdates.length > 0 && {
|
|
370
|
+
parameterUpdates: pendingParameterUpdates
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
375
|
+
if (options.length === 0) {
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
return {
|
|
379
|
+
type: "nextQuestion",
|
|
380
|
+
questionSlug: step.slug,
|
|
381
|
+
question: step.question[ctx.language],
|
|
382
|
+
questionType: step.type,
|
|
383
|
+
options,
|
|
384
|
+
allowFreeText: resolvedAllowFreeText,
|
|
385
|
+
...pendingParameterUpdates.length > 0 && {
|
|
386
|
+
parameterUpdates: pendingParameterUpdates
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
391
|
+
return {
|
|
392
|
+
type: "fulfilled",
|
|
393
|
+
dataInvestigationResult,
|
|
394
|
+
...pendingParameterUpdates.length > 0 && {
|
|
395
|
+
parameterUpdates: pendingParameterUpdates
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
299
400
|
// ../connectors/src/auth-types.ts
|
|
300
401
|
var AUTH_TYPES = {
|
|
301
402
|
OAUTH: "oauth",
|
|
@@ -322,6 +423,125 @@ NOTE: The Dashboard REST API endpoints (events/segmentation, funnels, retention,
|
|
|
322
423
|
}
|
|
323
424
|
});
|
|
324
425
|
|
|
426
|
+
// ../connectors/src/connectors/amplitude/utils.ts
|
|
427
|
+
function getBaseUrl(params) {
|
|
428
|
+
const region = params[parameters.region.slug];
|
|
429
|
+
return region === "eu" ? "https://analytics.eu.amplitude.com" : "https://amplitude.com";
|
|
430
|
+
}
|
|
431
|
+
async function apiFetch(params, path2, init) {
|
|
432
|
+
const apiKey = params[parameters.apiKey.slug];
|
|
433
|
+
const secretKey = params[parameters.secretKey.slug];
|
|
434
|
+
if (!apiKey || !secretKey) {
|
|
435
|
+
throw new Error(
|
|
436
|
+
"amplitude: missing required parameters: api-key and secret-key"
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
const url = `${getBaseUrl(params)}${path2.startsWith("/") ? "" : "/"}${path2}`;
|
|
440
|
+
const headers = new Headers(init?.headers);
|
|
441
|
+
headers.set("Authorization", `Basic ${btoa(`${apiKey}:${secretKey}`)}`);
|
|
442
|
+
return fetch(url, { ...init, headers });
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// ../connectors/src/connectors/amplitude/setup-flow.ts
|
|
446
|
+
var AMPLITUDE_SETUP_MAX_ENTITIES = 10;
|
|
447
|
+
var AMPLITUDE_SETUP_MAX_EVENTS = 50;
|
|
448
|
+
var ENTITY_LABELS = {
|
|
449
|
+
events: { en: "Events", ja: "Events (\u30A4\u30D9\u30F3\u30C8)" },
|
|
450
|
+
userProperties: {
|
|
451
|
+
en: "User properties",
|
|
452
|
+
ja: "User properties (\u30E6\u30FC\u30B6\u30FC\u30D7\u30ED\u30D1\u30C6\u30A3)"
|
|
453
|
+
},
|
|
454
|
+
cohorts: { en: "Cohorts", ja: "Cohorts (\u30B3\u30DB\u30FC\u30C8)" },
|
|
455
|
+
charts: { en: "Charts", ja: "Charts (\u30C1\u30E3\u30FC\u30C8)" },
|
|
456
|
+
dashboards: { en: "Dashboards", ja: "Dashboards (\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9)" }
|
|
457
|
+
};
|
|
458
|
+
var ENTITY_DESCRIPTIONS = {
|
|
459
|
+
events: {
|
|
460
|
+
en: "Tracked event types with metadata.",
|
|
461
|
+
ja: "\u30E1\u30BF\u30C7\u30FC\u30BF\u4ED8\u304D\u3067\u8FFD\u8DE1\u3055\u308C\u3066\u3044\u308B\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u3002"
|
|
462
|
+
},
|
|
463
|
+
userProperties: {
|
|
464
|
+
en: "User-level properties used for segmentation.",
|
|
465
|
+
ja: "\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u4F7F\u308F\u308C\u308B\u30E6\u30FC\u30B6\u30FC\u30EC\u30D9\u30EB\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u3002"
|
|
466
|
+
},
|
|
467
|
+
cohorts: {
|
|
468
|
+
en: "Saved user cohorts.",
|
|
469
|
+
ja: "\u4FDD\u5B58\u6E08\u307F\u306E\u30E6\u30FC\u30B6\u30FC\u30B3\u30DB\u30FC\u30C8\u3002"
|
|
470
|
+
},
|
|
471
|
+
charts: {
|
|
472
|
+
en: "Saved analytics charts.",
|
|
473
|
+
ja: "\u4FDD\u5B58\u6E08\u307F\u306E\u30A2\u30CA\u30EA\u30C6\u30A3\u30AF\u30B9\u30C1\u30E3\u30FC\u30C8\u3002"
|
|
474
|
+
},
|
|
475
|
+
dashboards: {
|
|
476
|
+
en: "Saved dashboards.",
|
|
477
|
+
ja: "\u4FDD\u5B58\u6E08\u307F\u306E\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u3002"
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
var ENTITY_VALUES = [
|
|
481
|
+
"events",
|
|
482
|
+
"userProperties",
|
|
483
|
+
"cohorts",
|
|
484
|
+
"charts",
|
|
485
|
+
"dashboards"
|
|
486
|
+
];
|
|
487
|
+
async function fetchEventNames(params) {
|
|
488
|
+
try {
|
|
489
|
+
const res = await apiFetch(params, "/api/2/taxonomy/event");
|
|
490
|
+
if (!res.ok) return [];
|
|
491
|
+
const data = await res.json();
|
|
492
|
+
return (data.data ?? []).map((e) => e.event_type ?? "").filter((name) => name);
|
|
493
|
+
} catch {
|
|
494
|
+
return [];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
var amplitudeSetupFlow = {
|
|
498
|
+
initialState: () => ({}),
|
|
499
|
+
steps: [
|
|
500
|
+
{
|
|
501
|
+
slug: "entities",
|
|
502
|
+
type: "multiSelect",
|
|
503
|
+
question: {
|
|
504
|
+
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",
|
|
505
|
+
en: "Select target entities (multi-select allowed)"
|
|
506
|
+
},
|
|
507
|
+
async fetchOptions(_state, rt) {
|
|
508
|
+
return ENTITY_VALUES.map((value) => ({
|
|
509
|
+
value,
|
|
510
|
+
label: ENTITY_LABELS[value][rt.language]
|
|
511
|
+
}));
|
|
512
|
+
},
|
|
513
|
+
applyAnswer: (state, answer) => ({ ...state, entities: answer })
|
|
514
|
+
}
|
|
515
|
+
],
|
|
516
|
+
async finalize(state, rt) {
|
|
517
|
+
if (!state.entities) {
|
|
518
|
+
throw new Error("Amplitude setup: incomplete state on finalize");
|
|
519
|
+
}
|
|
520
|
+
const selected = state.entities.filter(
|
|
521
|
+
(e) => ENTITY_VALUES.includes(e)
|
|
522
|
+
).slice(0, AMPLITUDE_SETUP_MAX_ENTITIES);
|
|
523
|
+
const sections = ["## Amplitude", ""];
|
|
524
|
+
for (const entity of selected) {
|
|
525
|
+
sections.push(`### ${ENTITY_LABELS[entity].en}`, "");
|
|
526
|
+
sections.push(ENTITY_DESCRIPTIONS[entity][rt.language], "");
|
|
527
|
+
if (entity === "events") {
|
|
528
|
+
const names = (await fetchEventNames(rt.params)).slice(
|
|
529
|
+
0,
|
|
530
|
+
AMPLITUDE_SETUP_MAX_EVENTS
|
|
531
|
+
);
|
|
532
|
+
if (names.length > 0) {
|
|
533
|
+
sections.push("Event names:", "");
|
|
534
|
+
for (const name of names) {
|
|
535
|
+
sections.push(`- ${name}`);
|
|
536
|
+
}
|
|
537
|
+
sections.push("");
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return sections.join("\n");
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
325
545
|
// ../connectors/src/connectors/amplitude/tools/request.ts
|
|
326
546
|
import { z } from "zod";
|
|
327
547
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
@@ -550,7 +770,42 @@ export default async function handler(c: Context) {
|
|
|
550
770
|
- \`i\` \u2014 \u30A4\u30F3\u30BF\u30FC\u30D0\u30EB\uFF081=\u65E5\u6B21\u30017=\u9031\u6B21\u300130=\u6708\u6B21\uFF09
|
|
551
771
|
- \`g\` \u2014 \u30B0\u30EB\u30FC\u30D7\u5316\u30D7\u30ED\u30D1\u30C6\u30A3`
|
|
552
772
|
},
|
|
553
|
-
tools
|
|
773
|
+
tools,
|
|
774
|
+
setup: (params, ctx, config) => runSetupFlow(amplitudeSetupFlow, params, ctx, config),
|
|
775
|
+
async checkConnection(params, _config) {
|
|
776
|
+
const apiKey = params[parameters.apiKey.slug];
|
|
777
|
+
const secretKey = params[parameters.secretKey.slug];
|
|
778
|
+
if (!apiKey || !secretKey) {
|
|
779
|
+
return {
|
|
780
|
+
success: false,
|
|
781
|
+
error: "Missing required parameters: api-key and secret-key"
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
const region = params[parameters.region.slug];
|
|
785
|
+
const baseUrl = region === "eu" ? "https://analytics.eu.amplitude.com" : "https://amplitude.com";
|
|
786
|
+
try {
|
|
787
|
+
const res = await fetch(`${baseUrl}/api/2/events/list`, {
|
|
788
|
+
method: "GET",
|
|
789
|
+
headers: {
|
|
790
|
+
Authorization: `Basic ${btoa(`${apiKey}:${secretKey}`)}`,
|
|
791
|
+
Accept: "application/json"
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
if (!res.ok) {
|
|
795
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
796
|
+
return {
|
|
797
|
+
success: false,
|
|
798
|
+
error: `Amplitude API failed: HTTP ${res.status} ${errorText}`
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
return { success: true };
|
|
802
|
+
} catch (error) {
|
|
803
|
+
return {
|
|
804
|
+
success: false,
|
|
805
|
+
error: error instanceof Error ? error.message : String(error)
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
}
|
|
554
809
|
});
|
|
555
810
|
|
|
556
811
|
// src/connectors/create-connector-sdk.ts
|
|
@@ -579,6 +834,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
579
834
|
import { getContext } from "hono/context-storage";
|
|
580
835
|
import { getCookie } from "hono/cookie";
|
|
581
836
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
837
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
582
838
|
function normalizeHeaders(input) {
|
|
583
839
|
const out = {};
|
|
584
840
|
if (!input) return out;
|
|
@@ -587,6 +843,11 @@ function normalizeHeaders(input) {
|
|
|
587
843
|
});
|
|
588
844
|
return out;
|
|
589
845
|
}
|
|
846
|
+
function extractInputUrl(input) {
|
|
847
|
+
if (typeof input === "string") return input;
|
|
848
|
+
if (input instanceof URL) return input.href;
|
|
849
|
+
return input.url;
|
|
850
|
+
}
|
|
590
851
|
function createSandboxProxyFetch(connectionId) {
|
|
591
852
|
return async (input, init) => {
|
|
592
853
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -596,10 +857,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
596
857
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
597
858
|
);
|
|
598
859
|
}
|
|
599
|
-
const originalUrl =
|
|
860
|
+
const originalUrl = extractInputUrl(input);
|
|
861
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
862
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
863
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
864
|
+
return fetch(sessionUrl, {
|
|
865
|
+
method: "POST",
|
|
866
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
867
|
+
});
|
|
868
|
+
}
|
|
600
869
|
const originalMethod = init?.method ?? "GET";
|
|
601
870
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
602
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
603
871
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
604
872
|
return fetch(proxyUrl, {
|
|
605
873
|
method: "POST",
|
|
@@ -625,10 +893,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
625
893
|
}
|
|
626
894
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
627
895
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
896
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
628
897
|
return async (input, init) => {
|
|
629
|
-
const originalUrl =
|
|
630
|
-
const originalMethod = init?.method ?? "GET";
|
|
631
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
898
|
+
const originalUrl = extractInputUrl(input);
|
|
632
899
|
const c = getContext();
|
|
633
900
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
634
901
|
if (!appSession) {
|
|
@@ -636,6 +903,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
636
903
|
"No authentication method available for connection proxy."
|
|
637
904
|
);
|
|
638
905
|
}
|
|
906
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
907
|
+
return fetch(sessionUrl, {
|
|
908
|
+
method: "POST",
|
|
909
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
const originalMethod = init?.method ?? "GET";
|
|
913
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
639
914
|
return fetch(proxyUrl, {
|
|
640
915
|
method: "POST",
|
|
641
916
|
headers: {
|
|
@@ -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/anthropic/parameters.ts
|
|
57
|
+
init_parameter_definition();
|
|
46
58
|
var parameters = {
|
|
47
59
|
apiKey: new ParameterDefinition({
|
|
48
60
|
slug: "api-key",
|
|
@@ -83,6 +95,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
83
95
|
tools;
|
|
84
96
|
query;
|
|
85
97
|
checkConnection;
|
|
98
|
+
/**
|
|
99
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
100
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
101
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
102
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
103
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
104
|
+
*/
|
|
105
|
+
setup;
|
|
106
|
+
/**
|
|
107
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
108
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
109
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
110
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
111
|
+
*
|
|
112
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
113
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
114
|
+
* connectionId, which doesn't exist until the row is saved
|
|
115
|
+
*
|
|
116
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
117
|
+
* the default verify-on-create behavior without opt-in.
|
|
118
|
+
*/
|
|
119
|
+
skipConnectionCheckOnCreate;
|
|
86
120
|
constructor(config) {
|
|
87
121
|
this.slug = config.slug;
|
|
88
122
|
this.authType = config.authType;
|
|
@@ -99,6 +133,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
99
133
|
this.tools = config.tools;
|
|
100
134
|
this.query = config.query;
|
|
101
135
|
this.checkConnection = config.checkConnection;
|
|
136
|
+
this.setup = config.setup;
|
|
137
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
102
138
|
}
|
|
103
139
|
get connectorKey() {
|
|
104
140
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -234,7 +270,39 @@ export default async function handler(c: Context) {
|
|
|
234
270
|
}
|
|
235
271
|
\`\`\``
|
|
236
272
|
},
|
|
237
|
-
tools
|
|
273
|
+
tools,
|
|
274
|
+
async checkConnection(params, _config) {
|
|
275
|
+
try {
|
|
276
|
+
const apiKey = params[parameters.apiKey.slug];
|
|
277
|
+
if (!apiKey) {
|
|
278
|
+
return {
|
|
279
|
+
success: false,
|
|
280
|
+
error: "Missing required parameter: api-key"
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
const res = await fetch("https://api.anthropic.com/v1/models", {
|
|
284
|
+
method: "GET",
|
|
285
|
+
headers: {
|
|
286
|
+
"x-api-key": apiKey,
|
|
287
|
+
"anthropic-version": "2023-06-01",
|
|
288
|
+
Accept: "application/json"
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
if (!res.ok) {
|
|
292
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
error: `Anthropic API failed: HTTP ${res.status} ${errorText}`
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
return { success: true };
|
|
299
|
+
} catch (error) {
|
|
300
|
+
return {
|
|
301
|
+
success: false,
|
|
302
|
+
error: error instanceof Error ? error.message : String(error)
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
238
306
|
});
|
|
239
307
|
|
|
240
308
|
// src/connectors/create-connector-sdk.ts
|
|
@@ -263,6 +331,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
263
331
|
import { getContext } from "hono/context-storage";
|
|
264
332
|
import { getCookie } from "hono/cookie";
|
|
265
333
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
334
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
266
335
|
function normalizeHeaders(input) {
|
|
267
336
|
const out = {};
|
|
268
337
|
if (!input) return out;
|
|
@@ -271,6 +340,11 @@ function normalizeHeaders(input) {
|
|
|
271
340
|
});
|
|
272
341
|
return out;
|
|
273
342
|
}
|
|
343
|
+
function extractInputUrl(input) {
|
|
344
|
+
if (typeof input === "string") return input;
|
|
345
|
+
if (input instanceof URL) return input.href;
|
|
346
|
+
return input.url;
|
|
347
|
+
}
|
|
274
348
|
function createSandboxProxyFetch(connectionId) {
|
|
275
349
|
return async (input, init) => {
|
|
276
350
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -280,10 +354,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
280
354
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
281
355
|
);
|
|
282
356
|
}
|
|
283
|
-
const originalUrl =
|
|
357
|
+
const originalUrl = extractInputUrl(input);
|
|
358
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
359
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
360
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
361
|
+
return fetch(sessionUrl, {
|
|
362
|
+
method: "POST",
|
|
363
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
364
|
+
});
|
|
365
|
+
}
|
|
284
366
|
const originalMethod = init?.method ?? "GET";
|
|
285
367
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
286
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
287
368
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
288
369
|
return fetch(proxyUrl, {
|
|
289
370
|
method: "POST",
|
|
@@ -309,10 +390,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
309
390
|
}
|
|
310
391
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
311
392
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
393
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
312
394
|
return async (input, init) => {
|
|
313
|
-
const originalUrl =
|
|
314
|
-
const originalMethod = init?.method ?? "GET";
|
|
315
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
395
|
+
const originalUrl = extractInputUrl(input);
|
|
316
396
|
const c = getContext();
|
|
317
397
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
318
398
|
if (!appSession) {
|
|
@@ -320,6 +400,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
320
400
|
"No authentication method available for connection proxy."
|
|
321
401
|
);
|
|
322
402
|
}
|
|
403
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
404
|
+
return fetch(sessionUrl, {
|
|
405
|
+
method: "POST",
|
|
406
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
const originalMethod = init?.method ?? "GET";
|
|
410
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
323
411
|
return fetch(proxyUrl, {
|
|
324
412
|
method: "POST",
|
|
325
413
|
headers: {
|