Skip to content

Commit

Permalink
Don't use Symbol internally
Browse files Browse the repository at this point in the history
Fixes #813
  • Loading branch information
gustavohenke committed Dec 29, 2019
1 parent 96eaea6 commit 303b5eb
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 38 deletions.
4 changes: 2 additions & 2 deletions src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ export interface Request {
query?: Record<string, any>;
}

export const contextsSymbol = Symbol('express-validator#contexts');
export const contextsKey = 'express-validator#contexts';

export interface InternalRequest extends Request {
[contextsSymbol]?: ReadonlyContext[];
[contextsKey]?: ReadonlyContext[];
}

export type Middleware = (req: Request, res: any, next: (err?: any) => void) => void;
Expand Down
14 changes: 7 additions & 7 deletions src/chain/context-runner-impl.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Context } from '../context';
import { FieldInstance, InternalRequest, ValidationHalt, contextsSymbol } from '../base';
import { FieldInstance, InternalRequest, ValidationHalt, contextsKey } from '../base';
import { ContextBuilder } from '../context-builder';
import { ContextItem } from '../context-items';
import { ContextRunnerImpl } from './context-runner-impl';
Expand Down Expand Up @@ -127,20 +127,20 @@ it('rethrows unexpected errors', async () => {
expect(item1).toHaveBeenCalled();
});

it('concats to req[contextsSymbol]', async () => {
it('concats to req[contextsKey]', async () => {
const req: InternalRequest = {};
const context1 = await contextRunner.run(req);
const context2 = await contextRunner.run(req);

expect(req[contextsSymbol]).toHaveLength(2);
expect(req[contextsSymbol]).toEqual([context1, context2]);
expect(req[contextsKey]).toHaveLength(2);
expect(req[contextsKey]).toEqual([context1, context2]);
});

it('does not concat to req[contextsSymbol] with saveContext: false option', async () => {
it('does not concat to req[contextsKey] with saveContext: false option', async () => {
const req: InternalRequest = {};
const context1 = await contextRunner.run(req);
await contextRunner.run(req, { saveContext: false });

expect(req[contextsSymbol]).toHaveLength(1);
expect(req[contextsSymbol]).toEqual([context1]);
expect(req[contextsKey]).toHaveLength(1);
expect(req[contextsKey]).toEqual([context1]);
});
4 changes: 2 additions & 2 deletions src/chain/context-runner-impl.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SelectFields, selectFields as baseSelectFields } from '../select-fields';
import { InternalRequest, Request, ValidationHalt, contextsSymbol } from '../base';
import { InternalRequest, Request, ValidationHalt, contextsKey } from '../base';
import { ContextBuilder } from '../context-builder';
import { ContextRunner } from './context-runner';

Expand Down Expand Up @@ -44,7 +44,7 @@ export class ContextRunnerImpl implements ContextRunner {

if (options.saveContext === undefined || options.saveContext) {
const internalReq = req as InternalRequest;
internalReq[contextsSymbol] = (internalReq[contextsSymbol] || []).concat(context);
internalReq[contextsKey] = (internalReq[contextsKey] || []).concat(context);
}

return context;
Expand Down
4 changes: 2 additions & 2 deletions src/matched-data.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as _ from 'lodash';
import { FieldInstance, InternalRequest, Location, Request, contextsSymbol } from './base';
import { FieldInstance, InternalRequest, Location, Request, contextsKey } from './base';
import { Context } from './context';

interface FieldInstanceBag {
Expand All @@ -23,7 +23,7 @@ export function matchedData(
const validityFilter = createValidityFilter(options.onlyValidData);
const locationFilter = createLocationFilter(options.locations);

return _(internalReq[contextsSymbol])
return _(internalReq[contextsKey])
.flatMap(fieldExtractor)
.filter(validityFilter)
.map(field => field.instance)
Expand Down
10 changes: 5 additions & 5 deletions src/middlewares/check.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ContextHandlerImpl, ContextRunnerImpl, SanitizersImpl, ValidatorsImpl } from '../chain';
import { InternalRequest, contextsSymbol } from '../base';
import { InternalRequest, contextsKey } from '../base';
import { check } from './check';

it('has context handler methods', () => {
Expand Down Expand Up @@ -38,13 +38,13 @@ it('does not share contexts between chain runs', done => {
const chain = check('foo', ['body']).isEmail();
const req1: InternalRequest = { body: { foo: 'bla' } };
chain(req1, {}, () => {
const context1 = req1[contextsSymbol]![0];
const context1 = req1[contextsKey]![0];

const req2: InternalRequest = {};
chain(req2, {}, () => {
expect(req2[contextsSymbol]).toHaveLength(1);
expect(req2[contextsSymbol]![0]).not.toBe(context1);
expect(req2[contextsSymbol]![0].errors).toHaveLength(1);
expect(req2[contextsKey]).toHaveLength(1);
expect(req2[contextsKey]![0]).not.toBe(context1);
expect(req2[contextsKey]![0].errors).toHaveLength(1);
done();
});
});
Expand Down
6 changes: 3 additions & 3 deletions src/middlewares/one-of.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { InternalRequest, contextsSymbol } from '../base';
import { InternalRequest, contextsKey } from '../base';
import { ContextRunnerImpl } from '../chain/context-runner-impl';
import { check } from './validation-chain-builders';
import { oneOf } from './one-of';

const getOneOfContext = (req: InternalRequest) => {
const contexts = req[contextsSymbol] || [];
const contexts = req[contextsKey] || [];
return contexts[contexts.length - 1];
};

Expand All @@ -14,7 +14,7 @@ it('concats to contexts create by previous chains', done => {
const chainA = check('foo');
chainA(req, {}, () => {
oneOf([check('bar'), check('baz')])(req, {}, () => {
expect(req[contextsSymbol]).toHaveLength(2);
expect(req[contextsKey]).toHaveLength(2);
done();
});
});
Expand Down
4 changes: 2 additions & 2 deletions src/middlewares/one-of.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as _ from 'lodash';
import { ValidationChain } from '../chain';
import { InternalRequest, Middleware, Request, contextsSymbol } from '../base';
import { InternalRequest, Middleware, Request, contextsKey } from '../base';
import { ContextBuilder } from '../context-builder';

export type OneOfCustomMessageBuilder = (options: { req: Request }) => any;
Expand Down Expand Up @@ -34,7 +34,7 @@ export function oneOf(chains: (ValidationChain | ValidationChain[])[], message?:
return groupErrors;
});

req[contextsSymbol] = (req[contextsSymbol] || []).concat(surrogateContext);
req[contextsKey] = (req[contextsKey] || []).concat(surrogateContext);

try {
const allErrors = await Promise.all(promises);
Expand Down
26 changes: 13 additions & 13 deletions src/validation-result.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ValidationError, contextsSymbol } from './base';
import { ValidationError, contextsKey } from './base';
import { ErrorFormatter, validationResult } from './validation-result';
import { ContextBuilder } from './context-builder';

Expand Down Expand Up @@ -32,29 +32,29 @@ it('works when there are no errors', () => {

describe('#isEmpty()', () => {
it('returns whether there are errors', () => {
let result = validationResult({ [contextsSymbol]: makeContextsList([]) });
let result = validationResult({ [contextsKey]: makeContextsList([]) });
expect(result.isEmpty()).toBe(true);

result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) });
result = validationResult({ [contextsKey]: makeContextsList(allErrors) });
expect(result.isEmpty()).toBe(false);
});
});

describe('#array()', () => {
it('returns all errors', () => {
const result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) });
const result = validationResult({ [contextsKey]: makeContextsList(allErrors) });
expect(result.array()).toEqual(allErrors);
});

it('returns only the first error for each field when onlyFirstError = true', () => {
const result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) });
const result = validationResult({ [contextsKey]: makeContextsList(allErrors) });
expect(result.array({ onlyFirstError: true })).toEqual([allErrors[0], allErrors[2]]);
});
});

describe('#mapped()', () => {
it('returns an object with the first error of each field', () => {
const result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) });
const result = validationResult({ [contextsKey]: makeContextsList(allErrors) });
expect(result.mapped()).toEqual({
foo: allErrors[0],
bar: allErrors[2],
Expand All @@ -64,17 +64,17 @@ describe('#mapped()', () => {

describe('#throw()', () => {
it('does not throw when there are no errors', () => {
const result = validationResult({ [contextsSymbol]: makeContextsList([]) });
const result = validationResult({ [contextsKey]: makeContextsList([]) });
expect(() => result.throw()).not.toThrow();
});

it('throws when there are errors', () => {
const result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) });
const result = validationResult({ [contextsKey]: makeContextsList(allErrors) });
expect(() => result.throw()).toThrowError();
});

it('throws error decorated as Result', done => {
const result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) });
const result = validationResult({ [contextsKey]: makeContextsList(allErrors) });
try {
result.throw();
done(new Error('no errors thrown'));
Expand All @@ -88,13 +88,13 @@ describe('#throw()', () => {

describe('#formatWith()', () => {
it('returns a new instance of Result', () => {
const result = validationResult({ [contextsSymbol]: makeContextsList([]) });
const result = validationResult({ [contextsKey]: makeContextsList([]) });
expect(result.formatWith(err => err.msg)).not.toBe(result);
});

it('sets a new formatter that is used with #array()', () => {
const formatter: ErrorFormatter = err => err.msg;
const result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) }).formatWith(
const result = validationResult({ [contextsKey]: makeContextsList(allErrors) }).formatWith(
formatter,
);

Expand All @@ -103,7 +103,7 @@ describe('#formatWith()', () => {

it('sets a new formatter that is used with #mapped()', () => {
const formatter: ErrorFormatter = err => err.msg;
const result = validationResult({ [contextsSymbol]: makeContextsList(allErrors) }).formatWith(
const result = validationResult({ [contextsKey]: makeContextsList(allErrors) }).formatWith(
formatter,
);

Expand All @@ -119,7 +119,7 @@ describe('.withDefaults()', () => {
let formatter: ErrorFormatter = err => `${err.param} is broken, fix it`;
const customFactory = validationResult.withDefaults({ formatter });

let result = customFactory({ [contextsSymbol]: makeContextsList(allErrors) });
let result = customFactory({ [contextsKey]: makeContextsList(allErrors) });
expect(result.array()).toEqual(allErrors.map(formatter));

formatter = err => err.msg;
Expand Down
4 changes: 2 additions & 2 deletions src/validation-result.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as _ from 'lodash';
import { InternalRequest, Request, ValidationError, contextsSymbol } from './base';
import { InternalRequest, Request, ValidationError, contextsKey } from './base';
import { bindAll } from './utils';

export type ErrorFormatter<T = any> = (error: ValidationError) => T;
Expand Down Expand Up @@ -59,7 +59,7 @@ function withDefaults<T = any>(
const actualOptions = _.defaults(options, defaults);

return (req: InternalRequest) => {
const contexts = req[contextsSymbol] || [];
const contexts = req[contextsKey] || [];
const errors = _.flatMap(contexts, 'errors');
return new Result(actualOptions.formatter, errors);
};
Expand Down

0 comments on commit 303b5eb

Please sign in to comment.