@explorins/pers-sdk 2.1.23 → 2.1.24

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 (107) 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-rmjhPvHo.cjs → pers-sdk-DXCcAgUS.cjs} +370 -85
  26. package/dist/chunks/pers-sdk-DXCcAgUS.cjs.map +1 -0
  27. package/dist/chunks/{pers-sdk-DgSbePI0.js → pers-sdk-DkCRHY5i.js} +370 -85
  28. package/dist/chunks/pers-sdk-DkCRHY5i.js.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/services/auth-service.d.ts +24 -3
  48. package/dist/core/auth/services/auth-service.d.ts.map +1 -1
  49. package/dist/core/events/event-emitter.d.ts +13 -1
  50. package/dist/core/events/event-emitter.d.ts.map +1 -1
  51. package/dist/core/events/event-types.d.ts +11 -0
  52. package/dist/core/events/event-types.d.ts.map +1 -1
  53. package/dist/core/pers-config.d.ts +13 -0
  54. package/dist/core/pers-config.d.ts.map +1 -1
  55. package/dist/core.cjs +5 -5
  56. package/dist/core.js +5 -5
  57. package/dist/index.cjs +5 -5
  58. package/dist/index.d.ts +2 -2
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +5 -5
  61. package/dist/managers/auth-manager.d.ts +61 -3
  62. package/dist/managers/auth-manager.d.ts.map +1 -1
  63. package/dist/managers/business-manager.d.ts +4 -4
  64. package/dist/managers/business-manager.d.ts.map +1 -1
  65. package/dist/managers/campaign-manager.d.ts +33 -39
  66. package/dist/managers/campaign-manager.d.ts.map +1 -1
  67. package/dist/managers/events-manager.d.ts.map +1 -1
  68. package/dist/managers/index.d.ts +1 -0
  69. package/dist/managers/index.d.ts.map +1 -1
  70. package/dist/managers/redemption-manager.d.ts +25 -3
  71. package/dist/managers/redemption-manager.d.ts.map +1 -1
  72. package/dist/managers/tenant-manager.d.ts +16 -0
  73. package/dist/managers/tenant-manager.d.ts.map +1 -1
  74. package/dist/node.cjs +5 -5
  75. package/dist/node.js +5 -5
  76. package/dist/package.json +2 -2
  77. package/dist/pers-sdk.d.ts +12 -6
  78. package/dist/pers-sdk.d.ts.map +1 -1
  79. package/dist/redemption/api/redemption-api.d.ts +5 -11
  80. package/dist/redemption/api/redemption-api.d.ts.map +1 -1
  81. package/dist/redemption/index.d.ts +2 -1
  82. package/dist/redemption/index.d.ts.map +1 -1
  83. package/dist/redemption/models/index.d.ts +17 -3
  84. package/dist/redemption/models/index.d.ts.map +1 -1
  85. package/dist/redemption/services/redemption-service.d.ts +13 -18
  86. package/dist/redemption/services/redemption-service.d.ts.map +1 -1
  87. package/dist/redemption.cjs +1 -1
  88. package/dist/redemption.js +1 -1
  89. package/dist/tenant/api/tenant-api.d.ts +7 -0
  90. package/dist/tenant/api/tenant-api.d.ts.map +1 -1
  91. package/dist/tenant/services/tenant-service.d.ts +4 -0
  92. package/dist/tenant/services/tenant-service.d.ts.map +1 -1
  93. package/dist/tenant.cjs +1 -1
  94. package/dist/tenant.js +1 -1
  95. package/dist/web3-manager.cjs +3 -3
  96. package/dist/web3-manager.js +3 -3
  97. package/dist/web3.cjs +3 -3
  98. package/dist/web3.js +3 -3
  99. package/package.json +2 -2
  100. package/dist/chunks/business-membership-service-BfHzIQlc.cjs.map +0 -1
  101. package/dist/chunks/business-membership-service-CFa-TI39.js.map +0 -1
  102. package/dist/chunks/pers-sdk-DgSbePI0.js.map +0 -1
  103. package/dist/chunks/pers-sdk-rmjhPvHo.cjs.map +0 -1
  104. package/dist/chunks/redemption-service-B6ZlAV6_.cjs.map +0 -1
  105. package/dist/chunks/redemption-service-C0vys0OQ.js.map +0 -1
  106. package/dist/chunks/tenant-service-BnTAZCxS.js.map +0 -1
  107. 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);
358
- }
359
- if (authType && extendedProvider.setAuthType) {
360
- console.log('[AuthService] Storing auth type:', authType);
361
- await extendedProvider.setAuthType(authType);
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
+ }
362
448
  }
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);
@@ -1401,6 +1487,7 @@ function generateEventId() {
1401
1487
  *
1402
1488
  * All events flow through one subscription point.
1403
1489
  * Optional filtering at subscription level.
1490
+ * Supports replay of last auth event for late subscribers.
1404
1491
  *
1405
1492
  * @example Basic Usage
1406
1493
  * ```typescript
@@ -1424,6 +1511,13 @@ function generateEventId() {
1424
1511
  * showNotification(event.userMessage);
1425
1512
  * }, { excludeDomains: ['validation'] });
1426
1513
  *
1514
+ * // Subscribe with replay - get last auth event if missed
1515
+ * sdk.events.subscribe((event) => {
1516
+ * if (event.type === 'session_restored') {
1517
+ * setUser(event.details.user);
1518
+ * }
1519
+ * }, { domains: ['authentication'], replay: true });
1520
+ *
1427
1521
  * // Cleanup
1428
1522
  * unsubscribe();
1429
1523
  * ```
@@ -1431,6 +1525,8 @@ function generateEventId() {
1431
1525
  let emitterInstanceCounter = 0;
1432
1526
  class PersEventEmitter {
1433
1527
  constructor() {
1528
+ // Store last auth event for replay to late subscribers
1529
+ this.lastAuthEvent = null;
1434
1530
  this.handlers = new Set();
1435
1531
  this._instanceId = ++emitterInstanceCounter;
1436
1532
  }
@@ -1441,7 +1537,7 @@ class PersEventEmitter {
1441
1537
  * Subscribe to events
1442
1538
  *
1443
1539
  * @param handler - Callback for matching events
1444
- * @param filter - Optional filter by domain and/or level
1540
+ * @param filter - Optional filter by domain and/or level. Set `replay: true` to receive last auth event if missed.
1445
1541
  * @returns Unsubscribe function
1446
1542
  *
1447
1543
  * @example All events
@@ -1465,10 +1561,35 @@ class PersEventEmitter {
1465
1561
  * confetti();
1466
1562
  * }, { domains: ['transaction'], levels: ['success'] });
1467
1563
  * ```
1564
+ *
1565
+ * @example Auth events with replay (catches session_restored even if emitted before subscription)
1566
+ * ```typescript
1567
+ * sdk.events.subscribe((event) => {
1568
+ * if (event.type === 'session_restored') {
1569
+ * const { user } = event.details;
1570
+ * setUser(user);
1571
+ * }
1572
+ * }, { domains: ['authentication'], replay: true });
1573
+ * ```
1468
1574
  */
1469
1575
  subscribe(handler, filter) {
1470
1576
  const filteredHandler = { handler, filter };
1471
1577
  this.handlers.add(filteredHandler);
1578
+ // If replay is requested and we have a cached auth event, replay it immediately
1579
+ if (filter?.replay && this.lastAuthEvent) {
1580
+ // Check if event matches the filter
1581
+ if (!filter || this.matchesFilter(this.lastAuthEvent, filter)) {
1582
+ // Use queueMicrotask to ensure handler runs after subscribe returns
1583
+ queueMicrotask(() => {
1584
+ try {
1585
+ handler(this.lastAuthEvent);
1586
+ }
1587
+ catch (error) {
1588
+ console.error('[PersEventEmitter] Replay handler error:', error);
1589
+ }
1590
+ });
1591
+ }
1592
+ }
1472
1593
  return () => this.handlers.delete(filteredHandler);
1473
1594
  }
1474
1595
  /**
@@ -1493,6 +1614,7 @@ class PersEventEmitter {
1493
1614
  * Emit a success event
1494
1615
  *
1495
1616
  * Domain is restricted to business domains only (Domain type).
1617
+ * Auth events (login_success, session_restored) are cached for replay to late subscribers.
1496
1618
  *
1497
1619
  * @param event - Success event data (id and timestamp auto-generated)
1498
1620
  * @returns The complete event object
@@ -1513,6 +1635,15 @@ class PersEventEmitter {
1513
1635
  id: generateEventId(),
1514
1636
  timestamp: Date.now()
1515
1637
  };
1638
+ // Cache auth events for replay to late subscribers
1639
+ if (event.domain === 'authentication' &&
1640
+ (event.type === 'login_success' || event.type === 'session_restored')) {
1641
+ this.lastAuthEvent = fullEvent;
1642
+ }
1643
+ // Clear cached auth on logout
1644
+ if (event.domain === 'authentication' && event.type === 'logout_success') {
1645
+ this.lastAuthEvent = null;
1646
+ }
1516
1647
  this.notifyHandlers(fullEvent);
1517
1648
  return fullEvent;
1518
1649
  }
@@ -1540,6 +1671,10 @@ class PersEventEmitter {
1540
1671
  id: generateEventId(),
1541
1672
  timestamp: Date.now()
1542
1673
  };
1674
+ // Clear cached auth on auth failure (session invalid)
1675
+ if (event.domain === 'authentication' && event.type === 'session_restoration_failed') {
1676
+ this.lastAuthEvent = null;
1677
+ }
1543
1678
  this.notifyHandlers(fullEvent);
1544
1679
  return fullEvent;
1545
1680
  }
@@ -1663,7 +1798,8 @@ class AuthManager {
1663
1798
  this.events?.emitSuccess({
1664
1799
  domain: 'authentication',
1665
1800
  type: 'login_success',
1666
- userMessage: 'Successfully logged in'
1801
+ userMessage: 'Successfully logged in',
1802
+ details: { user: result.user }
1667
1803
  });
1668
1804
  return result;
1669
1805
  }
@@ -1711,7 +1847,66 @@ class AuthManager {
1711
1847
  */
1712
1848
  async loginAsBusiness(jwtToken, options) {
1713
1849
  const authService = this.apiClient.getAuthService();
1714
- return authService.loginBusiness(jwtToken, options);
1850
+ const result = await authService.loginBusiness(jwtToken, options);
1851
+ this.events?.emitSuccess({
1852
+ domain: 'authentication',
1853
+ type: 'login_success',
1854
+ userMessage: 'Successfully logged in as business',
1855
+ details: { user: result.user, business: result.business }
1856
+ });
1857
+ return result;
1858
+ }
1859
+ /**
1860
+ * Login as tenant admin with JWT token
1861
+ *
1862
+ * Authenticates an admin in a tenant context.
1863
+ *
1864
+ * **Auto-Selection Behavior:**
1865
+ * - If admin has access to a single tenant, it's auto-selected
1866
+ * - If admin has access to multiple tenants and no tenantId is provided,
1867
+ * throws `MULTIPLE_CONTEXT_SELECTION_REQUIRED` error with available options
1868
+ *
1869
+ * @param jwtToken - JWT token from auth provider (Firebase, etc.)
1870
+ * @param options - Tenant authentication options (tenantId for multi-tenant admins)
1871
+ * @returns Promise resolving to authentication response with tenant context
1872
+ * @throws Error with code `MULTIPLE_CONTEXT_SELECTION_REQUIRED` when tenantId is needed
1873
+ *
1874
+ * @example Single Tenant Access
1875
+ * ```typescript
1876
+ * // Auto-selects the admin's only tenant
1877
+ * const result = await sdk.auth.loginAsTenant(jwt);
1878
+ * console.log('Tenant:', result.admin?.tenantId);
1879
+ * ```
1880
+ *
1881
+ * @example Multiple Tenant Access
1882
+ * ```typescript
1883
+ * try {
1884
+ * const result = await sdk.auth.loginAsTenant(jwt);
1885
+ * } catch (error) {
1886
+ * if (error.code === 'MULTIPLE_CONTEXT_SELECTION_REQUIRED') {
1887
+ * // Show tenant selector UI
1888
+ * const selectedId = await showTenantSelector(error.details.availableOptions);
1889
+ * const result = await sdk.auth.loginAsTenant(jwt, { tenantId: selectedId });
1890
+ * }
1891
+ * }
1892
+ * ```
1893
+ *
1894
+ * @example Direct Tenant Selection
1895
+ * ```typescript
1896
+ * const result = await sdk.auth.loginAsTenant(jwt, { tenantId: 'tenant-123' });
1897
+ * console.log('Authenticated as admin for tenant:', result.admin?.tenantId);
1898
+ * ```
1899
+ */
1900
+ async loginAsTenant(jwtToken, options) {
1901
+ const authService = this.apiClient.getAuthService();
1902
+ const result = await authService.loginTenantAdmin(jwtToken, options);
1903
+ this.events?.emitSuccess({
1904
+ domain: 'authentication',
1905
+ type: 'login_success',
1906
+ userMessage: 'Successfully logged in as tenant admin',
1907
+ details: { admin: result.admin }
1908
+ });
1909
+ return result;
1715
1910
  }
1716
1911
  /**
1717
1912
  * Get current business context
@@ -1729,7 +1924,27 @@ class AuthManager {
1729
1924
  * ```
1730
1925
  */
1731
1926
  async getCurrentBusiness() {
1732
- return this.apiClient.get('/businesses/me');
1927
+ const authService = this.apiClient.getAuthService();
1928
+ return authService.getCurrentBusiness();
1929
+ }
1930
+ /**
1931
+ * Get current admin context
1932
+ *
1933
+ * Retrieves the current admin data if authenticated as tenant admin.
1934
+ * Requires prior tenant authentication via {@link loginAsTenant}.
1935
+ *
1936
+ * @returns Promise resolving to current admin data
1937
+ * @throws {PersApiError} When not authenticated as tenant admin
1938
+ *
1939
+ * @example
1940
+ * ```typescript
1941
+ * const admin = await sdk.auth.getCurrentAdmin();
1942
+ * console.log('Current admin:', admin.email);
1943
+ * ```
1944
+ */
1945
+ async getCurrentAdmin() {
1946
+ const authService = this.apiClient.getAuthService();
1947
+ return authService.getCurrentAdmin();
1733
1948
  }
1734
1949
  /**
1735
1950
  * Login with raw user data
@@ -1773,7 +1988,8 @@ class AuthManager {
1773
1988
  * ```
1774
1989
  */
1775
1990
  async getCurrentUser() {
1776
- return this.apiClient.get('/users/me');
1991
+ const authService = this.apiClient.getAuthService();
1992
+ return authService.getCurrentUser();
1777
1993
  }
1778
1994
  /**
1779
1995
  * Check if user is authenticated
@@ -4071,58 +4287,52 @@ class CampaignManager {
4071
4287
  async deleteCampaignBusinessEngagement(campaignId, engagementId) {
4072
4288
  return this.campaignService.deleteCampaignBusinessEngagement(campaignId, engagementId);
4073
4289
  }
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
4290
  /**
4106
4291
  * Admin: Get campaign claims with optional filters
4107
4292
  *
4108
- * Retrieves campaign claims with optional filtering by campaign, user, or business.
4293
+ * Retrieves campaign claims with optional filtering by campaign, user, business, or date range.
4109
4294
  * This operation requires administrator privileges and provides system-wide
4110
4295
  * visibility into campaign performance and user engagement.
4111
4296
  *
4112
4297
  * @param filters - Optional filters and pagination options
4298
+ * @param filters.campaignId - Filter by specific campaign ID
4299
+ * @param filters.userId - Filter by specific user ID
4300
+ * @param filters.businessId - Filter by specific business ID
4301
+ * @param filters.dateFrom - Filter claims from this date (inclusive)
4302
+ * @param filters.dateTo - Filter claims until this date (inclusive)
4303
+ * @param filters.page - Page number for pagination
4304
+ * @param filters.limit - Items per page
4305
+ * @param filters.sortBy - Field to sort by
4306
+ * @param filters.sortOrder - Sort direction ('asc' or 'desc')
4307
+ * @param include - Optional relations to include for enrichment
4113
4308
  * @returns Promise resolving to paginated campaign claims
4114
4309
  * @throws {PersApiError} When not authenticated as administrator
4115
4310
  *
4116
- * @example
4311
+ * @example Get All Claims
4117
4312
  * ```typescript
4118
- * // Get all claims
4119
- * const allClaims = await sdk.campaigns.getCampaignClaims();
4313
+ * const { data: allClaims, pagination } = await sdk.campaigns.getCampaignClaims();
4314
+ * console.log(`Total: ${pagination.total}`);
4315
+ * ```
4120
4316
  *
4121
- * // Get claims for specific user
4122
- * const userClaims = await sdk.campaigns.getCampaignClaims({ userId: 'user-123' });
4317
+ * @example Filter by User
4318
+ * ```typescript
4319
+ * const { data: userClaims } = await sdk.campaigns.getCampaignClaims({ userId: 'user-123' });
4320
+ * ```
4123
4321
  *
4124
- * // Get claims for specific campaign with pagination
4125
- * const page1 = await sdk.campaigns.getCampaignClaims({
4322
+ * @example Filter by Date Range
4323
+ * ```typescript
4324
+ * // Get claims within a specific date range
4325
+ * const { data: monthClaims } = await sdk.campaigns.getCampaignClaims({
4326
+ * dateFrom: new Date('2024-01-01'),
4327
+ * dateTo: new Date('2024-01-31'),
4328
+ * limit: 100
4329
+ * });
4330
+ * console.log(`${monthClaims.length} claims in January 2024`);
4331
+ * ```
4332
+ *
4333
+ * @example With Pagination and Campaign Filter
4334
+ * ```typescript
4335
+ * const { data: page1 } = await sdk.campaigns.getCampaignClaims({
4126
4336
  * campaignId: 'campaign-456',
4127
4337
  * page: 1,
4128
4338
  * limit: 50
@@ -4727,9 +4937,19 @@ class RedemptionManager {
4727
4937
  *
4728
4938
  * Retrieves all redemption redeems across the platform with filtering capabilities.
4729
4939
  * 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)
4940
+ * activity. Supports filtering by user, redemption offer, date range, and enrichment of related entities.
4941
+ *
4942
+ * @param filters - Filter options (userId, redemptionId, businessId, status, dateFrom, dateTo, pagination)
4943
+ * @param filters.userId - Filter by specific user ID
4944
+ * @param filters.redemptionId - Filter by specific redemption offer ID
4945
+ * @param filters.businessId - Filter by specific business ID
4946
+ * @param filters.status - Filter by redeem status
4947
+ * @param filters.dateFrom - Filter redeems from this date (inclusive)
4948
+ * @param filters.dateTo - Filter redeems until this date (inclusive)
4949
+ * @param filters.page - Page number for pagination
4950
+ * @param filters.limit - Items per page
4951
+ * @param filters.sortBy - Field to sort by
4952
+ * @param filters.sortOrder - Sort direction ('asc' or 'desc')
4733
4953
  * @param include - Optional relations to include for enrichment
4734
4954
  * @returns Promise resolving to paginated list of redemption redeems
4735
4955
  * @throws {PersApiError} When not authenticated as admin
@@ -4754,6 +4974,18 @@ class RedemptionManager {
4754
4974
  * console.log(`User has ${userRedeems.length} redemptions`);
4755
4975
  * ```
4756
4976
  *
4977
+ * @example Filter by Date Range
4978
+ * ```typescript
4979
+ * // Get redeems within a specific date range
4980
+ * const { data: recentRedeems } = await sdk.redemptions.getRedemptionRedeems({
4981
+ * dateFrom: new Date('2024-01-01'),
4982
+ * dateTo: new Date('2024-01-31'),
4983
+ * limit: 100
4984
+ * });
4985
+ *
4986
+ * console.log(`${recentRedeems.length} redeems in January 2024`);
4987
+ * ```
4988
+ *
4757
4989
  * @example With Enriched Data
4758
4990
  * ```typescript
4759
4991
  * const { data: redeems } = await sdk.redemptions.getRedemptionRedeems(
@@ -8690,7 +8922,8 @@ class WalletEventsManager {
8690
8922
  }
8691
8923
  // Save subscriptions for auto-resubscribe on reconnect
8692
8924
  this.lastSubscriptions.wallets = wallets;
8693
- return this.client.subscribeWallets(wallets);
8925
+ const result = await this.client.subscribeWallets(wallets);
8926
+ return result;
8694
8927
  }
8695
8928
  /**
8696
8929
  * Subscribe to chain events (Admin Dashboard)
@@ -8713,7 +8946,8 @@ class WalletEventsManager {
8713
8946
  }
8714
8947
  // Save subscriptions for auto-resubscribe on reconnect
8715
8948
  this.lastSubscriptions.chains = chains;
8716
- return this.client.subscribeChains(chains);
8949
+ const result = await this.client.subscribeChains(chains);
8950
+ return result;
8717
8951
  }
8718
8952
  /**
8719
8953
  * Unsubscribe from wallet events
@@ -9023,6 +9257,24 @@ class PersSDK {
9023
9257
  this.apiClient.setEvents(this._events);
9024
9258
  // Auto-connect to wallet events on successful login (if enabled)
9025
9259
  this.setupWalletEventsAutoConnect();
9260
+ // Auto-restore session from stored tokens (if enabled, default: true)
9261
+ this.setupAutoRestoreSession();
9262
+ }
9263
+ /**
9264
+ * Setup automatic session restoration from stored tokens
9265
+ * @internal
9266
+ */
9267
+ setupAutoRestoreSession() {
9268
+ const config = this.apiClient.getConfig();
9269
+ // Check if autoRestoreSession is enabled (default: true)
9270
+ if (config.autoRestoreSession === false) {
9271
+ return;
9272
+ }
9273
+ // Fire-and-forget: restore session asynchronously
9274
+ // Events will be emitted on success/failure
9275
+ this.restoreSession().catch(() => {
9276
+ // Error already emitted via session_restoration_failed event
9277
+ });
9026
9278
  }
9027
9279
  /**
9028
9280
  * Setup auto-connect for wallet events on authentication
@@ -9100,22 +9352,23 @@ class PersSDK {
9100
9352
  /**
9101
9353
  * Restore user session from stored tokens
9102
9354
  *
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.
9355
+ * **Note:** This method is called automatically on SDK initialization when
9356
+ * `autoRestoreSession` is enabled (default: true). You only need to call this
9357
+ * manually if you disabled auto-restore or need to force a session refresh.
9358
+ *
9359
+ * Validates stored tokens and fetches user data to restore the session.
9360
+ * Emits `session_restored` event on success, `session_restoration_failed` on error.
9106
9361
  *
9107
9362
  * **Important:** Only works for USER and BUSINESS accounts. Admin/tenant
9108
9363
  * accounts don't support user data fetching, so this will return null for them
9109
9364
  * (though their tokens remain valid for API calls).
9110
9365
  *
9111
- * Emits auth domain success event when session is restored.
9112
- *
9113
9366
  * @returns Promise resolving to User data if session restored, null if no session or admin account
9114
9367
  * @throws {PersError} If token validation or user fetch fails
9115
9368
  *
9116
9369
  * @example
9117
9370
  * ```typescript
9118
- * // Call after initial render for better perceived performance
9371
+ * // Manual restore (only needed if autoRestoreSession: false)
9119
9372
  * const user = await sdk.restoreSession();
9120
9373
  * if (user) {
9121
9374
  * console.log('Welcome back,', user.name);
@@ -9129,25 +9382,57 @@ class PersSDK {
9129
9382
  }
9130
9383
  // Check auth type - only restore session for user and business accounts
9131
9384
  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
9385
+ const authType = authProvider?.getAuthType ? await authProvider.getAuthType() : AccountOwnerType.USER;
9386
+ if (authType === AccountOwnerType.TENANT) {
9387
+ // Ensure token is valid (refresh if expired) before fetching admin
9388
+ try {
9389
+ await this.auth.ensureValidToken();
9390
+ // Fetch current admin data
9391
+ const adminData = await this.auth.getCurrentAdmin();
9392
+ // Emit session restored for tenant admin
9393
+ this._events.emitSuccess({
9394
+ type: 'session_restored',
9395
+ domain: 'authentication',
9396
+ userMessage: 'Admin session restored successfully',
9397
+ details: { admin: adminData }
9398
+ });
9137
9399
  return null;
9138
9400
  }
9401
+ catch (error) {
9402
+ await this.auth.clearAuth();
9403
+ this._events.emitError({
9404
+ type: 'session_restoration_failed',
9405
+ domain: 'authentication',
9406
+ userMessage: 'Admin session restoration failed',
9407
+ code: 'SESSION_INVALID',
9408
+ details: { error }
9409
+ });
9410
+ throw error;
9411
+ }
9139
9412
  }
9140
9413
  try {
9141
9414
  // Ensure token is valid (refresh if expired) before fetching user
9142
9415
  await this.auth.ensureValidToken();
9143
- // Fetch user data to restore session
9416
+ // For BUSINESS auth, only fetch business context (no access to /users/me)
9417
+ if (authType === AccountOwnerType.BUSINESS) {
9418
+ const businessData = await this.auth.getCurrentBusiness();
9419
+ // Emit event with business data (no user data for business auth)
9420
+ this._events.emitSuccess({
9421
+ type: 'session_restored',
9422
+ domain: 'authentication',
9423
+ userMessage: 'Business session restored successfully',
9424
+ details: { business: businessData }
9425
+ });
9426
+ return null; // No user data for business auth
9427
+ }
9428
+ // For USER auth, fetch user data
9144
9429
  const userData = await this.auth.getCurrentUser();
9145
- // Emit event through proper event emitter
9430
+ // Emit event with user data
9146
9431
  this._events.emitSuccess({
9147
9432
  type: 'session_restored',
9148
9433
  domain: 'authentication',
9149
9434
  userMessage: 'Session restored successfully',
9150
- details: { userId: userData.id }
9435
+ details: { user: userData }
9151
9436
  });
9152
9437
  return userData;
9153
9438
  }
@@ -9652,4 +9937,4 @@ function createPersSDK(httpClient, config) {
9652
9937
  }
9653
9938
 
9654
9939
  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
9940
+ //# sourceMappingURL=pers-sdk-DkCRHY5i.js.map