sfdx-hardis 6.4.4 → 6.5.0

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.
@@ -0,0 +1,163 @@
1
+ // External Libraries and Node.js Modules
2
+ import c from 'chalk';
3
+ // Salesforce Specific Libraries
4
+ import { SfError } from '@salesforce/core';
5
+ // Project Specific Utilities
6
+ import { uxLog } from './index.js';
7
+ // Optimized API Limits Management System
8
+ export class ApiLimitsManager {
9
+ conn;
10
+ commandThis;
11
+ // Caching system
12
+ cachedLimits = null;
13
+ lastRefreshTime = 0;
14
+ cacheDuration = 5 * 60 * 1000; // 5 minutes
15
+ // Local tracking counters
16
+ localRestApiCalls = 0;
17
+ localBulkApiCalls = 0;
18
+ // Base limits from Salesforce
19
+ baseRestApiUsed = 0;
20
+ baseRestApiLimit = 0;
21
+ baseBulkApiUsed = 0;
22
+ baseBulkApiLimit = 0;
23
+ // Thresholds for API management
24
+ WARNING_THRESHOLD = 70; // Force refresh at 70%
25
+ DANGER_THRESHOLD = 80; // Stop operations at 80%
26
+ constructor(conn, commandThis) {
27
+ this.conn = conn;
28
+ this.commandThis = commandThis;
29
+ }
30
+ // Initialize the limits manager with initial API limits data
31
+ async initialize() {
32
+ await this.refreshLimits(); // Initial refresh
33
+ }
34
+ // Refresh limits from Salesforce
35
+ async refreshLimits() {
36
+ const now = Date.now();
37
+ try {
38
+ uxLog("log", this.commandThis, c.grey(`Refreshing API limits from Salesforce...`));
39
+ // Fetch fresh limits from Salesforce
40
+ this.cachedLimits = await this.conn.limits();
41
+ if (!this.cachedLimits) {
42
+ throw new SfError("Unable to retrieve API limit information from Salesforce org.");
43
+ }
44
+ // Extract REST API limits
45
+ if (!this.cachedLimits.DailyApiRequests) {
46
+ throw new SfError("DailyApiRequests limit not available from Salesforce org.");
47
+ }
48
+ this.baseRestApiUsed = this.cachedLimits.DailyApiRequests.Max - this.cachedLimits.DailyApiRequests.Remaining;
49
+ this.baseRestApiLimit = this.cachedLimits.DailyApiRequests.Max;
50
+ // Extract Bulk API v2 limits
51
+ if (!this.cachedLimits.DailyBulkV2QueryJobs) {
52
+ throw new SfError("DailyBulkV2QueryJobs limit not available from Salesforce org.");
53
+ }
54
+ this.baseBulkApiUsed = this.cachedLimits.DailyBulkV2QueryJobs.Max - this.cachedLimits.DailyBulkV2QueryJobs.Remaining;
55
+ this.baseBulkApiLimit = this.cachedLimits.DailyBulkV2QueryJobs.Max;
56
+ // Reset local counters on fresh data
57
+ this.localRestApiCalls = 0;
58
+ this.localBulkApiCalls = 0;
59
+ this.lastRefreshTime = now;
60
+ uxLog("success", this.commandThis, `API Limits refreshed - REST: ${this.baseRestApiUsed}/${this.baseRestApiLimit}, Bulk: ${this.baseBulkApiUsed}/${this.baseBulkApiLimit}`);
61
+ }
62
+ catch (error) {
63
+ if (error instanceof SfError)
64
+ throw error;
65
+ throw new SfError(`Failed to refresh API limits: ${error?.message || 'Unknown error'}`);
66
+ }
67
+ }
68
+ // Track API call and check if we need to wait or refresh
69
+ async trackApiCall(apiType) {
70
+ // Increment local counter
71
+ if (apiType === 'REST') {
72
+ this.localRestApiCalls++;
73
+ }
74
+ else {
75
+ this.localBulkApiCalls++;
76
+ }
77
+ // Check if cache has expired (5 minutes)
78
+ const now = Date.now();
79
+ const cacheAge = now - this.lastRefreshTime;
80
+ const cacheExpired = cacheAge >= this.cacheDuration;
81
+ if (cacheExpired) {
82
+ await this.refreshLimits(); // Use smart caching (no force)
83
+ }
84
+ // Calculate current usage after potential refresh
85
+ const currentRestUsage = this.baseRestApiUsed + this.localRestApiCalls;
86
+ const currentBulkUsage = this.baseBulkApiUsed + this.localBulkApiCalls;
87
+ const restPercent = (currentRestUsage / this.baseRestApiLimit) * 100;
88
+ const bulkPercent = (currentBulkUsage / this.baseBulkApiLimit) * 100;
89
+ // Check if we need to wait due to danger threshold
90
+ if (apiType === 'REST' && restPercent >= this.DANGER_THRESHOLD) {
91
+ await this.waitForLimitReset('REST', restPercent);
92
+ }
93
+ if (apiType === 'BULK' && bulkPercent >= this.DANGER_THRESHOLD) {
94
+ await this.waitForLimitReset('BULK', bulkPercent);
95
+ }
96
+ } // Wait for API limits to reset
97
+ async waitForLimitReset(apiType, currentPercent) {
98
+ const WAIT_INTERVAL = 300; // 5 minutes
99
+ const MAX_CYCLES = 12; // 1 hour max
100
+ uxLog("warning", this.commandThis, c.yellow(`${apiType} API at ${currentPercent.toFixed(1)}%. Waiting for limits to reset...`));
101
+ for (let cycle = 0; cycle < MAX_CYCLES; cycle++) {
102
+ uxLog("action", this.commandThis, c.cyan(`Waiting ${WAIT_INTERVAL}s for ${apiType} API reset (${cycle + 1}/${MAX_CYCLES})...`));
103
+ // Wait in 1-second intervals
104
+ for (let i = 0; i < WAIT_INTERVAL; i++) {
105
+ await new Promise(resolve => setTimeout(resolve, 1000));
106
+ }
107
+ // Check if limits have reset
108
+ await this.refreshLimits();
109
+ const currentUsage = apiType === 'REST'
110
+ ? this.baseRestApiUsed + this.localRestApiCalls
111
+ : this.baseBulkApiUsed + this.localBulkApiCalls;
112
+ const limit = apiType === 'REST' ? this.baseRestApiLimit : this.baseBulkApiLimit;
113
+ const percent = (currentUsage / limit) * 100;
114
+ if (percent < this.WARNING_THRESHOLD) {
115
+ uxLog("success", this.commandThis, c.green(`${apiType} API usage dropped to ${percent.toFixed(1)}%. Resuming operations.`));
116
+ return;
117
+ }
118
+ }
119
+ throw new SfError(`${apiType} API limits did not reset after ${MAX_CYCLES * WAIT_INTERVAL / 60} minutes.`);
120
+ }
121
+ // Get current API usage status for display
122
+ getUsageStatus() {
123
+ const currentRestUsage = this.baseRestApiUsed + this.localRestApiCalls;
124
+ const currentBulkUsage = this.baseBulkApiUsed + this.localBulkApiCalls;
125
+ const restPercent = (currentRestUsage / this.baseRestApiLimit) * 100;
126
+ const bulkPercent = (currentBulkUsage / this.baseBulkApiLimit) * 100;
127
+ return {
128
+ rest: restPercent,
129
+ bulk: bulkPercent,
130
+ message: `[REST: ${restPercent.toFixed(1)}% | Bulk: ${bulkPercent.toFixed(1)}%]`
131
+ };
132
+ }
133
+ // Get current usage for API consumption estimation
134
+ getCurrentUsage() {
135
+ const currentRestUsage = this.baseRestApiUsed + this.localRestApiCalls;
136
+ const currentBulkUsage = this.baseBulkApiUsed + this.localBulkApiCalls;
137
+ return {
138
+ restUsed: currentRestUsage,
139
+ restLimit: this.baseRestApiLimit,
140
+ bulkUsed: currentBulkUsage,
141
+ bulkLimit: this.baseBulkApiLimit,
142
+ restRemaining: this.baseRestApiLimit - currentRestUsage,
143
+ bulkRemaining: this.baseBulkApiLimit - currentBulkUsage
144
+ };
145
+ }
146
+ // Get final usage for reporting (forces a fresh refresh)
147
+ async getFinalUsage() {
148
+ await this.refreshLimits(); // Get fresh data
149
+ // Try to get fresh limits from Salesforce
150
+ const currentLimits = this.cachedLimits;
151
+ const restUsed = currentLimits.DailyApiRequests.Max - currentLimits.DailyApiRequests.Remaining;
152
+ const bulkUsed = currentLimits.DailyBulkV2QueryJobs.Max - currentLimits.DailyBulkV2QueryJobs.Remaining;
153
+ return {
154
+ restUsed: restUsed,
155
+ restLimit: currentLimits.DailyApiRequests.Max,
156
+ restRemaining: currentLimits.DailyApiRequests.Remaining,
157
+ bulkUsed: bulkUsed,
158
+ bulkLimit: currentLimits.DailyBulkV2QueryJobs.Max,
159
+ bulkRemaining: currentLimits.DailyBulkV2QueryJobs.Remaining
160
+ };
161
+ }
162
+ }
163
+ //# sourceMappingURL=limitUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limitUtils.js","sourceRoot":"","sources":["../../../src/common/utils/limitUtils.ts"],"names":[],"mappings":"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"}