Skip to content

Commit

Permalink
Don't import Joi typings
Browse files Browse the repository at this point in the history
  • Loading branch information
kanongil committed Apr 9, 2024
1 parent 200a5af commit d30a243
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 67 deletions.
2 changes: 1 addition & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -2712,7 +2712,7 @@ Registers a server validation module used to compile raw validation rules into v

- `validator` - the validation module (e.g. **joi**).

Return value: none.
Return value: The `server` object.

Note: the validator is only used when validation rules are not pre-compiled schemas. When a validation rules is a function or schema object, the rule is used as-is and the validator is not used. When setting a validator inside a plugin, the validator is only applied to routes set up by the plugin and plugins registered by it.

Expand Down
5 changes: 4 additions & 1 deletion lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,10 @@ internals.routeBase = Validate.object({
failAction: internals.failAction,
errorFields: Validate.object(),
options: Validate.object().default(),
validator: Validate.object()
validator: Validate.object({
compile: Validate.function().required()
})
.unknown()
})
.default()
});
Expand Down
3 changes: 1 addition & 2 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const Request = require('./request');
const Response = require('./response');
const Route = require('./route');
const Toolkit = require('./toolkit');
const Validation = require('./validation');


const internals = {
Expand Down Expand Up @@ -128,7 +127,7 @@ exports = module.exports = internals.Core = class {
this._initializeCache();

if (this.settings.routes.validate.validator) {
this.validator = Validation.validator(this.settings.routes.validate.validator);
this.validator = this.settings.routes.validate.validator;
}

this.listener = this._createListener();
Expand Down
2 changes: 1 addition & 1 deletion lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ internals.config = function (chain) {

let config = chain[0];
for (const item of chain) {
config = Hoek.applyToDefaults(config, item, { shallow: ['bind', 'validate.headers', 'validate.payload', 'validate.params', 'validate.query', 'validate.state'] });
config = Hoek.applyToDefaults(config, item, { shallow: ['bind', 'validate.headers', 'validate.payload', 'validate.params', 'validate.query', 'validate.state', 'validate.validator'] });
}

return config;
Expand Down
5 changes: 4 additions & 1 deletion lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,12 @@ internals.Server = class {

validator(validator) {

Hoek.assert(typeof validator?.compile === 'function', 'Validator must have a compile() method');
Hoek.assert(!this.realm.validator, 'Validator already set');

this.realm.validator = Validation.validator(validator);
this.realm.validator = validator;

return this;
}

start() {
Expand Down
73 changes: 41 additions & 32 deletions lib/types/route.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@

import { ObjectSchema, ValidationOptions, SchemaMap, Schema } from 'joi';

import { PluginSpecificConfiguration} from './plugin';
import { MergeType, ReqRef, ReqRefDefaults, MergeRefs, AuthMode } from './request';
import { ContentDecoders, ContentEncoders, RouteRequestExtType, RouteExtObject, Server } from './server';
import { ContentDecoders, ContentEncoders, RouteRequestExtType, RouteExtObject, Server, Validation, ServerApplicationState } from './server';
import { Lifecycle, Json, HTTP_METHODS } from './utils';

/**
Expand Down Expand Up @@ -363,26 +361,24 @@ export interface RouteOptionsPreObject<Refs extends ReqRef = ReqRefDefaults> {
failAction?: Lifecycle.FailAction | undefined;
}

export type ValidationObject = SchemaMap;

/**
* * true - any query parameter value allowed (no validation performed). false - no parameter value allowed.
* * a joi validation object.
* * a validation function using the signature async function(value, options) where:
* * * value - the request.* object containing the request parameters.
* * * options - options.
*/
export type RouteOptionsResponseSchema =
boolean
| ValidationObject
| Schema
| ((value: object | Buffer | string, options: ValidationOptions) => Promise<any>);
export type RouteOptionsSchema<V extends Validation.Compiler | null, T extends Validation.ValidatedReqProperties | null> =
boolean
| Validation.ExtractedSchema<V>
| Validation.Validator
| Validation.DirectValidator<T>;

/**
* Processing rules for the outgoing response.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsresponse)
*/
export interface RouteOptionsResponse {
export interface RouteOptionsResponse<V extends Validation.Compiler | null> {
/**
* @default 204.
* The default HTTP status code when the payload is considered empty. Value can be 200 or 204. Note that a 200 status code is converted to a 204 only at the time of response transmission (the
Expand Down Expand Up @@ -411,7 +407,7 @@ export interface RouteOptionsResponse {
* custom validation function is defined via schema or status then options can an arbitrary object that will be passed to this function as the second argument.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsresponseoptions)
*/
options?: ValidationOptions | undefined; // TODO needs validation
options?: Validation.ExtractedOptions<V> | undefined;

/**
* @default true.
Expand Down Expand Up @@ -440,15 +436,15 @@ export interface RouteOptionsResponse {
* output.payload. If an error is thrown, the error is processed according to failAction.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsresponseschema)
*/
schema?: RouteOptionsResponseSchema | undefined;
schema?: RouteOptionsSchema<V, null> | undefined;

/**
* @default none.
* Validation schemas for specific HTTP status codes. Responses (excluding errors) not matching the listed status codes are validated using the default schema.
* status is set to an object where each key is a 3 digit HTTP status code and the value has the same definition as schema.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsresponsestatus)
*/
status?: Record<string, RouteOptionsResponseSchema> | undefined;
status?: Record<string, RouteOptionsSchema<V, null>> | undefined;

/**
* The default HTTP status code used to set a response error when the request is closed or aborted before the
Expand Down Expand Up @@ -558,7 +554,7 @@ export type RouteOptionsSecure = boolean | RouteOptionsSecureObject;
* Request input validation rules for various request components.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsvalidate)
*/
export interface RouteOptionsValidate {
export interface RouteOptionsValidate<V extends Validation.Compiler | null> {
/**
* @default none.
* An optional object with error fields copied into every validation error response.
Expand All @@ -580,7 +576,7 @@ export interface RouteOptionsValidate {
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsvalidateheaders)
* @default true
*/
headers?: RouteOptionsResponseSchema | undefined;
headers?: RouteOptionsSchema<V, 'headers'> | undefined;

/**
* An options object passed to the joi rules or the custom validation methods. Used for setting global options such as stripUnknown or abortEarly (the complete list is available here).
Expand All @@ -593,7 +589,7 @@ export interface RouteOptionsValidate {
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsvalidateparams)
* @default true
*/
options?: ValidationOptions | object | undefined;
options?: Validation.ExtractedOptions<V> | undefined;

/**
* Validation rules for incoming request path parameters, after matching the path against the route, extracting any parameters, and storing them in request.params, where:
Expand All @@ -607,7 +603,7 @@ export interface RouteOptionsValidate {
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsvalidateparams)
* @default true
*/
params?: RouteOptionsResponseSchema | undefined;
params?: RouteOptionsSchema<V, 'params'> | undefined;

/**
* Validation rules for incoming request payload (request body), where:
Expand All @@ -617,7 +613,7 @@ export interface RouteOptionsValidate {
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsvalidatepayload)
* @default true
*/
payload?: RouteOptionsResponseSchema | undefined;
payload?: RouteOptionsSchema<V, 'payload'> | undefined;

/**
* Validation rules for incoming request URI query component (the key-value part of the URI between '?' and '#'). The query is parsed into its individual key-value pairs, decoded, and stored in
Expand All @@ -628,17 +624,23 @@ export interface RouteOptionsValidate {
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsvalidatequery)
* @default true
*/
query?: RouteOptionsResponseSchema | undefined;
query?: RouteOptionsSchema<V, 'query'> | undefined;

/**
* Validation rules for incoming cookies.
* The cookie header is parsed and decoded into the request.state prior to validation.
* @default true
*/
state?: RouteOptionsResponseSchema | undefined;
state?: RouteOptionsSchema<V, 'state'> | undefined;

/**
* Sets a server validation module used to compile raw validation rules into validation schemas (e.g. **joi**).
* @default null
*/
validator?: V | null;
}

export interface CommonRouteProperties<Refs extends ReqRef = ReqRefDefaults> {
export interface CommonRouteProperties<Refs extends ReqRef = ReqRefDefaults, V extends Validation.Compiler | null = null> {
/**
* Application-specific route configuration state. Should not be used by plugins which should use options.plugins[name] instead.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsapp)
Expand Down Expand Up @@ -812,7 +814,7 @@ export interface CommonRouteProperties<Refs extends ReqRef = ReqRefDefaults> {
* Processing rules for the outgoing response.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsresponse)
*/
response?: RouteOptionsResponse | undefined;
response?: RouteOptionsResponse<V> | undefined;

/**
* @default false (security headers disabled).
Expand Down Expand Up @@ -864,7 +866,7 @@ export interface CommonRouteProperties<Refs extends ReqRef = ReqRefDefaults> {
* Request input validation rules for various request components.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsvalidate)
*/
validate?: RouteOptionsValidate | undefined;
validate?: RouteOptionsValidate<V> | undefined;
}

export interface AccessScopes {
Expand All @@ -884,15 +886,15 @@ export interface AuthSettings {
access?: AccessSetting[] | undefined;
}

export interface RouteSettings<Refs extends ReqRef = ReqRefDefaults> extends CommonRouteProperties<Refs> {
export interface RouteSettings<Refs extends ReqRef = ReqRefDefaults, V extends Validation.Compiler | null = null> extends CommonRouteProperties<Refs, V> {
auth?: AuthSettings | undefined;
}

/**
* Each route can be customized to change the default behavior of the request lifecycle.
* For context [See docs](https://github.com/hapijs/hapi/blob/master/API.md#route-options)
*/
export interface RouteOptions<Refs extends ReqRef = ReqRefDefaults> extends CommonRouteProperties<Refs> {
export interface RouteOptions<Refs extends ReqRef = ReqRefDefaults, V extends Validation.Compiler | null = null> extends CommonRouteProperties<Refs, V> {
/**
* Route authentication configuration. Value can be:
* false to disable authentication if a default strategy is set.
Expand All @@ -913,10 +915,17 @@ export interface RulesInfo {
vhost: string;
}

export interface RulesOptions<Refs extends ReqRef = ReqRefDefaults> {
validate: {
schema?: ObjectSchema<MergeRefs<Refs>['Rules']> | Record<keyof MergeRefs<Refs>['Rules'], Schema> | undefined;
options?: ValidationOptions | undefined;
export interface JoiLikeSchema {
validate(value: unknown, options: Record<string, any>): { value: any } | { error: any };
}

export interface RulesOptions<V extends Validation.Compiler | null> {
validate: V extends null ? {
schema: JoiLikeSchema;
options?: Record<string, any> | undefined;
} : {
schema: Validation.ExtractedSchema<V>;
options?: Validation.ExtractedOptions<V> | undefined;
};
}

Expand All @@ -941,7 +950,7 @@ type RouteDefMethods = Exclude<HTTP_METHODS | Lowercase<HTTP_METHODS>, 'HEAD' |
* * rules - route custom rules object. The object is passed to each rules processor registered with server.rules(). Cannot be used if route.options.rules is defined.
* For context [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-serverrouteroute)
*/
export interface ServerRoute<Refs extends ReqRef = ReqRefDefaults> {
export interface ServerRoute<Refs extends ReqRef = ReqRefDefaults, V extends Validation.Compiler | null = null> {
/**
* (required) the absolute path used to match incoming requests (must begin with '/'). Incoming requests are compared to the configured paths based on the server's router configuration. The path
* can include named parameters enclosed in {} which will be matched against literal values in the request as described in Path parameters. For context [See
Expand Down Expand Up @@ -971,7 +980,7 @@ export interface ServerRoute<Refs extends ReqRef = ReqRefDefaults> {
* additional route options. The options value can be an object or a function that returns an object using the signature function(server) where server is the server the route is being added to
* and this is bound to the current realm's bind option.
*/
options?: RouteOptions<Refs> | ((server: Server) => RouteOptions<Refs>) | undefined;
options?: RouteOptions<Refs, V> | ((server: Server<ServerApplicationState, V>) => RouteOptions<Refs, V>) | undefined;

/**
* route custom rules object. The object is passed to each rules processor registered with server.rules(). Cannot be used if route.options.rules is defined.
Expand Down
1 change: 1 addition & 0 deletions lib/types/server/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './methods';
export * from './options';
export * from './server';
export * from './state';
export * from './validation';
6 changes: 4 additions & 2 deletions lib/types/server/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import * as https from 'https';
import { MimosOptions } from '@hapi/mimos';

import { PluginSpecificConfiguration } from '../plugin';
import { ReqRefDefaults } from '../request';
import { RouteOptions } from '../route';
import { CacheProvider, ServerOptionsCache } from './cache';
import { SameSitePolicy } from './state';
import { Validation } from './validation';

export interface ServerOptionsCompression {
minBytes: number;
Expand All @@ -25,7 +27,7 @@ export interface ServerOptionsApp {
* All options are optionals.
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-server-options)
*/
export interface ServerOptions {
export interface ServerOptions<V extends Validation.Compiler | null> {
/**
* @default '0.0.0.0' (all available network interfaces).
* Sets the hostname or IP address the server will listen on. If not configured, defaults to host if present, otherwise to all available network interfaces. Set to '127.0.0.1' or 'localhost' to
Expand Down Expand Up @@ -194,7 +196,7 @@ export interface ServerOptions {
* @default none.
* A route options object used as the default configuration for every route.
*/
routes?: RouteOptions | undefined;
routes?: RouteOptions<ReqRefDefaults, V> | undefined;

/**
* Default value:
Expand Down
Loading

0 comments on commit d30a243

Please sign in to comment.