@@ -11,19 +11,21 @@ const mkdirp = require('mkdirp')
11
11
const collect = require ( 'collect-stream' )
12
12
const argv = require ( 'yargs' ) . argv
13
13
14
- const { loadMetadata } = require ( './lib/metadata ' )
14
+ const hypercore = require ( 'hypercore ' )
15
15
16
- const Status = {
17
- UNMOUNTED : 0 ,
18
- MOUNTED : 1
19
- }
16
+ const { loadMetadata } = require ( './lib/metadata' )
20
17
21
18
class Hypermount {
22
- constructor ( store ) {
19
+ constructor ( store , db ) {
23
20
this . store = store
21
+ this . db = db
24
22
this . drives = new Map ( )
25
23
}
26
24
25
+ ready ( ) {
26
+ return this . store . ready ( )
27
+ }
28
+
27
29
async mount ( key , mnt , opts ) {
28
30
if ( typeof opts === 'function' ) return this . mount ( key , mnt , null , opts )
29
31
opts = opts || { }
@@ -32,14 +34,18 @@ class Hypermount {
32
34
coreOpts . seed = ( opts . seed !== undefined ) ? opts . seed : true
33
35
return this . store . get ( key , coreOpts )
34
36
}
37
+
35
38
const drive = hyperdrive ( factory , key , {
36
39
...opts ,
37
40
factory : true ,
38
41
sparse : ( opts . sparse !== undefined ) ? opts . sparse : true ,
39
42
sparseMetadata : ( opts . sparseMetadata !== undefined ) ? opts . sparseMetadata : true
40
43
} )
41
44
42
- const mountInfo = await hyperfuse . mount ( drive , mnt )
45
+ const mountInfo = await hyperfuse . mount ( drive , mnt , {
46
+ force : true ,
47
+ displayFolder : true
48
+ } )
43
49
this . drives . set ( mountInfo . key , drive )
44
50
45
51
return mountInfo
@@ -52,32 +58,89 @@ class Hypermount {
52
58
close ( ) {
53
59
return this . store . close ( )
54
60
}
55
- }
56
61
57
- async function start ( ) {
58
- const metadata = await loadMetadata ( )
59
- const storageRoot = argv . storage || './storage'
62
+ async mount ( key , mnt , opts ) {
63
+ let { key : mountedKey } = await this . mount ( key , mnt , opts )
60
64
61
- await ( ( ) => {
65
+ await this . db . put ( mnt , {
66
+ ...opts ,
67
+ key : mountedKey ,
68
+ mnt
69
+ } )
70
+
71
+ return mountedKey
72
+ }
73
+
74
+ async unmount ( mnt ) {
75
+ await this . unmount ( mnt )
76
+
77
+ let record = await this . db . get ( mnt )
78
+ if ( ! record ) return
79
+
80
+ await this . db . put ( mnt , record )
81
+ }
82
+
83
+ unmountAll ( ) {
62
84
return new Promise ( ( resolve , reject ) => {
63
- mkdirp ( storageRoot , err => {
64
- if ( err ) return reject ( err )
65
- return resolve ( )
85
+ pump (
86
+ this . db . createReadStream ( ) ,
87
+ through . obj ( ( { key, value : record } , enc , cb ) => {
88
+ let unmountPromise = this . unmount ( key )
89
+ unmountPromise . then ( ( ) => cb ( null ) )
90
+ unmountPromise . catch ( err => cb ( err ) )
91
+ } ) ,
92
+ err => {
93
+ if ( err ) return reject ( err )
94
+ return resolve ( )
95
+ }
96
+ )
97
+ } )
98
+ }
99
+
100
+ refreshMounts ( ) {
101
+ return new Promise ( ( resolve , reject ) => {
102
+ pump (
103
+ this . db . createReadStream ( ) ,
104
+ through . obj ( ( { key, value : record } , enc , cb ) => {
105
+ const mountPromise = this . mount ( record . key , key , record )
106
+ mountPromise . then ( ( ) => cb ( null ) )
107
+ mountPromise . catch ( cb )
108
+ } ) ,
109
+ err => {
110
+ if ( err ) return reject ( err )
111
+ return resolve ( )
112
+ }
113
+ )
114
+ } )
115
+ }
116
+
117
+ list ( ) {
118
+ return new Promise ( ( resolve , reject ) => {
119
+ const result = { }
120
+ const stream = this . db . createReadStream ( )
121
+ stream . on ( 'data' , ( { key : mnt , value : record } ) => {
122
+ const entry = result [ record . key ] = { mnt }
123
+ const drive = this . drives . get ( record . key )
124
+ entry . networking = {
125
+ metadata : drive . metadata . stats ,
126
+ content : drive . content && drive . content . stats
127
+ }
128
+ } )
129
+ stream . on ( 'end' , ( ) => {
130
+ return resolve ( result )
66
131
} )
132
+ stream . on ( 'error' , reject )
67
133
} )
68
- } ) ( )
134
+ }
69
135
70
- const store = corestore ( p . join ( storageRoot , 'cores' ) , {
71
- network : {
72
- port : argv . replicationPort || 3006
73
- }
74
- } )
75
- const db = level ( p . join ( storageRoot , 'db' ) , {
76
- valueEncoding : 'json'
77
- } )
78
- const hypermount = new Hypermount ( store )
79
- const app = express ( )
136
+ async cleanup ( ) {
137
+ await this . unmountAll ( )
138
+ await this . store . close ( )
139
+ await this . db . close ( )
140
+ }
141
+ }
80
142
143
+ function bindRoutes ( app , hypermount ) {
81
144
app . use ( express . json ( ) )
82
145
app . use ( ( req , res , next ) => {
83
146
if ( ! req . headers . authorization ) return res . sendStatus ( 403 )
@@ -88,7 +151,7 @@ async function start () {
88
151
app . post ( '/mount' , async ( req , res ) => {
89
152
try {
90
153
let { key, mnt } = req . body
91
- key = await mount ( hypermount , db , key , mnt , req . body )
154
+ key = await hypermount . mount ( key , mnt , req . body )
92
155
return res . status ( 201 ) . json ( { key, mnt } )
93
156
} catch ( err ) {
94
157
console . error ( 'Mount error:' , err )
@@ -99,7 +162,7 @@ async function start () {
99
162
app . post ( '/unmount' , async ( req , res ) => {
100
163
try {
101
164
const mnt = req . body . mnt
102
- await unmount ( hypermount , db , mnt )
165
+ await hypermount . unmount ( mnt )
103
166
104
167
return res . sendStatus ( 200 )
105
168
} catch ( err ) {
@@ -124,113 +187,56 @@ async function start () {
124
187
125
188
app . get ( '/list' , async ( req , res ) => {
126
189
try {
127
- let result = await list ( hypermount , db )
190
+ let result = await hypermount . list ( )
128
191
return res . json ( result )
129
192
} catch ( err ) {
130
193
console . error ( 'List error:' , err )
131
194
return res . sendStatus ( 500 )
132
195
}
133
196
} )
134
-
135
- await store . ready ( )
136
- await refreshMounts ( hypermount , db )
137
-
138
- process . once ( 'SIGINT' , cleanup )
139
- process . once ( 'SIGTERM' , cleanup )
140
-
141
- var server = app . listen ( argv . port || 3005 )
142
-
143
- async function cleanup ( ) {
144
- await unmountAll ( hypermount , db )
145
- await store . close ( )
146
- await db . close ( )
147
- server . close ( )
148
- }
149
197
}
150
198
151
- function list ( hypermount , db ) {
152
- return new Promise ( ( resolve , reject ) => {
153
- const result = { }
154
- const stream = db . createReadStream ( )
155
- stream . on ( 'data' , ( { key : mnt , value : record } ) => {
156
- const entry = result [ record . key ] = { mnt }
157
- const drive = hypermount . drives . get ( record . key )
158
- entry . networking = {
159
- metadata : drive . metadata . stats ,
160
- content : drive . content && drive . content . stats
161
- }
162
- } )
163
- stream . on ( 'end' , ( ) => {
164
- return resolve ( result )
165
- } )
166
- stream . on ( 'error' , reject )
167
- } )
168
- }
199
+ async function start ( ) {
200
+ const metadata = await loadMetadata ( )
201
+ const storageRoot = argv . storage || './storage'
169
202
170
- async function mount ( hypermount , db , key , mnt , opts ) {
171
- let { key : mountedKey } = await hypermount . mount ( key , mnt , opts )
203
+ await ( ( ) => {
204
+ return new Promise ( ( resolve , reject ) => {
205
+ mkdirp ( storageRoot , err => {
206
+ if ( err ) return reject ( err )
207
+ return resolve ( )
208
+ } )
209
+ } )
210
+ } ) ( )
172
211
173
- await db . put ( mnt , {
174
- ...opts ,
175
- key : mountedKey ,
176
- mnt,
177
- status : Status . MOUNTED
212
+ const store = corestore ( p . join ( storageRoot , 'cores' ) , {
213
+ network : {
214
+ port : argv . replicationPort || 3006
215
+ }
178
216
} )
217
+ const db = level ( p . join ( storageRoot , 'db' ) , {
218
+ valueEncoding : 'json'
219
+ } )
220
+ const hypermount = new Hypermount ( store , db )
221
+ const app = express ( )
179
222
180
- return mountedKey
181
- }
182
-
183
- async function unmount ( hypermount , db , mnt ) {
184
- await hypermount . unmount ( mnt )
223
+ await hypermount . ready ( )
224
+ await hypermount . refreshMounts ( )
185
225
186
- let record = await db . get ( mnt )
187
- if ( ! record ) return
188
- record . status = Status . UNMOUNTED
226
+ bindRoutes ( app , hypermount )
227
+ var server = app . listen ( argv . port || 3005 )
189
228
190
- await db . put ( mnt , record )
191
- }
229
+ process . once ( 'SIGINT' , cleanup )
230
+ process . once ( 'SIGTERM' , cleanup )
231
+ process . once ( 'unhandledRejection' , cleanup )
232
+ process . once ( 'uncaughtException' , cleanup )
192
233
193
- function unmountAll ( hypermount , db ) {
194
- return new Promise ( ( resolve , reject ) => {
195
- pump (
196
- db . createReadStream ( ) ,
197
- through . obj ( ( { key, value : record } , enc , cb ) => {
198
- if ( record . status === Status . MOUNTED ) {
199
- let unmountPromise = unmount ( hypermount , db , key )
200
- unmountPromise . then ( ( ) => cb ( null ) )
201
- unmountPromise . catch ( err => cb ( err ) )
202
- } else {
203
- return cb ( null )
204
- }
205
- } ) ,
206
- err => {
207
- if ( err ) return reject ( err )
208
- return resolve ( )
209
- }
210
- )
211
- } )
234
+ async function cleanup ( ) {
235
+ await hypermount . cleanup ( )
236
+ server . close ( )
237
+ }
212
238
}
213
239
214
- function refreshMounts ( hypermount , db ) {
215
- return new Promise ( ( resolve , reject ) => {
216
- pump (
217
- db . createReadStream ( ) ,
218
- through . obj ( ( { key, value : record } , enc , cb ) => {
219
- if ( record . status === Status . UNMOUNTED ) {
220
- const mountPromise = mount ( hypermount , db , record . key , key , record )
221
- mountPromise . then ( ( ) => cb ( null ) )
222
- mountPromise . catch ( cb )
223
- } else {
224
- return cb ( null )
225
- }
226
- } ) ,
227
- err => {
228
- if ( err ) return reject ( err )
229
- return resolve ( )
230
- }
231
- )
232
- } )
233
- }
234
240
235
241
if ( require . main === module ) {
236
242
start ( )
0 commit comments