Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom validator error names #50

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ node_modules
/package
.env
.env.*
.pnpm-debug.log
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"javascript.preferences.importModuleSpecifierEnding": "js",
"typescript.preferences.importModuleSpecifierEnding": "js"
"typescript.preferences.importModuleSpecifierEnding": "js",
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
3 changes: 2 additions & 1 deletion src/docs/6_Validators.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ filename: 6_Validators.md
## Validators

- validators now need to be called directly, thus providing type safe auto-completion
- validators now return a function that return an object `{ valid: boolean, name: string = 'validator_name' }`
- validators now return a function that return an object `{ valid: boolean, name: string = 'validator_name' }
- All built-in validators can be passed an additional parameter with a custom error name, e.g. `required('field is required')` or `between(0, 10, 'not between 1 and 10')`

Check [custom validators](#custom-validator) for more info

Expand Down
4 changes: 2 additions & 2 deletions src/lib/validators/between.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Validator } from './validator.js';

export function between(min: number, max: number): Validator {
export function between(min: number, max: number, name = 'between'): Validator {
return (value: any) => {
const val = isNaN(value) ? value.length : parseFloat(value);
return { valid: val >= min && val <= max, name: 'between' };
return { valid: val >= min && val <= max, name };
};
}
4 changes: 2 additions & 2 deletions src/lib/validators/email.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Validator } from './validator.js';

export function email(): Validator {
export function email(name = 'not_an_email'): Validator {
return (value: any) => {
const regex = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
return { valid: Boolean(value) && regex.test(value), name: 'not_an_email' };
return { valid: Boolean(value) && regex.test(value), name };
};
}
4 changes: 2 additions & 2 deletions src/lib/validators/matchField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { Field } from '$lib/types';
import type { Readable } from 'svelte/store';
import { get } from 'svelte/store';

export function matchField(store: Readable<Field<any>>) {
export function matchField(store: Readable<Field<any>>, name = 'match_field') {
return (value) => {
return { valid: get(store).value === value, name: 'match_field' };
return { valid: get(store).value === value, name };
};
}
4 changes: 2 additions & 2 deletions src/lib/validators/max.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { Validator } from './validator.js';

export function max(n: number): Validator {
export function max(n: number, name = 'max'): Validator {
return (value: any) => {
const val = typeof value === 'string' ? value.length : isNaN(value) ? 0 : parseFloat(value);

return { valid: val <= n, name: 'max' };
return { valid: val <= n, name };
};
}
4 changes: 2 additions & 2 deletions src/lib/validators/min.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Validator } from './validator.js';

export function min(n: number): Validator {
export function min(n: number, name = 'min'): Validator {
return (value: any) => {
const val = isNaN(value) ? value.length : parseFloat(value);
return { valid: val >= n, name: 'min' };
return { valid: val >= n, name };
};
}
4 changes: 2 additions & 2 deletions src/lib/validators/pattern.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { Validator } from './validator.js';

export function pattern(pattern: RegExp): Validator {
export function pattern(pattern: RegExp, name = 'pattern'): Validator {
return (value: any) => {
if (value === null || value === undefined) {
return { valid: false, name: 'pattern' };
}

return { valid: pattern.test(value), name: 'pattern' };
return { valid: pattern.test(value), name };
};
}
4 changes: 2 additions & 2 deletions src/lib/validators/required.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Validator } from './validator.js';

export function required(): Validator {
export function required(name = 'required'): Validator {
return (val: string) => {
let valid = true;
if (val === undefined || val === null) valid = false;
Expand All @@ -11,6 +11,6 @@ export function required(): Validator {
valid = tmp.length > 0;
}

return { valid, name: 'required' };
return { valid, name };
};
}
4 changes: 2 additions & 2 deletions src/lib/validators/url.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Validator } from './validator.js';

export function url(): Validator {
export function url(name = 'url'): Validator {
const regex =
/(https?|ftp|git|svn):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/i;
return (value: string) => ({ valid: regex.test(value), name: 'url' });
return (value: string) => ({ valid: regex.test(value), name });
}
34 changes: 34 additions & 0 deletions src/tests/validators/customErrorName.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import cases from 'jest-in-case';
import * as v from '$lib/validators';
import { field } from '$lib/field';
import type { FieldValidation } from '$lib';

const valueOfFieldToMatchAgainst = 10;
const fieldToMatchAgainst = field('fieldToMatchAgainst', valueOfFieldToMatchAgainst);

cases(
'max(max)',
(opts) => {
const result = opts.validator(
...(opts.args || []),
'custom message'
)(opts.invalidValue) as FieldValidation;

expect(result.valid).toBe(false);
expect(result.name).toBe('custom message');
},
{
between: _(v.between, 50, [0, 10]),
email: _(v.email, 0),
matchField: _(v.matchField, valueOfFieldToMatchAgainst + 10, [fieldToMatchAgainst]),
max: _(v.max, 15, [10]),
min: _(v.min, 5, [10]),
pattern: _(v.pattern, 'foo', [/bar/]),
required: _(v.required, null),
url: _(v.url, 5)
}
);

function _(validator, invalidValue, args = []) {
return { validator, invalidValue, args };
}