Skip to content

Commit e8bdeb7

Browse files
authored
feat: add types (#661)
Resolves #43 Closes (supersedes) #110 Closes (supersedes) #492
1 parent 96f572f commit e8bdeb7

6 files changed

Lines changed: 98 additions & 35 deletions

File tree

scripts/build.mjs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,6 @@ async function main() {
2525
sourcemap: false,
2626
});
2727

28-
// Remove the types file from the dist-src folder
29-
const typeFiles = await glob([
30-
"./pkg/dist-src/**/types.js.map",
31-
"./pkg/dist-src/**/types.js",
32-
]);
33-
for (const typeFile of typeFiles) {
34-
await rm(typeFile);
35-
}
36-
3728
const entryPoints = ["./pkg/dist-src/index.js"];
3829

3930
await esbuild.build({

src/bottleneck.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/** Minimal typings for "bottleneck/light.js" based on the usage in this library. */
2+
declare module "bottleneck/light.js" {
3+
export type RetryableInfo = { readonly retryCount: number };
4+
5+
export class Bottleneck {
6+
constructor(options?: any);
7+
8+
on(name: "failed", fn: (error: any, info: RetryableInfo) => any): void;
9+
10+
schedule<A extends unknown[], R>(
11+
task: (...args: A) => Promise<R>,
12+
...taskArgs: A
13+
): Promise<R>;
14+
}
15+
export default Bottleneck;
16+
}

src/error-request.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
1-
// @ts-ignore
1+
import { type RetryPlugin, type RetryState } from "./types.js";
2+
import type { RequestRequestOptions } from "@octokit/types";
3+
import type { RequestError } from "@octokit/request-error";
24

3-
export async function errorRequest(state, octokit, error, options) {
4-
if (!error.request || !error.request.request) {
5+
export function isRequestError(error: any): error is RequestError {
6+
return error.request !== undefined;
7+
}
8+
9+
export async function errorRequest(
10+
state: RetryState,
11+
octokit: RetryPlugin,
12+
error: RequestError | Error,
13+
options: { request: RequestRequestOptions },
14+
): Promise<any> {
15+
if (!isRequestError(error) || !error?.request.request) {
516
// address https://github.com/octokit/plugin-retry.js/issues/8
617
throw error;
718
}

src/index.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import type { Octokit } from "@octokit/core";
1+
import type { Octokit, OctokitOptions } from "@octokit/core";
22
import type { RequestError } from "@octokit/request-error";
33

44
import { VERSION } from "./version.js";
55
import { errorRequest } from "./error-request.js";
66
import { wrapRequest } from "./wrap-request.js";
7+
import type { RetryOptions, RetryPlugin, RetryState } from "./types.js";
8+
import type { RequestRequestOptions } from "@octokit/types";
79
export { VERSION } from "./version.js";
810

9-
export function retry(octokit: Octokit, octokitOptions: any) {
10-
const state = Object.assign(
11+
export function retry(
12+
octokit: Octokit,
13+
octokitOptions: OctokitOptions,
14+
): RetryPlugin {
15+
const state: RetryState = Object.assign(
1116
{
1217
enabled: true,
1318
retryAfterBaseValue: 1000,
1419
doNotRetry: [400, 401, 403, 404, 410, 422, 451],
1520
retries: 3,
16-
},
21+
} satisfies RetryState,
1722
octokitOptions.retry,
1823
);
1924

20-
if (state.enabled) {
21-
octokit.hook.error("request", errorRequest.bind(null, state, octokit));
22-
octokit.hook.wrap("request", wrapRequest.bind(null, state, octokit));
23-
}
24-
25-
return {
25+
const retryPlugin: RetryPlugin = {
2626
retry: {
2727
retryRequest: (
2828
error: RequestError,
@@ -32,11 +32,26 @@ export function retry(octokit: Octokit, octokitOptions: any) {
3232
error.request.request = Object.assign({}, error.request.request, {
3333
retries: retries,
3434
retryAfter: retryAfter,
35-
});
35+
} satisfies RequestRequestOptions);
3636

3737
return error;
3838
},
3939
},
4040
};
41+
42+
if (state.enabled) {
43+
octokit.hook.error("request", errorRequest.bind(null, state, retryPlugin));
44+
octokit.hook.wrap("request", wrapRequest.bind(null, state, retryPlugin));
45+
}
46+
47+
return retryPlugin;
4148
}
4249
retry.VERSION = VERSION;
50+
51+
declare module "@octokit/core/types" {
52+
interface OctokitOptions {
53+
retry?: RetryOptions;
54+
}
55+
}
56+
57+
export type { RetryPlugin, RetryOptions };

src/types.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { RequestError } from "@octokit/request-error";
2+
3+
export interface RetryPlugin {
4+
retry: {
5+
retryRequest: (
6+
error: RequestError,
7+
retries: number,
8+
retryAfter: number,
9+
) => RequestError;
10+
};
11+
}
12+
13+
export interface RetryOptions {
14+
enabled?: boolean;
15+
retryAfterBaseValue?: number;
16+
doNotRetry?: number[];
17+
retries?: number;
18+
}
19+
20+
export type RetryState = Required<RetryOptions>;

src/wrap-request.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
1-
// @ts-nocheck
2-
import Bottleneck from "bottleneck/light.js";
1+
import Bottleneck, { type RetryableInfo } from "bottleneck/light.js";
32
import { RequestError } from "@octokit/request-error";
43
import { errorRequest } from "./error-request.js";
4+
import type { RetryPlugin, RetryState } from "./types.js";
5+
import type { EndpointDefaults, OctokitResponse } from "@octokit/types";
56

6-
export async function wrapRequest(state, octokit, request, options) {
7+
type RequestHook = (
8+
options: Required<EndpointDefaults>,
9+
) => OctokitResponse<any, number> | Promise<OctokitResponse<any, number>>;
10+
11+
export async function wrapRequest(
12+
state: RetryState,
13+
octokit: RetryPlugin,
14+
request: RequestHook,
15+
options: Required<EndpointDefaults>,
16+
) {
717
const limiter = new Bottleneck();
818

9-
limiter.on("failed", function (error, info) {
10-
const maxRetries = ~~error.request.request.retries;
11-
const after = ~~error.request.request.retryAfter;
19+
limiter.on("failed", function (error: RequestError, info: RetryableInfo) {
20+
const maxRetries = ~~error.request.request?.retries;
21+
const after = ~~error.request.request?.retryAfter;
1222
options.request.retryCount = info.retryCount + 1;
1323

1424
if (maxRetries > info.retryCount) {
@@ -25,12 +35,12 @@ export async function wrapRequest(state, octokit, request, options) {
2535
}
2636

2737
async function requestWithGraphqlErrorHandling(
28-
state,
29-
octokit,
30-
request,
31-
options,
32-
) {
33-
const response = await request(request, options);
38+
state: RetryState,
39+
octokit: RetryPlugin,
40+
request: RequestHook,
41+
options: Required<EndpointDefaults>,
42+
): Promise<OctokitResponse<any, number>> {
43+
const response = await request(options);
3444

3545
if (
3646
response.data &&

0 commit comments

Comments
 (0)