@strictly/define 0.0.8 → 0.0.9

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.
Files changed (35) hide show
  1. package/.out/index.d.ts +2 -0
  2. package/.out/index.js +2 -0
  3. package/.out/transformers/flatteners/flatten_type_to.d.ts +1 -1
  4. package/.out/transformers/flatteners/flatten_type_to.js +1 -1
  5. package/.out/tsconfig.tsbuildinfo +1 -1
  6. package/.out/types/builders.d.ts +1 -2
  7. package/.out/types/builders.js +3 -7
  8. package/.out/validation/validator.d.ts +9 -7
  9. package/.out/validation/validator.js +6 -0
  10. package/.out/validation/validators/minimum_string_length_validator.js +1 -1
  11. package/.out/validation/validators/optional_validator_proxy.d.ts +13 -0
  12. package/.out/validation/validators/optional_validator_proxy.js +26 -0
  13. package/.out/validation/validators/regexp_validator.d.ts +29 -0
  14. package/.out/validation/validators/regexp_validator.js +37 -0
  15. package/.out/validation/validators/specs/minimum_string_length_validator.tests.d.ts +1 -0
  16. package/.out/validation/validators/specs/minimum_string_length_validator.tests.js +69 -0
  17. package/.out/validation/validators/specs/regexp_validator.tests.d.ts +1 -0
  18. package/.out/validation/validators/specs/regexp_validator.tests.js +98 -0
  19. package/.turbo/turbo-build.log +8 -8
  20. package/.turbo/turbo-check-types.log +1 -1
  21. package/.turbo/turbo-release$colon$exports.log +1 -1
  22. package/dist/index.cjs +87 -8
  23. package/dist/index.d.cts +53 -10
  24. package/dist/index.d.ts +53 -10
  25. package/dist/index.js +83 -8
  26. package/index.ts +2 -0
  27. package/package.json +1 -1
  28. package/transformers/flatteners/flatten_type_to.ts +2 -2
  29. package/types/builders.ts +4 -13
  30. package/validation/validator.ts +13 -4
  31. package/validation/validators/minimum_string_length_validator.ts +1 -1
  32. package/validation/validators/optional_validator_proxy.ts +52 -0
  33. package/validation/validators/regexp_validator.ts +61 -0
  34. package/validation/validators/specs/minimum_string_length_validator.tests.ts +76 -0
  35. package/validation/validators/specs/regexp_validator.tests.ts +108 -0
@@ -9,8 +9,7 @@ declare class TypeDefBuilder<T extends ValidatingTypeDef> implements ValidatingT
9
9
  readonly definition: T;
10
10
  constructor(definition: T);
11
11
  enforce<E2>(rule: Rule<E2, ValueOfType<Type<T>>> | Validator<ValueOfType<Type<T>>, E2, never, never>): TypeDefBuilder<ValidatingTypeDefWithError<T, E2>>;
12
- required(): TypeDefBuilder<ValidatingTypeDefWithError<T, never>>;
13
- required<RequiredError>(rule: Rule<RequiredError, ValueOfType<typeof this.narrow>>): TypeDefBuilder<ValidatingTypeDefWithError<T, RequiredError>>;
12
+ required(): TypeDefBuilder<T>;
14
13
  readonly(): TypeDefBuilder<T>;
15
14
  get _type(): TypeOfType<Type<T>>;
16
15
  get narrow(): ValidatingType<T>;
@@ -1,4 +1,4 @@
1
- import { isAnnotatedValidator, validate, } from 'validation/validator';
1
+ import { isAnnotatedValidator, mergeAnnotations, validate, } from 'validation/validator';
2
2
  import { TypeDefType, } from './definitions';
3
3
  import { typeOfType, } from './type_of_type';
4
4
  function emptyRule() {
@@ -14,7 +14,7 @@ class TypeDefBuilder {
14
14
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
15
15
  {
16
16
  ...this.definition,
17
- ...(isAnnotatedValidator(rule) ? rule.annotations(null, null) : {}),
17
+ ...(isAnnotatedValidator(rule) ? mergeAnnotations(rule.annotations(null, null), this.definition) : {}),
18
18
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
19
  rule: (value) => {
20
20
  return this.definition.rule(value) ?? validate(rule, value, null, null);
@@ -22,15 +22,11 @@ class TypeDefBuilder {
22
22
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
23
  });
24
24
  }
25
- required(rule) {
25
+ required() {
26
26
  return new TypeDefBuilder(
27
27
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
28
28
  {
29
29
  ...this.definition,
30
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
- rule: (v) => {
32
- return this.definition.rule(v) || rule?.(v);
33
- },
34
30
  required: true,
35
31
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
32
  });
@@ -1,11 +1,12 @@
1
1
  import { type Simplify } from 'type-fest';
2
+ export type Annotations = {
3
+ readonly required: boolean;
4
+ readonly readonly: boolean;
5
+ };
2
6
  export type FunctionalValidator<V = any, E = any, ValuePath extends string = any, Context = any> = (v: V, valuePath: ValuePath, context: Context) => E | null;
3
7
  export type AnnotatedValidator<V = any, E = any, ValuePath extends string = any, Context = any> = {
4
8
  readonly validate: (v: V, valuePath: ValuePath, context: Context) => E | null;
5
- readonly annotations: (valuePath: ValuePath, context: Context) => {
6
- readonly required: boolean;
7
- readonly readonly: boolean;
8
- };
9
+ readonly annotations: (valuePath: ValuePath, context: Context) => Annotations;
9
10
  };
10
11
  export type Validator<V = any, E = any, ValuePath extends string = any, Context = any> = FunctionalValidator<V, E, ValuePath, Context> | AnnotatedValidator<V, E, ValuePath, Context>;
11
12
  export type ErrorOfValidator<V extends Validator> = V extends Validator<infer _V, infer E> ? E : never;
@@ -15,7 +16,8 @@ export type ValidationError<Type extends string, Data = {}> = Simplify<{
15
16
  export declare function isFunctionalValidator<V, E, ValuePath extends string, Context>(v: Validator<V, E, ValuePath, Context>): v is FunctionalValidator<V, E, ValuePath, Context>;
16
17
  export declare function isAnnotatedValidator<V, E, ValuePath extends string, Context>(v: Validator<V, E, ValuePath, Context>): v is AnnotatedValidator<V, E, ValuePath, Context>;
17
18
  export declare function validate<V = any, E = any, ValuePath extends string = any, Context = any>(validator: Validator<V, E, ValuePath, Context>, v: V, valuePath: ValuePath, context: Context): E | null;
18
- export declare function annotations<V = any, E = any, ValuePath extends string = any, Context = any>(validator: Validator<V, E, ValuePath, Context>, valuePath: ValuePath, context: Context): {
19
- readonly required: boolean;
20
- readonly readonly: boolean;
19
+ export declare function annotations<V = any, E = any, ValuePath extends string = any, Context = any>(validator: Validator<V, E, ValuePath, Context>, valuePath: ValuePath, context: Context): Annotations;
20
+ export declare function mergeAnnotations(a1: Annotations, a2: Annotations): {
21
+ readonly: boolean;
22
+ required: boolean;
21
23
  };
@@ -23,3 +23,9 @@ export function annotations(validator, valuePath, context) {
23
23
  };
24
24
  }
25
25
  }
26
+ export function mergeAnnotations(a1, a2) {
27
+ return {
28
+ readonly: a1.readonly || a2.readonly,
29
+ required: a1.required || a2.required,
30
+ };
31
+ }
@@ -16,7 +16,7 @@ export class MinimumStringLengthValidator {
16
16
  }
17
17
  annotations() {
18
18
  return {
19
- required: true,
19
+ required: this.minimumLength > 0,
20
20
  readonly: false,
21
21
  };
22
22
  }
@@ -0,0 +1,13 @@
1
+ import { type AnnotatedValidator } from 'validation/validator';
2
+ export declare class OptionalValidatorProxy<V, V1 extends V, E, ValuePath extends string, Context> implements AnnotatedValidator<V, E, ValuePath, Context> {
3
+ private readonly proxied;
4
+ private readonly isRequired;
5
+ static createNullable<V, E, ValuePath extends string, Context>(proxied: AnnotatedValidator<NonNullable<V>, E, ValuePath, Context>): OptionalValidatorProxy<V, NonNullable<V>, E, ValuePath, Context>;
6
+ static createNullableOrEmptyString<V extends string | null | undefined, E, ValuePath extends string, Context>(proxied: AnnotatedValidator<NonNullable<V>, E, ValuePath, Context>): OptionalValidatorProxy<V, NonNullable<V>, E, ValuePath, Context>;
7
+ constructor(proxied: AnnotatedValidator<V1, E, ValuePath, Context>, isRequired: (v: V) => v is V1);
8
+ validate(v: V, valuePath: ValuePath, context: Context): E | null;
9
+ annotations(valuePath: ValuePath, context: Context): {
10
+ required: boolean;
11
+ readonly: boolean;
12
+ };
13
+ }
@@ -0,0 +1,26 @@
1
+ export class OptionalValidatorProxy {
2
+ proxied;
3
+ isRequired;
4
+ static createNullable(proxied) {
5
+ return new OptionalValidatorProxy(proxied, (v) => v != null);
6
+ }
7
+ static createNullableOrEmptyString(proxied) {
8
+ return new OptionalValidatorProxy(proxied, (v) => v != null && v !== '');
9
+ }
10
+ constructor(proxied, isRequired) {
11
+ this.proxied = proxied;
12
+ this.isRequired = isRequired;
13
+ }
14
+ validate(v, valuePath, context) {
15
+ if (this.isRequired(v)) {
16
+ return this.proxied.validate(v, valuePath, context);
17
+ }
18
+ return null;
19
+ }
20
+ annotations(valuePath, context) {
21
+ return {
22
+ ...this.proxied.annotations(valuePath, context),
23
+ required: false,
24
+ };
25
+ }
26
+ }
@@ -0,0 +1,29 @@
1
+ import { type AnnotatedValidator } from 'validation/validator';
2
+ export declare const RegexpValidationErrorType = "regexp";
3
+ export type RegexpValidationError<Intent extends string> = {
4
+ type: typeof RegexpValidationErrorType;
5
+ intent: Intent;
6
+ };
7
+ export declare class RegexpValidator<Intent extends string> implements AnnotatedValidator<string, RegexpValidationError<Intent>, never, never> {
8
+ private readonly regexp;
9
+ private readonly intent;
10
+ /**
11
+ * Extremely permissive email validator
12
+ */
13
+ static readonly email: RegexpValidator<"email">;
14
+ /**
15
+ * Extremely permissive phone number validator
16
+ */
17
+ static readonly phone: RegexpValidator<"phone">;
18
+ private readonly negate;
19
+ private readonly required;
20
+ constructor(regexp: RegExp, intent: Intent, { negate, required, }?: {
21
+ negate?: boolean;
22
+ required?: boolean;
23
+ });
24
+ validate(value: string): RegexpValidationError<Intent> | null;
25
+ annotations(): {
26
+ required: boolean;
27
+ readonly: boolean;
28
+ };
29
+ }
@@ -0,0 +1,37 @@
1
+ export const RegexpValidationErrorType = 'regexp';
2
+ export class RegexpValidator {
3
+ regexp;
4
+ intent;
5
+ /**
6
+ * Extremely permissive email validator
7
+ */
8
+ static email = new RegexpValidator(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, 'email');
9
+ /**
10
+ * Extremely permissive phone number validator
11
+ */
12
+ static phone = new RegexpValidator(/^(\+\d{1,4}[\s]*)?(((\([\d\s-]{1,6}\))|\d)[\s-]*){3,14}(\d|(\(\d+\)))$/, 'phone');
13
+ negate;
14
+ required;
15
+ constructor(regexp, intent, { negate = false, required = false, } = {}) {
16
+ this.regexp = regexp;
17
+ this.intent = intent;
18
+ this.negate = negate;
19
+ this.required = required;
20
+ }
21
+ validate(value) {
22
+ const passes = this.regexp.test(value);
23
+ if (!passes && !this.negate || passes && this.negate) {
24
+ return {
25
+ type: RegexpValidationErrorType,
26
+ intent: this.intent,
27
+ };
28
+ }
29
+ return null;
30
+ }
31
+ annotations() {
32
+ return {
33
+ required: this.required,
34
+ readonly: false,
35
+ };
36
+ }
37
+ }
@@ -0,0 +1,69 @@
1
+ import { MinimumStringLengthValidationErrorType, MinimumStringLengthValidator, } from 'validation/validators/minimum_string_length_validator';
2
+ describe('MinimumStringLengthValidator', () => {
3
+ describe('required', () => {
4
+ it.each([
5
+ 1,
6
+ 2,
7
+ 100,
8
+ ])('is required when the string length is %s', (minimumLength) => {
9
+ const validator = new MinimumStringLengthValidator(minimumLength);
10
+ expect(validator.annotations().required).toBeTruthy();
11
+ });
12
+ it('is not required when the string length is zero', () => {
13
+ const validator = new MinimumStringLengthValidator(0);
14
+ expect(validator.annotations().required).toBeFalsy();
15
+ });
16
+ });
17
+ describe('validation', () => {
18
+ it.each([
19
+ [
20
+ 1,
21
+ 'a',
22
+ ],
23
+ [
24
+ 2,
25
+ 'asdf',
26
+ ],
27
+ [
28
+ 0,
29
+ '',
30
+ ],
31
+ [
32
+ 20,
33
+ '12345678901234567890',
34
+ ],
35
+ ])('passes validation with minimum length %s and value "%s"', (minimumLength, value) => {
36
+ const validator = new MinimumStringLengthValidator(minimumLength);
37
+ expect(validator.validate(value)).toBeNull();
38
+ });
39
+ it.each([
40
+ [
41
+ 1,
42
+ '',
43
+ 0,
44
+ ],
45
+ [
46
+ 2,
47
+ 'a',
48
+ 1,
49
+ ],
50
+ [
51
+ 20,
52
+ '1234567890123456789',
53
+ 19,
54
+ ],
55
+ [
56
+ 100,
57
+ '',
58
+ 0,
59
+ ],
60
+ ])('fails validation with minimum length %s and value "%s', (minimumLength, value, receivedLength) => {
61
+ const validator = new MinimumStringLengthValidator(minimumLength);
62
+ expect(validator.validate(value)).toEqual({
63
+ type: MinimumStringLengthValidationErrorType,
64
+ minimumLength,
65
+ receivedLength,
66
+ });
67
+ });
68
+ });
69
+ });
@@ -0,0 +1,98 @@
1
+ import { RegexpValidationErrorType, RegexpValidator, } from 'validation/validators/regexp_validator';
2
+ describe('RegexpValidator', () => {
3
+ describe('phone', () => {
4
+ it.each([
5
+ '0403545000',
6
+ '+12 (1800) 000 000',
7
+ '1-2-3-4-5-6',
8
+ '+1 394 3234 000 (2)',
9
+ '1234',
10
+ ])('accepts "%s"', (phoneNumber) => {
11
+ expect(RegexpValidator.phone.validate(phoneNumber)).toBeNull();
12
+ });
13
+ it.each([
14
+ '',
15
+ 'ABC',
16
+ '1',
17
+ ' 0412345678',
18
+ '----1245456',
19
+ '1 2',
20
+ '234234+234',
21
+ ])('rejects "%s"', (phoneNumber) => {
22
+ expect(RegexpValidator.phone.validate(phoneNumber)).toEqual({
23
+ type: RegexpValidationErrorType,
24
+ intent: 'phone',
25
+ });
26
+ });
27
+ });
28
+ describe('email', () => {
29
+ it.each([
30
+ 'x@y.z',
31
+ 'support@company.com',
32
+ '...@......',
33
+ '1234@3454.23',
34
+ ])('accepts "%s"', (email) => {
35
+ expect(RegexpValidator.email.validate(email)).toBeNull();
36
+ });
37
+ it.each([
38
+ '',
39
+ '@@@@',
40
+ 'email',
41
+ '@bee.com',
42
+ 'aaa@bbb',
43
+ 'a a@b b.c c',
44
+ ])('rejects "%s"', (email) => {
45
+ expect(RegexpValidator.email.validate(email)).toEqual({
46
+ type: RegexpValidationErrorType,
47
+ intent: 'email',
48
+ });
49
+ });
50
+ });
51
+ describe('required', () => {
52
+ it.each([
53
+ true,
54
+ false,
55
+ ])('exposes required %s', (required) => {
56
+ const validator = new RegexpValidator(/a/, 'test', {
57
+ required,
58
+ });
59
+ expect(validator.annotations().required).toBe(required);
60
+ });
61
+ });
62
+ describe('general', () => {
63
+ // not here to test if regexp works
64
+ it.each([
65
+ [
66
+ '^a$',
67
+ 'a',
68
+ ],
69
+ [
70
+ '^\\w+$',
71
+ 'asdf',
72
+ ],
73
+ ])('passes validation with regexp "%s" and value "%s"', (regexpString, value) => {
74
+ const regexp = new RegExp(regexpString);
75
+ const validator = new RegexpValidator(regexp, 'test');
76
+ expect(validator.validate(value)).toBeNull();
77
+ });
78
+ it.each([
79
+ [
80
+ '^$',
81
+ 'something',
82
+ 'empty',
83
+ ],
84
+ [
85
+ '^\\w+$',
86
+ '',
87
+ 'non-empty',
88
+ ],
89
+ ])('fails validation with regexp "%s" and value "%s', (regexpString, value, intent) => {
90
+ const regexp = new RegExp(regexpString);
91
+ const validator = new RegexpValidator(regexp, intent);
92
+ expect(validator.validate(value)).toEqual({
93
+ type: RegexpValidationErrorType,
94
+ intent,
95
+ });
96
+ });
97
+ });
98
+ });
@@ -7,12 +7,12 @@ $ tsup
7
7
  CLI Target: esnext
8
8
  CJS Build start
9
9
  ESM Build start
10
- CJS dist/index.cjs 27.01 KB
11
- CJS ⚡️ Build success in 39ms
12
- ESM dist/index.js 24.82 KB
13
- ESM ⚡️ Build success in 41ms
10
+ CJS dist/index.cjs 29.06 KB
11
+ CJS ⚡️ Build success in 62ms
12
+ ESM dist/index.js 26.67 KB
13
+ ESM ⚡️ Build success in 63ms
14
14
  DTS Build start
15
- DTS ⚡️ Build success in 5294ms
16
- DTS dist/index.d.cts 38.21 KB
17
- DTS dist/index.d.ts 38.21 KB
18
- Done in 6.14s.
15
+ DTS ⚡️ Build success in 5551ms
16
+ DTS dist/index.d.cts 40.10 KB
17
+ DTS dist/index.d.ts 40.10 KB
18
+ Done in 6.43s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ tsc
3
- Done in 4.75s.
3
+ Done in 4.85s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ json -f package.json -f package.exports.json --merge > package.release.json
3
- Done in 0.12s.
3
+ Done in 0.11s.
package/dist/index.cjs CHANGED
@@ -23,6 +23,9 @@ __export(index_exports, {
23
23
  DefinedValidator: () => DefinedValidator,
24
24
  MinimumStringLengthValidationErrorType: () => MinimumStringLengthValidationErrorType,
25
25
  MinimumStringLengthValidator: () => MinimumStringLengthValidator,
26
+ OptionalValidatorProxy: () => OptionalValidatorProxy,
27
+ RegexpValidationErrorType: () => RegexpValidationErrorType,
28
+ RegexpValidator: () => RegexpValidator,
26
29
  TypeDefType: () => TypeDefType,
27
30
  annotations: () => annotations,
28
31
  booleanType: () => booleanType,
@@ -40,6 +43,7 @@ __export(index_exports, {
40
43
  jsonPathPop: () => jsonPathPop,
41
44
  list: () => list,
42
45
  literal: () => literal,
46
+ mergeAnnotations: () => mergeAnnotations,
43
47
  mobxCopy: () => mobxCopy,
44
48
  nullType: () => nullType,
45
49
  nullable: () => nullable,
@@ -430,7 +434,7 @@ function flattenTypeTo({ definition }, mapper2) {
430
434
  return (0, import_base4.reduce)(
431
435
  typeDefs,
432
436
  function(acc, key, typeDef) {
433
- acc[key] = mapper2(typeDef);
437
+ acc[key] = mapper2(typeDef, key);
434
438
  return acc;
435
439
  },
436
440
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -695,6 +699,12 @@ function annotations(validator, valuePath, context) {
695
699
  };
696
700
  }
697
701
  }
702
+ function mergeAnnotations(a1, a2) {
703
+ return {
704
+ readonly: a1.readonly || a2.readonly,
705
+ required: a1.required || a2.required
706
+ };
707
+ }
698
708
 
699
709
  // types/type_of_type.ts
700
710
  var import_base6 = require("@strictly/base");
@@ -786,7 +796,7 @@ var TypeDefBuilder = class _TypeDefBuilder {
786
796
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
787
797
  {
788
798
  ...this.definition,
789
- ...isAnnotatedValidator(rule) ? rule.annotations(null, null) : {},
799
+ ...isAnnotatedValidator(rule) ? mergeAnnotations(rule.annotations(null, null), this.definition) : {},
790
800
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
791
801
  rule: (value) => {
792
802
  return this.definition.rule(value) ?? validate(rule, value, null, null);
@@ -795,15 +805,11 @@ var TypeDefBuilder = class _TypeDefBuilder {
795
805
  }
796
806
  );
797
807
  }
798
- required(rule) {
808
+ required() {
799
809
  return new _TypeDefBuilder(
800
810
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
801
811
  {
802
812
  ...this.definition,
803
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
804
- rule: (v) => {
805
- return this.definition.rule(v) || rule?.(v);
806
- },
807
813
  required: true
808
814
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
809
815
  }
@@ -1045,7 +1051,76 @@ var MinimumStringLengthValidator = class {
1045
1051
  }
1046
1052
  annotations() {
1047
1053
  return {
1048
- required: true,
1054
+ required: this.minimumLength > 0,
1055
+ readonly: false
1056
+ };
1057
+ }
1058
+ };
1059
+
1060
+ // validation/validators/optional_validator_proxy.ts
1061
+ var OptionalValidatorProxy = class _OptionalValidatorProxy {
1062
+ constructor(proxied, isRequired) {
1063
+ this.proxied = proxied;
1064
+ this.isRequired = isRequired;
1065
+ }
1066
+ static createNullable(proxied) {
1067
+ return new _OptionalValidatorProxy(proxied, (v) => v != null);
1068
+ }
1069
+ static createNullableOrEmptyString(proxied) {
1070
+ return new _OptionalValidatorProxy(proxied, (v) => v != null && v !== "");
1071
+ }
1072
+ validate(v, valuePath, context) {
1073
+ if (this.isRequired(v)) {
1074
+ return this.proxied.validate(v, valuePath, context);
1075
+ }
1076
+ return null;
1077
+ }
1078
+ annotations(valuePath, context) {
1079
+ return {
1080
+ ...this.proxied.annotations(valuePath, context),
1081
+ required: false
1082
+ };
1083
+ }
1084
+ };
1085
+
1086
+ // validation/validators/regexp_validator.ts
1087
+ var RegexpValidationErrorType = "regexp";
1088
+ var RegexpValidator = class _RegexpValidator {
1089
+ constructor(regexp, intent, {
1090
+ negate = false,
1091
+ required = false
1092
+ } = {}) {
1093
+ this.regexp = regexp;
1094
+ this.intent = intent;
1095
+ this.negate = negate;
1096
+ this.required = required;
1097
+ }
1098
+ /**
1099
+ * Extremely permissive email validator
1100
+ */
1101
+ static email = new _RegexpValidator(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, "email");
1102
+ /**
1103
+ * Extremely permissive phone number validator
1104
+ */
1105
+ static phone = new _RegexpValidator(
1106
+ /^(\+\d{1,4}[\s]*)?(((\([\d\s-]{1,6}\))|\d)[\s-]*){3,14}(\d|(\(\d+\)))$/,
1107
+ "phone"
1108
+ );
1109
+ negate;
1110
+ required;
1111
+ validate(value) {
1112
+ const passes = this.regexp.test(value);
1113
+ if (!passes && !this.negate || passes && this.negate) {
1114
+ return {
1115
+ type: RegexpValidationErrorType,
1116
+ intent: this.intent
1117
+ };
1118
+ }
1119
+ return null;
1120
+ }
1121
+ annotations() {
1122
+ return {
1123
+ required: this.required,
1049
1124
  readonly: false
1050
1125
  };
1051
1126
  }
@@ -1055,6 +1130,9 @@ var MinimumStringLengthValidator = class {
1055
1130
  DefinedValidator,
1056
1131
  MinimumStringLengthValidationErrorType,
1057
1132
  MinimumStringLengthValidator,
1133
+ OptionalValidatorProxy,
1134
+ RegexpValidationErrorType,
1135
+ RegexpValidator,
1058
1136
  TypeDefType,
1059
1137
  annotations,
1060
1138
  booleanType,
@@ -1072,6 +1150,7 @@ var MinimumStringLengthValidator = class {
1072
1150
  jsonPathPop,
1073
1151
  list,
1074
1152
  literal,
1153
+ mergeAnnotations,
1075
1154
  mobxCopy,
1076
1155
  nullType,
1077
1156
  nullable,