@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
@@ -5,12 +5,12 @@ var index = require('./index-CVuttuU8.cjs');
5
5
  var user = require('../user.cjs');
6
6
  var userStatus = require('../user-status.cjs');
7
7
  var tokenService = require('./token-service-C1xe11OX.cjs');
8
- var businessMembershipService = require('./business-membership-service-BfHzIQlc.cjs');
8
+ var businessMembershipService = require('./business-membership-service-DXLG5fP9.cjs');
9
9
  var campaign = require('../campaign.cjs');
10
- var redemptionService = require('./redemption-service-B6ZlAV6_.cjs');
10
+ var redemptionService = require('./redemption-service-5Mu78Sne.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-BIQONvmF.cjs');
13
+ var tenantManager = require('./tenant-manager-D3toTiB9.cjs');
14
14
  var paginationUtils = require('./pagination-utils-B2jRHMSO.cjs');
15
15
  var analyticsService = require('./analytics-service-CF9AsMQH.cjs');
16
16
  var donation = require('../donation.cjs');
@@ -32,7 +32,8 @@ const DEFAULT_PERS_CONFIG = {
32
32
  retries: 3,
33
33
  tokenRefreshMargin: 60, // Refresh tokens 60 seconds before expiry
34
34
  backgroundRefreshThreshold: 30, // Use background refresh if >30s remaining
35
- captureWalletEvents: true // Auto-connect to wallet events after auth
35
+ captureWalletEvents: true, // Auto-connect to wallet events after auth
36
+ autoRestoreSession: true // Auto-restore session from stored tokens on init
36
37
  };
37
38
  /**
38
39
  * Build the API root URL based on config
@@ -99,11 +100,28 @@ class AuthApi {
99
100
  }
100
101
  /**
101
102
  * Login tenant admin with JWT
103
+ *
104
+ * Authenticates an admin in a tenant context.
105
+ *
106
+ * @param jwt - Authentication token (Firebase JWT)
107
+ * @param options - Tenant authentication options (tenantId for multi-tenant admins)
108
+ * @returns Session response with tenant context
109
+ * @throws MultipleContextSelectionError when tenantId is required but not provided
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // Single tenant - auto-selects
114
+ * const response = await authApi.loginTenantAdmin(jwt);
115
+ *
116
+ * // Multiple tenants - explicit selection
117
+ * const response = await authApi.loginTenantAdmin(jwt, { tenantId: 'tenant-123' });
118
+ * ```
102
119
  */
103
- async loginTenantAdmin(jwt) {
120
+ async loginTenantAdmin(jwt, options) {
104
121
  const body = {
105
122
  authToken: jwt,
106
- authType: persShared.AccountOwnerType.TENANT
123
+ authType: persShared.AccountOwnerType.TENANT,
124
+ context: options?.tenantId ? { tenantId: options.tenantId } : undefined
107
125
  };
108
126
  return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
109
127
  }
@@ -161,6 +179,30 @@ class AuthApi {
161
179
  async refreshAccessToken(refreshToken) {
162
180
  return this.apiClient.post(`${this.basePath}/refresh`, { refreshToken }, { bypassAuth: true, isRefreshRequest: true });
163
181
  }
182
+ // ==========================================
183
+ // IDENTITY VERIFICATION (for session restore)
184
+ // Note: These duplicate calls in domain APIs (user-api, business-api)
185
+ // but are kept here to avoid circular dependencies during initialization.
186
+ // If endpoints change, update both locations.
187
+ // ==========================================
188
+ /**
189
+ * Get current authenticated user
190
+ */
191
+ async getCurrentUser() {
192
+ return this.apiClient.get('/users/me');
193
+ }
194
+ /**
195
+ * Get current business context
196
+ */
197
+ async getCurrentBusiness() {
198
+ return this.apiClient.get('/businesses/me');
199
+ }
200
+ /**
201
+ * Get current admin context
202
+ */
203
+ async getCurrentAdmin() {
204
+ return this.apiClient.get('/admins/me');
205
+ }
164
206
  }
165
207
 
166
208
  /**
@@ -185,6 +227,12 @@ exports.AuthStatus = void 0;
185
227
  AuthStatus["SESSION_RESTORATION_FAILED"] = "session_restoration_failed";
186
228
  })(exports.AuthStatus || (exports.AuthStatus = {}));
187
229
 
230
+ /**
231
+ * Type guard to check if provider implements extended storage methods
232
+ */
233
+ function isExtendedProvider(provider) {
234
+ return 'setAuthType' in provider && typeof provider.setAuthType === 'function';
235
+ }
188
236
  /**
189
237
  * Platform-agnostic authentication service
190
238
  * Handles login, token refresh, and storage operations
@@ -196,6 +244,12 @@ class AuthService {
196
244
  this.activeRefreshPromise = null;
197
245
  this.currentAuthStatus = exports.AuthStatus.UNAUTHENTICATED;
198
246
  }
247
+ /**
248
+ * Get extended provider if available, null otherwise
249
+ */
250
+ get extendedProvider() {
251
+ return this.authProvider && isExtendedProvider(this.authProvider) ? this.authProvider : null;
252
+ }
199
253
  /**
200
254
  * Emit auth status change to the app
201
255
  */
@@ -203,9 +257,10 @@ class AuthService {
203
257
  if (this.currentAuthStatus === status)
204
258
  return; // No change
205
259
  this.currentAuthStatus = status;
206
- if (this.authProvider && typeof this.authProvider.onAuthStatusChange === 'function') {
260
+ const extended = this.extendedProvider;
261
+ if (extended?.onAuthStatusChange) {
207
262
  try {
208
- await this.authProvider.onAuthStatusChange(status);
263
+ await extended.onAuthStatusChange(status);
209
264
  }
210
265
  catch (error) {
211
266
  console.warn('[AuthService] Auth status change callback failed:', error);
@@ -217,9 +272,14 @@ class AuthService {
217
272
  // ==========================================
218
273
  /**
219
274
  * Login tenant admin with JWT
275
+ *
276
+ * @param jwt - Authentication token (Firebase JWT)
277
+ * @param options - Tenant authentication options (tenantId for multi-tenant admins)
278
+ * @returns Session response with tenant context
279
+ * @throws Error with code MULTIPLE_CONTEXT_SELECTION_REQUIRED when tenantId is required but not provided
220
280
  */
221
- async loginTenantAdmin(jwt) {
222
- const response = await this.authApi.loginTenantAdmin(jwt);
281
+ async loginTenantAdmin(jwt, options) {
282
+ const response = await this.authApi.loginTenantAdmin(jwt, options);
223
283
  if (this.authProvider && response.accessToken) {
224
284
  await this.storeTokens(response.accessToken, response.refreshToken, persShared.AccountOwnerType.TENANT, jwt);
225
285
  }
@@ -300,9 +360,13 @@ class AuthService {
300
360
  if (!tokenToUse) {
301
361
  throw new Error('No refresh token available for token refresh');
302
362
  }
363
+ // Get the current authType to preserve it after refresh
364
+ const extended = this.extendedProvider;
365
+ const currentAuthType = extended?.getAuthType ? await extended.getAuthType() ?? undefined : undefined;
303
366
  const response = await this.authApi.refreshAccessToken(tokenToUse);
304
367
  if (this.authProvider && response.accessToken) {
305
- await this.storeTokens(response.accessToken, response.refreshToken);
368
+ // Preserve the authType during refresh
369
+ await this.storeTokens(response.accessToken, response.refreshToken, currentAuthType);
306
370
  }
307
371
  return response;
308
372
  }
@@ -340,6 +404,27 @@ class AuthService {
340
404
  return !!token;
341
405
  }
342
406
  // ==========================================
407
+ // CONTEXT RETRIEVAL
408
+ // ==========================================
409
+ /**
410
+ * Get current authenticated user
411
+ */
412
+ async getCurrentUser() {
413
+ return this.authApi.getCurrentUser();
414
+ }
415
+ /**
416
+ * Get current business context
417
+ */
418
+ async getCurrentBusiness() {
419
+ return this.authApi.getCurrentBusiness();
420
+ }
421
+ /**
422
+ * Get current admin context
423
+ */
424
+ async getCurrentAdmin() {
425
+ return this.authApi.getCurrentAdmin();
426
+ }
427
+ // ==========================================
343
428
  // PRIVATE HELPERS
344
429
  // ==========================================
345
430
  /**
@@ -353,17 +438,18 @@ class AuthService {
353
438
  if (refreshToken) {
354
439
  await this.authProvider.setRefreshToken(refreshToken);
355
440
  }
356
- // Type-safe handling of extended token storage features
357
- const extendedProvider = this.authProvider;
358
- if (providerToken && extendedProvider.setProviderToken) {
359
- await extendedProvider.setProviderToken(providerToken);
441
+ // Handle optional extended storage methods
442
+ const extended = this.extendedProvider;
443
+ if (extended) {
444
+ if (providerToken && extended.setProviderToken) {
445
+ await extended.setProviderToken(providerToken);
446
+ }
447
+ if (authType && extended.setAuthType) {
448
+ await extended.setAuthType(authType);
449
+ }
360
450
  }
361
- if (authType && extendedProvider.setAuthType) {
362
- console.log('[AuthService] Storing auth type:', authType);
363
- await extendedProvider.setAuthType(authType);
364
- }
365
- else {
366
- console.warn('[AuthService] Auth type not stored - authType:', authType, 'has setAuthType:', !!extendedProvider.setAuthType);
451
+ else if (authType) {
452
+ console.warn('[AuthService] Auth type not stored - provider does not implement setAuthType');
367
453
  }
368
454
  // Emit authenticated status on successful token storage
369
455
  await this.emitAuthStatus(exports.AuthStatus.AUTHENTICATED);
@@ -908,6 +994,11 @@ class DefaultAuthProvider {
908
994
  async hasValidToken() {
909
995
  return this.tokenManager.hasAccessToken();
910
996
  }
997
+ async setAuthType(authType) {
998
+ // Auth type is derived from JWT, so this is a no-op
999
+ // The authType in JWT is the source of truth
1000
+ // This method exists to satisfy the ExtendedTokenStorageProvider interface
1001
+ }
911
1002
  async getAuthType() {
912
1003
  // Read from JWT instead of separate storage for single source of truth
913
1004
  const token = await this.tokenManager.getAccessToken();
@@ -1403,6 +1494,7 @@ function generateEventId() {
1403
1494
  *
1404
1495
  * All events flow through one subscription point.
1405
1496
  * Optional filtering at subscription level.
1497
+ * Supports replay of last auth event for late subscribers.
1406
1498
  *
1407
1499
  * @example Basic Usage
1408
1500
  * ```typescript
@@ -1426,6 +1518,13 @@ function generateEventId() {
1426
1518
  * showNotification(event.userMessage);
1427
1519
  * }, { excludeDomains: ['validation'] });
1428
1520
  *
1521
+ * // Subscribe with replay - get last auth event if missed
1522
+ * sdk.events.subscribe((event) => {
1523
+ * if (event.type === 'session_restored') {
1524
+ * setUser(event.details.user);
1525
+ * }
1526
+ * }, { domains: ['authentication'], replay: true });
1527
+ *
1429
1528
  * // Cleanup
1430
1529
  * unsubscribe();
1431
1530
  * ```
@@ -1433,6 +1532,8 @@ function generateEventId() {
1433
1532
  let emitterInstanceCounter = 0;
1434
1533
  class PersEventEmitter {
1435
1534
  constructor() {
1535
+ // Store last auth event for replay to late subscribers
1536
+ this.lastAuthEvent = null;
1436
1537
  this.handlers = new Set();
1437
1538
  this._instanceId = ++emitterInstanceCounter;
1438
1539
  }
@@ -1443,7 +1544,7 @@ class PersEventEmitter {
1443
1544
  * Subscribe to events
1444
1545
  *
1445
1546
  * @param handler - Callback for matching events
1446
- * @param filter - Optional filter by domain and/or level
1547
+ * @param filter - Optional filter by domain and/or level. Set `replay: true` to receive last auth event if missed.
1447
1548
  * @returns Unsubscribe function
1448
1549
  *
1449
1550
  * @example All events
@@ -1467,10 +1568,35 @@ class PersEventEmitter {
1467
1568
  * confetti();
1468
1569
  * }, { domains: ['transaction'], levels: ['success'] });
1469
1570
  * ```
1571
+ *
1572
+ * @example Auth events with replay (catches session_restored even if emitted before subscription)
1573
+ * ```typescript
1574
+ * sdk.events.subscribe((event) => {
1575
+ * if (event.type === 'session_restored') {
1576
+ * const { user } = event.details;
1577
+ * setUser(user);
1578
+ * }
1579
+ * }, { domains: ['authentication'], replay: true });
1580
+ * ```
1470
1581
  */
1471
1582
  subscribe(handler, filter) {
1472
1583
  const filteredHandler = { handler, filter };
1473
1584
  this.handlers.add(filteredHandler);
1585
+ // If replay is requested and we have a cached auth event, replay it immediately
1586
+ if (filter?.replay && this.lastAuthEvent) {
1587
+ // Check if event matches the filter
1588
+ if (!filter || this.matchesFilter(this.lastAuthEvent, filter)) {
1589
+ // Use queueMicrotask to ensure handler runs after subscribe returns
1590
+ queueMicrotask(() => {
1591
+ try {
1592
+ handler(this.lastAuthEvent);
1593
+ }
1594
+ catch (error) {
1595
+ console.error('[PersEventEmitter] Replay handler error:', error);
1596
+ }
1597
+ });
1598
+ }
1599
+ }
1474
1600
  return () => this.handlers.delete(filteredHandler);
1475
1601
  }
1476
1602
  /**
@@ -1495,6 +1621,7 @@ class PersEventEmitter {
1495
1621
  * Emit a success event
1496
1622
  *
1497
1623
  * Domain is restricted to business domains only (Domain type).
1624
+ * Auth events (login_success, session_restored) are cached for replay to late subscribers.
1498
1625
  *
1499
1626
  * @param event - Success event data (id and timestamp auto-generated)
1500
1627
  * @returns The complete event object
@@ -1515,6 +1642,15 @@ class PersEventEmitter {
1515
1642
  id: generateEventId(),
1516
1643
  timestamp: Date.now()
1517
1644
  };
1645
+ // Cache auth events for replay to late subscribers
1646
+ if (event.domain === 'authentication' &&
1647
+ (event.type === 'login_success' || event.type === 'session_restored')) {
1648
+ this.lastAuthEvent = fullEvent;
1649
+ }
1650
+ // Clear cached auth on logout
1651
+ if (event.domain === 'authentication' && event.type === 'logout_success') {
1652
+ this.lastAuthEvent = null;
1653
+ }
1518
1654
  this.notifyHandlers(fullEvent);
1519
1655
  return fullEvent;
1520
1656
  }
@@ -1542,6 +1678,10 @@ class PersEventEmitter {
1542
1678
  id: generateEventId(),
1543
1679
  timestamp: Date.now()
1544
1680
  };
1681
+ // Clear cached auth on auth failure (session invalid)
1682
+ if (event.domain === 'authentication' && event.type === 'session_restoration_failed') {
1683
+ this.lastAuthEvent = null;
1684
+ }
1545
1685
  this.notifyHandlers(fullEvent);
1546
1686
  return fullEvent;
1547
1687
  }
@@ -1665,7 +1805,8 @@ class AuthManager {
1665
1805
  this.events?.emitSuccess({
1666
1806
  domain: 'authentication',
1667
1807
  type: 'login_success',
1668
- userMessage: 'Successfully logged in'
1808
+ userMessage: 'Successfully logged in',
1809
+ details: { user: result.user }
1669
1810
  });
1670
1811
  return result;
1671
1812
  }
@@ -1713,7 +1854,66 @@ class AuthManager {
1713
1854
  */
1714
1855
  async loginAsBusiness(jwtToken, options) {
1715
1856
  const authService = this.apiClient.getAuthService();
1716
- return authService.loginBusiness(jwtToken, options);
1857
+ const result = await authService.loginBusiness(jwtToken, options);
1858
+ this.events?.emitSuccess({
1859
+ domain: 'authentication',
1860
+ type: 'login_success',
1861
+ userMessage: 'Successfully logged in as business',
1862
+ details: { user: result.user, business: result.business }
1863
+ });
1864
+ return result;
1865
+ }
1866
+ /**
1867
+ * Login as tenant admin with JWT token
1868
+ *
1869
+ * Authenticates an admin in a tenant context.
1870
+ *
1871
+ * **Auto-Selection Behavior:**
1872
+ * - If admin has access to a single tenant, it's auto-selected
1873
+ * - If admin has access to multiple tenants and no tenantId is provided,
1874
+ * throws `MULTIPLE_CONTEXT_SELECTION_REQUIRED` error with available options
1875
+ *
1876
+ * @param jwtToken - JWT token from auth provider (Firebase, etc.)
1877
+ * @param options - Tenant authentication options (tenantId for multi-tenant admins)
1878
+ * @returns Promise resolving to authentication response with tenant context
1879
+ * @throws Error with code `MULTIPLE_CONTEXT_SELECTION_REQUIRED` when tenantId is needed
1880
+ *
1881
+ * @example Single Tenant Access
1882
+ * ```typescript
1883
+ * // Auto-selects the admin's only tenant
1884
+ * const result = await sdk.auth.loginAsTenant(jwt);
1885
+ * console.log('Tenant:', result.admin?.tenantId);
1886
+ * ```
1887
+ *
1888
+ * @example Multiple Tenant Access
1889
+ * ```typescript
1890
+ * try {
1891
+ * const result = await sdk.auth.loginAsTenant(jwt);
1892
+ * } catch (error) {
1893
+ * if (error.code === 'MULTIPLE_CONTEXT_SELECTION_REQUIRED') {
1894
+ * // Show tenant selector UI
1895
+ * const selectedId = await showTenantSelector(error.details.availableOptions);
1896
+ * const result = await sdk.auth.loginAsTenant(jwt, { tenantId: selectedId });
1897
+ * }
1898
+ * }
1899
+ * ```
1900
+ *
1901
+ * @example Direct Tenant Selection
1902
+ * ```typescript
1903
+ * const result = await sdk.auth.loginAsTenant(jwt, { tenantId: 'tenant-123' });
1904
+ * console.log('Authenticated as admin for tenant:', result.admin?.tenantId);
1905
+ * ```
1906
+ */
1907
+ async loginAsTenant(jwtToken, options) {
1908
+ const authService = this.apiClient.getAuthService();
1909
+ const result = await authService.loginTenantAdmin(jwtToken, options);
1910
+ this.events?.emitSuccess({
1911
+ domain: 'authentication',
1912
+ type: 'login_success',
1913
+ userMessage: 'Successfully logged in as tenant admin',
1914
+ details: { admin: result.admin }
1915
+ });
1916
+ return result;
1717
1917
  }
1718
1918
  /**
1719
1919
  * Get current business context
@@ -1731,7 +1931,27 @@ class AuthManager {
1731
1931
  * ```
1732
1932
  */
1733
1933
  async getCurrentBusiness() {
1734
- return this.apiClient.get('/businesses/me');
1934
+ const authService = this.apiClient.getAuthService();
1935
+ return authService.getCurrentBusiness();
1936
+ }
1937
+ /**
1938
+ * Get current admin context
1939
+ *
1940
+ * Retrieves the current admin data if authenticated as tenant admin.
1941
+ * Requires prior tenant authentication via {@link loginAsTenant}.
1942
+ *
1943
+ * @returns Promise resolving to current admin data
1944
+ * @throws {PersApiError} When not authenticated as tenant admin
1945
+ *
1946
+ * @example
1947
+ * ```typescript
1948
+ * const admin = await sdk.auth.getCurrentAdmin();
1949
+ * console.log('Current admin:', admin.email);
1950
+ * ```
1951
+ */
1952
+ async getCurrentAdmin() {
1953
+ const authService = this.apiClient.getAuthService();
1954
+ return authService.getCurrentAdmin();
1735
1955
  }
1736
1956
  /**
1737
1957
  * Login with raw user data
@@ -1775,7 +1995,8 @@ class AuthManager {
1775
1995
  * ```
1776
1996
  */
1777
1997
  async getCurrentUser() {
1778
- return this.apiClient.get('/users/me');
1998
+ const authService = this.apiClient.getAuthService();
1999
+ return authService.getCurrentUser();
1779
2000
  }
1780
2001
  /**
1781
2002
  * Check if user is authenticated
@@ -1853,6 +2074,11 @@ class AuthManager {
1853
2074
  async clearAuth() {
1854
2075
  const authService = this.apiClient.getAuthService();
1855
2076
  await authService.clearTokens();
2077
+ this.events?.emitSuccess({
2078
+ domain: 'authentication',
2079
+ type: 'logout_success',
2080
+ userMessage: 'Successfully logged out'
2081
+ });
1856
2082
  }
1857
2083
  /**
1858
2084
  * Ensure authentication token is valid
@@ -4073,58 +4299,52 @@ class CampaignManager {
4073
4299
  async deleteCampaignBusinessEngagement(campaignId, engagementId) {
4074
4300
  return this.campaignService.deleteCampaignBusinessEngagement(campaignId, engagementId);
4075
4301
  }
4076
- /**
4077
- * Admin: Get all campaign claims
4078
- *
4079
- * Retrieves all campaign claims across the system for comprehensive reporting
4080
- * and analytics. This operation requires administrator privileges and provides
4081
- * system-wide visibility into campaign performance and user engagement.
4082
- *
4083
- * @returns Promise resolving to array of all campaign claims
4084
- * @throws {PersApiError} When not authenticated as administrator
4085
- *
4086
- * @example
4087
- * ```typescript
4088
- * // Admin operation - get campaign performance data
4089
- * const allClaims = await sdk.campaigns.getCampaignClaims();
4090
- *
4091
- * console.log(`Campaign Performance Report:`);
4092
- * console.log(`Total claims: ${allClaims.length}`);
4093
- *
4094
- * // Analyze claims by campaign
4095
- * const claimsByCampaign = allClaims.reduce((acc, claim) => {
4096
- * const campaignId = claim.campaignId;
4097
- * acc[campaignId] = (acc[campaignId] || 0) + 1;
4098
- * return acc;
4099
- * }, {});
4100
- *
4101
- * console.log('\nClaims by Campaign:');
4102
- * Object.entries(claimsByCampaign).forEach(([campaignId, count]) => {
4103
- * console.log(`${campaignId}: ${count} claims`);
4104
- * });
4105
- * ```
4106
- */
4107
4302
  /**
4108
4303
  * Admin: Get campaign claims with optional filters
4109
4304
  *
4110
- * Retrieves campaign claims with optional filtering by campaign, user, or business.
4305
+ * Retrieves campaign claims with optional filtering by campaign, user, business, or date range.
4111
4306
  * This operation requires administrator privileges and provides system-wide
4112
4307
  * visibility into campaign performance and user engagement.
4113
4308
  *
4114
4309
  * @param filters - Optional filters and pagination options
4310
+ * @param filters.campaignId - Filter by specific campaign ID
4311
+ * @param filters.userId - Filter by specific user ID
4312
+ * @param filters.businessId - Filter by specific business ID
4313
+ * @param filters.dateFrom - Filter claims from this date (inclusive)
4314
+ * @param filters.dateTo - Filter claims until this date (inclusive)
4315
+ * @param filters.page - Page number for pagination
4316
+ * @param filters.limit - Items per page
4317
+ * @param filters.sortBy - Field to sort by
4318
+ * @param filters.sortOrder - Sort direction ('asc' or 'desc')
4319
+ * @param include - Optional relations to include for enrichment
4115
4320
  * @returns Promise resolving to paginated campaign claims
4116
4321
  * @throws {PersApiError} When not authenticated as administrator
4117
4322
  *
4118
- * @example
4323
+ * @example Get All Claims
4119
4324
  * ```typescript
4120
- * // Get all claims
4121
- * const allClaims = await sdk.campaigns.getCampaignClaims();
4325
+ * const { data: allClaims, pagination } = await sdk.campaigns.getCampaignClaims();
4326
+ * console.log(`Total: ${pagination.total}`);
4327
+ * ```
4122
4328
  *
4123
- * // Get claims for specific user
4124
- * const userClaims = await sdk.campaigns.getCampaignClaims({ userId: 'user-123' });
4329
+ * @example Filter by User
4330
+ * ```typescript
4331
+ * const { data: userClaims } = await sdk.campaigns.getCampaignClaims({ userId: 'user-123' });
4332
+ * ```
4333
+ *
4334
+ * @example Filter by Date Range
4335
+ * ```typescript
4336
+ * // Get claims within a specific date range
4337
+ * const { data: monthClaims } = await sdk.campaigns.getCampaignClaims({
4338
+ * dateFrom: new Date('2024-01-01'),
4339
+ * dateTo: new Date('2024-01-31'),
4340
+ * limit: 100
4341
+ * });
4342
+ * console.log(`${monthClaims.length} claims in January 2024`);
4343
+ * ```
4125
4344
  *
4126
- * // Get claims for specific campaign with pagination
4127
- * const page1 = await sdk.campaigns.getCampaignClaims({
4345
+ * @example With Pagination and Campaign Filter
4346
+ * ```typescript
4347
+ * const { data: page1 } = await sdk.campaigns.getCampaignClaims({
4128
4348
  * campaignId: 'campaign-456',
4129
4349
  * page: 1,
4130
4350
  * limit: 50
@@ -4729,9 +4949,19 @@ class RedemptionManager {
4729
4949
  *
4730
4950
  * Retrieves all redemption redeems across the platform with filtering capabilities.
4731
4951
  * This is an admin-level operation that allows monitoring and analytics of redemption
4732
- * activity. Supports filtering by user, redemption offer, and enrichment of related entities.
4733
- *
4734
- * @param filters - Filter options (userId, redemptionId, pagination)
4952
+ * activity. Supports filtering by user, redemption offer, date range, and enrichment of related entities.
4953
+ *
4954
+ * @param filters - Filter options (userId, redemptionId, businessId, status, dateFrom, dateTo, pagination)
4955
+ * @param filters.userId - Filter by specific user ID
4956
+ * @param filters.redemptionId - Filter by specific redemption offer ID
4957
+ * @param filters.businessId - Filter by specific business ID
4958
+ * @param filters.status - Filter by redeem status
4959
+ * @param filters.dateFrom - Filter redeems from this date (inclusive)
4960
+ * @param filters.dateTo - Filter redeems until this date (inclusive)
4961
+ * @param filters.page - Page number for pagination
4962
+ * @param filters.limit - Items per page
4963
+ * @param filters.sortBy - Field to sort by
4964
+ * @param filters.sortOrder - Sort direction ('asc' or 'desc')
4735
4965
  * @param include - Optional relations to include for enrichment
4736
4966
  * @returns Promise resolving to paginated list of redemption redeems
4737
4967
  * @throws {PersApiError} When not authenticated as admin
@@ -4756,6 +4986,18 @@ class RedemptionManager {
4756
4986
  * console.log(`User has ${userRedeems.length} redemptions`);
4757
4987
  * ```
4758
4988
  *
4989
+ * @example Filter by Date Range
4990
+ * ```typescript
4991
+ * // Get redeems within a specific date range
4992
+ * const { data: recentRedeems } = await sdk.redemptions.getRedemptionRedeems({
4993
+ * dateFrom: new Date('2024-01-01'),
4994
+ * dateTo: new Date('2024-01-31'),
4995
+ * limit: 100
4996
+ * });
4997
+ *
4998
+ * console.log(`${recentRedeems.length} redeems in January 2024`);
4999
+ * ```
5000
+ *
4759
5001
  * @example With Enriched Data
4760
5002
  * ```typescript
4761
5003
  * const { data: redeems } = await sdk.redemptions.getRedemptionRedeems(
@@ -8692,7 +8934,8 @@ class WalletEventsManager {
8692
8934
  }
8693
8935
  // Save subscriptions for auto-resubscribe on reconnect
8694
8936
  this.lastSubscriptions.wallets = wallets;
8695
- return this.client.subscribeWallets(wallets);
8937
+ const result = await this.client.subscribeWallets(wallets);
8938
+ return result;
8696
8939
  }
8697
8940
  /**
8698
8941
  * Subscribe to chain events (Admin Dashboard)
@@ -8715,7 +8958,8 @@ class WalletEventsManager {
8715
8958
  }
8716
8959
  // Save subscriptions for auto-resubscribe on reconnect
8717
8960
  this.lastSubscriptions.chains = chains;
8718
- return this.client.subscribeChains(chains);
8961
+ const result = await this.client.subscribeChains(chains);
8962
+ return result;
8719
8963
  }
8720
8964
  /**
8721
8965
  * Unsubscribe from wallet events
@@ -9025,6 +9269,24 @@ class PersSDK {
9025
9269
  this.apiClient.setEvents(this._events);
9026
9270
  // Auto-connect to wallet events on successful login (if enabled)
9027
9271
  this.setupWalletEventsAutoConnect();
9272
+ // Auto-restore session from stored tokens (if enabled, default: true)
9273
+ this.setupAutoRestoreSession();
9274
+ }
9275
+ /**
9276
+ * Setup automatic session restoration from stored tokens
9277
+ * @internal
9278
+ */
9279
+ setupAutoRestoreSession() {
9280
+ const config = this.apiClient.getConfig();
9281
+ // Check if autoRestoreSession is enabled (default: true)
9282
+ if (config.autoRestoreSession === false) {
9283
+ return;
9284
+ }
9285
+ // Fire-and-forget: restore session asynchronously
9286
+ // Events will be emitted on success/failure
9287
+ this.restoreSession().catch(() => {
9288
+ // Error already emitted via session_restoration_failed event
9289
+ });
9028
9290
  }
9029
9291
  /**
9030
9292
  * Setup auto-connect for wallet events on authentication
@@ -9102,22 +9364,23 @@ class PersSDK {
9102
9364
  /**
9103
9365
  * Restore user session from stored tokens
9104
9366
  *
9105
- * Call this method after SDK initialization to restore the user's session
9106
- * if valid tokens exist. This is useful for maintaining login state across
9107
- * app restarts.
9367
+ * **Note:** This method is called automatically on SDK initialization when
9368
+ * `autoRestoreSession` is enabled (default: true). You only need to call this
9369
+ * manually if you disabled auto-restore or need to force a session refresh.
9370
+ *
9371
+ * Validates stored tokens and fetches user data to restore the session.
9372
+ * Emits `session_restored` event on success, `session_restoration_failed` on error.
9108
9373
  *
9109
9374
  * **Important:** Only works for USER and BUSINESS accounts. Admin/tenant
9110
9375
  * accounts don't support user data fetching, so this will return null for them
9111
9376
  * (though their tokens remain valid for API calls).
9112
9377
  *
9113
- * Emits auth domain success event when session is restored.
9114
- *
9115
9378
  * @returns Promise resolving to User data if session restored, null if no session or admin account
9116
9379
  * @throws {PersError} If token validation or user fetch fails
9117
9380
  *
9118
9381
  * @example
9119
9382
  * ```typescript
9120
- * // Call after initial render for better perceived performance
9383
+ * // Manual restore (only needed if autoRestoreSession: false)
9121
9384
  * const user = await sdk.restoreSession();
9122
9385
  * if (user) {
9123
9386
  * console.log('Welcome back,', user.name);
@@ -9131,25 +9394,57 @@ class PersSDK {
9131
9394
  }
9132
9395
  // Check auth type - only restore session for user and business accounts
9133
9396
  const authProvider = this.apiClient.getConfig().authProvider;
9134
- if (authProvider?.getAuthType) {
9135
- const authType = await authProvider.getAuthType();
9136
- if (authType === persShared.AccountOwnerType.TENANT) {
9137
- // Admin sessions don't support getCurrentUser(), skip restoration
9138
- // Tokens are valid and will be used for API calls
9397
+ const authType = authProvider?.getAuthType ? await authProvider.getAuthType() : persShared.AccountOwnerType.USER;
9398
+ if (authType === persShared.AccountOwnerType.TENANT) {
9399
+ // Ensure token is valid (refresh if expired) before fetching admin
9400
+ try {
9401
+ await this.auth.ensureValidToken();
9402
+ // Fetch current admin data
9403
+ const adminData = await this.auth.getCurrentAdmin();
9404
+ // Emit session restored for tenant admin
9405
+ this._events.emitSuccess({
9406
+ type: 'session_restored',
9407
+ domain: 'authentication',
9408
+ userMessage: 'Admin session restored successfully',
9409
+ details: { admin: adminData }
9410
+ });
9139
9411
  return null;
9140
9412
  }
9413
+ catch (error) {
9414
+ await this.auth.clearAuth();
9415
+ this._events.emitError({
9416
+ type: 'session_restoration_failed',
9417
+ domain: 'authentication',
9418
+ userMessage: 'Admin session restoration failed',
9419
+ code: 'SESSION_INVALID',
9420
+ details: { error }
9421
+ });
9422
+ throw error;
9423
+ }
9141
9424
  }
9142
9425
  try {
9143
9426
  // Ensure token is valid (refresh if expired) before fetching user
9144
9427
  await this.auth.ensureValidToken();
9145
- // Fetch user data to restore session
9428
+ // For BUSINESS auth, only fetch business context (no access to /users/me)
9429
+ if (authType === persShared.AccountOwnerType.BUSINESS) {
9430
+ const businessData = await this.auth.getCurrentBusiness();
9431
+ // Emit event with business data (no user data for business auth)
9432
+ this._events.emitSuccess({
9433
+ type: 'session_restored',
9434
+ domain: 'authentication',
9435
+ userMessage: 'Business session restored successfully',
9436
+ details: { business: businessData }
9437
+ });
9438
+ return null; // No user data for business auth
9439
+ }
9440
+ // For USER auth, fetch user data
9146
9441
  const userData = await this.auth.getCurrentUser();
9147
- // Emit event through proper event emitter
9442
+ // Emit event with user data
9148
9443
  this._events.emitSuccess({
9149
9444
  type: 'session_restored',
9150
9445
  domain: 'authentication',
9151
9446
  userMessage: 'Session restored successfully',
9152
- details: { userId: userData.id }
9447
+ details: { user: userData }
9153
9448
  });
9154
9449
  return userData;
9155
9450
  }
@@ -9698,4 +9993,4 @@ exports.buildWalletEventsWsUrl = buildWalletEventsWsUrl;
9698
9993
  exports.createPersEventsClient = createPersEventsClient;
9699
9994
  exports.createPersSDK = createPersSDK;
9700
9995
  exports.mergeWithDefaults = mergeWithDefaults;
9701
- //# sourceMappingURL=pers-sdk-rmjhPvHo.cjs.map
9996
+ //# sourceMappingURL=pers-sdk-tAxjWu7_.cjs.map