Skip to content
25 changes: 24 additions & 1 deletion library/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,38 @@ module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:regexp/recommended',
'canonical/regexp',
'plugin:security/recommended',
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'import'],
plugins: ['@typescript-eslint', 'import', 'unicorn'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/consistent-type-imports': 'warn',
'@typescript-eslint/no-non-null-assertion': 'off',
'no-duplicate-imports': 'off',
'import/extensions': ['error', 'always'],

'security/detect-object-injection': 'off', // too many false positives

// regexp rules not turned on by regexp/recommend and canonical/regexp
// avoid unneeded regexps characters / style
'regexp/no-control-character': 'error',
'regexp/no-octal': 'error',
'regexp/no-standalone-backslash': 'error',
'regexp/prefer-escape-replacement-dollar-char': 'error',
'regexp/prefer-quantifier': 'error',
'regexp/hexadecimal-escape': ['error', 'always'],
'regexp/sort-alternatives': 'error',

'regexp/no-super-linear-move': 'error', // prevent DoS regexps
'regexp/require-unicode-regexp': 'error', // /u flag is faster and enables regexp strict mode
'regexp/prefer-regexp-exec': 'error', // enforce that RegExp#exec is used instead of String#match if no global flag is provided, as exec is faster
'unicorn/better-regex': 'error', // auto-optimize regexps
'unicorn/prefer-regexp-test': 'error', // RegExp#test is fastest
// 'unicorn/prefer-string-replace-all': 'warn', // String#replaceAll avoids the need for resetting lastIndex when using cached global regex
'unicorn/prefer-string-starts-ends-with': 'error', // RegExp#startsWith and RegExp#endsWith are faster
},
};
4 changes: 4 additions & 0 deletions library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@
"@typescript-eslint/parser": "^5.60.0",
"@vitest/coverage-v8": "^0.33.0",
"eslint": "^8.43.0",
"eslint-config-canonical": "^41.3.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-regexp": "^1.15.0",
"eslint-plugin-security": "^1.7.1",
"eslint-plugin-unicorn": "^48.0.1",
"jsdom": "^22.1.0",
"tsup": "^7.1.0",
"typescript": "^5.1.3",
Expand Down
2 changes: 1 addition & 1 deletion library/src/schemas/special/special.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { special } from './special.ts';

type PixelString = `${number}px`;
const isPixelString = (input: unknown) =>
typeof input === 'string' && /^\d+px$/.test(input);
typeof input === 'string' && /^\d+px$/u.test(input);

describe('special', () => {
test('should pass only pixel strings', () => {
Expand Down
2 changes: 1 addition & 1 deletion library/src/schemas/special/specialAsync.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { specialAsync } from './specialAsync.ts';

type PixelString = `${number}px`;
const isPixelString = (input: unknown) =>
typeof input === 'string' && /^\d+px$/.test(input);
typeof input === 'string' && /^\d+px$/u.test(input);

describe('specialAsync', () => {
test('should pass only pixel strings', async () => {
Expand Down
2 changes: 1 addition & 1 deletion library/src/utils/isLuhnAlgo/isLuhnAlgo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
export function isLuhnAlgo(input: string) {
// Remove any non-digit chars
const number = input.replace(/\D/g, '');
const number = input.replace(/\D/gu, '');

// Create necessary variables
let length = number.length;
Expand Down
2 changes: 1 addition & 1 deletion library/src/validations/bytes/bytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates the byte length of a string.
* Creates a validation function that validates the byte length of a string.
*
* @param requirement The byte length.
* @param error The error message.
Expand Down
4 changes: 2 additions & 2 deletions library/src/validations/cuid2/cuid2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a [cuid2](https://github.com/paralleldrive/cuid2#cuid2).
* Creates a validation function that validates a [cuid2](https://github.com/paralleldrive/cuid2#cuid2).
*
* @param error The error message.
*
* @returns A validation function.
*/
export function cuid2<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^[a-z][a-z0-9]*$/.test(input)
!/^[a-z][\da-z]*$/u.test(input)
? getPipeIssues('cuid2', error || 'Invalid cuid2', input)
: getOutput(input);
}
5 changes: 3 additions & 2 deletions library/src/validations/email/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a email.
* Creates a validation function that validates a email.
*
* @param error The error message.
*
* @returns A validation function.
*/
export function email<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^[\w+-]+(?:\.[\w+-]+)*@[A-Z0-9]+(?:(?:\.|-)[A-Z0-9]+)*\.[A-Z]{2,}$/i.test(
// eslint-disable-next-line security/detect-unsafe-regex -- false positive according to https://devina.io/redos-checker
!/^[\w+-]+(?:\.[\w+-]+)*@[\da-z]+(?:[.-][\da-z]+)*\.[a-z]{2,}$/iu.test(
input
)
? getPipeIssues('email', error || 'Invalid email', input)
Expand Down
4 changes: 2 additions & 2 deletions library/src/validations/emoji/emoji.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a emoji.
* Creates a validation function that validates a emoji.
*
* @param error The error message.
*
* @returns A validation function.
*/
export function emoji<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^(\p{Extended_Pictographic}|\p{Emoji_Component})+$/u.test(input)
!/^[\p{Extended_Pictographic}\p{Emoji_Component}]+$/u.test(input)
? getPipeIssues('emoji', error || 'Invalid emoji', input)
: getOutput(input);
}
2 changes: 1 addition & 1 deletion library/src/validations/endsWith/endsWith.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates the end of a string.
* Creates a validation function that validates the end of a string.
*
* @param requirement The end string.
* @param error The error message.
Expand Down
2 changes: 1 addition & 1 deletion library/src/validations/excludes/excludes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function excludes<TInput extends TItem[], TItem>(
): (input: TInput) => PipeResult<TInput>;

/**
* Creates a validation functions that validates the content of a string or array.
* Creates a validation function that validates the content of a string or array.
*
* @param requirement The content to be excluded.
* @param error The error message.
Expand Down
6 changes: 3 additions & 3 deletions library/src/validations/imei/imei.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues, isLuhnAlgo } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a IMEI.
* Creates a validation function that validates a IMEI.
*
* Format: AA-BBBBBB-CCCCCC-D
*
Expand All @@ -12,8 +12,8 @@ import { getOutput, getPipeIssues, isLuhnAlgo } from '../../utils/index.ts';
*/
export function imei<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^\d{2}[ |/|-]?\d{6}[ |/|-]?\d{6}[ |/|-]?\d$/.test(input) ||
!isLuhnAlgo(input)
// eslint-disable-next-line security/detect-unsafe-regex -- false positive according to https://devina.io/redos-checker
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this rule is so buggy, we should consider removing it in general or create an issue on GitHub.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.. this is one of the longest standing issues of the security plugin: eslint-community/eslint-plugin-security#28

Two alternatives exist:

For my personal config I've opted with sticking with eslint-plugin-security until they've sorted out what to use, but I wasn't aware of eslint-plugin-redos-detector until now. Maybe worth trying out. I'll also mention that one in the thread above

Copy link
Owner

@fabian-hiller fabian-hiller Oct 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as there is no fix, I prefer to disable or replace this linting rule globally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll play with the two plugins and update the PR accordingly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colinhacks/zod#2849 the zod PR is also interesting for this PR I'd say

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we should keep an eye on this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to go with redos-detector, since it seems to find more (non-false positives) of redos regexps.

!/^\d{2}(?:[ /|-]?\d{6}){2}[ /|-]?\d$/u.test(input) || !isLuhnAlgo(input)
? getPipeIssues('imei', error || 'Invalid IMEI', input)
: getOutput(input);
}
2 changes: 1 addition & 1 deletion library/src/validations/includes/includes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function includes<TInput extends TItem[], TItem>(
): (input: TInput) => PipeResult<TInput>;

/**
* Creates a validation functions that validates the content of a string or array.
* Creates a validation function that validates the content of a string or array.
*
* @param requirement The content to be included.
* @param error The error message.
Expand Down
8 changes: 5 additions & 3 deletions library/src/validations/ip/ip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a IP v4 or v6 address.
* Creates a validation function that validates an IP v4 or v6 address.
*
* @param error The error message.
*
* @returns A validation function.
*/
export function ip<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/.test(input) &&
!/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(
// eslint-disable-next-line security/detect-unsafe-regex -- false positive according to https://devina.io/redos-checker
!/^(?:(?:25[0-5]|(?:2[0-4]|1\d|[1-9])?\d)\.?\b){4}$/u.test(input) &&
// eslint-disable-next-line security/detect-unsafe-regex -- false positive according to https://devina.io/redos-checker
!/^(?:(?:[\dA-Fa-f]{1,4}:){7}[\dA-Fa-f]{1,4}|(?:[\dA-Fa-f]{1,4}:){1,7}:|(?:[\dA-Fa-f]{1,4}:){1,6}:[\dA-Fa-f]{1,4}|(?:[\dA-Fa-f]{1,4}:){1,5}(?::[\dA-Fa-f]{1,4}){1,2}|(?:[\dA-Fa-f]{1,4}:){1,4}(?::[\dA-Fa-f]{1,4}){1,3}|(?:[\dA-Fa-f]{1,4}:){1,3}(?::[\dA-Fa-f]{1,4}){1,4}|(?:[\dA-Fa-f]{1,4}:){1,2}(?::[\dA-Fa-f]{1,4}){1,5}|[\dA-Fa-f]{1,4}:(?::[\dA-Fa-f]{1,4}){1,6}|:(?:(?::[\dA-Fa-f]{1,4}){1,7}|:)|fe80:(?::[\dA-Fa-f]{0,4}){0,4}%[\dA-Za-z]+|::(?:f{4}(?::0{1,4})?:)?(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d)|(?:[\dA-Fa-f]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d))$/u.test(
input
)
? getPipeIssues('ip', error || 'Invalid IP', input)
Expand Down
5 changes: 3 additions & 2 deletions library/src/validations/ipv4/ipv4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a IP v4 address.
* Creates a validation function that validates an IP v4 address.
*
* @param error The error message.
*
* @returns A validation function.
*/
export function ipv4<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/.test(input)
// eslint-disable-next-line security/detect-unsafe-regex -- false positive according to https://devina.io/redos-checker
!/^(?:(?:25[0-5]|(?:2[0-4]|1\d|[1-9])?\d)\.?\b){4}$/u.test(input)
? getPipeIssues('ipv4', error || 'Invalid IP v4', input)
: getOutput(input);
}
5 changes: 3 additions & 2 deletions library/src/validations/ipv6/ipv6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a IP v6 address.
* Creates a validation function that validates an IP v6 address.
*
* @param error The error message.
*
* @returns A validation function.
*/
export function ipv6<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(
// eslint-disable-next-line security/detect-unsafe-regex -- false positive according to https://devina.io/redos-checker
!/^(?:(?:[\dA-Fa-f]{1,4}:){7}[\dA-Fa-f]{1,4}|(?:[\dA-Fa-f]{1,4}:){1,7}:|(?:[\dA-Fa-f]{1,4}:){1,6}:[\dA-Fa-f]{1,4}|(?:[\dA-Fa-f]{1,4}:){1,5}(?::[\dA-Fa-f]{1,4}){1,2}|(?:[\dA-Fa-f]{1,4}:){1,4}(?::[\dA-Fa-f]{1,4}){1,3}|(?:[\dA-Fa-f]{1,4}:){1,3}(?::[\dA-Fa-f]{1,4}){1,4}|(?:[\dA-Fa-f]{1,4}:){1,2}(?::[\dA-Fa-f]{1,4}){1,5}|[\dA-Fa-f]{1,4}:(?::[\dA-Fa-f]{1,4}){1,6}|:(?:(?::[\dA-Fa-f]{1,4}){1,7}|:)|fe80:(?::[\dA-Fa-f]{0,4}){0,4}%[\dA-Za-z]+|::(?:f{4}(?::0{1,4})?:)?(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d)|(?:[\dA-Fa-f]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d))$/u.test(
input
)
? getPipeIssues('ipv6', error || 'Invalid IP v6', input)
Expand Down
4 changes: 2 additions & 2 deletions library/src/validations/isoDate/isoDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a date.
* Creates a validation function that validates a date.
*
* Format: yyyy-mm-dd
*
Expand All @@ -16,7 +16,7 @@ import { getOutput, getPipeIssues } from '../../utils/index.ts';
*/
export function isoDate<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^\d{4}-(0[1-9]|1[0-2])-([12]\d|0[1-9]|3[01])$/.test(input)
!/^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])$/u.test(input)
? getPipeIssues('iso_date', error || 'Invalid date', input)
: getOutput(input);
}
4 changes: 2 additions & 2 deletions library/src/validations/isoDateTime/isoDateTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a datetime.
* Creates a validation function that validates a datetime.
*
* Format: yyyy-mm-ddThh:mm
*
Expand All @@ -16,7 +16,7 @@ import { getOutput, getPipeIssues } from '../../utils/index.ts';
*/
export function isoDateTime<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^\d{4}-(0[1-9]|1[0-2])-([12]\d|0[1-9]|3[01])T(0[0-9]|1\d|2[0-3]):[0-5]\d$/.test(
!/^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])T(?:0\d|1\d|2[0-3]):[0-5]\d$/u.test(
input
)
? getPipeIssues('iso_date_time', error || 'Invalid datetime', input)
Expand Down
4 changes: 2 additions & 2 deletions library/src/validations/isoTime/isoTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a time.
* Creates a validation function that validates a time.
*
* Format: hh:mm
*
Expand All @@ -12,7 +12,7 @@ import { getOutput, getPipeIssues } from '../../utils/index.ts';
*/
export function isoTime<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^(0[0-9]|1\d|2[0-3]):[0-5]\d$/.test(input)
!/^(?:0\d|1\d|2[0-3]):[0-5]\d$/u.test(input)
? getPipeIssues('iso_time', error || 'Invalid time', input)
: getOutput(input);
}
4 changes: 2 additions & 2 deletions library/src/validations/isoTimeSecond/isoTimeSecond.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a time with seconds.
* Creates a validation function that validates a time with seconds.
*
* Format: hh:mm:ss
*
Expand All @@ -12,7 +12,7 @@ import { getOutput, getPipeIssues } from '../../utils/index.ts';
*/
export function isoTimeSecond<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^(0[0-9]|1\d|2[0-3]):[0-5]\d:[0-5]\d$/.test(input)
!/^(?:0\d|1\d|2[0-3])(?::[0-5]\d){2}$/u.test(input)
? getPipeIssues('iso_time_second', error || 'Invalid time', input)
: getOutput(input);
}
4 changes: 2 additions & 2 deletions library/src/validations/isoTimestamp/isoTimestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a timestamp.
* Creates a validation function that validates a timestamp.
*
* Format: yyyy-mm-ddThh:mm:ss.sssZ
*
Expand All @@ -16,7 +16,7 @@ import { getOutput, getPipeIssues } from '../../utils/index.ts';
*/
export function isoTimestamp<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^\d{4}-(0[1-9]|1[0-2])-([12]\d|0[1-9]|3[01])T(0[0-9]|1\d|2[0-3]):[0-5]\d:[0-5]\d\.\d{3}Z$/.test(
!/^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])T(?:0\d|1\d|2[0-3])(?::[0-5]\d){2}\.\d{3}Z$/u.test(
input
)
? getPipeIssues('iso_timestamp', error || 'Invalid timestamp', input)
Expand Down
4 changes: 2 additions & 2 deletions library/src/validations/isoWeek/isoWeek.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates a week.
* Creates a validation function that validates a week.
*
* Format: yyyy-Www
*
Expand All @@ -16,7 +16,7 @@ import { getOutput, getPipeIssues } from '../../utils/index.ts';
*/
export function isoWeek<TInput extends string>(error?: ErrorMessage) {
return (input: TInput): PipeResult<TInput> =>
!/^\d{4}-W(0[1-9]|[1-4]\d|5[0-3])$/.test(input)
!/^\d{4}-W(?:0[1-9]|[1-4]\d|5[0-3])$/u.test(input)
? getPipeIssues('iso_week', error || 'Invalid week', input)
: getOutput(input);
}
2 changes: 1 addition & 1 deletion library/src/validations/length/length.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates the length of a string or array.
* Creates a validation function that validates the length of a string or array.
*
* @param requirement The length.
* @param error The error message.
Expand Down
2 changes: 1 addition & 1 deletion library/src/validations/maxBytes/maxBytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates the byte length of a string.
* Creates a validation function that validates the byte length of a string.
*
* @param requirement The maximum length in byte.
* @param error The error message.
Expand Down
2 changes: 1 addition & 1 deletion library/src/validations/maxLength/maxLength.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates the length of a string or array.
* Creates a validation function that validates the length of a string or array.
*
* @param requirement The maximum length.
* @param error The error message.
Expand Down
2 changes: 1 addition & 1 deletion library/src/validations/maxSize/maxSize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ErrorMessage, PipeResult } from '../../types.ts';
import { getOutput, getPipeIssues } from '../../utils/index.ts';

/**
* Creates a validation functions that validates the size of a map, set or blob.
* Creates a validation function that validates the size of a map, set or blob.
*
* @param requirement The maximum size.
* @param error The error message.
Expand Down
Loading