@burdenoff/fe-libs 2026.531.4 → 2026.531.5

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.
@@ -25,15 +25,22 @@ export interface UseActorProfilesOptions {
25
25
  apiGatewayUrl?: string;
26
26
  authToken?: string;
27
27
  orgId?: string;
28
+ workspaceId?: string;
28
29
  }
29
30
  export declare function buildActorFallback(actor: ActorInput): ActorProfile;
30
31
  /**
31
32
  * Resolves a list of actor IDs to human-friendly profiles (displayName + email
32
- * + avatar), with a 5-minute in-memory cache and inflight de-duplication.
33
+ * + avatar), with a 5-minute in-memory cache and scope-aware batch lookups.
33
34
  *
34
- * Backed by the global gateway `user(id)` query. Non-user actor types resolve
35
- * locally to a humanized fallback. Network failures return the fallback rather
36
- * than throwing UI always has *something* to render.
35
+ * Resolution order for user actors:
36
+ * 1. workspace-scoped batch lookup when workspaceId is available
37
+ * 2. organization-scoped batch lookup when orgId is available
38
+ * 3. global batch lookup for super/tenant admins
39
+ * 4. local fallback
40
+ *
41
+ * Non-user actor types resolve locally to a humanized fallback. Network
42
+ * failures return the fallback rather than throwing — UI always has *something*
43
+ * to render.
37
44
  *
38
45
  * Pair with the {@link ActorIdentity} component for consistent UUID hygiene:
39
46
  * displayName + email in the primary slot, UUID hidden in a drill-down.
@@ -1 +1 @@
1
- {"version":3,"file":"useActorProfiles.d.ts","sourceRoot":"","sources":["../../../src/shared/actors/useActorProfiles.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmDD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,CAWlE;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,GAAE,uBAA4B,GACpC,eAAe,CA0HjB"}
1
+ {"version":3,"file":"useActorProfiles.d.ts","sourceRoot":"","sources":["../../../src/shared/actors/useActorProfiles.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAOD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAwFD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,CAWlE;AAgID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,GAAE,uBAA4B,GACpC,eAAe,CA0NjB"}
@@ -1,12 +1,12 @@
1
1
  import { resolveGatewayUrls as e } from "../config/gatewayUrls.js";
2
- import { graphqlFetch as t } from "../graphql/fetch.js";
3
- import { useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
2
+ import { getStoredAuthToken as t, graphqlFetch as n } from "../graphql/fetch.js";
3
+ import { useEffect as r, useMemo as i, useState as a } from "react";
4
4
  //#region src/shared/actors/useActorProfiles.ts
5
- var o = "\n query ActorProfileUser($id: ID!) {\n user(id: $id) {\n id\n email\n firstName\n lastName\n name\n username\n avatar\n }\n }\n";
6
- function s(e) {
5
+ var o = "\n query ActorProfilesUsersByIds($ids: [ID!]!) {\n usersByIds(ids: $ids) {\n id\n email\n firstName\n lastName\n name\n username\n avatar\n }\n }\n", s = "\n query ActorProfilesWorkspaceMemberIdentities($userIds: [ID!]!, $workspaceId: ID) {\n workspaceMemberIdentities(userIds: $userIds, workspaceId: $workspaceId) {\n userId\n displayName\n email\n avatar\n }\n }\n", c = "\n query ActorProfilesOrganizationMemberIdentities($userIds: [ID!]!, $organizationId: String!) {\n organizationMemberIdentities(userIds: $userIds, organizationId: $organizationId) {\n userId\n displayName\n email\n avatar\n }\n }\n";
6
+ function l(e) {
7
7
  return e.length <= 12 ? e : `${e.slice(0, 8)}…${e.slice(-4)}`;
8
8
  }
9
- function c(e) {
9
+ function u(e) {
10
10
  switch (e.toLowerCase()) {
11
11
  case "user": return "User";
12
12
  case "app": return "App";
@@ -15,104 +15,217 @@ function c(e) {
15
15
  default: return e.split("_").map((e) => e.charAt(0) + e.slice(1).toLowerCase()).join(" ");
16
16
  }
17
17
  }
18
- function l(e) {
18
+ function d(e) {
19
19
  return {
20
20
  actorId: e.actorId,
21
21
  actorType: e.actorType,
22
- displayName: e.actorType.toLowerCase() === "user" ? `User ${s(e.actorId)}` : c(e.actorType),
23
- secondaryLabel: s(e.actorId),
22
+ displayName: e.actorType.toLowerCase() === "user" ? `User ${l(e.actorId)}` : u(e.actorType),
23
+ secondaryLabel: l(e.actorId),
24
24
  resolved: !1
25
25
  };
26
26
  }
27
- var u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = 300 * 1e3, p = /* @__PURE__ */ new Map();
28
- function m(e) {
29
- let t = p.get(e);
30
- if (!t || t < Date.now()) {
31
- u.delete(e), p.delete(e);
27
+ var f = /* @__PURE__ */ new Map(), p = 300 * 1e3, m = /* @__PURE__ */ new Map(), h = 50;
28
+ function g(e, t) {
29
+ if (e.length === 0) return [];
30
+ let n = [];
31
+ for (let r = 0; r < e.length; r += t) n.push(e.slice(r, r + t));
32
+ return n;
33
+ }
34
+ function _(e) {
35
+ return e.workspaceId ? `workspace:${e.workspaceId}` : e.orgId ? `org:${e.orgId}` : "global";
36
+ }
37
+ function v(e, t) {
38
+ let n = e.actorType.toLowerCase();
39
+ return n === "user" ? `${n}:${e.actorId}:${_(t)}` : `${n}:${e.actorId}`;
40
+ }
41
+ function y(e, t) {
42
+ let n = v(e, t), r = m.get(n);
43
+ if (!r || r < Date.now()) {
44
+ f.delete(n), m.delete(n);
32
45
  return;
33
46
  }
34
- return u.get(e);
47
+ return f.get(n);
48
+ }
49
+ function b(e, t) {
50
+ let n = v({
51
+ actorId: e.actorId,
52
+ actorType: e.actorType
53
+ }, t);
54
+ f.set(n, e), m.set(n, Date.now() + p);
55
+ }
56
+ function x(e) {
57
+ try {
58
+ let [, t] = e.split(".");
59
+ if (!t || typeof atob != "function") return null;
60
+ let n = t.replace(/-/g, "+").replace(/_/g, "/"), r = n.padEnd(n.length + (4 - n.length % 4) % 4, "=");
61
+ return JSON.parse(atob(r));
62
+ } catch {
63
+ return null;
64
+ }
35
65
  }
36
- function h(e) {
37
- u.set(e.actorId, e), p.set(e.actorId, Date.now() + f);
66
+ function S(e) {
67
+ if (!e) return !1;
68
+ let t = x(e), n = typeof t?.role == "string" ? t.role : void 0, r = typeof t?.actor_type == "string" ? t.actor_type : void 0;
69
+ return n === "SUPER_ADMIN" || n === "TENANT_ADMIN" || r === "super_admin";
38
70
  }
39
- function g(c, u = {}) {
40
- let { apiGatewayUrl: f, authToken: p, orgId: g } = u, _ = (e) => /(?:gw-wspace|graphqlworkspaces|workspaces\.)/.test(e), v = r(() => {
41
- if (f && !_(f)) return f;
71
+ function C(e) {
72
+ return {
73
+ actorId: e.userId,
74
+ actorType: "user",
75
+ displayName: e.displayName,
76
+ secondaryLabel: e.email ?? l(e.userId),
77
+ email: e.email ?? void 0,
78
+ avatarUrl: e.avatar ?? void 0,
79
+ resolved: !0
80
+ };
81
+ }
82
+ function w(e) {
83
+ let t = e.name?.trim() || [e.firstName, e.lastName].filter(Boolean).join(" ").trim() || e.username?.trim() || e.email?.trim() || `User ${l(e.id)}`;
84
+ return {
85
+ actorId: e.id,
86
+ actorType: "user",
87
+ displayName: t,
88
+ secondaryLabel: e.email ?? l(e.id),
89
+ email: e.email ?? void 0,
90
+ avatarUrl: e.avatar ?? void 0,
91
+ resolved: !0
92
+ };
93
+ }
94
+ function T(l, u = {}) {
95
+ let { apiGatewayUrl: f, authToken: p, orgId: m, workspaceId: _ } = u, v = p ?? t() ?? void 0, x = i(() => ({
96
+ workspaceId: _,
97
+ orgId: m
98
+ }), [m, _]), T = (e) => /(?:gw-wspace|graphqlworkspaces|workspaces\.)/.test(e), { resolvedGlobalBaseUrl: E, resolvedWorkspaceBaseUrl: D } = i(() => {
42
99
  try {
43
- return e().globalBaseUrl;
100
+ let t = e();
101
+ return f ? T(f) ? {
102
+ resolvedGlobalBaseUrl: t.globalBaseUrl,
103
+ resolvedWorkspaceBaseUrl: f
104
+ } : {
105
+ resolvedGlobalBaseUrl: f,
106
+ resolvedWorkspaceBaseUrl: t.workspaceBaseUrl
107
+ } : {
108
+ resolvedGlobalBaseUrl: t.globalBaseUrl,
109
+ resolvedWorkspaceBaseUrl: t.workspaceBaseUrl
110
+ };
44
111
  } catch {
45
- return;
112
+ return {
113
+ resolvedGlobalBaseUrl: void 0,
114
+ resolvedWorkspaceBaseUrl: void 0
115
+ };
46
116
  }
47
- }, [f]), [y, b] = a(() => {
117
+ }, [f]), [O, k] = a(() => {
48
118
  let e = {};
49
- for (let t of c) {
50
- let n = m(t.actorId);
51
- e[t.actorId] = n ?? l(t);
119
+ for (let t of l) {
120
+ let n = y(t, x);
121
+ e[t.actorId] = n ?? d(t);
52
122
  }
53
123
  return e;
54
- }), x = r(() => c.map((e) => `${e.actorId}|${e.actorType}`).sort().join(","), [c]), S = i(void 0);
55
- return n(() => {
124
+ });
125
+ return r(() => {
56
126
  let e = !1;
57
- S.current = p;
58
- async function n(e) {
59
- let n = m(e.actorId);
60
- if (n?.resolved) return n;
61
- if (e.actorType.toLowerCase() !== "user") {
62
- let t = l(e);
63
- return h(t), t;
127
+ async function t() {
128
+ let t = {};
129
+ for (let e of l) t[e.actorId] = y(e, x) ?? d(e);
130
+ e || k((e) => ({
131
+ ...e,
132
+ ...t
133
+ }));
134
+ let r = l.filter((e) => e.actorType.toLowerCase() === "user" ? !y(e, x)?.resolved : !1), i = [...new Set(r.map((e) => e.actorId))];
135
+ if (i.length === 0) return;
136
+ let a = /* @__PURE__ */ new Map(), u = i;
137
+ if (_ && D && u.length > 0) try {
138
+ for (let t of g(u, h)) {
139
+ if (e) return;
140
+ let r = await n({
141
+ gateway: "workspace",
142
+ baseUrl: D,
143
+ authToken: v,
144
+ workspaceId: _,
145
+ organizationId: m,
146
+ workspaceToken: !0,
147
+ query: s,
148
+ variables: {
149
+ userIds: t,
150
+ workspaceId: _
151
+ }
152
+ });
153
+ for (let e of r.data?.workspaceMemberIdentities ?? []) {
154
+ let t = C(e);
155
+ b(t, x), a.set(e.userId, t);
156
+ }
157
+ u = u.filter((e) => !a.has(e));
158
+ }
159
+ } catch {
160
+ u = u.filter((e) => !a.has(e));
64
161
  }
65
- let r = e.actorId, i = d.get(r);
66
- if (i) return i;
67
- let a = (async () => {
68
- try {
69
- let n = await t({
162
+ if (m && E && u.length > 0) try {
163
+ for (let t of g(u, h)) {
164
+ if (e) return;
165
+ let r = await n({
70
166
  gateway: "global",
71
- baseUrl: v,
72
- authToken: p,
73
- organizationId: g,
167
+ baseUrl: E,
168
+ authToken: v,
169
+ organizationId: m,
170
+ query: c,
171
+ variables: {
172
+ userIds: t,
173
+ organizationId: m
174
+ }
175
+ });
176
+ for (let e of r.data?.organizationMemberIdentities ?? []) {
177
+ let t = C(e);
178
+ b(t, x), a.set(e.userId, t);
179
+ }
180
+ u = u.filter((e) => !a.has(e));
181
+ }
182
+ } catch {
183
+ u = u.filter((e) => !a.has(e));
184
+ }
185
+ if (E && u.length > 0 && S(v)) try {
186
+ for (let t of g(u, h)) {
187
+ if (e) return;
188
+ let r = await n({
189
+ gateway: "global",
190
+ baseUrl: E,
191
+ authToken: v,
192
+ organizationId: m,
74
193
  query: o,
75
- variables: { id: e.actorId }
194
+ variables: { ids: t }
76
195
  });
77
- if (n.errors?.length || !n.data?.user) {
78
- let t = l(e);
79
- return h(t), t;
196
+ for (let e of r.data?.usersByIds ?? []) {
197
+ let t = w(e);
198
+ b(t, x), a.set(e.id, t);
80
199
  }
81
- let r = n.data.user, i = r.name?.trim() || [r.firstName, r.lastName].filter(Boolean).join(" ").trim() || r.username?.trim() || r.email?.trim() || `User ${s(e.actorId)}`, a = {
82
- actorId: e.actorId,
83
- actorType: e.actorType,
84
- displayName: i,
85
- secondaryLabel: r.email ?? s(e.actorId),
86
- email: r.email ?? void 0,
87
- avatarUrl: r.avatar ?? void 0,
88
- resolved: !0
89
- };
90
- return h(a), a;
91
- } catch {
92
- return l(e);
93
- } finally {
94
- d.delete(r);
200
+ u = u.filter((e) => !a.has(e));
95
201
  }
96
- })();
97
- return d.set(r, a), a;
98
- }
99
- async function r() {
100
- let t = await Promise.all(c.map(n));
101
- e || b((e) => {
102
- let n = { ...e };
103
- for (let e of t) n[e.actorId] = e;
104
- return n;
202
+ } catch {}
203
+ let f = l.map((e) => {
204
+ let t = a.get(e.actorId);
205
+ if (t) return t;
206
+ let n = y(e, x);
207
+ if (n) return n;
208
+ let r = d(e);
209
+ return b(r, x), r;
210
+ });
211
+ e || k((e) => {
212
+ let t = { ...e };
213
+ for (let e of f) t[e.actorId] = e;
214
+ return t;
105
215
  });
106
216
  }
107
- return r(), () => {
217
+ return t(), () => {
108
218
  e = !0;
109
219
  };
110
220
  }, [
111
- x,
112
- p,
221
+ i(() => l.map((e) => `${e.actorId}|${e.actorType}`).sort().join(","), [l]),
113
222
  v,
114
- g
115
- ]), y;
223
+ m,
224
+ E,
225
+ D,
226
+ x,
227
+ _
228
+ ]), O;
116
229
  }
117
230
  //#endregion
118
- export { l as buildActorFallback, g as useActorProfiles };
231
+ export { d as buildActorFallback, T as useActorProfiles };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.531.4",
3
+ "version": "2026.531.5",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "imports": {