Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

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.1.4 to 0.1.5

samples/CodeSharingValidation/CodeSharingValidation.js

2

lib/Assets.js

@@ -325,3 +325,3 @@ /**

catch (err) {
console.warn('Public folder does not exist: ' + pubFolderAbs);
console.warn('Public folder does not exist: ' + pubFolderRel);
return

@@ -328,0 +328,0 @@ }

@@ -39,2 +39,8 @@ /**

Public: {
/**
* Do it all over: Kill current instance and try again.
* This is effectively a page refresh for browsers but possibly
* needs some extra work so it works for webworkers
* or other environments.
*/
refresh: function() { }

@@ -54,2 +60,15 @@ }

return 'ComponentBootstrapImpl_';
},
getCurrentBootstrapperImpl: function() {
return Shared.Libs[this.getImplComponentLibName()];
},
Private: {
/**
* Get the current instance of the bootstrapper implementation.
*/
getCurrentBootstrapperImpl: function() {
return this.Instance.Libs[this.Shared.getImplComponentLibName()];
},
}

@@ -103,6 +122,2 @@ }}),

getCurrentBootstrapperImpl: function() {
return Shared.Libs[this.getImplComponentLibName()];
},
// ###############################################################################################################################

@@ -279,2 +294,6 @@ // Tools for bootstrapper implementations

},
refresh: function() {
this.getCurrentBootstrapperImpl().client.refresh();
}
},

@@ -350,2 +369,6 @@

Instance.Libs.CommandProxy.execHostCommands(bootstrapData.componentCmds);
},
refresh: function() {
this.getCurrentBootstrapperImpl().refresh();
}

@@ -413,3 +436,3 @@ },

// can properly set some initial client-side stuff
setTimeout(function() {
//setTimeout(function() {
// call `onNewComponent`

@@ -445,3 +468,3 @@ Instance.forEachComponentOfAnyType(function(component) {

}
}, 1);
//}, 1);
}

@@ -448,0 +471,0 @@ }

@@ -9,7 +9,11 @@ /**

// squishy gives us some misc utilities
require('squishy');
var StacktraceBuilder = squishy.Stacktrace;
var CodeBuilder = squishy.CodeBuilder;
var path = require('path');
// TODO: Move this out of here

@@ -99,3 +103,2 @@ var Dev = 1;

squishy.assert(typeof(factory) === 'function', 'ComponentDef.defBase must be called on a factory function that returns the `Base` component prototype.');
return new HostCore.FactoryDef(factory, 'Base', creationFrame, 'defBase');

@@ -117,3 +120,6 @@ },

defHost: function(factory) {
return new HostCore.FactoryDef(factory, 'Host');
var trace = StacktraceBuilder.getStacktrace();
var creationFrame = trace[1];
return new HostCore.FactoryDef(factory, 'Host', creationFrame, 'defHost');
}

@@ -469,6 +475,10 @@ };

*/
var installComponentOnHost = function(componentDef, clientDefs, map) {
var installComponentOnHost = function(componentDef, clientDefs, map, creationFrame) {
// get all command names and make them ready
fixComponentDefinition(componentDef, 'Host');
fixComponentDefinition(componentDef, 'Client');
// add `File` and `Folder` to `Host` def
componentDef.Host.File = creationFrame.fileName;
componentDef.Host.Folder = path.dirname(creationFrame.fileName);

@@ -564,11 +574,8 @@ // let each endpoint know all commands of the other side

var creationFrame;
if (def.Client instanceof HostCore.FactoryDef) {
creationFrame = def.Client.creationFrame;
}
else {
var trace = StacktraceBuilder.getStacktrace();
creationFrame = trace[defStackDepth || 1];
}
console.assert(def.Client || def.Base || def.Host,
'Component definition is invalid. It must at least define one property named `Host`, `Client` or `Base`.');
creationFrame = (def.Host || def.Client || def.Base).creationFrame;
if (!name) {
if (!name && creationFrame) {
// deduct component name from filename

@@ -588,10 +595,6 @@ name = creationFrame.fileName;

// sanity checks:
// validate name (depends on client definition)
squishy.assert(name, 'Unnamed component is illegal. Make sure to add a `Name` property to your component.');
// get & validate Client definition
var clientDef = def.Client;
squishy.assert(!clientDef || (clientDef instanceof HostCore.FactoryDef && clientDef.type === 'Client'),
'Component definition `' + fullName + '` did not have a client factory. Make sure that the `Client` property is declared with `ComponentDef.defClient`.');
console.assert(!clientDef || (clientDef instanceof HostCore.FactoryDef && clientDef.type === 'Client'),
'Component definition has an invalid `Client` factory. Make sure that the `Client` property is declared with `Def.defClient(...)`.');

@@ -601,11 +604,16 @@

var baseDef = def.Base;
squishy.assert(!baseDef || (baseDef instanceof HostCore.FactoryDef && baseDef.type === 'Base'),
'Component definition `' + fullName + '` declared invalid `Base` factory. Make sure that the `Base` property is declared with `ComponentDef.defBase`.');
console.assert(!baseDef || (baseDef instanceof HostCore.FactoryDef && baseDef.type === 'Base'),
'Component definition has an invalid `Base` factory. Make sure that the `Base` property is declared with `Def.defBase(...)`.');
// get & validate Host definition
var hostDef = def.Host;
squishy.assert(!hostDef || (hostDef instanceof HostCore.FactoryDef && hostDef.type === 'Host'),
'Component definition `' + fullName + '` declared invalid `Host` factory. Make sure that the `Host` property is declared with `ComponentDef.defHost`.');
console.assert(!hostDef || (hostDef instanceof HostCore.FactoryDef && hostDef.type === 'Host'),
'Component definition has an invalid `Host` factory. Make sure that the `Host` property is declared with `Def.defHost(...)`.');
return installComponentOnHost(def, defs || clientDefs.Components, map || Shared);
// sanity checks:
// validate name (depends on client definition)
console.assert(name, 'Unnamed component is illegal. Make sure to add a `Name` property to your component.');
console.assert(creationFrame, 'INTERNAL ERROR: `creationFrame` was not defined when it should have been.');
return installComponentOnHost(def, defs || clientDefs.Components, map || Shared, creationFrame);
},

@@ -612,0 +620,0 @@

@@ -30,3 +30,3 @@ /**

var ComponentLoader = ComponentDef.lib({
Base: ComponentDef.defBase(function(Tools, Shared) {
Base: ComponentDef.defBase(function(SharedTools, Shared) {

@@ -39,3 +39,3 @@ return {

Host: ComponentDef.defHost(function(Tools, Shared) {
Host: ComponentDef.defHost(function(SharedTools, Shared) {

@@ -51,2 +51,4 @@ return {

// store config
this.cfg = cfg;

@@ -72,18 +74,14 @@ // set default configuration

// TODO: We don't really need this
// load all components from user-given folder
for (var i = 0; i < cfg.files.length; ++i) {
var fname = cfg.files[i];
// fix the file ending
if (!fname.endsWith('.js')) fname += '.js';
var fPathAbs = path.join(componentFolder, fname);
// all we need to do is to require the file and its containing components automatically register with ComponentDef
var component = require(fPathAbs);
// get file name
component._def.File = fPathAbs;
component._def.Folder = path.dirname(fPathAbs);
// load all explicitely requested components from user-given folder
if (cfg.files) {
for (var i = 0; i < cfg.files.length; ++i) {
var fname = cfg.files[i];
// fix the file ending
if (!fname.endsWith('.js')) fname += '.js';
var fPathAbs = path.join(componentFolder, fname);
// all we need to do is to require the file and its containing components automatically register with ComponentDef
require(fPathAbs);
}
}

@@ -102,2 +100,12 @@

return Shared;
},
Private: {
onNewClient: function() {
var cfg = this.Shared.cfg;
if (!cfg.lazyLoad) {
// by default, automatically deploy all components to the client:
this.Tools.requestClientComponents(Object.keys(this.Instance));
}
}
}

@@ -104,0 +112,0 @@ };

@@ -23,3 +23,3 @@ /**

if (!(componentNames instanceof Array)) {
componentNames = Array.prototype.slice.call(arguments, 0); // convert arguments set to array
componentNames = Array.prototype.slice.call(arguments, 0); // convert arguments to array
}

@@ -29,2 +29,6 @@ Instance.Libs.ComponentBootstrap.requestClientComponentsFromHost(componentNames);

/**
* Keeps buffering even after the current call ended.
* This is to signal the beginning of an asynchronous operation whose result is to be sent to the client.
*/
keepOpen: function() {

@@ -36,8 +40,14 @@ Instance.Libs.ComponentCommunications.keepOpen();

* Flushes the current buffer.
* This is generally only needed for connections that are not always open,
* and need to be explicitely kept open during and flushed after asynchronous transactions.
* This is to signal the end of an asynchronous operation whose result has already been sent to the client.
*/
flush: function() {
Instance.Libs.ComponentCommunications.flush();
}
},
/**
* Tell client to refresh current page.
*/
refresh: function() {
Instance.Libs.ComponentBootstrap.refresh();
}
};

@@ -62,2 +72,7 @@ },

Tools.requestClientComponents = Instance.Libs.ComponentBootstrap.requestClientComponents.bind(Instance.Libs.ComponentBootstrap);
/**
* Refresh current page.
*/
Tools.refresh = Instance.Libs.ComponentBootstrap.refresh.bind(Instance.Libs.ComponentBootstrap);
},

@@ -64,0 +79,0 @@ },

{
"name": "nogap",
"version": "0.1.4",
"version": "0.1.5",
"author": {

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

NoGap
=============
The NoGap framework delivers RPC + asset management + some other good stuff for Host &lt;-> Client communication.
The NoGap framework delivers RPC + asset management + some other good stuff for enjoyable Host &lt;-> Client architecture development.
Have a look at the <a href="https://github.com/Domiii/NoGap/tree/master/testapp">Sample App</a> for reference.
This module is called `No` `Gap` because it removes the typical gap that exists between
host and client and that makes a client<->server architecture so cumbersome to develop.
NoGap's primary use case is to develop rich client-side applications while alleviating the typical hassles of doing so.
Have a look at the [Samples](samples) for reference.
Installation
=============
* [Install Node](http://nodejs.org/download/)
* Make sure to select `Add to PATH` during GUI-based installation.
* Open a command line
* On Windows: Press `Ctrl+R` -> Type `cmd` -> `Enter`
* Run: `npm install nogap`
* Done.
[Samples](samples)
=============
## [HelloWorld](samples/HelloWorld)
```js
var NoGapDef = require('nogap').Def;
module.exports = NoGapDef.component({
Client: NoGapDef.defHost(function(Tools, Instance, Context) {
return {
initClient: function() {
document.body.innerHTML = 'Hello World!';
}
};
});
});
```
### Concepts
* Get the NoGap module's `Def` helper: `var NoGapDef = require('nogap').Def;`
* Define a new component: `NoGapDef.component({ ... });`
* Add a `Client` definition to the component: `Client: NoGapDef.defClient(function(Tools, Instance, Context) { ... })`
* Add `initClient` method to `Client`
### What is the trick?
* The `Client` code is automatically deployed to the client
* `initClient` is then automatically called on the client, right after installation
## [TwoWayStreet](samples/TwoWayStreet)<a name="twowaystreet"></a>
```js
var NoGapDef = require('nogap').Def;
NoGapDef.component({
Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) {
var iAttempt = 0;
return {
Public: {
tellClientSomething: function() {
this.client.showHostMessage('We have exchanged ' + ++iAttempt + ' messages.');
}
}
};
}),
Client: NoGapDef.defClient(function(Tools, Instance, Context) {
return {
initClient: function() {
window.clickMe = function() {
document.body.innerHTML +='Button was clicked.<br />';
this.host.tellClientSomething();
}.bind(this);
document.body.innerHTML += '<button onclick="window.clickMe();">Click Me!</button><br />';
},
Public: {
showHostMessage: function(msg) {
document.body.innerHTML +='Server said: ' + msg + '<br />';
}
}
};
})
});
```
### Concepts
* Add a `Client` definition to the component: `Client: NoGapDef.defClient(function(Tools, Instance, Context) { ... })`
* `Client.initClient`
* Add a `Host` definition to the component: `Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) { ... })`
* `Host.Public`
* `Client.Public`
### What is the trick?
* `this.host` gives us an object on which we can call `Public` methods on the host
* For example, we can call `tellClientSomething` which is a method that was defined in `Host.Public`
* Once the host receives our request, it calls `this.client.showHostMessage`
* Note:
* Client: `this.host` vs.
* Host: `this.client`
## [TwoWayStreetAsync](samples/TwoWayStreetAsync)
Now that our code keeps growing and you are starting to get the picture, let us just focus on code snippets from now on.
Imagine the server had to do an asynchronous operation in [`tellClientSomething`](#twowaystreet).
For example, it needs to read a file, or get something from the database.
```js
tellClientSomething: function() {
this.Tools.keepOpen();
// wait 500 milliseconds before replying
setTimeout(function() {
this.client.showHostMessage('We have exchanged ' + ++iAttempt + ' messages.');
this.Tools.flush();
}.bind(this), 500);
}
```
### New Concepts
* We need to perform an asynchronous request whose result is to be sent to the other side:
* In that case, first call `this.Tools.keepOpen()`, so the client connection will not be closed automatically
* Once you sent everything to the client, call `this.Tools.flush()`
## [CodeSharingWithBase](samples/CodeSharingWithBase)
```js
tellClientSomething: function() {
this.Tools.keepOpen();
// wait 500 milliseconds before replying
setTimeout(function() {
this.client.showHostMessage('We have exchanged ' + ++iAttempt + ' messages.');
this.Tools.flush();
}.bind(this), 500);
}
```
### New Concepts
* We need to perform an asynchronous request whose result is to be sent to the other side:
* In that case, first call `this.Tools.keepOpen()`, so the client connection will not be closed automatically
* Once you sent everything to the client, call `this.Tools.flush()`
<a name="getting_started"></a>Getting Started
=============
This tutorial is aimed at those who are new to `NoGap`, and new to `Node` in general.
It should help you bridge the gap from the [Code Snippets](#code_snippets) to a real-world application.
## Recommended File Structure
.
+-- components/
+-- lib/
+-- pub/
+-- package.json
+-- appConfig.js
+-- app.js
Let's have a look at the different files and folders:
### package.json
This is the standard `Node` configuration file. Here you can declare your app's basic metadata and, most importantly, your dependencies.
If you need one of the thousands over thousands of publicly available `Node` modules, two steps are required:
1. add their name and your preferred version to `dependencies`
2. Run `npm install`
Done. Now the new module is available in your code via:
`var someModule = require('some-module');`
where `some-module` is the name you gave it in the package.json file.
Check out <a href="https://www.npmjs.org/">https://www.npmjs.org/</a> to see all available modules.
### `components/`
This folder contains your `NoGap` components, and possibly (some of) their assets. You can name it anything you want.
NOTE: Placing assets (such as *.html templates, stylesheets, images etc.) next to code is actually good style, if it supports modularization.
If your components are mostly self-contained, you can easily move their whole folder, including their assets, to deploy them in other places.
### `appConfig.js`
This is your custom configuration file. You can name it anything you want.
It contains some basic constant data that your application needs, such as database login and other setup information.
The following is an example of a `NoGap` configuration. It requires at least three entries:
* `baseFolder`
* This is the folder, relative to your application (e.g. `app.js`) where you defined all NoGap components.
* `publicFolder`
* The folder to find all client asset files that cannot be found relative to a component.
* Usually this is used to store client-only and shared javascript libraries that do not have `NoGap` support.
* `files`
* The actual component files (sans ".js"). Whenever you add a component, don't forget to list it here!
```js
"nogap": {
"baseFolder" : "components",
"publicFolder" : "pub",
"files" : [
// list all components here:
// utilities
"ValidationUtil",
// pages for guests
"Guest",
// pages for users
"Main",
"Home"
]
}
```
There are more, optional parameters. Documentation will come soon.
### `app.js`
This defines your actual application. You can name it anything you want. Usually this file only does two things:
1. Setup your app
2. Start your <a href="http://expressjs.com/4x/api.html">`express` server</a>
Express is the standard Node way of starting a web server and let clients connect.
Once it is running you can connect to it with your browser on the specified port.
With `NoGap`, we add one more job to it:
1. Setup your app
2. Initialize `NoGap`
3. Start your <a href="http://expressjs.com/4x/api.html">`express` server</a>

Sorry, the diff of this file is not supported yet

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