Skip to content

Commit

Permalink
PR #23 (GetRayo/test/integration)
Browse files Browse the repository at this point in the history
Test/integrations, updated and version patch.
  • Loading branch information
aichholzer authored Jun 2, 2018
2 parents cce11b5 + c5a1180 commit 231519d
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 83 deletions.
4 changes: 2 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
"error",
{
"semi": true,
"printWidth": 100,
"printWidth": 80,
"singleQuote": true,
"arrowParens": "always"
}
],
"func-names": ["error", "always"],
"comma-dangle": ["error", "never"],
"no-param-reassign": ["error", { "props": false }],
"max-len": ["error", 100, { "ignoreRegExpLiterals": true }]
"max-len": ["error", 80, { "ignoreRegExpLiterals": true }]
}
}
2 changes: 1 addition & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"semi": true,
"printWidth": 100,
"printWidth": 80,
"singleQuote": true,
"arrowParens": "always"
}
84 changes: 33 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@

```
Everything in the -modern- web is arguable,
however we are convinced that Rayo is the fastest framework.
In the world.
however we believe that Rayo is the fastest framework for Nodejs.
Period.
```

## In a nutshell

- Really fast (yeah, like really fast. Up to 50% faster than Express)
- API similiar to Express.
- Compatible with existing Express middlware.
- Extensible & plugable.
- Less than 150 lines of code, with routing and all.
- Really fast (yeah, like really fast. See [how it compares](#how-does-it-compare)),
- similar API to express¹,
- compatible with express middleware,
- extensible & plugable,
- less than 150 lines of code, with routing and all.

> ¹ `Rayo` is not intended to be an express replacement, thus the API is similar, inspired-by, and not identical.

## Install
Expand Down Expand Up @@ -75,7 +76,7 @@ rayo({ port: 5050 })

`handler` functions accept an [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) (a.k.a `req`), a [ServerResponse](https://nodejs.org/dist/latest-v9.x/docs/api/http.html#http_class_http_serverresponse) (a.k.a `res`) and a `step through` (a.k.a `step`) function. `step()` is optional and it may be used to move the program's execution logic to the next handler in the stack.

`step()` may also be used to invoke an error at any time. See [error handling](#error-handling).
`step()` may also be used to return an error at any time. See [error handling](#error-handling).

> **Note:** An error will be thrown if `step()` is called on an empty stack.
Expand Down Expand Up @@ -114,15 +115,35 @@ const fn = (req, res, step) => {

#### Error handling

## API

```
Please keep in mind that:
"Your code, your errors."¹
- It's your responsibility to deal with them accordingly.
```

> ¹ `Rayo` is WIP, so you may encounter actual errors that need to be dealt with. If so, please point them out to us via a `pull request`. 👍
> ² `Rayo` is WIP, so you may encounter actual errors that need to be dealt with. If so, please point them out to us via a `pull request`. 👍
If you have implemented a custom error function (see `onError` under [options](#rayooptions--)) you may invoke it at any time by calling the `step()` function with an argument.
```js
const rayo = require('rayo');

const options = {
port: 5050,
onError: (error, req, res) => {
res.end(`Here's your error: ${error}`);
}
};

rayo(options)
.get('/', (req, res, step) => step('Thunderstruck!'))
.start();
```
In the above example, the error will be returned on the `/` path, since `step()` is being called with an argument. Run the example, open your browser and go to [http://localhost:5050](http://localhost:5050) and you will see "Here's your error: Thunderstruck!".

If you don't have a custom error function, you may still call `step()` (with an argument), in which case the error will be returned using Rayo's standard function.


## API

#### rayo(options = {})
```
Expand Down Expand Up @@ -155,26 +176,7 @@ Please keep in mind that:
// Your custom logic.
}
```

`Default:` A "Page not found." message with a `404` status code.<br />

```js
const rayo = require('rayo');
const options = {
port: 5050,
notFound: (req, res) => {
res.end('The requested page is magically gone.');
}
};
/**
* Visit `/hello` to trigger the `notFound` method.
*/
rayo(options)
.get('/', (req, res) => res.end('Thunderstruck, GET'))
.start();
```
`Default:` Rayo will send a "Page not found." message with a `404` status code.

* `options.onError` _{function}_

Expand All @@ -192,26 +194,6 @@ Please keep in mind that:
}
```
`Default:` The error message (the argument) with a `400` status code.<br />
```js
const rayo = require('rayo');

const options = {
port: 5050,
onError: (error, req, res) => {
res.end(`Here's your error: ${error}`);
}
};

/**
* Visit `/` to trigger the `onError` method.
*/
rayo(options)
.get('/', (req, res, step) => step('Thunderstruck, error'))
.start();
```
#### .verb(path, ...handlers)
```
Expand Down
11 changes: 8 additions & 3 deletions bin/bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ module.exports = class Bridge {
this.t = this.h['*'] && this.h['*']['*'] ? this.h['*']['*'] : [];
bridgeThrough(this);
} else {
const [verb, path] = this.bridgedPath ? ['all', this.bridgedPath] : ['*', '*'];
const [verb, path] = this.bridgedPath
? ['all', this.bridgedPath]
: ['*', '*'];
this.route(verb, path, ...handlers);
}

Expand All @@ -61,7 +63,9 @@ module.exports = class Bridge {
this.h[m] = this.h[m] || {};
this.routes[m].push(parse(path));
this.h[m][path] = this.h[m][path] || [];
this.h[m][path] = this.h[m][path].concat(handlers).map((fn) => (...args) => fn(...args));
this.h[m][path] = this.h[m][path]
.concat(handlers)
.map((fn) => (...args) => fn(...args));
};

if (verb === 'all') {
Expand All @@ -75,7 +79,8 @@ module.exports = class Bridge {

fetch(verb, path) {
this.cache.urls[verb] = this.cache.urls[verb] || {};
const url = this.cache.urls[verb][path] || match(path, this.routes[verb] || []);
const url =
this.cache.urls[verb][path] || match(path, this.routes[verb] || []);
this.cache.urls[verb][path] = url;
return !url.length
? null
Expand Down
8 changes: 5 additions & 3 deletions bin/rayo.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ class Index extends Bridge {
const parsedUrl = parseurl(req);
const route = this.fetch(req.method, parsedUrl.pathname);
if (!route) {
return this.notFound ? this.notFound.call(null, req, res) : res.send('Page not found.', 404);
return this.notFound
? this.notFound(req, res)
: res.send('Page not found.', 404);
}

req.params = route.params;
Expand All @@ -47,15 +49,15 @@ class Index extends Bridge {
const fn = middleware.shift();
if (error) {
return this.onError
? this.onError.call(null, error, req, res, fn)
? this.onError(error, req, res, fn)
: res.send(error, statusCode || 400);
}

if (fn) {
return fn(req, res, this.step.bind(this, req, res, middleware));
}

throw new Error('No middleware to move to, there is nothing left in the stack.');
throw new Error('No handler to move to, the stack is empty.');
}
}

Expand Down
6 changes: 4 additions & 2 deletions bin/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ const isJSON = (payload) => {
module.exports = {
send(payload, statusCode) {
const { valid, json } = isJSON(payload);
const response = valid ? json : payload;
this.writeHead(statusCode || 200, {
'Content-Type': valid ? 'application/json' : 'text/plain'
'Content-Type': valid ? 'application/json' : 'text/plain',
'Content-Length': (response || '').length
});
this.write(valid ? json : payload);
this.write(response);
this.end();
}
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rayo",
"version": "1.0.1",
"version": "1.0.2",
"description": "⚡️⚡️ Rayo, an extremely fast micro-framework for Nodejs.",
"main": "bin/rayo.js",
"engines": {
Expand Down Expand Up @@ -40,7 +40,7 @@
"hapi": "17.x",
"minimist": "1.x",
"mocha": "5.x",
"nyc": "11.x",
"nyc": "12.x",
"ora": "2.x",
"polka": "0.x",
"prettier": "1.x",
Expand Down
4 changes: 3 additions & 1 deletion test/benchmarks/compare/fastify.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ const schema = {
}
};

fastify.get('/', schema, (req, reply) => reply.send('Thunderstruck...')).listen(5050);
fastify
.get('/', schema, (req, reply) => reply.send('Thunderstruck...'))
.listen(5050);
8 changes: 5 additions & 3 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const loadUnit = (unit) => require.call(null, `./${unit}`);

describe('Unit tests', () => {
describe('rayo.js', loadUnit('units/rayo'));
describe('response.js', loadUnit('units/response'));
describe('bridge.js', loadUnit('units/bridge'));
describe('Rayo', loadUnit('units/rayo'));
describe('Bridge', loadUnit('units/bridge'));
describe('Response', loadUnit('units/response'));

describe('Integration tests', loadUnit('units/integration'));
});
11 changes: 9 additions & 2 deletions test/units/bridge.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
const Bridge = require('../../bin/bridge');
const should = require('should');
const sinon = require('sinon');
const { METHODS } = require('http');
const Bridge = require('../../bin/bridge');

const test = (bridge, path = null) => {
should(bridge).be.an.Object();
should(bridge).have.properties('id', 'bridgedPath', 'routes', 'through', 'route', 'fetch');
should(bridge).have.properties(
'id',
'bridgedPath',
'routes',
'through',
'route',
'fetch'
);
should(bridge.id).be.a.String();
should(bridge.bridgedPath).be.equal(path);
should(bridge.routes).be.an.Object();
Expand Down
Loading

0 comments on commit 231519d

Please sign in to comment.