@pagamio/frontend-commons-lib 0.8.189 → 0.8.191
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/lib/api/client.js +5 -3
- package/lib/api/context.d.ts +2 -1
- package/lib/api/context.js +2 -1
- package/lib/api/types.d.ts +1 -0
- package/lib/auth/types/auth.types.d.ts +48 -0
- package/lib/auth/utils/Transformers.d.ts +39 -1
- package/lib/auth/utils/Transformers.js +101 -0
- package/package.json +1 -1
package/lib/api/client.js
CHANGED
|
@@ -11,6 +11,7 @@ export class ApiClient {
|
|
|
11
11
|
defaultHeaders: {
|
|
12
12
|
'Content-Type': 'application/json',
|
|
13
13
|
},
|
|
14
|
+
credentials: 'include',
|
|
14
15
|
...config,
|
|
15
16
|
};
|
|
16
17
|
}
|
|
@@ -214,7 +215,7 @@ export class ApiClient {
|
|
|
214
215
|
* Makes the actual HTTP request.
|
|
215
216
|
*/
|
|
216
217
|
async makeRequest(endpoint, method, config) {
|
|
217
|
-
const { params, timeout, skipAuth, skipRefresh, requestConfig, overrideDefaultHeaders, signal } = config;
|
|
218
|
+
const { params, timeout, skipAuth, skipRefresh, requestConfig, overrideDefaultHeaders, signal, overrideDefaultCredentials, } = config;
|
|
218
219
|
const url = this.createUrl(endpoint, params);
|
|
219
220
|
// Use provided signal, or create a new AbortController for this request
|
|
220
221
|
let requestSignal;
|
|
@@ -227,7 +228,7 @@ export class ApiClient {
|
|
|
227
228
|
this.activeControllers.add(controller);
|
|
228
229
|
requestSignal = controller.signal;
|
|
229
230
|
}
|
|
230
|
-
let finalConfig = this.buildRequestConfig(requestConfig, method, overrideDefaultHeaders, requestSignal);
|
|
231
|
+
let finalConfig = this.buildRequestConfig(requestConfig, method, overrideDefaultHeaders, overrideDefaultCredentials, requestSignal);
|
|
231
232
|
finalConfig = await this.injectAuthHeader(finalConfig, skipAuth);
|
|
232
233
|
finalConfig = await this.applyOnRequestHook(finalConfig);
|
|
233
234
|
let response;
|
|
@@ -243,7 +244,7 @@ export class ApiClient {
|
|
|
243
244
|
}
|
|
244
245
|
return response;
|
|
245
246
|
}
|
|
246
|
-
buildRequestConfig(requestConfig, method, overrideDefaultHeaders, signal) {
|
|
247
|
+
buildRequestConfig(requestConfig, method, overrideDefaultHeaders, overrideDefaultCredentials, signal) {
|
|
247
248
|
return {
|
|
248
249
|
...requestConfig,
|
|
249
250
|
method,
|
|
@@ -252,6 +253,7 @@ export class ApiClient {
|
|
|
252
253
|
...requestConfig.headers,
|
|
253
254
|
},
|
|
254
255
|
signal,
|
|
256
|
+
credentials: requestConfig.credentials ?? overrideDefaultCredentials ?? this.config.credentials ?? 'same-origin',
|
|
255
257
|
};
|
|
256
258
|
}
|
|
257
259
|
async injectAuthHeader(finalConfig, skipAuth) {
|
package/lib/api/context.d.ts
CHANGED
|
@@ -102,11 +102,12 @@ export declare function useApi<T extends CustomAuthConfig>(): ApiClient<T>;
|
|
|
102
102
|
* });
|
|
103
103
|
* ```
|
|
104
104
|
*/
|
|
105
|
-
export declare function createApiClient<T extends CustomAuthConfig>({ baseURL, tokenManager, defaultHeaders, timeout, retries, }: {
|
|
105
|
+
export declare function createApiClient<T extends CustomAuthConfig>({ baseURL, tokenManager, defaultHeaders, timeout, retries, credentials, }: {
|
|
106
106
|
baseURL: string;
|
|
107
107
|
tokenManager: TokenManager<T>;
|
|
108
108
|
defaultHeaders?: HeadersInit;
|
|
109
109
|
timeout?: number;
|
|
110
110
|
retries?: number;
|
|
111
|
+
credentials?: RequestCredentials;
|
|
111
112
|
}): ApiClient<T>;
|
|
112
113
|
export {};
|
package/lib/api/context.js
CHANGED
|
@@ -94,12 +94,13 @@ export function useApi() {
|
|
|
94
94
|
* });
|
|
95
95
|
* ```
|
|
96
96
|
*/
|
|
97
|
-
export function createApiClient({ baseURL, tokenManager, defaultHeaders = {}, timeout = 30000, retries = 1, }) {
|
|
97
|
+
export function createApiClient({ baseURL, tokenManager, defaultHeaders = {}, timeout = 30000, retries = 1, credentials, }) {
|
|
98
98
|
return new ApiClient({
|
|
99
99
|
baseURL,
|
|
100
100
|
tokenManager,
|
|
101
101
|
defaultHeaders,
|
|
102
102
|
timeout,
|
|
103
103
|
retries,
|
|
104
|
+
credentials,
|
|
104
105
|
});
|
|
105
106
|
}
|
package/lib/api/types.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface ApiClientConfig<T extends CustomAuthConfig> {
|
|
|
22
22
|
onResponse?: <T>(response: Response, data: T) => Promise<T> | T;
|
|
23
23
|
onError?: (error: ApiError) => Promise<void> | void;
|
|
24
24
|
onUnauthorized?: () => Promise<void> | void;
|
|
25
|
+
credentials?: RequestCredentials;
|
|
25
26
|
}
|
|
26
27
|
export interface RequestConfig extends RequestInit {
|
|
27
28
|
params?: Record<string, string>;
|
|
@@ -231,4 +231,52 @@ export interface VasAppAuthConfig extends CustomAuthConfig {
|
|
|
231
231
|
password: string;
|
|
232
232
|
};
|
|
233
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Authentication configuration for the Commerce application.
|
|
236
|
+
* Defines the structure of user information, token data, and login credentials
|
|
237
|
+
* specific to the Commerce app authentication flow.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const authService = createAuthService<CommerceAppAuthConfig>({
|
|
242
|
+
* baseUrl: 'https://api.commerce.example.com',
|
|
243
|
+
* endpoints: {
|
|
244
|
+
* login: '/auth/login',
|
|
245
|
+
* register: '/auth/register',
|
|
246
|
+
* }
|
|
247
|
+
* });
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export interface CommerceAppAuthConfig extends CustomAuthConfig {
|
|
251
|
+
/** User information structure for Commerce app */
|
|
252
|
+
UserInfo: {
|
|
253
|
+
/** Unique identifier for the user */
|
|
254
|
+
id: string;
|
|
255
|
+
/** Username used for authentication */
|
|
256
|
+
userName: string;
|
|
257
|
+
/** Current onboarding step */
|
|
258
|
+
onboardingStep?: string | null;
|
|
259
|
+
/** Secondary user identifier */
|
|
260
|
+
userId: string;
|
|
261
|
+
/** User type (e.g., customer, merchant, admin) */
|
|
262
|
+
userType: string;
|
|
263
|
+
/** User type identifier */
|
|
264
|
+
userTypeId: string;
|
|
265
|
+
};
|
|
266
|
+
/** Token information structure */
|
|
267
|
+
TokenInfo: {
|
|
268
|
+
/** JWT or other authentication token */
|
|
269
|
+
token: string;
|
|
270
|
+
/** Token expiration time in seconds */
|
|
271
|
+
expiresIn: number;
|
|
272
|
+
};
|
|
273
|
+
/** Login credentials structure */
|
|
274
|
+
Credentials: {
|
|
275
|
+
/** Username or email for authentication */
|
|
276
|
+
username?: string;
|
|
277
|
+
email?: string;
|
|
278
|
+
/** User's password */
|
|
279
|
+
password: string;
|
|
280
|
+
};
|
|
281
|
+
}
|
|
234
282
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApiResponseTransformer, AuthResponse, EventsAppAuthConfig, VasAppAuthConfig } from '../types';
|
|
1
|
+
import type { ApiResponseTransformer, AuthResponse, CommerceAppAuthConfig, EventsAppAuthConfig, VasAppAuthConfig } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* Transforms authentication responses from the Events App API format into a standardized AuthResponse.
|
|
4
4
|
* This transformer handles responses that include a single token and role-based user information.
|
|
@@ -115,6 +115,44 @@ export declare class VasAppResponseTransformer implements ApiResponseTransformer
|
|
|
115
115
|
*/
|
|
116
116
|
transform(response: any, remember?: boolean): AuthResponse<VasAppAuthConfig>;
|
|
117
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Transforms authentication responses from the Commerce App API format into a standardized AuthResponse.
|
|
120
|
+
* This transformer handles responses wrapped in a success/data structure.
|
|
121
|
+
*
|
|
122
|
+
* Expected API response format:
|
|
123
|
+
* ```typescript
|
|
124
|
+
* {
|
|
125
|
+
* success: boolean;
|
|
126
|
+
* data: {
|
|
127
|
+
* user: {...};
|
|
128
|
+
* accessToken: string;
|
|
129
|
+
* refreshToken: string;
|
|
130
|
+
* };
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @implements {ApiResponseTransformer<CommerceAppAuthConfig>}
|
|
135
|
+
*/
|
|
136
|
+
export declare class CommerceAppResponseTransformer implements ApiResponseTransformer<CommerceAppAuthConfig> {
|
|
137
|
+
/**
|
|
138
|
+
* Checks if the given response matches the Commerce App API format.
|
|
139
|
+
* Verifies the presence of required fields specific to Commerce App responses.
|
|
140
|
+
*
|
|
141
|
+
* @param response - The raw API response to check
|
|
142
|
+
* @returns True if the response contains 'success' and 'data' fields with user and tokens
|
|
143
|
+
*/
|
|
144
|
+
canHandle(response: any): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Transforms a Commerce App API response into the standardized AuthResponse format.
|
|
147
|
+
* Maps API-specific fields to the common auth response structure.
|
|
148
|
+
*
|
|
149
|
+
* @param response - The raw API response to transform
|
|
150
|
+
* @param remember - Whether to use extended token expiration
|
|
151
|
+
* @returns Standardized auth response with user and token information
|
|
152
|
+
* @throws Error if required fields are missing from the response
|
|
153
|
+
*/
|
|
154
|
+
transform(response: any, remember?: boolean): AuthResponse<CommerceAppAuthConfig>;
|
|
155
|
+
}
|
|
118
156
|
/**
|
|
119
157
|
* Factory class for creating and managing response transformers.
|
|
120
158
|
* Implements the Factory pattern to dynamically select the appropriate transformer
|
|
@@ -211,6 +211,106 @@ export class VasAppResponseTransformer {
|
|
|
211
211
|
};
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Transforms authentication responses from the Commerce App API format into a standardized AuthResponse.
|
|
216
|
+
* This transformer handles responses wrapped in a success/data structure.
|
|
217
|
+
*
|
|
218
|
+
* Expected API response format:
|
|
219
|
+
* ```typescript
|
|
220
|
+
* {
|
|
221
|
+
* success: boolean;
|
|
222
|
+
* data: {
|
|
223
|
+
* user: {...};
|
|
224
|
+
* accessToken: string;
|
|
225
|
+
* refreshToken: string;
|
|
226
|
+
* };
|
|
227
|
+
* }
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* @implements {ApiResponseTransformer<CommerceAppAuthConfig>}
|
|
231
|
+
*/
|
|
232
|
+
export class CommerceAppResponseTransformer {
|
|
233
|
+
/**
|
|
234
|
+
* Checks if the given response matches the Commerce App API format.
|
|
235
|
+
* Verifies the presence of required fields specific to Commerce App responses.
|
|
236
|
+
*
|
|
237
|
+
* @param response - The raw API response to check
|
|
238
|
+
* @returns True if the response contains 'success' and 'data' fields with user and tokens
|
|
239
|
+
*/
|
|
240
|
+
canHandle(response) {
|
|
241
|
+
return (response.hasOwnProperty('success') &&
|
|
242
|
+
response.hasOwnProperty('data') &&
|
|
243
|
+
response.data?.hasOwnProperty('user') &&
|
|
244
|
+
response.data?.hasOwnProperty('accessToken'));
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Transforms a Commerce App API response into the standardized AuthResponse format.
|
|
248
|
+
* Maps API-specific fields to the common auth response structure.
|
|
249
|
+
*
|
|
250
|
+
* @param response - The raw API response to transform
|
|
251
|
+
* @param remember - Whether to use extended token expiration
|
|
252
|
+
* @returns Standardized auth response with user and token information
|
|
253
|
+
* @throws Error if required fields are missing from the response
|
|
254
|
+
*/
|
|
255
|
+
transform(response, remember) {
|
|
256
|
+
const { data } = response;
|
|
257
|
+
// Decode access token to get expiration
|
|
258
|
+
let decodedAccessToken;
|
|
259
|
+
try {
|
|
260
|
+
decodedAccessToken = jwtDecode(data.accessToken);
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
console.error('Error decoding JWT access token:', error);
|
|
264
|
+
throw new Error('Failed to decode JWT access token. Please check the token format.');
|
|
265
|
+
}
|
|
266
|
+
if (!decodedAccessToken.exp) {
|
|
267
|
+
throw new Error('Access token does not contain an expiry time (exp claim)');
|
|
268
|
+
}
|
|
269
|
+
// Calculate access token expiration in seconds from now
|
|
270
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
271
|
+
const accessExpiresIn = decodedAccessToken.exp - currentTime;
|
|
272
|
+
if (accessExpiresIn <= 0) {
|
|
273
|
+
throw new Error('Access token has already expired');
|
|
274
|
+
}
|
|
275
|
+
// Decode refresh token to get expiration (if present)
|
|
276
|
+
let refreshExpiresIn;
|
|
277
|
+
if (data.refreshToken) {
|
|
278
|
+
try {
|
|
279
|
+
const decodedRefreshToken = jwtDecode(data.refreshToken);
|
|
280
|
+
if (decodedRefreshToken.exp) {
|
|
281
|
+
refreshExpiresIn = decodedRefreshToken.exp - currentTime;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
console.error('Error decoding JWT refresh token:', error);
|
|
286
|
+
// Use fallback if refresh token can't be decoded
|
|
287
|
+
refreshExpiresIn = remember ? 30 * 24 * 60 * 60 : 7 * 24 * 60 * 60; // 30 days or 7 days
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
user: {
|
|
292
|
+
id: data.user.id,
|
|
293
|
+
userName: data.user.userName,
|
|
294
|
+
onboardingStep: data.user.onboardingStep,
|
|
295
|
+
userId: data.user.id,
|
|
296
|
+
userType: data.user.userType || 'customer',
|
|
297
|
+
userTypeId: data.user.userTypeId || data.user.employeeId || data.user.id,
|
|
298
|
+
},
|
|
299
|
+
auth: {
|
|
300
|
+
accessToken: {
|
|
301
|
+
token: data.accessToken,
|
|
302
|
+
expiresIn: accessExpiresIn,
|
|
303
|
+
},
|
|
304
|
+
refreshToken: data.refreshToken && refreshExpiresIn
|
|
305
|
+
? {
|
|
306
|
+
token: data.refreshToken,
|
|
307
|
+
expiresIn: refreshExpiresIn,
|
|
308
|
+
}
|
|
309
|
+
: undefined,
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
}
|
|
214
314
|
/**
|
|
215
315
|
* Factory class for creating and managing response transformers.
|
|
216
316
|
* Implements the Factory pattern to dynamically select the appropriate transformer
|
|
@@ -232,6 +332,7 @@ export class ResponseTransformerFactory {
|
|
|
232
332
|
* @static
|
|
233
333
|
*/
|
|
234
334
|
static transformers = [
|
|
335
|
+
new CommerceAppResponseTransformer(),
|
|
235
336
|
new EventsAppResponseTransformer(),
|
|
236
337
|
new VasAppResponseTransformer(),
|
|
237
338
|
];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagamio/frontend-commons-lib",
|
|
3
3
|
"description": "Pagamio library for Frontend reusable components like the form engine and table container",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.191",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"provenance": false
|