@e22m4u/js-repository 0.6.4 → 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 (90) hide show
  1. package/README.md +6 -532
  2. package/dist/cjs/index.cjs +141 -1156
  3. package/package.json +7 -7
  4. package/src/adapter/adapter.d.ts +2 -4
  5. package/src/adapter/adapter.js +2 -6
  6. package/src/adapter/adapter.spec.js +3 -15
  7. package/src/adapter/builtin/memory-adapter.js +41 -12
  8. package/src/adapter/builtin/memory-adapter.spec.js +47 -0
  9. package/src/adapter/decorator/index.d.ts +0 -2
  10. package/src/adapter/decorator/index.js +0 -2
  11. package/src/definition/model/index.d.ts +0 -2
  12. package/src/definition/model/index.js +0 -2
  13. package/src/definition/model/properties/index.d.ts +0 -2
  14. package/src/definition/model/properties/index.js +0 -2
  15. package/src/definition/model/properties/properties-definition-validator.js +0 -169
  16. package/src/definition/model/properties/properties-definition-validator.spec.js +0 -162
  17. package/src/definition/model/properties/property-definition.d.ts +1 -5
  18. package/src/definition/model/properties/property-uniqueness-validator.js +2 -2
  19. package/src/filter/filter-clause.d.ts +3 -4
  20. package/src/filter/where-clause-tool.js +2 -2
  21. package/src/utils/index.d.ts +1 -5
  22. package/src/utils/index.js +1 -5
  23. package/src/utils/is-plain-object.d.ts +6 -0
  24. package/src/utils/{is-pure-object.js → is-plain-object.js} +2 -2
  25. package/src/utils/is-plain-object.spec.js +25 -0
  26. package/src/utils/model-name-to-model-key.js +0 -4
  27. package/src/utils/model-name-to-model-key.spec.js +0 -23
  28. package/tsconfig.json +2 -2
  29. package/src/adapter/decorator/data-transformation-decorator.d.ts +0 -14
  30. package/src/adapter/decorator/data-transformation-decorator.js +0 -54
  31. package/src/adapter/decorator/data-transformation-decorator.spec.js +0 -193
  32. package/src/adapter/decorator/data-validation-decorator.d.ts +0 -14
  33. package/src/adapter/decorator/data-validation-decorator.js +0 -54
  34. package/src/adapter/decorator/data-validation-decorator.spec.js +0 -105
  35. package/src/definition/model/model-data-transformer.d.ts +0 -16
  36. package/src/definition/model/model-data-transformer.js +0 -170
  37. package/src/definition/model/model-data-transformer.spec.js +0 -2312
  38. package/src/definition/model/model-data-validator.d.ts +0 -16
  39. package/src/definition/model/model-data-validator.js +0 -318
  40. package/src/definition/model/model-data-validator.spec.js +0 -4528
  41. package/src/definition/model/properties/property-transformer/builtin/index.d.ts +0 -3
  42. package/src/definition/model/properties/property-transformer/builtin/index.js +0 -3
  43. package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.d.ts +0 -6
  44. package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.js +0 -19
  45. package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.spec.js +0 -39
  46. package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.d.ts +0 -6
  47. package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.js +0 -19
  48. package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.spec.js +0 -39
  49. package/src/definition/model/properties/property-transformer/builtin/trim-transformer.d.ts +0 -6
  50. package/src/definition/model/properties/property-transformer/builtin/trim-transformer.js +0 -19
  51. package/src/definition/model/properties/property-transformer/builtin/trim-transformer.spec.js +0 -39
  52. package/src/definition/model/properties/property-transformer/index.d.ts +0 -2
  53. package/src/definition/model/properties/property-transformer/index.js +0 -2
  54. package/src/definition/model/properties/property-transformer/property-transformer-registry.d.ts +0 -29
  55. package/src/definition/model/properties/property-transformer/property-transformer-registry.js +0 -76
  56. package/src/definition/model/properties/property-transformer/property-transformer-registry.spec.js +0 -133
  57. package/src/definition/model/properties/property-transformer/property-transformer.d.ts +0 -27
  58. package/src/definition/model/properties/property-transformer/property-transformer.js +0 -1
  59. package/src/definition/model/properties/property-validator/builtin/index.d.ts +0 -3
  60. package/src/definition/model/properties/property-validator/builtin/index.js +0 -3
  61. package/src/definition/model/properties/property-validator/builtin/max-length-validator.d.ts +0 -6
  62. package/src/definition/model/properties/property-validator/builtin/max-length-validator.js +0 -28
  63. package/src/definition/model/properties/property-validator/builtin/max-length-validator.spec.js +0 -100
  64. package/src/definition/model/properties/property-validator/builtin/min-length-validator.d.ts +0 -6
  65. package/src/definition/model/properties/property-validator/builtin/min-length-validator.js +0 -28
  66. package/src/definition/model/properties/property-validator/builtin/min-length-validator.spec.js +0 -100
  67. package/src/definition/model/properties/property-validator/builtin/regexp-validator.d.ts +0 -6
  68. package/src/definition/model/properties/property-validator/builtin/regexp-validator.js +0 -30
  69. package/src/definition/model/properties/property-validator/builtin/regexp-validator.spec.js +0 -102
  70. package/src/definition/model/properties/property-validator/index.d.ts +0 -2
  71. package/src/definition/model/properties/property-validator/index.js +0 -2
  72. package/src/definition/model/properties/property-validator/property-validator-registry.d.ts +0 -29
  73. package/src/definition/model/properties/property-validator/property-validator-registry.js +0 -76
  74. package/src/definition/model/properties/property-validator/property-validator-registry.spec.js +0 -132
  75. package/src/definition/model/properties/property-validator/property-validator.d.ts +0 -25
  76. package/src/definition/model/properties/property-validator/property-validator.js +0 -1
  77. package/src/utils/get-ctor-name.d.ts +0 -6
  78. package/src/utils/get-ctor-name.js +0 -11
  79. package/src/utils/get-ctor-name.spec.js +0 -17
  80. package/src/utils/get-decorator-target-type.d.ts +0 -27
  81. package/src/utils/get-decorator-target-type.js +0 -63
  82. package/src/utils/get-decorator-target-type.spec.js +0 -80
  83. package/src/utils/is-ctor.d.ts +0 -8
  84. package/src/utils/is-ctor.js +0 -11
  85. package/src/utils/is-ctor.spec.js +0 -26
  86. package/src/utils/is-pure-object.d.ts +0 -6
  87. package/src/utils/is-pure-object.spec.js +0 -25
  88. package/src/utils/transform-promise.d.ts +0 -13
  89. package/src/utils/transform-promise.js +0 -15
  90. package/src/utils/transform-promise.spec.js +0 -19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-repository",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "Реализация репозитория для работы с базами данных",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "dependencies": {
42
42
  "@e22m4u/js-empty-values": "~0.1.3",
43
43
  "@e22m4u/js-format": "~0.2.1",
44
- "@e22m4u/js-service": "~0.4.5"
44
+ "@e22m4u/js-service": "~0.4.6"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@commitlint/cli": "~20.1.0",
@@ -51,21 +51,21 @@
51
51
  "@types/chai-spies": "~1.0.6",
52
52
  "@types/mocha": "~10.0.10",
53
53
  "c8": "~10.1.3",
54
- "chai": "~6.2.0",
54
+ "chai": "~6.2.1",
55
55
  "chai-as-promised": "~8.0.2",
56
56
  "chai-spies": "~1.1.0",
57
- "esbuild": "~0.25.12",
57
+ "esbuild": "~0.27.0",
58
58
  "eslint": "~9.39.1",
59
59
  "eslint-config-prettier": "~10.1.8",
60
60
  "eslint-plugin-chai-expect": "~3.1.0",
61
- "eslint-plugin-jsdoc": "~61.1.12",
61
+ "eslint-plugin-jsdoc": "~61.4.1",
62
62
  "eslint-plugin-mocha": "~11.2.0",
63
63
  "husky": "~9.1.7",
64
64
  "mocha": "~11.7.5",
65
65
  "prettier": "~3.6.2",
66
- "rimraf": "~6.1.0",
66
+ "rimraf": "~6.1.2",
67
67
  "ts-node": "~10.9.2",
68
68
  "typescript": "~5.9.3",
69
- "typescript-eslint": "~8.46.3"
69
+ "typescript-eslint": "~8.48.0"
70
70
  }
71
71
  }
@@ -12,11 +12,9 @@ import {ServiceContainer} from '@e22m4u/js-service';
12
12
  */
13
13
  export declare class Adapter extends Service {
14
14
  /**
15
- * Kind.
16
- *
17
- * @type {string}
15
+ * Kinds.
18
16
  */
19
- static kind: string;
17
+ static kinds: string[];
20
18
 
21
19
  /**
22
20
  * Settings.
@@ -4,10 +4,8 @@ import {Service} from '@e22m4u/js-service';
4
4
  import {NotImplementedError} from '../errors/index.js';
5
5
  import {InclusionDecorator} from './decorator/index.js';
6
6
  import {DefaultValuesDecorator} from './decorator/index.js';
7
- import {DataValidationDecorator} from './decorator/index.js';
8
7
  import {DataSanitizingDecorator} from './decorator/index.js';
9
8
  import {FieldsFilteringDecorator} from './decorator/index.js';
10
- import {DataTransformationDecorator} from './decorator/index.js';
11
9
  import {PropertyUniquenessDecorator} from './decorator/index.js';
12
10
 
13
11
  /**
@@ -22,9 +20,9 @@ export const ADAPTER_CLASS_NAME = 'Adapter';
22
20
  */
23
21
  export class Adapter extends Service {
24
22
  /**
25
- * Kind.
23
+ * Kinds.
26
24
  *
27
- * @type {string}
25
+ * @type {string[]}
28
26
  */
29
27
  static kinds = [...Service.kinds, ADAPTER_CLASS_NAME];
30
28
 
@@ -57,8 +55,6 @@ export class Adapter extends Service {
57
55
  if (this.constructor !== Adapter) {
58
56
  this.getService(DataSanitizingDecorator).decorate(this);
59
57
  this.getService(DefaultValuesDecorator).decorate(this);
60
- this.getService(DataTransformationDecorator).decorate(this);
61
- this.getService(DataValidationDecorator).decorate(this);
62
58
  this.getService(PropertyUniquenessDecorator).decorate(this);
63
59
  this.getService(FieldsFilteringDecorator).decorate(this);
64
60
  this.getService(InclusionDecorator).decorate(this);
@@ -7,10 +7,8 @@ import {ServiceContainer} from '@e22m4u/js-service';
7
7
  import {DatabaseSchema} from '../database-schema.js';
8
8
  import {InclusionDecorator} from './decorator/index.js';
9
9
  import {DefaultValuesDecorator} from './decorator/index.js';
10
- import {DataValidationDecorator} from './decorator/index.js';
11
10
  import {DataSanitizingDecorator} from './decorator/index.js';
12
11
  import {FieldsFilteringDecorator} from './decorator/index.js';
13
- import {DataTransformationDecorator} from './decorator/index.js';
14
12
  import {PropertyUniquenessDecorator} from './decorator/index.js';
15
13
 
16
14
  const sandbox = chai.spy.sandbox();
@@ -45,11 +43,9 @@ describe('Adapter', function () {
45
43
  const dbs = new DatabaseSchema();
46
44
  const dec1 = dbs.getService(DataSanitizingDecorator);
47
45
  const dec2 = dbs.getService(DefaultValuesDecorator);
48
- const dec3 = dbs.getService(DataTransformationDecorator);
49
- const dec4 = dbs.getService(DataValidationDecorator);
50
- const dec5 = dbs.getService(PropertyUniquenessDecorator);
51
- const dec6 = dbs.getService(FieldsFilteringDecorator);
52
- const dec7 = dbs.getService(InclusionDecorator);
46
+ const dec3 = dbs.getService(PropertyUniquenessDecorator);
47
+ const dec4 = dbs.getService(FieldsFilteringDecorator);
48
+ const dec5 = dbs.getService(InclusionDecorator);
53
49
  const order = [];
54
50
  const decorate = function (ctx) {
55
51
  expect(ctx).to.be.instanceof(Adapter);
@@ -60,8 +56,6 @@ describe('Adapter', function () {
60
56
  sandbox.on(dec3, 'decorate', decorate);
61
57
  sandbox.on(dec4, 'decorate', decorate);
62
58
  sandbox.on(dec5, 'decorate', decorate);
63
- sandbox.on(dec6, 'decorate', decorate);
64
- sandbox.on(dec7, 'decorate', decorate);
65
59
  new Adapter(dbs.container);
66
60
  expect(order).to.be.empty;
67
61
  expect(dec1.decorate).to.be.not.called;
@@ -69,8 +63,6 @@ describe('Adapter', function () {
69
63
  expect(dec3.decorate).to.be.not.called;
70
64
  expect(dec4.decorate).to.be.not.called;
71
65
  expect(dec5.decorate).to.be.not.called;
72
- expect(dec6.decorate).to.be.not.called;
73
- expect(dec7.decorate).to.be.not.called;
74
66
  class ExtendedAdapter extends Adapter {}
75
67
  new ExtendedAdapter(dbs.container);
76
68
  expect(order[0]).to.be.eql(dec1);
@@ -78,15 +70,11 @@ describe('Adapter', function () {
78
70
  expect(order[2]).to.be.eql(dec3);
79
71
  expect(order[3]).to.be.eql(dec4);
80
72
  expect(order[4]).to.be.eql(dec5);
81
- expect(order[5]).to.be.eql(dec6);
82
- expect(order[6]).to.be.eql(dec7);
83
73
  expect(dec1.decorate).to.be.called.once;
84
74
  expect(dec2.decorate).to.be.called.once;
85
75
  expect(dec3.decorate).to.be.called.once;
86
76
  expect(dec4.decorate).to.be.called.once;
87
77
  expect(dec5.decorate).to.be.called.once;
88
- expect(dec6.decorate).to.be.called.once;
89
- expect(dec7.decorate).to.be.called.once;
90
78
  });
91
79
  });
92
80
 
@@ -50,10 +50,9 @@ export class MemoryAdapter extends Adapter {
50
50
  * @returns {number}
51
51
  */
52
52
  _genNextIdValue(modelName, propName) {
53
- const propType = this.getService(
54
- ModelDefinitionUtils,
55
- ).getDataTypeByPropertyName(modelName, propName);
56
- if (propType !== DataType.ANY && propType !== DataType.NUMBER)
53
+ const modelUtils = this.getService(ModelDefinitionUtils);
54
+ const propType = modelUtils.getDataTypeByPropertyName(modelName, propName);
55
+ if (propType !== DataType.ANY && propType !== DataType.NUMBER) {
57
56
  throw new InvalidArgumentError(
58
57
  'The memory adapter able to generate only Number identifiers, ' +
59
58
  'but the primary key %v of the model %v is defined as %s. ' +
@@ -65,18 +64,36 @@ export class MemoryAdapter extends Adapter {
65
64
  capitalize(propType),
66
65
  propName,
67
66
  );
68
- const tableName =
69
- this.getService(ModelDefinitionUtils).getTableNameByModelName(modelName);
70
- const lastId = this._lastIds.get(tableName) ?? 0;
71
- const nextId = lastId + 1;
72
- this._lastIds.set(tableName, nextId);
67
+ }
68
+ const tableName = modelUtils.getTableNameByModelName(modelName);
73
69
  const table = this._getTableOrCreate(modelName);
74
- const existedIds = Array.from(table.keys());
75
- if (existedIds.includes(nextId))
76
- return this._genNextIdValue(modelName, propName);
70
+ let nextId = this._lastIds.get(tableName) ?? 0;
71
+ do {
72
+ nextId++;
73
+ } while (table.has(nextId));
74
+ this._lastIds.set(tableName, nextId);
77
75
  return nextId;
78
76
  }
79
77
 
78
+ /**
79
+ * Update last id value if needed.
80
+ *
81
+ * Если переданное значение последнего использованного
82
+ * идентификатора больше текущего, то текущее значение
83
+ * перезаписывается полученным.
84
+ *
85
+ * @param {string} modelName
86
+ * @param {number} idValue
87
+ */
88
+ _updateLastIdValueIfNeeded(modelName, idValue) {
89
+ const tableName =
90
+ this.getService(ModelDefinitionUtils).getTableNameByModelName(modelName);
91
+ const currentLastId = this._lastIds.get(tableName) ?? 0;
92
+ if (idValue > currentLastId) {
93
+ this._lastIds.set(tableName, idValue);
94
+ }
95
+ }
96
+
80
97
  /**
81
98
  * Create
82
99
  *
@@ -95,6 +112,12 @@ export class MemoryAdapter extends Adapter {
95
112
  if (idValue == null || idValue === '' || idValue === 0) {
96
113
  idValue = this._genNextIdValue(modelName, pkPropName);
97
114
  }
115
+ // если идентификатор передан вручную и является числом,
116
+ // то значение последнего использованного идентификатора
117
+ // обновляется на полученное
118
+ else if (typeof idValue === 'number') {
119
+ this._updateLastIdValueIfNeeded(modelName, idValue);
120
+ }
98
121
 
99
122
  const table = this._getTableOrCreate(modelName);
100
123
  if (table.has(idValue))
@@ -174,6 +197,12 @@ export class MemoryAdapter extends Adapter {
174
197
  if (idValue == null || idValue === '' || idValue === 0) {
175
198
  idValue = this._genNextIdValue(modelName, pkPropName);
176
199
  }
200
+ // если идентификатор передан вручную и является числом,
201
+ // то значение последнего использованного идентификатора
202
+ // обновляется на полученное
203
+ else if (typeof idValue === 'number') {
204
+ this._updateLastIdValueIfNeeded(modelName, idValue);
205
+ }
177
206
 
178
207
  const table = this._getTableOrCreate(modelName);
179
208
  modelData = cloneDeep(modelData);
@@ -56,6 +56,53 @@ describe('MemoryAdapter', function () {
56
56
  expect(id2).to.be.eq(2);
57
57
  expect(id3).to.be.eq(3);
58
58
  });
59
+
60
+ it('increments from the the last known identifier', function () {
61
+ const dbs = new DatabaseSchema();
62
+ dbs.defineModel({name: 'model'});
63
+ const A = dbs.getService(MemoryAdapter);
64
+ A._lastIds.set('model', 10);
65
+ const id1 = A._genNextIdValue('model', DEF_PK);
66
+ const id2 = A._genNextIdValue('model', DEF_PK);
67
+ const id3 = A._genNextIdValue('model', DEF_PK);
68
+ expect(id1).to.be.eq(11);
69
+ expect(id2).to.be.eq(12);
70
+ expect(id3).to.be.eq(13);
71
+ });
72
+ });
73
+
74
+ describe('_updateLastIdValueIfNeeded', function () {
75
+ it('does nothing when the given identifier is lower or equal', function () {
76
+ const dbs = new DatabaseSchema();
77
+ dbs.defineModel({name: 'model'});
78
+ const A = dbs.getService(MemoryAdapter);
79
+ A._lastIds.set('model', 10);
80
+ A._updateLastIdValueIfNeeded('model', 9);
81
+ A._updateLastIdValueIfNeeded('model', 10);
82
+ const res = A._lastIds.get('model');
83
+ expect(res).to.be.eq(10);
84
+ });
85
+
86
+ it('updates the last known identifier if the given identifier is greater', function () {
87
+ const dbs = new DatabaseSchema();
88
+ dbs.defineModel({name: 'model'});
89
+ const A = dbs.getService(MemoryAdapter);
90
+ A._lastIds.set('model', 10);
91
+ A._updateLastIdValueIfNeeded('model', 15);
92
+ const res = A._lastIds.get('model');
93
+ expect(res).to.be.eq(15);
94
+ });
95
+
96
+ it('correctly resolves table name from model name', function () {
97
+ const dbs = new DatabaseSchema();
98
+ dbs.defineModel({name: 'MyModel', tableName: 'custom_table_name'});
99
+ const A = dbs.getService(MemoryAdapter);
100
+ A._lastIds.set('custom_table_name', 10);
101
+ A._updateLastIdValueIfNeeded('MyModel', 20);
102
+ const res = A._lastIds.get('custom_table_name');
103
+ expect(res).to.be.eq(20);
104
+ expect(A._lastIds.has('MyModel')).to.be.false;
105
+ });
59
106
  });
60
107
 
61
108
  describe('create', function () {
@@ -1,7 +1,5 @@
1
1
  export * from './inclusion-decorator.js';
2
2
  export * from './default-values-decorator.js';
3
3
  export * from './data-sanitizing-decorator.js';
4
- export * from './data-validation-decorator.js';
5
4
  export * from './fields-filtering-decorator.js';
6
- export * from './data-transformation-decorator.js';
7
5
  export * from './property-uniqueness-decorator.js';
@@ -1,7 +1,5 @@
1
1
  export * from './inclusion-decorator.js';
2
2
  export * from './default-values-decorator.js';
3
3
  export * from './data-sanitizing-decorator.js';
4
- export * from './data-validation-decorator.js';
5
4
  export * from './fields-filtering-decorator.js';
6
- export * from './data-transformation-decorator.js';
7
5
  export * from './property-uniqueness-decorator.js';
@@ -1,8 +1,6 @@
1
1
  export * from './relations/index.js';
2
2
  export * from './properties/index.js';
3
3
  export * from './model-definition.js';
4
- export * from './model-data-validator.js';
5
4
  export * from './model-data-sanitizer.js';
6
- export * from './model-data-transformer.js';
7
5
  export * from './model-definition-utils.js';
8
6
  export * from './model-definition-validator.js';
@@ -1,8 +1,6 @@
1
1
  export * from './relations/index.js';
2
2
  export * from './properties/index.js';
3
3
  export * from './model-definition.js';
4
- export * from './model-data-validator.js';
5
4
  export * from './model-data-sanitizer.js';
6
- export * from './model-data-transformer.js';
7
5
  export * from './model-definition-utils.js';
8
6
  export * from './model-definition-validator.js';
@@ -1,8 +1,6 @@
1
1
  export * from './data-type.js';
2
2
  export * from './property-definition.js';
3
3
  export * from './property-uniqueness.js';
4
- export * from './property-validator/index.js';
5
- export * from './property-transformer/index.js';
6
4
  export * from './property-uniqueness-validator.js';
7
5
  export * from './properties-definition-validator.js';
8
6
  export * from './primary-keys-definition-validator.js';
@@ -1,8 +1,6 @@
1
1
  export * from './data-type.js';
2
2
  export * from './property-definition.js';
3
3
  export * from './property-uniqueness.js';
4
- export * from './property-validator/index.js';
5
- export * from './property-transformer/index.js';
6
4
  export * from './property-uniqueness-validator.js';
7
5
  export * from './properties-definition-validator.js';
8
6
  export * from './primary-keys-definition-validator.js';
@@ -3,8 +3,6 @@ import {DataType as Type} from './data-type.js';
3
3
  import {capitalize} from '../../../utils/index.js';
4
4
  import {PropertyUniqueness} from './property-uniqueness.js';
5
5
  import {InvalidArgumentError} from '../../../errors/index.js';
6
- import {PropertyValidatorRegistry} from './property-validator/index.js';
7
- import {PropertyTransformerRegistry} from './property-transformer/index.js';
8
6
  import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
9
7
 
10
8
  /**
@@ -228,173 +226,6 @@ export class PropertiesDefinitionValidator extends Service {
228
226
  propName,
229
227
  modelName,
230
228
  );
231
- // если определена опция "validate", то проверяется значение
232
- // опции, которое может являться строкой, массивом или объектом
233
- if (propDef.validate != null) {
234
- const propertyValidatorRegistry = this.getService(
235
- PropertyValidatorRegistry,
236
- );
237
- // если опция "validate" содержит строку, то проверяется
238
- // наличие зарегистрированного валидатора по названию
239
- if (propDef.validate && typeof propDef.validate === 'string') {
240
- // если название валидатора не зарегистрировано,
241
- // то выбрасывается ошибка
242
- if (!propertyValidatorRegistry.hasValidator(propDef.validate))
243
- throw new InvalidArgumentError(
244
- 'The property validator %v is not found.',
245
- propDef.validate,
246
- );
247
- }
248
- // если опция "validate" содержит функцию, то данная функция
249
- // воспринимается как пользовательский валидатор
250
- else if (propDef.validate && typeof propDef.validate === 'function') {
251
- // (допустимо)
252
- }
253
- // если опция "validate" содержит массив, то проверяется
254
- // каждый элемент массива
255
- else if (Array.isArray(propDef.validate)) {
256
- for (const validatorOrName of propDef.validate) {
257
- // если элемент массива является строкой, то проверяется
258
- // наличие зарегистрированного валидатора по названию
259
- if (validatorOrName && typeof validatorOrName === 'string') {
260
- if (!propertyValidatorRegistry.hasValidator(validatorOrName))
261
- throw new InvalidArgumentError(
262
- 'The property validator %v is not found.',
263
- validatorOrName,
264
- );
265
- }
266
- // если элемент массива является функцией, то данная функция
267
- // воспринимается как пользовательский валидатор
268
- else if (validatorOrName && typeof validatorOrName === 'function') {
269
- // (допустимо)
270
- }
271
- // если элемент массива не является названием зарегистрированного
272
- // валидатора или функцией-валидатором, то выбрасывается ошибка
273
- else {
274
- throw new InvalidArgumentError(
275
- 'The provided option "validate" for the property %v in the model %v ' +
276
- 'has an Array value that should contain validator names or validator ' +
277
- 'functions, but %v was given.',
278
- propName,
279
- modelName,
280
- validatorOrName,
281
- );
282
- }
283
- }
284
- }
285
- // если опция "validate" содержит объект, то проверяются ключи данного
286
- // объекта, которые должны являться названиями зарегистрированных
287
- // валидаторов, а значения их аргументами
288
- else if (typeof propDef.validate === 'object') {
289
- Object.keys(propDef.validate).forEach(validatorName => {
290
- // если ключ объекта не является названием зарегистрированного
291
- // валидатора, то выбрасывается ошибка
292
- if (!propertyValidatorRegistry.hasValidator(validatorName))
293
- throw new InvalidArgumentError(
294
- 'The property validator %v is not found.',
295
- validatorName,
296
- );
297
- });
298
- }
299
- // если опция "validate" не является не пустой строкой, функцией,
300
- // массивом и объектом, то выбрасывается ошибка
301
- else {
302
- throw new InvalidArgumentError(
303
- 'The provided option "validate" for the property %v in the model %v ' +
304
- 'should be either a validator name, a validator function, an array ' +
305
- 'of validator names or functions, or an object mapping validator ' +
306
- 'names to their arguments, but %v was given.',
307
- propName,
308
- modelName,
309
- propDef.validate,
310
- );
311
- }
312
- }
313
- // если определена опция "transform", то проверяется значение
314
- // опции, которое может являться строкой, массивом или объектом
315
- if (propDef.transform != null) {
316
- const propertyTransformerRegistry = this.getService(
317
- PropertyTransformerRegistry,
318
- );
319
- // если опция "transform" содержит строку, то проверяется
320
- // наличие зарегистрированного трансформера по названию
321
- if (propDef.transform && typeof propDef.transform === 'string') {
322
- // если название трансформера не зарегистрировано,
323
- // то выбрасывается ошибка
324
- if (!propertyTransformerRegistry.hasTransformer(propDef.transform))
325
- throw new InvalidArgumentError(
326
- 'The property transformer %v is not found.',
327
- propDef.transform,
328
- );
329
- }
330
- // если опция "transform" содержит функцию, то данная функция
331
- // воспринимается как пользовательский трансформер
332
- else if (propDef.transform && typeof propDef.transform === 'function') {
333
- // (допустимо)
334
- }
335
- // если опция "transform" содержит массив, то проверяется
336
- // каждый элемент массива
337
- else if (Array.isArray(propDef.transform)) {
338
- for (const transformerOrName of propDef.transform) {
339
- // если элемент массива является строкой, то проверяется
340
- // наличие зарегистрированного трансформера по названию
341
- if (transformerOrName && typeof transformerOrName === 'string') {
342
- if (!propertyTransformerRegistry.hasTransformer(transformerOrName))
343
- throw new InvalidArgumentError(
344
- 'The property transformer %v is not found.',
345
- transformerOrName,
346
- );
347
- }
348
- // если элемент массива является функцией, то данная функция
349
- // воспринимается как пользовательский трансформер
350
- else if (
351
- transformerOrName &&
352
- typeof transformerOrName === 'function'
353
- ) {
354
- // (допустимо)
355
- }
356
- // если элемент массива не является названием зарегистрированного
357
- // трансформера или функцией-трансформером, то выбрасывается ошибка
358
- else {
359
- throw new InvalidArgumentError(
360
- 'The provided option "transform" for the property %v in the model %v ' +
361
- 'has an Array value that should contain transformer names or transformer ' +
362
- 'functions, but %v was given.',
363
- propName,
364
- modelName,
365
- transformerOrName,
366
- );
367
- }
368
- }
369
- }
370
- // если опция "transform" содержит объект, то проверяются ключи данного
371
- // объекта, которые должны являться названиями зарегистрированных
372
- // трансформеров, а значения их аргументами
373
- else if (typeof propDef.transform === 'object') {
374
- Object.keys(propDef.transform).forEach(transformerName => {
375
- // если ключ объекта не является названием зарегистрированного
376
- // валидатора, то выбрасывается ошибка
377
- if (!propertyTransformerRegistry.hasTransformer(transformerName))
378
- throw new InvalidArgumentError(
379
- 'The property transformer %v is not found.',
380
- transformerName,
381
- );
382
- });
383
- }
384
- // если опция "transform" не является не пустой строкой, функцией,
385
- // массивом и объектом, то выбрасывается ошибка
386
- else {
387
- throw new InvalidArgumentError(
388
- 'The provided option "transform" for the property %v in the model %v ' +
389
- 'should be either a transformer name, a transformer function, an array ' +
390
- 'of transformer names or functions, or an object mapping transformer ' +
391
- 'names to their arguments, but %v was given.',
392
- propName,
393
- modelName,
394
- propDef.transform,
395
- );
396
- }
397
- }
398
229
  if (propDef.unique) {
399
230
  if (
400
231
  typeof propDef.unique !== 'boolean' &&