@burdenoff/fe-libs 2026.1022.1 → 2026.1022.2
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.
|
@@ -163,6 +163,17 @@ export interface EnqueueGraphQLFetchOptions {
|
|
|
163
163
|
/** Dispatch at once, outside any batch, with fetch `keepalive`. */
|
|
164
164
|
keepalive?: boolean;
|
|
165
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* True when the promise returned by `enqueueGraphQLFetch` was served from
|
|
168
|
+
* the in-memory response cache without a network request. The marker is
|
|
169
|
+
* attached to the promise itself, so the caller must hold the promise
|
|
170
|
+
* reference (not just the awaited value) to inspect it:
|
|
171
|
+
*
|
|
172
|
+
* const promise = enqueueGraphQLFetch(url, headers, body, signal);
|
|
173
|
+
* const result = await promise;
|
|
174
|
+
* if (!isGraphqlFetchCacheHit(promise)) markConnectionHealthy();
|
|
175
|
+
*/
|
|
176
|
+
export declare function isGraphqlFetchCacheHit(promise: Promise<unknown> | unknown): boolean;
|
|
166
177
|
/**
|
|
167
178
|
* Drop the short-lived GraphQL read caches so the next read of any operation
|
|
168
179
|
* hits the network.
|
|
@@ -55,11 +55,11 @@ function C(e) {
|
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
function
|
|
58
|
+
function w(e) {
|
|
59
59
|
let t = C(e)?.exp;
|
|
60
60
|
return typeof t == "number" ? t * 1e3 <= Date.now() + 3e4 : !1;
|
|
61
61
|
}
|
|
62
|
-
function
|
|
62
|
+
function ee() {
|
|
63
63
|
try {
|
|
64
64
|
let e = sessionStorage.getItem("bf-active-profile");
|
|
65
65
|
if (e) {
|
|
@@ -72,7 +72,7 @@ function te() {
|
|
|
72
72
|
return null;
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
function
|
|
75
|
+
function T() {
|
|
76
76
|
try {
|
|
77
77
|
let e = sessionStorage.getItem("bf-active-profile");
|
|
78
78
|
if (e) {
|
|
@@ -84,31 +84,31 @@ function w() {
|
|
|
84
84
|
return "en";
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
function
|
|
87
|
+
function E() {
|
|
88
88
|
return s("workspace");
|
|
89
89
|
}
|
|
90
|
-
function
|
|
90
|
+
function D() {
|
|
91
91
|
return s("organization");
|
|
92
92
|
}
|
|
93
|
-
function
|
|
93
|
+
function O() {
|
|
94
94
|
return s("tenant");
|
|
95
95
|
}
|
|
96
|
-
function
|
|
96
|
+
function k() {
|
|
97
97
|
return s("project");
|
|
98
98
|
}
|
|
99
|
-
function
|
|
99
|
+
function A() {
|
|
100
100
|
try {
|
|
101
101
|
return typeof window > "u" ? null : new URLSearchParams(window.location.search).get("org");
|
|
102
102
|
} catch {
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
function
|
|
106
|
+
function te(e) {
|
|
107
107
|
return {
|
|
108
|
-
workspaceId: typeof e.workspaceId == "string" ? e.workspaceId :
|
|
109
|
-
organizationId: typeof e.organizationId == "string" ? e.organizationId :
|
|
110
|
-
tenantId: typeof e.tenantId == "string" ? e.tenantId :
|
|
111
|
-
projectId: typeof e.projectId == "string" ? e.projectId :
|
|
108
|
+
workspaceId: typeof e.workspaceId == "string" ? e.workspaceId : E() || void 0,
|
|
109
|
+
organizationId: typeof e.organizationId == "string" ? e.organizationId : D() || A() || void 0,
|
|
110
|
+
tenantId: typeof e.tenantId == "string" ? e.tenantId : O() || void 0,
|
|
111
|
+
projectId: typeof e.projectId == "string" ? e.projectId : k() || void 0
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
114
|
function j(e, t, n) {
|
|
@@ -129,9 +129,9 @@ function M(e, t, n) {
|
|
|
129
129
|
async function N(e) {
|
|
130
130
|
let { url: t, authToken: n, workspaceId: r, organizationId: i, projectId: a, locale: o, signal: s, currentQuery: c, issuanceGuard: l } = e;
|
|
131
131
|
if (!n || c.includes("issueWorkspaceToken") || l && !l.isCurrent()) return null;
|
|
132
|
-
let u = r ||
|
|
132
|
+
let u = r || E();
|
|
133
133
|
if (!u) return null;
|
|
134
|
-
let d = b(), p =
|
|
134
|
+
let d = b(), p = E(), m = i || D() || A();
|
|
135
135
|
if (d && p === u && f(d, {
|
|
136
136
|
workspaceId: u,
|
|
137
137
|
organizationId: m,
|
|
@@ -198,33 +198,37 @@ function B() {
|
|
|
198
198
|
let e = L();
|
|
199
199
|
return e.__graphqlFetchPendingResponses ||= /* @__PURE__ */ new Map(), e.__graphqlFetchPendingResponses;
|
|
200
200
|
}
|
|
201
|
-
|
|
201
|
+
var V = Symbol.for("@burdenoff/fe-libs:graphql-fetch-cache-hit");
|
|
202
|
+
function H(e) {
|
|
203
|
+
return !!(e && typeof e == "object" && e[V] === !0);
|
|
204
|
+
}
|
|
205
|
+
function ne() {
|
|
202
206
|
z().clear(), B().clear(), n();
|
|
203
207
|
}
|
|
204
|
-
var
|
|
208
|
+
var re = 10, ie = 600, U = 100, ae = 1e4, W = 15e3, oe = new Set([
|
|
205
209
|
"traceparent",
|
|
206
210
|
"tracestate",
|
|
207
211
|
"baggage"
|
|
208
212
|
]), G = "Apollo-Require-Preflight";
|
|
209
|
-
function
|
|
213
|
+
function se() {
|
|
210
214
|
if (typeof performance > "u") return U;
|
|
211
215
|
let e = L();
|
|
212
|
-
return e.__graphqlFetchBurstStartedAt ??= performance.now(), performance.now() - e.__graphqlFetchBurstStartedAt <
|
|
216
|
+
return e.__graphqlFetchBurstStartedAt ??= performance.now(), performance.now() - e.__graphqlFetchBurstStartedAt < ae ? ie : U;
|
|
213
217
|
}
|
|
214
|
-
function
|
|
218
|
+
function ce(e) {
|
|
215
219
|
return typeof e.query == "string" ? /^\s*query\b/.test(e.query) : !1;
|
|
216
220
|
}
|
|
217
|
-
function
|
|
221
|
+
function le(e) {
|
|
218
222
|
return typeof e.operationName == "string" && e.operationName.length > 0 ? {
|
|
219
223
|
operationName: e.operationName,
|
|
220
224
|
variables: e.variables ?? null
|
|
221
225
|
} : e;
|
|
222
226
|
}
|
|
223
|
-
function
|
|
227
|
+
function ue(e) {
|
|
224
228
|
let t = /* @__PURE__ */ new Map();
|
|
225
229
|
for (let [n, r] of Object.entries(e)) {
|
|
226
230
|
let e = n.toLowerCase();
|
|
227
|
-
|
|
231
|
+
oe.has(e) || t.set(e, r);
|
|
228
232
|
}
|
|
229
233
|
return Object.fromEntries(Array.from(t.entries()).sort(([e], [t]) => e.localeCompare(t)));
|
|
230
234
|
}
|
|
@@ -237,13 +241,13 @@ function K(t) {
|
|
|
237
241
|
};
|
|
238
242
|
}
|
|
239
243
|
function q(e) {
|
|
240
|
-
return
|
|
244
|
+
return de(e) && Array.isArray(e.errors);
|
|
241
245
|
}
|
|
242
246
|
function J(e) {
|
|
243
247
|
let t = e.status;
|
|
244
248
|
return t === 401 ? "Invalid email or password." : t === 403 ? "You do not have permission to do that." : t === 404 ? "We could not find what you were looking for." : t === 408 || t === 504 ? "The server took too long to respond. Please try again." : t === 429 ? "Too many requests. Please wait a moment and try again." : t >= 500 && t < 600 ? "The server is having trouble right now. Please try again in a moment." : t >= 400 && t < 500 ? "The request could not be processed. Please refresh and try again." : "We could not reach the server. Please check your connection and try again.";
|
|
245
249
|
}
|
|
246
|
-
function
|
|
250
|
+
function de(e) {
|
|
247
251
|
return typeof e == "object" && !!e && !Array.isArray(e);
|
|
248
252
|
}
|
|
249
253
|
async function Y(e) {
|
|
@@ -302,12 +306,15 @@ async function X(e, t, n) {
|
|
|
302
306
|
}
|
|
303
307
|
}
|
|
304
308
|
function Z(e, t, n, r, i) {
|
|
305
|
-
let a =
|
|
309
|
+
let a = ue(t), o = i?.keepalive === !0, s = o ? 1 : Math.max(1, i?.batchMax ?? re), c = Math.max(0, i?.batchInterval ?? se()), l = `${e}|${JSON.stringify(a)}`, u = ce(n) ? `${l}|${JSON.stringify(le(n))}` : void 0;
|
|
306
310
|
if (r?.aborted) return Promise.reject(F(r));
|
|
307
311
|
if (u) {
|
|
308
312
|
let e = z(), t = e.get(u);
|
|
309
313
|
if (t) {
|
|
310
|
-
if (t.expiresAt > Date.now())
|
|
314
|
+
if (t.expiresAt > Date.now()) {
|
|
315
|
+
let e = Promise.resolve(t.value);
|
|
316
|
+
return e[V] = !0, e;
|
|
317
|
+
}
|
|
311
318
|
e.delete(u);
|
|
312
319
|
}
|
|
313
320
|
let n = B().get(u);
|
|
@@ -357,9 +364,9 @@ function Q(e, t, n) {
|
|
|
357
364
|
i && (r.delete(n), i.timer &&= (clearTimeout(i.timer), null), X(e, t, i.requests));
|
|
358
365
|
}
|
|
359
366
|
async function $(e) {
|
|
360
|
-
let { gateway: n, query: r, variables: i, operationName: a, authToken: o, workspaceToken: s, workspaceId: c, organizationId: u, tenantId: h, projectId: _, locale: v, baseUrl: x, extraHeaders: C, signal:
|
|
361
|
-
I(
|
|
362
|
-
let
|
|
367
|
+
let { gateway: n, query: r, variables: i, operationName: a, authToken: o, workspaceToken: s, workspaceId: c, organizationId: u, tenantId: h, projectId: _, locale: v, baseUrl: x, extraHeaders: C, signal: E, suppressGlobalErrorEvent: D, keepalive: k } = e;
|
|
368
|
+
I(E);
|
|
369
|
+
let A = d(P(n, x)), j = o && !w(o) ? o : y();
|
|
363
370
|
if (!j && !e.skipAuthRetry && typeof window < "u" && !window.location.pathname.startsWith("/auth/") && S()) {
|
|
364
371
|
let e = await import("../utils/authErrorHandling.js");
|
|
365
372
|
await e.attemptTokenRefresh({
|
|
@@ -368,9 +375,9 @@ async function $(e) {
|
|
|
368
375
|
}) ? j = y() : g({
|
|
369
376
|
operationName: a,
|
|
370
377
|
gateway: n
|
|
371
|
-
}), I(
|
|
378
|
+
}), I(E);
|
|
372
379
|
}
|
|
373
|
-
let M = v ??
|
|
380
|
+
let M = v ?? T(), F = te({
|
|
374
381
|
workspaceId: c,
|
|
375
382
|
organizationId: u,
|
|
376
383
|
tenantId: h,
|
|
@@ -380,19 +387,19 @@ async function $(e) {
|
|
|
380
387
|
[G]: "true"
|
|
381
388
|
};
|
|
382
389
|
j && (L.Authorization = `Bearer ${j}`), M && (L["Accept-Language"] = M);
|
|
383
|
-
let R =
|
|
390
|
+
let R = ee();
|
|
384
391
|
if (R?.country && (L["X-Geo-Country"] = R.country), R?.currency && (L["X-Geo-Currency"] = R.currency), R?.timezone && (L["X-Geo-Timezone"] = R.timezone), n === "workspace" ? s !== !1 : s) {
|
|
385
392
|
let e = typeof s == "string" ? s : b();
|
|
386
393
|
e && !f(e, F) && (e = null), !e && (s === !0 || n === "workspace" && s === void 0 || typeof s == "string") && (e = await N({
|
|
387
|
-
url:
|
|
394
|
+
url: A,
|
|
388
395
|
authToken: j,
|
|
389
396
|
workspaceId: F.workspaceId,
|
|
390
397
|
organizationId: F.organizationId,
|
|
391
398
|
projectId: F.projectId,
|
|
392
399
|
locale: M,
|
|
393
|
-
signal:
|
|
400
|
+
signal: E,
|
|
394
401
|
currentQuery: r
|
|
395
|
-
}), I(
|
|
402
|
+
}), I(E)), e && (L["X-Workspace-Authorization"] = `Bearer ${e}`);
|
|
396
403
|
}
|
|
397
404
|
if (n === "workspace" || c) {
|
|
398
405
|
let e = F.workspaceId;
|
|
@@ -403,7 +410,7 @@ async function $(e) {
|
|
|
403
410
|
e && (L["x-org-id"] = e);
|
|
404
411
|
}
|
|
405
412
|
if (h) {
|
|
406
|
-
let e = typeof h == "string" ? h :
|
|
413
|
+
let e = typeof h == "string" ? h : O();
|
|
407
414
|
e && (L["x-tenant-id"] = e);
|
|
408
415
|
}
|
|
409
416
|
if (n === "workspace" || _) {
|
|
@@ -431,24 +438,24 @@ async function $(e) {
|
|
|
431
438
|
}), null) : null;
|
|
432
439
|
};
|
|
433
440
|
try {
|
|
434
|
-
let e =
|
|
435
|
-
if (m(),
|
|
436
|
-
let
|
|
437
|
-
if (
|
|
438
|
-
|
|
441
|
+
let e = Z(A, L, B, E, k ? { keepalive: !0 } : void 0), t = await e;
|
|
442
|
+
if (H(e) || m(), t.errors?.length) {
|
|
443
|
+
let e = await V(t.errors);
|
|
444
|
+
if (e) return e;
|
|
445
|
+
D || p({ errors: t.errors }, { operationName: a });
|
|
439
446
|
}
|
|
440
|
-
return
|
|
447
|
+
return t;
|
|
441
448
|
} catch (e) {
|
|
442
449
|
let t = e.errors;
|
|
443
450
|
if (t?.length) {
|
|
444
451
|
let e = await V(t);
|
|
445
452
|
if (e) return e;
|
|
446
453
|
}
|
|
447
|
-
throw
|
|
454
|
+
throw D || p(e, {
|
|
448
455
|
operationName: a,
|
|
449
456
|
fallbackMessage: "We could not reach the server. Please check your connection and try again."
|
|
450
457
|
}), e;
|
|
451
458
|
}
|
|
452
459
|
}
|
|
453
460
|
//#endregion
|
|
454
|
-
export { h as SESSION_EXPIRED_EVENT,
|
|
461
|
+
export { h as SESSION_EXPIRED_EVENT, ne as clearGraphqlFetchResponseCache, Z as enqueueGraphQLFetch, N as ensureWorkspaceToken, y as getStoredAuthToken, T as getStoredLocale, D as getStoredOrganizationId, k as getStoredProjectId, O as getStoredTenantId, E as getStoredWorkspaceId, b as getStoredWorkspaceToken, $ as graphqlFetch, P as resolveGatewayUrl };
|
|
@@ -51,8 +51,21 @@ export declare function isAbortError(input: unknown): boolean;
|
|
|
51
51
|
export declare function isTransportError(input: unknown): boolean;
|
|
52
52
|
/**
|
|
53
53
|
* Signal that connectivity is healthy again. Called from the GraphQL success
|
|
54
|
-
* paths; clears the connection indicator exactly once on recovery.
|
|
55
|
-
*
|
|
54
|
+
* paths; clears the connection indicator exactly once on recovery.
|
|
55
|
+
*
|
|
56
|
+
* Always dispatches the `online: true` event (not only when the latch was
|
|
57
|
+
* previously set). The connection-status toast in `AppShellProvider` can be
|
|
58
|
+
* shown by either an `online: false` event *or* a browser `offline` event
|
|
59
|
+
* that did not correspond to an actual transport error (e.g. a transient
|
|
60
|
+
* navigator.onLine blip during a Cloudflare Access redirect — see BOFF-8081).
|
|
61
|
+
* In that second case the latch was never tripped, so a previous version that
|
|
62
|
+
* returned early here left a stale "Connection lost. Trying to reconnect…"
|
|
63
|
+
* toast stuck forever even though every subsequent request succeeded. By
|
|
64
|
+
* always announcing recovery we keep the listener's toast state in sync with
|
|
65
|
+
* the actual connectivity.
|
|
66
|
+
*
|
|
67
|
+
* The listener treats `online: true` as a no-op when no banner is shown, so
|
|
68
|
+
* the extra dispatch on every successful request is cheap.
|
|
56
69
|
*/
|
|
57
70
|
export declare function markConnectionHealthy(): void;
|
|
58
71
|
export declare function extractBackendError(input: unknown, options?: ExtractBackendErrorOptions): BackendErrorDisplay | null;
|
|
@@ -111,7 +111,7 @@ function x(e, n) {
|
|
|
111
111
|
} })));
|
|
112
112
|
}
|
|
113
113
|
function S() {
|
|
114
|
-
typeof window > "u" || b && (b = !1, y = 0, window.dispatchEvent(new CustomEvent(t, { detail: {
|
|
114
|
+
typeof window > "u" || (b && (b = !1, y = 0), window.dispatchEvent(new CustomEvent(t, { detail: {
|
|
115
115
|
online: !0,
|
|
116
116
|
since: Date.now()
|
|
117
117
|
} })));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/fe-libs",
|
|
3
|
-
"version": "2026.1022.
|
|
3
|
+
"version": "2026.1022.2",
|
|
4
4
|
"description": "Burdenoff frontend primitives and domain libraries",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -330,7 +330,7 @@
|
|
|
330
330
|
"test:package-livekit-optional": "node scripts/validate-livekit-optional.mjs",
|
|
331
331
|
"verify:package": "node scripts/verify-package-contents.mjs",
|
|
332
332
|
"test:handsfree-browser": "node scripts/handsfree-browser-run.mjs",
|
|
333
|
-
"test": "bun test scripts/graphql-schema-drift/__tests__ scripts/a11y-audit/__tests__ scripts/i18n/__tests__ src/credentials src/connections src/storage src/shared/assistant src/shared/feature-flags src/platform-pages src/admin-overview src/shared/components src/shared/graphql/links/sse-link.test.ts src/shared/graphql/fetch.test.ts src/shared/graphql/prepareWorkspaceRequest.test.ts src/shared/graphql/client.test.ts src/shared/utils/apollo.test.ts src/shared/utils/canvasTokens.test.ts src/shared/graphql/tourWorkspaceAuth.test.ts src/shared/config/gatewayUrls.test.ts src/shared/config/authBridgeUrls.test.ts src/shared/config/shellRoutes.test.ts src/shared/config/gatewayFallback.test.ts scripts/__tests__ src/shared/config/products.test.ts src/shared/config/docsUrls.test.ts src/shared/config/productSlug.test.ts src/shared/hooks/shell/useProducts.test.ts src/shared/hooks/shell/useGlobalSearch.test.ts src/shared/providers/shell/brandAttribute.test.ts src/chrome/ProductSwitcher.test.ts src/shared/utils/gatewayFetchRewrite.test.ts src/shared/utils/authCookie.test.ts src/shared/utils/redirectAllowlist.test.ts src/shared/providers/shell/ProfileStorageManager.test.ts src/shared/providers/AppShellProvider.test.ts src/shared/providers/shell/interpolate.test.ts src/shared/providers/shell/resolveTranslation.test.ts src/shared/providers/shell/I18nProvider.render.test.tsx src/shared/providers/shell/I18nProvider.client.test.tsx src/shared/providers/shell/translationStore.test.ts src/shared/providers/shell/translationLayers.test.ts src/shared/providers/shell/directionMode.test.ts src/shared/providers/shell/authProvider/ssoRelay.test.ts src/shared/providers/shell/authProvider/useAuthActions.signOut.test.tsx src/shared/providers/shell/personaSurfaceRemote.test.ts src/shared/providers/shell/workspaceSwitch.client.test.tsx src/shared/events/sinks/RybbitSink.test.ts src/shared/events/sinks/RybbitSink.client.test.tsx src/shell-native src/shared/native src/shared/navigation src/shared/tours src/chrome/__tests__ src/ui/__tests__",
|
|
333
|
+
"test": "bun test scripts/graphql-schema-drift/__tests__ scripts/a11y-audit/__tests__ scripts/i18n/__tests__ src/credentials src/connections src/storage src/shared/assistant src/shared/feature-flags src/platform-pages src/admin-overview src/shared/components src/shared/graphql/links/sse-link.test.ts src/shared/graphql/fetch.test.ts src/shared/graphql/prepareWorkspaceRequest.test.ts src/shared/graphql/client.test.ts src/shared/utils/apollo.test.ts src/shared/utils/canvasTokens.test.ts src/shared/graphql/tourWorkspaceAuth.test.ts src/shared/config/gatewayUrls.test.ts src/shared/config/authBridgeUrls.test.ts src/shared/config/shellRoutes.test.ts src/shared/config/gatewayFallback.test.ts scripts/__tests__ src/shared/config/products.test.ts src/shared/config/docsUrls.test.ts src/shared/config/productSlug.test.ts src/shared/hooks/shell/useProducts.test.ts src/shared/hooks/shell/useGlobalSearch.test.ts src/shared/providers/shell/brandAttribute.test.ts src/chrome/ProductSwitcher.test.ts src/shared/utils/backendErrors.test.ts src/shared/utils/gatewayFetchRewrite.test.ts src/shared/utils/authCookie.test.ts src/shared/utils/redirectAllowlist.test.ts src/shared/providers/shell/ProfileStorageManager.test.ts src/shared/providers/AppShellProvider.test.ts src/shared/providers/shell/interpolate.test.ts src/shared/providers/shell/resolveTranslation.test.ts src/shared/providers/shell/I18nProvider.render.test.tsx src/shared/providers/shell/I18nProvider.client.test.tsx src/shared/providers/shell/translationStore.test.ts src/shared/providers/shell/translationLayers.test.ts src/shared/providers/shell/directionMode.test.ts src/shared/providers/shell/authProvider/ssoRelay.test.ts src/shared/providers/shell/authProvider/useAuthActions.signOut.test.tsx src/shared/providers/shell/personaSurfaceRemote.test.ts src/shared/providers/shell/workspaceSwitch.client.test.tsx src/shared/events/sinks/RybbitSink.test.ts src/shared/events/sinks/RybbitSink.client.test.tsx src/shell-native src/shared/native src/shared/navigation src/shared/tours src/chrome/__tests__ src/ui/__tests__",
|
|
334
334
|
"sanity": "bash scripts/build-limits.sh --gate bash -c 'bun run lint:sanity && bun run format && bun run type:check && bun run test && bun run build && bun run verify:package'",
|
|
335
335
|
"switch:status": "bun scripts/deps-mode.ts status",
|
|
336
336
|
"switch:remote": "bun scripts/deps-mode.ts remote",
|