@e22m4u/js-repository 0.0.31

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 (183) hide show
  1. package/.c8rc +9 -0
  2. package/.commitlintrc +5 -0
  3. package/.editorconfig +13 -0
  4. package/.eslintignore +1 -0
  5. package/.eslintrc.cjs +27 -0
  6. package/.husky/commit-msg +4 -0
  7. package/.husky/pre-commit +9 -0
  8. package/.mocharc.cjs +7 -0
  9. package/.prettierrc +7 -0
  10. package/LICENSE +21 -0
  11. package/README.md +523 -0
  12. package/mocha.setup.js +10 -0
  13. package/package.json +57 -0
  14. package/src/adapter/adapter-loader.d.ts +16 -0
  15. package/src/adapter/adapter-loader.js +63 -0
  16. package/src/adapter/adapter-loader.spec.js +31 -0
  17. package/src/adapter/adapter-registry.d.ts +14 -0
  18. package/src/adapter/adapter-registry.js +36 -0
  19. package/src/adapter/adapter-registry.spec.js +36 -0
  20. package/src/adapter/adapter.d.ts +118 -0
  21. package/src/adapter/adapter.js +181 -0
  22. package/src/adapter/adapter.spec.js +144 -0
  23. package/src/adapter/builtin/memory-adapter.d.ts +118 -0
  24. package/src/adapter/builtin/memory-adapter.js +342 -0
  25. package/src/adapter/builtin/memory-adapter.spec.js +2925 -0
  26. package/src/adapter/decorator/data-sanitizing-decorator.d.ts +13 -0
  27. package/src/adapter/decorator/data-sanitizing-decorator.js +44 -0
  28. package/src/adapter/decorator/data-sanitizing-decorator.spec.js +59 -0
  29. package/src/adapter/decorator/data-validation-decorator.d.ts +13 -0
  30. package/src/adapter/decorator/data-validation-decorator.js +41 -0
  31. package/src/adapter/decorator/data-validation-decorator.spec.js +59 -0
  32. package/src/adapter/decorator/default-values-decorator.d.ts +13 -0
  33. package/src/adapter/decorator/default-values-decorator.js +57 -0
  34. package/src/adapter/decorator/default-values-decorator.spec.js +141 -0
  35. package/src/adapter/decorator/fields-filtering-decorator.d.ts +13 -0
  36. package/src/adapter/decorator/fields-filtering-decorator.js +72 -0
  37. package/src/adapter/decorator/fields-filtering-decorator.spec.js +119 -0
  38. package/src/adapter/decorator/inclusion-decorator.d.ts +13 -0
  39. package/src/adapter/decorator/inclusion-decorator.js +78 -0
  40. package/src/adapter/decorator/inclusion-decorator.spec.js +117 -0
  41. package/src/adapter/decorator/index.d.ts +5 -0
  42. package/src/adapter/decorator/index.js +5 -0
  43. package/src/adapter/index.d.ts +3 -0
  44. package/src/adapter/index.js +3 -0
  45. package/src/definition/datasource/datasource-definition-validator.d.ts +14 -0
  46. package/src/definition/datasource/datasource-definition-validator.js +33 -0
  47. package/src/definition/datasource/datasource-definition-validator.spec.js +63 -0
  48. package/src/definition/datasource/datasource-definition.d.ts +7 -0
  49. package/src/definition/datasource/index.d.ts +2 -0
  50. package/src/definition/datasource/index.js +1 -0
  51. package/src/definition/definition-registry.d.ts +50 -0
  52. package/src/definition/definition-registry.js +98 -0
  53. package/src/definition/definition-registry.spec.js +78 -0
  54. package/src/definition/index.d.ts +3 -0
  55. package/src/definition/index.js +3 -0
  56. package/src/definition/model/index.d.ts +7 -0
  57. package/src/definition/model/index.js +6 -0
  58. package/src/definition/model/model-data-sanitizer.d.ts +15 -0
  59. package/src/definition/model/model-data-sanitizer.js +33 -0
  60. package/src/definition/model/model-data-validator.d.ts +32 -0
  61. package/src/definition/model/model-data-validator.js +144 -0
  62. package/src/definition/model/model-data-validator.spec.js +1889 -0
  63. package/src/definition/model/model-definition-utils.d.ts +161 -0
  64. package/src/definition/model/model-definition-utils.js +371 -0
  65. package/src/definition/model/model-definition-utils.spec.js +1474 -0
  66. package/src/definition/model/model-definition-validator.d.ts +14 -0
  67. package/src/definition/model/model-definition-validator.js +83 -0
  68. package/src/definition/model/model-definition-validator.spec.js +143 -0
  69. package/src/definition/model/model-definition.d.ts +28 -0
  70. package/src/definition/model/properties/data-type.d.ts +11 -0
  71. package/src/definition/model/properties/data-type.js +11 -0
  72. package/src/definition/model/properties/default-values-definition-validator.d.ts +15 -0
  73. package/src/definition/model/properties/default-values-definition-validator.js +53 -0
  74. package/src/definition/model/properties/default-values-definition-validator.spec.js +136 -0
  75. package/src/definition/model/properties/index.d.ts +5 -0
  76. package/src/definition/model/properties/index.js +4 -0
  77. package/src/definition/model/properties/primary-keys-definition-validator.d.ts +15 -0
  78. package/src/definition/model/properties/primary-keys-definition-validator.js +55 -0
  79. package/src/definition/model/properties/primary-keys-definition-validator.spec.js +145 -0
  80. package/src/definition/model/properties/properties-definition-validator.d.ts +15 -0
  81. package/src/definition/model/properties/properties-definition-validator.js +194 -0
  82. package/src/definition/model/properties/properties-definition-validator.spec.js +373 -0
  83. package/src/definition/model/properties/property-definition.d.ts +20 -0
  84. package/src/definition/model/relations/index.d.ts +3 -0
  85. package/src/definition/model/relations/index.js +2 -0
  86. package/src/definition/model/relations/relation-definition.d.ts +254 -0
  87. package/src/definition/model/relations/relation-type.d.ts +9 -0
  88. package/src/definition/model/relations/relation-type.js +9 -0
  89. package/src/definition/model/relations/relations-definition-validator.d.ts +15 -0
  90. package/src/definition/model/relations/relations-definition-validator.js +449 -0
  91. package/src/definition/model/relations/relations-definition-validator.spec.js +772 -0
  92. package/src/errors/index.d.ts +3 -0
  93. package/src/errors/index.js +3 -0
  94. package/src/errors/invalid-argument-error.d.ts +6 -0
  95. package/src/errors/invalid-argument-error.js +6 -0
  96. package/src/errors/invalid-argument-error.spec.js +33 -0
  97. package/src/errors/invalid-operator-value-error.d.ts +13 -0
  98. package/src/errors/invalid-operator-value-error.js +24 -0
  99. package/src/errors/invalid-operator-value-error.spec.js +11 -0
  100. package/src/errors/not-implemented-error.d.ts +6 -0
  101. package/src/errors/not-implemented-error.js +6 -0
  102. package/src/errors/not-implemented-error.spec.js +33 -0
  103. package/src/filter/fields-clause-tool.d.ts +38 -0
  104. package/src/filter/fields-clause-tool.js +88 -0
  105. package/src/filter/fields-clause-tool.spec.js +133 -0
  106. package/src/filter/filter.d.ts +335 -0
  107. package/src/filter/include-clause-tool.d.ts +53 -0
  108. package/src/filter/include-clause-tool.js +364 -0
  109. package/src/filter/include-clause-tool.spec.js +653 -0
  110. package/src/filter/index.d.ts +7 -0
  111. package/src/filter/index.js +6 -0
  112. package/src/filter/operator-clause-tool.d.ts +223 -0
  113. package/src/filter/operator-clause-tool.js +515 -0
  114. package/src/filter/operator-clause-tool.spec.js +1064 -0
  115. package/src/filter/order-clause-tool.d.ts +32 -0
  116. package/src/filter/order-clause-tool.js +97 -0
  117. package/src/filter/order-clause-tool.spec.js +438 -0
  118. package/src/filter/slice-clause-tool.d.ts +30 -0
  119. package/src/filter/slice-clause-tool.js +65 -0
  120. package/src/filter/slice-clause-tool.spec.js +117 -0
  121. package/src/filter/where-clause-tool.d.ts +23 -0
  122. package/src/filter/where-clause-tool.js +165 -0
  123. package/src/filter/where-clause-tool.spec.js +280 -0
  124. package/src/index.d.ts +9 -0
  125. package/src/index.js +8 -0
  126. package/src/relations/belongs-to-resolver.d.ts +46 -0
  127. package/src/relations/belongs-to-resolver.js +242 -0
  128. package/src/relations/belongs-to-resolver.spec.js +1047 -0
  129. package/src/relations/has-many-resolver.d.ts +67 -0
  130. package/src/relations/has-many-resolver.js +317 -0
  131. package/src/relations/has-many-resolver.spec.js +2911 -0
  132. package/src/relations/has-one-resolver.d.ts +67 -0
  133. package/src/relations/has-one-resolver.js +311 -0
  134. package/src/relations/has-one-resolver.spec.js +2274 -0
  135. package/src/relations/index.d.ts +4 -0
  136. package/src/relations/index.js +4 -0
  137. package/src/relations/references-many-resolver.d.ts +27 -0
  138. package/src/relations/references-many-resolver.js +113 -0
  139. package/src/relations/references-many-resolver.spec.js +631 -0
  140. package/src/repository/index.d.ts +2 -0
  141. package/src/repository/index.js +2 -0
  142. package/src/repository/repository-registry.d.ts +29 -0
  143. package/src/repository/repository-registry.js +57 -0
  144. package/src/repository/repository-registry.spec.js +38 -0
  145. package/src/repository/repository.d.ts +164 -0
  146. package/src/repository/repository.js +207 -0
  147. package/src/repository/repository.spec.js +202 -0
  148. package/src/schema.d.ts +37 -0
  149. package/src/schema.js +41 -0
  150. package/src/types.d.ts +30 -0
  151. package/src/utils/capitalize.d.ts +6 -0
  152. package/src/utils/capitalize.js +10 -0
  153. package/src/utils/capitalize.spec.js +14 -0
  154. package/src/utils/clone-deep.d.ts +6 -0
  155. package/src/utils/clone-deep.js +61 -0
  156. package/src/utils/clone-deep.spec.js +28 -0
  157. package/src/utils/exclude-object-keys.d.ts +10 -0
  158. package/src/utils/exclude-object-keys.js +20 -0
  159. package/src/utils/exclude-object-keys.spec.js +49 -0
  160. package/src/utils/get-ctor-name.d.ts +6 -0
  161. package/src/utils/get-ctor-name.js +11 -0
  162. package/src/utils/get-ctor-name.spec.js +17 -0
  163. package/src/utils/get-value-by-path.d.ts +12 -0
  164. package/src/utils/get-value-by-path.js +23 -0
  165. package/src/utils/get-value-by-path.spec.js +36 -0
  166. package/src/utils/index.d.ts +10 -0
  167. package/src/utils/index.js +10 -0
  168. package/src/utils/is-ctor.d.ts +7 -0
  169. package/src/utils/is-ctor.js +10 -0
  170. package/src/utils/is-ctor.spec.js +26 -0
  171. package/src/utils/is-pure-object.d.ts +6 -0
  172. package/src/utils/is-pure-object.js +15 -0
  173. package/src/utils/is-pure-object.spec.js +25 -0
  174. package/src/utils/select-object-keys.d.ts +10 -0
  175. package/src/utils/select-object-keys.js +37 -0
  176. package/src/utils/select-object-keys.spec.js +40 -0
  177. package/src/utils/singularize.d.ts +6 -0
  178. package/src/utils/singularize.js +22 -0
  179. package/src/utils/singularize.spec.js +23 -0
  180. package/src/utils/string-to-regexp.d.ts +10 -0
  181. package/src/utils/string-to-regexp.js +22 -0
  182. package/src/utils/string-to-regexp.spec.js +35 -0
  183. package/tsconfig.json +9 -0
@@ -0,0 +1,373 @@
1
+ import chai from 'chai';
2
+ import {expect} from 'chai';
3
+ import {DataType} from './data-type.js';
4
+ import {format} from '@e22m4u/js-format';
5
+ import {PropertiesDefinitionValidator} from './properties-definition-validator.js';
6
+ import {PrimaryKeysDefinitionValidator} from './primary-keys-definition-validator.js';
7
+ import {DefaultValuesDefinitionValidator} from './default-values-definition-validator.js';
8
+
9
+ const S = new PropertiesDefinitionValidator();
10
+ const sandbox = chai.spy.sandbox();
11
+
12
+ describe('PropertiesDefinitionValidator', function () {
13
+ afterEach(function () {
14
+ sandbox.restore();
15
+ });
16
+
17
+ describe('validate', function () {
18
+ it('requires a first argument to be a non-empty string', function () {
19
+ const validate = v => () => S.validate(v, {});
20
+ const error = v =>
21
+ format(
22
+ 'A first argument of PropertiesDefinitionValidator.validate ' +
23
+ 'should be a non-empty String, but %s given.',
24
+ v,
25
+ );
26
+ expect(validate('')).to.throw(error('""'));
27
+ expect(validate(10)).to.throw(error('10'));
28
+ expect(validate(true)).to.throw(error('true'));
29
+ expect(validate(false)).to.throw(error('false'));
30
+ expect(validate([])).to.throw(error('Array'));
31
+ expect(validate({})).to.throw(error('Object'));
32
+ expect(validate(undefined)).to.throw(error('undefined'));
33
+ expect(validate(null)).to.throw(error('null'));
34
+ validate('model')();
35
+ });
36
+
37
+ it('requires a second argument to be an object', function () {
38
+ const validate = v => () => S.validate('model', v);
39
+ const error = v =>
40
+ format(
41
+ 'The provided option "properties" of the model "model" ' +
42
+ 'should be an Object, but %s given.',
43
+ v,
44
+ );
45
+ expect(validate('str')).to.throw(error('"str"'));
46
+ expect(validate(10)).to.throw(error('10'));
47
+ expect(validate(true)).to.throw(error('true'));
48
+ expect(validate(false)).to.throw(error('false'));
49
+ expect(validate([])).to.throw(error('Array'));
50
+ expect(validate(undefined)).to.throw(error('undefined'));
51
+ expect(validate(null)).to.throw(error('null'));
52
+ validate({})();
53
+ });
54
+
55
+ it('requires a property name as a non-empty string', function () {
56
+ const validate = v => () => S.validate('model', v);
57
+ const error = v =>
58
+ format(
59
+ 'The property name of the model "model" should be ' +
60
+ 'a non-empty String, but %s given.',
61
+ v,
62
+ );
63
+ expect(validate({['']: {}})).to.throw(error('""'));
64
+ validate({foo: DataType.STRING})();
65
+ });
66
+
67
+ it('requires a property definition', function () {
68
+ const validate = v => () => S.validate('model', {foo: v});
69
+ const error = v =>
70
+ format(
71
+ 'The property "foo" of the model "model" should have ' +
72
+ 'a property definition, but %s given.',
73
+ v,
74
+ );
75
+ expect(validate(undefined)).to.throw(error('undefined'));
76
+ expect(validate(null)).to.throw(error('null'));
77
+ validate(DataType.STRING)();
78
+ validate({type: DataType.STRING})();
79
+ });
80
+
81
+ it('expects a short property definition to be DataType', function () {
82
+ const validate = v => () => S.validate('model', {foo: v});
83
+ const error = v =>
84
+ format(
85
+ 'In case of a short property definition, the property "foo" ' +
86
+ 'of the model "model" should have one of data types: %l, but %s given.',
87
+ Object.values(DataType),
88
+ v,
89
+ );
90
+ expect(validate('invalid')).to.throw(error('"invalid"'));
91
+ validate(DataType.STRING)();
92
+ });
93
+
94
+ it('expects a full property definition to be an object', function () {
95
+ const validate = v => () => S.validate('model', {foo: v});
96
+ const error = v =>
97
+ format(
98
+ 'In case of a full property definition, the property "foo" ' +
99
+ 'of the model "model" should be an Object, but %s given.',
100
+ v,
101
+ );
102
+ expect(validate(10)).to.throw(error('10'));
103
+ expect(validate(true)).to.throw(error('true'));
104
+ expect(validate([])).to.throw(error('Array'));
105
+ validate({type: DataType.STRING})();
106
+ });
107
+
108
+ it('requires the option "type" to be a DataType', function () {
109
+ const validate = v => () => S.validate('model', {foo: {type: v}});
110
+ const error = v =>
111
+ format(
112
+ 'The property "foo" of the model "model" requires the option "type" ' +
113
+ 'to have one of data types: %l, but %s given.',
114
+ Object.values(DataType),
115
+ v,
116
+ );
117
+ expect(validate('str')).to.throw(error('"str"'));
118
+ expect(validate(10)).to.throw(error('10'));
119
+ expect(validate(true)).to.throw(error('true'));
120
+ expect(validate(false)).to.throw(error('false'));
121
+ expect(validate([])).to.throw(error('Array'));
122
+ expect(validate({})).to.throw(error('Object'));
123
+ expect(validate(undefined)).to.throw(error('undefined'));
124
+ expect(validate(null)).to.throw(error('null'));
125
+ validate(DataType.STRING)();
126
+ });
127
+
128
+ it('expects provided the option "itemType" to be a DataType', function () {
129
+ const validate = v => {
130
+ const foo = {type: DataType.ARRAY, itemType: v};
131
+ return () => S.validate('model', {foo});
132
+ };
133
+ const error = v =>
134
+ format(
135
+ 'The provided option "itemType" of the property "foo" in the model "model" ' +
136
+ 'should have one of data types: %l, but %s given.',
137
+ Object.values(DataType),
138
+ v,
139
+ );
140
+ expect(validate('str')).to.throw(error('"str"'));
141
+ expect(validate(10)).to.throw(error('10'));
142
+ expect(validate(true)).to.throw(error('true'));
143
+ expect(validate([])).to.throw(error('Array'));
144
+ expect(validate({})).to.throw(error('Object'));
145
+ validate(DataType.STRING)();
146
+ });
147
+
148
+ it('expects provided the option "model" to be a string', function () {
149
+ const validate = v => {
150
+ const foo = {
151
+ type: DataType.OBJECT,
152
+ model: v,
153
+ };
154
+ return () => S.validate('model', {foo});
155
+ };
156
+ const error = v =>
157
+ format(
158
+ 'The provided option "model" of the property "foo" in the model "model" ' +
159
+ 'should be a String, but %s given.',
160
+ v,
161
+ );
162
+ expect(validate(10)).to.throw(error('10'));
163
+ expect(validate(true)).to.throw(error('true'));
164
+ expect(validate([])).to.throw(error('Array'));
165
+ expect(validate({})).to.throw(error('Object'));
166
+ validate('model')();
167
+ });
168
+
169
+ it('expects provided the option "primaryKey" to be a boolean', function () {
170
+ const validate = v => {
171
+ const foo = {
172
+ type: DataType.STRING,
173
+ primaryKey: v,
174
+ };
175
+ return () => S.validate('model', {foo});
176
+ };
177
+ const error = v =>
178
+ format(
179
+ 'The provided option "primaryKey" of the property "foo" in the model "model" ' +
180
+ 'should be a Boolean, but %s given.',
181
+ v,
182
+ );
183
+ expect(validate(10)).to.throw(error('10'));
184
+ expect(validate([])).to.throw(error('Array'));
185
+ expect(validate({})).to.throw(error('Object'));
186
+ validate(true)();
187
+ validate(false)();
188
+ });
189
+
190
+ it('expects provided the option "columnName" to be a string', function () {
191
+ const validate = v => {
192
+ const foo = {
193
+ type: DataType.STRING,
194
+ columnName: v,
195
+ };
196
+ return () => S.validate('model', {foo});
197
+ };
198
+ const error = v =>
199
+ format(
200
+ 'The provided option "columnName" of the property "foo" in the model "model" ' +
201
+ 'should be a String, but %s given.',
202
+ v,
203
+ );
204
+ expect(validate(10)).to.throw(error('10'));
205
+ expect(validate(true)).to.throw(error('true'));
206
+ expect(validate([])).to.throw(error('Array'));
207
+ expect(validate({})).to.throw(error('Object'));
208
+ validate('columnName')();
209
+ });
210
+
211
+ it('expects provided the option "columnType" to be a string', function () {
212
+ const validate = v => {
213
+ const foo = {
214
+ type: DataType.STRING,
215
+ columnType: v,
216
+ };
217
+ return () => S.validate('model', {foo});
218
+ };
219
+ const error = v =>
220
+ format(
221
+ 'The provided option "columnType" of the property "foo" in the model "model" ' +
222
+ 'should be a String, but %s given.',
223
+ v,
224
+ );
225
+ expect(validate(10)).to.throw(error('10'));
226
+ expect(validate(true)).to.throw(error('true'));
227
+ expect(validate([])).to.throw(error('Array'));
228
+ expect(validate({})).to.throw(error('Object'));
229
+ validate('columnType')();
230
+ });
231
+
232
+ it('expects provided the option "required" to be a boolean', function () {
233
+ const validate = v => {
234
+ const foo = {
235
+ type: DataType.STRING,
236
+ required: v,
237
+ };
238
+ return () => S.validate('model', {foo});
239
+ };
240
+ const error = v =>
241
+ format(
242
+ 'The provided option "required" of the property "foo" in the model "model" ' +
243
+ 'should be a Boolean, but %s given.',
244
+ v,
245
+ );
246
+ expect(validate(10)).to.throw(error('10'));
247
+ expect(validate([])).to.throw(error('Array'));
248
+ expect(validate({})).to.throw(error('Object'));
249
+ validate(true)();
250
+ validate(false)();
251
+ });
252
+
253
+ it('expects the required property should not have the option "default" to be provided', function () {
254
+ const validate = v => () => {
255
+ const foo = {
256
+ type: DataType.ANY,
257
+ required: true,
258
+ default: v,
259
+ };
260
+ S.validate('model', {foo});
261
+ };
262
+ const error = format(
263
+ 'The property "foo" of the model "model" is a required property, ' +
264
+ 'so it should not have the option "default" to be provided.',
265
+ );
266
+ expect(validate('str')).to.throw(error);
267
+ expect(validate(10)).to.throw(error);
268
+ expect(validate(true)).to.throw(error);
269
+ expect(validate(false)).to.throw(error);
270
+ expect(validate([])).to.throw(error);
271
+ expect(validate({})).to.throw(error);
272
+ expect(validate(null)).to.throw(error);
273
+ validate(undefined);
274
+ });
275
+
276
+ it('expects the primary key should not have the option "required" to be true', function () {
277
+ const validate = v => () => {
278
+ const foo = {
279
+ type: DataType.ANY,
280
+ primaryKey: true,
281
+ required: v,
282
+ };
283
+ S.validate('model', {foo});
284
+ };
285
+ const error = format(
286
+ 'The property "foo" of the model "model" is a primary key, ' +
287
+ 'so it should not have the option "required" to be provided.',
288
+ );
289
+ expect(validate(true)).to.throw(error);
290
+ validate(false);
291
+ validate(undefined);
292
+ });
293
+
294
+ it('expects the primary key should not have the option "default" to be provided', function () {
295
+ const validate = v => () => {
296
+ const foo = {
297
+ type: DataType.ANY,
298
+ primaryKey: true,
299
+ default: v,
300
+ };
301
+ S.validate('model', {foo});
302
+ };
303
+ const error = format(
304
+ 'The property "foo" of the model "model" is a primary key, ' +
305
+ 'so it should not have the option "default" to be provided.',
306
+ );
307
+ expect(validate('str')).to.throw(error);
308
+ expect(validate(10)).to.throw(error);
309
+ expect(validate(true)).to.throw(error);
310
+ expect(validate(false)).to.throw(error);
311
+ expect(validate([])).to.throw(error);
312
+ expect(validate({})).to.throw(error);
313
+ expect(validate(null)).to.throw(error);
314
+ validate(undefined);
315
+ });
316
+
317
+ it('expects a non-array property should not have the option "itemType" to be provided', function () {
318
+ const validate = v => () => {
319
+ const foo = {
320
+ type: v,
321
+ itemType: DataType.STRING,
322
+ };
323
+ S.validate('model', {foo});
324
+ };
325
+ const error =
326
+ 'The property "foo" of the model "model" has the non-array type, ' +
327
+ 'so it should not have the option "itemType" to be provided.';
328
+ expect(validate(DataType.ANY)).to.throw(error);
329
+ expect(validate(DataType.STRING)).to.throw(error);
330
+ expect(validate(DataType.NUMBER)).to.throw(error);
331
+ expect(validate(DataType.BOOLEAN)).to.throw(error);
332
+ expect(validate(DataType.OBJECT)).to.throw(error);
333
+ validate(DataType.ARRAY);
334
+ });
335
+
336
+ it('expects a non-object property should not have the option "model" to be provided', function () {
337
+ const validate = v => () => {
338
+ const foo = {
339
+ type: v,
340
+ model: 'model',
341
+ };
342
+ S.validate('model', {foo});
343
+ };
344
+ const error =
345
+ 'The property "foo" of the model "model" has the non-object type, ' +
346
+ 'so it should not have the option "model" to be provided.';
347
+ expect(validate(DataType.ANY)).to.throw(error);
348
+ expect(validate(DataType.STRING)).to.throw(error);
349
+ expect(validate(DataType.NUMBER)).to.throw(error);
350
+ expect(validate(DataType.BOOLEAN)).to.throw(error);
351
+ expect(validate(DataType.ARRAY)).to.throw(error);
352
+ validate(DataType.OBJECT);
353
+ });
354
+
355
+ it('uses PrimaryKeysDefinitionValidator to validate primary keys', function () {
356
+ const V = S.getService(PrimaryKeysDefinitionValidator);
357
+ sandbox.on(V, 'validate');
358
+ const propDefs = {};
359
+ S.validate('model', propDefs);
360
+ expect(V.validate).to.have.been.called.once;
361
+ expect(V.validate).to.have.been.called.with.exactly('model', propDefs);
362
+ });
363
+
364
+ it('uses DefaultValuesDefinitionValidator to validate default values', function () {
365
+ const V = S.getService(DefaultValuesDefinitionValidator);
366
+ sandbox.on(V, 'validate');
367
+ const propDefs = {};
368
+ S.validate('model', propDefs);
369
+ expect(V.validate).to.have.been.called.once;
370
+ expect(V.validate).to.have.been.called.with.exactly('model', propDefs);
371
+ });
372
+ });
373
+ });
@@ -0,0 +1,20 @@
1
+ import {DataType} from './data-type.js';
2
+
3
+ /**
4
+ * Full property definition.
5
+ */
6
+ export declare type FullPropertyDefinition = {
7
+ type: DataType;
8
+ itemType?: DataType;
9
+ model?: string;
10
+ primaryKey?: boolean;
11
+ columnName?: string;
12
+ columnType?: string;
13
+ required?: boolean;
14
+ default?: unknown;
15
+ };
16
+
17
+ /**
18
+ * Property definition.
19
+ */
20
+ declare type PropertyDefinition = DataType | FullPropertyDefinition;
@@ -0,0 +1,3 @@
1
+ export * from './relation-type.js';
2
+ export * from './relation-definition.js';
3
+ export * from './relations-definition-validator.js';
@@ -0,0 +1,2 @@
1
+ export * from './relation-type.js';
2
+ export * from './relations-definition-validator.js';
@@ -0,0 +1,254 @@
1
+ import {RelationType} from './relation-type.js';
2
+
3
+ /**
4
+ * Relation definition.
5
+ *
6
+ * @example Available options.
7
+ * ```ts
8
+ * {
9
+ * type: RelationType;
10
+ * model?: string;
11
+ * foreignKey?: string;
12
+ * polymorphic?: boolean | string;
13
+ * discriminator?: string;
14
+ * }
15
+ * ```
16
+ */
17
+ export declare type RelationDefinition =
18
+ // belongsTo
19
+ | BelongsToDefinition
20
+ | PolyBelongsToDefinition
21
+ // hasOne
22
+ | HasOneDefinition
23
+ | PolyHasOneDefinitionWithTargetRelationName
24
+ | PolyHasOneDefinitionWithTargetKeys
25
+ // hasMany
26
+ | HasManyDefinition
27
+ | PolyHasManyDefinitionWithTargetRelationName
28
+ | PolyHasManyDefinitionWithTargetKeys
29
+ // referencesMany
30
+ | ReferencesManyDefinition;
31
+
32
+ /**
33
+ * The regular "belongsTo" relation.
34
+ *
35
+ * @example Required options only.
36
+ * ```
37
+ * {
38
+ * type: RelationType.BELONGS_TO,
39
+ * model: 'model',
40
+ * }
41
+ * ```
42
+ *
43
+ * @example Verbose definition.
44
+ * ```
45
+ * {
46
+ * type: RelationType.BELONGS_TO,
47
+ * model: 'model',
48
+ * foreignKey: 'modelId',
49
+ * }
50
+ * ```
51
+ */
52
+ export declare type BelongsToDefinition = {
53
+ type: RelationType.BELONGS_TO;
54
+ polymorphic?: false;
55
+ model: string;
56
+ foreignKey?: string;
57
+ };
58
+
59
+ /**
60
+ * The polymorphic "belongsTo" relation.
61
+ *
62
+ * @example Required fields only.
63
+ * ```
64
+ * {
65
+ * type: RelationType.BELONGS_TO,
66
+ * polymorphic: true,
67
+ * }
68
+ * ```
69
+ *
70
+ * @example Verbose definition.
71
+ * ```
72
+ * {
73
+ * type: RelationType.BELONGS_TO,
74
+ * polymorphic: true,
75
+ * foreignKey: 'referenceId',
76
+ * discriminator: 'referenceType,
77
+ * }
78
+ * ```
79
+ */
80
+ export declare type PolyBelongsToDefinition = {
81
+ type: RelationType.BELONGS_TO;
82
+ polymorphic: true;
83
+ foreignKey?: string;
84
+ discriminator?: string;
85
+ };
86
+
87
+ /**
88
+ * The regular "hasOne" relation.
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * {
93
+ * type: RelationType.HAS_ONE,
94
+ * model: 'model',
95
+ * foreignKey: 'modelId',
96
+ * }
97
+ * ```
98
+ */
99
+ export declare type HasOneDefinition = {
100
+ type: RelationType.HAS_ONE;
101
+ model: string;
102
+ polymorphic?: false;
103
+ foreignKey?: string;
104
+ discriminator?: undefined;
105
+ };
106
+
107
+ /**
108
+ * The polymorphic "hasOne" relation with a target relation name.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * {
113
+ * type: RelationType.HAS_ONE,
114
+ * model: 'model',
115
+ * polymorphic: 'reference',
116
+ * }
117
+ * ```
118
+ */
119
+ export declare type PolyHasOneDefinitionWithTargetRelationName = {
120
+ type: RelationType.HAS_ONE;
121
+ model: string;
122
+ polymorphic: string;
123
+ foreignKey?: undefined;
124
+ discriminator?: undefined;
125
+ };
126
+
127
+ /**
128
+ * The polymorphic "hasOne" relation with target relation keys.
129
+ *
130
+ * @example Required options only.
131
+ * ```
132
+ * {
133
+ * type: RelationType.HAS_ONE,
134
+ * model: 'model',
135
+ * polymorphic: true,
136
+ * }
137
+ * ```
138
+ *
139
+ * @example Verbose definition.
140
+ * ```
141
+ * {
142
+ * type: RelationType.HAS_ONE,
143
+ * model: 'model',
144
+ * polymorphic: true,
145
+ * foreignKey: 'referenceId',
146
+ * discriminator: 'referenceType,
147
+ * }
148
+ * ```
149
+ */
150
+ export declare type PolyHasOneDefinitionWithTargetKeys = {
151
+ type: RelationType.HAS_ONE;
152
+ model: string;
153
+ polymorphic: true;
154
+ foreignKey?: string;
155
+ discriminator?: string;
156
+ };
157
+
158
+ /**
159
+ * The regular "hasMany" relation.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * {
164
+ * type: RelationType.HAS_MANY,
165
+ * model: 'model',
166
+ * foreignKey: 'modelId',
167
+ * }
168
+ * ```
169
+ */
170
+ export declare type HasManyDefinition = {
171
+ type: RelationType.HAS_MANY;
172
+ model: string;
173
+ polymorphic?: false;
174
+ foreignKey?: string;
175
+ discriminator?: undefined;
176
+ };
177
+
178
+ /**
179
+ * The polymorphic "hasMany" relation with a target relation name.
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * {
184
+ * type: RelationType.HAS_MANY,
185
+ * model: 'model',
186
+ * polymorphic: 'reference',
187
+ * }
188
+ * ```
189
+ */
190
+ export declare type PolyHasManyDefinitionWithTargetRelationName = {
191
+ type: RelationType.HAS_MANY;
192
+ model: string;
193
+ polymorphic: string;
194
+ foreignKey?: undefined;
195
+ discriminator?: undefined;
196
+ };
197
+
198
+ /**
199
+ * The polymorphic "hasMany" relation with target relation keys.
200
+ *
201
+ * @example Required options only.
202
+ * ```
203
+ * {
204
+ * type: RelationType.HAS_MANY,
205
+ * model: 'model',
206
+ * polymorphic: true,
207
+ * }
208
+ * ```
209
+ *
210
+ * @example Verbose definition.
211
+ * ```
212
+ * {
213
+ * type: RelationType.HAS_MANY,
214
+ * model: 'model',
215
+ * polymorphic: true,
216
+ * foreignKey: 'referenceId',
217
+ * discriminator: 'referenceType,
218
+ * }
219
+ * ```
220
+ */
221
+ export declare type PolyHasManyDefinitionWithTargetKeys = {
222
+ type: RelationType.HAS_MANY;
223
+ model: string;
224
+ polymorphic: true;
225
+ foreignKey?: string;
226
+ discriminator?: string;
227
+ };
228
+
229
+ /**
230
+ * The regular "referencesMany" relation.
231
+ *
232
+ * @example Required options only.
233
+ * ```
234
+ * {
235
+ * type: RelationType.REFERENCES_MANY,
236
+ * model: 'model',
237
+ * }
238
+ * ```
239
+ *
240
+ * @example Verbose definition.
241
+ * ```
242
+ * {
243
+ * type: RelationType.REFERENCES_MANY,
244
+ * model: 'model',
245
+ * foreignKey: 'modelIds',
246
+ * }
247
+ * ```
248
+ */
249
+ export declare type ReferencesManyDefinition = {
250
+ type: RelationType.REFERENCES_MANY;
251
+ model: string;
252
+ foreignKey?: string;
253
+ discriminator?: undefined;
254
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Relation type.
3
+ */
4
+ export declare enum RelationType {
5
+ BELONGS_TO = 'belongsTo',
6
+ HAS_ONE = 'hasOne',
7
+ HAS_MANY = 'hasMany',
8
+ REFERENCES_MANY = 'referencesMany',
9
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Relation type.
3
+ */
4
+ export const RelationType = {
5
+ BELONGS_TO: 'belongsTo',
6
+ HAS_ONE: 'hasOne',
7
+ HAS_MANY: 'hasMany',
8
+ REFERENCES_MANY: 'referencesMany',
9
+ };
@@ -0,0 +1,15 @@
1
+ import {Service} from '@e22m4u/js-service';
2
+ import {RelationDefinitionMap} from '../model-definition.js';
3
+
4
+ /**
5
+ * Relations definition validator.
6
+ */
7
+ export declare class RelationsDefinitionValidator extends Service {
8
+ /**
9
+ * Validate.
10
+ *
11
+ * @param modelName
12
+ * @param relDefs
13
+ */
14
+ validate(modelName: string, relDefs: RelationDefinitionMap): void;
15
+ }