Skip to content

Commit 4974572

Browse files
committed
ci: regenerated with OpenAPI Doc 0.1.0, Speakeay CLI 0.18.0
1 parent b3422fa commit 4974572

File tree

12 files changed

+432
-201
lines changed

12 files changed

+432
-201
lines changed

gen.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
management:
22
openapi-checksum: 8e8183d84cace76310a3208e63cd7855
33
openapi-version: 0.1.0
4-
speakeasy-version: 0.17.4
4+
speakeasy-version: 0.18.0
55
telemetryenabled: null
66
typescript:
77
author: Speakeasy
88
packagename: '@speakeasy-api/speakeasy-client-sdk-typescript'
9-
version: 0.7.1
9+
version: 0.8.0

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@speakeasy-api/speakeasy-client-sdk-typescript",
3-
"version": "0.7.1",
3+
"version": "0.8.0",
44
"author": "Speakeasy",
55
"scripts": {
66
"prepare": "tsc --build"

src/internal/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ export * from "./headers";
33
export * from "./pathparams";
44
export * from "./queryparams";
55
export * from "./requestbody";
6+
export * from "./retries";
67
export * from "./security";
78
export * from "./utils";

src/internal/utils/retries.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { AxiosError, AxiosResponse } from "axios";
2+
3+
export class BackoffStrategy {
4+
initialInterval: number;
5+
maxInterval: number;
6+
exponent: number;
7+
maxElapsedTime: number;
8+
9+
constructor(
10+
initialInterval: number,
11+
maxInterval: number,
12+
exponent: number,
13+
maxElapsedTime: number
14+
) {
15+
this.initialInterval = initialInterval;
16+
this.maxInterval = maxInterval;
17+
this.exponent = exponent;
18+
this.maxElapsedTime = maxElapsedTime;
19+
}
20+
}
21+
22+
export class RetryConfig {
23+
strategy: string;
24+
backoff?: BackoffStrategy;
25+
retryConnectionErrors: boolean;
26+
27+
constructor(strategy: string, retryConnectionErrors: boolean = true) {
28+
this.strategy = strategy;
29+
this.retryConnectionErrors = retryConnectionErrors;
30+
}
31+
}
32+
33+
export class Retries {
34+
config: RetryConfig;
35+
statusCodes: string[];
36+
37+
constructor(config: RetryConfig, statusCodes: string[]) {
38+
this.config = config;
39+
this.statusCodes = statusCodes;
40+
}
41+
}
42+
43+
class PermanentError extends Error {
44+
inner: unknown;
45+
46+
constructor(inner: unknown) {
47+
super("Permanent error");
48+
this.inner = inner;
49+
}
50+
}
51+
52+
class TemporaryError extends Error {
53+
res: AxiosResponse<any, any>;
54+
55+
constructor(res: AxiosResponse<any, any>) {
56+
super("Temporary error");
57+
this.res = res;
58+
}
59+
}
60+
61+
export async function Retry(
62+
fn: () => Promise<AxiosResponse<any, any>>,
63+
retries: Retries
64+
): Promise<AxiosResponse<any, any>> {
65+
switch (retries.config.strategy) {
66+
case "backoff":
67+
return retryBackoff(
68+
async () => {
69+
try {
70+
const res = await fn();
71+
if (isRetryableResponse(res, retries.statusCodes)) {
72+
throw new TemporaryError(res);
73+
}
74+
75+
return res;
76+
} catch (err) {
77+
if (err instanceof AxiosError) {
78+
if (err.response) {
79+
if (isRetryableResponse(err.response, retries.statusCodes)) {
80+
throw err;
81+
}
82+
throw new PermanentError(err);
83+
} else if (err.request) {
84+
throw err;
85+
} else {
86+
throw new PermanentError(err);
87+
}
88+
} else if (err instanceof TemporaryError) {
89+
throw err;
90+
}
91+
throw new PermanentError(err);
92+
}
93+
},
94+
retries.config.backoff?.initialInterval ?? 500,
95+
retries.config.backoff?.maxInterval ?? 60000,
96+
retries.config.backoff?.exponent ?? 1.5,
97+
retries.config.backoff?.maxElapsedTime ?? 3600000
98+
);
99+
default:
100+
return await fn();
101+
}
102+
}
103+
104+
function isRetryableResponse(
105+
res: AxiosResponse<any, any>,
106+
statusCodes: string[]
107+
): boolean {
108+
for (const code of statusCodes) {
109+
if (code.toUpperCase().includes("X")) {
110+
const codeRange = parseInt(code[0]);
111+
if (isNaN(codeRange)) {
112+
throw new Error("Invalid status code range");
113+
}
114+
115+
const s = res.status / 100;
116+
117+
if (s >= codeRange && s < codeRange + 1) {
118+
return true;
119+
}
120+
} else if (res.status == parseInt(code)) {
121+
return true;
122+
}
123+
}
124+
125+
return false;
126+
}
127+
128+
async function retryBackoff(
129+
fn: () => Promise<AxiosResponse<any, any>>,
130+
initialInterval: number,
131+
maxInterval: number,
132+
exponent: number,
133+
maxElapsedTime: number
134+
): Promise<AxiosResponse<any, any>> {
135+
const start = Date.now();
136+
let x = 0;
137+
138+
while (true) {
139+
try {
140+
return await fn();
141+
} catch (err) {
142+
if (err instanceof PermanentError) {
143+
throw err.inner;
144+
}
145+
146+
const now = Date.now();
147+
if (now - start > maxElapsedTime) {
148+
if (err instanceof TemporaryError) {
149+
return err.res;
150+
}
151+
152+
throw err;
153+
}
154+
155+
const d = Math.min(
156+
initialInterval * Math.pow(x, exponent) + Math.random() * 1000,
157+
maxInterval
158+
);
159+
160+
await delay(d);
161+
x++;
162+
}
163+
}
164+
}
165+
166+
async function delay(delay: number): Promise<void> {
167+
return new Promise((resolve) => setTimeout(resolve, delay));
168+
}

src/sdk/apiendpoints.ts

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ export class ApiEndpoints {
3737

3838
const client: AxiosInstance = this._securityClient!;
3939

40-
return client
41-
.request({
42-
url: url,
43-
method: "delete",
44-
...config,
45-
}).then((httpRes: AxiosResponse) => {
40+
41+
const r = client.request({
42+
url: url,
43+
method: "delete",
44+
...config,
45+
});
46+
47+
return r.then((httpRes: AxiosResponse) => {
4648
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
4749

4850
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);
@@ -81,12 +83,14 @@ export class ApiEndpoints {
8183

8284
const client: AxiosInstance = this._securityClient!;
8385

84-
return client
85-
.request({
86-
url: url,
87-
method: "get",
88-
...config,
89-
}).then((httpRes: AxiosResponse) => {
86+
87+
const r = client.request({
88+
url: url,
89+
method: "get",
90+
...config,
91+
});
92+
93+
return r.then((httpRes: AxiosResponse) => {
9094
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
9195

9296
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);
@@ -128,12 +132,14 @@ export class ApiEndpoints {
128132

129133
const client: AxiosInstance = this._securityClient!;
130134

131-
return client
132-
.request({
133-
url: url,
134-
method: "get",
135-
...config,
136-
}).then((httpRes: AxiosResponse) => {
135+
136+
const r = client.request({
137+
url: url,
138+
method: "get",
139+
...config,
140+
});
141+
142+
return r.then((httpRes: AxiosResponse) => {
137143
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
138144

139145
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);
@@ -174,12 +180,14 @@ export class ApiEndpoints {
174180

175181
const client: AxiosInstance = this._securityClient!;
176182

177-
return client
178-
.request({
179-
url: url,
180-
method: "get",
181-
...config,
182-
}).then((httpRes: AxiosResponse) => {
183+
184+
const r = client.request({
185+
url: url,
186+
method: "get",
187+
...config,
188+
});
189+
190+
return r.then((httpRes: AxiosResponse) => {
183191
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
184192

185193
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);
@@ -218,12 +226,14 @@ export class ApiEndpoints {
218226

219227
const client: AxiosInstance = this._securityClient!;
220228

221-
return client
222-
.request({
223-
url: url,
224-
method: "get",
225-
...config,
226-
}).then((httpRes: AxiosResponse) => {
229+
230+
const r = client.request({
231+
url: url,
232+
method: "get",
233+
...config,
234+
});
235+
236+
return r.then((httpRes: AxiosResponse) => {
227237
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
228238

229239
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);
@@ -262,12 +272,14 @@ export class ApiEndpoints {
262272

263273
const client: AxiosInstance = this._securityClient!;
264274

265-
return client
266-
.request({
267-
url: url,
268-
method: "get",
269-
...config,
270-
}).then((httpRes: AxiosResponse) => {
275+
276+
const r = client.request({
277+
url: url,
278+
method: "get",
279+
...config,
280+
});
281+
282+
return r.then((httpRes: AxiosResponse) => {
271283
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
272284

273285
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);
@@ -306,12 +318,14 @@ export class ApiEndpoints {
306318

307319
const client: AxiosInstance = this._securityClient!;
308320

309-
return client
310-
.request({
311-
url: url,
312-
method: "get",
313-
...config,
314-
}).then((httpRes: AxiosResponse) => {
321+
322+
const r = client.request({
323+
url: url,
324+
method: "get",
325+
...config,
326+
});
327+
328+
return r.then((httpRes: AxiosResponse) => {
315329
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
316330

317331
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);
@@ -364,14 +378,16 @@ export class ApiEndpoints {
364378

365379
const headers = {...reqBodyHeaders, ...config?.headers};
366380
if (reqBody == null || Object.keys(reqBody).length === 0) throw new Error("request body is required");
367-
return client
368-
.request({
369-
url: url,
370-
method: "put",
371-
headers: headers,
372-
data: reqBody,
373-
...config,
374-
}).then((httpRes: AxiosResponse) => {
381+
382+
const r = client.request({
383+
url: url,
384+
method: "put",
385+
headers: headers,
386+
data: reqBody,
387+
...config,
388+
});
389+
390+
return r.then((httpRes: AxiosResponse) => {
375391
const contentType: string = httpRes?.headers?.["content-type"] ?? "";
376392

377393
if (httpRes?.status == null) throw new Error(`status code not found in response: ${httpRes}`);

0 commit comments

Comments
 (0)