@wildix/xbees-conversations-utils 2.0.1 → 4.0.2
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.
- package/dist-cjs/anonymousEmail/index.js +3 -3
- package/dist-cjs/rateLimits/RedisCooldown.js +66 -0
- package/dist-cjs/rateLimits/constants.js +43 -0
- package/dist-cjs/rateLimits/createRateLimitedStreamProxy.js +92 -0
- package/dist-cjs/rateLimits/exception/createRateLimitExceededException.js +21 -0
- package/dist-cjs/rateLimits/exception/processStreamRateLimitException.js +47 -0
- package/dist-cjs/rateLimits/executeStreamRequestWithRateLimitHandling.js +94 -0
- package/dist-cjs/rateLimits/generatedMethodNames.js +320 -0
- package/dist-cjs/rateLimits/helpers/RedisCooldown.js +174 -0
- package/dist-cjs/rateLimits/helpers/createRateLimitExceededException.js +32 -0
- package/dist-cjs/rateLimits/helpers/executeWithRateLimitHandling.js +144 -0
- package/dist-cjs/rateLimits/helpers/headerUtils.js +40 -0
- package/dist-cjs/rateLimits/helpers/isStreamChannelLike.js +23 -0
- package/dist-cjs/rateLimits/helpers/processStreamBudgetHeaders.js +93 -0
- package/dist-cjs/rateLimits/helpers/processStreamRateLimitException.js +63 -0
- package/dist-cjs/rateLimits/helpers/processStreamRateLimitHeaders.js +50 -0
- package/dist-cjs/rateLimits/helpers/rateLimitSnapshot.js +31 -0
- package/dist-cjs/rateLimits/helpers/registerStreamBudgetInterceptors.js +48 -0
- package/dist-cjs/rateLimits/helpers/registerStreamInterceptors.js +58 -0
- package/dist-cjs/rateLimits/helpers/splitCallArgsAndOptions.js +21 -0
- package/dist-cjs/rateLimits/index.js +7 -0
- package/dist-cjs/rateLimits/types.js +3 -0
- package/dist-cjs/rateLimits/withStreamRateLimitOptions.js +10 -0
- package/dist-cjs/streamRateLimitHandlingProxy/constants.js +42 -0
- package/dist-cjs/streamRateLimitHandlingProxy/createRateLimitedStreamProxy.js +92 -0
- package/dist-cjs/streamRateLimitHandlingProxy/generatedMethodNames.js +320 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/RedisCooldown.js +174 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/createRateLimitExceededException.js +29 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/executeWithRateLimitHandling.js +153 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/headerUtils.js +48 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/isStreamChannelLike.js +23 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/processStreamBudgetHeaders.js +93 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/processStreamRateLimitException.js +63 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/processStreamRateLimitHeaders.js +46 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/rateLimitSnapshot.js +31 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/registerStreamInterceptors.js +64 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/sleep.js +6 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/splitCallArgsAndOptions.js +21 -0
- package/dist-cjs/streamRateLimitHandlingProxy/index.js +5 -0
- package/dist-cjs/streamRateLimitHandlingProxy/types.js +3 -0
- package/dist-cjs/streamRateLimitHandlingProxy/withStreamRateLimitOptions.js +10 -0
- package/dist-es/anonymousEmail/index.js +1 -1
- package/dist-es/rateLimits/RedisCooldown.js +62 -0
- package/dist-es/rateLimits/constants.js +33 -0
- package/dist-es/rateLimits/createRateLimitedStreamProxy.js +88 -0
- package/dist-es/rateLimits/exception/createRateLimitExceededException.js +17 -0
- package/dist-es/rateLimits/exception/processStreamRateLimitException.js +37 -0
- package/dist-es/rateLimits/executeStreamRequestWithRateLimitHandling.js +93 -0
- package/dist-es/rateLimits/generatedMethodNames.js +317 -0
- package/dist-es/rateLimits/helpers/RedisCooldown.js +170 -0
- package/dist-es/rateLimits/helpers/createRateLimitExceededException.js +28 -0
- package/dist-es/rateLimits/helpers/executeWithRateLimitHandling.js +140 -0
- package/dist-es/rateLimits/helpers/headerUtils.js +34 -0
- package/dist-es/rateLimits/helpers/isStreamChannelLike.js +19 -0
- package/dist-es/rateLimits/helpers/processStreamBudgetHeaders.js +89 -0
- package/dist-es/rateLimits/helpers/processStreamRateLimitException.js +59 -0
- package/dist-es/rateLimits/helpers/processStreamRateLimitHeaders.js +46 -0
- package/dist-es/rateLimits/helpers/rateLimitSnapshot.js +26 -0
- package/dist-es/rateLimits/helpers/registerStreamBudgetInterceptors.js +44 -0
- package/dist-es/rateLimits/helpers/registerStreamInterceptors.js +54 -0
- package/dist-es/rateLimits/helpers/splitCallArgsAndOptions.js +17 -0
- package/dist-es/rateLimits/index.js +4 -0
- package/dist-es/rateLimits/types.js +1 -0
- package/dist-es/rateLimits/withStreamRateLimitOptions.js +6 -0
- package/dist-es/streamRateLimitHandlingProxy/constants.js +32 -0
- package/dist-es/streamRateLimitHandlingProxy/createRateLimitedStreamProxy.js +88 -0
- package/dist-es/streamRateLimitHandlingProxy/generatedMethodNames.js +317 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/RedisCooldown.js +170 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/createRateLimitExceededException.js +25 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/executeWithRateLimitHandling.js +148 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/headerUtils.js +42 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/isStreamChannelLike.js +19 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/processStreamBudgetHeaders.js +89 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/processStreamRateLimitException.js +59 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/processStreamRateLimitHeaders.js +42 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/rateLimitSnapshot.js +26 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/registerStreamInterceptors.js +60 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/sleep.js +4 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/splitCallArgsAndOptions.js +17 -0
- package/dist-es/streamRateLimitHandlingProxy/index.js +2 -0
- package/dist-es/streamRateLimitHandlingProxy/types.js +1 -0
- package/dist-es/streamRateLimitHandlingProxy/withStreamRateLimitOptions.js +6 -0
- package/dist-types/anonymousEmail/index.d.ts +1 -0
- package/dist-types/rateLimits/RedisCooldown.d.ts +7 -0
- package/dist-types/rateLimits/constants.d.ts +29 -0
- package/dist-types/rateLimits/createRateLimitedStreamProxy.d.ts +11 -0
- package/dist-types/rateLimits/exception/createRateLimitExceededException.d.ts +12 -0
- package/dist-types/rateLimits/exception/processStreamRateLimitException.d.ts +8 -0
- package/dist-types/rateLimits/executeStreamRequestWithRateLimitHandling.d.ts +8 -0
- package/dist-types/rateLimits/generatedMethodNames.d.ts +11 -0
- package/dist-types/rateLimits/helpers/RedisCooldown.d.ts +11 -0
- package/dist-types/rateLimits/helpers/createRateLimitExceededException.d.ts +10 -0
- package/dist-types/rateLimits/helpers/executeWithRateLimitHandling.d.ts +2 -0
- package/dist-types/rateLimits/helpers/headerUtils.d.ts +4 -0
- package/dist-types/rateLimits/helpers/isStreamChannelLike.d.ts +6 -0
- package/dist-types/rateLimits/helpers/processStreamBudgetHeaders.d.ts +9 -0
- package/dist-types/rateLimits/helpers/processStreamRateLimitException.d.ts +3 -0
- package/dist-types/rateLimits/helpers/processStreamRateLimitHeaders.d.ts +6 -0
- package/dist-types/rateLimits/helpers/rateLimitSnapshot.d.ts +3 -0
- package/dist-types/rateLimits/helpers/registerStreamBudgetInterceptors.d.ts +2 -0
- package/dist-types/rateLimits/helpers/registerStreamInterceptors.d.ts +2 -0
- package/dist-types/rateLimits/helpers/splitCallArgsAndOptions.d.ts +6 -0
- package/dist-types/rateLimits/index.d.ts +4 -0
- package/dist-types/rateLimits/types.d.ts +68 -0
- package/dist-types/rateLimits/withStreamRateLimitOptions.d.ts +6 -0
- package/dist-types/streamRateLimitHandlingProxy/constants.d.ts +28 -0
- package/dist-types/streamRateLimitHandlingProxy/createRateLimitedStreamProxy.d.ts +11 -0
- package/dist-types/streamRateLimitHandlingProxy/generatedMethodNames.d.ts +11 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/RedisCooldown.d.ts +11 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/createRateLimitExceededException.d.ts +10 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/executeWithRateLimitHandling.d.ts +2 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/headerUtils.d.ts +4 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/isStreamChannelLike.d.ts +6 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/processStreamBudgetHeaders.d.ts +9 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/processStreamRateLimitException.d.ts +3 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/processStreamRateLimitHeaders.d.ts +6 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/rateLimitSnapshot.d.ts +3 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/registerStreamInterceptors.d.ts +2 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/sleep.d.ts +2 -0
- package/dist-types/streamRateLimitHandlingProxy/helpers/splitCallArgsAndOptions.d.ts +6 -0
- package/dist-types/streamRateLimitHandlingProxy/index.d.ts +2 -0
- package/dist-types/streamRateLimitHandlingProxy/types.d.ts +68 -0
- package/dist-types/streamRateLimitHandlingProxy/withStreamRateLimitOptions.d.ts +6 -0
- package/package.json +7 -4
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
export const STREAM_METHOD_NAMES = [
|
|
2
|
+
'_addChannelConfig',
|
|
3
|
+
'_buildWSPayload',
|
|
4
|
+
'_callClientListeners',
|
|
5
|
+
'_createImport',
|
|
6
|
+
'_createImportURL',
|
|
7
|
+
'_deleteUserMessageReference',
|
|
8
|
+
'_enrichAxiosOptions',
|
|
9
|
+
'_getConnectionID',
|
|
10
|
+
'_getImport',
|
|
11
|
+
'_getToken',
|
|
12
|
+
'_handleClientEvent',
|
|
13
|
+
'_handleUserEvent',
|
|
14
|
+
'_hasConnectionID',
|
|
15
|
+
'_isUsingServerAuth',
|
|
16
|
+
'_listImports',
|
|
17
|
+
'_logApiError',
|
|
18
|
+
'_logApiRequest',
|
|
19
|
+
'_logApiResponse',
|
|
20
|
+
'_muteStatus',
|
|
21
|
+
'_normalizeDate',
|
|
22
|
+
'_normalizeExpiration',
|
|
23
|
+
'_queryFlagReports',
|
|
24
|
+
'_queryFlags',
|
|
25
|
+
'_reviewFlagReport',
|
|
26
|
+
'_sayHi',
|
|
27
|
+
'_setToken',
|
|
28
|
+
'_setupConnection',
|
|
29
|
+
'_setUser',
|
|
30
|
+
'_startCleaning',
|
|
31
|
+
'_unblockMessage',
|
|
32
|
+
'_updateMemberWatcherReferences',
|
|
33
|
+
'_updateUserMessageReferences',
|
|
34
|
+
'_updateUserReferences',
|
|
35
|
+
'_validateAndGetMessageId',
|
|
36
|
+
'addDevice',
|
|
37
|
+
'banUser',
|
|
38
|
+
'channel',
|
|
39
|
+
'closeConnection',
|
|
40
|
+
'commitMessage',
|
|
41
|
+
'connect',
|
|
42
|
+
'connectAnonymousUser',
|
|
43
|
+
'connectUser',
|
|
44
|
+
'createAbortControllerForNextRequest',
|
|
45
|
+
'createBlockList',
|
|
46
|
+
'createCampaign',
|
|
47
|
+
'createChannelType',
|
|
48
|
+
'createCommand',
|
|
49
|
+
'createPermission',
|
|
50
|
+
'createRole',
|
|
51
|
+
'createSegment',
|
|
52
|
+
'createToken',
|
|
53
|
+
'deactivateUser',
|
|
54
|
+
'deactivateUsers',
|
|
55
|
+
'delete',
|
|
56
|
+
'deleteBlockList',
|
|
57
|
+
'deleteCampaign',
|
|
58
|
+
'deleteChannels',
|
|
59
|
+
'deleteChannelType',
|
|
60
|
+
'deleteCommand',
|
|
61
|
+
'deleteMessage',
|
|
62
|
+
'deletePermission',
|
|
63
|
+
'deletePushProvider',
|
|
64
|
+
'deleteRole',
|
|
65
|
+
'deleteSegment',
|
|
66
|
+
'deleteUser',
|
|
67
|
+
'deleteUsers',
|
|
68
|
+
'devToken',
|
|
69
|
+
'disconnect',
|
|
70
|
+
'disconnectUser',
|
|
71
|
+
'dispatchEvent',
|
|
72
|
+
'doAxiosRequest',
|
|
73
|
+
'enrichURL',
|
|
74
|
+
'errorFromResponse',
|
|
75
|
+
'exportChannel',
|
|
76
|
+
'exportChannels',
|
|
77
|
+
'exportUser',
|
|
78
|
+
'exportUsers',
|
|
79
|
+
'flagMessage',
|
|
80
|
+
'flagUser',
|
|
81
|
+
'get',
|
|
82
|
+
'getAppSettings',
|
|
83
|
+
'getAuthType',
|
|
84
|
+
'getBlockList',
|
|
85
|
+
'getCallToken',
|
|
86
|
+
'getChannelById',
|
|
87
|
+
'getChannelByMembers',
|
|
88
|
+
'getChannelType',
|
|
89
|
+
'getCommand',
|
|
90
|
+
'getDevices',
|
|
91
|
+
'getExportChannelStatus',
|
|
92
|
+
'getMessage',
|
|
93
|
+
'getPermission',
|
|
94
|
+
'getRateLimits',
|
|
95
|
+
'getTask',
|
|
96
|
+
'getUnreadCount',
|
|
97
|
+
'getUserAgent',
|
|
98
|
+
'handleEvent',
|
|
99
|
+
'handleResponse',
|
|
100
|
+
'hydrateActiveChannels',
|
|
101
|
+
'listBlockLists',
|
|
102
|
+
'listChannelTypes',
|
|
103
|
+
'listCommands',
|
|
104
|
+
'listPermissions',
|
|
105
|
+
'listPushProviders',
|
|
106
|
+
'listRoles',
|
|
107
|
+
'markAllRead',
|
|
108
|
+
'markChannelsRead',
|
|
109
|
+
'muteUser',
|
|
110
|
+
'off',
|
|
111
|
+
'on',
|
|
112
|
+
'openConnection',
|
|
113
|
+
'partialUpdateMessage',
|
|
114
|
+
'partialUpdateUser',
|
|
115
|
+
'partialUpdateUsers',
|
|
116
|
+
'patch',
|
|
117
|
+
'pinMessage',
|
|
118
|
+
'post',
|
|
119
|
+
'put',
|
|
120
|
+
'queryBannedUsers',
|
|
121
|
+
'queryCampaigns',
|
|
122
|
+
'queryChannels',
|
|
123
|
+
'queryMessageFlags',
|
|
124
|
+
'queryRecipients',
|
|
125
|
+
'querySegments',
|
|
126
|
+
'queryUsers',
|
|
127
|
+
'reactivateUser',
|
|
128
|
+
'reactivateUsers',
|
|
129
|
+
'recoverState',
|
|
130
|
+
'removeDevice',
|
|
131
|
+
'removeShadowBan',
|
|
132
|
+
'restoreUsers',
|
|
133
|
+
'resumeCampaign',
|
|
134
|
+
'revokeTokens',
|
|
135
|
+
'revokeUsersToken',
|
|
136
|
+
'revokeUserToken',
|
|
137
|
+
'scheduleCampaign',
|
|
138
|
+
'search',
|
|
139
|
+
'sendFile',
|
|
140
|
+
'sendUserCustomEvent',
|
|
141
|
+
'setAnonymousUser',
|
|
142
|
+
'setBaseURL',
|
|
143
|
+
'setGuestUser',
|
|
144
|
+
'setLocalDevice',
|
|
145
|
+
'setUser',
|
|
146
|
+
'setUserAgent',
|
|
147
|
+
'shadowBan',
|
|
148
|
+
'stopCampaign',
|
|
149
|
+
'sync',
|
|
150
|
+
'testCampaign',
|
|
151
|
+
'testPushSettings',
|
|
152
|
+
'testSQSSettings',
|
|
153
|
+
'translateMessage',
|
|
154
|
+
'unbanUser',
|
|
155
|
+
'unblockMessage',
|
|
156
|
+
'unflagMessage',
|
|
157
|
+
'unflagUser',
|
|
158
|
+
'unmuteUser',
|
|
159
|
+
'unpinMessage',
|
|
160
|
+
'updateAppSettings',
|
|
161
|
+
'updateBlockList',
|
|
162
|
+
'updateCampaign',
|
|
163
|
+
'updateChannelType',
|
|
164
|
+
'updateCommand',
|
|
165
|
+
'updateMessage',
|
|
166
|
+
'updatePermission',
|
|
167
|
+
'updateSegment',
|
|
168
|
+
'updateUser',
|
|
169
|
+
'updateUsers',
|
|
170
|
+
'upsertPushProvider',
|
|
171
|
+
'upsertUser',
|
|
172
|
+
'upsertUsers',
|
|
173
|
+
'userMuteStatus',
|
|
174
|
+
'verifyWebhook',
|
|
175
|
+
];
|
|
176
|
+
export const STREAM_SYNC_METHOD_NAMES = [
|
|
177
|
+
'_addChannelConfig',
|
|
178
|
+
'_buildWSPayload',
|
|
179
|
+
'_callClientListeners',
|
|
180
|
+
'_deleteUserMessageReference',
|
|
181
|
+
'_enrichAxiosOptions',
|
|
182
|
+
'_getConnectionID',
|
|
183
|
+
'_getToken',
|
|
184
|
+
'_handleClientEvent',
|
|
185
|
+
'_handleUserEvent',
|
|
186
|
+
'_hasConnectionID',
|
|
187
|
+
'_isUsingServerAuth',
|
|
188
|
+
'_logApiError',
|
|
189
|
+
'_logApiRequest',
|
|
190
|
+
'_logApiResponse',
|
|
191
|
+
'_muteStatus',
|
|
192
|
+
'_normalizeDate',
|
|
193
|
+
'_normalizeExpiration',
|
|
194
|
+
'_sayHi',
|
|
195
|
+
'_setUser',
|
|
196
|
+
'_startCleaning',
|
|
197
|
+
'_updateMemberWatcherReferences',
|
|
198
|
+
'_updateUserMessageReferences',
|
|
199
|
+
'_updateUserReferences',
|
|
200
|
+
'_validateAndGetMessageId',
|
|
201
|
+
'createAbortControllerForNextRequest',
|
|
202
|
+
'createToken',
|
|
203
|
+
'devToken',
|
|
204
|
+
'dispatchEvent',
|
|
205
|
+
'errorFromResponse',
|
|
206
|
+
'getAuthType',
|
|
207
|
+
'getUserAgent',
|
|
208
|
+
'handleEvent',
|
|
209
|
+
'handleResponse',
|
|
210
|
+
'off',
|
|
211
|
+
'on',
|
|
212
|
+
'setBaseURL',
|
|
213
|
+
'setLocalDevice',
|
|
214
|
+
'setUserAgent',
|
|
215
|
+
'userMuteStatus',
|
|
216
|
+
'verifyWebhook',
|
|
217
|
+
];
|
|
218
|
+
export const STREAM_CHANNEL_RESULT_METHOD_NAMES = [
|
|
219
|
+
'channel',
|
|
220
|
+
'getChannelById',
|
|
221
|
+
'getChannelByMembers',
|
|
222
|
+
'hydrateActiveChannels',
|
|
223
|
+
'queryChannels',
|
|
224
|
+
];
|
|
225
|
+
export const STREAM_SYNC_CHANNEL_RESULT_METHOD_NAMES = [
|
|
226
|
+
'channel',
|
|
227
|
+
'getChannelById',
|
|
228
|
+
'getChannelByMembers',
|
|
229
|
+
'hydrateActiveChannels',
|
|
230
|
+
];
|
|
231
|
+
export const CHANNEL_METHOD_NAMES = [
|
|
232
|
+
'_callChannelListeners',
|
|
233
|
+
'_channelURL',
|
|
234
|
+
'_checkInitialized',
|
|
235
|
+
'_countMessageAsUnread',
|
|
236
|
+
'_disconnect',
|
|
237
|
+
'_extendEventWithOwnReactions',
|
|
238
|
+
'_handleChannelEvent',
|
|
239
|
+
'_initializeState',
|
|
240
|
+
'_update',
|
|
241
|
+
'acceptInvite',
|
|
242
|
+
'addMembers',
|
|
243
|
+
'addModerators',
|
|
244
|
+
'assignRoles',
|
|
245
|
+
'banUser',
|
|
246
|
+
'clean',
|
|
247
|
+
'countUnread',
|
|
248
|
+
'countUnreadMentions',
|
|
249
|
+
'create',
|
|
250
|
+
'createCall',
|
|
251
|
+
'delete',
|
|
252
|
+
'deleteFile',
|
|
253
|
+
'deleteImage',
|
|
254
|
+
'deleteReaction',
|
|
255
|
+
'demoteModerators',
|
|
256
|
+
'disableSlowMode',
|
|
257
|
+
'enableSlowMode',
|
|
258
|
+
'getClient',
|
|
259
|
+
'getConfig',
|
|
260
|
+
'getMessagesById',
|
|
261
|
+
'getPinnedMessages',
|
|
262
|
+
'getReactions',
|
|
263
|
+
'getReplies',
|
|
264
|
+
'hide',
|
|
265
|
+
'inviteMembers',
|
|
266
|
+
'keystroke',
|
|
267
|
+
'lastMessage',
|
|
268
|
+
'lastRead',
|
|
269
|
+
'markRead',
|
|
270
|
+
'markUnread',
|
|
271
|
+
'mute',
|
|
272
|
+
'muteStatus',
|
|
273
|
+
'off',
|
|
274
|
+
'on',
|
|
275
|
+
'query',
|
|
276
|
+
'queryMembers',
|
|
277
|
+
'rejectInvite',
|
|
278
|
+
'removeMembers',
|
|
279
|
+
'removeShadowBan',
|
|
280
|
+
'search',
|
|
281
|
+
'sendAction',
|
|
282
|
+
'sendEvent',
|
|
283
|
+
'sendFile',
|
|
284
|
+
'sendImage',
|
|
285
|
+
'sendMessage',
|
|
286
|
+
'sendReaction',
|
|
287
|
+
'shadowBan',
|
|
288
|
+
'show',
|
|
289
|
+
'stopTyping',
|
|
290
|
+
'stopWatching',
|
|
291
|
+
'truncate',
|
|
292
|
+
'unbanUser',
|
|
293
|
+
'unmute',
|
|
294
|
+
'update',
|
|
295
|
+
'updatePartial',
|
|
296
|
+
'watch',
|
|
297
|
+
];
|
|
298
|
+
export const CHANNEL_SYNC_METHOD_NAMES = [
|
|
299
|
+
'_callChannelListeners',
|
|
300
|
+
'_channelURL',
|
|
301
|
+
'_checkInitialized',
|
|
302
|
+
'_countMessageAsUnread',
|
|
303
|
+
'_disconnect',
|
|
304
|
+
'_extendEventWithOwnReactions',
|
|
305
|
+
'_handleChannelEvent',
|
|
306
|
+
'_initializeState',
|
|
307
|
+
'clean',
|
|
308
|
+
'countUnread',
|
|
309
|
+
'countUnreadMentions',
|
|
310
|
+
'getConfig',
|
|
311
|
+
'lastMessage',
|
|
312
|
+
'lastRead',
|
|
313
|
+
'muteStatus',
|
|
314
|
+
'off',
|
|
315
|
+
'on',
|
|
316
|
+
];
|
|
317
|
+
export const CHANNEL_SYNC_PROXY_RESULT_METHOD_NAMES = ['getClient'];
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { STREAM_RATE_LIMIT_COOLDOWN_KEY_PREFIX } from '../constants';
|
|
2
|
+
export class RedisCooldown {
|
|
3
|
+
static resolveRedisKey(cooldownKey, options) {
|
|
4
|
+
const keyPrefix = options?.keyPrefix ?? STREAM_RATE_LIMIT_COOLDOWN_KEY_PREFIX;
|
|
5
|
+
return `${keyPrefix}${cooldownKey}`;
|
|
6
|
+
}
|
|
7
|
+
static async getRemainingMs(cooldownKey, context, options) {
|
|
8
|
+
const { redis, logger } = context;
|
|
9
|
+
try {
|
|
10
|
+
const ttlMs = await redis.pttl(RedisCooldown.resolveRedisKey(cooldownKey, options));
|
|
11
|
+
if (ttlMs > 0) {
|
|
12
|
+
return ttlMs;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
logger.warn('Failed to read stream rate-limit cooldown from Redis', {
|
|
17
|
+
cooldownKey,
|
|
18
|
+
error,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
static async setRemainingMs(cooldownKey, cooldownMs, context, options) {
|
|
24
|
+
if (cooldownMs <= 0) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const { redis, logger } = context;
|
|
28
|
+
const redisKey = RedisCooldown.resolveRedisKey(cooldownKey, options);
|
|
29
|
+
try {
|
|
30
|
+
await redis.eval(`
|
|
31
|
+
local key = KEYS[1]
|
|
32
|
+
local new_ttl = tonumber(ARGV[1])
|
|
33
|
+
local current_ttl = redis.call('PTTL', key)
|
|
34
|
+
|
|
35
|
+
if current_ttl == -2 then
|
|
36
|
+
redis.call('SET', key, '1', 'PX', new_ttl)
|
|
37
|
+
return 1
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if current_ttl == -1 or current_ttl < new_ttl then
|
|
41
|
+
redis.call('PEXPIRE', key, new_ttl)
|
|
42
|
+
return 2
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
return 0
|
|
46
|
+
`, 1, redisKey, cooldownMs.toString());
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
logger.warn('Failed to write stream rate-limit cooldown to Redis', {
|
|
50
|
+
cooldownKey,
|
|
51
|
+
cooldownMs,
|
|
52
|
+
error,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
static async setRemainingMsExact(cooldownKey, cooldownMs, context, options) {
|
|
57
|
+
if (cooldownMs <= 0) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const { redis, logger } = context;
|
|
61
|
+
try {
|
|
62
|
+
await redis.set(RedisCooldown.resolveRedisKey(cooldownKey, options), '1', 'PX', cooldownMs);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
logger.warn('Failed to write exact stream rate-limit cooldown to Redis', {
|
|
66
|
+
cooldownKey,
|
|
67
|
+
cooldownMs,
|
|
68
|
+
error,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
static async getValue(cooldownKey, context, options) {
|
|
73
|
+
const { redis, logger } = context;
|
|
74
|
+
try {
|
|
75
|
+
const value = await redis.get(RedisCooldown.resolveRedisKey(cooldownKey, options));
|
|
76
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
logger.warn('Failed to read stream rate-limit metadata from Redis', {
|
|
82
|
+
cooldownKey,
|
|
83
|
+
error,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
static async setValueWithRemainingMs(cooldownKey, value, cooldownMs, context, options) {
|
|
88
|
+
if (value.length === 0 || cooldownMs <= 0) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const { redis, logger } = context;
|
|
92
|
+
try {
|
|
93
|
+
await redis.eval(`
|
|
94
|
+
local key = KEYS[1]
|
|
95
|
+
local value = ARGV[1]
|
|
96
|
+
local new_ttl = tonumber(ARGV[2])
|
|
97
|
+
local current_ttl = redis.call('PTTL', key)
|
|
98
|
+
|
|
99
|
+
if current_ttl == -2 then
|
|
100
|
+
redis.call('SET', key, value, 'PX', new_ttl)
|
|
101
|
+
return 1
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if current_ttl == -1 or current_ttl < new_ttl then
|
|
105
|
+
redis.call('SET', key, value, 'PX', new_ttl)
|
|
106
|
+
return 2
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
redis.call('SET', key, value, 'KEEPTTL')
|
|
110
|
+
return 0
|
|
111
|
+
`, 1, RedisCooldown.resolveRedisKey(cooldownKey, options), value, cooldownMs.toString());
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
logger.warn('Failed to write stream rate-limit metadata to Redis', {
|
|
115
|
+
cooldownKey,
|
|
116
|
+
cooldownMs,
|
|
117
|
+
error,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
static async setRemainingMsWithValue(cooldownKey, valueKey, value, cooldownMs, context, options) {
|
|
122
|
+
if (value.length === 0 || cooldownMs <= 0) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const { redis, logger } = context;
|
|
126
|
+
const cooldownRedisKey = RedisCooldown.resolveRedisKey(cooldownKey, options);
|
|
127
|
+
const valueRedisKey = RedisCooldown.resolveRedisKey(valueKey, options);
|
|
128
|
+
try {
|
|
129
|
+
await redis.eval(`
|
|
130
|
+
local cooldown_key = KEYS[1]
|
|
131
|
+
local value_key = KEYS[2]
|
|
132
|
+
local value = ARGV[1]
|
|
133
|
+
local new_ttl = tonumber(ARGV[2])
|
|
134
|
+
local current_ttl = redis.call('PTTL', cooldown_key)
|
|
135
|
+
local final_ttl = new_ttl
|
|
136
|
+
|
|
137
|
+
if current_ttl == -2 then
|
|
138
|
+
redis.call('SET', cooldown_key, '1', 'PX', new_ttl)
|
|
139
|
+
elseif current_ttl == -1 or current_ttl < new_ttl then
|
|
140
|
+
redis.call('PEXPIRE', cooldown_key, new_ttl)
|
|
141
|
+
else
|
|
142
|
+
final_ttl = current_ttl
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
redis.call('SET', value_key, value, 'PX', final_ttl)
|
|
146
|
+
return final_ttl
|
|
147
|
+
`, 2, cooldownRedisKey, valueRedisKey, value, cooldownMs.toString());
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
logger.warn('Failed to write stream rate-limit cooldown and metadata to Redis', {
|
|
151
|
+
cooldownKey,
|
|
152
|
+
valueKey,
|
|
153
|
+
cooldownMs,
|
|
154
|
+
error,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
static async clear(cooldownKey, context, options) {
|
|
159
|
+
const { redis, logger } = context;
|
|
160
|
+
try {
|
|
161
|
+
await redis.del(RedisCooldown.resolveRedisKey(cooldownKey, options));
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
logger.warn('Failed to clear stream rate-limit cooldown from Redis', {
|
|
165
|
+
cooldownKey,
|
|
166
|
+
error,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RateLimitExceededException } from '@wildix/xbees-conversations-client';
|
|
2
|
+
import { DEFAULT_RETRY_AFTER_MS } from '../constants';
|
|
3
|
+
const RETRY_AFTER_HEADER_PADDING_MS = 3000;
|
|
4
|
+
function toPositiveMilliseconds(milliseconds) {
|
|
5
|
+
return Math.max(0, Math.ceil(milliseconds));
|
|
6
|
+
}
|
|
7
|
+
function toEpochSecondsFromNow(delayMs) {
|
|
8
|
+
return Math.ceil((Date.now() + toPositiveMilliseconds(delayMs)) / 1000);
|
|
9
|
+
}
|
|
10
|
+
export function createRateLimitExceededException(options = {}) {
|
|
11
|
+
const { rateLimit, message, operation, retryAfterMs = DEFAULT_RETRY_AFTER_MS } = options;
|
|
12
|
+
const defaultMessage = operation ? `Rate limit exceeded for ${operation}` : 'Rate limit exceeded';
|
|
13
|
+
const retryAfterFromResetMs = rateLimit?.reset != null ? rateLimit.reset - Date.now() : undefined;
|
|
14
|
+
const effectiveRetryAfterMs = retryAfterFromResetMs ?? retryAfterMs;
|
|
15
|
+
const retryAfterMilliseconds = toPositiveMilliseconds(effectiveRetryAfterMs);
|
|
16
|
+
const retryAfterEpochSeconds = toEpochSecondsFromNow(effectiveRetryAfterMs + RETRY_AFTER_HEADER_PADDING_MS);
|
|
17
|
+
return new RateLimitExceededException({
|
|
18
|
+
$metadata: {},
|
|
19
|
+
message: message || defaultMessage,
|
|
20
|
+
rateLimitRemaining: rateLimit?.remaining || 0,
|
|
21
|
+
retryAfter: retryAfterEpochSeconds,
|
|
22
|
+
rateLimit: rateLimit?.limit?.toString() || 'unknown',
|
|
23
|
+
rateLimitReset: retryAfterMilliseconds,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { BUDGET_COOLDOWN_SLEEP_CHUNK_MS, BUDGET_DELAY_MAX_MS, DEFAULT_JITTER_MS, DEFAULT_RETRY_AFTER_MS, RETRY_AFTER_BUFFER_MS, STREAM_BUDGET_COOLDOWN_KEY, STREAM_BUDGET_COOLDOWN_KEY_PREFIX, STREAM_RATE_LIMIT_COOLDOWN_KEY_PREFIX, STREAM_RATE_LIMIT_METADATA_KEY_SUFFIX, STREAM_RATE_LIMIT_SOFT_COOLDOWN_KEY, } from '../constants';
|
|
2
|
+
import { createRateLimitExceededException } from './createRateLimitExceededException';
|
|
3
|
+
import { processStreamRateLimitException } from './processStreamRateLimitException';
|
|
4
|
+
import { parseRateLimitSnapshot, serializeRateLimitSnapshot } from './rateLimitSnapshot';
|
|
5
|
+
import { RedisCooldown } from './RedisCooldown';
|
|
6
|
+
import sleep from './sleep';
|
|
7
|
+
function calculateRateLimitDelayMs(error, maxDelayMs) {
|
|
8
|
+
const retryAfterMs = typeof error.rateLimitReset === 'number' && error.rateLimitReset > 0 ? error.rateLimitReset : 0;
|
|
9
|
+
const hasServerRetryAfter = retryAfterMs > 0;
|
|
10
|
+
const baseDelayMs = hasServerRetryAfter ? retryAfterMs + RETRY_AFTER_BUFFER_MS : DEFAULT_RETRY_AFTER_MS;
|
|
11
|
+
const jitterMs = Math.floor(Math.random() * DEFAULT_JITTER_MS);
|
|
12
|
+
const computedDelayMs = baseDelayMs + jitterMs;
|
|
13
|
+
if (hasServerRetryAfter) {
|
|
14
|
+
return computedDelayMs;
|
|
15
|
+
}
|
|
16
|
+
return Math.min(maxDelayMs, computedDelayMs);
|
|
17
|
+
}
|
|
18
|
+
function getRateLimitMetadataKey(operation) {
|
|
19
|
+
return `${operation}${STREAM_RATE_LIMIT_METADATA_KEY_SUFFIX}`;
|
|
20
|
+
}
|
|
21
|
+
function toCooldownRateLimit(snapshot, cooldownMs) {
|
|
22
|
+
return {
|
|
23
|
+
limit: snapshot.limit,
|
|
24
|
+
remaining: snapshot.remaining,
|
|
25
|
+
reset: Math.max(snapshot.reset, Date.now() + cooldownMs),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function toRateLimitSnapshot(error) {
|
|
29
|
+
const limit = Number(error.rateLimit);
|
|
30
|
+
const remaining = error.rateLimitRemaining;
|
|
31
|
+
const resetMs = error.rateLimitReset;
|
|
32
|
+
if (!Number.isFinite(limit) ||
|
|
33
|
+
typeof remaining !== 'number' ||
|
|
34
|
+
!Number.isFinite(remaining) ||
|
|
35
|
+
typeof resetMs !== 'number' ||
|
|
36
|
+
!Number.isFinite(resetMs) ||
|
|
37
|
+
resetMs <= 0) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
limit,
|
|
42
|
+
remaining,
|
|
43
|
+
reset: Date.now() + resetMs,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function throwIfOperationCooldownActive(operation, context) {
|
|
47
|
+
const { logger, redis } = context;
|
|
48
|
+
const cooldownMs = await RedisCooldown.getRemainingMs(operation, { redis, logger });
|
|
49
|
+
if (cooldownMs <= 0) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const rateLimitSnapshot = parseRateLimitSnapshot(await RedisCooldown.getValue(getRateLimitMetadataKey(operation), { redis, logger }));
|
|
53
|
+
logger.warn('Skipping stream request due to active rate-limit cooldown', {
|
|
54
|
+
operation,
|
|
55
|
+
cooldown: cooldownMs,
|
|
56
|
+
rateLimitSnapshot,
|
|
57
|
+
});
|
|
58
|
+
throw createRateLimitExceededException({
|
|
59
|
+
operation,
|
|
60
|
+
retryAfterMs: cooldownMs,
|
|
61
|
+
rateLimit: rateLimitSnapshot ? toCooldownRateLimit(rateLimitSnapshot, cooldownMs) : undefined,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export async function executeWithRateLimitHandling(execute, operation, context, options) {
|
|
65
|
+
const { logger, redis } = context;
|
|
66
|
+
const { enableCooldown, maxAttempts, maxDelayMs, maxRetryableDelayMs } = options;
|
|
67
|
+
let attempt = 1;
|
|
68
|
+
if (enableCooldown) {
|
|
69
|
+
await throwIfOperationCooldownActive(operation, { logger, redis });
|
|
70
|
+
let waitedForSharedCooldown = false;
|
|
71
|
+
const softCooldownMs = await RedisCooldown.getRemainingMs(STREAM_RATE_LIMIT_SOFT_COOLDOWN_KEY, { redis, logger }, { keyPrefix: STREAM_RATE_LIMIT_COOLDOWN_KEY_PREFIX });
|
|
72
|
+
if (softCooldownMs > 0) {
|
|
73
|
+
logger.info('Delaying stream request due to active soft rate-limit cooldown', {
|
|
74
|
+
operation,
|
|
75
|
+
cooldown: softCooldownMs,
|
|
76
|
+
});
|
|
77
|
+
await sleep(softCooldownMs);
|
|
78
|
+
waitedForSharedCooldown = true;
|
|
79
|
+
}
|
|
80
|
+
const budgetCooldownMs = await RedisCooldown.getRemainingMs(STREAM_BUDGET_COOLDOWN_KEY, { redis, logger }, { keyPrefix: STREAM_BUDGET_COOLDOWN_KEY_PREFIX });
|
|
81
|
+
if (budgetCooldownMs > 0) {
|
|
82
|
+
logger.warn('Delaying stream request due to active budget cooldown', {
|
|
83
|
+
operation,
|
|
84
|
+
cooldown: budgetCooldownMs,
|
|
85
|
+
});
|
|
86
|
+
let totalBudgetWaitMs = 0;
|
|
87
|
+
for (;;) {
|
|
88
|
+
const waitMs = await RedisCooldown.getRemainingMs(STREAM_BUDGET_COOLDOWN_KEY, { redis, logger }, { keyPrefix: STREAM_BUDGET_COOLDOWN_KEY_PREFIX });
|
|
89
|
+
if (waitMs <= 0 || totalBudgetWaitMs >= BUDGET_DELAY_MAX_MS) {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
const chunkMs = Math.min(waitMs, BUDGET_COOLDOWN_SLEEP_CHUNK_MS, BUDGET_DELAY_MAX_MS - totalBudgetWaitMs);
|
|
93
|
+
await sleep(chunkMs);
|
|
94
|
+
totalBudgetWaitMs += chunkMs;
|
|
95
|
+
waitedForSharedCooldown = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (waitedForSharedCooldown) {
|
|
99
|
+
await throwIfOperationCooldownActive(operation, { logger, redis });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (;;) {
|
|
103
|
+
try {
|
|
104
|
+
return await execute();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const rateLimitError = processStreamRateLimitException(error, logger);
|
|
108
|
+
if (!rateLimitError) {
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
const retryAfterMs = calculateRateLimitDelayMs(rateLimitError, maxDelayMs);
|
|
112
|
+
if (enableCooldown) {
|
|
113
|
+
const rateLimitSnapshot = toRateLimitSnapshot(rateLimitError);
|
|
114
|
+
if (rateLimitSnapshot) {
|
|
115
|
+
await RedisCooldown.setRemainingMsWithValue(operation, getRateLimitMetadataKey(operation), serializeRateLimitSnapshot(rateLimitSnapshot), retryAfterMs, { redis, logger });
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
await RedisCooldown.setRemainingMs(operation, retryAfterMs, { redis, logger });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (attempt < maxAttempts && retryAfterMs <= maxRetryableDelayMs) {
|
|
122
|
+
logger.warn('Retrying stream request after rate limit', {
|
|
123
|
+
operation,
|
|
124
|
+
attempt,
|
|
125
|
+
maxAttempts,
|
|
126
|
+
retryAfterMs,
|
|
127
|
+
rateLimit: rateLimitError.rateLimit,
|
|
128
|
+
rateLimitRemaining: rateLimitError.rateLimitRemaining,
|
|
129
|
+
rateLimitReset: rateLimitError.rateLimitReset,
|
|
130
|
+
});
|
|
131
|
+
await sleep(retryAfterMs);
|
|
132
|
+
attempt++;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
logger.warn('Propagating stream rate limit w/o retry', {
|
|
136
|
+
operation,
|
|
137
|
+
attempt,
|
|
138
|
+
maxAttempts,
|
|
139
|
+
retryAfterMs,
|
|
140
|
+
maxRetryableDelayMs,
|
|
141
|
+
rateLimit: rateLimitError.rateLimit,
|
|
142
|
+
rateLimitRemaining: rateLimitError.rateLimitRemaining,
|
|
143
|
+
rateLimitReset: rateLimitError.rateLimitReset,
|
|
144
|
+
});
|
|
145
|
+
throw rateLimitError;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const EPOCH_SECONDS_PAST_SKEW_SECONDS = 60;
|
|
2
|
+
const EPOCH_SECONDS_FUTURE_SKEW_SECONDS = 24 * 60 * 60;
|
|
3
|
+
export function getHeaderCaseInsensitive(headers, key) {
|
|
4
|
+
if (!headers) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
const direct = headers[key];
|
|
8
|
+
if (direct !== undefined) {
|
|
9
|
+
return direct;
|
|
10
|
+
}
|
|
11
|
+
const normalizedKey = key.toLowerCase();
|
|
12
|
+
for (const [headerKey, headerValue] of Object.entries(headers)) {
|
|
13
|
+
if (headerKey.toLowerCase() === normalizedKey) {
|
|
14
|
+
return headerValue;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function parseHeaderNumber(headers, key) {
|
|
19
|
+
const raw = getHeaderCaseInsensitive(headers, key);
|
|
20
|
+
if (typeof raw === 'number' && Number.isFinite(raw)) {
|
|
21
|
+
return raw;
|
|
22
|
+
}
|
|
23
|
+
if (typeof raw === 'string') {
|
|
24
|
+
const parsed = Number(raw);
|
|
25
|
+
if (Number.isFinite(parsed)) {
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function normalizeResetToEpochMs(reset) {
|
|
31
|
+
const nowMs = Date.now();
|
|
32
|
+
if (!Number.isFinite(reset)) {
|
|
33
|
+
return nowMs;
|
|
34
|
+
}
|
|
35
|
+
if (reset >= 10000000000)
|
|
36
|
+
return Math.round(reset);
|
|
37
|
+
const nowSeconds = nowMs / 1000;
|
|
38
|
+
const looksLikeEpochSeconds = reset >= nowSeconds - EPOCH_SECONDS_PAST_SKEW_SECONDS && reset <= nowSeconds + EPOCH_SECONDS_FUTURE_SKEW_SECONDS;
|
|
39
|
+
if (looksLikeEpochSeconds)
|
|
40
|
+
return Math.round(reset * 1000);
|
|
41
|
+
return nowMs + Math.round(reset * 1000);
|
|
42
|
+
}
|