|
2 | 2 |
|
3 | 3 | In this guide, we will show how to develop applications with the Dat ecosystem. The Dat ecosystem is very modular making it easy to develop custom applications using Dat. |
4 | 4 |
|
| 5 | +Dat comes with a built in javascript API we use in Dat Desktop and dat command line. For custom applications, or more control, you can also use the core Dat modules separately. |
| 6 | + |
| 7 | +Use Dat in your JS Application: |
| 8 | + |
| 9 | +1. `require('dat')`: use the [high-level Dat JS API](https://github.com/datproject/dat-node). |
| 10 | +2. Build your own! |
| 11 | + |
| 12 | +This tutorial will cover the second option and get you familiar with the core Dat modules. |
| 13 | + |
| 14 | +### The Dat Core Modules |
| 15 | + |
5 | 16 | This tutorial will follow the steps for sharing and downloading files using Dat. In practice, we implement these in [dat-node](https://github.com/datproject/dat-node), a high-level module for using Dat that provides easy access to the core Dat modules. |
6 | 17 |
|
7 | | -For any Dat application, there are three essential modules you will start with: |
| 18 | +For any Dat application, there are two essential modules you will start with: |
8 | 19 |
|
9 | 20 | 1. [hyperdrive](https://npmjs.org/hyperdrive) for file synchronization and versioning |
10 | | -2. [hyperdrive-archive-swarm](https://npmjs.org/hyperdrive-archive-swarm) helps discover and connect to peers over local networks and the internet |
11 | | -3. A [LevelDB](https://npmjs.org/level) compatible database for storing metadata. |
| 21 | +2. [hyperdiscovery](https://npmjs.org/hyperdiscovery) helps discover and connect to peers over local networks and the internet |
12 | 22 |
|
13 | | -The [Dat CLI](https://npmjs.org/dat) module itself combines these modules and wraps them in a command-line API. These modules can be swapped out for a similarly compatible module, such as switching LevelDb for [MemDB](https://github.com/juliangruber/memdb) (which we do in the first example). More details on how these module work together are available in [How Dat Works](how-dat-works.md). |
| 23 | +The [Dat CLI](https://npmjs.org/dat) module itself combines these modules and wraps them in a command-line API. We also use the [dat-storage](https://github.com/datproject/dat-storage) module to handle file and key storage. These modules can be swapped out for a similarly compatible module, such as switching storage for [random-access-memory](https://github.com/mafintosh/random-access-memory). |
14 | 24 |
|
15 | 25 | ## Getting Started |
16 | 26 |
|
17 | 27 | You will need node and npm installed to build with Dat. [Read more](https://github.com/datproject/dat/blob/master/CONTRIBUTING.md#development-workflow) about our development work flow to learn how we manage our module dependencies during development. |
18 | 28 |
|
19 | 29 | ## Download a File |
20 | 30 |
|
21 | | -Our first module will download files from a Dat link entered by the user. View the code for this module on [Github](https://github.com/joehand/diy-dat-examples/tree/master/module-1). |
| 31 | +Our first module will download files from a Dat link entered by the user. |
22 | 32 |
|
23 | 33 | ```bash |
24 | 34 | mkdir module-1 && cd module-1 |
25 | 35 | npm init |
26 | | -npm install --save hyperdrive memdb hyperdrive-archive-swarm |
| 36 | +npm install --save hyperdrive random-access-memory hyperdiscovery |
27 | 37 | touch index.js |
28 | 38 | ``` |
29 | 39 |
|
30 | | -For this example, we will use [memdb](https://github.com/juliangruber/memdb) for our database (keeping the metadata in memory rather than on the file system). In your `index.js` file, require the main modules and set them up: |
| 40 | +For this example, we will use random-access-memory for our database (keeping the metadata in memory rather than on the file system). In your `index.js` file, require the main modules and set them up: |
31 | 41 |
|
32 | 42 | ```js |
33 | | -var memdb = require('memdb') |
34 | | -var Hyperdrive = require('hyperdrive') |
35 | | -var Swarm = require('hyperdrive-archive-swarm') |
| 43 | +var ram = require('random-access-memory') |
| 44 | +var hyperdrive = require('hyperdrive') |
| 45 | +var discovery = require('hyperdiscovery') |
36 | 46 |
|
37 | 47 | var link = process.argv[2] // user inputs the dat link |
38 | 48 |
|
39 | | -var db = memdb() |
40 | | -var drive = Hyperdrive(db) |
41 | | -var archive = drive.createArchive(link) |
42 | | -var swarm = Swarm(archive) |
| 49 | +var archive = hyperdrive(ram, link) |
| 50 | +archive.ready(function () { |
| 51 | + discovery(archive) |
| 52 | +}) |
43 | 53 | ``` |
44 | 54 |
|
45 | | -Notice, the user will input the link for the second argument The easiest way to get a file from a hyperdrive archive is to make a read stream. `archive.createFileReadStream` accepts the index number of filename for the first argument. To display the file, we can create a file stream and pipe it to `process.stdout`. |
| 55 | +Notice, the user will input the link for the second argument The easiest way to get a file from a hyperdrive archive is to make a read stream. `archive.readFile` accepts the index number of filename for the first argument. To display the file, we can create a file stream and pipe it to `process.stdout`. |
46 | 56 |
|
47 | 57 | ```js |
48 | | -var stream = archive.createFileReadStream(0) // get the first file |
49 | | -stream.pipe(process.stdout) |
| 58 | +// Make sure your archive has a dat.json file! |
| 59 | +var stream = archive.readFile('dat.json', 'utf-8', function (err, data) { |
| 60 | + if (err) throw err |
| 61 | + console.log(data) |
| 62 | +}) |
50 | 63 | ``` |
51 | 64 |
|
52 | | -Now, you can run the module! To download the first file from our docs Dat, run: |
| 65 | +Now, you can run the module! To download the `dat.json` file from an archive: |
53 | 66 |
|
54 | 67 | ``` |
55 | | -node index.js 395e3467bb5b2fa083ee8a4a17a706c5574b740b5e1be6efd65754d4ab7328c2 |
| 68 | +node index.js dat://<link> |
56 | 69 | ``` |
57 | 70 |
|
58 | | -You should see the first file in our docs repo. |
| 71 | +You should see the `dat.json` file. |
59 | 72 |
|
60 | 73 | #### Bonus: Display any file in the Dat |
61 | 74 |
|
62 | 75 | With a few more lines of code, the user can enter a file to display from the Dat link. |
63 | 76 |
|
64 | | -Challenge: create a module that will allow the user to input a Dat link and a filename: `node bonus.js <dat-link> <filename>`. The module will print out that file from the link, as we did above. To get a specific file you can change the file stream to use the filename instead of the index number: |
| 77 | +Challenge: create a module that will allow the user to input a Dat link and a filename: `node bonus.js <dat-link> <filename>`. The module will print out that file from the link, as we did above: |
65 | 78 |
|
66 | 79 | ```js |
67 | | -var stream = archive.createFileReadStream(fileName) |
| 80 | +var stream = archive.readFile(fileName) |
68 | 81 | ``` |
69 | 82 |
|
70 | 83 | Once you are finished, see if you can view this file by running: |
71 | 84 |
|
72 | 85 | ```bash |
73 | | -node bonus.js 395e3467bb5b2fa083ee8a4a17a706c5574b740b5e1be6efd65754d4ab7328c2 cookbook/diy-dat.md |
| 86 | +node bonus.js 395e3467bb5b2fa083ee8a4a17a706c5574b740b5e1be6efd65754d4ab7328c2 readme.md |
74 | 87 | ``` |
75 | 88 |
|
76 | | -[See how we coded it](https://github.com/joehand/diy-dat-examples/blob/master/module-1/bonus.js). |
77 | | - |
78 | 89 | ## Download all files to computer |
79 | 90 |
|
80 | | -This module will build on the last module. Instead of displaying a single file, we will download all of the files from a Dat into a local directory. View the code for this module on [Github](https://github.com/joehand/diy-dat-examples/tree/master/module-2). |
| 91 | +This module will build on the last module. Instead of displaying a single file, we will download all of the files from a Dat into a local directory. |
81 | 92 |
|
82 | | -To download the files to the file system, instead of to a database, we will use the `file` option in `hyperdrive` and the [random-access-file](http://npmjs.org/random-access-file) module. We will also learn two new archive functions that make handling all the files a bit easier than the file stream in module #1. |
| 93 | +To download the files to the file system, we are going to use [mirror-folder](https://github.com/mafintosh/mirror-folder). [Read more](/using-fs) about how mirror-folder works with hyperdrive. |
83 | 94 |
|
84 | | -Setup will be the same as before (make sure you install random-access-file and stream-each this time): |
| 95 | +In practice, you should use [dat-storage](https://github.com/datproject/dat-storage) to do this as it'll be more efficient and keep the metadata on disk. |
85 | 96 |
|
86 | | -```bash |
87 | | -mkdir module-2 && cd module-2 |
88 | | -npm init |
89 | | -npm install --save hyperdrive memdb hyperdrive-archive-swarm random-access-file stream-each |
90 | | -touch index.js |
91 | | -``` |
92 | | - |
93 | | -The first part of the module will look the same. We will add random-access-file (and [stream-each](http://npmjs.org/stream-each) to make things easier). The only difference is that we have to specify the `file` option when creating our archive: |
| 97 | +Setup will be the same as before (make sure you install `mirror-folder`). The first part of the module will look the same. |
94 | 98 |
|
95 | 99 | ```js |
96 | | -var memdb = require('memdb') |
97 | | -var Hyperdrive = require('hyperdrive') |
98 | | -var Swarm = require('hyperdrive-archive-swarm') |
99 | | -var raf = require('random-access-file') // this is new! |
100 | | -var each = require('stream-each') |
101 | | - |
102 | | -var link = process.argv[2] |
103 | | - |
104 | | -var db = memdb() |
105 | | -var drive = Hyperdrive(db) |
106 | | -var archive = drive.createArchive(link, { |
107 | | - file: function (name) { |
108 | | - return raf(path.join('download', name)) // download into a "download" dir |
109 | | - } |
110 | | -}) |
111 | | -var swarm = Swarm(archive) |
112 | | -``` |
| 100 | +var ram = require('random-access-memory') |
| 101 | +var hyperdrive = require('hyperdrive') |
| 102 | +var discovery = require('hyperdiscovery') |
| 103 | +var mirror = require('mirror-folder') |
113 | 104 |
|
114 | | -Now that we are setup, we can work with the archive. The `archive.download` function downloads the file content (to wherever you specified in the file option). To download all the files, we will need a list of files and then we will call download on each of them. `archive.list` will give us the list of the files. We use the stream-each module to make it easy to iterate over each item in the archive, then exit when the stream is finished. |
| 105 | +var link = process.argv[2] // user inputs the dat link |
| 106 | +var dir = process.cwd() // download to cwd |
115 | 107 |
|
116 | | -```js |
117 | | -var stream = archive.list({live: false}) // Use {live: false} for now to make the stream easier to handle. |
118 | | -each(stream, function (entry, next) { |
119 | | - archive.download(entry, function (err) { |
120 | | - if (err) return console.error(err) |
121 | | - console.log('downloaded', entry.name) |
122 | | - next() |
| 108 | +var archive = hyperdrive(ram, link) |
| 109 | +archive.ready(function () { |
| 110 | + discovery(archive) |
| 111 | + |
| 112 | + var progress = mirror({name: '/', fs: archive}, dir, function (err) { |
| 113 | + console.log('done downloading!') |
| 114 | + }) |
| 115 | + progress.on('put', function (src) { |
| 116 | + console.log(src.name, 'downloaded') |
123 | 117 | }) |
124 | | -}, function () { |
125 | | - process.exit(0) |
126 | 118 | }) |
127 | 119 | ``` |
128 | 120 |
|
129 | 121 | You should be able to run the module and see all our docs files in the `download` folder: |
130 | 122 |
|
131 | 123 | ```bash |
132 | | -node index.js 395e3467bb5b2fa083ee8a4a17a706c5574b740b5e1be6efd65754d4ab7328c2 |
| 124 | +node index.js dat://<link> |
133 | 125 | ``` |
0 commit comments