@wildix/xbees-conversations-client 1.2.10 → 1.2.12

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.
@@ -9,6 +9,44 @@ const middleware_retry_1 = require("@smithy/middleware-retry");
9
9
  const smithy_client_1 = require("@smithy/smithy-client");
10
10
  Object.defineProperty(exports, "__Client", { enumerable: true, get: function () { return smithy_client_1.Client; } });
11
11
  const smithy_utils_1 = require("@wildix/smithy-utils");
12
+ const getHeaderCaseInsensitive = (headers, ...names) => {
13
+ if (!headers) {
14
+ return undefined;
15
+ }
16
+ const normalizedNames = names.map((name) => name.toLowerCase());
17
+ for (const [key, value] of Object.entries(headers)) {
18
+ if (normalizedNames.includes(key.toLowerCase())) {
19
+ return value;
20
+ }
21
+ }
22
+ return undefined;
23
+ };
24
+ const parseHeaderDelayMs = (rawValue) => {
25
+ if (typeof rawValue === "number" && Number.isFinite(rawValue)) {
26
+ if (rawValue > 1000000000000) {
27
+ return Math.max(0, Math.round(rawValue - Date.now()));
28
+ }
29
+ if (rawValue > 1000000000) {
30
+ return Math.max(0, Math.round(rawValue * 1000 - Date.now()));
31
+ }
32
+ if (rawValue >= 1000) {
33
+ return Math.max(0, Math.round(rawValue));
34
+ }
35
+ return Math.max(0, Math.round(rawValue * 1000));
36
+ }
37
+ if (typeof rawValue !== "string") {
38
+ return undefined;
39
+ }
40
+ const asNumber = Number(rawValue);
41
+ if (!Number.isNaN(asNumber)) {
42
+ return parseHeaderDelayMs(asNumber);
43
+ }
44
+ const asDateMs = Date.parse(rawValue);
45
+ if (!Number.isNaN(asDateMs)) {
46
+ return Math.max(0, asDateMs - Date.now());
47
+ }
48
+ return undefined;
49
+ };
12
50
  class ConversationsClient extends smithy_client_1.Client {
13
51
  config;
14
52
  constructor(...[configuration]) {
@@ -32,44 +70,6 @@ class ConversationsClient extends smithy_client_1.Client {
32
70
  this.middlewareStack.add(smithy_utils_1.authorizationMiddleware.bind(this, configuration.token), { step: "build" });
33
71
  this.middlewareStack.use((0, middleware_user_agent_1.getUserAgentPlugin)(this.config));
34
72
  this.middlewareStack.use((0, middleware_retry_1.getRetryPlugin)(this.config));
35
- this.middlewareStack.add((next) => async (args) => {
36
- try {
37
- return await next(args);
38
- }
39
- catch (error) {
40
- const statusCode = error?.$metadata?.httpStatusCode ?? error?.$response?.statusCode;
41
- const headers = error?.$response?.headers;
42
- if (statusCode === 429 && headers) {
43
- const headerEntries = Object.entries(headers);
44
- const getHeaderWithKey = (name) => {
45
- const normalizedName = name.toLowerCase();
46
- for (const [key, value] of headerEntries) {
47
- if (key.toLowerCase() === normalizedName && (typeof value === "string" || typeof value === "number")) {
48
- return [key, value];
49
- }
50
- }
51
- return undefined;
52
- };
53
- const retryAfterHeader = getHeaderWithKey("retry-after");
54
- if (retryAfterHeader) {
55
- const [retryAfterKey, retryAfterValueRaw] = retryAfterHeader;
56
- const retryAfterNumeric = Number(retryAfterValueRaw);
57
- if (!Number.isNaN(retryAfterNumeric) && retryAfterNumeric >= 1000) {
58
- const normalizedRetryAfterValue = new Date(Date.now() + retryAfterNumeric).toUTCString();
59
- headers[retryAfterKey] = normalizedRetryAfterValue;
60
- if (configuration?.retryLogging) {
61
- console.warn(`[ConversationsClient] Normalized retry-after header from ${String(retryAfterValueRaw)} to ${normalizedRetryAfterValue}`);
62
- }
63
- }
64
- }
65
- }
66
- throw error;
67
- }
68
- }, {
69
- name: "retryAfterHeaderNormalizationMiddleware",
70
- step: "finalizeRequest",
71
- priority: "low",
72
- });
73
73
  if (configuration?.retryLogging) {
74
74
  this.middlewareStack.add((next) => async (args) => {
75
75
  const request = args.request;
@@ -91,50 +91,20 @@ class ConversationsClient extends smithy_client_1.Client {
91
91
  const statusCode = error?.$metadata?.httpStatusCode ?? error?.$response?.statusCode;
92
92
  const willRetry = attempt < maxAttempts && this.config.retryDecider(error);
93
93
  const responseHeaders = (error?.$response?.headers ?? {});
94
- const headerEntries = Object.entries(responseHeaders);
95
- const getHeader = (...names) => {
96
- const normalizedNames = names.map((name) => name.toLowerCase());
97
- for (const [key, value] of headerEntries) {
98
- if (normalizedNames.includes(key.toLowerCase())) {
99
- return value;
100
- }
101
- }
102
- return undefined;
103
- };
104
- const retryAfterRaw = getHeader("retry-after");
105
- const rateLimitResetRaw = getHeader("x-ratelimit-reset", "ratelimit-reset", "rateLimitReset");
106
- const rateLimitRaw = getHeader("x-ratelimit-limit", "ratelimit-limit", "rateLimit");
107
- const rateLimitRemainingRaw = getHeader("x-ratelimit-remaining", "ratelimit-remaining", "rateLimitRemaining");
108
- let retryAfterDelayMs;
109
- if (retryAfterRaw !== undefined) {
110
- const retryAfterNumeric = Number(retryAfterRaw);
111
- if (!Number.isNaN(retryAfterNumeric)) {
112
- retryAfterDelayMs = retryAfterNumeric >= 1000 ? retryAfterNumeric : retryAfterNumeric * 1000;
113
- }
114
- else {
115
- retryAfterDelayMs = new Date(retryAfterRaw).getTime() - Date.now();
116
- }
117
- }
118
- let rateLimitResetDelayMs;
119
- if (rateLimitResetRaw !== undefined) {
120
- const resetValue = Number(rateLimitResetRaw);
121
- if (!Number.isNaN(resetValue)) {
122
- if (resetValue > 1000000000) {
123
- rateLimitResetDelayMs = (resetValue * 1000) - Date.now();
124
- }
125
- else {
126
- rateLimitResetDelayMs = resetValue >= 1000 ? resetValue : resetValue * 1000;
127
- }
128
- }
129
- }
94
+ const retryAfterRaw = getHeaderCaseInsensitive(responseHeaders, "retry-after");
95
+ const rateLimitResetRaw = getHeaderCaseInsensitive(responseHeaders, "x-ratelimit-reset", "ratelimit-reset", "rateLimitReset");
96
+ const rateLimitRaw = getHeaderCaseInsensitive(responseHeaders, "x-ratelimit-limit", "ratelimit-limit", "rateLimit");
97
+ const rateLimitRemainingRaw = getHeaderCaseInsensitive(responseHeaders, "x-ratelimit-remaining", "ratelimit-remaining", "rateLimitRemaining");
98
+ const retryAfterDelayMs = parseHeaderDelayMs(retryAfterRaw);
99
+ const rateLimitResetDelayMs = parseHeaderDelayMs(rateLimitResetRaw);
130
100
  if (willRetry) {
131
101
  console.warn(`[ConversationsClient] Retry decision: will retry after attempt ${attempt}/${maxAttempts} (status=${statusCode ?? "unknown"}, time=${new Date().toISOString()})`);
132
- console.warn(`[ConversationsClient] Retry headers: retry-after=${retryAfterRaw ?? "n/a"}, x-ratelimit-reset=${rateLimitResetRaw ?? "n/a"}, x-ratelimit-limit=${rateLimitRaw ?? "n/a"}, x-ratelimit-remaining=${rateLimitRemainingRaw ?? "n/a"}`);
133
- console.warn(`[ConversationsClient] Parsed retry timing: retryAfterDelayMs=${retryAfterDelayMs ?? "n/a"}, rateLimitResetDelayMs=${rateLimitResetDelayMs ?? "n/a"}`);
134
102
  }
135
103
  else {
136
104
  console.warn(`[ConversationsClient] Retry decision: stop after attempt ${attempt}/${maxAttempts} (status=${statusCode ?? "unknown"}, time=${new Date().toISOString()})`);
137
105
  }
106
+ console.warn(`[ConversationsClient] Retry headers: retry-after=${String(retryAfterRaw ?? "n/a")}, x-ratelimit-reset=${String(rateLimitResetRaw ?? "n/a")}, x-ratelimit-limit=${String(rateLimitRaw ?? "n/a")}, x-ratelimit-remaining=${String(rateLimitRemainingRaw ?? "n/a")}`);
107
+ console.warn(`[ConversationsClient] Parsed retry timing: retryAfterDelayMs=${retryAfterDelayMs ?? "n/a"}, rateLimitResetDelayMs=${rateLimitResetDelayMs ?? "n/a"}`);
138
108
  throw error;
139
109
  }
140
110
  }, {
@@ -6,6 +6,44 @@ import { getRetryPlugin, resolveRetryConfig, } from "@smithy/middleware-retry";
6
6
  import { Client as __Client, } from "@smithy/smithy-client";
7
7
  import { authorizationMiddleware } from '@wildix/smithy-utils';
8
8
  export { __Client };
9
+ const getHeaderCaseInsensitive = (headers, ...names) => {
10
+ if (!headers) {
11
+ return undefined;
12
+ }
13
+ const normalizedNames = names.map((name) => name.toLowerCase());
14
+ for (const [key, value] of Object.entries(headers)) {
15
+ if (normalizedNames.includes(key.toLowerCase())) {
16
+ return value;
17
+ }
18
+ }
19
+ return undefined;
20
+ };
21
+ const parseHeaderDelayMs = (rawValue) => {
22
+ if (typeof rawValue === "number" && Number.isFinite(rawValue)) {
23
+ if (rawValue > 1000000000000) {
24
+ return Math.max(0, Math.round(rawValue - Date.now()));
25
+ }
26
+ if (rawValue > 1000000000) {
27
+ return Math.max(0, Math.round(rawValue * 1000 - Date.now()));
28
+ }
29
+ if (rawValue >= 1000) {
30
+ return Math.max(0, Math.round(rawValue));
31
+ }
32
+ return Math.max(0, Math.round(rawValue * 1000));
33
+ }
34
+ if (typeof rawValue !== "string") {
35
+ return undefined;
36
+ }
37
+ const asNumber = Number(rawValue);
38
+ if (!Number.isNaN(asNumber)) {
39
+ return parseHeaderDelayMs(asNumber);
40
+ }
41
+ const asDateMs = Date.parse(rawValue);
42
+ if (!Number.isNaN(asDateMs)) {
43
+ return Math.max(0, asDateMs - Date.now());
44
+ }
45
+ return undefined;
46
+ };
9
47
  export class ConversationsClient extends __Client {
10
48
  config;
11
49
  constructor(...[configuration]) {
@@ -29,44 +67,6 @@ export class ConversationsClient extends __Client {
29
67
  this.middlewareStack.add(authorizationMiddleware.bind(this, configuration.token), { step: "build" });
30
68
  this.middlewareStack.use(getUserAgentPlugin(this.config));
31
69
  this.middlewareStack.use(getRetryPlugin(this.config));
32
- this.middlewareStack.add((next) => async (args) => {
33
- try {
34
- return await next(args);
35
- }
36
- catch (error) {
37
- const statusCode = error?.$metadata?.httpStatusCode ?? error?.$response?.statusCode;
38
- const headers = error?.$response?.headers;
39
- if (statusCode === 429 && headers) {
40
- const headerEntries = Object.entries(headers);
41
- const getHeaderWithKey = (name) => {
42
- const normalizedName = name.toLowerCase();
43
- for (const [key, value] of headerEntries) {
44
- if (key.toLowerCase() === normalizedName && (typeof value === "string" || typeof value === "number")) {
45
- return [key, value];
46
- }
47
- }
48
- return undefined;
49
- };
50
- const retryAfterHeader = getHeaderWithKey("retry-after");
51
- if (retryAfterHeader) {
52
- const [retryAfterKey, retryAfterValueRaw] = retryAfterHeader;
53
- const retryAfterNumeric = Number(retryAfterValueRaw);
54
- if (!Number.isNaN(retryAfterNumeric) && retryAfterNumeric >= 1000) {
55
- const normalizedRetryAfterValue = new Date(Date.now() + retryAfterNumeric).toUTCString();
56
- headers[retryAfterKey] = normalizedRetryAfterValue;
57
- if (configuration?.retryLogging) {
58
- console.warn(`[ConversationsClient] Normalized retry-after header from ${String(retryAfterValueRaw)} to ${normalizedRetryAfterValue}`);
59
- }
60
- }
61
- }
62
- }
63
- throw error;
64
- }
65
- }, {
66
- name: "retryAfterHeaderNormalizationMiddleware",
67
- step: "finalizeRequest",
68
- priority: "low",
69
- });
70
70
  if (configuration?.retryLogging) {
71
71
  this.middlewareStack.add((next) => async (args) => {
72
72
  const request = args.request;
@@ -88,50 +88,20 @@ export class ConversationsClient extends __Client {
88
88
  const statusCode = error?.$metadata?.httpStatusCode ?? error?.$response?.statusCode;
89
89
  const willRetry = attempt < maxAttempts && this.config.retryDecider(error);
90
90
  const responseHeaders = (error?.$response?.headers ?? {});
91
- const headerEntries = Object.entries(responseHeaders);
92
- const getHeader = (...names) => {
93
- const normalizedNames = names.map((name) => name.toLowerCase());
94
- for (const [key, value] of headerEntries) {
95
- if (normalizedNames.includes(key.toLowerCase())) {
96
- return value;
97
- }
98
- }
99
- return undefined;
100
- };
101
- const retryAfterRaw = getHeader("retry-after");
102
- const rateLimitResetRaw = getHeader("x-ratelimit-reset", "ratelimit-reset", "rateLimitReset");
103
- const rateLimitRaw = getHeader("x-ratelimit-limit", "ratelimit-limit", "rateLimit");
104
- const rateLimitRemainingRaw = getHeader("x-ratelimit-remaining", "ratelimit-remaining", "rateLimitRemaining");
105
- let retryAfterDelayMs;
106
- if (retryAfterRaw !== undefined) {
107
- const retryAfterNumeric = Number(retryAfterRaw);
108
- if (!Number.isNaN(retryAfterNumeric)) {
109
- retryAfterDelayMs = retryAfterNumeric >= 1000 ? retryAfterNumeric : retryAfterNumeric * 1000;
110
- }
111
- else {
112
- retryAfterDelayMs = new Date(retryAfterRaw).getTime() - Date.now();
113
- }
114
- }
115
- let rateLimitResetDelayMs;
116
- if (rateLimitResetRaw !== undefined) {
117
- const resetValue = Number(rateLimitResetRaw);
118
- if (!Number.isNaN(resetValue)) {
119
- if (resetValue > 1000000000) {
120
- rateLimitResetDelayMs = (resetValue * 1000) - Date.now();
121
- }
122
- else {
123
- rateLimitResetDelayMs = resetValue >= 1000 ? resetValue : resetValue * 1000;
124
- }
125
- }
126
- }
91
+ const retryAfterRaw = getHeaderCaseInsensitive(responseHeaders, "retry-after");
92
+ const rateLimitResetRaw = getHeaderCaseInsensitive(responseHeaders, "x-ratelimit-reset", "ratelimit-reset", "rateLimitReset");
93
+ const rateLimitRaw = getHeaderCaseInsensitive(responseHeaders, "x-ratelimit-limit", "ratelimit-limit", "rateLimit");
94
+ const rateLimitRemainingRaw = getHeaderCaseInsensitive(responseHeaders, "x-ratelimit-remaining", "ratelimit-remaining", "rateLimitRemaining");
95
+ const retryAfterDelayMs = parseHeaderDelayMs(retryAfterRaw);
96
+ const rateLimitResetDelayMs = parseHeaderDelayMs(rateLimitResetRaw);
127
97
  if (willRetry) {
128
98
  console.warn(`[ConversationsClient] Retry decision: will retry after attempt ${attempt}/${maxAttempts} (status=${statusCode ?? "unknown"}, time=${new Date().toISOString()})`);
129
- console.warn(`[ConversationsClient] Retry headers: retry-after=${retryAfterRaw ?? "n/a"}, x-ratelimit-reset=${rateLimitResetRaw ?? "n/a"}, x-ratelimit-limit=${rateLimitRaw ?? "n/a"}, x-ratelimit-remaining=${rateLimitRemainingRaw ?? "n/a"}`);
130
- console.warn(`[ConversationsClient] Parsed retry timing: retryAfterDelayMs=${retryAfterDelayMs ?? "n/a"}, rateLimitResetDelayMs=${rateLimitResetDelayMs ?? "n/a"}`);
131
99
  }
132
100
  else {
133
101
  console.warn(`[ConversationsClient] Retry decision: stop after attempt ${attempt}/${maxAttempts} (status=${statusCode ?? "unknown"}, time=${new Date().toISOString()})`);
134
102
  }
103
+ console.warn(`[ConversationsClient] Retry headers: retry-after=${String(retryAfterRaw ?? "n/a")}, x-ratelimit-reset=${String(rateLimitResetRaw ?? "n/a")}, x-ratelimit-limit=${String(rateLimitRaw ?? "n/a")}, x-ratelimit-remaining=${String(rateLimitRemainingRaw ?? "n/a")}`);
104
+ console.warn(`[ConversationsClient] Parsed retry timing: retryAfterDelayMs=${retryAfterDelayMs ?? "n/a"}, rateLimitResetDelayMs=${rateLimitResetDelayMs ?? "n/a"}`);
135
105
  throw error;
136
106
  }
137
107
  }, {
@@ -152,7 +152,7 @@ export interface ClientDefaults extends Partial<__SmithyConfiguration<__HttpHand
152
152
  */
153
153
  retryDecider?: (error: any) => boolean;
154
154
  /**
155
- * Enables console logging for retry attempts and retry decisions.
155
+ * Enables console logging for retry attempts and timing headers.
156
156
  * Defaults to `false`.
157
157
  */
158
158
  retryLogging?: boolean;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wildix/xbees-conversations-client",
3
3
  "description": "@wildix/xbees-conversations-client client",
4
- "version": "1.2.10",
4
+ "version": "1.2.12",
5
5
  "scripts": {
6
6
  "build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'",
7
7
  "build:cjs": "tsc -p tsconfig.cjs.json",