Rename to swarm-api, swarmapi CLI updated

Renamed library to swarm-api to appease npm

swarmapi NodeJS CLI bin updated to use all of the newest functions in the library

README updated with API doc
This commit is contained in:
emizzle 2018-09-12 11:55:22 +10:00
parent a1aa94424a
commit ca951546b6
9 changed files with 219 additions and 87 deletions

View File

@ -4,11 +4,9 @@
"env": { "env": {
"browser": { "browser": {
"ignore": [ "ignore": [
"src/swarmapi.js",
"src/index.js", "src/index.js",
"src/node/index.js", "src/node/index.js",
"src/standalone/index.js", "src/standalone/index.js"
"bin/swarmapi"
], ],
"plugins": [ "plugins": [
["@babel/plugin-transform-runtime", { ["@babel/plugin-transform-runtime", {
@ -26,8 +24,7 @@
"node": { "node": {
"ignore": [ "ignore": [
"src/browser.js", "src/browser.js",
"src/standalone/index.js", "src/standalone/index.js"
"bin/swarmapi"
], ],
"plugins": [ "plugins": [
["@babel/plugin-transform-runtime", { ["@babel/plugin-transform-runtime", {

4
.gitignore vendored
View File

@ -33,8 +33,8 @@ package
.vscode .vscode
.eslintrc.json .eslintrc.json
swarmapi.min.js swarm-api.min.js
swarmapi-*.tgz swarm-api-*.tgz
NOTES NOTES
npm-debug.log npm-debug.log
TODO TODO

102
README.md
View File

@ -1,58 +1,57 @@
# SwarmAPI # SwarmJS
A javascript library for interacting with [Swarm](https://swarm-guide.readthedocs.io/en/latest/), a decentralised and distributed storage platform. A javascript library for interacting with [Swarm](https://swarm-guide.readthedocs.io/en/latest/), a decentralised and distributed storage platform.
Under the hood, SwarmAPI uses the Swarm HTTP API to communicate with the Swarm gateway. Under the hood, SwarmJS uses the Swarm HTTP API to communicate with the Swarm gateway.
## Installation ## Installation
``` ```
npm install swarmapi --save npm install swarmjs --save
``` ```
## Basic usage ## JS usage
First, import SwarmAPI. First, import SwarmJS.
Using **CommonJS**: Using **CommonJS**:
``` ```
const SwarmAPI = require('swarmapi'); const SwarmJS = require('swarmjs');
``` ```
Or, with **ES6**: Or, with **ES6**:
``` ```
import SwarmAPI from 'swarmapi'; import SwarmJS from 'swarmjs';
``` ```
Then instantiate SwarmAPI, specifying the gateway you'd like to connect to. *If you are [running your own node](https://swarm-guide.readthedocs.io/en/latest/gettingstarted.html) (recommended), the node should be started before proceeding.* Then instantiate SwarmJS, specifying the gateway you'd like to connect to. *If you are [running your own node](https://swarm-guide.readthedocs.io/en/latest/gettingstarted.html) (recommended), the node should be started before proceeding.*
``` ```
// instantiate SwarmAPI // instantiate SwarmJS
const swarmapi = new SwarmAPI({ gateway: 'http://localhost:8500' }); const swarmjs = new SwarmJS({ gateway: 'http://localhost:8500' });
``` ```
Available options: Available options:
| Option | Description | Default | | Option | Description | Default |
| -----| ------------| ------- | | -----| ------------| ------- |
| `gateway` | URL of the Swarm gateway, ie `http://localhost:8500`. | `https://swarm-gateways.net` | | `gateway` | URL of the Swarm gateway, ie `http://localhost:8500`. | `swarm-gateways.net` |
| `mode` | Protocol of the default gateway URL. If `gateway` is provided, this has no effect. | `https` |
NOTE: If no options are provided, the default gateway URL will be `https://swarm-gateways.net`. This means you don't necessarily need to [run your own Swarm node](https://swarm-guide.readthedocs.io/en/latest/gettingstarted.html), however there is an upload limit of ~2.5MB and no guarantees regarding permanence. *It is recommended to run your own Swarm node.* NOTE: If no options are provided, the default gateway URL will be `https://swarm-gateways.net`. This means you don't necessarily need to [run your own Swarm node](https://swarm-guide.readthedocs.io/en/latest/gettingstarted.html), however there is an upload limit of ~2.5MB and no guarantees about permanence. It is recommended to run your own Swarm node.
##### Check gateway availability ##### Check gateway availability
``` ```
// Check gateway availability swarmjs.isAvailable((err, isAvailable) => {
swarmapi.isAvailable((err, isAvailable) => {
if(err) return console.error('Error checking Swarm availability', err); if(err) return console.error('Error checking Swarm availability', err);
console.log(`Gateway at 'http://localhost:8500' is ${isAvailable ? '' : 'un'}available`); console.log(`Gateway at 'http://localhost:8500' is ${isAvailable ? '' : 'un'}available`);
}); });
// > Gateway at 'http://localhost:8500' is available // Gateway at 'http://localhost:8500' is available
``` ```
##### Upload of raw content ##### Upload of raw content
``` ```
// Upload of raw content
let testHash; let testHash;
swarmapi.uploadRaw('test', (err, hash) => { swarmjs.uploadRaw('test', (err, hash) => {
if(err) return console.error('Error uploading contents', err); if(err) return console.error('Error uploading contents', err);
testHash = hash; testHash = hash;
console.log(`test can now be accessed from 'http://localhost:8500/bzz-raw:/${hash}'`); console.log(`test can now be accessed from 'http://localhost:8500/bzz-raw:/${hash}'`);
}); });
// > test can now be accessed from 'http://localhost:8500/bzz-raw:/6de1faa7d29b1931b4ba3d44befcf7a5e43e947cd0bf2db154172bac5ecac3a6' // test can now be accessed from 'http://localhost:8500/bzz-raw:/6de1faa7d29b1931b4ba3d44befcf7a5e43e947cd0bf2db154172bac5ecac3a6'
``` ```
##### Upload file ##### Upload file
If you want to upload a file, first read the file's contents, then upload as the raw contents
``` ```
// If you want to upload a file, first read the file's contents, then upload as the raw contents
const fs = require('fs'); const fs = require('fs');
fs.readFile('./index.html', (err, data) => { fs.readFile('./index.html', (err, data) => {
if (err) throw err; if (err) throw err;
@ -61,24 +60,79 @@ fs.readFile('./index.html', (err, data) => {
console.log(`file contents can now be accessed from 'http://localhost:8500/bzz-raw:/${hash}'`); console.log(`file contents can now be accessed from 'http://localhost:8500/bzz-raw:/${hash}'`);
}); });
}); });
// > file contents can now be accessed from 'http://localhost:8500/bzz-raw:/178739cbbd084e90ae0cef3f95e4b92baa85e83edb1a52d28dc370277db9d457' // file contents can now be accessed from 'http://localhost:8500/bzz-raw:/178739cbbd084e90ae0cef3f95e4b92baa85e83edb1a52d28dc370277db9d457'
``` ```
##### Upload directory (only available in NodeJS, not available in the browser!) ##### Upload directory (only available in NodeJS, not available in the browser!)
Once uploaded, the hash of **the manifest** is returned. Accessing the manifest from `bzz:/` will not return anything. Instead, you can use the hash as the root of your directory and access the individual files by appending them to the end of the URL. So, if we uploaded a directory containing `index.html`, we will be able to access it via `<gateway url>/bzz:/<hash>/index.html`. Once uploaded, the hash of **the manifest** is returned. Accessing the manifest from `bzz:/` will not return anything. Instead, you can use the hash as the root of your directory and access the individual files by appending them to the end of the URL. So, if we uploaded a directory containing `index.html`, we will be able to access it via `<gateway url>/bzz:/<hash>/index.html`.
``` ```
// upload the dist folder, and for this example, we can assume this folder contains index.html and dapp.css // upload the dist folder, and for this example, we can assume this folder contains index.html and dapp.css
swarm.uploadDirectory('dist/', (err, hash) => { swarm.uploadDirectory('dist/', null, (err, hash) => {
if(err) return console.error('Error uploading directory', err); if(err) return console.error('Error uploading directory', err);
console.log(`We can now access our directory via 'http://localhost:8500/bzz:/${hash}/index.html' and 'http://localhost:8500/bzz:/${hash}/dapp.css'`); console.log(`We can now access our directory via 'http://localhost:8500/bzz:/${hash}/index.html' and 'http://localhost:8500/bzz:/${hash}/dapp.css'`);
}); });
// > We can now access our directory via 'http://localhost:8500/bzz:/26089099a5f473dfb7b172de6558972989f8db4d3948daedbb974025be7c8534/index.html' and 'http://localhost:8500/bzz:/26089099a5f473dfb7b172de6558972989f8db4d3948daedbb974025be7c8534/dapp.css' // We can now access our directory via 'http://localhost:8500/bzz:/26089099a5f473dfb7b172de6558972989f8db4d3948daedbb974025be7c8534/index.html' and 'http://localhost:8500/bzz:/26089099a5f473dfb7b172de6558972989f8db4d3948daedbb974025be7c8534/dapp.css'
``` ```
##### Download content ##### Download content
``` ```
// Download content via hash // Download content via hash
swarmapi.downloadRaw(testHash, (err, content) => { swarmjs.downloadRaw(testHash, (err, content) => {
if(err) return console.error(err); if(err) return console.error(err);
console.log(`contents of our test: ${content}`); console.log(`contents of our test: ${content}`);
}); });
// > contents of our test: test // contents of our test: test
```
## CLI
### Installation
SwarmAPI can be installed globally to be accessed from the CLI
```
npm install -g swarm-api
```
Or installed locally to be accessed from the current folder
```
npm install swarm-api
```
### CLI Usage
##### Check gateway availability
```
swarmapi ping --gateway http://localhost:8500
// [http://localhost:8500] The Swarm gateway at http://localhost:8500 is available
```
##### Upload of raw content
```
swarmapi uploadraw 'Hello World' --gateway http://localhost:8500
// [http://localhost:8500] Swarm hash: a294d3a33dc0b4d9a12fdb48f5a7aed5f8dd2d8fc6a4253487c63012210e210e
```
##### Upload file
```
swarmapi uploadfile index.html --gateway http://localhost:8500
// [http://localhost:8500] Swarm hash: 91a3e25c9cec6d470eeaff24f2e5b5e56b87482eb289da8041b1f97a3dbbd39f
```
##### Upload directory (only available in NodeJS, not available in the browser!)
Once uploaded, the hash of **the manifest** is returned. Accessing the manifest from `bzz:/` will 404. Instead, you can use the hash as the root of your directory and access the individual files by appending them to the end of the URL, then call `swarmapi download <uri>`.
So, if our uploaded directory looked like:
```
├── dist
│ └── root.html
│ ├── folder
│ │ └── index.js
```
Run the upload directory command
```
swarmapi uploaddir dist --gateway http://localhost:8500
// [http://localhost:8500] Swarm manifest hash: 06da636c60c4a5472b209c71e35170044e8cf939aca6acfec765514f33a72b87. Resources can be retreived using bzz:/<hash>/<path:optional>/<filename>, for example (assuming /index.html was uploaded):
// swarmapi download bzz:/06da636c60c4a5472b209c71e35170044e8cf939aca6acfec765514f33a72b87/index.html -g http://localhost:8500
```
We will be able to access the `root.html` file via
```
swarmapi download bzz:/06da636c60c4a5472b209c71e35170044e8cf939aca6acfec765514f33a72b87/root.html -g http://localhost:8500
```
And the `folder/index.js` file via
```
swarmapi download bzz:/06da636c60c4a5472b209c71e35170044e8cf939aca6acfec765514f33a72b87/folder/index.js -g http://localhost:8500
```
##### Download content
```
swarmapi downloadraw a294d3a33dc0b4d9a12fdb48f5a7aed5f8dd2d8fc6a4253487c63012210e210e -g http://localhost:8500
// Hello World
``` ```

View File

@ -1,68 +1,144 @@
#!/usr/bin/env node #!/usr/bin/env node
const SwarmAPI = require('../src/index.js'); const SwarmAPI = require('../dist/node/index.js');
const swarmhash = require('swarmhash'); require('colors');
const fs = require('fs');
const yargs = require('yargs') const yargs = require('yargs')
.usage('Usage: $0 [command]') .usage('Usage: $0 [command]')
.command('get <gateway> <hash>', 'Download content', { .command('ping', 'Check if the gateway is running and available')
gateway: { .command('download <uri>', 'Download content from a given URI', {
alias: 'g', uri: {
default: 'http://swarm-gateways.net' alias: 'u',
}, description: 'GETs a resource at the given URI, ie bzz:/<hash>',
hash: { demandOption: true
alias: 'h'
} }
}) })
.command('put <gateway> <filename>', 'Upload file', { .command('downloadraw <hash>', 'Download content')
gateway: { .command('upload <uri>', 'POST content to the given URI', {
alias: 'g', uri: {
default: 'http://swarm-gateways.net' alias: 'u',
}, description: 'POSTS a resource to the given URI, ie bzz-raw:/'
}
})
.command('uploadraw <content>', 'Upload content (ie file contents)', {
content: {
alias: 'c'
}
})
.command('uploadfile <filename>', 'Upload file', {
filename: { filename: {
alias: 'f' alias: 'f'
} }
}) })
.command('calculate <filename>', 'Calculate the hash only without uploading') .command('uploaddir <dirpath>', 'Upload directory', {
dirpath: {
alias: 'd',
description: 'path to directory, relative to the currrent working directory, ie \'dist\''
}
})
.command('hash', 'Calculate the hash only without uploading. If both --filename and --content are provided, --filename takes precendence.',
function (yargs) {
return yargs.option('f', {
alias: 'filename',
describe: 'calculate the hash of the specified file'
})
.option('c', {
alias: 'content',
describe: 'calculate the hash of the specified string content. Wrap your string in quotes to get the correct hash'
});
},
function (argv) {
argv.content = (argv.filename || argv.content);
})
.option('gateway', {
alias: 'g',
describe: 'Swarm gateway URI ',
demandOption: true,
default: 'https://swarm-gateways.net',
defaultDescription: 'https://swarm-gateways.net'
})
//.demandOption(['gateway'], 'Please specify the gateway parameter with --gateway or -g, ie swarami -g http://localhost:8500 ping')
.coerce('filename', (filename) => {
return require('fs').readFileSync(filename);
})
.alias('h', 'hash')
.strict() .strict()
.version() .version()
.showHelpOnFail(false, 'Specify --help for available options') .showHelpOnFail(false, 'Specify --help for available options')
.help() .help()
.demand(1, 'Must provide a command'); .demand(1, 'Must provide a command')
.epilogue('For more information, please see https://github.com/embark-framework/swarm-api');
const argv = yargs.argv; const argv = yargs.argv;
const gateway = argv.gateway; const gateway = argv.gateway;
const command = argv._[0]; const command = argv._[0];
const swarmapi = new SwarmAPI({gateway}); const swarmapi = new SwarmAPI({gateway});
function abort(msg) { function abort(msg, err) {
console.log(msg || 'Error occured'); console.error(`[${gateway}] ${(msg || 'Error occured')}`.red, err);
process.exit(1); process.exit(1);
} }
switch (command) { function success(msg) {
case 'get': console.log(`[${gateway}] ${msg}`.green);
swarmapi.downloadRaw(argv.hash, function (err, ret) { }
if (err) {
abort('Failed to download: ' + err); try {
} else { switch (command) {
console.log(ret); case 'ping':
} swarmapi.isAvailable((err, isAvailable) => {
}); if (err) return abort('Failed to check gateway availability: ', err);
break; success(`The Swarm gateway at ${gateway} is ${isAvailable ? '' : 'un'}available`);
case 'put': });
swarmapi.uploadRaw(fs.readFileSync(argv.filename), function (err, ret) { break;
if (err) { case 'download':
console.log('Failed to upload: ' + err); swarmapi.download(argv.uri, (err, content) => {
} else { if (err) return abort('Failed to download: ', err);
console.log('Swarm hash: ' + ret); success(content);
} });
}); break;
break; case 'downloadraw':
case 'calculate': swarmapi.downloadRaw(argv.hash, (err, content) => {
console.log('Swarm hash: ' + swarmhash(fs.readFileSync(argv.filename)).toString('hex')); if (err) return abort('Failed to download: ', err);
break; success(content);
default: });
console.log('Invalid arguments. Type \'swarmapi --help\' for valid options'); break;
case 'upload':
swarmapi.upload(argv.uri, (err, hash) => {
if (err) return abort('Failed to upload: ', err);
success(`Swarm hash: ${hash}`);
});
break;
case 'uploadraw':
swarmapi.uploadRaw(argv.content, (err, hash) => {
if (err) {
return abort(`Failed to upload: ${err}`);
}
success(`Swarm hash: ${hash}`);
});
break;
case 'uploadfile':
swarmapi.uploadRaw(argv.filename, (err, hash) => {
if (err) return abort('Failed to upload file: ', err);
success(`Swarm hash: ${hash}`);
});
break;
case 'uploaddir':
swarmapi.uploadDirectory(argv.dirpath, null, (err, hash) => {
if (err) return abort('Failed to upload directory: ', err);
success(`Swarm manifest hash: ${hash}. Resources can be retreived using bzz:/<hash>/<path:optional>/<filename>, for example (assuming /index.html was uploaded):\nswarmapi download bzz:/${hash}/index.html -g ${gateway}`);
});
break;
case 'hash':
swarmapi.hash(argv.content, (err, hash) => {
if (err) return abort('Failed to get hash of content: ', err);
success(`Swarm hash: ${hash}`);
});
break;
default:
abort(`Invalid arguments. Type 'swarmapi --help' for valid options`);
}
}
catch (error) {
abort('Error occurred', error);
} }

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>SwarmAPI &mdash; standalone</title> <title>SwarmAPI &mdash; standalone</title>
<script src="swarmapi.min.js"></script> <script src="swarm-api.min.js"></script>
</head> </head>
<body></body> <body></body>
</html> </html>

View File

@ -1,5 +1,5 @@
{ {
"name": "swarmapi", "name": "swarm-api",
"version": "0.0.1", "version": "0.0.1",
"description": "JavaScript library for easily interacting with Swarm distributed storage.", "description": "JavaScript library for easily interacting with Swarm distributed storage.",
"main": "dist/node/index.js", "main": "dist/node/index.js",
@ -8,7 +8,7 @@
"./dist/node/index.js": "./dist/browser/browser.js" "./dist/node/index.js": "./dist/browser/browser.js"
}, },
"bin": { "bin": {
"swarmapi": "./bin/swarmapi" "swarmapi": "./dist/bin/swarmapi"
}, },
"browserslist": [ "browserslist": [
"last 1 version", "last 1 version",
@ -17,8 +17,7 @@
], ],
"files": [ "files": [
"dist", "dist",
"swarmapi.min.js", "swarm-api.min.js",
"bin/swarmapi",
"src" "src"
], ],
"scripts": { "scripts": {
@ -27,7 +26,7 @@
"babel:browser": "cross-env BABEL_ENV=browser babel --out-dir dist/browser src", "babel:browser": "cross-env BABEL_ENV=browser babel --out-dir dist/browser src",
"babel:node": "cross-env BABEL_ENV=node babel --out-dir dist src", "babel:node": "cross-env BABEL_ENV=node babel --out-dir dist src",
"build": "npm run clean && npm run babel && npm run webpack", "build": "npm run clean && npm run babel && npm run webpack",
"clean": "rimraf dist swarmapi-*.tgz package", "clean": "rimraf dist swarm-api-*.tgz package",
"http-server": "http-server", "http-server": "http-server",
"prepare": "npm run build", "prepare": "npm run build",
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
@ -35,7 +34,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/embark-framework/swarmapi.git" "url": "git+https://github.com/embark-framework/swarm-api.git"
}, },
"author": "", "author": "",
"license": "MIT", "license": "MIT",
@ -47,11 +46,12 @@
"serverless" "serverless"
], ],
"bugs": { "bugs": {
"url": "https://github.com/embark-framework/swarmapi/issues" "url": "https://github.com/embark-framework/swarm-api/issues"
}, },
"homepage": "https://github.com/embark-framework/swarmapi#readme", "homepage": "https://github.com/embark-framework/swarm-api#readme",
"dependencies": { "dependencies": {
"@babel/runtime-corejs2": "7.0.0-rc.1", "@babel/runtime-corejs2": "7.0.0-rc.1",
"colors": "1.3.2",
"klaw": "^3.0.0", "klaw": "^3.0.0",
"request": "^2.87.0", "request": "^2.87.0",
"swarmhash": "^0.1.0", "swarmhash": "^0.1.0",
@ -66,11 +66,11 @@
"@babel/preset-env": "7.0.0-rc.1", "@babel/preset-env": "7.0.0-rc.1",
"ajv": "6.5.2", "ajv": "6.5.2",
"cross-env": "5.2.0", "cross-env": "5.2.0",
"eslint": "4.19.1",
"http-server": "0.11.1", "http-server": "0.11.1",
"rimraf": "2.6.2", "rimraf": "2.6.2",
"webpack": "4.16.1", "webpack": "4.16.1",
"webpack-cli": "3.0.8", "webpack-cli": "3.0.8"
"eslint": "^4.13.1"
}, },
"engines": { "engines": {
"node": ">=8.11.3" "node": ">=8.11.3"

View File

@ -1,4 +1,5 @@
const request = require('request'); const request = require('request');
const swarmhash = require('swarmhash');
class SwarmAPI { class SwarmAPI {
@ -82,5 +83,9 @@ class SwarmAPI {
cb(e); cb(e);
} }
} }
hash(content, cb){
cb(null, swarmhash(content).toString('hex'));
}
} }
export default SwarmAPI; export default SwarmAPI;

View File

@ -1 +1 @@
module.exports = require('../../smarmjs.min'); module.exports = require('../../smarm-api.min');

View File

@ -7,7 +7,7 @@ const standalone = {
// minimize: false // minimize: false
// }, // },
output: { output: {
filename: 'swarmapi.min.js', filename: 'swarm-api.min.js',
globalObject: 'typeof self !== \'undefined\' ? self : this', globalObject: 'typeof self !== \'undefined\' ? self : this',
library: 'SwarmAPI', library: 'SwarmAPI',
libraryTarget: 'umd', libraryTarget: 'umd',