Socket
Socket
Sign inDemoInstall

nogap

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nogap - npm Package Compare versions

Comparing version 0.5.10 to 0.5.11

58

_README.md

@@ -180,23 +180,48 @@ [![NPM version](https://badge.fury.io/js/nogap.svg)](http://badge.fury.io/js/nogap)

```js
tellMeSomething: function(name) {
nBytes += (message && message.length) || 0;
return 'Host has received a total of ' + nBytes + ' bytes.';
}
var NoGapDef = require('nogap').Def;
// ...
NoGapDef.component({
Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) {
var nBytes = 0;
onButtonClick: function() {
document.body.innerHTML +='Button was clicked.<br />';
this.host.tellMeSomething('hello!')
.bind(this) // this is tricky!
.then(function(hostMessage) {
this.showHostMessage(hostMessage);
});
},
return {
Public: {
tellMeSomething: function(message) {
nBytes += (message && message.length) || 0;
this.Tools.log('Client said: ' + message);
return 'Thank you! I now received a total of ' + nBytes + ' bytes.';
}
}
};
}),
Client: NoGapDef.defClient(function(Tools, Instance, Context) {
return {
initClient: function() {
// bind a button to a component function (quick + dirty):
window.clickMe = this.onButtonClick.bind(this);
document.body.innerHTML += '<button onclick="window.clickMe();">Click Me!</button><br />';
},
onButtonClick: function() {
document.body.innerHTML +='Button was clicked.<br />';
this.host.tellMeSomething('hello!')
.then(function(hostMessage) {
document.body.innerHTML += 'Host said: ' + hostMessage + '<br />';
})
.catch(function(err) {
// this can be a connection error, a bug, a Host-side `reject` etc etc...
console.error('Something went wrong: ' + (err.stack || err));
});
}
};
})
});
```
**New Concepts**
* `Client.initClient` will be called right after the Client connected.
* Upon button click, we call `this.host.tellMeSomething(...)` which will send a request to the `Host` to invoke that method (given it is in `Host.Public`).
* Calling a `Public` function on a component's `host` object returns a promise.
* That promise is part of a full-stack [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them). A value returned by a `Host`'s `Public` function (or by a promise returned by such function), will be received by the client.
* Note that [JavaScript's `this` is tricky](http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/)!
* That promise is part of a full-stack [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them). Once finnished, we get the return value from that `Host` method in our `then` callback.

@@ -247,3 +272,4 @@

* We need to perform an asynchronous request whose result is to be sent to the other side
* Simply use [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them)!
* Simply use [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them)!
* NOTE: [JavaScript's `this` is tricky](http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/)!

@@ -250,0 +276,0 @@

@@ -21,2 +21,4 @@ /**

initHost: function(app, cfg) {},
bootstrap: function(app, cfg) {},

@@ -31,8 +33,11 @@ Private: {

Client: ComponentDef.defClient(function(Tools, Instance, Context) { return {
Private: {
/**
* This client-side function tells the host to execute the given command of the given component.
*/
sendClientRequestToHost: function(clientRequest) {},
/**
* This client-side function tells the host to execute the given command of the given component.
*/
sendRequestToHost: function(clientRequest) {},
Public: {
refresh: function() {},
redirect: function(newLocation, inOldContext) {}
}

@@ -181,2 +186,12 @@ }})

}
},
redirect: function(newLocation, inOldContext) {
var connection = this.getDefaultConnection();
if (connection.client) {
connection.client.redirect(newLocation, inOldContext);
}
else {
connection.redirect(newLocation, inOldContext);
}
}

@@ -471,3 +486,3 @@ }

.then(function() {
return connection.sendCustomClientRequestToHost.apply(connection, args);
return connection.sendRequestToHost.apply(connection, args);
})

@@ -519,3 +534,3 @@

var clientRequest = this._requestPacket.compilePacket();
return this.getDefaultConnection().sendClientRequestToHost(clientRequest)
return this.getDefaultConnection().sendRequestToHost(clientRequest)

@@ -673,2 +688,6 @@ // once received, handle reply sent back by Host

}
},
getCurrentConnectionState: function() {
return this._currentConnectionState;
}

@@ -745,3 +764,3 @@ }

'ComponentCommunications', 'requestRefresh');
this.Def.InstanceProto.sendResponseToClient(responsePacket, res);
this.Def.InstanceProto.sendRPCResponseToClient(responsePacket, res);
res.end();

@@ -769,3 +788,3 @@ return null;

var connection = Instance.Libs.ComponentCommunications.getDefaultConnection();
connection.sendResponseToClient(hostResponseData, res);
connection.sendRPCResponseToClient(hostResponseData, res);
});

@@ -827,2 +846,5 @@ };

router.get(cfg.baseUrl + "*", function(req, res, next) {
this._currentConnectionState = res;
this._lastReq = req;
// register error handler to avoid application crash

@@ -853,4 +875,5 @@ var onError = function(err) {

router.post(cfg.baseUrl, function(req, res, next) {
// extract body data
// see: http://stackoverflow.com/a/4310087/2228771
// remember request object
this._lastReq = req;
var Instance = req.getInstance();

@@ -860,6 +883,9 @@ if (!Instance) {

// res.end();
return;
}
this._currentConnectionState = res;
// extract body data
// see: http://stackoverflow.com/a/4310087/2228771
var body = '';

@@ -870,30 +896,9 @@ req.on('data', function (data) {

req.on('end', function () {
// execute RPC request and send host's response back to client
var implementationInstance = Instance.Libs.ComponentCommunications.getDefaultConnection();
var clientRequest;
try {
clientRequest = serializer.deserialize(body);
}
catch (err) {
// empty request is invalid
var maxLen = 800;
if (body.length > maxLen) {
// truncate to at most maxLen characters
body = body.substring(0, maxLen) + '...';
}
err = new Error('Invalid data sent by client cannot be parsed: ' +
body + ' -- Error: ' + err.message || err);
implementationInstance._serializeAndSendError(err, res);
return;
}
if (!clientRequest) {
// empty request is invalid
implementationInstance._serializeAndSendError(new Error('Empty client request'), res);
return;
}
// handle the request
implementationInstance._handleClientRPCRequest(req, res, next, clientRequest);
implementationInstance.handleClientRPCRequestString(body, req.headers, res)
.bind(this)
.finally(function() {
this._currentConnectionState = null;
});
}.bind(this));

@@ -903,6 +908,2 @@ }.bind(this));

setGlobal: function(varName, varValue) {
GLOBAL[varName] = varValue;
},
Private: {

@@ -929,16 +930,3 @@ __ctor: function() {

_serializeAndSendError: function(err, res) {
var hostResponseData = [this.Instance.Libs.ComponentCommunications.serializeRPCError(err)];
return this.Instance.Libs.ComponentCommunications.executeInOrder(function() {
return hostResponseData;
})
.bind(this)
.then(function(packet) {
this.sendResponseToClient(packet, res);
});
},
_handleClientBootstrapRequest: function(req, res, next) {
this._lastReq = req;
// store some client information

@@ -1023,14 +1011,51 @@ var clientRoot = req.protocol + '://' + req.get('host');

_handleClientRPCRequest: function(req, res, next, clientRequest) {
// remember request object
this._lastReq = req;
_serializeAndSendError: function(err, connectionState) {
var hostResponseData = [this.Instance.Libs.ComponentCommunications.serializeRPCError(err)];
return this.Instance.Libs.ComponentCommunications.executeInOrder(function() {
return hostResponseData;
})
.bind(this)
.then(function(packet) {
this.sendRPCResponseToClient(packet, connectionState);
});
},
handleClientRPCRequestString: function(requestString, requestMetadata, connectionState) {
var clientRequest;
try {
clientRequest = serializer.deserialize(requestString);
}
catch (err) {
// empty request is invalid
var maxLen = 800;
if (requestString.length > maxLen) {
// truncate to at most maxLen characters
requestString = requestString.substring(0, maxLen) + '...';
}
err = new Error('Invalid data sent by client cannot be parsed: ' +
requestString + ' -- Error: ' + err.message || err);
this._serializeAndSendError(err, connectionState);
return;
}
if (!clientRequest) {
// empty request is invalid
this._serializeAndSendError(new Error('Empty client request'), connectionState);
return;
}
// handle the request
return this.handleClientRPCRequest(clientRequest, requestMetadata, connectionState);
},
handleClientRPCRequest: function(clientRequest, requestMetadata, connectionState) {
var Tools = this.Instance.Libs.ComponentCommunications.Tools;
// Execute commands.
// Once finished executing, `sendResponseToClient` will be called
// Once finished executing, `sendRPCResponseToClient` will be called
// with the response packet to be interpreted on the client side.
return this.Instance.Libs.ComponentCommunications.handleClientRequest(req.headers, clientRequest)
return this.Instance.Libs.ComponentCommunications.handleClientRequest(requestMetadata, clientRequest)
.then(function(hostResponseData) {
this.sendResponseToClient(hostResponseData, res);
this.sendRPCResponseToClient(hostResponseData, connectionState);
}.bind(this))

@@ -1045,17 +1070,18 @@

*/
sendResponseToClient: function(response, res) {
console.assert(res, 'Tried to call `sendResponseToClient` without `res` connection state object.');
sendRPCResponseToClient: function(hostResponseData, connectionState) {
// connectionState == HtppResponse object
console.assert(connectionState, 'Tried to call `sendRPCResponseToClient` without `connectionState` connection state object.');
// if response object is given, send right away
var commandStr;
var hostResponseString;
try {
// Serialize
commandStr = serializer.serialize(response);
hostResponseString = serializer.serialize(hostResponseData);
}
catch (err) {
// produce pruned string representation
var commStr = squishy.objToString(response, true, 3);
var commStr = squishy.objToString(hostResponseData, true, 3);
res.statusCode = 500;
res.end();
connectionState.statusCode = 500;
connectionState.end();

@@ -1070,6 +1096,7 @@ // then report error

// flush response & close connection
res.contentType('application/json');
res.setHeader("Access-Control-Allow-Origin", "*");
res.write(commandStr);
res.end();
connectionState.contentType('application/json');
connectionState.setHeader("Access-Control-Allow-Origin", "*");
connectionState.write(hostResponseString);
connectionState.end();
this._currentConnectionState = null;
},

@@ -1102,2 +1129,3 @@ }

},
/**

@@ -1107,11 +1135,5 @@ * This client-side function is called when a host command is called from a client component.

*/
sendClientRequestToHost: function(clientRequestData) {
return this.sendCustomClientRequestToHost('', clientRequestData, true);
},
sendRequestToHost: function(clientRequestData, path, dontSerialize, requestMetadata) {
path = path || '';
/**
* This client-side function is called when a host command is called from a client component.
* It will transport the commands to the host, wait for the reply, and then execute the commands that were sent back.
*/
sendCustomClientRequestToHost: function(path, clientRequestData, serialize, customHeaders) {
var ComponentCommunications = Instance.Libs.ComponentCommunications;

@@ -1124,4 +1146,4 @@ if (ComponentCommunications.hasRefreshBeenRequested()) {

// add security and other metadata, required by NoGap
customHeaders = customHeaders || {};
ComponentCommunications.prepareRequestMetadata(customHeaders);
requestMetadata = requestMetadata || {};
ComponentCommunications.prepareRequestMetadata(requestMetadata);

@@ -1131,3 +1153,8 @@

// send Ajax POST request (without jQuery)
var xhReq = (typeof(XMLHttpRequest) !== 'undefined') ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
var xhReq = (typeof(XMLHttpRequest) !== 'undefined') ? new XMLHttpRequest() :
((typeof(ActiveXObject) !== 'undefined') && new ActiveXObject("Microsoft.XMLHTTP"));
if (!xhReq) {
throw new Error('Could not `sendRequestToHost` - `XMLHttpRequest` is not available.');
}

@@ -1137,8 +1164,8 @@ // send out the command request

xhReq.open('POST', cfg.remoteUrl + path, true);
if (serialize) {
if (!dontSerialize) {
xhReq.setRequestHeader('Content-type','application/json; charset=' + (cfg.charset || 'utf-8') + ';');
clientRequestData = serializer.serialize(clientRequestData);
}
for (var headerName in customHeaders) {
xhReq.setRequestHeader(headerName, customHeaders[headerName]);
for (var headerName in requestMetadata) {
xhReq.setRequestHeader(headerName, requestMetadata[headerName]);
}

@@ -1204,2 +1231,7 @@

window.location.reload();
},
redirect: function(newLocation, inOldContext) {
// open new location (really: an URL)
window.open(newLocation, inOldContext ? null : '_blank');
}

@@ -1206,0 +1238,0 @@ },

{
"name": "nogap",
"version": "0.5.10",
"version": "0.5.11",
"author": {

@@ -5,0 +5,0 @@ "name": "Dominik Seifert",

@@ -217,23 +217,48 @@ [![NPM version](https://badge.fury.io/js/nogap.svg)](http://badge.fury.io/js/nogap)

```js
tellMeSomething: function(name) {
nBytes += (message && message.length) || 0;
return 'Host has received a total of ' + nBytes + ' bytes.';
}
var NoGapDef = require('nogap').Def;
// ...
NoGapDef.component({
Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) {
var nBytes = 0;
onButtonClick: function() {
document.body.innerHTML +='Button was clicked.<br />';
this.host.tellMeSomething('hello!')
.bind(this) // this is tricky!
.then(function(hostMessage) {
this.showHostMessage(hostMessage);
});
},
return {
Public: {
tellMeSomething: function(message) {
nBytes += (message && message.length) || 0;
this.Tools.log('Client said: ' + message);
return 'Thank you! I now received a total of ' + nBytes + ' bytes.';
}
}
};
}),
Client: NoGapDef.defClient(function(Tools, Instance, Context) {
return {
initClient: function() {
// bind a button to a component function (quick + dirty):
window.clickMe = this.onButtonClick.bind(this);
document.body.innerHTML += '<button onclick="window.clickMe();">Click Me!</button><br />';
},
onButtonClick: function() {
document.body.innerHTML +='Button was clicked.<br />';
this.host.tellMeSomething('hello!')
.then(function(hostMessage) {
document.body.innerHTML += 'Host said: ' + hostMessage + '<br />';
})
.catch(function(err) {
// this can be a connection error, a bug, a Host-side `reject` etc etc...
console.error('Something went wrong: ' + (err.stack || err));
});
}
};
})
});
```
**New Concepts**
* `Client.initClient` will be called right after the Client connected.
* Upon button click, we call `this.host.tellMeSomething(...)` which will send a request to the `Host` to invoke that method (given it is in `Host.Public`).
* Calling a `Public` function on a component's `host` object returns a promise.
* That promise is part of a full-stack [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them). A value returned by a `Host`'s `Public` function (or by a promise returned by such function), will be received by the client.
* Note that [JavaScript's `this` is tricky](http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/)!
* That promise is part of a full-stack [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them). Once finnished, we get the return value from that `Host` method in our `then` callback.

@@ -284,3 +309,4 @@

* We need to perform an asynchronous request whose result is to be sent to the other side
* Simply use [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them)!
* Simply use [Promise chains](https://github.com/petkaantonov/bluebird#what-are-promises-and-why-should-i-use-them)!
* NOTE: [JavaScript's `this` is tricky](http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/)!

@@ -287,0 +313,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc