-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathindex.browser.ts
105 lines (93 loc) · 2.91 KB
/
index.browser.ts
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { FileSystem } from './system'
import JSZip from 'jszip'
class JSZipFS extends FileSystem {
sep = '/'
type: 'zip' | 'path' = 'zip'
writeable = true
root = ''
protected normalizePath(path: string): string {
if (path.startsWith('/')) {
path = path.substring(1)
}
if (this.root !== '') {
path = [this.root, path].join('/')
}
return path
}
join(...paths: string[]): string {
return paths.join('/')
}
isDirectory(name: string): Promise<boolean> {
name = this.normalizePath(name)
name = name.endsWith('/') ? name : name + '/'
return Promise.resolve(Object.keys(this.zip.files).some((e) => e.startsWith(name)))
}
async writeFile(name: string, data: Uint8Array): Promise<void> {
name = this.normalizePath(name)
this.zip.file(name, data)
}
existsFile(name: string): Promise<boolean> {
name = this.normalizePath(name)
if (this.zip.files[name] !== undefined) { return Promise.resolve(true) }
return this.isDirectory(name)
}
readFile(name: any, encoding?: any): Promise<any> {
name = this.normalizePath(name)
if (!encoding) {
return this.zip.files[name].async('uint8array')
}
if (encoding === 'utf-8') {
return this.zip.files[name].async('text')
}
if (encoding === 'base64') {
return this.zip.files[name].async('base64')
}
throw new TypeError(`Expect encoding to be utf-8/base64 or empty. Got ${encoding}.`)
}
async listFiles(name: string): Promise<string[]> {
if (!await this.isDirectory(name)) { return Promise.reject(new TypeError('Require a directory!')) }
name = this.normalizePath(name)
return Promise.resolve(Object.keys(this.zip.files)
.filter((e) => e.startsWith(name))
.map((e) => e.substring(name.length))
.map((e) => e.startsWith('/') ? e.substring(1) : e)
.map((e) => e.split('/')[0]))
}
cd(name: string): void {
if (name.startsWith('/')) {
this.root = name.substring(1)
return
}
const paths = name.split('/')
for (const path of paths) {
if (path === '.') {
continue
} else if (path === '..') {
const sub = this.root.split('/')
if (sub.length > 0) {
sub.pop()
this.root = sub.join('/')
}
} else {
if (this.root === '') {
this.root = path
} else {
this.root += `/${path}`
}
}
}
}
constructor(private zip: JSZip) { super() }
}
export async function openFileSystem(basePath: string | Uint8Array): Promise<FileSystem> {
if (typeof basePath === 'string') { throw new Error('Unsupported') }
return new JSZipFS(await JSZip.loadAsync(basePath))
}
export function resolveFileSystem(base: string | Uint8Array | FileSystem): Promise<FileSystem> {
if (typeof base === 'string' || base instanceof Uint8Array) {
return openFileSystem(base)
} else {
return Promise.resolve(base)
}
}
export * from './system'