@azure-net/kit 5.1.0 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,10 +16,12 @@ export type ValidationMessage = string | {
16
16
  key: string;
17
17
  vars?: Record<string, unknown>;
18
18
  };
19
+ export declare const SKIP_REMAINING_VALIDATION: unique symbol;
20
+ export type ValidationControl = typeof SKIP_REMAINING_VALIDATION;
19
21
  export interface ValidationErrorsMap {
20
22
  [key: string]: ValidationMessage | ValidationErrorsMap;
21
23
  }
22
- export type ValidationResult = ValidationMessage | ValidationErrorsMap | ValidationErrorsMap[] | undefined;
24
+ export type ValidationResult = ValidationMessage | ValidationErrorsMap | ValidationErrorsMap[] | ValidationControl | undefined;
23
25
  export type ValidationRuleResult<CurrentValue, ListValues = unknown, CurrentKey = string> = (params: ValidationParams<CurrentValue, ListValues, CurrentKey>) => ValidationResult;
24
26
  type ValidationErrors<Errors> = Errors extends ReadonlyArray<infer U> ? ValidationErrors<U>[] : IsAtomic<Errors> extends true ? ValidationMessage : Errors extends object ? {
25
27
  [K in keyof Errors]?: ValidationErrors<Errors[K]>;
@@ -1,5 +1,6 @@
1
1
  import { FormDataUtil } from '../../external/tools/index.js';
2
2
  import { AzureNetKitInternalError } from '../../shared/app-error/AppError.js';
3
+ export const SKIP_REMAINING_VALIDATION = Symbol('skipRemainingValidation');
3
4
  export class SchemaFail extends Error {
4
5
  _errors;
5
6
  data;
@@ -92,6 +93,8 @@ class SchemaBuilderImpl {
92
93
  listValues: _preparedData,
93
94
  key: key
94
95
  });
96
+ if (failMessage === SKIP_REMAINING_VALIDATION)
97
+ break;
95
98
  if (failMessage) {
96
99
  setByPath(_errors, key, failMessage);
97
100
  _isValid = false;
@@ -1,7 +1,8 @@
1
1
  import type { BaseValidationMessages } from './messages/Types.js';
2
2
  import type { ValidationParams, ValidationRuleResult } from '../index.js';
3
+ type ValidationMessageOverride<T> = T extends (...args: never[]) => unknown ? T : Partial<T>;
3
4
  export type ValidationRuleParams<T extends keyof BaseValidationMessages, D = object> = D & {
4
- message?: BaseValidationMessages[T];
5
+ message?: ValidationMessageOverride<BaseValidationMessages[T]>;
5
6
  };
6
7
  export type LengthParams = {
7
8
  length?: {
@@ -15,6 +16,35 @@ export type RangeParams = {
15
16
  max?: number;
16
17
  };
17
18
  };
19
+ export type DateRangeParams = {
20
+ range?: {
21
+ min?: Date | string;
22
+ max?: Date | string;
23
+ };
24
+ };
25
+ export type PatternParams = {
26
+ regexp: RegExp;
27
+ };
28
+ export type UrlParams = {
29
+ protocols?: string[];
30
+ allowRelative?: boolean;
31
+ };
32
+ export type FileParams = {
33
+ maxSize?: number;
34
+ mimeTypes?: string[];
35
+ extensions?: string[];
36
+ };
37
+ export type EmailParams = {
38
+ trim?: boolean;
39
+ maxLength?: number;
40
+ allowedDomains?: string[];
41
+ blockedDomains?: string[];
42
+ };
43
+ export type PhoneParams = {
44
+ requireCountryCode?: boolean;
45
+ minDigits?: number;
46
+ maxDigits?: number;
47
+ };
18
48
  type ArrayItemRules<Context> = ValidationRuleResult<Context>[] | Record<string, ValidationRuleResult<Context>[]>;
19
49
  type ArrayParams<Context> = LengthParams & {
20
50
  schema?: ArrayItemRules<Context>;
@@ -47,17 +77,21 @@ export declare const createRules: <M extends BaseValidationMessages>(validationM
47
77
  boolean: <T = unknown, D_6 = unknown>(params?: ValidationRuleParams<"boolean", {
48
78
  expected?: boolean;
49
79
  }>) => ValidationRuleResult<T, D_6>;
50
- email: <T = unknown, D_7 = unknown>(params?: ValidationRuleParams<"email">) => ValidationRuleResult<T, D_7>;
80
+ email: <T = unknown, D_7 = unknown>(params?: ValidationRuleParams<"email", EmailParams>) => ValidationRuleResult<T, D_7>;
51
81
  finite: <T = unknown, D_8 = unknown>(params?: ValidationRuleParams<"finite", RangeParams & {
52
82
  maxDigitsAfterDot?: number;
53
83
  }>) => ValidationRuleResult<T, D_8>;
54
84
  lettersOnly: <T = unknown, D_9 = unknown>(params?: ValidationRuleParams<"lettersOnly", {
55
85
  whiteSpaces?: boolean;
56
86
  }>) => ValidationRuleResult<T, D_9>;
57
- phone: <T = unknown, D_10 = unknown>(params?: ValidationRuleParams<"phone">) => ValidationRuleResult<T, D_10>;
58
- date: <T = unknown, D_11 = unknown>(params?: ValidationRuleParams<"date">) => ValidationRuleResult<T, D_11>;
59
- allowedOnly: <T = unknown, D_12 = unknown>(params?: ValidationRuleParams<"allowedOnly", {
87
+ phone: <T = unknown, D_10 = unknown>(params?: ValidationRuleParams<"phone", PhoneParams>) => ValidationRuleResult<T, D_10>;
88
+ date: <T = unknown, D_11 = unknown>(params?: ValidationRuleParams<"date", DateRangeParams>) => ValidationRuleResult<T, D_11>;
89
+ condition: <T = unknown, D_12 = unknown, K = string>(predicate: (params: ValidationParams<T, D_12, K>) => boolean) => ValidationRuleResult<T, D_12, K>;
90
+ pattern: <T = unknown, D_13 = unknown>(params: ValidationRuleParams<"pattern", PatternParams>) => ValidationRuleResult<T, D_13>;
91
+ url: <T = unknown, D_14 = unknown>(params?: ValidationRuleParams<"url", UrlParams>) => ValidationRuleResult<T, D_14>;
92
+ file: <T = unknown, D_15 = unknown>(params?: ValidationRuleParams<"file", FileParams>) => ValidationRuleResult<T, D_15>;
93
+ allowedOnly: <T = unknown, D_16 = unknown>(params?: ValidationRuleParams<"allowedOnly", {
60
94
  allowed?: unknown[];
61
- }>) => ValidationRuleResult<T, D_12>;
95
+ }>) => ValidationRuleResult<T, D_16>;
62
96
  };
63
97
  export {};
@@ -1,4 +1,5 @@
1
1
  import { DateUtil, ObjectUtil } from '../../../external/tools/index.js';
2
+ import { SKIP_REMAINING_VALIDATION } from '../Schema.js';
2
3
  /**
3
4
  *
4
5
  * @param validationMessages - BaseValidationMessages
@@ -9,6 +10,98 @@ export const createRules = (validationMessages) => {
9
10
  const checkVal = (val) => {
10
11
  return val !== undefined && val !== null;
11
12
  };
13
+ /**
14
+ * Checks a value against a regular expression.
15
+ */
16
+ const pattern = (params) => {
17
+ const { regexp, message = validationMessages.pattern } = params;
18
+ return ({ val }) => {
19
+ if (!checkVal(val))
20
+ return undefined;
21
+ if (typeof val !== 'string')
22
+ return message();
23
+ regexp.lastIndex = 0;
24
+ const matches = regexp.test(val);
25
+ regexp.lastIndex = 0;
26
+ return matches ? undefined : message();
27
+ };
28
+ };
29
+ /**
30
+ * Checks absolute URLs and, when enabled, relative URL paths.
31
+ */
32
+ const url = (params) => {
33
+ const { protocols, allowRelative = false, message } = {
34
+ ...params,
35
+ message: { ...validationMessages.url, ...params?.message }
36
+ };
37
+ const normalizedProtocols = protocols?.map((protocol) => protocol.toLowerCase().replace(/:$/, '')).filter(Boolean);
38
+ return ({ val }) => {
39
+ if (!checkVal(val))
40
+ return undefined;
41
+ if (typeof val !== 'string' || !val.length)
42
+ return message.base();
43
+ let parsed;
44
+ let relative = false;
45
+ try {
46
+ parsed = new URL(val);
47
+ }
48
+ catch {
49
+ if (!allowRelative || !val.startsWith('/') || val.startsWith('//'))
50
+ return message.base();
51
+ parsed = new URL(val, 'https://azure-net.local');
52
+ relative = true;
53
+ }
54
+ if (!relative && normalizedProtocols?.length && !normalizedProtocols.includes(parsed.protocol.slice(0, -1).toLowerCase())) {
55
+ return message.protocol(normalizedProtocols.join(', '));
56
+ }
57
+ return undefined;
58
+ };
59
+ };
60
+ /**
61
+ * Checks one or multiple File/Blob values and optional size, MIME type and extension constraints.
62
+ */
63
+ const file = (params) => {
64
+ const { maxSize, mimeTypes, extensions, message } = {
65
+ ...params,
66
+ message: { ...validationMessages.file, ...params?.message }
67
+ };
68
+ const normalizedMimeTypes = mimeTypes?.map((mimeType) => mimeType.trim().toLowerCase()).filter(Boolean);
69
+ const normalizedExtensions = extensions?.map((extension) => extension.trim().toLowerCase().replace(/^\./, '')).filter(Boolean);
70
+ const isBlobLike = (value) => typeof value === 'object' &&
71
+ value !== null &&
72
+ typeof value.size === 'number' &&
73
+ typeof value.type === 'string' &&
74
+ typeof value.arrayBuffer === 'function';
75
+ const matchesMimeType = (actual, expected) => {
76
+ if (expected === '*/*')
77
+ return true;
78
+ if (expected.endsWith('/*'))
79
+ return actual.startsWith(expected.slice(0, -1));
80
+ return actual === expected;
81
+ };
82
+ return ({ val }) => {
83
+ if (!checkVal(val))
84
+ return undefined;
85
+ const rawFiles = Array.isArray(val) ? val : typeof FileList !== 'undefined' && val instanceof FileList ? Array.from(val) : [val];
86
+ if (!rawFiles.length || !rawFiles.every(isBlobLike))
87
+ return message.base();
88
+ for (const currentFile of rawFiles) {
89
+ if (maxSize !== undefined && currentFile.size > maxSize)
90
+ return message.maxSize(maxSize);
91
+ const mimeType = currentFile.type.toLowerCase();
92
+ if (normalizedMimeTypes?.length && !normalizedMimeTypes.some((allowed) => matchesMimeType(mimeType, allowed))) {
93
+ return message.mimeType(normalizedMimeTypes.join(', '));
94
+ }
95
+ if (normalizedExtensions?.length) {
96
+ const fileName = currentFile.name?.toLowerCase() ?? '';
97
+ const extension = fileName.includes('.') ? (fileName.split('.').pop() ?? '') : '';
98
+ if (!normalizedExtensions.includes(extension))
99
+ return message.extension(normalizedExtensions.join(', '));
100
+ }
101
+ }
102
+ return undefined;
103
+ };
104
+ };
12
105
  /**
13
106
  *
14
107
  * @param params - ValidationRuleParams<'string', LengthParams>
@@ -136,6 +229,8 @@ export const createRules = (validationMessages) => {
136
229
  listValues,
137
230
  key: `${key}[${index}]`
138
231
  });
232
+ if (fail === SKIP_REMAINING_VALIDATION)
233
+ break;
139
234
  if (fail) {
140
235
  itemErrors['_error'] = fail;
141
236
  break;
@@ -156,6 +251,8 @@ export const createRules = (validationMessages) => {
156
251
  listValues,
157
252
  key: `${key}[${index}].${fieldKey}`
158
253
  });
254
+ if (fail === SKIP_REMAINING_VALIDATION)
255
+ break;
159
256
  if (fail) {
160
257
  itemErrors[fieldKey] = fail;
161
258
  break;
@@ -176,73 +273,109 @@ export const createRules = (validationMessages) => {
176
273
  };
177
274
  /**
178
275
  *
179
- * @param params - ValidationRuleParams<'phone'>
276
+ * @param params - ValidationRuleParams<'phone', PhoneParams>
180
277
  * @returns ValidationRuleResult<T, D>
181
278
  * @description Checks if the value is a phone number and if it is valid.
182
279
  */
183
280
  const phone = (params) => {
184
- const { message } = { ...params, message: params?.message ?? validationMessages.phone };
281
+ const { requireCountryCode = false, minDigits = 7, maxDigits = 15, message } = {
282
+ ...params,
283
+ message: { ...validationMessages.phone, ...params?.message }
284
+ };
185
285
  return ({ val }) => {
186
286
  if (checkVal(val)) {
187
287
  const rawVal = String(val).trim();
188
288
  if (!rawVal) {
189
- return message();
289
+ return message.base();
190
290
  }
191
291
  if (!/^[\d+\s().-]+$/.test(rawVal)) {
192
- return message();
292
+ return message.base();
193
293
  }
194
294
  const normalized = rawVal.replace(/[\s().-]/g, '');
195
295
  if (!normalized) {
196
- return message();
296
+ return message.base();
197
297
  }
198
298
  const plusCount = (normalized.match(/\+/g) ?? []).length;
199
299
  if (plusCount > 1 || (plusCount === 1 && !normalized.startsWith('+'))) {
200
- return message();
300
+ return message.base();
201
301
  }
202
302
  const hasInternationalPrefix = normalized.startsWith('+');
203
303
  const digitsOnly = hasInternationalPrefix ? normalized.slice(1) : normalized;
204
304
  if (!/^\d+$/.test(digitsOnly)) {
205
- return message();
206
- }
207
- if (hasInternationalPrefix) {
208
- return /^[1-9]\d{6,14}$/.test(digitsOnly) ? undefined : message();
305
+ return message.base();
209
306
  }
210
- return /^\d{7,15}$/.test(digitsOnly) ? undefined : message();
307
+ if (requireCountryCode && !hasInternationalPrefix)
308
+ return message.countryCode();
309
+ if (hasInternationalPrefix && digitsOnly.startsWith('0'))
310
+ return message.base();
311
+ if (digitsOnly.length < minDigits)
312
+ return params?.minDigits === undefined ? message.base() : message.minDigits(minDigits);
313
+ if (digitsOnly.length > maxDigits)
314
+ return params?.maxDigits === undefined ? message.base() : message.maxDigits(maxDigits);
315
+ return undefined;
211
316
  }
212
317
  return undefined;
213
318
  };
214
319
  };
215
320
  /**
216
321
  *
217
- * @param params - ValidationRuleParams<'date'>
322
+ * @param params - ValidationRuleParams<'date', DateRangeParams>
218
323
  * @returns ValidationRuleResult<T, D>
219
324
  * @description Checks if the value is a valid date.
220
325
  */
221
326
  const date = (params) => {
222
- const { message } = { ...params, message: params?.message ?? validationMessages.date };
327
+ const { message, range } = { ...params, message: { ...validationMessages.date, ...params?.message } };
223
328
  return ({ val }) => {
224
- if (checkVal(val)) {
225
- return val instanceof Date || typeof val === 'string' ? (DateUtil.isDate(val) ? undefined : message()) : message();
226
- }
329
+ if (!checkVal(val))
330
+ return undefined;
331
+ if (!(val instanceof Date || typeof val === 'string') || !DateUtil.isDate(val))
332
+ return message.base();
333
+ if (range?.min !== undefined && DateUtil.isBefore(val, range.min))
334
+ return message.min(range.min);
335
+ if (range?.max !== undefined && DateUtil.isAfter(val, range.max))
336
+ return message.max(range.max);
227
337
  return undefined;
228
338
  };
229
339
  };
340
+ /**
341
+ * Stops validation of the current field when the predicate returns false.
342
+ */
343
+ const condition = (predicate) => {
344
+ return (params) => (predicate(params) ? undefined : SKIP_REMAINING_VALIDATION);
345
+ };
230
346
  /**
231
347
  *
232
- * @param params - ValidationRuleParams<'email'>
348
+ * @param params - ValidationRuleParams<'email', EmailParams>
233
349
  * @returns ValidationRuleResult<T, D>
234
350
  * @description Checks if the value is a valid email address.
235
351
  */
236
352
  const email = (params) => {
237
- const { message } = { message: params?.message ?? validationMessages.email };
353
+ const { trim = false, maxLength, allowedDomains, blockedDomains, message } = {
354
+ ...params,
355
+ message: { ...validationMessages.email, ...params?.message }
356
+ };
357
+ const normalizeDomain = (domain) => domain.trim().toLowerCase().replace(/^@/, '');
358
+ const normalizedAllowedDomains = allowedDomains?.map(normalizeDomain).filter(Boolean);
359
+ const normalizedBlockedDomains = blockedDomains?.map(normalizeDomain).filter(Boolean);
238
360
  const emailRegExp =
239
361
  // eslint-disable-next-line no-control-regex
240
362
  /^(?:[A-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|[\x01-\x09\x0B\x0C\x0E-\x7F])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]{2,}(?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21-\x5A\x53-\x7F]|\\[\x01-\x09\x0B\x0C\x0E-\x7F])+)])$/i;
241
363
  return ({ val }) => {
242
- if (checkVal(val)) {
243
- const stringedVal = typeof val === 'string' ? String(val) : undefined;
244
- return stringedVal && emailRegExp.test(stringedVal) ? undefined : message();
364
+ if (!checkVal(val))
365
+ return undefined;
366
+ if (typeof val !== 'string')
367
+ return message.base();
368
+ const emailValue = trim ? val.trim() : val;
369
+ if (!emailRegExp.test(emailValue))
370
+ return message.base();
371
+ if (maxLength !== undefined && emailValue.length > maxLength)
372
+ return message.maxLength(maxLength);
373
+ const domain = normalizeDomain(emailValue.slice(emailValue.lastIndexOf('@') + 1));
374
+ if (normalizedAllowedDomains?.length && !normalizedAllowedDomains.includes(domain)) {
375
+ return message.allowedDomain(normalizedAllowedDomains.join(', '));
245
376
  }
377
+ if (normalizedBlockedDomains?.length && normalizedBlockedDomains.includes(domain))
378
+ return message.blockedDomain(domain);
246
379
  return undefined;
247
380
  };
248
381
  };
@@ -377,5 +510,24 @@ export const createRules = (validationMessages) => {
377
510
  return undefined;
378
511
  };
379
512
  };
380
- return { string, number, required, password, notSameAs, sameAs, array, boolean, email, finite, lettersOnly, phone, date, allowedOnly };
513
+ return {
514
+ string,
515
+ number,
516
+ required,
517
+ password,
518
+ notSameAs,
519
+ sameAs,
520
+ array,
521
+ boolean,
522
+ email,
523
+ finite,
524
+ lettersOnly,
525
+ phone,
526
+ date,
527
+ condition,
528
+ pattern,
529
+ url,
530
+ file,
531
+ allowedOnly
532
+ };
381
533
  };
@@ -1,7 +1,32 @@
1
1
  export const validationMessagesEn = {
2
- date: () => 'Invalid date format',
3
- phone: () => 'Invalid phone number format',
4
- email: () => 'Invalid email address',
2
+ pattern: () => 'Invalid field format',
3
+ url: {
4
+ base: () => 'Invalid URL format',
5
+ protocol: (value) => `URL protocol must be one of: ${value}`
6
+ },
7
+ file: {
8
+ base: () => 'This field must contain a file',
9
+ maxSize: (value) => `File size must not exceed ${value} bytes`,
10
+ mimeType: (value) => `File type must be one of: ${value}`,
11
+ extension: (value) => `File extension must be one of: ${value}`
12
+ },
13
+ date: {
14
+ base: () => 'Invalid date format',
15
+ min: (value) => `The date must be on or after ${value instanceof Date ? value.toISOString() : value}`,
16
+ max: (value) => `The date must be on or before ${value instanceof Date ? value.toISOString() : value}`
17
+ },
18
+ phone: {
19
+ base: () => 'Invalid phone number format',
20
+ countryCode: () => 'Phone number must include an international country code',
21
+ minDigits: (value) => `Phone number must contain at least ${value} digits`,
22
+ maxDigits: (value) => `Phone number must contain at most ${value} digits`
23
+ },
24
+ email: {
25
+ base: () => 'Invalid email address',
26
+ maxLength: (value) => `Email address must not exceed ${value} characters`,
27
+ allowedDomain: (value) => `Email domain must be one of: ${value}`,
28
+ blockedDomain: (value) => `Email domain is not allowed: ${value}`
29
+ },
5
30
  required: () => 'This field is required',
6
31
  lettersOnly: (whiteSpaces) => `This field may contain letters only${whiteSpaces ? '' : ' and must not contain spaces'}`,
7
32
  allowedOnly: (value) => value && value.length ? `This field may contain only one of the following values: ${value}` : 'This field has no allowed values',
@@ -1,7 +1,32 @@
1
1
  export const validationMessagesRu = {
2
- date: () => 'Неверный формат даты',
3
- phone: () => 'Неверный формат номера телефона',
4
- email: () => 'Невалидный email',
2
+ pattern: () => 'Значение не соответствует требуемому формату',
3
+ url: {
4
+ base: () => 'Неверный формат URL',
5
+ protocol: (value) => `Протокол URL должен быть одним из: ${value}`
6
+ },
7
+ file: {
8
+ base: () => 'Поле должно содержать файл',
9
+ maxSize: (value) => `Размер файла не должен превышать ${value} байт`,
10
+ mimeType: (value) => `Тип файла должен быть одним из: ${value}`,
11
+ extension: (value) => `Расширение файла должно быть одним из: ${value}`
12
+ },
13
+ date: {
14
+ base: () => 'Неверный формат даты',
15
+ min: (value) => `Дата должна быть не раньше ${value instanceof Date ? value.toISOString() : value}`,
16
+ max: (value) => `Дата должна быть не позже ${value instanceof Date ? value.toISOString() : value}`
17
+ },
18
+ phone: {
19
+ base: () => 'Неверный формат номера телефона',
20
+ countryCode: () => 'Номер телефона должен содержать международный код страны',
21
+ minDigits: (value) => `Номер телефона должен содержать не менее ${value} цифр`,
22
+ maxDigits: (value) => `Номер телефона должен содержать не более ${value} цифр`
23
+ },
24
+ email: {
25
+ base: () => 'Невалидный email',
26
+ maxLength: (value) => `Email не должен быть длиннее ${value} символов`,
27
+ allowedDomain: (value) => `Домен email должен быть одним из: ${value}`,
28
+ blockedDomain: (value) => `Домен email запрещен: ${value}`
29
+ },
5
30
  required: () => 'Поле обязательно к заполнению',
6
31
  lettersOnly: (whiteSpaces) => `Поле может содержать только буквы ${whiteSpaces ? '' : 'и не должно содержать пробелы'}`,
7
32
  allowedOnly: (value) => value && value.length ? `Поле может содержать только одно из следующих значений:: ${value}` : 'Поле не имеет допустимых значений',
@@ -1,8 +1,33 @@
1
1
  import type { ValidationMessage } from '../../index.js';
2
2
  export type BaseValidationMessages = {
3
- date: () => ValidationMessage;
4
- phone: () => ValidationMessage;
5
- email: () => ValidationMessage;
3
+ pattern: () => ValidationMessage;
4
+ url: {
5
+ base: () => ValidationMessage;
6
+ protocol: (value: string) => ValidationMessage;
7
+ };
8
+ file: {
9
+ base: () => ValidationMessage;
10
+ maxSize: (value: number) => ValidationMessage;
11
+ mimeType: (value: string) => ValidationMessage;
12
+ extension: (value: string) => ValidationMessage;
13
+ };
14
+ date: {
15
+ base: () => ValidationMessage;
16
+ min: (value: Date | string) => ValidationMessage;
17
+ max: (value: Date | string) => ValidationMessage;
18
+ };
19
+ phone: {
20
+ base: () => ValidationMessage;
21
+ countryCode: () => ValidationMessage;
22
+ minDigits: (value: number) => ValidationMessage;
23
+ maxDigits: (value: number) => ValidationMessage;
24
+ };
25
+ email: {
26
+ base: () => ValidationMessage;
27
+ maxLength: (value: number) => ValidationMessage;
28
+ allowedDomain: (value: string) => ValidationMessage;
29
+ blockedDomain: (value: string) => ValidationMessage;
30
+ };
6
31
  required: () => ValidationMessage;
7
32
  lettersOnly: (whiteSpaces: boolean) => ValidationMessage;
8
33
  allowedOnly: (allowed: string) => ValidationMessage;
@@ -1,7 +1,32 @@
1
1
  export const validationMessagesI18n = {
2
- date: () => 'validation.date',
3
- phone: () => 'validation.phone',
4
- email: () => 'validation.email',
2
+ pattern: () => 'validation.pattern',
3
+ url: {
4
+ base: () => 'validation.url',
5
+ protocol: (value) => ({ key: 'validation.urlProtocol', vars: { value } })
6
+ },
7
+ file: {
8
+ base: () => 'validation.file',
9
+ maxSize: (value) => ({ key: 'validation.fileMaxSize', vars: { value } }),
10
+ mimeType: (value) => ({ key: 'validation.fileMimeType', vars: { value } }),
11
+ extension: (value) => ({ key: 'validation.fileExtension', vars: { value } })
12
+ },
13
+ date: {
14
+ base: () => 'validation.date',
15
+ min: (value) => ({ key: 'validation.dateMin', vars: { value: value instanceof Date ? value.toISOString() : value } }),
16
+ max: (value) => ({ key: 'validation.dateMax', vars: { value: value instanceof Date ? value.toISOString() : value } })
17
+ },
18
+ phone: {
19
+ base: () => 'validation.phone',
20
+ countryCode: () => 'validation.phoneCountryCode',
21
+ minDigits: (value) => ({ key: 'validation.phoneMinDigits', vars: { value } }),
22
+ maxDigits: (value) => ({ key: 'validation.phoneMaxDigits', vars: { value } })
23
+ },
24
+ email: {
25
+ base: () => 'validation.email',
26
+ maxLength: (value) => ({ key: 'validation.emailMaxLength', vars: { value } }),
27
+ allowedDomain: (value) => ({ key: 'validation.emailAllowedDomain', vars: { value } }),
28
+ blockedDomain: (value) => ({ key: 'validation.emailBlockedDomain', vars: { value } })
29
+ },
5
30
  required: () => 'validation.required',
6
31
  lettersOnly: (whiteSpaces) => (whiteSpaces ? 'validation.lettersOnlyWithWhiteSpaces' : 'validation.lettersOnly'),
7
32
  allowedOnly: (value) => ({ key: value && value.length ? 'validation.allowedOnly.base' : 'validation.allowedOnly.nothing', vars: { value } }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-net/kit",
3
- "version": "5.1.0",
3
+ "version": "5.1.1",
4
4
  "license": "MIT",
5
5
  "author": "Pixel1917",
6
6
  "description": "Universal toolkit and library collection, developed as part of the Azure-net ecosystem",