@platecms/delta-validation 0.4.1 → 0.7.0

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 (149) hide show
  1. package/package.json +5 -6
  2. package/src/lib/enums/rule-types.enum.ts +10 -0
  3. package/src/lib/errors/invalid-validation-arguments.error.ts +1 -0
  4. package/src/lib/errors/invalid-validation-rule-settings.error.ts +1 -0
  5. package/src/lib/errors/validation-error-details.ts +15 -0
  6. package/src/lib/errors/validation.error.ts +18 -0
  7. package/src/lib/helpers/deserialize-validation-rule.ts +94 -0
  8. package/src/lib/helpers/rule-to-schema.spec.ts +254 -0
  9. package/src/lib/helpers/rule-to-schema.ts +95 -0
  10. package/src/lib/helpers/schema-builder.spec.ts +52 -0
  11. package/src/lib/helpers/schema-builder.ts +28 -0
  12. package/src/lib/helpers/validate-with-function.spec.ts +264 -0
  13. package/src/lib/helpers/validate-with-function.ts +45 -0
  14. package/src/lib/schemas/array.schema.spec.ts +127 -0
  15. package/src/lib/schemas/array.schema.ts +104 -0
  16. package/src/lib/schemas/base.schema.spec.ts +168 -0
  17. package/src/lib/schemas/base.schema.ts +150 -0
  18. package/src/lib/schemas/content-value.schema.spec.ts +133 -0
  19. package/src/lib/schemas/content-value.schema.ts +61 -0
  20. package/src/lib/schemas/date.schema.spec.ts +144 -0
  21. package/src/lib/schemas/date.schema.ts +82 -0
  22. package/src/lib/schemas/number.schema.spec.ts +232 -0
  23. package/src/lib/schemas/number.schema.ts +123 -0
  24. package/src/lib/schemas/string.schema.spec.ts +135 -0
  25. package/src/lib/schemas/string.schema.ts +73 -0
  26. package/src/lib/test-utils/setup-files.ts +1 -0
  27. package/src/lib/test-utils/validation-result-matcher.ts +71 -0
  28. package/src/lib/types/{existing-content-validation-rules-settings.type.d.ts → existing-content-validation-rules-settings.type.ts} +10 -1
  29. package/src/lib/types/{existing-content-validation-rules.type.d.ts → existing-content-validation-rules.type.ts} +10 -1
  30. package/src/lib/types/{existing-validation-schemas.type.d.ts → existing-validation-schemas.type.ts} +7 -1
  31. package/src/lib/types/rule-instance.interface.ts +9 -0
  32. package/src/lib/types/{validation-context.interface.d.ts → validation-context.interface.ts} +3 -2
  33. package/src/lib/types/{validation-error-data.interface.d.ts → validation-error-data.interface.ts} +5 -4
  34. package/src/lib/types/{validation-result.interface.d.ts → validation-result.interface.ts} +3 -2
  35. package/src/lib/types/validation-schema.interface.ts +15 -0
  36. package/src/lib/validation-rules/allowed-values.validation-rule.spec.ts +57 -0
  37. package/src/lib/validation-rules/allowed-values.validation-rule.ts +53 -0
  38. package/src/lib/validation-rules/base.validation-rule.ts +35 -0
  39. package/src/lib/validation-rules/count.validation-rule.spec.ts +67 -0
  40. package/src/lib/validation-rules/count.validation-rule.ts +60 -0
  41. package/src/lib/validation-rules/date-between.validation-rule.spec.ts +77 -0
  42. package/src/lib/validation-rules/date-between.validation-rule.ts +54 -0
  43. package/src/lib/validation-rules/decimal-count.validation-rule.spec.ts +46 -0
  44. package/src/lib/validation-rules/decimal-count.validation-rule.ts +52 -0
  45. package/src/lib/validation-rules/number-between.validation-rule.spec.ts +77 -0
  46. package/src/lib/validation-rules/number-between.validation-rule.ts +58 -0
  47. package/src/lib/validation-rules/relatable-content-types.validation-rule.spec.ts +35 -0
  48. package/src/lib/validation-rules/relatable-content-types.validation-rule.ts +61 -0
  49. package/src/lib/validation-rules/string-format.validation-rule.spec.ts +43 -0
  50. package/src/lib/validation-rules/string-format.validation-rule.ts +50 -0
  51. package/src/lib/validation-rules/validation-rule-function.factory.ts +23 -0
  52. package/src/lib/validation-rules/value-type.validation-rule.spec.ts +108 -0
  53. package/src/lib/validation-rules/value-type.validation-rule.ts +76 -0
  54. package/src/index.js +0 -23
  55. package/src/index.js.map +0 -1
  56. package/src/lib/enums/rule-types.enum.d.ts +0 -10
  57. package/src/lib/enums/rule-types.enum.js +0 -15
  58. package/src/lib/enums/rule-types.enum.js.map +0 -1
  59. package/src/lib/errors/invalid-validation-arguments.error.d.ts +0 -2
  60. package/src/lib/errors/invalid-validation-arguments.error.js +0 -7
  61. package/src/lib/errors/invalid-validation-arguments.error.js.map +0 -1
  62. package/src/lib/errors/invalid-validation-rule-settings.error.d.ts +0 -2
  63. package/src/lib/errors/invalid-validation-rule-settings.error.js +0 -7
  64. package/src/lib/errors/invalid-validation-rule-settings.error.js.map +0 -1
  65. package/src/lib/errors/validation-error-details.d.ts +0 -6
  66. package/src/lib/errors/validation-error-details.js +0 -18
  67. package/src/lib/errors/validation-error-details.js.map +0 -1
  68. package/src/lib/errors/validation.error.d.ts +0 -8
  69. package/src/lib/errors/validation.error.js +0 -13
  70. package/src/lib/errors/validation.error.js.map +0 -1
  71. package/src/lib/helpers/deserialize-validation-rule.d.ts +0 -2
  72. package/src/lib/helpers/deserialize-validation-rule.js +0 -42
  73. package/src/lib/helpers/deserialize-validation-rule.js.map +0 -1
  74. package/src/lib/helpers/rule-to-schema.d.ts +0 -4
  75. package/src/lib/helpers/rule-to-schema.js +0 -65
  76. package/src/lib/helpers/rule-to-schema.js.map +0 -1
  77. package/src/lib/helpers/schema-builder.d.ts +0 -12
  78. package/src/lib/helpers/schema-builder.js +0 -27
  79. package/src/lib/helpers/schema-builder.js.map +0 -1
  80. package/src/lib/helpers/validate-with-function.d.ts +0 -4
  81. package/src/lib/helpers/validate-with-function.js +0 -31
  82. package/src/lib/helpers/validate-with-function.js.map +0 -1
  83. package/src/lib/schemas/array.schema.d.ts +0 -17
  84. package/src/lib/schemas/array.schema.js +0 -84
  85. package/src/lib/schemas/array.schema.js.map +0 -1
  86. package/src/lib/schemas/base.schema.d.ts +0 -20
  87. package/src/lib/schemas/base.schema.js +0 -95
  88. package/src/lib/schemas/base.schema.js.map +0 -1
  89. package/src/lib/schemas/content-value.schema.d.ts +0 -15
  90. package/src/lib/schemas/content-value.schema.js +0 -42
  91. package/src/lib/schemas/content-value.schema.js.map +0 -1
  92. package/src/lib/schemas/date.schema.d.ts +0 -13
  93. package/src/lib/schemas/date.schema.js +0 -62
  94. package/src/lib/schemas/date.schema.js.map +0 -1
  95. package/src/lib/schemas/number.schema.d.ts +0 -16
  96. package/src/lib/schemas/number.schema.js +0 -84
  97. package/src/lib/schemas/number.schema.js.map +0 -1
  98. package/src/lib/schemas/string.schema.d.ts +0 -11
  99. package/src/lib/schemas/string.schema.js +0 -56
  100. package/src/lib/schemas/string.schema.js.map +0 -1
  101. package/src/lib/types/existing-content-validation-rules-settings.type.js +0 -3
  102. package/src/lib/types/existing-content-validation-rules-settings.type.js.map +0 -1
  103. package/src/lib/types/existing-content-validation-rules.type.js +0 -3
  104. package/src/lib/types/existing-content-validation-rules.type.js.map +0 -1
  105. package/src/lib/types/existing-validation-schemas.type.js +0 -3
  106. package/src/lib/types/existing-validation-schemas.type.js.map +0 -1
  107. package/src/lib/types/rule-instance.interface.d.ts +0 -6
  108. package/src/lib/types/rule-instance.interface.js +0 -3
  109. package/src/lib/types/rule-instance.interface.js.map +0 -1
  110. package/src/lib/types/validation-context.interface.js +0 -3
  111. package/src/lib/types/validation-context.interface.js.map +0 -1
  112. package/src/lib/types/validation-error-data.interface.js +0 -3
  113. package/src/lib/types/validation-error-data.interface.js.map +0 -1
  114. package/src/lib/types/validation-result.interface.js +0 -3
  115. package/src/lib/types/validation-result.interface.js.map +0 -1
  116. package/src/lib/types/validation-schema.interface.d.ts +0 -7
  117. package/src/lib/types/validation-schema.interface.js +0 -3
  118. package/src/lib/types/validation-schema.interface.js.map +0 -1
  119. package/src/lib/validation-rules/allowed-values.validation-rule.d.ts +0 -13
  120. package/src/lib/validation-rules/allowed-values.validation-rule.js +0 -36
  121. package/src/lib/validation-rules/allowed-values.validation-rule.js.map +0 -1
  122. package/src/lib/validation-rules/base.validation-rule.d.ts +0 -13
  123. package/src/lib/validation-rules/base.validation-rule.js +0 -14
  124. package/src/lib/validation-rules/base.validation-rule.js.map +0 -1
  125. package/src/lib/validation-rules/count.validation-rule.d.ts +0 -16
  126. package/src/lib/validation-rules/count.validation-rule.js +0 -36
  127. package/src/lib/validation-rules/count.validation-rule.js.map +0 -1
  128. package/src/lib/validation-rules/date-between.validation-rule.d.ts +0 -16
  129. package/src/lib/validation-rules/date-between.validation-rule.js +0 -36
  130. package/src/lib/validation-rules/date-between.validation-rule.js.map +0 -1
  131. package/src/lib/validation-rules/decimal-count.validation-rule.d.ts +0 -13
  132. package/src/lib/validation-rules/decimal-count.validation-rule.js +0 -37
  133. package/src/lib/validation-rules/decimal-count.validation-rule.js.map +0 -1
  134. package/src/lib/validation-rules/number-between.validation-rule.d.ts +0 -16
  135. package/src/lib/validation-rules/number-between.validation-rule.js +0 -37
  136. package/src/lib/validation-rules/number-between.validation-rule.js.map +0 -1
  137. package/src/lib/validation-rules/relatable-content-types.validation-rule.d.ts +0 -13
  138. package/src/lib/validation-rules/relatable-content-types.validation-rule.js +0 -37
  139. package/src/lib/validation-rules/relatable-content-types.validation-rule.js.map +0 -1
  140. package/src/lib/validation-rules/string-format.validation-rule.d.ts +0 -13
  141. package/src/lib/validation-rules/string-format.validation-rule.js +0 -35
  142. package/src/lib/validation-rules/string-format.validation-rule.js.map +0 -1
  143. package/src/lib/validation-rules/validation-rule-function.factory.d.ts +0 -4
  144. package/src/lib/validation-rules/validation-rule-function.factory.js +0 -9
  145. package/src/lib/validation-rules/validation-rule-function.factory.js.map +0 -1
  146. package/src/lib/validation-rules/value-type.validation-rule.d.ts +0 -13
  147. package/src/lib/validation-rules/value-type.validation-rule.js +0 -53
  148. package/src/lib/validation-rules/value-type.validation-rule.js.map +0 -1
  149. /package/src/{index.d.ts → index.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platecms/delta-validation",
3
- "version": "0.4.1",
3
+ "version": "0.7.0",
4
4
  "description": "This package contains the validation system for Plate.",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
@@ -17,12 +17,11 @@
17
17
  "src/**/*"
18
18
  ],
19
19
  "peerDependencies": {
20
- "@platecms/delta-cast": "0.4.1",
21
- "@platecms/delta-plate-resource-notation": "0.4.1",
22
- "@platecms/delta-types": "0.4.1",
20
+ "@platecms/delta-cast": "0.7.0",
21
+ "@platecms/delta-plate-resource-notation": "0.7.0",
22
+ "@platecms/delta-types": "0.7.0",
23
23
  "class-transformer": "0.5.1",
24
24
  "reflect-metadata": "0.2.2",
25
25
  "tslib": "2.8.1"
26
- },
27
- "type": "commonjs"
26
+ }
28
27
  }
@@ -0,0 +1,10 @@
1
+ export enum RuleType {
2
+ ALLOWED_VALUES = "ALLOWED_VALUES",
3
+ COUNT = "COUNT",
4
+ DATE_BETWEEN = "DATE_BETWEEN",
5
+ DECIMAL_COUNT = "DECIMAL_COUNT",
6
+ NUMBER_BETWEEN = "NUMBER_BETWEEN",
7
+ RELATABLE_CONTENT_TYPES = "RELATABLE_CONTENT_TYPES",
8
+ STRING_FORMAT = "STRING_FORMAT",
9
+ VALUE_TYPE = "VALUE_TYPE",
10
+ }
@@ -0,0 +1 @@
1
+ export class InvalidValidationArgumentsError extends Error {}
@@ -0,0 +1 @@
1
+ export class InvalidValidationRuleSettingsError extends Error {}
@@ -0,0 +1,15 @@
1
+ import { Transform } from "class-transformer";
2
+ import { deserializeValidationRule } from "../helpers/deserialize-validation-rule";
3
+ import { RuleInstance } from "../types/rule-instance.interface";
4
+
5
+ export class ValidationErrorDetails<TRuleInstance extends RuleInstance<unknown>> {
6
+ public readonly message: string;
7
+
8
+ @Transform((validationRule: unknown) => deserializeValidationRule(validationRule))
9
+ public readonly validationRule: TRuleInstance;
10
+
11
+ public constructor(message: string, validationRule: TRuleInstance) {
12
+ this.message = message;
13
+ this.validationRule = validationRule;
14
+ }
15
+ }
@@ -0,0 +1,18 @@
1
+ import { RuleInstance } from "../types/rule-instance.interface";
2
+ import { ValidationErrorData } from "../types/validation-error-data.interface";
3
+
4
+ export class ValidationError<TSettings extends object = object>
5
+ extends Error
6
+ implements ValidationErrorData<TSettings>
7
+ {
8
+ public readonly path: string[];
9
+ public readonly validationRule: RuleInstance<TSettings>;
10
+ public readonly provided: unknown;
11
+
12
+ public constructor(path: string[], message: string, validationRule: RuleInstance<TSettings>, provided: unknown) {
13
+ super(message);
14
+ this.path = path;
15
+ this.validationRule = validationRule;
16
+ this.provided = provided;
17
+ }
18
+ }
@@ -0,0 +1,94 @@
1
+ import { PRN } from "@platecms/delta-plate-resource-notation";
2
+ import { ExistingContentValidationRules } from "../types/existing-content-validation-rules.type";
3
+ import { RuleType } from "../enums/rule-types.enum";
4
+ import {
5
+ AllowedValuesValidationRule,
6
+ AllowedValuesValidationRuleSettings,
7
+ } from "../validation-rules/allowed-values.validation-rule";
8
+ import { CountValidationRule, CountValidationRuleSettings } from "../validation-rules/count.validation-rule";
9
+ import {
10
+ DateBetweenValidationRule,
11
+ DateBetweenValidationRuleSettings,
12
+ } from "../validation-rules/date-between.validation-rule";
13
+ import {
14
+ DecimalCountValidationRule,
15
+ DecimalCountValidationRuleSettings,
16
+ } from "../validation-rules/decimal-count.validation-rule";
17
+ import {
18
+ NumberBetweenValidationRule,
19
+ NumberBetweenValidationRuleSettings,
20
+ } from "../validation-rules/number-between.validation-rule";
21
+ import {
22
+ RelatableContentTypesValidationRule,
23
+ RelatableContentTypesValidationRuleSettings,
24
+ } from "../validation-rules/relatable-content-types.validation-rule";
25
+ import {
26
+ StringFormatValidationRule,
27
+ StringFormatValidationRuleSettings,
28
+ } from "../validation-rules/string-format.validation-rule";
29
+ import {
30
+ ValueTypeValidationRule,
31
+ ValueTypeValidationRuleSettings,
32
+ } from "../validation-rules/value-type.validation-rule";
33
+
34
+ /**
35
+ * @param input The input containing the untyped rule: `const input = { value: untypedRule }`
36
+ */
37
+ export function deserializeValidationRule(input: unknown): ExistingContentValidationRules {
38
+ if (typeof input !== "object" || input == null) {
39
+ throw new Error(`The input is not an object or is null. Input: '${JSON.stringify(input)}'`);
40
+ }
41
+
42
+ if (input["value" as keyof object] == null) {
43
+ throw new Error(`The input does not contain a 'value' property. Input: '${JSON.stringify(input)}'`);
44
+ }
45
+
46
+ // Check the property ruleType of the validationRule object and initialize the appropriate class.
47
+ const rawValidationRule = input["value" as keyof object] as ExistingContentValidationRules;
48
+
49
+ switch (rawValidationRule.ruleType) {
50
+ case RuleType.ALLOWED_VALUES:
51
+ return new AllowedValuesValidationRule(
52
+ rawValidationRule.prn,
53
+ rawValidationRule.settings as AllowedValuesValidationRuleSettings,
54
+ );
55
+ case RuleType.COUNT:
56
+ return new CountValidationRule(rawValidationRule.prn, rawValidationRule.settings as CountValidationRuleSettings);
57
+ case RuleType.DATE_BETWEEN:
58
+ return new DateBetweenValidationRule(
59
+ rawValidationRule.prn,
60
+ rawValidationRule.settings as DateBetweenValidationRuleSettings,
61
+ );
62
+ case RuleType.DECIMAL_COUNT:
63
+ return new DecimalCountValidationRule(
64
+ rawValidationRule.prn,
65
+ rawValidationRule.settings as DecimalCountValidationRuleSettings,
66
+ );
67
+ case RuleType.NUMBER_BETWEEN:
68
+ return new NumberBetweenValidationRule(
69
+ rawValidationRule.prn,
70
+ rawValidationRule.settings as NumberBetweenValidationRuleSettings,
71
+ );
72
+ case RuleType.RELATABLE_CONTENT_TYPES:
73
+ return new RelatableContentTypesValidationRule(
74
+ rawValidationRule.prn,
75
+ rawValidationRule.settings as RelatableContentTypesValidationRuleSettings<PRN>,
76
+ );
77
+ case RuleType.STRING_FORMAT:
78
+ return new StringFormatValidationRule(
79
+ rawValidationRule.prn,
80
+ rawValidationRule.settings as StringFormatValidationRuleSettings,
81
+ );
82
+ case RuleType.VALUE_TYPE:
83
+ return new ValueTypeValidationRule(
84
+ rawValidationRule.prn,
85
+ rawValidationRule.settings as ValueTypeValidationRuleSettings,
86
+ );
87
+ default:
88
+ throw new Error(
89
+ `Unknown validation rule type: ${
90
+ rawValidationRule.ruleType as string
91
+ }. Rule: ${JSON.stringify(rawValidationRule)}`,
92
+ );
93
+ }
94
+ }
@@ -0,0 +1,254 @@
1
+ import { PRN } from "@platecms/delta-plate-resource-notation";
2
+ import { ContentValueTypeNames } from "@platecms/delta-types";
3
+ import { RuleType } from "../enums/rule-types.enum";
4
+ import { ArrayValidationSchema } from "../schemas/array.schema";
5
+ import { ruleToSchema } from "./rule-to-schema";
6
+
7
+ describe("ruleToSchema", () => {
8
+ const mockPrn = PRN.fromString("prn:plate:-1:cxc:validation-rule:1");
9
+
10
+ describe("ALLOWED_VALUES rule", () => {
11
+ it("converts ALLOWED_VALUES rule to array schema with inner content-value schema", () => {
12
+ const rule = {
13
+ ruleType: RuleType.ALLOWED_VALUES,
14
+ settings: { allowedValues: ["option1", "option2", "option3"] },
15
+ prn: PRN.fromString("prn:plate:-1:cxc:validation-rule:1"),
16
+ };
17
+
18
+ const schema = ruleToSchema(rule);
19
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
20
+
21
+ const validationResult = schema.validate(["option1", "invalid"], { path: ["test"] });
22
+ expect(validationResult.isValid).toBe(false);
23
+ expect(validationResult.errors).toHaveLength(1);
24
+ expect(validationResult.errors[0].message).toBe("The provided value must be one of option1, option2, option3");
25
+ });
26
+ });
27
+
28
+ describe("COUNT rule", () => {
29
+ it("converts COUNT rule to array schema", () => {
30
+ const ruleInstance = {
31
+ ruleType: RuleType.COUNT,
32
+ settings: {
33
+ min: 1,
34
+ max: 10,
35
+ },
36
+ prn: mockPrn,
37
+ };
38
+
39
+ const schema = ruleToSchema(ruleInstance);
40
+
41
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
42
+ expect(schema.type).toBe("array");
43
+
44
+ const validationResult = schema.validate([], { path: ["test"] });
45
+ expect(validationResult.isValid).toBe(false);
46
+ expect(validationResult.errors).toHaveLength(1);
47
+ });
48
+
49
+ it("handles COUNT rule with undefined min/max", () => {
50
+ const ruleInstance = {
51
+ ruleType: RuleType.COUNT,
52
+ settings: {},
53
+ prn: mockPrn,
54
+ };
55
+
56
+ const schema = ruleToSchema(ruleInstance);
57
+
58
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
59
+ expect(schema.type).toBe("array");
60
+
61
+ const validationResult = schema.validate([1, 2, 3], { path: ["test"] });
62
+ expect(validationResult.isValid).toBe(true);
63
+ });
64
+ });
65
+
66
+ describe("STRING_FORMAT rule", () => {
67
+ it("converts STRING_FORMAT rule to array schema with inner string schema", () => {
68
+ const rule = {
69
+ ruleType: RuleType.STRING_FORMAT,
70
+ settings: { allowedFormat: ".*@.*\\..*" },
71
+ prn: PRN.fromString("prn:plate:-1:cxc:validation-rule:1"),
72
+ };
73
+
74
+ const schema = ruleToSchema(rule);
75
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
76
+
77
+ const validationResult = schema.validate(["invalid-email"], { path: ["test"] });
78
+ expect(validationResult.isValid).toBe(false);
79
+ });
80
+ });
81
+
82
+ describe("NUMBER_BETWEEN rule", () => {
83
+ it("converts NUMBER_BETWEEN rule to array schema with inner number schema", () => {
84
+ const ruleInstance = {
85
+ ruleType: RuleType.NUMBER_BETWEEN,
86
+ settings: {
87
+ min: 0,
88
+ max: 100,
89
+ },
90
+ prn: mockPrn,
91
+ };
92
+
93
+ const schema = ruleToSchema(ruleInstance);
94
+
95
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
96
+ expect(schema.type).toBe("array");
97
+
98
+ const validationResult = schema.validate([150], { path: ["test"] });
99
+ expect(validationResult.isValid).toBe(false);
100
+ });
101
+
102
+ it("handles NUMBER_BETWEEN rule with only min", () => {
103
+ const ruleInstance = {
104
+ ruleType: RuleType.NUMBER_BETWEEN,
105
+ settings: {
106
+ min: 0,
107
+ },
108
+ prn: mockPrn,
109
+ };
110
+
111
+ const schema = ruleToSchema(ruleInstance);
112
+
113
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
114
+ expect(schema.type).toBe("array");
115
+
116
+ const validationResult = schema.validate([-1], { path: ["test"] });
117
+ expect(validationResult.isValid).toBe(false);
118
+ });
119
+
120
+ it("handles NUMBER_BETWEEN rule with only max", () => {
121
+ const ruleInstance = {
122
+ ruleType: RuleType.NUMBER_BETWEEN,
123
+ settings: {
124
+ max: 100,
125
+ },
126
+ prn: mockPrn,
127
+ };
128
+
129
+ const schema = ruleToSchema(ruleInstance);
130
+
131
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
132
+ expect(schema.type).toBe("array");
133
+
134
+ const validationResult = schema.validate([150], { path: ["test"] });
135
+ expect(validationResult.isValid).toBe(false);
136
+ });
137
+ });
138
+
139
+ describe("DATE_BETWEEN rule", () => {
140
+ it("converts DATE_BETWEEN rule to array schema with inner date schema", () => {
141
+ const startDate = new Date("2023-01-01");
142
+ const endDate = new Date("2023-12-31");
143
+ const ruleInstance = {
144
+ ruleType: RuleType.DATE_BETWEEN,
145
+ settings: {
146
+ start: startDate,
147
+ end: endDate,
148
+ },
149
+ prn: mockPrn,
150
+ };
151
+
152
+ const schema = ruleToSchema(ruleInstance);
153
+
154
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
155
+ expect(schema.type).toBe("array");
156
+
157
+ const validationResult = schema.validate([new Date("2024-01-01")], { path: ["test"] });
158
+ expect(validationResult.isValid).toBe(false);
159
+ });
160
+
161
+ it("handles DATE_BETWEEN rule with only min", () => {
162
+ const startDate = new Date("2023-01-01");
163
+ const ruleInstance = {
164
+ ruleType: RuleType.DATE_BETWEEN,
165
+ settings: {
166
+ start: startDate,
167
+ },
168
+ prn: mockPrn,
169
+ };
170
+
171
+ const schema = ruleToSchema(ruleInstance);
172
+
173
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
174
+ expect(schema.type).toBe("array");
175
+
176
+ const validationResult = schema.validate([new Date("2022-01-01")], { path: ["test"] });
177
+ expect(validationResult.isValid).toBe(false);
178
+ });
179
+
180
+ it("handles DATE_BETWEEN rule with only max", () => {
181
+ const endDate = new Date("2023-12-31");
182
+ const ruleInstance = {
183
+ ruleType: RuleType.DATE_BETWEEN,
184
+ settings: {
185
+ end: endDate,
186
+ },
187
+ prn: mockPrn,
188
+ };
189
+
190
+ const schema = ruleToSchema(ruleInstance);
191
+
192
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
193
+ expect(schema.type).toBe("array");
194
+
195
+ const validationResult = schema.validate([new Date("2024-01-01")], { path: ["test"] });
196
+ expect(validationResult.isValid).toBe(false);
197
+ });
198
+ });
199
+
200
+ describe("DECIMAL_COUNT rule", () => {
201
+ it("converts DECIMAL_COUNT rule to array schema with inner number schema", () => {
202
+ const ruleInstance = {
203
+ ruleType: RuleType.DECIMAL_COUNT,
204
+ settings: {
205
+ max: 2,
206
+ },
207
+ prn: mockPrn,
208
+ };
209
+
210
+ const schema = ruleToSchema(ruleInstance);
211
+
212
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
213
+ expect(schema.type).toBe("array");
214
+
215
+ const validationResult = schema.validate([3.14159], { path: ["test"] });
216
+ expect(validationResult.isValid).toBe(false);
217
+ });
218
+ });
219
+
220
+ describe("VALUE_TYPE rule", () => {
221
+ it("converts VALUE_TYPE rule to array schema with inner content-value schema", () => {
222
+ const ruleInstance = {
223
+ ruleType: RuleType.VALUE_TYPE,
224
+ settings: {
225
+ allowedTypes: [ContentValueTypeNames.STRING, ContentValueTypeNames.NUMBER],
226
+ },
227
+ prn: mockPrn,
228
+ };
229
+
230
+ const schema = ruleToSchema(ruleInstance);
231
+
232
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
233
+
234
+ const validationResult = schema.validate([true], { path: ["test"] });
235
+ expect(validationResult.isValid).toBe(false);
236
+ });
237
+ });
238
+
239
+ describe("RELATABLE_CONTENT_TYPES rule", () => {
240
+ it("converts RELATABLE_CONTENT_TYPES rule to array schema with inner content-value schema", () => {
241
+ const rule = {
242
+ ruleType: RuleType.RELATABLE_CONTENT_TYPES,
243
+ settings: { allowedTypes: [ContentValueTypeNames.STRING, ContentValueTypeNames.NUMBER] },
244
+ prn: PRN.fromString("prn:plate:-1:cxc:validation-rule:1"),
245
+ };
246
+
247
+ const schema = ruleToSchema(rule);
248
+ expect(schema).toBeInstanceOf(ArrayValidationSchema);
249
+
250
+ const validationResult = schema.validate(["string"], { path: ["test"] });
251
+ expect(validationResult.isValid).toBe(true);
252
+ });
253
+ });
254
+ });
@@ -0,0 +1,95 @@
1
+ import { PRN } from "@platecms/delta-plate-resource-notation";
2
+ import { ContentValueType } from "@platecms/delta-types";
3
+ import { RuleType } from "../enums/rule-types.enum";
4
+ import { RuleInstance } from "../types/rule-instance.interface";
5
+ import { AllowedValuesValidationRuleSettings } from "../validation-rules/allowed-values.validation-rule";
6
+ import { CountValidationRuleSettings } from "../validation-rules/count.validation-rule";
7
+ import { DateBetweenValidationRuleSettings } from "../validation-rules/date-between.validation-rule";
8
+ import { DecimalCountValidationRuleSettings } from "../validation-rules/decimal-count.validation-rule";
9
+ import { NumberBetweenValidationRuleSettings } from "../validation-rules/number-between.validation-rule";
10
+ import { RelatableContentTypesValidationRuleSettings } from "../validation-rules/relatable-content-types.validation-rule";
11
+ import { StringFormatValidationRuleSettings } from "../validation-rules/string-format.validation-rule";
12
+ import { ValueTypeValidationRuleSettings } from "../validation-rules/value-type.validation-rule";
13
+ import { ArrayValidationSchema } from "../schemas/array.schema";
14
+ import { ContentValueValidationSchema } from "../schemas/content-value.schema";
15
+ import { StringValidationSchema } from "../schemas/string.schema";
16
+ import { NumberValidationSchema } from "../schemas/number.schema";
17
+ import { DateValidationSchema } from "../schemas/date.schema";
18
+
19
+ export function ruleToSchema(ruleInstance: RuleInstance<unknown>): ArrayValidationSchema<ContentValueType> {
20
+ switch (ruleInstance.ruleType) {
21
+ case RuleType.ALLOWED_VALUES: {
22
+ const settings = ruleInstance.settings as AllowedValuesValidationRuleSettings;
23
+ return new ArrayValidationSchema<ContentValueType>().of(
24
+ new ContentValueValidationSchema(ruleInstance).allowedValues(settings.allowedValues),
25
+ );
26
+ }
27
+
28
+ case RuleType.COUNT: {
29
+ const countSettings = ruleInstance.settings as CountValidationRuleSettings;
30
+ return new ArrayValidationSchema<ContentValueType>(ruleInstance)
31
+ .min(countSettings.min ?? 0)
32
+ .max(countSettings.max ?? 0);
33
+ }
34
+
35
+ case RuleType.STRING_FORMAT: {
36
+ const formatSettings = ruleInstance.settings as StringFormatValidationRuleSettings;
37
+ return new ArrayValidationSchema<ContentValueType>().of(
38
+ new StringValidationSchema(ruleInstance).format(formatSettings.allowedFormat),
39
+ );
40
+ }
41
+
42
+ case RuleType.NUMBER_BETWEEN: {
43
+ const numberSettings = ruleInstance.settings as NumberBetweenValidationRuleSettings;
44
+ const numberSchema = new NumberValidationSchema(ruleInstance);
45
+
46
+ if (numberSettings.min !== undefined) {
47
+ numberSchema.min(numberSettings.min);
48
+ }
49
+ if (numberSettings.max !== undefined) {
50
+ numberSchema.max(numberSettings.max);
51
+ }
52
+
53
+ return new ArrayValidationSchema<ContentValueType>().of(numberSchema);
54
+ }
55
+
56
+ case RuleType.DATE_BETWEEN: {
57
+ const dateSettings = ruleInstance.settings as DateBetweenValidationRuleSettings;
58
+ const dateSchema = new DateValidationSchema(ruleInstance);
59
+
60
+ if (dateSettings.start) {
61
+ dateSchema.start(dateSettings.start);
62
+ }
63
+ if (dateSettings.end) {
64
+ dateSchema.end(dateSettings.end);
65
+ }
66
+
67
+ return new ArrayValidationSchema<ContentValueType>().of(dateSchema);
68
+ }
69
+
70
+ case RuleType.DECIMAL_COUNT: {
71
+ const decimalSettings = ruleInstance.settings as DecimalCountValidationRuleSettings;
72
+ return new ArrayValidationSchema<ContentValueType>().of(
73
+ new NumberValidationSchema(ruleInstance).maxDecimals(decimalSettings.max),
74
+ );
75
+ }
76
+
77
+ case RuleType.VALUE_TYPE: {
78
+ const valueTypeSettings = ruleInstance.settings as ValueTypeValidationRuleSettings;
79
+ return new ArrayValidationSchema<ContentValueType>().of(
80
+ new ContentValueValidationSchema(ruleInstance).allowedValueTypes(valueTypeSettings.allowedTypes),
81
+ );
82
+ }
83
+
84
+ case RuleType.RELATABLE_CONTENT_TYPES: {
85
+ const relatableSettings = ruleInstance.settings as RelatableContentTypesValidationRuleSettings<PRN>;
86
+ return new ArrayValidationSchema<ContentValueType>().of(
87
+ new ContentValueValidationSchema(ruleInstance).allowedContentTypes(relatableSettings.allowedContentTypes),
88
+ );
89
+ }
90
+
91
+ default: {
92
+ return new ArrayValidationSchema<ContentValueType>();
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,52 @@
1
+ import { SchemaBuilder } from "./schema-builder";
2
+ import { StringValidationSchema } from "../schemas/string.schema";
3
+ import { NumberValidationSchema } from "../schemas/number.schema";
4
+ import { DateValidationSchema } from "../schemas/date.schema";
5
+ import { ArrayValidationSchema } from "../schemas/array.schema";
6
+ import { ContentValueValidationSchema } from "../schemas/content-value.schema";
7
+ import { ContentValueTypeNames } from "@platecms/delta-types";
8
+
9
+ describe("SchemaBuilder", () => {
10
+ it("creates string schema correctly", () => {
11
+ const stringSchema = SchemaBuilder.string();
12
+ expect(stringSchema).toBeInstanceOf(StringValidationSchema);
13
+ });
14
+
15
+ it("creates number schema correctly", () => {
16
+ const numberSchema = SchemaBuilder.number();
17
+ expect(numberSchema).toBeInstanceOf(NumberValidationSchema);
18
+ });
19
+
20
+ it("creates date schema correctly", () => {
21
+ const dateSchema = SchemaBuilder.date();
22
+ expect(dateSchema).toBeInstanceOf(DateValidationSchema);
23
+ });
24
+
25
+ it("creates array schema correctly", () => {
26
+ const arraySchema = SchemaBuilder.array();
27
+ expect(arraySchema).toBeInstanceOf(ArrayValidationSchema);
28
+ });
29
+
30
+ it("creates content value schema correctly", () => {
31
+ const contentValueSchema = SchemaBuilder.contentValue();
32
+ expect(contentValueSchema).toBeInstanceOf(ContentValueValidationSchema);
33
+ });
34
+
35
+ it("supports complex schema composition", () => {
36
+ const contentValueSchema = SchemaBuilder.contentValue().allowedValueTypes([
37
+ ContentValueTypeNames.STRING,
38
+ ContentValueTypeNames.NUMBER,
39
+ ]);
40
+
41
+ const arraySchema = SchemaBuilder.array().min(1).max(10).of(contentValueSchema);
42
+
43
+ expect(arraySchema).toBeInstanceOf(ArrayValidationSchema);
44
+ });
45
+
46
+ it("validates complex nested schemas", () => {
47
+ const arraySchema = SchemaBuilder.array().of(SchemaBuilder.number().min(0));
48
+
49
+ const result = arraySchema.validate([1, 2, 3], { path: ["test"] });
50
+ expect(result.isValid).toBe(true);
51
+ });
52
+ });
@@ -0,0 +1,28 @@
1
+ import { ArrayValidationSchema } from "../schemas/array.schema";
2
+ import { ContentValueValidationSchema } from "../schemas/content-value.schema";
3
+ import { DateValidationSchema } from "../schemas/date.schema";
4
+ import { NumberValidationSchema } from "../schemas/number.schema";
5
+ import { StringValidationSchema } from "../schemas/string.schema";
6
+
7
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
8
+ export class SchemaBuilder {
9
+ public static string(): StringValidationSchema {
10
+ return new StringValidationSchema();
11
+ }
12
+
13
+ public static number(): NumberValidationSchema {
14
+ return new NumberValidationSchema();
15
+ }
16
+
17
+ public static date(): DateValidationSchema {
18
+ return new DateValidationSchema();
19
+ }
20
+
21
+ public static array<T>(): ArrayValidationSchema<T> {
22
+ return new ArrayValidationSchema<T>();
23
+ }
24
+
25
+ public static contentValue(): ContentValueValidationSchema {
26
+ return new ContentValueValidationSchema();
27
+ }
28
+ }