@oxyhq/core 3.4.16 → 3.4.18

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.
@@ -401,6 +401,7 @@ class AuthManager {
401
401
  user: {
402
402
  id: session.user.id,
403
403
  username: session.user.username,
404
+ name: session.user.name,
404
405
  avatar: session.user.avatar ?? null,
405
406
  },
406
407
  accessToken: session.accessToken,
@@ -632,6 +633,7 @@ class AuthManager {
632
633
  return {
633
634
  id: account.user.id,
634
635
  username: account.user.username,
636
+ name: account.user.name,
635
637
  avatar: account.user.avatar ?? undefined,
636
638
  };
637
639
  }
@@ -676,6 +678,7 @@ class AuthManager {
676
678
  this.currentUser = {
677
679
  id: hydrated.id,
678
680
  username: hydrated.username,
681
+ name: hydrated.name,
679
682
  avatar: hydrated.avatar ?? undefined,
680
683
  };
681
684
  this.notifyListeners();
@@ -877,6 +880,7 @@ class AuthManager {
877
880
  ? {
878
881
  id: updated.user.id,
879
882
  username: updated.user.username,
883
+ name: updated.user.name,
880
884
  avatar: updated.user.avatar ?? undefined,
881
885
  }
882
886
  : null;
@@ -932,6 +936,7 @@ class AuthManager {
932
936
  ? {
933
937
  id: next.user.id,
934
938
  username: next.user.username,
939
+ name: next.user.name,
935
940
  avatar: next.user.avatar ?? undefined,
936
941
  }
937
942
  : null;
@@ -700,7 +700,10 @@ class HttpService {
700
700
  const refreshed = await this.refreshAccessToken('preflight');
701
701
  if (refreshed)
702
702
  return `Bearer ${refreshed}`;
703
- // Refresh failed — don't use the expired token (would cause 401 loop)
703
+ if (decoded.exp > currentTime) {
704
+ return `Bearer ${accessToken}`;
705
+ }
706
+ // Refresh failed — don't use an expired token (would cause 401 loop)
704
707
  return null;
705
708
  }
706
709
  return `Bearer ${accessToken}`;
@@ -494,7 +494,7 @@ function OxyServicesAuthMixin(Base) {
494
494
  continue;
495
495
  }
496
496
  const userId = e.user.id ?? e.user._id;
497
- if (!userId || !e.user.username) {
497
+ if (!userId || !e.user.username || !e.user.name?.displayName) {
498
498
  continue;
499
499
  }
500
500
  if (typeof e.authuser !== 'number') {
@@ -115,12 +115,13 @@ function OxyServicesSsoMixin(Base) {
115
115
  throw this.handleError(new Error('SSO exchange returned no sessionId'));
116
116
  }
117
117
  const userId = payload.user?.id ?? payload.user?._id;
118
- if (!userId || typeof payload.user?.username !== 'string') {
118
+ if (!userId || typeof payload.user?.username !== 'string' || typeof payload.user.name?.displayName !== 'string') {
119
119
  throw this.handleError(new Error('SSO exchange returned an invalid user'));
120
120
  }
121
121
  const user = {
122
122
  id: userId,
123
123
  username: payload.user.username,
124
+ name: payload.user.name,
124
125
  avatar: payload.user.avatar,
125
126
  };
126
127
  // Plant the access token exactly like exchangeIdTokenForSession does.
@@ -27,7 +27,7 @@ function OxyServicesUserMixin(Base) {
27
27
  }
28
28
  /**
29
29
  * Lightweight username lookup for login flows.
30
- * Returns minimal public info: exists, color, avatar, displayName.
30
+ * Returns minimal public info: exists, color, avatar, name.displayName.
31
31
  * Faster than getProfileByUsername — no stats, no formatting.
32
32
  */
33
33
  async lookupUsername(username) {
@@ -21,12 +21,13 @@ exports.formatPublicKeyHandle = formatPublicKeyHandle;
21
21
  * Resolve a friendly display name for a user.
22
22
  *
23
23
  * Order of preference:
24
- * 1. `displayName` from the API contract.
24
+ * 1. `name.displayName` from the API user contract.
25
25
  * 2. `name.full`, or composed `name.first name.last` for local unsaved shapes.
26
- * 3. `name` when stored as a plain string.
27
- * 4. `username`
28
- * 5. `Account 0x12345678…` (derived from publicKey, when present)
29
- * 6. Translated fallback (e.g. "Unnamed")
26
+ * 3. `name` when passed as a plain string by local non-DTO call sites.
27
+ * 4. pre-normalized account-row `displayName`.
28
+ * 5. `username`
29
+ * 6. `Account 0x12345678…` (derived from publicKey, when present)
30
+ * 7. Translated fallback (e.g. "Unnamed")
30
31
  *
31
32
  * The translation key `common.unnamed` is used for the final fallback. If the
32
33
  * caller does not pass a locale, the default English translation is used.
@@ -35,9 +36,10 @@ const getAccountDisplayName = (user, locale) => {
35
36
  if (!user)
36
37
  return (0, i18n_1.translate)(locale, 'common.unnamed');
37
38
  const { name, displayName, username, publicKey } = user;
38
- if (typeof displayName === 'string' && displayName.trim())
39
- return displayName.trim();
40
39
  if (name && typeof name === 'object') {
40
+ if (typeof name.displayName === 'string' && name.displayName.trim()) {
41
+ return name.displayName.trim();
42
+ }
41
43
  if (typeof name.full === 'string' && name.full.trim())
42
44
  return name.full.trim();
43
45
  const first = typeof name.first === 'string' ? name.first.trim() : '';
@@ -49,6 +51,8 @@ const getAccountDisplayName = (user, locale) => {
49
51
  else if (typeof name === 'string' && name.trim()) {
50
52
  return name.trim();
51
53
  }
54
+ if (typeof displayName === 'string' && displayName.trim())
55
+ return displayName.trim();
52
56
  if (typeof username === 'string' && username.trim())
53
57
  return username.trim();
54
58
  if (typeof publicKey === 'string' && publicKey.length > 0) {
@@ -103,18 +107,19 @@ const createQuickAccount = (sessionId, userData, existingAccount, getFileDownloa
103
107
  const userId = userData.id || (typeof userData._id === 'string' ? userData._id : userData._id?.toString());
104
108
  // Preserve existing avatarUrl if avatar hasn't changed (prevents image reload)
105
109
  let avatarUrl;
106
- if (existingAccount && existingAccount.avatar === userData.avatar && existingAccount.avatarUrl) {
110
+ const avatar = userData.avatar ?? undefined;
111
+ if (existingAccount && existingAccount.avatar === avatar && existingAccount.avatarUrl) {
107
112
  avatarUrl = existingAccount.avatarUrl;
108
113
  }
109
- else if (userData.avatar && getFileDownloadUrl) {
110
- avatarUrl = getFileDownloadUrl(userData.avatar, 'thumb');
114
+ else if (avatar && getFileDownloadUrl) {
115
+ avatarUrl = getFileDownloadUrl(avatar, 'thumb');
111
116
  }
112
117
  return {
113
118
  sessionId,
114
119
  userId,
115
120
  username: userData.username || '',
116
121
  displayName,
117
- avatar: userData.avatar,
122
+ avatar,
118
123
  avatarUrl,
119
124
  };
120
125
  };