Skip to content

Commit f7a9136

Browse files
committed
feat: initial version
1 parent c8e5495 commit f7a9136

File tree

6 files changed

+130
-0
lines changed

6 files changed

+130
-0
lines changed

src/auth.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Authentication } from "./types";
2+
3+
export async function auth(reason: string): Promise<Authentication> {
4+
return {
5+
type: "unauthenticated",
6+
reason,
7+
};
8+
}

src/hook.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { RequestError } from "@octokit/request-error";
2+
3+
import {
4+
AnyResponse,
5+
EndpointDefaults,
6+
EndpointOptions,
7+
RequestInterface,
8+
RequestParameters,
9+
Route,
10+
} from "./types";
11+
import { isRateLimitError } from "./is-rate-limit-error";
12+
import { isAbuseLimitError } from "./is-abuse-limit-error";
13+
14+
const MUTATING_METHODS = ["DELETE", "PATCH", "POST", "PUT"];
15+
16+
export async function hook(
17+
reason: string,
18+
request: RequestInterface,
19+
route: Route | EndpointOptions,
20+
parameters?: RequestParameters
21+
): Promise<AnyResponse> {
22+
const endpoint: EndpointDefaults = request.endpoint.merge(
23+
route as string,
24+
parameters
25+
);
26+
27+
if (MUTATING_METHODS.includes(endpoint.method)) {
28+
throw new RequestError(
29+
`"${endpoint.method} ${endpoint.url}" is not permitted due to lack authentication. Reason: ${reason}`,
30+
403,
31+
{
32+
request: request.endpoint.parse(endpoint),
33+
}
34+
);
35+
}
36+
37+
return request(endpoint as EndpointOptions).catch((error) => {
38+
if (error.status === 404) {
39+
error.message = `Not found. May be due to lack of authentication. Reason: ${reason}`;
40+
}
41+
42+
if (isRateLimitError(error)) {
43+
error.message = `API rate limit exceeded. This maybe caused by the lack of authentication. Reason: ${reason}`;
44+
}
45+
46+
if (isAbuseLimitError(error)) {
47+
error.message = `You have triggered an abuse detection mechanism. This maybe caused by the lack of authentication. Reason: ${reason}`;
48+
}
49+
50+
throw error;
51+
});
52+
}

src/index.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { auth } from "./auth";
2+
import { hook } from "./hook";
3+
import { StrategyInterface, Options, Authentication } from "./types";
4+
5+
export type Types = {
6+
StrategyOptions: Options;
7+
AuthOptions: never;
8+
Authentication: Authentication;
9+
};
10+
11+
export const createUnauthenticatedAuth: StrategyInterface = function createUnauthenticatedAuth(
12+
options: Options
13+
) {
14+
if (!options || !options.reason) {
15+
throw new Error(
16+
"[@octokit/auth-unauthenticated] No reason passed to createUnauthenticatedAuth"
17+
);
18+
}
19+
20+
return Object.assign(auth.bind(null, options.reason), {
21+
hook: hook.bind(null, options.reason),
22+
});
23+
};

src/is-abuse-limit-error.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { RequestError } from "@octokit/request-error";
2+
3+
const REGEX_ABUSE_LIMIT_MESSAGE = /\babuse\b/i;
4+
5+
export function isAbuseLimitError(error: RequestError) {
6+
if (error.status !== 403) {
7+
return false;
8+
}
9+
10+
return REGEX_ABUSE_LIMIT_MESSAGE.test(error.message);
11+
}

src/is-rate-limit-error.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { RequestError } from "@octokit/request-error";
2+
3+
export function isRateLimitError(error: RequestError) {
4+
if (error.status !== 403) {
5+
return false;
6+
}
7+
8+
/* istanbul ignore if */
9+
if (!error.headers) {
10+
return false;
11+
}
12+
13+
return error.headers["x-ratelimit-remaining"] === "0";
14+
}

src/types.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as OctokitTypes from "@octokit/types";
2+
3+
export type AnyResponse = OctokitTypes.OctokitResponse<any>;
4+
export type StrategyInterface = OctokitTypes.StrategyInterface<
5+
[Options],
6+
[],
7+
Authentication
8+
>;
9+
10+
export type EndpointDefaults = OctokitTypes.EndpointDefaults;
11+
export type EndpointOptions = OctokitTypes.EndpointOptions;
12+
export type RequestParameters = OctokitTypes.RequestParameters;
13+
export type RequestInterface = OctokitTypes.RequestInterface;
14+
export type Route = OctokitTypes.Route;
15+
16+
export type Options = {
17+
reason: string;
18+
};
19+
export type Authentication = {
20+
type: "unauthenticated";
21+
reason: string;
22+
};

0 commit comments

Comments
 (0)