Merge pull request #16065 from AJamesPhillips/hapi-v16.1

Hapi v16.1, Inert, nes, hapi-auth-jwt2, hapi-decorators.  New definitions for catbox, h2o2, mime-db, mimos, podium, shot, vision, hapi-auth-basic
This commit is contained in:
Arthur Ozga
2017-05-15 14:45:07 -07:00
committed by GitHub
123 changed files with 11643 additions and 2733 deletions

View File

@@ -3,8 +3,6 @@
// Definitions by: Igor Rogatty <http://github.com/rogatty>, AJP <http://github.com/AJamesPhillips>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/// <reference types="node" />
export = Boom;
declare namespace Boom {

View File

@@ -6,7 +6,7 @@
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": false,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"

247
types/catbox/index.d.ts vendored Normal file
View File

@@ -0,0 +1,247 @@
// Type definitions for catbox 7.1
// Project: https://github.com/hapijs/catbox
// Definitions by: Jason Swearingen <http://github.com/jasonswearingen>, AJP <https://github.com/AJamesPhillips>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
import * as Boom from 'boom';
export interface CallBackNoResult {
(err?: Boom.BoomError): void;
}
export interface CallBackWithResult<T> {
(err: Boom.BoomError | null | undefined, result: T): void;
}
/**
* Client
* The Client object provides a low-level cache abstraction. The object is constructed using new Client(engine, options) where:
* engine - is an object or a prototype function implementing the cache strategy:
* * function - a prototype function with the signature function(options). catbox will call new func(options).
* * object - a pre instantiated client implementation object. Does not support passing options.
* options - the strategy configuration object. Each strategy defines its own configuration options with the following common options:
* * partition - the partition name used to isolate the cached results across multiple clients. The partition name is used as the MongoDB database name, the Riak bucket, or as a key prefix in Redis and Memcached. To share the cache across multiple clients, use the same partition name.
* @see {@link https://github.com/hapijs/catbox#client}
*/
export interface Client extends ClientApi {
new(engine: EnginePrototypeOrObject, options: ClientOptions): Client;
}
type EnginePrototypeOrObject = EnginePrototype | ClientApi;
/**
* A prototype CatBox engine function
*/
export interface EnginePrototype {
new(settings: ClientOptions): ClientApi;
}
/**
* Client API
* The Client object provides the following methods:
* @see {@link https://github.com/hapijs/catbox#api}
*/
export interface ClientApi {
/** start(callback) - creates a connection to the cache server. Must be called before any other method is available. The callback signature is function(err). */
start(callback: CallBackNoResult): void;
/** stop() - terminates the connection to the cache server. */
stop(): void;
/**
* get(key, callback) - retrieve an item from the cache engine if found where:
* * key - a cache key object (see [ICacheKey]).
* * callback - a function with the signature function(err, cached). If the item is not found, both err and cached are null. If found, the cached object is returned
*/
get(key: CacheKey, callback: CallBackWithResult<null | CachedObject>): CacheItem;
/**
* set(key, value, ttl, callback) - store an item in the cache for a specified length of time, where:
* * key - a cache key object (see [ICacheKey]).
* * value - the string or object value to be stored.
* * ttl - a time-to-live value in milliseconds after which the item is automatically removed from the cache (or is marked invalid).
* * callback - a function with the signature function(err).
*/
set(key: CacheKey, value: CacheItem, ttl: number, callback: CallBackNoResult): void;
/**
* drop(key, callback) - remove an item from cache where:
* * key - a cache key object (see [ICacheKey]).
* * callback - a function with the signature function(err).
*/
drop(key: CacheKey, callback: CallBackNoResult): void;
/** isReady() - returns true if cache engine determines itself as ready, false if it is not ready. */
isReady(): boolean;
/** validateSegmentName(segment) - returns null if the segment name is valid (see below), otherwise should return an instance of Error with an appropriate message. */
validateSegmentName(segment: string): null | Boom.BoomError;
}
/**
* Any method with a key argument takes an object with the following required properties:
*/
export interface CacheKey {
/** segment - a caching segment name string. Enables using a single cache server for storing different sets of items with overlapping ids. */
segment: string;
/** id - a unique item identifier string (per segment). Can be an empty string. */
id: string;
}
/** Cached object contains the following: */
export interface CachedObject {
/** item - the value stored in the cache using set(). */
item: any;
/** stored - the timestamp when the item was stored in the cache (in milliseconds). */
stored: number;
/** ttl - the remaining time-to-live (not the original value used when storing the object). */
ttl: number;
}
type CacheItem = any;
export interface ClientOptions {
partition: string;
}
/**
* The Policy object provides a convenient cache interface by setting a global policy which is automatically applied to every storage action. The object is constructed using new Policy(options, [cache, segment]) where:
* * options - an object with the IPolicyOptions structure
* * cache - a Client instance (which has already been started).
* * segment - required when cache is provided. The segment name used to isolate cached items within the cache partition.
* @see {@link https://github.com/hapijs/catbox#policy}
*/
export interface Policy extends PolicyAPI {
new(options: PolicyOptions, cache: Client, segment: string): Policy;
}
/**
* Policy API
* The Policy object provides the following methods:
* @see {@link https://github.com/hapijs/catbox#api-1}
*/
export interface PolicyAPI {
/**
* get(id, callback) - retrieve an item from the cache. If the item is not found and the generateFunc method was provided, a new value is generated, stored in the cache, and returned. Multiple concurrent requests are queued and processed once. The method arguments are:
* * id - the unique item identifier (within the policy segment). Can be a string or an object with the required 'id' key.
* * callback - the return function.
*/
get(id: string | {id: string}, callback: PolicyGetCallback): CacheItem;
/**
* set(id, value, ttl, callback) - store an item in the cache where:
* * id - the unique item identifier (within the policy segment).
* * value - the string or object value to be stored.
* * ttl - a time-to-live override value in milliseconds after which the item is automatically removed from the cache (or is marked invalid). This should be set to 0 in order to use the caching rules configured when creating the Policy object.
* * callback - a function with the signature function(err).
*/
set(id: string | {id: string}, value: CacheItem, ttl: number | null, callback: CallBackNoResult): void;
/**
* drop(id, callback) - remove the item from cache where:
* * id - the unique item identifier (within the policy segment).
* * callback - a function with the signature function(err).
*/
drop(id: string | {id: string}, callback: CallBackNoResult): void;
/** ttl(created) - given a created timestamp in milliseconds, returns the time-to-live left based on the configured rules. */
ttl(created: number): number;
/** rules(options) - changes the policy rules after construction (note that items already stored will not be affected) */
rules(options: PolicyOptions): void;
/** isReady() - returns true if cache engine determines itself as ready, false if it is not ready or if there is no cache engine set. */
isReady(): boolean;
/** stats - an object with cache statistics */
stats(): CacheStatisticsObject;
}
/**
* The return function. The function signature is function(err, value, cached, report) where:
* @param err - any errors encountered.
* @param value - the fetched or generated value.
* @param cached - null if a valid item was not found in the cache, or IPolicyGetCallbackCachedOptions
* @param report - an object with logging information about the generation operation
*/
export interface PolicyGetCallback{
(err: null | Boom.BoomError, value: CacheItem, cached: PolicyGetCallbackCachedOptions, report: PolicyGetCallbackReportLog): void;
}
export interface PolicyGetCallbackCachedOptions {
/** item - the cached value. */
item: CacheItem;
/** stored - the timestamp when the item was stored in the cache. */
stored: number;
/** ttl - the cache ttl value for the record. */
ttl: number;
/** isStale - true if the item is stale. */
isStale: boolean;
}
/**
* @see {@link https://github.com/hapijs/catbox#policy}
*/
export interface PolicyOptions {
/** expiresIn - relative expiration expressed in the number of milliseconds since the item was saved in the cache. Cannot be used together with expiresAt. */
expiresIn?: number;
/** expiresAt - time of day expressed in 24h notation using the 'HH:MM' format, at which point all cache records for the route expire. Uses local time. Cannot be used together with expiresIn. */
expiresAt?: string;
/** generateFunc - a function used to generate a new cache item if one is not found in the cache when calling get(). The method's signature is function(id, next) where: */
generateFunc?: GenerateFunc;
/**
* staleIn - number of milliseconds to mark an item stored in cache as stale and attempt to regenerate it when generateFunc is provided. Must be less than expiresIn. Alternatively function that returns staleIn value in milliseconds. The function signature is function(stored, ttl) where:
* * stored - the timestamp when the item was stored in the cache (in milliseconds).
* * ttl - the remaining time-to-live (not the original value used when storing the object).
*/
staleIn?: number | ((stored: number, ttl: number) => number);
/** staleTimeout - number of milliseconds to wait before returning a stale value while generateFunc is generating a fresh value. */
staleTimeout?: number;
/** generateTimeout - number of milliseconds to wait before returning a timeout error when the generateFunc function takes too long to return a value. When the value is eventually returned, it is stored in the cache for future requests. Required if generateFunc is present. Set to false to disable timeouts which may cause all get() requests to get stuck forever. */
generateTimeout?: number | false;
/** dropOnError - if true, an error or timeout in the generateFunc causes the stale value to be evicted from the cache. Defaults to true. */
dropOnError?: boolean;
/** generateOnReadError - if false, an upstream cache read error will stop the get() method from calling the generate function and will instead pass back the cache error. Defaults to true. */
generateOnReadError?: boolean;
/** generateIgnoreWriteError - if false, an upstream cache write error will be passed back with the generated value when calling the get() method. Defaults to true. */
generateIgnoreWriteError?: boolean;
/** pendingGenerateTimeout - number of milliseconds while generateFunc call is in progress for a given id, before a subsequent generateFunc call is allowed. Defaults to 0, no blocking of concurrent generateFunc calls beyond staleTimeout. */
pendingGenerateTimeout?: number;
}
/**
* generateFunc
* Is used in PolicyOptions
* A function used to generate a new cache item if one is not found in the cache when calling get(). The method's signature is function(id, next)
* @param id - the id string or object provided to the get() method.
* @param next - the method called when the new item is returned with the signature function(err, value, ttl) where:
* * err - an error condition.
* * value - the new value generated.
* * ttl - the cache ttl value in milliseconds. Set to 0 to skip storing in the cache. Defaults to the cache global policy.
* @see {@link https://github.com/hapijs/catbox#policy}
*/
export interface GenerateFunc {
(id: string, next: ((err: null | Boom.BoomError, value: CacheItem, ttl?: number) => void)): void;
}
/**
* An object with logging information about the generation operation containing the following keys (as relevant):
*/
export interface PolicyGetCallbackReportLog {
/** msec - the cache lookup time in milliseconds. */
msec: number;
/** stored - the timestamp when the item was stored in the cache. */
stored: number;
/** isStale - true if the item is stale. */
isStale: boolean;
/** ttl - the cache ttl value for the record. */
ttl: number;
/** error - lookup error. */
error?: Boom.BoomError;
}
/**
* an object with cache statistics where:
*/
export interface CacheStatisticsObject {
/** sets - number of cache writes. */
sets: number;
/** gets - number of cache get() requests. */
gets: number;
/** hits - number of cache get() requests in which the requested id was found in the cache (can be stale). */
hits: number;
/** stales - number of cache reads with stale requests (only counts the first request in a queued get() operation). */
stales: number;
/** generates - number of calls to the generate function. */
generates: number;
/** errors - cache operations errors. TODO check this*/
errors: number;
}

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts"
]
}

165
types/h2o2/h2o2-tests.ts Normal file
View File

@@ -0,0 +1,165 @@
import http = require("http");
import * as Boom from 'boom';
import * as Hapi from 'hapi';
import * as Wreck from 'wreck';
import h2o2 = require('h2o2');
// https://github.com/hapijs/h2o2#manual-loading
const server = new Hapi.Server({});
server.register({
register: h2o2
}, function (err) {
if (err) {
console.log('Failed to load h2o2');
}
server.start(function (err) {
console.log('Server started at: ' + server.info!.uri);
});
});
// https://github.com/hapijs/h2o2#replyproxyoptions
const handler: Hapi.RouteHandler = function (request, reply) {
return reply.proxy({ host: 'example.com', port: 80, protocol: 'http' });
};
// https://github.com/hapijs/h2o2#using-the-host-port-protocol-options
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
host: '10.33.33.1',
port: '443',
protocol: 'https'
}
}
});
// https://github.com/hapijs/h2o2#using-the-uri-option
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
uri: 'https://some.upstream.service.com/that/has?what=you&want=todo'
}
}
});
// https://github.com/hapijs/h2o2#custom-uri-template-values
server.route({
method: 'GET',
path: '/foo',
handler: {
proxy: {
uri: '{protocol}://{host}:{port}/go/to/{path}'
}
}
});
server.route({
method: 'GET',
path: '/foo/{bar}',
handler: {
proxy: {
uri: 'https://some.upstream.service.com/some/path/to/{bar}'
}
}
});
// https://github.com/hapijs/h2o2#using-the-mapuri-and-onresponse-options
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
mapUri: function (request, callback) {
console.log('doing some aditional stuff before redirecting');
callback(null, 'https://some.upstream.service.com/');
},
onResponse: function (err, res, request, reply, settings, ttl) {
console.log('receiving the response from the upstream.');
Wreck.read(res, { json: true }, function (err, payload) {
console.log('some payload manipulation if you want to.')
reply(payload).headers = res.headers;
});
}
}
}
});
/**
* test code added in additional to code in docs. Demonstrates that for the moment
* you need flat
* objects with typing along the way to benefit from typescript catching
* misspelt, or unsupported keys.
* This is because of an unknown reason. Expecting this to work because:
* "Object literals get special treatment and undergo excess
* property checking when assigning them to other variables, or passing them
* as arguments", see github.com/Microsoft/TypeScript
*/
var proxyOptions: h2o2.ProxyHandlerOptions = {
host: '10.33.33.1',
port: '443',
protocol: 'https' // errors correctly if misspelt
}
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
host: '10.33.33.1',
port: '443',
BAD_protocol: 'https' // TODO change typings to fix this / submit bug report
}
}
})
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
uri: 'https://some.upstream.service.com/that/has?what=you&want=todo'
}
}
})
server.route({
method: 'GET',
path: '/',
handler: {
proxy: {
mapUri: function (request: Hapi.Request, callback: (err: null | Boom.BoomError, value: string) => void) {
console.log('doing some aditional stuff before redirecting');
callback(null, 'https://some.upstream.service.com/');
},
onResponse: function (err: null | Boom.BoomError, res: http.IncomingMessage, request: Hapi.Request, reply: Hapi.ReplyWithContinue, settings: h2o2.ProxyHandlerOptions, ttl: number) {
console.log('receiving the response from the upstream.');
Wreck.read(res, { json: true }, function (err: null | Boom.BoomError, payload: any) {
console.log('some payload manipulation if you want to.')
reply(payload).headers = res.headers;
});
}
}
}
});

91
types/h2o2/index.d.ts vendored Normal file
View File

@@ -0,0 +1,91 @@
// Type definitions for h2o2 5.4
// Project: https://github.com/hapijs/catbox
// Definitions by: Jason Swearingen <http://github.com/jasonswearingen>, AJP <https://github.com/AJamesPhillips>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
/// <reference types="node" />
import http = require("http");
import * as hapi from 'hapi';
import * as Boom from 'boom';
declare namespace H2o2 {
/** Proxy handler options */
export interface ProxyHandlerOptions {
/** host - upstream service host to proxy requests to. It will have the same path as the client request. */
host?: string;
/** port - upstream service port. */
port?: number | string;
/** protocol - protocol to use when making the request to the proxied host: */
protocol?: 'http' | 'https';
/** uri - absolute URI used instead of host, port, protocol, path, and query. Cannot be used with host, port, protocol, or mapUri. */
uri?: string;
/** passThrough - if set to true, it forwards the headers from the client to the upstream service, headers sent from the upstream service will also be forwarded to the client. Defaults to false. */
passThrough?: boolean;
/** localStatePassThrough - if set tofalse, any locally defined state is removed from incoming requests before being sent to the upstream service. This value can be overridden on a per state basis via the server.state()``passThrough option. Defaults to false */
localStatePassThrough?: boolean;
/** acceptEncoding - if set to false, does not pass-through the 'Accept-Encoding' HTTP header which is useful for the onResponse post-processing to avoid receiving an encoded response. Can only be used together with passThrough. Defaults to true (passing header). */
acceptEncoding?: boolean;
/** rejectUnauthorized - sets the rejectUnauthorized property on the https agent making the request. This value is only used when the proxied server uses TLS/SSL. If set it will override the node.js rejectUnauthorized property. If false then ssl errors will be ignored. When true the server certificate is verified and an 500 response will be sent when verification fails. This shouldn't be used alongside the agent setting as the agent will be used instead. Defaults to the https agent default value of true. */
rejectUnauthorized?: boolean;
/** xforward - if set to true, sets the 'X-Forwarded-For', 'X-Forwarded-Port', 'X-Forwarded-Proto', 'X-Forwarded-Host' headers when making a request to the proxied upstream endpoint. Defaults to false. */
xforward?: boolean;
/** redirects - the maximum number of HTTP redirections allowed to be followed automatically by the handler. Set to false or 0 to disable all redirections (the response will contain the redirection received from the upstream service). If redirections are enabled, no redirections (301, 302, 307, 308) will be passed along to the client, and reaching the maximum allowed redirections will return an error response. Defaults to false. */
redirects?: number | false;
/** timeout - number of milliseconds before aborting the upstream request. Defaults to 180000 (3 minutes). */
timeout?: number;
/** mapUri - a function used to map the request URI to the proxied URI. Cannot be used together with host, port, protocol, or uri. The function signature is function (request, callback) where:
* @param request - is the incoming request object.
* @param callback - is function (err, uri, headers) where:
* @param err - internal error condition. TODO: check this is of type BoomError or just Error.
* @param uri - the absolute proxy URI.
* @param headers - optional object where each key is an HTTP request header and the value is the header content.
*/
mapUri?: (request: hapi.Request, callback: (err: null | Boom.BoomError, uri: string, headers?: { [key: string]: string }) => void) => void;
/**
* onResponse - a custom function for processing the response from the upstream service before sending to the client. Useful for custom error handling of responses from the proxied endpoint or other payload manipulation. Function signature is function (err, res, request, reply, settings, ttl) where:
* @param err - internal or upstream error returned from attempting to contact the upstream proxy. TODO: check this is of type BoomError or just Error.
* @param res - the node response object received from the upstream service. res is a readable stream (use the wreck module read method to easily convert it to a Buffer or string).
* @param request - is the incoming request object.
* @param reply - the reply interface function.
* @param settings - the proxy handler configuration.
* @param ttl - the upstream TTL in milliseconds if proxy.ttl it set to 'upstream' and the upstream response included a valid 'Cache-Control' header with 'max-age'.
*/
onResponse?: (err: null | Boom.BoomError,
res: http.IncomingMessage,
req: hapi.Request,
reply: hapi.ReplyWithContinue, // TODO, check it has continue
settings: ProxyHandlerOptions,
ttl: number) => void;
/** ttl - if set to 'upstream', applies the upstream response caching policy to the response using the response.ttl() method (or passed as an argument to the onResponse method if provided). */
ttl?: 'upstream';
/** agent - a node http(s) agent to be used for connections to upstream server. @see {@link https://nodejs.org/api/http.html#http_class_http_agent} */
agent?: http.Agent;
/** maxSockets - sets the maximum number of sockets available per outgoing proxy host connection. false means use the wreck module default value (Infinity). Does not affect non-proxy outgoing client connections. Defaults to Infinity. */
maxSockets?: false | number;
}
}
declare module 'hapi' {
/**
* As one of the handlers for hapi, it is used through the route configuration object.
* [see docs](https://github.com/hapijs/h2o2#usage)
*/
interface RouteHandlerPlugins {
proxy?: H2o2.ProxyHandlerOptions;
}
interface Base_Reply {
/**
* Proxies the request to an upstream endpoint
* @param options an object including the same keys and restrictions defined by the [route proxy handler options](https://github.com/hapijs/h2o2#options).
* [see docs](https://github.com/hapijs/h2o2#replyproxyoptions)
*/
proxy(options: H2o2.ProxyHandlerOptions): void;
}
}
declare var H2o2: hapi.PluginFunction<{}>;
export = H2o2;

22
types/h2o2/tsconfig.json Normal file
View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"h2o2-tests.ts"
]
}

View File

@@ -0,0 +1,42 @@
// from https://github.com/hapijs/hapi-auth-basic#hapi-auth-basic
import Bcrypt = require('bcrypt');
import Basic = require('hapi-auth-basic');
import * as Hapi from 'hapi';
const server = new Hapi.Server();
interface User {
username: string;
password: string;
name: string;
id: string;
}
const users: {[index: string]: User} = {
john: {
username: 'john',
password: '$2a$10$iqJSHD.BGr0E2IxQwYgJmeP3NvhPrXAeLSaGCj6IR/XU5QtjVu5Tm', // 'secret'
name: 'John Doe',
id: '2133d32a'
}
};
const validate: Basic.ValidateFunc = function (request, username, password, callback) {
const user = users[username];
if (!user) {
return callback(null, false);
}
Bcrypt.compare(password, user.password, (err, isValid) => {
callback(err, isValid, { id: user.id, name: user.name });
});
};
server.register(Basic, (err) => {
server.auth.strategy('simple', 'basic', { validateFunc: validate });
server.route({ method: 'GET', path: '/', config: { auth: 'simple' } });
});

21
types/hapi-auth-basic/index.d.ts vendored Normal file
View File

@@ -0,0 +1,21 @@
// Type definitions for hapi 4.2
// Project: https://github.com/hapijs/hapi-auth-basic
// Definitions by: AJP <https://github.com/AJamesPhillips>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
import * as Hapi from 'hapi';
declare namespace Basic {
interface ValidateFuncCallback {
(err: Error | null, isValid: boolean, userCredentials?: any): void;
}
interface ValidateFunc {
(request: Hapi.Request, username: string, password: string, callback: ValidateFuncCallback): void;
}
}
declare var Basic: Hapi.PluginFunction<{}>;
export = Basic;

View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"hapi-auth-basic-tests.ts"
]
}

View File

@@ -2,125 +2,129 @@
// Project: http://github.com/dwyl/hapi-auth-jwt2
// Definitions by: Warren Seymour <http://github.com/warrenseymour>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
import {Request, Response} from 'hapi';
import {Request, Response, PluginFunction} from 'hapi';
/**
* A key lookup function
*
* @param decoded the *decoded* but *unverified* JWT received from client
* @param callback the key lookup callback
*/
export type KeyLookup = (decoded: any, callback: KeyLookupCallback) => void;
/**
* Called when key lookup function has completed
*
* @param err an internal error
* @param key the secret key
* @param extraInfo any additional information that you would like
* to use in `validateFunc` which can be accessed via
* `request.plugins['hapi-auth-jwt2'].extraInfo`
*/
export type KeyLookupCallback = (err: any, key: string, extraInfo?: any) => void;
/**
* Called when Validation has completed
*
* @param err an internal error
* @param valid `true` if the JWT was valid, otherwise `false`
* @param credentials alternative credentials to be set instead of `decoded`
*/
export type ValidateCallback = (err: any, valid: boolean, credentials?: any) => void;
/**
* Options passed to `hapi.auth.strategy` when this plugin is used
*/
export interface Options {
/**
* The secret key used to check the signature of the token *or* a *key lookup function*
*/
key?: string | KeyLookup;
/**
* The function which is run once the Token has been decoded
*
* @param decoded the *decoded* and *verified* JWT received from the client in *request.headers.authorization*
* @param request the original *request* received from the client
* @param callback the validation callback
*/
validateFunc(decoded: {}, request: Request, callback: ValidateCallback): void;
/**
* Settings to define how tokens are verified by the jsonwebtoken library
*/
verifyOptions?: {
declare namespace hapiAuthJwt2 {
/**
* Ignore expired tokens
* A key lookup function
*
* @param decoded the *decoded* but *unverified* JWT received from client
* @param callback the key lookup callback
*/
ignoreExpiration?: boolean;
type KeyLookup = (decoded: any, callback: KeyLookupCallback) => void;
/**
* Do not enforce token audience
* Called when key lookup function has completed
*
* @param err an internal error
* @param key the secret key
* @param extraInfo any additional information that you would like
* to use in `validateFunc` which can be accessed via
* `request.plugins['hapi-auth-jwt2'].extraInfo`
*/
audience?: boolean;
type KeyLookupCallback = (err: any, key: string, extraInfo?: any) => void;
/**
* Do not require the issuer to be valid
* Called when Validation has completed
*
* @param err an internal error
* @param valid `true` if the JWT was valid, otherwise `false`
* @param credentials alternative credentials to be set instead of `decoded`
*/
issuer?: boolean;
type ValidateCallback = (err: any, valid: boolean, credentials?: any) => void;
/**
* List of allowed algorithms
* Options passed to `hapi.auth.strategy` when this plugin is used
*/
algorithms?: string[];
};
interface Options {
/**
* The secret key used to check the signature of the token *or* a *key lookup function*
*/
key?: string | KeyLookup;
/**
* function called to decorate the response with authentication headers
* before the response headers or payload is written
*
* @param request the Request object
* @param reply is called if an error occurred
*/
responseFunc?(request: Request, reply: (err: any, response: Response) => void): void;
/**
* The function which is run once the Token has been decoded
*
* @param decoded the *decoded* and *verified* JWT received from the client in *request.headers.authorization*
* @param request the original *request* received from the client
* @param callback the validation callback
*/
validateFunc(decoded: {}, request: Request, callback: ValidateCallback): void;
/**
* If you prefer to pass your token via url, simply add a token url
* parameter to your request or use a custom parameter by setting `urlKey.
* To disable the url parameter set urlKey to `false` or ''.
* @default 'token'
*/
urlKey?: string | boolean;
/**
* Settings to define how tokens are verified by the jsonwebtoken library
*/
verifyOptions?: {
/**
* Ignore expired tokens
*/
ignoreExpiration?: boolean;
/**
* If you prefer to set your own cookie key or your project has a cookie
* called 'token' for another purpose, you can set a custom key for your
* cookie by setting `options.cookieKey='yourkeyhere'`. To disable cookies
* set cookieKey to `false` or ''.
* @default 'token'
*/
cookieKey?: string | boolean;
/**
* Do not enforce token audience
*/
audience?: boolean;
/**
* If you want to set a custom key for your header token use the
* `headerKey` option. To disable header token set headerKey to `false` or
* ''.
* @default 'authorization'
*/
headerKey?: string | boolean;
/**
* Do not require the issuer to be valid
*/
issuer?: boolean;
/**
* Allow custom token type, e.g. `Authorization: <tokenType> 12345678`
*/
tokenType?: string;
/**
* List of allowed algorithms
*/
algorithms?: string[];
};
/**
* Set to `true` to receive the complete token (`decoded.header`,
* `decoded.payload` and `decoded.signature`) as decoded argument to key
* lookup and `verifyFunc` callbacks (*not `validateFunc`*)
* @default false
*/
complete?: boolean;
/**
* function called to decorate the response with authentication headers
* before the response headers or payload is written
*
* @param request the Request object
* @param reply is called if an error occurred
*/
responseFunc?(request: Request, reply: (err: any, response: Response) => void): void;
/**
* If you prefer to pass your token via url, simply add a token url
* parameter to your request or use a custom parameter by setting `urlKey.
* To disable the url parameter set urlKey to `false` or ''.
* @default 'token'
*/
urlKey?: string | boolean;
/**
* If you prefer to set your own cookie key or your project has a cookie
* called 'token' for another purpose, you can set a custom key for your
* cookie by setting `options.cookieKey='yourkeyhere'`. To disable cookies
* set cookieKey to `false` or ''.
* @default 'token'
*/
cookieKey?: string | boolean;
/**
* If you want to set a custom key for your header token use the
* `headerKey` option. To disable header token set headerKey to `false` or
* ''.
* @default 'authorization'
*/
headerKey?: string | boolean;
/**
* Allow custom token type, e.g. `Authorization: <tokenType> 12345678`
*/
tokenType?: string;
/**
* Set to `true` to receive the complete token (`decoded.header`,
* `decoded.payload` and `decoded.signature`) as decoded argument to key
* lookup and `verifyFunc` callbacks (*not `validateFunc`*)
* @default false
*/
complete?: boolean;
}
}
export default function hapiAuthJwt2(): void;
declare var hapiAuthJwt2: PluginFunction<{}>;
export = hapiAuthJwt2;

View File

@@ -4,7 +4,7 @@ import { controller, get, post, put, cache, config, route, validate, Controller
@controller('/test')
class TestController implements Controller {
baseUrl: string;
routes: () => hapi.IRouteConfiguration[];
routes: () => hapi.RouteConfiguration[];
@get('/')
@config({
@@ -16,22 +16,22 @@ class TestController implements Controller {
@validate({
payload: false
})
getHandler(request: hapi.Request, reply: hapi.IReply) {
getHandler(request: hapi.Request, reply: hapi.ReplyNoContinue) {
reply({ success: true });
}
@post('/')
postHandler(request: hapi.Request, reply: hapi.IReply) {
postHandler(request: hapi.Request, reply: hapi.ReplyNoContinue) {
reply({ success: true });
}
@put('/{id}')
putHandler(request: hapi.Request, reply: hapi.IReply) {
putHandler(request: hapi.Request, reply: hapi.ReplyNoContinue) {
reply({ success: true });
}
@route('delete', '/{id}')
deleteHandler(request: hapi.Request, reply: hapi.IReply) {
deleteHandler(request: hapi.Request, reply: hapi.ReplyNoContinue) {
reply({ success: true });
}
}
@@ -50,7 +50,7 @@ class SimpleTestController implements Controller {
}
baseUrl: string;
routes: () => hapi.IRouteConfiguration[];
routes: () => hapi.RouteConfiguration[];
}
server.route(new SimpleTestController('bar').routes());

View File

@@ -4,12 +4,13 @@
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
import * as hapi from 'hapi';
import * as Joi from 'joi';
interface ControllerStatic {
new (...args: any[]): Controller;
}
export interface Controller {
baseUrl: string;
routes: () => hapi.IRouteConfiguration[];
routes: () => hapi.RouteConfiguration[];
}
export function controller(baseUrl: string): (target: ControllerStatic) => void;
interface IRouteSetup {
@@ -28,61 +29,9 @@ export const put: IRouteConfig;
// export const delete: IRouteConfig;
export const patch: IRouteConfig;
export const all: IRouteConfig;
export function config(config: hapi.IRouteAdditionalConfigurationOptions): (target: any, key: any, descriptor: any) => any;
interface IValidateConfig {
/** validation rules for incoming request headers.Values allowed:
* trueany headers allowed (no validation performed).This is the default.
falseno headers allowed (this will cause all valid HTTP requests to fail).
a Joi validation object.
a validation function using the signature function(value, options, next) where:
valuethe object containing the request headers.
optionsthe server validation options.
next(err, value)the callback function called when validation is completed.
*/
headers?: boolean | hapi.IJoi | hapi.IValidationFunction;
/** validation rules for incoming request path parameters, after matching the path against the route and extracting any parameters then stored in request.params.Values allowed:
trueany path parameters allowed (no validation performed).This is the default.
falseno path variables allowed.
a Joi validation object.
a validation function using the signature function(value, options, next) where:
valuethe object containing the path parameters.
optionsthe server validation options.
next(err, value)the callback function called when validation is completed. */
params?: boolean | hapi.IJoi | hapi.IValidationFunction;
/** validation rules for an incoming request URI query component (the key- value part of the URI between '?' and '#').The query is parsed into its individual key- value pairs (using the qs module) and stored in request.query prior to validation.Values allowed:
trueany query parameters allowed (no validation performed).This is the default.
falseno query parameters allowed.
a Joi validation object.
a validation function using the signature function(value, options, next) where:
valuethe object containing the query parameters.
optionsthe server validation options.
next(err, value)the callback function called when validation is completed. */
query?: boolean | hapi.IJoi | hapi.IValidationFunction;
/** validation rules for an incoming request payload (request body).Values allowed:
trueany payload allowed (no validation performed).This is the default.
falseno payload allowed.
a Joi validation object.
a validation function using the signature function(value, options, next) where:
valuethe object containing the payload object.
optionsthe server validation options.
next(err, value)the callback function called when validation is completed. */
payload?: boolean | hapi.IJoi | hapi.IValidationFunction;
/** an optional object with error fields copied into every validation error response. */
errorFields?: any;
/** determines how to handle invalid requests.Allowed values are:
'error'return a Bad Request (400) error response.This is the default value.
'log'log the error but continue processing the request.
'ignore'take no action.
OR a custom error handler function with the signature 'function(request, reply, source, error)` where:
requestthe request object.
replythe continuation reply interface.
sourcethe source of the invalid field (e.g. 'path', 'query', 'payload').
errorthe error object prepared for the client response (including the validation function error under error.data). */
failAction?: string | hapi.IRouteFailFunction;
/** options to pass to Joi.Useful to set global options such as stripUnknown or abortEarly (the complete list is available here: https://github.com/hapijs/joi#validatevalue-schema-options-callback ).Defaults to no options. */
options?: any;
}
export function validate(config: IValidateConfig): (target: any, key: any, descriptor: any) => any;
export function config(config: hapi.RouteAdditionalConfigurationOptions): (target: any, key: any, descriptor: any) => any;
export function validate(config: hapi.RouteValidationConfigurationObject): (target: any, key: any, descriptor: any) => any;
interface ICacheConfig {
privacy?: string;
expiresIn?: number;

4970
types/hapi/index.d.ts vendored

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
// From https://hapijs.com/api/16.1.1#servertablehost
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80, host: 'example.com' });
server.route({ method: 'GET', path: '/example', handler: function (request, reply) { return reply(); } });
const connection = server.connections[0];
const table = connection.table();
/*
[
{
method: 'get',
path: '/example',
settings: { ... }
}
]
*/

View File

@@ -0,0 +1,16 @@
// From https://hapijs.com/tutorials/getting-started#creating-a-server
'use strict';
import Hapi = require('hapi');
const server = new Hapi.Server();
server.connection({ port: 3000, host: 'localhost' });
server.start((err) => {
if (err) {
throw err;
}
console.log(`Server running at: ${server.info!.uri}`);
});

View File

@@ -0,0 +1,32 @@
// from https://hapijs.com/tutorials/getting-started#adding-routes
'use strict';
import Hapi = require('hapi');
const server = new Hapi.Server();
server.connection({ port: 3000, host: 'localhost' });
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Hello, world!');
}
});
server.route({
method: 'GET',
path: '/{name}',
handler: function (request, reply) {
reply('Hello, ' + encodeURIComponent(request.params.name) + '!');
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log(`Server running at: ${server.info!.uri}`);
});

View File

@@ -0,0 +1,23 @@
'use strict';
import Hapi = require('hapi');
import Inert = require('inert');
const server = new Hapi.Server();
// from https://hapijs.com/tutorials/getting-started#creating-static-pages-and-content
server.register(Inert, (err) => {
if (err) {
throw err;
}
server.route({
method: 'GET',
path: '/hello',
handler: function (request, reply) {
reply.file('./public/hello.html');
}
});
});

View File

@@ -0,0 +1,56 @@
// from https://hapijs.com/tutorials/getting-started#using-plugins
'use strict';
import Hapi = require('hapi');
const Good = require('good');
const server = new Hapi.Server();
server.connection({ port: 3000, host: 'localhost' });
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Hello, world!');
}
});
server.route({
method: 'GET',
path: '/{name}',
handler: function (request, reply) {
reply('Hello, ' + encodeURIComponent(request.params.name) + '!');
}
});
server.register({
register: Good,
options: {
reporters: {
console: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{
response: '*',
log: '*'
}]
}, {
module: 'good-console'
}, 'stdout']
}
}
}, (err) => {
if (err) {
throw err; // something bad happened loading the plugin
}
server.start((err) => {
if (err) {
throw err;
}
server.log('info', 'Server running at: ' + server.info!.uri);
});
});

View File

@@ -0,0 +1,15 @@
// From https://hapijs.com/api/16.1.1#catch-all-route
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.route({
method: '*',
path: '/{p*}',
handler: function (request, reply) {
return reply('The page was not found').code(404);
}
});

View File

@@ -0,0 +1,33 @@
// From https://hapijs.com/api/16.1.1#path-parameters
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const getAlbum: Hapi.RouteHandler = function (request, reply) {
return reply('You asked for ' +
(request.params.song ? request.params.song + ' from ' : '') +
request.params.album);
};
server.route({
path: '/{album}/{song?}',
method: 'GET',
handler: getAlbum
});
// Example 2
const getPerson: Hapi.RouteHandler = function (request, reply) {
const nameParts = request.params.name.split('/');
return reply({ first: nameParts[0], last: nameParts[1] });
};
server.route({
path: '/person/{name*2}', // Matches '/person/john/doe'
method: 'GET',
handler: getPerson
});

View File

@@ -0,0 +1,36 @@
// From https://hapijs.com/api/16.1.1#serverinfo
import * as Hapi from 'hapi';
// added in addition to code from docs
interface PluginOptions {
quantity: number;
}
// modified from docs
var registerFunction: Hapi.PluginFunction<PluginOptions> = function(server, options, next) {
server.route({
method: 'GET',
path: '/test',
handler: function (request, reply) {
// modified from docs
return reply(`ok ${options.quantity}`);
}
});
return next();
};
var attributes: Hapi.PluginAttributes = {
name: 'test',
version: '1.0.0'
};
var attributes: Hapi.PluginAttributes = {
pkg: {} // require('./package.json'),
};
registerFunction.attributes = attributes;

View File

@@ -0,0 +1,15 @@
// From https://hapijs.com/api/16.1.1#replycontinueresult
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const onRequest: Hapi.ServerExtRequestHandler = function (request, reply) {
// Change all requests to '/test'
request.setUrl('/test');
return reply.continue();
};
server.ext('onRequest', onRequest);

View File

@@ -0,0 +1,24 @@
// From https://hapijs.com/api/16.1.1#replyentityoptions
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.route({
method: 'GET',
path: '/',
config: {
cache: { expiresIn: 5000 },
handler: function (request, reply) {
const response = reply.entity({ etag: 'abc' });
if (response) {
response.header('X', 'y');
return;
}
return reply('ok');
}
}
});

View File

@@ -0,0 +1,8 @@
// From https://hapijs.com/api/16.1.1#replyredirecturi
import * as Hapi from 'hapi';
const handler: Hapi.RouteHandler = function (request, reply) {
return reply.redirect('http://example.com');
};

View File

@@ -0,0 +1,22 @@
// From https://hapijs.com/api/16.1.1#replyerr-result
import * as Hapi from 'hapi';
// verbose notation
const handler: Hapi.RouteHandler = function (request, reply) {
const response = reply('success');
response.type('text/plain');
response.header('X-Custom', 'some-value');
};
// Chained notation
const handler2: Hapi.RouteHandler = function (request, reply) {
return reply('success')
.type('text/plain')
.header('X-Custom', 'some-value');
};

View File

@@ -0,0 +1,33 @@
// from https://hapijs.com/tutorials/cookies?lang=en_US
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.state('data', {
ttl: null,
isSecure: true,
isHttpOnly: true,
encoding: 'base64json',
clearInvalid: false, // remove invalid cookies
strictHeader: true // don't allow violations of RFC 6265
});
server.route({
method: 'GET',
path: '/say-hello',
config: {
state: {
parse: true, // parse and store in request.state
failAction: 'error' // may also be 'ignore' or 'log'
}
},
handler: function(request, reply) {
// TODO test this
reply('Hello').state('data', { firstVisit: false });
}
})

View File

@@ -0,0 +1,30 @@
// From https://hapijs.com/api/16.1.1#requestsetmethodmethod
import * as Hapi from 'hapi';
const Crypto = require('crypto');
const server = new Hapi.Server();
server.connection({ port: 80 });
const onRequest: Hapi.ServerExtRequestHandler = function (request, reply) {
const hash = Crypto.createHash('sha1');
request.on('peek', (chunk) => {
hash.update(chunk);
});
request.once('finish', () => {
console.log(hash.digest('hex'));
});
request.once('disconnect', () => {
console.error('request aborted');
});
return reply.continue();
};
server.ext('onRequest', onRequest);

View File

@@ -0,0 +1,21 @@
// From https://hapijs.com/api/16.1.1#requestgenerateresponsesource-options
import * as Hapi from 'hapi';
// Added in addition to code from docs
function promiseMethod() {
return Promise.resolve(true);
}
const handler: Hapi.ServerExtRequestHandler = function (request, reply) {
const result = promiseMethod().then((thing: boolean) => {
if (!thing) {
return request.generateResponse().code(214);
}
return thing;
});
return reply(result);
};

View File

@@ -0,0 +1,12 @@
// From https://hapijs.com/api/16.1.1#requestgetlogtags-internal
import * as Hapi from 'hapi';
var request: Hapi.Request = <any> {};
request.getLog();
request.getLog('error');
request.getLog(['error', 'auth']);
request.getLog(['error'], true);
request.getLog(false);

View File

@@ -0,0 +1,19 @@
// From https://hapijs.com/api/16.1.1#requestlogtags-data-timestamp
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80, routes: { log: true, security: false } });
server.on('request', (request, event, tags) => {
if (tags.error) {
console.log(event);
}
});
const handler: Hapi.RouteHandler = function (request, reply) {
request.log(['test', 'error'], 'Test event');
return reply();
};

View File

@@ -0,0 +1,15 @@
// From https://hapijs.com/api/16.1.1#requestsetmethodmethod
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const onRequest: Hapi.ServerExtRequestHandler = function (request, reply) {
// Change all requests to 'GET'
request.setMethod('GET');
return reply.continue();
};
server.ext('onRequest', onRequest);

View File

@@ -0,0 +1,32 @@
// From https://hapijs.com/api/16.1.1#requestseturlurl-striptrailingslash
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
var onRequest: Hapi.ServerExtRequestHandler = function (request, reply) {
// Change all requests to '/test'
request.setUrl('/test');
return reply.continue();
};
server.ext('onRequest', onRequest);
// Example 2
const Url = require('url');
const Qs = require('qs');
onRequest = function (request, reply) {
const uri = request.raw.req.url;
const parsed = Url.parse(uri, false);
parsed.query = Qs.parse(parsed.query);
request.setUrl(parsed);
return reply.continue();
};
server.ext('onRequest', onRequest);

View File

@@ -0,0 +1,26 @@
// From https://hapijs.com/api/16.1.1#requestsetmethodmethod
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const get: Hapi.RouteHandler = function (request, reply) {
const dbTail = request.tail('write to database');
var db: any;
db.save('key', 'value', () => {
dbTail();
});
return reply('Success!');
};
server.route({ method: 'GET', path: '/', handler: get });
server.on('tail', (request) => {
console.log('Request completed including db activity');
});

View File

@@ -0,0 +1,33 @@
// From https://hapijs.com/api/16.1.1#error-transformation
import * as Hapi from 'hapi';
import Vision from 'vision';
const server = new Hapi.Server();
server.register(Vision, {}, (err) => {
server.views({
engines: {
html: require('handlebars')
}
});
});
server.connection({ port: 80 });
const preResponse: Hapi.ServerExtRequestHandler = function (request, reply) {
const response = request.response!;
if (!response.isBoom) {
return reply.continue();
}
// Replace error with friendly HTML
const error = response;
const ctx = {
message: (error.output!.statusCode === 404 ? 'page not found' : 'something went wrong')
};
return reply.view('error', ctx);
};
server.ext('onPreResponse', preResponse);

View File

@@ -0,0 +1,25 @@
// From https://hapijs.com/api/16.1.1#error-response
import * as Hapi from 'hapi';
const Boom = require('boom');
const server = new Hapi.Server();
server.route({
method: 'GET',
path: '/badRequest',
handler: function (request, reply) {
return reply(Boom.badRequest('Unsupported parameter'));
}
});
server.route({
method: 'GET',
path: '/internal',
handler: function (request, reply) {
return reply(new Error('unexpect error'));
}
});

View File

@@ -0,0 +1,30 @@
// From https://hapijs.com/api/16.1.1#response-events
import * as Hapi from 'hapi';
const Crypto = require('crypto');
const server = new Hapi.Server();
server.connection({ port: 80 });
const preResponse: Hapi.ServerExtRequestHandler = function (request, reply) {
const response = request.response!;
if (response.isBoom) {
return reply();
}
const hash = Crypto.createHash('sha1');
response.on('peek', (chunk) => {
hash.update(chunk);
});
response.once('finish', () => {
console.log(hash.digest('hex'));
});
return reply.continue();
};
server.ext('onPreResponse', preResponse);

View File

@@ -0,0 +1,14 @@
// From https://hapijs.com/api/16.1.1#flow-control
import * as Hapi from 'hapi';
const handler = function (request: Hapi.Request, reply: Hapi.ReplyWithContinue) {
const response = reply('success').hold();
setTimeout(() => {
response.send();
}, 1000);
};

View File

@@ -0,0 +1,39 @@
'use strict';
import * as Hapi from 'hapi';
var authConfig: Hapi.RouteAdditionalConfigurationOptions = {
app: {}
};
// Handler in config
const user: Hapi.RouteAdditionalConfigurationOptions = {
cache: { expiresIn: 5000, statuses: [200, 201] },
handler: function (request, reply) {
return reply({ name: 'John' });
}
};
// Add in addition to examples in docs
var cache: Hapi.RouteCacheOptions = {
privacy: 'default',
expiresIn: 5000,
};
cache = {
privacy: 'default',
expiresAt: '22:44',
};
cache = {
privacy: 'default',
};
/* should error (as does!)
var cache: Hapi.RouteCacheOptions = {
expiresIn: 5000,
expiresAt: '22:44',
};
*/

View File

@@ -0,0 +1,25 @@
'use strict';
import * as Hapi from 'hapi';
var routeMoreConfig: Hapi.RouteAdditionalConfigurationOptions = {
auth: false,
}
routeMoreConfig = {
auth: 'some_strategy',
}
routeMoreConfig = {
auth: {
mode: 'required',
strategies: ['strat1', 'strat2'],
strategy: 'should not be given when strategies given',
payload: false,
access: {
scope: false,
entity: 'any',
},
// Will over write values in access
scope: false,
entity: 'any',
}
}

View File

@@ -0,0 +1,46 @@
'use strict';
import * as Hapi from 'hapi';
// different methods
var routeConfig: Hapi.RouteConfiguration = {
path: '/signin',
method: 'PUT',
vhost: 'site.coms',
};
var routeConfig: Hapi.RouteConfiguration = {
path: '/signin',
method: '*'
};
var routeConfig: Hapi.RouteConfiguration = {
path: '/signin',
method: ['OPTIONS', '*']
};
// different handlers
var routeConfig: Hapi.RouteConfiguration = {
path: '/signin',
method: 'PUT',
handler: 'some registered handler'
};
var routeConfig: Hapi.RouteConfiguration = {
path: '/signin',
method: 'PUT',
handler: function (request, reply) {
return reply('ok');
}
};
const server = new Hapi.Server();
server.route(routeConfig);
// Handler in config
const user: Hapi.RouteAdditionalConfigurationOptions = {
cache: { expiresIn: 5000 },
handler: function (request, reply) {
return reply({ name: 'John' });
}
};
server.route({method: 'GET', path: '/user', config: user });

View File

@@ -0,0 +1,10 @@
'use strict';
import * as Hapi from 'hapi';
var handler: Hapi.RouteHandler = function(request, reply) {
reply('success');
}
var strictHandler: Hapi.RouteHandler = function(request, reply) {
reply(123);
}

View File

@@ -0,0 +1,47 @@
// From https://hapijs.com/api/16.1.1#route-prerequisites
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const pre1: Hapi.RoutePrerequisiteRequestHandler = function (request, reply) {
return reply('Hello');
};
const pre2: Hapi.RoutePrerequisiteRequestHandler = function (request, reply) {
return reply('World');
};
const pre3: Hapi.RoutePrerequisiteRequestHandler = function (request, reply) {
const pre = request.pre as Pre1;
return reply(pre.m1 + ' ' + pre.m2);
};
server.route({
method: 'GET',
path: '/',
config: {
pre: [
[
// m1 and m2 executed in parallel
{ method: pre1, assign: 'm1' },
{ method: pre2, assign: 'm2' }
],
{ method: pre3, assign: 'm3' },
],
handler: function (request, reply) {
const pre = request.pre as Pre2;
return reply(pre.m3 + '\n');
}
}
});
interface Pre1 {
m1: string;
m2: string;
}
interface Pre2 extends Pre1 {
m3: string;
}

View File

@@ -0,0 +1,17 @@
'use strict';
import * as Hapi from 'hapi';
var route = <Hapi.RoutePublicInterface> {};
var a: string = route.method;
var a: string = route.path;
if (typeof(route.vhost) == 'string') {
var a: string = route.vhost;
} else {
var b: string[] = route.vhost!;
}
var c: Hapi.ServerRealm = route.realm;
var d: Hapi.RouteAdditionalConfigurationOptions = route.settings;
var a: string = route.fingerprint;
var e: boolean = route.auth.access(<Hapi.Request> {});

View File

@@ -0,0 +1,11 @@
// From https://hapijs.com/api/16.1.1#serverapp
import * as Hapi from 'hapi';
var server = new Hapi.Server();
server.app.key = 'value';
const handler: Hapi.RouteHandler = function (request, reply) {
return reply(request.server.app.key);
};

View File

@@ -0,0 +1,101 @@
// From https://hapijs.com/api/16.1.1#serverauthapi
import * as Hapi from 'hapi';
import * as Boom from 'boom';
const server = new Hapi.Server();
server.connection({ port: 80 });
var scheme: Hapi.ServerAuthScheme = function (server, options) {
return {
api: {
settings: {
x: 5
}
},
authenticate: function (request, reply) {
const req = request.raw.req;
const authorization = req.headers.authorization;
if (!authorization) {
return reply(Boom.unauthorized(null, 'Custom'));
}
return reply.continue({ credentials: { user: 'john' } });
}
};
};
server.auth.scheme('custom', scheme);
server.auth.strategy('default', 'custom');
console.log(server.auth.api.default.settings.x); // 5
// Default
server.auth.default('default');
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
return reply(request.auth.credentials.user);
}
});
// scheme
scheme = function (server, options) {
return {
authenticate: function (request, reply) {
const req = request.raw.req;
const authorization = req.headers.authorization;
if (!authorization) {
return reply(Boom.unauthorized(null, 'Custom'));
}
return reply.continue({ credentials: { user: 'john' } });
}
};
};
server.auth.scheme('custom', scheme);
// strategy
server.auth.scheme('custom', scheme);
server.auth.strategy('default', 'custom');
server.route({
method: 'GET',
path: '/',
config: {
auth: 'default',
handler: function (request, reply) {
return reply(request.auth.credentials.user);
}
}
});
// test
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
request.server.auth.test('default', request, (err, credentials) => {
if (err) {
return reply({ status: false });
}
return reply({ status: true, user: (credentials as any).name });
});
}
});

View File

@@ -0,0 +1,24 @@
// From https://hapijs.com/api/16.1.1#serverbindcontext
import * as Hapi from 'hapi';
interface HandlerThis {
message: string;
}
const handler: Hapi.RouteHandler = function (this: HandlerThis, request, reply) {
return reply(this.message);
};
var register: Hapi.PluginFunction<{}> = function (server, options, next) {
const bind: HandlerThis = {
message: 'hello'
};
server.bind(bind);
server.route({ method: 'GET', path: '/', handler: handler });
return next();
};

View File

@@ -0,0 +1,33 @@
// From https://hapijs.com/api/16.1.1#servercacheoptions
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const cache = server.cache({ segment: 'countries', expiresIn: 60 * 60 * 1000 });
cache.set('norway', { capital: 'oslo' }, null, (err) => {
cache.get('norway', (err, value, cached, log) => {
// value === { capital: 'oslo' };
});
});
// provision
// From https://hapijs.com/api/16.1.1#servercacheprovisionoptions-callback
server.initialize((err) => {
server.cache.provision({ engine: require('catbox-memory'), name: 'countries' }, (err) => {
const cache = server.cache({ cache: 'countries', expiresIn: 60 * 60 * 1000 });
cache.set('norway', { capital: 'oslo' }, null, (err) => {
cache.get('norway', (err, value, cached, log) => {
// value === { capital: 'oslo' };
});
});
});
});

View File

@@ -0,0 +1,39 @@
// From https://hapijs.com/api/16.1.1#serverconnectionoptions
import * as Hapi from 'hapi';
const server = new Hapi.Server();
const web = server.connection({ port: 8000, host: 'example.com', labels: ['web'] });
const admin = server.connection({ port: 8001, host: 'example.com', labels: ['admin'] });
server.connections.length === 2;
web.connections.length === 1;
admin.connections.length === 1;
// example 2
var registerFunction: Hapi.PluginFunction<{}> = function (srv, options, next) {
// Use the 'srv' argument to add a new connection
const server = srv.connection();
// Use the 'server' return value to manage the new connection
server.route({
path: '/',
method: 'GET',
handler: function (request, reply) {
return reply('hello');
}
});
return next();
};
registerFunction.attributes = {
name: 'example',
connections: false
};

View File

@@ -0,0 +1,13 @@
// From https://hapijs.com/api/16.1.1#serverconnections
import * as Hapi from 'hapi';
var server = new Hapi.Server();
server.connection({ port: 80, labels: 'a' });
server.connection({ port: 8080, labels: 'b' });
// server.connections.length === 2
const a = server.select('a');
// a.connections.length === 1

View File

@@ -0,0 +1,9 @@
// From https://hapijs.com/api/16.1.1#serverdecoderencoding-decoder
import * as Hapi from 'hapi';
import * as Zlib from 'zlib';
const server = new Hapi.Server();
server.connection({ port: 80, routes: { payload: { compression: { special: { chunkSize: 16 * 1024 } } } } });
server.decoder('special', (options) => Zlib.createGunzip(options));

View File

@@ -0,0 +1,68 @@
// From https://hapijs.com/api/16.1.1#serverdecoratetype-property-method-options
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const success = function (this: Hapi.ReplyNoContinue) {
return this.response({ status: 'ok' });
};
server.decorate('reply', 'success', success);
declare module 'hapi' {
interface Base_Reply {
success: () => Response;
}
}
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
return reply.success();
}
});
// custom typing code for decorating request
server.decorate('request', 'some_request_method', (request) => {
return function() {
// Do some sort of processing;
return request.id;
}
}, {apply: true});
declare module 'hapi' {
interface Request {
some_request_method(): void;
}
}
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
request.some_request_method();
return reply();
}
});
// custom typing code for decorating server
server.decorate('server', 'some_server_method', (server: Hapi.Server) => {
return function(arg1: number){
return "some text";
}
});
declare module 'hapi' {
interface Server {
some_server_method(arg1: number): string;
}
}
server.some_server_method(1);

View File

@@ -0,0 +1,24 @@
// From https://hapijs.com/api/16.1.1#serverdependencydependencies-after
import * as Hapi from 'hapi';
const after: Hapi.AfterDependencyLoadCallback = function (server, next) {
// Additional plugin registration logic
return next();
};
var registerFunction: Hapi.PluginFunction<{}> = function (server, options, next) {
server.dependency('yar', after);
return next();
};
// Example 2, via attributes
registerFunction.attributes = {
name: 'test',
version: '1.0.0',
dependencies: 'yar'
};

View File

@@ -0,0 +1,12 @@
// From https://hapijs.com/api/16.1.1#serveremitcriteria-data-callback
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.event('test');
server.on('test', (update: Update) => console.log(update));
type Update = string;
var toSend: Update = 'hello';
server.emit('test', toSend);

View File

@@ -0,0 +1,9 @@
// From https://hapijs.com/api/16.1.1#serverencoderencoding-encoder
import * as Hapi from 'hapi';
import * as Zlib from 'zlib';
const server = new Hapi.Server();
server.connection({ port: 80, routes: { compression: { special: { chunkSize: 16 * 1024 } } } });
server.encoder('special', (options) => Zlib.createGzip(options));

View File

@@ -0,0 +1,12 @@
// From https://hapijs.com/api/16.1.1#servereventevents
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.event('test');
server.on('test', (update: Update) => console.log(update));
type Update = string;
var toSend: Update = 'hello';
server.emit('test', toSend);

View File

@@ -0,0 +1,17 @@
// From https://hapijs.com/api/16.1.1#serverexposekey-value
import * as Hapi from 'hapi';
var register: Hapi.PluginFunction<{}> = function (server, options, next) {
server.expose('util', function () { console.log('something'); });
return next();
};
// example of `expose()` merging object
register = function (server, options, next) {
server.expose({ util: function () { console.log('something'); } });
return next();
};

View File

@@ -0,0 +1,46 @@
// From https://hapijs.com/api/16.1.1#serverextevents
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.ext({
type: 'onRequest',
method: <Hapi.ServerExtRequestHandler> function (request, reply) {
// Change all requests to '/test'
request.setUrl('/test');
return reply.continue();
}
});
var handler: Hapi.RouteHandler = function (request, reply) {
return reply({ status: 'ok' });
};
server.route({ method: 'GET', path: '/test', handler: handler });
server.start((err) => { });
// All requests will get routed to '/test'
// Example 2
server.ext('onRequest', <Hapi.ServerExtRequestHandler> function (request, reply) {
// Change all requests to '/test'
request.setUrl('/test');
return reply.continue();
});
handler = function (request, reply) {
return reply({ status: 'ok' });
};
server.route({ method: 'GET', path: '/test', handler: handler });
server.start((err) => { });
// All requests will get routed to '/test'

View File

@@ -0,0 +1,55 @@
// From https://hapijs.com/api/16.1.1#serverhandlername-method
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ host: 'localhost', port: 8000 });
// Defines new handler for routes on this server
var handler: Hapi.MakeRouteHandler = function (route, options) {
return function (request, reply) {
return reply('new handler: ' + options.msg);
}
};
server.handler('test', handler);
interface TestPluginConfig {
msg: string;
}
declare module 'hapi' {
interface RouteHandlerPlugins {
test?: TestPluginConfig;
}
}
server.route({
method: 'GET',
path: '/',
handler: { test: { msg: 'test' } }
});
server.start(function (err) { });
// example 2
handler = function (route, options: TestPluginConfig) {
return function (request, reply) {
return reply('new handler: ' + options.msg);
}
};
// Change the default payload processing for this handler
handler.defaults = {
payload: {
output: 'stream',
parse: false
}
};
server.handler('test', handler);

View File

@@ -0,0 +1,16 @@
// From https://hapijs.com/api/16.1.1#serverinfo
import assert = require('assert');
import * as Hapi from 'hapi';
const server = new Hapi.Server();
var options: Hapi.ServerConnectionOptions = { port: 80 };
server.connection(options);
if(server.info) assert(server.info.port === 80);
options = { port: 8080 };
server.connection(options);
assert(server.info === null);
assert(server.connections[1].info.port === 8080);

View File

@@ -0,0 +1,12 @@
// From https://hapijs.com/api/16.1.1#serverinitializecallback
import * as Hapi from 'hapi';
const Hoek = require('hoek');
const server = new Hapi.Server();
server.connection({ port: 80 });
server.initialize((err) => {
Hoek.assert(!err, err);
});

View File

@@ -0,0 +1,18 @@
// From https://hapijs.com/api/16.1.1#serverinjectoptions-callback
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
const handler: Hapi.RouteHandler = function (request, reply) {
return reply('Success!');
};
server.route({ method: 'GET', path: '/', handler: handler });
server.inject('/', (res) => {
console.log(res.result);
});

View File

@@ -0,0 +1,19 @@
// From https://hapijs.com/api/16.1.1#serverlistener
import * as Hapi from 'hapi';
import SocketIO = require('socket.io');
const server = new Hapi.Server();
server.connection({ port: 80 });
// https://socket.io/docs/server-api/#server-attach-httpserver-options
const io = SocketIO.listen(server.listener);
io.sockets.on('connection', (socket) => {
// TODO, FIXME by removing <any>, probably `socket` type given here is
// a wrapper around socket.io. Much less likely is either
// a type error in the TypeScript definitions of socket.io or
// an error in the Hapi docs.
socket.emit(<any> { msg: 'welcome' });
});

View File

@@ -0,0 +1,7 @@
// From https://hapijs.com/api/16.1.1#serverload
import * as Hapi from 'hapi';
const server = new Hapi.Server({ load: { sampleInterval: 1000 } });
var d: number = server.load.rss;

View File

@@ -0,0 +1,15 @@
// From https://hapijs.com/api/16.1.1#serverlogtags-data-timestamp
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.on('log', (event, tags) => {
if (tags.error) {
console.log(event);
}
});
server.log(['test', 'error'], 'Test event');

View File

@@ -0,0 +1,19 @@
// From https://hapijs.com/api/16.1.1#serverlookupid
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection();
server.route({
method: 'GET',
path: '/',
config: {
handler: function (request, reply) {
return reply();
},
id: 'root'
}
});
const route = server.lookup('root');

View File

@@ -0,0 +1,19 @@
// From https://hapijs.com/api/16.1.1#servermatchmethod-path-host
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection();
server.route({
method: 'GET',
path: '/',
config: {
handler: function (request, reply) {
return reply();
},
id: 'root'
}
});
const route = server.match('get', '/');

View File

@@ -0,0 +1,78 @@
// From https://hapijs.com/api/16.1.1#servermethodname-method-options
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
// Simple arguments
const add = function (a: number, b: number, next: Hapi.ServerMethodNext) {
return next(null, a + b);
};
server.method('sum', add, { cache: { expiresIn: 2000, generateTimeout: 100 } });
var next: Hapi.ServerMethodNext = (err, result) => {
console.log(result);
};
server.methods.sum(4, 5, next);
// Object argument
const addArray = function (array: number[], next: Hapi.ServerMethodNext) {
let sum = 0;
array.forEach((item) => {
sum += item;
});
return next(null, sum);
};
server.method('sumObj', addArray, {
cache: { expiresIn: 2000, generateTimeout: 100 },
generateKey: function (array) {
return array.join(',');
}
});
var next: Hapi.ServerMethodNext = (err, result) => {
console.log(result);
};
server.methods.sumObj([5, 6], next);
// Synchronous method with cache
const addSync = function (a: number, b: number) {
return a + b;
};
server.method('sumSync', addSync, { cache: { expiresIn: 2000, generateTimeout: 100 }, callback: false });
var next: Hapi.ServerMethodNext = (err, result) => {
console.log(result);
};
server.methods.sumSync(4, 5, next);
// server.method(methods)
var config = {
name: 'sum',
method: add,
options: {
cache: {
expiresIn: 2000,
generateTimeout: 100
}
}
};
server.method(config);
server.method([config]);

View File

@@ -0,0 +1,17 @@
// From https://hapijs.com/api/16.1.1#servermethods
import * as Hapi from 'hapi';
const server = new Hapi.Server();
const add = function (a: number, b: number, next: (err: Error | null, result: number) => void) {
return next(null, a + b);
};
server.method('add', add);
server.methods.add(1, 2, (err: Error | null, result: number) => {
// result === 3
});

View File

@@ -0,0 +1,21 @@
// From https://hapijs.com/api/16.1.1#servermime
import * as Hapi from 'hapi';
const options: Hapi.ServerOptions = {
mime: {
override: {
'node/module': {
source: 'steve',
compressible: false,
extensions: ['node', 'module', 'npm'],
type: 'node/module'
}
}
}
};
const server = new Hapi.Server(options);
server.mime.path('code.js').type === 'application/javascript';
server.mime.path('file.npm').type === 'node/module';

View File

@@ -0,0 +1,65 @@
'use strict';
import * as Hapi from 'hapi';
new Hapi.Server();
new Hapi.Server({
app: {some: 'values'},
cache: require('catbox-redis'),
});
const server = new Hapi.Server({
cache: require('catbox-redis'),
load: {
sampleInterval: 1000
}
});
// Specific cache configuration options
new Hapi.Server({
cache: {
engine: require('catbox-redis'),
// name: 'optionally omitted when only a single cache used',
}
});
new Hapi.Server({
cache: [{
engine: require('catbox-redis'),
name: 'unique 1',
},
{
engine: require('catbox-redis'),
name: 'unique 2',
shared: true,
otherOptions: 'will be passed to the catbox strategy',
}]
});
new Hapi.Server({
cache: [{
engine: require('catbox-redis'),
},
// Does not correctly error but will be caught by hapi at runtime
{
engine: require('catbox-redis'),
}]
});
new Hapi.Server({
connections: {
app: {},
compression: false,
load: {
maxHeapUsedBytes: 10,
maxRssBytes: 10,
maxEventLoopDelay: 10,
},
plugins: {
'some-plugin-name': {options: 'here'}
},
router: {
isCaseSensitive: false,
stripTrailingSlash: true,
},
routes: {}
}
})

View File

@@ -0,0 +1,43 @@
// From https://hapijs.com/api/16.1.1#serveroncriteria-listener
// From https://hapijs.com/api/16.1.1#server-events
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.event('test');
server.on('test', (update: Update) => console.log(update));
type Update = string;
var toSend: Update = 'hello';
server.emit('test', toSend);
server.on('log', (event, tags) => {
if (tags.error) {
console.log('Server error: ' + (event.data || 'unspecified'));
}
});
server.on('request', (request, event, tags) => {
if (tags.received) {
console.log('New request: ' + request.id);
}
});
server.on('request-error', (request, err) => {
console.log('Error response (500) sent for request: ' + request.id + ' because: ' + err.message);
});
server.on('response', (request) => {
console.log('Response sent for request: ' + request.id);
});
server.on('route', (route, connection, server) => {
console.log('New route added: ' + route.path);
});

View File

@@ -0,0 +1,14 @@
// From https://hapijs.com/api/16.1.1#serveroncecriteria-listener
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.event('test');
server.once('test', (update: Update) => console.log(update));
type Update = string;
var toSend: Update = 'hello';
server.emit('test', toSend);
server.emit('test', toSend); // Ignored

View File

@@ -0,0 +1,13 @@
// From https://hapijs.com/api/16.1.1#serverpathrelativeto
import * as Hapi from 'hapi';
var register: Hapi.PluginFunction<{}> = function (server, options, next) {
// Assuming the Inert plugin was registered previously
server.path(__dirname + '../static');
server.route({ path: '/file', method: 'GET', handler: { file: './test.html' } });
next();
};

View File

@@ -0,0 +1,15 @@
// From https://hapijs.com/api/16.1.1#serverplugins
import * as Hapi from 'hapi';
var registerFunction: Hapi.PluginFunction<{}> = function(server, options, next) {
server.expose('key', 'value');
server.plugins.example.key === 'value';
return next();
};
registerFunction.attributes = {
name: 'example'
};

View File

@@ -0,0 +1,10 @@
// From https://hapijs.com/api/16.1.1#serverrealm
import * as Hapi from 'hapi';
var registerFunction: Hapi.PluginFunction<{}> = function(server, options, next) {
console.log(server.realm.modifiers.route.prefix);
return next();
};

View File

@@ -0,0 +1,18 @@
// From https://hapijs.com/api/16.1.1#serverregisterplugins-options-callback
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.register({
register: require('plugin_name'),
options: {
message: 'hello'
}
}, (err) => {
if (err) {
console.log('Failed loading plugin');
}
});

View File

@@ -0,0 +1,12 @@
// From https://hapijs.com/api/16.1.1#serverrouteoptions
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.route({ method: 'GET', path: '/', handler: function (request, reply) { return reply('ok'); } });
server.route([
{ method: 'GET', path: '/1', handler: function (request, reply) { return reply('ok'); } },
{ method: 'GET', path: '/2', handler: function (request, reply) { return reply('ok'); } }
]);

View File

@@ -0,0 +1,11 @@
// From https://hapijs.com/api/16.1.1#serverselectlabels
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80, labels: ['a', 'b'] });
server.connection({ port: 8080, labels: ['a', 'c'] });
server.connection({ port: 8081, labels: ['b', 'c'] });
const a = server.select('a'); // 80, 8080
const ac = a.select('c'); // 8080

View File

@@ -0,0 +1,11 @@
// From https://hapijs.com/api/16.1.1#serversettings
import * as Hapi from 'hapi';
const server = new Hapi.Server({
app: {
key: 'value'
}
});
server.settings.app === { key: 'value' };

View File

@@ -0,0 +1,13 @@
// From https://hapijs.com/api/16.1.1#serverstartcallback
import * as Hapi from 'hapi';
import * as Hoek from 'hoek';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.start((err) => {
Hoek.assert(!err, err!);
console.log('Server started at: ' + server.info!.uri);
});

View File

@@ -0,0 +1,38 @@
// From https://hapijs.com/api/16.1.1#serverstatename-options
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
// Set cookie definition
server.state('session', {
ttl: 24 * 60 * 60 * 1000, // One day
isSecure: true,
path: '/',
encoding: 'base64json'
});
// Set state in route handler
const handler: Hapi.RouteHandler = function (request, reply) {
let session = request.state.session;
if (!session) {
session = { user: 'joe' };
}
session.last = Date.now();
return reply('Success').state('session', session);
};
// Example 2
server.on('request-internal', (request, event, tags) => {
if (tags.error && tags.state) {
console.error(event);
}
});

View File

@@ -0,0 +1,11 @@
// From https://hapijs.com/api/16.1.1#serverstopoptions-callback
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80 });
server.stop({ timeout: 60 * 1000 }, (err) => {
console.log('Server stopped');
});

View File

@@ -0,0 +1,9 @@
// From https://hapijs.com/api/16.1.1#servertablehost
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.connection({ port: 80, host: 'example.com' });
server.route({ method: 'GET', path: '/example', handler: function (request, reply) { return reply(); } });
const table = server.table();

View File

@@ -0,0 +1,6 @@
// From http://hapijs.com/api#serversettings
import * as Hapi from 'hapi';
const server = new Hapi.Server();
server.version === '8.0.0'

View File

@@ -6,7 +6,7 @@
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": false,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
@@ -17,6 +17,76 @@
},
"files": [
"index.d.ts",
"hapi-tests.ts"
"test/connection/table.ts",
"test/getting-started/01-creating-a-server.ts",
"test/getting-started/02-adding-routes.ts",
"test/getting-started/03-serving-static-content.ts",
"test/getting-started/04-using-plugins.ts",
"test/path/catch-all.ts",
"test/path/parameters.ts",
"test/plugins/options.ts",
"test/reply/continue.ts",
"test/reply/entity.ts",
"test/reply/redirect.ts",
"test/reply/reply.ts",
"test/reply/state_cookie.ts",
"test/request/event-types.ts",
"test/request/generate-response.ts",
"test/request/get-log.ts",
"test/request/log.ts",
"test/request/set-method.ts",
"test/request/set-url.ts",
"test/request/tail.ts",
"test/response/error-representation.ts",
"test/response/error.ts",
"test/response/events.ts",
"test/response/flow-control.ts",
"test/route/additional-options.ts",
"test/route/auth.ts",
"test/route/config.ts",
"test/route/handler.ts",
"test/route/prerequisites.ts",
"test/route/public-interface.ts",
"test/server/app.ts",
"test/server/auth.ts",
"test/server/bind.ts",
"test/server/cache.ts",
"test/server/connection-options.ts",
"test/server/connections.ts",
"test/server/decoder.ts",
"test/server/decorate.ts",
"test/server/dependency.ts",
"test/server/emit.ts",
"test/server/encoder.ts",
"test/server/event.ts",
"test/server/expose.ts",
"test/server/ext.ts",
"test/server/handler.ts",
"test/server/info.ts",
"test/server/initialize.ts",
"test/server/inject.ts",
"test/server/listener.ts",
"test/server/load.ts",
"test/server/log.ts",
"test/server/lookup.ts",
"test/server/match.ts",
"test/server/method.ts",
"test/server/methods.ts",
"test/server/mime.ts",
"test/server/new.ts",
"test/server/on.ts",
"test/server/once.ts",
"test/server/path.ts",
"test/server/plugins.ts",
"test/server/realm.ts",
"test/server/register.ts",
"test/server/route.ts",
"test/server/select.ts",
"test/server/settings.ts",
"test/server/start.ts",
"test/server/state.ts",
"test/server/stop.ts",
"test/server/table.ts",
"test/server/version.ts"
]
}

View File

@@ -1,15 +0,0 @@
{
"extends": "dtslint/dt.json",
"rules": {
"indent": [true, "tabs"],
// All TODOs
"ban-types": false,
"callable-types": false,
"interface-name": false,
"jsdoc-format": false,
"max-line-length": false,
"no-empty-interface": false,
"unified-signatures": false
}
}

View File

@@ -0,0 +1,114 @@
// Copied directly from 918608a5e007d925f4f60a275881057f07c12619 which seems to
// be the last author to work on v12.0
import * as Hapi from 'hapi';
// Create a server with a host and port
var server = new Hapi.Server();
server.connection(<Hapi.IServerConnectionOptions>{
host: "localhost",
port: 8000
});
// Add plugins
var plugin: any = {
register: function (plugin: Object, options: Object, next: Function) {
next();
}
};
plugin.register.attributes = {
name: "test",
version: "1.0.0"
};
// optional options parameter
server.register({}, function (err) {});
// optional options.routes.vhost parameter
server.register({}, { select: 'api', routes: { prefix: '/prefix' } }, function (err) {});
//server.pack.register(plugin, (err: Object) => {
// if (err) { throw err; }
//});
//server.pack.register([plugin], (err: Object) => {
// if (err) { throw err; }
//});
// Add server method
var add = function (a: number, b: number, next: (err: any, result?: any, ttl?: number) => void) {
next(null, a + b);
};
server.method("sum", add);//, { cache: { expiresIn: 2000 } });
server.methods["sum"](4, 5, (err: any, result: any) => {
console.log(result);
});
var addArray = function (array: Array<number>, next: (err: any, result?: any, ttl?: number) => void) {
var sum: number = 0;
array.forEach((item: number) => {
sum += item;
});
next(null, sum);
};
server.method("sumObj", addArray, {
//cache: { expiresIn: 2000 },
generateKey: (array: Array<number>) => {
return array.join(',');
}
});
server.methods["sumObj"]([5, 6], (err: any, result: any) => {
console.log(result);
});
// Add the route
server.route({
method: 'GET',
path: '/hello',
handler: function (request: Hapi.Request, reply: Function) {
reply('hello world');
}
});
server.route([{
method: 'GET',
path: '/hello2',
handler: function (request: Hapi.Request, reply: Function) {
reply('hello world2');
}
}]);
// config.validate parameters should be optional
server.route([{
method: 'GET',
path: '/hello2',
handler: function(request: Hapi.Request, reply: Function) {
reply('hello world2');
},
config: {
validate: {
}
}
}]);
// Should be able to chain reply options
server.route([{
method: 'GET',
path: '/chained-notation',
handler: function(request: Hapi.Request, reply: Hapi.IReply) {
reply('chained-notation')
.bytes(16)
.code(200)
.type('text/plain')
.header('X-Custom', 'some-value');
}
}]);
// Start the server
server.start();

2331
types/hapi/v12/index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": false,
"baseUrl": "../../",
"typeRoots": [
"../../"
],
"types": [],
"paths": {
"hapi": [
"hapi/v12"
]
},
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"hapi-tests.ts"
]
}

2497
types/hapi/v15/index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": false,
"baseUrl": "../../",
"typeRoots": [
"../../"
],
"types": [],
"paths": {
"hapi": [
"hapi/v15"
]
},
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"hapi-tests.ts"
]
}

View File

@@ -5,10 +5,8 @@
import * as hapi from 'hapi';
declare module 'hapi' {
interface IFileHandler {
/** path - a path string or function as described above (required). */
path: string | IRequestHandler<string>;
declare namespace inert {
export interface ReplyFileHandlerOptions {
/** confine - serve file relative to this directory and returns 403 Forbidden if the path resolves outside the confine directory. Defaults to true which uses the relativeTo route option as the confine. Set to false to disable this security feature. */
confine?: boolean;
/** filename - an optional filename to specify if sending a 'Content-Disposition' header, defaults to the basename of path */
@@ -37,13 +35,18 @@ declare module 'hapi' {
end?: number;
}
interface IDirectoryHandler {
export interface FileHandlerRouteObject extends ReplyFileHandlerOptions {
/** path - a path string or function as described above (required). */
path: string | hapi.RequestHandler<string>;
}
export interface DirectoryHandlerRouteObject {
/** path - (required) the directory root path (relative paths are resolved based on the route files configuration). Value can be:
* * a single path string used as the prefix for any resources requested by appending the request path parameter to the provided string.
* * an array of path strings. Each path will be attempted in order until a match is found (by following the same process as the single path string).
* * a function with the signature function(request) which returns the path string or an array of path strings. If the function returns an error, the error is passed back to the client in the response.
*/
path: string | string[] | IRequestHandler<string | string[] | Error>;
path: string | string[] | hapi.RequestHandler<string | string[] | Error>;
/** index - optional boolean|string|string[], determines if an index file will be served if found in the folder when requesting a directory. The given string or strings specify the name(s) of the index file to look for. If true, looks for 'index.html'. Any falsy value disables index file lookup. Defaults to true. */
index?: boolean | string | string[];
/** listing - optional boolean, determines if directory listing is generated when a directory is requested without an index document. Defaults to false. */
@@ -65,23 +68,48 @@ declare module 'hapi' {
defaultExtension?: string;
}
interface IRouteConfiguration {
/**
* inert accepts the following registration options
* @see {@link https://github.com/hapijs/inert#registration-options}
*/
interface OptionalRegistrationOptions {
/**
* sets the maximum number of file etag hash values stored in the etags cache. Defaults to 10000.
*/
etagsCacheMaxSize?: number;
}
}
declare module 'hapi' {
interface RouteHandlerPlugins {
/**
* The file handler
*
* Generates a static file endpoint for serving a single file. file can be set to:
* * a relative or absolute file path string (relative paths are resolved based on the route files configuration).
* * a function with the signature function(request) which returns the relative or absolute file path.
* * an object with one or more of the following options:
* * an object with one or more of the following options @see IFileHandler
* @see {@link https://github.com/hapijs/inert#the-file-handler}
*/
file?: string | IRequestHandler<string> | IFileHandler;
file?: string | RequestHandler<string> | inert.FileHandlerRouteObject;
/**
* The directory handler
*
* Generates a directory endpoint for serving static content from a directory. Routes using the directory handler must include a path parameter at the end of the path string (e.g. /path/to/somewhere/{param} where the parameter name does not matter). The path parameter can use any of the parameter options (e.g. {param} for one level files only, {param?} for one level files or the directory root, {param*} for any level, or {param*3} for a specific level). If additional path parameters are present, they are ignored for the purpose of selecting the file system resource. The directory handler is an object with the following options:
* @see {@link https://github.com/hapijs/inert#the-directory-handler}
*/
directory?: IDirectoryHandler;
directory?: inert.DirectoryHandlerRouteObject;
}
interface Base_Reply {
/**
* Transmits a file from the file system. The 'Content-Type' header defaults to the matching mime type based on filename extension.
* @see {@link https://github.com/hapijs/inert#replyfilepath-options}
*/
file: (path: string, options?: inert.ReplyFileHandlerOptions) => Response;
}
}
declare var inert: hapi.PluginFunction<inert.OptionalRegistrationOptions>;
export = inert;

View File

@@ -1,36 +1,132 @@
import * as HapiES6 from 'hapi';
import * as InertES6 from 'inert';
// Copied from: https://github.com/hapijs/inert#examples
const server = new HapiES6.Server({});
server.register(InertES6, () => {});
/// <reference types="node" />
import Path = require('path');
import Hapi = require('hapi');
import Inert = require('inert');
const server = new Hapi.Server({
connections: {
routes: {
files: {
relativeTo: Path.join(__dirname, 'public')
}
}
}
});
server.connection({ port: 3000 });
server.register(Inert, () => {});
// added in addition to code from docs
const options: Inert.OptionalRegistrationOptions = {etagsCacheMaxSize: 400};
server.register({
register: Inert,
options,
}, (err) => {});
// added in addition to code from docs
server.register({
register: Inert,
once: true,
}, (err) => {});
server.route({
method: 'GET',
path: '/{param*}',
handler: {
directory: {
path: '.',
redirectToSlash: true,
index: true
}
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info!.uri);
});
// https://github.com/hapijs/inert#serving-a-single-file
server.route({
method: 'GET',
path: '/{path*}',
handler: {
file: 'page.html'
}
});
// https://github.com/hapijs/inert#customized-file-response
server.route({
method: 'GET',
path: '/file',
handler: function (request, reply) {
let path = 'plain.txt';
if (request.headers['x-magic'] === 'sekret') {
path = 'awesome.png';
}
return reply.file(path).vary('x-magic');
}
});
const handler: Hapi.ServerExtRequestHandler = function (request, reply) {
const response = request.response!;
if (response.isBoom &&
response.output!.statusCode === 404) {
return reply.file('404.html').code(404);
}
return reply.continue();
}
server.ext('onPostHandler', handler);
// additional code added in addition to doc example code
var file: Inert.FileHandlerRouteObject = {
path: '',
confine: true,
};
var directory: Inert.DirectoryHandlerRouteObject = {
path: '',
listing: true
};
file = {
path: '',
confine: true,
};
server.route({
path: '',
method: 'GET',
file: {
path: '',
confine: true,
handler: {
file,
directory: {
path: function(){
if(Math.random() > 0.5) {
return '';
}
else if(Math.random() > 0) {
return [''];
}
return new Error('');
},
BAD_listing: true, // TODO change typings to make this error
},
},
directory: {
path: '',
listing: true
}
config: { files: { relativeTo: __dirname } }
})
var fileHandler: HapiES6.IFileHandler = {
path: '',
confine: true,
}
var directoryHandler: HapiES6.IDirectoryHandler = {
path: function(){
if(Math.random() > 0.5) {
return '';
}
else if(Math.random() > 0) {
return [''];
}
return new Error('');
},
listing: true,
}

21
types/mime-db/index.d.ts vendored Normal file
View File

@@ -0,0 +1,21 @@
// Type definitions for mime-db 1.27
// Project: https://github.com/jshttp/mime-db
// Definitions by: AJP <https://github.com/AJamesPhillips>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
/**
* Data Structure
* If unknown, every property could be undefined.
* @see {@link https://github.com/jshttp/mime-db#data-structure}
*/
export interface DataStructure {
/** where the mime type is defined. If not set, it's probably a custom media type. */
source?: string;
/** known extensions associated with this mime type. */
extensions?: string[];
/** whether a file of this type can be gzipped. */
compressible?: boolean;
/** the default charset associated with this type, if any. */
charset?: string;
}

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts"
]
}

27
types/mimos/index.d.ts vendored Normal file
View File

@@ -0,0 +1,27 @@
// Type definitions for mimos 3.0
// Project: https://github.com/hapijs/mimos
// Definitions by: AJP <https://github.com/AJamesPhillips>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
import {DataStructure as MimeDbDataStructure} from 'mime-db';
/**
*
* @see {@link https://github.com/hapijs/mimos#new-mimosoptions}
*/
export interface MimosOptions {
/**
* an object hash that is merged into the built in mime information specified here {@link https://github.com/jshttp/mime-db}. Each key value pair represents a single mime object. Each override value should follow this schema:
* * the key is the lower-cased correct mime-type. (Ex. "application/javascript").
* * the value should an object @see MimosOptionsValue
*/
override: {[index: string]: MimosOptionsValue};
}
export interface MimosOptionsValue extends MimeDbDataStructure {
/** specify the type value of result objects, defaults to key. See the example below for more clarification. */
type?: string;
/** method with signature function(mime) when this mime type is found in the database, this function will run. This allows you make customizations to mime based on developer criteria. */
predicate?: (mime: MimosOptionsValue) => MimosOptionsValue;
}

21
types/mimos/tsconfig.json Normal file
View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts"
]
}

54
types/nes/client.d.ts vendored Normal file
View File

@@ -0,0 +1,54 @@
// Type definitions for nes 6.4.2
// Project: https://github.com/hapijs/nes
// Definitions by: Ivo Stratev <https://github.com/NoHomey>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
declare class Client {
constructor(url: string, options?: Client.ClientOptions);
onError: (err: any) => void;
onConnect: () => void;
onDisconnect: () => void;
onUpdate: (message: any) => void;
connect(options: Client.ClientConnectOptions, callback: (err?: any) => void): void;
connect(callback: (err?: any) => void): void;
disconnect(): void;
id: any; // can be `null | number` but also the "socket" value from websocket message data.
request(options: string | Client.ClientRequestOptions, callback: (err: any, payload: any, statusCode?: number, headers?: Object) => void): void;
message(message: any, callback: (err: any, message: any) => void): void;
subscribe(path: string, handler: Client.Handler, callback: (err?: any) => void): void;
unsubscribe(path: string, handler: Client.Handler, callback: (err?: any) => void): void;
subscriptions(): string[];
overrideReconnectionAuth(auth: any): void;
}
declare namespace Client {
interface Handler {
(message: any, flags: Client.ClientSubscribeFlags): void;
}
interface ClientOptions {
ws?: any;
timeout?: number | boolean;
}
interface ClientConnectOptions {
auth?: any;
delay?: number;
maxDelay?: number;
retries?: number;
timeout?: number;
}
interface ClientRequestOptions {
path: string;
method?: string;
headers?: Object;
payload?: any;
}
interface ClientSubscribeFlags {
revoked?: boolean;
}
}
export = Client;

Some files were not shown because too many files have changed in this diff Show More