diff --git a/.aegir.js b/.aegir.js index 92764bc6c3..06490c5f1f 100644 --- a/.aegir.js +++ b/.aegir.js @@ -10,4 +10,3 @@ module.exports = { }] } } - diff --git a/.gitignore b/.gitignore index 254988dc81..d9cb651ee0 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ node_modules lib dist + +examples/transfer-files/complete/public/js/ipfs.js diff --git a/README.md b/README.md index bd916c09da..4fb81385bd 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@
- + @@ -137,7 +137,7 @@ The CLI is available by using the command `jsipfs` in your terminal. This is ali ### Use in the browser with browserify, webpack or any bundler -Simply require it as you would do for Node.js, but when transpiling+minifying with your bundler, make sure to swap `zlib` with a full replacement for the browser: `zlib: 'browserify-zlib-next'`. We have submited PR's to browserify and WebPack to make this as part of the standard node libraries that are transpiled, you can follow this development in [browserify](https://github.com/substack/node-browserify/issues/1672), [webpack](https://github.com/webpack/node-libs-browser/issues/51). +Simply require it as you would do for Node.js, but when transpiling+minifying with your bundler, make sure to swap `zlib` with a full replacement for the browser: `zlib: 'browserify-zlib-next'`. We have submitted PR's to browserify and WebPack to make this as part of the standard node libraries that are transpiled, you can follow this development in [browserify](https://github.com/substack/node-browserify/issues/1672), [webpack](https://github.com/webpack/node-libs-browser/issues/51). You can also find examples of how to do this bundling at: `https://github.com/ipfs/js-ipfs/tree/master/examples` @@ -151,10 +151,10 @@ The last published version of the package become [available for download](https: ```html - + - + ``` @@ -162,7 +162,7 @@ The last published version of the package become [available for download](https: ### CLI -The `jsipfs` CLI, available when `js-ipfs` is installed globably, follows(should, it is a WIP) the same interface defined by `go-ipfs`, you can always use the `help` command for help menus. +The `jsipfs` CLI, available when `js-ipfs` is installed globally, follows(should, it is a WIP) the same interface defined by `go-ipfs`, you can always use the `help` command for help menus. ```sh # Install js-ipfs globally @@ -285,7 +285,7 @@ Every IPFS instance also exposes the libp2p API at `ipfs.libp2p`. The formal int ## Development -### Clone and install dependnecies +### Clone and install dependencies ```sh > git clone https://github.com/ipfs/js-ipfs.git @@ -297,7 +297,7 @@ Every IPFS instance also exposes the libp2p API at `ipfs.libp2p`. The formal int ```sh # run all the unit tsts -> npm test +> npm test # run just IPFS tests in Node.js > npm run test:unit:node:core @@ -319,7 +319,7 @@ Every IPFS instance also exposes the libp2p API at `ipfs.libp2p`. The formal int ```sh # run all the interop tsts -> npm run test:interop +> npm run test:interop # run just IPFS interop tests in Node.js using one go-ipfs daemon and one js-ipfs daemon > npm run test:interop:node @@ -332,7 +332,7 @@ Every IPFS instance also exposes the libp2p API at `ipfs.libp2p`. The formal int ```sh # run all the interop tsts -> npm run test:benchmark +> npm run test:benchmark # run just IPFS benchmarks in Node.js > npm run test:benchmark:node @@ -373,11 +373,11 @@ Every IPFS instance also exposes the libp2p API at `ipfs.libp2p`. The formal int > tree src -L 2 src # Main source code folder ├── cli # Implementation of the IPFS CLI -│   └── ... +│ └── ... ├── http-api # The HTTP-API implementation of IPFS as defined by http-api-spec ├── core # IPFS implementation, the core (what gets loaded in browser) -│   ├── components # Each of IPFS subcomponent -│   └── ... +│ ├── components # Each of IPFS subcomponent +│ └── ... └── ... ``` diff --git a/examples/README.md b/examples/README.md index 78b7c23347..f9a954b30e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -11,3 +11,5 @@ Let us know if you find any issue or if you want to contribute and add a new tut - [How to bundle js-ipfs with WebPack](/bundle-webpack) ## Tutorials + +- [Transfer files between a Browser node and Desktop node](/transfer-files) diff --git a/examples/basics/index.js b/examples/basics/index.js index cb127f3e33..a3c9c1c2ee 100644 --- a/examples/basics/index.js +++ b/examples/basics/index.js @@ -2,14 +2,17 @@ const fs = require('fs') const os = require('os') +const path = require('path') const series = require('async/series') -const IPFS = require('../../src/core') // replace this by line below +const IPFS = require('../../src/core') +// replace this by line below if you are using ipfs as a dependency of your +// project // const IPFS = require('ipfs') /* * Create a new IPFS instance, using default repo (fs) on default path (~/.ipfs) */ -const node = new IPFS(os.tmpDir() + '/' + new Date().toString()) +const node = new IPFS(path.join(os.tmpDir() + '/' + new Date().toString())) const fileToAdd = { path: 'hello.txt', diff --git a/examples/bundle-browserify/README.md b/examples/bundle-browserify/README.md index e3da1419d6..86d4cb92bf 100644 --- a/examples/bundle-browserify/README.md +++ b/examples/bundle-browserify/README.md @@ -19,4 +19,4 @@ You should see the following: ## Special note In order to use js-ipfs in the browser, you need to replace the default `zlib` library by `browserify-zlib-next`, a full implementation of the native `zlib` package, full in Node.js. -See the package.json to learn how to do this and avoid this pitfall. More context on: https://github.com/ipfs/js-ipfs#use-in-the-browser-with-browserify-webpack-or-any-bundler +See the package.json to learn how to do this and avoid this pitfall (see the `browser` key). More context on: https://github.com/ipfs/js-ipfs#use-in-the-browser-with-browserify-webpack-or-any-bundler diff --git a/examples/transfer-files/.gitignore b/examples/transfer-files/.gitignore new file mode 100644 index 0000000000..f96c726227 --- /dev/null +++ b/examples/transfer-files/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +public/ipfs.js diff --git a/examples/transfer-files/README.md b/examples/transfer-files/README.md new file mode 100644 index 0000000000..84ccd01ae9 --- /dev/null +++ b/examples/transfer-files/README.md @@ -0,0 +1,220 @@ +# Tutorial - Transfer files between the browser and other IPFS nodes + +> Welcome! This tutorial will help you build a tiny web application where you can fetch and add files to IPFS and transfer these between a go-ipfs node and a js-ipfs node. + +There are a couple of caveats: + +- js-ipfs currently doesn't support DHT peer discovery, the peer from which you are fetching data should be within the reach (local or in public IP) of the browser node. +- We need to use a signalling server to establish the WebRTC connections, this won't be necessary as soon as libp2p-relay gets developed +- [full go-ipfs interop is not complete yet, blocked by an interop stream multiplexer](https://github.com/ipfs/js-ipfs/issues/721) + +That being said, we will explain throughout this tutorial to circunvent the caveats and once they are fixed, we will update the tutorial as well. + +## Application diagram + +The goal of this tutorial is to create a application with a IPFS node that dials to other instances of it using WebRTC, and at the same time dial and transfer files from a Desktop IPFS node using WebSockets as the transport. + +┌──────────────┐ ┌──────────────┐ +│ Browser │ │ Browser │ +│ │ WebRTC │ │ +│ │◀─────────────────▶│ │ +│ │ │ │ +└──────────────┘ └──────────────┘ + ▲ ▲ + │ │ + │ │ + │ │ + │WebSockets WebSockets│ + │ │ + │ │ + │ ┌──────────────┐ │ + │ │ Desktop │ │ + │ │ │ │ + └───────▶│ │◀─────────┘ + │ │ + └──────────────┘ + +## Check out the final state + +If you just want to check out what is the final state of how this application will look like, go to the complete folder, install the dependencies and run it. + +```sh +> cd complete +> npm install +> npm start +# open your browser (Chrome or Firefox) in http://localhost:12345 +``` + +You should get something like this: + +TODO: Insert final screenshot here + +## Step-by-step instructions + +Here's what we are going to be doing, today: + +- 1. Set up, install a go-ipfs node in your machine +- 2. Make your daemons listen on WebSockets +- 3. Initialize the project +- 4. Create the frame for your IPFS enabled app +- 5. Add and cat a file +- 6. Use WebRTC to dial between browser nodes +- 7. Dial to a node using WebSockets (your Desktop ones) +- 8. Transfer files between all of your nodes, have fun! + +Let's go. + +### 1. Set up + +You'll need to have an implementation of IPFS running on your machine. Currently, this means either go-ipfs or js-ipfs. + +Installing go-ipfs can be done by installing the binary [here](https://ipfs.io/ipns/dist.ipfs.io/#go-ipfs). Alternatively, you could follow the instructions in the README at [ipfs/go-ipfs](https://github.com/ipfs/go-ipfs). + +Installing js-ipfs requires you to have node and [npm](https://www.npmjs.com). Then, you simply run: + +```sh +> npm install --global ipfs +... +> jsipfs --help +Commands: +... +``` + +This will alias `jsipfs` on your machine; this is to avoid issues with `go-ipfs` being called `ipfs`. + +At this point, you have either js-ipfs or go-ipfs running. Now, initialize it: + +``` +> ipfs init +``` + +or + +``` +> jsipfs init +``` + +This will set up an `init` file in your home directory. + +### 2. Make your daemons listen on WebSockets + +At this point, you need to edit your `config` file, the one you just set up with `{js}ipfs init`. It should be in either `~/.jsipfs/config` or `~/.ipfs/config`, depending on whether you're using JS or Go. You can run `cat ~/.jsipfs/config` to see the contents of the JSON file. + +Since websockets are currently not stable and are experimental, you'll need to add the ability for your daemon to listen on Websocket addresses. Look into your init file (using `cat`) and find the `Addresses` block: + +```json + "Addresses": { + "Swarm": [ + "/ip4/0.0.0.0/tcp/4002" + ], + "API": "/ip4/127.0.0.1/tcp/5002", + "Gateway": "/ip4/127.0.0.1/tcp/9090" + } +``` + +To make Websockets work, open up the `config` file and add the following entry to your `Swarm` array: `/ip4/0.0.0.0/tcp/9999/ws`. Now, it should look like this: + + +```json + "Addresses": { + "Swarm": [ + "/ip4/0.0.0.0/tcp/4002", + "/ip4/0.0.0.0/tcp/9999/ws" + ], + "API": "/ip4/127.0.0.1/tcp/5002", + "Gateway": "/ip4/127.0.0.1/tcp/9090" + } +``` + +Now it should listen on Websockets. We're ready to start the daemon. + +```sh +> ipfs daemon +``` + +(Again, either `jsipfs` or `ipfs` works. I'll stop explaining that from here on out.) + +You should see the Websocket address in the output: + +```sh +Initializing daemon... +Swarm listening on /ip4/127.0.0.1/tcp/4001 +Swarm listening on /ip4/127.0.0.1/tcp/9999/ws +Swarm listening on /ip4/192.168.10.38/tcp/4001 +Swarm listening on /ip4/192.168.10.38/tcp/9999/ws +API server listening on /ip4/127.0.0.1/tcp/5001 +Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080 +Daemon is ready +``` + +It's there in line 5 - see the `/ws`? Good. that means it is listening. + +### 3. Start the WebApp project + + +Now, you'll need to make sure you are in `js-ipfs/examples/transfer-files/complete`. You'll see a `package.json`: this manifest holds the information for which packages you'll need to install to run the webapp. Let's install them, and then start the project: + +```sh +> npm install +> npm start +``` + +You should see this text: + +```sh +Starting up http-server, serving public +Available on: + http://127.0.0.1:12345 + http://192.168.1.24:12345 +Hit CTRL-C to stop the server +``` + +Go to http://127.0.0.1:12345 in your browser; you're now in the webapp, if all went well. + +### 4. Create the frame for your IPFS enabled app + +TODO: Not sure what this means. + +### 5. Add and cat a file + +### 6. Use WebRTC to dial between browser nodes +### 7. Dial to a node using WebSockets (your Desktop ones) +### 8. Transfer files between all of your nodes, have fun! + +-------- + +## Start the example + +**NOTE!** Before running the examples, you need to build `js-ipfs`. You can do this by following the instructions in https://github.com/ipfs/js-ipfs#clone-and-install-dependnecies and then building it as per https://github.com/ipfs/js-ipfs#build-a-dist-version. + +``` +npm install +npm start +``` + +Open http://127.0.0.1:8080 in a browser. + +**TODO: add instructions how to cat a hash in the UI.** + +## Tutorial + +Steps +1. create IPFS instance + +TODO. See `./start-ipfs.js` + +3. add a file in go-ipfs +4. copy file's hash +5. ipfs.files.cat + +TODO. add ipfs.files.cat code examples from index.html + +6. output the buffer to + +``` +... +stream.on('end', () => { + const blob = new Blob(buf) + picture.src = URL.createObjectURL(blob) +}) +``` diff --git a/examples/transfer-files/complete/.gitignore b/examples/transfer-files/complete/.gitignore new file mode 100644 index 0000000000..257a410ec0 --- /dev/null +++ b/examples/transfer-files/complete/.gitignore @@ -0,0 +1 @@ +js/ipfs.js diff --git a/examples/transfer-files/complete/css/app.css b/examples/transfer-files/complete/css/app.css new file mode 100644 index 0000000000..c6deb4e2c8 --- /dev/null +++ b/examples/transfer-files/complete/css/app.css @@ -0,0 +1,248 @@ +body { + height: 100vh; + font-family: sans-serif; + color: white; + background: linear-gradient(to bottom,#041727 0%,#062b3f 100%); + pointer-events: auto; +} + +.dragover-popup { + position: absolute; + top: 10px; right: 10px; bottom: 10px; left: 10px; + background-color: rgba(0, 0, 0, 0.5); + text-align: center; + padding-top: 30%; + display: none; + pointer-events: none; +} + +.wrapper { + width: 900px; + margin: 0 auto; + /* filter: blur(5px); */ +} + +.header { + text-align: center; + /* filter: blur(5px); */ +} + +#filesStatus { + padding: 10px; +} + +h1, h2, h3 { + margin: 0px; +} + +h1 { + font-size: 2em; + font-weight: 300; +} + +h2 { + font-size: 1.25em; + font-weight: 700; +} + +h3 { + font-size: 1.0em; + font-weight: 700; +} + + +.header h1 { + margin-top: 20px; + margin-bottom: 20px; +} + +.hidden { + display: none; +} + +.visible { + display: inherit; + font-size: 0.8em; +} + +.error { + font-style: italic; + color: red; +} + +.ipfs { + padding-bottom: 50px; + border-radius: 1px; + box-sizing: border-box; +} + +#details { + padding: 10px; + width: 100%; + box-sizing: border-box; +} + +ul { + margin: 0px; padding: 0px; + list-style: none; + font-size: 11px; +} + +ul li { + margin-top: 10px; + margin-bottom: 10px; + font-size: 9px; + word-wrap: break-word; +} + +button { + background-color: rgba(0,0,0,0.2); + color: #6acad1; + border: 2px solid #6acad1; + font-size: 15px; + padding: 10px 25px 10px 25px; + border-radius: 2px; + margin: 5px; +} + +.multihash-wrapper input { + width: 80%; + float: left; + height: 40px; + margin-left: 1%; + font-size: 16px; + box-sizing: border-box; +} + +.multihash-wrapper button { + width: 17%; + float: left; + height: 40px; + margin: 0px; + margin-left: 1%; +} + +.file-list { + display: block; + margin: 10px; +} + +.file-list a { + font-size: 16px; + color: white; + display: block; +} + +button.connect-peer { + margin: 0px; + margin-top: 2px; + width: 100%; +} + +button:hover { + color: white; + border: 2px solid white; + cursor: pointer; +} + +.address { + font-family: monospace +} + +button:disabled { + opacity: 0.2; +} +input:disabled { + opacity: 0.2; +} +.disabled { + opacity: 0.2; +} + +input { + width: 100%; + border: 2px solid #444; + color: black; + padding: 7px; + border-radius: 2px; + font-size: 9px; +} + +textarea, input, button { + outline: none; +} + +button:focus, input:focus { + outline: 3px solid #6acad1; +} + +.picture { + margin-top: 1em; + width: 100%; + background-color: rgba(196, 196, 196, 0.1); + /*padding: 0.25em;*/ + /*font-size: 1.2em;*/ +} + +.settings { + padding: 15px; +} + +.left { + box-sizing: border-box; + /* background-color: red; */ +} + +.right { + /* background-color: green; */ +} + +.setting-item { + margin-top: 20px; +} + +.left, .right { + width: 48%; + float: left; + background-color: rgba(255, 255, 255, 0.05); + box-sizing: border-box; + margin: 1%; + padding: 10px; +} + + + +#files { + padding-top: 10px; + background-color: rgba(255, 255, 255, 0.05); + margin: 1%; +} + +.left.centered { + float: none; + margin: 0px auto; + text-align: center; +} + +.clear { + clear: both; +} + +.note { + position: absolute; + top: 10px; + right: 10px; + font-size: 10px; + font-size: 10px; +} + +#peers i { + display: block; + margin-top: 5px; + margin-bottom: 5px; + font-size: 14px; +} + +.error { + font-size: 18px; +} diff --git a/examples/transfer-files/complete/favicon.ico b/examples/transfer-files/complete/favicon.ico new file mode 100644 index 0000000000..801f728c08 Binary files /dev/null and b/examples/transfer-files/complete/favicon.ico differ diff --git a/examples/transfer-files/complete/index.html b/examples/transfer-files/complete/index.html new file mode 100644 index 0000000000..1be2122b8c --- /dev/null +++ b/examples/transfer-files/complete/index.html @@ -0,0 +1,72 @@ + + + + + + IPFS - Transfer Files + + +
+

Drop file to upload

+
+
+ + + +

Transfer Files

+
+ P.S. drop files anywhere to upload them! +
+
+
+
+
+
+ + +
+
+

Your daemon

+

ID

+
N/A
+

Addresses

+
    +
  • Not yet online
  • +
+
+
+
+
+

Peers

+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ +
+
+ + + + + + + + + diff --git a/examples/transfer-files/complete/ipfs-logo.svg b/examples/transfer-files/complete/ipfs-logo.svg new file mode 100644 index 0000000000..5091cce61e --- /dev/null +++ b/examples/transfer-files/complete/ipfs-logo.svg @@ -0,0 +1 @@ +IPFS logo (new) \ No newline at end of file diff --git a/examples/transfer-files/complete/js/app.js b/examples/transfer-files/complete/js/app.js new file mode 100644 index 0000000000..4e9e60b94c --- /dev/null +++ b/examples/transfer-files/complete/js/app.js @@ -0,0 +1,253 @@ +const $startButton = document.querySelector('#start') +const $stopButton = document.querySelector('#stop') +const $peers = document.querySelector('#peers') +const $errors = document.querySelector('#errors') +const $filesStatus = document.querySelector('#filesStatus') +const $multihashInput = document.querySelector('#multihash') +const $catButton = document.querySelector('#cat') +const $connectPeer = document.querySelector('input.connect-peer') +const $connectPeerButton = document.querySelector('button.connect-peer') +const $dragoverPopup = document.querySelector('.dragover-popup') +const $wrapper = document.querySelector('.wrapper') +const $header = document.querySelector('.header') +const $body = document.querySelector('body') +const $idContainer = document.querySelector('.id-container') +const $addressesContainer = document.querySelector('.addresses-container') +const $details = document.querySelector('#details') +const $allDisabledButtons = document.querySelectorAll('button:disabled') +const $allDisabledInputs = document.querySelectorAll('input:disabled') + +let ipfs +let peerInfo + +// TODO groups to refactor into +// ipfs stuff +// start node +// get details +// get peers +// connect to peer +// get contents of hash +// add files to ipfs +// creating html stuff +// list of peers / peers state +// add file to download list +// error handling +// show ipfs id +// show ipfs addressess +// drag-and-drop +// event listeners +// states + +function start () { + if (!ipfs) { + updateView('starting', ipfs) + window.createNode((err, node) => { + if (err) { + return onError(err) + } + ipfs = node + ipfs.id().then((id) => { + peerInfo = id + updateView('ready', ipfs) + setInterval(updatePeers, 1000) + $peers.innerHTML = '

Peers

Waiting for peers...' + }) + }) + } +} + +const stop = () => { + window.location.href = window.location.href +} + +const connectPeer = (e) => { + e.target.disabled = true + // Connect directly to a peer via it's multiaddr + ipfs.swarm.connect($connectPeer.value, (err) => { + console.log(err) + if (err) return onError(err) + $connectPeer.value = '' + setTimeout(() => { + e.target.disabled = false + }, 500) + }) +} + +const catFile = () => { + const multihash = $multihashInput.value + $multihashInput.value = '' + $errors.className = 'hidden' + if (multihash) { + // Get a file or many files + ipfs.files.get(multihash, (err, stream) => { + if (err) { + onError(err) + } + console.log(stream) + + // .get gives us a stream of files + stream.on('data', (file) => { + console.log('got file', file) + + const buf = [] + + if (file.content) { + // once we get a file, we also want to read the data for that file + file.content.on('data', (data) => buf.push(data)) + + file.content.on('end', () => { + console.log('The buf', buf) + + const content = new window.Blob(buf, {type: 'application/octet-binary'}) + const contentUrl = window.URL.createObjectURL(content) + + const listItem = document.createElement('div') + const link = document.createElement('a') + link.setAttribute('href', contentUrl) + link.setAttribute('download', multihash) + const date = (new Date()).toLocaleTimeString() + + link.innerText = date + ' - ' + multihash + ' - Size: ' + file.size + const fileList = document.querySelector('.file-list') + + listItem.appendChild(link) + fileList.insertBefore(listItem, fileList.firstChild) + }) + + file.content.resume() + } + }) + + stream.on('end', () => console.log('no more files')) + }) + } +} + +const onError = (e) => { + console.error(e) + let msg = 'An error occured, check the dev console' + if (e.stack !== undefined) { + msg = e.stack + } else if (typeof e === 'string') { + msg = e + } + $errors.innerHTML = '' + msg + '' + $errors.className = 'error visible' +} +window.onerror = onError + +const onDragEnter = () => { + $dragoverPopup.style.display = 'block' + $wrapper.style.filter = 'blur(5px)' + $header.style.filter = 'blur(5px)' +} + +const onDragExit = () => { + console.log('drag left') + $dragoverPopup.style.display = 'none' + $wrapper.style.filter = '' + $header.style.filter = '' +} + +// Handle file drop +const onDrop = (event) => { + onDragExit() + $errors.className = 'hidden' + event.preventDefault() + var dt = event.dataTransfer + var files = dt.files + const readFileContents = (file) => { + return new Promise((resolve) => { + const reader = new window.FileReader() + reader.onload = (event) => resolve(event.target.result) + reader.readAsArrayBuffer(file) + }) + } + + // TODO: Promise reduce? + for (var i = 0; i < files.length; i++) { + const file = files[i] + console.log('Add file', file.name, file.size) + readFileContents(file) + .then((buffer) => { + return ipfs.files.add([{ + path: file.name, + content: new ipfs.types.Buffer(buffer) + }]) + }) + .then((files) => { + console.log('Files added', files) + $multihashInput.value = files[0].hash + $filesStatus.innerHTML = files + .map((e) => `Added ${e.path} as ${e.hash}`) + .join('
') + }) + .catch(onError) + } +} + +// Get peers from IPFS and display them +let numberOfPeersLastTime = 0 +const updatePeers = () => { + // Once in a while, we need to refresh our list of peers in the UI + // .swarm.peers returns an array with all our currently connected peer + ipfs.swarm.peers((err, res) => { + if (err) onError(err) + if (numberOfPeersLastTime !== res.length) { + const peersAsHtml = res.map((p) => p.addr.toString()) + .map((p) => { + return '
  • ' + p + '
  • ' + }).join() + + $peers.innerHTML = res.length > 0 + ? '

    Remote Peers

    ' + : '

    Remote Peers

    Waiting for peers...' + } + numberOfPeersLastTime = res.length + }) +} + +function setupEventListeners () { + $body.addEventListener('dragenter', onDragEnter) + $body.addEventListener('drop', onDrop) + // TODO should work to hide the dragover-popup but doesn't... + $body.addEventListener('dragleave', onDragExit) + + $startButton.addEventListener('click', start) + $stopButton.addEventListener('click', stop) + $catButton.addEventListener('click', catFile) + $connectPeerButton.addEventListener('click', connectPeer) +} + +const states = { + ready: () => { + const addressesHtml = peerInfo.addresses.map((address) => { + return '
  • ' + address + '
  • ' + }).join('') + $idContainer.innerText = peerInfo.id + $addressesContainer.innerHTML = addressesHtml + $allDisabledButtons.forEach(b => { b.disabled = false }) + $allDisabledInputs.forEach(b => { b.disabled = false }) + $peers.className = '' + $details.className = '' + $stopButton.disabled = false + $startButton.disabled = true + }, + starting: () => { + $startButton.disabled = true + } +} + +function updateView (state, ipfs) { + if (states[state] !== undefined) { + states[state]() + } else { + throw new Error('Could not find state "' + state + '"') + } +} + +const startApplication = () => { + setupEventListeners() +} + +startApplication() diff --git a/examples/transfer-files/complete/js/create-node.js b/examples/transfer-files/complete/js/create-node.js new file mode 100644 index 0000000000..899c801a8c --- /dev/null +++ b/examples/transfer-files/complete/js/create-node.js @@ -0,0 +1,41 @@ +'use strict' + +window.createNode = (callback) => { + // Create a new repository for IPFS in a random path always + const repoPath = '/tmp/ipfs' + Math.random() + const node = new window.Ipfs(repoPath) + + // Initialize our repository with no extra files + node.init({ emptyRepo: true }, updateConfig) + + function updateConfig (err) { + if (err) return callback(err) + + // Retrieve the initialized default configuration + node.config.get((err, config) => { + if (err) return callback(err) + + // Add our webrtc-star address so we can find other peers easily + const signalDomain = 'star-signal.cloud.ipfs.team' + const wstarMultiaddr = `/libp2p-webrtc-star/dns/${signalDomain}/wss/ipfs/${config.Identity.PeerID}` + config.Addresses.Swarm = config.Addresses.Swarm.concat([ wstarMultiaddr ]) + + // Set the new configuration + node.config.replace(config, bootNode) + }) + } + + function bootNode (err) { + if (err) return callback(err) + + node.load((err) => { + if (err) return callback(err) + + // Actually start all the services and start ipfs + node.goOnline((err) => { + if (err) return callback(err) + callback(null, node) + }) + }) + } +} diff --git a/examples/transfer-files/complete/package.json b/examples/transfer-files/complete/package.json new file mode 100644 index 0000000000..828b227cc1 --- /dev/null +++ b/examples/transfer-files/complete/package.json @@ -0,0 +1,14 @@ +{ + "name": "transfer-files", + "version": "1.0.0", + "scripts": { + "check-bundle": "test -f ../../../dist/index.js && npm run copy-bundle || (echo \"js-ipfs dist file not found, go up two dirs and run 'npm run build' first\" && exit 1)", + "copy-bundle": "cp ../../../dist/index.js ./js/ipfs.js", + "serve": "http-server -c-1 -p 12345", + "start": "npm run check-bundle && npm run serve" + }, + "license": "MIT", + "devDependencies": { + "http-server": "^0.9.0" + } +} diff --git a/examples/transfer-files/img/diagram.monopic b/examples/transfer-files/img/diagram.monopic new file mode 100644 index 0000000000..35f88ab30f Binary files /dev/null and b/examples/transfer-files/img/diagram.monopic differ diff --git a/examples/transfer-files/img/diagram.txt b/examples/transfer-files/img/diagram.txt new file mode 100644 index 0000000000..05c9ff91cb --- /dev/null +++ b/examples/transfer-files/img/diagram.txt @@ -0,0 +1,19 @@ +┌──────────────┐ ┌──────────────┐ +│ Browser │ │ Browser │ +│ │ WebRTC │ │ +│ │◀─────────────────▶│ │ +│ │ │ │ +└──────────────┘ └──────────────┘ + ▲ ▲ + │ │ + │ │ + │ │ + │WebSockets WebSockets│ + │ │ + │ │ + │ ┌──────────────┐ │ + │ │ Desktop │ │ + │ │ │ │ + └───────▶│ │◀─────────┘ + │ │ + └──────────────┘ \ No newline at end of file diff --git a/package.json b/package.json index 1684020bbf..45bb469298 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs", - "version": "0.21.2", + "version": "0.21.5", "description": "JavaScript implementation of the IPFS specification", "bin": { "jsipfs": "src/cli/bin.js" @@ -10,7 +10,7 @@ "libp2p-ipfs-nodejs": "libp2p-ipfs-browser", "./src/core/default-repo.js": "./src/core/default-repo-browser.js", "./src/core/components/init-assets.js": false, - "./test/utils/temp-repo.js": "./test/utils/temp-repo-browser.js", + "./test/utils/create-repo-node.js": "./test/utils/create-repo-browser.js", "stream": "readable-stream" }, "go-ipfs": { @@ -61,7 +61,7 @@ }, "homepage": "https://github.com/ipfs/js-ipfs#readme", "devDependencies": { - "aegir": "^9.3.3", + "aegir": "^9.4.0", "buffer-loader": "0.0.1", "chai": "^3.5.0", "delay": "^1.3.1", @@ -89,6 +89,7 @@ "async": "^2.1.4", "bl": "^1.2.0", "boom": "^4.2.0", + "buffer": "^5.0.2", "debug": "^2.6.0", "fs-pull-blob-store": "^0.3.0", "glob": "^7.1.1", @@ -108,8 +109,8 @@ "isstream": "^0.1.2", "libp2p-floodsub": "0.7.1", "joi": "^10.2.0", - "libp2p-ipfs-nodejs": "^0.17.7", - "libp2p-ipfs-browser": "^0.17.6", + "libp2p-ipfs-nodejs": "^0.17.8", + "libp2p-ipfs-browser": "^0.17.7", "lodash.flatmap": "^4.5.0", "lodash.get": "^4.4.2", "lodash.has": "^4.5.2", @@ -118,7 +119,7 @@ "lodash.values": "^4.3.0", "mafmt": "^2.1.6", "multiaddr": "^2.2.0", - "multihashes": "^0.3.1", + "multihashes": "^0.3.2", "path-exists": "^3.0.0", "peer-book": "^0.3.0", "peer-id": "^0.8.1", @@ -144,6 +145,7 @@ "Andrew de Andrade ", "Christian Couder ", "Daniel J. O'Quinn ", + "Daniela Borges Matos de Carvalho ", "David Dias ", "Felix Yan ", "Francisco Baio Dias ", @@ -170,4 +172,4 @@ "nginnever ", "npmcdn-to-unpkg-bot " ] -} +} \ No newline at end of file diff --git a/src/core/components/bootstrap.js b/src/core/components/bootstrap.js index bfa5d14bdb..af2bd95818 100644 --- a/src/core/components/bootstrap.js +++ b/src/core/components/bootstrap.js @@ -1,6 +1,10 @@ 'use strict' -const defaultNodes = require('../../init-files/default-config.json').Bootstrap +const isNode = require('detect-node') + +const defaultNodes = isNode + ? require('../../init-files/default-config-node.json').Bootstrap + : require('../../init-files/default-config-browser.json').Bootstrap module.exports = function bootstrap (self) { return { diff --git a/src/core/components/id.js b/src/core/components/id.js index 8e8485eda0..9c113015b7 100644 --- a/src/core/components/id.js +++ b/src/core/components/id.js @@ -1,6 +1,7 @@ 'use strict' const promisify = require('promisify-es6') +const mafmt = require('mafmt') module.exports = function id (self) { return promisify((opts, callback) => { @@ -8,23 +9,19 @@ module.exports = function id (self) { callback = opts opts = {} } - if (!self._peerInfo) { // because of split second warmup - setTimeout(ready, 100) - } else { - ready() - } - function ready () { - callback(null, { - id: self._peerInfo.id.toB58String(), - publicKey: self._peerInfo.id.pubKey.bytes.toString('base64'), - addresses: self._peerInfo.multiaddrs.map((ma) => { - const addr = ma.toString() + '/ipfs/' + self._peerInfo.id.toB58String() - return addr - }).sort(), - agentVersion: 'js-ipfs', - protocolVersion: '9000' - }) - } + setImmediate(() => callback(null, { + id: self._peerInfo.id.toB58String(), + publicKey: self._peerInfo.id.pubKey.bytes.toString('base64'), + addresses: self._peerInfo.multiaddrs.map((ma) => { + if (mafmt.IPFS.matches(ma)) { + return ma.toString() + } else { + return ma.toString() + '/ipfs/' + self._peerInfo.id.toB58String() + } + }).sort(), + agentVersion: 'js-ipfs', + protocolVersion: '9000' + })) }) } diff --git a/src/core/components/init.js b/src/core/components/init.js index 0350563a0e..59d517544a 100644 --- a/src/core/components/init.js +++ b/src/core/components/init.js @@ -3,6 +3,7 @@ const peerId = require('peer-id') const waterfall = require('async/waterfall') const parallel = require('async/parallel') +const isNode = require('detect-node') const addDefaultAssets = require('./init-assets') @@ -20,13 +21,9 @@ module.exports = function init (self) { opts.bits = Number(opts.bits) || 2048 opts.log = opts.log || function () {} - let config - // Pre-set config values. - try { - config = require('../../init-files/default-config.json') - } catch (err) { - return callback(err) - } + const config = isNode + ? require('../../init-files/default-config-node.json') + : require('../../init-files/default-config-browser.json') waterfall([ // Verify repo does not yet exist. @@ -62,9 +59,7 @@ module.exports = function init (self) { ] if (typeof addDefaultAssets === 'function') { - tasks.push( - (cb) => addDefaultAssets(self, opts.log, cb) - ) + tasks.push((cb) => addDefaultAssets(self, opts.log, cb)) } parallel(tasks, (err) => { diff --git a/src/core/index.js b/src/core/index.js index fa4c2e8ae2..6d0df427fd 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -25,6 +25,8 @@ const files = require('./components/files') const bitswap = require('./components/bitswap') const pubsub = require('./components/pubsub') +const Buffer = require('buffer/').Buffer + exports = module.exports = IPFS function IPFS (repoInstance) { @@ -70,4 +72,9 @@ function IPFS (repoInstance) { this.bitswap = bitswap(this) this.ping = ping(this) this.pubsub = pubsub(this) + + // Exposed data types + this.types = { + Buffer: Buffer + } } diff --git a/src/init-files/default-config-browser.json b/src/init-files/default-config-browser.json new file mode 100644 index 0000000000..fb0220729c --- /dev/null +++ b/src/init-files/default-config-browser.json @@ -0,0 +1,14 @@ +{ + "Addresses": { + "Swarm": [], + "API": "/ip4/127.0.0.1/tcp/5002", + "Gateway": "/ip4/127.0.0.1/tcp/9090" + }, + "Discovery": { + "MDNS": { + "Enabled": false, + "Interval": 10 + } + }, + "Bootstrap": [] +} diff --git a/src/init-files/default-config.json b/src/init-files/default-config-node.json similarity index 83% rename from src/init-files/default-config.json rename to src/init-files/default-config-node.json index 33046e3871..91736bf291 100644 --- a/src/init-files/default-config.json +++ b/src/init-files/default-config-node.json @@ -1,7 +1,8 @@ { "Addresses": { "Swarm": [ - "/ip4/0.0.0.0/tcp/4002" + "/ip4/0.0.0.0/tcp/4002", + "/ip4/127.0.0.1/tcp/4003/ws" ], "API": "/ip4/127.0.0.1/tcp/5002", "Gateway": "/ip4/127.0.0.1/tcp/9090" @@ -12,17 +13,6 @@ "Interval": 10 } }, - "Mounts": { - "IPFS": "/ipfs", - "IPNS": "/ipns" - }, - "Ipns": { - "ResolveCacheSize": 128 - }, - "Gateway": { - "RootRedirect": "", - "Writable": false - }, "Bootstrap": [ "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", diff --git a/test/browser.js b/test/browser.js deleted file mode 100644 index 9e2051e8ec..0000000000 --- a/test/browser.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' - -require('./core/browser') diff --git a/test/core/both/test-bitswap.js b/test/core/bitswap.spec.js similarity index 90% rename from test/core/both/test-bitswap.js rename to test/core/bitswap.spec.js index 576f93d8a3..83bb63f4e5 100644 --- a/test/core/both/test-bitswap.js +++ b/test/core/bitswap.spec.js @@ -16,7 +16,11 @@ const API = require('ipfs-api') const multiaddr = require('multiaddr') const isNode = require('detect-node') -const IPFS = require('../../../src/core') +// This gets replaced by require('../utils/create-repo-browser.js') +// in the browser +const createTempRepo = require('../utils/create-repo-node.js') + +const IPFS = require('../../src/core') function makeBlock (cb) { return cb(null, new Block(`IPFS is awesome ${Math.random()}`)) @@ -27,19 +31,24 @@ describe('bitswap', () => { let swarmAddrsBak beforeEach((done) => { - inProcNode = new IPFS(require('../../utils/repo-path')) - if (!isNode) { - inProcNode.config.get('Addresses.Swarm', (err, swarmAddrs) => { - expect(err).to.not.exist - swarmAddrsBak = swarmAddrs - inProcNode.config.set('Addresses.Swarm', [], (err) => { - expect(err).to.not.exist - inProcNode.load(done) - }) - }) - } else { - inProcNode.load(done) - } + const repo = createTempRepo() + inProcNode = new IPFS(repo) + series([ + (cb) => inProcNode.init({ bits: 2048 }, cb), + (cb) => { + if (!isNode) { + inProcNode.config.get('Addresses.Swarm', (err, swarmAddrs) => { + expect(err).to.not.exist + swarmAddrsBak = swarmAddrs + inProcNode.config.set('Addresses.Swarm', [], cb) + }) + } else { + cb() + } + }, + (cb) => inProcNode.config.set('Discovery.MDNS.Enabled', false, cb), + (cb) => inProcNode.load(cb) + ], done) }) afterEach((done) => { diff --git a/test/core/both/test-bootstrap.js b/test/core/bootstrap.spec.js similarity index 86% rename from test/core/both/test-bootstrap.js rename to test/core/bootstrap.spec.js index 9e6a90d47e..729f2ec31e 100644 --- a/test/core/both/test-bootstrap.js +++ b/test/core/bootstrap.spec.js @@ -2,15 +2,27 @@ 'use strict' const expect = require('chai').expect +const isNode = require('detect-node') +const series = require('async/series') -const IPFS = require('../../../src/core') +// This gets replaced by require('../utils/create-repo-browser.js') +// in the browser +const createTempRepo = require('../utils/create-repo-node.js') + +const IPFS = require('../../src/core') describe('bootstrap', () => { - var ipfs + if (!isNode) { return } + + let ipfs before((done) => { - ipfs = new IPFS(require('../../utils/repo-path')) - ipfs.load(done) + const repo = createTempRepo() + ipfs = new IPFS(repo) + series([ + (cb) => ipfs.init({ bits: 1024 }, cb), + (cb) => ipfs.load(cb) + ], done) }) const defaultList = [ diff --git a/test/core/both/index.js b/test/core/both/index.js deleted file mode 100644 index a6dc8e5621..0000000000 --- a/test/core/both/index.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -describe('--both', () => { - require('./test-bitswap') - require('./test-block') - require('./test-bootstrap') - require('./test-config') - require('./test-files') - require('./test-generic') - require('./test-init') - require('./test-object') -}) diff --git a/test/core/both/test-init.js b/test/core/both/test-init.js deleted file mode 100644 index 80849ebf7d..0000000000 --- a/test/core/both/test-init.js +++ /dev/null @@ -1,59 +0,0 @@ -/* eslint max-nested-callbacks: ["error", 8] */ -/* eslint-env mocha */ -'use strict' - -const expect = require('chai').expect -const IPFS = require('../../../src/core') -const createTempRepo = require('../../utils/temp-repo') - -describe('init', function () { - this.timeout(50 * 1000) - - it('basic', (done) => { - const repo = createTempRepo() - const ipfs = new IPFS(repo) - - ipfs.init({ emptyRepo: true, bits: 1024 }, (err) => { - expect(err).to.not.exist - - repo.exists((err, res) => { - expect(err).to.not.exist - expect(res).to.equal(true) - - repo.config.get((err, config) => { - expect(err).to.not.exist - expect(config.Identity).to.exist - - repo.teardown(done) - }) - }) - }) - }) - - it('set # of bits in key', (done) => { - const repo1 = createTempRepo() - const repo2 = createTempRepo() - const ipfsShort = new IPFS(repo1) - const ipfsLong = new IPFS(repo2) - ipfsShort.init({ bits: 1024, emptyRepo: true }, (err) => { - expect(err).to.not.exist - - ipfsLong.init({ bits: 2048, emptyRepo: true }, (err) => { - expect(err).to.not.exist - - repo1.config.get((err, config1) => { - expect(err).to.not.exist - - repo2.config.get((err, config2) => { - expect(err).to.not.exist - expect(config1.Identity.PrivKey.length).is.below(config2.Identity.PrivKey.length) - - repo1.teardown(() => { - repo2.teardown(done) - }) - }) - }) - }) - }) - }) -}) diff --git a/test/core/browser-only/index.js b/test/core/browser-only/index.js deleted file mode 100644 index 97ab80c35d..0000000000 --- a/test/core/browser-only/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -describe('--browser only', () => { - require('./test-swarm') -}) diff --git a/test/core/browser-only/test-swarm.js b/test/core/browser-only/test-swarm.js deleted file mode 100644 index ccacec309b..0000000000 --- a/test/core/browser-only/test-swarm.js +++ /dev/null @@ -1 +0,0 @@ -'use strict' diff --git a/test/core/browser.js b/test/core/browser.js deleted file mode 100644 index 54731912c9..0000000000 --- a/test/core/browser.js +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const series = require('async/series') -const Store = require('idb-pull-blob-store') -const _ = require('lodash') -const pull = require('pull-stream') - -const repoContext = require.context('buffer!./../go-ipfs-repo', true) - -const idb = window.indexedDB || - window.mozIndexedDB || - window.webkitIndexedDB || - window.msIndexedDB - -idb.deleteDatabase('ipfs') -idb.deleteDatabase('ipfs/blocks') - -describe('core', function () { - this.timeout(10000) - before(function (done) { - var repoData = [] - repoContext.keys().forEach(function (key) { - repoData.push({ - key: key.replace('./', ''), - value: repoContext(key) - }) - }) - - const mainBlob = new Store('ipfs') - const blocksBlob = new Store('ipfs/blocks') - - series(repoData.map((file) => (cb) => { - if (_.startsWith(file.key, 'datastore/')) { - return cb() - } - - const blocks = _.startsWith(file.key, 'blocks/') - const blob = blocks ? blocksBlob : mainBlob - const key = blocks ? file.key.replace(/^blocks\//, '') : file.key - - pull( - pull.values([file.value]), - blob.write(key, cb) - ) - }), done) - }) - - require('./both') - require('./browser-only') -}) diff --git a/test/core/init.spec.js b/test/core/init.spec.js new file mode 100644 index 0000000000..89176bbabe --- /dev/null +++ b/test/core/init.spec.js @@ -0,0 +1,81 @@ +/* eslint max-nested-callbacks: ["error", 8] */ +/* eslint-env mocha */ +'use strict' + +const expect = require('chai').expect +const isNode = require('detect-node') +const IPFS = require('../../src/core') + +// This gets replaced by require('../utils/create-repo-browser.js') +// in the browser +const createTempRepo = require('../utils/create-repo-node.js') + +describe('init', () => { + if (!isNode) { return } + + let ipfs + let repo + + beforeEach(() => { + repo = createTempRepo() + ipfs = new IPFS(repo) + }) + + afterEach((done) => repo.teardown(done)) + + it('basic', (done) => { + ipfs.init({ bits: 1024 }, (err) => { + expect(err).to.not.exist + + repo.exists((err, res) => { + expect(err).to.not.exist + expect(res).to.equal(true) + + repo.config.get((err, config) => { + expect(err).to.not.exist + expect(config.Identity).to.exist + done() + }) + }) + }) + }) + + it('set # of bits in key', (done) => { + ipfs.init({ bits: 2048 }, (err) => { + expect(err).to.not.exist + + repo.config.get((err, config) => { + expect(err).to.not.exist + expect(config.Identity.PrivKey.length).is.above(256) + done() + }) + }) + }) + + it('init docs are written', (done) => { + ipfs.init({ bits: 1024 }, (err) => { + expect(err).to.not.exist + const multihash = new Buffer('12205e7c3ce237f936c76faf625e90f7751a9f5eeb048f59873303c215e9cce87599', 'hex') + + ipfs.object.get(multihash, {}, (err, node) => { + expect(err).to.not.exist + expect(node.links).to.exist + done() + }) + }) + }) + + it('empty repo', (done) => { + ipfs.init({ bits: 1024, emptyRepo: true }, (err) => { + expect(err).to.not.exist + + // Should not have default assets + const multihash = new Buffer('12205e7c3ce237f936c76faf625e90f7751a9f5eeb048f59873303c215e9cce87599', 'hex') + + ipfs.object.get(multihash, {}, (err, node) => { + expect(err).to.exist + done() + }) + }) + }) +}) diff --git a/test/core/both/test-block.js b/test/core/interface/block.js similarity index 100% rename from test/core/both/test-block.js rename to test/core/interface/block.js diff --git a/test/core/both/test-config.js b/test/core/interface/config.js similarity index 100% rename from test/core/both/test-config.js rename to test/core/interface/config.js diff --git a/test/core/both/test-files.js b/test/core/interface/files.js similarity index 100% rename from test/core/both/test-files.js rename to test/core/interface/files.js diff --git a/test/core/both/test-generic.js b/test/core/interface/generic.js similarity index 100% rename from test/core/both/test-generic.js rename to test/core/interface/generic.js diff --git a/test/core/interface/interface.spec.js b/test/core/interface/interface.spec.js new file mode 100644 index 0000000000..a3cfae8350 --- /dev/null +++ b/test/core/interface/interface.spec.js @@ -0,0 +1,17 @@ +/* eslint-env mocha */ + +'use strict' + +const isNode = require('detect-node') + +describe('interface-ipfs-core tests', () => { + require('./block') + require('./config') + require('./files') + require('./generic') + require('./object') + if (isNode) { + require('./swarm') + require('./pubsub') + } +}) diff --git a/test/core/both/test-object.js b/test/core/interface/object.js similarity index 100% rename from test/core/both/test-object.js rename to test/core/interface/object.js diff --git a/test/core/node-only/test-pubsub.js b/test/core/interface/pubsub.js similarity index 100% rename from test/core/node-only/test-pubsub.js rename to test/core/interface/pubsub.js diff --git a/test/core/node-only/test-swarm.js b/test/core/interface/swarm.js similarity index 100% rename from test/core/node-only/test-swarm.js rename to test/core/interface/swarm.js diff --git a/test/core/node-only/index.js b/test/core/node-only/index.js deleted file mode 100644 index a11396620b..0000000000 --- a/test/core/node-only/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const fs = require('fs') -const ncp = require('ncp').ncp -const expect = require('chai').expect -const path = require('path') -const clean = require('../../utils/clean') - -describe('--node only', () => { - const repoExample = path.join(__dirname, '../../go-ipfs-repo') - const repoTests = require('../../utils/repo-path') - - before((done) => { - clean(repoTests) - ncp(repoExample, repoTests, (err) => { - expect(err).to.equal(null) - done() - }) - }) - - after(() => { - clean(repoTests) - }) - - const tests = fs.readdirSync(__dirname) - tests.filter((file) => { - if (file === 'index.js') { - return false - } else { - return true - } - }).forEach((file) => { - require('./' + file) - }) -}) diff --git a/test/core/node-only/test-init.js b/test/core/node-only/test-init.js deleted file mode 100644 index 918abf27ff..0000000000 --- a/test/core/node-only/test-init.js +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint max-nested-callbacks: ["error", 8] */ -/* eslint-env mocha */ -'use strict' - -const expect = require('chai').expect -const IPFS = require('../../../src/core') -const createTempRepo = require('../../utils/temp-repo') - -describe('init (Node.js specific)', () => { - let ipfs - let repo - - beforeEach((done) => { - repo = createTempRepo() - ipfs = new IPFS(repo) - done() - }) - - afterEach((done) => { - repo.teardown(done) - }) - - it('init docs are written', (done) => { - ipfs.init({ bits: 1024 }, (err) => { - expect(err).to.not.exist - const multihash = new Buffer('12205e7c3ce237f936c76faf625e90f7751a9f5eeb048f59873303c215e9cce87599', 'hex') - - setTimeout(() => { - ipfs.object.get(multihash, {}, (err, node) => { - expect(err).to.not.exist - expect(node.links).to.exist - done() - }) - }, 1000) - }) - }) - - it('empty repo', (done) => { - ipfs.init({ bits: 1024, emptyRepo: true }, (err) => { - expect(err).to.not.exist - - // Check for default assets - var multihash = new Buffer('12205e7c3ce237f936c76faf625e90f7751a9f5eeb048f59873303c215e9cce87599', 'hex') - ipfs.object.get(multihash, {}, (err, node) => { - expect(err).to.exist - done() - }) - }) - }) -}) diff --git a/test/core/node.js b/test/core/node.js deleted file mode 100644 index ac5dbcbe55..0000000000 --- a/test/core/node.js +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const ncp = require('ncp').ncp -const expect = require('chai').expect -const path = require('path') -const clean = require('../utils/clean') - -describe('core', () => { - const repoExample = path.join(__dirname, '../go-ipfs-repo') - const repoTests = require('../utils/repo-path') - - before((done) => { - clean(repoTests) - ncp(repoExample, repoTests, (err) => { - expect(err).to.equal(null) - done() - }) - }) - - after(() => { - clean(repoTests) - }) - require('./both') - require('./node-only') -}) diff --git a/test/http-api/index.js b/test/http-api/index.js index 243af44982..b28a805438 100644 --- a/test/http-api/index.js +++ b/test/http-api/index.js @@ -36,33 +36,32 @@ describe('HTTP API', () => { }) }) - describe('## direct tests (inject)', () => { - const tests = fs.readdirSync(path.join(__dirname, '/inject')) + describe('## http-api spec tests', () => { + const tests = fs.readdirSync(path.join(__dirname, '/spec')) tests.filter((file) => { return file.match(/test-.*\.js/) }).forEach((file) => { - require('./inject/' + file)(http) + require('./spec/' + file)(http) }) }) describe('## interface-ipfs-core tests over ipfs-api', () => { - const tests = fs.readdirSync(path.join(__dirname, - '/interface-ipfs-core-over-ipfs-api')) + const tests = fs.readdirSync(path.join(__dirname, '/interface')) tests.filter((file) => { return file.match(/test-.*\.js/) }).forEach((file) => { - require('./interface-ipfs-core-over-ipfs-api/' + file) + require('./interface/' + file) }) }) describe('## custom ipfs-api tests', () => { - const tests = fs.readdirSync(path.join(__dirname, '/custom-ipfs-api')) + const tests = fs.readdirSync(path.join(__dirname, '/over-ipfs-api')) const ctl = APIctl('/ip4/127.0.0.1/tcp/6001') tests.filter((file) => { return file.match(/test-.*\.js/) }).forEach((file) => { - require('./custom-ipfs-api/' + file)(ctl) + require('./over-ipfs-api/' + file)(ctl) }) }) }) diff --git a/test/http-api/interface-ipfs-core-over-ipfs-api/test-block.js b/test/http-api/interface/test-block.js similarity index 100% rename from test/http-api/interface-ipfs-core-over-ipfs-api/test-block.js rename to test/http-api/interface/test-block.js diff --git a/test/http-api/interface-ipfs-core-over-ipfs-api/test-config.js b/test/http-api/interface/test-config.js similarity index 100% rename from test/http-api/interface-ipfs-core-over-ipfs-api/test-config.js rename to test/http-api/interface/test-config.js diff --git a/test/http-api/interface-ipfs-core-over-ipfs-api/test-files.js b/test/http-api/interface/test-files.js similarity index 100% rename from test/http-api/interface-ipfs-core-over-ipfs-api/test-files.js rename to test/http-api/interface/test-files.js diff --git a/test/http-api/interface-ipfs-core-over-ipfs-api/test-object.js b/test/http-api/interface/test-object.js similarity index 100% rename from test/http-api/interface-ipfs-core-over-ipfs-api/test-object.js rename to test/http-api/interface/test-object.js diff --git a/test/http-api/interface-ipfs-core-over-ipfs-api/test-pubsub.js b/test/http-api/interface/test-pubsub.js similarity index 100% rename from test/http-api/interface-ipfs-core-over-ipfs-api/test-pubsub.js rename to test/http-api/interface/test-pubsub.js diff --git a/test/http-api/interface-ipfs-core-over-ipfs-api/test-swarm.js b/test/http-api/interface/test-swarm.js similarity index 100% rename from test/http-api/interface-ipfs-core-over-ipfs-api/test-swarm.js rename to test/http-api/interface/test-swarm.js diff --git a/test/http-api/custom-ipfs-api/test-bitswap.js b/test/http-api/over-ipfs-api/test-bitswap.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-bitswap.js rename to test/http-api/over-ipfs-api/test-bitswap.js diff --git a/test/http-api/custom-ipfs-api/test-block.js b/test/http-api/over-ipfs-api/test-block.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-block.js rename to test/http-api/over-ipfs-api/test-block.js diff --git a/test/http-api/custom-ipfs-api/test-bootstrap.js b/test/http-api/over-ipfs-api/test-bootstrap.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-bootstrap.js rename to test/http-api/over-ipfs-api/test-bootstrap.js diff --git a/test/http-api/custom-ipfs-api/test-config.js b/test/http-api/over-ipfs-api/test-config.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-config.js rename to test/http-api/over-ipfs-api/test-config.js diff --git a/test/http-api/custom-ipfs-api/test-id.js b/test/http-api/over-ipfs-api/test-id.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-id.js rename to test/http-api/over-ipfs-api/test-id.js diff --git a/test/http-api/custom-ipfs-api/test-object.js b/test/http-api/over-ipfs-api/test-object.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-object.js rename to test/http-api/over-ipfs-api/test-object.js diff --git a/test/http-api/custom-ipfs-api/test-repo.js b/test/http-api/over-ipfs-api/test-repo.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-repo.js rename to test/http-api/over-ipfs-api/test-repo.js diff --git a/test/http-api/custom-ipfs-api/test-swarm.js b/test/http-api/over-ipfs-api/test-swarm.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-swarm.js rename to test/http-api/over-ipfs-api/test-swarm.js diff --git a/test/http-api/custom-ipfs-api/test-version.js b/test/http-api/over-ipfs-api/test-version.js similarity index 100% rename from test/http-api/custom-ipfs-api/test-version.js rename to test/http-api/over-ipfs-api/test-version.js diff --git a/test/http-api/inject/test-bitswap.js b/test/http-api/spec/test-bitswap.js similarity index 100% rename from test/http-api/inject/test-bitswap.js rename to test/http-api/spec/test-bitswap.js diff --git a/test/http-api/inject/test-block.js b/test/http-api/spec/test-block.js similarity index 100% rename from test/http-api/inject/test-block.js rename to test/http-api/spec/test-block.js diff --git a/test/http-api/inject/test-bootstrap.js b/test/http-api/spec/test-bootstrap.js similarity index 98% rename from test/http-api/inject/test-bootstrap.js rename to test/http-api/spec/test-bootstrap.js index 6c25584393..0e830f04ea 100644 --- a/test/http-api/inject/test-bootstrap.js +++ b/test/http-api/spec/test-bootstrap.js @@ -3,7 +3,7 @@ const expect = require('chai').expect const qs = require('qs') -const defaultList = require('../../../src/init-files/default-config.json').Bootstrap +const defaultList = require('../../../src/init-files/default-config-node.json').Bootstrap module.exports = (http) => { describe('/bootstrap', () => { diff --git a/test/http-api/inject/test-config.js b/test/http-api/spec/test-config.js similarity index 100% rename from test/http-api/inject/test-config.js rename to test/http-api/spec/test-config.js diff --git a/test/http-api/inject/test-files.js b/test/http-api/spec/test-files.js similarity index 100% rename from test/http-api/inject/test-files.js rename to test/http-api/spec/test-files.js diff --git a/test/http-api/inject/test-id.js b/test/http-api/spec/test-id.js similarity index 100% rename from test/http-api/inject/test-id.js rename to test/http-api/spec/test-id.js diff --git a/test/http-api/inject/test-object.js b/test/http-api/spec/test-object.js similarity index 100% rename from test/http-api/inject/test-object.js rename to test/http-api/spec/test-object.js diff --git a/test/http-api/inject/test-pubsub.js b/test/http-api/spec/test-pubsub.js similarity index 100% rename from test/http-api/inject/test-pubsub.js rename to test/http-api/spec/test-pubsub.js diff --git a/test/http-api/inject/test-repo.js b/test/http-api/spec/test-repo.js similarity index 100% rename from test/http-api/inject/test-repo.js rename to test/http-api/spec/test-repo.js diff --git a/test/http-api/inject/test-swarm.js b/test/http-api/spec/test-swarm.js similarity index 100% rename from test/http-api/inject/test-swarm.js rename to test/http-api/spec/test-swarm.js diff --git a/test/http-api/inject/test-version.js b/test/http-api/spec/test-version.js similarity index 100% rename from test/http-api/inject/test-version.js rename to test/http-api/spec/test-version.js diff --git a/test/node.js b/test/node.js index 839824a7e7..7c50c663cb 100644 --- a/test/node.js +++ b/test/node.js @@ -23,7 +23,7 @@ if (process.env.TEST) { } if (testCore) { - require('./core/node') + // require('./core/node') } if (testHTTP) { diff --git a/test/utils/temp-repo-browser.js b/test/utils/create-repo-browser.js similarity index 100% rename from test/utils/temp-repo-browser.js rename to test/utils/create-repo-browser.js diff --git a/test/utils/temp-repo.js b/test/utils/create-repo-node.js similarity index 93% rename from test/utils/temp-repo.js rename to test/utils/create-repo-node.js index 0fb997bba2..b1a17512e1 100644 --- a/test/utils/temp-repo.js +++ b/test/utils/create-repo-node.js @@ -14,7 +14,7 @@ function createTempRepo (repoPath) { repo.teardown = (done) => { clean(repoPath) - done() + setImmediate(() => done()) } return repo diff --git a/test/utils/factory-core/index.js b/test/utils/factory-core/index.js index 69cafdf5e8..56598e9060 100644 --- a/test/utils/factory-core/index.js +++ b/test/utils/factory-core/index.js @@ -5,7 +5,7 @@ const series = require('async/series') const defaultConfig = require('./default-config.json') const IPFS = require('../../../src/core') -const createTempRepo = require('../temp-repo') +const createTempRepo = require('../create-repo-node') module.exports = Factory diff --git a/test/utils/on-and-off.js b/test/utils/on-and-off.js index 531b109e44..da0bd2d7b5 100644 --- a/test/utils/on-and-off.js +++ b/test/utils/on-and-off.js @@ -1,24 +1,23 @@ /* eslint-env mocha */ 'use strict' -const HttpAPI = require('../../src/http-api') +const HTTPAPI = require('../../src/http-api') -module.exports = function onlineAndOffline (repoPath, tests) { - describe('api offline', () => { - tests() - }) +/* + * CLI Utility to run the tests offline (daemon off) and online (daemon on) + */ +module.exports = (repoPath, tests) => { + describe('with daemon off (requiring js-ipfs core directly)', () => tests()) - describe('api running', () => { + describe('with daemon on (contacting js-ipfs through http-api)', () => { let httpAPI before((done) => { - httpAPI = new HttpAPI(repoPath) + httpAPI = new HTTPAPI(repoPath) httpAPI.start(done) }) - after((done) => { - httpAPI.stop(done) - }) + after((done) => httpAPI.stop(done)) tests() }) diff --git a/test/utils/repo-path.js b/test/utils/repo-path.js deleted file mode 100644 index a44e93d5d1..0000000000 --- a/test/utils/repo-path.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict' - -const path = require('path') -const isNode = require('detect-node') - -if (isNode) { - module.exports = path.join(__dirname, '../repo-tests-run') -} else { - module.exports = 'ipfs' -} diff --git a/test/utils/temp-node.js b/test/utils/temp-node.js index a61fa2a201..85fdbb5ac9 100644 --- a/test/utils/temp-node.js +++ b/test/utils/temp-node.js @@ -5,7 +5,7 @@ const leftPad = require('left-pad') const series = require('async/series') const IPFS = require('../../src/core') -const createTempRepo = require('./temp-repo') +const createTempRepo = require('./create-repo-node.js') function setAddresses (repo, num, callback) { repo.config.get((err, config) => {