diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..c3c64f8 --- /dev/null +++ b/.babelrc @@ -0,0 +1,40 @@ +{ + "comments": false, + "compact": false, + "env": { + "browser": { + "ignore": [ + "src/swarmjs.js", + "src/node/index.js", + "src/standalone/index.js", + "bin/swarmjs" + ], + "plugins": [ + ["@babel/plugin-transform-runtime", { + "corejs": 2 + }] + ], + "presets": [ + ["@babel/env", { + "targets": {"node": "8.11.3"} + }] + ] + }, + "node": { + "ignore": [ + "src/browser.js", + "bin/swarmjs" + ], + "plugins": [ + ["@babel/plugin-transform-runtime", { + "corejs": 2 + }] + ], + "presets": [ + ["@babel/env", { + "targets": {"node": "8.11.3"} + }] + ] + } + } +} diff --git a/.gitignore b/.gitignore index 123ae94..df1263c 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,16 @@ build/Release # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules + +dist +package + +.idea +.vscode +.eslintrc.json + +swarm.min.js +swarmjs-*.tgz +NOTES +npm-debug.log +TODO diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..ad50df6 --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +engine-strict = true +package-lock = false +save-exact = true diff --git a/bin/swarmjs b/bin/swarmjs index 970f882..8e3c844 100755 --- a/bin/swarmjs +++ b/bin/swarmjs @@ -1,6 +1,6 @@ #!/usr/bin/env node -const SwarmJS = require('./index.js'); +const SwarmJS = require('../src/index.js'); const swarmhash = require('swarmhash'); const fs = require('fs'); @@ -43,7 +43,7 @@ function abort(msg) { switch (command) { case 'get': - swarmjs.get(argv.hash, function (err, ret) { + swarmjs.downloadRaw(argv.hash, function (err, ret) { if (err) { abort('Failed to download: ' + err) } else { @@ -52,7 +52,7 @@ switch (command) { }) break case 'put': - swarmjs.putFile(fs.readFileSync(argv.filename), function (err, ret) { + swarmjs.uploadRaw(fs.readFileSync(argv.filename), function (err, ret) { if (err) { console.log('Failed to upload: ' + err) } else { diff --git a/index.html b/index.html new file mode 100644 index 0000000..6c7def9 --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ + + + + + SwarmJS — standalone + + + + diff --git a/package.json b/package.json index 64b2f56..7d858bc 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,50 @@ { "name": "swarmjs", "version": "0.0.1", - "description": "", - "main": "src/index.js", + "description": "JavaScript library for easily interacting with Swarm distributed storage.", + "main": "dist/node/index.js", + "browser": { + "request": "xhr", + "./dist/node/index.js": "./dist/browser/browser.js" + }, "bin": { "swarmjs": "./bin/swarmjs" }, + "browserslist": [ + "last 1 version", + "not dead", + "> 0.2%" + ], + "scripts": { + "lint": "./node_modules/.bin/eslint 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", + "build": "npm run clean && npm run babel && npm run webpack", + "clean": "rimraf dist swarmjs-*.tgz package", + "http-server": "http-server", + "prepare": "npm run build", + "test": "echo \"Error: no test specified\" && exit 1", + "webpack": "webpack" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/embark-framework/swarmjs.git" + }, + "author": "", + "license": "MIT", + "keywords": [ + "ethereum", + "dapps", + "swarm", + "blockchain", + "serverless" + ], + "bugs": { + "url": "https://github.com/embark-framework/swarmjs/issues" + }, + "homepage": "https://github.com/embark-framework/swarmjs#readme", "dependencies": { + "@babel/runtime-corejs2": "7.0.0-rc.1", "klaw": "^3.0.0", "request": "^2.87.0", "swarmhash": "^0.1.0", @@ -15,27 +53,19 @@ "yargs": "^12.0.0" }, "devDependencies": { + "@babel/cli": "7.0.0-rc.1", + "@babel/core": "7.0.0-rc.1", + "@babel/plugin-transform-runtime": "7.0.0-rc.1", + "@babel/preset-env": "7.0.0-rc.1", + "ajv": "6.5.2", + "cross-env": "5.2.0", + "http-server": "0.11.1", + "rimraf": "2.6.2", + "webpack": "4.16.1", + "webpack-cli": "3.0.8", "eslint": "^4.13.1" }, - "scripts": { - "lint": "./node_modules/.bin/eslint src/", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/embark-framework/swarmjs.git" - }, - "keywords": [ - "ethereum", - "swarm" - ], - "author": "", - "license": "MIT", - "bugs": { - "url": "https://github.com/embark-framework/swarmjs/issues" - }, - "homepage": "https://github.com/embark-framework/swarmjs#readme", - "browser": { - "request": "xhr" + "engines": { + "node": ">=8.11.3" } } diff --git a/src/browser.js b/src/browser.js new file mode 100644 index 0000000..d948104 --- /dev/null +++ b/src/browser.js @@ -0,0 +1,126 @@ +const request = require('request'); + +//class SwarmJS { + + // constructor(opts) { + // this.opts = opts || {}; + // if (this.opts.gateway) { + // this.gateway = opts.gateway + // } else if (this.opts.mode === 'http') { + // this.gateway = 'http://swarm-gateways.net' + // } else { + // this.gateway = 'https://swarm-gateways.net' + // } + // } + + function SwarmJS(opts){ + this.opts = opts || {}; + if (this.opts.gateway) { + this.gateway = opts.gateway + } else if (this.opts.mode === 'http') { + this.gateway = 'http://swarm-gateways.net' + } else { + this.gateway = 'https://swarm-gateways.net' + } + } + + SwarmJS.prototype._isValidHash = (hash) => { + return /^[0-9a-f]{64}$/.test(hash) + } + + SwarmJS.prototype._hashResponse = (error, response, body, cb) => { + if (error) { + cb(error) + } else if (response.statusCode !== 200) { + cb(body) + } else if (!this._isValidHash(body)) { + cb('Invalid hash') + } else { + cb(null, body) + } + } + + SwarmJS.prototype.download = (url, cb) => { + request(`${this.gateway}/${url}`, (error, response, body) => { + if (error) { + cb(error) + } else if (response.statusCode !== 200) { + cb(body) + } else { + cb(null, body) + } + }); + } + + SwarmJS.prototype.downloadRaw = (hash, cb) => { + this.download(`bzz-raw:/${hash}`, cb); + } + + SwarmJS.prototype.upload = (url, content, cb) => { + request.post({ + url: `${this.gateway}/${url}`, + body: content + }, (error, response, body) => this._hashResponse(error, response, body, cb)) + } + + SwarmJS.prototype.uploadRaw = (content, cb) => { + this.upload('bzz-raw:', content, cb); + } + + SwarmJS.prototype.uploadForm = (formData, cb) => { + request.post({ + url: `${this.gateway}/bzz:/`, + formData: formData + }, (error, response, body) => this._hashResponse(error, response, body, cb)); + } + + + + + SwarmJS.prototype.isAvailable = (cb) => { + const testContent = "test"; + const testHash = "6de1faa7d29b1931b4ba3d44befcf7a5e43e947cd0bf2db154172bac5ecac3a6"; + try { + this.uploadRaw(testContent, (err, hash) => { + if (err) return cb(err); + cb(null, hash === testHash); + }); + } catch (e) { + cb(e); + } + } +//} + +module.exports = SwarmJS; + +// (opts) => { +// opts = opts || {}; +// if (!opts.gateway) { +// if (opts.mode === 'http') { +// opts.gateway = 'http://swarm-gateways.net'; +// } else { +// opts.gateway = 'https://swarm-gateways.net'; +// } +// } +// //const swarmjs = new SwarmJS(opts); +// // return { +// // download: swarmjs.download, +// // downloadRaw: swarmjs.downloadRaw, +// // upload: swarmjs.upload, +// // uploadRaw: swarmjs.uploadRaw, +// // uploadForm: swarmjs.uploadForm, +// // gateway: swarmjs.gateway, +// // isAvailable: swarmjs.isAvailable, +// // _hashResponse: swarmjs._hashResponse +// // } +// return { +// download: download, +// downloadRaw: downloadRaw, +// upload: upload, +// uploadRaw: uploadRaw, +// uploadForm: uploadForm, +// gateway: opts.gateway, +// isAvailable: isAvailable, +// _hashResponse: _hashResponse +// } +// } \ No newline at end of file diff --git a/src/node/index.js b/src/node/index.js new file mode 100644 index 0000000..b99882d --- /dev/null +++ b/src/node/index.js @@ -0,0 +1 @@ +module.exports = require('../swarmjs').default; diff --git a/src/standalone/index.js b/src/standalone/index.js new file mode 100644 index 0000000..7dda107 --- /dev/null +++ b/src/standalone/index.js @@ -0,0 +1 @@ +module.exports = require('../../smarmjs.min'); diff --git a/src/swarmjs.js b/src/swarmjs.js new file mode 100644 index 0000000..1d09e94 --- /dev/null +++ b/src/swarmjs.js @@ -0,0 +1 @@ +export {default} from './index'; \ No newline at end of file diff --git a/swarmjs.min.js b/swarmjs.min.js new file mode 100644 index 0000000..1b975f9 --- /dev/null +++ b/swarmjs.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("SwarmJS",[],e):"object"==typeof exports?exports.SwarmJS=e():t.SwarmJS=e()}("undefined"!=typeof self?self:this,function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";var o=n(1);function r(t){this.opts=t||{},this.opts.gateway?this.gateway=t.gateway:"http"===this.opts.mode?this.gateway="http://swarm-gateways.net":this.gateway="https://swarm-gateways.net"}r.prototype._isValidHash=function(t){return/^[0-9a-f]{64}$/.test(t)},r.prototype._hashResponse=function(t,e,n,o){t?o(t):200!==e.statusCode?o(n):(void 0)._isValidHash(n)?o(null,n):o("Invalid hash")},r.prototype.download=function(t,e){o("".concat((void 0).gateway,"/").concat(t),function(t,n,o){t?e(t):200!==n.statusCode?e(o):e(null,o)})},r.prototype.downloadRaw=function(t,e){(void 0).download("bzz-raw:/".concat(t),e)},r.prototype.upload=function(t,e,n){o.post({url:"".concat((void 0).gateway,"/").concat(t),body:e},function(t,e,o){return(void 0)._hashResponse(t,e,o,n)})},r.prototype.uploadRaw=function(t,e){(void 0).upload("bzz-raw:",t,e)},r.prototype.uploadForm=function(t,e){o.post({url:"".concat((void 0).gateway,"/bzz:/"),formData:t},function(t,n,o){return(void 0)._hashResponse(t,n,o,e)})},r.prototype.isAvailable=function(t){try{(void 0).uploadRaw("test",function(e,n){if(e)return t(e);t(null,"6de1faa7d29b1931b4ba3d44befcf7a5e43e947cd0bf2db154172bac5ecac3a6"===n)})}catch(e){t(e)}},t.exports=r},function(t,e,n){"use strict";var o=n(2),r=n(4),a=n(5),u=n(9);function i(t,e,n){var o=t;return r(e)?(n=e,"string"==typeof t&&(o={uri:t})):o=u(e,{uri:t}),o.callback=n,o}function s(t,e,n){return c(e=i(t,e,n))}function c(t){if(void 0===t.callback)throw new Error("callback argument missing");var e=!1,n=function(n,o,r){e||(e=!0,t.callback(n,o,r))};function o(t){return clearTimeout(f),t instanceof Error||(t=new Error(""+(t||"Unknown XMLHttpRequest Error"))),t.statusCode=0,n(t,b)}function r(){if(!i){var e;clearTimeout(f),e=t.useXDR&&void 0===c.status?200:1223===c.status?204:c.status;var o=b,r=null;return 0!==e?(o={body:function(){var t=void 0;if(t=c.response?c.response:c.responseText||function(t){try{if("document"===t.responseType)return t.responseXML;var e=t.responseXML&&"parsererror"===t.responseXML.documentElement.nodeName;if(""===t.responseType&&!e)return t.responseXML}catch(t){}return null}(c),w)try{t=JSON.parse(t)}catch(t){}return t}(),statusCode:e,method:l,headers:{},url:p,rawRequest:c},c.getAllResponseHeaders&&(o.headers=a(c.getAllResponseHeaders()))):r=new Error("Internal XMLHttpRequest Error"),n(r,o,o.body)}}var u,i,c=t.xhr||null;c||(c=t.cors||t.useXDR?new s.XDomainRequest:new s.XMLHttpRequest);var f,p=c.url=t.uri||t.url,l=c.method=t.method||"GET",d=t.body||t.data,y=c.headers=t.headers||{},h=!!t.sync,w=!1,b={body:void 0,headers:{},statusCode:0,method:l,url:p,rawRequest:c};if("json"in t&&!1!==t.json&&(w=!0,y.accept||y.Accept||(y.Accept="application/json"),"GET"!==l&&"HEAD"!==l&&(y["content-type"]||y["Content-Type"]||(y["Content-Type"]="application/json"),d=JSON.stringify(!0===t.json?d:t.json))),c.onreadystatechange=function(){4===c.readyState&&setTimeout(r,0)},c.onload=r,c.onerror=o,c.onprogress=function(){},c.onabort=function(){i=!0},c.ontimeout=o,c.open(l,p,!h,t.username,t.password),h||(c.withCredentials=!!t.withCredentials),!h&&t.timeout>0&&(f=setTimeout(function(){if(!i){i=!0,c.abort("timeout");var t=new Error("XMLHttpRequest timeout");t.code="ETIMEDOUT",o(t)}},t.timeout)),c.setRequestHeader)for(u in y)y.hasOwnProperty(u)&&c.setRequestHeader(u,y[u]);else if(t.headers&&!function(t){for(var e in t)if(t.hasOwnProperty(e))return!1;return!0}(t.headers))throw new Error("Headers cannot be set on an XDomainRequest object");return"responseType"in t&&(c.responseType=t.responseType),"beforeSend"in t&&"function"==typeof t.beforeSend&&t.beforeSend(c),c.send(d||null),c}t.exports=s,t.exports.default=s,s.XMLHttpRequest=o.XMLHttpRequest||function(){},s.XDomainRequest="withCredentials"in new s.XMLHttpRequest?s.XMLHttpRequest:o.XDomainRequest,function(t,e){for(var n=0;n=3&&(u=n),"[object Array]"===r.call(t)?function(t,e,n){for(var o=0,r=t.length;o