@goralys/core 1.5.0 → 1.6.1
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 +26 -10
- package/dist/index.js +53 -25
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -74,11 +74,20 @@ type UserRole = {
|
|
|
74
74
|
declare const USER_ROLES: readonly ["admin", "teacher", "student", "none"];
|
|
75
75
|
type UserData = {
|
|
76
76
|
username: string;
|
|
77
|
-
|
|
77
|
+
fullName: string;
|
|
78
78
|
role: UserRole["role"];
|
|
79
|
-
|
|
79
|
+
publicId: string;
|
|
80
80
|
email: string | null | undefined;
|
|
81
81
|
};
|
|
82
|
+
type UserProfile = {
|
|
83
|
+
id: number;
|
|
84
|
+
username: string;
|
|
85
|
+
pubId: string;
|
|
86
|
+
fullName: string;
|
|
87
|
+
role: UserRole["role"];
|
|
88
|
+
email: string;
|
|
89
|
+
createdAt: PHPDateTime;
|
|
90
|
+
};
|
|
82
91
|
type User = {
|
|
83
92
|
username: string;
|
|
84
93
|
publicId: string;
|
|
@@ -95,8 +104,8 @@ type AuthTokenContext = "admin-panel" | "profile";
|
|
|
95
104
|
type AuthToken = {
|
|
96
105
|
username: string;
|
|
97
106
|
name: string;
|
|
98
|
-
expires:
|
|
99
|
-
created:
|
|
107
|
+
expires: PHPDateTime;
|
|
108
|
+
created: PHPDateTime;
|
|
100
109
|
};
|
|
101
110
|
|
|
102
111
|
declare function useAuthTokens(context: AuthTokenContext, target?: string | null): {
|
|
@@ -179,8 +188,8 @@ declare function useSupportTickets(): {
|
|
|
179
188
|
|
|
180
189
|
interface UseSyncedResourceOptions<T> {
|
|
181
190
|
name: string;
|
|
182
|
-
cacheKey
|
|
183
|
-
syncKey
|
|
191
|
+
cacheKey?: string;
|
|
192
|
+
syncKey?: string;
|
|
184
193
|
fetcher: () => Promise<Response | null | undefined>;
|
|
185
194
|
parse: (data: unknown) => T | null;
|
|
186
195
|
requireAuth?: boolean;
|
|
@@ -232,8 +241,8 @@ declare const SUPPORT_TICKET_CACHE = "support-tickets-cache";
|
|
|
232
241
|
declare const SUPPORT_TICKET_SYNC = "support-tickets-synced";
|
|
233
242
|
declare const SUBJECT_SYNCS: Record<UserRole["role"], string>;
|
|
234
243
|
declare const SUBJECT_CACHES: Record<UserRole["role"], string>;
|
|
235
|
-
declare const AUTH_TOKEN_SYNCS: Record<AuthTokenContext, string>;
|
|
236
|
-
declare const AUTH_TOKEN_CACHES: Record<AuthTokenContext, string>;
|
|
244
|
+
declare const AUTH_TOKEN_SYNCS: Record<AuthTokenContext, string | undefined>;
|
|
245
|
+
declare const AUTH_TOKEN_CACHES: Record<AuthTokenContext, string | undefined>;
|
|
237
246
|
type UserType = {
|
|
238
247
|
type: "users-virtual" | "users-real" | "admins-virtual" | "admins-real";
|
|
239
248
|
};
|
|
@@ -266,6 +275,10 @@ declare function isFoolsDay(): boolean;
|
|
|
266
275
|
declare function buildArray<T>(...items: (T | false | null | undefined)[]): T[];
|
|
267
276
|
declare const fromPhpDate: (phpDate: PHPDateTime) => Date;
|
|
268
277
|
declare const parsePhpDateTime: (phpDate: PHPDateTime) => string;
|
|
278
|
+
declare function separateNames(fullName: string): {
|
|
279
|
+
firstName: string;
|
|
280
|
+
lastName: string;
|
|
281
|
+
};
|
|
269
282
|
|
|
270
283
|
declare function emitAuthEvent(event: AuthEvent): void;
|
|
271
284
|
declare function onAuthEvent(callback: (event: AuthEvent) => void): () => void;
|
|
@@ -289,8 +302,11 @@ type HttpMethod = (typeof HTTP_METHODS)[number];
|
|
|
289
302
|
* @returns true if the string is an HTTP method.
|
|
290
303
|
*/
|
|
291
304
|
declare function isHTTPMethod(maybeMethod: string): maybeMethod is HttpMethod;
|
|
305
|
+
type GoralysFetchOptions = RequestInit & {
|
|
306
|
+
suppressRedirect?: boolean;
|
|
307
|
+
};
|
|
292
308
|
|
|
293
|
-
declare function goralysFetchClient(method: HttpMethod, input: string | URL | Request, payload?: Record<string, string | number | boolean | null> | FormData, requestOptions?:
|
|
309
|
+
declare function goralysFetchClient(method: HttpMethod, input: string | URL | Request, payload?: Record<string, string | number | boolean | null> | FormData, requestOptions?: GoralysFetchOptions): Promise<Response>;
|
|
294
310
|
declare function fetchCsrfClient(formId: string): Promise<string | null>;
|
|
295
311
|
declare function buildApiUrl(endpoint: string, params: Record<string, string | null>, domain?: boolean): string;
|
|
296
312
|
declare function handleToastRequest(r: Response, showToast: ToastFn, redirect?: boolean, duration?: number): Promise<boolean>;
|
|
@@ -339,4 +355,4 @@ declare function fetchVirtualUsersClient(): Promise<Response>;
|
|
|
339
355
|
declare function fetchAdminsClient(): Promise<Response>;
|
|
340
356
|
declare function fetchVirtualAdminsClient(): Promise<Response>;
|
|
341
357
|
|
|
342
|
-
export { ADMIN_CACHE_RADIX, ADMIN_SYNC_RADIX, AUTH_TOKEN_CACHES, AUTH_TOKEN_CACHE_RADIX, AUTH_TOKEN_SYNCS, AUTH_TOKEN_SYNC_RADIX, type AuthEvent, type AuthToken, type AuthTokenContext, COOKIES_DISMISSED_KEY, type CheckAuthImpl, type ConfirmOptions, type CookieValue, type CookiesAdapter, type DraftModalResult, EMAIL_KEY, FLASH_TOAST_KEY, FULL_NAME_KEY, GoralysActionHandler, type GoralysClientConfig, HTTP_METHODS, type HttpMethod, LOGO_PATH, PERSISTANT_COOKIES, PERSISTANT_LOCALS, type PHPDateTime, PUB_ID_KEY, ROLE_KEY, SUBJECT_CACHES, SUBJECT_CACHE_RADIX, SUBJECT_SYNCS, SUBJECT_SYNC_RADIX, SUPPORT_TICKET_CACHE, SUPPORT_TICKET_SYNC, type StorageAdapter, type Subject, type SubjectStatus, SubjectStatusConfig, type SubjectsSearchField, type SupportReasons, type SupportTicket, type Toast, type ToastConfig, type ToastFn, USERNAME_KEY, USER_CACHES, USER_CACHE_RADIX, USER_ROLES, USER_SYNCS, USER_SYNC_RADIX, type UseSyncedResourceOptions, type User, type UserData, type UserEvent, type UserRole, type UserType, buildApiUrl, buildArray, cacheUserDataClient, configGoralysCore, configureCheckAuth, configureCookies, configureGoralysClient, configureStorage, configureToast, cookiesGet, cookiesGetAll, cookiesOnChange, cookiesRemove, cookiesSet, emitAuthEvent, emitNavigationEvent, emitUserEvent, emptyUserCacheClient, fetchAdminsClient, fetchAuthTokensForContext, fetchCsrfClient, fetchSubjectsForRoleClient, fetchTokensAdminPanel, fetchTokensProfile, fetchUsersClient, fetchVirtualAdminsClient, fetchVirtualUsersClient, fromPhpDate, getGoralysClientConfig, getLongFromShort, getShortFromLong, getStatusHelper, getStatusLabel, getToastConfig, goralysFetchClient, handleToastRequest, helpContent, isAuthenticated, isFoolsDay, isHTTPMethod, onAuthEvent, onNavigationEvent, onUserEvent, parsePhpDateTime, reasonsConfig, searchFields, storageGet, storageKeyAt, storageRemove, storageSet, storageSize, useAdmins, useAuthTokens, useSubjects, useSupportTickets, useSyncedResource, useUsers, useVirtualAdmins, useVirtualUsers };
|
|
358
|
+
export { ADMIN_CACHE_RADIX, ADMIN_SYNC_RADIX, AUTH_TOKEN_CACHES, AUTH_TOKEN_CACHE_RADIX, AUTH_TOKEN_SYNCS, AUTH_TOKEN_SYNC_RADIX, type AuthEvent, type AuthToken, type AuthTokenContext, COOKIES_DISMISSED_KEY, type CheckAuthImpl, type ConfirmOptions, type CookieValue, type CookiesAdapter, type DraftModalResult, EMAIL_KEY, FLASH_TOAST_KEY, FULL_NAME_KEY, GoralysActionHandler, type GoralysClientConfig, type GoralysFetchOptions, HTTP_METHODS, type HttpMethod, LOGO_PATH, PERSISTANT_COOKIES, PERSISTANT_LOCALS, type PHPDateTime, PUB_ID_KEY, ROLE_KEY, SUBJECT_CACHES, SUBJECT_CACHE_RADIX, SUBJECT_SYNCS, SUBJECT_SYNC_RADIX, SUPPORT_TICKET_CACHE, SUPPORT_TICKET_SYNC, type StorageAdapter, type Subject, type SubjectStatus, SubjectStatusConfig, type SubjectsSearchField, type SupportReasons, type SupportTicket, type Toast, type ToastConfig, type ToastFn, USERNAME_KEY, USER_CACHES, USER_CACHE_RADIX, USER_ROLES, USER_SYNCS, USER_SYNC_RADIX, type UseSyncedResourceOptions, type User, type UserData, type UserEvent, type UserProfile, type UserRole, type UserType, buildApiUrl, buildArray, cacheUserDataClient, configGoralysCore, configureCheckAuth, configureCookies, configureGoralysClient, configureStorage, configureToast, cookiesGet, cookiesGetAll, cookiesOnChange, cookiesRemove, cookiesSet, emitAuthEvent, emitNavigationEvent, emitUserEvent, emptyUserCacheClient, fetchAdminsClient, fetchAuthTokensForContext, fetchCsrfClient, fetchSubjectsForRoleClient, fetchTokensAdminPanel, fetchTokensProfile, fetchUsersClient, fetchVirtualAdminsClient, fetchVirtualUsersClient, fromPhpDate, getGoralysClientConfig, getLongFromShort, getShortFromLong, getStatusHelper, getStatusLabel, getToastConfig, goralysFetchClient, handleToastRequest, helpContent, isAuthenticated, isFoolsDay, isHTTPMethod, onAuthEvent, onNavigationEvent, onUserEvent, parsePhpDateTime, reasonsConfig, searchFields, separateNames, storageGet, storageKeyAt, storageRemove, storageSet, storageSize, useAdmins, useAuthTokens, useSubjects, useSupportTickets, useSyncedResource, useUsers, useVirtualAdmins, useVirtualUsers };
|
package/dist/index.js
CHANGED
|
@@ -111,11 +111,12 @@ var SUBJECT_CACHES = {
|
|
|
111
111
|
none: SUBJECT_CACHE_RADIX + "unknown"
|
|
112
112
|
};
|
|
113
113
|
var AUTH_TOKEN_SYNCS = {
|
|
114
|
-
"admin-panel":
|
|
114
|
+
"admin-panel": void 0,
|
|
115
115
|
profile: AUTH_TOKEN_SYNC_RADIX + "profile"
|
|
116
116
|
};
|
|
117
117
|
var AUTH_TOKEN_CACHES = {
|
|
118
|
-
"admin-panel":
|
|
118
|
+
"admin-panel": void 0,
|
|
119
|
+
// no caching
|
|
119
120
|
profile: AUTH_TOKEN_CACHE_RADIX + "profile"
|
|
120
121
|
};
|
|
121
122
|
var USER_SYNCS = {
|
|
@@ -361,9 +362,9 @@ async function cacheUserDataClient() {
|
|
|
361
362
|
}
|
|
362
363
|
const data = (await res.json())["data"];
|
|
363
364
|
cookiesSet(USERNAME_KEY, data.username, "/", 1.5 * 60 * 60);
|
|
364
|
-
cookiesSet(FULL_NAME_KEY, data.
|
|
365
|
+
cookiesSet(FULL_NAME_KEY, data.fullName, "/", 1.5 * 60 * 60);
|
|
365
366
|
cookiesSet(ROLE_KEY, data.role, "/", 1.5 * 60 * 60);
|
|
366
|
-
cookiesSet(PUB_ID_KEY, data.
|
|
367
|
+
cookiesSet(PUB_ID_KEY, data.publicId, "/", 1.5 * 60 * 60);
|
|
367
368
|
if (data?.email)
|
|
368
369
|
cookiesSet(EMAIL_KEY, data.email, "/", 1.5 * 60 * 60);
|
|
369
370
|
else
|
|
@@ -456,7 +457,7 @@ async function goralysFetchClient(method, input, payload, requestOptions) {
|
|
|
456
457
|
if (!(contentType && contentType.toLowerCase().trim().includes("application/json")))
|
|
457
458
|
return res;
|
|
458
459
|
const data = await clone.json();
|
|
459
|
-
if (data?.redirect) {
|
|
460
|
+
if (data?.redirect && requestOptions?.suppressRedirect) {
|
|
460
461
|
emitNavigationEvent({ type: "redirect", url: data.redirect });
|
|
461
462
|
}
|
|
462
463
|
if (res.status === 401) {
|
|
@@ -523,7 +524,8 @@ async function fetchTokensProfile() {
|
|
|
523
524
|
console.error("[fetchTokensProfile] No username cookies, aborting");
|
|
524
525
|
return null;
|
|
525
526
|
}
|
|
526
|
-
|
|
527
|
+
const csrf = await fetchCsrfClient("get-auth-tokens");
|
|
528
|
+
return await goralysFetchClient("GET", buildApiUrl("user/tokens", { "csrf-token": csrf }));
|
|
527
529
|
}
|
|
528
530
|
async function fetchTokensAdminPanel(target) {
|
|
529
531
|
const username = cookiesGet(USERNAME_KEY);
|
|
@@ -531,7 +533,8 @@ async function fetchTokensAdminPanel(target) {
|
|
|
531
533
|
console.error("[fetchTokensProfile] No username cookies, aborting");
|
|
532
534
|
return null;
|
|
533
535
|
}
|
|
534
|
-
|
|
536
|
+
const csrf = await fetchCsrfClient("get-auth-tokens");
|
|
537
|
+
return await goralysFetchClient("GET", buildApiUrl("user/tokens/any", { pubId: target, "csrf-token": csrf }));
|
|
535
538
|
}
|
|
536
539
|
async function fetchAuthTokensForContext(ctx, target = null) {
|
|
537
540
|
switch (ctx) {
|
|
@@ -545,6 +548,7 @@ async function fetchAuthTokensForContext(ctx, target = null) {
|
|
|
545
548
|
// src/hooks/use-synced-ressource.ts
|
|
546
549
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
547
550
|
function useSyncedResource({ name, cacheKey, syncKey, fetcher, parse, requireAuth = true, guard }) {
|
|
551
|
+
const caching = !!cacheKey && !!syncKey;
|
|
548
552
|
const [data, setData] = useState(null);
|
|
549
553
|
const showToast = getToastConfig().getShowToast();
|
|
550
554
|
const showToastRef = useRef(showToast);
|
|
@@ -569,48 +573,52 @@ function useSyncedResource({ name, cacheKey, syncKey, fetcher, parse, requireAut
|
|
|
569
573
|
resolve = r;
|
|
570
574
|
});
|
|
571
575
|
try {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
576
|
+
if (caching) {
|
|
577
|
+
const syncValue = cookiesGet(syncKey);
|
|
578
|
+
if (syncValue == "1") {
|
|
579
|
+
const raw2 = storageGet(cacheKey);
|
|
580
|
+
if (raw2 === null || raw2 === void 0) {
|
|
581
|
+
cookiesSet(syncKey, "0");
|
|
582
|
+
storageRemove(cacheKey);
|
|
583
|
+
inFlightRef.current = null;
|
|
584
|
+
resolve();
|
|
585
|
+
await fetchResource();
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
const cached = JSON.parse(raw2 ?? "null");
|
|
589
|
+
setData((prev) => JSON.stringify(prev) === JSON.stringify(cached) ? prev : cached);
|
|
581
590
|
return;
|
|
582
591
|
}
|
|
583
|
-
const cached = JSON.parse(raw2 ?? "null");
|
|
584
|
-
setData((prev) => JSON.stringify(prev) === JSON.stringify(cached) ? prev : cached);
|
|
585
|
-
return;
|
|
586
592
|
}
|
|
587
593
|
const res = await fetcher();
|
|
588
594
|
if (res)
|
|
589
595
|
await handleToastRequest(res, showToastRef.current, false);
|
|
590
596
|
const raw = await res?.json();
|
|
591
|
-
|
|
592
|
-
|
|
597
|
+
if (caching) {
|
|
598
|
+
cookiesSet(syncKey, "1");
|
|
599
|
+
storageSet(cacheKey, JSON.stringify(raw));
|
|
600
|
+
}
|
|
593
601
|
const result = parse(raw);
|
|
594
602
|
setData((prev) => JSON.stringify(prev) === JSON.stringify(result) ? prev : result);
|
|
595
603
|
} finally {
|
|
596
604
|
inFlightRef.current = null;
|
|
597
605
|
resolve();
|
|
598
606
|
}
|
|
599
|
-
}, [cacheKey, syncKey, fetcher, parse, requireAuth, guard, name]);
|
|
607
|
+
}, [cacheKey, syncKey, fetcher, parse, requireAuth, guard, name, caching]);
|
|
600
608
|
useEffect(() => {
|
|
601
609
|
const onChange = () => {
|
|
602
|
-
if (inFlightRef.current)
|
|
610
|
+
if (inFlightRef.current || !caching)
|
|
603
611
|
return;
|
|
604
612
|
if (cookiesGet(syncKey) != "1") {
|
|
605
613
|
void fetchResource();
|
|
606
614
|
}
|
|
607
615
|
};
|
|
608
616
|
return cookiesOnChange(onChange);
|
|
609
|
-
}, [fetchResource, syncKey]);
|
|
617
|
+
}, [fetchResource, syncKey, caching]);
|
|
610
618
|
useEffect(() => {
|
|
611
619
|
void fetchResource();
|
|
612
620
|
}, [fetchResource]);
|
|
613
|
-
return useMemo(() => ({ data, refetch: fetchResource, syncKey }), [data, fetchResource, syncKey]);
|
|
621
|
+
return useMemo(() => ({ data, refetch: fetchResource, syncKey: syncKey ?? "" }), [data, fetchResource, syncKey]);
|
|
614
622
|
}
|
|
615
623
|
|
|
616
624
|
// src/hooks/use-auth-tokens.ts
|
|
@@ -749,6 +757,25 @@ var parsePhpDateTime = (phpDate) => {
|
|
|
749
757
|
minute: "2-digit"
|
|
750
758
|
});
|
|
751
759
|
};
|
|
760
|
+
function separateNames(fullName) {
|
|
761
|
+
const parts = fullName.split(" ");
|
|
762
|
+
const firstNameParts = [];
|
|
763
|
+
const lastNameParts = [];
|
|
764
|
+
let current = "first";
|
|
765
|
+
parts.forEach((p) => {
|
|
766
|
+
if (p.toUpperCase() === p)
|
|
767
|
+
current = "last";
|
|
768
|
+
switch (current) {
|
|
769
|
+
case "first":
|
|
770
|
+
firstNameParts.push(p);
|
|
771
|
+
break;
|
|
772
|
+
case "last":
|
|
773
|
+
lastNameParts.push(p);
|
|
774
|
+
break;
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
return { firstName: firstNameParts.join(" "), lastName: lastNameParts.join(" ") };
|
|
778
|
+
}
|
|
752
779
|
|
|
753
780
|
// src/lib/subjects/subjects-utils.ts
|
|
754
781
|
var SUBJECTS = [
|
|
@@ -976,6 +1003,7 @@ export {
|
|
|
976
1003
|
parsePhpDateTime,
|
|
977
1004
|
reasonsConfig,
|
|
978
1005
|
searchFields,
|
|
1006
|
+
separateNames,
|
|
979
1007
|
storageGet,
|
|
980
1008
|
storageKeyAt,
|
|
981
1009
|
storageRemove,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goralys/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"license": "LGPL-2.1-or-later",
|
|
5
5
|
"description": "Shared business logic for the Goralys web application",
|
|
6
6
|
"repository": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"build": "tsup",
|
|
32
32
|
"typeCheck": "tsgo --noEmit",
|
|
33
33
|
"dev": "tsup --watch",
|
|
34
|
-
"barrel": "
|
|
34
|
+
"barrel": "node -e \"require('fs').rmSync('./src/index.ts',{force:true})\" && barrelsby -d ./src -l top"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": ">=18"
|