Comparing version 1.0.0-alpha.2 to 1.0.0-alpha.3
/// <reference types="node" /> | ||
import * as https from 'https'; | ||
import { Server, RequestHandler } from './server'; | ||
export interface createServerOptions { | ||
export declare type CreateServerOptions = { | ||
tls?: https.ServerOptions; | ||
} | ||
}; | ||
/** | ||
@@ -14,3 +14,3 @@ * Create a HTTP(S) Server | ||
*/ | ||
export declare function createServer(options: createServerOptions, handler: RequestHandler): Server; | ||
export declare function createServer(options: CreateServerOptions, handler: RequestHandler): Server; | ||
/** | ||
@@ -22,3 +22,3 @@ * Create a HTTP(S) Server | ||
*/ | ||
export declare function createServer(options: createServerOptions): Server; | ||
export declare function createServer(options: CreateServerOptions): Server; | ||
/** | ||
@@ -25,0 +25,0 @@ * Create a HTTP(S) Server |
@@ -0,3 +1,3 @@ | ||
export * from './response'; | ||
export * from './factory'; | ||
export * from './server'; | ||
export * from './factory'; | ||
export * from './response'; |
@@ -6,4 +6,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./response")); | ||
__export(require("./factory")); | ||
__export(require("./server")); | ||
__export(require("./factory")); | ||
__export(require("./response")); |
@@ -5,18 +5,31 @@ /// <reference types="node" /> | ||
import * as https from 'https'; | ||
export declare type RequestHandler = (request: Request) => any; | ||
export declare type RequestHandler = (req: IRequest) => any; | ||
export declare type EventListener = (...args: any[]) => any; | ||
export declare type Request = http.IncomingMessage; | ||
export interface IRequest extends http.IncomingMessage { | ||
} | ||
/** | ||
* High level server for request handling | ||
*/ | ||
export declare class Server { | ||
native: http.Server | https.Server; | ||
/** | ||
* Initialize a `Server` instance | ||
* The internal server | ||
* | ||
* @param native The native HTTP(S) server | ||
* @protected | ||
*/ | ||
constructor(native: http.Server | https.Server); | ||
protected _server: http.Server | https.Server; | ||
/** | ||
* Add a request handler | ||
* Create a new server instance | ||
* | ||
* @param server The HTTP(S) native server | ||
* @constructor | ||
* @public | ||
*/ | ||
constructor(server: http.Server | https.Server); | ||
/** | ||
* Add a handler for the `request` event | ||
* | ||
* @param event The `request` event | ||
* @param handler The `request` handler | ||
* @public | ||
*/ | ||
on(event: 'request', handler: RequestHandler): this; | ||
@@ -27,7 +40,31 @@ /** | ||
* @param event The event name | ||
* @param listener The event listener | ||
* @public | ||
*/ | ||
on(event: string, listener: EventListener): this; | ||
/** | ||
* Add a one time `listener` for the given `event` | ||
* | ||
* @param event The event name | ||
* @param fn The event listener | ||
* @public | ||
*/ | ||
on(event: string, fn: EventListener): this; | ||
once(event: string, fn: EventListener): this; | ||
/** | ||
* Trigger the `event` with `args` | ||
* | ||
* @param event The event name | ||
* @param args The optional arguments to pass | ||
* @public | ||
*/ | ||
emit(event: string, ...args: any[]): boolean; | ||
/** | ||
* Stop listening to the given `event` | ||
* | ||
* @param event The event name | ||
* @param fn The event listener | ||
* @public | ||
*/ | ||
off(event?: string, fn?: EventListener): this; | ||
/** | ||
* Start a server listening for requests | ||
@@ -45,8 +82,8 @@ * | ||
/** | ||
* Wrap the request event listener | ||
* Wrap the request handler | ||
* | ||
* @param handler The request event listener | ||
* @private | ||
* @param handler The request handler | ||
* @protected | ||
*/ | ||
private _wrap(handler); | ||
protected _wrap(handler: EventListener): EventListener; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const is_1 = require("@sindresorhus/is"); | ||
const timers_1 = require("timers"); | ||
const response_1 = require("./response"); | ||
/** | ||
* High level server for request handling | ||
*/ | ||
class Server { | ||
/** | ||
* Initialize a `Server` instance | ||
* Create a new server instance | ||
* | ||
* @param native The native HTTP(S) server | ||
* @param server The HTTP(S) native server | ||
* @constructor | ||
* @public | ||
*/ | ||
constructor(native) { | ||
this.native = native; | ||
constructor(server) { | ||
this._server = server; | ||
} | ||
on(event, handler) { | ||
on(event, fn) { | ||
if (event === 'request') | ||
handler = this._wrap(handler); | ||
this.native.on(event, _defer(handler)); | ||
fn = this._wrap(fn); | ||
// attach the listener | ||
this._server.on(event, _defer(fn)); | ||
return this; | ||
} | ||
/** | ||
* Add a one time `listener` for the given `event` | ||
* | ||
* @param event The event name | ||
* @param fn The event listener | ||
* @public | ||
*/ | ||
once(event, fn) { | ||
this._server.once(event, _defer(fn)); | ||
return this; | ||
} | ||
/** | ||
* Trigger the `event` with `args` | ||
* | ||
* @param event The event name | ||
* @param args The optional arguments to pass | ||
* @public | ||
*/ | ||
emit(event, ...args) { | ||
return this._server.emit(event, ...args); | ||
} | ||
/** | ||
* Stop listening to the given `event` | ||
* | ||
* @param event The event name | ||
* @param fn The event listener | ||
* @public | ||
*/ | ||
off(event, fn) { | ||
if (event == null || fn == null) { | ||
this._server.removeAllListeners(event); | ||
} | ||
else { | ||
this._server.removeListener(event, fn); | ||
} | ||
return this; | ||
} | ||
/** | ||
* Start a server listening for requests | ||
@@ -27,9 +69,12 @@ * | ||
start(portOrOptions) { | ||
// attach a default error handler | ||
if (!this._server.listenerCount('error')) | ||
this.on('error', _onError); | ||
return new Promise((resolve, reject) => { | ||
// attach the error listener | ||
this.native.once('error', reject); | ||
this._server.once('error', reject); | ||
// listening | ||
this.native.listen(portOrOptions, () => { | ||
this._server.listen(portOrOptions, () => { | ||
// remove the unecessary error listener | ||
this.native.removeListener('error', reject); | ||
this._server.removeListener('error', reject); | ||
// resolve the promise | ||
@@ -47,14 +92,19 @@ resolve(); | ||
return new Promise((resolve, reject) => { | ||
this.native.close((e) => e ? reject(e) : resolve()); | ||
this._server.close((e) => e ? reject(e) : resolve()); | ||
}); | ||
} | ||
/** | ||
* Wrap the request event listener | ||
* Wrap the request handler | ||
* | ||
* @param handler The request event listener | ||
* @private | ||
* @param handler The request handler | ||
* @protected | ||
*/ | ||
_wrap(handler) { | ||
return (req, res) => { | ||
new Promise((resolve) => resolve(handler(req))).catch((err) => { | ||
return async (req, res) => { | ||
try { | ||
let output = await handler(req); | ||
let response = response_1.createResponse(output); | ||
await response.send(res); | ||
} | ||
catch (err) { | ||
// normalize | ||
@@ -64,20 +114,12 @@ if (!(err instanceof Error)) { | ||
} | ||
// delegate | ||
this.native.emit('error', err); | ||
let status = err.status || err.statusCode; | ||
let body = err.expose ? err.message : 'Internal Server Error'; | ||
// support ENOENT | ||
if (err.code === 'ENOENT') | ||
status = 404; | ||
return new response_1.Response(body) | ||
.status(_isValid(status) ? status : 500) | ||
.type('text/plain; charset=utf-8') | ||
.set(err.headers || {}); | ||
}) | ||
.then((response) => { | ||
if (!(response instanceof response_1.Response)) { | ||
response = new response_1.Response(response); | ||
if (err.code === 'ENOENT') { | ||
err.expose = true; | ||
err.status = 404; | ||
} | ||
response.send(res); | ||
}); | ||
// send | ||
response_1.createErrorResponse(err).send(res); | ||
// delegate | ||
this.emit('error', err); | ||
} | ||
}; | ||
@@ -88,18 +130,23 @@ } | ||
/** | ||
* Defer the function invocation to the next tick | ||
* The default `error` event listener | ||
* | ||
* @param fn The event listener | ||
* @param err The error object | ||
* @private | ||
*/ | ||
function _defer(fn) { | ||
return (...args) => timers_1.setImmediate(fn, ...args); | ||
function _onError(err) { | ||
if (err.status === 404 || err.expose) | ||
return; | ||
let msg = err.stack || err.toString(); | ||
console.error(); | ||
console.error(msg.replace(/^/gm, ' ')); | ||
console.error(); | ||
} | ||
/** | ||
* Check if the status code is a valid number | ||
* Defer the function invocation to the next tick | ||
* | ||
* @param status | ||
* @param fn The event listener | ||
* @private | ||
*/ | ||
function _isValid(status) { | ||
return typeof status === 'number' && status >= 100 && status <= 999; | ||
function _defer(fn) { | ||
return (...args) => setImmediate(fn, ...args); | ||
} |
{ | ||
"name": "aldo-http", | ||
"version": "1.0.0-alpha.2", | ||
"version": "1.0.0-alpha.3", | ||
"description": "Enhanced HTTP `createServer` module for Node.js", | ||
@@ -16,3 +16,3 @@ "types": "lib/index.d.ts", | ||
"build": "tsc", | ||
"prepublishOnly": "tsc && npm test && npm test", | ||
"prepublishOnly": "tsc && npm test", | ||
"test": "mocha -R dot -r ts-node/register \"test/**/*.ts\"" | ||
@@ -43,3 +43,2 @@ }, | ||
"@types/sinon": "^4.3.0", | ||
"@types/statuses": "^1.3.0", | ||
"mocha": "^5.0.0", | ||
@@ -52,5 +51,4 @@ "sinon": "^4.4.2", | ||
"@sindresorhus/is": "^0.9.0", | ||
"mime-types": "^2.1.18", | ||
"statuses": "^1.5.0" | ||
"mime-types": "^2.1.18" | ||
} | ||
} |
@@ -56,3 +56,3 @@ | ||
Each handler will receive the `http.IncomingMessage` object as a single input, and could return anything as a response. | ||
Each handler will receive the `http.IncomingMessage` object as a request, and could return anything as a response. | ||
@@ -69,7 +69,7 @@ ```ts | ||
To get more control over the response to send, [Response](#response) instances could be returned. | ||
To get more control over the response to send, [Response](#response) instances could be used. | ||
## Response | ||
The response instance let you construct a complex response (status code, body and headers) | ||
The response instance let you construct a complex response with status code, body and headers. | ||
@@ -85,19 +85,41 @@ ```ts | ||
type(value: string): this; | ||
etag(value: string): this; | ||
length(value: number): this; | ||
location(url: string): this; | ||
has(header: string): boolean; | ||
remove(header: string): this; | ||
setCookie(value: string): this; | ||
vary(...headers: string[]): this; | ||
send(res: http.ServerResponse): void; | ||
lastModified(value: string | Date): this; | ||
status(code: number, message?: string): this; | ||
append(header: string, value: string | string[]): this; | ||
get(header: string): string | number | string[] | undefined; | ||
set(header: string, value: string | number | string[]): this; | ||
set(headers: { [field: string]: string | number | string[]; }): this; | ||
reset(headers?: { [field: string]: string | number | string[]; }): this; | ||
type(value: string): this; // set the `Content-Type` header | ||
etag(value: string): this; // set the `ETag` header | ||
length(value: number): this; // set the `Content-Length` header | ||
location(url: string): this; // set the `Location` header | ||
has(header: string): boolean; // check the given header is already set | ||
remove(header: string): this; // remove the give header | ||
setCookie(value: string): this; // append a `Set-Cookie` header | ||
vary(...headers: string[]): this; // append a `Vary` header | ||
send(res: http.ServerResponse): void; // send the response to the client (used internally) | ||
lastModified(value: string | Date): this; // set the `Last-Modfied` header | ||
status(code: number, message?: string): this; // set the status code and message | ||
append(header: string, value: string | string[]): this; // append a header value | ||
get(header: string): string | number | string[] | undefined; // get the header value | ||
set(header: string, value: string | number | string[]): this; // set the header value | ||
set(headers: { [field: string]: string | number | string[]; }): this; // set multiple headers | ||
reset(headers?: { [field: string]: string | number | string[]; }): this; // reset the headers | ||
} | ||
``` | ||
To create [Response](#response) instances, you may use the `constructor` or one of the available factories: | ||
- `createRespnse(content?)` to create a response based on the given content. | ||
- `createEmptyResponse()` to create an empty response (default status code `204`). | ||
- `createHtmlResponse(html)` to create a HTML response, sets the `Content-Type` header to `text/html; charset=utf-8` and the `Content-Length` header. | ||
- `createTextResponse(text)` to create a text response, sets the `Content-Type` header to `text/plain; charset=utf-8` and the `Content-Length` header. | ||
- `createBufferResponse(buff)` to create a buffered response, sets the `Content-Type` header to `application/octet-stream` and the `Content-Length` header. | ||
- `createStreamResponse(stream)` to create a streamed response, sets the `Content-Type` header to `application/octet-stream`. | ||
- `createJsonResponse(object)` to create a JSON response, sets the `Content-Type` header to `application/json; charset=utf-8` and the `Content-Length` header. | ||
```js | ||
const { createServer, createTextResponse } = require('aldo-http') | ||
// handler | ||
const handler = () => createTextResponse("Hello world!") | ||
// server | ||
const server = createServer(handler) | ||
// start | ||
server.start(3000) | ||
``` |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
33606
2
8
19
1061
123
3
- Removedstatuses@^1.5.0
- Removedstatuses@1.5.0(transitive)