@explorins/pers-sdk 2.1.23 → 2.1.26

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.
Files changed (109) hide show
  1. package/dist/business/api/business-api.d.ts +6 -9
  2. package/dist/business/api/business-api.d.ts.map +1 -1
  3. package/dist/business/index.d.ts +1 -0
  4. package/dist/business/index.d.ts.map +1 -1
  5. package/dist/business/services/business-service.d.ts +8 -5
  6. package/dist/business/services/business-service.d.ts.map +1 -1
  7. package/dist/business.cjs +1 -1
  8. package/dist/business.js +1 -1
  9. package/dist/campaign/api/campaign-api.d.ts +4 -12
  10. package/dist/campaign/api/campaign-api.d.ts.map +1 -1
  11. package/dist/campaign/index.d.ts +2 -1
  12. package/dist/campaign/index.d.ts.map +1 -1
  13. package/dist/campaign/models/index.d.ts +16 -6
  14. package/dist/campaign/models/index.d.ts.map +1 -1
  15. package/dist/campaign/services/campaign-service.d.ts +9 -26
  16. package/dist/campaign/services/campaign-service.d.ts.map +1 -1
  17. package/dist/campaign.cjs +10 -3
  18. package/dist/campaign.cjs.map +1 -1
  19. package/dist/campaign.js +10 -3
  20. package/dist/campaign.js.map +1 -1
  21. package/dist/chunks/{business-membership-service-BfHzIQlc.cjs → business-membership-service-DXLG5fP9.cjs} +17 -2
  22. package/dist/chunks/business-membership-service-DXLG5fP9.cjs.map +1 -0
  23. package/dist/chunks/{business-membership-service-CFa-TI39.js → business-membership-service-IyY5CkL0.js} +17 -2
  24. package/dist/chunks/business-membership-service-IyY5CkL0.js.map +1 -0
  25. package/dist/chunks/{pers-sdk-DgSbePI0.js → pers-sdk-Ddw3SoDH.js} +380 -85
  26. package/dist/chunks/pers-sdk-Ddw3SoDH.js.map +1 -0
  27. package/dist/chunks/{pers-sdk-rmjhPvHo.cjs → pers-sdk-tAxjWu7_.cjs} +380 -85
  28. package/dist/chunks/pers-sdk-tAxjWu7_.cjs.map +1 -0
  29. package/dist/chunks/{redemption-service-B6ZlAV6_.cjs → redemption-service-5Mu78Sne.cjs} +21 -5
  30. package/dist/chunks/redemption-service-5Mu78Sne.cjs.map +1 -0
  31. package/dist/chunks/{redemption-service-C0vys0OQ.js → redemption-service-CoODony4.js} +21 -5
  32. package/dist/chunks/redemption-service-CoODony4.js.map +1 -0
  33. package/dist/chunks/{tenant-manager-BIQONvmF.cjs → tenant-manager-D3toTiB9.cjs} +20 -2
  34. package/dist/chunks/{tenant-manager-BIQONvmF.cjs.map → tenant-manager-D3toTiB9.cjs.map} +1 -1
  35. package/dist/chunks/{tenant-manager-C5txKrZA.js → tenant-manager-D8-eD2CZ.js} +20 -2
  36. package/dist/chunks/{tenant-manager-C5txKrZA.js.map → tenant-manager-D8-eD2CZ.js.map} +1 -1
  37. package/dist/chunks/{tenant-service-Ch-V3mj-.cjs → tenant-service-8vZWmTLV.cjs} +16 -1
  38. package/dist/chunks/tenant-service-8vZWmTLV.cjs.map +1 -0
  39. package/dist/chunks/{tenant-service-BnTAZCxS.js → tenant-service-DlhdZAs9.js} +16 -1
  40. package/dist/chunks/tenant-service-DlhdZAs9.js.map +1 -0
  41. package/dist/chunks/{web3-manager-D3VYTPBZ.js → web3-manager-DZXBaBh0.js} +2 -2
  42. package/dist/chunks/{web3-manager-D3VYTPBZ.js.map → web3-manager-DZXBaBh0.js.map} +1 -1
  43. package/dist/chunks/{web3-manager-C891F2cd.cjs → web3-manager-ojRB6_ty.cjs} +2 -2
  44. package/dist/chunks/{web3-manager-C891F2cd.cjs.map → web3-manager-ojRB6_ty.cjs.map} +1 -1
  45. package/dist/core/auth/api/auth-api.d.ts +37 -2
  46. package/dist/core/auth/api/auth-api.d.ts.map +1 -1
  47. package/dist/core/auth/default-auth-provider.d.ts +1 -0
  48. package/dist/core/auth/default-auth-provider.d.ts.map +1 -1
  49. package/dist/core/auth/services/auth-service.d.ts +24 -3
  50. package/dist/core/auth/services/auth-service.d.ts.map +1 -1
  51. package/dist/core/events/event-emitter.d.ts +13 -1
  52. package/dist/core/events/event-emitter.d.ts.map +1 -1
  53. package/dist/core/events/event-types.d.ts +11 -0
  54. package/dist/core/events/event-types.d.ts.map +1 -1
  55. package/dist/core/pers-config.d.ts +13 -0
  56. package/dist/core/pers-config.d.ts.map +1 -1
  57. package/dist/core.cjs +5 -5
  58. package/dist/core.js +5 -5
  59. package/dist/index.cjs +5 -5
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +5 -5
  63. package/dist/managers/auth-manager.d.ts +61 -3
  64. package/dist/managers/auth-manager.d.ts.map +1 -1
  65. package/dist/managers/business-manager.d.ts +4 -4
  66. package/dist/managers/business-manager.d.ts.map +1 -1
  67. package/dist/managers/campaign-manager.d.ts +33 -39
  68. package/dist/managers/campaign-manager.d.ts.map +1 -1
  69. package/dist/managers/events-manager.d.ts.map +1 -1
  70. package/dist/managers/index.d.ts +1 -0
  71. package/dist/managers/index.d.ts.map +1 -1
  72. package/dist/managers/redemption-manager.d.ts +25 -3
  73. package/dist/managers/redemption-manager.d.ts.map +1 -1
  74. package/dist/managers/tenant-manager.d.ts +16 -0
  75. package/dist/managers/tenant-manager.d.ts.map +1 -1
  76. package/dist/node.cjs +5 -5
  77. package/dist/node.js +5 -5
  78. package/dist/package.json +2 -2
  79. package/dist/pers-sdk.d.ts +12 -6
  80. package/dist/pers-sdk.d.ts.map +1 -1
  81. package/dist/redemption/api/redemption-api.d.ts +5 -11
  82. package/dist/redemption/api/redemption-api.d.ts.map +1 -1
  83. package/dist/redemption/index.d.ts +2 -1
  84. package/dist/redemption/index.d.ts.map +1 -1
  85. package/dist/redemption/models/index.d.ts +17 -3
  86. package/dist/redemption/models/index.d.ts.map +1 -1
  87. package/dist/redemption/services/redemption-service.d.ts +13 -18
  88. package/dist/redemption/services/redemption-service.d.ts.map +1 -1
  89. package/dist/redemption.cjs +1 -1
  90. package/dist/redemption.js +1 -1
  91. package/dist/tenant/api/tenant-api.d.ts +7 -0
  92. package/dist/tenant/api/tenant-api.d.ts.map +1 -1
  93. package/dist/tenant/services/tenant-service.d.ts +4 -0
  94. package/dist/tenant/services/tenant-service.d.ts.map +1 -1
  95. package/dist/tenant.cjs +1 -1
  96. package/dist/tenant.js +1 -1
  97. package/dist/web3-manager.cjs +3 -3
  98. package/dist/web3-manager.js +3 -3
  99. package/dist/web3.cjs +3 -3
  100. package/dist/web3.js +3 -3
  101. package/package.json +2 -2
  102. package/dist/chunks/business-membership-service-BfHzIQlc.cjs.map +0 -1
  103. package/dist/chunks/business-membership-service-CFa-TI39.js.map +0 -1
  104. package/dist/chunks/pers-sdk-DgSbePI0.js.map +0 -1
  105. package/dist/chunks/pers-sdk-rmjhPvHo.cjs.map +0 -1
  106. package/dist/chunks/redemption-service-B6ZlAV6_.cjs.map +0 -1
  107. package/dist/chunks/redemption-service-C0vys0OQ.js.map +0 -1
  108. package/dist/chunks/tenant-service-BnTAZCxS.js.map +0 -1
  109. package/dist/chunks/tenant-service-Ch-V3mj-.cjs.map +0 -1
@@ -3,12 +3,12 @@ import { i as isTokenExpired, E as ErrorUtils, A as AuthenticationError, b as Pe
3
3
  import { UserService, UserApi } from '../user.js';
4
4
  import { createUserStatusSDK } from '../user-status.js';
5
5
  import { a as TokenService, T as TokenApi } from './token-service-BxEO5YVN.js';
6
- import { B as BusinessApi, b as BusinessService, a as BusinessMembershipApi, c as BusinessMembershipService } from './business-membership-service-CFa-TI39.js';
6
+ import { B as BusinessApi, b as BusinessService, a as BusinessMembershipApi, c as BusinessMembershipService } from './business-membership-service-IyY5CkL0.js';
7
7
  import { CampaignService, CampaignApi } from '../campaign.js';
8
- import { a as RedemptionService, R as RedemptionApi } from './redemption-service-C0vys0OQ.js';
8
+ import { a as RedemptionService, R as RedemptionApi } from './redemption-service-CoODony4.js';
9
9
  import { a as TransactionService, T as TransactionApi } from './transaction-request.builder-BZ6Uq6Qe.js';
10
10
  import { a as PaymentService, P as PurchaseApi } from './payment-service-IvM6rryM.js';
11
- import { T as TenantManager } from './tenant-manager-C5txKrZA.js';
11
+ import { T as TenantManager } from './tenant-manager-D8-eD2CZ.js';
12
12
  import { b as buildPaginationParams, n as normalizeToPaginated } from './pagination-utils-9vQ-Npkr.js';
13
13
  import { a as AnalyticsService, A as AnalyticsApi } from './analytics-service-vm7B7LhS.js';
14
14
  import { DonationService, DonationApi } from '../donation.js';
@@ -30,7 +30,8 @@ const DEFAULT_PERS_CONFIG = {
30
30
  retries: 3,
31
31
  tokenRefreshMargin: 60, // Refresh tokens 60 seconds before expiry
32
32
  backgroundRefreshThreshold: 30, // Use background refresh if >30s remaining
33
- captureWalletEvents: true // Auto-connect to wallet events after auth
33
+ captureWalletEvents: true, // Auto-connect to wallet events after auth
34
+ autoRestoreSession: true // Auto-restore session from stored tokens on init
34
35
  };
35
36
  /**
36
37
  * Build the API root URL based on config
@@ -97,11 +98,28 @@ class AuthApi {
97
98
  }
98
99
  /**
99
100
  * Login tenant admin with JWT
101
+ *
102
+ * Authenticates an admin in a tenant context.
103
+ *
104
+ * @param jwt - Authentication token (Firebase JWT)
105
+ * @param options - Tenant authentication options (tenantId for multi-tenant admins)
106
+ * @returns Session response with tenant context
107
+ * @throws MultipleContextSelectionError when tenantId is required but not provided
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // Single tenant - auto-selects
112
+ * const response = await authApi.loginTenantAdmin(jwt);
113
+ *
114
+ * // Multiple tenants - explicit selection
115
+ * const response = await authApi.loginTenantAdmin(jwt, { tenantId: 'tenant-123' });
116
+ * ```
100
117
  */
101
- async loginTenantAdmin(jwt) {
118
+ async loginTenantAdmin(jwt, options) {
102
119
  const body = {
103
120
  authToken: jwt,
104
- authType: AccountOwnerType.TENANT
121
+ authType: AccountOwnerType.TENANT,
122
+ context: options?.tenantId ? { tenantId: options.tenantId } : undefined
105
123
  };
106
124
  return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
107
125
  }
@@ -159,6 +177,30 @@ class AuthApi {
159
177
  async refreshAccessToken(refreshToken) {
160
178
  return this.apiClient.post(`${this.basePath}/refresh`, { refreshToken }, { bypassAuth: true, isRefreshRequest: true });
161
179
  }
180
+ // ==========================================
181
+ // IDENTITY VERIFICATION (for session restore)
182
+ // Note: These duplicate calls in domain APIs (user-api, business-api)
183
+ // but are kept here to avoid circular dependencies during initialization.
184
+ // If endpoints change, update both locations.
185
+ // ==========================================
186
+ /**
187
+ * Get current authenticated user
188
+ */
189
+ async getCurrentUser() {
190
+ return this.apiClient.get('/users/me');
191
+ }
192
+ /**
193
+ * Get current business context
194
+ */
195
+ async getCurrentBusiness() {
196
+ return this.apiClient.get('/businesses/me');
197
+ }
198
+ /**
199
+ * Get current admin context
200
+ */
201
+ async getCurrentAdmin() {
202
+ return this.apiClient.get('/admins/me');
203
+ }
162
204
  }
163
205
 
164
206
  /**
@@ -183,6 +225,12 @@ var AuthStatus;
183
225
  AuthStatus["SESSION_RESTORATION_FAILED"] = "session_restoration_failed";
184
226
  })(AuthStatus || (AuthStatus = {}));
185
227
 
228
+ /**
229
+ * Type guard to check if provider implements extended storage methods
230
+ */
231
+ function isExtendedProvider(provider) {
232
+ return 'setAuthType' in provider && typeof provider.setAuthType === 'function';
233
+ }
186
234
  /**
187
235
  * Platform-agnostic authentication service
188
236
  * Handles login, token refresh, and storage operations
@@ -194,6 +242,12 @@ class AuthService {
194
242
  this.activeRefreshPromise = null;
195
243
  this.currentAuthStatus = AuthStatus.UNAUTHENTICATED;
196
244
  }
245
+ /**
246
+ * Get extended provider if available, null otherwise
247
+ */
248
+ get extendedProvider() {
249
+ return this.authProvider && isExtendedProvider(this.authProvider) ? this.authProvider : null;
250
+ }
197
251
  /**
198
252
  * Emit auth status change to the app
199
253
  */
@@ -201,9 +255,10 @@ class AuthService {
201
255
  if (this.currentAuthStatus === status)
202
256
  return; // No change
203
257
  this.currentAuthStatus = status;
204
- if (this.authProvider && typeof this.authProvider.onAuthStatusChange === 'function') {
258
+ const extended = this.extendedProvider;
259
+ if (extended?.onAuthStatusChange) {
205
260
  try {
206
- await this.authProvider.onAuthStatusChange(status);
261
+ await extended.onAuthStatusChange(status);
207
262
  }
208
263
  catch (error) {
209
264
  console.warn('[AuthService] Auth status change callback failed:', error);
@@ -215,9 +270,14 @@ class AuthService {
215
270
  // ==========================================
216
271
  /**
217
272
  * Login tenant admin with JWT
273
+ *
274
+ * @param jwt - Authentication token (Firebase JWT)
275
+ * @param options - Tenant authentication options (tenantId for multi-tenant admins)
276
+ * @returns Session response with tenant context
277
+ * @throws Error with code MULTIPLE_CONTEXT_SELECTION_REQUIRED when tenantId is required but not provided
218
278
  */
219
- async loginTenantAdmin(jwt) {
220
- const response = await this.authApi.loginTenantAdmin(jwt);
279
+ async loginTenantAdmin(jwt, options) {
280
+ const response = await this.authApi.loginTenantAdmin(jwt, options);
221
281
  if (this.authProvider && response.accessToken) {
222
282
  await this.storeTokens(response.accessToken, response.refreshToken, AccountOwnerType.TENANT, jwt);
223
283
  }
@@ -298,9 +358,13 @@ class AuthService {
298
358
  if (!tokenToUse) {
299
359
  throw new Error('No refresh token available for token refresh');
300
360
  }
361
+ // Get the current authType to preserve it after refresh
362
+ const extended = this.extendedProvider;
363
+ const currentAuthType = extended?.getAuthType ? await extended.getAuthType() ?? undefined : undefined;
301
364
  const response = await this.authApi.refreshAccessToken(tokenToUse);
302
365
  if (this.authProvider && response.accessToken) {
303
- await this.storeTokens(response.accessToken, response.refreshToken);
366
+ // Preserve the authType during refresh
367
+ await this.storeTokens(response.accessToken, response.refreshToken, currentAuthType);
304
368
  }
305
369
  return response;
306
370
  }
@@ -338,6 +402,27 @@ class AuthService {
338
402
  return !!token;
339
403
  }
340
404
  // ==========================================
405
+ // CONTEXT RETRIEVAL
406
+ // ==========================================
407
+ /**
408
+ * Get current authenticated user
409
+ */
410
+ async getCurrentUser() {
411
+ return this.authApi.getCurrentUser();
412
+ }
413
+ /**
414
+ * Get current business context
415
+ */
416
+ async getCurrentBusiness() {
417
+ return this.authApi.getCurrentBusiness();
418
+ }
419
+ /**
420
+ * Get current admin context
421
+ */
422
+ async getCurrentAdmin() {
423
+ return this.authApi.getCurrentAdmin();
424
+ }
425
+ // ==========================================
341
426
  // PRIVATE HELPERS
342
427
  // ==========================================
343
428
  /**
@@ -351,17 +436,18 @@ class AuthService {
351
436
  if (refreshToken) {
352
437
  await this.authProvider.setRefreshToken(refreshToken);
353
438
  }
354
- // Type-safe handling of extended token storage features
355
- const extendedProvider = this.authProvider;
356
- if (providerToken && extendedProvider.setProviderToken) {
357
- await extendedProvider.setProviderToken(providerToken);
439
+ // Handle optional extended storage methods
440
+ const extended = this.extendedProvider;
441
+ if (extended) {
442
+ if (providerToken && extended.setProviderToken) {
443
+ await extended.setProviderToken(providerToken);
444
+ }
445
+ if (authType && extended.setAuthType) {
446
+ await extended.setAuthType(authType);
447
+ }
358
448
  }
359
- if (authType && extendedProvider.setAuthType) {
360
- console.log('[AuthService] Storing auth type:', authType);
361
- await extendedProvider.setAuthType(authType);
362
- }
363
- else {
364
- console.warn('[AuthService] Auth type not stored - authType:', authType, 'has setAuthType:', !!extendedProvider.setAuthType);
449
+ else if (authType) {
450
+ console.warn('[AuthService] Auth type not stored - provider does not implement setAuthType');
365
451
  }
366
452
  // Emit authenticated status on successful token storage
367
453
  await this.emitAuthStatus(AuthStatus.AUTHENTICATED);
@@ -906,6 +992,11 @@ class DefaultAuthProvider {
906
992
  async hasValidToken() {
907
993
  return this.tokenManager.hasAccessToken();
908
994
  }
995
+ async setAuthType(authType) {
996
+ // Auth type is derived from JWT, so this is a no-op
997
+ // The authType in JWT is the source of truth
998
+ // This method exists to satisfy the ExtendedTokenStorageProvider interface
999
+ }
909
1000
  async getAuthType() {
910
1001
  // Read from JWT instead of separate storage for single source of truth
911
1002
  const token = await this.tokenManager.getAccessToken();
@@ -1401,6 +1492,7 @@ function generateEventId() {
1401
1492
  *
1402
1493
  * All events flow through one subscription point.
1403
1494
  * Optional filtering at subscription level.
1495
+ * Supports replay of last auth event for late subscribers.
1404
1496
  *
1405
1497
  * @example Basic Usage
1406
1498
  * ```typescript
@@ -1424,6 +1516,13 @@ function generateEventId() {
1424
1516
  * showNotification(event.userMessage);
1425
1517
  * }, { excludeDomains: ['validation'] });
1426
1518
  *
1519
+ * // Subscribe with replay - get last auth event if missed
1520
+ * sdk.events.subscribe((event) => {
1521
+ * if (event.type === 'session_restored') {
1522
+ * setUser(event.details.user);
1523
+ * }
1524
+ * }, { domains: ['authentication'], replay: true });
1525
+ *
1427
1526
  * // Cleanup
1428
1527
  * unsubscribe();
1429
1528
  * ```
@@ -1431,6 +1530,8 @@ function generateEventId() {
1431
1530
  let emitterInstanceCounter = 0;
1432
1531
  class PersEventEmitter {
1433
1532
  constructor() {
1533
+ // Store last auth event for replay to late subscribers
1534
+ this.lastAuthEvent = null;
1434
1535
  this.handlers = new Set();
1435
1536
  this._instanceId = ++emitterInstanceCounter;
1436
1537
  }
@@ -1441,7 +1542,7 @@ class PersEventEmitter {
1441
1542
  * Subscribe to events
1442
1543
  *
1443
1544
  * @param handler - Callback for matching events
1444
- * @param filter - Optional filter by domain and/or level
1545
+ * @param filter - Optional filter by domain and/or level. Set `replay: true` to receive last auth event if missed.
1445
1546
  * @returns Unsubscribe function
1446
1547
  *
1447
1548
  * @example All events
@@ -1465,10 +1566,35 @@ class PersEventEmitter {
1465
1566
  * confetti();
1466
1567
  * }, { domains: ['transaction'], levels: ['success'] });
1467
1568
  * ```
1569
+ *
1570
+ * @example Auth events with replay (catches session_restored even if emitted before subscription)
1571
+ * ```typescript
1572
+ * sdk.events.subscribe((event) => {
1573
+ * if (event.type === 'session_restored') {
1574
+ * const { user } = event.details;
1575
+ * setUser(user);
1576
+ * }
1577
+ * }, { domains: ['authentication'], replay: true });
1578
+ * ```
1468
1579
  */
1469
1580
  subscribe(handler, filter) {
1470
1581
  const filteredHandler = { handler, filter };
1471
1582
  this.handlers.add(filteredHandler);
1583
+ // If replay is requested and we have a cached auth event, replay it immediately
1584
+ if (filter?.replay && this.lastAuthEvent) {
1585
+ // Check if event matches the filter
1586
+ if (!filter || this.matchesFilter(this.lastAuthEvent, filter)) {
1587
+ // Use queueMicrotask to ensure handler runs after subscribe returns
1588
+ queueMicrotask(() => {
1589
+ try {
1590
+ handler(this.lastAuthEvent);
1591
+ }
1592
+ catch (error) {
1593
+ console.error('[PersEventEmitter] Replay handler error:', error);
1594
+ }
1595
+ });
1596
+ }
1597
+ }
1472
1598
  return () => this.handlers.delete(filteredHandler);
1473
1599
  }
1474
1600
  /**
@@ -1493,6 +1619,7 @@ class PersEventEmitter {
1493
1619
  * Emit a success event
1494
1620
  *
1495
1621
  * Domain is restricted to business domains only (Domain type).
1622
+ * Auth events (login_success, session_restored) are cached for replay to late subscribers.
1496
1623
  *
1497
1624
  * @param event - Success event data (id and timestamp auto-generated)
1498
1625
  * @returns The complete event object
@@ -1513,6 +1640,15 @@ class PersEventEmitter {
1513
1640
  id: generateEventId(),
1514
1641
  timestamp: Date.now()
1515
1642
  };
1643
+ // Cache auth events for replay to late subscribers
1644
+ if (event.domain === 'authentication' &&
1645
+ (event.type === 'login_success' || event.type === 'session_restored')) {
1646
+ this.lastAuthEvent = fullEvent;
1647
+ }
1648
+ // Clear cached auth on logout
1649
+ if (event.domain === 'authentication' && event.type === 'logout_success') {
1650
+ this.lastAuthEvent = null;
1651
+ }
1516
1652
  this.notifyHandlers(fullEvent);
1517
1653
  return fullEvent;
1518
1654
  }
@@ -1540,6 +1676,10 @@ class PersEventEmitter {
1540
1676
  id: generateEventId(),
1541
1677
  timestamp: Date.now()
1542
1678
  };
1679
+ // Clear cached auth on auth failure (session invalid)
1680
+ if (event.domain === 'authentication' && event.type === 'session_restoration_failed') {
1681
+ this.lastAuthEvent = null;
1682
+ }
1543
1683
  this.notifyHandlers(fullEvent);
1544
1684
  return fullEvent;
1545
1685
  }
@@ -1663,7 +1803,8 @@ class AuthManager {
1663
1803
  this.events?.emitSuccess({
1664
1804
  domain: 'authentication',
1665
1805
  type: 'login_success',
1666
- userMessage: 'Successfully logged in'
1806
+ userMessage: 'Successfully logged in',
1807
+ details: { user: result.user }
1667
1808
  });
1668
1809
  return result;
1669
1810
  }
@@ -1711,7 +1852,66 @@ class AuthManager {
1711
1852
  */
1712
1853
  async loginAsBusiness(jwtToken, options) {
1713
1854
  const authService = this.apiClient.getAuthService();
1714
- return authService.loginBusiness(jwtToken, options);
1855
+ const result = await authService.loginBusiness(jwtToken, options);
1856
+ this.events?.emitSuccess({
1857
+ domain: 'authentication',
1858
+ type: 'login_success',
1859
+ userMessage: 'Successfully logged in as business',
1860
+ details: { user: result.user, business: result.business }
1861
+ });
1862
+ return result;
1863
+ }
1864
+ /**
1865
+ * Login as tenant admin with JWT token
1866
+ *
1867
+ * Authenticates an admin in a tenant context.
1868
+ *
1869
+ * **Auto-Selection Behavior:**
1870
+ * - If admin has access to a single tenant, it's auto-selected
1871
+ * - If admin has access to multiple tenants and no tenantId is provided,
1872
+ * throws `MULTIPLE_CONTEXT_SELECTION_REQUIRED` error with available options
1873
+ *
1874
+ * @param jwtToken - JWT token from auth provider (Firebase, etc.)
1875
+ * @param options - Tenant authentication options (tenantId for multi-tenant admins)
1876
+ * @returns Promise resolving to authentication response with tenant context
1877
+ * @throws Error with code `MULTIPLE_CONTEXT_SELECTION_REQUIRED` when tenantId is needed
1878
+ *
1879
+ * @example Single Tenant Access
1880
+ * ```typescript
1881
+ * // Auto-selects the admin's only tenant
1882
+ * const result = await sdk.auth.loginAsTenant(jwt);
1883
+ * console.log('Tenant:', result.admin?.tenantId);
1884
+ * ```
1885
+ *
1886
+ * @example Multiple Tenant Access
1887
+ * ```typescript
1888
+ * try {
1889
+ * const result = await sdk.auth.loginAsTenant(jwt);
1890
+ * } catch (error) {
1891
+ * if (error.code === 'MULTIPLE_CONTEXT_SELECTION_REQUIRED') {
1892
+ * // Show tenant selector UI
1893
+ * const selectedId = await showTenantSelector(error.details.availableOptions);
1894
+ * const result = await sdk.auth.loginAsTenant(jwt, { tenantId: selectedId });
1895
+ * }
1896
+ * }
1897
+ * ```
1898
+ *
1899
+ * @example Direct Tenant Selection
1900
+ * ```typescript
1901
+ * const result = await sdk.auth.loginAsTenant(jwt, { tenantId: 'tenant-123' });
1902
+ * console.log('Authenticated as admin for tenant:', result.admin?.tenantId);
1903
+ * ```
1904
+ */
1905
+ async loginAsTenant(jwtToken, options) {
1906
+ const authService = this.apiClient.getAuthService();
1907
+ const result = await authService.loginTenantAdmin(jwtToken, options);
1908
+ this.events?.emitSuccess({
1909
+ domain: 'authentication',
1910
+ type: 'login_success',
1911
+ userMessage: 'Successfully logged in as tenant admin',
1912
+ details: { admin: result.admin }
1913
+ });
1914
+ return result;
1715
1915
  }
1716
1916
  /**
1717
1917
  * Get current business context
@@ -1729,7 +1929,27 @@ class AuthManager {
1729
1929
  * ```
1730
1930
  */
1731
1931
  async getCurrentBusiness() {
1732
- return this.apiClient.get('/businesses/me');
1932
+ const authService = this.apiClient.getAuthService();
1933
+ return authService.getCurrentBusiness();
1934
+ }
1935
+ /**
1936
+ * Get current admin context
1937
+ *
1938
+ * Retrieves the current admin data if authenticated as tenant admin.
1939
+ * Requires prior tenant authentication via {@link loginAsTenant}.
1940
+ *
1941
+ * @returns Promise resolving to current admin data
1942
+ * @throws {PersApiError} When not authenticated as tenant admin
1943
+ *
1944
+ * @example
1945
+ * ```typescript
1946
+ * const admin = await sdk.auth.getCurrentAdmin();
1947
+ * console.log('Current admin:', admin.email);
1948
+ * ```
1949
+ */
1950
+ async getCurrentAdmin() {
1951
+ const authService = this.apiClient.getAuthService();
1952
+ return authService.getCurrentAdmin();
1733
1953
  }
1734
1954
  /**
1735
1955
  * Login with raw user data
@@ -1773,7 +1993,8 @@ class AuthManager {
1773
1993
  * ```
1774
1994
  */
1775
1995
  async getCurrentUser() {
1776
- return this.apiClient.get('/users/me');
1996
+ const authService = this.apiClient.getAuthService();
1997
+ return authService.getCurrentUser();
1777
1998
  }
1778
1999
  /**
1779
2000
  * Check if user is authenticated
@@ -1851,6 +2072,11 @@ class AuthManager {
1851
2072
  async clearAuth() {
1852
2073
  const authService = this.apiClient.getAuthService();
1853
2074
  await authService.clearTokens();
2075
+ this.events?.emitSuccess({
2076
+ domain: 'authentication',
2077
+ type: 'logout_success',
2078
+ userMessage: 'Successfully logged out'
2079
+ });
1854
2080
  }
1855
2081
  /**
1856
2082
  * Ensure authentication token is valid
@@ -4071,58 +4297,52 @@ class CampaignManager {
4071
4297
  async deleteCampaignBusinessEngagement(campaignId, engagementId) {
4072
4298
  return this.campaignService.deleteCampaignBusinessEngagement(campaignId, engagementId);
4073
4299
  }
4074
- /**
4075
- * Admin: Get all campaign claims
4076
- *
4077
- * Retrieves all campaign claims across the system for comprehensive reporting
4078
- * and analytics. This operation requires administrator privileges and provides
4079
- * system-wide visibility into campaign performance and user engagement.
4080
- *
4081
- * @returns Promise resolving to array of all campaign claims
4082
- * @throws {PersApiError} When not authenticated as administrator
4083
- *
4084
- * @example
4085
- * ```typescript
4086
- * // Admin operation - get campaign performance data
4087
- * const allClaims = await sdk.campaigns.getCampaignClaims();
4088
- *
4089
- * console.log(`Campaign Performance Report:`);
4090
- * console.log(`Total claims: ${allClaims.length}`);
4091
- *
4092
- * // Analyze claims by campaign
4093
- * const claimsByCampaign = allClaims.reduce((acc, claim) => {
4094
- * const campaignId = claim.campaignId;
4095
- * acc[campaignId] = (acc[campaignId] || 0) + 1;
4096
- * return acc;
4097
- * }, {});
4098
- *
4099
- * console.log('\nClaims by Campaign:');
4100
- * Object.entries(claimsByCampaign).forEach(([campaignId, count]) => {
4101
- * console.log(`${campaignId}: ${count} claims`);
4102
- * });
4103
- * ```
4104
- */
4105
4300
  /**
4106
4301
  * Admin: Get campaign claims with optional filters
4107
4302
  *
4108
- * Retrieves campaign claims with optional filtering by campaign, user, or business.
4303
+ * Retrieves campaign claims with optional filtering by campaign, user, business, or date range.
4109
4304
  * This operation requires administrator privileges and provides system-wide
4110
4305
  * visibility into campaign performance and user engagement.
4111
4306
  *
4112
4307
  * @param filters - Optional filters and pagination options
4308
+ * @param filters.campaignId - Filter by specific campaign ID
4309
+ * @param filters.userId - Filter by specific user ID
4310
+ * @param filters.businessId - Filter by specific business ID
4311
+ * @param filters.dateFrom - Filter claims from this date (inclusive)
4312
+ * @param filters.dateTo - Filter claims until this date (inclusive)
4313
+ * @param filters.page - Page number for pagination
4314
+ * @param filters.limit - Items per page
4315
+ * @param filters.sortBy - Field to sort by
4316
+ * @param filters.sortOrder - Sort direction ('asc' or 'desc')
4317
+ * @param include - Optional relations to include for enrichment
4113
4318
  * @returns Promise resolving to paginated campaign claims
4114
4319
  * @throws {PersApiError} When not authenticated as administrator
4115
4320
  *
4116
- * @example
4321
+ * @example Get All Claims
4117
4322
  * ```typescript
4118
- * // Get all claims
4119
- * const allClaims = await sdk.campaigns.getCampaignClaims();
4323
+ * const { data: allClaims, pagination } = await sdk.campaigns.getCampaignClaims();
4324
+ * console.log(`Total: ${pagination.total}`);
4325
+ * ```
4120
4326
  *
4121
- * // Get claims for specific user
4122
- * const userClaims = await sdk.campaigns.getCampaignClaims({ userId: 'user-123' });
4327
+ * @example Filter by User
4328
+ * ```typescript
4329
+ * const { data: userClaims } = await sdk.campaigns.getCampaignClaims({ userId: 'user-123' });
4330
+ * ```
4331
+ *
4332
+ * @example Filter by Date Range
4333
+ * ```typescript
4334
+ * // Get claims within a specific date range
4335
+ * const { data: monthClaims } = await sdk.campaigns.getCampaignClaims({
4336
+ * dateFrom: new Date('2024-01-01'),
4337
+ * dateTo: new Date('2024-01-31'),
4338
+ * limit: 100
4339
+ * });
4340
+ * console.log(`${monthClaims.length} claims in January 2024`);
4341
+ * ```
4123
4342
  *
4124
- * // Get claims for specific campaign with pagination
4125
- * const page1 = await sdk.campaigns.getCampaignClaims({
4343
+ * @example With Pagination and Campaign Filter
4344
+ * ```typescript
4345
+ * const { data: page1 } = await sdk.campaigns.getCampaignClaims({
4126
4346
  * campaignId: 'campaign-456',
4127
4347
  * page: 1,
4128
4348
  * limit: 50
@@ -4727,9 +4947,19 @@ class RedemptionManager {
4727
4947
  *
4728
4948
  * Retrieves all redemption redeems across the platform with filtering capabilities.
4729
4949
  * This is an admin-level operation that allows monitoring and analytics of redemption
4730
- * activity. Supports filtering by user, redemption offer, and enrichment of related entities.
4731
- *
4732
- * @param filters - Filter options (userId, redemptionId, pagination)
4950
+ * activity. Supports filtering by user, redemption offer, date range, and enrichment of related entities.
4951
+ *
4952
+ * @param filters - Filter options (userId, redemptionId, businessId, status, dateFrom, dateTo, pagination)
4953
+ * @param filters.userId - Filter by specific user ID
4954
+ * @param filters.redemptionId - Filter by specific redemption offer ID
4955
+ * @param filters.businessId - Filter by specific business ID
4956
+ * @param filters.status - Filter by redeem status
4957
+ * @param filters.dateFrom - Filter redeems from this date (inclusive)
4958
+ * @param filters.dateTo - Filter redeems until this date (inclusive)
4959
+ * @param filters.page - Page number for pagination
4960
+ * @param filters.limit - Items per page
4961
+ * @param filters.sortBy - Field to sort by
4962
+ * @param filters.sortOrder - Sort direction ('asc' or 'desc')
4733
4963
  * @param include - Optional relations to include for enrichment
4734
4964
  * @returns Promise resolving to paginated list of redemption redeems
4735
4965
  * @throws {PersApiError} When not authenticated as admin
@@ -4754,6 +4984,18 @@ class RedemptionManager {
4754
4984
  * console.log(`User has ${userRedeems.length} redemptions`);
4755
4985
  * ```
4756
4986
  *
4987
+ * @example Filter by Date Range
4988
+ * ```typescript
4989
+ * // Get redeems within a specific date range
4990
+ * const { data: recentRedeems } = await sdk.redemptions.getRedemptionRedeems({
4991
+ * dateFrom: new Date('2024-01-01'),
4992
+ * dateTo: new Date('2024-01-31'),
4993
+ * limit: 100
4994
+ * });
4995
+ *
4996
+ * console.log(`${recentRedeems.length} redeems in January 2024`);
4997
+ * ```
4998
+ *
4757
4999
  * @example With Enriched Data
4758
5000
  * ```typescript
4759
5001
  * const { data: redeems } = await sdk.redemptions.getRedemptionRedeems(
@@ -8690,7 +8932,8 @@ class WalletEventsManager {
8690
8932
  }
8691
8933
  // Save subscriptions for auto-resubscribe on reconnect
8692
8934
  this.lastSubscriptions.wallets = wallets;
8693
- return this.client.subscribeWallets(wallets);
8935
+ const result = await this.client.subscribeWallets(wallets);
8936
+ return result;
8694
8937
  }
8695
8938
  /**
8696
8939
  * Subscribe to chain events (Admin Dashboard)
@@ -8713,7 +8956,8 @@ class WalletEventsManager {
8713
8956
  }
8714
8957
  // Save subscriptions for auto-resubscribe on reconnect
8715
8958
  this.lastSubscriptions.chains = chains;
8716
- return this.client.subscribeChains(chains);
8959
+ const result = await this.client.subscribeChains(chains);
8960
+ return result;
8717
8961
  }
8718
8962
  /**
8719
8963
  * Unsubscribe from wallet events
@@ -9023,6 +9267,24 @@ class PersSDK {
9023
9267
  this.apiClient.setEvents(this._events);
9024
9268
  // Auto-connect to wallet events on successful login (if enabled)
9025
9269
  this.setupWalletEventsAutoConnect();
9270
+ // Auto-restore session from stored tokens (if enabled, default: true)
9271
+ this.setupAutoRestoreSession();
9272
+ }
9273
+ /**
9274
+ * Setup automatic session restoration from stored tokens
9275
+ * @internal
9276
+ */
9277
+ setupAutoRestoreSession() {
9278
+ const config = this.apiClient.getConfig();
9279
+ // Check if autoRestoreSession is enabled (default: true)
9280
+ if (config.autoRestoreSession === false) {
9281
+ return;
9282
+ }
9283
+ // Fire-and-forget: restore session asynchronously
9284
+ // Events will be emitted on success/failure
9285
+ this.restoreSession().catch(() => {
9286
+ // Error already emitted via session_restoration_failed event
9287
+ });
9026
9288
  }
9027
9289
  /**
9028
9290
  * Setup auto-connect for wallet events on authentication
@@ -9100,22 +9362,23 @@ class PersSDK {
9100
9362
  /**
9101
9363
  * Restore user session from stored tokens
9102
9364
  *
9103
- * Call this method after SDK initialization to restore the user's session
9104
- * if valid tokens exist. This is useful for maintaining login state across
9105
- * app restarts.
9365
+ * **Note:** This method is called automatically on SDK initialization when
9366
+ * `autoRestoreSession` is enabled (default: true). You only need to call this
9367
+ * manually if you disabled auto-restore or need to force a session refresh.
9368
+ *
9369
+ * Validates stored tokens and fetches user data to restore the session.
9370
+ * Emits `session_restored` event on success, `session_restoration_failed` on error.
9106
9371
  *
9107
9372
  * **Important:** Only works for USER and BUSINESS accounts. Admin/tenant
9108
9373
  * accounts don't support user data fetching, so this will return null for them
9109
9374
  * (though their tokens remain valid for API calls).
9110
9375
  *
9111
- * Emits auth domain success event when session is restored.
9112
- *
9113
9376
  * @returns Promise resolving to User data if session restored, null if no session or admin account
9114
9377
  * @throws {PersError} If token validation or user fetch fails
9115
9378
  *
9116
9379
  * @example
9117
9380
  * ```typescript
9118
- * // Call after initial render for better perceived performance
9381
+ * // Manual restore (only needed if autoRestoreSession: false)
9119
9382
  * const user = await sdk.restoreSession();
9120
9383
  * if (user) {
9121
9384
  * console.log('Welcome back,', user.name);
@@ -9129,25 +9392,57 @@ class PersSDK {
9129
9392
  }
9130
9393
  // Check auth type - only restore session for user and business accounts
9131
9394
  const authProvider = this.apiClient.getConfig().authProvider;
9132
- if (authProvider?.getAuthType) {
9133
- const authType = await authProvider.getAuthType();
9134
- if (authType === AccountOwnerType.TENANT) {
9135
- // Admin sessions don't support getCurrentUser(), skip restoration
9136
- // Tokens are valid and will be used for API calls
9395
+ const authType = authProvider?.getAuthType ? await authProvider.getAuthType() : AccountOwnerType.USER;
9396
+ if (authType === AccountOwnerType.TENANT) {
9397
+ // Ensure token is valid (refresh if expired) before fetching admin
9398
+ try {
9399
+ await this.auth.ensureValidToken();
9400
+ // Fetch current admin data
9401
+ const adminData = await this.auth.getCurrentAdmin();
9402
+ // Emit session restored for tenant admin
9403
+ this._events.emitSuccess({
9404
+ type: 'session_restored',
9405
+ domain: 'authentication',
9406
+ userMessage: 'Admin session restored successfully',
9407
+ details: { admin: adminData }
9408
+ });
9137
9409
  return null;
9138
9410
  }
9411
+ catch (error) {
9412
+ await this.auth.clearAuth();
9413
+ this._events.emitError({
9414
+ type: 'session_restoration_failed',
9415
+ domain: 'authentication',
9416
+ userMessage: 'Admin session restoration failed',
9417
+ code: 'SESSION_INVALID',
9418
+ details: { error }
9419
+ });
9420
+ throw error;
9421
+ }
9139
9422
  }
9140
9423
  try {
9141
9424
  // Ensure token is valid (refresh if expired) before fetching user
9142
9425
  await this.auth.ensureValidToken();
9143
- // Fetch user data to restore session
9426
+ // For BUSINESS auth, only fetch business context (no access to /users/me)
9427
+ if (authType === AccountOwnerType.BUSINESS) {
9428
+ const businessData = await this.auth.getCurrentBusiness();
9429
+ // Emit event with business data (no user data for business auth)
9430
+ this._events.emitSuccess({
9431
+ type: 'session_restored',
9432
+ domain: 'authentication',
9433
+ userMessage: 'Business session restored successfully',
9434
+ details: { business: businessData }
9435
+ });
9436
+ return null; // No user data for business auth
9437
+ }
9438
+ // For USER auth, fetch user data
9144
9439
  const userData = await this.auth.getCurrentUser();
9145
- // Emit event through proper event emitter
9440
+ // Emit event with user data
9146
9441
  this._events.emitSuccess({
9147
9442
  type: 'session_restored',
9148
9443
  domain: 'authentication',
9149
9444
  userMessage: 'Session restored successfully',
9150
- details: { userId: userData.id }
9445
+ details: { user: userData }
9151
9446
  });
9152
9447
  return userData;
9153
9448
  }
@@ -9652,4 +9947,4 @@ function createPersSDK(httpClient, config) {
9652
9947
  }
9653
9948
 
9654
9949
  export { AuthStatus as A, BusinessManager as B, CampaignManager as C, DefaultAuthProvider as D, FileApi as E, FileManager as F, FileService as G, ApiKeyApi as H, WebhookApi as I, WebhookService as J, PersEventsClient as K, LocalStorageTokenStorage as L, MemoryTokenStorage as M, createPersEventsClient as N, PersSDK as P, RedemptionManager as R, SDK_NAME as S, TokenManager as T, UserManager as U, WebDPoPCryptoProvider as W, AuthTokenManager as a, AUTH_STORAGE_KEYS as b, createPersSDK as c, DPOP_STORAGE_KEYS as d, SDK_VERSION as e, SDK_USER_AGENT as f, PersApiClient as g, DEFAULT_PERS_CONFIG as h, buildApiRoot as i, buildWalletEventsWsUrl as j, StaticJwtAuthProvider as k, AuthApi as l, mergeWithDefaults as m, AuthService as n, DPoPManager as o, PersEventEmitter as p, AuthManager as q, UserStatusManager as r, TransactionManager as s, PurchaseManager as t, ApiKeyManager as u, AnalyticsManager as v, DonationManager as w, TriggerSourceManager as x, WebhookManager as y, WalletEventsManager as z };
9655
- //# sourceMappingURL=pers-sdk-DgSbePI0.js.map
9950
+ //# sourceMappingURL=pers-sdk-Ddw3SoDH.js.map