@wildix/xbees-conversations-utils 1.1.85 → 1.1.86
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/README.md +118 -1
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/streamRateLimitHandlingProxy/constants.js +43 -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 +32 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/executeWithRateLimitHandling.js +144 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/headerUtils.js +40 -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 +72 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/rateLimitSnapshot.js +31 -0
- package/dist-cjs/streamRateLimitHandlingProxy/helpers/registerStreamInterceptors.js +58 -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/index.js +1 -1
- package/dist-es/streamRateLimitHandlingProxy/constants.js +33 -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 +28 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/executeWithRateLimitHandling.js +140 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/headerUtils.js +34 -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 +68 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/rateLimitSnapshot.js +26 -0
- package/dist-es/streamRateLimitHandlingProxy/helpers/registerStreamInterceptors.js +54 -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/index.d.ts +1 -1
- package/dist-types/streamRateLimitHandlingProxy/constants.d.ts +29 -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/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 +1 -1
package/README.md
CHANGED
|
@@ -1 +1,118 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `streamRateLimitHandlingProxy`
|
|
2
|
+
|
|
3
|
+
This package wraps a `StreamChat` client into a proxy that adds shared rate-limit protection around Stream SDK calls without changing the normal sync API contract. Async calls go through retry / cooldown handling, while sync methods stay sync. If a proxied call returns a channel-like object, that object is wrapped too, so the same protection continues on nested channel operations.
|
|
4
|
+
|
|
5
|
+
## Public entry points
|
|
6
|
+
|
|
7
|
+
- `createRateLimitedStreamProxy(stream, {redis, logger})`
|
|
8
|
+
Creates the proxy, attaches response interceptors once, and returns a rate-limit-aware `StreamChat` instance.
|
|
9
|
+
Code: `src/streamRateLimitHandlingProxy/createRateLimitedStreamProxy.ts`
|
|
10
|
+
- `withStreamRateLimitOptions(options)`
|
|
11
|
+
Builds a marker token that can be passed as the last argument of a proxied async call to override retry behavior for that single call.
|
|
12
|
+
Code: `src/streamRateLimitHandlingProxy/withStreamRateLimitOptions.ts`
|
|
13
|
+
- Public exports are re-exported from `src/streamRateLimitHandlingProxy/index.ts` and then from `src/index.ts`.
|
|
14
|
+
|
|
15
|
+
## How it works
|
|
16
|
+
|
|
17
|
+
1. `createRateLimitedStreamProxy(...)` tries to register axios response interceptors on the underlying Stream transport.
|
|
18
|
+
2. The proxy classifies Stream methods into groups generated in `generatedMethodNames.ts`:
|
|
19
|
+
- pure sync methods: returned as-is;
|
|
20
|
+
- sync methods returning channel/client objects: returned sync, but results are re-wrapped;
|
|
21
|
+
- async methods: executed through the rate-limit handler.
|
|
22
|
+
3. Every async call is normalized through `executeWithRateLimitHandling(...)`.
|
|
23
|
+
4. Returned channel-like objects are detected and wrapped again, so calls like `stream.channel(...).sendMessage(...)` stay protected end to end.
|
|
24
|
+
|
|
25
|
+
If the underlying Stream SDK transport does not expose an axios instance, the proxy still works, but shared protection driven by response headers becomes less effective because no interceptors can be attached.
|
|
26
|
+
|
|
27
|
+
## Protection layers
|
|
28
|
+
|
|
29
|
+
### 1. Soft global throttle
|
|
30
|
+
|
|
31
|
+
The interceptor reads `x-ratelimit-limit` and `x-ratelimit-remaining`. When usage becomes high, it enables a short shared Redis cooldown before real 429 responses start happening. This smooths bursts instead of waiting for hard throttling.
|
|
32
|
+
|
|
33
|
+
- Trigger source: response headers on successful or failed requests
|
|
34
|
+
- Effect:
|
|
35
|
+
- usage `>= 95%`: delay next requests by `3000ms`;
|
|
36
|
+
- usage between `85%` and `95%`: delay by `1500ms`;
|
|
37
|
+
- usage between `70%` and `85%`: delay by `500ms`;
|
|
38
|
+
- usage `< 70%`: clear soft throttle.
|
|
39
|
+
- Scope: global shared throttle
|
|
40
|
+
- Code: `helpers/processStreamRateLimitHeaders.ts`
|
|
41
|
+
|
|
42
|
+
### 2. Hard per-operation 429 cooldown
|
|
43
|
+
|
|
44
|
+
If Stream returns HTTP 429, the handler converts that error into `RateLimitExceededException`, calculates retry delay from `retry-after` or fallback values, stores a Redis cooldown for the specific operation, and optionally retries the call.
|
|
45
|
+
|
|
46
|
+
If another worker hits the same operation while that cooldown is still active, the request is short-circuited locally before touching Stream. To keep that synthetic error useful, the latest real `x-ratelimit-*` snapshot is cached in Redis next to the cooldown and reused in the locally generated exception.
|
|
47
|
+
|
|
48
|
+
- Trigger source: HTTP 429 / `retry-after` / `x-ratelimit-*`
|
|
49
|
+
- Effect: per-operation block, optional retry, synthetic local short-circuit when cooldown is already known
|
|
50
|
+
- Scope: operation-level
|
|
51
|
+
- Code:
|
|
52
|
+
- execution flow: `helpers/executeWithRateLimitHandling.ts`
|
|
53
|
+
- 429 parsing: `helpers/processStreamRateLimitException.ts`
|
|
54
|
+
- exception creation: `helpers/createRateLimitExceededException.ts`
|
|
55
|
+
- snapshot serialization: `helpers/rateLimitSnapshot.ts`
|
|
56
|
+
|
|
57
|
+
### 3. App-wide budget cooldown
|
|
58
|
+
|
|
59
|
+
The interceptor also reads `x-budget-*` headers. If overall Stream app budget usage becomes high, it enables a global Redis cooldown. While this cooldown is active, requests are delayed in small sleep chunks so they can resume early if a fresher response lowers the cooldown.
|
|
60
|
+
|
|
61
|
+
- Trigger source: `x-budget-limit-ms`, `x-budget-remaining-ms`, `x-budget-used-ms`
|
|
62
|
+
- Effect:
|
|
63
|
+
- usage `>= 80%`: enable strong cooldown (`30s-60s`);
|
|
64
|
+
- usage between `70%` and `80%`: keep a relaxed cooldown (`5s-10s`);
|
|
65
|
+
- usage between `60%` and `70%`: keep a minimal cooldown (`1s-2s`);
|
|
66
|
+
- usage `< 60%`: clear cooldown.
|
|
67
|
+
- Scope: whole application, not a single operation
|
|
68
|
+
- Code: `helpers/processStreamBudgetHeaders.ts`
|
|
69
|
+
|
|
70
|
+
## Retry and cooldown behavior
|
|
71
|
+
|
|
72
|
+
- Local preflight checks happen before request execution when `enableCooldown` is on:
|
|
73
|
+
- active per-operation cooldown: fail fast with a synthetic `RateLimitExceededException`;
|
|
74
|
+
- active soft throttle: delay request briefly;
|
|
75
|
+
- active budget cooldown: delay request globally.
|
|
76
|
+
- Real 429 responses can still be retried if:
|
|
77
|
+
- `attempt < maxAttempts`;
|
|
78
|
+
- computed delay `<= maxRetryableDelayMs`.
|
|
79
|
+
- Delay calculation rules:
|
|
80
|
+
- if Stream provides `Retry-After` / reset information, that server value is preferred even if it is larger than `maxDelayMs`;
|
|
81
|
+
- `maxDelayMs` only caps fallback delay when server retry timing is missing or malformed;
|
|
82
|
+
- `maxRetryableDelayMs` decides whether that computed delay is still retryable or should be propagated immediately.
|
|
83
|
+
- If retry is not allowed, the processed rate-limit exception is propagated to the caller.
|
|
84
|
+
|
|
85
|
+
Core logic: `src/streamRateLimitHandlingProxy/helpers/executeWithRateLimitHandling.ts`
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
Default behavior is defined in `src/streamRateLimitHandlingProxy/constants.ts`:
|
|
90
|
+
|
|
91
|
+
- `maxAttempts = 3`
|
|
92
|
+
- `enableCooldown = true`
|
|
93
|
+
- `maxDelayMs = 5000`
|
|
94
|
+
- `maxRetryableDelayMs = 10000`
|
|
95
|
+
|
|
96
|
+
The same file also contains:
|
|
97
|
+
|
|
98
|
+
- Redis key prefixes for hard cooldown, soft throttle, and budget cooldown
|
|
99
|
+
- fallback retry values and jitter
|
|
100
|
+
- budget thresholds and cooldown ranges
|
|
101
|
+
- soft-throttle thresholds and delays
|
|
102
|
+
|
|
103
|
+
Notes:
|
|
104
|
+
|
|
105
|
+
- `enableCooldown` controls local Redis-based preflight checks and shared cooldown reuse.
|
|
106
|
+
- `maxDelayMs` is a fallback cap, not a hard upper bound for server-provided `Retry-After`.
|
|
107
|
+
- Missing / invalid rate-limit headers do not break the proxy, but they reduce how much shared throttling state can be inferred.
|
|
108
|
+
|
|
109
|
+
Per-call overrides are passed as the last argument:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
stream.queryChannels(filters, sort, options, withStreamRateLimitOptions({
|
|
113
|
+
maxAttempts: 1,
|
|
114
|
+
maxRetryableDelayMs: 0,
|
|
115
|
+
}));
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Argument extraction is implemented in `helpers/splitCallArgsAndOptions.ts`.
|
package/dist-cjs/index.js
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./normalization"), exports);
|
|
5
|
-
tslib_1.__exportStar(require("./
|
|
5
|
+
tslib_1.__exportStar(require("./streamRateLimitHandlingProxy"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./stream"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_OPTIONS = exports.SOFT_THROTTLE_DELAY_HIGH_MS = exports.SOFT_THROTTLE_DELAY_MEDIUM_MS = exports.SOFT_THROTTLE_DELAY_LOW_MS = exports.SOFT_THROTTLE_USAGE_HIGH = exports.SOFT_THROTTLE_USAGE_MEDIUM = exports.SOFT_THROTTLE_USAGE_LOW = exports.BUDGET_COOLDOWN_SLEEP_CHUNK_MS = exports.BUDGET_MINIMAL_DELAY_MAX_MS = exports.BUDGET_MINIMAL_DELAY_MIN_MS = exports.BUDGET_RELAXED_DELAY_MAX_MS = exports.BUDGET_RELAXED_DELAY_MIN_MS = exports.BUDGET_RELAXED_USAGE_THRESHOLD = exports.BUDGET_CLEAR_USAGE_THRESHOLD = exports.BUDGET_DELAY_MAX_MS = exports.BUDGET_DELAY_MIN_MS = exports.BUDGET_THRESHOLD = exports.STREAM_BUDGET_COOLDOWN_KEY = exports.STREAM_RATE_LIMIT_METADATA_KEY_SUFFIX = exports.STREAM_RATE_LIMIT_SOFT_COOLDOWN_KEY = exports.STREAM_RATE_LIMIT_OPTIONS_MARKER = exports.STREAM_BUDGET_COOLDOWN_KEY_PREFIX = exports.STREAM_RATE_LIMIT_COOLDOWN_KEY_PREFIX = exports.RETRY_AFTER_BUFFER_MS = exports.DEFAULT_JITTER_MS = exports.DEFAULT_RETRY_AFTER_MS = exports.DEFAULT_MAX_DELAY_MS = exports.STREAM_SYNC_METHOD_NAMES = exports.STREAM_SYNC_CHANNEL_RESULT_METHOD_NAMES = exports.STREAM_METHOD_NAMES = exports.STREAM_CHANNEL_RESULT_METHOD_NAMES = exports.CHANNEL_SYNC_PROXY_RESULT_METHOD_NAMES = exports.CHANNEL_SYNC_METHOD_NAMES = exports.CHANNEL_METHOD_NAMES = void 0;
|
|
4
|
+
var generatedMethodNames_1 = require("./generatedMethodNames");
|
|
5
|
+
Object.defineProperty(exports, "CHANNEL_METHOD_NAMES", { enumerable: true, get: function () { return generatedMethodNames_1.CHANNEL_METHOD_NAMES; } });
|
|
6
|
+
Object.defineProperty(exports, "CHANNEL_SYNC_METHOD_NAMES", { enumerable: true, get: function () { return generatedMethodNames_1.CHANNEL_SYNC_METHOD_NAMES; } });
|
|
7
|
+
Object.defineProperty(exports, "CHANNEL_SYNC_PROXY_RESULT_METHOD_NAMES", { enumerable: true, get: function () { return generatedMethodNames_1.CHANNEL_SYNC_PROXY_RESULT_METHOD_NAMES; } });
|
|
8
|
+
Object.defineProperty(exports, "STREAM_CHANNEL_RESULT_METHOD_NAMES", { enumerable: true, get: function () { return generatedMethodNames_1.STREAM_CHANNEL_RESULT_METHOD_NAMES; } });
|
|
9
|
+
Object.defineProperty(exports, "STREAM_METHOD_NAMES", { enumerable: true, get: function () { return generatedMethodNames_1.STREAM_METHOD_NAMES; } });
|
|
10
|
+
Object.defineProperty(exports, "STREAM_SYNC_CHANNEL_RESULT_METHOD_NAMES", { enumerable: true, get: function () { return generatedMethodNames_1.STREAM_SYNC_CHANNEL_RESULT_METHOD_NAMES; } });
|
|
11
|
+
Object.defineProperty(exports, "STREAM_SYNC_METHOD_NAMES", { enumerable: true, get: function () { return generatedMethodNames_1.STREAM_SYNC_METHOD_NAMES; } });
|
|
12
|
+
exports.DEFAULT_MAX_DELAY_MS = 5000;
|
|
13
|
+
exports.DEFAULT_RETRY_AFTER_MS = 10000;
|
|
14
|
+
exports.DEFAULT_JITTER_MS = 150;
|
|
15
|
+
exports.RETRY_AFTER_BUFFER_MS = 1000;
|
|
16
|
+
exports.STREAM_RATE_LIMIT_COOLDOWN_KEY_PREFIX = 'stream-rate-limit-cooldown:';
|
|
17
|
+
exports.STREAM_BUDGET_COOLDOWN_KEY_PREFIX = 'stream-budget-cooldown:';
|
|
18
|
+
exports.STREAM_RATE_LIMIT_OPTIONS_MARKER = '__xbsRateLimitOptions';
|
|
19
|
+
exports.STREAM_RATE_LIMIT_SOFT_COOLDOWN_KEY = 'stream-rate-limit-soft-global';
|
|
20
|
+
exports.STREAM_RATE_LIMIT_METADATA_KEY_SUFFIX = ':meta';
|
|
21
|
+
exports.STREAM_BUDGET_COOLDOWN_KEY = 'stream-budget-global';
|
|
22
|
+
exports.BUDGET_THRESHOLD = 0.8;
|
|
23
|
+
exports.BUDGET_DELAY_MIN_MS = 30000;
|
|
24
|
+
exports.BUDGET_DELAY_MAX_MS = 60000;
|
|
25
|
+
exports.BUDGET_CLEAR_USAGE_THRESHOLD = 0.6;
|
|
26
|
+
exports.BUDGET_RELAXED_USAGE_THRESHOLD = 0.7;
|
|
27
|
+
exports.BUDGET_RELAXED_DELAY_MIN_MS = 5000;
|
|
28
|
+
exports.BUDGET_RELAXED_DELAY_MAX_MS = 10000;
|
|
29
|
+
exports.BUDGET_MINIMAL_DELAY_MIN_MS = 1000;
|
|
30
|
+
exports.BUDGET_MINIMAL_DELAY_MAX_MS = 2000;
|
|
31
|
+
exports.BUDGET_COOLDOWN_SLEEP_CHUNK_MS = 3000;
|
|
32
|
+
exports.SOFT_THROTTLE_USAGE_LOW = 0.7;
|
|
33
|
+
exports.SOFT_THROTTLE_USAGE_MEDIUM = 0.85;
|
|
34
|
+
exports.SOFT_THROTTLE_USAGE_HIGH = 0.95;
|
|
35
|
+
exports.SOFT_THROTTLE_DELAY_LOW_MS = 500;
|
|
36
|
+
exports.SOFT_THROTTLE_DELAY_MEDIUM_MS = 1500;
|
|
37
|
+
exports.SOFT_THROTTLE_DELAY_HIGH_MS = 3000;
|
|
38
|
+
exports.DEFAULT_OPTIONS = {
|
|
39
|
+
maxAttempts: 3,
|
|
40
|
+
enableCooldown: true,
|
|
41
|
+
maxDelayMs: 5000,
|
|
42
|
+
maxRetryableDelayMs: 10000,
|
|
43
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRateLimitedStreamProxy = void 0;
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
const executeWithRateLimitHandling_1 = require("./helpers/executeWithRateLimitHandling");
|
|
6
|
+
const isStreamChannelLike_1 = require("./helpers/isStreamChannelLike");
|
|
7
|
+
const registerStreamInterceptors_1 = require("./helpers/registerStreamInterceptors");
|
|
8
|
+
const splitCallArgsAndOptions_1 = require("./helpers/splitCallArgsAndOptions");
|
|
9
|
+
const STREAM_SYNC_METHODS = new Set(constants_1.STREAM_SYNC_METHOD_NAMES);
|
|
10
|
+
const STREAM_CHANNEL_RESULT_METHODS = new Set(constants_1.STREAM_CHANNEL_RESULT_METHOD_NAMES);
|
|
11
|
+
const STREAM_SYNC_CHANNEL_RESULT_METHODS = new Set(constants_1.STREAM_SYNC_CHANNEL_RESULT_METHOD_NAMES);
|
|
12
|
+
const CHANNEL_SYNC_METHODS = new Set(constants_1.CHANNEL_SYNC_METHOD_NAMES);
|
|
13
|
+
const CHANNEL_SYNC_PROXY_RESULT_METHODS = new Set(constants_1.CHANNEL_SYNC_PROXY_RESULT_METHOD_NAMES);
|
|
14
|
+
function wrapKnownChannelResult(result, dependencies) {
|
|
15
|
+
if (Array.isArray(result)) {
|
|
16
|
+
return result.map((item) => wrapKnownChannelResult(item, dependencies));
|
|
17
|
+
}
|
|
18
|
+
if (typeof result !== 'object' || result === null) {
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
return wrapTarget(result, dependencies);
|
|
22
|
+
}
|
|
23
|
+
function normalizeStreamCallResult(result, dependencies, wrapAsChannelResult = false) {
|
|
24
|
+
if (wrapAsChannelResult) {
|
|
25
|
+
return wrapKnownChannelResult(result, dependencies);
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(result)) {
|
|
28
|
+
return result.map((item) => normalizeStreamCallResult(item, dependencies));
|
|
29
|
+
}
|
|
30
|
+
if (!(0, isStreamChannelLike_1.isStreamChannelLike)(result)) {
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
return wrapTarget(result, dependencies);
|
|
34
|
+
}
|
|
35
|
+
function createRateLimitedMethodWrapper(target, value, operation, dependencies, wrapAsChannelResult) {
|
|
36
|
+
return async (...args) => {
|
|
37
|
+
const { callArgs, callOptions } = (0, splitCallArgsAndOptions_1.splitCallArgsAndOptions)(args);
|
|
38
|
+
const result = await (0, executeWithRateLimitHandling_1.executeWithRateLimitHandling)(() => Reflect.apply(value, target, callArgs), operation, dependencies.context, {
|
|
39
|
+
...constants_1.DEFAULT_OPTIONS,
|
|
40
|
+
...callOptions,
|
|
41
|
+
});
|
|
42
|
+
return normalizeStreamCallResult(result, dependencies, wrapAsChannelResult);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function wrapTarget(target, dependencies) {
|
|
46
|
+
const cachedObject = dependencies.cache.get(target);
|
|
47
|
+
if (cachedObject) {
|
|
48
|
+
return cachedObject;
|
|
49
|
+
}
|
|
50
|
+
const proxy = new Proxy(target, {
|
|
51
|
+
get: (originalTarget, property, receiver) => {
|
|
52
|
+
const value = Reflect.get(originalTarget, property, receiver);
|
|
53
|
+
if (typeof property !== 'string' || typeof value !== 'function') {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
if (STREAM_SYNC_CHANNEL_RESULT_METHODS.has(property)) {
|
|
57
|
+
return (...args) => {
|
|
58
|
+
const { callArgs } = (0, splitCallArgsAndOptions_1.splitCallArgsAndOptions)(args);
|
|
59
|
+
const result = Reflect.apply(value, originalTarget, callArgs);
|
|
60
|
+
return normalizeStreamCallResult(result, dependencies, true);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (CHANNEL_SYNC_PROXY_RESULT_METHODS.has(property)) {
|
|
64
|
+
return (...args) => {
|
|
65
|
+
const { callArgs } = (0, splitCallArgsAndOptions_1.splitCallArgsAndOptions)(args);
|
|
66
|
+
const result = Reflect.apply(value, originalTarget, callArgs);
|
|
67
|
+
if (typeof result === 'object' && result !== null) {
|
|
68
|
+
return wrapTarget(result, dependencies);
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (STREAM_SYNC_METHODS.has(property) || CHANNEL_SYNC_METHODS.has(property)) {
|
|
74
|
+
return (...args) => {
|
|
75
|
+
const { callArgs } = (0, splitCallArgsAndOptions_1.splitCallArgsAndOptions)(args);
|
|
76
|
+
return Reflect.apply(value, originalTarget, callArgs);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return createRateLimitedMethodWrapper(originalTarget, value, property, dependencies, STREAM_CHANNEL_RESULT_METHODS.has(property));
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
dependencies.cache.set(target, proxy);
|
|
83
|
+
return proxy;
|
|
84
|
+
}
|
|
85
|
+
function createRateLimitedStreamProxy(stream, context) {
|
|
86
|
+
(0, registerStreamInterceptors_1.registerStreamInterceptors)(stream, context);
|
|
87
|
+
return wrapTarget(stream, {
|
|
88
|
+
context,
|
|
89
|
+
cache: new WeakMap(),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
exports.createRateLimitedStreamProxy = createRateLimitedStreamProxy;
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CHANNEL_SYNC_PROXY_RESULT_METHOD_NAMES = exports.CHANNEL_SYNC_METHOD_NAMES = exports.CHANNEL_METHOD_NAMES = exports.STREAM_SYNC_CHANNEL_RESULT_METHOD_NAMES = exports.STREAM_CHANNEL_RESULT_METHOD_NAMES = exports.STREAM_SYNC_METHOD_NAMES = exports.STREAM_METHOD_NAMES = void 0;
|
|
4
|
+
exports.STREAM_METHOD_NAMES = [
|
|
5
|
+
'_addChannelConfig',
|
|
6
|
+
'_buildWSPayload',
|
|
7
|
+
'_callClientListeners',
|
|
8
|
+
'_createImport',
|
|
9
|
+
'_createImportURL',
|
|
10
|
+
'_deleteUserMessageReference',
|
|
11
|
+
'_enrichAxiosOptions',
|
|
12
|
+
'_getConnectionID',
|
|
13
|
+
'_getImport',
|
|
14
|
+
'_getToken',
|
|
15
|
+
'_handleClientEvent',
|
|
16
|
+
'_handleUserEvent',
|
|
17
|
+
'_hasConnectionID',
|
|
18
|
+
'_isUsingServerAuth',
|
|
19
|
+
'_listImports',
|
|
20
|
+
'_logApiError',
|
|
21
|
+
'_logApiRequest',
|
|
22
|
+
'_logApiResponse',
|
|
23
|
+
'_muteStatus',
|
|
24
|
+
'_normalizeDate',
|
|
25
|
+
'_normalizeExpiration',
|
|
26
|
+
'_queryFlagReports',
|
|
27
|
+
'_queryFlags',
|
|
28
|
+
'_reviewFlagReport',
|
|
29
|
+
'_sayHi',
|
|
30
|
+
'_setToken',
|
|
31
|
+
'_setupConnection',
|
|
32
|
+
'_setUser',
|
|
33
|
+
'_startCleaning',
|
|
34
|
+
'_unblockMessage',
|
|
35
|
+
'_updateMemberWatcherReferences',
|
|
36
|
+
'_updateUserMessageReferences',
|
|
37
|
+
'_updateUserReferences',
|
|
38
|
+
'_validateAndGetMessageId',
|
|
39
|
+
'addDevice',
|
|
40
|
+
'banUser',
|
|
41
|
+
'channel',
|
|
42
|
+
'closeConnection',
|
|
43
|
+
'commitMessage',
|
|
44
|
+
'connect',
|
|
45
|
+
'connectAnonymousUser',
|
|
46
|
+
'connectUser',
|
|
47
|
+
'createAbortControllerForNextRequest',
|
|
48
|
+
'createBlockList',
|
|
49
|
+
'createCampaign',
|
|
50
|
+
'createChannelType',
|
|
51
|
+
'createCommand',
|
|
52
|
+
'createPermission',
|
|
53
|
+
'createRole',
|
|
54
|
+
'createSegment',
|
|
55
|
+
'createToken',
|
|
56
|
+
'deactivateUser',
|
|
57
|
+
'deactivateUsers',
|
|
58
|
+
'delete',
|
|
59
|
+
'deleteBlockList',
|
|
60
|
+
'deleteCampaign',
|
|
61
|
+
'deleteChannels',
|
|
62
|
+
'deleteChannelType',
|
|
63
|
+
'deleteCommand',
|
|
64
|
+
'deleteMessage',
|
|
65
|
+
'deletePermission',
|
|
66
|
+
'deletePushProvider',
|
|
67
|
+
'deleteRole',
|
|
68
|
+
'deleteSegment',
|
|
69
|
+
'deleteUser',
|
|
70
|
+
'deleteUsers',
|
|
71
|
+
'devToken',
|
|
72
|
+
'disconnect',
|
|
73
|
+
'disconnectUser',
|
|
74
|
+
'dispatchEvent',
|
|
75
|
+
'doAxiosRequest',
|
|
76
|
+
'enrichURL',
|
|
77
|
+
'errorFromResponse',
|
|
78
|
+
'exportChannel',
|
|
79
|
+
'exportChannels',
|
|
80
|
+
'exportUser',
|
|
81
|
+
'exportUsers',
|
|
82
|
+
'flagMessage',
|
|
83
|
+
'flagUser',
|
|
84
|
+
'get',
|
|
85
|
+
'getAppSettings',
|
|
86
|
+
'getAuthType',
|
|
87
|
+
'getBlockList',
|
|
88
|
+
'getCallToken',
|
|
89
|
+
'getChannelById',
|
|
90
|
+
'getChannelByMembers',
|
|
91
|
+
'getChannelType',
|
|
92
|
+
'getCommand',
|
|
93
|
+
'getDevices',
|
|
94
|
+
'getExportChannelStatus',
|
|
95
|
+
'getMessage',
|
|
96
|
+
'getPermission',
|
|
97
|
+
'getRateLimits',
|
|
98
|
+
'getTask',
|
|
99
|
+
'getUnreadCount',
|
|
100
|
+
'getUserAgent',
|
|
101
|
+
'handleEvent',
|
|
102
|
+
'handleResponse',
|
|
103
|
+
'hydrateActiveChannels',
|
|
104
|
+
'listBlockLists',
|
|
105
|
+
'listChannelTypes',
|
|
106
|
+
'listCommands',
|
|
107
|
+
'listPermissions',
|
|
108
|
+
'listPushProviders',
|
|
109
|
+
'listRoles',
|
|
110
|
+
'markAllRead',
|
|
111
|
+
'markChannelsRead',
|
|
112
|
+
'muteUser',
|
|
113
|
+
'off',
|
|
114
|
+
'on',
|
|
115
|
+
'openConnection',
|
|
116
|
+
'partialUpdateMessage',
|
|
117
|
+
'partialUpdateUser',
|
|
118
|
+
'partialUpdateUsers',
|
|
119
|
+
'patch',
|
|
120
|
+
'pinMessage',
|
|
121
|
+
'post',
|
|
122
|
+
'put',
|
|
123
|
+
'queryBannedUsers',
|
|
124
|
+
'queryCampaigns',
|
|
125
|
+
'queryChannels',
|
|
126
|
+
'queryMessageFlags',
|
|
127
|
+
'queryRecipients',
|
|
128
|
+
'querySegments',
|
|
129
|
+
'queryUsers',
|
|
130
|
+
'reactivateUser',
|
|
131
|
+
'reactivateUsers',
|
|
132
|
+
'recoverState',
|
|
133
|
+
'removeDevice',
|
|
134
|
+
'removeShadowBan',
|
|
135
|
+
'restoreUsers',
|
|
136
|
+
'resumeCampaign',
|
|
137
|
+
'revokeTokens',
|
|
138
|
+
'revokeUsersToken',
|
|
139
|
+
'revokeUserToken',
|
|
140
|
+
'scheduleCampaign',
|
|
141
|
+
'search',
|
|
142
|
+
'sendFile',
|
|
143
|
+
'sendUserCustomEvent',
|
|
144
|
+
'setAnonymousUser',
|
|
145
|
+
'setBaseURL',
|
|
146
|
+
'setGuestUser',
|
|
147
|
+
'setLocalDevice',
|
|
148
|
+
'setUser',
|
|
149
|
+
'setUserAgent',
|
|
150
|
+
'shadowBan',
|
|
151
|
+
'stopCampaign',
|
|
152
|
+
'sync',
|
|
153
|
+
'testCampaign',
|
|
154
|
+
'testPushSettings',
|
|
155
|
+
'testSQSSettings',
|
|
156
|
+
'translateMessage',
|
|
157
|
+
'unbanUser',
|
|
158
|
+
'unblockMessage',
|
|
159
|
+
'unflagMessage',
|
|
160
|
+
'unflagUser',
|
|
161
|
+
'unmuteUser',
|
|
162
|
+
'unpinMessage',
|
|
163
|
+
'updateAppSettings',
|
|
164
|
+
'updateBlockList',
|
|
165
|
+
'updateCampaign',
|
|
166
|
+
'updateChannelType',
|
|
167
|
+
'updateCommand',
|
|
168
|
+
'updateMessage',
|
|
169
|
+
'updatePermission',
|
|
170
|
+
'updateSegment',
|
|
171
|
+
'updateUser',
|
|
172
|
+
'updateUsers',
|
|
173
|
+
'upsertPushProvider',
|
|
174
|
+
'upsertUser',
|
|
175
|
+
'upsertUsers',
|
|
176
|
+
'userMuteStatus',
|
|
177
|
+
'verifyWebhook',
|
|
178
|
+
];
|
|
179
|
+
exports.STREAM_SYNC_METHOD_NAMES = [
|
|
180
|
+
'_addChannelConfig',
|
|
181
|
+
'_buildWSPayload',
|
|
182
|
+
'_callClientListeners',
|
|
183
|
+
'_deleteUserMessageReference',
|
|
184
|
+
'_enrichAxiosOptions',
|
|
185
|
+
'_getConnectionID',
|
|
186
|
+
'_getToken',
|
|
187
|
+
'_handleClientEvent',
|
|
188
|
+
'_handleUserEvent',
|
|
189
|
+
'_hasConnectionID',
|
|
190
|
+
'_isUsingServerAuth',
|
|
191
|
+
'_logApiError',
|
|
192
|
+
'_logApiRequest',
|
|
193
|
+
'_logApiResponse',
|
|
194
|
+
'_muteStatus',
|
|
195
|
+
'_normalizeDate',
|
|
196
|
+
'_normalizeExpiration',
|
|
197
|
+
'_sayHi',
|
|
198
|
+
'_setUser',
|
|
199
|
+
'_startCleaning',
|
|
200
|
+
'_updateMemberWatcherReferences',
|
|
201
|
+
'_updateUserMessageReferences',
|
|
202
|
+
'_updateUserReferences',
|
|
203
|
+
'_validateAndGetMessageId',
|
|
204
|
+
'createAbortControllerForNextRequest',
|
|
205
|
+
'createToken',
|
|
206
|
+
'devToken',
|
|
207
|
+
'dispatchEvent',
|
|
208
|
+
'errorFromResponse',
|
|
209
|
+
'getAuthType',
|
|
210
|
+
'getUserAgent',
|
|
211
|
+
'handleEvent',
|
|
212
|
+
'handleResponse',
|
|
213
|
+
'off',
|
|
214
|
+
'on',
|
|
215
|
+
'setBaseURL',
|
|
216
|
+
'setLocalDevice',
|
|
217
|
+
'setUserAgent',
|
|
218
|
+
'userMuteStatus',
|
|
219
|
+
'verifyWebhook',
|
|
220
|
+
];
|
|
221
|
+
exports.STREAM_CHANNEL_RESULT_METHOD_NAMES = [
|
|
222
|
+
'channel',
|
|
223
|
+
'getChannelById',
|
|
224
|
+
'getChannelByMembers',
|
|
225
|
+
'hydrateActiveChannels',
|
|
226
|
+
'queryChannels',
|
|
227
|
+
];
|
|
228
|
+
exports.STREAM_SYNC_CHANNEL_RESULT_METHOD_NAMES = [
|
|
229
|
+
'channel',
|
|
230
|
+
'getChannelById',
|
|
231
|
+
'getChannelByMembers',
|
|
232
|
+
'hydrateActiveChannels',
|
|
233
|
+
];
|
|
234
|
+
exports.CHANNEL_METHOD_NAMES = [
|
|
235
|
+
'_callChannelListeners',
|
|
236
|
+
'_channelURL',
|
|
237
|
+
'_checkInitialized',
|
|
238
|
+
'_countMessageAsUnread',
|
|
239
|
+
'_disconnect',
|
|
240
|
+
'_extendEventWithOwnReactions',
|
|
241
|
+
'_handleChannelEvent',
|
|
242
|
+
'_initializeState',
|
|
243
|
+
'_update',
|
|
244
|
+
'acceptInvite',
|
|
245
|
+
'addMembers',
|
|
246
|
+
'addModerators',
|
|
247
|
+
'assignRoles',
|
|
248
|
+
'banUser',
|
|
249
|
+
'clean',
|
|
250
|
+
'countUnread',
|
|
251
|
+
'countUnreadMentions',
|
|
252
|
+
'create',
|
|
253
|
+
'createCall',
|
|
254
|
+
'delete',
|
|
255
|
+
'deleteFile',
|
|
256
|
+
'deleteImage',
|
|
257
|
+
'deleteReaction',
|
|
258
|
+
'demoteModerators',
|
|
259
|
+
'disableSlowMode',
|
|
260
|
+
'enableSlowMode',
|
|
261
|
+
'getClient',
|
|
262
|
+
'getConfig',
|
|
263
|
+
'getMessagesById',
|
|
264
|
+
'getPinnedMessages',
|
|
265
|
+
'getReactions',
|
|
266
|
+
'getReplies',
|
|
267
|
+
'hide',
|
|
268
|
+
'inviteMembers',
|
|
269
|
+
'keystroke',
|
|
270
|
+
'lastMessage',
|
|
271
|
+
'lastRead',
|
|
272
|
+
'markRead',
|
|
273
|
+
'markUnread',
|
|
274
|
+
'mute',
|
|
275
|
+
'muteStatus',
|
|
276
|
+
'off',
|
|
277
|
+
'on',
|
|
278
|
+
'query',
|
|
279
|
+
'queryMembers',
|
|
280
|
+
'rejectInvite',
|
|
281
|
+
'removeMembers',
|
|
282
|
+
'removeShadowBan',
|
|
283
|
+
'search',
|
|
284
|
+
'sendAction',
|
|
285
|
+
'sendEvent',
|
|
286
|
+
'sendFile',
|
|
287
|
+
'sendImage',
|
|
288
|
+
'sendMessage',
|
|
289
|
+
'sendReaction',
|
|
290
|
+
'shadowBan',
|
|
291
|
+
'show',
|
|
292
|
+
'stopTyping',
|
|
293
|
+
'stopWatching',
|
|
294
|
+
'truncate',
|
|
295
|
+
'unbanUser',
|
|
296
|
+
'unmute',
|
|
297
|
+
'update',
|
|
298
|
+
'updatePartial',
|
|
299
|
+
'watch',
|
|
300
|
+
];
|
|
301
|
+
exports.CHANNEL_SYNC_METHOD_NAMES = [
|
|
302
|
+
'_callChannelListeners',
|
|
303
|
+
'_channelURL',
|
|
304
|
+
'_checkInitialized',
|
|
305
|
+
'_countMessageAsUnread',
|
|
306
|
+
'_disconnect',
|
|
307
|
+
'_extendEventWithOwnReactions',
|
|
308
|
+
'_handleChannelEvent',
|
|
309
|
+
'_initializeState',
|
|
310
|
+
'clean',
|
|
311
|
+
'countUnread',
|
|
312
|
+
'countUnreadMentions',
|
|
313
|
+
'getConfig',
|
|
314
|
+
'lastMessage',
|
|
315
|
+
'lastRead',
|
|
316
|
+
'muteStatus',
|
|
317
|
+
'off',
|
|
318
|
+
'on',
|
|
319
|
+
];
|
|
320
|
+
exports.CHANNEL_SYNC_PROXY_RESULT_METHOD_NAMES = ['getClient'];
|