@explorins/pers-sdk 2.1.3 → 2.1.4

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 (97) hide show
  1. package/dist/analytics/api/analytics-api.d.ts +175 -1
  2. package/dist/analytics/api/analytics-api.d.ts.map +1 -1
  3. package/dist/analytics/models/index.d.ts +2 -5
  4. package/dist/analytics/models/index.d.ts.map +1 -1
  5. package/dist/analytics/services/analytics-service.d.ts +32 -1
  6. package/dist/analytics/services/analytics-service.d.ts.map +1 -1
  7. package/dist/analytics.cjs +9 -44
  8. package/dist/analytics.cjs.map +1 -1
  9. package/dist/analytics.js +2 -45
  10. package/dist/analytics.js.map +1 -1
  11. package/dist/campaign/api/campaign-api.d.ts +59 -4
  12. package/dist/campaign/api/campaign-api.d.ts.map +1 -1
  13. package/dist/campaign/services/campaign-service.d.ts +49 -7
  14. package/dist/campaign/services/campaign-service.d.ts.map +1 -1
  15. package/dist/campaign.cjs +150 -14
  16. package/dist/campaign.cjs.map +1 -1
  17. package/dist/campaign.js +150 -14
  18. package/dist/campaign.js.map +1 -1
  19. package/dist/chunks/analytics-service-B9IfG6ox.js +271 -0
  20. package/dist/chunks/analytics-service-B9IfG6ox.js.map +1 -0
  21. package/dist/chunks/analytics-service-DwkeBB08.cjs +274 -0
  22. package/dist/chunks/analytics-service-DwkeBB08.cjs.map +1 -0
  23. package/dist/chunks/{pers-sdk-fWg-J3_h.js → pers-sdk-CAM0iQyK.js} +982 -189
  24. package/dist/chunks/pers-sdk-CAM0iQyK.js.map +1 -0
  25. package/dist/chunks/{pers-sdk-BQw3QUWR.cjs → pers-sdk-Di_R6AiT.cjs} +986 -190
  26. package/dist/chunks/pers-sdk-Di_R6AiT.cjs.map +1 -0
  27. package/dist/chunks/{redemption-service-D-hBqh42.js → redemption-service-CQtTLdic.js} +32 -10
  28. package/dist/chunks/redemption-service-CQtTLdic.js.map +1 -0
  29. package/dist/chunks/{redemption-service-rMB6T2W5.cjs → redemption-service-DsH7sRdv.cjs} +32 -10
  30. package/dist/chunks/redemption-service-DsH7sRdv.cjs.map +1 -0
  31. package/dist/chunks/{transaction-request.builder-C1vVVFto.js → transaction-request.builder-C8ahJYwi.js} +122 -70
  32. package/dist/chunks/transaction-request.builder-C8ahJYwi.js.map +1 -0
  33. package/dist/chunks/{transaction-request.builder-BpgtuMMq.cjs → transaction-request.builder-CkYd5bl6.cjs} +122 -70
  34. package/dist/chunks/transaction-request.builder-CkYd5bl6.cjs.map +1 -0
  35. package/dist/core/pers-api-client.d.ts.map +1 -1
  36. package/dist/core.cjs +5 -4
  37. package/dist/core.cjs.map +1 -1
  38. package/dist/core.js +4 -4
  39. package/dist/index.cjs +13 -6
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +5 -5
  44. package/dist/managers/analytics-manager.d.ts +165 -2
  45. package/dist/managers/analytics-manager.d.ts.map +1 -1
  46. package/dist/managers/campaign-manager.d.ts +180 -30
  47. package/dist/managers/campaign-manager.d.ts.map +1 -1
  48. package/dist/managers/index.d.ts +1 -0
  49. package/dist/managers/index.d.ts.map +1 -1
  50. package/dist/managers/redemption-manager.d.ts +52 -2
  51. package/dist/managers/redemption-manager.d.ts.map +1 -1
  52. package/dist/managers/transaction-manager.d.ts +66 -131
  53. package/dist/managers/transaction-manager.d.ts.map +1 -1
  54. package/dist/managers/trigger-source-manager.d.ts +194 -0
  55. package/dist/managers/trigger-source-manager.d.ts.map +1 -0
  56. package/dist/managers/user-manager.d.ts +38 -7
  57. package/dist/managers/user-manager.d.ts.map +1 -1
  58. package/dist/node.cjs +4 -4
  59. package/dist/node.js +4 -4
  60. package/dist/package.json +2 -2
  61. package/dist/pers-sdk.d.ts +33 -2
  62. package/dist/pers-sdk.d.ts.map +1 -1
  63. package/dist/redemption/api/redemption-api.d.ts +8 -4
  64. package/dist/redemption/api/redemption-api.d.ts.map +1 -1
  65. package/dist/redemption/services/redemption-service.d.ts +7 -3
  66. package/dist/redemption/services/redemption-service.d.ts.map +1 -1
  67. package/dist/redemption.cjs +1 -1
  68. package/dist/redemption.js +1 -1
  69. package/dist/transaction/api/transaction-api.d.ts +37 -42
  70. package/dist/transaction/api/transaction-api.d.ts.map +1 -1
  71. package/dist/transaction/models/index.d.ts +21 -0
  72. package/dist/transaction/models/index.d.ts.map +1 -1
  73. package/dist/transaction/services/transaction-service.d.ts +10 -15
  74. package/dist/transaction/services/transaction-service.d.ts.map +1 -1
  75. package/dist/transaction.cjs +1 -1
  76. package/dist/transaction.js +1 -1
  77. package/dist/trigger-source/api/trigger-source-api.d.ts +86 -0
  78. package/dist/trigger-source/api/trigger-source-api.d.ts.map +1 -0
  79. package/dist/trigger-source/index.d.ts +9 -0
  80. package/dist/trigger-source/index.d.ts.map +1 -0
  81. package/dist/trigger-source/services/trigger-source-service.d.ts +42 -0
  82. package/dist/trigger-source/services/trigger-source-service.d.ts.map +1 -0
  83. package/dist/user/api/user-api.d.ts +26 -1
  84. package/dist/user/api/user-api.d.ts.map +1 -1
  85. package/dist/user/services/user-service.d.ts +3 -1
  86. package/dist/user/services/user-service.d.ts.map +1 -1
  87. package/dist/user.cjs +34 -4
  88. package/dist/user.cjs.map +1 -1
  89. package/dist/user.js +34 -4
  90. package/dist/user.js.map +1 -1
  91. package/package.json +2 -2
  92. package/dist/chunks/pers-sdk-BQw3QUWR.cjs.map +0 -1
  93. package/dist/chunks/pers-sdk-fWg-J3_h.js.map +0 -1
  94. package/dist/chunks/redemption-service-D-hBqh42.js.map +0 -1
  95. package/dist/chunks/redemption-service-rMB6T2W5.cjs.map +0 -1
  96. package/dist/chunks/transaction-request.builder-BpgtuMMq.cjs.map +0 -1
  97. package/dist/chunks/transaction-request.builder-C1vVVFto.js.map +0 -1
@@ -5,12 +5,12 @@ import { createUserStatusSDK } from '../user-status.js';
5
5
  import { a as TokenService, T as TokenApi } from './token-service-Bfj6C0yz.js';
6
6
  import { B as BusinessApi, b as BusinessService, a as BusinessMembershipApi, c as BusinessMembershipService } from './business-membership-service-D6vaVQTR.js';
7
7
  import { CampaignService, CampaignApi } from '../campaign.js';
8
- import { a as RedemptionService, R as RedemptionApi } from './redemption-service-D-hBqh42.js';
9
- import { a as TransactionService, T as TransactionApi } from './transaction-request.builder-C1vVVFto.js';
8
+ import { a as RedemptionService, R as RedemptionApi } from './redemption-service-CQtTLdic.js';
9
+ import { a as TransactionService, T as TransactionApi } from './transaction-request.builder-C8ahJYwi.js';
10
10
  import { a as PaymentService, P as PurchaseApi } from './payment-service-IvM6rryM.js';
11
11
  import { a as TenantService, T as TenantApi } from './tenant-service-CsRA3O2V.js';
12
12
  import { b as buildPaginationParams, n as normalizeToPaginated } from './pagination-utils-9vQ-Npkr.js';
13
- import { AnalyticsService, AnalyticsApi } from '../analytics.js';
13
+ import { a as AnalyticsService, A as AnalyticsApi } from './analytics-service-B9IfG6ox.js';
14
14
  import { DonationService, DonationApi } from '../donation.js';
15
15
 
16
16
  /**
@@ -1112,13 +1112,15 @@ class PersApiClient {
1112
1112
  * @internal
1113
1113
  */
1114
1114
  emitErrorEvent(errorDetails, errorMessage, endpoint, method, status, error) {
1115
- console.log('[PersApiClient] emitErrorEvent called', {
1116
- hasEvents: !!this._events,
1117
- instanceId: this._events?.instanceId ?? 'none',
1118
- subscriberCount: this._events?.subscriberCount ?? 0,
1119
- domain: errorDetails.domain,
1120
- message: errorDetails.message || errorMessage
1121
- });
1115
+ /* console.log('[PersApiClient] emitErrorEvent called', {
1116
+ hasEvents: !!this._events,
1117
+ instanceId: this._events?.instanceId ?? 'none',
1118
+ subscriberCount: this._events?.subscriberCount ?? 0,
1119
+ domain: errorDetails.domain,
1120
+ code: errorDetails.code,
1121
+ status: status,
1122
+ message: errorDetails.message || errorMessage
1123
+ }); */
1122
1124
  this._events?.emitError({
1123
1125
  domain: errorDetails.domain || 'external',
1124
1126
  type: errorDetails.code || 'API_ERROR',
@@ -2081,26 +2083,57 @@ class UserManager {
2081
2083
  * requires administrator privileges and returns full user profiles including
2082
2084
  * private information.
2083
2085
  *
2084
- * @returns Promise resolving to array of all users with complete data
2086
+ * @param options - Pagination and sorting options
2087
+ * @param options.page - Page number (1-based, default: 1)
2088
+ * @param options.limit - Items per page (default: 50)
2089
+ * @param options.sortBy - Sort by field. Supported fields:
2090
+ * - 'id', 'email', 'identifierEmail', 'firstName', 'lastName'
2091
+ * - 'externalId', 'accountAddress', 'isActive'
2092
+ * - 'createdAt', 'updatedAt'
2093
+ * - Default: 'createdAt'
2094
+ * @param options.sortOrder - Sort order: SortOrder.ASC or SortOrder.DESC (default: DESC)
2095
+ * @param search - Optional search query to filter users
2096
+ * @returns Promise resolving to paginated users with complete data
2085
2097
  * @throws {PersApiError} When not authenticated as admin
2086
2098
  *
2087
- * @example
2099
+ * @example Basic Usage
2088
2100
  * ```typescript
2089
2101
  * // Admin operation - requires admin authentication
2090
2102
  * try {
2091
- * const allUsers = await sdk.users.getAllUsers();
2092
- * console.log(`Total users: ${allUsers.length}`);
2103
+ * const result = await sdk.users.getAllUsers();
2104
+ * console.log(`Total users: ${result.pagination.total}`);
2093
2105
  *
2094
- * allUsers.forEach(user => {
2095
- * console.log(`${user.name} - ${user.email} - Active: ${user.isActive}`);
2106
+ * result.data.forEach(user => {
2107
+ * console.log(`${user.firstName} - ${user.email} - Active: ${user.isActive}`);
2096
2108
  * });
2097
2109
  * } catch (error) {
2098
2110
  * console.log('Admin access required');
2099
2111
  * }
2100
2112
  * ```
2113
+ *
2114
+ * @example With Sorting
2115
+ * ```typescript
2116
+ * import { SortOrder } from '@explorins/pers-sdk';
2117
+ *
2118
+ * // Get users sorted by email ascending
2119
+ * const result = await sdk.users.getAllUsers({
2120
+ * page: 1,
2121
+ * limit: 20,
2122
+ * sortBy: 'email',
2123
+ * sortOrder: SortOrder.ASC
2124
+ * });
2125
+ *
2126
+ * // Get users sorted by creation date (newest first)
2127
+ * const recent = await sdk.users.getAllUsers({
2128
+ * page: 1,
2129
+ * limit: 10,
2130
+ * sortBy: 'createdAt',
2131
+ * sortOrder: SortOrder.DESC
2132
+ * });
2133
+ * ```
2101
2134
  */
2102
- async getAllUsers(options) {
2103
- return this.userService.getAllRemoteUsers(options);
2135
+ async getAllUsers(options, search) {
2136
+ return this.userService.getAllRemoteUsers(options, search);
2104
2137
  }
2105
2138
  /**
2106
2139
  * Business/Admin: Create or update a user
@@ -3265,6 +3298,7 @@ class CampaignManager {
3265
3298
  * business partnerships, eligibility criteria, and claiming requirements.
3266
3299
  *
3267
3300
  * @param campaignId - Unique campaign identifier
3301
+ * @param include - Relations to include: 'triggerSources', 'businesses'
3268
3302
  * @returns Promise resolving to campaign data with complete details
3269
3303
  * @throws {PersApiError} When campaign with specified ID is not found
3270
3304
  *
@@ -3293,9 +3327,17 @@ class CampaignManager {
3293
3327
  * console.log('Campaign not found:', error.message);
3294
3328
  * }
3295
3329
  * ```
3330
+ *
3331
+ * @example With Include Relations
3332
+ * ```typescript
3333
+ * // Get campaign with trigger sources and businesses included
3334
+ * const campaign = await sdk.campaigns.getCampaignById('campaign-123', ['triggerSources', 'businesses']);
3335
+ * console.log('Trigger sources:', campaign.included?.triggerSources);
3336
+ * console.log('Businesses:', campaign.included?.businesses);
3337
+ * ```
3296
3338
  */
3297
- async getCampaignById(campaignId) {
3298
- return this.campaignService.getCampaignById(campaignId);
3339
+ async getCampaignById(campaignId, include) {
3340
+ return this.campaignService.getCampaignById(campaignId, include);
3299
3341
  }
3300
3342
  /**
3301
3343
  * Claim a campaign reward
@@ -3440,6 +3482,11 @@ class CampaignManager {
3440
3482
  * page: 1,
3441
3483
  * limit: 25
3442
3484
  * });
3485
+ *
3486
+ * // Include related data (trigger sources and businesses)
3487
+ * const campaignsWithRelations = await sdk.campaigns.getCampaigns({
3488
+ * include: ['triggerSources', 'businesses']
3489
+ * });
3443
3490
  * ```
3444
3491
  */
3445
3492
  async getCampaigns(options) {
@@ -3557,57 +3604,188 @@ class CampaignManager {
3557
3604
  async toggleCampaignTestnet(campaignId) {
3558
3605
  return this.campaignService.toggleCampaignTestnet(campaignId);
3559
3606
  }
3607
+ // ==========================================
3608
+ // CAMPAIGN TRIGGER OPERATIONS
3609
+ // Rules & limits for campaign activation
3610
+ // ==========================================
3560
3611
  /**
3561
- * Admin: Get campaign triggers
3612
+ * Admin: Get all campaign triggers (paginated)
3562
3613
  *
3563
- * Retrieves all available campaign trigger mechanisms that can be used to
3564
- * automatically activate campaigns based on user actions or system events.
3565
- * Requires administrator privileges.
3614
+ * Retrieves all campaign trigger rules that define rate limits, geo-validation,
3615
+ * conditions, and trigger types for campaign activation.
3566
3616
  *
3567
- * @returns Promise resolving to array of campaign trigger definitions
3617
+ * @param options - Pagination options
3618
+ * @returns Promise resolving to paginated list of campaign triggers
3568
3619
  *
3569
3620
  * @example
3570
3621
  * ```typescript
3571
- * // Admin operation - view available triggers
3572
- * const triggers = await sdk.campaigns.getCampaignTriggers();
3573
- *
3574
- * console.log('Available Campaign Triggers:');
3575
- * triggers.forEach(trigger => {
3576
- * console.log(`- ${trigger.name}: ${trigger.description}`);
3577
- * console.log(` Type: ${trigger.type}`);
3578
- * console.log(` Parameters: ${JSON.stringify(trigger.parameters)}`);
3622
+ * const triggers = await sdk.campaigns.getCampaignTriggers({ page: 1, limit: 20 });
3623
+ * console.log(`Found ${triggers.total} triggers`);
3624
+ * triggers.data.forEach(trigger => {
3625
+ * console.log(`- ${trigger.name}: max ${trigger.maxPerDayPerUser}/day`);
3579
3626
  * });
3580
3627
  * ```
3581
3628
  */
3582
3629
  async getCampaignTriggers(options) {
3583
- return this.campaignService.getCampaignTriggers();
3630
+ return this.campaignService.getCampaignTriggers(options);
3631
+ }
3632
+ /**
3633
+ * Admin: Get campaign trigger by ID
3634
+ *
3635
+ * @param triggerId - The campaign trigger ID
3636
+ * @returns Promise resolving to the campaign trigger
3637
+ *
3638
+ * @example
3639
+ * ```typescript
3640
+ * const trigger = await sdk.campaigns.getCampaignTriggerById('trigger-123');
3641
+ * console.log('Max per day:', trigger.maxPerDayPerUser);
3642
+ * ```
3643
+ */
3644
+ async getCampaignTriggerById(triggerId) {
3645
+ return this.campaignService.getCampaignTriggerById(triggerId);
3646
+ }
3647
+ /**
3648
+ * Admin: Create a new campaign trigger
3649
+ *
3650
+ * Creates a trigger rule that defines rate limits, geo-validation, and conditions
3651
+ * for campaign activation. Triggers are created independently and then assigned
3652
+ * to campaigns via `setCampaignTrigger()`.
3653
+ *
3654
+ * @param data - Trigger configuration
3655
+ * @returns Promise resolving to created trigger
3656
+ *
3657
+ * @example
3658
+ * ```typescript
3659
+ * const trigger = await sdk.campaigns.createCampaignTrigger({
3660
+ * name: 'Daily Check-in',
3661
+ * maxPerDayPerUser: 1,
3662
+ * maxPerUser: 100,
3663
+ * minCooldownSeconds: 3600,
3664
+ * maxGeoDistanceInMeters: 50,
3665
+ * triggerType: 'CLAIM_BY_USER'
3666
+ * });
3667
+ *
3668
+ * // Then assign to campaign
3669
+ * await sdk.campaigns.setCampaignTrigger(campaignId, trigger.id);
3670
+ * ```
3671
+ */
3672
+ async createCampaignTrigger(data) {
3673
+ const result = await this.campaignService.createCampaignTrigger(data);
3674
+ this.events?.emitSuccess({
3675
+ domain: 'campaign',
3676
+ type: 'CAMPAIGN_TRIGGER_CREATED',
3677
+ userMessage: `Trigger "${data.name}" created successfully`,
3678
+ details: { triggerId: result.id, name: data.name }
3679
+ });
3680
+ return result;
3681
+ }
3682
+ /**
3683
+ * Admin: Update an existing campaign trigger
3684
+ *
3685
+ * @param triggerId - The campaign trigger ID
3686
+ * @param data - Updated trigger configuration (partial)
3687
+ * @returns Promise resolving to updated trigger
3688
+ *
3689
+ * @example
3690
+ * ```typescript
3691
+ * const updated = await sdk.campaigns.updateCampaignTrigger('trigger-123', {
3692
+ * maxPerDayPerUser: 5,
3693
+ * minCooldownSeconds: 1800
3694
+ * });
3695
+ * ```
3696
+ */
3697
+ async updateCampaignTrigger(triggerId, data) {
3698
+ const result = await this.campaignService.updateCampaignTrigger(triggerId, data);
3699
+ this.events?.emitSuccess({
3700
+ domain: 'campaign',
3701
+ type: 'CAMPAIGN_TRIGGER_UPDATED',
3702
+ userMessage: 'Trigger updated successfully',
3703
+ details: { triggerId, updates: Object.keys(data) }
3704
+ });
3705
+ return result;
3706
+ }
3707
+ /**
3708
+ * Admin: Delete a campaign trigger
3709
+ *
3710
+ * @param triggerId - The campaign trigger ID
3711
+ * @returns Promise resolving to success status
3712
+ *
3713
+ * @example
3714
+ * ```typescript
3715
+ * await sdk.campaigns.deleteCampaignTrigger('trigger-123');
3716
+ * ```
3717
+ */
3718
+ async deleteCampaignTrigger(triggerId) {
3719
+ const result = await this.campaignService.deleteCampaignTrigger(triggerId);
3720
+ this.events?.emitSuccess({
3721
+ domain: 'campaign',
3722
+ type: 'CAMPAIGN_TRIGGER_DELETED',
3723
+ userMessage: 'Trigger deleted successfully',
3724
+ details: { triggerId }
3725
+ });
3726
+ return result;
3584
3727
  }
3585
3728
  /**
3586
- * Admin: Set campaign trigger
3729
+ * Admin: Assign a trigger to a campaign
3587
3730
  *
3588
- * Associates a specific trigger mechanism with a campaign, enabling automatic
3589
- * campaign activation based on defined conditions. Requires administrator privileges.
3731
+ * Associates a trigger rule with a campaign. A campaign can have only one trigger
3732
+ * at a time. Assigning a new trigger replaces any existing trigger.
3590
3733
  *
3591
3734
  * @param campaignId - ID of the campaign
3592
3735
  * @param triggerId - ID of the trigger to associate
3593
- * @returns Promise resolving to updated campaign data
3594
- * @throws {PersApiError} When not authenticated as admin or entities not found
3736
+ * @returns Promise resolving to updated campaign
3595
3737
  *
3596
3738
  * @example
3597
3739
  * ```typescript
3598
- * // Admin operation - set up automatic campaign trigger
3599
3740
  * const updated = await sdk.campaigns.setCampaignTrigger(
3600
- * 'new-user-welcome',
3601
- * 'user-registration-trigger'
3741
+ * 'campaign-123',
3742
+ * 'trigger-456'
3602
3743
  * );
3603
- *
3604
- * console.log('Trigger set for campaign:', updated.title);
3605
- * console.log('Trigger will activate on user registration');
3744
+ * console.log('Trigger assigned:', updated.trigger?.name);
3606
3745
  * ```
3607
3746
  */
3608
3747
  async setCampaignTrigger(campaignId, triggerId) {
3609
- return this.campaignService.setCampaignTrigger(campaignId, triggerId);
3748
+ const result = await this.campaignService.setCampaignTrigger(campaignId, triggerId);
3749
+ this.events?.emitSuccess({
3750
+ domain: 'campaign',
3751
+ type: 'CAMPAIGN_TRIGGER_ASSIGNED',
3752
+ userMessage: 'Trigger assigned to campaign',
3753
+ details: { campaignId, triggerId }
3754
+ });
3755
+ return result;
3610
3756
  }
3757
+ /**
3758
+ * Admin: Remove a trigger from a campaign
3759
+ *
3760
+ * Removes the trigger rule from a campaign. The trigger itself is not deleted
3761
+ * and can be reassigned to other campaigns.
3762
+ *
3763
+ * @param campaignId - ID of the campaign
3764
+ * @param triggerId - ID of the trigger to remove
3765
+ * @returns Promise resolving to updated campaign
3766
+ *
3767
+ * @example
3768
+ * ```typescript
3769
+ * const updated = await sdk.campaigns.removeCampaignTrigger(
3770
+ * 'campaign-123',
3771
+ * 'trigger-456'
3772
+ * );
3773
+ * console.log('Trigger removed:', updated.trigger === null);
3774
+ * ```
3775
+ */
3776
+ async removeCampaignTrigger(campaignId, triggerId) {
3777
+ const result = await this.campaignService.removeCampaignTrigger(campaignId, triggerId);
3778
+ this.events?.emitSuccess({
3779
+ domain: 'campaign',
3780
+ type: 'CAMPAIGN_TRIGGER_REMOVED',
3781
+ userMessage: 'Trigger removed from campaign',
3782
+ details: { campaignId, triggerId }
3783
+ });
3784
+ return result;
3785
+ }
3786
+ // ==========================================
3787
+ // TOKEN UNIT OPERATIONS
3788
+ // ==========================================
3611
3789
  /**
3612
3790
  * Admin: Create campaign token unit
3613
3791
  *
@@ -3816,8 +3994,8 @@ class CampaignManager {
3816
3994
  * });
3817
3995
  * ```
3818
3996
  */
3819
- async getCampaignClaims(filters) {
3820
- return this.campaignService.getCampaignClaims(filters);
3997
+ async getCampaignClaims(filters, include) {
3998
+ return this.campaignService.getCampaignClaims(filters, include);
3821
3999
  }
3822
4000
  /**
3823
4001
  * Admin: Get campaign claims by user ID
@@ -3852,8 +4030,8 @@ class CampaignManager {
3852
4030
  * console.log(`\nTotal rewards earned: ${totalRewards}`);
3853
4031
  * ```
3854
4032
  */
3855
- async getCampaignClaimsByUserId(userId, options) {
3856
- return this.campaignService.getCampaignClaimsByUserId(userId);
4033
+ async getCampaignClaimsByUserId(userId, options, include) {
4034
+ return this.campaignService.getCampaignClaimsByUserId(userId, options, include);
3857
4035
  }
3858
4036
  /**
3859
4037
  * Admin: Get campaign claims by business ID
@@ -3893,8 +4071,79 @@ class CampaignManager {
3893
4071
  * console.log(`\nTotal rewards distributed: ${totalRewardsDistributed}`);
3894
4072
  * ```
3895
4073
  */
3896
- async getCampaignClaimsByBusinessId(businessId, options) {
3897
- return this.campaignService.getCampaignClaimsByBusinessId(businessId);
4074
+ async getCampaignClaimsByBusinessId(businessId, options, include) {
4075
+ return this.campaignService.getCampaignClaimsByBusinessId(businessId, options, include);
4076
+ }
4077
+ // ==========================================
4078
+ // TRIGGER SOURCE ASSIGNMENT
4079
+ // Note: TriggerSource CRUD is in TriggerSourceManager (sdk.triggerSources)
4080
+ // ==========================================
4081
+ /**
4082
+ * Admin: Assign a trigger source to a campaign
4083
+ *
4084
+ * Associates a trigger source with a campaign, enabling the trigger source
4085
+ * to activate campaign rewards when triggered. A campaign can have multiple
4086
+ * trigger sources. Requires administrator privileges.
4087
+ *
4088
+ * Note: To create/update/delete trigger sources, use `sdk.triggerSources`.
4089
+ *
4090
+ * @param campaignId - Campaign UUID
4091
+ * @param triggerSourceId - Trigger source UUID
4092
+ * @returns Promise resolving to updated campaign with trigger source assigned
4093
+ * @throws {PersApiError} When not authenticated as admin or entities not found
4094
+ *
4095
+ * @example
4096
+ * ```typescript
4097
+ * // Create trigger source first
4098
+ * const source = await sdk.triggerSources.create({
4099
+ * type: 'QR_CODE',
4100
+ * name: 'Store Entrance QR'
4101
+ * });
4102
+ *
4103
+ * // Then assign to campaign
4104
+ * const updated = await sdk.campaigns.assignTriggerSource(
4105
+ * 'campaign-123',
4106
+ * source.id
4107
+ * );
4108
+ *
4109
+ * console.log('Trigger source assigned:', updated.triggerSourceIds.length);
4110
+ * ```
4111
+ */
4112
+ async assignTriggerSource(campaignId, triggerSourceId) {
4113
+ const result = await this.campaignService.assignTriggerSourceToCampaign(campaignId, triggerSourceId);
4114
+ this.events?.emitSuccess({
4115
+ domain: 'campaign',
4116
+ type: 'TRIGGER_SOURCE_ASSIGNED',
4117
+ userMessage: 'Trigger source assigned to campaign',
4118
+ details: { campaignId, triggerSourceId }
4119
+ });
4120
+ return result;
4121
+ }
4122
+ /**
4123
+ * Admin: Remove a trigger source from a campaign
4124
+ *
4125
+ * Removes the association between a trigger source and a campaign. The trigger
4126
+ * source itself is not deleted and can be reassigned to other campaigns.
4127
+ * Requires administrator privileges.
4128
+ *
4129
+ * @param campaignId - Campaign UUID
4130
+ * @param triggerSourceId - Trigger source UUID
4131
+ * @returns Promise resolving to updated campaign with trigger source removed
4132
+ * @throws {PersApiError} When not authenticated as admin or entities not found
4133
+ *
4134
+ * @example
4135
+ * ```typescript
4136
+ * // Remove a trigger source from a campaign
4137
+ * const updated = await sdk.campaigns.removeTriggerSource(
4138
+ * 'campaign-123',
4139
+ * 'source-456'
4140
+ * );
4141
+ *
4142
+ * console.log('Remaining trigger source IDs:', updated.triggerSourceIds.length);
4143
+ * ```
4144
+ */
4145
+ async removeTriggerSource(campaignId, triggerSourceId) {
4146
+ return this.campaignService.removeTriggerSourceFromCampaign(campaignId, triggerSourceId);
3898
4147
  }
3899
4148
  /**
3900
4149
  * Get the full campaign service for advanced operations
@@ -4278,8 +4527,57 @@ class RedemptionManager {
4278
4527
  * });
4279
4528
  * ```
4280
4529
  */
4281
- async getUserRedemptions(options) {
4282
- return this.redemptionService.getUserRedeems(options);
4530
+ async getUserRedemptions(options, include) {
4531
+ return this.redemptionService.getUserRedeems(options, include);
4532
+ }
4533
+ /**
4534
+ * Admin: Get all redemption redeems with filtering and enriched data
4535
+ *
4536
+ * Retrieves all redemption redeems across the platform with filtering capabilities.
4537
+ * This is an admin-level operation that allows monitoring and analytics of redemption
4538
+ * activity. Supports filtering by user, redemption offer, and enrichment of related entities.
4539
+ *
4540
+ * @param filters - Filter options (userId, redemptionId, pagination)
4541
+ * @param include - Optional relations to include for enrichment
4542
+ * @returns Promise resolving to paginated list of redemption redeems
4543
+ * @throws {PersApiError} When not authenticated as admin
4544
+ *
4545
+ * @example Get All Redeems
4546
+ * ```typescript
4547
+ * // Admin operation - get all redemption redeems
4548
+ * const { data: allRedeems, pagination } = await sdk.redemptions.getRedemptionRedeems();
4549
+ *
4550
+ * console.log(`Total redeems: ${pagination.total}`);
4551
+ * console.log(`Page ${pagination.page} of ${pagination.pages}`);
4552
+ * ```
4553
+ *
4554
+ * @example Filter by User
4555
+ * ```typescript
4556
+ * // Get redeems for specific user
4557
+ * const { data: userRedeems } = await sdk.redemptions.getRedemptionRedeems({
4558
+ * userId: 'user-123',
4559
+ * limit: 50
4560
+ * });
4561
+ *
4562
+ * console.log(`User has ${userRedeems.length} redemptions`);
4563
+ * ```
4564
+ *
4565
+ * @example With Enriched Data
4566
+ * ```typescript
4567
+ * const { data: redeems } = await sdk.redemptions.getRedemptionRedeems(
4568
+ * { page: 1, limit: 20 },
4569
+ * ['redemption', 'user', 'business']
4570
+ * );
4571
+ *
4572
+ * redeems.forEach(redeem => {
4573
+ * const redemptionName = redeem.included?.redemption?.name || 'Unknown';
4574
+ * const userEmail = redeem.included?.user?.email || redeem.userId;
4575
+ * console.log(`${redemptionName} - ${userEmail}`);
4576
+ * });
4577
+ * ```
4578
+ */
4579
+ async getRedemptionRedeems(filters, include) {
4580
+ return this.redemptionService.getRedemptionRedeems(filters, include);
4283
4581
  }
4284
4582
  /**
4285
4583
  * Admin: Create new redemption offer
@@ -4522,8 +4820,8 @@ class RedemptionManager {
4522
4820
  *
4523
4821
  * @example Administrative Reporting
4524
4822
  * ```typescript
4525
- * // Admin: Get all tenant transactions for analysis
4526
- * const allTransactions = await sdk.transactions.getTenantTransactions();
4823
+ * // Admin: Get paginated transactions for analysis
4824
+ * const allTransactions = await sdk.transactions.getPaginatedTransactions({ page: 1, limit: 100 });
4527
4825
  *
4528
4826
  * // Export transaction data
4529
4827
  * const csvBlob = await sdk.transactions.exportTransactionsCSV();
@@ -4546,13 +4844,18 @@ class TransactionManager {
4546
4844
  * Provides complete transaction audit trail and verification data.
4547
4845
  *
4548
4846
  * @param transactionId - Unique transaction identifier
4847
+ * @param include - Optional relations to include (sender, recipient, business) for enriched entity data
4549
4848
  * @returns Promise resolving to complete transaction data
4550
4849
  * @throws {PersApiError} When transaction with specified ID is not found or access denied
4551
4850
  *
4552
4851
  * @example
4553
4852
  * ```typescript
4554
4853
  * try {
4555
- * const transaction = await sdk.transactions.getTransactionById('txn-abc123');
4854
+ * // Get transaction with enriched sender/recipient data
4855
+ * const transaction = await sdk.transactions.getTransactionById(
4856
+ * 'txn-abc123',
4857
+ * ['sender', 'recipient', 'business']
4858
+ * );
4556
4859
  *
4557
4860
  * console.log('Transaction Details:');
4558
4861
  * console.log('ID:', transaction.id);
@@ -4565,16 +4868,19 @@ class TransactionManager {
4565
4868
  * console.log('Description:', transaction.description);
4566
4869
  * }
4567
4870
  *
4568
- * if (transaction.business) {
4569
- * console.log('Business:', transaction.business.displayName);
4871
+ * // Access enriched sender data
4872
+ * if (transaction.included?.sender) {
4873
+ * console.log('Sender:', transaction.included.sender);
4570
4874
  * }
4571
4875
  *
4572
- * // Show token movements
4573
- * if (transaction.tokenTransfers?.length) {
4574
- * console.log('\nToken Transfers:');
4575
- * transaction.tokenTransfers.forEach(transfer => {
4576
- * console.log(`${transfer.amount} ${transfer.token.symbol} ${transfer.direction}`);
4577
- * });
4876
+ * // Access enriched recipient data
4877
+ * if (transaction.included?.recipient) {
4878
+ * console.log('Recipient:', transaction.included.recipient);
4879
+ * }
4880
+ *
4881
+ * // Access enriched business data
4882
+ * if (transaction.included?.engagedBusiness) {
4883
+ * console.log('Business:', transaction.included.engagedBusiness.displayName);
4578
4884
  * }
4579
4885
  *
4580
4886
  * // Show blockchain confirmation
@@ -4587,8 +4893,8 @@ class TransactionManager {
4587
4893
  * }
4588
4894
  * ```
4589
4895
  */
4590
- async getTransactionById(transactionId) {
4591
- return this.transactionService.getTransactionById(transactionId);
4896
+ async getTransactionById(transactionId, include) {
4897
+ return this.transactionService.getTransactionById(transactionId, include);
4592
4898
  }
4593
4899
  /**
4594
4900
  * Create a new transaction
@@ -4682,150 +4988,62 @@ class TransactionManager {
4682
4988
  /**
4683
4989
  * Get user's transaction history
4684
4990
  *
4685
- * Retrieves transaction history for the authenticated user, filtered by
4686
- * transaction role. Provides chronological view of all user's loyalty
4991
+ * Retrieves transaction history for the authenticated user with comprehensive
4992
+ * filtering options. Provides chronological view of all user's loyalty
4687
4993
  * activities including purchases, rewards, redemptions, and transfers.
4994
+ * Optionally enrich with related entities (sender, recipient, business).
4688
4995
  *
4689
- * @param role - Optional role filter (TransactionRole.SENDER, TransactionRole.RECIPIENT). If undefined, returns all user transactions
4690
- * @param limit - Maximum number of transactions to return (default: 1000)
4691
- * @returns Promise resolving to array of user's transactions
4996
+ * @param options - Query options including filters, pagination, and include relations
4997
+ * @returns Promise resolving to paginated transaction data with optional included entities
4692
4998
  *
4693
4999
  * @example All Transactions
4694
5000
  * ```typescript
4695
- * const allTransactions = await sdk.transactions.getUserTransactionHistory('ALL');
5001
+ * const result = await sdk.transactions.getUserTransactionHistory();
4696
5002
  *
4697
- * console.log(` Transaction History (${allTransactions.length} transactions):`);
5003
+ * console.log(`Transaction History (${result.data.length} of ${result.pagination.total} transactions)`);
4698
5004
  *
4699
- * allTransactions.forEach((transaction, index) => {
5005
+ * result.data.forEach((transaction, index) => {
4700
5006
  * const date = new Date(transaction.createdAt).toLocaleDateString();
4701
5007
  * console.log(`\n${index + 1}. ${transaction.type} - ${date}`);
4702
5008
  * console.log(` ${transaction.description || 'No description'}`);
4703
5009
  * console.log(` Status: ${transaction.status}`);
4704
- *
4705
- * if (transaction.amount && transaction.currency) {
4706
- * console.log(` Amount: ${transaction.amount} ${transaction.currency}`);
4707
- * }
4708
- *
4709
- * if (transaction.business) {
4710
- * console.log(` Business: ${transaction.business.displayName}`);
4711
- * }
4712
5010
  * });
4713
5011
  * ```
4714
5012
  *
4715
- * @example Filtered by Type
5013
+ * @example Filter by Role and Status
4716
5014
  * ```typescript
4717
- * // Get only purchase transactions
4718
- * const purchases = await sdk.transactions.getUserTransactionHistory('PURCHASE');
4719
- *
4720
- * let totalSpent = 0;
4721
- * let totalRewards = 0;
4722
- *
4723
- * purchases.forEach(purchase => {
4724
- * if (purchase.amount) {
4725
- * totalSpent += purchase.amount;
4726
- * }
4727
- *
4728
- * if (purchase.tokensEarned?.length) {
4729
- * purchase.tokensEarned.forEach(reward => {
4730
- * totalRewards += reward.amount;
4731
- * });
4732
- * }
5015
+ * // Get only completed sent transactions
5016
+ * const sent = await sdk.transactions.getUserTransactionHistory({
5017
+ * role: TransactionRole.SENDER,
5018
+ * status: TransactionStatus.COMPLETED,
5019
+ * include: ['recipient', 'business'],
5020
+ * page: 1,
5021
+ * limit: 50
4733
5022
  * });
4734
5023
  *
4735
- * console.log('Purchase Summary:');
4736
- * console.log(`Total purchases: ${purchases.length}`);
4737
- * console.log(`Total spent: $${totalSpent.toFixed(2)}`);
4738
- * console.log(`Total rewards earned: ${totalRewards} points`);
4739
- * ```
4740
- *
4741
- * @example Recent Activity
4742
- * ```typescript
4743
- * const recentTransactions = await sdk.transactions.getUserTransactionHistory('ALL');
4744
- *
4745
- * // Filter to last 30 days
4746
- * const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
4747
- * const recentActivity = recentTransactions.filter(t =>
4748
- * new Date(t.createdAt) > thirtyDaysAgo
4749
- * );
4750
- *
4751
- * console.log(`Recent Activity (${recentActivity.length} transactions in last 30 days):`);
4752
- *
4753
- * // Group by type
4754
- * const activityByType = recentActivity.reduce((acc, t) => {
4755
- * acc[t.type] = (acc[t.type] || 0) + 1;
4756
- * return acc;
4757
- * }, {});
4758
- *
4759
- * Object.entries(activityByType).forEach(([type, count]) => {
4760
- * console.log(`${type}: ${count} transactions`);
5024
+ * sent.data.forEach(tx => {
5025
+ * console.log(`Sent to: ${tx.included?.recipient?.displayName || tx.recipientAddress}`);
4761
5026
  * });
4762
5027
  * ```
4763
- */
4764
- async getUserTransactionHistory(role, options) {
4765
- return this.transactionService.getUserTransactionHistory(role, options);
4766
- }
4767
- /**
4768
- * Admin: Get all tenant transactions
4769
- *
4770
- * Retrieves all transactions across the entire tenant/organization for
4771
- * comprehensive reporting and analysis. This operation requires administrator
4772
- * privileges and provides system-wide transaction visibility.
4773
5028
  *
4774
- * @param limit - Maximum number of transactions to return (default: 1000)
4775
- * @returns Promise resolving to array of all tenant transactions
4776
- * @throws {PersApiError} When not authenticated as administrator
4777
- *
4778
- * @example
5029
+ * @example Filter by Trigger Process (Campaign/Redemption)
4779
5030
  * ```typescript
4780
- * // Admin operation - comprehensive transaction analysis
4781
- * const allTransactions = await sdk.transactions.getTenantTransactions();
4782
- *
4783
- * console.log(`Tenant Transaction Overview:`);
4784
- * console.log(`Total transactions: ${allTransactions.length}`);
4785
- *
4786
- * // Analyze by status
4787
- * const statusCounts = allTransactions.reduce((acc, t) => {
4788
- * acc[t.status] = (acc[t.status] || 0) + 1;
4789
- * return acc;
4790
- * }, {});
4791
- *
4792
- * console.log('\nBy status:');
4793
- * Object.entries(statusCounts).forEach(([status, count]) => {
4794
- * console.log(`${status}: ${count} transactions`);
5031
+ * // Get all transactions triggered by a specific campaign claim
5032
+ * const claimTxs = await sdk.transactions.getUserTransactionHistory({
5033
+ * triggerProcessId: 'claim-abc123',
5034
+ * include: ['sender', 'recipient', 'business']
4795
5035
  * });
4796
5036
  *
4797
- * // Analyze by type
4798
- * const typeCounts = allTransactions.reduce((acc, t) => {
4799
- * acc[t.type] = (acc[t.type] || 0) + 1;
4800
- * return acc;
4801
- * }, {});
4802
- *
4803
- * console.log('\nBy type:');
4804
- * Object.entries(typeCounts).forEach(([type, count]) => {
4805
- * console.log(`${type}: ${count} transactions`);
5037
+ * claimTxs.data.forEach(tx => {
5038
+ * console.log('Transaction from claim:', tx.id);
5039
+ * if (tx.included?.engagedBusiness) {
5040
+ * console.log('Business:', tx.included.engagedBusiness.displayName);
5041
+ * }
4806
5042
  * });
4807
- *
4808
- * // Calculate volume metrics
4809
- * const totalVolume = allTransactions.reduce((sum, t) =>
4810
- * sum + (t.amount || 0), 0
4811
- * );
4812
- *
4813
- * const avgTransactionSize = totalVolume / allTransactions.length;
4814
- *
4815
- * console.log('\nVolume metrics:');
4816
- * console.log(`Total volume: $${totalVolume.toFixed(2)}`);
4817
- * console.log(`Average transaction: $${avgTransactionSize.toFixed(2)}`);
4818
- *
4819
- * // Recent activity analysis
4820
- * const last24Hours = allTransactions.filter(t =>
4821
- * new Date(t.createdAt) > new Date(Date.now() - 24 * 60 * 60 * 1000)
4822
- * );
4823
- *
4824
- * console.log(`\n⏰ Last 24 hours: ${last24Hours.length} transactions`);
4825
5043
  * ```
4826
5044
  */
4827
- async getTenantTransactions(options) {
4828
- return this.transactionService.getTenantTransactions(options);
5045
+ async getUserTransactionHistory(options) {
5046
+ return this.transactionService.getUserTransactionHistory(options);
4829
5047
  }
4830
5048
  /**
4831
5049
  * Admin: Get paginated transactions
@@ -4889,9 +5107,23 @@ class TransactionManager {
4889
5107
  * console.log(`$${transaction.amount} - ${transaction.business?.displayName}`);
4890
5108
  * });
4891
5109
  * ```
5110
+ *
5111
+ * @example With Included Relations
5112
+ * ```typescript
5113
+ * // Include sender and recipient entities
5114
+ * const result = await sdk.transactions.getPaginatedTransactions(
5115
+ * { page: 1, limit: 50 },
5116
+ * ['sender', 'recipient', 'business']
5117
+ * );
5118
+ *
5119
+ * result.data.forEach(tx => {
5120
+ * if (tx.included?.sender) console.log('From:', tx.included.sender);
5121
+ * if (tx.included?.recipient) console.log('To:', tx.included.recipient);
5122
+ * });
5123
+ * ```
4892
5124
  */
4893
- async getPaginatedTransactions(params) {
4894
- return this.transactionService.getPaginatedTransactions(params);
5125
+ async getPaginatedTransactions(params, include) {
5126
+ return this.transactionService.getPaginatedTransactions(params, include);
4895
5127
  }
4896
5128
  /**
4897
5129
  * Admin: Export transactions as CSV
@@ -6554,6 +6786,179 @@ class AnalyticsManager {
6554
6786
  async getTransactionAnalytics(request) {
6555
6787
  return this.analyticsService.getTransactionAnalytics(request);
6556
6788
  }
6789
+ /**
6790
+ * Get campaign claim analytics with aggregation
6791
+ *
6792
+ * Retrieves aggregated analytics for campaign claims with flexible grouping,
6793
+ * filtering, and metric selection. Provides insights into campaign performance,
6794
+ * claim patterns, and user engagement across the loyalty ecosystem.
6795
+ *
6796
+ * @param request - Analytics request with filters, groupBy, and metrics
6797
+ * @returns Promise resolving to campaign claim analytics data
6798
+ *
6799
+ * @example Claims per campaign
6800
+ * ```typescript
6801
+ * const analytics = await sdk.analytics.getCampaignClaimAnalytics({
6802
+ * filters: { status: 'COMPLETED' },
6803
+ * groupBy: ['campaignId'],
6804
+ * metrics: ['count'],
6805
+ * sortBy: 'count',
6806
+ * sortOrder: 'DESC',
6807
+ * limit: 10
6808
+ * });
6809
+ *
6810
+ * console.log('Top campaigns:', analytics.results);
6811
+ * ```
6812
+ */
6813
+ async getCampaignClaimAnalytics(request) {
6814
+ return this.analyticsService.getCampaignClaimAnalytics(request);
6815
+ }
6816
+ /**
6817
+ * Get user analytics with engagement metrics
6818
+ *
6819
+ * Retrieves aggregated user statistics including engagement rate, active users,
6820
+ * transaction metrics, and per-active-user averages. Provides comprehensive
6821
+ * insights into user behavior, engagement patterns, and platform adoption metrics.
6822
+ *
6823
+ * NEW: Added per-active-user metrics (averageTransactionsPerActiveUser, etc.) which
6824
+ * show concentrated engagement among active users - more useful than diluted all-user averages.
6825
+ *
6826
+ * Request structure matches TransactionAnalytics and CampaignClaimAnalytics:
6827
+ * - Use filters object for business-specific scoping
6828
+ * - startDate/endDate at root level for date range filtering
6829
+ *
6830
+ * @param request - Analytics request with optional filters and date range
6831
+ * @returns Promise resolving to user analytics data with per-user and per-active-user metrics
6832
+ *
6833
+ * @example Basic user analytics (compare per-user vs per-active-user)
6834
+ * ```typescript
6835
+ * const analytics = await sdk.analytics.getUserAnalytics({});
6836
+ * console.log(`Total users: ${analytics.totalUsers}`);
6837
+ * console.log(`Active users: ${analytics.activeUsers} (${analytics.engagementRate.toFixed(1)}%)`);
6838
+ *
6839
+ * // Per-user averages (includes inactive users - lower numbers)
6840
+ * console.log(`\\nPer-User Averages (all users):`);
6841
+ * console.log(` Transactions: ${analytics.averageTransactionsPerUser.toFixed(2)}`);
6842
+ * console.log(` Claims: ${analytics.averageClaimsPerUser.toFixed(2)}`);
6843
+ * console.log(` Redemptions: ${analytics.averageRedemptionsPerUser.toFixed(2)}`);
6844
+ *
6845
+ * // Per-active-user averages (only engaged users - higher, more meaningful numbers)
6846
+ * console.log(`\\nPer-Active-User Averages (engaged users only):`);
6847
+ * console.log(` Transactions: ${analytics.averageTransactionsPerActiveUser.toFixed(2)}`);
6848
+ * console.log(` Claims: ${analytics.averageClaimsPerActiveUser.toFixed(2)}`);
6849
+ * console.log(` Redemptions: ${analytics.averageRedemptionsPerActiveUser.toFixed(2)}`);
6850
+ * ```
6851
+ *
6852
+ * @example Monthly user analytics with date range
6853
+ * ```typescript
6854
+ * const analytics = await sdk.analytics.getUserAnalytics({
6855
+ * startDate: new Date('2026-02-01'),
6856
+ * endDate: new Date('2026-02-28')
6857
+ * });
6858
+ *
6859
+ * console.log('February 2026 User Metrics:');
6860
+ * console.log(`Total users: ${analytics.totalUsers}`);
6861
+ * console.log(`Active users: ${analytics.activeUsers}`);
6862
+ * console.log(`New users: ${analytics.newUsers}`);
6863
+ * console.log(`Engagement rate: ${analytics.engagementRate.toFixed(2)}%`);
6864
+ * console.log(`Total transaction volume: $${analytics.totalTransactionVolume.toLocaleString()}`);
6865
+ * console.log(`Avg transaction amount: $${analytics.averageTransactionAmount.toFixed(2)}`);
6866
+ * console.log(`\\nFilters applied: ${analytics.metadata.dateRange?.startDate} to ${analytics.metadata.dateRange?.endDate}`);
6867
+ * ```
6868
+ *
6869
+ * @example Business-specific user analytics with filters
6870
+ * ```typescript
6871
+ * const analytics = await sdk.analytics.getUserAnalytics({
6872
+ * filters: { businessId: 'business-123' },
6873
+ * startDate: new Date('2026-01-01'),
6874
+ * endDate: new Date('2026-12-31')
6875
+ * });
6876
+ *
6877
+ * console.log(`Business customer metrics for 2026:`);
6878
+ * console.log(`Active customers: ${analytics.activeUsers} / ${analytics.totalUsers}`);
6879
+ * console.log(`Customer engagement: ${analytics.engagementRate.toFixed(1)}%`);
6880
+ * console.log(`Avg spend per customer: $${analytics.averageTransactionAmount.toFixed(2)}`);
6881
+ * console.log(`Avg spend per active customer: $${(analytics.totalTransactionVolume / analytics.activeUsers).toFixed(2)}`);
6882
+ * console.log(`Avg claims per active customer: ${analytics.averageClaimsPerActiveUser.toFixed(2)}`);
6883
+ * ```
6884
+ */
6885
+ async getUserAnalytics(request = {}) {
6886
+ return this.analyticsService.getUserAnalytics(request);
6887
+ }
6888
+ /**
6889
+ * Get user transaction ranking with enriched user data
6890
+ *
6891
+ * Retrieves ranked list of users with full user details (email, externalUserId)
6892
+ * and transaction metrics. Data enrichment happens via efficient SQL JOINs + UNION
6893
+ * (handles legacy transactions). Ideal for leaderboards, engagement analysis, and
6894
+ * identifying power users for targeted campaigns.
6895
+ *
6896
+ * Use Cases:
6897
+ * - Admin leaderboards showing top users by activity
6898
+ * - User engagement analysis with full user context
6899
+ * - Identifying power users for campaigns
6900
+ * - Customer segmentation by transaction behavior
6901
+ *
6902
+ * @param request - Ranking request with filters, sorting, and limit
6903
+ * @returns Promise resolving to ranked user list with transaction metrics
6904
+ *
6905
+ * @example Top 50 users by transaction count
6906
+ * ```typescript
6907
+ * const ranking = await sdk.analytics.getUserRanking({
6908
+ * sortBy: 'totalTransactions',
6909
+ * sortOrder: 'DESC',
6910
+ * limit: 50
6911
+ * });
6912
+ *
6913
+ * console.log(`Top ${ranking.totalUsers} users:`);
6914
+ * ranking.results.forEach((user, index) => {
6915
+ * console.log(`#${index + 1}: ${user.email || user.externalUserId}`);
6916
+ * console.log(` Transactions: ${user.totalTransactions}`);
6917
+ * console.log(` Token spent: ${user.tokenSpent}`);
6918
+ * });
6919
+ * ```
6920
+ *
6921
+ * @example Top users by STAMP spending
6922
+ * ```typescript
6923
+ * const ranking = await sdk.analytics.getUserRanking({
6924
+ * filters: { tokenType: 'STAMP' },
6925
+ * sortBy: 'tokenSpent',
6926
+ * sortOrder: 'DESC',
6927
+ * limit: 20
6928
+ * });
6929
+ *
6930
+ * console.log('Top 20 STAMP spenders:');
6931
+ * ranking.results.forEach((user, index) => {
6932
+ * const identifier = user.email || user.externalUserId || user.userId;
6933
+ * console.log(`${index + 1}. ${identifier} - ${user.tokenSpent} STAMP`);
6934
+ * });
6935
+ * ```
6936
+ */
6937
+ async getUserRanking(request = {}) {
6938
+ return this.analyticsService.getUserRanking(request);
6939
+ }
6940
+ /**
6941
+ * Get business transaction ranking with enriched business data
6942
+ *
6943
+ * Returns ranked list of businesses with full business details and transaction metrics.
6944
+ *
6945
+ * @param request - Ranking request with filters, sorting, and limit
6946
+ * @returns Promise resolving to ranked business list
6947
+ */
6948
+ async getBusinessRanking(request = {}) {
6949
+ return this.analyticsService.getBusinessRanking(request);
6950
+ }
6951
+ /**
6952
+ * Get monthly user retention analytics
6953
+ *
6954
+ * Returns monthly retention data with user metrics and retention rates.
6955
+ *
6956
+ * @param request - Retention request with monthsBack and filters
6957
+ * @returns Promise resolving to monthly retention data
6958
+ */
6959
+ async getRetentionAnalytics(request = {}) {
6960
+ return this.analyticsService.getRetentionAnalytics(request);
6961
+ }
6557
6962
  /**
6558
6963
  * Get the full analytics service for advanced operations
6559
6964
  *
@@ -6648,6 +7053,360 @@ class DonationManager {
6648
7053
  }
6649
7054
  }
6650
7055
 
7056
+ /**
7057
+ * Platform-Agnostic TriggerSource API Client
7058
+ *
7059
+ * Handles all trigger source operations:
7060
+ * - CRUD operations for trigger sources (QR codes, NFC tags, GPS geofences, webhooks, etc.)
7061
+ * - Trigger sources are independent entities that can be assigned to campaigns
7062
+ *
7063
+ * Uses @explorins/pers-shared DTOs for consistency with backend.
7064
+ */
7065
+ class TriggerSourceApi {
7066
+ constructor(apiClient) {
7067
+ this.apiClient = apiClient;
7068
+ }
7069
+ /**
7070
+ * PUBLIC: Get trigger sources with optional filters and pagination
7071
+ *
7072
+ * @param options - Filter and pagination options
7073
+ * @returns Paginated list of trigger sources
7074
+ *
7075
+ * @example
7076
+ * ```typescript
7077
+ * // Get all QR code trigger sources
7078
+ * const qrSources = await triggerSourceApi.getTriggerSources({ type: 'QR_CODE' });
7079
+ *
7080
+ * // Get trigger sources for a specific campaign
7081
+ * const campaignSources = await triggerSourceApi.getTriggerSources({
7082
+ * campaignId: 'campaign-123',
7083
+ * page: 1,
7084
+ * limit: 20
7085
+ * });
7086
+ * ```
7087
+ */
7088
+ async getTriggerSources(options) {
7089
+ const params = buildPaginationParams(options);
7090
+ if (options?.type)
7091
+ params.set('type', options.type);
7092
+ if (options?.businessId)
7093
+ params.set('businessId', options.businessId);
7094
+ if (options?.campaignId)
7095
+ params.set('campaignId', options.campaignId);
7096
+ if (options?.active !== undefined)
7097
+ params.set('active', String(options.active));
7098
+ const response = await this.apiClient.get(`/trigger-sources?${params.toString()}`);
7099
+ return normalizeToPaginated(response);
7100
+ }
7101
+ /**
7102
+ * PUBLIC: Get trigger source by ID
7103
+ *
7104
+ * @param triggerSourceId - UUID of the trigger source
7105
+ * @returns Trigger source details
7106
+ */
7107
+ async getTriggerSourceById(triggerSourceId) {
7108
+ return this.apiClient.get(`/trigger-sources/${triggerSourceId}`);
7109
+ }
7110
+ /**
7111
+ * ADMIN: Create a new trigger source
7112
+ *
7113
+ * @param triggerSource - Trigger source creation data
7114
+ * @returns Created trigger source
7115
+ *
7116
+ * @example
7117
+ * ```typescript
7118
+ * const qrSource = await triggerSourceApi.createTriggerSource({
7119
+ * type: 'QR_CODE',
7120
+ * name: 'Store Entrance QR',
7121
+ * description: 'QR code at main entrance',
7122
+ * businessId: 'business-123',
7123
+ * coordsLatitude: 47.6062,
7124
+ * coordsLongitude: -122.3321
7125
+ * });
7126
+ * ```
7127
+ */
7128
+ async createTriggerSource(triggerSource) {
7129
+ return this.apiClient.post('/trigger-sources', triggerSource);
7130
+ }
7131
+ /**
7132
+ * ADMIN: Update a trigger source
7133
+ *
7134
+ * @param triggerSourceId - UUID of the trigger source to update
7135
+ * @param triggerSource - Updated trigger source data (partial)
7136
+ * @returns Updated trigger source
7137
+ */
7138
+ async updateTriggerSource(triggerSourceId, triggerSource) {
7139
+ return this.apiClient.put(`/trigger-sources/${triggerSourceId}`, triggerSource);
7140
+ }
7141
+ /**
7142
+ * ADMIN: Delete (soft delete) a trigger source
7143
+ *
7144
+ * @param triggerSourceId - UUID of the trigger source to delete
7145
+ * @returns Success status
7146
+ */
7147
+ async deleteTriggerSource(triggerSourceId) {
7148
+ return this.apiClient.delete(`/trigger-sources/${triggerSourceId}`);
7149
+ }
7150
+ }
7151
+
7152
+ /**
7153
+ * Platform-Agnostic TriggerSource Service
7154
+ *
7155
+ * Contains trigger source business logic and operations that work across platforms.
7156
+ * No framework dependencies - pure TypeScript business logic.
7157
+ */
7158
+ class TriggerSourceService {
7159
+ constructor(triggerSourceApi) {
7160
+ this.triggerSourceApi = triggerSourceApi;
7161
+ }
7162
+ /**
7163
+ * Get trigger sources with optional filters
7164
+ */
7165
+ async getTriggerSources(options) {
7166
+ return this.triggerSourceApi.getTriggerSources(options);
7167
+ }
7168
+ /**
7169
+ * Get trigger source by ID
7170
+ */
7171
+ async getTriggerSourceById(triggerSourceId) {
7172
+ return this.triggerSourceApi.getTriggerSourceById(triggerSourceId);
7173
+ }
7174
+ /**
7175
+ * ADMIN: Create a new trigger source
7176
+ */
7177
+ async createTriggerSource(triggerSource) {
7178
+ return this.triggerSourceApi.createTriggerSource(triggerSource);
7179
+ }
7180
+ /**
7181
+ * ADMIN: Update a trigger source
7182
+ */
7183
+ async updateTriggerSource(triggerSourceId, triggerSource) {
7184
+ return this.triggerSourceApi.updateTriggerSource(triggerSourceId, triggerSource);
7185
+ }
7186
+ /**
7187
+ * ADMIN: Delete a trigger source
7188
+ */
7189
+ async deleteTriggerSource(triggerSourceId) {
7190
+ return this.triggerSourceApi.deleteTriggerSource(triggerSourceId);
7191
+ }
7192
+ }
7193
+
7194
+ /**
7195
+ * TriggerSource Manager - Clean, high-level interface for trigger source operations
7196
+ *
7197
+ * Manages trigger sources which are physical or digital activation points for campaigns:
7198
+ * - QR_CODE: Scannable QR codes
7199
+ * - NFC_TAG: NFC tap points
7200
+ * - GPS_GEOFENCE: Location-based triggers
7201
+ * - API_WEBHOOK: External system integration
7202
+ * - TRANSACTION: Purchase/payment based triggers
7203
+ *
7204
+ * Trigger sources are independent entities that can be created, managed, and then
7205
+ * assigned to campaigns. This separation allows reuse and flexible campaign configuration.
7206
+ *
7207
+ * @group Managers
7208
+ * @category TriggerSource Management
7209
+ *
7210
+ * @example Basic TriggerSource Operations
7211
+ * ```typescript
7212
+ * // Get all QR code trigger sources
7213
+ * const qrSources = await sdk.triggerSources.getAll({ type: 'QR_CODE' });
7214
+ *
7215
+ * // Create a new QR code trigger source
7216
+ * const source = await sdk.triggerSources.create({
7217
+ * type: 'QR_CODE',
7218
+ * name: 'Store Entrance QR',
7219
+ * businessId: 'business-123'
7220
+ * });
7221
+ *
7222
+ * // Assign to campaign (via CampaignManager)
7223
+ * await sdk.campaigns.assignTriggerSource('campaign-456', source.id);
7224
+ * ```
7225
+ */
7226
+ class TriggerSourceManager {
7227
+ constructor(apiClient, events) {
7228
+ this.apiClient = apiClient;
7229
+ this.events = events;
7230
+ const triggerSourceApi = new TriggerSourceApi(apiClient);
7231
+ this.triggerSourceService = new TriggerSourceService(triggerSourceApi);
7232
+ }
7233
+ /**
7234
+ * Get trigger sources with optional filters and pagination
7235
+ *
7236
+ * Retrieves trigger sources (QR codes, NFC tags, GPS geofences, webhooks, etc.)
7237
+ * that can be used to activate campaigns. Supports filtering by type, business,
7238
+ * campaign association, and active status.
7239
+ *
7240
+ * @param options - Filter and pagination options
7241
+ * @returns Promise resolving to paginated trigger sources
7242
+ *
7243
+ * @example
7244
+ * ```typescript
7245
+ * // Get all QR code trigger sources
7246
+ * const qrSources = await sdk.triggerSources.getAll({ type: 'QR_CODE' });
7247
+ *
7248
+ * // Get trigger sources for a specific business
7249
+ * const businessSources = await sdk.triggerSources.getAll({
7250
+ * businessId: 'business-123',
7251
+ * active: true,
7252
+ * page: 1,
7253
+ * limit: 20
7254
+ * });
7255
+ *
7256
+ * // Get trigger sources assigned to a campaign
7257
+ * const campaignSources = await sdk.triggerSources.getAll({
7258
+ * campaignId: 'campaign-456'
7259
+ * });
7260
+ * ```
7261
+ */
7262
+ async getAll(options) {
7263
+ return this.triggerSourceService.getTriggerSources(options);
7264
+ }
7265
+ /**
7266
+ * Get trigger source by ID
7267
+ *
7268
+ * Retrieves detailed information for a specific trigger source including
7269
+ * its type, location, metadata, and usage analytics.
7270
+ *
7271
+ * @param triggerSourceId - UUID of the trigger source
7272
+ * @returns Promise resolving to trigger source details
7273
+ * @throws {PersApiError} When trigger source with specified ID is not found
7274
+ *
7275
+ * @example
7276
+ * ```typescript
7277
+ * const source = await sdk.triggerSources.getById('source-123');
7278
+ *
7279
+ * console.log('Trigger Source:', source.name);
7280
+ * console.log('Type:', source.type);
7281
+ * console.log('Active:', source.isActive);
7282
+ *
7283
+ * if (source.coordsLatitude && source.coordsLongitude) {
7284
+ * console.log('Location:', source.coordsLatitude, source.coordsLongitude);
7285
+ * }
7286
+ * ```
7287
+ */
7288
+ async getById(triggerSourceId) {
7289
+ return this.triggerSourceService.getTriggerSourceById(triggerSourceId);
7290
+ }
7291
+ /**
7292
+ * Admin: Create a new trigger source
7293
+ *
7294
+ * Creates a new trigger source (QR code, NFC tag, GPS geofence, webhook, or
7295
+ * transaction-based trigger) that can be assigned to campaigns. Requires
7296
+ * administrator privileges.
7297
+ *
7298
+ * @param triggerSource - Trigger source creation data
7299
+ * @returns Promise resolving to created trigger source
7300
+ * @throws {PersApiError} When not authenticated as admin or validation fails
7301
+ *
7302
+ * @example
7303
+ * ```typescript
7304
+ * // Create a QR code trigger source
7305
+ * const qrSource = await sdk.triggerSources.create({
7306
+ * type: 'QR_CODE',
7307
+ * name: 'Store Entrance QR',
7308
+ * description: 'QR code at main entrance',
7309
+ * businessId: 'business-123',
7310
+ * coordsLatitude: 47.6062,
7311
+ * coordsLongitude: -122.3321
7312
+ * });
7313
+ *
7314
+ * // Create an NFC tag trigger source
7315
+ * const nfcSource = await sdk.triggerSources.create({
7316
+ * type: 'NFC_TAG',
7317
+ * name: 'Product Display NFC',
7318
+ * metadata: { productId: 'SKU-12345' }
7319
+ * });
7320
+ *
7321
+ * // Create a GPS geofence trigger source
7322
+ * const geoSource = await sdk.triggerSources.create({
7323
+ * type: 'GPS_GEOFENCE',
7324
+ * name: 'Store Area',
7325
+ * coordsLatitude: 47.6062,
7326
+ * coordsLongitude: -122.3321,
7327
+ * metadata: { radiusMeters: 100 }
7328
+ * });
7329
+ * ```
7330
+ */
7331
+ async create(triggerSource) {
7332
+ const result = await this.triggerSourceService.createTriggerSource(triggerSource);
7333
+ this.events?.emitSuccess({
7334
+ domain: 'trigger-source',
7335
+ type: 'TRIGGER_SOURCE_CREATED',
7336
+ userMessage: 'Trigger source created successfully',
7337
+ details: { triggerSourceId: result.id, type: result.type }
7338
+ });
7339
+ return result;
7340
+ }
7341
+ /**
7342
+ * Admin: Update a trigger source
7343
+ *
7344
+ * Updates an existing trigger source's configuration. All fields are optional;
7345
+ * only provided fields will be updated. Requires administrator privileges.
7346
+ *
7347
+ * @param triggerSourceId - UUID of the trigger source to update
7348
+ * @param triggerSource - Updated trigger source data (partial)
7349
+ * @returns Promise resolving to updated trigger source
7350
+ * @throws {PersApiError} When not authenticated as admin or trigger source not found
7351
+ *
7352
+ * @example
7353
+ * ```typescript
7354
+ * // Update trigger source name and location
7355
+ * const updated = await sdk.triggerSources.update('source-123', {
7356
+ * name: 'Updated Store Entrance QR',
7357
+ * description: 'New description',
7358
+ * coordsLatitude: 47.6063,
7359
+ * coordsLongitude: -122.3322
7360
+ * });
7361
+ * ```
7362
+ */
7363
+ async update(triggerSourceId, triggerSource) {
7364
+ const result = await this.triggerSourceService.updateTriggerSource(triggerSourceId, triggerSource);
7365
+ this.events?.emitSuccess({
7366
+ domain: 'trigger-source',
7367
+ type: 'TRIGGER_SOURCE_UPDATED',
7368
+ userMessage: 'Trigger source updated successfully',
7369
+ details: { triggerSourceId }
7370
+ });
7371
+ return result;
7372
+ }
7373
+ /**
7374
+ * Admin: Delete a trigger source
7375
+ *
7376
+ * Soft deletes a trigger source, making it inactive. The trigger source will
7377
+ * be removed from any campaigns it was assigned to. Requires administrator
7378
+ * privileges.
7379
+ *
7380
+ * @param triggerSourceId - UUID of the trigger source to delete
7381
+ * @returns Promise resolving to success status
7382
+ * @throws {PersApiError} When not authenticated as admin or trigger source not found
7383
+ *
7384
+ * @example
7385
+ * ```typescript
7386
+ * const success = await sdk.triggerSources.delete('source-123');
7387
+ * console.log('Trigger source deleted:', success);
7388
+ * ```
7389
+ */
7390
+ async delete(triggerSourceId) {
7391
+ const result = await this.triggerSourceService.deleteTriggerSource(triggerSourceId);
7392
+ this.events?.emitSuccess({
7393
+ domain: 'trigger-source',
7394
+ type: 'TRIGGER_SOURCE_DELETED',
7395
+ userMessage: 'Trigger source deleted successfully',
7396
+ details: { triggerSourceId }
7397
+ });
7398
+ return result;
7399
+ }
7400
+ /**
7401
+ * Get the full trigger source service for advanced operations
7402
+ *
7403
+ * @returns TriggerSourceService instance with full API access
7404
+ */
7405
+ getTriggerSourceService() {
7406
+ return this.triggerSourceService;
7407
+ }
7408
+ }
7409
+
6651
7410
  /**
6652
7411
  * @fileoverview PERS SDK - Platform-agnostic TypeScript SDK with High-Level Managers
6653
7412
  *
@@ -7134,6 +7893,40 @@ class PersSDK {
7134
7893
  }
7135
7894
  return this._donations;
7136
7895
  }
7896
+ /**
7897
+ * TriggerSource manager - High-level trigger source operations (Admin Only)
7898
+ *
7899
+ * Provides CRUD operations for managing trigger sources (QR codes, NFC tags,
7900
+ * GPS geofences, API webhooks). TriggerSources are standalone entities that
7901
+ * can be assigned to campaigns via the campaigns manager.
7902
+ *
7903
+ * @returns TriggerSourceManager instance
7904
+ *
7905
+ * @example TriggerSource Operations
7906
+ * ```typescript
7907
+ * // Create a QR code trigger source
7908
+ * const qrSource = await sdk.triggerSources.create({
7909
+ * name: 'Store Entrance QR',
7910
+ * type: 'QR_CODE',
7911
+ * description: 'QR code at main entrance'
7912
+ * });
7913
+ *
7914
+ * // Get all trigger sources
7915
+ * const sources = await sdk.triggerSources.getAll();
7916
+ *
7917
+ * // Update trigger source
7918
+ * await sdk.triggerSources.update(sourceId, { name: 'Updated Name' });
7919
+ *
7920
+ * // Assign to campaign (via campaigns manager)
7921
+ * await sdk.campaigns.assignTriggerSource(campaignId, qrSource.id);
7922
+ * ```
7923
+ */
7924
+ get triggerSources() {
7925
+ if (!this._triggerSources) {
7926
+ this._triggerSources = new TriggerSourceManager(this.apiClient, this._events);
7927
+ }
7928
+ return this._triggerSources;
7929
+ }
7137
7930
  /**
7138
7931
  * Gets the API client for direct PERS API requests
7139
7932
  *
@@ -7183,5 +7976,5 @@ function createPersSDK(httpClient, config) {
7183
7976
  return new PersSDK(httpClient, config);
7184
7977
  }
7185
7978
 
7186
- export { AuthStatus as A, BusinessManager as B, CampaignManager as C, DefaultAuthProvider as D, FileManager as F, LocalStorageTokenStorage as L, MemoryTokenStorage as M, PersSDK as P, RedemptionManager as R, 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, StaticJwtAuthProvider as j, AuthApi as k, AuthService as l, mergeWithDefaults as m, DPoPManager as n, PersEventEmitter as o, AuthManager as p, UserStatusManager as q, TransactionManager as r, PurchaseManager as s, TenantManager as t, ApiKeyManager as u, AnalyticsManager as v, DonationManager as w, FileApi as x, FileService as y, ApiKeyApi as z };
7187
- //# sourceMappingURL=pers-sdk-fWg-J3_h.js.map
7979
+ export { AuthStatus as A, BusinessManager as B, CampaignManager as C, DefaultAuthProvider as D, ApiKeyApi as E, FileManager as F, TriggerSourceApi as G, TriggerSourceService as H, LocalStorageTokenStorage as L, MemoryTokenStorage as M, 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, StaticJwtAuthProvider as j, AuthApi as k, AuthService as l, mergeWithDefaults as m, DPoPManager as n, PersEventEmitter as o, AuthManager as p, UserStatusManager as q, TransactionManager as r, PurchaseManager as s, TenantManager as t, ApiKeyManager as u, AnalyticsManager as v, DonationManager as w, TriggerSourceManager as x, FileApi as y, FileService as z };
7980
+ //# sourceMappingURL=pers-sdk-CAM0iQyK.js.map