@squadbase/vite-server 0.1.12-dev.822582a → 0.1.12-dev.93b8799
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 +343 -46
- package/dist/connectors/airtable-oauth.js +9 -0
- package/dist/connectors/airtable.js +9 -0
- package/dist/connectors/amplitude.js +9 -0
- package/dist/connectors/anthropic.js +9 -0
- package/dist/connectors/asana.js +9 -0
- package/dist/connectors/attio.js +9 -0
- package/dist/connectors/aws-billing.js +9 -0
- package/dist/connectors/azure-sql.js +9 -0
- package/dist/connectors/backlog-api-key.js +9 -0
- package/dist/connectors/clickup.js +9 -0
- package/dist/connectors/cosmosdb.js +9 -0
- package/dist/connectors/customerio.js +9 -0
- package/dist/connectors/dbt.js +9 -0
- package/dist/connectors/freshdesk.js +9 -0
- package/dist/connectors/freshsales.js +9 -0
- package/dist/connectors/freshservice.js +9 -0
- package/dist/connectors/gamma.js +9 -0
- package/dist/connectors/gemini.js +9 -0
- package/dist/connectors/github.js +9 -0
- package/dist/connectors/gmail-oauth.js +9 -0
- package/dist/connectors/gmail.js +9 -0
- package/dist/connectors/google-ads.js +9 -0
- package/dist/connectors/google-analytics-oauth.js +9 -0
- package/dist/connectors/google-analytics.js +9 -0
- package/dist/connectors/google-audit-log.js +9 -0
- package/dist/connectors/google-calendar-oauth.js +9 -0
- package/dist/connectors/google-calendar.js +9 -0
- package/dist/connectors/google-docs.js +9 -0
- package/dist/connectors/google-drive.js +9 -0
- package/dist/connectors/google-search-console-oauth.js +9 -0
- package/dist/connectors/google-sheets.js +9 -0
- package/dist/connectors/google-slides.js +9 -0
- package/dist/connectors/grafana.js +9 -0
- package/dist/connectors/hubspot-oauth.js +9 -0
- package/dist/connectors/hubspot.js +9 -0
- package/dist/connectors/influxdb.js +9 -0
- package/dist/connectors/intercom-oauth.js +9 -0
- package/dist/connectors/intercom.js +9 -0
- package/dist/connectors/jdbc.js +9 -0
- package/dist/connectors/jira-api-key.js +9 -0
- package/dist/connectors/kintone-api-token.js +9 -0
- package/dist/connectors/kintone.js +9 -0
- package/dist/connectors/linear.js +9 -0
- package/dist/connectors/linkedin-ads.js +9 -0
- package/dist/connectors/mailchimp-oauth.js +9 -0
- package/dist/connectors/mailchimp.js +9 -0
- package/dist/connectors/meta-ads-oauth.js +9 -0
- package/dist/connectors/meta-ads.js +9 -0
- package/dist/connectors/mixpanel.js +9 -0
- package/dist/connectors/monday.js +9 -0
- package/dist/connectors/mongodb.js +9 -0
- package/dist/connectors/notion-oauth.js +9 -0
- package/dist/connectors/notion.js +9 -0
- package/dist/connectors/openai.js +9 -0
- package/dist/connectors/oracle.js +9 -0
- package/dist/connectors/outlook-oauth.js +9 -0
- package/dist/connectors/powerbi-oauth.js +9 -0
- package/dist/connectors/salesforce.js +9 -0
- package/dist/connectors/semrush.js +9 -0
- package/dist/connectors/sentry.js +9 -0
- package/dist/connectors/shopify-oauth.js +9 -0
- package/dist/connectors/shopify.js +9 -0
- package/dist/connectors/sqlserver.js +9 -0
- package/dist/connectors/stripe-api-key.js +9 -0
- package/dist/connectors/stripe-oauth.js +9 -0
- package/dist/connectors/supabase.js +9 -0
- package/dist/connectors/tableau.js +129 -55
- package/dist/connectors/tiktok-ads.js +9 -0
- package/dist/connectors/wix-store.js +9 -0
- package/dist/connectors/zendesk-oauth.js +9 -0
- package/dist/connectors/zendesk.js +9 -0
- package/dist/index.js +343 -46
- package/dist/main.js +343 -46
- package/dist/vite-plugin.js +343 -46
- package/package.json +1 -1
package/dist/vite-plugin.js
CHANGED
|
@@ -118,6 +118,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
118
118
|
tools;
|
|
119
119
|
query;
|
|
120
120
|
checkConnection;
|
|
121
|
+
/**
|
|
122
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
123
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
124
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
125
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
126
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
127
|
+
*/
|
|
128
|
+
setup;
|
|
121
129
|
constructor(config) {
|
|
122
130
|
this.slug = config.slug;
|
|
123
131
|
this.authType = config.authType;
|
|
@@ -134,6 +142,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
134
142
|
this.tools = config.tools;
|
|
135
143
|
this.query = config.query;
|
|
136
144
|
this.checkConnection = config.checkConnection;
|
|
145
|
+
this.setup = config.setup;
|
|
137
146
|
}
|
|
138
147
|
get connectorKey() {
|
|
139
148
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -198,6 +207,50 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
198
207
|
}
|
|
199
208
|
};
|
|
200
209
|
|
|
210
|
+
// ../connectors/src/setup-flow.ts
|
|
211
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
212
|
+
const runtime = {
|
|
213
|
+
params,
|
|
214
|
+
language: ctx.language,
|
|
215
|
+
config
|
|
216
|
+
};
|
|
217
|
+
let state = flow.initialState();
|
|
218
|
+
let answerIdx = 0;
|
|
219
|
+
for (const step of flow.steps) {
|
|
220
|
+
const ans = ctx.answers[answerIdx];
|
|
221
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
222
|
+
state = step.applyAnswer(state, ans.answer);
|
|
223
|
+
answerIdx += 1;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (step.type === "text") {
|
|
227
|
+
return {
|
|
228
|
+
type: "nextQuestion",
|
|
229
|
+
questionSlug: step.slug,
|
|
230
|
+
question: step.question[ctx.language],
|
|
231
|
+
questionType: "text"
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
235
|
+
if (options.length === 0) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
if (step.autoSelectIfSingle && options.length === 1) {
|
|
239
|
+
state = step.applyAnswer(state, [options[0].value]);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
type: "nextQuestion",
|
|
244
|
+
questionSlug: step.slug,
|
|
245
|
+
question: step.question[ctx.language],
|
|
246
|
+
questionType: "multiSelect",
|
|
247
|
+
options
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
251
|
+
return { type: "fulfilled", dataInvestigationResult };
|
|
252
|
+
}
|
|
253
|
+
|
|
201
254
|
// ../connectors/src/auth-types.ts
|
|
202
255
|
var AUTH_TYPES = {
|
|
203
256
|
OAUTH: "oauth",
|
|
@@ -359,6 +412,125 @@ var parameters = {
|
|
|
359
412
|
})
|
|
360
413
|
};
|
|
361
414
|
|
|
415
|
+
// ../connectors/src/connectors/snowflake/setup-flow.ts
|
|
416
|
+
var ALL_TABLES = "__ALL_TABLES__";
|
|
417
|
+
var INTERNAL_SCHEMAS = /* @__PURE__ */ new Set([
|
|
418
|
+
"INFORMATION_SCHEMA",
|
|
419
|
+
"ACCOUNT_USAGE",
|
|
420
|
+
"READER_ACCOUNT_USAGE",
|
|
421
|
+
"DATA_SHARING_USAGE"
|
|
422
|
+
]);
|
|
423
|
+
function createSnowflakeSetupFlow(runQuery3) {
|
|
424
|
+
return {
|
|
425
|
+
initialState: () => ({}),
|
|
426
|
+
steps: [
|
|
427
|
+
{
|
|
428
|
+
slug: "database",
|
|
429
|
+
type: "multiSelect",
|
|
430
|
+
autoSelectIfSingle: true,
|
|
431
|
+
question: {
|
|
432
|
+
ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF081 \u4EF6\u306E\u307F\uFF09",
|
|
433
|
+
en: "Select the database to use for setup (pick one)"
|
|
434
|
+
},
|
|
435
|
+
async fetchOptions(_state, rt) {
|
|
436
|
+
const rows = await runQuery3(rt.params, "SHOW DATABASES");
|
|
437
|
+
return rows.map((r) => String(r["name"] ?? "")).filter((name) => name && !name.endsWith("_SHARE")).map((value) => ({ value }));
|
|
438
|
+
},
|
|
439
|
+
applyAnswer: (state, answer) => ({ ...state, database: answer[0] })
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
slug: "schema",
|
|
443
|
+
type: "multiSelect",
|
|
444
|
+
autoSelectIfSingle: true,
|
|
445
|
+
question: {
|
|
446
|
+
ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u30B9\u30AD\u30FC\u30DE\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF081 \u4EF6\u306E\u307F\uFF09",
|
|
447
|
+
en: "Select the schema to use for setup (pick one)"
|
|
448
|
+
},
|
|
449
|
+
async fetchOptions(state, rt) {
|
|
450
|
+
if (!state.database) return [];
|
|
451
|
+
const rows = await runQuery3(
|
|
452
|
+
rt.params,
|
|
453
|
+
`SHOW SCHEMAS IN DATABASE "${state.database}"`
|
|
454
|
+
);
|
|
455
|
+
return rows.map((r) => String(r["name"] ?? "")).filter(
|
|
456
|
+
(name) => name && !INTERNAL_SCHEMAS.has(name.toUpperCase())
|
|
457
|
+
).map((value) => ({ value }));
|
|
458
|
+
},
|
|
459
|
+
applyAnswer: (state, answer) => ({ ...state, schema: answer[0] })
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
slug: "tables",
|
|
463
|
+
type: "multiSelect",
|
|
464
|
+
question: {
|
|
465
|
+
ja: "\u5BFE\u8C61\u30C6\u30FC\u30D6\u30EB\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
466
|
+
en: "Select target tables (multi-select allowed)"
|
|
467
|
+
},
|
|
468
|
+
async fetchOptions(state, rt) {
|
|
469
|
+
if (!state.database || !state.schema) return [];
|
|
470
|
+
const rows = await runQuery3(
|
|
471
|
+
rt.params,
|
|
472
|
+
`SHOW TABLES IN SCHEMA "${state.database}"."${state.schema}"`
|
|
473
|
+
);
|
|
474
|
+
const tableOptions = rows.map((r) => String(r["name"] ?? "")).filter((name) => name).map((value) => ({ value }));
|
|
475
|
+
return [
|
|
476
|
+
{
|
|
477
|
+
value: ALL_TABLES,
|
|
478
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C6\u30FC\u30D6\u30EB" : "All tables"
|
|
479
|
+
},
|
|
480
|
+
...tableOptions
|
|
481
|
+
];
|
|
482
|
+
},
|
|
483
|
+
applyAnswer: (state, answer) => ({ ...state, tables: answer })
|
|
484
|
+
}
|
|
485
|
+
],
|
|
486
|
+
async finalize(state, rt) {
|
|
487
|
+
if (!state.database || !state.schema || !state.tables) {
|
|
488
|
+
throw new Error("Snowflake setup: incomplete state on finalize");
|
|
489
|
+
}
|
|
490
|
+
const db = state.database;
|
|
491
|
+
const schema = state.schema;
|
|
492
|
+
let targetTables;
|
|
493
|
+
if (state.tables.includes(ALL_TABLES)) {
|
|
494
|
+
const rows = await runQuery3(
|
|
495
|
+
rt.params,
|
|
496
|
+
`SHOW TABLES IN SCHEMA "${db}"."${schema}"`
|
|
497
|
+
);
|
|
498
|
+
targetTables = rows.map((r) => String(r["name"] ?? "")).filter((name) => name);
|
|
499
|
+
} else {
|
|
500
|
+
targetTables = state.tables.filter((t) => t !== ALL_TABLES);
|
|
501
|
+
}
|
|
502
|
+
const sections = [
|
|
503
|
+
"## Snowflake",
|
|
504
|
+
"",
|
|
505
|
+
`### Database: ${db}`,
|
|
506
|
+
"",
|
|
507
|
+
`#### Schema: ${schema}`,
|
|
508
|
+
""
|
|
509
|
+
];
|
|
510
|
+
for (const table of targetTables) {
|
|
511
|
+
const cols = await runQuery3(
|
|
512
|
+
rt.params,
|
|
513
|
+
`DESCRIBE TABLE "${db}"."${schema}"."${table}"`
|
|
514
|
+
);
|
|
515
|
+
sections.push(`##### Table: ${table}`, "");
|
|
516
|
+
sections.push("| Column | Type | Nullable | Default |");
|
|
517
|
+
sections.push("|--------|------|----------|---------|");
|
|
518
|
+
for (const c of cols) {
|
|
519
|
+
const name = String(c["name"] ?? "");
|
|
520
|
+
const type = String(c["type"] ?? "");
|
|
521
|
+
const nullable = String(c["null?"] ?? "");
|
|
522
|
+
const defaultValue = c["default"] == null ? "-" : String(c["default"]);
|
|
523
|
+
sections.push(
|
|
524
|
+
`| ${name} | ${type} | ${nullable} | ${defaultValue} |`
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
sections.push("");
|
|
528
|
+
}
|
|
529
|
+
return sections.join("\n");
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
362
534
|
// ../connectors/src/connectors/snowflake/tools/execute-query.ts
|
|
363
535
|
import { z } from "zod";
|
|
364
536
|
|
|
@@ -403,6 +575,49 @@ function decryptPrivateKey(pem, passphrase) {
|
|
|
403
575
|
passphrase
|
|
404
576
|
}).export({ type: "pkcs8", format: "pem" });
|
|
405
577
|
}
|
|
578
|
+
async function runQuery(params, sql) {
|
|
579
|
+
const snowflake = (await import("snowflake-sdk")).default;
|
|
580
|
+
snowflake.configure({ logLevel: "ERROR" });
|
|
581
|
+
const privateKeyPem = Buffer.from(
|
|
582
|
+
params[parameters.privateKeyBase64.slug],
|
|
583
|
+
"base64"
|
|
584
|
+
).toString("utf-8");
|
|
585
|
+
const privateKeyPass = params[parameters.privateKeyPassphrase.slug] || void 0;
|
|
586
|
+
const privateKey = decryptPrivateKey(privateKeyPem, privateKeyPass);
|
|
587
|
+
const conn = snowflake.createConnection({
|
|
588
|
+
account: params[parameters.account.slug],
|
|
589
|
+
username: params[parameters.user.slug],
|
|
590
|
+
role: params[parameters.role.slug],
|
|
591
|
+
warehouse: params[parameters.warehouse.slug],
|
|
592
|
+
authenticator: "SNOWFLAKE_JWT",
|
|
593
|
+
privateKey
|
|
594
|
+
});
|
|
595
|
+
await new Promise((resolve, reject) => {
|
|
596
|
+
conn.connect((err) => {
|
|
597
|
+
if (err) reject(new Error(`Snowflake connect failed: ${err.message}`));
|
|
598
|
+
else resolve();
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
try {
|
|
602
|
+
return await new Promise((resolve, reject) => {
|
|
603
|
+
conn.execute({
|
|
604
|
+
sqlText: sql,
|
|
605
|
+
complete: (err, _stmt, rows) => {
|
|
606
|
+
if (err) reject(new Error(`Snowflake query failed: ${err.message}`));
|
|
607
|
+
else resolve(rows ?? []);
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
} finally {
|
|
612
|
+
conn.destroy((err) => {
|
|
613
|
+
if (err) {
|
|
614
|
+
console.warn(
|
|
615
|
+
`[connector-query] Snowflake destroy error: ${err.message}`
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
}
|
|
406
621
|
async function executeWithSizeLimit(conn, sql, options) {
|
|
407
622
|
const rows = [];
|
|
408
623
|
let acc = 0;
|
|
@@ -557,6 +772,7 @@ Memory guidance:
|
|
|
557
772
|
});
|
|
558
773
|
|
|
559
774
|
// ../connectors/src/connectors/snowflake/index.ts
|
|
775
|
+
var snowflakeSetupFlow = createSnowflakeSetupFlow(runQuery);
|
|
560
776
|
var tools = { executeQuery: executeQueryTool };
|
|
561
777
|
var snowflakeConnector = new ConnectorPlugin({
|
|
562
778
|
slug: "snowflake",
|
|
@@ -603,6 +819,7 @@ The business logic type for this connector is "sql".
|
|
|
603
819
|
- INFORMATION_SCHEMA \u3082\u5229\u7528\u53EF\u80FD: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``
|
|
604
820
|
},
|
|
605
821
|
tools,
|
|
822
|
+
setup: (params, ctx, config) => runSetupFlow(snowflakeSetupFlow, params, ctx, config),
|
|
606
823
|
async checkConnection(params, _config) {
|
|
607
824
|
try {
|
|
608
825
|
const snowflake = (await import("snowflake-sdk")).default;
|
|
@@ -735,6 +952,47 @@ var parameters2 = {
|
|
|
735
952
|
})
|
|
736
953
|
};
|
|
737
954
|
|
|
955
|
+
// ../connectors/src/connectors/snowflake-pat/utils.ts
|
|
956
|
+
async function runQuery2(params, sql) {
|
|
957
|
+
const snowflake = (await import("snowflake-sdk")).default;
|
|
958
|
+
snowflake.configure({ logLevel: "ERROR" });
|
|
959
|
+
const conn = snowflake.createConnection({
|
|
960
|
+
account: params[parameters2.account.slug],
|
|
961
|
+
username: params[parameters2.user.slug],
|
|
962
|
+
role: params[parameters2.role.slug],
|
|
963
|
+
warehouse: params[parameters2.warehouse.slug],
|
|
964
|
+
password: params[parameters2.pat.slug]
|
|
965
|
+
});
|
|
966
|
+
await new Promise((resolve, reject) => {
|
|
967
|
+
conn.connect((err) => {
|
|
968
|
+
if (err) reject(new Error(`Snowflake connect failed: ${err.message}`));
|
|
969
|
+
else resolve();
|
|
970
|
+
});
|
|
971
|
+
});
|
|
972
|
+
try {
|
|
973
|
+
return await new Promise((resolve, reject) => {
|
|
974
|
+
conn.execute({
|
|
975
|
+
sqlText: sql,
|
|
976
|
+
complete: (err, _stmt, rows) => {
|
|
977
|
+
if (err) reject(new Error(`Snowflake query failed: ${err.message}`));
|
|
978
|
+
else resolve(rows ?? []);
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
});
|
|
982
|
+
} finally {
|
|
983
|
+
conn.destroy((err) => {
|
|
984
|
+
if (err) {
|
|
985
|
+
console.warn(
|
|
986
|
+
`[connector-query] Snowflake destroy error: ${err.message}`
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// ../connectors/src/connectors/snowflake-pat/setup-flow.ts
|
|
994
|
+
var snowflakePatSetupFlow = createSnowflakeSetupFlow(runQuery2);
|
|
995
|
+
|
|
738
996
|
// ../connectors/src/connectors/snowflake-pat/tools/execute-query.ts
|
|
739
997
|
import { z as z2 } from "zod";
|
|
740
998
|
var MAX_ROWS = 500;
|
|
@@ -887,6 +1145,7 @@ The business logic type for this connector is "sql".
|
|
|
887
1145
|
- INFORMATION_SCHEMA \u3082\u5229\u7528\u53EF\u80FD: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``
|
|
888
1146
|
},
|
|
889
1147
|
tools: tools2,
|
|
1148
|
+
setup: (params, ctx, config) => runSetupFlow(snowflakePatSetupFlow, params, ctx, config),
|
|
890
1149
|
async checkConnection(params, _config) {
|
|
891
1150
|
try {
|
|
892
1151
|
const snowflake = (await import("snowflake-sdk")).default;
|
|
@@ -27962,6 +28221,10 @@ import { z as z98 } from "zod";
|
|
|
27962
28221
|
var DEFAULT_API_VERSION = "3.28";
|
|
27963
28222
|
var REQUEST_TIMEOUT_MS75 = 6e4;
|
|
27964
28223
|
var sessionCache = /* @__PURE__ */ new Map();
|
|
28224
|
+
var inFlightSignIns = /* @__PURE__ */ new Map();
|
|
28225
|
+
function sessionCacheKey(serverUrl, siteContentUrl, patName) {
|
|
28226
|
+
return `${serverUrl}|${siteContentUrl}|${patName}`;
|
|
28227
|
+
}
|
|
27965
28228
|
function buildBaseUrl4(serverUrl, apiVersion) {
|
|
27966
28229
|
return `${serverUrl.replace(/\/$/, "")}/api/${apiVersion}`;
|
|
27967
28230
|
}
|
|
@@ -27996,21 +28259,39 @@ async function signIn(serverUrl, apiVersion, siteContentUrl, patName, patSecret)
|
|
|
27996
28259
|
expiresAt: Date.now() + 30 * 60 * 1e3
|
|
27997
28260
|
};
|
|
27998
28261
|
}
|
|
27999
|
-
async function getSession(serverUrl, apiVersion, siteContentUrl, patName, patSecret) {
|
|
28000
|
-
const cacheKey =
|
|
28001
|
-
|
|
28002
|
-
|
|
28003
|
-
|
|
28262
|
+
async function getSession(serverUrl, apiVersion, siteContentUrl, patName, patSecret, { forceRefresh = false } = {}) {
|
|
28263
|
+
const cacheKey = sessionCacheKey(serverUrl, siteContentUrl, patName);
|
|
28264
|
+
if (forceRefresh) {
|
|
28265
|
+
sessionCache.delete(cacheKey);
|
|
28266
|
+
} else {
|
|
28267
|
+
const cached = sessionCache.get(cacheKey);
|
|
28268
|
+
if (cached && cached.expiresAt > Date.now() + 6e4) {
|
|
28269
|
+
return cached;
|
|
28270
|
+
}
|
|
28004
28271
|
}
|
|
28005
|
-
const
|
|
28272
|
+
const existing = inFlightSignIns.get(cacheKey);
|
|
28273
|
+
if (existing) return existing;
|
|
28274
|
+
const promise = signIn(
|
|
28006
28275
|
serverUrl,
|
|
28007
28276
|
apiVersion,
|
|
28008
28277
|
siteContentUrl,
|
|
28009
28278
|
patName,
|
|
28010
28279
|
patSecret
|
|
28011
|
-
)
|
|
28012
|
-
|
|
28013
|
-
|
|
28280
|
+
).then((session) => {
|
|
28281
|
+
sessionCache.set(cacheKey, session);
|
|
28282
|
+
return session;
|
|
28283
|
+
}).finally(() => {
|
|
28284
|
+
inFlightSignIns.delete(cacheKey);
|
|
28285
|
+
});
|
|
28286
|
+
inFlightSignIns.set(cacheKey, promise);
|
|
28287
|
+
return promise;
|
|
28288
|
+
}
|
|
28289
|
+
function invalidateSession(serverUrl, siteContentUrl, patName, staleAuthToken) {
|
|
28290
|
+
const cacheKey = sessionCacheKey(serverUrl, siteContentUrl, patName);
|
|
28291
|
+
const current = sessionCache.get(cacheKey);
|
|
28292
|
+
if (current && current.authToken === staleAuthToken) {
|
|
28293
|
+
sessionCache.delete(cacheKey);
|
|
28294
|
+
}
|
|
28014
28295
|
}
|
|
28015
28296
|
var inputSchema98 = z98.object({
|
|
28016
28297
|
toolUseIntent: z98.string().optional().describe(
|
|
@@ -28066,48 +28347,64 @@ Accept and Content-Type headers default to application/json so list responses co
|
|
|
28066
28347
|
const patName = parameters81.patName.getValue(connection);
|
|
28067
28348
|
const patSecret = parameters81.patSecret.getValue(connection);
|
|
28068
28349
|
const apiVersion = parameters81.apiVersion.tryGetValue(connection) || DEFAULT_API_VERSION;
|
|
28069
|
-
const
|
|
28070
|
-
|
|
28071
|
-
|
|
28072
|
-
siteContentUrl,
|
|
28073
|
-
patName,
|
|
28074
|
-
patSecret
|
|
28075
|
-
);
|
|
28076
|
-
const resolvedPath = path4.trim().replace(/\{siteId\}/g, session.siteId).replace(/^([^/])/, "/$1");
|
|
28077
|
-
let url = `${buildBaseUrl4(serverUrl, apiVersion)}${resolvedPath}`;
|
|
28078
|
-
if (queryParams) {
|
|
28079
|
-
const searchParams = new URLSearchParams(queryParams);
|
|
28080
|
-
url += `?${searchParams.toString()}`;
|
|
28081
|
-
}
|
|
28350
|
+
const trimmedPath = path4.trim().replace(/^([^/])/, "/$1");
|
|
28351
|
+
const queryString = queryParams ? `?${new URLSearchParams(queryParams).toString()}` : "";
|
|
28352
|
+
const baseUrl = buildBaseUrl4(serverUrl, apiVersion);
|
|
28082
28353
|
const controller = new AbortController();
|
|
28083
28354
|
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS75);
|
|
28084
28355
|
try {
|
|
28085
|
-
|
|
28086
|
-
|
|
28087
|
-
|
|
28088
|
-
|
|
28089
|
-
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
28095
|
-
|
|
28096
|
-
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
28100
|
-
|
|
28101
|
-
|
|
28102
|
-
|
|
28103
|
-
|
|
28356
|
+
let attempt = 0;
|
|
28357
|
+
while (true) {
|
|
28358
|
+
const session = await getSession(
|
|
28359
|
+
serverUrl,
|
|
28360
|
+
apiVersion,
|
|
28361
|
+
siteContentUrl,
|
|
28362
|
+
patName,
|
|
28363
|
+
patSecret,
|
|
28364
|
+
{ forceRefresh: attempt > 0 }
|
|
28365
|
+
);
|
|
28366
|
+
const resolvedPath = trimmedPath.replace(
|
|
28367
|
+
/\{siteId\}/g,
|
|
28368
|
+
session.siteId
|
|
28369
|
+
);
|
|
28370
|
+
const url = `${baseUrl}${resolvedPath}${queryString}`;
|
|
28371
|
+
const init = {
|
|
28372
|
+
method,
|
|
28373
|
+
headers: {
|
|
28374
|
+
"X-Tableau-Auth": session.authToken,
|
|
28375
|
+
Accept: "application/json",
|
|
28376
|
+
"Content-Type": "application/json"
|
|
28377
|
+
},
|
|
28378
|
+
signal: controller.signal
|
|
28379
|
+
};
|
|
28380
|
+
if (body !== void 0) {
|
|
28381
|
+
init.body = JSON.stringify(body);
|
|
28104
28382
|
}
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
const
|
|
28108
|
-
|
|
28383
|
+
const response = await fetch(url, init);
|
|
28384
|
+
const text = await response.text();
|
|
28385
|
+
const data = text ? (() => {
|
|
28386
|
+
try {
|
|
28387
|
+
return JSON.parse(text);
|
|
28388
|
+
} catch {
|
|
28389
|
+
return text;
|
|
28390
|
+
}
|
|
28391
|
+
})() : null;
|
|
28392
|
+
if (response.status === 401 && attempt === 0) {
|
|
28393
|
+
invalidateSession(
|
|
28394
|
+
serverUrl,
|
|
28395
|
+
siteContentUrl,
|
|
28396
|
+
patName,
|
|
28397
|
+
session.authToken
|
|
28398
|
+
);
|
|
28399
|
+
attempt++;
|
|
28400
|
+
continue;
|
|
28401
|
+
}
|
|
28402
|
+
if (!response.ok) {
|
|
28403
|
+
const errorMessage = data && typeof data === "object" && "error" in data ? JSON.stringify(data.error) : typeof data === "string" && data ? data : `HTTP ${response.status} ${response.statusText}`;
|
|
28404
|
+
return { success: false, error: errorMessage };
|
|
28405
|
+
}
|
|
28406
|
+
return { success: true, status: response.status, data };
|
|
28109
28407
|
}
|
|
28110
|
-
return { success: true, status: response.status, data };
|
|
28111
28408
|
} finally {
|
|
28112
28409
|
clearTimeout(timeout);
|
|
28113
28410
|
}
|