Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📝 Export Token, document token types #400

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions scripts/build.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import esbuild from "esbuild";
import { copyFile, readFile, writeFile, rm } from "node:fs/promises";
import { glob } from "glob";
import { copyFile, readFile, rm, writeFile } from "node:fs/promises";

const sharedOptions = {
sourcemap: "external",
Expand Down Expand Up @@ -68,12 +68,15 @@ async function main() {
types: "./dist-types/index.d.ts",
import: "./dist-bundle/index.js",
},
"./types": {
types: "./dist-types/types.d.ts",
},
},
sideEffects: false,
},
null,
2
)
2,
),
);
}
main();
2 changes: 1 addition & 1 deletion src/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Token, Authentication } from "./types.js";
import type { Authentication, Token } from "./types.js";

const REGEX_IS_INSTALLATION_LEGACY = /^v1\./;
const REGEX_IS_INSTALLATION = /^ghs_/;
Expand Down
28 changes: 28 additions & 0 deletions src/create-token-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { auth } from "./auth.js";
import { hook } from "./hook.js";
import type { BearerToken, StrategyInterface, Token } from "./types.js";

export const createTokenAuth: StrategyInterface = function createTokenAuth(
token: Token | BearerToken,
) {
if (!token) {
throw new Error("[@octokit/auth-token] No token passed to createTokenAuth");
}

if (typeof token !== "string") {
throw new Error(
"[@octokit/auth-token] Token passed to createTokenAuth is not a string",
);
}

token = toToken(token);

return Object.assign(auth.bind(null, token), {
hook: hook.bind(null, token),
});
};

/** Turns a {@link BearerToken} into a {@link Token}. */
function toToken(token: BearerToken | Token): Token {
return token.replace(/^(token|bearer) +/i, "") as Token;
}
1 change: 0 additions & 1 deletion src/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type {
Route,
Token,
} from "./types.js";

import { withAuthorizationPrefix } from "./with-authorization-prefix.js";

export async function hook(
Expand Down
36 changes: 7 additions & 29 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,7 @@
import { auth } from "./auth.js";
import { hook } from "./hook.js";
import type { StrategyInterface, Token, Authentication } from "./types.js";

export type Types = {
StrategyOptions: Token;
AuthOptions: never;
Authentication: Authentication;
};

export const createTokenAuth: StrategyInterface = function createTokenAuth(
token: Token,
) {
if (!token) {
throw new Error("[@octokit/auth-token] No token passed to createTokenAuth");
}

if (typeof token !== "string") {
throw new Error(
"[@octokit/auth-token] Token passed to createTokenAuth is not a string",
);
}

token = token.replace(/^(token|bearer) +/i, "");

return Object.assign(auth.bind(null, token), {
hook: hook.bind(null, token),
});
};
export * from "./create-token-auth.js";
export type {
Authentication,
StrategyInterface,
Token,
Types,
} from "./types.js";
57 changes: 55 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type * as OctokitTypes from "@octokit/types";

export type AnyResponse = OctokitTypes.OctokitResponse<any>;
export type StrategyInterface = OctokitTypes.StrategyInterface<
[Token],
[Token | BearerToken],
[],
Authentication
>;
Expand All @@ -12,7 +12,54 @@ export type RequestParameters = OctokitTypes.RequestParameters;
export type RequestInterface = OctokitTypes.RequestInterface;
export type Route = OctokitTypes.Route;

export type Token = string;
/** GitHub App server-to-server token
* @see https://docs.github.com/en/developers/apps/authenticating-with-github-apps#authenticating-as-an-installation */
export type ServerToServerToken = `ghs_${string}`;
export type InstallallationTokenV1 = `v1.${string}`;
/** Your app can make API requests on behalf of a user. API requests made by an
* app on behalf of a user will be attributed to that user. For example, if your
* app posts a comment on behalf of a user, the GitHub UI will show the user's
* avatar photo along with the app's identicon badge as the author of the issue.
*
* @see https://docs.github.com/en/developers/apps/identifying-and-authorizing-users-for-github-apps
* */
export type InstallationUserToServerToken = `ghu_${string}`;
/** In order to authenticate as an app or generate an installation access token,
* you must generate a JSON Web Token (JWT). If a REST API endpoint requires a
* JWT, the documentation for that endpoint will indicate that you must use a
* JWT to access the endpoint.
*
* @see https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app
*/
export type JWT = `${string}.${string}.${string}`;
/** This access token allows you to make requests to the API on a behalf of a
* user.
*
* @see https://docs.github.com/en/developers/apps/authorizing-oauth-apps
*/
export type OAuthToken = `gho_${string}`;
/**
* Personal access tokens are an alternative to using passwords for
* authentication to GitHub when using the [GitHub API](https://docs.github.com/en/rest/overview/authenticating-to-the-rest-api)
* or the [command line](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#using-a-personal-access-token-on-the-command-line).
*
* @see https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token
*/
export type PersonalAccessToken = `ghp_${string}`;

export type Token =
| ServerToServerToken
| InstallallationTokenV1
| InstallationUserToServerToken
| JWT
| OAuthToken
| PersonalAccessToken;

export type BearerToken =
| `bearer ${Token}`
| `Bearer ${Token}`
| `token ${Token}`
| `Token ${Token}`;

export type OAuthTokenAuthentication = {
type: "token";
Expand All @@ -39,3 +86,9 @@ export type Authentication =
| InstallationTokenAuthentication
| AppAuthentication
| UserToServerAuthentication;

export type Types = {
wolfy1339 marked this conversation as resolved.
Show resolved Hide resolved
StrategyOptions: Token;
AuthOptions: never;
Authentication: Authentication;
};
2 changes: 2 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ test("User-to-server token (User authentication through app installation)", asyn
});

test("invalid token", async () => {
// @ts-expect-error Argument of type `"whatislove"` is not assignable to
// parameter of type`Token | BearerToken`.
const auth = createTokenAuth("whatislove");
const authentication = await auth();

Expand Down