Skip to content
This repository was archived by the owner on Jan 7, 2022. It is now read-only.

Commit 318dd07

Browse files
author
Joe Hand
authored
Sleep support (#128)
* basic sleep implementation * owner -> writable * cleanup * add secret key storage * use network speed again * better storage * better storage init, mirror-folder, clean deps * add jsdoc + cleanup * upgrade mirror-folder & live-> watch * start updating tests * add temp share test * take out dat-secret-storage for now * update import tests + fix opts bug * add downloader to example * remove network tests for now * upgrade standard * update misc tests * update more tests * add helpers * disable live test on travis * update readme * add concurrent import test * clarify examples * fix link * remove todo
1 parent 9dc73f8 commit 318dd07

File tree

18 files changed

+1137
-1480
lines changed

18 files changed

+1137
-1480
lines changed

dat.js

Lines changed: 98 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,40 @@ var assert = require('assert')
22
var path = require('path')
33
var multicb = require('multicb')
44
var xtend = require('xtend')
5+
var untildify = require('untildify')
56
var importFiles = require('./lib/import-files')
67
var createNetwork = require('./lib/network')
78
var stats = require('./lib/stats')
89
var debug = require('debug')('dat-node')
910

1011
module.exports = Dat
1112

12-
function Dat (archive, db, opts) {
13-
if (!(this instanceof Dat)) return new Dat(archive, db, opts)
14-
if (typeof opts === 'undefined') return Dat(archive, null, db)
13+
/**
14+
* @class Dat
15+
* @type {Object}
16+
* @param {Object} archive - Hyperdrive archive
17+
* @param {Object} [opts] - Options
18+
* @param {String} [opts.dir] - Directory of archive
19+
*
20+
* @property {Object} archive - Hyperdrive Archive
21+
* @property {String} path - Resolved path of archive
22+
* @property {Buffer} key - Archive Key (`archive.key`)
23+
* @property {Boolean} live - Archive is live (`archive.live`)
24+
* @property {Boolean} writable - Archive is writable (`archive.metadata.writable`)
25+
* @property {Boolean} version - Archive version (`archive.version`)
26+
* @property {Object} options - Initial options and all options passed to childen functions.
27+
* @returns {Object} Dat
28+
*/
29+
function Dat (archive, opts) {
30+
if (!(this instanceof Dat)) return new Dat(archive, opts)
1531
assert.ok(archive, 'archive required')
16-
// assert.ok(db, 'database required') // maybe not be required for multidrive...
17-
assert.ok(opts.dir, 'opts.directory required')
18-
19-
this.path = path.resolve(opts.dir)
20-
this.options = xtend(opts)
32+
var self = this
2133

2234
this.archive = archive
23-
this.db = db
24-
25-
var self = this
35+
this.options = xtend(opts)
36+
if (opts.dir) {
37+
this.path = path.resolve(untildify(opts.dir))
38+
}
2639

2740
// Getters for convenience accessors
2841
Object.defineProperties(this, {
@@ -38,23 +51,36 @@ function Dat (archive, db, opts) {
3851
return self.archive.live
3952
}
4053
},
41-
owner: {
54+
resumed: {
4255
enumerable: true,
4356
get: function () {
44-
return self.archive.owner
57+
return self.archive.resumed
4558
}
4659
},
47-
resumed: {
60+
writable: {
4861
enumerable: true,
4962
get: function () {
50-
return self.archive.resumed
63+
return self.archive.metadata.writable
64+
}
65+
},
66+
version: {
67+
enumerable: true,
68+
get: function () {
69+
return self.archive.version
5170
}
5271
}
5372
})
5473
}
5574

56-
Dat.prototype.join =
57-
Dat.prototype.joinNetwork = function (opts, cb) {
75+
/**
76+
* Join Dat Network via Hyperdiscovery
77+
* @type {Function}
78+
* @param {Object} [opts] - Network options, passed to hyperdiscovery.
79+
* @param {Function} [cb] - Callback after first round of discovery is finished.
80+
* @returns {Object} Discovery Swarm Instance
81+
*/
82+
Dat.prototype.joinNetwork =
83+
Dat.prototype.join = function (opts, cb) {
5884
if (typeof opts === 'function') {
5985
cb = opts
6086
opts = {}
@@ -69,97 +95,116 @@ Dat.prototype.joinNetwork = function (opts, cb) {
6995
stream: function (peer) {
7096
var stream = self.archive.replicate({
7197
upload: !(opts.upload === false),
72-
download: !self.archive.owner && opts.download
98+
download: !self.writable && opts.download,
99+
live: !self.writable && !opts.end
73100
})
74101
stream.on('error', function (err) {
75102
debug('Replication error:', err.message)
76103
})
104+
stream.on('end', function () {
105+
self.downloaded = true
106+
debug('Replication stream ended')
107+
})
77108
return stream
78109
}
79110
}, opts)
80111

81112
var network = self.network = createNetwork(self.archive, netOpts, cb)
82113
self.options.network = netOpts
83-
network.swarm = network // 1.0 backwards compat. TODO: Remove in v2
84-
85-
if (self.owner) return network
86114

87-
network.once('connection', function () {
88-
// automatically open archive
89-
self.archive.open(noop)
90-
})
91115
return network
92116
}
93117

94-
Dat.prototype.leave =
95-
Dat.prototype.leaveNetwork = function (cb) {
118+
/**
119+
* Leave Dat Network
120+
* @type {Function}
121+
* @param {Function} [cb] - Callback after network is closed
122+
*/
123+
Dat.prototype.leaveNetwork =
124+
Dat.prototype.leave = function (cb) {
96125
if (!this.network) return
97126
debug('leaveNetwork()')
98-
this.archive.unreplicate()
127+
// TODO: v8 unreplicate ?
128+
// this.archive.unreplicate()
99129
this.network.leave(this.archive.discoveryKey)
100130
this.network.destroy(cb)
101131
delete this.network
102132
}
103133

134+
/**
135+
* Pause Dat Network
136+
* @type {Function}
137+
*/
104138
Dat.prototype.pause = function () {
105139
debug('pause()')
106140
this.leave()
107141
}
108142

143+
/**
144+
* Resume Dat Network
145+
* @type {Function}
146+
*/
109147
Dat.prototype.resume = function () {
110148
debug('resume()')
111149
this.join()
112150
}
113151

152+
/**
153+
* Track archive stats
154+
* @type {Function}
155+
*/
114156
Dat.prototype.trackStats = function (opts) {
115-
opts = opts || {}
116-
assert.ok(opts.db || this.db, 'Dat needs database to track stats')
117-
this.stats = stats(this.archive, opts.db || this.db)
157+
opts = xtend({}, opts)
158+
this.stats = stats(this.archive, opts)
118159
return this.stats
119160
}
120161

121-
Dat.prototype.importFiles = function (target, opts, cb) {
122-
if (!this.archive.owner) throw new Error('Must be archive owner to import files.')
123-
if (typeof target !== 'string') return this.importFiles('', target, opts)
124-
if (typeof opts === 'function') return this.importFiles(target, {}, opts)
162+
/**
163+
* Import files to archive via mirror-folder
164+
* @type {Function}
165+
* @param {String} [src=dat.path] - Directory or File to import to `archive`.
166+
* @param {Function} [cb] - Callback after import is finished
167+
* @param {Object} [opts] - Options passed to `mirror-folder` and `dat-ignore`
168+
* @returns {Object} - Import progress
169+
*/
170+
Dat.prototype.importFiles = function (src, opts, cb) {
171+
if (!this.writable) throw new Error('Must be archive owner to import files.')
172+
if (typeof src !== 'string') return this.importFiles('', src, opts)
173+
if (typeof opts === 'function') return this.importFiles(src, {}, opts)
125174

126175
var self = this
127-
target = target && target.length ? target : self.path
176+
src = src && src.length ? src : self.path
128177
opts = xtend({
129-
indexing: opts && opts.indexing || (target === self.path)
178+
indexing: (opts && opts.indexing) || (src === self.path)
130179
}, opts)
131180

132-
self.importer = importFiles(self.archive, target, opts, cb)
181+
self.importer = importFiles(self.archive, src, opts, cb)
133182
self.options.importer = self.importer.options
134183
return self.importer
135184
}
136185

186+
/**
187+
* Close Dat archive and other things
188+
* @type {Function}
189+
* @param {Function} [cb] - Callback after all items closed
190+
*/
137191
Dat.prototype.close = function (cb) {
138192
cb = cb || noop
139193
if (this._closed) return cb(new Error('Dat is already closed'))
140194

141195
var self = this
142196
self._closed = true
143-
self.archive.unreplicate()
144197

145198
var done = multicb()
146199
closeNet(done())
147200
closeFileWatch(done())
148-
closeArchiveDb(done())
201+
closeArchive(done())
149202

150203
done(cb)
151204

152-
function closeArchiveDb (cb) {
153-
self.archive.close(function (err) {
154-
if (err) return cb(err)
155-
if (self.options.db || !self.db) return cb(null)
156-
closeDb(cb)
157-
})
158-
}
159-
160-
function closeDb (cb) {
161-
if (!self.db) return cb()
162-
self.db.close(cb)
205+
function closeArchive (cb) {
206+
// self.archive.unreplicate()
207+
self.archive.close(cb)
163208
}
164209

165210
function closeNet (cb) {
@@ -169,11 +214,8 @@ Dat.prototype.close = function (cb) {
169214

170215
function closeFileWatch (cb) {
171216
if (!self.importer) return cb()
172-
self.importer.close()
173-
process.nextTick(function () {
174-
// TODO: dat importer close is currently sync-ish
175-
cb()
176-
})
217+
self.importer.destroy()
218+
process.nextTick(cb)
177219
}
178220
}
179221

examples/download.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
var fs = require('fs')
2+
var path = require('path')
3+
var mirror = require('mirror-folder')
4+
var ram = require('random-access-memory')
5+
var Dat = require('..')
6+
7+
var key = process.argv[2]
8+
if (!key) {
9+
console.error('Run with: node examples/download.js <key>')
10+
process.exit(1)
11+
}
12+
13+
var dest = path.join(__dirname, 'tmp')
14+
fs.mkdirSync(dest)
15+
16+
Dat(ram, {key: key, sparse: true}, function (err, dat) {
17+
if (err) throw err
18+
19+
var network = dat.joinNetwork()
20+
network.once('connection', function () {
21+
console.log('Connected')
22+
})
23+
dat.archive.metadata.update(download)
24+
25+
function download () {
26+
var progress = mirror({fs: dat.archive, name: '/'}, dest, function (err) {
27+
if (err) throw err
28+
console.log('Done')
29+
})
30+
progress.on('put', function (src) {
31+
console.log('Downloading', src.name)
32+
})
33+
}
34+
35+
console.log(`Downloading: ${dat.key.toString('hex')}\n`)
36+
})

examples/readme.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Run Example
2+
3+
The example will import all the files in the repo and then download them.
4+
5+
## Share
6+
7+
```
8+
node examples/share.js
9+
```
10+
11+
Copy key printed.
12+
13+
## Download
14+
15+
```
16+
node examples/download.js <key>
17+
```
18+
19+
This will download all files to `examples/tmp`. If not something may be broken.

examples/share.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
var path = require('path')
2+
var Dat = require('..')
3+
4+
var src = path.join(__dirname, '..')
5+
6+
Dat(src, {temp: true}, function (err, dat) {
7+
if (err) throw err
8+
9+
var network = dat.joinNetwork()
10+
network.once('connection', function () {
11+
console.log('Connected')
12+
})
13+
var progress = dat.importFiles(src, {
14+
ignore: ['**/dat-node/node_modules/**']
15+
}, function (err) {
16+
if (err) throw err
17+
console.log('Done importing')
18+
console.log('Archive size:', dat.archive.content.byteLength)
19+
})
20+
progress.on('put', function (src, dest) {
21+
console.log('Added', dest.name)
22+
})
23+
24+
console.log(`Sharing: ${dat.key.toString('hex')}\n`)
25+
})

0 commit comments

Comments
 (0)