diff --git a/README.md b/README.md index 0f65026..107c2ab 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This library allows you to interact with the Swarm network from JavaScript. It: ## Basic usage -The simplest use case for Swarm is uploading/downloading raw data and directories. +The simplest use case for Swarm is uploading/downloading raw data and directories. First, load the lib: ```javascript // Loads the Swarm API pointing to the official gateway @@ -31,44 +31,52 @@ const swarm = require("swarm-js").at("http://swarm-gateways.net"); #### Upload raw data +To upload raw data, just call `swarm.upload(buffer)`. It returns a promise with the uploaded hash. + ```javascript const file = "test file"; -swarm.uploadData(new Buffer(file)).then(hash => { +swarm.upload(new Buffer(file)).then(hash => { console.log("Uploaded file. Address:", hash); }) ``` #### Downlod raw data +To download raw data, just call `swarm.download(hash)`. It returns a promise with the data buffer. + ```javascript const fileHash = "a5c10851ef054c268a2438f10a21f6efe3dc3dcdcc2ea0e6a1a7a38bf8c91e23"; -swarm.downloadData(fileHash).then(buffer => { +swarm.download(fileHash).then(buffer => { console.log("Downloaded file:", buffer.toString()); }); ``` #### Upload a directory +To upload a directory, just call `swarm.upload(directory)`, where directory is an object mapping paths to entries, those containing a mime-type and the data (a buffer). + ```javascript const dir = { - "/foo.txt": "sample file", - "/bar.txt": "another file" + "/foo.txt": {type: "text/plain", data: new Buffer("sample file")}, + "/bar.txt": {type: "text/plain", data: new Buffer("another file")} }; -swarm.uploadDirectory(dir).then(hash => { +swarm.upload(dir).then(hash => { console.log("Uploaded directory. Address:", hash); }); ``` #### Download a directory +To dowwnload a directory, just call `swarm.download(hash)`. Swarm.js will return a directory instead of a buffer by detecting the existence of a manifest on that hash. + ```javascript const dirHash = "7e980476df218c05ecfcb0a2ca73597193a34c5a9d6da84d54e295ecd8e0c641"; -swarm.downloadDirectory(dirHash).then(dir => { +swarm.download(dirHash).then(dir => { console.log("Downloaded directory:"); for (let path in dir) { - console.log("-", path, ":", dir[path].toString()); + console.log("-", path, ":", dir[path].data.toString()); } -} +}); ``` For examples of how to upload/download from disk, please check the [`examples`](https://github.com/MaiaVictor/swarm-js/tree/master/examples) directory. @@ -92,14 +100,14 @@ const indexHtml = (...) const exampleDApp = { - "" : indexHtml, - "/index.html" : indexHtml, - "/ethereum_icon.png" : ethereumIconPng, - "/foo/test_text_1.txt" : testText1, - "/foo/test_text_2.txt" : testText2 + "" : {type: "text/html", data: indexHtml}, + "/index.html" : {type: "text/html", data: indexHtml}, + "/ethereum_icon.png" : {type: "image/png", data: ethereumIconPng}, + "/foo/test_text_1.txt" : {type: "text/plain", data: testText1}, + "/foo/test_text_2.txt" : {type: "text/plain", data: testText2} } -swarm.uploadDirectory(exampleDApp) +swarm.upload(exampleDApp) .then(console.log) .catch(console.log); ``` @@ -131,7 +139,7 @@ const config = { Swarm.local(config, swarm => new Promise((resolve, reject) => { // Uploads data using the local node - swarm.uploadData("test").then(hash => { + swarm.upload(new Buffer("test")).then(hash => { console.log("Uploaded data. Address:", hash); // Closes the Swarm process. diff --git a/examples/dapp_download.js b/examples/dapp_download.js index a4c8965..cc29aed 100644 --- a/examples/dapp_download.js +++ b/examples/dapp_download.js @@ -6,16 +6,27 @@ const swarm = require("./../swarm.js").at("http://swarm-gateways.net"); // The hash of the DApp we uploaded on the other example. -const exampleDAppHash = "8587c8e716bfceea12a7306d85a8a8ccad5019020916eb5a21fa47a7f1826891"; +const exampleDAppHash = "379d2791624c3e3719bb28f7bfa362cc9c726ec06482b5800c8e3cefaf2b7bcf"; // Download the example DApp and print its index.html. -swarm.downloadDirectory(exampleDAppHash) +// It knows it is a DApp (not a file) by checking the existence of a manifest. +swarm.download(exampleDAppHash) .then(console.log) .catch(console.log); // This script outputs: -// { '': , -// 'index.html': ,/ -// 'ethereum_icon.png': , -// 'foo/test_text_1.txt': , -// 'foo/test_text_2.txt': } +// { 'ethereum_icon.png': +// { type: 'image/png', +// data: }, +// 'index.html': +// { type: 'text/html', +// data: }, +// '': +// { type: 'text/html', +// data: }, +// 'foo/test_text_1.txt': +// { type: 'text/plain', +// data: }, +// 'foo/test_text_2.txt': +// { type: 'text/plain', +// data: } } diff --git a/examples/dapp_download_to_disk.js b/examples/dapp_download_to_disk.js index b689e8f..52aa82a 100644 --- a/examples/dapp_download_to_disk.js +++ b/examples/dapp_download_to_disk.js @@ -7,6 +7,6 @@ const path = require("path"); const exampleDAppHash = "8587c8e716bfceea12a7306d85a8a8ccad5019020916eb5a21fa47a7f1826891"; const targetDirPath = path.join(__dirname,"example_dapp"); -swarm.downloadDirectoryToDisk(exampleDAppHash)(targetDirPath) +swarm.download(exampleDAppHash, targetDirPath) .then(dirPath => console.log(`Downloaded DApp to ${dirPath}.`)) .catch(console.log); diff --git a/examples/dapp_upload.js b/examples/dapp_upload.js index cd44f32..1fcddda 100644 --- a/examples/dapp_upload.js +++ b/examples/dapp_upload.js @@ -1,9 +1,9 @@ // This uploads a DApp to the Swarm network *without* using the filesystem. // That allows a web application running on the browser to upload any DApp. // Outputs the DApp address. In this case, it is: -// 8587c8e716bfceea12a7306d85a8a8ccad5019020916eb5a21fa47a7f1826891 +// 379d2791624c3e3719bb28f7bfa362cc9c726ec06482b5800c8e3cefaf2b7bcf // You can access it at: -// http://swarm-gateways.net/bzz:/8587c8e716bfceea12a7306d85a8a8ccad5019020916eb5a21fa47a7f1826891/ +// http://swarm-gateways.net/bzz:/379d2791624c3e3719bb28f7bfa362cc9c726ec06482b5800c8e3cefaf2b7bcf/ const swarm = require("./../swarm.js").at("http://swarm-gateways.net"); @@ -49,16 +49,16 @@ const testText2 = "test text #2"; // The DApp is just an object mapping routes to contents, which can be either // strings or buffers. Mime types are inferred from the extension. You can also // force them by using `{"type": "application/json", "content": "[1,2,3]"}`, for -// example. Notice the empty route also poiting to index.html. +// example. Notice the empty route also pointing to index.html. const exampleDApp = { - "" : indexHtml, - "/index.html" : indexHtml, - "/ethereum_icon.png" : ethereumIconPng, - "/foo/test_text_1.txt" : testText1, - "/foo/test_text_2.txt" : testText2 + "" : {type: "text/html", data: indexHtml}, + "/index.html" : {type: "text/html", data: indexHtml}, + "/ethereum_icon.png" : {type: "image/png", data: ethereumIconPng}, + "/foo/test_text_1.txt" : {type: "text/plain", data: testText1}, + "/foo/test_text_2.txt" : {type: "text/plain", data: testText2} } // Now we just upload it. -swarm.uploadDirectory(exampleDApp) +swarm.upload(exampleDApp) .then(console.log) .catch(console.log); diff --git a/examples/dapp_upload_from_disk.js b/examples/dapp_upload_from_disk.js index 5ec418c..601c5b6 100644 --- a/examples/dapp_upload_from_disk.js +++ b/examples/dapp_upload_from_disk.js @@ -1,12 +1,10 @@ // Uploads a DApp from a local directory to the Swarm network. // Outputs the DApp address. In this case, it is: -// 8587c8e716bfceea12a7306d85a8a8ccad5019020916eb5a21fa47a7f1826891 +// 379d2791624c3e3719bb28f7bfa362cc9c726ec06482b5800c8e3cefaf2b7bcf const swarm = require("./../swarm.js").at("http://swarm-gateways.net"); const path = require("path"); -// Notice we use the `WithDefaultPath` version, which allows us to specify a -// root file that will be served on the empty path (e.g., bzz:/my_dapp.eth/). -swarm.uploadDirectoryFromDiskWithDefaultPath("/index.html")(path.join(__dirname,"example_dapp")) +swarm.uploadDirectoryFromDisk("/index.html", path.join(__dirname,"example_dapp")) .then(console.log) .catch(console.log); diff --git a/examples/data_download.js b/examples/data_download.js index 3a64933..937280e 100644 --- a/examples/data_download.js +++ b/examples/data_download.js @@ -1,10 +1,10 @@ // Downloads raw data from the Swarm network. -// Outputs the downloaded data: "test string" +// Outputs the downloaded data: "test" const swarm = require("./../swarm.js").at("http://swarm-gateways.net"); -const hash = "a5c10851ef054c268a2438f10a21f6efe3dc3dcdcc2ea0e6a1a7a38bf8c91e23"; +const hash = "c9a99c7d326dcc6316f32fe2625b311f6dc49a175e6877681ded93137d3569e7"; -swarm.downloadData(hash) +swarm.download(hash) .then(buffer => console.log(buffer.toString())) .catch(console.log); diff --git a/examples/data_upload.js b/examples/data_upload.js index 97a16a0..f829397 100644 --- a/examples/data_upload.js +++ b/examples/data_upload.js @@ -1,8 +1,8 @@ // Uploads raw data to the Swarm network. -// Outputs the Swarm address: a5c10851ef054c268a2438f10a21f6efe3dc3dcdcc2ea0e6a1a7a38bf8c91e23 +// Outputs the Swarm address: c9a99c7d326dcc6316f32fe2625b311f6dc49a175e6877681ded93137d3569e7 const swarm = require("./../swarm.js").at("http://swarm-gateways.net"); -swarm.uploadData("test string") +swarm.upload(new Buffer("test")) .then(console.log) .catch(console.log); diff --git a/examples/examples.js b/examples/examples.js index 3268e67..72a2154 100644 --- a/examples/examples.js +++ b/examples/examples.js @@ -2,30 +2,30 @@ const swarm = require("./../swarm.js").at("http://swarm-gateways.net"); // Uploading raw data const file = "test file"; -swarm.uploadData(new Buffer(file)).then(hash => { +swarm.upload(new Buffer(file)).then(hash => { console.log("Uploaded file. Address:", hash); }) // Downloading raw data const fileHash = "a5c10851ef054c268a2438f10a21f6efe3dc3dcdcc2ea0e6a1a7a38bf8c91e23"; -swarm.downloadData(fileHash).then(buffer => { +swarm.download(fileHash).then(buffer => { console.log("Downloaded file:", buffer.toString()); }); // Uploading directory const dir = { - "/foo.txt": "sample file", - "/bar.txt": "another file" + "/foo.txt": {type: "text/plain", data: new Buffer("sample file")}, + "/bar.txt": {type: "text/plain", data: new Buffer("another file")} }; -swarm.uploadDirectory(dir).then(hash => { +swarm.upload(dir).then(hash => { console.log("Uploaded directory. Address:", hash); }); // Downloaading a directory const dirHash = "7e980476df218c05ecfcb0a2ca73597193a34c5a9d6da84d54e295ecd8e0c641"; -swarm.downloadDirectory(dirHash).then(dir => { +swarm.download(dirHash).then(dir => { console.log("Downloaded directory:"); for (let path in dir) { - console.log("-", path, ":", dir[path].toString()); + console.log("-", path, ":", dir[path].data.toString()); } }); diff --git a/examples/runNode.js b/examples/run_node.js similarity index 82% rename from examples/runNode.js rename to examples/run_node.js index 5353c48..549e95d 100644 --- a/examples/runNode.js +++ b/examples/run_node.js @@ -12,14 +12,16 @@ const config = { // Magically starts a local Swarm node // Downloads binaries if necessary Swarm.local(config)(swarm => new Promise((resolve, reject) => { + console.log("running"); + console.log(swarm); // Uploads data using the local node - swarm.uploadData("test").then(hash => { + swarm.upload(new Buffer("test")).then(hash => { console.log("Uploaded data. Address:", hash); // Closes the Swarm process. resolve(); }); -})).then(() => console.log("Done!")); - +})) +.then(() => console.log("Done!")); diff --git a/package.json b/package.json index a6635d3..db9b680 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,19 @@ { "name": "swarm-js", - "version": "0.1.0", + "version": "0.1.3", "description": "Swarm tools for JavaScript.", "main": "swarm.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "MaiaVictor", - "license": "MIT" + "license": "MIT", + "dependencies": { + "bluebird": "^3.4.7", + "fs-promise": "^2.0.0", + "got": "^6.7.1", + "mimetype": "0.0.8", + "mkdirp-promise": "^5.0.1", + "tar.gz": "^1.0.5" + } } diff --git a/swarm.js b/swarm.js index 8c6071d..48ba058 100644 --- a/swarm.js +++ b/swarm.js @@ -42,39 +42,64 @@ const downloadData = swarmUrl => hash => got(rawUrl(swarmUrl)(hash), {encoding: null}) .then(response => response.body); -// String -> String -> Promise (Map String String) -// Gets the routing table of a Swarm address. -// Returns a map from paths to addresses. -const downloadRoutes = swarmUrl => hash => { +// type Entry = {"type": String, "hash": String} +// type File = {"type": String, "data": Buffer} + +// String -> String -> Promise (Map String Entry) +// Solves the manifest of a Swarm address recursively. +// Returns a map from full paths to entries. +const downloadEntries = swarmUrl => hash => { const search = hash => path => routes => { - const entryContents = entry => + + // Formats an entry to the Swarm.js type. + const format = entry => ({ + type: entry.contentType, + hash: entry.hash}); + + // To download a single entry: + // if type is bzz-manifest, go deeper + // if not, add it to the routing table + const downloadEntry = entry => entry.contentType === "application/bzz-manifest+json" - ? search(entry.hash)(path + entry.path)(routes) - : Q.resolve(impureInsert(path + entry.path)(entry.hash)(routes)); + ? search (entry.hash) (path + entry.path) (routes) + : Q.resolve (impureInsert (path + entry.path) (format(entry)) (routes)); + + // Downloads the initial manifest and then each entry. return downloadData(swarmUrl)(hash) .then(text => JSON.parse(text).entries) - .then(entries => Q.reduce(entries.map(entryContents), (a,b) => b)); + .then(entries => Q.reduce(entries.map(downloadEntry), (a,b) => b)); + } - return search(hash)("")({}); + return search (hash) ("") ({}); } -// String -> String -> Promise (Map String Buffer) +// String -> String -> Promise (Map String String) +// Same as `downloadEntries`, but returns only hashes (no types). +const downloadRoutes = swarmUrl => hash => + downloadEntries(swarmUrl)(hash) + .then(entries => toMap + (Object.keys(entries)) + (Object.keys(entries).map(route => entries[route].hash))); + +// String -> String -> Promise (Map String File) // Gets the entire directory tree in a Swarm address. // Returns a promise mapping paths to file contents. const downloadDirectory = swarmUrl => hash => - downloadRoutes (swarmUrl) (hash) - .then(routingTable => { - const paths = Object.keys(routingTable); - const hashs = paths.map(path => routingTable[path]); - const contents = hashs.map(downloadData(swarmUrl)); - return Q.all(contents).then(contents => toMap(paths)(contents)); + downloadEntries (swarmUrl) (hash) + .then(entries => { + const paths = Object.keys(entries); + const hashs = paths.map(path => entries[path].hash); + const types = paths.map(path => entries[path].type); + const datas = hashs.map(downloadData(swarmUrl)); + const files = datas => datas.map((data, i) => ({type: types[i], data: data})); + return Q.all(datas).then(datas => toMap(paths)(files(datas))); }); -// String -> String -> Promise String +// String -> String -> String -> Promise String // Gets the raw contents of a Swarm hash address. // Returns a promise with the downloaded file path. const downloadDataToDisk = swarmUrl => hash => filePath => - files.download(rawUrl(swarmUrl)(hash))(filePath); + files.download (rawUrl(swarmUrl)(hash)) (filePath); // String -> String -> String -> Promise (Map String String) // Gets the entire directory tree in a Swarm address. @@ -95,59 +120,97 @@ const downloadDirectoryToDisk = swarmUrl => hash => dirPath => // String -> Buffer -> Promise String // Uploads raw data to Swarm. // Returns a promise with the uploaded hash. -const uploadData = swarmUrl => contents => - got(`${swarmUrl}/bzzr:/`, {"body": contents}) +const uploadData = swarmUrl => data => + got(`${swarmUrl}/bzzr:/`, {"body": data, "retries": 2}) .then(response => response.body); -// String -> String -> String -> String -> String -> Promise String -// Uploads raw data to the Swarm manifest at a given hash, -// under a specific route. -// Returns a promise containing the uploaded hash. -const uploadToManifest = swarmUrl => hash => route => mimeType => contents => - got.put(`${swarmUrl}/bzz:/${hash}${route}`, { - "headers": {"content-type": mimeType}, - "body": contents}) - .then(response => response.body); +// String -> String -> String -> File -> Promise String +// Uploads a file to the Swarm manifest at a given hash, under a specific +// route. Returns a promise containing the uploaded hash. +// FIXME: for some reasons Swarm-Gateways is sometimes returning +// error 404 (bad request), so we retry up to 3 times. Why? +const uploadToManifest = swarmUrl => hash => route => file => { + const attempt = n => { + const url = `${swarmUrl}/bzz:/${hash}${route}`; + const opt = { + "headers": {"content-type": file.type}, + "body": file.data}; + return got.put(url, opt) + .then(response => response.body) + .catch(e => n > 0 && attempt (n-1)); + }; + return attempt(3); +}; -// String -> Map String Buffer -> Promise String +// String -> Map String File -> Promise String // Uploads a directory to Swarm. The directory is -// represented as a map of routes and raw contents. +// represented as a map of routes and files. // A default path is encoded by having a "" route. const uploadDirectory = swarmUrl => directory => uploadData(swarmUrl)("{}") .then(hash => { - const uploadRoute = route => hash => { - const contents = directory[route]; - const mimeType = contents["content-type"] || mimetype.lookup(route); - return uploadToManifest(swarmUrl)(hash)(route)(mimeType)(contents); - }; - return Object.keys(directory).reduce( - (hash,route) => hash.then(uploadRoute(route)), - Q.resolve(hash)); + const uploadRoute = route => hash => uploadToManifest(swarmUrl)(hash)(route)(directory[route]); + const uploadToHash = (hash, route) => hash.then(uploadRoute(route)); + return Object.keys(directory).reduce(uploadToHash, Q.resolve(hash)); }); -// String -> Nullable String -> Map String Buffer -> Promise String -const uploadDirectoryWithDefaultPath = swarmUrl => defaultPath => directory => - uploadDirectory(swarmUrl)(merge(directory)(defaultPath ? {"": directory[defaultPath] || ""} : {})); - // String -> Promise String const uploadDataFromDisk = swarmUrl => filePath => fsp.readFile(filePath) .then(uploadData(swarmUrl)); // String -> Nullable String -> String -> Promise String -const uploadDirectoryFromDiskWithDefaultPath = swarmUrl => defaultPath => dirPath => +const uploadDirectoryFromDisk = swarmUrl => defaultPath => dirPath => files.directoryTree(dirPath) - .then(fullPaths => { - const files = Q.all(fullPaths.map(path => fsp.readFile(path))); - const paths = Q.resolve(fullPaths.map(path => path.slice(dirPath.length))); - return Q.join(paths, files, (paths, files) => toMap (paths) (files)) - }) - .then(uploadDirectoryWithDefaultPath(swarmUrl)(defaultPath)); + .then(fullPaths => Q.all(fullPaths.map(path => fsp.readFile(path))).then(datas => { + const paths = fullPaths.map(path => path.slice(dirPath.length)); + const types = fullPaths.map(path => mimetype.lookup(path) || "text/plain"); + return toMap (paths) (datas.map((data, i) => ({type: types[i], data: data}))); + })) + .then(directory => merge (defaultPath ? {"": directory[defaultPath]} : {}) (directory)) + .then(uploadDirectory(swarmUrl)); + +// String -> Buffer | Map String Buffer | String -> Nullable String -> Promise String +// Simplified multi-type upload which calls the correct one based on the +// type of the argument given. +const upload = swarmUrl => pathOrContents => defaultFile => { + // Upload raw data (buffer) + if (pathOrContents instanceof Buffer) { + return uploadData(swarmUrl)(pathOrContents); + + // Upload directory with JSON + } else if (pathOrContents instanceof Object) { + return uploadDirectory(swarmUrl)(pathOrContents); + + // Upload directory/file from disk + } else if (typeof pathOrContents === "string") { + const path = pathOrContents; + return fsp.lstat(path).then(stat => { + return stat.isDirectory() + ? uploadDirectoryFromDisk(swarmUrl)(path)(defaultFile) + : uploadFileFromDisk(swarmUrl)(path); + }); + } -// String -> String -> Promise String -const uploadDirectoryFromDisk = swarmUrl => dirPath => - uploadDirectoryFromDiskWithDefaultPath (swarmUrl) (null) (dirPath); + return Q.reject(new Error("Bad arguments")); +} + +// String -> String -> Nullable String -> Promise (String | Buffer | Map String Buffer) +// Simplified multi-type download which calls the correct function based on +// the type of the argument given, and on whether the Swwarm address has a +// directory or a file. +const download = swarmUrl => hash => path => + isDirectory(swarmUrl)(hash).then(isDir => { + if (isDir) { + return path + ? downloadDirectoryToDisk(swarmUrl)(hash)(path) + : downloadDirectory(swarmUrl)(hash); + } else { + return path + ? downloadDataToDisk(swarmUrl)(hash)(path) + : downloadData(swarmUrl)(hash); + } + }); // String -> Promise String // Downloads the Swarm binaries into a path. Returns a promise that only @@ -231,6 +294,7 @@ const stopProcess = process => new Q((resolve, reject) => { // SwarmSetup -> (SwarmAPI -> Promise ()) -> Promise () // Receives a Swarm configuration object and a callback function. It then +// checks if a local Swarm node is running. If no local Swarm is found, it // downloads the Swarm binaries to the dataDir (if not there), checksums, // starts the Swarm process and calls the callback function with an API // object using the local node. That callback must return a promise which @@ -239,14 +303,18 @@ const stopProcess = process => new Q((resolve, reject) => { // user is done with the API and the Swarm process is closed. // TODO: check if Swarm process is already running (improve `isAvailable`) const local = swarmSetup => useAPI => - downloadBinary(path.join(swarmSetup.dataDir, "bin", "swarm")) - .then(() => startProcess(swarmSetup)) - .then(process => useAPI(at("http://localhost:8500")).then(() => process)) - .then(stopProcess); - + isAvailable("http://localhost:8500").then(isAvailable => + isAvailable + ? useAPI(at("http://localhost:8500")).then(() => {}) + : downloadBinary(path.join(swarmSetup.dataDir, "bin", "swarm")) + .then(() => startProcess(swarmSetup)) + .then(process => useAPI(at("http://localhost:8500")).then(() => process)) + .then(stopProcess)); + // String ~> Promise Bool // Returns true if Swarm is available on `url`. -// TODO: too slow; can this be improved? +// Perfoms a test upload to determine that. +// TODO: improve this? const isAvailable = swarmUrl => { const testFile = "test"; const testHash = "c9a99c7d326dcc6316f32fe2625b311f6dc49a175e6877681ded93137d3569e7"; @@ -255,43 +323,67 @@ const isAvailable = swarmUrl => { .catch(() => false); }; +// String -> String ~> Promise Bool +// Returns a Promise which is true if that Swarm address is a directory. +// Determines that by checking that it (i) is a JSON, (ii) has a .entries. +// TODO: improve this? +const isDirectory = swarmUrl => hash => + downloadData(swarmUrl)(hash) + .then(data => !!JSON.parse(data.toString()).entries) + .catch(() => false); + +// Uncurries a function; used to allow the f(x,y,z) style on exports. +const uncurry = f => (a,b,c,d,e) => { + // Hardcoded because efficiency (`arguments` is very slow). + if (typeof a !== "undefined") f = f(a); + if (typeof b !== "undefined") f = f(b); + if (typeof c !== "undefined") f = f(c); + if (typeof d !== "undefined") f = f(d); + if (typeof e !== "undefined") f = f(e); + return f; +}; + // () -> Promise Bool // Not sure how to mock Swarm to test it properly. Ideas? const test = () => Q.resolve(true); // String -> SwarmAPI +// Fixes the `swarmUrl`, returning an API where you don't have to pass it. const at = swarmUrl => ({ - downloadData: downloadData(swarmUrl), - downloadDataToDisk: downloadDataToDisk(swarmUrl), - downloadDirectory: downloadDirectory(swarmUrl), - downloadDirectoryToDisk: downloadDirectoryToDisk(swarmUrl), - downloadRoutes: downloadRoutes(swarmUrl), + download: (hash,path) => download(swarmUrl)(hash)(path), + downloadData: uncurry(downloadData(swarmUrl)), + downloadDataToDisk: uncurry(downloadDataToDisk(swarmUrl)), + downloadDirectory: uncurry(downloadDirectory(swarmUrl)), + downloadDirectoryToDisk: uncurry(downloadDirectoryToDisk(swarmUrl)), + downloadRoutes: uncurry(downloadRoutes(swarmUrl)), + downloadEntries: uncurry(downloadEntries(swarmUrl)), isAvailable: () => isAvailable(swarmUrl), - uploadData: uploadData(swarmUrl), - uploadDataFromDisk: uploadDataFromDisk(swarmUrl), - uploadDirectory: uploadDirectory(swarmUrl), - uploadDirectoryFromDisk: uploadDirectoryFromDisk(swarmUrl), - uploadDirectoryFromDiskWithDefaultPath: uploadDirectoryFromDiskWithDefaultPath(swarmUrl), - uploadToManifest: uploadToManifest(swarmUrl), + upload: (pathOrContents,defaultFile) => upload(swarmUrl)(pathOrContents)(defaultFile), + uploadData: uncurry(uploadData(swarmUrl)), + uploadDataFromDisk: uncurry(uploadDataFromDisk(swarmUrl)), + uploadDirectory: uncurry(uploadDirectory(swarmUrl)), + uploadDirectoryFromDisk: uncurry(uploadDirectoryFromDisk(swarmUrl)), + uploadToManifest: uncurry(uploadToManifest(swarmUrl)), }); module.exports = { at, - local, + download, downloadBinary, downloadData, downloadDataToDisk, downloadDirectory, downloadDirectoryToDisk, downloadRoutes, + downloadEntries, isAvailable, + local, startProcess, stopProcess, + upload, uploadData, uploadDataFromDisk, uploadDirectory, uploadDirectoryFromDisk, - uploadDirectoryFromDiskWithDefaultPath, uploadToManifest, }; -