@burdenoff/fe-libs 2026.1023.9 → 2026.1023.10

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.
@@ -95,6 +95,22 @@ export interface ActiveContextBootstrapFields {
95
95
  * around it needs a DOM.
96
96
  */
97
97
  export declare function applyAuthStoreContextFallback(resolved: ActiveContextBootstrapFields, authStore: AuthStoreContextSnapshot): ActiveContextBootstrapFields;
98
+ /**
99
+ * Pair the URL's context with the tab's saved one, axis by axis, without ever
100
+ * mixing two contexts.
101
+ *
102
+ * A URL value always wins. A saved child axis is used only while every parent
103
+ * axis is still the saved one: once the URL names another organization, the
104
+ * saved workspace and project belong to the old one, and once it names another
105
+ * workspace, the saved project does. A deep link such as
106
+ * `/workflows/runs?org=<o>&workspace=<other>` used to keep the previous
107
+ * workspace's saved project, so the shell asked for a workspace token for a
108
+ * project outside the workspace, never got one, and the module waited for it
109
+ * for ever (and wrote the stale `project=` back into the URL).
110
+ *
111
+ * Exported so this can be unit-tested directly: it is pure.
112
+ */
113
+ export declare function mergeUrlWithSavedContext(fromUrl: ActiveContextBootstrapFields, readSaved: (field: 'organization' | 'workspace' | 'project') => string | null): ActiveContextBootstrapFields;
98
114
  /**
99
115
  * Resolve the organization / workspace / project the provider should start
100
116
  * from: URL (when synced) > ActiveContext's own storage > persisted auth store.
@@ -42,40 +42,44 @@ function D(e, t) {
42
42
  projectId: e.projectId ?? (a ? t.projectId : null)
43
43
  };
44
44
  }
45
- function O(e, t, n, r) {
46
- if (n) {
47
- let e = s(t);
48
- if (e) return e;
49
- }
50
- return c(e, r) || null;
45
+ function O(e, t) {
46
+ let n = /* @__PURE__ */ new Map(), r = (e) => (n.has(e) || n.set(e, t(e)), n.get(e) ?? null), i = e.organizationId ?? r("organization"), a = () => i === r("organization"), o = e.workspaceId ?? (a() ? r("workspace") : null);
47
+ return {
48
+ organizationId: i,
49
+ workspaceId: o,
50
+ projectId: e.projectId ?? (a() && o === r("workspace") ? r("project") : null)
51
+ };
52
+ }
53
+ function k(e, t) {
54
+ return t && s(e) || null;
51
55
  }
52
- function k(t) {
56
+ function A(t) {
53
57
  if (typeof window > "u") return {
54
58
  organizationId: null,
55
59
  workspaceId: null,
56
60
  projectId: null
57
61
  };
58
- let { storageKey: n, syncToUrl: r, urlParams: i } = t, o = {
59
- organizationId: O("organization", i.organization ?? a.organization, r, n),
60
- workspaceId: O("workspace", i.workspace ?? a.workspace, r, n),
61
- projectId: O("project", i.project ?? a.project, r, n)
62
- }, c = r && s(i.project ?? a.project), u = (t) => {
63
- if (c) try {
62
+ let { storageKey: n, syncToUrl: r, urlParams: i } = t, o = O({
63
+ organizationId: k(i.organization ?? a.organization, r),
64
+ workspaceId: k(i.workspace ?? a.workspace, r),
65
+ projectId: k(i.project ?? a.project, r)
66
+ }, (e) => c(e, n) || null), u = r && s(i.project ?? a.project), d = (t) => {
67
+ if (u) try {
64
68
  e() && f(t);
65
69
  } catch {}
66
70
  };
67
- if (u(o), !c && p(o)) return {
71
+ if (d(o), !u && p(o)) return {
68
72
  ...o,
69
73
  projectId: null
70
74
  };
71
75
  if (o.organizationId !== null && o.workspaceId !== null && o.projectId !== null) return o;
72
- let d = D(o, l());
73
- return u(d), !c && p(d) ? {
74
- ...d,
76
+ let m = D(o, l());
77
+ return d(m), !u && p(m) ? {
78
+ ...m,
75
79
  projectId: null
76
- } : d;
80
+ } : m;
77
81
  }
78
- function A(e) {
82
+ function j(e) {
79
83
  if (typeof window > "u" || m() || window.location.pathname.startsWith("/auth/")) return;
80
84
  let t = new URL(window.location.href);
81
85
  Object.entries(e).forEach(([e, n]) => {
@@ -84,20 +88,20 @@ function A(e) {
84
88
  let n = window.history.state ?? null;
85
89
  window.history.replaceState(n, "", t.toString());
86
90
  }
87
- function j(e, t) {
91
+ function M(e, t) {
88
92
  return e === null || e === "" || e === t ? { apply: !1 } : {
89
93
  apply: !0,
90
94
  value: e
91
95
  };
92
96
  }
93
- function M({ children: e, defaultOrganizationId: l = null, defaultWorkspaceId: m = null, defaultProjectId: h = null, defaultTenantId: g = null, storageKey: T = i, syncToUrl: D = !1, urlParams: O = a }) {
94
- let [M] = x(() => k({
97
+ function N({ children: e, defaultOrganizationId: l = null, defaultWorkspaceId: m = null, defaultProjectId: h = null, defaultTenantId: g = null, storageKey: T = i, syncToUrl: D = !1, urlParams: O = a }) {
98
+ let [k] = x(() => A({
95
99
  storageKey: T,
96
100
  syncToUrl: D,
97
101
  urlParams: O
98
- })), [N, P] = x(() => typeof window > "u" ? l : M.organizationId ?? l), [F, I] = x(() => {
102
+ })), [N, P] = x(() => typeof window > "u" ? l : k.organizationId ?? l), [F, I] = x(() => {
99
103
  if (typeof window > "u") return m;
100
- let e = M.workspaceId ?? m;
104
+ let e = k.workspaceId ?? m;
101
105
  if (e) {
102
106
  let i = n();
103
107
  if (i) {
@@ -109,13 +113,14 @@ function M({ children: e, defaultOrganizationId: l = null, defaultWorkspaceId: m
109
113
  }
110
114
  }
111
115
  return e;
112
- }), [L, R] = x(() => typeof window > "u" ? h : p(M) && !M.projectId ? null : M.projectId ?? h), [z, B] = x(() => {
116
+ }), [L, R] = x(() => typeof window > "u" ? h : p(k) && !k.projectId ? null : k.projectId ?? h), [z, B] = x(() => {
113
117
  if (typeof window > "u") return g;
114
118
  if (D) {
115
119
  let e = s(O.tenant);
116
120
  if (e) return e;
117
121
  }
118
- return c("tenant", T) || g;
122
+ let e = c("organization", T) || null;
123
+ return e !== null && k.organizationId !== null && k.organizationId !== e ? g : c("tenant", T) || g;
119
124
  }), V = b(null);
120
125
  V.current === null && (V.current = w(N));
121
126
  let H = b(null);
@@ -148,7 +153,7 @@ function M({ children: e, defaultOrganizationId: l = null, defaultWorkspaceId: m
148
153
  L,
149
154
  z
150
155
  ]), v(() => {
151
- D && A({
156
+ D && j({
152
157
  [O.organization]: N,
153
158
  [O.workspace]: F,
154
159
  [O.project]: L,
@@ -164,13 +169,13 @@ function M({ children: e, defaultOrganizationId: l = null, defaultWorkspaceId: m
164
169
  ]), v(() => {
165
170
  if (!D) return;
166
171
  let e = () => {
167
- let e = s(O.organization), t = s(O.workspace), n = s(O.project), r = s(O.tenant), i = j(e, N);
172
+ let e = s(O.organization), t = s(O.workspace), n = s(O.project), r = s(O.tenant), i = M(e, N);
168
173
  i.apply && (P(i.value), V.current.previous = V.current.current, V.current.current = i.value);
169
- let a = j(t, F);
174
+ let a = M(t, F);
170
175
  a.apply && (I(a.value), H.current.previous = H.current.current, H.current.current = a.value);
171
- let o = j(n, L);
176
+ let o = M(n, L);
172
177
  o.apply && (R(o.value), U.current.previous = U.current.current, U.current.current = o.value);
173
- let c = j(r, z);
178
+ let c = M(r, z);
174
179
  c.apply && (B(c.value), W.current.previous = W.current.current, W.current.current = c.value);
175
180
  };
176
181
  return window.addEventListener("popstate", e), () => window.removeEventListener("popstate", e);
@@ -183,7 +188,7 @@ function M({ children: e, defaultOrganizationId: l = null, defaultWorkspaceId: m
183
188
  z
184
189
  ]);
185
190
  let G = _((e, t) => {
186
- D && A({ [O[e] ?? a[e]]: t });
191
+ D && j({ [O[e] ?? a[e]]: t });
187
192
  }, [D, O]), K = _((e) => {
188
193
  if (!E("organizationId", V.current, e, Date.now())) return;
189
194
  P(e), d("organization", e, T), G("organization", e);
@@ -259,10 +264,10 @@ function M({ children: e, defaultOrganizationId: l = null, defaultWorkspaceId: m
259
264
  children: e
260
265
  });
261
266
  }
262
- function N() {
267
+ function P() {
263
268
  let e = g(C);
264
269
  if (!e) throw Error("useActiveContext must be used within an ActiveContextProvider");
265
270
  return e;
266
271
  }
267
272
  //#endregion
268
- export { M as ActiveContextProvider, N as useActiveContext };
273
+ export { N as ActiveContextProvider, P as useActiveContext };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.1023.9",
3
+ "version": "2026.1023.10",
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/utils/brandContrast.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__ src/shared/graphql/workspaceSwitchGuard.test.ts",
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/utils/brandContrast.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/shell/ActiveContextProvider.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__ src/shared/graphql/workspaceSwitchGuard.test.ts",
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",