Introduced bson support for browser js client lib. (#308)

* Added blake3 import and safari compatibility fix.
* Created browser lib with bson support.
* Added 'terser' for minification.
* Added TextEncoder compatiblity fix.
This commit is contained in:
Ravin Perera
2021-05-13 15:14:29 +05:30
committed by GitHub
parent 5da88aa5c5
commit 6a8f449d5b
8 changed files with 9058 additions and 2501 deletions

View File

@@ -0,0 +1,16 @@
# Hot Pocket javascript client library and examples
Single-file javascript library to support json and bson protocols in NodeJs and Browser environments.
## NodeJs
1. Run `npm install` to install all the dependencies.
1. `lib/hp-client-lib.js` is the Hot Pocket client library for NodeJs.
1. `text-client.js` is the example for json mode.
1. `file-client.js` is the example for bson mode.
## Browser
1. Run `npm install` to install all the compilation dependencies.
1. Run `npm run build-browser` to produced the minified library for the browser.
1. `browser-example.html` is the simple html/javascript example for json mode.
(For BSON support in browser, a slightly modified version of https://www.npmjs.com/package/bson is used. The minified library includes this bson support library as well)

View File

@@ -3,19 +3,14 @@
<head>
<title>HotPocket browser example</title>
<script src="hp-client-lib.js"></script>
<!--'npm run build-browser' to generate the browser lib.-->
<script src="dist/hp-client-lib.min.js"></script>
<!--Hot Pocket client library requires libsodium js for cryptographic operations.-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/libsodium-wrappers/0.5.4/sodium.min.js"
integrity="sha512-oRfU7aik4u7f0dPAKgOyA4+bb/YRGfAaD5RA4Z3Mb2ycPcGDs+k8qAnDNd7ouruoqlIHSuGVaTTlEs91Gvd37A=="
crossorigin="anonymous"></script>
<!--Hot Pocket client library requires blake3 for hashing operations.-->
<script type="module">
import init from 'https://cdn.jsdelivr.net/npm/blake3@2.1.4/browser-async.js';
init().then(blake3 => HotPocket.setBlake3(blake3)).catch(console.error);
</script>
<script>
async function testFunc() {

View File

@@ -2,7 +2,7 @@ const fs = require('fs');
const readline = require('readline');
const bson = require('bson');
var path = require("path");
const HotPocket = require('./hp-client-lib');
const HotPocket = require('./lib/hp-client-lib');
async function main() {

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,9 @@
/**
* Hot Pocket javascript client library (for NodeJs and Browser)
* NodeJs: const HotPocket = require("./hp-client-lib")
* Browser: window.HotPocket
*/
(() => {
// Whether we are in Browser or NodeJs.
@@ -7,6 +13,14 @@
if (isBrowser && window.HotPocket)
return;
// Common data type initialization.
if (!isBrowser) {
// In browser, these are available in the global scopre. It's just in NodeJs they are in 'util' scope.
const util = require("util");
TextEncoder = util.TextEncoder;
TextDecoder = util.TextDecoder;
}
const supportedHpVersion = "1.0.0";
const serverChallengeSize = 16;
const outputValidationPassThreshold = 0.8;
@@ -26,7 +40,7 @@
/*--- Included in public interface. ---*/
const protocols = {
json: "json",
bson: "bson" // (Requires nodejs or browserified hp client library on Browser)
bson: "bson"
}
Object.freeze(protocols);
@@ -108,7 +122,7 @@
await initBlake3();
initWebSocket();
if (opt.protocol == protocols.bson)
initBson();
await initBson();
// Load servers and serverKeys to object keys to avoid duplicates.
@@ -684,7 +698,7 @@
catch (e) {
liblog(1, e);
liblog(0, "Exception deserializing: ");
liblog(0, (data && (isTextMode ? data.toString() : data) || rcvd));
liblog(0, data || rcvd);
// If we get invalid message during handshake, close the socket.
if (connectionStatus < 2)
@@ -1078,7 +1092,7 @@
}
else { // nodejs
if (!sodium)
sodium = require('libsodium-wrappers');
sodium = require("libsodium-wrappers");
await sodium.ready;
}
@@ -1087,13 +1101,28 @@
}
// Set bson reference.
function initBson() {
if (bson) // If already set, do nothing.
let bsonAwaiter = null;
async function initBson() {
if (bson) { // If already set, do nothing.
return;
else if (isBrowser && window.BSON) // browser
bson = window.BSON;
else if (!isBrowser) // nodejs
bson = require('bson');
}
else if (isBrowser) { // Browser
if (!bsonAwaiter) {
bsonAwaiter = new Promise(resolve => {
// Trigger a event loop cycle to let the bson lib load.
setTimeout(() => {
// We assume our custom version of bson-browser.js lib is now loaded.
bson = window.BSON;
window.Buffer = window.BSON.BufferPolyfill; // Buffer polyfill exposed in our modified BSON lib.
resolve();
}, 0);
});
}
await bsonAwaiter;
}
else if (!isBrowser) { // nodejs
bson = require("bson");
}
if (!bson)
throw "BSON reference not found.";
@@ -1106,15 +1135,14 @@
else if (isBrowser && window.WebSocket) // browser
WebSocket = window.WebSocket;
else if (!isBrowser) // nodejs
WebSocket = require('ws');
WebSocket = require("ws");
if (!WebSocket)
throw "WebSocket reference not found.";
}
let blake3Resolver = null;
let blake3awaiter = null;
// Set blake3 reference.
let blake3awaiter = null;
async function initBlake3() {
if (blake3) { // If already set, do nothing.
return;
@@ -1122,29 +1150,51 @@
else if (isBrowser && window.blake3) {// browser (if blake3 already loaded)
blake3 = window.blake3;
}
else if (isBrowser && !window.blake3) { // If blake3 not yet loaded in browser, wait for it.
if (!blake3awaiter)
blake3awaiter = new Promise(resolve => blake3Resolver = resolve);
blake3 = await blake3awaiter;
else if (isBrowser && !window.blake3) { // If blake3 not yet loaded in browser, load it.
if (!blake3awaiter) {
blake3awaiter = new Promise(resolve => {
// The Blake3 library we are using (https://github.com/connor4312/blake3) causes issue on Mac/iOS (Safari) due
// to Safari's lack of support for BigInt/BigUint64Array data types as of 25 Apr 2021. Here, we are adding empty
// definitions to avoid complete initialization failure of Blake3 library on Mac/iOS.
if (typeof (BigUint64Array) === "undefined")
BigUint64Array = function (v) { }
if (typeof (BigInt) === "undefined")
BigInt = function (v) { }
// Import the blake3 browser module at runtime.
const url = "https://cdn.jsdelivr.net/npm/blake3@2.1.4/browser-async.js";
import(url).then(module => {
module.default()
.then(blake3ref => {
blake3 = blake3ref;
resolve();
})
.catch(err => {
console.error(err);
resolve();
});
}).catch(err => {
console.error(err);
resolve();
});
});
}
await blake3awaiter;
return;
}
else if (!isBrowser) { // nodejs
blake3 = require('blake3');
blake3 = require("blake3");
}
if (!blake3)
throw "Blake3 reference not found.";
}
function setBlake3(blake3ref) {
if (blake3Resolver) {
blake3Resolver(blake3ref)
blake3Resolver = null;
}
else {
blake3 = blake3ref;
}
}
function setLogLevel(level) {
logLevel = level;
}
@@ -1160,7 +1210,6 @@
createClient,
events,
protocols,
setBlake3,
setLogLevel
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,9 @@
{
"scripts": {
"build-node": "browserify --node -p tinyify hp-client-lib.js -o dist/hp-node-client-lib.js",
"build-browser": "browserify -p tinyify hp-client-lib.js -o dist/hp-browser-client-lib.js"
"merge-browser": "rm -r dist ; mkdir -p dist && cp lib/bson-browser.js dist/hp-client-lib.js && cat lib/hp-client-lib.js >> dist/hp-client-lib.js",
"minify-browser": "terser --compress --mangle reserved=['Binary','Buffer'] -- dist/hp-client-lib.js > dist/hp-client-lib.min.js && rm dist/hp-client-lib.js",
"build-browser": "npm run merge-browser && npm run minify-browser",
"build-nodejs": "ncc build lib/hp-client-lib.js -o dist/hp-client"
},
"dependencies": {
"libsodium-wrappers": "0.7.6",
@@ -10,9 +12,6 @@
"bson": "4.0.4"
},
"devDependencies": {
"tinyify": "3.0.0",
"browserify": "16.5.2",
"utf-8-validate": "5.0.2",
"bufferutil": "4.0.1"
"terser": "5.7.0"
}
}

View File

@@ -1,5 +1,5 @@
const readline = require('readline');
const HotPocket = require('./hp-client-lib');
const HotPocket = require('./lib/hp-client-lib');
async function main() {