diff --git a/src/constants/gist-constants.ts b/src/constants/gist-constants.ts new file mode 100644 index 0000000..48fc7e2 --- /dev/null +++ b/src/constants/gist-constants.ts @@ -0,0 +1,8 @@ +import { config } from '../config'; + +export const gistsBaseUrl = 'https://api.github.com/gists'; + +export const headers = { + 'X-GitHub-Api-Version': '2022-11-28', + Authorization: 'Bearer ' + config.api.github, +}; diff --git a/src/controllers/gist-controller.ts b/src/controllers/gist-controller.ts index 2156c36..d30bff8 100644 --- a/src/controllers/gist-controller.ts +++ b/src/controllers/gist-controller.ts @@ -1,15 +1,10 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import axios, { type AxiosError } from 'axios'; +import axios, { all, type AxiosError } from 'axios'; import { Request, Response } from 'express'; -import { config } from '../config'; import { IGistCommitItem } from '../interfaces/gist-commit-item'; import { IGistFile } from '../interfaces/gist-file'; - -const gistsBaseUrl = 'https://api.github.com/gists'; -const headers = { - 'X-GitHub-Api-Version': '2022-11-28', - Authorization: 'Bearer ' + config.api.github, -}; +import { gistsBaseUrl, headers } from '../constants/gist-constants'; +import { GistService } from '../services/gist-service'; async function get(req: Request, res: Response) { try { @@ -73,9 +68,14 @@ async function create(req: Request, res: Response) { { headers }, ); + const returnData = { + id: data.id, + files: data.files, + }; + res.status(200).json({ success: true, - data, + data: returnData, }); } catch { res.status(500).json({ @@ -145,10 +145,9 @@ async function del(req: Request, res: Response) { async function getCommits(req: Request, res: Response) { try { - const { data } = await axios.get(`${gistsBaseUrl}/${req.params.id}/commits`, { - headers, - params: req.query, - }); + const page = req.query.page ? parseInt(req.query.page as string) : undefined; + const perPage = req.query.per_page ? parseInt(req.query.per_page as string) : undefined; + const data = await GistService.getCommits(req.params.id, perPage, page); const cleanData = data.map((x: IGistCommitItem) => { const { user, url, ...rest } = x; @@ -176,9 +175,7 @@ async function getCommits(req: Request, res: Response) { async function getRevision(req: Request, res: Response) { try { - const { data } = await axios.get(`${gistsBaseUrl}/${req.params.id}/${req.params.sha}`, { - headers, - }); + const data = await GistService.getRevision(req.params.id, req.params.sha); const { owner, @@ -220,4 +217,51 @@ async function getRevision(req: Request, res: Response) { } } -export { get, create, del, update, getCommits, getRevision }; +async function getRevisionsForFile(req: Request, res: Response) { + try { + const gistId = req.params.id; + const file = req.params.file; + + const page = req.query.page ? parseInt(req.query.page as string) : undefined; + const perPage = req.query.per_page ? parseInt(req.query.per_page as string) : undefined; + + const allCommits = await GistService.getCommits(gistId, perPage, page); + const versionsToExclude: string[] = []; + + const promises = allCommits.map((version: IGistCommitItem) => + GistService.getRevision(gistId, version.version).then((revision) => { + if (!revision.files[file]) { + versionsToExclude.push(version.version); + } + }), + ); + + await Promise.all(promises); + + const versions = allCommits + .filter((v: IGistCommitItem) => !versionsToExclude.includes(v.version)) + .map((v: IGistCommitItem) => { + const { user, url, ...rest } = v; + return rest; + }); + + res.status(200).json({ + success: true, + data: versions, + }); + } catch (e) { + if ((e as AxiosError).status === 404) { + res.status(404).json({ + success: false, + message: 'Gist not found', + }); + } else { + res.status(500).json({ + success: false, + message: 'Something went wrong', + }); + } + } +} + +export { get, create, del, update, getCommits, getRevision, getRevisionsForFile }; diff --git a/src/routes/gist-route.ts b/src/routes/gist-route.ts index 588c4a9..693bc18 100644 --- a/src/routes/gist-route.ts +++ b/src/routes/gist-route.ts @@ -1,5 +1,13 @@ import express from 'express'; -import { create, del, get, getCommits, update, getRevision } from '../controllers/gist-controller'; +import { + create, + del, + get, + getCommits, + update, + getRevision, + getRevisionsForFile, +} from '../controllers/gist-controller'; const gistRouter = express.Router(); @@ -9,5 +17,6 @@ gistRouter.delete('/:id', del); gistRouter.patch('/:id', update); gistRouter.get('/:id/commits', getCommits); gistRouter.get('/:id/:sha', getRevision); +gistRouter.get('/:id/file-versions/:file', getRevisionsForFile); export { gistRouter }; diff --git a/src/services/gist-service.ts b/src/services/gist-service.ts new file mode 100644 index 0000000..5fc23d5 --- /dev/null +++ b/src/services/gist-service.ts @@ -0,0 +1,24 @@ +import axios from 'axios'; +import { gistsBaseUrl, headers } from '../constants/gist-constants'; + +export const GistService = { + getCommits: async (gistId: string, perPage?: number, page?: number) => { + const { data } = await axios.get(`${gistsBaseUrl}/${gistId}/commits`, { + headers, + params: { + per_page: perPage, + page, + }, + }); + + return data; + }, + + getRevision: async (gistId: string, sha: string) => { + const { data } = await axios.get(`${gistsBaseUrl}/${gistId}/${sha}`, { + headers, + }); + + return data; + }, +};