Skip to content

Commit

Permalink
enhance: throw auth errors in repo client
Browse files Browse the repository at this point in the history
  • Loading branch information
CalvinWilkinson committed May 14, 2024
1 parent 3ec8790 commit cfe63d6
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 20 deletions.
2 changes: 1 addition & 1 deletion GitHubClients/Errors/AuthError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class AuthError extends Error {
*/
constructor(message?: string) {
const errorMessage = message === undefined
? "Authentication error occurred. Please check your credentials and try again."
? "Authentication error occurred. Please check the GitHub token used and try again."
: message;

super(errorMessage);
Expand Down
89 changes: 70 additions & 19 deletions GitHubClients/RepoClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { decodeBase64, encodeBase64, isAbsolute } from "../deps.ts";
import { AuthError, decodeBase64, encodeBase64, isAbsolute } from "../deps.ts";
import { GitHubHttpStatusCodes } from "../core/Enums.ts";
import { GitHubClient } from "../deps.ts";
import { Guard } from "../core/Guard.ts";
Expand Down Expand Up @@ -31,12 +31,20 @@ export class RepoClient extends GitHubClient {
/**
* Gets information about a repository with a name that matches the given {@link RepoClient}.{@link repoName}.
* @returns A repository information.
* @throws The {@link RepoError} if the repository does not exist.
* @throws The following errors:
* 1. An {@link AuthError} if there was a problem with the authentication.
* 2. The {@link RepoError} if the repository owner does not exist.
*/
public async getRepo(): Promise<RepoModel> {
const foundRepos = await this.getAllDataUntil<RepoModel>(
async (page, qtyPerPage) => {
return await this.getAllReposInternal(page, qtyPerPage ?? 100);
const [allRepos, response] = await this.getAllReposInternal(page, qtyPerPage ?? 100);

if (response.status === GitHubHttpStatusCodes.Unauthorized) {
throw new AuthError();
}

return [allRepos, response];
},
1, // Start page
100, // Qty per page
Expand Down Expand Up @@ -65,15 +73,19 @@ export class RepoClient extends GitHubClient {
* @remarks The {@link page} value must be greater than 0. If less than 1, the value of 1 will be used.
* The {@link qtyPerPage} value must be a value between 1 and 100. If less than 1, the value will
* be set to 1, if greater than 100, the value will be set to 100.
* @throws The {@link RepoError} if the repository owner does not exist.
* @throws The following errors:
* 1. An {@link AuthError} if there was a problem with the authentication.
* 2. The {@link RepoError} if the repository owner does not exist.
*/
public async getAllRepos(page: number, qtyPerPage: number): Promise<RepoModel[]> {
page = page < 1 ? 1 : page;
qtyPerPage = Utils.clamp(qtyPerPage, 1, 100);

const [allRepos, response] = await this.getAllReposInternal(page, qtyPerPage);

if (response.status === GitHubHttpStatusCodes.NotFound) {
if (response.status === GitHubHttpStatusCodes.Unauthorized) {
throw new AuthError();
} else if (response.status === GitHubHttpStatusCodes.NotFound) {
const errorMsg = this.buildErrorMsg(
`Not found. Check that the repository owner '${this.ownerName}' is a valid repository owner.`,
response,
Expand All @@ -88,7 +100,9 @@ export class RepoClient extends GitHubClient {
/**
* Checks if a repository with a name that matches the {@link RepoClient}.{@link repoName} exists.
* @returns True if the repo exists; otherwise, false.
* @throws The {@link RepoError} if there was a problem checking if the repository exists.
* @throws The following errors:
* 1. An {@link AuthError} if there was a problem with the authentication.
* 2. The {@link RepoError} if the repository owner does not exist.
*/
public async exists(): Promise<boolean> {
const url = `${this.baseUrl}/repos/${this.ownerName}/${this.repoName}`;
Expand All @@ -101,6 +115,8 @@ export class RepoClient extends GitHubClient {
}

switch (response.status) {
case GitHubHttpStatusCodes.Unauthorized:
throw new AuthError();
case GitHubHttpStatusCodes.MovedPermanently:
case GitHubHttpStatusCodes.Forbidden: {
const errorMsg = this.buildErrorMsg(
Expand All @@ -121,7 +137,10 @@ export class RepoClient extends GitHubClient {
* @param relativeFilePath The relative path of the file.
* @returns The content of the file.
* @remarks The {@link relativeFilePath} is relative to the root of the repository.
* @throws The {@link RepoError} if there was a problem getting the file content.
* @throws The following errors:
* 1. If any of the parameters are undefined, null, or empty.
* 2. An {@link AuthError} if there was a problem with the authentication.
* 3. The {@link RepoError} if the file content does not exist.
*/
public async getFileContent(branchName: string, relativeFilePath: string): Promise<string> {
const funcName = "getFileContent";
Expand All @@ -145,7 +164,10 @@ export class RepoClient extends GitHubClient {
* @param relativeFilePath The relative path of the file.
* @returns True if the file exists; otherwise, false.
* @remarks The {@link relativeFilePath} is relative to the root of the repository.
* @throws The {@link RepoError} if there was problem checking if the file exists.
* @throws The following errors:
* 1. If any of the parameters are undefined, null, or empty.
* 2. An {@link AuthError} if there was a problem with the authentication.
* 3. The {@link RepoError} if the there was a problem checking if the file exists or if the file path is invalid.
*/
public async fileExists(branchName: string, relativeFilePath: string): Promise<boolean> {
const funcName = "fileExists";
Expand All @@ -169,7 +191,9 @@ export class RepoClient extends GitHubClient {

const response: Response = await this.requestGET(url);

if (response.status != GitHubHttpStatusCodes.OK) {
if (response.status === GitHubHttpStatusCodes.Unauthorized) {
throw new AuthError();
} else if (response.status != GitHubHttpStatusCodes.OK) {
if (response.status === GitHubHttpStatusCodes.NotFound) {
return false;
} else {
Expand All @@ -189,7 +213,9 @@ export class RepoClient extends GitHubClient {
/**
* Gets a list of all the variables for a repository with a name that matches the given {@link RepoClient}.{@link repoName}.
* @returns A list of all repositories variables.
* @throws The {@link RepoError} if there was a problem getting the variables.
* @throws The following errors:
* 1. An {@link AuthError} if there was a problem with the authentication.
* 2. The {@link RepoError} if the there was a problem getting all of the repository variables.
*/
public async getVariables(): Promise<GitHubVarModel[]> {
return await this.getAllData<GitHubVarModel>(async (page: number, qtyPerPage?: number) => {
Expand All @@ -198,7 +224,9 @@ export class RepoClient extends GitHubClient {

const response = await this.requestGET(url);

if (response.status != GitHubHttpStatusCodes.OK) {
if (response.status === GitHubHttpStatusCodes.Unauthorized) {
throw new AuthError();
} else if (response.status != GitHubHttpStatusCodes.OK) {
const errorMsg = this.buildErrorMsg(
`An error occurred when getting the variables for the owner '${this.ownerName}'.`,
response,
Expand All @@ -218,7 +246,10 @@ export class RepoClient extends GitHubClient {
* in a repository with a name that matches the given {@link RepoClient}.{@link repoName}.
* @param variableName The name of the variable.
* @returns True if the variable exists; otherwise, false.
* @throws The {@link RepoError} if there was a problem checking if the variable exists.
* @throws The following errors:
* 1. If the parameter is undefined, null, or empty.
* 2. An {@link AuthError} if there was a problem with the authentication.
* 3. The {@link RepoError} if the there was a problem getting all of the repository variables.
*/
public async repoVariableExists(variableName: string): Promise<boolean> {
Guard.isNothing(variableName, "repoVariableExists", "variableName");
Expand All @@ -234,7 +265,10 @@ export class RepoClient extends GitHubClient {
* the given {@link variableName} in a repository with a name that matches the given {@link RepoClient}.{@link repoName}.
* @param variableName The name of the variable.
* @param variableValue The value of the variable.
* @throws The {@link RepoError} if there was a problem updating the variable or if the variable does not exist.
* @throws The following errors:
* 1. If any of the parameters are undefined, null, or empty.
* 2. An {@link AuthError} if there was a problem with the authentication.
* 3. The {@link RepoError} if the a variable with the given {@link variableName} does not exist or a problem updating the variable.
*/
public async updateVariable(variableName: string, variableValue: string): Promise<void> {
const funcName = "updateVariable";
Expand All @@ -254,7 +288,9 @@ export class RepoClient extends GitHubClient {

const response = await this.requestPATCH(url, JSON.stringify(body));

if (response.status != GitHubHttpStatusCodes.NoContent) {
if (response.status === GitHubHttpStatusCodes.Unauthorized) {
throw new AuthError();
} else if (response.status != GitHubHttpStatusCodes.NoContent) {
const errorMsg = this.buildErrorMsg(
`An error occurred when updating the variable '${variableName}'` +
` for the repository '${this.repoName}'.`,
Expand All @@ -274,7 +310,10 @@ export class RepoClient extends GitHubClient {
* @param relativeFilePath The relative path of where to add the file.
* @param fileContent The content of the file.
* @param commitMessage The commit message.
* @throws The {@link RepoError} if there was a problem creating the file or if the file already exists.
* @throws The following errors:
* 1. If any of the parameters are undefined, null, or empty.
* 2. An {@link AuthError} if there was a problem with the authentication.
* 3. The {@link RepoError} if the file already exists or a problem creating the file.
*/
public async createFile(
branchName: string,
Expand Down Expand Up @@ -305,7 +344,9 @@ export class RepoClient extends GitHubClient {

const response = await this.requestPUT(url, JSON.stringify(body));

if (response.status != GitHubHttpStatusCodes.OK && response.status != GitHubHttpStatusCodes.Created) {
if (response.status === GitHubHttpStatusCodes.Unauthorized) {
throw new AuthError();
} else if (response.status != GitHubHttpStatusCodes.OK && response.status != GitHubHttpStatusCodes.Created) {
const errorMsg = this.buildErrorMsg(
`An error occurred when creating the file '${relativeFilePath}' in the repository '${this.repoName}'` +
` for branch '${branchName}'.`,
Expand All @@ -325,7 +366,10 @@ export class RepoClient extends GitHubClient {
* @param fileContent The content of the file.
* @param commitMessage The commit message.
* @remarks If the file does not exist, an error will be thrown.
* @throws The {@link RepoError} if there was a problem updating the file or if the file does not exist.
* @throws The following errors:
* 1. If any of the parameters are undefined, null, or empty.
* 2. An {@link AuthError} if there was a problem with the authentication.
* 3. The {@link RepoError} if the file does not exist or a problem updating the file.
*/
public async updateFile(
branchName: string,
Expand Down Expand Up @@ -368,7 +412,9 @@ export class RepoClient extends GitHubClient {

const response = await this.requestPUT(url, JSON.stringify(body));

if (response.status != GitHubHttpStatusCodes.OK && response.status != GitHubHttpStatusCodes.Created) {
if (response.status === GitHubHttpStatusCodes.Unauthorized) {
throw new AuthError();
} else if (response.status != GitHubHttpStatusCodes.OK && response.status != GitHubHttpStatusCodes.Created) {
const errorMsg = this.buildErrorMsg(
`An error occurred when creating the file '${relativeFilePath}' in the repository '${this.repoName}'` +
` for branch '${branchName}'.`,
Expand All @@ -386,7 +432,10 @@ export class RepoClient extends GitHubClient {
* @param relativeFilePath The relative path of the file.
* @returns The content of the file and a boolean flag indicating whether or not the file exists.
* @remarks The {@link relativeFilePath} is relative to the root of the repository.
* @throws The {@link RepoError} if there was a problem getting the file content.
* @throws The following errors:
* 1. If any of the parameters are undefined, null, or empty.
* 2. An {@link AuthError} if there was a problem with the authentication.
* 3. The {@link RepoError} if the file does not exist or a problem getting the file content.
*/
private async getFileContentInternal(
branchName: string,
Expand Down Expand Up @@ -414,6 +463,8 @@ export class RepoClient extends GitHubClient {
const response: Response = await this.requestGET(url);

switch (response.status) {
case GitHubHttpStatusCodes.Unauthorized:
throw new AuthError();
case GitHubHttpStatusCodes.NotFound:
case GitHubHttpStatusCodes.TemporaryRedirect:
case GitHubHttpStatusCodes.Forbidden: {
Expand Down

0 comments on commit cfe63d6

Please sign in to comment.