@oxyhq/core 3.4.15 → 3.4.17

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.
@@ -397,6 +397,7 @@ export class AuthManager {
397
397
  user: {
398
398
  id: session.user.id,
399
399
  username: session.user.username,
400
+ name: session.user.name,
400
401
  avatar: session.user.avatar ?? null,
401
402
  },
402
403
  accessToken: session.accessToken,
@@ -628,6 +629,7 @@ export class AuthManager {
628
629
  return {
629
630
  id: account.user.id,
630
631
  username: account.user.username,
632
+ name: account.user.name,
631
633
  avatar: account.user.avatar ?? undefined,
632
634
  };
633
635
  }
@@ -672,6 +674,7 @@ export class AuthManager {
672
674
  this.currentUser = {
673
675
  id: hydrated.id,
674
676
  username: hydrated.username,
677
+ name: hydrated.name,
675
678
  avatar: hydrated.avatar ?? undefined,
676
679
  };
677
680
  this.notifyListeners();
@@ -873,6 +876,7 @@ export class AuthManager {
873
876
  ? {
874
877
  id: updated.user.id,
875
878
  username: updated.user.username,
879
+ name: updated.user.name,
876
880
  avatar: updated.user.avatar ?? undefined,
877
881
  }
878
882
  : null;
@@ -928,6 +932,7 @@ export class AuthManager {
928
932
  ? {
929
933
  id: next.user.id,
930
934
  username: next.user.username,
935
+ name: next.user.name,
931
936
  avatar: next.user.avatar ?? undefined,
932
937
  }
933
938
  : null;
@@ -489,7 +489,7 @@ export function OxyServicesAuthMixin(Base) {
489
489
  continue;
490
490
  }
491
491
  const userId = e.user.id ?? e.user._id;
492
- if (!userId || !e.user.username) {
492
+ if (!userId || !e.user.username || !e.user.name?.displayName) {
493
493
  continue;
494
494
  }
495
495
  if (typeof e.authuser !== 'number') {
@@ -111,12 +111,13 @@ export function OxyServicesSsoMixin(Base) {
111
111
  throw this.handleError(new Error('SSO exchange returned no sessionId'));
112
112
  }
113
113
  const userId = payload.user?.id ?? payload.user?._id;
114
- if (!userId || typeof payload.user?.username !== 'string') {
114
+ if (!userId || typeof payload.user?.username !== 'string' || typeof payload.user.name?.displayName !== 'string') {
115
115
  throw this.handleError(new Error('SSO exchange returned an invalid user'));
116
116
  }
117
117
  const user = {
118
118
  id: userId,
119
119
  username: payload.user.username,
120
+ name: payload.user.name,
120
121
  avatar: payload.user.avatar,
121
122
  };
122
123
  // Plant the access token exactly like exchangeIdTokenForSession does.
@@ -24,7 +24,7 @@ export function OxyServicesUserMixin(Base) {
24
24
  }
25
25
  /**
26
26
  * Lightweight username lookup for login flows.
27
- * Returns minimal public info: exists, color, avatar, displayName.
27
+ * Returns minimal public info: exists, color, avatar, name.displayName.
28
28
  * Faster than getProfileByUsername — no stats, no formatting.
29
29
  */
30
30
  async lookupUsername(username) {
@@ -17,16 +17,13 @@ export const formatPublicKeyHandle = (publicKey) => {
17
17
  * Resolve a friendly display name for a user.
18
18
  *
19
19
  * Order of preference:
20
- * 1. `name.full`, or composed `name.first name.last` (FIRST-NAME-ONLY SAFE —
21
- * a user with only a first name resolves to that first name, never to the
22
- * lowercase username; this is the exact drift bug the auth app hit).
23
- * 2. `name` (when stored as a plain string)
24
- * 3. `displayName` (server `displayName` virtual — `username || truncatedKey`).
25
- * Placed AFTER the structured name on purpose: the server virtual ignores
26
- * `name`, so preferring it first would re-introduce the first-only bug.
27
- * 4. `username`
28
- * 5. `Account 0x12345678…` (derived from publicKey, when present)
29
- * 6. Translated fallback (e.g. "Unnamed")
20
+ * 1. `name.displayName` from the API user contract.
21
+ * 2. `name.full`, or composed `name.first name.last` for local unsaved shapes.
22
+ * 3. `name` when passed as a plain string by local non-DTO call sites.
23
+ * 4. pre-normalized account-row `displayName`.
24
+ * 5. `username`
25
+ * 6. `Account 0x12345678…` (derived from publicKey, when present)
26
+ * 7. Translated fallback (e.g. "Unnamed")
30
27
  *
31
28
  * The translation key `common.unnamed` is used for the final fallback. If the
32
29
  * caller does not pass a locale, the default English translation is used.
@@ -36,6 +33,9 @@ export const getAccountDisplayName = (user, locale) => {
36
33
  return translate(locale, 'common.unnamed');
37
34
  const { name, displayName, username, publicKey } = user;
38
35
  if (name && typeof name === 'object') {
36
+ if (typeof name.displayName === 'string' && name.displayName.trim()) {
37
+ return name.displayName.trim();
38
+ }
39
39
  if (typeof name.full === 'string' && name.full.trim())
40
40
  return name.full.trim();
41
41
  const first = typeof name.first === 'string' ? name.first.trim() : '';
@@ -100,18 +100,19 @@ export const createQuickAccount = (sessionId, userData, existingAccount, getFile
100
100
  const userId = userData.id || (typeof userData._id === 'string' ? userData._id : userData._id?.toString());
101
101
  // Preserve existing avatarUrl if avatar hasn't changed (prevents image reload)
102
102
  let avatarUrl;
103
- if (existingAccount && existingAccount.avatar === userData.avatar && existingAccount.avatarUrl) {
103
+ const avatar = userData.avatar ?? undefined;
104
+ if (existingAccount && existingAccount.avatar === avatar && existingAccount.avatarUrl) {
104
105
  avatarUrl = existingAccount.avatarUrl;
105
106
  }
106
- else if (userData.avatar && getFileDownloadUrl) {
107
- avatarUrl = getFileDownloadUrl(userData.avatar, 'thumb');
107
+ else if (avatar && getFileDownloadUrl) {
108
+ avatarUrl = getFileDownloadUrl(avatar, 'thumb');
108
109
  }
109
110
  return {
110
111
  sessionId,
111
112
  userId,
112
113
  username: userData.username || '',
113
114
  displayName,
114
- avatar: userData.avatar,
115
+ avatar,
115
116
  avatarUrl,
116
117
  };
117
118
  };