@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.
- package/dist/index.d.ts +15 -16
- package/dist/index.js +207 -214
- 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
|
|
14
|
-
declare
|
|
15
|
-
declare
|
|
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
|
|
33
|
-
declare
|
|
34
|
-
declare
|
|
35
|
-
declare
|
|
36
|
-
declare
|
|
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,
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
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.
|
|
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",
|