@doist/twist-sdk 2.1.3 → 2.2.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.
- package/dist/cjs/authentication.js +5 -5
- package/dist/cjs/batch-builder.js +2 -2
- package/dist/cjs/clients/add-comment-helper.js +35 -0
- package/dist/cjs/clients/channels-client.js +14 -14
- package/dist/cjs/clients/comments-client.js +8 -21
- package/dist/cjs/clients/conversation-messages-client.js +6 -6
- package/dist/cjs/clients/conversations-client.js +16 -16
- package/dist/cjs/clients/groups-client.js +10 -10
- package/dist/cjs/clients/inbox-client.js +7 -7
- package/dist/cjs/clients/reactions-client.js +4 -4
- package/dist/cjs/clients/search-client.js +4 -4
- package/dist/cjs/clients/threads-client.js +54 -21
- package/dist/cjs/clients/users-client.js +15 -15
- package/dist/cjs/clients/workspace-users-client.js +11 -11
- package/dist/cjs/clients/workspaces-client.js +8 -8
- package/dist/cjs/testUtils/msw-setup.js +1 -1
- package/dist/cjs/{rest-client.js → transport/fetch-with-retry.js} +108 -153
- package/dist/cjs/transport/http-client.js +108 -0
- package/dist/cjs/transport/http-dispatcher.js +128 -0
- package/dist/cjs/types/requests.js +3 -1
- package/dist/esm/authentication.js +1 -1
- package/dist/esm/batch-builder.js +1 -1
- package/dist/esm/clients/add-comment-helper.js +32 -0
- package/dist/esm/clients/channels-client.js +1 -1
- package/dist/esm/clients/comments-client.js +3 -16
- package/dist/esm/clients/conversation-messages-client.js +1 -1
- package/dist/esm/clients/conversations-client.js +1 -1
- package/dist/esm/clients/groups-client.js +1 -1
- package/dist/esm/clients/inbox-client.js +1 -1
- package/dist/esm/clients/reactions-client.js +1 -1
- package/dist/esm/clients/search-client.js +1 -1
- package/dist/esm/clients/threads-client.js +35 -2
- package/dist/esm/clients/users-client.js +1 -1
- package/dist/esm/clients/workspace-users-client.js +1 -1
- package/dist/esm/clients/workspaces-client.js +1 -1
- package/dist/esm/testUtils/msw-setup.js +1 -1
- package/dist/esm/{rest-client.js → transport/fetch-with-retry.js} +108 -150
- package/dist/esm/transport/http-client.js +103 -0
- package/dist/esm/transport/http-dispatcher.js +91 -0
- package/dist/esm/types/requests.js +2 -0
- package/dist/types/clients/add-comment-helper.d.ts +14 -0
- package/dist/types/clients/threads-client.d.ts +57 -2
- package/dist/types/transport/fetch-with-retry.d.ts +4 -0
- package/dist/types/{rest-client.d.ts → transport/http-client.d.ts} +1 -4
- package/dist/types/transport/http-dispatcher.d.ts +3 -0
- package/dist/types/types/requests.d.ts +18 -0
- package/package.json +1 -1
|
@@ -15,8 +15,9 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
15
15
|
})();
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { ENDPOINT_COMMENTS } from '../consts/endpoints.js';
|
|
18
|
-
import { request } from '../
|
|
18
|
+
import { request } from '../transport/http-client.js';
|
|
19
19
|
import { CommentSchema } from '../types/entities.js';
|
|
20
|
+
import { addCommentRequest } from './add-comment-helper.js';
|
|
20
21
|
import { BaseClient } from './base-client.js';
|
|
21
22
|
/**
|
|
22
23
|
* Client for interacting with Twist comment endpoints.
|
|
@@ -67,21 +68,7 @@ var CommentsClient = /** @class */ (function (_super) {
|
|
|
67
68
|
}).then(function (response) { return wrappedSchema.parse(response.data); });
|
|
68
69
|
};
|
|
69
70
|
CommentsClient.prototype.createComment = function (args, options) {
|
|
70
|
-
|
|
71
|
-
var url = "".concat(ENDPOINT_COMMENTS, "/add");
|
|
72
|
-
var params = args;
|
|
73
|
-
var schema = CommentSchema;
|
|
74
|
-
if (options === null || options === void 0 ? void 0 : options.batch) {
|
|
75
|
-
return { method: method, url: url, params: params, schema: schema };
|
|
76
|
-
}
|
|
77
|
-
return request({
|
|
78
|
-
httpMethod: method,
|
|
79
|
-
baseUri: this.getBaseUri(),
|
|
80
|
-
relativePath: url,
|
|
81
|
-
apiToken: this.apiToken,
|
|
82
|
-
payload: params,
|
|
83
|
-
customFetch: this.customFetch,
|
|
84
|
-
}).then(function (response) { return schema.parse(response.data); });
|
|
71
|
+
return addCommentRequest({ baseUri: this.getBaseUri(), apiToken: this.apiToken, customFetch: this.customFetch }, args, options);
|
|
85
72
|
};
|
|
86
73
|
CommentsClient.prototype.updateComment = function (args, options) {
|
|
87
74
|
var method = 'POST';
|
|
@@ -15,7 +15,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
15
15
|
})();
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { ENDPOINT_CONVERSATION_MESSAGES } from '../consts/endpoints.js';
|
|
18
|
-
import { request } from '../
|
|
18
|
+
import { request } from '../transport/http-client.js';
|
|
19
19
|
import { ConversationMessageSchema } from '../types/entities.js';
|
|
20
20
|
import { BaseClient } from './base-client.js';
|
|
21
21
|
/**
|
|
@@ -15,7 +15,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
15
15
|
})();
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { ENDPOINT_CONVERSATIONS } from '../consts/endpoints.js';
|
|
18
|
-
import { request } from '../
|
|
18
|
+
import { request } from '../transport/http-client.js';
|
|
19
19
|
import { ConversationSchema, UnreadConversationSchema, } from '../types/entities.js';
|
|
20
20
|
import { BaseClient } from './base-client.js';
|
|
21
21
|
/**
|
|
@@ -14,7 +14,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
14
14
|
};
|
|
15
15
|
})();
|
|
16
16
|
import { ENDPOINT_GROUPS } from '../consts/endpoints.js';
|
|
17
|
-
import { request } from '../
|
|
17
|
+
import { request } from '../transport/http-client.js';
|
|
18
18
|
import { GroupSchema } from '../types/entities.js';
|
|
19
19
|
import { BaseClient } from './base-client.js';
|
|
20
20
|
/**
|
|
@@ -15,7 +15,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
15
15
|
})();
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { ENDPOINT_INBOX } from '../consts/endpoints.js';
|
|
18
|
-
import { request } from '../
|
|
18
|
+
import { request } from '../transport/http-client.js';
|
|
19
19
|
import { InboxThreadSchema } from '../types/entities.js';
|
|
20
20
|
import { BaseClient } from './base-client.js';
|
|
21
21
|
/**
|
|
@@ -14,7 +14,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
14
14
|
};
|
|
15
15
|
})();
|
|
16
16
|
import { ENDPOINT_REACTIONS } from '../consts/endpoints.js';
|
|
17
|
-
import { request } from '../
|
|
17
|
+
import { request } from '../transport/http-client.js';
|
|
18
18
|
import { BaseClient } from './base-client.js';
|
|
19
19
|
/**
|
|
20
20
|
* Client for interacting with Twist reaction endpoints.
|
|
@@ -25,7 +25,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
25
25
|
return __assign.apply(this, arguments);
|
|
26
26
|
};
|
|
27
27
|
import { ENDPOINT_SEARCH } from '../consts/endpoints.js';
|
|
28
|
-
import { request } from '../
|
|
28
|
+
import { request } from '../transport/http-client.js';
|
|
29
29
|
import { SearchResultSchema, } from '../types/entities.js';
|
|
30
30
|
import { BaseClient } from './base-client.js';
|
|
31
31
|
/**
|
|
@@ -13,10 +13,33 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
13
13
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
14
|
};
|
|
15
15
|
})();
|
|
16
|
+
var __assign = (this && this.__assign) || function () {
|
|
17
|
+
__assign = Object.assign || function(t) {
|
|
18
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
+
s = arguments[i];
|
|
20
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
21
|
+
t[p] = s[p];
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
};
|
|
25
|
+
return __assign.apply(this, arguments);
|
|
26
|
+
};
|
|
27
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
28
|
+
var t = {};
|
|
29
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
30
|
+
t[p] = s[p];
|
|
31
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
32
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
33
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
34
|
+
t[p[i]] = s[p[i]];
|
|
35
|
+
}
|
|
36
|
+
return t;
|
|
37
|
+
};
|
|
16
38
|
import { z } from 'zod';
|
|
17
39
|
import { ENDPOINT_THREADS } from '../consts/endpoints.js';
|
|
18
|
-
import { request } from '../
|
|
19
|
-
import { ThreadSchema, UnreadThreadSchema } from '../types/entities.js';
|
|
40
|
+
import { request } from '../transport/http-client.js';
|
|
41
|
+
import { ThreadSchema, UnreadThreadSchema, } from '../types/entities.js';
|
|
42
|
+
import { addCommentRequest } from './add-comment-helper.js';
|
|
20
43
|
import { BaseClient } from './base-client.js';
|
|
21
44
|
/**
|
|
22
45
|
* Client for interacting with Twist thread endpoints.
|
|
@@ -358,6 +381,16 @@ var ThreadsClient = /** @class */ (function (_super) {
|
|
|
358
381
|
customFetch: this.customFetch,
|
|
359
382
|
}).then(function (response) { return schema.parse(response.data); });
|
|
360
383
|
};
|
|
384
|
+
ThreadsClient.prototype.closeThread = function (args, options) {
|
|
385
|
+
return this.addCommentWithAction(args, 'close', options);
|
|
386
|
+
};
|
|
387
|
+
ThreadsClient.prototype.reopenThread = function (args, options) {
|
|
388
|
+
return this.addCommentWithAction(args, 'reopen', options);
|
|
389
|
+
};
|
|
390
|
+
ThreadsClient.prototype.addCommentWithAction = function (args, threadAction, options) {
|
|
391
|
+
var id = args.id, rest = __rest(args, ["id"]);
|
|
392
|
+
return addCommentRequest({ baseUri: this.getBaseUri(), apiToken: this.apiToken, customFetch: this.customFetch }, __assign({ threadId: id }, rest), __assign(__assign({}, options), { threadAction: threadAction }));
|
|
393
|
+
};
|
|
361
394
|
return ThreadsClient;
|
|
362
395
|
}(BaseClient));
|
|
363
396
|
export { ThreadsClient };
|
|
@@ -14,7 +14,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
14
14
|
};
|
|
15
15
|
})();
|
|
16
16
|
import { ENDPOINT_USERS } from '../consts/endpoints.js';
|
|
17
|
-
import { request } from '../
|
|
17
|
+
import { request } from '../transport/http-client.js';
|
|
18
18
|
import { UserSchema } from '../types/entities.js';
|
|
19
19
|
import { BaseClient } from './base-client.js';
|
|
20
20
|
/**
|
|
@@ -13,7 +13,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
13
13
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
14
|
};
|
|
15
15
|
})();
|
|
16
|
-
import { request } from '../
|
|
16
|
+
import { request } from '../transport/http-client.js';
|
|
17
17
|
import { WorkspaceUserSchema } from '../types/entities.js';
|
|
18
18
|
import { BaseClient } from './base-client.js';
|
|
19
19
|
/**
|
|
@@ -14,7 +14,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
14
14
|
};
|
|
15
15
|
})();
|
|
16
16
|
import { ENDPOINT_WORKSPACES } from '../consts/endpoints.js';
|
|
17
|
-
import { request } from '../
|
|
17
|
+
import { request } from '../transport/http-client.js';
|
|
18
18
|
import { ChannelSchema, WorkspaceSchema } from '../types/entities.js';
|
|
19
19
|
import { BaseClient } from './base-client.js';
|
|
20
20
|
/**
|
|
@@ -4,7 +4,7 @@ import { afterAll, afterEach, beforeAll } from 'vitest';
|
|
|
4
4
|
export var server = setupServer();
|
|
5
5
|
// Start server before all tests
|
|
6
6
|
beforeAll(function () {
|
|
7
|
-
// Only warn on unhandled requests instead of error, since
|
|
7
|
+
// Only warn on unhandled requests instead of error, since transport/http-client.test.ts
|
|
8
8
|
// uses direct fetch mocking which bypasses MSW
|
|
9
9
|
server.listen({ onUnhandledRequest: 'warn' });
|
|
10
10
|
});
|
|
@@ -45,117 +45,26 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
45
45
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
/**
|
|
53
|
-
* HTTP agent with keepAlive disabled to prevent hanging connections
|
|
54
|
-
* This ensures the process exits immediately after requests complete
|
|
55
|
-
*/
|
|
56
|
-
var httpAgent = new Agent({
|
|
57
|
-
keepAliveTimeout: 1, // Close connections after 1ms of idle time
|
|
58
|
-
keepAliveMaxTimeout: 1, // Maximum time to keep connections alive
|
|
59
|
-
});
|
|
60
|
-
export function paramsSerializer(params) {
|
|
61
|
-
var qs = new URLSearchParams();
|
|
62
|
-
Object.keys(params).forEach(function (key) {
|
|
63
|
-
var value = params[key];
|
|
64
|
-
if (value != null) {
|
|
65
|
-
if (Array.isArray(value)) {
|
|
66
|
-
qs.append(key, value.join(','));
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
qs.append(key, String(value));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
return qs.toString();
|
|
74
|
-
}
|
|
75
|
-
var defaultHeaders = {
|
|
76
|
-
'Content-Type': 'application/json',
|
|
77
|
-
};
|
|
78
|
-
function getAuthHeader(apiToken) {
|
|
79
|
-
return "Bearer ".concat(apiToken);
|
|
80
|
-
}
|
|
81
|
-
function getRequestConfiguration(baseURL, apiToken, requestId) {
|
|
82
|
-
var authHeader = apiToken ? { Authorization: getAuthHeader(apiToken) } : undefined;
|
|
83
|
-
var requestIdHeader = requestId ? { 'X-Request-Id': requestId } : undefined;
|
|
84
|
-
var headers = __assign(__assign(__assign({}, defaultHeaders), authHeader), requestIdHeader);
|
|
85
|
-
return { baseURL: baseURL, headers: headers, timeout: 30000 };
|
|
86
|
-
}
|
|
87
|
-
function sleep(ms) {
|
|
88
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
89
|
-
return __generator(this, function (_a) {
|
|
90
|
-
return [2 /*return*/, new Promise(function (resolve) { return setTimeout(resolve, ms); })];
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
function isNetworkError(error) {
|
|
95
|
-
return error.name === 'TypeError' || error.message.toLowerCase().includes('network');
|
|
96
|
-
}
|
|
97
|
-
function getRetryDelay(retryCount) {
|
|
98
|
-
return retryCount === 1 ? 0 : 500;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Creates an AbortSignal that aborts after timeoutMs. Returns the signal and a
|
|
102
|
-
* clear function to cancel the timeout early.
|
|
103
|
-
*/
|
|
104
|
-
function createTimeoutSignal(timeoutMs, existingSignal) {
|
|
105
|
-
var controller = new AbortController();
|
|
106
|
-
var timeoutId = setTimeout(function () {
|
|
107
|
-
controller.abort(new Error("Request timeout after ".concat(timeoutMs, "ms")));
|
|
108
|
-
}, timeoutMs);
|
|
109
|
-
function clear() {
|
|
110
|
-
clearTimeout(timeoutId);
|
|
111
|
-
}
|
|
112
|
-
// Forward existing signal if provided
|
|
113
|
-
if (existingSignal) {
|
|
114
|
-
if (existingSignal.aborted) {
|
|
115
|
-
controller.abort(existingSignal.reason);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
existingSignal.addEventListener('abort', function () {
|
|
119
|
-
controller.abort(existingSignal.reason);
|
|
120
|
-
clear();
|
|
121
|
-
}, { once: true });
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return { signal: controller.signal, clear: clear };
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Converts native fetch Response to CustomFetchResponse for consistent interface
|
|
128
|
-
*/
|
|
129
|
-
function convertResponseToCustomFetch(response) {
|
|
130
|
-
var headers = {};
|
|
131
|
-
response.headers.forEach(function (value, key) {
|
|
132
|
-
headers[key] = value;
|
|
133
|
-
});
|
|
134
|
-
return {
|
|
135
|
-
ok: response.ok,
|
|
136
|
-
status: response.status,
|
|
137
|
-
statusText: response.statusText,
|
|
138
|
-
headers: headers,
|
|
139
|
-
text: function () { return response.clone().text(); },
|
|
140
|
-
json: function () { return response.json(); },
|
|
141
|
-
};
|
|
142
|
-
}
|
|
48
|
+
import { TwistRequestError } from '../types/errors.js';
|
|
49
|
+
import { camelCaseKeys } from '../utils/case-conversion.js';
|
|
50
|
+
import { transformTimestamps } from '../utils/timestamp-conversion.js';
|
|
51
|
+
import { getDefaultDispatcher } from './http-dispatcher.js';
|
|
143
52
|
export function fetchWithRetry(url_1, options_1) {
|
|
144
53
|
return __awaiter(this, arguments, void 0, function (url, options, maxRetries, customFetch) {
|
|
145
|
-
var lastError, attempt, clearTimeoutFn, requestSignal, timeoutResult, response, _a,
|
|
146
|
-
var
|
|
54
|
+
var lastError, attempt, clearTimeoutFn, requestSignal, timeoutResult, response, _a, responseText, responseData, camelCased, transformed, error_1, delay;
|
|
55
|
+
var _b;
|
|
147
56
|
if (maxRetries === void 0) { maxRetries = 3; }
|
|
148
|
-
return __generator(this, function (
|
|
149
|
-
switch (
|
|
57
|
+
return __generator(this, function (_c) {
|
|
58
|
+
switch (_c.label) {
|
|
150
59
|
case 0:
|
|
151
60
|
attempt = 0;
|
|
152
|
-
|
|
61
|
+
_c.label = 1;
|
|
153
62
|
case 1:
|
|
154
63
|
if (!(attempt <= maxRetries)) return [3 /*break*/, 13];
|
|
155
64
|
clearTimeoutFn = void 0;
|
|
156
|
-
|
|
65
|
+
_c.label = 2;
|
|
157
66
|
case 2:
|
|
158
|
-
|
|
67
|
+
_c.trys.push([2, 8, , 12]);
|
|
159
68
|
requestSignal = options.signal || undefined;
|
|
160
69
|
if (options.timeout && options.timeout > 0) {
|
|
161
70
|
timeoutResult = createTimeoutSignal(options.timeout, requestSignal);
|
|
@@ -165,26 +74,22 @@ export function fetchWithRetry(url_1, options_1) {
|
|
|
165
74
|
if (!customFetch) return [3 /*break*/, 4];
|
|
166
75
|
return [4 /*yield*/, customFetch(url, options)];
|
|
167
76
|
case 3:
|
|
168
|
-
_a =
|
|
77
|
+
_a = _c.sent();
|
|
169
78
|
return [3 /*break*/, 6];
|
|
170
|
-
case 4:
|
|
171
|
-
_b = convertResponseToCustomFetch;
|
|
172
|
-
return [4 /*yield*/, fetch(url, __assign(__assign({}, options), { signal: requestSignal,
|
|
173
|
-
// @ts-expect-error - dispatcher is valid for Node.js fetch but not in TS types
|
|
174
|
-
dispatcher: httpAgent }))];
|
|
79
|
+
case 4: return [4 /*yield*/, fetchWithDefaultTransport(url, options, requestSignal)];
|
|
175
80
|
case 5:
|
|
176
|
-
_a =
|
|
177
|
-
|
|
81
|
+
_a = _c.sent();
|
|
82
|
+
_c.label = 6;
|
|
178
83
|
case 6:
|
|
179
84
|
response = _a;
|
|
180
85
|
return [4 /*yield*/, response.text()];
|
|
181
86
|
case 7:
|
|
182
|
-
responseText =
|
|
87
|
+
responseText = _c.sent();
|
|
183
88
|
responseData = void 0;
|
|
184
89
|
try {
|
|
185
90
|
responseData = responseText ? JSON.parse(responseText) : undefined;
|
|
186
91
|
}
|
|
187
|
-
catch (
|
|
92
|
+
catch (_d) {
|
|
188
93
|
responseData = responseText;
|
|
189
94
|
}
|
|
190
95
|
if (!response.ok) {
|
|
@@ -192,7 +97,6 @@ export function fetchWithRetry(url_1, options_1) {
|
|
|
192
97
|
}
|
|
193
98
|
camelCased = camelCaseKeys(responseData);
|
|
194
99
|
transformed = transformTimestamps(camelCased);
|
|
195
|
-
// Success – clear pending timeout (if any) so Node can exit promptly
|
|
196
100
|
if (clearTimeoutFn) {
|
|
197
101
|
clearTimeoutFn();
|
|
198
102
|
}
|
|
@@ -202,27 +106,20 @@ export function fetchWithRetry(url_1, options_1) {
|
|
|
202
106
|
headers: response.headers,
|
|
203
107
|
}];
|
|
204
108
|
case 8:
|
|
205
|
-
error_1 =
|
|
109
|
+
error_1 = _c.sent();
|
|
110
|
+
if (clearTimeoutFn) {
|
|
111
|
+
clearTimeoutFn();
|
|
112
|
+
}
|
|
206
113
|
lastError = error_1 instanceof Error ? error_1 : new Error('Unknown error');
|
|
207
114
|
if (!(attempt < maxRetries && isNetworkError(lastError))) return [3 /*break*/, 11];
|
|
208
115
|
delay = getRetryDelay(attempt + 1);
|
|
209
116
|
if (!(delay > 0)) return [3 /*break*/, 10];
|
|
210
117
|
return [4 /*yield*/, sleep(delay)];
|
|
211
118
|
case 9:
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
case 10:
|
|
215
|
-
|
|
216
|
-
if (clearTimeoutFn) {
|
|
217
|
-
clearTimeoutFn();
|
|
218
|
-
}
|
|
219
|
-
return [3 /*break*/, 12];
|
|
220
|
-
case 11:
|
|
221
|
-
// Final error – clear timeout before throwing
|
|
222
|
-
if (clearTimeoutFn) {
|
|
223
|
-
clearTimeoutFn();
|
|
224
|
-
}
|
|
225
|
-
return [3 /*break*/, 13];
|
|
119
|
+
_c.sent();
|
|
120
|
+
_c.label = 10;
|
|
121
|
+
case 10: return [3 /*break*/, 12];
|
|
122
|
+
case 11: return [3 /*break*/, 13];
|
|
226
123
|
case 12:
|
|
227
124
|
attempt++;
|
|
228
125
|
return [3 /*break*/, 1];
|
|
@@ -230,35 +127,96 @@ export function fetchWithRetry(url_1, options_1) {
|
|
|
230
127
|
if (lastError instanceof TwistRequestError) {
|
|
231
128
|
throw lastError;
|
|
232
129
|
}
|
|
233
|
-
throw new TwistRequestError((
|
|
130
|
+
throw new TwistRequestError((_b = lastError === null || lastError === void 0 ? void 0 : lastError.message) !== null && _b !== void 0 ? _b : 'Request failed');
|
|
234
131
|
}
|
|
235
132
|
});
|
|
236
133
|
});
|
|
237
134
|
}
|
|
238
|
-
|
|
135
|
+
function fetchWithDefaultTransport(url, options, signal) {
|
|
239
136
|
return __awaiter(this, void 0, void 0, function () {
|
|
240
|
-
var
|
|
241
|
-
return __generator(this, function (
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return [
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
137
|
+
var dispatcher, response, _a;
|
|
138
|
+
return __generator(this, function (_b) {
|
|
139
|
+
switch (_b.label) {
|
|
140
|
+
case 0: return [4 /*yield*/, getDefaultDispatcher()];
|
|
141
|
+
case 1:
|
|
142
|
+
dispatcher = _b.sent();
|
|
143
|
+
if (!dispatcher) return [3 /*break*/, 3];
|
|
144
|
+
return [4 /*yield*/, fetch(url, __assign(__assign({}, options), { signal: signal,
|
|
145
|
+
// @ts-expect-error - dispatcher is valid for Node.js fetch but not in TS types
|
|
146
|
+
dispatcher: dispatcher }))];
|
|
147
|
+
case 2:
|
|
148
|
+
_a = _b.sent();
|
|
149
|
+
return [3 /*break*/, 5];
|
|
150
|
+
case 3: return [4 /*yield*/, fetch(url, __assign(__assign({}, options), { signal: signal }))];
|
|
151
|
+
case 4:
|
|
152
|
+
_a = _b.sent();
|
|
153
|
+
_b.label = 5;
|
|
154
|
+
case 5:
|
|
155
|
+
response = _a;
|
|
156
|
+
return [2 /*return*/, convertResponseToCustomFetch(response)];
|
|
257
157
|
}
|
|
258
|
-
return [2 /*return*/, fetchWithRetry(url, options, 3, customFetch)];
|
|
259
158
|
});
|
|
260
159
|
});
|
|
261
160
|
}
|
|
262
|
-
|
|
263
|
-
return
|
|
161
|
+
function sleep(ms) {
|
|
162
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
163
|
+
return __generator(this, function (_a) {
|
|
164
|
+
return [2 /*return*/, new Promise(function (resolve) { return setTimeout(resolve, ms); })];
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
var timeoutErrorName = 'TimeoutError';
|
|
169
|
+
function createTimeoutError(timeoutMs) {
|
|
170
|
+
var error = new Error("Request timeout after ".concat(timeoutMs, "ms"));
|
|
171
|
+
error.name = timeoutErrorName;
|
|
172
|
+
return error;
|
|
173
|
+
}
|
|
174
|
+
function isNetworkError(error) {
|
|
175
|
+
return (error.name === 'TypeError' ||
|
|
176
|
+
error.name === timeoutErrorName ||
|
|
177
|
+
error.message.toLowerCase().includes('network'));
|
|
178
|
+
}
|
|
179
|
+
function getRetryDelay(retryCount) {
|
|
180
|
+
return retryCount === 1 ? 0 : 500;
|
|
181
|
+
}
|
|
182
|
+
function createTimeoutSignal(timeoutMs, existingSignal) {
|
|
183
|
+
var controller = new AbortController();
|
|
184
|
+
var timeoutId = setTimeout(function () {
|
|
185
|
+
controller.abort(createTimeoutError(timeoutMs));
|
|
186
|
+
}, timeoutMs);
|
|
187
|
+
var abortHandler;
|
|
188
|
+
function clear() {
|
|
189
|
+
clearTimeout(timeoutId);
|
|
190
|
+
if (existingSignal && abortHandler) {
|
|
191
|
+
existingSignal.removeEventListener('abort', abortHandler);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (existingSignal) {
|
|
195
|
+
if (existingSignal.aborted) {
|
|
196
|
+
clearTimeout(timeoutId);
|
|
197
|
+
controller.abort(existingSignal.reason);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
abortHandler = function () {
|
|
201
|
+
clearTimeout(timeoutId);
|
|
202
|
+
controller.abort(existingSignal.reason);
|
|
203
|
+
};
|
|
204
|
+
existingSignal.addEventListener('abort', abortHandler, { once: true });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return { signal: controller.signal, clear: clear };
|
|
208
|
+
}
|
|
209
|
+
function convertResponseToCustomFetch(response) {
|
|
210
|
+
var headers = {};
|
|
211
|
+
response.headers.forEach(function (value, key) {
|
|
212
|
+
headers[key] = value;
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
ok: response.ok,
|
|
216
|
+
status: response.status,
|
|
217
|
+
statusText: response.statusText,
|
|
218
|
+
headers: headers,
|
|
219
|
+
text: function () { return response.clone().text(); },
|
|
220
|
+
json: function () { return response.json(); },
|
|
221
|
+
};
|
|
264
222
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
23
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
import { snakeCaseKeys } from '../utils/case-conversion.js';
|
|
49
|
+
import { fetchWithRetry } from './fetch-with-retry.js';
|
|
50
|
+
export function paramsSerializer(params) {
|
|
51
|
+
var qs = new URLSearchParams();
|
|
52
|
+
Object.keys(params).forEach(function (key) {
|
|
53
|
+
var value = params[key];
|
|
54
|
+
if (value != null) {
|
|
55
|
+
if (Array.isArray(value)) {
|
|
56
|
+
qs.append(key, value.join(','));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
qs.append(key, String(value));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return qs.toString();
|
|
64
|
+
}
|
|
65
|
+
var defaultHeaders = {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
};
|
|
68
|
+
function getAuthHeader(apiToken) {
|
|
69
|
+
return "Bearer ".concat(apiToken);
|
|
70
|
+
}
|
|
71
|
+
function getRequestConfiguration(baseURL, apiToken, requestId) {
|
|
72
|
+
var authHeader = apiToken ? { Authorization: getAuthHeader(apiToken) } : undefined;
|
|
73
|
+
var requestIdHeader = requestId ? { 'X-Request-Id': requestId } : undefined;
|
|
74
|
+
var headers = __assign(__assign(__assign({}, defaultHeaders), authHeader), requestIdHeader);
|
|
75
|
+
return { baseURL: baseURL, headers: headers, timeout: 30000 };
|
|
76
|
+
}
|
|
77
|
+
export function request(args) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
79
|
+
var httpMethod, baseUri, relativePath, apiToken, payload, requestId, customFetch, config, url, options, searchParams, urlWithParams;
|
|
80
|
+
return __generator(this, function (_a) {
|
|
81
|
+
httpMethod = args.httpMethod, baseUri = args.baseUri, relativePath = args.relativePath, apiToken = args.apiToken, payload = args.payload, requestId = args.requestId, customFetch = args.customFetch;
|
|
82
|
+
config = getRequestConfiguration(baseUri, apiToken, requestId);
|
|
83
|
+
url = new URL(relativePath, config.baseURL).toString();
|
|
84
|
+
options = {
|
|
85
|
+
method: httpMethod,
|
|
86
|
+
headers: config.headers,
|
|
87
|
+
timeout: config.timeout,
|
|
88
|
+
};
|
|
89
|
+
if (httpMethod === 'GET' && payload) {
|
|
90
|
+
searchParams = paramsSerializer(snakeCaseKeys(payload));
|
|
91
|
+
urlWithParams = searchParams ? "".concat(url, "?").concat(searchParams) : url;
|
|
92
|
+
return [2 /*return*/, fetchWithRetry(urlWithParams, options, 3, customFetch)];
|
|
93
|
+
}
|
|
94
|
+
if (payload && httpMethod !== 'GET') {
|
|
95
|
+
options.body = JSON.stringify(snakeCaseKeys(payload));
|
|
96
|
+
}
|
|
97
|
+
return [2 /*return*/, fetchWithRetry(url, options, 3, customFetch)];
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export function isSuccess(response) {
|
|
102
|
+
return response.status >= 200 && response.status < 300;
|
|
103
|
+
}
|