@explorins/pers-sdk 1.6.6 → 1.6.10
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/README.md +90 -367
- package/dist/chunks/{pers-sdk-eO4XUi8w.js → pers-sdk-DOuNyWFC.js} +112 -263
- package/dist/chunks/pers-sdk-DOuNyWFC.js.map +1 -0
- package/dist/chunks/{pers-sdk-CajYwGkL.cjs → pers-sdk-kb7j1DVU.cjs} +111 -263
- package/dist/chunks/pers-sdk-kb7j1DVU.cjs.map +1 -0
- package/dist/chunks/{web3-chain-service-BYkj61DN.cjs → web3-chain-service-D75TcHkh.cjs} +28 -21
- package/dist/chunks/web3-chain-service-D75TcHkh.cjs.map +1 -0
- package/dist/chunks/{web3-chain-service-DN6tJmvK.js → web3-chain-service-Dp5Z8p9I.js} +28 -22
- package/dist/chunks/web3-chain-service-Dp5Z8p9I.js.map +1 -0
- package/dist/core/auth/api/auth-api.d.ts +11 -14
- package/dist/core/auth/api/auth-api.d.ts.map +1 -1
- package/dist/core/auth/auth-provider.interface.d.ts +10 -5
- package/dist/core/auth/auth-provider.interface.d.ts.map +1 -1
- package/dist/core/auth/default-auth-provider.d.ts +3 -6
- package/dist/core/auth/default-auth-provider.d.ts.map +1 -1
- package/dist/core/auth/index.d.ts +2 -6
- package/dist/core/auth/index.d.ts.map +1 -1
- package/dist/core/auth/refresh-manager.d.ts +2 -5
- package/dist/core/auth/refresh-manager.d.ts.map +1 -1
- package/dist/core/auth/services/auth-service.d.ts +9 -20
- package/dist/core/auth/services/auth-service.d.ts.map +1 -1
- package/dist/core/auth/token-storage.d.ts +2 -4
- package/dist/core/auth/token-storage.d.ts.map +1 -1
- package/dist/core/environment.d.ts +2 -4
- package/dist/core/environment.d.ts.map +1 -1
- package/dist/core/index.d.ts +0 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/pers-api-client.d.ts +8 -34
- package/dist/core/pers-api-client.d.ts.map +1 -1
- package/dist/core/pers-config.d.ts +5 -9
- package/dist/core/pers-config.d.ts.map +1 -1
- package/dist/core/utils/jwt.function.d.ts +9 -0
- package/dist/core/utils/jwt.function.d.ts.map +1 -1
- package/dist/core.cjs +3 -4
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +3 -4
- package/dist/core.js.map +1 -1
- package/dist/file/services/file-service.d.ts +0 -4
- package/dist/file/services/file-service.d.ts.map +1 -1
- package/dist/index.cjs +2 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/managers/file-manager.d.ts +9 -9
- package/dist/managers/file-manager.d.ts.map +1 -1
- package/dist/package.json +2 -3
- package/dist/web3-chain.cjs +1 -2
- package/dist/web3-chain.cjs.map +1 -1
- package/dist/web3-chain.js +1 -2
- package/dist/web3-chain.js.map +1 -1
- package/package.json +2 -3
- package/dist/chunks/pers-sdk-CajYwGkL.cjs.map +0 -1
- package/dist/chunks/pers-sdk-eO4XUi8w.js.map +0 -1
- package/dist/chunks/web3-chain-service-BYkj61DN.cjs.map +0 -1
- package/dist/chunks/web3-chain-service-DN6tJmvK.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AccountOwnerType } from '@explorins/pers-shared';
|
|
2
|
+
import { i as isTokenExpired, a as Web3ChainService, W as Web3ChainApi } from './web3-chain-service-Dp5Z8p9I.js';
|
|
2
3
|
import { a as UserService, U as UserApi } from './user-service-D6mTa_WZ.js';
|
|
3
4
|
import { createUserStatusSDK } from '../user-status.js';
|
|
4
5
|
import { a as TokenService, T as TokenApi } from './token-service-CpVwC5Eb.js';
|
|
@@ -11,7 +12,6 @@ import { a as TenantService, T as TenantApi } from './tenant-service-DELk412y.js
|
|
|
11
12
|
import { a as AnalyticsService, A as AnalyticsApi } from './analytics-service-CxyrOwel.js';
|
|
12
13
|
import { a as DonationService, D as DonationApi } from './donation-service-CyJS4DIZ.js';
|
|
13
14
|
import { a as Web3InfrastructureApi, I as IPFSInfrastructureApi, W as Web3ApplicationService, b as getExplorerUrlByChainId } from './explorer.utils-Ckll15ja.js';
|
|
14
|
-
import { a as Web3ChainService, W as Web3ChainApi } from './web3-chain-service-DN6tJmvK.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* PERS SDK Configuration interfaces and utilities
|
|
@@ -57,25 +57,16 @@ function mergeWithDefaults(config) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* Platform-Agnostic Auth
|
|
61
|
-
*
|
|
62
|
-
* Handles authentication and authorization admin operations using the PERS backend.
|
|
63
|
-
* Uses @explorins/pers-shared DTOs for consistency with backend.
|
|
64
|
-
*
|
|
65
|
-
* Note: Special header handling (bypass-auth-interceptor) may need to be implemented
|
|
66
|
-
* at the PersApiClient level or through a specialized auth client.
|
|
60
|
+
* Platform-Agnostic Auth API Client
|
|
61
|
+
* Handles authentication operations using the PERS backend
|
|
67
62
|
*/
|
|
68
63
|
class AuthApi {
|
|
69
64
|
constructor(apiClient) {
|
|
70
65
|
this.apiClient = apiClient;
|
|
71
66
|
this.basePath = '/auth';
|
|
72
67
|
}
|
|
73
|
-
// ==========================================
|
|
74
|
-
// ADMIN AUTHENTICATION OPERATIONS
|
|
75
|
-
// ==========================================
|
|
76
68
|
/**
|
|
77
|
-
*
|
|
78
|
-
* Note: JWT handling and auth bypass headers may need special implementation
|
|
69
|
+
* Login tenant admin with JWT
|
|
79
70
|
*/
|
|
80
71
|
async loginTenantAdmin(jwt) {
|
|
81
72
|
const body = {
|
|
@@ -85,7 +76,7 @@ class AuthApi {
|
|
|
85
76
|
return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
|
|
86
77
|
}
|
|
87
78
|
/**
|
|
88
|
-
* Login user with JWT
|
|
79
|
+
* Login user with JWT
|
|
89
80
|
*/
|
|
90
81
|
async loginUser(jwt) {
|
|
91
82
|
const body = {
|
|
@@ -94,6 +85,9 @@ class AuthApi {
|
|
|
94
85
|
};
|
|
95
86
|
return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
|
|
96
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Login user with raw data (no external authentication)
|
|
90
|
+
*/
|
|
97
91
|
async loginUnAuthenticated(rawLoginData) {
|
|
98
92
|
const body = {
|
|
99
93
|
authToken: '',
|
|
@@ -103,21 +97,16 @@ class AuthApi {
|
|
|
103
97
|
return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
|
|
104
98
|
}
|
|
105
99
|
/**
|
|
106
|
-
* Refresh access token
|
|
100
|
+
* Refresh access token
|
|
107
101
|
*/
|
|
108
102
|
async refreshAccessToken(refreshToken) {
|
|
109
|
-
// Bypass auth headers for refresh calls to prevent circular dependency
|
|
110
103
|
return this.apiClient.post(`${this.basePath}/refresh`, { refreshToken }, { bypassAuth: true });
|
|
111
104
|
}
|
|
112
105
|
}
|
|
113
106
|
|
|
114
107
|
/**
|
|
115
|
-
* Platform-
|
|
116
|
-
*
|
|
117
|
-
* Contains auth admin business logic and operations that work across platforms.
|
|
118
|
-
* No framework dependencies - pure TypeScript business logic.
|
|
119
|
-
*
|
|
120
|
-
* Focuses only on actual backend capabilities.
|
|
108
|
+
* Platform-agnostic authentication service
|
|
109
|
+
* Handles login, token refresh, and storage operations
|
|
121
110
|
*/
|
|
122
111
|
class AuthService {
|
|
123
112
|
constructor(authApi, authProvider) {
|
|
@@ -126,110 +115,84 @@ class AuthService {
|
|
|
126
115
|
this.activeRefreshPromise = null;
|
|
127
116
|
}
|
|
128
117
|
// ==========================================
|
|
129
|
-
//
|
|
118
|
+
// AUTHENTICATION OPERATIONS
|
|
130
119
|
// ==========================================
|
|
131
120
|
/**
|
|
132
|
-
*
|
|
133
|
-
* Automatically stores tokens if auth provider supports token storage
|
|
121
|
+
* Login tenant admin with JWT
|
|
134
122
|
*/
|
|
135
123
|
async loginTenantAdmin(jwt) {
|
|
136
124
|
const response = await this.authApi.loginTenantAdmin(jwt);
|
|
137
|
-
// Store tokens if auth provider supports it
|
|
138
125
|
if (this.authProvider && response.accessToken) {
|
|
139
126
|
await this.storeTokens(response.accessToken, response.refreshToken, 'admin', jwt);
|
|
140
127
|
}
|
|
141
128
|
return response;
|
|
142
129
|
}
|
|
143
130
|
/**
|
|
144
|
-
*
|
|
131
|
+
* Login user with JWT
|
|
145
132
|
*/
|
|
146
133
|
async loginUser(jwt) {
|
|
147
134
|
const response = await this.authApi.loginUser(jwt);
|
|
148
|
-
// Store tokens if auth provider supports it
|
|
149
135
|
if (this.authProvider && response.accessToken) {
|
|
150
136
|
await this.storeTokens(response.accessToken, response.refreshToken, 'user', jwt);
|
|
151
137
|
}
|
|
152
138
|
return response;
|
|
153
139
|
}
|
|
154
140
|
/**
|
|
155
|
-
*
|
|
141
|
+
* Login user with raw data (no external auth)
|
|
156
142
|
*/
|
|
157
143
|
async loginUserWithRawData(rawLoginData) {
|
|
158
|
-
const
|
|
159
|
-
externalId: rawLoginData?.externalId,
|
|
160
|
-
email: rawLoginData?.email,
|
|
161
|
-
firstName: rawLoginData?.firstName,
|
|
162
|
-
lastName: rawLoginData?.lastName,
|
|
163
|
-
customData: rawLoginData?.customData
|
|
164
|
-
};
|
|
165
|
-
const response = await this.authApi.loginUnAuthenticated(loginData);
|
|
166
|
-
// Store tokens if auth provider supports it
|
|
144
|
+
const response = await this.authApi.loginUnAuthenticated(rawLoginData);
|
|
167
145
|
if (this.authProvider && response.accessToken) {
|
|
168
146
|
await this.storeTokens(response.accessToken, response.refreshToken, 'user');
|
|
169
147
|
}
|
|
170
148
|
return response;
|
|
171
149
|
}
|
|
172
150
|
/**
|
|
173
|
-
*
|
|
174
|
-
* Automatically stores new tokens if auth provider supports token storage
|
|
175
|
-
*
|
|
176
|
-
* Implements refresh deduplication to prevent race conditions when multiple
|
|
177
|
-
* requests trigger refresh simultaneously.
|
|
151
|
+
* Refresh access token with race condition protection
|
|
178
152
|
*/
|
|
179
153
|
async refreshAccessToken(refreshToken) {
|
|
180
|
-
// If there's already an active refresh, return that promise instead of starting a new one
|
|
181
154
|
if (this.activeRefreshPromise) {
|
|
182
|
-
console.log('[AuthService] Refresh already in progress, reusing existing promise');
|
|
183
155
|
try {
|
|
184
156
|
return await this.activeRefreshPromise;
|
|
185
157
|
}
|
|
186
158
|
catch (error) {
|
|
187
|
-
// If the active refresh failed, we'll try again with a fresh attempt
|
|
188
159
|
console.warn('[AuthService] Active refresh failed, attempting new refresh:', error);
|
|
189
160
|
this.activeRefreshPromise = null;
|
|
190
161
|
}
|
|
191
162
|
}
|
|
192
|
-
// Start a new refresh operation
|
|
193
163
|
this.activeRefreshPromise = this.performRefresh(refreshToken);
|
|
194
164
|
try {
|
|
195
|
-
|
|
196
|
-
return result;
|
|
165
|
+
return await this.activeRefreshPromise;
|
|
197
166
|
}
|
|
198
167
|
finally {
|
|
199
|
-
// Clear the active refresh promise when done (success or failure)
|
|
200
168
|
this.activeRefreshPromise = null;
|
|
201
169
|
}
|
|
202
170
|
}
|
|
203
171
|
/**
|
|
204
172
|
* Performs the actual refresh operation
|
|
205
|
-
* Separated from refreshAccessToken for cleaner promise management
|
|
206
173
|
*/
|
|
207
174
|
async performRefresh(refreshToken) {
|
|
208
|
-
// Use provided refresh token or get from auth provider
|
|
209
175
|
const tokenToUse = refreshToken || (this.authProvider ? await this.authProvider.getRefreshToken() : null);
|
|
210
176
|
if (!tokenToUse) {
|
|
211
177
|
throw new Error('No refresh token available for token refresh');
|
|
212
178
|
}
|
|
213
179
|
const response = await this.authApi.refreshAccessToken(tokenToUse);
|
|
214
|
-
// Store new tokens if auth provider supports it
|
|
215
180
|
if (this.authProvider && response.accessToken) {
|
|
216
181
|
await this.storeTokens(response.accessToken, response.refreshToken);
|
|
217
182
|
}
|
|
218
183
|
return response;
|
|
219
184
|
}
|
|
220
185
|
/**
|
|
221
|
-
* Clear stored tokens
|
|
222
|
-
* Also clears any active refresh operations
|
|
186
|
+
* Clear stored tokens and active refresh operations
|
|
223
187
|
*/
|
|
224
188
|
async clearTokens() {
|
|
225
|
-
// Clear any active refresh operation
|
|
226
189
|
this.activeRefreshPromise = null;
|
|
227
190
|
if (this.authProvider) {
|
|
228
191
|
await this.authProvider.clearTokens();
|
|
229
192
|
}
|
|
230
193
|
}
|
|
231
194
|
/**
|
|
232
|
-
* Check if we have valid tokens
|
|
195
|
+
* Check if we have valid authentication tokens
|
|
233
196
|
*/
|
|
234
197
|
async hasValidAuth() {
|
|
235
198
|
if (!this.authProvider)
|
|
@@ -241,43 +204,34 @@ class AuthService {
|
|
|
241
204
|
// PRIVATE HELPERS
|
|
242
205
|
// ==========================================
|
|
243
206
|
/**
|
|
244
|
-
* Store tokens using auth provider
|
|
207
|
+
* Store tokens using auth provider
|
|
245
208
|
*/
|
|
246
209
|
async storeTokens(accessToken, refreshToken, authType, providerToken) {
|
|
247
210
|
if (!this.authProvider)
|
|
248
211
|
return;
|
|
249
212
|
try {
|
|
250
|
-
|
|
251
|
-
if (
|
|
252
|
-
await this.authProvider.setAccessToken(accessToken);
|
|
253
|
-
}
|
|
254
|
-
// Store refresh token if provided and supported
|
|
255
|
-
if (refreshToken && this.authProvider) {
|
|
213
|
+
await this.authProvider.setAccessToken(accessToken);
|
|
214
|
+
if (refreshToken) {
|
|
256
215
|
await this.authProvider.setRefreshToken(refreshToken);
|
|
257
216
|
}
|
|
258
|
-
//
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
await
|
|
217
|
+
// Type-safe handling of extended token storage features
|
|
218
|
+
const extendedProvider = this.authProvider;
|
|
219
|
+
if (providerToken && extendedProvider.setProviderToken) {
|
|
220
|
+
await extendedProvider.setProviderToken(providerToken);
|
|
262
221
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
typeof this.authProvider.setAuthType === 'function') {
|
|
266
|
-
await this.authProvider.setAuthType(authType);
|
|
222
|
+
if (authType && extendedProvider.setAuthType) {
|
|
223
|
+
await extendedProvider.setAuthType(authType);
|
|
267
224
|
}
|
|
268
225
|
}
|
|
269
226
|
catch (error) {
|
|
270
|
-
// Log error for debugging but don't throw - token storage failure shouldn't break auth flow
|
|
271
227
|
console.warn('[AuthService] Failed to store tokens:', error);
|
|
272
228
|
}
|
|
273
229
|
}
|
|
274
230
|
}
|
|
275
231
|
|
|
276
232
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* Just moves the working refresh logic to a separate file for better organization.
|
|
280
|
-
* No overengineering - keeps the exact same simple logic.
|
|
233
|
+
* Token Refresh Manager
|
|
234
|
+
* Simple container for token refresh logic with better organization
|
|
281
235
|
*/
|
|
282
236
|
class TokenRefreshManager {
|
|
283
237
|
constructor(authService, authProvider) {
|
|
@@ -288,12 +242,7 @@ class TokenRefreshManager {
|
|
|
288
242
|
async ensureValidToken() {
|
|
289
243
|
try {
|
|
290
244
|
const token = await this.authProvider.getToken();
|
|
291
|
-
if (!token) {
|
|
292
|
-
await this.attemptInternalRefresh();
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
// Check if token is close to expiry (within 2 minutes)
|
|
296
|
-
if (this.isTokenExpiringSoon(token, this.tokenRefreshMarginSeconds)) {
|
|
245
|
+
if (!token || isTokenExpired(token, this.tokenRefreshMarginSeconds)) {
|
|
297
246
|
await this.attemptInternalRefresh();
|
|
298
247
|
}
|
|
299
248
|
}
|
|
@@ -311,27 +260,11 @@ class TokenRefreshManager {
|
|
|
311
260
|
return false;
|
|
312
261
|
}
|
|
313
262
|
}
|
|
314
|
-
isTokenExpiringSoon(token, marginSeconds) {
|
|
315
|
-
try {
|
|
316
|
-
const parts = token.split('.');
|
|
317
|
-
if (parts.length !== 3)
|
|
318
|
-
return true;
|
|
319
|
-
const payload = JSON.parse(atob(parts[1]));
|
|
320
|
-
if (!payload.exp)
|
|
321
|
-
return false;
|
|
322
|
-
const timeUntilExpiry = payload.exp - Math.floor(Date.now() / 1000);
|
|
323
|
-
return timeUntilExpiry <= marginSeconds;
|
|
324
|
-
}
|
|
325
|
-
catch {
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
263
|
}
|
|
330
264
|
|
|
331
265
|
/**
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* Simple, focused token storage with clear separation of concerns.
|
|
266
|
+
* Token Storage System
|
|
267
|
+
* Simple, focused token storage with clear separation of concerns
|
|
335
268
|
*/
|
|
336
269
|
const AUTH_STORAGE_KEYS = {
|
|
337
270
|
ACCESS_TOKEN: 'pers_access_token',
|
|
@@ -344,26 +277,24 @@ const AUTH_STORAGE_KEYS = {
|
|
|
344
277
|
*/
|
|
345
278
|
class LocalStorageTokenStorage {
|
|
346
279
|
async get(key) {
|
|
347
|
-
|
|
348
|
-
return null;
|
|
349
|
-
return localStorage.getItem(key);
|
|
280
|
+
return typeof localStorage !== 'undefined' ? localStorage.getItem(key) : null;
|
|
350
281
|
}
|
|
351
282
|
async set(key, value) {
|
|
352
|
-
if (typeof localStorage
|
|
353
|
-
|
|
354
|
-
|
|
283
|
+
if (typeof localStorage !== 'undefined') {
|
|
284
|
+
localStorage.setItem(key, value);
|
|
285
|
+
}
|
|
355
286
|
}
|
|
356
287
|
async remove(key) {
|
|
357
|
-
if (typeof localStorage
|
|
358
|
-
|
|
359
|
-
|
|
288
|
+
if (typeof localStorage !== 'undefined') {
|
|
289
|
+
localStorage.removeItem(key);
|
|
290
|
+
}
|
|
360
291
|
}
|
|
361
292
|
async clear() {
|
|
362
|
-
if (typeof localStorage
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
293
|
+
if (typeof localStorage !== 'undefined') {
|
|
294
|
+
Object.values(AUTH_STORAGE_KEYS).forEach(key => {
|
|
295
|
+
localStorage.removeItem(key);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
367
298
|
}
|
|
368
299
|
}
|
|
369
300
|
/**
|
|
@@ -388,34 +319,29 @@ class MemoryTokenStorage {
|
|
|
388
319
|
}
|
|
389
320
|
/**
|
|
390
321
|
* Token manager for authentication tokens
|
|
391
|
-
* Clean, focused on auth tokens only
|
|
392
322
|
*/
|
|
393
323
|
class AuthTokenManager {
|
|
394
324
|
constructor(storage = new LocalStorageTokenStorage()) {
|
|
395
325
|
this.storage = storage;
|
|
396
326
|
}
|
|
397
|
-
// Access token methods
|
|
398
327
|
async getAccessToken() {
|
|
399
328
|
return this.storage.get(AUTH_STORAGE_KEYS.ACCESS_TOKEN);
|
|
400
329
|
}
|
|
401
330
|
async setAccessToken(token) {
|
|
402
331
|
await this.storage.set(AUTH_STORAGE_KEYS.ACCESS_TOKEN, token);
|
|
403
332
|
}
|
|
404
|
-
// Refresh token methods
|
|
405
333
|
async getRefreshToken() {
|
|
406
334
|
return this.storage.get(AUTH_STORAGE_KEYS.REFRESH_TOKEN);
|
|
407
335
|
}
|
|
408
336
|
async setRefreshToken(token) {
|
|
409
337
|
await this.storage.set(AUTH_STORAGE_KEYS.REFRESH_TOKEN, token);
|
|
410
338
|
}
|
|
411
|
-
// Provider token methods
|
|
412
339
|
async getProviderToken() {
|
|
413
340
|
return this.storage.get(AUTH_STORAGE_KEYS.PROVIDER_TOKEN);
|
|
414
341
|
}
|
|
415
342
|
async setProviderToken(token) {
|
|
416
343
|
await this.storage.set(AUTH_STORAGE_KEYS.PROVIDER_TOKEN, token);
|
|
417
344
|
}
|
|
418
|
-
// Auth type methods
|
|
419
345
|
async getAuthType() {
|
|
420
346
|
const authType = await this.storage.get(AUTH_STORAGE_KEYS.AUTH_TYPE);
|
|
421
347
|
return authType;
|
|
@@ -423,7 +349,6 @@ class AuthTokenManager {
|
|
|
423
349
|
async setAuthType(authType) {
|
|
424
350
|
await this.storage.set(AUTH_STORAGE_KEYS.AUTH_TYPE, authType);
|
|
425
351
|
}
|
|
426
|
-
// Bulk operations
|
|
427
352
|
async setTokens(accessToken, refreshToken, providerToken) {
|
|
428
353
|
await this.setAccessToken(accessToken);
|
|
429
354
|
if (refreshToken)
|
|
@@ -434,7 +359,6 @@ class AuthTokenManager {
|
|
|
434
359
|
async clearAllTokens() {
|
|
435
360
|
await this.storage.clear();
|
|
436
361
|
}
|
|
437
|
-
// Utility methods
|
|
438
362
|
async hasAccessToken() {
|
|
439
363
|
const token = await this.getAccessToken();
|
|
440
364
|
return !!token;
|
|
@@ -446,31 +370,24 @@ class AuthTokenManager {
|
|
|
446
370
|
}
|
|
447
371
|
|
|
448
372
|
/**
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
* Simple, focused implementation of PERS authentication
|
|
452
|
-
* with clear separation of concerns and minimal complexity.
|
|
373
|
+
* Default Authentication Provider
|
|
374
|
+
* Simple implementation of PERS authentication with token lifecycle management
|
|
453
375
|
*/
|
|
454
376
|
/**
|
|
455
|
-
*
|
|
456
|
-
* Handles token lifecycle with minimal complexity
|
|
377
|
+
* Simple authentication provider with token storage
|
|
457
378
|
*/
|
|
458
379
|
class DefaultAuthProvider {
|
|
459
380
|
constructor(config = {}) {
|
|
460
381
|
this.config = config;
|
|
461
382
|
this.authType = config.authType || 'user';
|
|
462
|
-
// Use custom storage if provided, otherwise auto-detect
|
|
463
383
|
const storage = config.storage || this.createStorage();
|
|
464
384
|
this.tokenManager = new AuthTokenManager(storage);
|
|
465
385
|
}
|
|
466
386
|
createStorage() {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
return new LocalStorageTokenStorage();
|
|
387
|
+
return typeof window === 'undefined' || typeof localStorage === 'undefined'
|
|
388
|
+
? new MemoryTokenStorage()
|
|
389
|
+
: new LocalStorageTokenStorage();
|
|
472
390
|
}
|
|
473
|
-
// Core PersAuthProvider methods
|
|
474
391
|
getToken() {
|
|
475
392
|
return this.tokenManager.getAccessToken();
|
|
476
393
|
}
|
|
@@ -479,14 +396,10 @@ class DefaultAuthProvider {
|
|
|
479
396
|
}
|
|
480
397
|
async onTokenExpired() {
|
|
481
398
|
try {
|
|
482
|
-
// Note: Internal refresh token logic is now handled by PersApiClient.attemptInternalRefresh()
|
|
483
|
-
// This callback is only called when internal refresh fails or no refresh token is available
|
|
484
|
-
// Try custom expiration handler first
|
|
485
399
|
if (this.config.onTokenExpired) {
|
|
486
400
|
await this.config.onTokenExpired();
|
|
487
401
|
return;
|
|
488
402
|
}
|
|
489
|
-
// Try token provider (Firebase, Auth0, etc.) as fallback
|
|
490
403
|
if (this.config.tokenProvider) {
|
|
491
404
|
const newToken = await this.config.tokenProvider();
|
|
492
405
|
if (newToken) {
|
|
@@ -495,15 +408,12 @@ class DefaultAuthProvider {
|
|
|
495
408
|
return;
|
|
496
409
|
}
|
|
497
410
|
}
|
|
498
|
-
// Final fallback: clear all tokens (logout)
|
|
499
411
|
await this.tokenManager.clearAllTokens();
|
|
500
412
|
}
|
|
501
413
|
catch (error) {
|
|
502
|
-
// On any error, clear tokens to ensure clean state
|
|
503
414
|
await this.tokenManager.clearAllTokens();
|
|
504
415
|
}
|
|
505
416
|
}
|
|
506
|
-
// TokenStorageProvider methods
|
|
507
417
|
async setAccessToken(token) {
|
|
508
418
|
await this.tokenManager.setAccessToken(token);
|
|
509
419
|
}
|
|
@@ -516,7 +426,6 @@ class DefaultAuthProvider {
|
|
|
516
426
|
async clearTokens() {
|
|
517
427
|
await this.tokenManager.clearAllTokens();
|
|
518
428
|
}
|
|
519
|
-
// Utility methods
|
|
520
429
|
async setTokens(accessToken, refreshToken, providerToken) {
|
|
521
430
|
await this.tokenManager.setTokens(accessToken, refreshToken, providerToken);
|
|
522
431
|
}
|
|
@@ -618,39 +527,21 @@ class PersApiError extends Error {
|
|
|
618
527
|
|
|
619
528
|
// packages/pers-sdk/src/core/pers-api-client.ts
|
|
620
529
|
/**
|
|
621
|
-
* PERS API Client -
|
|
622
|
-
*
|
|
623
|
-
* Provides authenticated HTTP client with automatic token management,
|
|
624
|
-
* proactive refresh, and comprehensive error handling.
|
|
530
|
+
* PERS API Client - Platform-agnostic HTTP client with authentication
|
|
625
531
|
*
|
|
626
|
-
* Features:
|
|
627
|
-
* - Automatic token refresh before expiry
|
|
628
|
-
* - Background refresh for optimal performance
|
|
629
|
-
* - Provider token fallback for seamless authentication
|
|
630
|
-
* - Configurable retry and timeout settings
|
|
631
|
-
* - Platform-agnostic design
|
|
532
|
+
* Features: automatic token refresh, background validation, configurable settings
|
|
632
533
|
*
|
|
633
534
|
* @example
|
|
634
535
|
* ```typescript
|
|
635
536
|
* const client = new PersApiClient(httpClient, {
|
|
636
537
|
* environment: 'production',
|
|
637
538
|
* apiProjectKey: 'your-project-key',
|
|
638
|
-
* authProvider: new DefaultAuthProvider(
|
|
639
|
-
* tokenProvider: () => getFirebaseToken()
|
|
640
|
-
* })
|
|
539
|
+
* authProvider: new DefaultAuthProvider()
|
|
641
540
|
* });
|
|
642
541
|
*
|
|
643
|
-
* // Make authenticated requests
|
|
644
542
|
* const data = await client.get('/users/me');
|
|
645
543
|
* ```
|
|
646
544
|
*/
|
|
647
|
-
// Auth constants
|
|
648
|
-
const AUTH_METHODS = {
|
|
649
|
-
GET: 'GET',
|
|
650
|
-
POST: 'POST',
|
|
651
|
-
PUT: 'PUT',
|
|
652
|
-
DELETE: 'DELETE',
|
|
653
|
-
};
|
|
654
545
|
class PersApiClient {
|
|
655
546
|
/**
|
|
656
547
|
* Creates a new PERS API Client instance
|
|
@@ -699,72 +590,36 @@ class PersApiClient {
|
|
|
699
590
|
async attemptInternalRefresh() {
|
|
700
591
|
return this.refreshManager.attemptInternalRefresh();
|
|
701
592
|
}
|
|
702
|
-
/**
|
|
703
|
-
* Get request headers including auth token and project key
|
|
704
|
-
*/
|
|
705
|
-
async getHeaders() {
|
|
706
|
-
const headers = {
|
|
707
|
-
'Content-Type': 'application/json',
|
|
708
|
-
};
|
|
709
|
-
// Add authentication token
|
|
710
|
-
if (this.mergedConfig.authProvider) {
|
|
711
|
-
const token = await this.mergedConfig.authProvider.getToken();
|
|
712
|
-
if (token) {
|
|
713
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
714
|
-
}
|
|
715
|
-
else {
|
|
716
|
-
console.warn('[PersApiClient] No token available from auth provider');
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
else {
|
|
720
|
-
console.warn('[PersApiClient] No auth provider configured');
|
|
721
|
-
}
|
|
722
|
-
// Add project key
|
|
723
|
-
if (this.mergedConfig.authProvider) {
|
|
724
|
-
const projectKey = await this.mergedConfig.authProvider.getProjectKey();
|
|
725
|
-
if (projectKey) {
|
|
726
|
-
headers['x-project-key'] = projectKey;
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
else if (this.mergedConfig.apiProjectKey) {
|
|
730
|
-
// Fallback to config project key if no auth provider
|
|
731
|
-
headers['x-project-key'] = this.mergedConfig.apiProjectKey;
|
|
732
|
-
}
|
|
733
|
-
return headers;
|
|
734
|
-
}
|
|
735
593
|
/**
|
|
736
594
|
* Make a request with proper headers, auth, and error handling
|
|
737
595
|
*/
|
|
738
596
|
async request(method, endpoint, body, options) {
|
|
739
597
|
const { retryCount = 0, responseType = 'json', bypassAuth = false } = options || {};
|
|
740
598
|
const url = `${this.apiRoot}${endpoint}`;
|
|
741
|
-
// Proactive token
|
|
742
|
-
// Non-blocking for optimal performance - request proceeds immediately
|
|
599
|
+
// Proactive token validation for optimal performance
|
|
743
600
|
if (!bypassAuth && this.mergedConfig.authProvider && retryCount === 0) {
|
|
744
601
|
this.ensureValidToken().catch(error => {
|
|
745
|
-
// Log but don't block request - 401 handling will catch any issues
|
|
746
602
|
console.debug('[PersApiClient] Background token validation failed:', error);
|
|
747
603
|
});
|
|
748
604
|
}
|
|
749
605
|
const requestOptions = {
|
|
750
|
-
headers:
|
|
606
|
+
headers: await this.getHeaders(!bypassAuth),
|
|
751
607
|
timeout: this.mergedConfig.timeout,
|
|
752
608
|
responseType
|
|
753
609
|
};
|
|
754
|
-
// const isCSVEndpoint = endpoint.includes('/export/csv');
|
|
755
610
|
try {
|
|
756
611
|
let result;
|
|
757
612
|
switch (method) {
|
|
758
|
-
case
|
|
613
|
+
case 'GET':
|
|
759
614
|
result = await this.httpClient.get(url, requestOptions);
|
|
760
615
|
break;
|
|
761
|
-
case
|
|
616
|
+
case 'POST':
|
|
762
617
|
result = await this.httpClient.post(url, body, requestOptions);
|
|
763
618
|
break;
|
|
764
|
-
case
|
|
619
|
+
case 'PUT':
|
|
765
620
|
result = await this.httpClient.put(url, body, requestOptions);
|
|
766
621
|
break;
|
|
767
|
-
case
|
|
622
|
+
case 'DELETE':
|
|
768
623
|
result = await this.httpClient.delete(url, requestOptions);
|
|
769
624
|
break;
|
|
770
625
|
default:
|
|
@@ -817,46 +672,51 @@ class PersApiClient {
|
|
|
817
672
|
* ```
|
|
818
673
|
*/
|
|
819
674
|
async get(endpoint, responseType) {
|
|
820
|
-
return this.request(
|
|
675
|
+
return this.request('GET', endpoint, undefined, { responseType });
|
|
821
676
|
}
|
|
822
677
|
/**
|
|
823
678
|
* Performs an authenticated POST request
|
|
824
|
-
*
|
|
825
|
-
* @template T - Expected response type
|
|
826
|
-
* @param endpoint - API endpoint path (without base URL)
|
|
827
|
-
* @param body - Request payload data
|
|
828
|
-
* @param options - Request options including auth bypass
|
|
829
|
-
* @returns Promise resolving to typed response data
|
|
830
|
-
*
|
|
831
|
-
* @example
|
|
832
|
-
* ```typescript
|
|
833
|
-
* const user = await client.post<User>('/users', userData);
|
|
834
|
-
* const publicData = await client.post('/public/contact', formData, { bypassAuth: true });
|
|
835
|
-
* ```
|
|
836
679
|
*/
|
|
837
680
|
async post(endpoint, body, options) {
|
|
838
|
-
return this.request(
|
|
681
|
+
return this.request('POST', endpoint, body, options);
|
|
839
682
|
}
|
|
840
683
|
/**
|
|
841
684
|
* Generic PUT request
|
|
842
685
|
*/
|
|
843
686
|
async put(endpoint, body) {
|
|
844
|
-
return this.request(
|
|
687
|
+
return this.request('PUT', endpoint, body);
|
|
845
688
|
}
|
|
846
689
|
/**
|
|
847
690
|
* Generic DELETE request
|
|
848
691
|
*/
|
|
849
692
|
async delete(endpoint) {
|
|
850
|
-
return this.request(
|
|
693
|
+
return this.request('DELETE', endpoint);
|
|
851
694
|
}
|
|
852
695
|
/**
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
696
|
+
* Get request headers with optional auth token and project key
|
|
697
|
+
*
|
|
698
|
+
* @param includeAuth - Whether to include the Authorization header (default: true)
|
|
699
|
+
*/
|
|
700
|
+
async getHeaders(includeAuth = true) {
|
|
856
701
|
const headers = {
|
|
857
702
|
'Content-Type': 'application/json',
|
|
858
703
|
};
|
|
859
|
-
|
|
704
|
+
if (includeAuth) {
|
|
705
|
+
// Add authentication token
|
|
706
|
+
if (this.mergedConfig.authProvider) {
|
|
707
|
+
const token = await this.mergedConfig.authProvider.getToken();
|
|
708
|
+
if (token) {
|
|
709
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
console.warn('[PersApiClient] No token available from auth provider');
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
console.warn('[PersApiClient] No auth provider configured');
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
// Add project key
|
|
860
720
|
if (this.mergedConfig.authProvider) {
|
|
861
721
|
const projectKey = await this.mergedConfig.authProvider.getProjectKey();
|
|
862
722
|
if (projectKey) {
|
|
@@ -869,11 +729,10 @@ class PersApiClient {
|
|
|
869
729
|
return headers;
|
|
870
730
|
}
|
|
871
731
|
// ==========================================
|
|
872
|
-
// INTERNAL AUTH METHODS
|
|
732
|
+
// INTERNAL AUTH METHODS
|
|
873
733
|
// ==========================================
|
|
874
734
|
/**
|
|
875
735
|
* @internal - For AuthManager use only
|
|
876
|
-
* Direct access to auth service for manager layer
|
|
877
736
|
*/
|
|
878
737
|
getAuthService() {
|
|
879
738
|
return this.authService;
|
|
@@ -894,25 +753,21 @@ class PersApiClient {
|
|
|
894
753
|
|
|
895
754
|
/**
|
|
896
755
|
* Environment Detection Utility
|
|
897
|
-
*
|
|
898
|
-
* Detects the runtime environment to handle platform-specific behaviors
|
|
899
|
-
* for bundling and module resolution.
|
|
756
|
+
* Detects runtime environment for platform-specific behaviors
|
|
900
757
|
*/
|
|
901
758
|
/**
|
|
902
759
|
* Detects the current runtime environment
|
|
903
760
|
*/
|
|
904
761
|
function detectEnvironment() {
|
|
762
|
+
const global = globalThis;
|
|
905
763
|
const isNode = typeof process !== 'undefined' &&
|
|
906
|
-
process.versions != null &&
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
typeof globalThis.navigator.product === 'string' &&
|
|
913
|
-
globalThis.navigator.product.toLowerCase() === 'reactnative';
|
|
764
|
+
process.versions?.node != null &&
|
|
765
|
+
typeof global.window === 'undefined';
|
|
766
|
+
const isBrowser = typeof global.window !== 'undefined' &&
|
|
767
|
+
typeof global.document !== 'undefined';
|
|
768
|
+
const isReactNative = typeof global.navigator?.product === 'string' &&
|
|
769
|
+
global.navigator.product.toLowerCase() === 'reactnative';
|
|
914
770
|
const isWeb = isBrowser || isReactNative;
|
|
915
|
-
// Node.js streams: Only native in Node.js, need polyfills or avoidance in web
|
|
916
771
|
const needsNodeStreamPolyfills = isWeb;
|
|
917
772
|
return {
|
|
918
773
|
isNode,
|
|
@@ -927,7 +782,7 @@ function detectEnvironment() {
|
|
|
927
782
|
*/
|
|
928
783
|
const environment = detectEnvironment();
|
|
929
784
|
/**
|
|
930
|
-
* Warns if
|
|
785
|
+
* Warns if environment might have bundling issues
|
|
931
786
|
*/
|
|
932
787
|
function warnIfProblematicEnvironment(feature) {
|
|
933
788
|
if (environment.needsNodeStreamPolyfills) {
|
|
@@ -4430,12 +4285,6 @@ class FileService {
|
|
|
4430
4285
|
return this.fileApi;
|
|
4431
4286
|
}
|
|
4432
4287
|
}
|
|
4433
|
-
/**
|
|
4434
|
-
* Factory function for creating file service
|
|
4435
|
-
*/
|
|
4436
|
-
function createFileSDK(apiClient) {
|
|
4437
|
-
return new FileService(apiClient);
|
|
4438
|
-
}
|
|
4439
4288
|
|
|
4440
4289
|
/**
|
|
4441
4290
|
* File Manager - Clean, high-level interface for file operations
|
|
@@ -4502,7 +4351,7 @@ function createFileSDK(apiClient) {
|
|
|
4502
4351
|
class FileManager {
|
|
4503
4352
|
constructor(apiClient) {
|
|
4504
4353
|
this.apiClient = apiClient;
|
|
4505
|
-
this.
|
|
4354
|
+
this.fileService = new FileService(apiClient);
|
|
4506
4355
|
}
|
|
4507
4356
|
/**
|
|
4508
4357
|
* Get signed URL for file upload
|
|
@@ -4599,7 +4448,7 @@ class FileManager {
|
|
|
4599
4448
|
* ```
|
|
4600
4449
|
*/
|
|
4601
4450
|
async getSignedPutUrl(entityId, entityType, fileExtension) {
|
|
4602
|
-
return this.
|
|
4451
|
+
return this.fileService.getSignedPutUrl(entityId, entityType, fileExtension);
|
|
4603
4452
|
}
|
|
4604
4453
|
/**
|
|
4605
4454
|
* Get signed URL for file access
|
|
@@ -4691,7 +4540,7 @@ class FileManager {
|
|
|
4691
4540
|
* ```
|
|
4692
4541
|
*/
|
|
4693
4542
|
async getSignedGetUrl(entityId, entityType, expireSeconds) {
|
|
4694
|
-
return this.
|
|
4543
|
+
return this.fileService.getSignedGetUrl(entityId, entityType, expireSeconds);
|
|
4695
4544
|
}
|
|
4696
4545
|
/**
|
|
4697
4546
|
* Get signed URL for any file operation
|
|
@@ -4756,7 +4605,7 @@ class FileManager {
|
|
|
4756
4605
|
* ```
|
|
4757
4606
|
*/
|
|
4758
4607
|
async getSignedUrl(request) {
|
|
4759
|
-
return this.
|
|
4608
|
+
return this.fileService.getSignedUrl(request);
|
|
4760
4609
|
}
|
|
4761
4610
|
/**
|
|
4762
4611
|
* Optimize media file
|
|
@@ -4870,10 +4719,10 @@ class FileManager {
|
|
|
4870
4719
|
* ```
|
|
4871
4720
|
*/
|
|
4872
4721
|
async optimizeMedia(url, width, height) {
|
|
4873
|
-
return this.
|
|
4722
|
+
return this.fileService.optimizeMedia(url, width, height);
|
|
4874
4723
|
}
|
|
4875
4724
|
/**
|
|
4876
|
-
* Get the full file
|
|
4725
|
+
* Get the full file service for advanced operations
|
|
4877
4726
|
*
|
|
4878
4727
|
* Provides access to the complete FileService instance for advanced file
|
|
4879
4728
|
* operations, batch processing, storage analytics, and operations not
|
|
@@ -4883,20 +4732,20 @@ class FileManager {
|
|
|
4883
4732
|
*
|
|
4884
4733
|
* @example Advanced Operations
|
|
4885
4734
|
* ```typescript
|
|
4886
|
-
* const
|
|
4735
|
+
* const fileService = sdk.files.getFileService();
|
|
4887
4736
|
*
|
|
4888
4737
|
* // Access storage analytics
|
|
4889
|
-
* const storageStats = await
|
|
4738
|
+
* const storageStats = await fileService.getStorageAnalytics();
|
|
4890
4739
|
* console.log('Storage usage:', storageStats.totalSize);
|
|
4891
4740
|
*
|
|
4892
4741
|
* // Access batch file operations
|
|
4893
|
-
* const batchResult = await
|
|
4742
|
+
* const batchResult = await fileService.batchDeleteFiles(['file1', 'file2', 'file3']);
|
|
4894
4743
|
*
|
|
4895
4744
|
* // Access file metadata management
|
|
4896
|
-
* const metadata = await
|
|
4745
|
+
* const metadata = await fileService.getFileMetadata('entity-123', 'campaign');
|
|
4897
4746
|
*
|
|
4898
4747
|
* // Access advanced optimization options
|
|
4899
|
-
* const advancedOptimization = await
|
|
4748
|
+
* const advancedOptimization = await fileService.optimizeMediaAdvanced(url, {
|
|
4900
4749
|
* width: 400,
|
|
4901
4750
|
* height: 300,
|
|
4902
4751
|
* quality: 85,
|
|
@@ -4906,14 +4755,14 @@ class FileManager {
|
|
|
4906
4755
|
* });
|
|
4907
4756
|
*
|
|
4908
4757
|
* // Access file upload monitoring
|
|
4909
|
-
* const uploadProgress =
|
|
4758
|
+
* const uploadProgress = fileService.monitorUploadProgress('upload-session-123');
|
|
4910
4759
|
* uploadProgress.on('progress', (percent) => {
|
|
4911
4760
|
* console.log(`Upload: ${percent}%`);
|
|
4912
4761
|
* });
|
|
4913
4762
|
* ```
|
|
4914
4763
|
*/
|
|
4915
|
-
|
|
4916
|
-
return this.
|
|
4764
|
+
getFileService() {
|
|
4765
|
+
return this.fileService;
|
|
4917
4766
|
}
|
|
4918
4767
|
}
|
|
4919
4768
|
|
|
@@ -5813,5 +5662,5 @@ function createPersSDK(httpClient, config) {
|
|
|
5813
5662
|
return new PersSDK(httpClient, config);
|
|
5814
5663
|
}
|
|
5815
5664
|
|
|
5816
|
-
export { AuthTokenManager as A, BusinessManager as B, CampaignManager as C, DefaultAuthProvider as D, FileManager as F, LocalStorageTokenStorage as L, MemoryTokenStorage as M, PersSDK as P, RedemptionManager as R, TokenManager as T, UserManager as U, Web3Manager as W, PersApiClient as a, DEFAULT_PERS_CONFIG as b, createPersSDK as c, buildApiRoot as d, detectEnvironment as e, environment as f, AuthApi as g, AuthService as h, AuthManager as i, UserStatusManager as j, TransactionManager as k, PurchaseManager as l, mergeWithDefaults as m, TenantManager as n, AnalyticsManager as o, DonationManager as p, FileApi as q, FileService as r,
|
|
5817
|
-
//# sourceMappingURL=pers-sdk-
|
|
5665
|
+
export { AuthTokenManager as A, BusinessManager as B, CampaignManager as C, DefaultAuthProvider as D, FileManager as F, LocalStorageTokenStorage as L, MemoryTokenStorage as M, PersSDK as P, RedemptionManager as R, TokenManager as T, UserManager as U, Web3Manager as W, PersApiClient as a, DEFAULT_PERS_CONFIG as b, createPersSDK as c, buildApiRoot as d, detectEnvironment as e, environment as f, AuthApi as g, AuthService as h, AuthManager as i, UserStatusManager as j, TransactionManager as k, PurchaseManager as l, mergeWithDefaults as m, TenantManager as n, AnalyticsManager as o, DonationManager as p, FileApi as q, FileService as r, warnIfProblematicEnvironment as w };
|
|
5666
|
+
//# sourceMappingURL=pers-sdk-DOuNyWFC.js.map
|