Skip to content

BenoitClaveau/qwebs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Qwebs

Web application framework with native promise, dependency-injection and bundle.

NPM Build Status Coverage Status NPM Download Dependencies Status

Discover our starter kit with Polymer.

Features

Installation

npm install $qwebs --save
npm install $qwebs-http --save

Create a service.js

"use strict";

class Service {
	constructor() {	
};

index(request, response) {
 let content = {
  text: `hello ${request.params.name}`
 };
 return response.send({ request: request, content: content });
};

exports = module.exports = Service;

Define routes.json

{
    "services": [
        { "name": "$http", "location": "qwebs-http"},
        { "name": "$service", "location": "./service"}
    ],
    "locators": [
        { "get": "/:name", "service": "$service", "method": "index" },
    ]
}

Create config.json

{
    "routes": "./routes.json",
    "http": {
        "port": 3000
    }
}

Enjoy

Create a server.js

"use strict";

const Qwebs = require("qwebs");
new Qwebs().load();

Run server on http://localhost:3000

node server.js

Routing

Our goal is to find the final route as fast as possible. We use a tree data structure to represent all routes.

  • get(route, service, method)
  • post(route, service, method)
  • put(route, service, method)
  • patch(route, service, method)
  • delete(route, service, method)
{
    "services": [
        { "name": "$user", "location": "../services/info"}
    ],
    "locators": [
        { "get": "/user/:id", "service": "$user", "method": "get" },
        { "post": "/user", "service": "$user", "method": "save" }
    ]
}
qwebs.get("/user/:id", "$users", "get"); 
qwebs.post("/user", "$users", "save");
...

Services

Qwebs is deigned for POO. Create service, define a route and attached them in routes.json. Qwebs has an dependency injector for easier integration.

class ApplicationService {
    //$config service is automatically injected
    constructor($config) {
        if ($config.verbose) console.log("ApplicationService created.");
    };

    //send javascript object
    get(request, response) {
        let content = { message: "Hello World" };   
        return response.send({ request: request, content: content });
    };

    //send stream
    stream(request, response, reject) {
        let stream = fs.createReadStream('file.txt')
                       .on("error", reject)           //reject Promise
                       .pipe(new ToUpperCase())       //transform
                       .on("error", reject)           //reject Promise
        return response.send({ request: request, stream: stream });
    };
};

exports = module.exports = ApplicationService;
## Dependency injection

Just declare the service name in your constructor.

class UserService {
    //Config service wil be created as a singleton and injected when UserService will be created
    constructor($config)

Qwebs will create your service with its dependencies.

{
    "services": [
        { "name": "$user", "location": "../services/user"}
        ...
//server.js
qwebs.inject("$user", "./services/user");
## Response

Http response are automatically extended to compressed with Gzip or Deflate.

  • response.send({request, statusCode, header, content, stream})

You could override this default behaviour with POO. Override the default response service and inject the new one in Qwebs.

##### How override response.send ? ```services/my-response.js "use strict";

const DataError = require("qwebs").DataError; const ResponseService = require("qwebs/lib/services/response");

class MyResponseService extends ResponseService { constructor() { super(); };

send(response, dataToSend) {
    return new Promise((resolve, reject) => {
        if (dataToSend == undefined) reject(new DataError({ message: "No data." }));

        dataToSend.header = data.header || {};
        dataToSend.header["Cache-Control"] = "private";
        dataToSend.header["Expires"] = new Date(Date.now() + 3000).toUTCString();
        return super.send(response, dataToSend).then(resolve).catch(reject);
    });
};

};

exports = module.exports = MyResponseService;


Then replace $response service in $injector.

```routes.json
{
    "services": [
        { "name": "$response", "location": "../services/my-response"}
    ]
}
qwebs.inject("$response", "./services/my-response");
## Avoid disk access at runtime

All assets are loaded in memory at startup. Uploaded images are not saved in temporary files. $qjimp service is designed to read, manipulate image stream.

## Bundle (bundle.json)

You could create your own css or js bundle without WebPack. Qwebs includes a Sass preprocessor. You don't need to compile your sass via an external program.

{
    "/app.js":[
        "bower_components/angular-material/angular-material.js",
        "bower_components/angular-route/angular-route.js",
        "bower_components/angular-aria/angular-aria.js",
        "bower_components/angular-sanitize/angular-sanitize.js",
        "bower_components/angular-i18n/angular-locale_fr-fr.js",
        "bower_components/angular-animate/angular-animate.js",
        "web/app.js"
    ],
    "/app.css":[
        "assets/mixins.scss",
        "bower_components/angular-material/angular-material.css",
        "assets/master.scss"
    ]   
}
<!DOCTYPE html>
<html>
    <head>
        <link rel=stylesheet type="text/css" href="/app.css">
    </head>
    <body>
        <script src="/app.js"></script>
    </body>
</html>

Configuration

  • CORS
{
    "cors": {
        "enabled": true,
        "allow-origin": "*",
        "max-age": 3600,
        "allow-headers": "Content-Type, Access-Control-Allow-Headers, Authorization"
    }
}
## Promise
  • Easier to read
  • Easier to maintain in the future
  • Easier error handling
  • $config: your configuration.
  • $qwebs: qwebs instance.
  • $injector: resolve services at runtime.
  • $responseProxy: extand http.ServerResponse.
  • $response: default response extension.
  • $qjimp: convert and manipulate images.

Others Services

Examples

To run our examples, clone the Qwebs repo and install the dependencies.

$ git clone https://github.com/BenoitClaveau/qwebs --depth 1
$ cd qwebs
$ npm install
$ cd exemples/helloworld
$ node server.js

Test

To run our tests, clone the Qwebs repo and install the dependencies.

$ git clone https://github.com/BenoitClaveau/qwebs --depth 1
$ cd qwebs
$ npm install
$ cd tests
$ node.exe "..\node_modules\jasmine\bin\jasmine" --verbose .