Repository: conwnet/github1s
File: extensions/github1s/src/repository.ts (TypeScript)

Code before:
	private _pullMap: Map<string, RepositoryPull>;
	private _pullFilesMap: Map<string, RepositoryChangedFile[]>;

	private constructor() {
		this._branchRefsMap = new Map();
		this._tagRefsMap = new Map();
		this._pullsMap = new Map();
		this._pullMap = new Map();
		this._pullFilesMap = new Map();
	}

	public static getInstance() {
		if (Repository.instance) {
			return this.instance;
		}
		return (Repository.instance = new Repository());
	}

	// get current repo owner
	public getOwner() {
		const pathname = router.history.location.pathname;
		return pathname.split('/').filter(Boolean)[0] || 'conwnet';
	}

	// get current repo name
	public getRepo() {
		const pathname = router.history.location.pathname;
		return pathname.split('/').filter(Boolean)[1] || 'github1s';
	}

	// get all branches for current repository
	public getBranches = reuseable(
		async (forceUpdate: boolean = false): Promise<RepositoryRef[]> => {
			const [owner, repo] = [this.getOwner(), this.getRepo()];
			const key = `${owner}+${repo}`;

			if (!this._branchRefsMap.has(key) || forceUpdate) {
				this._branchRefsMap.set(key, await getGithubBranchRefs(owner, repo));
			}
			return this._branchRefsMap.get(key);
		}
	);

	// get all tags for current repository
	public getTags = reuseable(
		async (forceUpdate: boolean = false): Promise<RepositoryRef[]> => {
			const [owner, repo] = [this.getOwner(), this.getRepo()];
			const key = `${owner}+${repo}`;

			if (!this._tagRefsMap.has(key) || forceUpdate) {
				this._tagRefsMap.set(key, await getGithubTagRefs(owner, repo));

Review comment (performance):
~We might need to consolidate the maps into two maps, since the maps are used as cache layers.~

I think we should adopt a HTTP request client or invent a cache level on the network call side instead of put maps here. 

For example, if we leverage the [Got](https://github.com/sindresorhus/got), which has built-in cache support:
https://github.com/sindresorhus/got#cache-adapters

We could remove all the maps and this file can be significantly simplified.

for example
```js
	public getCommit = reuseable(
		async (
			commitSha: string,
			forceUpdate: boolean = false
		): Promise<RepositoryCommit> => {
			const [owner, repo] = [this.getOwner(), this.getRepo()];
			const key = `${owner}+${repo}+${commitSha}`;

			if (!this._commitMap.has(key) || forceUpdate) {
				const commitData = (await getGitHubCommitDetail(
					owner,
					repo,
					commitSha
				)) as RepositoryCommit;
				this._commitMap.set(key, commitData);
				this._commitFilesMap.set(key, commitData.files);
			}

			return this._commitMap.get(key);
		}
	);
```
->
```js
	public getCommit = reuseable(
		async (
			commitSha: string,
			forceUpdate: boolean = false
		): Promise<RepositoryCommit> => {
			const [owner, repo] = [this.getOwner(), this.getRepo()];
			return getGitHubCommitDetail(
				owner,
				repo,
				commitSha
			) as Promise<RepositoryCommit>;
		}
	);
```

Code after:
export interface RepositoryChangedFile {
	filename: string;
	previous_filename?: string;
	status: FileChangeType;
}

export class Repository {
	private static instance: Repository;
	private _branchRefsMap: Map<string, RepositoryRef[]>;
	private _tagRefsMap: Map<string, RepositoryRef[]>;

	private _pullsMap: Map<string, RepositoryPull[]>;
	private _pullMap: Map<string, RepositoryPull>;
	private _pullFilesMap: Map<string, RepositoryChangedFile[]>;

	private _commitMap: Map<string, RepositoryCommit>;
	private _commitFilesMap: Map<string, RepositoryChangedFile[]>;

	private constructor() {
		this._branchRefsMap = new Map();
		this._tagRefsMap = new Map();
		this._pullsMap = new Map();
		this._pullMap = new Map();
		this._pullFilesMap = new Map();
		this._commitMap = new Map();
		this._commitFilesMap = new Map();
	}

	public static getInstance() {
		if (Repository.instance) {
			return this.instance;
		}
		return (Repository.instance = new Repository());
	}

	// get current repo owner
	public getOwner() {
		const pathname = router.history.location.pathname;
		return pathname.split('/').filter(Boolean)[0] || 'conwnet';
	}

	// get current repo name
	public getRepo() {
		const pathname = router.history.location.pathname;
		return pathname.split('/').filter(Boolean)[1] || 'github1s';
	}

	// get all branches for current repository
	public getBranches = reuseable(
		async (forceUpdate: boolean = false): Promise<RepositoryRef[]> => {
			const [owner, repo] = [this.getOwner(), this.getRepo()];