varminer-app-header 2.2.1 → 2.2.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.
- package/dist/index.d.ts +27 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +80 -139
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +81 -139
- package/dist/index.js.map +1 -1
- package/dist/utils/localStorage.d.ts +25 -15
- package/dist/utils/localStorage.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -79,21 +79,38 @@ interface UserDetailsItem {
|
|
|
79
79
|
* Does not write or overwrite this key; IAM app is the source of truth.
|
|
80
80
|
*/
|
|
81
81
|
declare function getStoredUserDetails(): UserDetailsItem | null;
|
|
82
|
+
/** Unique localStorage key for this header package. Used only for access token; user details come from IAM (linn-i-am-userDetails). */
|
|
83
|
+
declare const PERSIST_HEADER_KEY = "persist:varminer-app-header";
|
|
84
|
+
/** Auth shape stored under PERSIST_HEADER_KEY. Host app should call setHeaderAuth after login so the header can make authenticated calls. */
|
|
85
|
+
interface HeaderAuthState {
|
|
86
|
+
accessToken?: string;
|
|
87
|
+
refreshToken?: string;
|
|
88
|
+
user_id?: number | string;
|
|
89
|
+
[key: string]: unknown;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Store auth (e.g. accessToken) in the header's own persist key. Call this after login so the header can use the token for profile picture etc.
|
|
93
|
+
* User details are not stored here; they come from IAM (linn-i-am-userDetails).
|
|
94
|
+
*/
|
|
95
|
+
declare function setHeaderAuth(auth: HeaderAuthState | null): void;
|
|
96
|
+
/**
|
|
97
|
+
* User display data: from IAM only (linn-i-am-userDetails). No dependency on persist:userdb.
|
|
98
|
+
*/
|
|
82
99
|
declare const getUserDataFromStorage: () => {
|
|
83
|
-
name:
|
|
84
|
-
email:
|
|
85
|
-
role:
|
|
86
|
-
avatar
|
|
87
|
-
initials
|
|
100
|
+
name: string;
|
|
101
|
+
email: string;
|
|
102
|
+
role: string;
|
|
103
|
+
avatar?: string;
|
|
104
|
+
initials?: string;
|
|
88
105
|
} | null;
|
|
89
106
|
declare const getNotificationCountFromStorage: () => number;
|
|
90
107
|
declare const getMessageCountFromStorage: () => number | undefined;
|
|
91
108
|
declare const getI18nLocaleFromStorage: () => string | null;
|
|
92
109
|
declare const setI18nLocaleToStorage: (locale: string) => void;
|
|
93
110
|
/**
|
|
94
|
-
* Get
|
|
95
|
-
*
|
|
96
|
-
* @returns
|
|
111
|
+
* Get auth (and decoded token) for header use. Reads from header's own persist key first; falls back to persist:userdb only for access token.
|
|
112
|
+
* User details are not read from userdb—use getStoredUserDetails / getUserDataFromStorage (IAM) for that.
|
|
113
|
+
* @returns Object with auth, decodedToken, and other keys (user/userDetails/profile null when using header key)
|
|
97
114
|
*/
|
|
98
115
|
declare const getAllDataFromStorage: () => any;
|
|
99
116
|
/**
|
|
@@ -102,13 +119,6 @@ declare const getAllDataFromStorage: () => any;
|
|
|
102
119
|
* @returns Profile picture URL or null if user_id is not available
|
|
103
120
|
*/
|
|
104
121
|
declare const getProfilePictureUrl: (baseUrl?: string) => string | null;
|
|
105
|
-
/**
|
|
106
|
-
* Get profile picture upload URL for the object store API.
|
|
107
|
-
* URL format: {baseUrl}/v1/objectStore/profilePictureUpload?tenantId=&userId=&roleId=
|
|
108
|
-
* @param baseUrl - Base URL for the object store API (default: http://objectstore.impact0mics.local:9012)
|
|
109
|
-
* @returns Full upload URL with query params, or null if tenantId, userId, or roleId is missing
|
|
110
|
-
*/
|
|
111
|
-
declare const getProfilePictureUploadUrl: (baseUrl?: string) => string | null;
|
|
112
122
|
/**
|
|
113
123
|
* Fetch profile picture from API with headers, get S3 URL, generate presigned URL, and return as blob URL
|
|
114
124
|
* This function:
|
|
@@ -130,5 +140,5 @@ declare const fetchProfilePictureAsBlobUrl: (baseUrl?: string, messageId?: strin
|
|
|
130
140
|
bucket?: string;
|
|
131
141
|
}) => Promise<string | null>;
|
|
132
142
|
|
|
133
|
-
export { AppHeader, DrawerProvider, USER_DETAILS_STORAGE_KEY, fetchProfilePictureAsBlobUrl, getAllDataFromStorage, getI18nLocaleFromStorage, getMessageCountFromStorage, getNotificationCountFromStorage,
|
|
134
|
-
export type { AppHeaderProps, SupportedLanguage, Translations, UserDetailsItem, UserDetailsStoredResponse, UserProfile };
|
|
143
|
+
export { AppHeader, DrawerProvider, PERSIST_HEADER_KEY, USER_DETAILS_STORAGE_KEY, fetchProfilePictureAsBlobUrl, getAllDataFromStorage, getI18nLocaleFromStorage, getMessageCountFromStorage, getNotificationCountFromStorage, getProfilePictureUrl, getStoredUserDetails, getTranslations, getUserDataFromStorage, setHeaderAuth, setI18nLocaleToStorage, translations, useDrawer };
|
|
144
|
+
export type { AppHeaderProps, HeaderAuthState, SupportedLanguage, Translations, UserDetailsItem, UserDetailsStoredResponse, UserProfile };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,EACtB,+BAA+B,EAC/B,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,+BAA+B,EAC/B,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,eAAe,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.esm.js
CHANGED
|
@@ -57,77 +57,38 @@ function getStoredUserDetails() {
|
|
|
57
57
|
return null;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
initials: name ? name.split(/\s+/).map((s) => s[0]).join("").slice(0, 2).toUpperCase() : undefined,
|
|
72
|
-
};
|
|
60
|
+
// --- Header-owned persist store (unique key, no conflict with other apps) ---
|
|
61
|
+
/** Unique localStorage key for this header package. Used only for access token; user details come from IAM (linn-i-am-userDetails). */
|
|
62
|
+
const PERSIST_HEADER_KEY = "persist:varminer-app-header";
|
|
63
|
+
/**
|
|
64
|
+
* Store auth (e.g. accessToken) in the header's own persist key. Call this after login so the header can use the token for profile picture etc.
|
|
65
|
+
* User details are not stored here; they come from IAM (linn-i-am-userDetails).
|
|
66
|
+
*/
|
|
67
|
+
function setHeaderAuth(auth) {
|
|
68
|
+
try {
|
|
69
|
+
const payload = auth ? { auth } : {};
|
|
70
|
+
localStorage.setItem(PERSIST_HEADER_KEY, JSON.stringify(payload));
|
|
73
71
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const parsedOuter = JSON.parse(userDbString);
|
|
78
|
-
const parseNested = (value) => {
|
|
79
|
-
if (typeof value === 'string') {
|
|
80
|
-
try {
|
|
81
|
-
return JSON.parse(value);
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
return value;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return value;
|
|
88
|
-
};
|
|
89
|
-
let userData = null;
|
|
90
|
-
if (parsedOuter.userDetails) {
|
|
91
|
-
const parsedUserDetails = parseNested(parsedOuter.userDetails);
|
|
92
|
-
userData = parsedUserDetails.user || parsedUserDetails.data || parsedUserDetails;
|
|
93
|
-
}
|
|
94
|
-
if (!userData && parsedOuter.user) {
|
|
95
|
-
const parsedUser = parseNested(parsedOuter.user);
|
|
96
|
-
userData = parsedUser.user || parsedUser.data || parsedUser.currentUser || parsedUser;
|
|
97
|
-
}
|
|
98
|
-
if (!userData && parsedOuter.authDetails) {
|
|
99
|
-
const parsedAuthDetails = parseNested(parsedOuter.authDetails);
|
|
100
|
-
if (parsedAuthDetails.auth) {
|
|
101
|
-
userData = parsedAuthDetails.auth.user || parsedAuthDetails.auth.userData;
|
|
102
|
-
}
|
|
103
|
-
if (!userData) {
|
|
104
|
-
userData = parsedAuthDetails.user || parsedAuthDetails.userData || parsedAuthDetails.currentUser;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (!userData && parsedOuter.profile) {
|
|
108
|
-
const parsedProfile = parseNested(parsedOuter.profile);
|
|
109
|
-
userData = parsedProfile.user || parsedProfile.data || parsedProfile;
|
|
110
|
-
}
|
|
111
|
-
if (userData) {
|
|
112
|
-
let name = userData.name || userData.fullName || userData.userName || "";
|
|
113
|
-
if (!name && (userData.firstName || userData.lastName)) {
|
|
114
|
-
name = [userData.firstName, userData.lastName].filter(Boolean).join(' ');
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
name: name || "",
|
|
118
|
-
email: userData.email || userData.emailAddress || "",
|
|
119
|
-
role: userData.role || userData.userRole || userData.designation || userData.title || "",
|
|
120
|
-
avatar: userData.avatar || userData.profilePicture || userData.imageUrl || userData.profileImage,
|
|
121
|
-
initials: userData.initials,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
catch (err) {
|
|
126
|
-
console.error("Error parsing user data from localStorage:", err);
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
console.error("Error setting header auth:", err);
|
|
129
74
|
}
|
|
130
|
-
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* User display data: from IAM only (linn-i-am-userDetails). No dependency on persist:userdb.
|
|
78
|
+
*/
|
|
79
|
+
const getUserDataFromStorage = () => {
|
|
80
|
+
const iamUser = getStoredUserDetails();
|
|
81
|
+
if (!iamUser)
|
|
82
|
+
return null;
|
|
83
|
+
const name = [iamUser.firstName, iamUser.lastName].filter(Boolean).join(" ").trim();
|
|
84
|
+
const role = iamUser.roles?.length ? iamUser.roles[0] : iamUser.workInfo?.jobTitle ?? "";
|
|
85
|
+
return {
|
|
86
|
+
name: name || "",
|
|
87
|
+
email: iamUser.email || "",
|
|
88
|
+
role: role || "",
|
|
89
|
+
avatar: undefined,
|
|
90
|
+
initials: name ? name.split(/\s+/).map((s) => s[0]).join("").slice(0, 2).toUpperCase() : undefined,
|
|
91
|
+
};
|
|
131
92
|
};
|
|
132
93
|
const getNotificationCountFromStorage = () => {
|
|
133
94
|
const userDbString = localStorage.getItem("persist:userdb");
|
|
@@ -243,26 +204,49 @@ const decodeJWT = (token) => {
|
|
|
243
204
|
return null;
|
|
244
205
|
}
|
|
245
206
|
};
|
|
207
|
+
const emptyStorageResult = () => ({
|
|
208
|
+
auth: null,
|
|
209
|
+
user: null,
|
|
210
|
+
authDetails: null,
|
|
211
|
+
userDetails: null,
|
|
212
|
+
profile: null,
|
|
213
|
+
notifications: null,
|
|
214
|
+
messages: null,
|
|
215
|
+
app: null,
|
|
216
|
+
decodedToken: null,
|
|
217
|
+
rawData: null,
|
|
218
|
+
});
|
|
246
219
|
/**
|
|
247
|
-
* Get
|
|
248
|
-
*
|
|
249
|
-
* @returns
|
|
220
|
+
* Get auth (and decoded token) for header use. Reads from header's own persist key first; falls back to persist:userdb only for access token.
|
|
221
|
+
* User details are not read from userdb—use getStoredUserDetails / getUserDataFromStorage (IAM) for that.
|
|
222
|
+
* @returns Object with auth, decodedToken, and other keys (user/userDetails/profile null when using header key)
|
|
250
223
|
*/
|
|
251
224
|
const getAllDataFromStorage = () => {
|
|
225
|
+
// Prefer header-owned persist key (unique, no conflict with other apps)
|
|
226
|
+
const headerStr = localStorage.getItem(PERSIST_HEADER_KEY);
|
|
227
|
+
if (headerStr) {
|
|
228
|
+
try {
|
|
229
|
+
const parsed = JSON.parse(headerStr);
|
|
230
|
+
const auth = parsed?.auth;
|
|
231
|
+
const accessToken = auth?.accessToken;
|
|
232
|
+
if (accessToken) {
|
|
233
|
+
const decodedToken = decodeJWT(accessToken);
|
|
234
|
+
return {
|
|
235
|
+
...emptyStorageResult(),
|
|
236
|
+
auth: auth,
|
|
237
|
+
decodedToken: decodedToken ? Object.fromEntries(Object.entries(decodedToken).map(([k, v]) => [k, v ?? null])) : null,
|
|
238
|
+
rawData: parsed,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
console.error("Error parsing header persist:", err);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Fallback: read access token from persist:userdb (e.g. legacy or shared auth)
|
|
252
247
|
const userDbString = localStorage.getItem("persist:userdb");
|
|
253
248
|
if (!userDbString) {
|
|
254
|
-
return
|
|
255
|
-
auth: null,
|
|
256
|
-
user: null,
|
|
257
|
-
authDetails: null,
|
|
258
|
-
userDetails: null,
|
|
259
|
-
profile: null,
|
|
260
|
-
notifications: null,
|
|
261
|
-
messages: null,
|
|
262
|
-
app: null,
|
|
263
|
-
decodedToken: null,
|
|
264
|
-
rawData: null,
|
|
265
|
-
};
|
|
249
|
+
return emptyStorageResult();
|
|
266
250
|
}
|
|
267
251
|
try {
|
|
268
252
|
const parsedOuter = JSON.parse(userDbString);
|
|
@@ -340,19 +324,7 @@ const getAllDataFromStorage = () => {
|
|
|
340
324
|
}
|
|
341
325
|
catch (err) {
|
|
342
326
|
console.error("Error parsing all data from localStorage:", err);
|
|
343
|
-
return {
|
|
344
|
-
auth: null,
|
|
345
|
-
user: null,
|
|
346
|
-
authDetails: null,
|
|
347
|
-
userDetails: null,
|
|
348
|
-
profile: null,
|
|
349
|
-
notifications: null,
|
|
350
|
-
messages: null,
|
|
351
|
-
app: null,
|
|
352
|
-
decodedToken: null,
|
|
353
|
-
rawData: null,
|
|
354
|
-
error: err instanceof Error ? err.message : 'Unknown error',
|
|
355
|
-
};
|
|
327
|
+
return { ...emptyStorageResult(), error: err instanceof Error ? err.message : "Unknown error" };
|
|
356
328
|
}
|
|
357
329
|
};
|
|
358
330
|
/**
|
|
@@ -373,43 +345,6 @@ const getProfilePictureUrl = (baseUrl = "http://objectstore.impact0mics.local:90
|
|
|
373
345
|
return null;
|
|
374
346
|
}
|
|
375
347
|
};
|
|
376
|
-
/**
|
|
377
|
-
* Get profile picture upload URL for the object store API.
|
|
378
|
-
* URL format: {baseUrl}/v1/objectStore/profilePictureUpload?tenantId=&userId=&roleId=
|
|
379
|
-
* @param baseUrl - Base URL for the object store API (default: http://objectstore.impact0mics.local:9012)
|
|
380
|
-
* @returns Full upload URL with query params, or null if tenantId, userId, or roleId is missing
|
|
381
|
-
*/
|
|
382
|
-
const getProfilePictureUploadUrl = (baseUrl = "http://objectstore.impact0mics.local:9012") => {
|
|
383
|
-
try {
|
|
384
|
-
const allData = getAllDataFromStorage();
|
|
385
|
-
const iamUser = getStoredUserDetails();
|
|
386
|
-
const tenantId = allData.decodedToken?.tenant_id ??
|
|
387
|
-
allData.decodedToken?.tenant ??
|
|
388
|
-
allData.auth?.tenant_id ??
|
|
389
|
-
allData.auth?.tenant ??
|
|
390
|
-
null;
|
|
391
|
-
const userId = allData.decodedToken?.user_id ??
|
|
392
|
-
allData.auth?.user_id ??
|
|
393
|
-
iamUser?.userId ??
|
|
394
|
-
null;
|
|
395
|
-
const roleId = allData.decodedToken?.role_id ??
|
|
396
|
-
allData.auth?.role_id ??
|
|
397
|
-
null;
|
|
398
|
-
if (tenantId == null || userId == null || roleId == null)
|
|
399
|
-
return null;
|
|
400
|
-
const cleanBaseUrl = baseUrl.replace(/\/$/, "");
|
|
401
|
-
const params = new URLSearchParams({
|
|
402
|
-
tenantId: String(tenantId),
|
|
403
|
-
userId: String(userId),
|
|
404
|
-
roleId: String(roleId),
|
|
405
|
-
});
|
|
406
|
-
return `${cleanBaseUrl}/v1/objectStore/profilePictureUpload?${params.toString()}`;
|
|
407
|
-
}
|
|
408
|
-
catch (err) {
|
|
409
|
-
console.error("Error getting profile picture upload URL:", err);
|
|
410
|
-
return null;
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
348
|
/**
|
|
414
349
|
* Generate AWS S3 presigned URL for accessing S3 object
|
|
415
350
|
* @param s3Url - Full S3 URL (e.g., https://bucket.s3.region.amazonaws.com/key)
|
|
@@ -531,13 +466,19 @@ const fetchProfilePictureAsBlobUrl = async (baseUrl = "http://objectstore.impact
|
|
|
531
466
|
// Generate message ID and correlation ID if not provided
|
|
532
467
|
const msgId = messageId || `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
533
468
|
const corrId = correlationId || `corr-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
469
|
+
const allData = getAllDataFromStorage();
|
|
470
|
+
const accessToken = allData.auth?.accessToken;
|
|
471
|
+
const headers = {
|
|
472
|
+
'X-Message-Id': msgId,
|
|
473
|
+
'X-Correlation-Id': corrId,
|
|
474
|
+
};
|
|
475
|
+
if (accessToken) {
|
|
476
|
+
headers['Authorization'] = `Bearer ${accessToken}`;
|
|
477
|
+
}
|
|
534
478
|
// Step 1: Fetch the profile picture path from API (returns JSON with filePath)
|
|
535
479
|
const apiResponse = await fetch(profilePictureUrl, {
|
|
536
480
|
method: 'GET',
|
|
537
|
-
headers
|
|
538
|
-
'X-Message-Id': msgId,
|
|
539
|
-
'X-Correlation-Id': corrId,
|
|
540
|
-
},
|
|
481
|
+
headers,
|
|
541
482
|
});
|
|
542
483
|
// Check if the API response is successful
|
|
543
484
|
if (!apiResponse.ok) {
|
|
@@ -1164,5 +1105,5 @@ const AppHeader = ({ language: languageProp }) => {
|
|
|
1164
1105
|
}, children: jsx(MoreIcon, {}) }) })] }) }), renderMobileMenu, renderMenu] }));
|
|
1165
1106
|
};
|
|
1166
1107
|
|
|
1167
|
-
export { AppHeader, DrawerProvider, USER_DETAILS_STORAGE_KEY, fetchProfilePictureAsBlobUrl, getAllDataFromStorage, getI18nLocaleFromStorage, getMessageCountFromStorage, getNotificationCountFromStorage,
|
|
1108
|
+
export { AppHeader, DrawerProvider, PERSIST_HEADER_KEY, USER_DETAILS_STORAGE_KEY, fetchProfilePictureAsBlobUrl, getAllDataFromStorage, getI18nLocaleFromStorage, getMessageCountFromStorage, getNotificationCountFromStorage, getProfilePictureUrl, getStoredUserDetails, getTranslations, getUserDataFromStorage, setHeaderAuth, setI18nLocaleToStorage, translations, useDrawer };
|
|
1168
1109
|
//# sourceMappingURL=index.esm.js.map
|