Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

celebrate

Package Overview
Dependencies
Maintainers
1
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

celebrate - npm Package Compare versions

Comparing version 12.0.0 to 12.0.1

2

lib/index.d.ts

@@ -63,3 +63,3 @@ import { ErrorRequestHandler, RequestHandler } from 'express';

*/
export declare function celebrate(schema: SchemaOptions, joiOptions?: ValidationOptions, opts?: CelebrateOptions): RequestHandler;
export declare function celebrate(requestRules: SchemaOptions, joiOpts?: ValidationOptions, opts?: CelebrateOptions): RequestHandler;

@@ -66,0 +66,0 @@ /**

@@ -5,6 +5,6 @@ const Assert = require('assert');

const {
middlewareSchema,
celebrateSchema,
sourceSchema,
optSchema,
CELEBRATEERROROPTSSCHEMA,
CELEBRATEOPTSSCHEMA,
REQUESTSCHEMA,
SEGMENTSCHEMA,
} = require('./schema');

@@ -29,75 +29,90 @@ const { segments } = require('./constants');

internals.validateSource = (segment, spec) => ({
internals.validateSegment = (segment) => (spec, {
config,
req,
}) => new Promise((resolve, reject) => {
spec.validateAsync(req[segment], config).then(({ value }) => {
resolve({
value,
segment,
});
}).catch((e) => reject(new internals.CelebrateError(
e,
segment,
internals.DEFAULT_ERROR_ARGS,
)));
});
}) => spec.validateAsync(req[segment], config);
internals.maybeValidateBody = (segment, spec) => (opts) => {
const method = opts.req.method.toLowerCase();
internals.maybeValidateBody = (segment) => {
const validateBody = internals.validateSegment(segment);
return (spec, opts) => {
const method = opts.req.method.toLowerCase();
if (method === 'get' || method === 'head') {
return Promise.resolve({
value: null,
segment,
});
}
if (method === 'get' || method === 'head') {
// This resolve is to emulate how Joi validates when there isn't an error. I'm doing this to
// standardize the resolve value.
return Promise.resolve({
value: null,
});
}
return internals.validateSource(segment, spec)(opts);
return validateBody(spec, opts);
};
};
// Map of segments to validation functions.
// The key order is the order validations will run in.
internals.REQ_VALIDATIONS = new Map([
[segments.HEADERS, internals.validateSource],
[segments.PARAMS, internals.validateSource],
[segments.QUERY, internals.validateSource],
[segments.COOKIES, internals.validateSource],
[segments.SIGNEDCOOKIES, internals.validateSource],
[segments.BODY, internals.maybeValidateBody],
]);
internals.REQ_VALIDATIONS = [
{
segment: segments.HEADERS,
validate: internals.validateSegment(segments.HEADERS),
},
{
segment: segments.PARAMS,
validate: internals.validateSegment(segments.PARAMS),
},
{
segment: segments.QUERY,
validate: internals.validateSegment(segments.QUERY),
},
{
segment: segments.COOKIES,
validate: internals.validateSegment(segments.COOKIES),
},
{
segment: segments.SIGNEDCOOKIES,
validate: internals.validateSegment(segments.SIGNEDCOOKIES),
},
{
segment: segments.BODY,
validate: internals.maybeValidateBody(segments.BODY),
},
];
// ⚠️ steps is mutated in this function
internals.check = (steps, opts) => {
const validateFn = steps.shift();
if (validateFn) {
return validateFn(opts).then(({ value, segment }) => {
// Lifted this idea from https://bit.ly/2vf3Xe0
internals.check = (steps, requestRules, opts) => steps.reduce((chain, {
validate: stepValidate,
segment: stepSegment,
}) => chain.then(() => {
// If there isn't a schema set up for this segment, early return
const currentSegmentSchema = requestRules.get(stepSegment);
if (!currentSegmentSchema) {
return Promise.resolve(null);
}
return stepValidate(currentSegmentSchema, opts)
.then(({ value }) => {
if (value != null) {
Object.defineProperty(opts.req, segment, {
Object.defineProperty(opts.req, stepSegment, {
value,
});
}
return internals.check(steps, opts);
return null;
})
.catch((e) => {
throw new internals.CelebrateError(
e,
stepSegment,
internals.DEFAULT_ERROR_ARGS,
);
});
}
// If we get here, all the promises have resolved
// and so we have a final resolve to end the recursion
return Promise.resolve(null);
};
}), Promise.resolve(null));
exports.celebrate = (schema, joiOpts = {}, opts = {}) => {
Joi.assert(schema, middlewareSchema);
Joi.assert(opts, celebrateSchema);
exports.celebrate = (_requestRules, joiOpts = {}, opts = {}) => {
Joi.assert(_requestRules, REQUESTSCHEMA);
Joi.assert(opts, CELEBRATEOPTSSCHEMA);
// Compile all schemas in advance and only do it once
const requestRules = Object.entries(_requestRules)
.reduce((memo, [key, value]) => memo.set(key, Joi.compile(value)), new Map());
const middleware = (req, res, next) => {
// We want a fresh copy of steps since `internals.check` mutates the array
const steps = [];
internals.REQ_VALIDATIONS.forEach((validateFn, segment) => {
const spec = schema[segment];
if (spec) {
steps.push(validateFn(segment, Joi.compile(spec)));
}
});
const finalConfig = opts.reqContext ? {
const config = opts.reqContext ? {
...joiOpts,

@@ -111,11 +126,10 @@ context: req,

return internals.check(steps, {
config: finalConfig,
// This promise is not part of the public API; it's only here to make the tests cleaner
return internals.check(internals.REQ_VALIDATIONS, requestRules, {
config,
req,
})
.then(next)
.catch(next);
}).then(next).catch(next);
};
middleware._schema = schema;
middleware._schema = _requestRules;

@@ -164,4 +178,4 @@ return middleware;

Assert.ok(error && error.isJoi, '"error" must be a Joi error');
Joi.assert(segment, sourceSchema);
Joi.assert(opts, optSchema);
Joi.assert(segment, SEGMENTSCHEMA);
Joi.assert(opts, CELEBRATEERROROPTSSCHEMA);
return new internals.CelebrateError(error, segment, opts);

@@ -168,0 +182,0 @@ };

const Joi = require('@hapi/joi');
const { segments } = require('./constants');
exports.middlewareSchema = Joi.object({
exports.REQUESTSCHEMA = Joi.object({
[segments.HEADERS]: Joi.any(),

@@ -13,7 +13,7 @@ [segments.PARAMS]: Joi.any(),

exports.celebrateSchema = Joi.object({
exports.CELEBRATEOPTSSCHEMA = Joi.object({
reqContext: Joi.boolean(),
});
exports.sourceSchema = Joi.string().valid(
exports.SEGMENTSCHEMA = Joi.string().valid(
segments.HEADERS,

@@ -27,4 +27,4 @@ segments.PARAMS,

exports.optSchema = Joi.object({
exports.CELEBRATEERROROPTSSCHEMA = Joi.object({
celebrated: Joi.boolean().default(false),
});
{
"name": "celebrate",
"version": "12.0.0",
"version": "12.0.1",
"description": "A joi validation middleware for Express.",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -50,3 +50,3 @@ [![celebrate](https://github.com/arb/celebrate/raw/master/images/logo.svg?sanitize=1)](https://www.npmjs.org/package/celebrate)

- [`Segments`](#segments)
- [`CelebrateError(err, segment, [opts])`](#celebrateerrorerr-segment-opts)
- [`CelebrateError(error, segment, [opts])`](#celebrateerrorerror-segment-opts)
- [`isCelebrate(err)`](#iscelebrateerr)

@@ -121,4 +121,4 @@ - [Validation Order](#validation-order)

- `schema` - an `object` where `key` can be one of the values from [`Segments`](#segments) and the `value` is a [joi](https://github.com/hapijs/joi/blob/master/API.md) validation schema. Only the keys specified will be validated against the incoming request object. If you omit a key, that part of the `req` object will not be validated. A schema must contain at least one valid key.
- `[joiOptions]` - optional `object` containing joi [options](https://github.com/hapijs/joi/blob/master/API.md#anyvalidatevalue-options) that are passed directly into the `validate` function. Defaults to `{ warnings: true }`.
- `requestRules` - an `object` where `key` can be one of the values from [`Segments`](#segments) and the `value` is a [joi](https://github.com/hapijs/joi/blob/master/API.md) validation schema. Only the keys specified will be validated against the incoming request object. If you omit a key, that part of the `req` object will not be validated. A schema must contain at least one valid key.
- `[joiOpts]` - optional `object` containing joi [options](https://github.com/hapijs/joi/blob/master/API.md#anyvalidatevalue-options) that are passed directly into the `validate` function. Defaults to `{ warnings: true }`.
- `[opts]` - an optional `object` with the following keys. Defaults to `{}`.

@@ -154,3 +154,3 @@ - `reqContext` - `bool` value that instructs joi to use the incoming `req` object as the `context` value during joi validation. If set, this will trump the value of `joiOptions.context`. This is useful if you want to validate part of the request object against another part of the request object. See the tests for more details.

### `CelebrateError(err, segment, [opts])`
### `CelebrateError(error, segment, [opts])`

@@ -157,0 +157,0 @@ A factory function for creating celebrate errors.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc