@explorins/pers-sdk 2.1.33 → 2.1.39
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 +7 -0
- package/dist/business/api/business-api.d.ts +10 -3
- package/dist/business/api/business-api.d.ts.map +1 -1
- package/dist/business/index.d.ts +1 -1
- package/dist/business/index.d.ts.map +1 -1
- package/dist/business/services/business-service.d.ts +2 -2
- package/dist/business/services/business-service.d.ts.map +1 -1
- package/dist/business.cjs +1 -1
- package/dist/business.js +1 -1
- package/dist/chunks/{base-token-service-BiSXWqOy.js → base-token-service-N1gwRD8N.js} +2 -2
- package/dist/chunks/{base-token-service-BiSXWqOy.js.map → base-token-service-N1gwRD8N.js.map} +1 -1
- package/dist/chunks/{base-token-service-CReAW_nz.cjs → base-token-service-W7TU23qU.cjs} +2 -2
- package/dist/chunks/{base-token-service-CReAW_nz.cjs.map → base-token-service-W7TU23qU.cjs.map} +1 -1
- package/dist/chunks/{business-membership-service-DXLG5fP9.cjs → business-membership-service-Dkb780NX.cjs} +38 -16
- package/dist/chunks/business-membership-service-Dkb780NX.cjs.map +1 -0
- package/dist/chunks/{business-membership-service-IyY5CkL0.js → business-membership-service-NLoqoFpG.js} +38 -16
- package/dist/chunks/business-membership-service-NLoqoFpG.js.map +1 -0
- package/dist/chunks/{index-CgbzGLYT.js → index--OssIds0.js} +14 -11
- package/dist/chunks/index--OssIds0.js.map +1 -0
- package/dist/chunks/{index-B_n8XiMt.cjs → index-C4K-jkRO.cjs} +13 -10
- package/dist/chunks/index-C4K-jkRO.cjs.map +1 -0
- package/dist/chunks/{pers-sdk-CySmOdzr.js → pers-sdk-CNIfzWYX.js} +298 -62
- package/dist/chunks/pers-sdk-CNIfzWYX.js.map +1 -0
- package/dist/chunks/{pers-sdk-DgsYyo1X.cjs → pers-sdk-Cwlrl8jb.cjs} +298 -62
- package/dist/chunks/pers-sdk-Cwlrl8jb.cjs.map +1 -0
- package/dist/chunks/{redemption-service-CVD2PzBO.cjs → redemption-service-KamEndzB.cjs} +15 -1
- package/dist/chunks/{redemption-service-CVD2PzBO.cjs.map → redemption-service-KamEndzB.cjs.map} +1 -1
- package/dist/chunks/{redemption-service-czBfCP-3.js → redemption-service-w0GMdF0m.js} +15 -1
- package/dist/chunks/{redemption-service-czBfCP-3.js.map → redemption-service-w0GMdF0m.js.map} +1 -1
- package/dist/chunks/{tenant-manager-DeEuSlk7.cjs → tenant-manager-DR5eSEJw.cjs} +2 -2
- package/dist/chunks/{tenant-manager-DeEuSlk7.cjs.map → tenant-manager-DR5eSEJw.cjs.map} +1 -1
- package/dist/chunks/{tenant-manager-BQP25Alv.js → tenant-manager-xmYKBFGu.js} +2 -2
- package/dist/chunks/{tenant-manager-BQP25Alv.js.map → tenant-manager-xmYKBFGu.js.map} +1 -1
- package/dist/chunks/{token-service-BxEO5YVN.js → token-service-BcuDj292.js} +153 -2
- package/dist/chunks/token-service-BcuDj292.js.map +1 -0
- package/dist/chunks/{token-service-C1xe11OX.cjs → token-service-CnnrCOsg.cjs} +153 -2
- package/dist/chunks/token-service-CnnrCOsg.cjs.map +1 -0
- package/dist/chunks/{web3-chain-service-BLrjcBTb.js → web3-chain-service-BWRmwmmJ.js} +2 -2
- package/dist/chunks/{web3-chain-service-BLrjcBTb.js.map → web3-chain-service-BWRmwmmJ.js.map} +1 -1
- package/dist/chunks/{web3-chain-service-Bilgr4M8.cjs → web3-chain-service-D6tBL0F7.cjs} +2 -2
- package/dist/chunks/{web3-chain-service-Bilgr4M8.cjs.map → web3-chain-service-D6tBL0F7.cjs.map} +1 -1
- package/dist/chunks/{web3-manager-DbfqhJF4.cjs → web3-manager-C-JflQ86.cjs} +4 -4
- package/dist/chunks/{web3-manager-DbfqhJF4.cjs.map → web3-manager-C-JflQ86.cjs.map} +1 -1
- package/dist/chunks/{web3-manager-BSvr7wJ7.js → web3-manager-Dvcq4xmn.js} +4 -4
- package/dist/chunks/{web3-manager-BSvr7wJ7.js.map → web3-manager-Dvcq4xmn.js.map} +1 -1
- package/dist/core/auth/dpop/dpop-manager.d.ts +0 -1
- package/dist/core/auth/dpop/dpop-manager.d.ts.map +1 -1
- package/dist/core/auth/refresh-manager.d.ts +12 -2
- package/dist/core/auth/refresh-manager.d.ts.map +1 -1
- package/dist/core/auth/services/auth-service.d.ts +10 -3
- package/dist/core/auth/services/auth-service.d.ts.map +1 -1
- package/dist/core/errors/index.d.ts +6 -6
- package/dist/core/errors/index.d.ts.map +1 -1
- package/dist/core/events/event-types.d.ts +5 -1
- package/dist/core/events/event-types.d.ts.map +1 -1
- package/dist/core/pers-api-client.d.ts.map +1 -1
- package/dist/core/utils/jwt.function.d.ts +3 -12
- package/dist/core/utils/jwt.function.d.ts.map +1 -1
- package/dist/core.cjs +6 -6
- package/dist/core.js +6 -6
- package/dist/index.cjs +7 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/managers/redemption-manager.d.ts +58 -1
- package/dist/managers/redemption-manager.d.ts.map +1 -1
- package/dist/managers/token-manager.d.ts +121 -2
- package/dist/managers/token-manager.d.ts.map +1 -1
- package/dist/node.cjs +6 -6
- package/dist/node.js +6 -6
- package/dist/package.json +2 -2
- package/dist/redemption/services/redemption-service.d.ts +10 -0
- package/dist/redemption/services/redemption-service.d.ts.map +1 -1
- package/dist/redemption.cjs +1 -1
- package/dist/redemption.js +1 -1
- package/dist/token/api/token-api.d.ts +79 -1
- package/dist/token/api/token-api.d.ts.map +1 -1
- package/dist/token/index.d.ts +1 -1
- package/dist/token/index.d.ts.map +1 -1
- package/dist/token/services/token-service.d.ts +61 -1
- package/dist/token/services/token-service.d.ts.map +1 -1
- package/dist/token.cjs +2 -2
- package/dist/token.js +2 -2
- package/dist/trigger-source/api/trigger-source-api.d.ts +9 -10
- package/dist/trigger-source/api/trigger-source-api.d.ts.map +1 -1
- package/dist/trigger-source/index.d.ts +1 -0
- package/dist/trigger-source/index.d.ts.map +1 -1
- package/dist/trigger-source/models/index.d.ts +5 -13
- package/dist/trigger-source/models/index.d.ts.map +1 -1
- package/dist/trigger-source/services/trigger-source-service.d.ts +3 -11
- package/dist/trigger-source/services/trigger-source-service.d.ts.map +1 -1
- package/dist/trigger-source.cjs +20 -1
- package/dist/trigger-source.cjs.map +1 -1
- package/dist/trigger-source.js +20 -1
- package/dist/trigger-source.js.map +1 -1
- package/dist/web3-chain.cjs +2 -2
- package/dist/web3-chain.js +2 -2
- package/dist/web3-manager.cjs +4 -4
- package/dist/web3-manager.js +4 -4
- package/dist/web3.cjs +4 -4
- package/dist/web3.js +4 -4
- package/package.json +2 -2
- package/dist/chunks/business-membership-service-DXLG5fP9.cjs.map +0 -1
- package/dist/chunks/business-membership-service-IyY5CkL0.js.map +0 -1
- package/dist/chunks/index-B_n8XiMt.cjs.map +0 -1
- package/dist/chunks/index-CgbzGLYT.js.map +0 -1
- package/dist/chunks/pers-sdk-CySmOdzr.js.map +0 -1
- package/dist/chunks/pers-sdk-DgsYyo1X.cjs.map +0 -1
- package/dist/chunks/token-service-BxEO5YVN.js.map +0 -1
- package/dist/chunks/token-service-C1xe11OX.cjs.map +0 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var persShared = require('@explorins/pers-shared');
|
|
4
|
-
var index = require('./index-
|
|
4
|
+
var index = require('./index-C4K-jkRO.cjs');
|
|
5
5
|
var user = require('../user.cjs');
|
|
6
6
|
var userStatus = require('../user-status.cjs');
|
|
7
|
-
var tokenService = require('./token-service-
|
|
8
|
-
var businessMembershipService = require('./business-membership-service-
|
|
7
|
+
var tokenService = require('./token-service-CnnrCOsg.cjs');
|
|
8
|
+
var businessMembershipService = require('./business-membership-service-Dkb780NX.cjs');
|
|
9
9
|
var campaign = require('../campaign.cjs');
|
|
10
|
-
var redemptionService = require('./redemption-service-
|
|
10
|
+
var redemptionService = require('./redemption-service-KamEndzB.cjs');
|
|
11
11
|
var transactionRequest_builder = require('./transaction-request.builder-D8pIzjYD.cjs');
|
|
12
12
|
var paymentService = require('./payment-service-Bkw7ZXev.cjs');
|
|
13
|
-
var tenantManager = require('./tenant-manager-
|
|
13
|
+
var tenantManager = require('./tenant-manager-DR5eSEJw.cjs');
|
|
14
14
|
var paginationUtils = require('./pagination-utils-B2jRHMSO.cjs');
|
|
15
15
|
var analyticsService = require('./analytics-service-CRs9cpkg.cjs');
|
|
16
16
|
var donation = require('../donation.cjs');
|
|
@@ -416,13 +416,17 @@ class AuthService {
|
|
|
416
416
|
* Returns true for:
|
|
417
417
|
* - Known fatal error codes (REFRESH_TOKEN_EXPIRED, TOKEN_REVOKED, etc.)
|
|
418
418
|
* - Fatal error codes in error messages (wrapped errors)
|
|
419
|
-
* - 401/403 HTTP status codes
|
|
420
419
|
*
|
|
421
|
-
* Returns false for (retryable
|
|
420
|
+
* Returns false for (retryable/recoverable):
|
|
422
421
|
* - Network errors
|
|
423
422
|
* - Timeouts
|
|
424
423
|
* - 5xx server errors
|
|
425
424
|
* - TOKEN_EXPIRED (normal refresh trigger)
|
|
425
|
+
* - Raw 401/403 without fatal code (should try refresh first)
|
|
426
|
+
*
|
|
427
|
+
* NOTE: We intentionally DO NOT treat raw 401/403 status as fatal.
|
|
428
|
+
* The HTTP client handles 401 by attempting token refresh first.
|
|
429
|
+
* Only if refresh fails WITH a fatal code do we logout.
|
|
426
430
|
*/
|
|
427
431
|
isDefinitiveAuthFailure(error) {
|
|
428
432
|
if (!error)
|
|
@@ -437,11 +441,12 @@ class AuthService {
|
|
|
437
441
|
if (isFatalAuthErrorInMessage(errorMessage)) {
|
|
438
442
|
return true;
|
|
439
443
|
}
|
|
440
|
-
//
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
444
|
+
// NOTE: We intentionally DO NOT check HTTP status codes here.
|
|
445
|
+
// A raw 401/403 without a fatal error code should trigger a refresh attempt,
|
|
446
|
+
// not an immediate logout. The HTTP client (pers-api-client.ts) handles this:
|
|
447
|
+
// 1. 401 received → try refresh token
|
|
448
|
+
// 2. Refresh succeeds → retry original request
|
|
449
|
+
// 3. Refresh fails with fatal CODE → then logout
|
|
445
450
|
// Everything else is considered retryable
|
|
446
451
|
return false;
|
|
447
452
|
}
|
|
@@ -499,6 +504,9 @@ class AuthService {
|
|
|
499
504
|
* Extracts context (tenantId/businessId) from the current refresh token to ensure
|
|
500
505
|
* the recovered session maintains the same context.
|
|
501
506
|
*
|
|
507
|
+
* This is a PUBLIC method that can be called by TokenRefreshManager when internal
|
|
508
|
+
* refresh fails, to try external (provider token) recovery before giving up.
|
|
509
|
+
*
|
|
502
510
|
* @returns true if session was successfully recovered
|
|
503
511
|
*/
|
|
504
512
|
async attemptProviderTokenRecovery() {
|
|
@@ -525,12 +533,17 @@ class AuthService {
|
|
|
525
533
|
const contextClaims = refreshToken ? index.decodeJwtPayload(refreshToken) : null;
|
|
526
534
|
// Re-authenticate using provider token based on auth type
|
|
527
535
|
// Pass the context from the previous session to avoid MULTIPLE_CONTEXT_SELECTION_REQUIRED
|
|
536
|
+
// Note: In AuthJWTPayload, when accountType=BUSINESS, sub contains the businessId
|
|
528
537
|
switch (authType) {
|
|
529
538
|
case persShared.AccountOwnerType.USER:
|
|
530
539
|
await this.loginUser(providerToken);
|
|
531
540
|
break;
|
|
532
541
|
case persShared.AccountOwnerType.BUSINESS:
|
|
533
|
-
|
|
542
|
+
// For BUSINESS auth, sub contains the businessId when accountType is BUSINESS
|
|
543
|
+
const businessId = contextClaims?.accountType === persShared.AccountOwnerType.BUSINESS
|
|
544
|
+
? contextClaims.sub
|
|
545
|
+
: undefined;
|
|
546
|
+
await this.loginBusiness(providerToken, businessId ? { businessId } : undefined);
|
|
534
547
|
break;
|
|
535
548
|
case persShared.AccountOwnerType.TENANT:
|
|
536
549
|
await this.loginTenantAdmin(providerToken, contextClaims?.tenantId ? { tenantId: contextClaims.tenantId } : undefined);
|
|
@@ -646,6 +659,8 @@ class TokenRefreshManager {
|
|
|
646
659
|
// Retry configuration for transient failures
|
|
647
660
|
this.MAX_RETRY_ATTEMPTS = 3;
|
|
648
661
|
this.RETRY_DELAY_MS = 1000;
|
|
662
|
+
// Active refresh promise for deduplication
|
|
663
|
+
this.activeRefreshPromise = null;
|
|
649
664
|
}
|
|
650
665
|
/**
|
|
651
666
|
* Ensures the access token is valid, refreshing if needed.
|
|
@@ -746,11 +761,27 @@ class TokenRefreshManager {
|
|
|
746
761
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
747
762
|
}
|
|
748
763
|
/**
|
|
749
|
-
*
|
|
764
|
+
* Attempt token refresh: internal first, then provider token fallback.
|
|
765
|
+
* DEDUPLICATES concurrent calls - all callers share the same promise.
|
|
750
766
|
*/
|
|
751
767
|
async attemptInternalRefresh() {
|
|
752
|
-
|
|
753
|
-
|
|
768
|
+
if (this.activeRefreshPromise) {
|
|
769
|
+
return this.activeRefreshPromise;
|
|
770
|
+
}
|
|
771
|
+
this.activeRefreshPromise = (async () => {
|
|
772
|
+
const result = await this.attemptRefreshWithRetry();
|
|
773
|
+
if (result.success)
|
|
774
|
+
return result;
|
|
775
|
+
// Internal failed - try provider token recovery
|
|
776
|
+
const recovered = await this.authService.attemptProviderTokenRecovery();
|
|
777
|
+
return recovered ? { success: true, retryable: false } : result;
|
|
778
|
+
})();
|
|
779
|
+
try {
|
|
780
|
+
return await this.activeRefreshPromise;
|
|
781
|
+
}
|
|
782
|
+
finally {
|
|
783
|
+
this.activeRefreshPromise = null;
|
|
784
|
+
}
|
|
754
785
|
}
|
|
755
786
|
}
|
|
756
787
|
|
|
@@ -1298,17 +1329,16 @@ class DPoPManager {
|
|
|
1298
1329
|
* Generate a short fingerprint of the public key for debugging
|
|
1299
1330
|
* This helps identify if the same key is being used across operations
|
|
1300
1331
|
*/
|
|
1301
|
-
getPublicKeyFingerprint(publicKey) {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
}
|
|
1332
|
+
/* private getPublicKeyFingerprint(publicKey: JsonWebKey): string {
|
|
1333
|
+
try {
|
|
1334
|
+
// Use the 'x' coordinate of the EC key as a fingerprint
|
|
1335
|
+
const x = publicKey.x || '';
|
|
1336
|
+
const y = publicKey.y || '';
|
|
1337
|
+
return `${x.substring(0, 8)}...${y.substring(0, 4)}`;
|
|
1338
|
+
} catch {
|
|
1339
|
+
return 'unknown';
|
|
1340
|
+
}
|
|
1341
|
+
} */
|
|
1312
1342
|
/**
|
|
1313
1343
|
* Clears DPoP keys (e.g. on logout)
|
|
1314
1344
|
*/
|
|
@@ -1557,7 +1587,7 @@ class DefaultAuthProvider {
|
|
|
1557
1587
|
/** SDK package name */
|
|
1558
1588
|
const SDK_NAME = "@explorins/pers-sdk";
|
|
1559
1589
|
/** SDK version - injected from package.json at build time */
|
|
1560
|
-
const SDK_VERSION = "2.1.
|
|
1590
|
+
const SDK_VERSION = "2.1.39";
|
|
1561
1591
|
/** Full SDK identifier for headers */
|
|
1562
1592
|
const SDK_USER_AGENT = `${SDK_NAME}/${SDK_VERSION}`;
|
|
1563
1593
|
|
|
@@ -1667,12 +1697,16 @@ class PersApiClient {
|
|
|
1667
1697
|
}
|
|
1668
1698
|
const { retryCount = 0, responseType = 'json', bypassAuth = false } = options || {};
|
|
1669
1699
|
const url = `${this.apiRoot}${endpoint}`;
|
|
1670
|
-
//
|
|
1700
|
+
// TOKEN VALIDATION: Ensure token is valid before request
|
|
1701
|
+
// This blocks the request until token validation completes - prevents 401s from expired tokens
|
|
1671
1702
|
if (!bypassAuth && this.mergedConfig.authProvider && retryCount === 0) {
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1703
|
+
try {
|
|
1704
|
+
await this.ensureValidToken();
|
|
1705
|
+
}
|
|
1706
|
+
catch (error) {
|
|
1707
|
+
console.debug('[PersApiClient] Token validation failed:', error);
|
|
1708
|
+
// Continue with request - it will fail with 401 and trigger retry logic
|
|
1709
|
+
}
|
|
1676
1710
|
}
|
|
1677
1711
|
const requestOptions = {
|
|
1678
1712
|
headers: await this.getHeaders(!bypassAuth, method, url),
|
|
@@ -1700,49 +1734,63 @@ class PersApiClient {
|
|
|
1700
1734
|
return result;
|
|
1701
1735
|
}
|
|
1702
1736
|
catch (error) {
|
|
1703
|
-
// Error handling - proactive token refresh should prevent most 401s
|
|
1704
1737
|
const status = index.ErrorUtils.getStatus(error);
|
|
1705
1738
|
const errorMessage = index.ErrorUtils.getMessage(error);
|
|
1706
|
-
// Handle 401 errors
|
|
1739
|
+
// Handle 401 Unauthorized errors
|
|
1707
1740
|
if (status === 401) {
|
|
1708
1741
|
const backendError = index.ErrorUtils.extractBackendErrorDetails(error);
|
|
1709
|
-
//
|
|
1710
|
-
//
|
|
1711
|
-
//
|
|
1742
|
+
// ===========================================
|
|
1743
|
+
// FATAL AUTH ERRORS → Immediate logout
|
|
1744
|
+
// ===========================================
|
|
1745
|
+
// Fatal codes: REFRESH_TOKEN_EXPIRED, TOKEN_REVOKED, INVALID_REFRESH_TOKEN, etc.
|
|
1712
1746
|
if (this.authService.isFatalAuthError(backendError.code)) {
|
|
1713
|
-
|
|
1747
|
+
console.warn(`[PersApiClient] Fatal auth error: ${backendError.code}`);
|
|
1714
1748
|
await this.authService.handleAuthFailure();
|
|
1715
1749
|
this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
|
|
1716
1750
|
throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
|
|
1717
1751
|
}
|
|
1718
|
-
//
|
|
1752
|
+
// ===========================================
|
|
1753
|
+
// REFRESH REQUEST FAILED → Logout (prevents infinite loop)
|
|
1754
|
+
// ===========================================
|
|
1719
1755
|
if (options?.isRefreshRequest) {
|
|
1720
|
-
|
|
1756
|
+
console.warn('[PersApiClient] Refresh request itself failed with 401');
|
|
1721
1757
|
await this.authService.handleAuthFailure();
|
|
1722
1758
|
this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
|
|
1723
1759
|
throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
|
|
1724
1760
|
}
|
|
1725
|
-
//
|
|
1761
|
+
// ===========================================
|
|
1762
|
+
// RETRYABLE 401 (TOKEN_EXPIRED) → Try refresh, then retry
|
|
1763
|
+
// ===========================================
|
|
1726
1764
|
if (retryCount === 0 && this.mergedConfig.authProvider) {
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1765
|
+
const refreshResult = await this.refreshManager.attemptInternalRefresh();
|
|
1766
|
+
if (refreshResult.success) {
|
|
1767
|
+
// Refresh succeeded → retry request with new token
|
|
1768
|
+
this._events?.emitSuccess({
|
|
1769
|
+
type: 'token_refreshed',
|
|
1770
|
+
domain: 'authentication',
|
|
1771
|
+
userMessage: 'Authentication token refreshed',
|
|
1772
|
+
});
|
|
1773
|
+
return await this.request(method, endpoint, body, { ...options, retryCount: 1 });
|
|
1774
|
+
}
|
|
1775
|
+
// Refresh failed - check if it's a definitive failure
|
|
1776
|
+
if (!refreshResult.retryable) {
|
|
1777
|
+
// Non-retryable failure (e.g., refresh token expired) → logout
|
|
1778
|
+
console.warn('[PersApiClient] Refresh failed with non-retryable error, logging out');
|
|
1779
|
+
await this.authService.handleAuthFailure();
|
|
1739
1780
|
}
|
|
1740
|
-
|
|
1741
|
-
//
|
|
1781
|
+
else {
|
|
1782
|
+
// Retryable failure (network error, etc.) → DON'T logout, let app retry later
|
|
1783
|
+
console.warn('[PersApiClient] Refresh failed with retryable error, NOT logging out');
|
|
1742
1784
|
}
|
|
1785
|
+
this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
|
|
1786
|
+
throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
|
|
1743
1787
|
}
|
|
1744
|
-
//
|
|
1745
|
-
|
|
1788
|
+
// ===========================================
|
|
1789
|
+
// RETRY FAILED (retryCount > 0) → Something wrong, but DON'T logout
|
|
1790
|
+
// ===========================================
|
|
1791
|
+
// We already refreshed successfully, but retry still got 401
|
|
1792
|
+
// This is unexpected - don't logout, let app investigate
|
|
1793
|
+
console.warn('[PersApiClient] Retry with new token still got 401 - not logging out');
|
|
1746
1794
|
this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
|
|
1747
1795
|
throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
|
|
1748
1796
|
}
|
|
@@ -1768,9 +1816,9 @@ class PersApiClient {
|
|
|
1768
1816
|
}); */
|
|
1769
1817
|
this._events?.emitError({
|
|
1770
1818
|
domain: errorDetails.domain || 'external',
|
|
1771
|
-
type:
|
|
1772
|
-
userMessage: errorDetails.message || errorMessage,
|
|
1773
|
-
code: errorDetails.code,
|
|
1819
|
+
type: 'api_error', // Event type discriminator (fixed value)
|
|
1820
|
+
userMessage: errorDetails.message || errorMessage,
|
|
1821
|
+
code: errorDetails.code, // Actual error code from backend
|
|
1774
1822
|
details: {
|
|
1775
1823
|
endpoint,
|
|
1776
1824
|
method,
|
|
@@ -3406,6 +3454,107 @@ class TokenManager {
|
|
|
3406
3454
|
async getTokenByContract(contractAddress, contractTokenId = null) {
|
|
3407
3455
|
return this.tokenService.getTokenByContractAddress(contractAddress, contractTokenId);
|
|
3408
3456
|
}
|
|
3457
|
+
/**
|
|
3458
|
+
* Get all token metadata with filtering, pagination, and include relations
|
|
3459
|
+
*
|
|
3460
|
+
* Retrieves token metadata (rewards/stamps) with server-side filtering, pagination,
|
|
3461
|
+
* and optional include relations for additional data.
|
|
3462
|
+
* Useful for displaying rewards (ERC1155) or stamps (ERC721) in admin tables.
|
|
3463
|
+
* Non-admin users always get active metadata only.
|
|
3464
|
+
*
|
|
3465
|
+
* @param options - Filter, pagination, and include options
|
|
3466
|
+
* @returns Promise resolving to paginated token metadata
|
|
3467
|
+
*
|
|
3468
|
+
* @example Get paginated rewards with counts
|
|
3469
|
+
* ```typescript
|
|
3470
|
+
* const rewards = await sdk.tokens.getTokenMetadata({
|
|
3471
|
+
* tokenType: 'ERC1155',
|
|
3472
|
+
* active: true,
|
|
3473
|
+
* page: 1,
|
|
3474
|
+
* limit: 10,
|
|
3475
|
+
* sortBy: 'name',
|
|
3476
|
+
* sortOrder: 'ASC',
|
|
3477
|
+
* include: ['mintCount', 'burnCount', 'token']
|
|
3478
|
+
* });
|
|
3479
|
+
*
|
|
3480
|
+
* rewards.data.forEach(r => {
|
|
3481
|
+
* console.log(`${r.name}: ${r.mintCount} minted, ${r.burnCount} burned`);
|
|
3482
|
+
* console.log(`Contract: ${r.included?.token?.contractAddress}`);
|
|
3483
|
+
* });
|
|
3484
|
+
* ```
|
|
3485
|
+
*
|
|
3486
|
+
* @example Get stamps with owner business
|
|
3487
|
+
* ```typescript
|
|
3488
|
+
* const stamps = await sdk.tokens.getTokenMetadata({
|
|
3489
|
+
* tokenType: 'ERC721',
|
|
3490
|
+
* search: 'gold',
|
|
3491
|
+
* include: ['ownerBusiness', 'token']
|
|
3492
|
+
* });
|
|
3493
|
+
*
|
|
3494
|
+
* stamps.data.forEach(s => {
|
|
3495
|
+
* console.log(`${s.name} owned by ${s.included?.ownerBusiness?.displayName}`);
|
|
3496
|
+
* });
|
|
3497
|
+
* ```
|
|
3498
|
+
*/
|
|
3499
|
+
async getTokenMetadata(options) {
|
|
3500
|
+
return this.tokenService.getTokenMetadata(options);
|
|
3501
|
+
}
|
|
3502
|
+
/**
|
|
3503
|
+
* Get rewards (ERC1155 token metadata) with filtering, pagination, and include relations
|
|
3504
|
+
*
|
|
3505
|
+
* Convenience method for fetching reward metadata. Rewards are ERC1155 tokens
|
|
3506
|
+
* that represent collectible items, vouchers, or other redeemable rewards.
|
|
3507
|
+
*
|
|
3508
|
+
* @param options - Filter, pagination, and include options (tokenType is set automatically)
|
|
3509
|
+
* @returns Promise resolving to paginated reward metadata
|
|
3510
|
+
*
|
|
3511
|
+
* @example Get active rewards with mint counts
|
|
3512
|
+
* ```typescript
|
|
3513
|
+
* const rewards = await sdk.tokens.getRewards({
|
|
3514
|
+
* active: true,
|
|
3515
|
+
* limit: 10,
|
|
3516
|
+
* include: ['mintCount', 'burnCount', 'token', 'ownerBusiness']
|
|
3517
|
+
* });
|
|
3518
|
+
*
|
|
3519
|
+
* rewards.data.forEach(r => {
|
|
3520
|
+
* console.log(`${r.name}: ${r.mintCount ?? 0} minted`);
|
|
3521
|
+
* if (r.included?.token) {
|
|
3522
|
+
* console.log(` Chain: ${r.included.token.chainId}, Contract: ${r.included.token.contractAddress}`);
|
|
3523
|
+
* }
|
|
3524
|
+
* });
|
|
3525
|
+
* ```
|
|
3526
|
+
*/
|
|
3527
|
+
async getRewards(options) {
|
|
3528
|
+
return this.tokenService.getRewards(options);
|
|
3529
|
+
}
|
|
3530
|
+
/**
|
|
3531
|
+
* Get stamps (ERC721 token metadata) with filtering, pagination, and include relations
|
|
3532
|
+
*
|
|
3533
|
+
* Convenience method for fetching stamp metadata. Stamps are ERC721 tokens
|
|
3534
|
+
* that represent achievements, badges, or collectible status markers.
|
|
3535
|
+
*
|
|
3536
|
+
* @param options - Filter, pagination, and include options (tokenType is set automatically)
|
|
3537
|
+
* @returns Promise resolving to paginated stamp metadata
|
|
3538
|
+
*
|
|
3539
|
+
* @example Get active stamps with all includes
|
|
3540
|
+
* ```typescript
|
|
3541
|
+
* const stamps = await sdk.tokens.getStamps({
|
|
3542
|
+
* active: true,
|
|
3543
|
+
* limit: 10,
|
|
3544
|
+
* include: ['mintCount', 'burnCount', 'token', 'ownerBusiness']
|
|
3545
|
+
* });
|
|
3546
|
+
*
|
|
3547
|
+
* stamps.data.forEach(s => {
|
|
3548
|
+
* console.log(`${s.name}: ${s.mintCount ?? 0} minted`);
|
|
3549
|
+
* if (s.included?.ownerBusiness) {
|
|
3550
|
+
* console.log(` Owner: ${s.included.ownerBusiness.displayName}`);
|
|
3551
|
+
* }
|
|
3552
|
+
* });
|
|
3553
|
+
* ```
|
|
3554
|
+
*/
|
|
3555
|
+
async getStamps(options) {
|
|
3556
|
+
return this.tokenService.getStamps(options);
|
|
3557
|
+
}
|
|
3409
3558
|
/**
|
|
3410
3559
|
* Admin: Create new token
|
|
3411
3560
|
*
|
|
@@ -3497,6 +3646,32 @@ class TokenManager {
|
|
|
3497
3646
|
async toggleTokenActive(tokenId) {
|
|
3498
3647
|
return this.tokenService.toggleTokenActive(tokenId);
|
|
3499
3648
|
}
|
|
3649
|
+
/**
|
|
3650
|
+
* Admin: Delete token metadata (soft delete)
|
|
3651
|
+
*
|
|
3652
|
+
* Soft deletes token metadata by setting deletedAt timestamp.
|
|
3653
|
+
* Requires administrator privileges. Will fail with 409 Conflict
|
|
3654
|
+
* if metadata is currently in use by active campaigns or redemptions.
|
|
3655
|
+
*
|
|
3656
|
+
* @param metadataId - ID of the token metadata to delete
|
|
3657
|
+
* @throws {PersApiError} When not authenticated as admin
|
|
3658
|
+
* @throws {PersApiError} 409 Conflict if metadata is in use
|
|
3659
|
+
*
|
|
3660
|
+
* @example
|
|
3661
|
+
* ```typescript
|
|
3662
|
+
* try {
|
|
3663
|
+
* await sdk.tokens.deleteTokenMetadata('metadata-123');
|
|
3664
|
+
* console.log('Token metadata deleted');
|
|
3665
|
+
* } catch (error) {
|
|
3666
|
+
* if (error.statusCode === 409) {
|
|
3667
|
+
* console.log('Cannot delete: metadata is used by campaigns/redemptions');
|
|
3668
|
+
* }
|
|
3669
|
+
* }
|
|
3670
|
+
* ```
|
|
3671
|
+
*/
|
|
3672
|
+
async deleteTokenMetadata(metadataId) {
|
|
3673
|
+
return this.tokenService.deleteTokenMetadata(metadataId);
|
|
3674
|
+
}
|
|
3500
3675
|
/**
|
|
3501
3676
|
* Get the full token SDK for advanced operations
|
|
3502
3677
|
*
|
|
@@ -5310,6 +5485,52 @@ class RedemptionManager {
|
|
|
5310
5485
|
async getRedemptions(options) {
|
|
5311
5486
|
return this.redemptionService.getRedemptions(options);
|
|
5312
5487
|
}
|
|
5488
|
+
/**
|
|
5489
|
+
* Get a specific redemption by ID
|
|
5490
|
+
*
|
|
5491
|
+
* Retrieves detailed information about a specific redemption offer.
|
|
5492
|
+
* Useful when you already have the redemption ID and need full details.
|
|
5493
|
+
*
|
|
5494
|
+
* @param id - Redemption UUID
|
|
5495
|
+
* @param include - Optional relations to include: 'redeemCount'
|
|
5496
|
+
* @returns Promise resolving to the redemption
|
|
5497
|
+
*
|
|
5498
|
+
* @example Basic usage
|
|
5499
|
+
* ```typescript
|
|
5500
|
+
* const redemption = await sdk.redemptions.getRedemptionById('7baf4d39-0bd6-45ca-9c66-8c0d655767c3');
|
|
5501
|
+
* console.log(redemption.name);
|
|
5502
|
+
* console.log(redemption.description);
|
|
5503
|
+
* ```
|
|
5504
|
+
*
|
|
5505
|
+
* @example With redeem count
|
|
5506
|
+
* ```typescript
|
|
5507
|
+
* const redemption = await sdk.redemptions.getRedemptionById(
|
|
5508
|
+
* 'redemption-123',
|
|
5509
|
+
* ['redeemCount']
|
|
5510
|
+
* );
|
|
5511
|
+
* console.log(`${redemption.name} has been redeemed ${redemption.redeemCount} times`);
|
|
5512
|
+
* ```
|
|
5513
|
+
*
|
|
5514
|
+
* @example Get redemption details for display
|
|
5515
|
+
* ```typescript
|
|
5516
|
+
* const redemption = await sdk.redemptions.getRedemptionById(id);
|
|
5517
|
+
*
|
|
5518
|
+
* console.log('Redemption Details:');
|
|
5519
|
+
* console.log(`Name: ${redemption.name}`);
|
|
5520
|
+
* console.log(`Description: ${redemption.description}`);
|
|
5521
|
+
* console.log(`Active: ${redemption.isActive}`);
|
|
5522
|
+
*
|
|
5523
|
+
* if (redemption.tokenUnits?.length) {
|
|
5524
|
+
* console.log('Cost:');
|
|
5525
|
+
* redemption.tokenUnits.forEach(unit => {
|
|
5526
|
+
* console.log(` ${unit.amount} ${unit.token.symbol}`);
|
|
5527
|
+
* });
|
|
5528
|
+
* }
|
|
5529
|
+
* ```
|
|
5530
|
+
*/
|
|
5531
|
+
async getRedemptionById(id, include) {
|
|
5532
|
+
return this.redemptionService.getRedemptionById(id, include);
|
|
5533
|
+
}
|
|
5313
5534
|
/**
|
|
5314
5535
|
* Get available redemption types
|
|
5315
5536
|
*
|
|
@@ -5844,6 +6065,21 @@ class RedemptionManager {
|
|
|
5844
6065
|
async deleteRedemptionType(id) {
|
|
5845
6066
|
return this.redemptionService.deleteRedemptionType(id);
|
|
5846
6067
|
}
|
|
6068
|
+
/**
|
|
6069
|
+
* Delete a redemption (soft delete)
|
|
6070
|
+
*
|
|
6071
|
+
* @param id - Redemption ID to delete
|
|
6072
|
+
* @returns Promise resolving to true if deleted successfully
|
|
6073
|
+
*
|
|
6074
|
+
* @example
|
|
6075
|
+
* ```typescript
|
|
6076
|
+
* const success = await sdk.redemptions.deleteRedemption('redemption-123');
|
|
6077
|
+
* console.log('Deleted:', success);
|
|
6078
|
+
* ```
|
|
6079
|
+
*/
|
|
6080
|
+
async deleteRedemption(id) {
|
|
6081
|
+
return this.redemptionService.deleteRedemption(id);
|
|
6082
|
+
}
|
|
5847
6083
|
/**
|
|
5848
6084
|
* Get the full redemption service for advanced operations
|
|
5849
6085
|
*
|
|
@@ -10713,4 +10949,4 @@ exports.createPersEventsClient = createPersEventsClient;
|
|
|
10713
10949
|
exports.createPersSDK = createPersSDK;
|
|
10714
10950
|
exports.isFatalAuthErrorInMessage = isFatalAuthErrorInMessage;
|
|
10715
10951
|
exports.mergeWithDefaults = mergeWithDefaults;
|
|
10716
|
-
//# sourceMappingURL=pers-sdk-
|
|
10952
|
+
//# sourceMappingURL=pers-sdk-Cwlrl8jb.cjs.map
|