-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.mjs
79 lines (71 loc) · 2.68 KB
/
index.mjs
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
import nodeId from './cdt/node-id.mjs'
import forest from './forest/index.mjs'
import getModule from './forest/index.mjs'
/** @typedef {import('./cdt/main-tree.mjs').State} StateTree */
/**
* @template T
* @typedef {import('./cdt/sub-tree.mjs').Nullable<T>} Nullable
*/
/** @typedef {import('./forest/index.mjs').ForestNodeId} ForestNodeId */
/** @typedef {import('./forest/index.mjs').ForestGet} ForestGet */
/** @typedef {import('./io/io.mjs').IO} IO */
/** @typedef {{[index: string] : Uint8Array | undefined}} Cache */
const { get } = getModule
/** @type {(forestNodeId: ForestNodeId) => string} */
const getPath = ([forestNodeId, isRoot]) => {
const dir = isRoot ? 'roots' : 'parts'
return `cdt0/${dir}/${forestNodeId.substring(0, 2)}/${forestNodeId.substring(2, 4)}/${forestNodeId.substring(4)}`
}
/** @type {(hostName: string) => (io: IO) => (forestNodeId: ForestNodeId) => Promise<Uint8Array>} */
const fetchRead = hostName => ({ fetch }) => forestNodeId => fetch(`https://${hostName}/${getPath(forestNodeId)}`)
.then(async (resp) => resp.arrayBuffer().then(buffer => new Uint8Array(buffer)))
/** @type {(mem: Cache) => (forestGet: ForestGet) => ForestGet} */
const cache = mem => forestGet => {
return async (nodeId) => {
const nodeIdString = `${nodeId[0]}${nodeId[1]}`
let buffer = mem[nodeIdString]
if (buffer !== undefined) {
return buffer
}
buffer = await forestGet(nodeId)
mem[nodeIdString] = buffer
return buffer
}
}
/** @type {(mem: Cache) => (io: IO) => (root: [string, string]) => Promise<number>} */
const getLocal = mem => io => async ([root, file]) => {
const tempFile = `_temp_${root}`
await io.write(tempFile, new Uint8Array())
/** @type {ForestGet} */
const read = cache(mem)(forestNodeId => io.read(getPath(forestNodeId)))
/** @type {(buffer: Uint8Array) => Promise<void>} */
const write = buffer => io.append(tempFile, buffer)
const error = await get({ read, write })(root)
if (error !== null) {
io.console.error(error)
return -1
}
await io.rename(tempFile, file)
return 0
}
/** @type {(mem: Cache) => (host: string) => (io: IO) => (root: [string, string]) => Promise<number>} */
const getRemote = mem => host => io => async ([root, file]) => {
const tempFile = `_temp_${root}`
await io.write(tempFile, new Uint8Array())
/** @type {ForestGet} */
const read = cache(mem)(fetchRead(host)(io))
/** @type {(buffer: Uint8Array) => Promise<void>} */
const write = buffer => io.append(tempFile, buffer)
const error = await get({ read, write })(root)
if (error !== null) {
io.console.error(error)
return -1
}
await io.rename(tempFile, file)
return 0
}
export default {
getLocal,
getRemote,
fetchRead
}