@e22m4u/js-repository 0.8.4 → 0.8.6
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.
- package/README.md +37 -49
- package/dist/cjs/index.cjs +762 -353
- package/eslint.config.js +1 -0
- package/package.json +14 -14
- package/src/adapter/adapter-loader.js +9 -4
- package/src/adapter/adapter-registry.js +3 -1
- package/src/adapter/builtin/memory-adapter.js +29 -13
- package/src/adapter/decorator/data-sanitizing-decorator.js +2 -1
- package/src/adapter/decorator/default-values-decorator.js +2 -1
- package/src/adapter/decorator/fields-filtering-decorator.js +14 -7
- package/src/adapter/decorator/inclusion-decorator.js +14 -7
- package/src/adapter/decorator/property-uniqueness-decorator.js +2 -1
- package/src/adapter/decorator/required-property-decorator.js +2 -1
- package/src/definition/datasource/datasource-definition-validator.js +6 -3
- package/src/definition/definition-registry.js +8 -4
- package/src/definition/model/model-data-sanitizer.js +4 -2
- package/src/definition/model/model-definition-utils.js +74 -35
- package/src/definition/model/model-definition-utils.spec.js +2 -6
- package/src/definition/model/model-definition-validator.js +10 -5
- package/src/definition/model/properties/primary-keys-definition-validator.js +4 -2
- package/src/definition/model/properties/properties-definition-validator.js +36 -18
- package/src/definition/model/properties/property-uniqueness-validator.js +30 -18
- package/src/definition/model/properties/property-uniqueness-validator.spec.js +734 -74
- package/src/definition/model/properties/required-property-validator.js +7 -12
- package/src/definition/model/properties/required-property-validator.spec.js +7 -46
- package/src/definition/model/relations/relations-definition-validator.js +70 -33
- package/src/filter/fields-clause-tool.js +31 -12
- package/src/filter/include-clause-tool.js +38 -15
- package/src/filter/operator-clause-tool.js +55 -23
- package/src/filter/order-clause-tool.js +36 -13
- package/src/filter/slice-clause-tool.js +16 -7
- package/src/filter/where-clause-tool.js +24 -10
- package/src/relations/belongs-to-resolver.js +44 -20
- package/src/relations/has-many-resolver.js +52 -25
- package/src/relations/has-one-resolver.js +58 -27
- package/src/relations/references-many-resolver.js +24 -11
- package/src/repository/repository-registry.js +3 -1
- package/src/repository/repository.js +2 -1
- package/src/utils/capitalize.js +3 -1
- package/src/utils/clone-deep.js +6 -2
- package/src/utils/exclude-object-keys.js +2 -1
- package/src/utils/get-value-by-path.js +6 -2
- package/src/utils/is-deep-equal.js +21 -7
- package/src/utils/is-promise.js +6 -2
- package/src/utils/model-name-to-model-key.js +2 -1
- package/src/utils/select-object-keys.js +9 -4
- package/src/utils/singularize.js +3 -1
package/eslint.config.js
CHANGED
|
@@ -28,6 +28,7 @@ export default [{
|
|
|
28
28
|
...eslintMochaPlugin.configs.recommended.rules,
|
|
29
29
|
...eslintChaiExpectPlugin.configs['recommended-flat'].rules,
|
|
30
30
|
...eslintJsdocPlugin.configs['flat/recommended-error'].rules,
|
|
31
|
+
'curly': 'error',
|
|
31
32
|
'no-duplicate-imports': 'error',
|
|
32
33
|
'import/export': 0,
|
|
33
34
|
'jsdoc/reject-any-type': 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e22m4u/js-repository",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "Реализация репозитория для работы с базами данных",
|
|
5
5
|
"author": "Mikhail Evstropov <e22m4u@yandex.ru>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"Datasource",
|
|
13
13
|
"Relations"
|
|
14
14
|
],
|
|
15
|
-
"homepage": "https://
|
|
15
|
+
"homepage": "https://gitverse.ru/e22m4u/js-repository",
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "git+https://
|
|
18
|
+
"url": "git+https://gitverse.ru/e22m4u/js-repository.git"
|
|
19
19
|
},
|
|
20
20
|
"type": "module",
|
|
21
21
|
"types": "./src/index.d.ts",
|
|
@@ -39,31 +39,31 @@
|
|
|
39
39
|
"prepare": "husky"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@e22m4u/js-
|
|
43
|
-
"@e22m4u/js-
|
|
44
|
-
"@e22m4u/js-service": "~0.5.1"
|
|
42
|
+
"@e22m4u/js-format": "~0.4.0",
|
|
43
|
+
"@e22m4u/js-service": "~0.6.1"
|
|
45
44
|
},
|
|
46
45
|
"devDependencies": {
|
|
47
|
-
"@commitlint/cli": "~20.3
|
|
48
|
-
"@commitlint/config-conventional": "~20.3
|
|
49
|
-
"@e22m4u/js-spy": "~0.3.
|
|
46
|
+
"@commitlint/cli": "~20.4.3",
|
|
47
|
+
"@commitlint/config-conventional": "~20.4.3",
|
|
48
|
+
"@e22m4u/js-spy": "~0.3.6",
|
|
49
|
+
"@eslint/js": "~9.39.2",
|
|
50
50
|
"@types/chai": "~5.2.3",
|
|
51
51
|
"@types/chai-as-promised": "~8.0.2",
|
|
52
52
|
"@types/mocha": "~10.0.10",
|
|
53
|
-
"c8": "~
|
|
53
|
+
"c8": "~11.0.0",
|
|
54
54
|
"chai": "~6.2.2",
|
|
55
55
|
"chai-as-promised": "~8.0.2",
|
|
56
|
-
"esbuild": "~0.27.
|
|
56
|
+
"esbuild": "~0.27.3",
|
|
57
57
|
"eslint": "~9.39.2",
|
|
58
58
|
"eslint-config-prettier": "~10.1.8",
|
|
59
59
|
"eslint-plugin-chai-expect": "~3.1.0",
|
|
60
60
|
"eslint-plugin-import": "~2.32.0",
|
|
61
|
-
"eslint-plugin-jsdoc": "~
|
|
61
|
+
"eslint-plugin-jsdoc": "~62.7.1",
|
|
62
62
|
"eslint-plugin-mocha": "~11.2.0",
|
|
63
63
|
"husky": "~9.1.7",
|
|
64
64
|
"mocha": "~11.7.5",
|
|
65
|
-
"prettier": "~3.
|
|
66
|
-
"rimraf": "~6.1.
|
|
65
|
+
"prettier": "~3.8.1",
|
|
66
|
+
"rimraf": "~6.1.3",
|
|
67
67
|
"typescript": "~5.9.3"
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -14,11 +14,12 @@ export class AdapterLoader extends Service {
|
|
|
14
14
|
* @returns {Promise<Adapter>}
|
|
15
15
|
*/
|
|
16
16
|
async loadByName(adapterName, settings = undefined) {
|
|
17
|
-
if (!adapterName || typeof adapterName !== 'string')
|
|
17
|
+
if (!adapterName || typeof adapterName !== 'string') {
|
|
18
18
|
throw new InvalidArgumentError(
|
|
19
19
|
'The adapter name should be a non-empty String, but %v was given.',
|
|
20
20
|
adapterName,
|
|
21
21
|
);
|
|
22
|
+
}
|
|
22
23
|
let adapterCtor;
|
|
23
24
|
try {
|
|
24
25
|
const module = await import(`./builtin/${adapterName}-adapter.js`);
|
|
@@ -26,7 +27,7 @@ export class AdapterLoader extends Service {
|
|
|
26
27
|
} catch {
|
|
27
28
|
/**/
|
|
28
29
|
}
|
|
29
|
-
if (!adapterCtor)
|
|
30
|
+
if (!adapterCtor) {
|
|
30
31
|
try {
|
|
31
32
|
const module = await import(
|
|
32
33
|
`@e22m4u/js-repository-${adapterName}-adapter`
|
|
@@ -35,11 +36,13 @@ export class AdapterLoader extends Service {
|
|
|
35
36
|
} catch {
|
|
36
37
|
/**/
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
}
|
|
40
|
+
if (!adapterCtor) {
|
|
39
41
|
throw new InvalidArgumentError(
|
|
40
42
|
'The adapter %v is not found.',
|
|
41
43
|
adapterName,
|
|
42
44
|
);
|
|
45
|
+
}
|
|
43
46
|
return new adapterCtor(this.container, settings);
|
|
44
47
|
}
|
|
45
48
|
}
|
|
@@ -52,7 +55,9 @@ export class AdapterLoader extends Service {
|
|
|
52
55
|
*/
|
|
53
56
|
function findAdapterCtorInModule(module) {
|
|
54
57
|
let adapterCtor;
|
|
55
|
-
if (!module || typeof module !== 'object' || Array.isArray(module))
|
|
58
|
+
if (!module || typeof module !== 'object' || Array.isArray(module)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
56
61
|
for (const ctor of Object.values(module)) {
|
|
57
62
|
if (
|
|
58
63
|
typeof ctor === 'function' &&
|
|
@@ -22,7 +22,9 @@ export class AdapterRegistry extends Service {
|
|
|
22
22
|
*/
|
|
23
23
|
async getAdapter(datasourceName) {
|
|
24
24
|
let adapter = this._adapters[datasourceName];
|
|
25
|
-
if (adapter)
|
|
25
|
+
if (adapter) {
|
|
26
|
+
return adapter;
|
|
27
|
+
}
|
|
26
28
|
const datasource =
|
|
27
29
|
this.getService(DefinitionRegistry).getDatasource(datasourceName);
|
|
28
30
|
const adapterName = datasource.adapter;
|
|
@@ -37,7 +37,9 @@ export class MemoryAdapter extends Adapter {
|
|
|
37
37
|
const tableName =
|
|
38
38
|
this.getService(ModelDefinitionUtils).getTableNameByModelName(modelName);
|
|
39
39
|
let table = this._tables.get(tableName);
|
|
40
|
-
if (table)
|
|
40
|
+
if (table) {
|
|
41
|
+
return table;
|
|
42
|
+
}
|
|
41
43
|
table = new Map();
|
|
42
44
|
this._tables.set(tableName, table);
|
|
43
45
|
return table;
|
|
@@ -121,13 +123,14 @@ export class MemoryAdapter extends Adapter {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
const table = this._getTableOrCreate(modelName);
|
|
124
|
-
if (table.has(idValue))
|
|
126
|
+
if (table.has(idValue)) {
|
|
125
127
|
throw new InvalidArgumentError(
|
|
126
128
|
'The value %v of the primary key %v already exists in the model %v.',
|
|
127
129
|
idValue,
|
|
128
130
|
pkPropName,
|
|
129
131
|
modelName,
|
|
130
132
|
);
|
|
133
|
+
}
|
|
131
134
|
|
|
132
135
|
modelData = cloneDeep(modelData);
|
|
133
136
|
modelData[pkPropName] = idValue;
|
|
@@ -159,13 +162,14 @@ export class MemoryAdapter extends Adapter {
|
|
|
159
162
|
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
160
163
|
modelName,
|
|
161
164
|
);
|
|
162
|
-
if (!isExists)
|
|
165
|
+
if (!isExists) {
|
|
163
166
|
throw new InvalidArgumentError(
|
|
164
167
|
'The value %v of the primary key %v does not exist in the model %v.',
|
|
165
168
|
id,
|
|
166
169
|
pkPropName,
|
|
167
170
|
modelName,
|
|
168
171
|
);
|
|
172
|
+
}
|
|
169
173
|
|
|
170
174
|
modelData = cloneDeep(modelData);
|
|
171
175
|
modelData[pkPropName] = id;
|
|
@@ -230,7 +234,9 @@ export class MemoryAdapter extends Adapter {
|
|
|
230
234
|
async patch(modelName, modelData, where = undefined) {
|
|
231
235
|
const table = this._getTableOrCreate(modelName);
|
|
232
236
|
const tableItems = Array.from(table.values());
|
|
233
|
-
if (!tableItems.length)
|
|
237
|
+
if (!tableItems.length) {
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
234
240
|
let modelItems = tableItems.map(tableItem =>
|
|
235
241
|
this.getService(ModelDefinitionUtils).convertColumnNamesToPropertyNames(
|
|
236
242
|
modelName,
|
|
@@ -238,8 +244,9 @@ export class MemoryAdapter extends Adapter {
|
|
|
238
244
|
),
|
|
239
245
|
);
|
|
240
246
|
|
|
241
|
-
if (where && typeof where === 'object')
|
|
247
|
+
if (where && typeof where === 'object') {
|
|
242
248
|
modelItems = this.getService(WhereClauseTool).filter(modelItems, where);
|
|
249
|
+
}
|
|
243
250
|
const size = modelItems.length;
|
|
244
251
|
|
|
245
252
|
const pkPropName =
|
|
@@ -277,13 +284,14 @@ export class MemoryAdapter extends Adapter {
|
|
|
277
284
|
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
278
285
|
modelName,
|
|
279
286
|
);
|
|
280
|
-
if (existingTableData == null)
|
|
287
|
+
if (existingTableData == null) {
|
|
281
288
|
throw new InvalidArgumentError(
|
|
282
289
|
'The value %v of the primary key %v does not exist in the model %v.',
|
|
283
290
|
id,
|
|
284
291
|
pkPropName,
|
|
285
292
|
modelName,
|
|
286
293
|
);
|
|
294
|
+
}
|
|
287
295
|
|
|
288
296
|
modelData = cloneDeep(modelData);
|
|
289
297
|
delete modelData[pkPropName];
|
|
@@ -320,19 +328,22 @@ export class MemoryAdapter extends Adapter {
|
|
|
320
328
|
);
|
|
321
329
|
|
|
322
330
|
if (filter && typeof filter === 'object') {
|
|
323
|
-
if (filter.where)
|
|
331
|
+
if (filter.where) {
|
|
324
332
|
modelItems = this.getService(WhereClauseTool).filter(
|
|
325
333
|
modelItems,
|
|
326
334
|
filter.where,
|
|
327
335
|
);
|
|
328
|
-
|
|
336
|
+
}
|
|
337
|
+
if (filter.skip || filter.limit) {
|
|
329
338
|
modelItems = this.getService(SliceClauseTool).slice(
|
|
330
339
|
modelItems,
|
|
331
340
|
filter.skip,
|
|
332
341
|
filter.limit,
|
|
333
342
|
);
|
|
334
|
-
|
|
343
|
+
}
|
|
344
|
+
if (filter.order) {
|
|
335
345
|
this.getService(OrderClauseTool).sort(modelItems, filter.order);
|
|
346
|
+
}
|
|
336
347
|
}
|
|
337
348
|
return modelItems;
|
|
338
349
|
}
|
|
@@ -353,13 +364,14 @@ export class MemoryAdapter extends Adapter {
|
|
|
353
364
|
this.getService(ModelDefinitionUtils).getPrimaryKeyAsPropertyName(
|
|
354
365
|
modelName,
|
|
355
366
|
);
|
|
356
|
-
if (!tableData)
|
|
367
|
+
if (!tableData) {
|
|
357
368
|
throw new InvalidArgumentError(
|
|
358
369
|
'The value %v of the primary key %v does not exist in the model %v.',
|
|
359
370
|
id,
|
|
360
371
|
pkPropName,
|
|
361
372
|
modelName,
|
|
362
373
|
);
|
|
374
|
+
}
|
|
363
375
|
return this.getService(
|
|
364
376
|
ModelDefinitionUtils,
|
|
365
377
|
).convertColumnNamesToPropertyNames(modelName, tableData);
|
|
@@ -375,7 +387,9 @@ export class MemoryAdapter extends Adapter {
|
|
|
375
387
|
async delete(modelName, where = undefined) {
|
|
376
388
|
const table = this._getTableOrCreate(modelName);
|
|
377
389
|
const tableItems = Array.from(table.values());
|
|
378
|
-
if (!tableItems.length)
|
|
390
|
+
if (!tableItems.length) {
|
|
391
|
+
return 0;
|
|
392
|
+
}
|
|
379
393
|
let modelItems = tableItems.map(tableItem =>
|
|
380
394
|
this.getService(ModelDefinitionUtils).convertColumnNamesToPropertyNames(
|
|
381
395
|
modelName,
|
|
@@ -383,8 +397,9 @@ export class MemoryAdapter extends Adapter {
|
|
|
383
397
|
),
|
|
384
398
|
);
|
|
385
399
|
|
|
386
|
-
if (where && typeof where === 'object')
|
|
400
|
+
if (where && typeof where === 'object') {
|
|
387
401
|
modelItems = this.getService(WhereClauseTool).filter(modelItems, where);
|
|
402
|
+
}
|
|
388
403
|
const size = modelItems.length;
|
|
389
404
|
|
|
390
405
|
const idPropName =
|
|
@@ -441,8 +456,9 @@ export class MemoryAdapter extends Adapter {
|
|
|
441
456
|
),
|
|
442
457
|
);
|
|
443
458
|
|
|
444
|
-
if (where && typeof where === 'object')
|
|
459
|
+
if (where && typeof where === 'object') {
|
|
445
460
|
modelItems = this.getService(WhereClauseTool).filter(modelItems, where);
|
|
461
|
+
}
|
|
446
462
|
return modelItems.length;
|
|
447
463
|
}
|
|
448
464
|
}
|
|
@@ -13,12 +13,13 @@ export class DataSanitizingDecorator extends Service {
|
|
|
13
13
|
* @param {Adapter} adapter
|
|
14
14
|
*/
|
|
15
15
|
decorate(adapter) {
|
|
16
|
-
if (!adapter || !(adapter instanceof Adapter))
|
|
16
|
+
if (!adapter || !(adapter instanceof Adapter)) {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The first argument of DataSanitizingDecorator.decorate should be ' +
|
|
19
19
|
'an Adapter instance, but %v was given.',
|
|
20
20
|
adapter,
|
|
21
21
|
);
|
|
22
|
+
}
|
|
22
23
|
|
|
23
24
|
const sanitizer = adapter.getService(ModelDataSanitizer);
|
|
24
25
|
const sanitize = (...args) => sanitizer.sanitize(...args);
|
|
@@ -13,12 +13,13 @@ export class DefaultValuesDecorator extends Service {
|
|
|
13
13
|
* @param {Adapter} adapter
|
|
14
14
|
*/
|
|
15
15
|
decorate(adapter) {
|
|
16
|
-
if (!adapter || !(adapter instanceof Adapter))
|
|
16
|
+
if (!adapter || !(adapter instanceof Adapter)) {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The first argument of DefaultValuesDecorator.decorate should be ' +
|
|
19
19
|
'an Adapter instance, but %v was given.',
|
|
20
20
|
adapter,
|
|
21
21
|
);
|
|
22
|
+
}
|
|
22
23
|
|
|
23
24
|
const utils = adapter.getService(ModelDefinitionUtils);
|
|
24
25
|
const setDefaults = (...args) =>
|
|
@@ -13,12 +13,13 @@ export class FieldsFilteringDecorator extends Service {
|
|
|
13
13
|
* @param {Adapter} adapter
|
|
14
14
|
*/
|
|
15
15
|
decorate(adapter) {
|
|
16
|
-
if (!adapter || !(adapter instanceof Adapter))
|
|
16
|
+
if (!adapter || !(adapter instanceof Adapter)) {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The first argument of FieldsFilteringDecorator.decorate should be ' +
|
|
19
19
|
'an Adapter instance, but %v was given.',
|
|
20
20
|
adapter,
|
|
21
21
|
);
|
|
22
|
+
}
|
|
22
23
|
|
|
23
24
|
const tool = adapter.getService(FieldsClauseTool);
|
|
24
25
|
const selectFields = (...args) => tool.filter(...args);
|
|
@@ -26,8 +27,9 @@ export class FieldsFilteringDecorator extends Service {
|
|
|
26
27
|
const create = adapter.create;
|
|
27
28
|
adapter.create = async function (modelName, modelData, filter) {
|
|
28
29
|
let result = await create.call(this, modelName, modelData, filter);
|
|
29
|
-
if (filter && typeof filter === 'object' && filter.fields)
|
|
30
|
+
if (filter && typeof filter === 'object' && filter.fields) {
|
|
30
31
|
result = selectFields(result, modelName, filter.fields);
|
|
32
|
+
}
|
|
31
33
|
return result;
|
|
32
34
|
};
|
|
33
35
|
|
|
@@ -40,8 +42,9 @@ export class FieldsFilteringDecorator extends Service {
|
|
|
40
42
|
modelData,
|
|
41
43
|
filter,
|
|
42
44
|
);
|
|
43
|
-
if (filter && typeof filter === 'object' && filter.fields)
|
|
45
|
+
if (filter && typeof filter === 'object' && filter.fields) {
|
|
44
46
|
result = selectFields(result, modelName, filter.fields);
|
|
47
|
+
}
|
|
45
48
|
return result;
|
|
46
49
|
};
|
|
47
50
|
|
|
@@ -53,32 +56,36 @@ export class FieldsFilteringDecorator extends Service {
|
|
|
53
56
|
modelData,
|
|
54
57
|
filter,
|
|
55
58
|
);
|
|
56
|
-
if (filter && typeof filter === 'object' && filter.fields)
|
|
59
|
+
if (filter && typeof filter === 'object' && filter.fields) {
|
|
57
60
|
result = selectFields(result, modelName, filter.fields);
|
|
61
|
+
}
|
|
58
62
|
return result;
|
|
59
63
|
};
|
|
60
64
|
|
|
61
65
|
const patchById = adapter.patchById;
|
|
62
66
|
adapter.patchById = async function (modelName, id, modelData, filter) {
|
|
63
67
|
let result = await patchById.call(this, modelName, id, modelData, filter);
|
|
64
|
-
if (filter && typeof filter === 'object' && filter.fields)
|
|
68
|
+
if (filter && typeof filter === 'object' && filter.fields) {
|
|
65
69
|
result = selectFields(result, modelName, filter.fields);
|
|
70
|
+
}
|
|
66
71
|
return result;
|
|
67
72
|
};
|
|
68
73
|
|
|
69
74
|
const find = adapter.find;
|
|
70
75
|
adapter.find = async function (modelName, filter) {
|
|
71
76
|
let result = await find.call(this, modelName, filter);
|
|
72
|
-
if (filter && typeof filter === 'object' && filter.fields)
|
|
77
|
+
if (filter && typeof filter === 'object' && filter.fields) {
|
|
73
78
|
result = selectFields(result, modelName, filter.fields);
|
|
79
|
+
}
|
|
74
80
|
return result;
|
|
75
81
|
};
|
|
76
82
|
|
|
77
83
|
const findById = adapter.findById;
|
|
78
84
|
adapter.findById = async function (modelName, id, filter) {
|
|
79
85
|
let result = await findById.call(this, modelName, id, filter);
|
|
80
|
-
if (filter && typeof filter === 'object' && filter.fields)
|
|
86
|
+
if (filter && typeof filter === 'object' && filter.fields) {
|
|
81
87
|
result = selectFields(result, modelName, filter.fields);
|
|
88
|
+
}
|
|
82
89
|
return result;
|
|
83
90
|
};
|
|
84
91
|
}
|
|
@@ -13,12 +13,13 @@ export class InclusionDecorator extends Service {
|
|
|
13
13
|
* @param {Adapter} adapter
|
|
14
14
|
*/
|
|
15
15
|
decorate(adapter) {
|
|
16
|
-
if (!adapter || !(adapter instanceof Adapter))
|
|
16
|
+
if (!adapter || !(adapter instanceof Adapter)) {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The first argument of InclusionDecorator.decorate should be ' +
|
|
19
19
|
'an Adapter instance, but %v was given.',
|
|
20
20
|
adapter,
|
|
21
21
|
);
|
|
22
|
+
}
|
|
22
23
|
|
|
23
24
|
const tool = adapter.getService(IncludeClauseTool);
|
|
24
25
|
const includeTo = (...args) => tool.includeTo(...args);
|
|
@@ -26,8 +27,9 @@ export class InclusionDecorator extends Service {
|
|
|
26
27
|
const create = adapter.create;
|
|
27
28
|
adapter.create = async function (modelName, modelData, filter) {
|
|
28
29
|
const retvalData = await create.call(this, modelName, modelData, filter);
|
|
29
|
-
if (filter && typeof filter === 'object' && filter.include)
|
|
30
|
+
if (filter && typeof filter === 'object' && filter.include) {
|
|
30
31
|
await includeTo([retvalData], modelName, filter.include);
|
|
32
|
+
}
|
|
31
33
|
return retvalData;
|
|
32
34
|
};
|
|
33
35
|
|
|
@@ -40,8 +42,9 @@ export class InclusionDecorator extends Service {
|
|
|
40
42
|
modelData,
|
|
41
43
|
filter,
|
|
42
44
|
);
|
|
43
|
-
if (filter && typeof filter === 'object' && filter.include)
|
|
45
|
+
if (filter && typeof filter === 'object' && filter.include) {
|
|
44
46
|
await includeTo([retvalData], modelName, filter.include);
|
|
47
|
+
}
|
|
45
48
|
return retvalData;
|
|
46
49
|
};
|
|
47
50
|
|
|
@@ -53,8 +56,9 @@ export class InclusionDecorator extends Service {
|
|
|
53
56
|
modelData,
|
|
54
57
|
filter,
|
|
55
58
|
);
|
|
56
|
-
if (filter && typeof filter === 'object' && filter.include)
|
|
59
|
+
if (filter && typeof filter === 'object' && filter.include) {
|
|
57
60
|
await includeTo([retvalData], modelName, filter.include);
|
|
61
|
+
}
|
|
58
62
|
return retvalData;
|
|
59
63
|
};
|
|
60
64
|
|
|
@@ -67,24 +71,27 @@ export class InclusionDecorator extends Service {
|
|
|
67
71
|
modelData,
|
|
68
72
|
filter,
|
|
69
73
|
);
|
|
70
|
-
if (filter && typeof filter === 'object' && filter.include)
|
|
74
|
+
if (filter && typeof filter === 'object' && filter.include) {
|
|
71
75
|
await includeTo([retvalData], modelName, filter.include);
|
|
76
|
+
}
|
|
72
77
|
return retvalData;
|
|
73
78
|
};
|
|
74
79
|
|
|
75
80
|
const find = adapter.find;
|
|
76
81
|
adapter.find = async function (modelName, filter) {
|
|
77
82
|
const modelItems = await find.call(this, modelName, filter);
|
|
78
|
-
if (filter && typeof filter === 'object' && filter.include)
|
|
83
|
+
if (filter && typeof filter === 'object' && filter.include) {
|
|
79
84
|
await includeTo(modelItems, modelName, filter.include);
|
|
85
|
+
}
|
|
80
86
|
return modelItems;
|
|
81
87
|
};
|
|
82
88
|
|
|
83
89
|
const findById = adapter.findById;
|
|
84
90
|
adapter.findById = async function (modelName, id, filter) {
|
|
85
91
|
const retvalData = await findById.call(this, modelName, id, filter);
|
|
86
|
-
if (filter && typeof filter === 'object' && filter.include)
|
|
92
|
+
if (filter && typeof filter === 'object' && filter.include) {
|
|
87
93
|
await includeTo([retvalData], modelName, filter.include);
|
|
94
|
+
}
|
|
88
95
|
return retvalData;
|
|
89
96
|
};
|
|
90
97
|
}
|
|
@@ -13,12 +13,13 @@ export class PropertyUniquenessDecorator extends Service {
|
|
|
13
13
|
* @param {Adapter} adapter
|
|
14
14
|
*/
|
|
15
15
|
decorate(adapter) {
|
|
16
|
-
if (!adapter || !(adapter instanceof Adapter))
|
|
16
|
+
if (!adapter || !(adapter instanceof Adapter)) {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The first argument of PropertyUniquenessDecorator.decorate should be ' +
|
|
19
19
|
'an Adapter instance, but %v was given.',
|
|
20
20
|
adapter,
|
|
21
21
|
);
|
|
22
|
+
}
|
|
22
23
|
const validator = this.getService(PropertyUniquenessValidator);
|
|
23
24
|
|
|
24
25
|
const create = adapter.create;
|
|
@@ -13,12 +13,13 @@ export class RequiredPropertyDecorator extends Service {
|
|
|
13
13
|
* @param {Adapter} adapter
|
|
14
14
|
*/
|
|
15
15
|
decorate(adapter) {
|
|
16
|
-
if (!adapter || !(adapter instanceof Adapter))
|
|
16
|
+
if (!adapter || !(adapter instanceof Adapter)) {
|
|
17
17
|
throw new InvalidArgumentError(
|
|
18
18
|
'The first argument of RequiredPropertyDecorator.decorate should be ' +
|
|
19
19
|
'an Adapter instance, but %v was given.',
|
|
20
20
|
adapter,
|
|
21
21
|
);
|
|
22
|
+
}
|
|
22
23
|
const validator = this.getService(RequiredPropertyValidator);
|
|
23
24
|
|
|
24
25
|
const create = adapter.create;
|
|
@@ -11,23 +11,26 @@ export class DatasourceDefinitionValidator extends Service {
|
|
|
11
11
|
* @param {object} datasourceDef
|
|
12
12
|
*/
|
|
13
13
|
validate(datasourceDef) {
|
|
14
|
-
if (!datasourceDef || typeof datasourceDef !== 'object')
|
|
14
|
+
if (!datasourceDef || typeof datasourceDef !== 'object') {
|
|
15
15
|
throw new InvalidArgumentError(
|
|
16
16
|
'The datasource definition should be an Object, but %v was given.',
|
|
17
17
|
datasourceDef,
|
|
18
18
|
);
|
|
19
|
-
|
|
19
|
+
}
|
|
20
|
+
if (!datasourceDef.name || typeof datasourceDef.name !== 'string') {
|
|
20
21
|
throw new InvalidArgumentError(
|
|
21
22
|
'The datasource definition requires the option "name" ' +
|
|
22
23
|
'as a non-empty String, but %v was given.',
|
|
23
24
|
datasourceDef.name,
|
|
24
25
|
);
|
|
25
|
-
|
|
26
|
+
}
|
|
27
|
+
if (!datasourceDef.adapter || typeof datasourceDef.adapter !== 'string') {
|
|
26
28
|
throw new InvalidArgumentError(
|
|
27
29
|
'The datasource %v requires the option "adapter" ' +
|
|
28
30
|
'as a non-empty String, but %v was given.',
|
|
29
31
|
datasourceDef.name,
|
|
30
32
|
datasourceDef.adapter,
|
|
31
33
|
);
|
|
34
|
+
}
|
|
32
35
|
}
|
|
33
36
|
}
|
|
@@ -30,11 +30,12 @@ export class DefinitionRegistry extends Service {
|
|
|
30
30
|
addDatasource(datasourceDef) {
|
|
31
31
|
this.getService(DatasourceDefinitionValidator).validate(datasourceDef);
|
|
32
32
|
const name = datasourceDef.name;
|
|
33
|
-
if (name in this._datasources)
|
|
33
|
+
if (name in this._datasources) {
|
|
34
34
|
throw new InvalidArgumentError(
|
|
35
35
|
'The datasource %v is already defined.',
|
|
36
36
|
name,
|
|
37
37
|
);
|
|
38
|
+
}
|
|
38
39
|
this._datasources[name] = datasourceDef;
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -56,8 +57,9 @@ export class DefinitionRegistry extends Service {
|
|
|
56
57
|
*/
|
|
57
58
|
getDatasource(name) {
|
|
58
59
|
const datasourceDef = this._datasources[name];
|
|
59
|
-
if (!datasourceDef)
|
|
60
|
+
if (!datasourceDef) {
|
|
60
61
|
throw new InvalidArgumentError('The datasource %v is not defined.', name);
|
|
62
|
+
}
|
|
61
63
|
return datasourceDef;
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -69,11 +71,12 @@ export class DefinitionRegistry extends Service {
|
|
|
69
71
|
addModel(modelDef) {
|
|
70
72
|
this.getService(ModelDefinitionValidator).validate(modelDef);
|
|
71
73
|
const modelKey = modelNameToModelKey(modelDef.name);
|
|
72
|
-
if (modelKey in this._models)
|
|
74
|
+
if (modelKey in this._models) {
|
|
73
75
|
throw new InvalidArgumentError(
|
|
74
76
|
'The model %v is already defined.',
|
|
75
77
|
modelDef.name,
|
|
76
78
|
);
|
|
79
|
+
}
|
|
77
80
|
this._models[modelKey] = modelDef;
|
|
78
81
|
}
|
|
79
82
|
|
|
@@ -97,8 +100,9 @@ export class DefinitionRegistry extends Service {
|
|
|
97
100
|
getModel(name) {
|
|
98
101
|
const modelKey = modelNameToModelKey(name);
|
|
99
102
|
const modelDef = this._models[modelKey];
|
|
100
|
-
if (!modelDef)
|
|
103
|
+
if (!modelDef) {
|
|
101
104
|
throw new InvalidArgumentError('The model %v is not defined.', name);
|
|
105
|
+
}
|
|
102
106
|
return modelDef;
|
|
103
107
|
}
|
|
104
108
|
}
|
|
@@ -14,18 +14,20 @@ export class ModelDataSanitizer extends Service {
|
|
|
14
14
|
* @returns {object}
|
|
15
15
|
*/
|
|
16
16
|
sanitize(modelName, modelData) {
|
|
17
|
-
if (!modelName || typeof modelName !== 'string')
|
|
17
|
+
if (!modelName || typeof modelName !== 'string') {
|
|
18
18
|
throw new InvalidArgumentError(
|
|
19
19
|
'The first argument of ModelDataSanitizer.sanitize ' +
|
|
20
20
|
'should be a string, but %v was given.',
|
|
21
21
|
modelName,
|
|
22
22
|
);
|
|
23
|
-
|
|
23
|
+
}
|
|
24
|
+
if (!modelData || typeof modelData !== 'object') {
|
|
24
25
|
throw new InvalidArgumentError(
|
|
25
26
|
'The second argument of ModelDataSanitizer.sanitize ' +
|
|
26
27
|
'should be an Object, but %v was given.',
|
|
27
28
|
modelData,
|
|
28
29
|
);
|
|
30
|
+
}
|
|
29
31
|
return this.getService(
|
|
30
32
|
ModelDefinitionUtils,
|
|
31
33
|
).excludeObjectKeysByRelationNames(modelName, modelData);
|