@explorins/pers-sdk 1.2.5 → 1.2.6
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/analytics.cjs +6 -0
- package/dist/analytics.cjs.map +1 -1
- package/dist/analytics.js +2 -0
- package/dist/analytics.js.map +1 -1
- package/dist/business.cjs +6 -0
- package/dist/business.cjs.map +1 -1
- package/dist/business.js +2 -0
- package/dist/business.js.map +1 -1
- package/dist/campaign.cjs +6 -0
- package/dist/campaign.cjs.map +1 -1
- package/dist/campaign.js +2 -0
- package/dist/campaign.js.map +1 -1
- package/dist/{auth-admin/api/auth-admin-api.d.ts → core/auth/api/auth-api.d.ts} +7 -8
- package/dist/core/auth/api/auth-api.d.ts.map +1 -0
- package/dist/core/auth/auth-provider.interface.d.ts +25 -1
- package/dist/core/auth/auth-provider.interface.d.ts.map +1 -1
- package/dist/core/auth/create-auth-provider.d.ts +3 -3
- package/dist/core/auth/create-auth-provider.d.ts.map +1 -1
- package/dist/core/auth/index.d.ts +38 -0
- package/dist/core/auth/index.d.ts.map +1 -0
- package/dist/core/auth/services/auth-service.d.ts +49 -0
- package/dist/core/auth/services/auth-service.d.ts.map +1 -0
- package/dist/core/auth/simple-sdk-auth-provider.d.ts +27 -0
- package/dist/core/auth/simple-sdk-auth-provider.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/pers-api-client.d.ts +25 -3
- package/dist/core/pers-api-client.d.ts.map +1 -1
- package/dist/core.cjs +470 -156
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +464 -157
- package/dist/core.js.map +1 -1
- package/dist/donation.cjs +6 -0
- package/dist/donation.cjs.map +1 -1
- package/dist/donation.js +2 -0
- package/dist/donation.js.map +1 -1
- package/dist/index.cjs +523 -360
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +518 -359
- package/dist/index.js.map +1 -1
- package/dist/package.json +5 -5
- package/dist/payment.cjs +6 -0
- package/dist/payment.cjs.map +1 -1
- package/dist/payment.js +2 -0
- package/dist/payment.js.map +1 -1
- package/dist/redemption/api/redemption-api.d.ts +26 -64
- package/dist/redemption/api/redemption-api.d.ts.map +1 -1
- package/dist/redemption/services/redemption-service.d.ts +21 -3
- package/dist/redemption/services/redemption-service.d.ts.map +1 -1
- package/dist/redemption.cjs +61 -94
- package/dist/redemption.cjs.map +1 -1
- package/dist/redemption.js +57 -94
- package/dist/redemption.js.map +1 -1
- package/dist/shared/interfaces/pers-shared-lib.interfaces.d.ts +1 -1
- package/dist/shared/interfaces/pers-shared-lib.interfaces.d.ts.map +1 -1
- package/dist/tenant.cjs +6 -0
- package/dist/tenant.cjs.map +1 -1
- package/dist/tenant.js +2 -0
- package/dist/tenant.js.map +1 -1
- package/dist/token.cjs +6 -0
- package/dist/token.cjs.map +1 -1
- package/dist/token.js +2 -0
- package/dist/token.js.map +1 -1
- package/dist/transaction.cjs +4 -0
- package/dist/transaction.cjs.map +1 -1
- package/dist/transaction.js +1 -0
- package/dist/transaction.js.map +1 -1
- package/dist/user-status.cjs +6 -0
- package/dist/user-status.cjs.map +1 -1
- package/dist/user-status.js +2 -0
- package/dist/user-status.js.map +1 -1
- package/dist/user.cjs +6 -0
- package/dist/user.cjs.map +1 -1
- package/dist/user.js +2 -0
- package/dist/user.js.map +1 -1
- package/dist/web3-chain.cjs +5 -0
- package/dist/web3-chain.cjs.map +1 -1
- package/dist/web3-chain.js +1 -0
- package/dist/web3-chain.js.map +1 -1
- package/dist/web3.cjs +1 -0
- package/dist/web3.cjs.map +1 -1
- package/dist/web3.js +1 -0
- package/dist/web3.js.map +1 -1
- package/package.json +5 -5
- package/dist/auth-admin/api/auth-admin-api.d.ts.map +0 -1
- package/dist/auth-admin/index.d.ts +0 -27
- package/dist/auth-admin/index.d.ts.map +0 -1
- package/dist/auth-admin/services/auth-admin-service.d.ts +0 -27
- package/dist/auth-admin/services/auth-admin-service.d.ts.map +0 -1
- package/dist/auth-admin.cjs +0 -115
- package/dist/auth-admin.cjs.map +0 -1
- package/dist/auth-admin.js +0 -111
- package/dist/auth-admin.js.map +0 -1
- package/dist/core/auth/simple-auth-config.interface.d.ts +0 -15
- package/dist/core/auth/simple-auth-config.interface.d.ts.map +0 -1
package/dist/core.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { AccountOwnerType } from '@explorins/pers-shared';
|
|
2
|
+
export { AccountOwnerType } from '@explorins/pers-shared';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* PERS SDK Configuration interfaces
|
|
3
6
|
*/
|
|
@@ -36,6 +39,241 @@ function mergeWithDefaults(config) {
|
|
|
36
39
|
};
|
|
37
40
|
}
|
|
38
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Platform-Agnostic Auth Admin API Client
|
|
44
|
+
*
|
|
45
|
+
* Handles authentication and authorization admin operations using the PERS backend.
|
|
46
|
+
* Uses @explorins/pers-shared DTOs for consistency with backend.
|
|
47
|
+
*
|
|
48
|
+
* Note: Special header handling (bypass-auth-interceptor) may need to be implemented
|
|
49
|
+
* at the PersApiClient level or through a specialized auth client.
|
|
50
|
+
*/
|
|
51
|
+
class AuthApi {
|
|
52
|
+
constructor(apiClient) {
|
|
53
|
+
this.apiClient = apiClient;
|
|
54
|
+
this.basePath = '/auth';
|
|
55
|
+
}
|
|
56
|
+
// ==========================================
|
|
57
|
+
// ADMIN AUTHENTICATION OPERATIONS
|
|
58
|
+
// ==========================================
|
|
59
|
+
/**
|
|
60
|
+
* ADMIN: Login tenant admin with JWT
|
|
61
|
+
* Note: JWT handling and auth bypass headers may need special implementation
|
|
62
|
+
*/
|
|
63
|
+
async loginTenantAdmin(jwt) {
|
|
64
|
+
const body = {
|
|
65
|
+
authToken: jwt,
|
|
66
|
+
authType: AccountOwnerType.TENANT
|
|
67
|
+
};
|
|
68
|
+
return this.apiClient.post(`${this.basePath}/token`, body);
|
|
69
|
+
}
|
|
70
|
+
async loginUser(jwt) {
|
|
71
|
+
const body = {
|
|
72
|
+
authToken: jwt,
|
|
73
|
+
authType: AccountOwnerType.USER
|
|
74
|
+
};
|
|
75
|
+
return this.apiClient.post(`${this.basePath}/token`, body);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* ADMIN: Refresh access token
|
|
79
|
+
* Note: Bypass header handling may need special implementation
|
|
80
|
+
*/
|
|
81
|
+
async refreshAccessToken(refreshToken) {
|
|
82
|
+
return this.apiClient.post(`${this.basePath}/refresh`, { refreshToken });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Platform-Agnostic Auth Admin Service
|
|
88
|
+
*
|
|
89
|
+
* Contains auth admin business logic and operations that work across platforms.
|
|
90
|
+
* No framework dependencies - pure TypeScript business logic.
|
|
91
|
+
*
|
|
92
|
+
* Focuses only on actual backend capabilities.
|
|
93
|
+
*/
|
|
94
|
+
class AuthService {
|
|
95
|
+
constructor(authApi, authProvider) {
|
|
96
|
+
this.authApi = authApi;
|
|
97
|
+
this.authProvider = authProvider;
|
|
98
|
+
}
|
|
99
|
+
// ==========================================
|
|
100
|
+
// ADMIN AUTHENTICATION OPERATIONS
|
|
101
|
+
// ==========================================
|
|
102
|
+
/**
|
|
103
|
+
* ADMIN: Login tenant admin with JWT
|
|
104
|
+
* Automatically stores tokens if auth provider supports token storage
|
|
105
|
+
*/
|
|
106
|
+
async loginTenantAdmin(jwt) {
|
|
107
|
+
const response = await this.authApi.loginTenantAdmin(jwt);
|
|
108
|
+
// Store tokens if auth provider supports it
|
|
109
|
+
if (this.authProvider && response.accessToken) {
|
|
110
|
+
await this.storeTokens(response.accessToken, response.refreshToken);
|
|
111
|
+
}
|
|
112
|
+
return response;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* ADMIN: Login user with JWT
|
|
116
|
+
* Automatically stores tokens if auth provider supports token storage
|
|
117
|
+
*/
|
|
118
|
+
async loginUser(jwt) {
|
|
119
|
+
const response = await this.authApi.loginUser(jwt);
|
|
120
|
+
// Store tokens if auth provider supports it
|
|
121
|
+
if (this.authProvider && response.accessToken) {
|
|
122
|
+
await this.storeTokens(response.accessToken, response.refreshToken);
|
|
123
|
+
}
|
|
124
|
+
return response;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* ADMIN: Refresh access token
|
|
128
|
+
* Automatically stores new tokens if auth provider supports token storage
|
|
129
|
+
*/
|
|
130
|
+
async refreshAccessToken(refreshToken) {
|
|
131
|
+
// Use provided refresh token or get from auth provider
|
|
132
|
+
const tokenToUse = refreshToken || (this.authProvider?.getRefreshToken ? await this.authProvider.getRefreshToken() : null);
|
|
133
|
+
if (!tokenToUse) {
|
|
134
|
+
throw new Error('No refresh token available for token refresh');
|
|
135
|
+
}
|
|
136
|
+
const response = await this.authApi.refreshAccessToken(tokenToUse);
|
|
137
|
+
// Store new tokens if auth provider supports it
|
|
138
|
+
if (this.authProvider && response.accessToken) {
|
|
139
|
+
await this.storeTokens(response.accessToken, response.refreshToken);
|
|
140
|
+
}
|
|
141
|
+
return response;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Automatic token refresh using stored refresh token
|
|
145
|
+
* Convenience method for 401 error handling
|
|
146
|
+
*/
|
|
147
|
+
async autoRefreshToken() {
|
|
148
|
+
return this.refreshAccessToken(); // Uses stored refresh token
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Clear stored tokens if auth provider supports it
|
|
152
|
+
*/
|
|
153
|
+
async clearTokens() {
|
|
154
|
+
if (this.authProvider?.clearTokens) {
|
|
155
|
+
await this.authProvider.clearTokens();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check if we have valid tokens for authentication
|
|
160
|
+
*/
|
|
161
|
+
hasValidAuth() {
|
|
162
|
+
return this.authProvider?.hasValidToken?.() ?? false;
|
|
163
|
+
}
|
|
164
|
+
// ==========================================
|
|
165
|
+
// PRIVATE HELPERS
|
|
166
|
+
// ==========================================
|
|
167
|
+
/**
|
|
168
|
+
* Store tokens using auth provider if it supports token storage
|
|
169
|
+
*/
|
|
170
|
+
async storeTokens(accessToken, refreshToken) {
|
|
171
|
+
if (!this.authProvider)
|
|
172
|
+
return;
|
|
173
|
+
try {
|
|
174
|
+
// Store access token
|
|
175
|
+
if (this.authProvider.setAccessToken) {
|
|
176
|
+
await this.authProvider.setAccessToken(accessToken);
|
|
177
|
+
}
|
|
178
|
+
// Store refresh token if provided and supported
|
|
179
|
+
if (refreshToken && this.authProvider.setRefreshToken) {
|
|
180
|
+
await this.authProvider.setRefreshToken(refreshToken);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.error('Failed to store tokens in auth provider:', error);
|
|
185
|
+
// Don't throw - token storage failure shouldn't break authentication
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Simple, self-contained authentication provider for SDK
|
|
192
|
+
*
|
|
193
|
+
* Manages tokens internally without external dependencies.
|
|
194
|
+
* Perfect for platform-agnostic usage.
|
|
195
|
+
*/
|
|
196
|
+
class SimpleSdkAuthProvider {
|
|
197
|
+
constructor(projectKey) {
|
|
198
|
+
this.accessToken = null;
|
|
199
|
+
this.refreshToken = null;
|
|
200
|
+
this.projectKey = null;
|
|
201
|
+
this.authType = 'admin';
|
|
202
|
+
this.projectKey = projectKey || null;
|
|
203
|
+
// Try to load tokens from localStorage if available
|
|
204
|
+
this.loadTokensFromStorage();
|
|
205
|
+
}
|
|
206
|
+
async getToken() {
|
|
207
|
+
// Return stored access token
|
|
208
|
+
return this.accessToken;
|
|
209
|
+
}
|
|
210
|
+
async getProjectKey() {
|
|
211
|
+
return this.projectKey;
|
|
212
|
+
}
|
|
213
|
+
async onTokenExpired() {
|
|
214
|
+
console.log('SimpleSdkAuthProvider: Token expired, attempting refresh...');
|
|
215
|
+
if (!this.refreshToken) {
|
|
216
|
+
console.warn('SimpleSdkAuthProvider: No refresh token available');
|
|
217
|
+
throw new Error('No refresh token available for refresh');
|
|
218
|
+
}
|
|
219
|
+
// Note: Actual refresh logic would be handled by the SDK's AuthService
|
|
220
|
+
// This provider just manages token storage
|
|
221
|
+
console.warn('SimpleSdkAuthProvider: Token refresh should be handled by SDK AuthService');
|
|
222
|
+
}
|
|
223
|
+
// Token storage methods
|
|
224
|
+
async setAccessToken(token) {
|
|
225
|
+
this.accessToken = token;
|
|
226
|
+
this.saveTokenToStorage('pers_access_token', token);
|
|
227
|
+
}
|
|
228
|
+
async setRefreshToken(token) {
|
|
229
|
+
this.refreshToken = token;
|
|
230
|
+
this.saveTokenToStorage('pers_refresh_token', token);
|
|
231
|
+
}
|
|
232
|
+
async getRefreshToken() {
|
|
233
|
+
return this.refreshToken;
|
|
234
|
+
}
|
|
235
|
+
async clearTokens() {
|
|
236
|
+
this.accessToken = null;
|
|
237
|
+
this.refreshToken = null;
|
|
238
|
+
// Clear from storage
|
|
239
|
+
this.removeTokenFromStorage('pers_access_token');
|
|
240
|
+
this.removeTokenFromStorage('pers_refresh_token');
|
|
241
|
+
}
|
|
242
|
+
// Internal methods for token persistence
|
|
243
|
+
loadTokensFromStorage() {
|
|
244
|
+
if (typeof localStorage !== 'undefined') {
|
|
245
|
+
try {
|
|
246
|
+
this.accessToken = localStorage.getItem('pers_access_token');
|
|
247
|
+
this.refreshToken = localStorage.getItem('pers_refresh_token');
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
console.error('Failed to load tokens from localStorage:', error);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
console.warn('localStorage is not available for token persistence');
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
saveTokenToStorage(key, value) {
|
|
258
|
+
if (typeof localStorage !== 'undefined') {
|
|
259
|
+
localStorage.setItem(key, value);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
removeTokenFromStorage(key) {
|
|
263
|
+
if (typeof localStorage !== 'undefined') {
|
|
264
|
+
localStorage.removeItem(key);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Utility methods for external integration
|
|
268
|
+
hasValidToken() {
|
|
269
|
+
const hasToken = !!this.accessToken;
|
|
270
|
+
return hasToken;
|
|
271
|
+
}
|
|
272
|
+
hasRefreshToken() {
|
|
273
|
+
return !!this.refreshToken;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
39
277
|
// packages/pers-sdk/src/core/pers-api-client.ts
|
|
40
278
|
/**
|
|
41
279
|
* PERS API Client - Core platform-agnostic client for PERS backend
|
|
@@ -46,8 +284,15 @@ class PersApiClient {
|
|
|
46
284
|
this.config = config;
|
|
47
285
|
// Merge user config with defaults (production + v2)
|
|
48
286
|
this.mergedConfig = mergeWithDefaults(config);
|
|
287
|
+
// Auto-create auth provider if none provided
|
|
288
|
+
if (!this.mergedConfig.authProvider) {
|
|
289
|
+
this.mergedConfig.authProvider = new SimpleSdkAuthProvider(this.mergedConfig.apiProjectKey);
|
|
290
|
+
}
|
|
49
291
|
// Build API root from merged environment and version
|
|
50
292
|
this.apiRoot = buildApiRoot(this.mergedConfig.environment, this.mergedConfig.apiVersion);
|
|
293
|
+
// Initialize auth services for direct authentication
|
|
294
|
+
this.authApi = new AuthApi(this);
|
|
295
|
+
this.authService = new AuthService(this.authApi, this.mergedConfig.authProvider);
|
|
51
296
|
}
|
|
52
297
|
/**
|
|
53
298
|
* Get request headers including auth token and project key
|
|
@@ -152,6 +397,45 @@ class PersApiClient {
|
|
|
152
397
|
async delete(endpoint) {
|
|
153
398
|
return this.request('DELETE', endpoint);
|
|
154
399
|
}
|
|
400
|
+
// ==========================================
|
|
401
|
+
// AUTHENTICATION METHODS
|
|
402
|
+
// ==========================================
|
|
403
|
+
/**
|
|
404
|
+
* Login admin user with external JWT (e.g., Firebase)
|
|
405
|
+
* Automatically stores tokens in auth provider if available
|
|
406
|
+
*/
|
|
407
|
+
async loginAdmin(externalJwt) {
|
|
408
|
+
return this.authService.loginTenantAdmin(externalJwt);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Login regular user with external JWT
|
|
412
|
+
* Automatically stores tokens in auth provider if available
|
|
413
|
+
*/
|
|
414
|
+
async loginUser(externalJwt) {
|
|
415
|
+
return this.authService.loginUser(externalJwt);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Refresh access token using stored refresh token
|
|
419
|
+
*/
|
|
420
|
+
async refreshToken() {
|
|
421
|
+
const refreshToken = await this.mergedConfig.authProvider?.getRefreshToken?.();
|
|
422
|
+
if (!refreshToken) {
|
|
423
|
+
throw new Error('No refresh token available');
|
|
424
|
+
}
|
|
425
|
+
return this.authService.refreshAccessToken(refreshToken);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Clear all stored authentication tokens
|
|
429
|
+
*/
|
|
430
|
+
async clearAuth() {
|
|
431
|
+
return this.authService.clearTokens();
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Check if user has valid authentication token
|
|
435
|
+
*/
|
|
436
|
+
hasValidAuth() {
|
|
437
|
+
return this.mergedConfig.authProvider?.hasValidToken?.() || false;
|
|
438
|
+
}
|
|
155
439
|
/**
|
|
156
440
|
* Get current configuration (returns merged config)
|
|
157
441
|
*/
|
|
@@ -174,168 +458,48 @@ class PersApiError extends Error {
|
|
|
174
458
|
this.name = 'PersApiError';
|
|
175
459
|
}
|
|
176
460
|
}
|
|
177
|
-
/**
|
|
178
|
-
* PERS API Client - Core platform-agnostic client for PERS backend
|
|
179
|
-
*/
|
|
180
|
-
/*import { HttpClient, RequestOptions } from './abstractions/http-client';
|
|
181
|
-
import { PersConfig, buildApiRoot, mergeWithDefaults } from './pers-config';
|
|
182
|
-
|
|
183
|
-
export class PersApiClient {
|
|
184
|
-
private readonly apiRoot: string;
|
|
185
|
-
private readonly mergedConfig: ReturnType<typeof mergeWithDefaults>;
|
|
186
|
-
|
|
187
|
-
constructor(
|
|
188
|
-
private httpClient: HttpClient,
|
|
189
|
-
private config: PersConfig
|
|
190
|
-
) {
|
|
191
|
-
// Merge user config with defaults (production + v2)
|
|
192
|
-
this.mergedConfig = mergeWithDefaults(config);
|
|
193
|
-
|
|
194
|
-
// Build API root from merged environment and version
|
|
195
|
-
this.apiRoot = buildApiRoot(this.mergedConfig.environment, this.mergedConfig.apiVersion);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Get request headers including auth token and project key
|
|
200
|
-
*/
|
|
201
|
-
/*private async getHeaders(): Promise<Record<string, string>> {
|
|
202
|
-
const headers: Record<string, string> = {
|
|
203
|
-
'Content-Type': 'application/json',
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
// Add authentication token
|
|
207
|
-
if (this.mergedConfig.authProvider) {
|
|
208
|
-
const token = await this.mergedConfig.authProvider.getToken();
|
|
209
|
-
if (token) {
|
|
210
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Add project key
|
|
215
|
-
if (this.mergedConfig.authProvider) {
|
|
216
|
-
const projectKey = await this.mergedConfig.authProvider.getProjectKey();
|
|
217
|
-
if (projectKey) {
|
|
218
|
-
headers['x-project-key'] = projectKey;
|
|
219
|
-
}
|
|
220
|
-
} else if(this.mergedConfig.apiProjectKey) {
|
|
221
|
-
// Fallback to config project key if no auth provider
|
|
222
|
-
headers['x-project-key'] = this.mergedConfig.apiProjectKey;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return headers;
|
|
226
|
-
}
|
|
227
461
|
|
|
228
462
|
/**
|
|
229
|
-
*
|
|
463
|
+
* Memory-based token storage (default)
|
|
230
464
|
*/
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
try {
|
|
246
|
-
switch (method) {
|
|
247
|
-
case 'GET':
|
|
248
|
-
return await this.httpClient.get<T>(url, requestOptions);
|
|
249
|
-
case 'POST':
|
|
250
|
-
return await this.httpClient.post<T>(url, body, requestOptions);
|
|
251
|
-
case 'PUT':
|
|
252
|
-
return await this.httpClient.put<T>(url, body, requestOptions);
|
|
253
|
-
case 'DELETE':
|
|
254
|
-
return await this.httpClient.delete<T>(url, requestOptions);
|
|
255
|
-
default:
|
|
256
|
-
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
257
|
-
}
|
|
258
|
-
} catch (error: any) {
|
|
259
|
-
// Handle 401 errors with automatic token refresh
|
|
260
|
-
if (error.status === 401 && retryCount === 0 && this.mergedConfig.authProvider?.onTokenExpired) {
|
|
261
|
-
try {
|
|
262
|
-
await this.mergedConfig.authProvider.onTokenExpired();
|
|
263
|
-
// Retry once with refreshed token
|
|
264
|
-
return this.request<T>(method, endpoint, body, { ...options, retryCount: 1 });
|
|
265
|
-
} catch (refreshError) {
|
|
266
|
-
throw new PersApiError(
|
|
267
|
-
`Authentication refresh failed: ${refreshError}`,
|
|
268
|
-
endpoint,
|
|
269
|
-
method,
|
|
270
|
-
401
|
|
271
|
-
);
|
|
272
|
-
}
|
|
465
|
+
class MemoryTokenStorage {
|
|
466
|
+
constructor() {
|
|
467
|
+
this.storage = new Map();
|
|
468
|
+
}
|
|
469
|
+
async setItem(key, value) {
|
|
470
|
+
this.storage.set(key, value);
|
|
471
|
+
}
|
|
472
|
+
async getItem(key) {
|
|
473
|
+
return this.storage.get(key) || null;
|
|
474
|
+
}
|
|
475
|
+
async removeItem(key) {
|
|
476
|
+
this.storage.delete(key);
|
|
273
477
|
}
|
|
274
|
-
|
|
275
|
-
throw new PersApiError(
|
|
276
|
-
`PERS API request failed: ${error.message || error}`,
|
|
277
|
-
endpoint,
|
|
278
|
-
method,
|
|
279
|
-
error.status
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Generic GET request
|
|
286
|
-
*/
|
|
287
|
-
/*async get<T>(endpoint: string): Promise<T> {
|
|
288
|
-
return this.request<T>('GET', endpoint);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Generic POST request
|
|
293
|
-
*/
|
|
294
|
-
/*async post<T>(endpoint: string, body?: any): Promise<T> {
|
|
295
|
-
return this.request<T>('POST', endpoint, body);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Generic PUT request
|
|
300
|
-
*/
|
|
301
|
-
/*async put<T>(endpoint: string, body?: any): Promise<T> {
|
|
302
|
-
return this.request<T>('PUT', endpoint, body);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Generic DELETE request
|
|
307
|
-
*/
|
|
308
|
-
/*async delete<T>(endpoint: string): Promise<T> {
|
|
309
|
-
return this.request<T>('DELETE', endpoint);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Get current configuration (returns merged config)
|
|
314
|
-
*/
|
|
315
|
-
/*getConfig(): ReturnType<typeof mergeWithDefaults> {
|
|
316
|
-
return this.mergedConfig;
|
|
317
478
|
}
|
|
318
|
-
|
|
319
479
|
/**
|
|
320
|
-
*
|
|
480
|
+
* localStorage-based token storage (browser only)
|
|
321
481
|
*/
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
)
|
|
334
|
-
|
|
335
|
-
|
|
482
|
+
class LocalStorageTokenStorage {
|
|
483
|
+
async setItem(key, value) {
|
|
484
|
+
if (typeof localStorage !== 'undefined') {
|
|
485
|
+
localStorage.setItem(key, value);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
throw new Error('localStorage is not available in this environment');
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
async getItem(key) {
|
|
492
|
+
if (typeof localStorage !== 'undefined') {
|
|
493
|
+
return localStorage.getItem(key);
|
|
494
|
+
}
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
async removeItem(key) {
|
|
498
|
+
if (typeof localStorage !== 'undefined') {
|
|
499
|
+
localStorage.removeItem(key);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
336
502
|
}
|
|
337
|
-
}*/
|
|
338
|
-
|
|
339
503
|
/**
|
|
340
504
|
* Creates a platform-agnostic AuthProvider from simple configuration
|
|
341
505
|
*
|
|
@@ -346,12 +510,33 @@ constructor(
|
|
|
346
510
|
* - Token caching with refresh support
|
|
347
511
|
* - Automatic token refresh on expiration
|
|
348
512
|
* - Configurable token providers
|
|
349
|
-
* -
|
|
513
|
+
* - Token storage (memory, localStorage, custom)
|
|
514
|
+
* - Platform-independent
|
|
350
515
|
*
|
|
351
516
|
* @param config - Simple auth configuration
|
|
352
517
|
* @returns AuthProvider implementation
|
|
353
518
|
*/
|
|
354
519
|
function createAuthProvider(config) {
|
|
520
|
+
// Initialize token storage
|
|
521
|
+
let tokenStorage;
|
|
522
|
+
switch (config.tokenStorage) {
|
|
523
|
+
case 'localStorage':
|
|
524
|
+
tokenStorage = new LocalStorageTokenStorage();
|
|
525
|
+
break;
|
|
526
|
+
case 'custom':
|
|
527
|
+
if (!config.customTokenStorage) {
|
|
528
|
+
throw new Error('Custom token storage configuration is required when tokenStorage is "custom"');
|
|
529
|
+
}
|
|
530
|
+
tokenStorage = config.customTokenStorage;
|
|
531
|
+
break;
|
|
532
|
+
case 'memory':
|
|
533
|
+
default:
|
|
534
|
+
tokenStorage = new MemoryTokenStorage();
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
// Token storage keys
|
|
538
|
+
const ACCESS_TOKEN_KEY = `pers_access_token_${config.authType || 'user'}`;
|
|
539
|
+
const REFRESH_TOKEN_KEY = `pers_refresh_token_${config.authType || 'user'}`;
|
|
355
540
|
// Store current token for refresh scenarios and caching
|
|
356
541
|
let currentToken = config.token || null;
|
|
357
542
|
let isRefreshing = false; // Prevent concurrent refresh attempts
|
|
@@ -368,6 +553,17 @@ function createAuthProvider(config) {
|
|
|
368
553
|
if (currentToken) {
|
|
369
554
|
return currentToken;
|
|
370
555
|
}
|
|
556
|
+
// Try to get token from storage
|
|
557
|
+
try {
|
|
558
|
+
const storedToken = await tokenStorage.getItem(ACCESS_TOKEN_KEY);
|
|
559
|
+
if (storedToken) {
|
|
560
|
+
currentToken = storedToken;
|
|
561
|
+
return storedToken;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
catch (error) {
|
|
565
|
+
console.warn('Failed to retrieve token from storage:', error);
|
|
566
|
+
}
|
|
371
567
|
// Custom token provider function (always fresh)
|
|
372
568
|
if (config.tokenProvider) {
|
|
373
569
|
const token = await config.tokenProvider();
|
|
@@ -380,6 +576,48 @@ function createAuthProvider(config) {
|
|
|
380
576
|
async getProjectKey() {
|
|
381
577
|
return config.projectKey || null;
|
|
382
578
|
},
|
|
579
|
+
// Token storage methods
|
|
580
|
+
async setAccessToken(token) {
|
|
581
|
+
currentToken = token;
|
|
582
|
+
try {
|
|
583
|
+
await tokenStorage.setItem(ACCESS_TOKEN_KEY, token);
|
|
584
|
+
}
|
|
585
|
+
catch (error) {
|
|
586
|
+
console.error('Failed to store access token:', error);
|
|
587
|
+
throw error;
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
async setRefreshToken(token) {
|
|
591
|
+
try {
|
|
592
|
+
await tokenStorage.setItem(REFRESH_TOKEN_KEY, token);
|
|
593
|
+
}
|
|
594
|
+
catch (error) {
|
|
595
|
+
console.error('Failed to store refresh token:', error);
|
|
596
|
+
throw error;
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
async getRefreshToken() {
|
|
600
|
+
try {
|
|
601
|
+
return await tokenStorage.getItem(REFRESH_TOKEN_KEY);
|
|
602
|
+
}
|
|
603
|
+
catch (error) {
|
|
604
|
+
console.warn('Failed to retrieve refresh token from storage:', error);
|
|
605
|
+
return null;
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
async clearTokens() {
|
|
609
|
+
currentToken = null;
|
|
610
|
+
try {
|
|
611
|
+
await Promise.all([
|
|
612
|
+
tokenStorage.removeItem(ACCESS_TOKEN_KEY),
|
|
613
|
+
tokenStorage.removeItem(REFRESH_TOKEN_KEY)
|
|
614
|
+
]);
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
console.error('Failed to clear tokens from storage:', error);
|
|
618
|
+
throw error;
|
|
619
|
+
}
|
|
620
|
+
},
|
|
383
621
|
async onTokenExpired() {
|
|
384
622
|
// Prevent concurrent refresh attempts
|
|
385
623
|
if (isRefreshing) {
|
|
@@ -391,7 +629,13 @@ function createAuthProvider(config) {
|
|
|
391
629
|
// No refresh logic provided
|
|
392
630
|
if (!config.onTokenExpired) {
|
|
393
631
|
console.warn('Token expired but no refresh logic provided');
|
|
394
|
-
currentToken = null;
|
|
632
|
+
currentToken = null;
|
|
633
|
+
try {
|
|
634
|
+
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
console.warn('Failed to clear expired token from storage:', error);
|
|
638
|
+
}
|
|
395
639
|
return;
|
|
396
640
|
}
|
|
397
641
|
// Start refresh process
|
|
@@ -405,6 +649,13 @@ function createAuthProvider(config) {
|
|
|
405
649
|
const newToken = await config.tokenProvider();
|
|
406
650
|
if (newToken && newToken !== currentToken) {
|
|
407
651
|
currentToken = newToken;
|
|
652
|
+
// Store the new token
|
|
653
|
+
try {
|
|
654
|
+
await tokenStorage.setItem(ACCESS_TOKEN_KEY, newToken);
|
|
655
|
+
}
|
|
656
|
+
catch (error) {
|
|
657
|
+
console.warn('Failed to store refreshed token:', error);
|
|
658
|
+
}
|
|
408
659
|
// Notify about successful token refresh
|
|
409
660
|
if (config.onTokenRefreshed) {
|
|
410
661
|
config.onTokenRefreshed(newToken);
|
|
@@ -413,17 +664,35 @@ function createAuthProvider(config) {
|
|
|
413
664
|
else {
|
|
414
665
|
console.warn('Token refresh completed but no new token received');
|
|
415
666
|
currentToken = null;
|
|
667
|
+
try {
|
|
668
|
+
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
669
|
+
}
|
|
670
|
+
catch (error) {
|
|
671
|
+
console.warn('Failed to clear token after failed refresh:', error);
|
|
672
|
+
}
|
|
416
673
|
}
|
|
417
674
|
}
|
|
418
675
|
else {
|
|
419
676
|
// For static token configs, clear the token since we can't refresh
|
|
420
677
|
console.warn('Token expired for static token config - clearing token');
|
|
421
678
|
currentToken = null;
|
|
679
|
+
try {
|
|
680
|
+
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
681
|
+
}
|
|
682
|
+
catch (error) {
|
|
683
|
+
console.warn('Failed to clear expired static token:', error);
|
|
684
|
+
}
|
|
422
685
|
}
|
|
423
686
|
}
|
|
424
687
|
catch (error) {
|
|
425
688
|
console.error('Token refresh failed:', error);
|
|
426
689
|
currentToken = null; // Clear token on refresh failure
|
|
690
|
+
try {
|
|
691
|
+
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
692
|
+
}
|
|
693
|
+
catch (storageError) {
|
|
694
|
+
console.warn('Failed to clear token after refresh failure:', storageError);
|
|
695
|
+
}
|
|
427
696
|
throw error; // Re-throw to let SDK handle the error
|
|
428
697
|
}
|
|
429
698
|
finally {
|
|
@@ -460,6 +729,44 @@ function createAuthProvider(config) {
|
|
|
460
729
|
};
|
|
461
730
|
} */
|
|
462
731
|
|
|
732
|
+
/**
|
|
733
|
+
* @explorins/pers-sdk/core/auth - Consolidated Auth Module
|
|
734
|
+
*
|
|
735
|
+
* All authentication functionality in one place:
|
|
736
|
+
* - Auth provider interfaces and implementations
|
|
737
|
+
* - Auth API and service logic
|
|
738
|
+
* - Token management
|
|
739
|
+
*/
|
|
740
|
+
// Auth provider interfaces and implementations
|
|
741
|
+
/**
|
|
742
|
+
* Create a complete Auth SDK instance (for backward compatibility)
|
|
743
|
+
* Note: This is now handled directly by PersApiClient
|
|
744
|
+
*
|
|
745
|
+
* @param apiClient - Configured PERS API client
|
|
746
|
+
* @param authProvider - Optional auth provider. If not provided, uses SimpleSdkAuthProvider
|
|
747
|
+
* @returns Auth SDK with flattened structure for better DX
|
|
748
|
+
*/
|
|
749
|
+
function createAuthSDK(apiClient, authProvider) {
|
|
750
|
+
// Use simple internal auth provider if none provided
|
|
751
|
+
const provider = authProvider || new SimpleSdkAuthProvider();
|
|
752
|
+
const authApi = new AuthApi(apiClient);
|
|
753
|
+
const authService = new AuthService(authApi, provider);
|
|
754
|
+
return {
|
|
755
|
+
// Direct access to service methods (primary interface)
|
|
756
|
+
// Admin authentication methods
|
|
757
|
+
loginTenantAdmin: (jwt) => authService.loginTenantAdmin(jwt),
|
|
758
|
+
loginUser: (jwt) => authService.loginUser(jwt),
|
|
759
|
+
refreshAccessToken: (refreshToken) => authService.refreshAccessToken(refreshToken),
|
|
760
|
+
clearTokens: () => authService.clearTokens(),
|
|
761
|
+
// Auth provider access for external integration
|
|
762
|
+
getAuthProvider: () => provider,
|
|
763
|
+
hasValidToken: () => provider.hasValidToken?.() || false,
|
|
764
|
+
// Advanced access for edge cases
|
|
765
|
+
api: authApi,
|
|
766
|
+
service: authService
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
|
|
463
770
|
/**
|
|
464
771
|
* PERS SDK - Minimal platform-agnostic client with built-in authentication
|
|
465
772
|
* Authentication is now handled at the SDK core level for better scalability
|
|
@@ -493,5 +800,5 @@ function createPersSDK(httpClient, config) {
|
|
|
493
800
|
return new PersSDK(httpClient, config);
|
|
494
801
|
}
|
|
495
802
|
|
|
496
|
-
export { DEFAULT_PERS_CONFIG, PersApiClient, PersApiError, PersSDK, buildApiRoot, createAuthProvider, createPersSDK, mergeWithDefaults };
|
|
803
|
+
export { AuthApi, AuthService, DEFAULT_PERS_CONFIG, PersApiClient, PersApiError, PersSDK, SimpleSdkAuthProvider, buildApiRoot, createAuthProvider, createAuthSDK, createPersSDK, mergeWithDefaults };
|
|
497
804
|
//# sourceMappingURL=core.js.map
|