New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

policeman

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

policeman - npm Package Compare versions

Comparing version 0.0.1 to 0.1.0

7

CHANGELOG.md

@@ -1,1 +0,6 @@

# CHANGELOG
# CHANGELOG
## 0.1.0
* Allow for filtering schema entries
* Add `isEmail`, `isMatching` and `isPassing` validators

7

lib/policeman.d.ts

@@ -1,2 +0,2 @@

import { Source, Result } from "mappet";
import { Source, Result, Filter } from "mappet";
export interface Message {

@@ -14,4 +14,5 @@ (value: any): string;

}
export declare type SchemaEntry = [string, string, EntryValidator[]];
export declare type Schema = SchemaEntry[];
export declare type BasicSchemaEntry = [string, string, EntryValidator[]];
export declare type FilterableSchemaEntry = [string, string, EntryValidator[], Filter];
export declare type Schema = [BasicSchemaEntry | FilterableSchemaEntry];
/**

@@ -18,0 +19,0 @@ * Produce validator based on provided schema

@@ -12,3 +12,4 @@ "use strict";

var dest = _a[0];
return valid && !get(errors, dest).length;
var err = get(errors, dest);
return valid && (err === undefined || get(errors, dest).length === 0);
}, true);

@@ -24,4 +25,4 @@ }

.map(function (_a) {
var dest = _a[0], source = _a[1], validators = _a[2];
return [dest, source, buildModifier(validators)];
var dest = _a[0], source = _a[1], validators = _a[2], filter = _a[3];
return [dest, source, buildModifier(validators), filter];
});

@@ -28,0 +29,0 @@ return function (source) {

import { Message } from "./policeman";
export declare const isRequired: (message: Message) => (value: string) => string;
export declare const minLength: (min: number) => (message: Message) => (value: string) => string;
export declare const maxLength: (max: number) => (message: Message) => (value: string) => string;
export declare const isRequired: _.CurriedFunction2<Message, string | boolean, string>;
export declare const minLength: _.CurriedFunction3<number, Message, string, string>;
export declare const maxLength: _.CurriedFunction3<number, Message, string, string>;
export declare const isEmail: _.CurriedFunction2<Message, string, string>;
export declare const isMatching: _.CurriedFunction3<RegExp, Message, string, string>;
export declare const isPassing: _.CurriedFunction3<(value: any) => boolean, Message, string, string>;
"use strict";
exports.isRequired = function (message) { return function (value) {
var valid = value !== null && value !== undefined && value !== "";
var curry = require("lodash/curry");
exports.isRequired = curry(function (message, value) {
var valid = value !== null && value !== undefined && value !== "" && value;
return valid ? null : message(value);
}; };
exports.minLength = function (min) { return function (message) { return function (value) {
});
exports.minLength = curry(function (min, message, value) {
var valid = value.length >= min;
return valid ? null : message(value);
}; }; };
exports.maxLength = function (max) { return function (message) { return function (value) {
});
exports.maxLength = curry(function (max, message, value) {
var valid = value.length <= max;
return valid ? null : message(value);
}; }; };
});
exports.isEmail = curry(function (message, value) {
var valid = /^[a-z0-9_\-\.]{2,}@[a-z0-9_\-\.]{2,}\.[a-z]{2,}$/i.test(value);
return valid ? null : message(value);
});
exports.isMatching = curry(function (regexp, message, value) {
var valid = regexp.test(value);
return valid ? null : message(value);
});
exports.isPassing = curry(function (predicate, message, value) {
var valid = predicate(value);
return valid ? null : message(value);
});
//# sourceMappingURL=validators.js.map
{
"name": "policeman",
"version": "0.0.1",
"version": "0.1.0",
"description": "Lightweight yet powerful schema validator",

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

# policeman
[![CircleCI](https://circleci.com/gh/MichalZalecki/policeman.svg?style=svg)](https://circleci.com/gh/MichalZalecki/policeman)
Lightweight yet powerful schema validator
***
[API Docs](https://michalzalecki.github.io/policeman)
[API Docs](https://michalzalecki.github.io/policeman) | [Examples](#examples)
***

@@ -16,2 +18,37 @@

npm i -S policeman
```
```
## Built-in validators
### `isRequired(message, value)`
Validates presence.
### `minLength(min, message, value)`
Passed `value` must be a string longer or with length equal to `min`.
### `maxLength(max, message, value)`
Passed `value` must be a string shorther or with length equal to `max`.
### `isEmail(message, value)`
Passed `value` must be a valid email.
### `isMatching(regexp, message, value)`
Passed `value` must pass `regexp`.
### `isPassing(predicate, message, value)`
Passed `predicate` answers on "Is `value` valid?". When `predicate` returns `true` validator passes,
when `predicate` returns `false` error message is returned.
See [tests](src/test/validators.test.ts) for more examples.
## Examples
TODO
See [tests](src/test/policeman.test.ts) for more examples.
import * as get from "lodash/get";
import mappet, { Source, Result, Modifier, Schema as MappetSchema } from "mappet";
import mappet, { Source, Result, Modifier, Filter, Schema as MappetSchema } from "mappet";

@@ -16,4 +16,5 @@ export interface Message {

export type SchemaEntry = [string, string, EntryValidator[]];
export type Schema = SchemaEntry[];
export type BasicSchemaEntry = [string, string, EntryValidator[]];
export type FilterableSchemaEntry = [string, string, EntryValidator[], Filter];
export type Schema = [BasicSchemaEntry | FilterableSchemaEntry];

@@ -27,3 +28,6 @@ function buildModifier(validators: EntryValidator[]): Modifier {

function checkValidity(schema: Schema, errors: Source): boolean {
return schema.reduce((valid, [dest]) => valid && !(<string[]>get(errors, dest)).length, true);
return schema.reduce((valid, [dest]) => {
const err = get(errors, dest);
return valid && (err === undefined || (<string[]> get(errors, dest)).length === 0);
}, true);
}

@@ -33,14 +37,15 @@

* Produce validator based on provided schema
*
*
* @returns Validator based on provided schema
*/
export default function policeman(schema: Schema): SchemaValidator {
const validationSchema = <MappetSchema>schema
.map(([dest, source, validators]) => [dest, source, buildModifier(validators)]);
const validationSchema = <MappetSchema> schema
.map(<FilterableSchemaEntry>([dest, source, validators, filter]) =>
[dest, source, buildModifier(validators), filter]);
return (source: Source) => {
const errors: Result = mappet(validationSchema)(source);
const valid: boolean = checkValidity(schema, errors);
const errors = mappet(validationSchema)(source);
const valid = checkValidity(schema, errors);
return { errors, valid };
};
}
}

@@ -0,16 +1,32 @@

import * as curry from "lodash/curry";
import { Message } from "./policeman";
export const isRequired = (message: Message) => (value: string) => {
const valid = value !== null && value !== undefined && value !== "";
export const isRequired = curry((message: Message, value: string | boolean) => {
const valid = value !== null && value !== undefined && value !== "" && value;
return valid ? null : message(value);
};
});
export const minLength = (min: number) => (message: Message) => (value: string) => {
export const minLength = curry((min: number, message: Message, value: string) => {
const valid = value.length >= min;
return valid ? null : message(value);
};
});
export const maxLength = (max: number) => (message: Message) => (value: string) => {
export const maxLength = curry((max: number, message: Message, value: string) => {
const valid = value.length <= max;
return valid ? null : message(value);
};
});
export const isEmail = curry((message: Message, value: string) => {
const valid = /^[a-z0-9_\-\.]{2,}@[a-z0-9_\-\.]{2,}\.[a-z]{2,}$/i.test(value);
return valid ? null : message(value);
});
export const isMatching = curry((regexp: RegExp, message: Message, value: string) => {
const valid = regexp.test(value);
return valid ? null : message(value);
});
export const isPassing = curry((predicate: ((value: any) => boolean), message: Message, value: string) => {
const valid = predicate(value);
return valid ? null : message(value);
});
import * as tape from "tape";
import { Filter } from "mappet";
import policeman, { Schema } from "../lib/policeman";

@@ -20,9 +21,9 @@ import { isRequired, minLength } from "../lib/validators";

bio: "Lorem ipsum",
}
};
const expected = {
firstName: <any[]>[],
firstName: <any[]> [],
lastName: ["is required"],
other: {
bio: ["should contain at least 10 characters"],
}
},
};

@@ -41,6 +42,26 @@ const { errors } = validator(source);

function makeUseOfMapperFilter(t: tape.Test) {
interface User {
name: string;
age: number;
clubCard: string;
}
const required = isRequired(() => "is required");
const isUnderage: Filter = (_value, source) => (<User> source).age < 18;
const schema: Schema = [
["name", "name", [required]],
["clubCard", "clubCard", [required], isUnderage],
];
const validator = policeman(schema);
t.is(validator({ name: "Foo", age: 18 }).valid, true);
t.is(validator({ name: "Foo", age: 17 }).valid, false);
t.deepEqual((<User> validator({ name: "Foo", age: 17 }).errors).clubCard, ["is required"]);
t.is(validator({ name: "Foo", age: 17, clubCard: "123ABC" }).valid, true);
}
tape("policeman", (t: tape.Test) => {
t.plan(3);
t.plan(7);
returnsErrorObjects(t);
determinesWhetherSourceIsValid(t);
});
makeUseOfMapperFilter(t);
});
import "./policeman.test";
import "./validators.test";
import "./validators.test";

@@ -7,22 +7,26 @@ import * as tape from "tape";

maxLength,
isEmail,
isMatching,
isPassing,
} from "../lib/validators";
function testIsRequired(t: tape.Test) {
const required = isRequired(() => "Is required");
t.is(required(""), "Is required", "isRequired fails on empty string");
t.is(required(null), "Is required", "isRequired fails on null");
t.is(required(undefined), "Is required", "isRequired fails on undefined");
t.is(required(""), "Is required", "isRequired accepts not empty strings");
const required = isRequired(() => "is required");
t.is(required(""), "is required", "isRequired fails on empty string");
t.is(required(null), "is required", "isRequired fails on null");
t.is(required(undefined), "is required", "isRequired fails on undefined");
t.is(required(false), "is required", "isRequired fails on false");
t.is(required("foo"), null, "isRequired accepts not empty strings");
}
function testMinLengthValidator(t: tape.Test) {
const minLength4: EntryValidator = minLength(4)(() => "Should be at least 4");
const minLength4: EntryValidator = minLength(4, () => "should be at least 4");
t.is(minLength4("foo bar"), null, "minLength(4) accepts strings with 4+ characters");
t.is(minLength4("fooz"), null, "minLength(4) accepts strings with 4 characters");
t.is(minLength4("foo"), "Should be at least 4", "minLength(4) fails on strings with 4- characters");
t.is(minLength4("foo"), "should be at least 4", "minLength(4) fails on strings with 4- characters");
}
function testMaxLengthValidator(t: tape.Test) {
const maxLength4: EntryValidator = maxLength(4)(() => "Should be at most 4");
t.is(maxLength4("foo bar"), "Should be at most 4", "maxLength(4) fails on strings with 4+ characters");
const maxLength4: EntryValidator = maxLength(4, () => "should be at most 4");
t.is(maxLength4("foo bar"), "should be at most 4", "maxLength(4) fails on strings with 4+ characters");
t.is(maxLength4("fooz"), null, "maxLength(4) accepts strings with 4 characters");

@@ -32,7 +36,30 @@ t.is(maxLength4("foo"), null, "maxLength(4) accepts strings with 4- characters");

function testIsEmail(t: tape.Test) {
const email = isEmail(() => "is invalid email");
t.is(email("foo@bar.com"), null, "isEmail accepts valid email");
t.is(email("foo@.com"), "is invalid email", "isEmail fails on invalid email");
}
function testIsMatching(t: tape.Test) {
const matching = isMatching(/^\d{3}-?\d{3}-?\d{3}$/, () => "is invalid number");
t.is(matching("777-888-999"), null, "isMatching(/^\d{3}-?\d{3}-?\d{3}$/) accepts valid number");
t.is(matching("777888999"), null, "isMatching(/^\d{3}-?\d{3}-?\d{3}$/) accepts valid number");
t.is(matching("aaa-bbb-ccc"), "is invalid number", "isMatching(/^\d{3}-?\d{3}-?\d{3}$/) fails on invalid number");
}
function testIsPassing(t: tape.Test) {
const isFoo = (str: string) => str === "foo";
const matching = isPassing(isFoo, () => "must be \"foo\"");
t.is(matching("foo"), null, "predicate returns true on \"foo\"");
t.is(matching("bar"), "must be \"foo\"", "predicate returns false on not \"foo\"");
}
tape("validators", (t: tape.Test) => {
t.plan(10);
t.plan(18);
testIsRequired(t);
testMinLengthValidator(t);
testMaxLengthValidator(t);
});
testIsEmail(t);
testIsMatching(t);
testIsPassing(t);
});

@@ -25,3 +25,3 @@ "use strict";

bio: ["should contain at least 10 characters"],
}
},
};

@@ -38,7 +38,21 @@ var errors = validator(source).errors;

}
function makeUseOfMapperFilter(t) {
var required = validators_1.isRequired(function () { return "is required"; });
var isUnderage = function (_value, source) { return source.age < 18; };
var schema = [
["name", "name", [required]],
["clubCard", "clubCard", [required], isUnderage],
];
var validator = policeman_1.default(schema);
t.is(validator({ name: "Foo", age: 18 }).valid, true);
t.is(validator({ name: "Foo", age: 17 }).valid, false);
t.deepEqual(validator({ name: "Foo", age: 17 }).errors.clubCard, ["is required"]);
t.is(validator({ name: "Foo", age: 17, clubCard: "123ABC" }).valid, true);
}
tape("policeman", function (t) {
t.plan(3);
t.plan(7);
returnsErrorObjects(t);
determinesWhetherSourceIsValid(t);
makeUseOfMapperFilter(t);
});
//# sourceMappingURL=policeman.test.js.map

@@ -5,26 +5,47 @@ "use strict";

function testIsRequired(t) {
var required = validators_1.isRequired(function () { return "Is required"; });
t.is(required(""), "Is required", "isRequired fails on empty string");
t.is(required(null), "Is required", "isRequired fails on null");
t.is(required(undefined), "Is required", "isRequired fails on undefined");
t.is(required(""), "Is required", "isRequired accepts not empty strings");
var required = validators_1.isRequired(function () { return "is required"; });
t.is(required(""), "is required", "isRequired fails on empty string");
t.is(required(null), "is required", "isRequired fails on null");
t.is(required(undefined), "is required", "isRequired fails on undefined");
t.is(required(false), "is required", "isRequired fails on false");
t.is(required("foo"), null, "isRequired accepts not empty strings");
}
function testMinLengthValidator(t) {
var minLength4 = validators_1.minLength(4)(function () { return "Should be at least 4"; });
var minLength4 = validators_1.minLength(4, function () { return "should be at least 4"; });
t.is(minLength4("foo bar"), null, "minLength(4) accepts strings with 4+ characters");
t.is(minLength4("fooz"), null, "minLength(4) accepts strings with 4 characters");
t.is(minLength4("foo"), "Should be at least 4", "minLength(4) fails on strings with 4- characters");
t.is(minLength4("foo"), "should be at least 4", "minLength(4) fails on strings with 4- characters");
}
function testMaxLengthValidator(t) {
var maxLength4 = validators_1.maxLength(4)(function () { return "Should be at most 4"; });
t.is(maxLength4("foo bar"), "Should be at most 4", "maxLength(4) fails on strings with 4+ characters");
var maxLength4 = validators_1.maxLength(4, function () { return "should be at most 4"; });
t.is(maxLength4("foo bar"), "should be at most 4", "maxLength(4) fails on strings with 4+ characters");
t.is(maxLength4("fooz"), null, "maxLength(4) accepts strings with 4 characters");
t.is(maxLength4("foo"), null, "maxLength(4) accepts strings with 4- characters");
}
function testIsEmail(t) {
var email = validators_1.isEmail(function () { return "is invalid email"; });
t.is(email("foo@bar.com"), null, "isEmail accepts valid email");
t.is(email("foo@.com"), "is invalid email", "isEmail fails on invalid email");
}
function testIsMatching(t) {
var matching = validators_1.isMatching(/^\d{3}-?\d{3}-?\d{3}$/, function () { return "is invalid number"; });
t.is(matching("777-888-999"), null, "isMatching(/^\d{3}-?\d{3}-?\d{3}$/) accepts valid number");
t.is(matching("777888999"), null, "isMatching(/^\d{3}-?\d{3}-?\d{3}$/) accepts valid number");
t.is(matching("aaa-bbb-ccc"), "is invalid number", "isMatching(/^\d{3}-?\d{3}-?\d{3}$/) fails on invalid number");
}
function testIsPassing(t) {
var isFoo = function (str) { return str === "foo"; };
var matching = validators_1.isPassing(isFoo, function () { return "must be \"foo\""; });
t.is(matching("foo"), null, "predicate returns true on \"foo\"");
t.is(matching("bar"), "must be \"foo\"", "predicate returns false on not \"foo\"");
}
tape("validators", function (t) {
t.plan(10);
t.plan(18);
testIsRequired(t);
testMinLengthValidator(t);
testMaxLengthValidator(t);
testIsEmail(t);
testIsMatching(t);
testIsPassing(t);
});
//# sourceMappingURL=validators.test.js.map

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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