Comparing version 0.2.0 to 0.2.1
@@ -37,7 +37,7 @@ /** | ||
// read file | ||
fs.readFile(fpath, function (err, data) { | ||
fs.readFile(actualPath, function (err, data) { | ||
// send file out | ||
if (err) { | ||
// could not read file | ||
var err = new Error(err + ': ' + fpath); | ||
var err = new Error(err + ': ' + actualPath); | ||
err.status = 500; | ||
@@ -52,3 +52,3 @@ next(err); | ||
// see: https://github.com/broofa/node-mime | ||
var mimeType = mime.lookup(fpath); | ||
var mimeType = mime.lookup(actualPath); | ||
res.writeHead(status, {'Content-Type': mimeType}); | ||
@@ -55,0 +55,0 @@ res.write(data); |
{ | ||
"name": "nogap", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"author": { | ||
@@ -31,4 +31,4 @@ "name": "Dominik Seifert", | ||
"readme": "NoGap\r\n=============\r\n\r\nThe NoGap framework delivers RPC + asset management + some other good stuff for enjoyable Host <-> Client architecture development.\r\n\r\nThis module is called `No` `Gap` because it removes the typical gap that exists between\r\nhost and client and that makes a client<->server architecture so cumbersome to develop.\r\n\r\nNoGap's primary use case is to develop rich client-side applications while alleviating the typical hassles of doing so.\r\n\r\nHave a look at the [Samples](samples) for reference.\r\n\r\n\r\n\r\nInstallation\r\n=============\r\n\r\n* [Install Node](http://nodejs.org/download/)\r\n * Make sure to select `Add to PATH` during GUI-based installation.\r\n* Open a command line\r\n\t* On Windows: Press `Ctrl+R` -> Type `cmd` -> `Enter`\r\n* Run: `npm install nogap`\r\n* Done.\r\n\r\n\r\n[Samples](samples)<a name=\"samples\"></a>\r\n=============\r\n\r\n## [HelloWorld](samples/HelloWorld)\r\n\r\n```js\r\nvar NoGapDef = require('nogap').Def;\r\n\r\nmodule.exports = NoGapDef.component({\r\n\tClient: NoGapDef.defHost(function(Tools, Instance, Context) {\r\n\t\treturn {\r\n\t\t\tinitClient: function() {\r\n\t\t\t\tdocument.body.innerHTML = 'Hello World!';\r\n\t\t\t}\r\n\t\t};\r\n\t});\r\n});\r\n```\r\n\r\n### Concepts\r\n * Get the NoGap module's `Def` helper: `var NoGapDef = require('nogap').Def;`\r\n * Define a new component: `NoGapDef.component({ ... });`\r\n * Add a `Client` definition to the component: `Client: NoGapDef.defClient(function(Tools, Instance, Context) { ... })`\r\n * Add `initClient` method to `Client`\r\n\r\n### What is the trick?\r\n * The `Client` code is automatically deployed to the client\r\n * `initClient` is then automatically called on the client, right after installation\r\n\r\n\r\n## [TwoWayStreet](samples/TwoWayStreet)<a name=\"twowaystreet\"></a>\r\n\r\n```js\r\nvar NoGapDef = require('nogap').Def;\r\n\r\nNoGapDef.component({\r\n Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) {\r\n var iAttempt = 0;\r\n\r\n return {\r\n Public: {\r\n tellClientSomething: function() {\r\n this.client.showHostMessage('We have exchanged ' + ++iAttempt + ' messages.');\r\n }\r\n }\r\n };\r\n }),\r\n\r\n Client: NoGapDef.defClient(function(Tools, Instance, Context) {\r\n return {\r\n initClient: function() {\r\n window.clickMe = function() {\r\n document.body.innerHTML +='Button was clicked.<br />';\r\n this.host.tellClientSomething();\r\n }.bind(this);\r\n\r\n document.body.innerHTML += '<button onclick=\"window.clickMe();\">Click Me!</button><br />';\r\n },\r\n\r\n Public: {\r\n showHostMessage: function(msg) {\r\n document.body.innerHTML +='Server said: ' + msg + '<br />';\r\n }\r\n }\r\n };\r\n })\r\n});\r\n```\r\n\r\n### Concepts\r\n * Add a `Client` definition to the component: `Client: NoGapDef.defClient(function(Tools, Instance, Context) { ... })`\r\n * `Client.initClient`\r\n * Add a `Host` definition to the component: `Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) { ... })`\r\n * `Host.Public`\r\n * `Client.Public`\r\n\r\n### What is the trick?\r\n * `this.host` gives us an object on which we can call `Public` methods on the host\r\n \t* For example, we can call `tellClientSomething` which is a method that was defined in `Host.Public`\r\n * Once the host receives our request, it calls `this.client.showHostMessage`\r\n * Note:\r\n \t* Client: `this.host` vs.\r\n \t* Host: `this.client`\r\n\r\n\r\n## [TwoWayStreetAsync](samples/TwoWayStreetAsync)\r\n\r\nNow that our code keeps growing and you are starting to get the picture, let us just focus on code snippets from now on.\r\n\r\nImagine the server had to do an asynchronous operation in [`tellClientSomething`](#twowaystreet).\r\nFor example, it needs to read a file, or get something from the database.\r\n\r\n```js\r\ntellClientSomething: function() {\r\n this.Tools.keepOpen();\r\n\r\n // wait 500 milliseconds before replying\r\n setTimeout(function() {\r\n this.client.showHostMessage('We have exchanged ' + ++iAttempt + ' messages.');\r\n this.Tools.flush();\r\n }.bind(this), 500);\r\n}\r\n```\r\n\r\n### New Concepts\r\n * We need to perform an asynchronous request whose result is to be sent to the other side:\r\n * In that case, first call `this.Tools.keepOpen()`, so the client connection will not be closed automatically\r\n * Once you sent everything to the client, call `this.Tools.flush()`\r\n\r\n\r\n## [CodeSharingValidation](samples/CodeSharingValidation)\r\n\r\n\r\n```js\r\n\tBase: NoGapDef.defBase(function(SharedTools, Shared, SharedContext) { return {\r\n\t validateText: function(text) {\r\n\t if (text.indexOf('a') >= 0 || text.indexOf('A') >= 0) {\r\n\t return null;\r\n\t }\r\n\t return text.trim();\r\n\t }\r\n\t};}),\r\n\r\n Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) { return {\r\n Public: {\r\n setValue: function(value) {\r\n this.value = this.Shared.validateText(value);\r\n // ...\r\n }\r\n }\r\n };}),\r\n\r\n Client: NoGapDef.defClient(function(Tools, Instance, Context) { return {\r\n \t// ...\r\n value = this.validateText(value);\r\n // ...\r\n };})\r\n```\r\n\r\n### New Concepts\r\n * The `Base` definition is merged into both `Client` and `Host`\r\n * You can use it to easily share code between them\r\n\r\n\r\n\r\n## [Assets](samples/Assets)\r\n\r\n```js\r\nNoGapDef.component({\r\n Host: NoGapDef.defHost(function(SharedTools, Shared, SharedContext) { return {\r\n Assets: {\r\n AutoIncludes: {\r\n js: [\r\n // jquery\r\n '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'\r\n ],\r\n\r\n css: [\r\n // bootstrap\r\n '//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css'\r\n ]\r\n },\r\n\r\n Files: {\r\n string: {\r\n view: 'template.html'\r\n }\r\n }\r\n }\r\n };}),\r\n\r\n Client: NoGapDef.defClient(function(Tools, Instance, Context) { return {\r\n initClient: function() {\r\n document.body.innerHTML += this.assets.view;\r\n }\r\n };})\r\n});\r\n```\r\n\r\n### New Concepts\r\n * So far, you can define two types of file-based assets:\r\n * `AutoIncludes` defines lists of `js` and `css` files that will be automatically included in the client header\r\n * `Files` will be read and it's contents will be available through the clients `assets` variable.\r\n * Currently they can only be interpreted as string. Future plans: `code`, `image` and more more more...\r\n\r\n\r\n## [Dynamic Loading of Components](samples/DynamicallyLoadedComponents)\r\n\r\n TODO: Not done yet...\r\n\r\n\r\n\r\n<a name=\"getting_started\"></a>Getting Started\r\n=============\r\n\r\nThis tutorial is aimed at those who are new to `NoGap`, and new to `Node` in general.\r\nIt should help you bridge the gap from the [Code Snippets](#samples) to a real-world application.\r\n\r\n## Recommended File Structure\r\n .\r\n +-- components/\r\n |\t+-- models/\r\n |\t+-- ui/\r\n +-- lib/\r\n +-- pub/\r\n +-- app.js\r\n +-- appConfig.js\r\n +-- package.json\r\n\r\nThis is the recommended file structure for the average web application. As always, the structure might look vastly different for special purpose applications.\r\n\r\n### `components/`\r\n\r\nThis folder contains your `NoGap` components, and possibly (some of) their assets. You can name it anything you want.\r\n\r\nNOTE: Placing assets (such as *.html templates, stylesheets, images etc.) next to code is actually good style, if it supports modularization.\r\nIf your components have a sufficiently modular design, you can simply copy their folder, to deploy them and their assets in other places.\r\n\r\n\r\n### `components/models/`\r\n\r\nThis folder contains the interface with your DB and possibly other storage systems. They provide [CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete) functionality to the rest of the application.\r\n\r\n\r\n### `components/ui/`\r\n\r\nThis folder contains UI-related components. That is UI controller and view code. Views are in separate files from the code, but they can be in the same folder to support modularity.\r\n\r\n\r\n\r\n### `app.js`\r\n\r\nThis defines your actual application. You can name it anything you want. Usually, this file only does three things:\r\n\r\n 1. Setup your app\r\n 2. Start `NoGap`\r\n 3. Start your [`express` server](http://expressjs.com/4x/api.html)\r\n\r\nExpress is the standard Node way of starting a HTTP server and let clients connect.\r\nOnce it is running you can connect to it with your browser on the specified port.\r\n\r\nNOTE: When using `NoGap` you will not need to work with express anymore (other than starting the server). You can use it, but you are recommended to use components instead.\r\n\r\n\r\n\r\n### `appConfig.js`\r\n\r\nThis is your custom configuration file. You can name it anything you want.\r\nIt contains some basic constant data that your application needs, such as database login and other setup information.\r\nThe following is an example of a `NoGap` configuration. It requires at least three entries:\r\n\r\n * `baseFolder`\r\n \t* This is the folder, relative to your application (e.g. `app.js`) where you defined all NoGap components.\r\n * `publicFolder`\r\n \t* The folder to find all client asset files that cannot be found relative to a component.\r\n \t* Usually this is used to store client-only and shared javascript libraries that do not have `NoGap` support.\r\n * `files`\r\n \t* The actual component files (sans \".js\"). Whenever you add a component, don't forget to list it here!\r\n\r\n\r\n```js\r\n\"nogap\": {\r\n \"baseFolder\" : \"components\",\r\n \"publicFolder\" : \"pub\",\r\n \"files\" : [\r\n // list all components here:\r\n\r\n // utilities\r\n \"ValidationUtil\",\r\n\r\n // pages for guests\r\n \"Guest\",\r\n\r\n // pages for users\r\n \"Main\",\r\n \"Home\"\r\n ]\r\n}\r\n```\r\n\r\nThere are more, optional parameters. Documentation will come soon.\r\n\r\n\r\n### package.json\r\n\r\nThis is the standard `Node` configuration file. Here you can declare your app's basic metadata and, most importantly, your dependencies.\r\nIf you need one of the thousands over thousands of publicly available `Node` modules, two steps are required:\r\n\r\n 1. Add their name and your preferred version to `dependencies`\r\n 2. Run `npm install`\r\n\r\nDone. Now the new module is available in your code via:\r\n\r\n`var someModule = require('some-module');`\r\n\r\nwhere `some-module` is the name you gave it in the package.json file.\r\n\r\nCheck out [NPM JS](https://www.npmjs.org/) to see all available modules.\r\n\r\n\r\n\r\nFinal Words\r\n=============\r\n\r\nGood luck! You are recommended to take a look at the [`NoGap Sample App`](samples/sample_app) for a slightly more complete example of using `NoGap`.\r\n\r\nIn case of questions, feel free to contact me.", | ||
"_id": "nogap@0.1.9", | ||
"_from": "nogap@" | ||
"_id": "nogap@0.2.0", | ||
"_from": "nogap@*" | ||
} |
@@ -13,2 +13,4 @@ NoGap | ||
This readme also outlines the typical [skeleton](#component-skeleton) of a NoGap component. | ||
If you want to get serious, take a look at the [Getting Started](#getting_started) section to figure out how to build a complete Node-based web application with NoGap. | ||
@@ -280,3 +282,4 @@ | ||
/** | ||
* Called right before `__ctor` of `Host` and `Client` | ||
* Called right before `__ctor` of `Host` and `Client`. | ||
* Will be removed once called. | ||
*/ | ||
@@ -308,5 +311,13 @@ __ctor: function() { | ||
return { | ||
/** | ||
* The ctor is called only once, during NoGap initialization, | ||
* when the shared component part is created. | ||
* Will be removed once called. | ||
*/ | ||
__ctor: function () { | ||
}, | ||
/** | ||
* Is called once on each component after all components have been created. | ||
*/ | ||
initHost: function() { | ||
@@ -319,2 +330,7 @@ }, | ||
Private: { | ||
/** | ||
* Is called only once per session and application start, | ||
* when the instance for the given session has been created. | ||
* Will be removed once called. | ||
*/ | ||
__ctor: function () { | ||
@@ -338,3 +354,3 @@ }, | ||
/** | ||
* Public instance methods that can be called by the other side. | ||
* Public instance methods that can be called by the client. | ||
*/ | ||
@@ -348,9 +364,28 @@ Public: { | ||
return { | ||
/** | ||
* Called once after creation of the client-side instance. | ||
* Will be removed once called. | ||
*/ | ||
__ctor: function () { | ||
}, | ||
/** | ||
* Called once after all currently deployed client-side | ||
* components have been created. | ||
* Will be removed once called. | ||
*/ | ||
initClient: function() { | ||
}, | ||
/** | ||
* This is optional and will be merged into the Client instance, | ||
* residing along-side the members defined above. | ||
*/ | ||
Private: { | ||
}, | ||
/** | ||
* Public instance methods that can be called by the host. | ||
*/ | ||
Public: { | ||
@@ -357,0 +392,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
347249
519