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

🚧Add folder and file inspection feature #42

Open
4 tasks
CalvinWilkinson opened this issue Feb 22, 2024 · 0 comments
Open
4 tasks

🚧Add folder and file inspection feature #42

CalvinWilkinson opened this issue Feb 22, 2024 · 0 comments
Assignees
Labels
medium-priority Medium Priority ✨new-feature New feature that does not exist

Comments

@CalvinWilkinson
Copy link
Member

Complete The Item Below

  • I have updated the title without removing the 🚧 emoji.

Description

Add the ability to do the following with folders and files in the RepoClient.

  1. Ability to check if a folder exists in a folder
  2. Ability to check if a file exists in a folder
  3. Ability to get a list of folders contained in another folder
  4. Ability to get a list of files contained in another folder
Sample Code

import { Guards, Utils } from "../../deps.ts";
import { RepoClient } from "../../deps.ts";
import { FileOrFolder } from "../../deps.ts";

export class RepoFileService {
	private readonly fileRegex: RegExp;
	private readonly orgName: string;
	private readonly repoName: string;
	private readonly token: string;
	private readonly repoClient: RepoClient;

	constructor(orgName: string, repoName: string, token: string) {
		Guards.isNothing(orgName);
		Guards.isNothing(repoName);
		Guards.isNothing(token);

		this.fileRegex = /^.+\..+$/gm;
		this.orgName = orgName;
		this.repoName = repoName;
		this.token = token;

		this.repoClient = new RepoClient(orgName, repoName, token);
	}

	public async folderExists(folderPath: string): Promise<boolean> {
		Guards.isNothing(folderPath);

		// Strip leading and trailing slashes
		folderPath = folderPath.startsWith("/") ? folderPath.substring(1) : folderPath;
		folderPath = folderPath.endsWith("/") ? folderPath.substring(0, folderPath.length - 1) : folderPath;
		
		let parentFolder = "";

		if (this.fileRegex.test(folderPath)) {
			Utils.printGitHubError(`The file name '${folderPath}' is not a valid folder path.`);
			Deno.exit(1);
		}

		if (folderPath.includes("/")) {
			const parts = folderPath.split("/");
			parentFolder = parts.slice(0, parts.length - 1).join("/");
		}

		const filesAndFolders = await this.getFilesAndFolders(parentFolder);

		return filesAndFolders.some(f => this.isDir(f.type) && f.name === folderPath);
	}

	public async fileExists(filePath: string) : Promise<boolean> {
		Guards.isNothing(filePath);

		filePath = filePath.trim();

		let folderName = "";
		let fileName = "";
		
		if (filePath.includes("/")) {
			const parts = filePath.split("/");
			fileName = parts[parts.length - 1];
			
			if (!this.fileRegex.test(fileName)) {
				Utils.printGitHubError(`The file name '${fileName}' is not a valid file name.`);
				Deno.exit(1);
			}

			folderName = parts.slice(0, parts.length - 1).join("/");
		} else {
			if (!this.fileRegex.test(fileName)) {
				Utils.printGitHubError(`The file name '${fileName}' is not a valid file name.`);
				Deno.exit(1);
			}

			fileName = filePath;
		}

		const filesAndFolders = await this.getFilesAndFolders(folderName);

		return filesAndFolders.some(f => this.isFile(f.type) && f.name === fileName);
	}

	private async getFilesAndFolders(relativePath: string): Promise<FileOrFolder[]> {
		// Guards.isNothing(relativePath);

		const baseUrl = "https://api.github.com";
		const url = `${baseUrl}/repos/KinsonDigital/Velaptor/contents/${relativePath}`;
		
		const result = await fetch(url, {
			method: "GET",
			headers: {
				"Authorization": `Bearer ${this.token}`,
				"Accept": "application/vnd.github+json",
				"X-Github-Api-Version": "2022-11-28"
			},
		});
		
		if (result.status != 200) {
			console.error(result.statusText);
			Deno.exit(1);
		}
		
		const data = await result.json() as FileOrFolder[];

		return data;
	}

	private isFile(type: string): type is "file" {
		return type === "file";
	}

	private isDir(type: string): type is "dir" {
		return type === "dir";
	}
}

Acceptance Criteria

The items to complete to satisfy the Definition of Done.

ToDo Items

The items to complete to satisfy the Definition of Done.

Issue Dependencies

No response

Related Work

No response

Additional Information:

Unit Tests

Reasons for local unit test execution:

  • Unit tests might pass locally but not in the CI environment during the status check process or vice-versa.
  • Tests might pass on the developer's machine but not necessarily on the code reviewer's machine.
  • If you notice that the test status check has passed but the test failed locally, please notify a project maintainer!

💡Warning💡
If the unit tests pass remotely and are not executed locally, this means we could be letting a bug slip into production.
Though bugs will always exist in some capacity, we should all do our part to help prevent them from happening.

Change Type Labels

Change Type Label
Bug Fixes 🐛bug
Breaking Changes 🧨breaking changes
New Feature ✨new feature
CICD Changes ♻️cicd
Config Changes ⚙️config
Performance Improvements 🏎️performance
Code Doc Changes 🗒️documentation/code
Product Doc Changes 📝documentation/product

Priority Type Labels

Priority Type Label
Low Priority low priority
Medium Priority medium priority
High Priority high priority

Code of Conduct

  • I agree to follow this project's Code of Conduct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
medium-priority Medium Priority ✨new-feature New feature that does not exist
Projects
Status: ⚪Not Set
Development

No branches or pull requests

1 participant