forked from RangerMauve/resolve-dat-path
/
index.js
90 lines (84 loc) · 1.98 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
const MANIFEST_LOCATION = '/bit.json'
const CHECK_PATHS = [
path => path,
path => `${path}index.html`,
path => `${path}index.md`,
path => `${path}/index.html`,
path => `${path}/index.md`,
path => `${path}.html`,
path => `${path}.md`
]
module.exports = async function resolveFileInArchive (archive, path) {
let {
web_root: webRoot = '',
fallback_page: fallbackPage
} = await getManifest(archive)
if (!path.startsWith('/')) {
path = `/${path}`
}
path = `${webRoot}${path}`
for (const makePath of CHECK_PATHS) {
const file = await getEntry(archive, makePath(path), 'file')
if (file) {
return file
}
}
const dir = await getEntry(archive, path, 'directory')
if (dir) {
return dir
}
if (fallbackPage) {
if (!fallbackPage.startsWith('/')) {
fallbackPage = `/${fallbackPage}`
}
let file
file = await getEntry(archive, fallbackPage, 'file')
if (file) {
return file
}
file = await getEntry(archive, `${webRoot}${fallbackPage}`, 'file')
if (file) {
return file
}
}
throw new Error('Not Found')
}
async function getManifest (archive) {
try {
const rawManifest = await readFile(archive, MANIFEST_LOCATION, 'utf-8')
return JSON.parse(rawManifest) || {}
} catch (error) {
// Oh well
return {}
}
}
async function getEntry (archive, path, type) {
try {
const stat = await asyncStat(archive, path)
if (
(type === 'directory' && stat.isDirectory()) ||
(type === 'file' && stat.isFile())
) {
return {
type,
path,
stat
}
}
} catch (error) {
// Oh well
}
return null
}
const asyncStat = (archive, path) => new Promise((resolve, reject) =>
archive.stat(path, (err, stat) => {
if (err) reject(err)
else resolve(stat)
})
)
const readFile = (archive, file, encoding) => new Promise((resolve, reject) =>
archive.readFile(file, encoding, (err, data) => {
if (err) reject(err)
else resolve(data)
})
)