Browse Source

chore: adds property validators

e22m4u 1 year ago
parent
commit
1fe2bafec5
100 changed files with 373 additions and 236 deletions
  1. 31 0
      README.md
  2. 0 0
      docs/assets/main.js
  3. 1 1
      docs/assets/navigation.js
  4. 0 0
      docs/assets/search.js
  5. 0 0
      docs/classes/Adapter.html
  6. 0 0
      docs/classes/AdapterLoader.html
  7. 0 0
      docs/classes/AdapterRegistry.html
  8. 0 0
      docs/classes/BelongsToResolver.html
  9. 0 0
      docs/classes/DatasourceDefinitionValidator.html
  10. 0 0
      docs/classes/DefinitionRegistry.html
  11. 0 0
      docs/classes/FieldsClauseTool.html
  12. 0 0
      docs/classes/HasManyResolver.html
  13. 0 0
      docs/classes/HasOneResolver.html
  14. 0 0
      docs/classes/IncludeClauseTool.html
  15. 0 0
      docs/classes/InvalidArgumentError.html
  16. 0 0
      docs/classes/InvalidOperatorValueError.html
  17. 0 0
      docs/classes/ModelDataSanitizer.html
  18. 0 0
      docs/classes/ModelDataValidator.html
  19. 0 0
      docs/classes/ModelDefinitionUtils.html
  20. 0 0
      docs/classes/ModelDefinitionValidator.html
  21. 0 0
      docs/classes/NotImplementedError.html
  22. 0 0
      docs/classes/OperatorClauseTool.html
  23. 0 0
      docs/classes/OrderClauseTool.html
  24. 0 0
      docs/classes/PrimaryKeysDefinitionValidator.html
  25. 0 0
      docs/classes/PropertiesDefinitionValidator.html
  26. 0 0
      docs/classes/PropertyValidatorRegistry.html
  27. 0 0
      docs/classes/ReferencesManyResolver.html
  28. 0 0
      docs/classes/RelationsDefinitionValidator.html
  29. 0 0
      docs/classes/Repository.html
  30. 0 0
      docs/classes/RepositoryRegistry.html
  31. 0 0
      docs/classes/Schema.html
  32. 0 0
      docs/classes/SliceClauseTool.html
  33. 0 0
      docs/classes/WhereClauseTool.html
  34. 0 0
      docs/enums/DataType.html
  35. 0 0
      docs/enums/DecoratorTargetType.html
  36. 0 0
      docs/enums/RelationType.html
  37. 0 0
      docs/functions/capitalize.html
  38. 0 0
      docs/functions/cloneDeep.html
  39. 0 0
      docs/functions/excludeObjectKeys.html
  40. 0 0
      docs/functions/getCtorName.html
  41. 0 0
      docs/functions/getDecoratorTargetType.html
  42. 0 0
      docs/functions/getValueByPath.html
  43. 0 0
      docs/functions/isCtor.html
  44. 0 0
      docs/functions/isPureObject.html
  45. 0 0
      docs/functions/selectObjectKeys.html
  46. 0 0
      docs/functions/singularize.html
  47. 0 0
      docs/functions/stringToRegexp.html
  48. 0 0
      docs/index.html
  49. 0 0
      docs/interfaces/AndClause.html
  50. 0 0
      docs/interfaces/Constructor.html
  51. 0 0
      docs/interfaces/OrClause.html
  52. 4 0
      docs/modules.html
  53. 0 0
      docs/types/AnyObject.html
  54. 0 0
      docs/types/BelongsToDefinition.html
  55. 0 0
      docs/types/DEFAULT_PRIMARY_KEY_PROPERTY_NAME.html
  56. 0 0
      docs/types/DatasourceDefinition.html
  57. 0 0
      docs/types/FieldsClause.html
  58. 0 0
      docs/types/FilterClause.html
  59. 0 0
      docs/types/Flatten.html
  60. 0 0
      docs/types/FullPropertyDefinition.html
  61. 0 0
      docs/types/HasManyDefinition.html
  62. 0 0
      docs/types/HasOneDefinition.html
  63. 0 0
      docs/types/Identity.html
  64. 0 0
      docs/types/IncludeClause.html
  65. 0 0
      docs/types/ItemFilterClause.html
  66. 0 0
      docs/types/ModelData.html
  67. 0 0
      docs/types/ModelDefinition.html
  68. 0 0
      docs/types/ModelId.html
  69. 0 0
      docs/types/NestedIncludeClause.html
  70. 0 0
      docs/types/NormalizedFieldsClause.html
  71. 0 0
      docs/types/NormalizedIncludeClause.html
  72. 0 0
      docs/types/OperatorClause.html
  73. 0 0
      docs/types/OptionalUnlessRequiredId.html
  74. 0 0
      docs/types/OrderClause.html
  75. 0 0
      docs/types/PartialBy.html
  76. 0 0
      docs/types/PartialWithoutId.html
  77. 0 0
      docs/types/PolyBelongsToDefinition.html
  78. 0 0
      docs/types/PolyHasManyDefinitionWithTargetKeys.html
  79. 0 0
      docs/types/PolyHasManyDefinitionWithTargetRelationName.html
  80. 0 0
      docs/types/PolyHasOneDefinitionWithTargetKeys.html
  81. 0 0
      docs/types/PolyHasOneDefinitionWithTargetRelationName.html
  82. 0 0
      docs/types/PropertiesClause.html
  83. 0 0
      docs/types/PropertyDefinition.html
  84. 0 0
      docs/types/PropertyDefinitionMap.html
  85. 0 0
      docs/types/PropertyValidateOptions.html
  86. 0 0
      docs/types/PropertyValidator.html
  87. 0 0
      docs/types/PropertyValidatorContext.html
  88. 0 0
      docs/types/ReferencesManyDefinition.html
  89. 0 0
      docs/types/RelationDefinition.html
  90. 0 0
      docs/types/RelationDefinitionMap.html
  91. 0 0
      docs/types/WhereClause.html
  92. 0 0
      docs/types/WithoutId.html
  93. 1 1
      package.json
  94. 18 10
      src/adapter/decorator/data-validation-decorator.js
  95. 40 0
      src/adapter/decorator/data-validation-decorator.spec.js
  96. 4 16
      src/definition/model/model-data-validator.d.ts
  97. 87 11
      src/definition/model/model-data-validator.js
  98. 185 197
      src/definition/model/model-data-validator.spec.js
  99. 1 0
      src/definition/model/properties/index.d.ts
  100. 1 0
      src/definition/model/properties/index.js

+ 31 - 0
README.md

@@ -9,6 +9,7 @@
 - [Источник данных](#Источник-данных)
 - [Модель](#Модель)
 - [Свойства](#Свойства)
+- [Валидаторы](#Валидаторы)
 - [Репозиторий](#Репозиторий)
 - [Фильтрация](#Фильтрация)
 - [Связи](#Связи)
@@ -221,6 +222,7 @@ schema.defineModel({
 - `columnType: string` тип колонки (определяется адаптером)
 - `required: boolean` объявить свойство обязательным
 - `default: any` значение по умолчанию
+- `validate: string | array | object` см. [Валидаторы](#Валидаторы)
 
 **Примеры**
 
@@ -274,6 +276,35 @@ schema.defineModel({
 });
 ```
 
+## Валидаторы
+
+Кроме проверки типа, более конкретные условия можно задать с помощью
+валидаторов, через которые будет проходить значение перед записью в базу.
+
+- `minLength: string` минимальная длинна строки или массива
+- `maxLength: string` максимальная длинна строки или массива
+
+**Пример**
+
+Валидаторы указываются в объявлении свойства модели параметром
+`validate`, который принимает объект с названиями валидаторов
+и их настройками.
+
+```js
+schema.defineModel({
+  name: 'user',
+  properties: {
+    name: {
+      type: DataType.STRING,
+      validate: { // валидаторы свойства "name"
+        minLength: 2, // минимальная длинна строки
+        maxLength: 24, // максимальная длинна строки
+      },
+    },
+  },
+});
+```
+
 ## Репозиторий
 
 Выполняет операции чтения и записи документов определенной модели.

File diff suppressed because it is too large
+ 0 - 0
docs/assets/main.js


+ 1 - 1
docs/assets/navigation.js

@@ -1 +1 @@
-window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA6WZa2/bNhSG/4s+B8satN2Wb07iYkbr2FCdFsEwBJx0YrOlSI08KqIO+++FbMuSeDmk0a9+3/Pwcng5lP/6L0N4wew6u2PINm0N2UVWM9xl1xnIpjKX/e+/7LAS2UX2lcsyu/79/4shEgqlGSq9YXoL6IW4ljAvB8GQK+kDjbUwYVayGkEPwYVgxoC5PArTyFdXntgPipUE4SAncHLYcoO6DZJ6A8W6AaHk1mxUDkaJb75+ORaK1+XUqEYXcAfPXPJuRj8xwcsuRS6btJPtnOzhaXA9FPEdB1GaW8EaAxulhMuzHRTtT2aWTLbhWbUMEdZKAoka6RRpIQvRlEAN0rHQvG9dsmZ621Qgca61L8k+VwJ1VcN+Y39iogEa7Vop/lKVILqV95F1y+O7b05dTxKRWOquJ048LeAH5MKEmFPXGdRob8/bk/cKF1UtoEsylIGMeUwUs88stWRdD0nUJdC4qYFirTWvmG7fQ2uSZpX20y2pGjRySG2IsFPt5PAMGmQBkePL76PJh/s1bQCUm26lVoaj8t0Hg5ZGCN8srocifix2UDGXcvidjBS8IE9ry0CxPu9AkyzLQFYgsjwYBwqXCPqZFV350atTxNWbtyPErZIGdVNMsj+CjHQKs9JER3qRAsxku/rnCxQ4ELCt96M4Clb0r3/89urNla+EGpaqzfJYYtS7+bvZw4fN0zpfLGf549P7+ePTOl+t5/nm8el+tpzbbUQDoi16ajGnEY8nxh2XTTZvrMU5AsFJd88ZtChHMERwhnb8ORrdCHE8XdvwPPldMfaxJgxjHUMCcSWJfNp6jLcoQSLH1ub0v0fjx9WlAxmLURJCRa0IW4/xTuWZDToJaYTgVFtyEm1ReimLMhZ9DwahJGfbY4lSla6Y4N+hpPa035XOpnvtt8Xo0xLRhk7VOKvLHxMPUoAxOfzbcA2lm6qQL8of6k8HOUgxyppp5EzcOFv1JCQSPnPcqQbd8dl6lKdEm3BXBmwpdOd47Pp2+C7Uldy+liIhP9lqX8Xes8rJ5Rmhib2YnORJQycifq7NhIEnREb7cHrl+LeLrSfyiAv4/DvdjViyOo5dsjpGnj7Bwn0O+eL8QyYosu04n+mZDa8pRh69XmzeSIpSQodd8ilXsJrj/oYaEM+NLPaP2ctBnXLevh4jhOr2BtReQi8SAHjZX42H58t0+w8gx0QAt4C3qPR0Nw+okUxDyO/5E170s76N3n/6u2nXHcuPHDkIFDe3kyfpgDgoZOi60WC/JseAQScwBgQUSCfP9lA4LreNYDqwIkcyBUHN5bb7C2ALL951OXU4qL9/AK5YS0UPGgAA"
+window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA6WZ227bOBCG30XXwWYbtN3d3DmOixqtY0N1WgRFEbDSxGZLkVqSKqIu9t0LWZZF8TCk0Vv9/3w8DA9D+/N/mYZnnV1nt0STbVtDdpHVRO+z6wx4U6nL4fsfe12x7CL7TnmZXf/9/8UYCYWQRAu5JXIH2gtxLWFeDoxoKrgPZGphwqwktQY5BheMKAXq8ihMI19ceWLfC1IihF5O4OSwo0rLNkgaDBjrBpjgO7UVOSjBfvj65VgwXpdTJRpZwC08UU67Gf1IGC27FLls1I62c7KHp8H1YMQ3FFip5ow0CrZCMJdnOzDaW6JWhLfhWbUMEdaaA4oydIy05AVrSsAG6Vhw3o8uWTO5ayrgeiGlL8k+VwJ1XcNhY38krAEc7Vox/kqUwLqV94F0y+Onb05dTxIRWequJ048LeB7TZkKMaeuM6jR3p63J++EXlY1gy7JUAYy5jFhzCGz2JJ1PShRloDjpgaMtZG0IrJ9B61KmlXcj7ckapCaQmpDiD2hnfZkDh+vQSvGz+EJJPACIsej34eT+/s7bYIwN95KLRTVwjcho5ZGCE+t68GIH4o9VMSl9N/RSEYL9DawDBjr0x4kyrIMaIXDy944UijXIJ9I0ZU3gzpFXL16bSDmgistm2KSfQNi6BhmLZGODCIGmPF2/fUbFHok6LY+jOIoWNF//vPXi1dXvhJtXKo2y2OJUW8Xb2b377ePm3y5muUPj+8WD4+bfL1Z5NuHx7vZamG3EQ2Ituip9ZxGPJ4Y1yzLbJ6pxTlMg5PugTNqUQ4jWoMztOPnaHTD2HCyhufJ74qxjzVnGOsYEohrjuTT1mO8ZQlcU93anOF7NN6sXh2IKUZJGipsRdh6jHcq/2zQSUgjBKfakpNoy9JLWZax6DtQGkp0tj2WKFXIijD6E0psT/td6Wy8135bjD4tQW3oVI2zuvwRds8ZKJXDvw2VULqpCvmi/LG+dZCjFKNsiNSUsBtnq56ERMInqvei0e74bD3KE6xNuCsDthS6czx2fet/d+pKel9LkZDfbHWoYu9I5eTyjNDEXkxO8qShIxG/12bCwBMio304vaL828XWE3nIBXz+ne5GrEgdx65InUo+vougP2/cVPttZ9LNKt3Ldcr0OHEu+EGKgY++GH/6JA3nMOSL8/uViZFtx/lMz+rwmmJk4zVn8wwpSgkd/smnfkFqqg839oh4anhxWISXozrlvH5pIpjozgqovYRBRADwfCgV+ufc9DgcQY4JAe5Az7WQ09NtRBkyDkH/P5nwon+j2OjDT6037aZj+ZGGA0FRNZ9s/hHRK2joppFgv65NwKgjGAUMCo0nz/ZgOMp3DSMysCINGYNoSfmu+8tlB8/edTl1OKgvvwBP4V6kfxsAAA=="

File diff suppressed because it is too large
+ 0 - 0
docs/assets/search.js


File diff suppressed because it is too large
+ 0 - 0
docs/classes/Adapter.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/AdapterLoader.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/AdapterRegistry.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/BelongsToResolver.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/DatasourceDefinitionValidator.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/DefinitionRegistry.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/FieldsClauseTool.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/HasManyResolver.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/HasOneResolver.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/IncludeClauseTool.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/InvalidArgumentError.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/InvalidOperatorValueError.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/ModelDataSanitizer.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/ModelDataValidator.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/ModelDefinitionUtils.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/ModelDefinitionValidator.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/NotImplementedError.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/OperatorClauseTool.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/OrderClauseTool.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/PrimaryKeysDefinitionValidator.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/PropertiesDefinitionValidator.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/PropertyValidatorRegistry.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/ReferencesManyResolver.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/RelationsDefinitionValidator.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/Repository.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/RepositoryRegistry.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/Schema.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/SliceClauseTool.html


File diff suppressed because it is too large
+ 0 - 0
docs/classes/WhereClauseTool.html


File diff suppressed because it is too large
+ 0 - 0
docs/enums/DataType.html


File diff suppressed because it is too large
+ 0 - 0
docs/enums/DecoratorTargetType.html


File diff suppressed because it is too large
+ 0 - 0
docs/enums/RelationType.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/capitalize.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/cloneDeep.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/excludeObjectKeys.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/getCtorName.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/getDecoratorTargetType.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/getValueByPath.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/isCtor.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/isPureObject.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/selectObjectKeys.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/singularize.html


File diff suppressed because it is too large
+ 0 - 0
docs/functions/stringToRegexp.html


File diff suppressed because it is too large
+ 0 - 0
docs/index.html


File diff suppressed because it is too large
+ 0 - 0
docs/interfaces/AndClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/interfaces/Constructor.html


File diff suppressed because it is too large
+ 0 - 0
docs/interfaces/OrClause.html


+ 4 - 0
docs/modules.html

@@ -22,6 +22,7 @@
 <a href="classes/OrderClauseTool.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Order<wbr/>Clause<wbr/>Tool</span></a>
 <a href="classes/PrimaryKeysDefinitionValidator.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Primary<wbr/>Keys<wbr/>Definition<wbr/>Validator</span></a>
 <a href="classes/PropertiesDefinitionValidator.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Properties<wbr/>Definition<wbr/>Validator</span></a>
+<a href="classes/PropertyValidatorRegistry.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Property<wbr/>Validator<wbr/>Registry</span></a>
 <a href="classes/ReferencesManyResolver.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>References<wbr/>Many<wbr/>Resolver</span></a>
 <a href="classes/RelationsDefinitionValidator.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Relations<wbr/>Definition<wbr/>Validator</span></a>
 <a href="classes/Repository.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Repository</span></a>
@@ -64,6 +65,9 @@
 <a href="types/PropertiesClause.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Properties<wbr/>Clause</span></a>
 <a href="types/PropertyDefinition.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Property<wbr/>Definition</span></a>
 <a href="types/PropertyDefinitionMap.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Property<wbr/>Definition<wbr/>Map</span></a>
+<a href="types/PropertyValidateOptions.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Property<wbr/>Validate<wbr/>Options</span></a>
+<a href="types/PropertyValidator.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Property<wbr/>Validator</span></a>
+<a href="types/PropertyValidatorContext.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Property<wbr/>Validator<wbr/>Context</span></a>
 <a href="types/ReferencesManyDefinition.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>References<wbr/>Many<wbr/>Definition</span></a>
 <a href="types/RelationDefinition.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Relation<wbr/>Definition</span></a>
 <a href="types/RelationDefinitionMap.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-2097152"></use></svg><span>Relation<wbr/>Definition<wbr/>Map</span></a>

File diff suppressed because it is too large
+ 0 - 0
docs/types/AnyObject.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/BelongsToDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/DEFAULT_PRIMARY_KEY_PROPERTY_NAME.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/DatasourceDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/FieldsClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/FilterClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/Flatten.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/FullPropertyDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/HasManyDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/HasOneDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/Identity.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/IncludeClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/ItemFilterClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/ModelData.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/ModelDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/ModelId.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/NestedIncludeClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/NormalizedFieldsClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/NormalizedIncludeClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/OperatorClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/OptionalUnlessRequiredId.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/OrderClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PartialBy.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PartialWithoutId.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PolyBelongsToDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PolyHasManyDefinitionWithTargetKeys.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PolyHasManyDefinitionWithTargetRelationName.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PolyHasOneDefinitionWithTargetKeys.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PolyHasOneDefinitionWithTargetRelationName.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PropertiesClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PropertyDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PropertyDefinitionMap.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PropertyValidateOptions.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PropertyValidator.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/PropertyValidatorContext.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/ReferencesManyDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/RelationDefinition.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/RelationDefinitionMap.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/WhereClause.html


File diff suppressed because it is too large
+ 0 - 0
docs/types/WithoutId.html


+ 1 - 1
package.json

@@ -37,7 +37,7 @@
   },
   "devDependencies": {
     "@commitlint/cli": "^18.6.1",
-    "@commitlint/config-conventional": "^18.6.1",
+    "@commitlint/config-conventional": "^18.6.2",
     "@types/chai": "^4.3.11",
     "@types/chai-as-promised": "^7.1.8",
     "@types/mocha": "^10.0.6",

+ 18 - 10
src/adapter/decorator/data-validation-decorator.js

@@ -21,32 +21,40 @@ export class DataValidationDecorator extends Service {
       );
 
     const create = adapter.create;
-    adapter.create = function (modelName, modelData, filter) {
-      this.getService(ModelDataValidator).validate(modelName, modelData);
+    adapter.create = async function (modelName, modelData, filter) {
+      await this.getService(ModelDataValidator).validate(modelName, modelData);
       return create.call(this, modelName, modelData, filter);
     };
 
     const replaceById = adapter.replaceById;
-    adapter.replaceById = function (modelName, id, modelData, filter) {
-      this.getService(ModelDataValidator).validate(modelName, modelData);
+    adapter.replaceById = async function (modelName, id, modelData, filter) {
+      await this.getService(ModelDataValidator).validate(modelName, modelData);
       return replaceById.call(this, modelName, id, modelData, filter);
     };
 
     const replaceOrCreate = adapter.replaceOrCreate;
-    adapter.replaceOrCreate = function (modelName, modelData, filter) {
-      this.getService(ModelDataValidator).validate(modelName, modelData);
+    adapter.replaceOrCreate = async function (modelName, modelData, filter) {
+      await this.getService(ModelDataValidator).validate(modelName, modelData);
       return replaceOrCreate.call(this, modelName, modelData, filter);
     };
 
     const patch = adapter.patch;
-    adapter.patch = function (modelName, modelData, where) {
-      this.getService(ModelDataValidator).validate(modelName, modelData, true);
+    adapter.patch = async function (modelName, modelData, where) {
+      await this.getService(ModelDataValidator).validate(
+        modelName,
+        modelData,
+        true,
+      );
       return patch.call(this, modelName, modelData, where);
     };
 
     const patchById = adapter.patchById;
-    adapter.patchById = function (modelName, id, modelData, filter) {
-      this.getService(ModelDataValidator).validate(modelName, modelData, true);
+    adapter.patchById = async function (modelName, id, modelData, filter) {
+      await this.getService(ModelDataValidator).validate(
+        modelName,
+        modelData,
+        true,
+      );
       return patchById.call(this, modelName, id, modelData, filter);
     };
   }

+ 40 - 0
src/adapter/decorator/data-validation-decorator.spec.js

@@ -74,4 +74,44 @@ describe('DataValidationDecorator', function () {
     expect(V.validate).to.be.called.once;
     expect(V.validate).to.be.called.with.exactly('model', data, true);
   });
+
+  it('waits the validator execution in the "create" method', async function () {
+    const schema = new Schema();
+    schema.defineModel({name: 'model'});
+    const adapter = S.getService(TestAdapter);
+    const validator = S.getService(ModelDataValidator);
+    validator.validate = () => Promise.reject('rejected');
+    const promise = adapter.create('model', {});
+    await expect(promise).to.be.rejectedWith('rejected');
+  });
+
+  it('waits the validator execution in the "replaceById" method', async function () {
+    const schema = new Schema();
+    schema.defineModel({name: 'model'});
+    const adapter = S.getService(TestAdapter);
+    const validator = S.getService(ModelDataValidator);
+    validator.validate = () => Promise.reject('rejected');
+    const promise = adapter.replaceById('model', 1, {});
+    await expect(promise).to.be.rejectedWith('rejected');
+  });
+
+  it('waits the validator execution in the "replaceOrCreate" method', async function () {
+    const schema = new Schema();
+    schema.defineModel({name: 'model'});
+    const adapter = S.getService(TestAdapter);
+    const validator = S.getService(ModelDataValidator);
+    validator.validate = () => Promise.reject('rejected');
+    const promise = adapter.replaceOrCreate('model', {});
+    await expect(promise).to.be.rejectedWith('rejected');
+  });
+
+  it('waits the validator execution in the "patchById" method', async function () {
+    const schema = new Schema();
+    schema.defineModel({name: 'model'});
+    const adapter = S.getService(TestAdapter);
+    const validator = S.getService(ModelDataValidator);
+    validator.validate = () => Promise.reject('rejected');
+    const promise = adapter.patchById('model', 1, {});
+    await expect(promise).to.be.rejectedWith('rejected');
+  });
 });

+ 4 - 16
src/definition/model/model-data-validator.d.ts

@@ -1,6 +1,5 @@
 import {ModelData} from '../../types.js';
 import {Service} from '@e22m4u/js-service';
-import {PropertyDefinition} from './properties/index.js';
 
 /**
  * Model data validator.
@@ -13,20 +12,9 @@ export declare class ModelDataValidator extends Service {
    * @param modelData
    * @param isPartial
    */
-  validate(modelName: string, modelData: ModelData, isPartial?: boolean): void;
-
-  /**
-   * Validate property value.
-   *
-   * @param modelName
-   * @param propName
-   * @param propDef
-   * @param propValue
-   */
-  validatePropertyValue(
+  validate(
     modelName: string,
-    propName: string,
-    propDef: PropertyDefinition,
-    propValue: unknown,
-  ): void;
+    modelData: ModelData,
+    isPartial?: boolean,
+  ): Promise<void>;
 }

+ 87 - 11
src/definition/model/model-data-validator.js

@@ -3,6 +3,7 @@ import {DataType} from './properties/index.js';
 import {getCtorName} from '../../utils/index.js';
 import {isPureObject} from '../../utils/index.js';
 import {InvalidArgumentError} from '../../errors/index.js';
+import {PropertyValidatorRegistry} from './properties/index.js';
 import {ModelDefinitionUtils} from './model-definition-utils.js';
 
 /**
@@ -15,8 +16,9 @@ export class ModelDataValidator extends Service {
    * @param {string} modelName
    * @param {object} modelData
    * @param {boolean} isPartial
+   * @returns {Promise<void>}
    */
-  validate(modelName, modelData, isPartial = false) {
+  async validate(modelName, modelData, isPartial = false) {
     if (!isPureObject(modelData))
       throw new InvalidArgumentError(
         'The data of the model %v should be an Object, but %v given.',
@@ -28,16 +30,16 @@ export class ModelDataValidator extends Service {
         ModelDefinitionUtils,
       ).getPropertiesDefinitionInBaseModelHierarchy(modelName);
     const propNames = Object.keys(isPartial ? modelData : propDefs);
-    propNames.forEach(propName => {
+    for (const propName of propNames) {
       const propDef = propDefs[propName];
-      if (!propDef) return;
-      this._validatePropertyValue(
+      if (!propDef) continue;
+      await this._validatePropertyValue(
         modelName,
         propName,
         propDef,
         modelData[propName],
       );
-    });
+    }
   }
 
   /**
@@ -47,8 +49,9 @@ export class ModelDataValidator extends Service {
    * @param {string} propName
    * @param {string|object} propDef
    * @param {*} propValue
+   * @returns {Promise<void>}
    */
-  _validatePropertyValue(modelName, propName, propDef, propValue) {
+  async _validatePropertyValue(modelName, propName, propDef, propValue) {
     // undefined and null
     if (propValue == null) {
       const isRequired =
@@ -62,7 +65,19 @@ export class ModelDataValidator extends Service {
       );
     }
     // DataType
-    this._validatePropertyValueType(modelName, propName, propDef, propValue);
+    await this._validatePropertyValueType(
+      modelName,
+      propName,
+      propDef,
+      propValue,
+    );
+    // PropertyValidators
+    await this._validateByPropertyValidators(
+      modelName,
+      propName,
+      propDef,
+      propValue,
+    );
   }
 
   /**
@@ -73,9 +88,9 @@ export class ModelDataValidator extends Service {
    * @param {string|object} propDef
    * @param {*} propValue
    * @param {boolean} isArrayValue
-   * @returns {void}
+   * @returns {Promise<void>}
    */
-  _validatePropertyValueType(
+  async _validatePropertyValueType(
     modelName,
     propName,
     propDef,
@@ -123,7 +138,7 @@ export class ModelDataValidator extends Service {
       // ARRAY
       case DataType.ARRAY:
         if (!Array.isArray(propValue)) throw createError('an Array');
-        propValue.forEach(value =>
+        const arrayItemsValidationPromises = propValue.map(async value =>
           this._validatePropertyValueType(
             modelName,
             propName,
@@ -132,13 +147,74 @@ export class ModelDataValidator extends Service {
             true,
           ),
         );
+        await Promise.all(arrayItemsValidationPromises);
         break;
       // OBJECT
       case DataType.OBJECT:
         if (!isPureObject(propValue)) throw createError('an Object');
         if (typeof propDef === 'object' && propDef.model)
-          this.validate(propDef.model, propValue);
+          await this.validate(propDef.model, propValue);
         break;
     }
   }
+
+  /**
+   * Validate by property validators.
+   *
+   * @param {string} modelName
+   * @param {string} propName
+   * @param {string|object} propDef
+   * @param {*} propValue
+   * @returns {Promise<void>}
+   */
+  async _validateByPropertyValidators(modelName, propName, propDef, propValue) {
+    if (typeof propDef === 'string' || propDef.validate == null) return;
+    const options = propDef.validate;
+    const propertyValidatorRegistry = this.getService(
+      PropertyValidatorRegistry,
+    );
+    const createError = validatorName =>
+      new InvalidArgumentError(
+        'The property %v of the model %v has an invalid value %v ' +
+          'that caught by the validator %v.',
+        propName,
+        modelName,
+        propValue,
+        validatorName,
+      );
+    const container = this.container;
+    const validateBy = async (validatorName, validatorOptions = undefined) => {
+      const validator = propertyValidatorRegistry.getValidator(validatorName);
+      const context = {validatorName, modelName, propName, propDef, container};
+      const valid = await validator(propValue, validatorOptions, context);
+      if (valid !== true) throw createError(validatorName);
+    };
+    if (options && typeof options === 'string') {
+      await validateBy(options);
+    } else if (Array.isArray(options)) {
+      const validationPromises = options.map(validatorName =>
+        validateBy(validatorName),
+      );
+      await Promise.all(validationPromises);
+    } else if (options !== null && typeof options === 'object') {
+      const validationPromises = [];
+      Object.keys(options).forEach(validatorName => {
+        if (Object.prototype.hasOwnProperty.call(options, validatorName)) {
+          const validatorOptions = options[validatorName];
+          const validationPromise = validateBy(validatorName, validatorOptions);
+          validationPromises.push(validationPromise);
+        }
+      });
+      await Promise.all(validationPromises);
+    } else {
+      throw new InvalidArgumentError(
+        'The provided option "validate" of the property %v in the model %v ' +
+          'should be a non-empty String, an Array of String or an Object, ' +
+          'but %v given.',
+        propName,
+        modelName,
+        options,
+      );
+    }
+  }
 }

File diff suppressed because it is too large
+ 185 - 197
src/definition/model/model-data-validator.spec.js


+ 1 - 0
src/definition/model/properties/index.d.ts

@@ -1,4 +1,5 @@
 export * from './data-type.js';
 export * from './property-definition.js';
+export * from './property-validator/index.js';
 export * from './properties-definition-validator.js';
 export * from './primary-keys-definition-validator.js';

+ 1 - 0
src/definition/model/properties/index.js

@@ -1,4 +1,5 @@
 export * from './data-type.js';
 export * from './property-definition.js';
+export * from './property-validator/index.js';
 export * from './properties-definition-validator.js';
 export * from './primary-keys-definition-validator.js';

Some files were not shown because too many files changed in this diff