dat-node

Dat is a decentralized tool for distributing data and
files, built for scientific and research data.
You can start using Dat today in these client applications:
dat-node is a high-level module to help
you build node applications using Dat on the file system.
See dat-js if you want to build browser-friendly Dat applications.
Read about the Dat protocol at datprotocol.com
Features
Goal of dat-node
Dat-node's primary goals are:
- consistent management of Dat archives on the file system. The Dat CLI uses Dat-node. Any applications built using dat-node will be compatible with the Dat CLI and each other.
- High-level glue for common Dat and hyperdrive modules, including: hyperdiscovery, hyperdrive-stats, and hyperdrive-import-files.
Usage
dat-node manages a single archive inside of a folder. The folder contains the files you want to share or where the files will be downloaded. A .dat
folder will be created inside the archive folder for the database.
Creating a Dat Archive
Create a Dat archive on the file system inside dir
:
var Dat = require('dat-node')
Dat(dir, function (err, dat) {
console.log(dat.path)
var db = dat.db
var archive = dat.archive
var key = dat.key
var importer = dat.importFiles(opts, cb)
})
This will create a .dat
folder inside dir
and import all the files within that directory.
To share the directory, you can join the network:
Dat(dir, function (err, dat) {
var importer = dat.importFiles(function () {
console.log('Done importing')
})
var network = dat.joinNetwork()
console.log('Share your dat:', dat.key.toString('hex'))
})
This will join the network as soon as you start importing files. This means peers can download files as soon as they are imported!
Downloading a Dat archive
Downloading a Dat archive is similar, but you also have to pass `{key: <download-key} as an option. You have to join the network in order for downloads to start!
var Dat = require('dat-node')
Dat(dir, {key: 'download-key'}, function (err, dat) {
var network = dat.joinNetwork(opts)
network.swarm
network.connected
var stats = dat.trackStats()
stats.network
})
Dat-node uses hyperdrive stats to track how much has been downloaded so you can display progress and exit when the download is finished.
FAQ
How do I start/stop replicating an archive?
Dat-node will automatically start replication when you join the network (dat.joinNetwork
). To stop replicating an archive, leave the network (dat.leave()
).
Example Applications
- dat-next: We use dat-node in the dat-next CLI. See that for a full example of how to use dat-node.
- YOUR APP HERE. Use dat-node in an interesting use case? Send us your example!
API
`Dat(dir|drive, [opts], cb)``
Initialize a Dat Archive in dir
. If there is an existing Dat Archive, the archive will be resumed. You can also pass a hyperdrive
instance.
dir
or opts.dir
is always required.
Most options are passed directly to the module you're using (e.g. dat.importFiles(opts)
. However, there are also some initial opts
can include:
opts = {
dir: 'some/dir',
key: '<dat-key>',
db: level(path.join(opts.dir, '.dat'))
live: false,
file: raf(path.join(opts.dir, name)),
sparse: false,
createIfMissing: true,
errorIfExists: false,
dbPath: path.join(opts.dir,'.dat')
}
The callback, cb(err, dat)
, includes a dat
object that has the following properties:
dat.key
: key of the dat (this will be set later for non-live archives)dat.archive
: Hyperdrive archive instance.dat.db
: leveldb database in .dat
folderdat.path
: Path of the Dat Archivedat.live
: archive.live
dat.owner
: archive.owner
dat.resumed
: true
if the archive was resumed from an existing databasedat.options
: All options passed to Dat and the other submodules
Module Interfaces
dat-node
provides an easy interface to common Dat modules for the created Dat Archive on the dat
object provided in the callback:
var network = dat.joinNetwork([opts])
Join the network to start transferring data for dat.key
, using hyperdiscovery. You can also can use dat.join([opts])
.
Returns a network
object with properties:
network.connected
- number of peers connectednetwork.on('listening')
- emitted with network is listeningnetwork.on('connection', connection, info)
- Emitted when you connect to another peer. Info is an object that contains info about the connection
Network Options
opts
are passed to hyperdiscovery, which can include:
opts = {
upload: true,
download: true,
port: 3282,
utp: true,
tcp: true
}
opts = {
dns: {
server:
domain:
}
dht: {
bootstrap:
}
}
Returns a discovery-swarm instance.
dat.leaveNetwork()
or dat.leave()
Leaves the network for the archive.
var importer = dat.importFiles([dir], [opts], [cb])
(must be the archive owner)
Import files to your Dat Archive from the directory using hyperdrive-import-files.
dir
- By default, files will be imported from the folder where the archive was initiated. Import files from another directory by specifying dir
.opts
- options passed to hyperdrive-import-files (see below).cb
- called when import is finished.
Returns a importer
object with properties:
importer.on('error', err)
importer.on('file imported', { path, mode=updated|created })
- file importedimporter.on('file skipped', { path })
- duplicate file in directory skipped importingimporter.on('file watch event', { path })
- file watch event firedimporter.fileCount
- the count of currently known filesimporter.totalSize
- total file size in bytes for fileCount
filesimporter.bytesImported
- total number of bytes imported so farimporter.countStats.files
- total number of files counted in target directoryimporter.countStats.bytes
- total number of bytes in target directory.
Importer Progress
To get import progress use:
importer.fileCount / importer.countStats.files
for file progressimporter.bytesImported / importer.countStats.bytes
for byte progress
Importer Options
Options include:
var opts = {
watch: false,
overwrite: true,
resume: false,
basePath: '',
ignore:
dryRun: false,
indexing: true
}
opts.ignore
dat-node
provides a default ignore option, ignoring the .dat
folder and all hidden files or directories. Use opts.ignoreHidden = false
to import hidden files or folders, except the .dat
directory.
It's important that the .dat
folder is not imported because it contains a private key that allows the owner to write to the archive.
var stats = dat.trackStats()
hyperdrive-stats instance for the Dat Archive. Stats are stored in a sublevel database in the .dat
folder.
stats.network
Get upload and download speeds: stats.network.uploadSpeed
or stats.network.downloadSpeed
. Transfer speeds are tracked using hyperdrive-network-speed.
dat.close(cb)
Stops replication and closes all the things opened for dat-node, including:
dat.archive.close(cb)
dat.db.close(cb)
dat.network.close(cb)
dat.importer.close()
(file watcher)
If you passed opts.db
, you'll be responsible for closing it.
Advanced Usage
Multiple Archives
Check out the multidat module with dat-node to manage many archives in one place.
One Swarm - Many Connections
TODO - Use a single swarm to manage many connections (hyperdiscovery is 1 swarm to 1 archive).
Moving from dat-js
dat-js -> dat-node
Dat-node was previously published as dat-js.
- Dat-node ^0.1.0 is compatible with dat-js ^4.0.0
- Dat-node 1.0.0 uses a new API. See details below for how to move from the old dat-js API.
Dat-node 1.0 has a very different API than dat-js and dat-node v0. The previous API returned an object with events. The new API uses a callback to ensure everything is done before using the archive.
Archives are created with a callback function. Once the archive is created, you can join the network directly without choosing to share or download. If the user owns the archive, they will be able to import files.
Directory is now the first argument, and a required argument.
Sharing
For example, previously to share files with dat-js we would write:
var dat = Dat({dir: dir})
dat.share(function () {
console.log('now sharing:', dat.key.toString())
})
In dat-node this would be:
Dat(dir, function (err, dat) {
var network = dat.joinNetwork(opts)
console.log('now sharing:', dat.key.toString())
var importer = dat.importFiles(opts, function () {
console.log('done importing files')
})
var stats = dat.trackStats()
})
You may have used the dat.open()
function previously. This is now done before the callback, no need to open anything! Don't worry, you can still close it.
Downloading
Previously to download files with dat-js we would write:
var dat = Dat({dir: dir, key: link})
dat.download()
console.log('downloading...')
In dat-node this would be:
Dat(dir, {key: link}, function (err, dat) {
var network = dat.joinNetwork(opts)
console.log('now downloading')
var stats = dat.trackStats()
})
Contributing
- Use standardjs formatting
npm test
to run the tests- Have fun!
Tour de Code
index.js
validates the arguments and initializes the archive with lib/init-archive.js
dat.js
contains the dat
class that is returned with the main callback.lib/*
contains opinionated wrappers around the modules we use (with the exception of lib/init-archive.js
). Some of this may move into the modules themselves eventually (or into dat.js
).
lib/import-files.js
- sets default ignore options.
- counts the files in target import directory for progress calculations
lib/stats.js
- Creates a sublevel database for hyperdrive-stats persistence
- Combines hyperdrive-stats and hyperdrive-network-speed into one interface.
lib/network.js
- Honestly doesn't do anything anymore. Could probably remove at this point =).
lib/init-archive.js
- This is a temporary workaround for resuming existing archives. It looks pretty confusing, and it is.
- Hyperdrive is moving to a one database = one archive model. Once updated, that change will eliminate the need for most of this file.
License
MIT