Skip to content

Commit

Permalink
added options and updated readme
Browse files Browse the repository at this point in the history
  • Loading branch information
jacoobia committed Jan 3, 2024
1 parent 55be15b commit ce8bdef
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/proud-beans-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"schemeit": minor
---

added options and updated readme
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,48 @@
# SchemeIt

A lightweight express-js request validator, originally written for my personal projects and separated out into its own package for easier use.
Schemeit will check individual elements against their chosen validators, ensure all non-optional elements are present in a payload and can also optionally enforce `noExtraElements` to prevent bloated payloads.

## Install

```
npm install schemeit
```

## Usage

The following is a basic example usage of schemeit to build a validator middleware for an endpoint:

```
import express from "express";
import { NumberValidator, StringValidator, validator } from '../Schemic';
const app = express();
const testValidator = validator({
name: StringValidator(),
age: NumberValidator.optional()
});
app.post('/test', testValidator, async (request: Request, response: Response) => {
response.status(200).json({ message: 'Success!' });
});
app.listen(3000);
```

You can also use the exported function `createValidator` to create your own validation function with custom rules like so:

```
const SpecificStringValidator: ValidationFunction = createValidator((object: unknown) => {
return object === 'foo' || object === 'bar';
});
```

## Validator Options

| Option | Description |
| --------------- | ---------------------------------------------------------------------------------------------------- |
| noExtraElements | Rejects payloads with elements that do not exist in the validator schema |
| errorListName | Sets the name of the error list returned by the validator middleware, by default it is just `errors` |
5 changes: 5 additions & 0 deletions src/@types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ export type DataTypeValidator = {
optional?: boolean;
};

export type ValidatorOptions = {
noExtraElements?: boolean;
errorListName?: string;
};

export type ValidationFunction = (() => DataTypeValidator) & { optional: () => DataTypeValidator };
export type ValidationError = Record<string, string>;
export type Payload = Record<string, any> | null;
26 changes: 22 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Request, Response, NextFunction, RequestHandler } from 'express';
import { DataTypeValidator, ValidationError, Payload, ValidationFunction } from './@types/index';
import {
DataTypeValidator,
ValidationError,
Payload,
ValidationFunction,
ValidatorOptions
} from './@types/index';

const extractPayload = (request: Request): Payload => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
Expand Down Expand Up @@ -46,7 +52,10 @@ export const BooleanValidator = createValidator((object) => typeof object === 'b
* @param validators The validation rules to follow
* @returns {RequestHandler} An express middleware
*/
export const validator = (validators: Record<string, DataTypeValidator>): RequestHandler => {
export const validator = (
validators: Record<string, DataTypeValidator>,
options?: ValidatorOptions
): RequestHandler => {
return (request: Request, response: Response, next: NextFunction) => {
const errors: ValidationError = {};
const payload: Payload = extractPayload(request);
Expand All @@ -60,12 +69,21 @@ export const validator = (validators: Record<string, DataTypeValidator>): Reques
errors[key] = 'Required element is missing or undefined';
}
} else if (!validator.validate(value)) {
errors[key] = 'Invalid type';
errors[key] = 'Invalid type: expected';
}
}

if (options?.noExtraElements) {
for (const key in payload) {
if (!validators[key]) {
errors[key] = 'Element does not exist in validator';
}
}
}

if (Object.keys(errors).length) {
return response.status(400).json({ errors });
const errorResponseKey = options?.errorListName ? options.errorListName : 'errors';
return response.status(400).json({ [errorResponseKey]: errors });
}

next();
Expand Down

0 comments on commit ce8bdef

Please sign in to comment.