@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/stripe-api-key/parameters.ts
|
|
57
|
+
init_parameter_definition();
|
|
46
58
|
var parameters = {
|
|
47
59
|
apiKey: new ParameterDefinition({
|
|
48
60
|
slug: "api-key",
|
|
@@ -133,6 +145,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
133
145
|
tools;
|
|
134
146
|
query;
|
|
135
147
|
checkConnection;
|
|
148
|
+
/**
|
|
149
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
150
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
151
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
152
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
153
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
154
|
+
*/
|
|
155
|
+
setup;
|
|
156
|
+
/**
|
|
157
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
158
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
159
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
160
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
161
|
+
*
|
|
162
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
163
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
164
|
+
* connectionId, which doesn't exist until the row is saved
|
|
165
|
+
*
|
|
166
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
167
|
+
* the default verify-on-create behavior without opt-in.
|
|
168
|
+
*/
|
|
169
|
+
skipConnectionCheckOnCreate;
|
|
136
170
|
constructor(config) {
|
|
137
171
|
this.slug = config.slug;
|
|
138
172
|
this.authType = config.authType;
|
|
@@ -149,6 +183,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
149
183
|
this.tools = config.tools;
|
|
150
184
|
this.query = config.query;
|
|
151
185
|
this.checkConnection = config.checkConnection;
|
|
186
|
+
this.setup = config.setup;
|
|
187
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
152
188
|
}
|
|
153
189
|
get connectorKey() {
|
|
154
190
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -213,6 +249,46 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
213
249
|
}
|
|
214
250
|
};
|
|
215
251
|
|
|
252
|
+
// ../connectors/src/setup-flow.ts
|
|
253
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
254
|
+
const runtime = {
|
|
255
|
+
params,
|
|
256
|
+
language: ctx.language,
|
|
257
|
+
config
|
|
258
|
+
};
|
|
259
|
+
let state = flow.initialState();
|
|
260
|
+
let answerIdx = 0;
|
|
261
|
+
for (const step of flow.steps) {
|
|
262
|
+
const ans = ctx.answers[answerIdx];
|
|
263
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
264
|
+
state = step.applyAnswer(state, ans.answer);
|
|
265
|
+
answerIdx += 1;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (step.type === "text") {
|
|
269
|
+
return {
|
|
270
|
+
type: "nextQuestion",
|
|
271
|
+
questionSlug: step.slug,
|
|
272
|
+
question: step.question[ctx.language],
|
|
273
|
+
questionType: "text"
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
277
|
+
if (options.length === 0) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
type: "nextQuestion",
|
|
282
|
+
questionSlug: step.slug,
|
|
283
|
+
question: step.question[ctx.language],
|
|
284
|
+
questionType: step.type,
|
|
285
|
+
options
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
289
|
+
return { type: "fulfilled", dataInvestigationResult };
|
|
290
|
+
}
|
|
291
|
+
|
|
216
292
|
// ../connectors/src/auth-types.ts
|
|
217
293
|
var AUTH_TYPES = {
|
|
218
294
|
OAUTH: "oauth",
|
|
@@ -352,6 +428,107 @@ var stripeApiKeyOnboarding = new ConnectorOnboarding({
|
|
|
352
428
|
}
|
|
353
429
|
});
|
|
354
430
|
|
|
431
|
+
// ../connectors/src/connectors/stripe-api-key/utils.ts
|
|
432
|
+
var BASE_URL3 = "https://api.stripe.com";
|
|
433
|
+
async function apiFetch(params, path2, init) {
|
|
434
|
+
const apiKey = params[parameters.apiKey.slug];
|
|
435
|
+
if (!apiKey) {
|
|
436
|
+
throw new Error("stripe-api-key: missing required parameter: api-key");
|
|
437
|
+
}
|
|
438
|
+
const url = `${BASE_URL3}${path2.startsWith("/") ? "" : "/"}${path2}`;
|
|
439
|
+
const headers = new Headers(init?.headers);
|
|
440
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
441
|
+
return fetch(url, { ...init, headers });
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// ../connectors/src/connectors/stripe-api-key/setup-flow.ts
|
|
445
|
+
var STRIPE_SETUP_MAX_ENTITIES = 10;
|
|
446
|
+
var ENTITY_LABELS = {
|
|
447
|
+
customers: { en: "Customers", ja: "Customers (\u9867\u5BA2)" },
|
|
448
|
+
charges: { en: "Charges", ja: "Charges (\u652F\u6255\u3044)" },
|
|
449
|
+
invoices: { en: "Invoices", ja: "Invoices (\u8ACB\u6C42\u66F8)" },
|
|
450
|
+
subscriptions: {
|
|
451
|
+
en: "Subscriptions",
|
|
452
|
+
ja: "Subscriptions (\u30B5\u30D6\u30B9\u30AF\u30EA\u30D7\u30B7\u30E7\u30F3)"
|
|
453
|
+
},
|
|
454
|
+
products: { en: "Products", ja: "Products (\u5546\u54C1)" },
|
|
455
|
+
prices: { en: "Prices", ja: "Prices (\u4FA1\u683C)" },
|
|
456
|
+
payouts: { en: "Payouts", ja: "Payouts (\u652F\u6255\u3044)" },
|
|
457
|
+
refunds: { en: "Refunds", ja: "Refunds (\u8FD4\u91D1)" },
|
|
458
|
+
disputes: { en: "Disputes", ja: "Disputes (\u7570\u8B70)" },
|
|
459
|
+
paymentIntents: {
|
|
460
|
+
en: "Payment intents",
|
|
461
|
+
ja: "Payment intents (\u652F\u6255\u3044\u30A4\u30F3\u30C6\u30F3\u30C8)"
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
var ENTITY_PATHS = {
|
|
465
|
+
customers: "/v1/customers?limit=1",
|
|
466
|
+
charges: "/v1/charges?limit=1",
|
|
467
|
+
invoices: "/v1/invoices?limit=1",
|
|
468
|
+
subscriptions: "/v1/subscriptions?limit=1",
|
|
469
|
+
products: "/v1/products?limit=1",
|
|
470
|
+
prices: "/v1/prices?limit=1",
|
|
471
|
+
payouts: "/v1/payouts?limit=1",
|
|
472
|
+
refunds: "/v1/refunds?limit=1",
|
|
473
|
+
disputes: "/v1/disputes?limit=1",
|
|
474
|
+
paymentIntents: "/v1/payment_intents?limit=1"
|
|
475
|
+
};
|
|
476
|
+
var ENTITY_VALUES = Object.keys(ENTITY_PATHS);
|
|
477
|
+
async function defaultFetchEntity(params, path2) {
|
|
478
|
+
return apiFetch(params, path2);
|
|
479
|
+
}
|
|
480
|
+
function createStripeSetupFlow(fetchEntity = defaultFetchEntity, labelPrefix = "Stripe") {
|
|
481
|
+
return {
|
|
482
|
+
initialState: () => ({}),
|
|
483
|
+
steps: [
|
|
484
|
+
{
|
|
485
|
+
slug: "entities",
|
|
486
|
+
type: "multiSelect",
|
|
487
|
+
question: {
|
|
488
|
+
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",
|
|
489
|
+
en: "Select target entities (multi-select allowed)"
|
|
490
|
+
},
|
|
491
|
+
async fetchOptions(_state, rt) {
|
|
492
|
+
return ENTITY_VALUES.map((value) => ({
|
|
493
|
+
value,
|
|
494
|
+
label: ENTITY_LABELS[value][rt.language]
|
|
495
|
+
}));
|
|
496
|
+
},
|
|
497
|
+
applyAnswer: (state, answer) => ({ ...state, entities: answer })
|
|
498
|
+
}
|
|
499
|
+
],
|
|
500
|
+
async finalize(state, rt) {
|
|
501
|
+
if (!state.entities) {
|
|
502
|
+
throw new Error("Stripe setup: incomplete state on finalize");
|
|
503
|
+
}
|
|
504
|
+
const selected = state.entities.filter(
|
|
505
|
+
(e) => ENTITY_VALUES.includes(e)
|
|
506
|
+
).slice(0, STRIPE_SETUP_MAX_ENTITIES);
|
|
507
|
+
const sections = [`## ${labelPrefix}`, ""];
|
|
508
|
+
for (const entity of selected) {
|
|
509
|
+
let count = "available";
|
|
510
|
+
const res = await fetchEntity(rt.params, ENTITY_PATHS[entity]);
|
|
511
|
+
if (res.ok) {
|
|
512
|
+
const data = await res.json();
|
|
513
|
+
if (Array.isArray(data.data) && data.data.length === 0) {
|
|
514
|
+
count = "0";
|
|
515
|
+
} else if (data.has_more === false) {
|
|
516
|
+
count = String(data.data?.length ?? 1);
|
|
517
|
+
} else if (Array.isArray(data.data)) {
|
|
518
|
+
count = "1+ (paginated)";
|
|
519
|
+
}
|
|
520
|
+
} else {
|
|
521
|
+
count = "unavailable";
|
|
522
|
+
}
|
|
523
|
+
sections.push(`### ${ENTITY_LABELS[entity].en}`, "");
|
|
524
|
+
sections.push(`Status: ${count}`, "");
|
|
525
|
+
}
|
|
526
|
+
return sections.join("\n");
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
var stripeApiKeySetupFlow = createStripeSetupFlow();
|
|
531
|
+
|
|
355
532
|
// ../connectors/src/connectors/stripe-api-key/index.ts
|
|
356
533
|
var tools = { request: requestTool };
|
|
357
534
|
var stripeApiKeyConnector = new ConnectorPlugin({
|
|
@@ -469,6 +646,7 @@ const data = await res.json();
|
|
|
469
646
|
\`\`\``
|
|
470
647
|
},
|
|
471
648
|
tools,
|
|
649
|
+
setup: (params, ctx, config) => runSetupFlow(stripeApiKeySetupFlow, params, ctx, config),
|
|
472
650
|
async checkConnection(params) {
|
|
473
651
|
try {
|
|
474
652
|
const apiKey = params["api-key"];
|
|
@@ -525,6 +703,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
525
703
|
import { getContext } from "hono/context-storage";
|
|
526
704
|
import { getCookie } from "hono/cookie";
|
|
527
705
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
706
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
528
707
|
function normalizeHeaders(input) {
|
|
529
708
|
const out = {};
|
|
530
709
|
if (!input) return out;
|
|
@@ -533,6 +712,11 @@ function normalizeHeaders(input) {
|
|
|
533
712
|
});
|
|
534
713
|
return out;
|
|
535
714
|
}
|
|
715
|
+
function extractInputUrl(input) {
|
|
716
|
+
if (typeof input === "string") return input;
|
|
717
|
+
if (input instanceof URL) return input.href;
|
|
718
|
+
return input.url;
|
|
719
|
+
}
|
|
536
720
|
function createSandboxProxyFetch(connectionId) {
|
|
537
721
|
return async (input, init) => {
|
|
538
722
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -542,10 +726,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
542
726
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
543
727
|
);
|
|
544
728
|
}
|
|
545
|
-
const originalUrl =
|
|
729
|
+
const originalUrl = extractInputUrl(input);
|
|
730
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
731
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
732
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
733
|
+
return fetch(sessionUrl, {
|
|
734
|
+
method: "POST",
|
|
735
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
736
|
+
});
|
|
737
|
+
}
|
|
546
738
|
const originalMethod = init?.method ?? "GET";
|
|
547
739
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
548
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
549
740
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
550
741
|
return fetch(proxyUrl, {
|
|
551
742
|
method: "POST",
|
|
@@ -571,10 +762,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
571
762
|
}
|
|
572
763
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
573
764
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
765
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
574
766
|
return async (input, init) => {
|
|
575
|
-
const originalUrl =
|
|
576
|
-
const originalMethod = init?.method ?? "GET";
|
|
577
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
767
|
+
const originalUrl = extractInputUrl(input);
|
|
578
768
|
const c = getContext();
|
|
579
769
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
580
770
|
if (!appSession) {
|
|
@@ -582,6 +772,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
582
772
|
"No authentication method available for connection proxy."
|
|
583
773
|
);
|
|
584
774
|
}
|
|
775
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
776
|
+
return fetch(sessionUrl, {
|
|
777
|
+
method: "POST",
|
|
778
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
const originalMethod = init?.method ?? "GET";
|
|
782
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
585
783
|
return fetch(proxyUrl, {
|
|
586
784
|
method: "POST",
|
|
587
785
|
headers: {
|
|
@@ -67,6 +67,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
67
67
|
tools;
|
|
68
68
|
query;
|
|
69
69
|
checkConnection;
|
|
70
|
+
/**
|
|
71
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
72
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
73
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
74
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
75
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
76
|
+
*/
|
|
77
|
+
setup;
|
|
78
|
+
/**
|
|
79
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
80
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
81
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
82
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
83
|
+
*
|
|
84
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
85
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
86
|
+
* connectionId, which doesn't exist until the row is saved
|
|
87
|
+
*
|
|
88
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
89
|
+
* the default verify-on-create behavior without opt-in.
|
|
90
|
+
*/
|
|
91
|
+
skipConnectionCheckOnCreate;
|
|
70
92
|
constructor(config) {
|
|
71
93
|
this.slug = config.slug;
|
|
72
94
|
this.authType = config.authType;
|
|
@@ -83,6 +105,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
83
105
|
this.tools = config.tools;
|
|
84
106
|
this.query = config.query;
|
|
85
107
|
this.checkConnection = config.checkConnection;
|
|
108
|
+
this.setup = config.setup;
|
|
109
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
86
110
|
}
|
|
87
111
|
get connectorKey() {
|
|
88
112
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -147,6 +171,46 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
147
171
|
}
|
|
148
172
|
};
|
|
149
173
|
|
|
174
|
+
// ../connectors/src/setup-flow.ts
|
|
175
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
176
|
+
const runtime = {
|
|
177
|
+
params,
|
|
178
|
+
language: ctx.language,
|
|
179
|
+
config
|
|
180
|
+
};
|
|
181
|
+
let state = flow.initialState();
|
|
182
|
+
let answerIdx = 0;
|
|
183
|
+
for (const step of flow.steps) {
|
|
184
|
+
const ans = ctx.answers[answerIdx];
|
|
185
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
186
|
+
state = step.applyAnswer(state, ans.answer);
|
|
187
|
+
answerIdx += 1;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (step.type === "text") {
|
|
191
|
+
return {
|
|
192
|
+
type: "nextQuestion",
|
|
193
|
+
questionSlug: step.slug,
|
|
194
|
+
question: step.question[ctx.language],
|
|
195
|
+
questionType: "text"
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
199
|
+
if (options.length === 0) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
type: "nextQuestion",
|
|
204
|
+
questionSlug: step.slug,
|
|
205
|
+
question: step.question[ctx.language],
|
|
206
|
+
questionType: step.type,
|
|
207
|
+
options
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
211
|
+
return { type: "fulfilled", dataInvestigationResult };
|
|
212
|
+
}
|
|
213
|
+
|
|
150
214
|
// ../connectors/src/auth-types.ts
|
|
151
215
|
var AUTH_TYPES = {
|
|
152
216
|
OAUTH: "oauth",
|
|
@@ -310,11 +374,98 @@ var stripeOnboarding = new ConnectorOnboarding({
|
|
|
310
374
|
// ../connectors/src/connectors/stripe-oauth/parameters.ts
|
|
311
375
|
var parameters = {};
|
|
312
376
|
|
|
377
|
+
// ../connectors/src/connectors/stripe-oauth/setup-flow.ts
|
|
378
|
+
var BASE_URL3 = "https://api.stripe.com";
|
|
379
|
+
var STRIPE_OAUTH_SETUP_MAX_ENTITIES = 10;
|
|
380
|
+
var ENTITY_LABELS = {
|
|
381
|
+
customers: { en: "Customers", ja: "Customers (\u9867\u5BA2)" },
|
|
382
|
+
charges: { en: "Charges", ja: "Charges (\u652F\u6255\u3044)" },
|
|
383
|
+
invoices: { en: "Invoices", ja: "Invoices (\u8ACB\u6C42\u66F8)" },
|
|
384
|
+
subscriptions: {
|
|
385
|
+
en: "Subscriptions",
|
|
386
|
+
ja: "Subscriptions (\u30B5\u30D6\u30B9\u30AF\u30EA\u30D7\u30B7\u30E7\u30F3)"
|
|
387
|
+
},
|
|
388
|
+
products: { en: "Products", ja: "Products (\u5546\u54C1)" },
|
|
389
|
+
prices: { en: "Prices", ja: "Prices (\u4FA1\u683C)" },
|
|
390
|
+
payouts: { en: "Payouts", ja: "Payouts (\u652F\u6255\u3044)" },
|
|
391
|
+
refunds: { en: "Refunds", ja: "Refunds (\u8FD4\u91D1)" },
|
|
392
|
+
disputes: { en: "Disputes", ja: "Disputes (\u7570\u8B70)" },
|
|
393
|
+
paymentIntents: {
|
|
394
|
+
en: "Payment intents",
|
|
395
|
+
ja: "Payment intents (\u652F\u6255\u3044\u30A4\u30F3\u30C6\u30F3\u30C8)"
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
var ENTITY_PATHS = {
|
|
399
|
+
customers: "/v1/customers?limit=1",
|
|
400
|
+
charges: "/v1/charges?limit=1",
|
|
401
|
+
invoices: "/v1/invoices?limit=1",
|
|
402
|
+
subscriptions: "/v1/subscriptions?limit=1",
|
|
403
|
+
products: "/v1/products?limit=1",
|
|
404
|
+
prices: "/v1/prices?limit=1",
|
|
405
|
+
payouts: "/v1/payouts?limit=1",
|
|
406
|
+
refunds: "/v1/refunds?limit=1",
|
|
407
|
+
disputes: "/v1/disputes?limit=1",
|
|
408
|
+
paymentIntents: "/v1/payment_intents?limit=1"
|
|
409
|
+
};
|
|
410
|
+
var ENTITY_VALUES = Object.keys(ENTITY_PATHS);
|
|
411
|
+
var stripeOauthSetupFlow = {
|
|
412
|
+
initialState: () => ({}),
|
|
413
|
+
steps: [
|
|
414
|
+
{
|
|
415
|
+
slug: "entities",
|
|
416
|
+
type: "multiSelect",
|
|
417
|
+
question: {
|
|
418
|
+
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",
|
|
419
|
+
en: "Select target entities (multi-select allowed)"
|
|
420
|
+
},
|
|
421
|
+
async fetchOptions(_state, rt) {
|
|
422
|
+
return ENTITY_VALUES.map((value) => ({
|
|
423
|
+
value,
|
|
424
|
+
label: ENTITY_LABELS[value][rt.language]
|
|
425
|
+
}));
|
|
426
|
+
},
|
|
427
|
+
applyAnswer: (state, answer) => ({ ...state, entities: answer })
|
|
428
|
+
}
|
|
429
|
+
],
|
|
430
|
+
async finalize(state, rt) {
|
|
431
|
+
if (!state.entities) {
|
|
432
|
+
throw new Error("Stripe setup: incomplete state on finalize");
|
|
433
|
+
}
|
|
434
|
+
const selected = state.entities.filter(
|
|
435
|
+
(e) => ENTITY_VALUES.includes(e)
|
|
436
|
+
).slice(0, STRIPE_OAUTH_SETUP_MAX_ENTITIES);
|
|
437
|
+
const sections = ["## Stripe", ""];
|
|
438
|
+
for (const entity of selected) {
|
|
439
|
+
let count = "available";
|
|
440
|
+
const res = await rt.config.proxyFetch(
|
|
441
|
+
`${BASE_URL3}${ENTITY_PATHS[entity]}`,
|
|
442
|
+
{ method: "GET" }
|
|
443
|
+
);
|
|
444
|
+
if (res.ok) {
|
|
445
|
+
const data = await res.json();
|
|
446
|
+
if (Array.isArray(data.data) && data.data.length === 0) {
|
|
447
|
+
count = "0";
|
|
448
|
+
} else if (data.has_more === false) {
|
|
449
|
+
count = String(data.data?.length ?? 1);
|
|
450
|
+
} else if (Array.isArray(data.data)) {
|
|
451
|
+
count = "1+ (paginated)";
|
|
452
|
+
}
|
|
453
|
+
} else {
|
|
454
|
+
count = "unavailable";
|
|
455
|
+
}
|
|
456
|
+
sections.push(`### ${ENTITY_LABELS[entity].en}`, "");
|
|
457
|
+
sections.push(`Status: ${count}`, "");
|
|
458
|
+
}
|
|
459
|
+
return sections.join("\n");
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
313
463
|
// ../connectors/src/connectors/stripe-oauth/index.ts
|
|
314
464
|
var tools = { request: requestTool };
|
|
315
465
|
var stripeOauthConnector = new ConnectorPlugin({
|
|
316
466
|
slug: "stripe",
|
|
317
467
|
authType: AUTH_TYPES.OAUTH,
|
|
468
|
+
skipConnectionCheckOnCreate: true,
|
|
318
469
|
name: "Stripe",
|
|
319
470
|
description: "Connect to Stripe for payment, customer, and subscription data using OAuth.",
|
|
320
471
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2QNK0u2doqp41uL0POS4Ks/7a92367e2388ec77c7f4ada143606f9a/stripe.jpeg",
|
|
@@ -431,6 +582,7 @@ const data = await res.json();
|
|
|
431
582
|
\`\`\``
|
|
432
583
|
},
|
|
433
584
|
tools,
|
|
585
|
+
setup: (params, ctx, config) => runSetupFlow(stripeOauthSetupFlow, params, ctx, config),
|
|
434
586
|
async checkConnection(_params, config) {
|
|
435
587
|
const { proxyFetch } = config;
|
|
436
588
|
try {
|
|
@@ -480,6 +632,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
480
632
|
import { getContext } from "hono/context-storage";
|
|
481
633
|
import { getCookie } from "hono/cookie";
|
|
482
634
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
635
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
483
636
|
function normalizeHeaders(input) {
|
|
484
637
|
const out = {};
|
|
485
638
|
if (!input) return out;
|
|
@@ -488,6 +641,11 @@ function normalizeHeaders(input) {
|
|
|
488
641
|
});
|
|
489
642
|
return out;
|
|
490
643
|
}
|
|
644
|
+
function extractInputUrl(input) {
|
|
645
|
+
if (typeof input === "string") return input;
|
|
646
|
+
if (input instanceof URL) return input.href;
|
|
647
|
+
return input.url;
|
|
648
|
+
}
|
|
491
649
|
function createSandboxProxyFetch(connectionId) {
|
|
492
650
|
return async (input, init) => {
|
|
493
651
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -497,10 +655,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
497
655
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
498
656
|
);
|
|
499
657
|
}
|
|
500
|
-
const originalUrl =
|
|
658
|
+
const originalUrl = extractInputUrl(input);
|
|
659
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
660
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
661
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
662
|
+
return fetch(sessionUrl, {
|
|
663
|
+
method: "POST",
|
|
664
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
665
|
+
});
|
|
666
|
+
}
|
|
501
667
|
const originalMethod = init?.method ?? "GET";
|
|
502
668
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
503
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
504
669
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
505
670
|
return fetch(proxyUrl, {
|
|
506
671
|
method: "POST",
|
|
@@ -526,10 +691,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
526
691
|
}
|
|
527
692
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
528
693
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
694
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
529
695
|
return async (input, init) => {
|
|
530
|
-
const originalUrl =
|
|
531
|
-
const originalMethod = init?.method ?? "GET";
|
|
532
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
696
|
+
const originalUrl = extractInputUrl(input);
|
|
533
697
|
const c = getContext();
|
|
534
698
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
535
699
|
if (!appSession) {
|
|
@@ -537,6 +701,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
537
701
|
"No authentication method available for connection proxy."
|
|
538
702
|
);
|
|
539
703
|
}
|
|
704
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
705
|
+
return fetch(sessionUrl, {
|
|
706
|
+
method: "POST",
|
|
707
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
const originalMethod = init?.method ?? "GET";
|
|
711
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
540
712
|
return fetch(proxyUrl, {
|
|
541
713
|
method: "POST",
|
|
542
714
|
headers: {
|