Skip to content

Commit

Permalink
Completely remove buffer from browser
Browse files Browse the repository at this point in the history
  • Loading branch information
VictorTaelin committed Aug 9, 2017
1 parent d52c111 commit 5542130
Show file tree
Hide file tree
Showing 14 changed files with 2,900 additions and 93 deletions.
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This library allows you to interact with the Swarm network from JavaScript.

- 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).
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 (Uint8Array or UTF-8 String).

```javascript
const dir = {
Expand Down Expand Up @@ -77,8 +77,8 @@ This library allows you to interact with the Swarm network from JavaScript.

```javascript
const fileHash = "a5c10851ef054c268a2438f10a21f6efe3dc3dcdcc2ea0e6a1a7a38bf8c91e23";
swarm.download(fileHash).then(buffer => {
console.log("Downloaded file:", buffer.toString());
swarm.download(fileHash).then(array => {
console.log("Downloaded file:", swarm.toString(array));
});
```

Expand Down Expand Up @@ -108,6 +108,15 @@ This library allows you to interact with the Swarm network from JavaScript.
(Just link the Swarm URL.)
#### SwarmHash
```javascript
console.log(swarm.hash("unicode string áéíóú λ"));
console.log(swarm.hash("0x41414141"));
console.log(swarm.hash([65, 65, 65, 65]));
console.log(swarm.hash(new Uint8Array([65, 65, 65, 65])));
```
### More
For more examples, check out [examples](/examples).
43 changes: 23 additions & 20 deletions examples/simple_usage.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
const swarm = require("./..").at("http://swarm-gateways.net");

(async () => {
try {
// Uploading raw data
const file = "this is a test";
const fileHash = await swarm.upload(new Buffer(file))
console.log("Uploaded file. SwarmHash:", fileHash);

// Uploading raw data
const file = "this is a test";
const fileHash = await swarm.upload(new Buffer(file))
console.log("Uploaded file. SwarmHash:", fileHash);
//// Downloading raw data
const fileBuffer = await swarm.download(fileHash);
console.log("Downloaded file. Contents:", swarm.toString(fileBuffer));

// Downloading raw data
const fileBuffer = await swarm.download(fileHash);
console.log("Downloaded file. Contents:", fileBuffer.toString());
// Uploading directory
const dir = {
"/foo.txt": {type: "text/plain", data: "this is foo.txt"},
"/bar.txt": {type: "text/plain", data: "this is bar.txt"}
};
const dirHash = await swarm.upload(dir);
console.log("Uploaded directory. SwarmHash:", dirHash);

// Uploading directory
const dir = {
"/foo.txt": {type: "text/plain", data: new Buffer("this is foo.txt")},
"/bar.txt": {type: "text/plain", data: new Buffer("this is bar.txt")}
};
const dirHash = await swarm.upload(dir);
console.log("Uploaded directory. SwarmHash:", dirHash);

//// Downloaading a directory
const dirObj = await swarm.download(dirHash);
console.log("Downloaded directory. Contents:");
for (let path in dirObj)
console.log("-", path, ":", dirObj[path].data.toString());
//// Downloaading a directory
const dirObj = await swarm.download(dirHash);
console.log("Downloaded directory. Contents:");
for (let path in dirObj)
console.log("-", path, ":", swarm.toString(dirObj[path].data));
} catch (e) {
console.log(e);
}

})();
22 changes: 21 additions & 1 deletion lib/api-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ var files = { download: unavailable, safeDownloadArchived: unavailable, director
var os = { platform: unavailable, arch: unavailable };
var path = { join: unavailable, slice: unavailable };
var child_process = { spawn: unavailable };
var mimetype = { lookup: unavailable };
var defaultArchives = {};
var downloadUrl = null;
var request = require("xhr-request-promise");
var bytes = require("eth-lib/lib/bytes");
var hash = require("./swarm-hash.js");
var pick = require("./pick.js");
var swarm = require("./swarm");

module.exports = swarm({ fsp: fsp, files: files, os: os, path: path, child_process: child_process });
module.exports = swarm({
fsp: fsp,
files: files,
os: os,
path: path,
child_process: child_process,
defaultArchives: defaultArchives,
mimetype: mimetype,
request: request,
downloadUrl: downloadUrl,
bytes: bytes,
hash: hash,
pick: pick
});
34 changes: 33 additions & 1 deletion lib/api-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,38 @@ var files = require("./files.js");
var os = require("os");
var path = require("path");
var child_process = require("child_process");
var mimetype = require('mime-types');
var defaultArchives = require("./../archives/archives.json");
var requester = require("xhr-request-promise");
var downloadUrl = "http://ethereum-mist.s3.amazonaws.com/swarm/";
var bytes = require("eth-lib/lib/bytes");
var hash = require("./swarm-hash.js");
var pick = require("./pick.js");
var swarm = require("./swarm");

module.exports = swarm({ fsp: fsp, files: files, os: os, path: path, child_process: child_process });
// Fixes issue that causes xhr-request-promise on Node.js to only accept Buffer
var request = function request(url, params) {
var newParams = {};
for (var key in params) {
newParams[key] = params[key];
}
if (typeof newParams.body !== "undefined") {
newParams.body = newParams.body instanceof Buffer ? newParams.body : new Buffer(newParams.body);
}
return requester(url, newParams);
};

module.exports = swarm({
fsp: fsp,
files: files,
os: os,
path: path,
child_process: child_process,
defaultArchives: defaultArchives,
mimetype: mimetype,
request: request,
downloadUrl: downloadUrl,
bytes: bytes,
hash: hash,
pick: pick
});
2 changes: 1 addition & 1 deletion lib/pick.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var picker = function picker(type) {
[].map.call(e.target.files, function (file) {
var reader = new FileReader();
reader.onload = function (e) {
var data = new Buffer(e.target.result);
var data = new Uint8Array(e.target.result);
if (type === "directory") {
var path = file.webkitRelativePath;
directory[path.slice(path.indexOf("/") + 1)] = {
Expand Down
11 changes: 10 additions & 1 deletion lib/swarm-hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@ var keccak = require("eth-lib/lib/hash").keccak256;
var Bytes = require("eth-lib/lib/bytes");

var swarmHashBlock = function swarmHashBlock(length, data) {
return keccak(Bytes.flatten([Bytes.reverse(Bytes.pad(6, Bytes.fromNumber(length))), "0x0000", data]));
var lengthEncoded = Bytes.reverse(Bytes.pad(6, Bytes.fromNumber(length)));
var bytes = Bytes.flatten([lengthEncoded, "0x0000", data]);
return keccak(bytes).slice(2);
};

// (Bytes | Uint8Array | String) -> String
var swarmHash = function swarmHash(data) {
if (typeof data === "string" && data.slice(0, 2) !== "0x") {
data = Bytes.fromString(data);
} else if (typeof data !== "string" && data.length !== undefined) {
data = Bytes.fromUint8Array(data);
}

var length = Bytes.length(data);

if (length <= 4096) {
Expand Down
92 changes: 63 additions & 29 deletions lib/swarm.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
var mimetype = require('mime-types');
var hash = require("./swarm-hash.js");
var pick = require("./pick.js");
var request = require("xhr-request-promise");
var downloadUrl = "http://ethereum-mist.s3.amazonaws.com/swarm/";
var defaultArchives = require("./../archives/archives.json");
var Buffer = require("buffer").Buffer;

// TODO: this is a temporary fix to hide those libraries from the browser. A
// slightly better long-term solution would be to split this file into two,
// separating the functions that are used on Node.js from the functions that
Expand All @@ -15,7 +7,14 @@ module.exports = function (_ref) {
files = _ref.files,
os = _ref.os,
path = _ref.path,
child_process = _ref.child_process;
child_process = _ref.child_process,
mimetype = _ref.mimetype,
defaultArchives = _ref.defaultArchives,
request = _ref.request,
downloadUrl = _ref.downloadUrl,
bytes = _ref.bytes,
hash = _ref.hash,
pick = _ref.pick;


// ∀ a . String -> JSON -> Map String a -o Map String a
Expand Down Expand Up @@ -52,25 +51,42 @@ module.exports = function (_ref) {
};
};

// ∀ a . [a] -> [a] -> Bool
var equals = function equals(a) {
return function (b) {
if (a.length !== b.length) {
return false;
} else {
for (var i = 0, l = a.length; i < a; ++i) {
if (a[i] !== b[i]) return false;
}
}
return true;
};
};

// String -> String -> String
var rawUrl = function rawUrl(swarmUrl) {
return function (hash) {
return swarmUrl + "/bzzr:/" + hash;
};
};

// String -> String -> Promise Buffer
// String -> String -> Promise Uint8Array
// Gets the raw contents of a Swarm hash address.
var downloadData = function downloadData(swarmUrl) {
return function (hash) {
return request(rawUrl(swarmUrl)(hash), { responseType: "arraybuffer" }).then(function (arrayBuffer) {
return new Buffer(arrayBuffer);
var uint8Array = new Uint8Array(arrayBuffer);
var error404 = [52, 48, 52, 32, 112, 97, 103, 101, 32, 110, 111, 116, 32, 102, 111, 117, 110, 100, 10];
if (equals(uint8Array)(error404)) throw "Error 404.";
return uint8Array;
});
};
};

// type Entry = {"type": String, "hash": String}
// type File = {"type": String, "data": Buffer}
// type File = {"type": String, "data": Uint8Array}

// String -> String -> Promise (Map String Entry)
// Solves the manifest of a Swarm address recursively.
Expand Down Expand Up @@ -100,7 +116,7 @@ module.exports = function (_ref) {

// Downloads the initial manifest and then each entry.
return downloadData(swarmUrl)(hash).then(function (text) {
return JSON.parse(text.toString()).entries;
return JSON.parse(toString(text)).entries;
}).then(function (entries) {
return Promise.all(entries.map(downloadEntry));
}).then(function () {
Expand Down Expand Up @@ -185,13 +201,13 @@ module.exports = function (_ref) {
};
};

// String -> Buffer -> Promise String
// String -> Uint8Array -> Promise String
// Uploads raw data to Swarm.
// Returns a promise with the uploaded hash.
var uploadData = function uploadData(swarmUrl) {
return function (data) {
return request(swarmUrl + "/bzzr:/", {
body: typeof data === "string" ? new Buffer(data) : data,
body: typeof data === "string" ? fromString(data) : data,
method: "POST" });
};
};
Expand All @@ -212,7 +228,12 @@ module.exports = function (_ref) {
method: "PUT",
headers: { "Content-Type": file.type },
body: file.data };
return request(url, opt).catch(function (e) {
return request(url, opt).then(function (response) {
if (response.indexOf("error") !== -1) {
throw response;
}
return response;
}).catch(function (e) {
return n > 0 && attempt(n - 1);
});
};
Expand All @@ -222,7 +243,7 @@ module.exports = function (_ref) {
};
};

// String -> {type: String, data: Buffer} -> Promise String
// String -> {type: String, data: Uint8Array} -> Promise String
var uploadFile = function uploadFile(swarmUrl) {
return function (file) {
return uploadDirectory(swarmUrl)({ "": file });
Expand Down Expand Up @@ -318,12 +339,8 @@ module.exports = function (_ref) {
return uploadDirectoryFromDisk(swarmUrl)(arg.defaultFile)(arg.path);
};

// Upload UTF-8 string
} else if (typeof arg === "string") {
return uploadData(swarmUrl)(new Buffer(arg));

// Upload raw data (buffer)
} else if (arg.length) {
// Upload UTF-8 string or raw data (buffer)
} else if (arg.length || typeof arg === "string") {
return uploadData(swarmUrl)(arg);

// Upload directory with JSON
Expand All @@ -335,7 +352,7 @@ module.exports = function (_ref) {
};
};

// String -> String -> Nullable String -> Promise (String | Buffer | Map String Buffer)
// String -> String -> Nullable String -> Promise (String | Uint8Array | Map String Uint8Array)
// 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.
Expand Down Expand Up @@ -506,9 +523,11 @@ module.exports = function (_ref) {
var isDirectory = function isDirectory(swarmUrl) {
return function (hash) {
return downloadData(swarmUrl)(hash).then(function (data) {
return !!JSON.parse(data.toString()).entries;
}).catch(function () {
return false;
try {
return !!JSON.parse(toString(data)).entries;
} catch (e) {
return false;
}
});
};
};
Expand All @@ -532,6 +551,16 @@ module.exports = function (_ref) {
return Promise.resolve(true);
};

// Uint8Array -> String
var toString = function toString(uint8Array) {
return bytes.toString(bytes.fromUint8Array(uint8Array));
};

// String -> Uint8Array
var fromString = function fromString(string) {
return bytes.toUint8Array(bytes.fromString(string));
};

// String -> SwarmAPI
// Fixes the `swarmUrl`, returning an API where you don't have to pass it.
var at = function at(swarmUrl) {
Expand All @@ -558,7 +587,10 @@ module.exports = function (_ref) {
uploadDirectory: uncurry(uploadDirectory(swarmUrl)),
uploadDirectoryFromDisk: uncurry(uploadDirectoryFromDisk(swarmUrl)),
uploadToManifest: uncurry(uploadToManifest(swarmUrl)),
pick: pick
pick: pick,
hash: hash,
fromString: fromString,
toString: toString
};
};

Expand All @@ -585,6 +617,8 @@ module.exports = function (_ref) {
uploadDirectoryFromDisk: uploadDirectoryFromDisk,
uploadToManifest: uploadToManifest,
pick: pick,
hash: hash
hash: hash,
fromString: fromString,
toString: toString
};
};
Loading

0 comments on commit 5542130

Please sign in to comment.