refactor: types on API

This commit is contained in:
EnixCoda 2019-02-22 12:22:21 +08:00
parent db5368fef3
commit 78f68ff2aa
No known key found for this signature in database
GPG key ID: 6825847C88AA329A
4 changed files with 67 additions and 56 deletions

View file

@ -77,7 +77,7 @@ const setUpTree: MethodCreator<Props, ConnectorState> = dispatch => () =>
const blobData = await GitHubHelper.getBlobData({
userName: metaData.userName,
repoName: metaData.repoName,
fileSHA: gitModules.sha,
sha: gitModules.sha,
accessToken,
})

View file

@ -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<RepoMetaData> {
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<TreeData> {
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<ItemData & BlobData, 'userName' | 'repoName' | 'accessToken' | 'fileSHA'>) {
const url = `https://api.github.com/repos/${userName}/${repoName}/git/blobs/${fileSHA}`
sha,
}: Pick<MetaData, 'userName' | 'repoName' | 'accessToken'> & {
sha: string
}): Promise<BlobData> {
const url = `https://api.github.com/repos/${userName}/${repoName}/git/blobs/${sha}`
return await request(url, { accessToken })
}

View file

@ -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 = <T extends (...args: any[]) => any>(f: T) => (...args: Parameters<T>) => !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<string, TreeNode>()
const pathToItem = new Map<string, RawItem>()
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
}

View file

@ -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