UNPKG

@demobook/server

Version:

## Setup

250 lines (204 loc) 6.08 kB
import { Request, Response } from 'express'; import { createDir, moveFiles, deleteDir } from '../deploy'; import { getComments, postCommentToPR, editComment } from '../bot'; import { generateOutput } from '../output'; import { Redis } from '../Redis'; export interface Item { dir: string; url: string; prNum: number | null; projectName: string; dateNum: number; totalSize: number; } const redis = new Redis(); redis.subscribeExpired(async (keyEvent, key) => { try { await deleteDir(key); } catch (e) { throw e; } }); // TODO: use websocket export async function getTimeSequence(req: Request, res: Response) { const keys = await redis.getKeys('*'); const demos = []; for (const item of keys) { const demo = await redis.get(item); const [, owner, repo, hash] = item.split('/'); demos.push({ ...demo, owner, key: hash, repo, url: `${process.env.URL}/demos/${owner}/${repo}/${hash}`, }); } const schema = demos.sort((a, b) => b.dateNum - a.dateNum); return res.json(schema); } type Owner = { name: string; url: string; updatedAt: number; demosNum: number; totalSize: number; }; export async function getOwners(req: Request, res: Response) { const keys = await redis.getKeys('*'); const schema: Record<string, Omit<Owner, 'name'>> = {}; for (const item of keys) { const demo = await redis.get(item); const [, owner, ,] = item.split('/'); if (!schema[owner]) { schema[owner] = { url: `${process.env.GITHUB_URL}/${owner}`, updatedAt: -1, demosNum: 0, totalSize: 0, }; } schema[owner]['demosNum']++; schema[owner]['totalSize'] += demo.totalSize; if (schema[owner]['updatedAt'] < demo.dateNum) schema[owner]['updatedAt'] = demo.dateNum; } return res.json(schema); } type Repo = { key: string; prUrl: string; totalSize: number; dateNum: number; }; // repo url export async function getRepos(req: Request, res: Response) { const { owner: name } = req.params; const keys = await redis.getKeys(`${process.env.OUTPUT_DIR}/${name}/*`); const schema: { owner: Owner; repos: Record<string, Repo[]>; } = { owner: { url: `${process.env.GITHUB_URL}/${name}`, name, demosNum: keys.length, totalSize: 0, updatedAt: -1, }, repos: {}, }; for (const item of keys) { const demo = await redis.get(item); const [, owner, repo, hash] = item.split('/'); if (!schema['repos'][repo]) schema['repos'][repo] = []; const prUrl = demo.prNum ? `${process.env.GITHUB_URL}/${owner}/${repo}/pull/${demo.prNum}` : null; schema['repos'][repo].push({ ...demo, key: hash, prUrl, }); schema['owner']['totalSize'] += demo.totalSize; if (schema['owner']['updatedAt'] < demo.dateNum) schema['owner']['updatedAt'] = demo.dateNum; } Object.entries(schema['repos']).forEach(([key, value]) => { // @ts-expect-error schema['repos'][key] = (value as Array<Item>).sort((a, b) => b.dateNum - a.dateNum); }); return res.json(schema); } export async function getDemos(req: Request, res: Response) {} export async function getAll(req: Request, res: Response) { const keys = await redis.getKeys('*'); const schema: Record<string, Record<string, Repo[]>> = {}; for (const item of keys) { const r = await redis.get(item); const [, owner, repo, hash] = item.split('/'); if (!schema[owner]) schema[owner] = {}; if (!schema[owner][repo]) schema[owner][repo] = []; schema[owner][repo].push({ key: hash, ...r, }); } return res.json(schema); } interface PostDemos extends Request { body: { file_path: Array<{ name: string; }>; name: string; pr_num: string; }; } export async function post(req: PostDemos, res: Response) { try { const { owner, repo } = req.params; // @ts-expect-error const dir = await createDir(req.params); let projectName, prNum, files, totalSize = 0; if (typeof req.body['file_path'] === 'string') { projectName = req.body['name'] || 'main'; prNum = req.body['pr_num'] ? Number(req.body['pr_num']) : null; // @ts-expect-error const info = req.files[0]; files = [ { name: req.body['file_path'], buffer: info.buffer, }, ]; totalSize = info.buffer.byteLength; } else { projectName = req.body['name'] && Array.isArray(req.body['name']) ? req.body['name'][0] : 'main'; prNum = req.body['pr_num'] && Array.isArray(req.body['pr_num']) ? Number(req.body['pr_num'][0]) : null; files = req.body['file_path'].map((name, i) => { // @ts-expect-error const info = req.files[i]; totalSize += info.buffer.byteLength; return { name: name, buffer: info.buffer, }; }); } await moveFiles(files, dir); const url = `${process.env.URL}/${dir}`.replace(process.env.OUTPUT_DIR || '', 'demos'); const item = { dir, url, prNum, projectName, dateNum: Date.now(), totalSize, }; await redis.set(item); if (prNum) { const comments = await getComments({ owner, repo, number: prNum }); // if bot exists, overwrite the comment // const existedComment = comments.data.find((comment: GetCommentsForRepoResponseItem) => { const existedComment = comments.data.find((comment: any) => { if (comment.user.login === process.env.GITHUB_USER_NAME) return true; return false; }); const body = generateOutput(item, existedComment?.body ?? null); if (existedComment) { await editComment({ owner, repo, body, id: String(existedComment.id) }); } else { await postCommentToPR({ owner, repo, number: prNum, body }); } } return res.json({ url }); } catch (e) { return res.status(500).json({ message: (e as Error).message }); } }