@planqk/planqk-service-sdk 1.9.1 → 2.1.1

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.
Files changed (221) hide show
  1. package/.devcontainer/devcontainer.json +32 -0
  2. package/.devcontainer/post-create.sh +7 -0
  3. package/.env.template +4 -0
  4. package/.gitlab-ci.yml +103 -0
  5. package/.python-version +1 -0
  6. package/.releaserc.json +45 -0
  7. package/LICENSE +201 -0
  8. package/README-node.md +41 -0
  9. package/README-python.md +52 -0
  10. package/README.md +42 -21
  11. package/dist/auth.js +12 -19
  12. package/dist/client.d.ts +2 -12
  13. package/dist/client.js +5 -76
  14. package/dist/sdk/Client.d.ts +4 -3
  15. package/dist/sdk/Client.js +4 -8
  16. package/dist/sdk/api/errors/BadRequestError.d.ts +1 -1
  17. package/dist/sdk/api/errors/BadRequestError.js +18 -8
  18. package/dist/sdk/api/errors/ForbiddenError.d.ts +1 -1
  19. package/dist/sdk/api/errors/ForbiddenError.js +18 -8
  20. package/dist/sdk/api/errors/InternalServerError.d.ts +1 -1
  21. package/dist/sdk/api/errors/InternalServerError.js +18 -8
  22. package/dist/sdk/api/errors/NotFoundError.d.ts +1 -1
  23. package/dist/sdk/api/errors/NotFoundError.js +18 -8
  24. package/dist/sdk/api/errors/UnauthorizedError.d.ts +1 -1
  25. package/dist/sdk/api/errors/UnauthorizedError.js +18 -8
  26. package/dist/sdk/api/resources/index.d.ts +0 -3
  27. package/dist/sdk/api/resources/index.js +18 -11
  28. package/dist/sdk/api/resources/serviceApi/client/Client.d.ts +65 -12
  29. package/dist/sdk/api/resources/serviceApi/client/Client.js +405 -261
  30. package/dist/sdk/api/resources/serviceApi/client/index.d.ts +1 -1
  31. package/dist/sdk/api/resources/serviceApi/client/index.js +0 -15
  32. package/dist/sdk/api/resources/serviceApi/types/GetResultResponse.d.ts +4 -1
  33. package/dist/sdk/api/resources/serviceApi/types/{GetInterimResultsResponse.d.ts → GetResultResponseEmbedded.d.ts} +3 -1
  34. package/dist/sdk/api/resources/serviceApi/types/GetResultResponseLinks.d.ts +7 -0
  35. package/dist/sdk/api/resources/{statusApi → serviceApi}/types/HealthCheckResponse.d.ts +1 -0
  36. package/dist/sdk/api/resources/serviceApi/types/index.d.ts +3 -1
  37. package/dist/sdk/api/resources/serviceApi/types/index.js +3 -1
  38. package/dist/sdk/api/types/HalLink.d.ts +21 -0
  39. package/dist/sdk/api/types/InputData.d.ts +1 -1
  40. package/dist/sdk/api/types/{InputRef.d.ts → InputDataRef.d.ts} +1 -1
  41. package/dist/sdk/api/types/InputParams.d.ts +1 -1
  42. package/dist/sdk/api/types/{Job.d.ts → ServiceExecution.d.ts} +2 -2
  43. package/dist/sdk/api/types/{JobStatus.d.ts → ServiceExecutionStatus.d.ts} +2 -2
  44. package/dist/sdk/api/types/{JobStatus.js → ServiceExecutionStatus.js} +2 -2
  45. package/dist/sdk/api/types/index.d.ts +4 -8
  46. package/dist/sdk/api/types/index.js +4 -8
  47. package/dist/sdk/core/fetcher/APIResponse.d.ts +1 -0
  48. package/dist/sdk/core/fetcher/Fetcher.d.ts +6 -5
  49. package/dist/sdk/core/fetcher/Fetcher.js +68 -112
  50. package/dist/sdk/core/fetcher/Supplier.js +2 -11
  51. package/dist/sdk/core/fetcher/createRequestUrl.d.ts +1 -0
  52. package/dist/sdk/core/fetcher/createRequestUrl.js +12 -0
  53. package/dist/sdk/core/fetcher/getFetchFn.d.ts +4 -0
  54. package/dist/sdk/core/fetcher/getFetchFn.js +57 -0
  55. package/dist/sdk/core/fetcher/getHeader.d.ts +1 -0
  56. package/dist/sdk/core/fetcher/getHeader.js +11 -0
  57. package/dist/sdk/core/fetcher/getRequestBody.d.ts +7 -0
  58. package/dist/sdk/core/fetcher/getRequestBody.js +11 -0
  59. package/dist/sdk/core/fetcher/getResponseBody.d.ts +1 -0
  60. package/dist/sdk/core/fetcher/getResponseBody.js +40 -0
  61. package/dist/sdk/core/fetcher/index.d.ts +1 -0
  62. package/dist/sdk/core/fetcher/index.js +3 -1
  63. package/dist/sdk/core/fetcher/makeRequest.d.ts +1 -0
  64. package/dist/sdk/core/fetcher/makeRequest.js +33 -0
  65. package/dist/sdk/core/fetcher/requestWithRetries.d.ts +1 -0
  66. package/dist/sdk/core/fetcher/requestWithRetries.js +20 -0
  67. package/dist/sdk/core/fetcher/signals.d.ts +11 -0
  68. package/dist/sdk/core/fetcher/signals.js +36 -0
  69. package/dist/sdk/core/fetcher/stream-wrappers/Node18UniversalStreamWrapper.d.ts +30 -0
  70. package/dist/sdk/core/fetcher/stream-wrappers/Node18UniversalStreamWrapper.js +232 -0
  71. package/dist/sdk/core/fetcher/stream-wrappers/NodePre18StreamWrapper.d.ts +21 -0
  72. package/dist/sdk/core/fetcher/stream-wrappers/NodePre18StreamWrapper.js +91 -0
  73. package/dist/sdk/core/fetcher/stream-wrappers/UndiciStreamWrapper.d.ts +31 -0
  74. package/dist/sdk/core/fetcher/stream-wrappers/UndiciStreamWrapper.js +214 -0
  75. package/dist/sdk/core/fetcher/stream-wrappers/chooseStreamWrapper.d.ts +18 -0
  76. package/dist/sdk/core/fetcher/stream-wrappers/chooseStreamWrapper.js +48 -0
  77. package/dist/sdk/core/index.d.ts +1 -0
  78. package/dist/sdk/core/index.js +1 -0
  79. package/dist/sdk/core/runtime/index.d.ts +1 -0
  80. package/dist/sdk/core/runtime/index.js +5 -0
  81. package/dist/sdk/core/runtime/runtime.d.ts +9 -0
  82. package/dist/sdk/core/runtime/runtime.js +92 -0
  83. package/dist/sdk/errors/PlanqkServiceApiError.js +2 -0
  84. package/dist/sdk/index.js +17 -7
  85. package/eslint.config.mjs +11 -0
  86. package/fern/fern.config.json +4 -0
  87. package/fern/generators.yml +25 -0
  88. package/fern/openapi/openapi.yml +342 -0
  89. package/notebooks/python-sdk.ipynb +280 -0
  90. package/package.json +27 -28
  91. package/planqk/__init__.py +0 -0
  92. package/planqk/service/__init__.py +1 -0
  93. package/planqk/service/_version.py +1 -0
  94. package/planqk/service/auth.py +30 -0
  95. package/planqk/service/client.py +151 -0
  96. package/planqk/service/sdk/__init__.py +48 -0
  97. package/planqk/service/sdk/client.py +152 -0
  98. package/planqk/service/sdk/core/__init__.py +47 -0
  99. package/planqk/service/sdk/core/api_error.py +17 -0
  100. package/planqk/service/sdk/core/client_wrapper.py +74 -0
  101. package/planqk/service/sdk/core/datetime_utils.py +30 -0
  102. package/planqk/service/sdk/core/file.py +70 -0
  103. package/planqk/service/sdk/core/http_client.py +575 -0
  104. package/planqk/service/sdk/core/jsonable_encoder.py +103 -0
  105. package/planqk/service/sdk/core/pydantic_utilities.py +323 -0
  106. package/planqk/service/sdk/core/query_encoder.py +60 -0
  107. package/planqk/service/sdk/core/remove_none_from_dict.py +11 -0
  108. package/planqk/service/sdk/core/request_options.py +35 -0
  109. package/planqk/service/sdk/core/serialization.py +276 -0
  110. package/planqk/service/sdk/environment.py +7 -0
  111. package/planqk/service/sdk/errors/__init__.py +15 -0
  112. package/planqk/service/sdk/errors/bad_request_error.py +9 -0
  113. package/planqk/service/sdk/errors/forbidden_error.py +9 -0
  114. package/planqk/service/sdk/errors/internal_server_error.py +9 -0
  115. package/planqk/service/sdk/errors/not_found_error.py +9 -0
  116. package/planqk/service/sdk/errors/unauthorized_error.py +9 -0
  117. package/planqk/service/sdk/service_api/__init__.py +15 -0
  118. package/planqk/service/sdk/service_api/client.py +1257 -0
  119. package/planqk/service/sdk/service_api/types/__init__.py +13 -0
  120. package/planqk/service/sdk/service_api/types/get_result_response.py +30 -0
  121. package/planqk/service/sdk/service_api/types/get_result_response_embedded.py +22 -0
  122. package/planqk/service/sdk/service_api/types/get_result_response_links.py +22 -0
  123. package/planqk/service/sdk/service_api/types/health_check_response.py +24 -0
  124. package/planqk/service/sdk/types/__init__.py +17 -0
  125. package/planqk/service/sdk/types/hal_link.py +59 -0
  126. package/planqk/service/sdk/types/input_data.py +5 -0
  127. package/planqk/service/sdk/types/input_data_ref.py +27 -0
  128. package/planqk/service/sdk/types/input_params.py +5 -0
  129. package/planqk/service/sdk/types/service_execution.py +34 -0
  130. package/planqk/service/sdk/types/service_execution_status.py +8 -0
  131. package/pyproject.toml +51 -0
  132. package/scripts/update-version.sh +6 -0
  133. package/src/client.ts +4 -78
  134. package/src/index.test.ts +43 -0
  135. package/src/sdk/Client.ts +4 -7
  136. package/src/sdk/api/errors/BadRequestError.ts +1 -1
  137. package/src/sdk/api/errors/ForbiddenError.ts +1 -1
  138. package/src/sdk/api/errors/InternalServerError.ts +1 -1
  139. package/src/sdk/api/errors/NotFoundError.ts +1 -1
  140. package/src/sdk/api/errors/UnauthorizedError.ts +1 -1
  141. package/src/sdk/api/resources/index.ts +0 -3
  142. package/src/sdk/api/resources/serviceApi/client/Client.ts +205 -32
  143. package/src/sdk/api/resources/serviceApi/client/index.ts +1 -1
  144. package/src/sdk/api/resources/serviceApi/types/GetResultResponse.ts +4 -5
  145. package/src/sdk/api/resources/serviceApi/types/GetResultResponseEmbedded.ts +9 -0
  146. package/src/sdk/api/resources/serviceApi/types/GetResultResponseLinks.ts +9 -0
  147. package/src/sdk/api/resources/{statusApi → serviceApi}/types/HealthCheckResponse.ts +1 -0
  148. package/src/sdk/api/resources/serviceApi/types/index.ts +3 -1
  149. package/src/sdk/api/types/HalLink.ts +22 -0
  150. package/src/sdk/api/types/InputData.ts +1 -1
  151. package/src/sdk/api/types/{InputRef.ts → InputDataRef.ts} +1 -1
  152. package/src/sdk/api/types/InputParams.ts +1 -1
  153. package/src/sdk/api/types/{Job.ts → ServiceExecution.ts} +2 -2
  154. package/src/sdk/api/types/{JobStatus.ts → ServiceExecutionStatus.ts} +2 -2
  155. package/src/sdk/api/types/index.ts +4 -8
  156. package/src/sdk/core/fetcher/APIResponse.ts +1 -0
  157. package/src/sdk/core/fetcher/Fetcher.ts +55 -72
  158. package/src/sdk/core/fetcher/createRequestUrl.ts +10 -0
  159. package/src/sdk/core/fetcher/getFetchFn.ts +25 -0
  160. package/src/sdk/core/fetcher/getHeader.ts +8 -0
  161. package/src/sdk/core/fetcher/getRequestBody.ts +14 -0
  162. package/src/sdk/core/fetcher/getResponseBody.ts +32 -0
  163. package/src/sdk/core/fetcher/index.ts +1 -0
  164. package/src/sdk/core/fetcher/makeRequest.ts +44 -0
  165. package/src/sdk/core/fetcher/requestWithRetries.ts +21 -0
  166. package/src/sdk/core/fetcher/signals.ts +38 -0
  167. package/src/sdk/core/fetcher/stream-wrappers/Node18UniversalStreamWrapper.ts +252 -0
  168. package/src/sdk/core/fetcher/stream-wrappers/NodePre18StreamWrapper.ts +106 -0
  169. package/src/sdk/core/fetcher/stream-wrappers/UndiciStreamWrapper.ts +239 -0
  170. package/src/sdk/core/fetcher/stream-wrappers/chooseStreamWrapper.ts +33 -0
  171. package/src/sdk/core/index.ts +1 -0
  172. package/src/sdk/core/runtime/index.ts +1 -0
  173. package/src/sdk/core/runtime/runtime.ts +126 -0
  174. package/tsconfig.json +15 -107
  175. package/uv.lock +1109 -0
  176. package/.eslintignore +0 -3
  177. package/.eslintrc +0 -7
  178. package/dist/sdk/api/resources/serviceApi/client/requests/GetInterimResultsRequest.d.ts +0 -9
  179. package/dist/sdk/api/resources/serviceApi/client/requests/StartExecutionRequest.d.ts +0 -13
  180. package/dist/sdk/api/resources/serviceApi/client/requests/index.d.ts +0 -2
  181. package/dist/sdk/api/resources/serviceApi/client/requests/index.js +0 -2
  182. package/dist/sdk/api/resources/statusApi/client/Client.d.ts +0 -28
  183. package/dist/sdk/api/resources/statusApi/client/Client.js +0 -97
  184. package/dist/sdk/api/resources/statusApi/client/index.d.ts +0 -1
  185. package/dist/sdk/api/resources/statusApi/client/index.js +0 -2
  186. package/dist/sdk/api/resources/statusApi/index.d.ts +0 -2
  187. package/dist/sdk/api/resources/statusApi/index.js +0 -18
  188. package/dist/sdk/api/resources/statusApi/types/index.d.ts +0 -1
  189. package/dist/sdk/api/resources/statusApi/types/index.js +0 -17
  190. package/dist/sdk/api/types/ArrayResponse.d.ts +0 -4
  191. package/dist/sdk/api/types/InterimResultResponse.d.ts +0 -4
  192. package/dist/sdk/api/types/InterimResultResponse.js +0 -5
  193. package/dist/sdk/api/types/Job.js +0 -5
  194. package/dist/sdk/api/types/NumberResponse.d.ts +0 -4
  195. package/dist/sdk/api/types/NumberResponse.js +0 -5
  196. package/dist/sdk/api/types/ObjectResponse.d.ts +0 -4
  197. package/dist/sdk/api/types/ObjectResponse.js +0 -5
  198. package/dist/sdk/api/types/StringResponse.d.ts +0 -4
  199. package/dist/sdk/api/types/StringResponse.js +0 -5
  200. package/jest.config.js +0 -12
  201. package/src/sdk/api/resources/serviceApi/client/requests/GetInterimResultsRequest.ts +0 -10
  202. package/src/sdk/api/resources/serviceApi/client/requests/StartExecutionRequest.ts +0 -15
  203. package/src/sdk/api/resources/serviceApi/client/requests/index.ts +0 -2
  204. package/src/sdk/api/resources/serviceApi/types/GetInterimResultsResponse.ts +0 -9
  205. package/src/sdk/api/resources/statusApi/client/Client.ts +0 -75
  206. package/src/sdk/api/resources/statusApi/client/index.ts +0 -1
  207. package/src/sdk/api/resources/statusApi/index.ts +0 -2
  208. package/src/sdk/api/resources/statusApi/types/index.ts +0 -1
  209. package/src/sdk/api/types/ArrayResponse.ts +0 -5
  210. package/src/sdk/api/types/InterimResultResponse.ts +0 -5
  211. package/src/sdk/api/types/NumberResponse.ts +0 -5
  212. package/src/sdk/api/types/ObjectResponse.ts +0 -5
  213. package/src/sdk/api/types/StringResponse.ts +0 -5
  214. package/tests/fixtures/complex-input.ts +0 -477
  215. package/tests/integration.test.ts +0 -92
  216. /package/dist/sdk/api/resources/serviceApi/{client/requests/GetInterimResultsRequest.js → types/GetResultResponseEmbedded.js} +0 -0
  217. /package/dist/sdk/api/resources/serviceApi/{client/requests/StartExecutionRequest.js → types/GetResultResponseLinks.js} +0 -0
  218. /package/dist/sdk/api/resources/{statusApi → serviceApi}/types/HealthCheckResponse.js +0 -0
  219. /package/dist/sdk/api/{resources/serviceApi/types/GetInterimResultsResponse.js → types/HalLink.js} +0 -0
  220. /package/dist/sdk/api/types/{ArrayResponse.js → InputDataRef.js} +0 -0
  221. /package/dist/sdk/api/types/{InputRef.js → ServiceExecution.js} +0 -0
@@ -1,6 +1,10 @@
1
- import axios, { AxiosAdapter, AxiosError, AxiosResponse } from "axios";
2
- import qs from "qs";
3
1
  import { APIResponse } from "./APIResponse";
2
+ import { createRequestUrl } from "./createRequestUrl";
3
+ import { getFetchFn } from "./getFetchFn";
4
+ import { getRequestBody } from "./getRequestBody";
5
+ import { getResponseBody } from "./getResponseBody";
6
+ import { makeRequest } from "./makeRequest";
7
+ import { requestWithRetries } from "./requestWithRetries";
4
8
 
5
9
  export type FetchFunction = <R = unknown>(args: Fetcher.Args) => Promise<APIResponse<R, Fetcher.Error>>;
6
10
 
@@ -10,14 +14,15 @@ export declare namespace Fetcher {
10
14
  method: string;
11
15
  contentType?: string;
12
16
  headers?: Record<string, string | undefined>;
13
- queryParameters?: Record<string, string | string[]>;
17
+ queryParameters?: Record<string, string | string[] | object | object[]>;
14
18
  body?: unknown;
15
19
  timeoutMs?: number;
16
20
  maxRetries?: number;
17
21
  withCredentials?: boolean;
18
- responseType?: "json" | "blob";
19
- adapter?: AxiosAdapter;
20
- onUploadProgress?: (event: ProgressEvent) => void;
22
+ abortSignal?: AbortSignal;
23
+ requestType?: "json" | "file" | "bytes";
24
+ responseType?: "json" | "blob" | "sse" | "streaming" | "text";
25
+ duplex?: "half";
21
26
  }
22
27
 
23
28
  export type Error = FailedStatusCodeError | NonJsonError | TimeoutError | UnknownError;
@@ -44,11 +49,7 @@ export declare namespace Fetcher {
44
49
  }
45
50
  }
46
51
 
47
- const INITIAL_RETRY_DELAY = 1;
48
- const MAX_RETRY_DELAY = 60;
49
- const DEFAULT_MAX_RETRIES = 2;
50
-
51
- async function fetcherImpl<R = unknown>(args: Fetcher.Args): Promise<APIResponse<R, Fetcher.Error>> {
52
+ export async function fetcherImpl<R = unknown>(args: Fetcher.Args): Promise<APIResponse<R, Fetcher.Error>> {
52
53
  const headers: Record<string, string> = {};
53
54
  if (args.body !== undefined && args.contentType != null) {
54
55
  headers["Content-Type"] = args.contentType;
@@ -62,70 +63,36 @@ async function fetcherImpl<R = unknown>(args: Fetcher.Args): Promise<APIResponse
62
63
  }
63
64
  }
64
65
 
65
- const makeRequest = async (): Promise<AxiosResponse> =>
66
- await axios({
67
- url: args.url,
68
- params: args.queryParameters,
69
- paramsSerializer: (params) => {
70
- return qs.stringify(params, { arrayFormat: "repeat" });
71
- },
72
- method: args.method,
73
- headers,
74
- data: args.body,
75
- validateStatus: () => true,
76
- transformResponse: (response) => response,
77
- timeout: args.timeoutMs,
78
- transitional: {
79
- clarifyTimeoutError: true,
80
- },
81
- withCredentials: args.withCredentials,
82
- adapter: args.adapter,
83
- onUploadProgress: args.onUploadProgress,
84
- maxBodyLength: Infinity,
85
- maxContentLength: Infinity,
86
- responseType: args.responseType ?? "json",
87
- });
66
+ const url = createRequestUrl(args.url, args.queryParameters);
67
+ let requestBody: BodyInit | undefined = await getRequestBody({
68
+ body: args.body,
69
+ type: args.requestType === "json" ? "json" : "other",
70
+ });
71
+ const fetchFn = await getFetchFn();
88
72
 
89
73
  try {
90
- let response = await makeRequest();
91
-
92
- for (let i = 0; i < (args.maxRetries ?? DEFAULT_MAX_RETRIES); ++i) {
93
- if (
94
- response.status === 408 ||
95
- response.status === 409 ||
96
- response.status === 429 ||
97
- response.status >= 500
98
- ) {
99
- const delay = Math.min(INITIAL_RETRY_DELAY * Math.pow(i, 2), MAX_RETRY_DELAY);
100
- await new Promise((resolve) => setTimeout(resolve, delay));
101
- response = await makeRequest();
102
- } else {
103
- break;
104
- }
105
- }
106
-
107
- let body: unknown;
108
- if (args.responseType === "blob") {
109
- body = response.data;
110
- } else if (response.data != null && response.data.length > 0) {
111
- try {
112
- body = JSON.parse(response.data) ?? undefined;
113
- } catch {
114
- return {
115
- ok: false,
116
- error: {
117
- reason: "non-json",
118
- statusCode: response.status,
119
- rawBody: response.data,
120
- },
121
- };
122
- }
123
- }
74
+ const response = await requestWithRetries(
75
+ async () =>
76
+ makeRequest(
77
+ fetchFn,
78
+ url,
79
+ args.method,
80
+ headers,
81
+ requestBody,
82
+ args.timeoutMs,
83
+ args.abortSignal,
84
+ args.withCredentials,
85
+ args.duplex
86
+ ),
87
+ args.maxRetries
88
+ );
89
+ let responseBody = await getResponseBody(response, args.responseType);
124
90
 
125
91
  if (response.status >= 200 && response.status < 400) {
126
92
  return {
127
93
  ok: true,
128
- body: body as R,
94
+ body: responseBody as R,
95
+ headers: response.headers,
129
96
  };
130
97
  } else {
131
98
  return {
@@ -133,25 +100,41 @@ async function fetcherImpl<R = unknown>(args: Fetcher.Args): Promise<APIResponse
133
100
  error: {
134
101
  reason: "status-code",
135
102
  statusCode: response.status,
136
- body,
103
+ body: responseBody,
137
104
  },
138
105
  };
139
106
  }
140
107
  } catch (error) {
141
- if ((error as AxiosError).code === "ETIMEDOUT") {
108
+ if (args.abortSignal != null && args.abortSignal.aborted) {
109
+ return {
110
+ ok: false,
111
+ error: {
112
+ reason: "unknown",
113
+ errorMessage: "The user aborted a request",
114
+ },
115
+ };
116
+ } else if (error instanceof Error && error.name === "AbortError") {
142
117
  return {
143
118
  ok: false,
144
119
  error: {
145
120
  reason: "timeout",
146
121
  },
147
122
  };
123
+ } else if (error instanceof Error) {
124
+ return {
125
+ ok: false,
126
+ error: {
127
+ reason: "unknown",
128
+ errorMessage: error.message,
129
+ },
130
+ };
148
131
  }
149
132
 
150
133
  return {
151
134
  ok: false,
152
135
  error: {
153
136
  reason: "unknown",
154
- errorMessage: (error as AxiosError).message,
137
+ errorMessage: JSON.stringify(error),
155
138
  },
156
139
  };
157
140
  }
@@ -0,0 +1,10 @@
1
+ import qs from "qs";
2
+
3
+ export function createRequestUrl(
4
+ baseUrl: string,
5
+ queryParameters?: Record<string, string | string[] | object | object[]>
6
+ ): string {
7
+ return Object.keys(queryParameters ?? {}).length > 0
8
+ ? `${baseUrl}?${qs.stringify(queryParameters, { arrayFormat: "repeat" })}`
9
+ : baseUrl;
10
+ }
@@ -0,0 +1,25 @@
1
+ import { RUNTIME } from "../runtime";
2
+
3
+ /**
4
+ * Returns a fetch function based on the runtime
5
+ */
6
+ export async function getFetchFn(): Promise<any> {
7
+ // In Node.js 18+ environments, use native fetch
8
+ if (RUNTIME.type === "node" && RUNTIME.parsedVersion != null && RUNTIME.parsedVersion >= 18) {
9
+ return fetch;
10
+ }
11
+
12
+ // In Node.js 18 or lower environments, the SDK always uses`node-fetch`.
13
+ if (RUNTIME.type === "node") {
14
+ return (await import("node-fetch")).default as any;
15
+ }
16
+
17
+ // Otherwise the SDK uses global fetch if available,
18
+ // and falls back to node-fetch.
19
+ if (typeof fetch == "function") {
20
+ return fetch;
21
+ }
22
+
23
+ // Defaults to node `node-fetch` if global fetch isn't available
24
+ return (await import("node-fetch")).default as any;
25
+ }
@@ -0,0 +1,8 @@
1
+ export function getHeader(headers: Record<string, any>, header: string): string | undefined {
2
+ for (const [headerKey, headerValue] of Object.entries(headers)) {
3
+ if (headerKey.toLowerCase() === header.toLowerCase()) {
4
+ return headerValue;
5
+ }
6
+ }
7
+ return undefined;
8
+ }
@@ -0,0 +1,14 @@
1
+ export declare namespace GetRequestBody {
2
+ interface Args {
3
+ body: unknown;
4
+ type: "json" | "file" | "bytes" | "other";
5
+ }
6
+ }
7
+
8
+ export async function getRequestBody({ body, type }: GetRequestBody.Args): Promise<BodyInit | undefined> {
9
+ if (type.includes("json")) {
10
+ return JSON.stringify(body);
11
+ } else {
12
+ return body as BodyInit;
13
+ }
14
+ }
@@ -0,0 +1,32 @@
1
+ import { chooseStreamWrapper } from "./stream-wrappers/chooseStreamWrapper";
2
+
3
+ export async function getResponseBody(response: Response, responseType?: string): Promise<unknown> {
4
+ if (response.body != null && responseType === "blob") {
5
+ return await response.blob();
6
+ } else if (response.body != null && responseType === "sse") {
7
+ return response.body;
8
+ } else if (response.body != null && responseType === "streaming") {
9
+ return chooseStreamWrapper(response.body);
10
+ } else if (response.body != null && responseType === "text") {
11
+ return await response.text();
12
+ } else {
13
+ const text = await response.text();
14
+ if (text.length > 0) {
15
+ try {
16
+ let responseBody = JSON.parse(text);
17
+ return responseBody;
18
+ } catch (err) {
19
+ return {
20
+ ok: false,
21
+ error: {
22
+ reason: "non-json",
23
+ statusCode: response.status,
24
+ rawBody: text,
25
+ },
26
+ };
27
+ }
28
+ } else {
29
+ return undefined;
30
+ }
31
+ }
32
+ }
@@ -1,4 +1,5 @@
1
1
  export type { APIResponse } from "./APIResponse";
2
2
  export { fetcher } from "./Fetcher";
3
3
  export type { Fetcher, FetchFunction } from "./Fetcher";
4
+ export { getHeader } from "./getHeader";
4
5
  export { Supplier } from "./Supplier";
@@ -0,0 +1,44 @@
1
+ import { anySignal, getTimeoutSignal } from "./signals";
2
+
3
+ export const makeRequest = async (
4
+ fetchFn: (url: string, init: RequestInit) => Promise<Response>,
5
+ url: string,
6
+ method: string,
7
+ headers: Record<string, string>,
8
+ requestBody: BodyInit | undefined,
9
+ timeoutMs?: number,
10
+ abortSignal?: AbortSignal,
11
+ withCredentials?: boolean,
12
+ duplex?: "half"
13
+ ): Promise<Response> => {
14
+ const signals: AbortSignal[] = [];
15
+
16
+ // Add timeout signal
17
+ let timeoutAbortId: NodeJS.Timeout | undefined = undefined;
18
+ if (timeoutMs != null) {
19
+ const { signal, abortId } = getTimeoutSignal(timeoutMs);
20
+ timeoutAbortId = abortId;
21
+ signals.push(signal);
22
+ }
23
+
24
+ // Add arbitrary signal
25
+ if (abortSignal != null) {
26
+ signals.push(abortSignal);
27
+ }
28
+ let newSignals = anySignal(signals);
29
+ const response = await fetchFn(url, {
30
+ method: method,
31
+ headers,
32
+ body: requestBody,
33
+ signal: newSignals,
34
+ credentials: withCredentials ? "include" : undefined,
35
+ // @ts-ignore
36
+ duplex,
37
+ });
38
+
39
+ if (timeoutAbortId != null) {
40
+ clearTimeout(timeoutAbortId);
41
+ }
42
+
43
+ return response;
44
+ };
@@ -0,0 +1,21 @@
1
+ const INITIAL_RETRY_DELAY = 1;
2
+ const MAX_RETRY_DELAY = 60;
3
+ const DEFAULT_MAX_RETRIES = 2;
4
+
5
+ export async function requestWithRetries(
6
+ requestFn: () => Promise<Response>,
7
+ maxRetries: number = DEFAULT_MAX_RETRIES
8
+ ): Promise<Response> {
9
+ let response: Response = await requestFn();
10
+
11
+ for (let i = 0; i < maxRetries; ++i) {
12
+ if ([408, 409, 429].includes(response.status) || response.status >= 500) {
13
+ const delay = Math.min(INITIAL_RETRY_DELAY * Math.pow(2, i), MAX_RETRY_DELAY);
14
+ await new Promise((resolve) => setTimeout(resolve, delay));
15
+ response = await requestFn();
16
+ } else {
17
+ break;
18
+ }
19
+ }
20
+ return response!;
21
+ }
@@ -0,0 +1,38 @@
1
+ const TIMEOUT = "timeout";
2
+
3
+ export function getTimeoutSignal(timeoutMs: number): { signal: AbortSignal; abortId: NodeJS.Timeout } {
4
+ const controller = new AbortController();
5
+ const abortId = setTimeout(() => controller.abort(TIMEOUT), timeoutMs);
6
+ return { signal: controller.signal, abortId };
7
+ }
8
+
9
+ /**
10
+ * Returns an abort signal that is getting aborted when
11
+ * at least one of the specified abort signals is aborted.
12
+ *
13
+ * Requires at least node.js 18.
14
+ */
15
+ export function anySignal(...args: AbortSignal[] | [AbortSignal[]]): AbortSignal {
16
+ // Allowing signals to be passed either as array
17
+ // of signals or as multiple arguments.
18
+ const signals = <AbortSignal[]>(args.length === 1 && Array.isArray(args[0]) ? args[0] : args);
19
+
20
+ const controller = new AbortController();
21
+
22
+ for (const signal of signals) {
23
+ if (signal.aborted) {
24
+ // Exiting early if one of the signals
25
+ // is already aborted.
26
+ controller.abort((signal as any)?.reason);
27
+ break;
28
+ }
29
+
30
+ // Listening for signals and removing the listeners
31
+ // when at least one symbol is aborted.
32
+ signal.addEventListener("abort", () => controller.abort((signal as any)?.reason), {
33
+ signal: controller.signal,
34
+ });
35
+ }
36
+
37
+ return controller.signal;
38
+ }
@@ -0,0 +1,252 @@
1
+ import type { Writable } from "stream";
2
+ import { EventCallback, StreamWrapper } from "./chooseStreamWrapper";
3
+
4
+ export class Node18UniversalStreamWrapper<ReadFormat extends Uint8Array | Uint16Array | Uint32Array>
5
+ implements
6
+ StreamWrapper<Node18UniversalStreamWrapper<ReadFormat> | Writable | WritableStream<ReadFormat>, ReadFormat>
7
+ {
8
+ private readableStream: ReadableStream<ReadFormat>;
9
+ private reader: ReadableStreamDefaultReader<ReadFormat>;
10
+ private events: Record<string, EventCallback[] | undefined>;
11
+ private paused: boolean;
12
+ private resumeCallback: ((value?: unknown) => void) | null;
13
+ private encoding: string | null;
14
+
15
+ constructor(readableStream: ReadableStream<ReadFormat>) {
16
+ this.readableStream = readableStream;
17
+ this.reader = this.readableStream.getReader();
18
+ this.events = {
19
+ data: [],
20
+ end: [],
21
+ error: [],
22
+ readable: [],
23
+ close: [],
24
+ pause: [],
25
+ resume: [],
26
+ };
27
+ this.paused = false;
28
+ this.resumeCallback = null;
29
+ this.encoding = null;
30
+ }
31
+
32
+ public on(event: string, callback: EventCallback): void {
33
+ this.events[event]?.push(callback);
34
+ }
35
+
36
+ public off(event: string, callback: EventCallback): void {
37
+ this.events[event] = this.events[event]?.filter((cb) => cb !== callback);
38
+ }
39
+
40
+ public pipe(
41
+ dest: Node18UniversalStreamWrapper<ReadFormat> | Writable | WritableStream<ReadFormat>
42
+ ): Node18UniversalStreamWrapper<ReadFormat> | Writable | WritableStream<ReadFormat> {
43
+ this.on("data", async (chunk) => {
44
+ if (dest instanceof Node18UniversalStreamWrapper) {
45
+ dest._write(chunk);
46
+ } else if (dest instanceof WritableStream) {
47
+ const writer = dest.getWriter();
48
+ writer.write(chunk).then(() => writer.releaseLock());
49
+ } else {
50
+ dest.write(chunk);
51
+ }
52
+ });
53
+
54
+ this.on("end", async () => {
55
+ if (dest instanceof Node18UniversalStreamWrapper) {
56
+ dest._end();
57
+ } else if (dest instanceof WritableStream) {
58
+ const writer = dest.getWriter();
59
+ writer.close();
60
+ } else {
61
+ dest.end();
62
+ }
63
+ });
64
+
65
+ this.on("error", async (error) => {
66
+ if (dest instanceof Node18UniversalStreamWrapper) {
67
+ dest._error(error);
68
+ } else if (dest instanceof WritableStream) {
69
+ const writer = dest.getWriter();
70
+ writer.abort(error);
71
+ } else {
72
+ dest.destroy(error);
73
+ }
74
+ });
75
+
76
+ this._startReading();
77
+
78
+ return dest;
79
+ }
80
+
81
+ public pipeTo(
82
+ dest: Node18UniversalStreamWrapper<ReadFormat> | Writable | WritableStream<ReadFormat>
83
+ ): Node18UniversalStreamWrapper<ReadFormat> | Writable | WritableStream<ReadFormat> {
84
+ return this.pipe(dest);
85
+ }
86
+
87
+ public unpipe(dest: Node18UniversalStreamWrapper<ReadFormat> | Writable | WritableStream<ReadFormat>): void {
88
+ this.off("data", async (chunk) => {
89
+ if (dest instanceof Node18UniversalStreamWrapper) {
90
+ dest._write(chunk);
91
+ } else if (dest instanceof WritableStream) {
92
+ const writer = dest.getWriter();
93
+ writer.write(chunk).then(() => writer.releaseLock());
94
+ } else {
95
+ dest.write(chunk);
96
+ }
97
+ });
98
+
99
+ this.off("end", async () => {
100
+ if (dest instanceof Node18UniversalStreamWrapper) {
101
+ dest._end();
102
+ } else if (dest instanceof WritableStream) {
103
+ const writer = dest.getWriter();
104
+ writer.close();
105
+ } else {
106
+ dest.end();
107
+ }
108
+ });
109
+
110
+ this.off("error", async (error) => {
111
+ if (dest instanceof Node18UniversalStreamWrapper) {
112
+ dest._error(error);
113
+ } else if (dest instanceof WritableStream) {
114
+ const writer = dest.getWriter();
115
+ writer.abort(error);
116
+ } else {
117
+ dest.destroy(error);
118
+ }
119
+ });
120
+ }
121
+
122
+ public destroy(error?: Error): void {
123
+ this.reader
124
+ .cancel(error)
125
+ .then(() => {
126
+ this._emit("close");
127
+ })
128
+ .catch((err) => {
129
+ this._emit("error", err);
130
+ });
131
+ }
132
+
133
+ public pause(): void {
134
+ this.paused = true;
135
+ this._emit("pause");
136
+ }
137
+
138
+ public resume(): void {
139
+ if (this.paused) {
140
+ this.paused = false;
141
+ this._emit("resume");
142
+ if (this.resumeCallback) {
143
+ this.resumeCallback();
144
+ this.resumeCallback = null;
145
+ }
146
+ }
147
+ }
148
+
149
+ public get isPaused(): boolean {
150
+ return this.paused;
151
+ }
152
+
153
+ public async read(): Promise<ReadFormat | undefined> {
154
+ if (this.paused) {
155
+ await new Promise((resolve) => {
156
+ this.resumeCallback = resolve;
157
+ });
158
+ }
159
+ const { done, value } = await this.reader.read();
160
+
161
+ if (done) {
162
+ return undefined;
163
+ }
164
+ return value;
165
+ }
166
+
167
+ public setEncoding(encoding: string): void {
168
+ this.encoding = encoding;
169
+ }
170
+
171
+ public async text(): Promise<string> {
172
+ const chunks: ReadFormat[] = [];
173
+
174
+ while (true) {
175
+ const { done, value } = await this.reader.read();
176
+ if (done) break;
177
+ if (value) chunks.push(value);
178
+ }
179
+
180
+ const decoder = new TextDecoder(this.encoding || "utf-8");
181
+ return decoder.decode(await new Blob(chunks).arrayBuffer());
182
+ }
183
+
184
+ public async json<T>(): Promise<T> {
185
+ const text = await this.text();
186
+ return JSON.parse(text);
187
+ }
188
+
189
+ private _write(chunk: ReadFormat): void {
190
+ this._emit("data", chunk);
191
+ }
192
+
193
+ private _end(): void {
194
+ this._emit("end");
195
+ }
196
+
197
+ private _error(error: any): void {
198
+ this._emit("error", error);
199
+ }
200
+
201
+ private _emit(event: string, data?: any): void {
202
+ if (this.events[event]) {
203
+ for (const callback of this.events[event] || []) {
204
+ callback(data);
205
+ }
206
+ }
207
+ }
208
+
209
+ private async _startReading(): Promise<void> {
210
+ try {
211
+ this._emit("readable");
212
+ while (true) {
213
+ if (this.paused) {
214
+ await new Promise((resolve) => {
215
+ this.resumeCallback = resolve;
216
+ });
217
+ }
218
+ const { done, value } = await this.reader.read();
219
+ if (done) {
220
+ this._emit("end");
221
+ this._emit("close");
222
+ break;
223
+ }
224
+ if (value) {
225
+ this._emit("data", value);
226
+ }
227
+ }
228
+ } catch (error) {
229
+ this._emit("error", error);
230
+ }
231
+ }
232
+
233
+ [Symbol.asyncIterator](): AsyncIterableIterator<ReadFormat> {
234
+ return {
235
+ next: async () => {
236
+ if (this.paused) {
237
+ await new Promise((resolve) => {
238
+ this.resumeCallback = resolve;
239
+ });
240
+ }
241
+ const { done, value } = await this.reader.read();
242
+ if (done) {
243
+ return { done: true, value: undefined };
244
+ }
245
+ return { done: false, value };
246
+ },
247
+ [Symbol.asyncIterator]() {
248
+ return this;
249
+ },
250
+ };
251
+ }
252
+ }