@geins/crm 0.1.1-canary

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 (63) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -0
  3. package/__tests__/GeinsCRM.auth.test.ts +284 -0
  4. package/__tests__/GeinsCRM.user.test.ts +109 -0
  5. package/dist/auth/authClient.d.ts +41 -0
  6. package/dist/auth/authClientDirect.d.ts +11 -0
  7. package/dist/auth/authClientProxy.d.ts +12 -0
  8. package/dist/auth/authHelpers.d.ts +5 -0
  9. package/dist/auth/authService.d.ts +17 -0
  10. package/dist/auth/authServiceClient.d.ts +20 -0
  11. package/dist/auth/index.d.ts +6 -0
  12. package/dist/geinsCRM.d.ts +34 -0
  13. package/dist/graphql/index.d.ts +1 -0
  14. package/dist/graphql/queries.d.ts +12 -0
  15. package/dist/index.cjs +24358 -0
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.esm.js +24346 -0
  18. package/dist/parsers/shared.d.ts +2 -0
  19. package/dist/services/index.d.ts +3 -0
  20. package/dist/services/pwResetService.d.ts +6 -0
  21. package/dist/services/userOrdersService.d.ts +9 -0
  22. package/dist/services/userService.d.ts +13 -0
  23. package/dist/types/crmTypes.d.ts +36 -0
  24. package/dist/types/index.d.ts +1 -0
  25. package/eslint.config.js +3 -0
  26. package/jest.config.js +8 -0
  27. package/package.json +30 -0
  28. package/rollup.config.js +26 -0
  29. package/src/auth/authClient.ts +318 -0
  30. package/src/auth/authClientDirect.ts +31 -0
  31. package/src/auth/authClientProxy.ts +82 -0
  32. package/src/auth/authHelpers.ts +65 -0
  33. package/src/auth/authService.ts +175 -0
  34. package/src/auth/authServiceClient.ts +267 -0
  35. package/src/auth/index.ts +6 -0
  36. package/src/geinsCRM.ts +306 -0
  37. package/src/graphql/auth/pw-reset-commit.gql +15 -0
  38. package/src/graphql/auth/pw-reset-request.gql +13 -0
  39. package/src/graphql/fragments/address.gql +16 -0
  40. package/src/graphql/fragments/balances.gql +5 -0
  41. package/src/graphql/fragments/campaign.gql +4 -0
  42. package/src/graphql/fragments/cart.gql +101 -0
  43. package/src/graphql/fragments/price.gql +13 -0
  44. package/src/graphql/fragments/stock.gql +7 -0
  45. package/src/graphql/fragments/user.gql +16 -0
  46. package/src/graphql/graphql.d.ts +9 -0
  47. package/src/graphql/index.ts +1 -0
  48. package/src/graphql/order/orders.gql +39 -0
  49. package/src/graphql/queries.ts +21 -0
  50. package/src/graphql/user/delete.gql +3 -0
  51. package/src/graphql/user/get.gql +6 -0
  52. package/src/graphql/user/register.gql +15 -0
  53. package/src/graphql/user/update.gql +16 -0
  54. package/src/index.ts +2 -0
  55. package/src/parsers/index.ts +0 -0
  56. package/src/parsers/shared.ts +23 -0
  57. package/src/services/index.ts +3 -0
  58. package/src/services/pwResetService.ts +30 -0
  59. package/src/services/userOrdersService.ts +34 -0
  60. package/src/services/userService.ts +83 -0
  61. package/src/types/crmTypes.ts +46 -0
  62. package/src/types/index.ts +1 -0
  63. package/tsconfig.json +19 -0
@@ -0,0 +1,2 @@
1
+ import { GeinsAddressTypeType } from '@geins/types';
2
+ export declare function parseAddress(data: any): GeinsAddressTypeType | undefined;
@@ -0,0 +1,3 @@
1
+ export * from './userService';
2
+ export * from './userOrdersService';
3
+ export * from './pwResetService';
@@ -0,0 +1,6 @@
1
+ import { BaseApiService } from '@geins/core';
2
+ export declare class PasswordResetService extends BaseApiService {
3
+ private generateVars;
4
+ request(email: string): Promise<any>;
5
+ commit(resetKey: string, password: string): Promise<any>;
6
+ }
@@ -0,0 +1,9 @@
1
+ import type { GeinsSettings, GeinsUserOrdersType } from '@geins/types';
2
+ import { BaseApiService } from '@geins/core';
3
+ export declare class UserOrdersService extends BaseApiService {
4
+ constructor(apiClient: any, geinsSettings: GeinsSettings);
5
+ private generateVars;
6
+ getRaw(variables: any): Promise<any>;
7
+ get(): Promise<GeinsUserOrdersType | undefined>;
8
+ protected parseResult(result: any): GeinsUserOrdersType | undefined;
9
+ }
@@ -0,0 +1,13 @@
1
+ import type { GeinsUserType, GeinsSettings } from '@geins/types';
2
+ import { BaseApiService, GeinsUserInputTypeType } from '@geins/core';
3
+ export declare class UserService extends BaseApiService {
4
+ constructor(apiClient: any, geinsSettings: GeinsSettings);
5
+ private generateVars;
6
+ private generateMutationVars;
7
+ getRaw(): Promise<any>;
8
+ get(): Promise<GeinsUserType | undefined>;
9
+ create(user: GeinsUserInputTypeType): Promise<any>;
10
+ update(user: GeinsUserInputTypeType): Promise<GeinsUserType>;
11
+ delete(): Promise<any>;
12
+ protected parseResult(data: any): GeinsUserType | undefined;
13
+ }
@@ -0,0 +1,36 @@
1
+ import { AuthCredentials, AuthResponse, GeinsUserInputTypeType, GeinsUserType, GeinsUserOrdersType } from '@geins/types';
2
+ export interface AuthInterface {
3
+ get(refreshToken?: string, userToken?: string): Promise<AuthResponse | undefined>;
4
+ login(credentials: AuthCredentials): Promise<AuthResponse | undefined>;
5
+ logout(): Promise<AuthResponse | undefined>;
6
+ refresh(refreshToken?: string): Promise<AuthResponse | undefined>;
7
+ authorized(refreshToken?: string): Promise<boolean>;
8
+ }
9
+ /**
10
+ * User interface
11
+ * This interface is used to define the user service
12
+ */
13
+ export interface UserInterface {
14
+ get(): Promise<GeinsUserType | undefined>;
15
+ update(user: GeinsUserInputTypeType): Promise<any>;
16
+ create(credentials: AuthCredentials, user?: GeinsUserInputTypeType): Promise<AuthResponse | undefined>;
17
+ remove(): Promise<any>;
18
+ password: UserPasswordInterface;
19
+ orders: UserOrdersInterface;
20
+ }
21
+ /**
22
+ * User password interface
23
+ * This interface is used to define the user password service
24
+ */
25
+ export interface UserPasswordInterface {
26
+ change(credentials: AuthCredentials): Promise<AuthResponse | undefined>;
27
+ requestReset(email: string): Promise<any>;
28
+ commitReset(resetKey: string, password: string): Promise<any>;
29
+ }
30
+ /**
31
+ * User orders interface
32
+ * This interface is used to define the user orders service
33
+ */
34
+ export interface UserOrdersInterface {
35
+ get(): Promise<GeinsUserOrdersType | undefined>;
36
+ }
@@ -0,0 +1 @@
1
+ export * from './crmTypes';
@@ -0,0 +1,3 @@
1
+ import { geinsSharedConfig } from '@geins/eslint-config/eslint-config.js';
2
+
3
+ export default [...geinsSharedConfig];
package/jest.config.js ADDED
@@ -0,0 +1,8 @@
1
+ // /packages/sdk/crm/jest.config.js
2
+ import baseConfig from '../../../jest.config.js';
3
+
4
+ export default {
5
+ ...baseConfig,
6
+ displayName: '@geins/crm',
7
+ roots: ['<rootDir>'],
8
+ };
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@geins/crm",
3
+ "version": "0.1.1-canary",
4
+ "main": "dist/index.cjs",
5
+ "module": "dist/index.esm.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "license": "MIT",
9
+ "scripts": {
10
+ "build": "rollup -c",
11
+ "prepublishOnly": "yarn build",
12
+ "lint": "eslint --fix .",
13
+ "link": "yarn link"
14
+ },
15
+ "dependencies": {
16
+ "@apollo/client": "^3.11.8",
17
+ "@geins/core": "0.1.1-canary",
18
+ "crypto-js": "^4.2.0",
19
+ "graphql": "^16.9.0"
20
+ },
21
+ "devDependencies": {
22
+ "@geins/eslint-config": "*",
23
+ "@geins/types": "0.1.1-canary",
24
+ "@rollup/plugin-commonjs": "^28.0.0",
25
+ "@rollup/plugin-node-resolve": "^15.3.0",
26
+ "@rollup/plugin-typescript": "^12.1.0",
27
+ "eslint": "^9.11.1",
28
+ "typescript": "^5.6.2"
29
+ }
30
+ }
@@ -0,0 +1,26 @@
1
+ import resolve from '@rollup/plugin-node-resolve';
2
+ import commonjs from '@rollup/plugin-commonjs';
3
+ import typescript from '@rollup/plugin-typescript';
4
+ import graphql from '@rollup/plugin-graphql';
5
+
6
+ export default {
7
+ input: 'src/index.ts',
8
+ output: [
9
+ {
10
+ file: 'dist/index.cjs',
11
+ format: 'cjs',
12
+ },
13
+ {
14
+ file: 'dist/index.esm.js',
15
+ format: 'esm',
16
+ },
17
+ ],
18
+ plugins: [
19
+ resolve({
20
+ preferBuiltins: true,
21
+ }),
22
+ commonjs(),
23
+ typescript(),
24
+ graphql(),
25
+ ],
26
+ };
@@ -0,0 +1,318 @@
1
+ import { CookieService, AUTH_COOKIES, AUTH_COOKIES_MAX_AGE } from '@geins/core';
2
+ import type { AuthResponse, AuthCredentials, AuthTokens, AuthUser } from '@geins/types';
3
+ import { authClaimsTokenSerializeToObject } from './authHelpers';
4
+ import { AuthService } from './authService';
5
+
6
+ export abstract class AuthClient {
7
+ protected _cookieService: CookieService;
8
+ protected _refreshToken: string | undefined;
9
+
10
+ constructor() {
11
+ this._cookieService = new CookieService();
12
+ }
13
+
14
+ // abstract methods
15
+ protected abstract handleLogin(credentials: AuthCredentials): Promise<AuthResponse | undefined>;
16
+ protected abstract handleRefresh(refreshToken?: string): Promise<AuthResponse | undefined>;
17
+ protected abstract handleGetUser(
18
+ refreshToken?: string,
19
+ userToken?: string,
20
+ ): Promise<AuthResponse | undefined>;
21
+ protected abstract handleChangePassword(
22
+ credentials: AuthCredentials,
23
+ refreshToken: string,
24
+ ): Promise<AuthResponse | undefined>;
25
+ protected abstract handleRegister(credentials: AuthCredentials): Promise<AuthResponse | undefined>;
26
+
27
+ // base methods
28
+ async login(credentials: AuthCredentials): Promise<AuthResponse | undefined> {
29
+ const authResponse = await this.handleLogin(credentials);
30
+
31
+ if (authResponse?.succeeded) {
32
+ this.setCookiesLogin(authResponse, credentials.rememberUser || false);
33
+ }
34
+
35
+ return authResponse;
36
+ }
37
+
38
+ async refresh(refreshToken?: string): Promise<AuthResponse | undefined> {
39
+ this._refreshToken = refreshToken || this.getCookieRefreshToken();
40
+
41
+ if (!this._refreshToken) {
42
+ return undefined;
43
+ }
44
+
45
+ const authResponse = await this.handleRefresh(this._refreshToken);
46
+
47
+ if (authResponse?.succeeded && authResponse.tokens) {
48
+ this.refreshLoginCookies(authResponse);
49
+ }
50
+
51
+ return authResponse;
52
+ }
53
+
54
+ async getUser(refreshToken?: string, userToken?: string): Promise<AuthResponse | undefined> {
55
+ const tokens = this.getCurrentTokens(refreshToken, userToken);
56
+ this._refreshToken = tokens.refreshToken;
57
+
58
+ if (!tokens.refreshToken) {
59
+ return undefined;
60
+ }
61
+
62
+ if (tokens.userToken && tokens.refreshToken) {
63
+ return this.handleUserTokenScenario({
64
+ userToken: tokens.userToken,
65
+ refreshToken: tokens.refreshToken,
66
+ });
67
+ }
68
+
69
+ return this.handleRefreshTokenOnlyScenario(tokens.refreshToken);
70
+ }
71
+
72
+ async changePassword(
73
+ credentials: AuthCredentials,
74
+ refreshToken?: string,
75
+ ): Promise<AuthResponse | undefined> {
76
+ this._refreshToken = refreshToken || this.getCookieRefreshToken();
77
+
78
+ if (!this._refreshToken) {
79
+ return undefined;
80
+ }
81
+
82
+ const authResponse = await this.handleChangePassword(credentials, this._refreshToken);
83
+
84
+ if (authResponse?.succeeded) {
85
+ this.setCookiesLogin(authResponse, credentials.rememberUser || false);
86
+ }
87
+ return authResponse;
88
+ }
89
+
90
+ async register(credentials: AuthCredentials): Promise<AuthResponse | undefined> {
91
+ const authResponse = await this.handleRegister(credentials);
92
+
93
+ if (authResponse?.succeeded) {
94
+ this.setCookiesLogin(authResponse, credentials.rememberUser || false);
95
+ }
96
+
97
+ return authResponse;
98
+ }
99
+
100
+ private async handleUserTokenScenario(tokens: {
101
+ refreshToken: string;
102
+ userToken: string;
103
+ }): Promise<AuthResponse | undefined> {
104
+ let authResponse = AuthService.getUserObjectFromToken(tokens.userToken, tokens.refreshToken);
105
+
106
+ if (authResponse?.succeeded && authResponse.tokens?.expiresSoon) {
107
+ return this.refreshUserTokens(tokens);
108
+ }
109
+
110
+ return authResponse;
111
+ }
112
+
113
+ private async refreshUserTokens(tokens: {
114
+ refreshToken: string;
115
+ userToken: string;
116
+ }): Promise<AuthResponse | undefined> {
117
+ const authResponse = await this.handleGetUser(tokens.refreshToken, tokens.userToken);
118
+
119
+ if (authResponse?.succeeded && authResponse.tokens) {
120
+ this._refreshToken = tokens.refreshToken;
121
+ this.refreshLoginCookies(authResponse);
122
+ }
123
+
124
+ return authResponse;
125
+ }
126
+
127
+ private async handleRefreshTokenOnlyScenario(refreshToken: string): Promise<AuthResponse | undefined> {
128
+ const authResponse = await this.handleGetUser(refreshToken);
129
+
130
+ if (authResponse?.succeeded && authResponse.tokens) {
131
+ this._refreshToken = refreshToken;
132
+ this.refreshLoginCookies(authResponse);
133
+ }
134
+
135
+ return authResponse;
136
+ }
137
+
138
+ // cookie methods
139
+ public async logout(): Promise<AuthResponse | undefined> {
140
+ return { succeeded: true };
141
+ }
142
+
143
+ public getUserFromCookie(token?: string, refreshToken?: string): AuthResponse | undefined {
144
+ token = token || this.getCookieUserToken();
145
+ refreshToken = refreshToken || this.getCookieRefreshToken();
146
+
147
+ if (!token || !refreshToken) {
148
+ return undefined;
149
+ }
150
+
151
+ return AuthService.getUserObjectFromToken(token, refreshToken);
152
+ }
153
+
154
+ public getCookieTokens(): AuthTokens {
155
+ return {
156
+ token: this.getCookieUserToken(),
157
+ refreshToken: this.getCookieRefreshToken(),
158
+ };
159
+ }
160
+
161
+ public setRefreshToken(token: string): void {
162
+ this._refreshToken = token;
163
+ }
164
+
165
+ protected getCookieUser(): string {
166
+ return this._cookieService.get(AUTH_COOKIES.USER);
167
+ }
168
+
169
+ protected getCookieRefreshToken(): string {
170
+ return this._cookieService.get(AUTH_COOKIES.REFRESH_TOKEN);
171
+ }
172
+
173
+ protected getCookieUserToken(): string {
174
+ return this._cookieService.get(AUTH_COOKIES.USER_AUTH);
175
+ }
176
+
177
+ protected getCookieMaxAge(): number {
178
+ const maxAge = this._cookieService.get(AUTH_COOKIES.USER_MAX_AGE);
179
+ if (!maxAge) {
180
+ return AUTH_COOKIES_MAX_AGE.DEFAULT;
181
+ }
182
+ return parseInt(maxAge, 10);
183
+ }
184
+
185
+ protected getCurrentTokens(
186
+ refreshToken?: string,
187
+ userToken?: string,
188
+ ): { refreshToken: string | undefined; userToken: string | undefined } {
189
+ const cookieRefreshToken = this.getCookieRefreshToken();
190
+ const cookieUserToken = this.getCookieUserToken();
191
+ return {
192
+ refreshToken: refreshToken || cookieRefreshToken,
193
+ userToken: userToken || cookieUserToken,
194
+ };
195
+ }
196
+
197
+ protected setCookieRefreshToken(token: string, maxAge?: number): void {
198
+ const setMaxAge = maxAge || this.getCookieMaxAge() || AUTH_COOKIES_MAX_AGE.DEFAULT;
199
+ this._cookieService.set({
200
+ name: AUTH_COOKIES.REFRESH_TOKEN,
201
+ payload: token,
202
+ maxAge: setMaxAge,
203
+ });
204
+ }
205
+
206
+ protected setCookieUserToken(token: string, maxAge: number): void {
207
+ const setMaxAge = maxAge || this.getCookieMaxAge() || AUTH_COOKIES_MAX_AGE.DEFAULT;
208
+ this._cookieService.set({
209
+ name: AUTH_COOKIES.USER_AUTH,
210
+ payload: token,
211
+ maxAge: setMaxAge,
212
+ });
213
+ }
214
+
215
+ protected setCookiesTokens(tokens?: AuthTokens, maxAge?: number): void {
216
+ if (!tokens) {
217
+ return;
218
+ }
219
+ const setMaxAge = maxAge || this.getCookieMaxAge() || AUTH_COOKIES_MAX_AGE.DEFAULT;
220
+ if (tokens?.refreshToken) {
221
+ this.setCookieRefreshToken(tokens.refreshToken, setMaxAge);
222
+ }
223
+ if (tokens?.token) {
224
+ this.setCookieUserToken(tokens.token, tokens.expiresIn || 900);
225
+ }
226
+ }
227
+
228
+ protected setCookiesUser(authUser?: AuthUser, maxAge?: number): void {
229
+ if (!authUser) {
230
+ return;
231
+ }
232
+ const setMaxAge = maxAge || this.getCookieMaxAge() || AUTH_COOKIES_MAX_AGE.DEFAULT;
233
+
234
+ this._cookieService.set({
235
+ name: AUTH_COOKIES.USER_MAX_AGE,
236
+ payload: setMaxAge.toString(),
237
+ maxAge: setMaxAge,
238
+ });
239
+
240
+ if (authUser?.username) {
241
+ this._cookieService.set({
242
+ name: AUTH_COOKIES.USER,
243
+ payload: authUser.username,
244
+ maxAge: setMaxAge,
245
+ });
246
+ }
247
+
248
+ if (authUser?.customerType) {
249
+ this._cookieService.set({
250
+ name: AUTH_COOKIES.USER_TYPE,
251
+ payload: authUser.customerType,
252
+ maxAge: setMaxAge,
253
+ });
254
+ }
255
+ }
256
+
257
+ protected setCookiesLogin(authResponse: AuthResponse, rememberUser: boolean): void {
258
+ const maxAge = rememberUser ? AUTH_COOKIES_MAX_AGE.REMEMBER_USER : AUTH_COOKIES_MAX_AGE.DEFAULT;
259
+ const { tokens, user } = authResponse;
260
+
261
+ this.setCookiesUser(user, maxAge);
262
+ this.setCookiesTokens(tokens, maxAge);
263
+ }
264
+
265
+ protected refreshLoginCookies(authResponse: AuthResponse): void {
266
+ const { tokens, user } = authResponse;
267
+ this.setCookiesUser(user);
268
+ this.setCookiesTokens(tokens);
269
+ }
270
+
271
+ public clearAuth(): void {
272
+ this.clearAuthCookies();
273
+ this._refreshToken = undefined;
274
+ }
275
+
276
+ public clearAuthCookies(): void {
277
+ Object.values(AUTH_COOKIES).forEach(cookieName => {
278
+ this._cookieService.remove(cookieName);
279
+ });
280
+ }
281
+
282
+ public spoofPreviewUser(token: string): string {
283
+ this.clearAuthCookies();
284
+
285
+ const maxAge = AUTH_COOKIES_MAX_AGE.DEFAULT;
286
+ const spoofedUser = authClaimsTokenSerializeToObject(token);
287
+
288
+ const username = spoofedUser?.spoofedBy || 'preview@geins.io';
289
+ const spoofDate = spoofedUser?.spoofDate;
290
+ const customerType = spoofedUser?.customerType || 'preview';
291
+
292
+ this._cookieService.set({
293
+ name: AUTH_COOKIES.USER,
294
+ payload: username,
295
+ maxAge,
296
+ });
297
+
298
+ this._cookieService.set({
299
+ name: AUTH_COOKIES.USER_AUTH,
300
+ payload: token,
301
+ maxAge,
302
+ });
303
+
304
+ this._cookieService.set({
305
+ name: AUTH_COOKIES.USER_TYPE,
306
+ payload: customerType,
307
+ maxAge,
308
+ });
309
+
310
+ this._cookieService.set({
311
+ name: AUTH_COOKIES.USER_MAX_AGE,
312
+ payload: maxAge.toString(),
313
+ maxAge,
314
+ });
315
+
316
+ return JSON.stringify(spoofedUser);
317
+ }
318
+ }
@@ -0,0 +1,31 @@
1
+ import type { AuthResponse, AuthCredentials } from '@geins/types';
2
+ import { AuthClient } from './authClient';
3
+ import { AuthService } from './authService';
4
+
5
+ export class AuthClientDirect extends AuthClient {
6
+ private _authService: AuthService;
7
+
8
+ constructor(signEndpoint: string, authEndpoint: string) {
9
+ super();
10
+ this._authService = new AuthService(signEndpoint, authEndpoint);
11
+ }
12
+
13
+ protected async handleLogin(credentials: AuthCredentials): Promise<AuthResponse | undefined> {
14
+ return this._authService.login(credentials);
15
+ }
16
+ protected async handleRefresh(refreshToken: string): Promise<AuthResponse | undefined> {
17
+ return this._authService.refresh(refreshToken);
18
+ }
19
+ protected async handleGetUser(refreshToken: string, userToken?: string): Promise<AuthResponse | undefined> {
20
+ return this._authService.getUser(refreshToken, userToken);
21
+ }
22
+ protected async handleChangePassword(
23
+ credentials: AuthCredentials,
24
+ refreshToken: string,
25
+ ): Promise<AuthResponse | undefined> {
26
+ return this._authService.changePassword(credentials, refreshToken);
27
+ }
28
+ protected async handleRegister(credentials: AuthCredentials): Promise<AuthResponse | undefined> {
29
+ return this._authService.register(credentials);
30
+ }
31
+ }
@@ -0,0 +1,82 @@
1
+ import { AUTH_HEADERS } from '@geins/core';
2
+ import type { AuthResponse, AuthCredentials } from '@geins/types';
3
+ import { AuthClient } from './authClient';
4
+ import { AuthService } from './authService';
5
+
6
+ export class AuthClientProxy extends AuthClient {
7
+ private _authEndpointApp: string;
8
+
9
+ constructor(authEndpointApp: string) {
10
+ super();
11
+ this._authEndpointApp = authEndpointApp;
12
+ }
13
+
14
+ private async request<T>(path: string, options: RequestInit): Promise<T> {
15
+ const refreshToken = this._refreshToken || this.getCookieRefreshToken();
16
+
17
+ if (!options.headers) {
18
+ options.headers = { 'Content-Type': 'application/json' };
19
+ }
20
+ if (refreshToken) {
21
+ options.headers = {
22
+ ...options.headers,
23
+ [`${AUTH_HEADERS.REFRESH_TOKEN}`]: refreshToken,
24
+ };
25
+ }
26
+
27
+ if (options.method === 'GET' || options.method === 'HEAD') {
28
+ delete options.body;
29
+ }
30
+
31
+ const response = await fetch(`${this._authEndpointApp}${path}`, {
32
+ ...options,
33
+ });
34
+
35
+ const result = await response.json();
36
+ if (!response.ok) {
37
+ console.error(result.message || 'API request failed');
38
+ throw new Error('API request failed');
39
+ }
40
+
41
+ return result.body?.data as T;
42
+ }
43
+
44
+ protected async handleLogin(credentials: AuthCredentials): Promise<AuthResponse | undefined> {
45
+ return this.request('/login', {
46
+ method: 'POST',
47
+ body: JSON.stringify(credentials),
48
+ });
49
+ }
50
+
51
+ protected async handleRefresh(refreshToken: string): Promise<AuthResponse | undefined> {
52
+ this._refreshToken = refreshToken;
53
+ return this.request('/refresh', {
54
+ method: 'POST',
55
+ });
56
+ }
57
+
58
+ protected async handleGetUser(refreshToken: string, userToken?: string): Promise<AuthResponse | undefined> {
59
+ this._refreshToken = refreshToken;
60
+ return this.request('/user', {
61
+ method: 'GET',
62
+ });
63
+ }
64
+
65
+ protected async handleChangePassword(
66
+ credentials: AuthCredentials,
67
+ refreshToken: string,
68
+ ): Promise<AuthResponse | undefined> {
69
+ this._refreshToken = refreshToken;
70
+ return this.request('/change-password', {
71
+ method: 'POST',
72
+ body: JSON.stringify(credentials),
73
+ });
74
+ }
75
+
76
+ protected async handleRegister(credentials: AuthCredentials): Promise<AuthResponse | undefined> {
77
+ return this.request('/register', {
78
+ method: 'POST',
79
+ body: JSON.stringify(credentials),
80
+ });
81
+ }
82
+ }
@@ -0,0 +1,65 @@
1
+ export function authClaimTokenParse(token: string): any {
2
+ try {
3
+ const base64Url = token.split('.')[1];
4
+ if (!base64Url) {
5
+ return null;
6
+ }
7
+
8
+ const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
9
+ const decodedString = atob(base64);
10
+ return JSON.parse(decodedString);
11
+ } catch (error) {
12
+ return null;
13
+ }
14
+ }
15
+
16
+ export function authClaimsTokenSerialize(token: string): string | null {
17
+ const claims = authClaimTokenParse(token);
18
+ if (!claims) {
19
+ return null;
20
+ }
21
+
22
+ return Object.entries(claims)
23
+ .map(([key, value]) =>
24
+ Array.isArray(value) ? value.map(v => `${key}=${v}`).join(';') : `${key}=${value}`,
25
+ )
26
+ .join(';');
27
+ }
28
+
29
+ export function authClaimsTokenSerializeToObject(token: string): Record<string, string> | null {
30
+ try {
31
+ const serializedClaims = authClaimsTokenSerialize(token);
32
+ if (!serializedClaims) {
33
+ return null;
34
+ }
35
+
36
+ const obj = serializedClaims.split(';').reduce(
37
+ (acc, pair) => {
38
+ let [key, value] = pair.split('=');
39
+ if (key.includes('/')) {
40
+ key = key.split('/').pop() || key;
41
+ }
42
+ key = key.charAt(0).toLowerCase() + key.slice(1);
43
+ acc[key] = value;
44
+ return acc;
45
+ },
46
+ {} as Record<string, string>,
47
+ );
48
+
49
+ return obj;
50
+ } catch (error) {
51
+ return null;
52
+ }
53
+ }
54
+
55
+ export function arrayBufferToBase64(buffer: ArrayBuffer): string {
56
+ const byteArray = new Uint8Array(buffer);
57
+ const binaryString = byteArray.reduce((acc, byte) => acc + String.fromCharCode(byte), '');
58
+ return btoa(binaryString);
59
+ }
60
+
61
+ export async function digest(password: string): Promise<string> {
62
+ const salt = 'Dd1dfLonNy6Am2fXQl2AcoI+IbhLhXvaibnDNn8uEa6vbJ05eyJajSuGFm9uQSmD';
63
+ const buffer = await crypto.subtle.digest('SHA-384', new TextEncoder().encode(password + salt));
64
+ return arrayBufferToBase64(buffer);
65
+ }