From 78f68ff2aaf40b606a72f633260d2537e924c8e8 Mon Sep 17 00:00:00 2001 From: EnixCoda Date: Fri, 22 Feb 2019 12:22:21 +0800 Subject: [PATCH] refactor: types on API --- src/driver/core/FileExplorer.ts | 2 +- src/utils/GitHubHelper.ts | 49 +++++++++++++-------- src/utils/treeParser.ts | 70 ++++++++++++++---------------- src/utils/visibleNodesGenerator.ts | 2 + 4 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/driver/core/FileExplorer.ts b/src/driver/core/FileExplorer.ts index f10c4e0..2469fa1 100644 --- a/src/driver/core/FileExplorer.ts +++ b/src/driver/core/FileExplorer.ts @@ -77,7 +77,7 @@ const setUpTree: MethodCreator = dispatch => () => const blobData = await GitHubHelper.getBlobData({ userName: metaData.userName, repoName: metaData.repoName, - fileSHA: gitModules.sha, + sha: gitModules.sha, accessToken, }) diff --git a/src/utils/GitHubHelper.ts b/src/utils/GitHubHelper.ts index ce1010e..0f6dec2 100644 --- a/src/utils/GitHubHelper.ts +++ b/src/utils/GitHubHelper.ts @@ -48,50 +48,65 @@ export type MetaData = { branchName?: string accessToken?: string type?: PageType - api?: any // it's ok + api?: RepoMetaData } -async function getRepoMeta({ userName, repoName, accessToken }: MetaData) { +type RepoMetaData = { + default_branch: string + html_url: string + owner: { + html_url: string + } +} + +async function getRepoMeta({ userName, repoName, accessToken }: MetaData): Promise { const url = `https://api.github.com/repos/${userName}/${repoName}` return await request(url, { accessToken }) } export type TreeItem = { path: string + mode: string + sha: string + size: number + url: string + type: 'blob' | 'commit' | 'tree' } export type TreeData = { - userName: string - repoName: string - branchName: string - accessToken: string + sha: string + truncated: boolean tree: TreeItem[] + url: string } -async function getTreeData({ userName, repoName, branchName, accessToken }: MetaData) { +async function getTreeData({ + userName, + repoName, + branchName, + accessToken, +}: MetaData): Promise { const url = `https://api.github.com/repos/${userName}/${repoName}/git/trees/${branchName}?recursive=1` return await request(url, { accessToken }) } -export type ItemData = { - userName: string - repoName: string - accessToken?: string -} - export type BlobData = { encoding: 'base64' | string - fileSHA: string + sha: string content?: string + size: number + url: string } async function getBlobData({ userName, repoName, accessToken, - fileSHA, -}: Pick) { - const url = `https://api.github.com/repos/${userName}/${repoName}/git/blobs/${fileSHA}` + sha, +}: Pick & { + sha: string +}): Promise { + const url = `https://api.github.com/repos/${userName}/${repoName}/git/blobs/${sha}` return await request(url, { accessToken }) } diff --git a/src/utils/treeParser.ts b/src/utils/treeParser.ts index d31b4c4..0e64998 100644 --- a/src/utils/treeParser.ts +++ b/src/utils/treeParser.ts @@ -1,36 +1,21 @@ import GitHubHelper, { MetaData, TreeData } from 'utils/GitHubHelper' +import { TreeNode } from './VisibleNodesGenerator' -interface BasicItem { - name: string | null - path: string | null - mode: null - type: string | null - url: string | null +interface RawItem { + name?: string | null + path?: string | null + mode?: string | null + type?: string | null + url?: string | null + sha?: string | null } -interface Folder extends BasicItem { - contents?: Item[] -} +const revert = any>(f: T) => (...args: Parameters) => !f(...args) -interface Blob extends BasicItem { - sha: string | null -} - -type Item = Folder & Blob - -const nodeTemplate: Blob = { - name: null, - path: null, - mode: null, - type: null, - sha: null, - url: null, -} - -const isFolder = (node: BasicItem) => node.type === 'tree' -const isNotFolder = (node: BasicItem) => !isFolder(node) -function sortFoldersToFront(root: Item) { - function depthFirstSearch(root: Item) { +const isFolder = (node: TreeNode) => node.type === 'tree' +const isNotFolder = revert(isFolder) +function sortFoldersToFront(root: TreeNode) { + function depthFirstSearch(root: TreeNode) { const nodes = root.contents if (nodes) { nodes.splice(0, Infinity, ...nodes.filter(isFolder), ...nodes.filter(isNotFolder)) @@ -41,7 +26,7 @@ function sortFoldersToFront(root: Item) { return depthFirstSearch(root) } -function findGitModules(root: Item) { +function findGitModules(root: TreeNode) { if (root.contents) { const modulesFile = root.contents.find(content => content.name === '.gitmodules') if (modulesFile) { @@ -55,19 +40,22 @@ function parse(treeData: TreeData, metaData: MetaData) { const { tree } = treeData // nodes are created from items and put onto tree - const pathToNode = new Map() - const pathToItem = new Map() + const pathToNode = new Map() + const pathToItem = new Map() - const root: Item = { ...nodeTemplate, name: '', path: '', contents: [] } + const root: TreeNode = { name: '', path: '', contents: [], type: 'tree' } pathToNode.set('', root) tree.forEach(item => pathToItem.set(item.path, item)) tree.forEach(item => { // bottom-up search for the deepest node created let path = item.path - const itemsToCreateTreeNode = [] + const itemsToCreateTreeNode: RawItem[] = [] while (path !== '' && !pathToNode.has(path)) { - itemsToCreateTreeNode.push(pathToItem.get(path)) + const item = pathToItem.get(path) + if (item) { + itemsToCreateTreeNode.push(item) + } // 'a/b' -> 'a' // 'a' -> '' path = path.substring(0, path.lastIndexOf('/')) @@ -76,14 +64,20 @@ function parse(treeData: TreeData, metaData: MetaData) { // top-down create nodes while (itemsToCreateTreeNode.length) { const item = itemsToCreateTreeNode.pop() + if (!item) continue const node = { - ...nodeTemplate, ...item, - name: item.path.replace(/^.*\//, ''), - url: item.url ? GitHubHelper.getUrlForRedirect(metaData, item.type, item.path) : null, + name: item.path && item.path.replace(/^.*\//, ''), + url: + item.url && item.type && item.path + ? GitHubHelper.getUrlForRedirect(metaData, item.type, item.path) + : null, contents: item.type === 'tree' ? [] : null, + } as TreeNode + const parentNode = pathToNode.get(path) + if (parentNode && parentNode.contents) { + parentNode.contents.push(node) } - pathToNode.get(path).contents.push(node) pathToNode.set(node.path, node) path = node.path } diff --git a/src/utils/visibleNodesGenerator.ts b/src/utils/visibleNodesGenerator.ts index 3145397..cb862e1 100644 --- a/src/utils/visibleNodesGenerator.ts +++ b/src/utils/visibleNodesGenerator.ts @@ -26,8 +26,10 @@ export type TreeNode = { contents?: TreeNode[] path: string url?: string + sha?: string virtual?: boolean type: 'tree' | 'blob' | 'commit' | 'virtual' + accessDenied?: boolean } const SEARCH_DELAY = 250