@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.
Files changed (76) hide show
  1. package/dist/cli/index.js +343 -46
  2. package/dist/connectors/airtable-oauth.js +9 -0
  3. package/dist/connectors/airtable.js +9 -0
  4. package/dist/connectors/amplitude.js +9 -0
  5. package/dist/connectors/anthropic.js +9 -0
  6. package/dist/connectors/asana.js +9 -0
  7. package/dist/connectors/attio.js +9 -0
  8. package/dist/connectors/aws-billing.js +9 -0
  9. package/dist/connectors/azure-sql.js +9 -0
  10. package/dist/connectors/backlog-api-key.js +9 -0
  11. package/dist/connectors/clickup.js +9 -0
  12. package/dist/connectors/cosmosdb.js +9 -0
  13. package/dist/connectors/customerio.js +9 -0
  14. package/dist/connectors/dbt.js +9 -0
  15. package/dist/connectors/freshdesk.js +9 -0
  16. package/dist/connectors/freshsales.js +9 -0
  17. package/dist/connectors/freshservice.js +9 -0
  18. package/dist/connectors/gamma.js +9 -0
  19. package/dist/connectors/gemini.js +9 -0
  20. package/dist/connectors/github.js +9 -0
  21. package/dist/connectors/gmail-oauth.js +9 -0
  22. package/dist/connectors/gmail.js +9 -0
  23. package/dist/connectors/google-ads.js +9 -0
  24. package/dist/connectors/google-analytics-oauth.js +9 -0
  25. package/dist/connectors/google-analytics.js +9 -0
  26. package/dist/connectors/google-audit-log.js +9 -0
  27. package/dist/connectors/google-calendar-oauth.js +9 -0
  28. package/dist/connectors/google-calendar.js +9 -0
  29. package/dist/connectors/google-docs.js +9 -0
  30. package/dist/connectors/google-drive.js +9 -0
  31. package/dist/connectors/google-search-console-oauth.js +9 -0
  32. package/dist/connectors/google-sheets.js +9 -0
  33. package/dist/connectors/google-slides.js +9 -0
  34. package/dist/connectors/grafana.js +9 -0
  35. package/dist/connectors/hubspot-oauth.js +9 -0
  36. package/dist/connectors/hubspot.js +9 -0
  37. package/dist/connectors/influxdb.js +9 -0
  38. package/dist/connectors/intercom-oauth.js +9 -0
  39. package/dist/connectors/intercom.js +9 -0
  40. package/dist/connectors/jdbc.js +9 -0
  41. package/dist/connectors/jira-api-key.js +9 -0
  42. package/dist/connectors/kintone-api-token.js +9 -0
  43. package/dist/connectors/kintone.js +9 -0
  44. package/dist/connectors/linear.js +9 -0
  45. package/dist/connectors/linkedin-ads.js +9 -0
  46. package/dist/connectors/mailchimp-oauth.js +9 -0
  47. package/dist/connectors/mailchimp.js +9 -0
  48. package/dist/connectors/meta-ads-oauth.js +9 -0
  49. package/dist/connectors/meta-ads.js +9 -0
  50. package/dist/connectors/mixpanel.js +9 -0
  51. package/dist/connectors/monday.js +9 -0
  52. package/dist/connectors/mongodb.js +9 -0
  53. package/dist/connectors/notion-oauth.js +9 -0
  54. package/dist/connectors/notion.js +9 -0
  55. package/dist/connectors/openai.js +9 -0
  56. package/dist/connectors/oracle.js +9 -0
  57. package/dist/connectors/outlook-oauth.js +9 -0
  58. package/dist/connectors/powerbi-oauth.js +9 -0
  59. package/dist/connectors/salesforce.js +9 -0
  60. package/dist/connectors/semrush.js +9 -0
  61. package/dist/connectors/sentry.js +9 -0
  62. package/dist/connectors/shopify-oauth.js +9 -0
  63. package/dist/connectors/shopify.js +9 -0
  64. package/dist/connectors/sqlserver.js +9 -0
  65. package/dist/connectors/stripe-api-key.js +9 -0
  66. package/dist/connectors/stripe-oauth.js +9 -0
  67. package/dist/connectors/supabase.js +9 -0
  68. package/dist/connectors/tableau.js +129 -55
  69. package/dist/connectors/tiktok-ads.js +9 -0
  70. package/dist/connectors/wix-store.js +9 -0
  71. package/dist/connectors/zendesk-oauth.js +9 -0
  72. package/dist/connectors/zendesk.js +9 -0
  73. package/dist/index.js +343 -46
  74. package/dist/main.js +343 -46
  75. package/dist/vite-plugin.js +343 -46
  76. package/package.json +1 -1
@@ -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 = `${serverUrl}|${siteContentUrl}|${patName}`;
28001
- const cached = sessionCache.get(cacheKey);
28002
- if (cached && cached.expiresAt > Date.now() + 6e4) {
28003
- return cached;
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 session = await signIn(
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
- sessionCache.set(cacheKey, session);
28013
- return session;
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 session = await getSession(
28070
- serverUrl,
28071
- apiVersion,
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
- const init = {
28086
- method,
28087
- headers: {
28088
- "X-Tableau-Auth": session.authToken,
28089
- Accept: "application/json",
28090
- "Content-Type": "application/json"
28091
- },
28092
- signal: controller.signal
28093
- };
28094
- if (body !== void 0) {
28095
- init.body = JSON.stringify(body);
28096
- }
28097
- const response = await fetch(url, init);
28098
- const text = await response.text();
28099
- const data = text ? (() => {
28100
- try {
28101
- return JSON.parse(text);
28102
- } catch {
28103
- return text;
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
- })() : null;
28106
- if (!response.ok) {
28107
- const errorMessage = data && typeof data === "object" && "error" in data ? JSON.stringify(data.error) : typeof data === "string" && data ? data : `HTTP ${response.status} ${response.statusText}`;
28108
- return { success: false, error: errorMessage };
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squadbase/vite-server",
3
- "version": "0.1.12-dev.822582a",
3
+ "version": "0.1.12-dev.93b8799",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {