@e22m4u/js-repository 0.1.1 → 0.1.3

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 (141) hide show
  1. package/.eslintrc.cjs +41 -17
  2. package/.husky/commit-msg +1 -4
  3. package/.husky/pre-commit +0 -3
  4. package/.mocharc.cjs +2 -2
  5. package/README.md +2 -2
  6. package/docs/assets/main.js +2 -2
  7. package/docs/assets/navigation.js +1 -1
  8. package/docs/assets/search.js +1 -1
  9. package/docs/assets/style.css +35 -15
  10. package/docs/classes/Adapter.html +19 -19
  11. package/docs/classes/AdapterLoader.html +8 -8
  12. package/docs/classes/AdapterRegistry.html +8 -8
  13. package/docs/classes/BelongsToResolver.html +9 -9
  14. package/docs/classes/DatasourceDefinitionValidator.html +8 -8
  15. package/docs/classes/DefinitionRegistry.html +12 -12
  16. package/docs/classes/FieldsClauseTool.html +10 -10
  17. package/docs/classes/HasManyResolver.html +10 -10
  18. package/docs/classes/HasOneResolver.html +10 -10
  19. package/docs/classes/IncludeClauseTool.html +12 -12
  20. package/docs/classes/InvalidArgumentError.html +7 -5
  21. package/docs/classes/InvalidOperatorValueError.html +7 -5
  22. package/docs/classes/ModelDataSanitizer.html +8 -8
  23. package/docs/classes/ModelDataValidator.html +9 -9
  24. package/docs/classes/ModelDefinitionUtils.html +23 -23
  25. package/docs/classes/ModelDefinitionValidator.html +8 -8
  26. package/docs/classes/NotImplementedError.html +7 -5
  27. package/docs/classes/OperatorClauseTool.html +32 -32
  28. package/docs/classes/OrderClauseTool.html +10 -10
  29. package/docs/classes/PrimaryKeysDefinitionValidator.html +8 -8
  30. package/docs/classes/PropertiesDefinitionValidator.html +8 -8
  31. package/docs/classes/ReferencesManyResolver.html +8 -8
  32. package/docs/classes/RelationsDefinitionValidator.html +8 -8
  33. package/docs/classes/Repository.html +28 -24
  34. package/docs/classes/RepositoryRegistry.html +9 -9
  35. package/docs/classes/Schema.html +10 -10
  36. package/docs/classes/SliceClauseTool.html +10 -10
  37. package/docs/classes/WhereClauseTool.html +9 -9
  38. package/docs/enums/DataType.html +2 -2
  39. package/docs/enums/DecoratorTargetType.html +11 -0
  40. package/docs/enums/RelationType.html +2 -2
  41. package/docs/functions/capitalize.html +1 -1
  42. package/docs/functions/cloneDeep.html +2 -2
  43. package/docs/functions/excludeObjectKeys.html +2 -2
  44. package/docs/functions/getCtorName.html +1 -1
  45. package/docs/functions/getDecoratorTargetType.html +2 -0
  46. package/docs/functions/getValueByPath.html +1 -1
  47. package/docs/functions/isCtor.html +3 -2
  48. package/docs/functions/isPureObject.html +1 -1
  49. package/docs/functions/selectObjectKeys.html +2 -2
  50. package/docs/functions/singularize.html +1 -1
  51. package/docs/functions/stringToRegexp.html +2 -2
  52. package/docs/index.html +3 -3
  53. package/docs/interfaces/AndClause.html +2 -2
  54. package/docs/interfaces/Constructor.html +4 -0
  55. package/docs/interfaces/OrClause.html +2 -2
  56. package/docs/modules.html +4 -1
  57. package/docs/types/AnyObject.html +1 -1
  58. package/docs/types/BelongsToDefinition.html +1 -1
  59. package/docs/types/DEFAULT_PRIMARY_KEY_PROPERTY_NAME.html +1 -1
  60. package/docs/types/DatasourceDefinition.html +1 -1
  61. package/docs/types/FieldsClause.html +1 -1
  62. package/docs/types/FilterClause.html +1 -1
  63. package/docs/types/Flatten.html +1 -1
  64. package/docs/types/FullPropertyDefinition.html +1 -1
  65. package/docs/types/HasManyDefinition.html +1 -1
  66. package/docs/types/HasOneDefinition.html +1 -1
  67. package/docs/types/Identity.html +2 -2
  68. package/docs/types/IncludeClause.html +1 -1
  69. package/docs/types/ItemFilterClause.html +2 -2
  70. package/docs/types/ModelData.html +1 -1
  71. package/docs/types/ModelDefinition.html +1 -1
  72. package/docs/types/ModelId.html +1 -1
  73. package/docs/types/NestedIncludeClause.html +1 -1
  74. package/docs/types/NormalizedFieldsClause.html +1 -1
  75. package/docs/types/NormalizedIncludeClause.html +1 -1
  76. package/docs/types/OperatorClause.html +3 -3
  77. package/docs/types/OptionalUnlessRequiredId.html +2 -2
  78. package/docs/types/OrderClause.html +1 -1
  79. package/docs/types/PartialBy.html +2 -2
  80. package/docs/types/PartialWithoutId.html +2 -2
  81. package/docs/types/PolyBelongsToDefinition.html +1 -1
  82. package/docs/types/PolyHasManyDefinitionWithTargetKeys.html +1 -1
  83. package/docs/types/PolyHasManyDefinitionWithTargetRelationName.html +1 -1
  84. package/docs/types/PolyHasOneDefinitionWithTargetKeys.html +1 -1
  85. package/docs/types/PolyHasOneDefinitionWithTargetRelationName.html +1 -1
  86. package/docs/types/PropertiesClause.html +3 -3
  87. package/docs/types/PropertyDefinition.html +1 -1
  88. package/docs/types/PropertyDefinitionMap.html +1 -1
  89. package/docs/types/ReferencesManyDefinition.html +1 -1
  90. package/docs/types/RelationDefinition.html +1 -1
  91. package/docs/types/RelationDefinitionMap.html +1 -1
  92. package/docs/types/WhereClause.html +2 -2
  93. package/docs/types/WithoutId.html +2 -2
  94. package/mocha.setup.js +8 -3
  95. package/package.json +23 -19
  96. package/src/adapter/decorator/data-sanitizing-decorator.d.ts +2 -1
  97. package/src/adapter/decorator/data-validation-decorator.d.ts +2 -1
  98. package/src/adapter/decorator/data-validation-decorator.js +18 -10
  99. package/src/adapter/decorator/data-validation-decorator.spec.js +40 -0
  100. package/src/adapter/decorator/default-values-decorator.d.ts +2 -1
  101. package/src/adapter/decorator/fields-filtering-decorator.d.ts +2 -1
  102. package/src/adapter/decorator/inclusion-decorator.d.ts +2 -1
  103. package/src/definition/model/index.js +1 -0
  104. package/src/definition/model/model-data-validator.d.ts +4 -16
  105. package/src/definition/model/model-data-validator.js +92 -11
  106. package/src/definition/model/model-data-validator.spec.js +1140 -442
  107. package/src/definition/model/model-definition.js +1 -0
  108. package/src/definition/model/properties/index.d.ts +1 -0
  109. package/src/definition/model/properties/index.js +2 -0
  110. package/src/definition/model/properties/properties-definition-validator.js +47 -0
  111. package/src/definition/model/properties/properties-definition-validator.spec.js +50 -0
  112. package/src/definition/model/properties/property-definition.d.ts +2 -0
  113. package/src/definition/model/properties/property-definition.js +1 -0
  114. package/src/definition/model/properties/property-validator/index.d.ts +2 -0
  115. package/src/definition/model/properties/property-validator/index.js +2 -0
  116. package/src/definition/model/properties/property-validator/property-validator-registry.d.ts +29 -0
  117. package/src/definition/model/properties/property-validator/property-validator-registry.js +69 -0
  118. package/src/definition/model/properties/property-validator/property-validator-registry.spec.js +120 -0
  119. package/src/definition/model/properties/property-validator/property-validator.d.ts +30 -0
  120. package/src/definition/model/properties/property-validator/property-validator.js +1 -0
  121. package/src/definition/model/relations/index.js +1 -0
  122. package/src/definition/model/relations/relation-definition.js +1 -0
  123. package/src/filter/filter-clause.d.ts +4 -4
  124. package/src/index.d.ts +1 -1
  125. package/src/index.js +1 -0
  126. package/src/repository/repository.d.ts +9 -3
  127. package/src/repository/repository.js +0 -1
  128. package/src/schema.d.ts +10 -1
  129. package/src/schema.js +13 -0
  130. package/src/schema.spec.ts +115 -0
  131. package/src/types.d.ts +8 -0
  132. package/src/types.js +1 -0
  133. package/src/utils/get-decorator-target-type.d.ts +27 -0
  134. package/src/utils/get-decorator-target-type.js +63 -0
  135. package/src/utils/get-decorator-target-type.spec.js +77 -0
  136. package/src/utils/index.d.ts +1 -0
  137. package/src/utils/index.js +1 -0
  138. package/src/utils/is-ctor.d.ts +2 -1
  139. package/src/utils/is-ctor.js +2 -1
  140. package/src/utils/is-ctor.spec.js +1 -1
  141. package/tsconfig.json +3 -1
@@ -1,3 +1,4 @@
1
+ import {Adapter} from '../adapter.js';
1
2
  import {Service} from '@e22m4u/js-service';
2
3
 
3
4
  /**
@@ -9,5 +10,5 @@ export declare class DataSanitizingDecorator extends Service {
9
10
  *
10
11
  * @param adapter
11
12
  */
12
- decorate(adapter): void;
13
+ decorate(adapter: Adapter): void;
13
14
  }
@@ -1,4 +1,5 @@
1
1
  import {Service} from '@e22m4u/js-service';
2
+ import {Adapter} from '../adapter.js';
2
3
 
3
4
  /**
4
5
  * Data validation decorator.
@@ -9,5 +10,5 @@ export declare class DataValidationDecorator extends Service {
9
10
  *
10
11
  * @param adapter
11
12
  */
12
- decorate(adapter): void;
13
+ decorate(adapter: Adapter): void;
13
14
  }
@@ -21,32 +21,40 @@ export class DataValidationDecorator extends Service {
21
21
  );
22
22
 
23
23
  const create = adapter.create;
24
- adapter.create = function (modelName, modelData, filter) {
25
- this.getService(ModelDataValidator).validate(modelName, modelData);
24
+ adapter.create = async function (modelName, modelData, filter) {
25
+ await this.getService(ModelDataValidator).validate(modelName, modelData);
26
26
  return create.call(this, modelName, modelData, filter);
27
27
  };
28
28
 
29
29
  const replaceById = adapter.replaceById;
30
- adapter.replaceById = function (modelName, id, modelData, filter) {
31
- this.getService(ModelDataValidator).validate(modelName, modelData);
30
+ adapter.replaceById = async function (modelName, id, modelData, filter) {
31
+ await this.getService(ModelDataValidator).validate(modelName, modelData);
32
32
  return replaceById.call(this, modelName, id, modelData, filter);
33
33
  };
34
34
 
35
35
  const replaceOrCreate = adapter.replaceOrCreate;
36
- adapter.replaceOrCreate = function (modelName, modelData, filter) {
37
- this.getService(ModelDataValidator).validate(modelName, modelData);
36
+ adapter.replaceOrCreate = async function (modelName, modelData, filter) {
37
+ await this.getService(ModelDataValidator).validate(modelName, modelData);
38
38
  return replaceOrCreate.call(this, modelName, modelData, filter);
39
39
  };
40
40
 
41
41
  const patch = adapter.patch;
42
- adapter.patch = function (modelName, modelData, where) {
43
- this.getService(ModelDataValidator).validate(modelName, modelData, true);
42
+ adapter.patch = async function (modelName, modelData, where) {
43
+ await this.getService(ModelDataValidator).validate(
44
+ modelName,
45
+ modelData,
46
+ true,
47
+ );
44
48
  return patch.call(this, modelName, modelData, where);
45
49
  };
46
50
 
47
51
  const patchById = adapter.patchById;
48
- adapter.patchById = function (modelName, id, modelData, filter) {
49
- this.getService(ModelDataValidator).validate(modelName, modelData, true);
52
+ adapter.patchById = async function (modelName, id, modelData, filter) {
53
+ await this.getService(ModelDataValidator).validate(
54
+ modelName,
55
+ modelData,
56
+ true,
57
+ );
50
58
  return patchById.call(this, modelName, id, modelData, filter);
51
59
  };
52
60
  }
@@ -74,4 +74,44 @@ describe('DataValidationDecorator', function () {
74
74
  expect(V.validate).to.be.called.once;
75
75
  expect(V.validate).to.be.called.with.exactly('model', data, true);
76
76
  });
77
+
78
+ it('waits the validator execution in the "create" method', async function () {
79
+ const schema = new Schema();
80
+ schema.defineModel({name: 'model'});
81
+ const adapter = S.getService(TestAdapter);
82
+ const validator = S.getService(ModelDataValidator);
83
+ validator.validate = () => Promise.reject('rejected');
84
+ const promise = adapter.create('model', {});
85
+ await expect(promise).to.be.rejectedWith('rejected');
86
+ });
87
+
88
+ it('waits the validator execution in the "replaceById" method', async function () {
89
+ const schema = new Schema();
90
+ schema.defineModel({name: 'model'});
91
+ const adapter = S.getService(TestAdapter);
92
+ const validator = S.getService(ModelDataValidator);
93
+ validator.validate = () => Promise.reject('rejected');
94
+ const promise = adapter.replaceById('model', 1, {});
95
+ await expect(promise).to.be.rejectedWith('rejected');
96
+ });
97
+
98
+ it('waits the validator execution in the "replaceOrCreate" method', async function () {
99
+ const schema = new Schema();
100
+ schema.defineModel({name: 'model'});
101
+ const adapter = S.getService(TestAdapter);
102
+ const validator = S.getService(ModelDataValidator);
103
+ validator.validate = () => Promise.reject('rejected');
104
+ const promise = adapter.replaceOrCreate('model', {});
105
+ await expect(promise).to.be.rejectedWith('rejected');
106
+ });
107
+
108
+ it('waits the validator execution in the "patchById" method', async function () {
109
+ const schema = new Schema();
110
+ schema.defineModel({name: 'model'});
111
+ const adapter = S.getService(TestAdapter);
112
+ const validator = S.getService(ModelDataValidator);
113
+ validator.validate = () => Promise.reject('rejected');
114
+ const promise = adapter.patchById('model', 1, {});
115
+ await expect(promise).to.be.rejectedWith('rejected');
116
+ });
77
117
  });
@@ -1,4 +1,5 @@
1
1
  import {Service} from '@e22m4u/js-service';
2
+ import {Adapter} from '../adapter.js';
2
3
 
3
4
  /**
4
5
  * Default values decorator.
@@ -9,5 +10,5 @@ export declare class DefaultValuesDecorator extends Service {
9
10
  *
10
11
  * @param adapter
11
12
  */
12
- decorate(adapter): void;
13
+ decorate(adapter: Adapter): void;
13
14
  }
@@ -1,4 +1,5 @@
1
1
  import {Service} from '@e22m4u/js-service';
2
+ import {Adapter} from '../adapter.js';
2
3
 
3
4
  /**
4
5
  * Fields filtering decorator.
@@ -9,5 +10,5 @@ export declare class FieldsFilteringDecorator extends Service {
9
10
  *
10
11
  * @param adapter
11
12
  */
12
- decorate(adapter): void;
13
+ decorate(adapter: Adapter): void;
13
14
  }
@@ -1,4 +1,5 @@
1
1
  import {Service} from '@e22m4u/js-service';
2
+ import {Adapter} from '../adapter.js';
2
3
 
3
4
  /**
4
5
  * Inclusion decorator.
@@ -9,5 +10,5 @@ export declare class InclusionDecorator extends Service {
9
10
  *
10
11
  * @param adapter
11
12
  */
12
- decorate(adapter): void;
13
+ decorate(adapter: Adapter): void;
13
14
  }
@@ -1,5 +1,6 @@
1
1
  export * from './relations/index.js';
2
2
  export * from './properties/index.js';
3
+ export * from './model-definition.js';
3
4
  export * from './model-data-validator.js';
4
5
  export * from './model-data-sanitizer.js';
5
6
  export * from './model-definition-utils.js';
@@ -1,6 +1,5 @@
1
1
  import {ModelData} from '../../types.js';
2
2
  import {Service} from '@e22m4u/js-service';
3
- import {PropertyDefinition} from './properties/index.js';
4
3
 
5
4
  /**
6
5
  * Model data validator.
@@ -13,20 +12,9 @@ export declare class ModelDataValidator extends Service {
13
12
  * @param modelData
14
13
  * @param isPartial
15
14
  */
16
- validate(modelName: string, modelData: ModelData, isPartial?: boolean): void;
17
-
18
- /**
19
- * Validate property value.
20
- *
21
- * @param modelName
22
- * @param propName
23
- * @param propDef
24
- * @param propValue
25
- */
26
- validatePropertyValue(
15
+ validate(
27
16
  modelName: string,
28
- propName: string,
29
- propDef: PropertyDefinition,
30
- propValue: unknown,
31
- ): void;
17
+ modelData: ModelData,
18
+ isPartial?: boolean,
19
+ ): Promise<void>;
32
20
  }
@@ -3,6 +3,7 @@ import {DataType} from './properties/index.js';
3
3
  import {getCtorName} from '../../utils/index.js';
4
4
  import {isPureObject} from '../../utils/index.js';
5
5
  import {InvalidArgumentError} from '../../errors/index.js';
6
+ import {PropertyValidatorRegistry} from './properties/index.js';
6
7
  import {ModelDefinitionUtils} from './model-definition-utils.js';
7
8
 
8
9
  /**
@@ -15,8 +16,9 @@ export class ModelDataValidator extends Service {
15
16
  * @param {string} modelName
16
17
  * @param {object} modelData
17
18
  * @param {boolean} isPartial
19
+ * @returns {Promise<void>}
18
20
  */
19
- validate(modelName, modelData, isPartial = false) {
21
+ async validate(modelName, modelData, isPartial = false) {
20
22
  if (!isPureObject(modelData))
21
23
  throw new InvalidArgumentError(
22
24
  'The data of the model %v should be an Object, but %v given.',
@@ -28,16 +30,16 @@ export class ModelDataValidator extends Service {
28
30
  ModelDefinitionUtils,
29
31
  ).getPropertiesDefinitionInBaseModelHierarchy(modelName);
30
32
  const propNames = Object.keys(isPartial ? modelData : propDefs);
31
- propNames.forEach(propName => {
33
+ for (const propName of propNames) {
32
34
  const propDef = propDefs[propName];
33
- if (!propDef) return;
34
- this._validatePropertyValue(
35
+ if (!propDef) continue;
36
+ await this._validatePropertyValue(
35
37
  modelName,
36
38
  propName,
37
39
  propDef,
38
40
  modelData[propName],
39
41
  );
40
- });
42
+ }
41
43
  }
42
44
 
43
45
  /**
@@ -47,8 +49,9 @@ export class ModelDataValidator extends Service {
47
49
  * @param {string} propName
48
50
  * @param {string|object} propDef
49
51
  * @param {*} propValue
52
+ * @returns {Promise<void>}
50
53
  */
51
- _validatePropertyValue(modelName, propName, propDef, propValue) {
54
+ async _validatePropertyValue(modelName, propName, propDef, propValue) {
52
55
  // undefined and null
53
56
  if (propValue == null) {
54
57
  const isRequired =
@@ -62,7 +65,19 @@ export class ModelDataValidator extends Service {
62
65
  );
63
66
  }
64
67
  // DataType
65
- this._validatePropertyValueType(modelName, propName, propDef, propValue);
68
+ await this._validatePropertyValueType(
69
+ modelName,
70
+ propName,
71
+ propDef,
72
+ propValue,
73
+ );
74
+ // PropertyValidators
75
+ await this._validateByPropertyValidators(
76
+ modelName,
77
+ propName,
78
+ propDef,
79
+ propValue,
80
+ );
66
81
  }
67
82
 
68
83
  /**
@@ -73,9 +88,9 @@ export class ModelDataValidator extends Service {
73
88
  * @param {string|object} propDef
74
89
  * @param {*} propValue
75
90
  * @param {boolean} isArrayValue
76
- * @returns {void}
91
+ * @returns {Promise<void>}
77
92
  */
78
- _validatePropertyValueType(
93
+ async _validatePropertyValueType(
79
94
  modelName,
80
95
  propName,
81
96
  propDef,
@@ -123,7 +138,7 @@ export class ModelDataValidator extends Service {
123
138
  // ARRAY
124
139
  case DataType.ARRAY:
125
140
  if (!Array.isArray(propValue)) throw createError('an Array');
126
- propValue.forEach(value =>
141
+ const arrayItemsValidationPromises = propValue.map(async value =>
127
142
  this._validatePropertyValueType(
128
143
  modelName,
129
144
  propName,
@@ -132,13 +147,79 @@ export class ModelDataValidator extends Service {
132
147
  true,
133
148
  ),
134
149
  );
150
+ await Promise.all(arrayItemsValidationPromises);
135
151
  break;
136
152
  // OBJECT
137
153
  case DataType.OBJECT:
138
154
  if (!isPureObject(propValue)) throw createError('an Object');
139
155
  if (typeof propDef === 'object' && propDef.model)
140
- this.validate(propDef.model, propValue);
156
+ await this.validate(propDef.model, propValue);
141
157
  break;
142
158
  }
143
159
  }
160
+
161
+ /**
162
+ * Validate by property validators.
163
+ *
164
+ * @param {string} modelName
165
+ * @param {string} propName
166
+ * @param {string|object} propDef
167
+ * @param {*} propValue
168
+ * @returns {Promise<void>}
169
+ */
170
+ async _validateByPropertyValidators(
171
+ modelName,
172
+ propName,
173
+ propDef,
174
+ propValue,
175
+ ) {
176
+ if (typeof propDef === 'string' || propDef.validate == null) return;
177
+ const options = propDef.validate;
178
+ const propertyValidatorRegistry = this.getService(
179
+ PropertyValidatorRegistry,
180
+ );
181
+ const createError = validatorName =>
182
+ new InvalidArgumentError(
183
+ 'The property %v of the model %v has an invalid value %v ' +
184
+ 'that caught by the validator %v.',
185
+ propName,
186
+ modelName,
187
+ propValue,
188
+ validatorName,
189
+ );
190
+ const container = this.container;
191
+ const validateBy = async (validatorName, validatorOptions = undefined) => {
192
+ const validator = propertyValidatorRegistry.getValidator(validatorName);
193
+ const context = {validatorName, modelName, propName, propDef, container};
194
+ const valid = await validator(propValue, validatorOptions, context);
195
+ if (valid !== true) throw createError(validatorName);
196
+ };
197
+ if (options && typeof options === 'string') {
198
+ await validateBy(options);
199
+ } else if (Array.isArray(options)) {
200
+ const validationPromises = options.map(validatorName =>
201
+ validateBy(validatorName),
202
+ );
203
+ await Promise.all(validationPromises);
204
+ } else if (options !== null && typeof options === 'object') {
205
+ const validationPromises = [];
206
+ Object.keys(options).forEach(validatorName => {
207
+ if (Object.prototype.hasOwnProperty.call(options, validatorName)) {
208
+ const validatorOptions = options[validatorName];
209
+ const validationPromise = validateBy(validatorName, validatorOptions);
210
+ validationPromises.push(validationPromise);
211
+ }
212
+ });
213
+ await Promise.all(validationPromises);
214
+ } else {
215
+ throw new InvalidArgumentError(
216
+ 'The provided option "validate" of the property %v in the model %v ' +
217
+ 'should be a non-empty String, an Array of String or an Object, ' +
218
+ 'but %v given.',
219
+ propName,
220
+ modelName,
221
+ options,
222
+ );
223
+ }
224
+ }
144
225
  }