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