Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/benoitclaveau/qwebs

Promise web server
https://github.com/benoitclaveau/qwebs

application dependency-injection fast framework promise stream web

Last synced: 18 days ago
JSON representation

Promise web server

Awesome Lists containing this project

README

        

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

[![NPM][npm-image]][npm-url]
[![Build Status][travis-image]][travis-url]
[![Coverage Status][coveralls-image]][coveralls-url]
[![NPM Download][npm-image-download]][npm-url]
[![Dependencies Status][david-dm-image]][david-dm-url]

Discover our [starter kit](https://www.npmjs.com/package/qwebs-starter-kit-polymer) with [Polymer](https://www.polymer-project.org/).

# Features

* [Promise](#promise)
* [Separate routes and services](#service)
* [Dependency injection](#di)
* [Object oriented programming (OOP)](#oop)
* [Compression & minification](#bundle)
* [0 disk access at runtime](#disk)
* [Bundle](#bundle) css, [sass](https://www.npmjs.com/package/node-sass)
* [Configuration](#config)

# Installation

```shell
npm install $qwebs --save
npm install $qwebs-http --save
```

## Create a service.js

```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

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

## Create config.json

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

## Enjoy

Create a server.js

```server.js
"use strict";

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

Run server on http://localhost:3000

```shell
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)

```routes.json
{
"services": [
{ "name": "$user", "location": "../services/info"}
],
"locators": [
{ "get": "/user/:id", "service": "$user", "method": "get" },
{ "post": "/user", "service": "$user", "method": "save" }
]
}
```

```or in javascript
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.

```service.js
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.

```services/user.js
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.

```routes.json
{
"services": [
{ "name": "$user", "location": "../services/user"}
...
```

```on server.js
//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})
- [request](https://nodejs.org/api/http.html#http_class_http_clientrequest)
- [statusCode](http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1)
- [header](http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.2)
- content: js, html, json, ... *(call response.write(content))*
- or
- [stream](https://nodejs.org/api/stream.html) *(call stream.pipe(response))*

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"}
]
}
```

```or server.js
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](https://www.npmjs.com/package/node-sass) preprocessor. You don't need to compile your sass via an external program.

```bundle.json
{
"/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"
]
}
```

```html






```

# Configuration

* CORS

```config.json
{
"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

## Services

* $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

* [$http](https://www.npmjs.com/package/qwebs-http)
* [$https](https://www.npmjs.com/package/qwebs-https)
* [$http-to-https](https://www.npmjs.com/package/qwebs-http-to-https)
* [$mongo](https://www.npmjs.com/package/qwebs-mongo)
* [$authentication](https://www.npmjs.com/package/qwebs-auth-jwt)
* [$https](https://www.npmjs.com/package/qwebs-https)
* [$nodemailer](https://www.npmjs.com/package/qwebs-nodemailer)
* [$bitbucket](https://www.npmjs.com/package/qwebs-bitbucket-deploy)
* [$aws-s3](https://www.npmjs.com/package/qwebs-aws-s3)
* [$aws-ses](https://www.npmjs.com/package/qwebs-aws-ses)
* [aws api gateway](https://www.npmjs.com/package/qwebs-aws-api-gateway)

## Examples

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

```bash
$ 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.

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

[npm-image]: https://img.shields.io/npm/v/qwebs.svg
[npm-image-download]: https://img.shields.io/npm/dm/qwebs.svg
[npm-url]: https://npmjs.org/package/qwebs
[travis-image]: https://travis-ci.org/BenoitClaveau/qwebs.svg?branch=master
[travis-url]: https://travis-ci.org/BenoitClaveau/qwebs
[coveralls-image]: https://coveralls.io/repos/BenoitClaveau/qwebs/badge.svg?branch=master&service=github
[coveralls-url]: https://coveralls.io/github/BenoitClaveau/qwebs?branch=master
[david-dm-image]: https://david-dm.org/BenoitClaveau/qwebs/status.svg
[david-dm-url]: https://david-dm.org/BenoitClaveau/qwebs