@doist/twist-sdk 2.1.2 → 2.1.4
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 +90 -5
- package/dist/cjs/batch-builder.js +2 -2
- package/dist/cjs/clients/base-client.js +2 -1
- package/dist/cjs/clients/channels-client.js +14 -14
- package/dist/cjs/clients/comments-client.js +7 -7
- 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 +21 -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/consts/endpoints.js +3 -2
- 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/api-version.js +6 -0
- package/dist/cjs/types/entities.js +4 -4
- package/dist/cjs/types/http.js +2 -0
- package/dist/cjs/types/index.js +1 -0
- package/dist/esm/authentication.js +85 -1
- package/dist/esm/batch-builder.js +1 -1
- package/dist/esm/clients/base-client.js +2 -1
- package/dist/esm/clients/channels-client.js +1 -1
- package/dist/esm/clients/comments-client.js +1 -1
- 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 +1 -1
- 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/consts/endpoints.js +3 -2
- 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/api-version.js +5 -1
- package/dist/esm/types/entities.js +1 -1
- package/dist/esm/types/http.js +1 -1
- package/dist/esm/types/index.js +1 -0
- package/dist/types/authentication.d.ts +5 -1
- package/dist/types/consts/endpoints.d.ts +2 -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/api-version.d.ts +3 -1
- package/dist/types/types/entities.d.ts +25 -0
- package/dist/types/types/http.d.ts +2 -1
- package/dist/types/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -46,8 +46,92 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
import { v4 as uuid } from 'uuid';
|
|
49
|
-
import { isSuccess, request } from './
|
|
49
|
+
import { isSuccess, request } from './transport/http-client.js';
|
|
50
50
|
import { TwistRequestError } from './types/errors.js';
|
|
51
|
+
/**
|
|
52
|
+
* OAuth scopes for the Twist API.
|
|
53
|
+
*
|
|
54
|
+
* @remarks
|
|
55
|
+
* Request only the scopes your application needs:
|
|
56
|
+
*
|
|
57
|
+
* **User Scopes:**
|
|
58
|
+
* - `user:read` - Access user's personal settings
|
|
59
|
+
* - `user:write` - Access and update user's personal settings
|
|
60
|
+
*
|
|
61
|
+
* **Workspace Scopes:**
|
|
62
|
+
* - `workspaces:read` - Access teams the user is part of
|
|
63
|
+
* - `workspaces:write` - Access and update teams the user is part of
|
|
64
|
+
*
|
|
65
|
+
* **Channel Scopes:**
|
|
66
|
+
* - `channels:read` - Access channels
|
|
67
|
+
* - `channels:write` - Access and update channels
|
|
68
|
+
* - `channels:remove` - Access, update, and delete channels
|
|
69
|
+
*
|
|
70
|
+
* **Thread Scopes:**
|
|
71
|
+
* - `threads:read` - Access threads
|
|
72
|
+
* - `threads:write` - Access and update threads
|
|
73
|
+
* - `threads:remove` - Access, update, and delete threads
|
|
74
|
+
*
|
|
75
|
+
* **Comment Scopes:**
|
|
76
|
+
* - `comments:read` - Access comments
|
|
77
|
+
* - `comments:write` - Access and update comments
|
|
78
|
+
* - `comments:remove` - Access, update, and delete comments
|
|
79
|
+
*
|
|
80
|
+
* **Group Scopes:**
|
|
81
|
+
* - `groups:read` - Access groups
|
|
82
|
+
* - `groups:write` - Access and update groups
|
|
83
|
+
* - `groups:remove` - Access, update, and delete groups
|
|
84
|
+
*
|
|
85
|
+
* **Message Scopes:**
|
|
86
|
+
* - `messages:read` - Access messages
|
|
87
|
+
* - `messages:write` - Access and update messages
|
|
88
|
+
* - `messages:remove` - Access, update, and delete messages
|
|
89
|
+
*
|
|
90
|
+
* **Reaction Scopes:**
|
|
91
|
+
* - `reactions:read` - Access reactions
|
|
92
|
+
* - `reactions:write` - Access and update reactions
|
|
93
|
+
* - `reactions:remove` - Access, update, and delete reactions
|
|
94
|
+
*
|
|
95
|
+
* **Search Scopes:**
|
|
96
|
+
* - `search:read` - Search
|
|
97
|
+
*
|
|
98
|
+
* **Attachment Scopes:**
|
|
99
|
+
* - `attachments:read` - Access attachments
|
|
100
|
+
* - `attachments:write` - Access and update attachments
|
|
101
|
+
*
|
|
102
|
+
* **Notification Scopes:**
|
|
103
|
+
* - `notifications:read` - Read user's notifications settings
|
|
104
|
+
* - `notifications:write` - Read and update user's notifications settings
|
|
105
|
+
*/
|
|
106
|
+
export var TWIST_SCOPES = [
|
|
107
|
+
'user:read',
|
|
108
|
+
'user:write',
|
|
109
|
+
'workspaces:read',
|
|
110
|
+
'workspaces:write',
|
|
111
|
+
'channels:read',
|
|
112
|
+
'channels:write',
|
|
113
|
+
'channels:remove',
|
|
114
|
+
'threads:read',
|
|
115
|
+
'threads:write',
|
|
116
|
+
'threads:remove',
|
|
117
|
+
'comments:read',
|
|
118
|
+
'comments:write',
|
|
119
|
+
'comments:remove',
|
|
120
|
+
'groups:read',
|
|
121
|
+
'groups:write',
|
|
122
|
+
'groups:remove',
|
|
123
|
+
'messages:read',
|
|
124
|
+
'messages:write',
|
|
125
|
+
'messages:remove',
|
|
126
|
+
'reactions:read',
|
|
127
|
+
'reactions:write',
|
|
128
|
+
'reactions:remove',
|
|
129
|
+
'search:read',
|
|
130
|
+
'attachments:read',
|
|
131
|
+
'attachments:write',
|
|
132
|
+
'notifications:read',
|
|
133
|
+
'notifications:write',
|
|
134
|
+
];
|
|
51
135
|
export function getAuthStateParameter() {
|
|
52
136
|
return uuid();
|
|
53
137
|
}
|
|
@@ -60,7 +60,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
60
60
|
};
|
|
61
61
|
import { z } from 'zod';
|
|
62
62
|
import { BaseClient } from './clients/base-client.js';
|
|
63
|
-
import { fetchWithRetry } from './
|
|
63
|
+
import { fetchWithRetry } from './transport/fetch-with-retry.js';
|
|
64
64
|
import { camelCaseKeys, snakeCaseKeys } from './utils/case-conversion.js';
|
|
65
65
|
import { transformTimestamps } from './utils/timestamp-conversion.js';
|
|
66
66
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getTwistBaseUri } from '../consts/endpoints.js';
|
|
2
|
+
import { DEFAULT_API_VERSION } from '../types/api-version.js';
|
|
2
3
|
/**
|
|
3
4
|
* Base client class that provides centralized URL management and configuration
|
|
4
5
|
* for all Twist API clients. Fixes the trailing slash bug and eliminates code duplication.
|
|
@@ -7,7 +8,7 @@ var BaseClient = /** @class */ (function () {
|
|
|
7
8
|
function BaseClient(config) {
|
|
8
9
|
this.apiToken = config.apiToken;
|
|
9
10
|
this.baseUrl = config.baseUrl;
|
|
10
|
-
this.defaultVersion = config.version ||
|
|
11
|
+
this.defaultVersion = config.version || DEFAULT_API_VERSION;
|
|
11
12
|
this.customFetch = config.customFetch;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
@@ -15,7 +15,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
15
15
|
})();
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { ENDPOINT_CHANNELS } from '../consts/endpoints.js';
|
|
18
|
-
import { request } from '../
|
|
18
|
+
import { request } from '../transport/http-client.js';
|
|
19
19
|
import { ChannelSchema } 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_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
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_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
|
/**
|
|
@@ -15,7 +15,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
15
15
|
})();
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { ENDPOINT_THREADS } from '../consts/endpoints.js';
|
|
18
|
-
import { request } from '../
|
|
18
|
+
import { request } from '../transport/http-client.js';
|
|
19
19
|
import { ThreadSchema, UnreadThreadSchema } 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_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
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { DEFAULT_API_VERSION } from '../types/api-version.js';
|
|
1
2
|
var BASE_URI = 'https://api.twist.com';
|
|
2
|
-
export var API_VERSION =
|
|
3
|
+
export var API_VERSION = DEFAULT_API_VERSION;
|
|
3
4
|
/**
|
|
4
5
|
* @deprecated Use getTwistBaseUri() instead. This constant is kept for backward compatibility.
|
|
5
6
|
*/
|
|
@@ -12,7 +13,7 @@ export var API_BASE_URI = "/api/".concat(API_VERSION, "/");
|
|
|
12
13
|
* @returns Complete base URI with trailing slash (e.g., 'https://api.twist.com/api/v3/')
|
|
13
14
|
*/
|
|
14
15
|
export function getTwistBaseUri(version, domainBase) {
|
|
15
|
-
if (version === void 0) { version =
|
|
16
|
+
if (version === void 0) { version = DEFAULT_API_VERSION; }
|
|
16
17
|
if (domainBase === void 0) { domainBase = BASE_URI; }
|
|
17
18
|
return new URL("/api/".concat(version, "/"), domainBase).toString();
|
|
18
19
|
}
|
|
@@ -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
|
}
|