@goralys/core 1.2.0 → 1.2.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +15 -16
  2. package/dist/index.js +207 -214
  3. package/package.json +3 -1
package/dist/index.d.ts CHANGED
@@ -6,13 +6,17 @@ declare function getGoralysClientConfig(): GoralysClientConfig;
6
6
 
7
7
  interface StorageAdapter {
8
8
  getItem(key: string): string | null;
9
+ getSize(): number;
10
+ keyAt(ids: number): string | undefined;
9
11
  setItem(key: string, value: string): void;
10
12
  removeItem(key: string): void;
11
13
  }
12
14
  declare function configureStorage(customAdapter: StorageAdapter): void;
13
- declare function storageGet(key: string): string | null;
14
- declare function storageSet(key: string, value: string): void;
15
- declare function storageRemove(key: string): void;
15
+ declare const storageGet: (key: string) => string | null;
16
+ declare const storageSet: (key: string, value: string) => void;
17
+ declare const storageSize: () => number;
18
+ declare const storageKeyAt: (idx: number) => string | undefined;
19
+ declare const storageRemove: (key: string) => void;
16
20
 
17
21
  interface PHPDateTime {
18
22
  date: string;
@@ -26,15 +30,14 @@ interface CookiesAdapter {
26
30
  getCookies(key: string): CookieValue;
27
31
  getAll(): Record<string, CookieValue>;
28
32
  setCookies(key: string, value: CookieValue, path: string, maxAge: number): void;
29
- removeCookies(key: string): void;
33
+ removeCookies(key: string, path: string): void;
30
34
  }
31
35
  declare function configureCookies(customAdapter: CookiesAdapter): void;
32
- declare function cookiesGet(key: string): CookieValue;
33
- declare function cookiesGetAll(): Record<string, CookieValue>;
34
- declare function cookiesSet(key: string, value: string, path?: string, maxAge?: number): void;
35
- declare function cookiesRemove(key: string): void;
36
- declare function cookiesOnChange(callback: () => void): () => void;
37
- declare function setCookiesExpire(duration: number): void;
36
+ declare const cookiesGet: (key: string) => CookieValue;
37
+ declare const cookiesGetAll: () => Record<string, CookieValue>;
38
+ declare const cookiesSet: (key: string, value: string, path?: string, maxAge?: number) => void;
39
+ declare const cookiesRemove: (key: string, path?: string) => void;
40
+ declare const cookiesOnChange: (callback: () => void) => (() => void);
38
41
 
39
42
  type CheckAuthImpl = () => boolean;
40
43
  declare function configureCheckAuth(impl: CheckAuthImpl): void;
@@ -45,10 +48,6 @@ interface GoralysCoreConfig {
45
48
  storage: StorageAdapter;
46
49
  cookies: CookiesAdapter;
47
50
  auth: CheckAuthImpl;
48
- cache: {
49
- cache: () => Promise<void>;
50
- empty: () => void;
51
- };
52
51
  }
53
52
  declare function configGoralysCore(cfg: GoralysCoreConfig): void;
54
53
 
@@ -171,6 +170,7 @@ declare const LOGO_PATH: {
171
170
  eye: string;
172
171
  };
173
172
 
173
+ declare const COOKIES_DISMISSED_KEY = "cookie-banner-dismissed";
174
174
  declare const PERSISTANT_COOKIES: string[];
175
175
  declare const PERSISTANT_LOCALS: string[];
176
176
  declare const USERNAME_KEY = "username";
@@ -273,7 +273,6 @@ declare function getLongFromShort(short: string): string;
273
273
 
274
274
  declare function fetchSubjectsForRoleClient(role: UserRole): Promise<Response | null>;
275
275
 
276
- declare function configureUserCacheCallbacks(cache: () => Promise<void>, empty: () => void): void;
277
276
  declare function cacheUserDataClient(): Promise<void>;
278
277
  declare function emptyUserCacheClient(): void;
279
278
  declare function fetchUsersClient(): Promise<Response>;
@@ -281,4 +280,4 @@ declare function fetchVirtualUsersClient(): Promise<Response>;
281
280
  declare function fetchAdminsClient(): Promise<Response>;
282
281
  declare function fetchVirtualAdminsClient(): Promise<Response>;
283
282
 
284
- export { ADMIN_CACHE_RADIX, ADMIN_SYNC_RADIX, type AuthEvent, type CheckAuthImpl, type ConfirmOptions, type CookieValue, type CookiesAdapter, type DraftModalResult, EMAIL_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 ToastFn, USERNAME_KEY, USER_CACHES, USER_CACHE_RADIX, USER_ROLES, USER_SYNCS, USER_SYNC_RADIX, type User, type UserData, type UserEvent, type UserRole, type UserType, buildApiUrl, buildArray, cacheUserDataClient, configGoralysCore, configureCheckAuth, configureCookies, configureGoralysClient, configureStorage, configureUserCacheCallbacks, cookiesGet, cookiesGetAll, cookiesOnChange, cookiesRemove, cookiesSet, emitAuthEvent, emitNavigationEvent, emitUserEvent, emptyUserCacheClient, fetchAdminsClient, fetchCsrfClient, fetchSubjectsForRoleClient, fetchUsersClient, fetchVirtualAdminsClient, fetchVirtualUsersClient, getGoralysClientConfig, getLongFromShort, getStatusHelper, getStatusLabel, goralysFetchClient, handleToastRequest, helpContent, isAuthenticated, isFoolsDay, isHTTPMethod, onAuthEvent, onNavigationEvent, onUserEvent, parsePhpDateTime, reasonsConfig, searchFields, setCookiesExpire, storageGet, storageRemove, storageSet, useAdmins, useSubjects, useSupportTickets, useUsers, useVirtualAdmins, useVirtualUsers };
283
+ export { ADMIN_CACHE_RADIX, ADMIN_SYNC_RADIX, type AuthEvent, COOKIES_DISMISSED_KEY, type CheckAuthImpl, type ConfirmOptions, type CookieValue, type CookiesAdapter, type DraftModalResult, EMAIL_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 ToastFn, USERNAME_KEY, USER_CACHES, USER_CACHE_RADIX, USER_ROLES, USER_SYNCS, USER_SYNC_RADIX, type User, type UserData, type UserEvent, type UserRole, type UserType, buildApiUrl, buildArray, cacheUserDataClient, configGoralysCore, configureCheckAuth, configureCookies, configureGoralysClient, configureStorage, cookiesGet, cookiesGetAll, cookiesOnChange, cookiesRemove, cookiesSet, emitAuthEvent, emitNavigationEvent, emitUserEvent, emptyUserCacheClient, fetchAdminsClient, fetchCsrfClient, fetchSubjectsForRoleClient, fetchUsersClient, fetchVirtualAdminsClient, fetchVirtualUsersClient, getGoralysClientConfig, getLongFromShort, getStatusHelper, getStatusLabel, goralysFetchClient, handleToastRequest, helpContent, isAuthenticated, isFoolsDay, isHTTPMethod, onAuthEvent, onNavigationEvent, onUserEvent, parsePhpDateTime, reasonsConfig, searchFields, storageGet, storageKeyAt, storageRemove, storageSet, storageSize, useAdmins, useSubjects, useSupportTickets, useUsers, useVirtualAdmins, useVirtualUsers };
package/dist/index.js CHANGED
@@ -21,15 +21,11 @@ function getAdapter() {
21
21
  }
22
22
  return adapter;
23
23
  }
24
- function storageGet(key) {
25
- return getAdapter().getItem(key);
26
- }
27
- function storageSet(key, value) {
28
- getAdapter().setItem(key, value);
29
- }
30
- function storageRemove(key) {
31
- getAdapter().removeItem(key);
32
- }
24
+ var storageGet = (key) => getAdapter().getItem(key);
25
+ var storageSet = (key, value) => getAdapter().setItem(key, value);
26
+ var storageSize = () => getAdapter().getSize();
27
+ var storageKeyAt = (idx) => getAdapter().keyAt(idx);
28
+ var storageRemove = (key) => getAdapter().removeItem(key);
33
29
 
34
30
  // src/lib/storage/cookies-adapter.ts
35
31
  var adapter2 = null;
@@ -42,24 +38,11 @@ function getAdapter2() {
42
38
  }
43
39
  return adapter2;
44
40
  }
45
- function cookiesGet(key) {
46
- return getAdapter2().getCookies(key);
47
- }
48
- function cookiesGetAll() {
49
- return getAdapter2().getAll();
50
- }
51
- function cookiesSet(key, value, path = "/", maxAge = 1.5 * 60) {
52
- getAdapter2().setCookies(key, value, path, maxAge);
53
- }
54
- function cookiesRemove(key) {
55
- getAdapter2().removeCookies(key);
56
- }
57
- function cookiesOnChange(callback) {
58
- return getAdapter2().onChange(callback);
59
- }
60
- function setCookiesExpire(duration) {
61
- storageSet("goralys-cookies-expire", String(Date.now() + duration * 1e3));
62
- }
41
+ var cookiesGet = (key) => getAdapter2().getCookies(key);
42
+ var cookiesGetAll = () => getAdapter2().getAll();
43
+ var cookiesSet = (key, value, path = "/", maxAge = 1.5 * 60) => getAdapter2().setCookies(key, value, path, maxAge);
44
+ var cookiesRemove = (key, path = "/") => getAdapter2().removeCookies(key, path);
45
+ var cookiesOnChange = (callback) => getAdapter2().onChange(callback);
63
46
 
64
47
  // src/lib/auth/check-auth.ts
65
48
  var checkAuthImpl;
@@ -73,6 +56,17 @@ function isAuthenticated() {
73
56
  return checkAuthImpl();
74
57
  }
75
58
 
59
+ // src/config.ts
60
+ function configGoralysCore(cfg) {
61
+ configureGoralysClient(cfg.client);
62
+ configureCookies(cfg.cookies);
63
+ configureStorage(cfg.storage);
64
+ configureCheckAuth(cfg.auth);
65
+ }
66
+
67
+ // src/hooks/useSubjects.ts
68
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
69
+
76
70
  // src/lib/auth/auth-event.ts
77
71
  var listeners = /* @__PURE__ */ new Set();
78
72
  function emitAuthEvent(event) {
@@ -95,191 +89,9 @@ function onNavigationEvent(listener) {
95
89
  return () => listeners2.delete(listener);
96
90
  }
97
91
 
98
- // src/lib/auth/user-event.ts
99
- var listeners3 = /* @__PURE__ */ new Set();
100
- function emitUserEvent(event) {
101
- listeners3.forEach((l) => l(event));
102
- }
103
- function onUserEvent(callback) {
104
- listeners3.add(callback);
105
- return () => {
106
- listeners3.delete(callback);
107
- };
108
- }
109
-
110
- // src/lib/fetch/goralys-action-handler.ts
111
- var GoralysActionHandler = class {
112
- constructor() {
113
- this.handle = async (r) => {
114
- const data = await r.clone().json();
115
- if (!data || !data.action) {
116
- return;
117
- }
118
- const action = data.action;
119
- if (action === "login-success") {
120
- await this.onLogin();
121
- }
122
- return;
123
- };
124
- this.onLogin = async () => {
125
- await cacheUserDataClient();
126
- emitUserEvent("login");
127
- return;
128
- };
129
- }
130
- };
131
-
132
- // src/lib/fetch/fetch.client.ts
133
- var actionHandler = new GoralysActionHandler();
134
- async function goralysFetchClient(method, input, payload, requestOptions) {
135
- const { apiDomain } = getGoralysClientConfig();
136
- const res = await fetch(`${apiDomain}/${input}`, {
137
- credentials: "include",
138
- method: method === "BREW" ? "POST" : method,
139
- headers: method === "BREW" ? { "X-HTTP-Method-Override": method } : {},
140
- body: payload ? payload instanceof FormData ? payload : JSON.stringify(payload) : void 0,
141
- ...requestOptions
142
- });
143
- const clone = res.clone();
144
- const contentType = clone.headers.get("Content-Type");
145
- if (!(contentType && contentType.toLowerCase().trim().includes("application/json")))
146
- return res;
147
- const data = await clone.json();
148
- if (res.status === 401) {
149
- try {
150
- emitAuthEvent(data?.authEvent ?? "unauthenticated");
151
- } catch {
152
- emitAuthEvent("unauthenticated");
153
- }
154
- }
155
- if (res.status === 418) {
156
- const teapotData = await res.clone().json();
157
- emitNavigationEvent({
158
- type: "teapot",
159
- toastType: teapotData.toastType,
160
- toastTitle: teapotData.toastTitle,
161
- toastMessage: teapotData.toastMessage
162
- });
163
- }
164
- await actionHandler.handle(res);
165
- return res;
166
- }
167
- async function fetchCsrfClient(formId) {
168
- const { apiDomain } = getGoralysClientConfig();
169
- const res = await fetch(`${apiDomain}/csrf`, {
170
- method: "POST",
171
- headers: { "Content-Type": "application/json" },
172
- credentials: "include",
173
- body: JSON.stringify({ form: formId })
174
- });
175
- if (!res.ok)
176
- return null;
177
- const json = await res.json();
178
- return json["csrf-token"];
179
- }
180
- function buildQueryString(params) {
181
- return Object.entries(params).filter(([, value]) => value !== null && value !== void 0).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
182
- }
183
- function buildApiUrl(endpoint, params, domain = false) {
184
- const { apiDomain } = getGoralysClientConfig();
185
- const queryString = buildQueryString(params);
186
- return `${domain ? apiDomain + "/" : ""}${endpoint}${queryString ? `?${queryString}` : ""}`;
187
- }
188
- async function handleToastRequest(r, showToast, redirect = true, duration) {
189
- const res = r.clone();
190
- const data = await res.json();
191
- if (data?.toast) {
192
- showToast({ type: data.toastType, title: data.toastTitle, message: data.toastMessage }, duration);
193
- if (data?.redirect && redirect) {
194
- emitNavigationEvent({ type: "redirect", url: data.redirect });
195
- }
196
- return true;
197
- }
198
- return false;
199
- }
200
-
201
- // src/lib/user/user.client.ts
202
- var cacheUserClient;
203
- var emptyCacheUserClient;
204
- function configureUserCacheCallbacks(cache, empty) {
205
- cacheUserClient = cache;
206
- emptyCacheUserClient = empty;
207
- }
208
- async function cacheUserDataClient() {
209
- if (!cacheUserClient) {
210
- throw new Error("User cache not configured. Call configUserCacheCallbacks() first.");
211
- }
212
- return await cacheUserClient();
213
- }
214
- function emptyUserCacheClient() {
215
- if (!emptyCacheUserClient) {
216
- throw new Error("User cache not configured. Call configUserCacheCallbacks() first.");
217
- }
218
- return emptyCacheUserClient();
219
- }
220
- async function fetchUsersClient() {
221
- const csrfToken = await fetchCsrfClient("get-all-users");
222
- return await goralysFetchClient("GET", buildApiUrl("users/all", { "csrf-token": csrfToken }));
223
- }
224
- async function fetchVirtualUsersClient() {
225
- const csrfToken = await fetchCsrfClient("get-virtual-users");
226
- return await goralysFetchClient("GET", buildApiUrl("users/virtual", { "csrf-token": csrfToken }));
227
- }
228
- async function fetchAdminsClient() {
229
- const csrfToken = await fetchCsrfClient("get-all-admins");
230
- return await goralysFetchClient("GET", buildApiUrl("admins/all", { "csrf-token": csrfToken }));
231
- }
232
- async function fetchVirtualAdminsClient() {
233
- const csrfToken = await fetchCsrfClient("get-virtual-admins");
234
- return await goralysFetchClient("GET", buildApiUrl("admins/virtual", { "csrf-token": csrfToken }));
235
- }
236
-
237
- // src/config.ts
238
- function configGoralysCore(cfg) {
239
- configureGoralysClient(cfg.client);
240
- configureCookies(cfg.cookies);
241
- configureStorage(cfg.storage);
242
- configureCheckAuth(cfg.auth);
243
- configureUserCacheCallbacks(cfg.cache.cache, cfg.cache.empty);
244
- }
245
-
246
- // src/hooks/useSubjects.ts
247
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
248
-
249
- // src/lib/subjects/subjects.client.ts
250
- async function fetchStudentSubjectsClient() {
251
- const csrfToken = await fetchCsrfClient("get-student-subjects");
252
- if (!csrfToken)
253
- return null;
254
- return await goralysFetchClient("GET", buildApiUrl("subjects/student", { "csrf-token": csrfToken }));
255
- }
256
- async function fetchTeacherSubjectsClient() {
257
- const csrfToken = await fetchCsrfClient("get-teacher-subjects");
258
- if (!csrfToken)
259
- return null;
260
- return await goralysFetchClient("GET", buildApiUrl("subjects/teacher", { "csrf-token": csrfToken }));
261
- }
262
- async function fetchAdminSubjectsClient() {
263
- const csrfToken = await fetchCsrfClient("get-admin-subjects");
264
- if (!csrfToken)
265
- return null;
266
- return await goralysFetchClient("GET", buildApiUrl("subjects/admin", { "csrf-token": csrfToken }));
267
- }
268
- async function fetchSubjectsForRoleClient(role) {
269
- switch (role.role) {
270
- case "student":
271
- return await fetchStudentSubjectsClient();
272
- case "teacher":
273
- return await fetchTeacherSubjectsClient();
274
- case "admin":
275
- return await fetchAdminSubjectsClient();
276
- default:
277
- return null;
278
- }
279
- }
280
-
281
92
  // src/lib/config.ts
282
- var PERSISTANT_COOKIES = ["cookie-banner-dismissed"];
93
+ var COOKIES_DISMISSED_KEY = "cookie-banner-dismissed";
94
+ var PERSISTANT_COOKIES = [COOKIES_DISMISSED_KEY, "rate_limit_token"];
283
95
  var PERSISTANT_LOCALS = ["goralys-cookies-expire", "flash_toast"];
284
96
  var USERNAME_KEY = "username";
285
97
  var ROLE_KEY = "user-role";
@@ -519,6 +331,186 @@ Attention : les administrateurs ont acc\xE8s \xE0 toutes les fonctionnalit\xE9s
519
331
  }
520
332
  ];
521
333
 
334
+ // src/lib/user/user.client.ts
335
+ async function cacheUserDataClient() {
336
+ const res = await goralysFetchClient("GET", "user/profile");
337
+ if (!res.ok) {
338
+ return;
339
+ }
340
+ const data = (await res.json())["data"];
341
+ cookiesSet(USERNAME_KEY, data.username, "/", 1.5 * 60 * 60);
342
+ cookiesSet(FULL_NAME_KEY, data.full_name, "/", 1.5 * 60 * 60);
343
+ cookiesSet(ROLE_KEY, data.role, "/", 1.5 * 60 * 60);
344
+ cookiesSet(PUB_ID_KEY, data.public_id, "/", 1.5 * 60 * 60);
345
+ if (data?.email)
346
+ cookiesSet(EMAIL_KEY, data.email, "/", 1.5 * 60 * 60);
347
+ else
348
+ cookiesRemove(EMAIL_KEY);
349
+ }
350
+ function emptyUserCacheClient() {
351
+ for (let i = 0; i < storageSize(); i++) {
352
+ const key = storageKeyAt(i);
353
+ if (!PERSISTANT_LOCALS.includes(key))
354
+ storageRemove(key);
355
+ }
356
+ Object.keys(cookiesGetAll()).forEach((name) => {
357
+ if (PERSISTANT_COOKIES.includes(name.trim()))
358
+ return;
359
+ if (name.startsWith("__next"))
360
+ return;
361
+ cookiesRemove(name);
362
+ });
363
+ }
364
+ async function fetchUsersClient() {
365
+ const csrfToken = await fetchCsrfClient("get-all-users");
366
+ return await goralysFetchClient("GET", buildApiUrl("users/all", { "csrf-token": csrfToken }));
367
+ }
368
+ async function fetchVirtualUsersClient() {
369
+ const csrfToken = await fetchCsrfClient("get-virtual-users");
370
+ return await goralysFetchClient("GET", buildApiUrl("users/virtual", { "csrf-token": csrfToken }));
371
+ }
372
+ async function fetchAdminsClient() {
373
+ const csrfToken = await fetchCsrfClient("get-all-admins");
374
+ return await goralysFetchClient("GET", buildApiUrl("admins/all", { "csrf-token": csrfToken }));
375
+ }
376
+ async function fetchVirtualAdminsClient() {
377
+ const csrfToken = await fetchCsrfClient("get-virtual-admins");
378
+ return await goralysFetchClient("GET", buildApiUrl("admins/virtual", { "csrf-token": csrfToken }));
379
+ }
380
+
381
+ // src/lib/auth/user-event.ts
382
+ var listeners3 = /* @__PURE__ */ new Set();
383
+ function emitUserEvent(event) {
384
+ listeners3.forEach((l) => l(event));
385
+ }
386
+ function onUserEvent(callback) {
387
+ listeners3.add(callback);
388
+ return () => {
389
+ listeners3.delete(callback);
390
+ };
391
+ }
392
+
393
+ // src/lib/fetch/goralys-action-handler.ts
394
+ var GoralysActionHandler = class {
395
+ handle = async (r) => {
396
+ const data = await r.clone().json();
397
+ if (!data || !data.action) {
398
+ return;
399
+ }
400
+ const action = data.action;
401
+ if (action === "login-success") {
402
+ await this.onLogin();
403
+ }
404
+ return;
405
+ };
406
+ onLogin = async () => {
407
+ await cacheUserDataClient();
408
+ emitUserEvent("login");
409
+ return;
410
+ };
411
+ };
412
+
413
+ // src/lib/fetch/fetch.client.ts
414
+ var actionHandler = new GoralysActionHandler();
415
+ async function goralysFetchClient(method, input, payload, requestOptions) {
416
+ const { apiDomain } = getGoralysClientConfig();
417
+ const res = await fetch(`${apiDomain}/${input}`, {
418
+ credentials: "include",
419
+ method: method === "BREW" ? "POST" : method,
420
+ headers: method === "BREW" ? { "X-HTTP-Method-Override": method } : {},
421
+ body: payload ? payload instanceof FormData ? payload : JSON.stringify(payload) : void 0,
422
+ ...requestOptions
423
+ });
424
+ const clone = res.clone();
425
+ const contentType = clone.headers.get("Content-Type");
426
+ if (!(contentType && contentType.toLowerCase().trim().includes("application/json")))
427
+ return res;
428
+ const data = await clone.json();
429
+ if (res.status === 401) {
430
+ try {
431
+ emitAuthEvent(data?.authEvent ?? "unauthenticated");
432
+ } catch {
433
+ emitAuthEvent("unauthenticated");
434
+ }
435
+ }
436
+ if (res.status === 418) {
437
+ const teapotData = await res.clone().json();
438
+ emitNavigationEvent({
439
+ type: "teapot",
440
+ toastType: teapotData.toastType,
441
+ toastTitle: teapotData.toastTitle,
442
+ toastMessage: teapotData.toastMessage
443
+ });
444
+ }
445
+ await actionHandler.handle(res);
446
+ return res;
447
+ }
448
+ async function fetchCsrfClient(formId) {
449
+ const { apiDomain } = getGoralysClientConfig();
450
+ const res = await fetch(`${apiDomain}/csrf`, {
451
+ method: "POST",
452
+ headers: { "Content-Type": "application/json" },
453
+ credentials: "include",
454
+ body: JSON.stringify({ form: formId })
455
+ });
456
+ if (!res.ok)
457
+ return null;
458
+ const json = await res.json();
459
+ return json["csrf-token"];
460
+ }
461
+ function buildQueryString(params) {
462
+ return Object.entries(params).filter(([, value]) => value !== null && value !== void 0).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
463
+ }
464
+ function buildApiUrl(endpoint, params, domain = false) {
465
+ const { apiDomain } = getGoralysClientConfig();
466
+ const queryString = buildQueryString(params);
467
+ return `${domain ? apiDomain + "/" : ""}${endpoint}${queryString ? `?${queryString}` : ""}`;
468
+ }
469
+ async function handleToastRequest(r, showToast, redirect = true, duration) {
470
+ const res = r.clone();
471
+ const data = await res.json();
472
+ if (data?.toast) {
473
+ showToast({ type: data.toastType, title: data.toastTitle, message: data.toastMessage }, duration);
474
+ if (data?.redirect && redirect) {
475
+ emitNavigationEvent({ type: "redirect", url: data.redirect });
476
+ }
477
+ return true;
478
+ }
479
+ return false;
480
+ }
481
+
482
+ // src/lib/subjects/subjects.client.ts
483
+ async function fetchStudentSubjectsClient() {
484
+ const csrfToken = await fetchCsrfClient("get-student-subjects");
485
+ if (!csrfToken)
486
+ return null;
487
+ return await goralysFetchClient("GET", buildApiUrl("subjects/student", { "csrf-token": csrfToken }));
488
+ }
489
+ async function fetchTeacherSubjectsClient() {
490
+ const csrfToken = await fetchCsrfClient("get-teacher-subjects");
491
+ if (!csrfToken)
492
+ return null;
493
+ return await goralysFetchClient("GET", buildApiUrl("subjects/teacher", { "csrf-token": csrfToken }));
494
+ }
495
+ async function fetchAdminSubjectsClient() {
496
+ const csrfToken = await fetchCsrfClient("get-admin-subjects");
497
+ if (!csrfToken)
498
+ return null;
499
+ return await goralysFetchClient("GET", buildApiUrl("subjects/admin", { "csrf-token": csrfToken }));
500
+ }
501
+ async function fetchSubjectsForRoleClient(role) {
502
+ switch (role.role) {
503
+ case "student":
504
+ return await fetchStudentSubjectsClient();
505
+ case "teacher":
506
+ return await fetchTeacherSubjectsClient();
507
+ case "admin":
508
+ return await fetchAdminSubjectsClient();
509
+ default:
510
+ return null;
511
+ }
512
+ }
513
+
522
514
  // src/hooks/useSubjects.ts
523
515
  function useSubjects(role, showToast) {
524
516
  const [subjects, setSubjects] = useState(null);
@@ -578,7 +570,7 @@ function useSubjects(role, showToast) {
578
570
  inFlightRef.current = null;
579
571
  resolve();
580
572
  }
581
- }, [role]);
573
+ }, [role, showToastRef]);
582
574
  useEffect(() => {
583
575
  const onChange = () => {
584
576
  if (inFlightRef.current)
@@ -884,6 +876,7 @@ var USER_ROLES = ["admin", "teacher", "student", "none"];
884
876
  export {
885
877
  ADMIN_CACHE_RADIX,
886
878
  ADMIN_SYNC_RADIX,
879
+ COOKIES_DISMISSED_KEY,
887
880
  EMAIL_KEY,
888
881
  FULL_NAME_KEY,
889
882
  GoralysActionHandler,
@@ -913,7 +906,6 @@ export {
913
906
  configureCookies,
914
907
  configureGoralysClient,
915
908
  configureStorage,
916
- configureUserCacheCallbacks,
917
909
  cookiesGet,
918
910
  cookiesGetAll,
919
911
  cookiesOnChange,
@@ -944,10 +936,11 @@ export {
944
936
  parsePhpDateTime,
945
937
  reasonsConfig,
946
938
  searchFields,
947
- setCookiesExpire,
948
939
  storageGet,
940
+ storageKeyAt,
949
941
  storageRemove,
950
942
  storageSet,
943
+ storageSize,
951
944
  useAdmins,
952
945
  useSubjects,
953
946
  useSupportTickets,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goralys/core",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "license": "LGPL-2.1-or-later",
5
5
  "description": "Shared business logic for the Goralys web application",
6
6
  "repository": {
@@ -28,12 +28,14 @@
28
28
  },
29
29
  "scripts": {
30
30
  "build": "tsup",
31
+ "typeCheck": "tsgo --noEmit",
31
32
  "dev": "tsup --watch"
32
33
  },
33
34
  "peerDependencies": {
34
35
  "react": ">=18"
35
36
  },
36
37
  "devDependencies": {
38
+ "@typescript/native-preview": "7.0.0-dev.20260705.1",
37
39
  "barrelsby": "^2.8.1",
38
40
  "esbuild-plugin-tsconfig-paths": "^1.0.2",
39
41
  "react": "^18.0.0",