@e22m4u/js-repository 0.6.5 → 0.8.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.
- package/.mocharc.json +2 -3
- package/README.md +128 -695
- package/dist/cjs/index.cjs +141 -1262
- package/eslint.config.js +29 -58
- package/jsconfig.json +7 -0
- package/package.json +12 -20
- package/src/adapter/adapter-loader.js +3 -4
- package/src/adapter/adapter.js +10 -11
- package/src/adapter/adapter.spec.js +13 -24
- package/src/adapter/builtin/memory-adapter.js +49 -19
- package/src/adapter/builtin/memory-adapter.spec.js +52 -2
- package/src/adapter/decorator/default-values-decorator.spec.js +1 -2
- package/src/adapter/decorator/index.js +0 -2
- package/src/database-schema.js +1 -2
- package/src/{database-schema.spec.ts → database-schema.spec.js} +5 -17
- package/src/definition/model/index.js +0 -3
- package/src/definition/model/model-definition-utils.js +1 -2
- package/src/definition/model/model-definition-utils.spec.js +5 -2
- package/src/definition/model/properties/index.js +0 -3
- package/src/definition/model/properties/properties-definition-validator.js +0 -169
- package/src/definition/model/properties/properties-definition-validator.spec.js +0 -162
- package/src/definition/model/relations/index.js +0 -1
- package/src/definition/model/relations/relations-definition-validator.js +4 -5
- package/src/filter/include-clause-tool.js +8 -6
- package/src/index.js +0 -1
- package/src/relations/belongs-to-resolver.js +1 -2
- package/src/relations/belongs-to-resolver.spec.js +6 -3
- package/src/relations/has-many-resolver.js +1 -2
- package/src/relations/has-many-resolver.spec.js +6 -3
- package/src/relations/has-one-resolver.js +1 -2
- package/src/relations/has-one-resolver.spec.js +6 -3
- package/src/relations/references-many-resolver.js +1 -2
- package/src/relations/references-many-resolver.spec.js +6 -3
- package/src/repository/repository.js +1 -2
- package/src/utils/index.js +0 -4
- package/src/utils/is-plain-object.js +4 -4
- package/src/utils/model-name-to-model-key.js +0 -4
- package/src/utils/model-name-to-model-key.spec.js +0 -23
- package/src/adapter/adapter-loader.d.ts +0 -16
- package/src/adapter/adapter-registry.d.ts +0 -14
- package/src/adapter/adapter.d.ts +0 -155
- package/src/adapter/builtin/memory-adapter.d.ts +0 -148
- package/src/adapter/decorator/data-sanitizing-decorator.d.ts +0 -14
- package/src/adapter/decorator/data-transformation-decorator.d.ts +0 -14
- package/src/adapter/decorator/data-transformation-decorator.js +0 -54
- package/src/adapter/decorator/data-transformation-decorator.spec.js +0 -193
- package/src/adapter/decorator/data-validation-decorator.d.ts +0 -14
- package/src/adapter/decorator/data-validation-decorator.js +0 -54
- package/src/adapter/decorator/data-validation-decorator.spec.js +0 -105
- package/src/adapter/decorator/default-values-decorator.d.ts +0 -14
- package/src/adapter/decorator/fields-filtering-decorator.d.ts +0 -14
- package/src/adapter/decorator/inclusion-decorator.d.ts +0 -14
- package/src/adapter/decorator/index.d.ts +0 -7
- package/src/adapter/decorator/property-uniqueness-decorator.d.ts +0 -14
- package/src/adapter/index.d.ts +0 -3
- package/src/database-schema.d.ts +0 -37
- package/src/definition/datasource/datasource-definition-validator.d.ts +0 -14
- package/src/definition/datasource/datasource-definition.d.ts +0 -8
- package/src/definition/datasource/index.d.ts +0 -2
- package/src/definition/definition-registry.d.ts +0 -50
- package/src/definition/index.d.ts +0 -3
- package/src/definition/model/index.d.ts +0 -8
- package/src/definition/model/model-data-sanitizer.d.ts +0 -15
- package/src/definition/model/model-data-transformer.d.ts +0 -16
- package/src/definition/model/model-data-transformer.js +0 -170
- package/src/definition/model/model-data-transformer.spec.js +0 -2312
- package/src/definition/model/model-data-validator.d.ts +0 -16
- package/src/definition/model/model-data-validator.js +0 -318
- package/src/definition/model/model-data-validator.spec.js +0 -4528
- package/src/definition/model/model-definition-utils.d.ts +0 -180
- package/src/definition/model/model-definition-validator.d.ts +0 -14
- package/src/definition/model/model-definition.d.ts +0 -28
- package/src/definition/model/model-definition.js +0 -1
- package/src/definition/model/properties/data-type.d.ts +0 -16
- package/src/definition/model/properties/index.d.ts +0 -8
- package/src/definition/model/properties/primary-keys-definition-validator.d.ts +0 -15
- package/src/definition/model/properties/properties-definition-validator.d.ts +0 -15
- package/src/definition/model/properties/property-definition.d.ts +0 -27
- package/src/definition/model/properties/property-definition.js +0 -1
- package/src/definition/model/properties/property-transformer/builtin/index.d.ts +0 -3
- package/src/definition/model/properties/property-transformer/builtin/index.js +0 -3
- package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.d.ts +0 -6
- package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.js +0 -19
- package/src/definition/model/properties/property-transformer/builtin/to-lower-case-transformer.spec.js +0 -39
- package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.d.ts +0 -6
- package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.js +0 -19
- package/src/definition/model/properties/property-transformer/builtin/to-upper-case-transformer.spec.js +0 -39
- package/src/definition/model/properties/property-transformer/builtin/trim-transformer.d.ts +0 -6
- package/src/definition/model/properties/property-transformer/builtin/trim-transformer.js +0 -19
- package/src/definition/model/properties/property-transformer/builtin/trim-transformer.spec.js +0 -39
- package/src/definition/model/properties/property-transformer/index.d.ts +0 -2
- package/src/definition/model/properties/property-transformer/index.js +0 -2
- package/src/definition/model/properties/property-transformer/property-transformer-registry.d.ts +0 -29
- package/src/definition/model/properties/property-transformer/property-transformer-registry.js +0 -76
- package/src/definition/model/properties/property-transformer/property-transformer-registry.spec.js +0 -133
- package/src/definition/model/properties/property-transformer/property-transformer.d.ts +0 -27
- package/src/definition/model/properties/property-transformer/property-transformer.js +0 -1
- package/src/definition/model/properties/property-uniqueness-validator.d.ts +0 -31
- package/src/definition/model/properties/property-uniqueness.d.ts +0 -14
- package/src/definition/model/properties/property-validator/builtin/index.d.ts +0 -3
- package/src/definition/model/properties/property-validator/builtin/index.js +0 -3
- package/src/definition/model/properties/property-validator/builtin/max-length-validator.d.ts +0 -6
- package/src/definition/model/properties/property-validator/builtin/max-length-validator.js +0 -28
- package/src/definition/model/properties/property-validator/builtin/max-length-validator.spec.js +0 -100
- package/src/definition/model/properties/property-validator/builtin/min-length-validator.d.ts +0 -6
- package/src/definition/model/properties/property-validator/builtin/min-length-validator.js +0 -28
- package/src/definition/model/properties/property-validator/builtin/min-length-validator.spec.js +0 -100
- package/src/definition/model/properties/property-validator/builtin/regexp-validator.d.ts +0 -6
- package/src/definition/model/properties/property-validator/builtin/regexp-validator.js +0 -30
- package/src/definition/model/properties/property-validator/builtin/regexp-validator.spec.js +0 -102
- package/src/definition/model/properties/property-validator/index.d.ts +0 -2
- package/src/definition/model/properties/property-validator/index.js +0 -2
- package/src/definition/model/properties/property-validator/property-validator-registry.d.ts +0 -29
- package/src/definition/model/properties/property-validator/property-validator-registry.js +0 -76
- package/src/definition/model/properties/property-validator/property-validator-registry.spec.js +0 -132
- package/src/definition/model/properties/property-validator/property-validator.d.ts +0 -25
- package/src/definition/model/properties/property-validator/property-validator.js +0 -1
- package/src/definition/model/relations/index.d.ts +0 -3
- package/src/definition/model/relations/relation-definition.d.ts +0 -236
- package/src/definition/model/relations/relation-definition.js +0 -1
- package/src/definition/model/relations/relation-type.d.ts +0 -14
- package/src/definition/model/relations/relations-definition-validator.d.ts +0 -15
- package/src/errors/index.d.ts +0 -3
- package/src/errors/invalid-argument-error.d.ts +0 -6
- package/src/errors/invalid-operator-value-error.d.ts +0 -13
- package/src/errors/not-implemented-error.d.ts +0 -6
- package/src/filter/fields-clause-tool.d.ts +0 -38
- package/src/filter/filter-clause.d.ts +0 -348
- package/src/filter/include-clause-tool.d.ts +0 -55
- package/src/filter/index.d.ts +0 -7
- package/src/filter/operator-clause-tool.d.ts +0 -224
- package/src/filter/order-clause-tool.d.ts +0 -32
- package/src/filter/slice-clause-tool.d.ts +0 -30
- package/src/filter/where-clause-tool.d.ts +0 -23
- package/src/index.d.ts +0 -9
- package/src/relations/belongs-to-resolver.d.ts +0 -46
- package/src/relations/has-many-resolver.d.ts +0 -67
- package/src/relations/has-one-resolver.d.ts +0 -67
- package/src/relations/index.d.ts +0 -4
- package/src/relations/references-many-resolver.d.ts +0 -27
- package/src/repository/index.d.ts +0 -2
- package/src/repository/repository-registry.d.ts +0 -29
- package/src/repository/repository.d.ts +0 -183
- package/src/types.d.ts +0 -43
- package/src/types.js +0 -1
- package/src/utils/capitalize.d.ts +0 -6
- package/src/utils/clone-deep.d.ts +0 -6
- package/src/utils/exclude-object-keys.d.ts +0 -10
- package/src/utils/get-ctor-name.d.ts +0 -6
- package/src/utils/get-ctor-name.js +0 -11
- package/src/utils/get-ctor-name.spec.js +0 -17
- package/src/utils/get-decorator-target-type.d.ts +0 -27
- package/src/utils/get-decorator-target-type.js +0 -63
- package/src/utils/get-decorator-target-type.spec.js +0 -80
- package/src/utils/get-value-by-path.d.ts +0 -12
- package/src/utils/index.d.ts +0 -16
- package/src/utils/is-ctor.d.ts +0 -8
- package/src/utils/is-ctor.js +0 -11
- package/src/utils/is-ctor.spec.js +0 -26
- package/src/utils/is-deep-equal.d.ts +0 -10
- package/src/utils/is-plain-object.d.ts +0 -6
- package/src/utils/is-promise.d.ts +0 -10
- package/src/utils/like-to-regexp.d.ts +0 -14
- package/src/utils/model-name-to-model-key.d.ts +0 -6
- package/src/utils/select-object-keys.d.ts +0 -10
- package/src/utils/singularize.d.ts +0 -6
- package/src/utils/string-to-regexp.d.ts +0 -10
- package/src/utils/transform-promise.d.ts +0 -13
- package/src/utils/transform-promise.js +0 -15
- package/src/utils/transform-promise.spec.js +0 -19
- package/tsconfig.json +0 -11
package/README.md
CHANGED
|
@@ -15,14 +15,6 @@
|
|
|
15
15
|
- [Источник данных](#источник-данных)
|
|
16
16
|
- [Модель](#модель)
|
|
17
17
|
- [Свойства](#свойства)
|
|
18
|
-
- [Валидаторы](#валидаторы)
|
|
19
|
-
- [Глобальные валидаторы](#глобальные-валидаторы)
|
|
20
|
-
- [Регистрация глобальных валидаторов](#регистрация-глобальных-валидаторов)
|
|
21
|
-
- [Локальные валидаторы](#локальные-валидаторы)
|
|
22
|
-
- [Трансформеры](#трансформеры)
|
|
23
|
-
- [Глобальные трансформеры](#глобальные-трансформеры)
|
|
24
|
-
- [Регистрация глобальных трансформеров](#регистрация-глобальных-трансформеров)
|
|
25
|
-
- [Локальные трансформеры](#локальные-трансформеры)
|
|
26
18
|
- [Пустые значения](#пустые-значения)
|
|
27
19
|
- [Переопределение пустых значений](#переопределение-пустых-значений)
|
|
28
20
|
- [Репозиторий](#репозиторий)
|
|
@@ -48,7 +40,6 @@
|
|
|
48
40
|
- [Has One (полиморфная)](#has-one-полиморфная-версия)
|
|
49
41
|
- [Has Many (полиморфная)](#has-many-полиморфная-версия)
|
|
50
42
|
- [Расширение](#расширение)
|
|
51
|
-
- [TypeScript](#typescript)
|
|
52
43
|
- [Тесты](#тесты)
|
|
53
44
|
- [Лицензия](#лицензия)
|
|
54
45
|
|
|
@@ -86,15 +77,14 @@ const {DatabaseSchema} = require('@e22m4u/js-repository');
|
|
|
86
77
|
Модуль позволяет абстрагироваться от различных интерфейсов баз данных,
|
|
87
78
|
представляя их как именованные *источники данных*, подключаемые к *моделям*.
|
|
88
79
|
*Модель* же описывает таблицу базы, колонки которой являются свойствами
|
|
89
|
-
модели. Свойства модели могут иметь определенный *тип* допустимого
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
«один к одному», «один ко многим» и другие типы отношений между моделями.
|
|
80
|
+
модели. Свойства модели могут иметь определенный *тип* допустимого значения.
|
|
81
|
+
Кроме того, *модель* может определять классические связи «один к одному»,
|
|
82
|
+
«один ко многим» и другие типы отношений между моделями.
|
|
93
83
|
|
|
94
|
-
Непосредственно чтение и запись данных
|
|
84
|
+
Непосредственно чтение и запись данных производятся с помощью *репозитория*,
|
|
95
85
|
который есть у каждой модели с объявленным *источником данных*. Репозиторий
|
|
96
86
|
может фильтровать запрашиваемые документы, выполнять валидацию свойств
|
|
97
|
-
согласно определению
|
|
87
|
+
согласно определению модели и встраивать связанные данные в результат
|
|
98
88
|
выборки.
|
|
99
89
|
|
|
100
90
|
- *Источник данных* - определяет способ подключения к базе
|
|
@@ -266,17 +256,36 @@ console.log(cityWithCountry);
|
|
|
266
256
|
|
|
267
257
|
## Схема
|
|
268
258
|
|
|
269
|
-
Экземпляр класса `DatabaseSchema` хранит определения источников данных
|
|
259
|
+
Экземпляр класса `DatabaseSchema` хранит определения источников данных
|
|
260
|
+
и моделей.
|
|
270
261
|
|
|
271
262
|
**Методы**
|
|
272
263
|
|
|
273
|
-
|
|
274
|
-
- `defineModel(modelDef: object): this` - добавить модель
|
|
275
|
-
- `getRepository(modelName: string): Repository` - получить репозиторий
|
|
264
|
+
Добавить источник
|
|
276
265
|
|
|
277
|
-
|
|
266
|
+
- `defineDatasource(datasourceDef)`
|
|
267
|
+
- `datasourceDef: object`: определение источника;
|
|
268
|
+
- результат: `this`;
|
|
269
|
+
|
|
270
|
+
Добавить модель:
|
|
271
|
+
|
|
272
|
+
- `defineModel(modelDef)`
|
|
273
|
+
- `modelDef: object`: определение модели;
|
|
274
|
+
- результат: `this`;
|
|
275
|
+
|
|
276
|
+
Получить репозиторий
|
|
277
|
+
|
|
278
|
+
- `getRepository(modelName)`
|
|
279
|
+
- `modelName: string` имя модели;
|
|
280
|
+
- результат: `Repository`;
|
|
281
|
+
|
|
282
|
+
**Пример**
|
|
283
|
+
|
|
284
|
+
Ниже приводится пошаговый пример настройки модели `product` и получения
|
|
285
|
+
экземпляра репозитория, с помощью которого можно управлять данными этой
|
|
286
|
+
коллекции.
|
|
278
287
|
|
|
279
|
-
Импорт класса и создание экземпляра схемы.
|
|
288
|
+
1\. Импорт класса и создание экземпляра схемы.
|
|
280
289
|
|
|
281
290
|
```js
|
|
282
291
|
import {DatabaseSchema} from '@e22m4u/js-repository';
|
|
@@ -284,7 +293,7 @@ import {DatabaseSchema} from '@e22m4u/js-repository';
|
|
|
284
293
|
const dbs = new DatabaseSchema();
|
|
285
294
|
```
|
|
286
295
|
|
|
287
|
-
Определение нового источника.
|
|
296
|
+
2\. Определение нового источника.
|
|
288
297
|
|
|
289
298
|
```js
|
|
290
299
|
dbs.defineDatasource({
|
|
@@ -293,7 +302,7 @@ dbs.defineDatasource({
|
|
|
293
302
|
});
|
|
294
303
|
```
|
|
295
304
|
|
|
296
|
-
Определение новой модели.
|
|
305
|
+
3\. Определение новой модели.
|
|
297
306
|
|
|
298
307
|
```js
|
|
299
308
|
dbs.defineModel({
|
|
@@ -306,7 +315,7 @@ dbs.defineModel({
|
|
|
306
315
|
});
|
|
307
316
|
```
|
|
308
317
|
|
|
309
|
-
Получение репозитория по названию модели.
|
|
318
|
+
4\. Получение репозитория по названию модели.
|
|
310
319
|
|
|
311
320
|
```js
|
|
312
321
|
const productRep = dbs.getRepository('product');
|
|
@@ -379,7 +388,7 @@ dbs.defineModel({
|
|
|
379
388
|
## Свойства
|
|
380
389
|
|
|
381
390
|
Параметр `properties` находится в определении модели и принимает объект, ключи
|
|
382
|
-
которого являются свойствами этой модели, а
|
|
391
|
+
которого являются свойствами этой модели, а значениями тип свойства или объект
|
|
383
392
|
с дополнительными параметрами.
|
|
384
393
|
|
|
385
394
|
**Тип данных**
|
|
@@ -401,20 +410,20 @@ dbs.defineModel({
|
|
|
401
410
|
- `columnType: string` тип колонки (определяется адаптером)
|
|
402
411
|
- `required: boolean` объявить свойство обязательным
|
|
403
412
|
- `default: any` значение по умолчанию
|
|
404
|
-
- `validate: string | Function | array | object` см. [Валидаторы](#Валидаторы)
|
|
405
413
|
- `unique: boolean | string` проверять значение на уникальность
|
|
406
414
|
|
|
407
415
|
**Параметр `unique`**
|
|
408
416
|
|
|
409
|
-
Если значением параметра `unique` является `true` или `'strict'`,
|
|
410
|
-
строгая проверка на уникальность. В этом режиме
|
|
411
|
-
так же подлежат проверке,
|
|
412
|
-
|
|
417
|
+
Если значением параметра `unique` является `true` или `'strict'`,
|
|
418
|
+
то выполняется строгая проверка на уникальность. В этом режиме
|
|
419
|
+
[пустые значения](#Пустые-значения) так же подлежат проверке,
|
|
420
|
+
где `null` и `undefined` также считаются значениями, которые
|
|
421
|
+
должны быть уникальными.
|
|
413
422
|
|
|
414
|
-
Режим `'sparse'` проверяет только значения с полезной нагрузкой,
|
|
415
|
-
[пустые значения](#Пустые-значения), список которых отличается
|
|
416
|
-
от типа свойства. Например, для типа `string`
|
|
417
|
-
`null` и `''` (пустая строка).
|
|
423
|
+
Режим `'sparse'` проверяет только значения с полезной нагрузкой,
|
|
424
|
+
исключая [пустые значения](#Пустые-значения), список которых отличается
|
|
425
|
+
в зависимости от типа свойства. Например, для типа `string` пустыми
|
|
426
|
+
значениями будут `undefined`, `null` и `''` (пустая строка).
|
|
418
427
|
|
|
419
428
|
- `unique: true | 'strict'` строгая проверка на уникальность
|
|
420
429
|
- `unique: 'sparse'` исключить из проверки [пустые значения](#Пустые-значения)
|
|
@@ -483,522 +492,6 @@ dbs.defineModel({
|
|
|
483
492
|
});
|
|
484
493
|
```
|
|
485
494
|
|
|
486
|
-
## Валидаторы
|
|
487
|
-
|
|
488
|
-
Валидаторы используются для проверки значения свойства перед записью в базу.
|
|
489
|
-
Проверка значения валидатором выполняется сразу после проверки типа, указанного
|
|
490
|
-
в определении свойства модели. [Пустые значения](#пустые-значения) пропускают
|
|
491
|
-
проверку валидаторами, так как не имеют полезной нагрузки.
|
|
492
|
-
|
|
493
|
-
### Глобальные валидаторы
|
|
494
|
-
|
|
495
|
-
Модуль поставляется с набором глобальных валидаторов:
|
|
496
|
-
|
|
497
|
-
- `regexp` проверка по регулярному выражению,
|
|
498
|
-
*параметр: `string | RegExp` - регулярное выражение;*
|
|
499
|
-
|
|
500
|
-
- `maxLength` максимальная длина строки или массива,
|
|
501
|
-
*параметр: `number` - максимальная длина;*
|
|
502
|
-
|
|
503
|
-
- `minLength` минимальная длина строки или массива,
|
|
504
|
-
*параметр: `number` - минимальная длина;*
|
|
505
|
-
|
|
506
|
-
Валидаторы указанные ниже находятся в разработке:
|
|
507
|
-
|
|
508
|
-
- `isLowerCase` проверка регистра (только строчные буквы);
|
|
509
|
-
- `isUpperCase` проверка регистра (только прописные буквы);
|
|
510
|
-
- `isEmail` проверка формата электронного адреса;
|
|
511
|
-
|
|
512
|
-
**Примеры**
|
|
513
|
-
|
|
514
|
-
Использование глобального валидатора.
|
|
515
|
-
|
|
516
|
-
```js
|
|
517
|
-
dbs.defineModel({
|
|
518
|
-
name: 'user',
|
|
519
|
-
properties: {
|
|
520
|
-
email: {
|
|
521
|
-
type: DataType.STRING,
|
|
522
|
-
validate: 'isEmail',
|
|
523
|
-
},
|
|
524
|
-
},
|
|
525
|
-
});
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
Использование глобальных валидаторов в виде массива.
|
|
529
|
-
|
|
530
|
-
```js
|
|
531
|
-
dbs.defineModel({
|
|
532
|
-
name: 'user',
|
|
533
|
-
properties: {
|
|
534
|
-
email: {
|
|
535
|
-
type: DataType.STRING,
|
|
536
|
-
validate: [
|
|
537
|
-
'isEmail',
|
|
538
|
-
'isLowerCase',
|
|
539
|
-
],
|
|
540
|
-
},
|
|
541
|
-
},
|
|
542
|
-
});
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
Использование глобальных валидаторов с передачей аргументов.
|
|
546
|
-
|
|
547
|
-
```js
|
|
548
|
-
dbs.defineModel({
|
|
549
|
-
name: 'user',
|
|
550
|
-
properties: {
|
|
551
|
-
name: {
|
|
552
|
-
type: DataType.STRING,
|
|
553
|
-
validate: {
|
|
554
|
-
minLength: 2,
|
|
555
|
-
maxLength: 24,
|
|
556
|
-
regexp: /^[a-zA-Z-']+$/,
|
|
557
|
-
},
|
|
558
|
-
},
|
|
559
|
-
},
|
|
560
|
-
});
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
Глобальные валидаторы без параметров могут принимать любые аргументы.
|
|
564
|
-
|
|
565
|
-
```js
|
|
566
|
-
dbs.defineModel({
|
|
567
|
-
name: 'user',
|
|
568
|
-
properties: {
|
|
569
|
-
email: {
|
|
570
|
-
type: DataType.STRING,
|
|
571
|
-
validate: {
|
|
572
|
-
maxLength: 100,
|
|
573
|
-
// так как валидатор "isEmail" не имеет параметров,
|
|
574
|
-
// его определение допускает передачу любого значения
|
|
575
|
-
// в качестве аргумента
|
|
576
|
-
isEmail: true,
|
|
577
|
-
},
|
|
578
|
-
},
|
|
579
|
-
},
|
|
580
|
-
});
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
### Регистрация глобальных валидаторов
|
|
584
|
-
|
|
585
|
-
Валидатором является функция, в которую передается значение соответствующего
|
|
586
|
-
поля перед записью в базу. Если во время проверки функция возвращает `false`,
|
|
587
|
-
то выбрасывается стандартная ошибка. Подмена стандартной ошибки возможна
|
|
588
|
-
с помощью выброса пользовательской ошибки непосредственно внутри проверяющей
|
|
589
|
-
функции.
|
|
590
|
-
|
|
591
|
-
Регистрация глобального валидатора выполняется методом `addValidator` сервиса
|
|
592
|
-
`PropertyValidatorRegistry`, который принимает название валидатора и функцию
|
|
593
|
-
для проверки значения.
|
|
594
|
-
|
|
595
|
-
**Примеры**
|
|
596
|
-
|
|
597
|
-
Регистрация глобального валидатора для проверки формата UUID.
|
|
598
|
-
|
|
599
|
-
```js
|
|
600
|
-
import {createError} from 'http-errors';
|
|
601
|
-
import {format} from '@e22m4u/js-format';
|
|
602
|
-
import {Errorf} from '@e22m4u/js-format';
|
|
603
|
-
import {PropertyValidatorRegistry} from '@e22m4u/js-repository';
|
|
604
|
-
|
|
605
|
-
// получение экземпляра сервиса
|
|
606
|
-
const pvr = dbs.getService(PropertyValidatorRegistry);
|
|
607
|
-
|
|
608
|
-
// регулярные выражения для разных версий UUID
|
|
609
|
-
const uuidRegex = {
|
|
610
|
-
any: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
611
|
-
v4: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
// регистрация глобального валидатора "isUuid",
|
|
615
|
-
// принимающего объект настроек со свойством "version"
|
|
616
|
-
pvr.addValidator('isUuid', (value, options, context) => {
|
|
617
|
-
// value - проверяемое значение;
|
|
618
|
-
// options - параметры валидатора;
|
|
619
|
-
// context - информация о проверяемом свойстве;
|
|
620
|
-
console.log(options);
|
|
621
|
-
// {
|
|
622
|
-
// version: 'v4'
|
|
623
|
-
// }
|
|
624
|
-
console.log(context);
|
|
625
|
-
// {
|
|
626
|
-
// validatorName: 'isUuid',
|
|
627
|
-
// modelName: 'device',
|
|
628
|
-
// propName: 'deviceId'
|
|
629
|
-
// }
|
|
630
|
-
|
|
631
|
-
// пустые значения не передаются в валидаторы
|
|
632
|
-
// (условие ниже никогда не сработает)
|
|
633
|
-
if (typeof value !== 'string') return false;
|
|
634
|
-
// поиск регулярного выражения для указанной
|
|
635
|
-
// версии UUID (из параметров валидатора)
|
|
636
|
-
const version = options?.version || 'any';
|
|
637
|
-
const regex = uuidRegex[version];
|
|
638
|
-
// если регулярное выражение не найдено,
|
|
639
|
-
// то выбрасывается внутренняя ошибка
|
|
640
|
-
if (!regex)
|
|
641
|
-
throw new Errorf(
|
|
642
|
-
'Invalid UUID version %v specified for validator.',
|
|
643
|
-
version,
|
|
644
|
-
);
|
|
645
|
-
// при неудачной проверке выбрасывается
|
|
646
|
-
// ошибка 400 BadRequest
|
|
647
|
-
if (!regex.test(value)) {
|
|
648
|
-
const versionString = version !== 'any' ? ` (version ${version})` : '';
|
|
649
|
-
throw createError(400, format(
|
|
650
|
-
'The property %v of the model %v must be a valid UUID%s.',
|
|
651
|
-
context.propName,
|
|
652
|
-
context.modelName,
|
|
653
|
-
versionString,
|
|
654
|
-
));
|
|
655
|
-
}
|
|
656
|
-
// при успешной проверке возвращается true,
|
|
657
|
-
// в противном случае выбрасывается стандартная
|
|
658
|
-
// ошибка проверки
|
|
659
|
-
return true;
|
|
660
|
-
});
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
Использование глобального валидатора в определении свойства.
|
|
664
|
-
|
|
665
|
-
```js
|
|
666
|
-
// определение модели "device"
|
|
667
|
-
dbs.defineModel({
|
|
668
|
-
name: 'device',
|
|
669
|
-
properties: {
|
|
670
|
-
deviceId: {
|
|
671
|
-
type: DataType.STRING,
|
|
672
|
-
required: true,
|
|
673
|
-
validate: {
|
|
674
|
-
// значение {version: 'v4'} будет передаваться
|
|
675
|
-
// вторым аргументом в функцию-валидатор
|
|
676
|
-
isUuid: {version: 'v4'},
|
|
677
|
-
},
|
|
678
|
-
},
|
|
679
|
-
},
|
|
680
|
-
});
|
|
681
|
-
```
|
|
682
|
-
|
|
683
|
-
### Локальные валидаторы
|
|
684
|
-
|
|
685
|
-
Функция-валидатор может быть передана непосредственно в определении свойства
|
|
686
|
-
без предварительной регистрации. Для этого достаточно передать функцию
|
|
687
|
-
в параметр `validate` в качестве значения или элемента массива наряду
|
|
688
|
-
с другими валидаторами.
|
|
689
|
-
|
|
690
|
-
**Примеры**
|
|
691
|
-
|
|
692
|
-
Использование локального валидатора для проверки сложности пароля.
|
|
693
|
-
|
|
694
|
-
```js
|
|
695
|
-
// валидатор `passwordStrength` проверяет сложность пароля
|
|
696
|
-
function passwordStrength(value, options, context) {
|
|
697
|
-
// value - проверяемое значение;
|
|
698
|
-
// options - не используется;
|
|
699
|
-
// context - информация о свойстве;
|
|
700
|
-
console.log(context);
|
|
701
|
-
// {
|
|
702
|
-
// validatorName: 'passwordStrength',
|
|
703
|
-
// modelName: 'user',
|
|
704
|
-
// propName: 'password'
|
|
705
|
-
// }
|
|
706
|
-
const errors = [];
|
|
707
|
-
if (value.length < 8)
|
|
708
|
-
errors.push('must be at least 8 characters long');
|
|
709
|
-
if (!/\d/.test(value))
|
|
710
|
-
errors.push('must contain at least one number');
|
|
711
|
-
if (!/[a-zA-Z]/.test(value))
|
|
712
|
-
errors.push('must contain at least one letter');
|
|
713
|
-
// если одно из условий сработало,
|
|
714
|
-
// то выбрасывается ошибка
|
|
715
|
-
if (errors.length > 0)
|
|
716
|
-
throw createError(400, format(
|
|
717
|
-
'Value of the property %v of the model %v %s.',
|
|
718
|
-
context.propName,
|
|
719
|
-
context.modelName,
|
|
720
|
-
errors.join(', '),
|
|
721
|
-
));
|
|
722
|
-
// при успешной проверке возвращается true,
|
|
723
|
-
// в противном случае выбрасывается стандартная
|
|
724
|
-
// ошибка проверки
|
|
725
|
-
return true;
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// определение модели "user"
|
|
729
|
-
dbs.defineModel({
|
|
730
|
-
name: 'user',
|
|
731
|
-
properties: {
|
|
732
|
-
password: {
|
|
733
|
-
type: DataType.STRING,
|
|
734
|
-
required: true,
|
|
735
|
-
validate: passwordStrength, // <=
|
|
736
|
-
// или
|
|
737
|
-
// validate: [passwordStrength, ...]
|
|
738
|
-
},
|
|
739
|
-
},
|
|
740
|
-
});
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
Использование анонимной функции-валидатора для проверки слага.
|
|
744
|
-
|
|
745
|
-
```js
|
|
746
|
-
// определение модели "article"
|
|
747
|
-
dbs.defineModel({
|
|
748
|
-
name: 'article',
|
|
749
|
-
properties: {
|
|
750
|
-
slug: {
|
|
751
|
-
type: DataType.STRING,
|
|
752
|
-
validate: (value) => {
|
|
753
|
-
const re = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
754
|
-
return re.test(value);
|
|
755
|
-
},
|
|
756
|
-
},
|
|
757
|
-
},
|
|
758
|
-
});
|
|
759
|
-
```
|
|
760
|
-
|
|
761
|
-
## Трансформеры
|
|
762
|
-
|
|
763
|
-
Трансформеры используются для модификации значения свойства перед проверкой
|
|
764
|
-
типа и передачей данных в базу. Трансформеры позволяют автоматически очищать
|
|
765
|
-
или приводить данные к нужному формату. [Пустые значения](#Пустые-значения)
|
|
766
|
-
не передаются в трансформеры, так как не имеют полезной нагрузки.
|
|
767
|
-
|
|
768
|
-
### Глобальные трансформеры
|
|
769
|
-
|
|
770
|
-
Модуль поставляется с набором глобальных трансформеров:
|
|
771
|
-
|
|
772
|
-
- `trim` удаление пробельных символов с начала и конца строки;
|
|
773
|
-
- `toUpperCase` перевод строки в верхний регистр;
|
|
774
|
-
- `toLowerCase` перевод строки в нижний регистр;
|
|
775
|
-
|
|
776
|
-
Трансформеры указанные ниже находятся в разработке:
|
|
777
|
-
|
|
778
|
-
- `cut` усечение строки или массива до указанной длины,
|
|
779
|
-
*параметр: `number` - максимальная длина;*
|
|
780
|
-
|
|
781
|
-
- `truncate` усечение строки с добавлением троеточия,
|
|
782
|
-
*параметр: `number` - максимальная длина;*
|
|
783
|
-
|
|
784
|
-
- `capitalize` перевод первой буквы каждого слова в верхний регистр,
|
|
785
|
-
*параметр: `{firstWordOnly?: boolean}`;*
|
|
786
|
-
|
|
787
|
-
**Примеры**
|
|
788
|
-
|
|
789
|
-
Использование глобального трансформера.
|
|
790
|
-
|
|
791
|
-
```js
|
|
792
|
-
dbs.defineModel({
|
|
793
|
-
name: 'user',
|
|
794
|
-
properties: {
|
|
795
|
-
username: {
|
|
796
|
-
type: DataType.STRING,
|
|
797
|
-
transform: 'toLowerCase',
|
|
798
|
-
},
|
|
799
|
-
},
|
|
800
|
-
});
|
|
801
|
-
```
|
|
802
|
-
|
|
803
|
-
Использование глобальных трансформеров в виде массива.
|
|
804
|
-
|
|
805
|
-
```js
|
|
806
|
-
dbs.defineModel({
|
|
807
|
-
name: 'user',
|
|
808
|
-
properties: {
|
|
809
|
-
firstName: {
|
|
810
|
-
type: DataType.STRING,
|
|
811
|
-
transform: [
|
|
812
|
-
'trim',
|
|
813
|
-
'capitalize',
|
|
814
|
-
],
|
|
815
|
-
},
|
|
816
|
-
},
|
|
817
|
-
});
|
|
818
|
-
```
|
|
819
|
-
|
|
820
|
-
Использование глобальных трансформеров с передачей аргументов.
|
|
821
|
-
|
|
822
|
-
```js
|
|
823
|
-
dbs.defineModel({
|
|
824
|
-
name: 'article',
|
|
825
|
-
properties: {
|
|
826
|
-
annotation: {
|
|
827
|
-
type: DataType.STRING,
|
|
828
|
-
transform: {
|
|
829
|
-
truncate: 200,
|
|
830
|
-
capitalize: {firstWordOnly: true},
|
|
831
|
-
},
|
|
832
|
-
},
|
|
833
|
-
},
|
|
834
|
-
});
|
|
835
|
-
```
|
|
836
|
-
|
|
837
|
-
Глобальные трансформеры без параметров могут принимать любые аргументы.
|
|
838
|
-
|
|
839
|
-
```js
|
|
840
|
-
dbs.defineModel({
|
|
841
|
-
name: 'user',
|
|
842
|
-
properties: {
|
|
843
|
-
firstName: {
|
|
844
|
-
type: DataType.STRING,
|
|
845
|
-
transform: {
|
|
846
|
-
cut: 60,
|
|
847
|
-
// так как трансформер "trim" не имеет параметров,
|
|
848
|
-
// его определение допускает передачу любого значения
|
|
849
|
-
// в качестве аргумента
|
|
850
|
-
trim: true,
|
|
851
|
-
},
|
|
852
|
-
},
|
|
853
|
-
},
|
|
854
|
-
});
|
|
855
|
-
```
|
|
856
|
-
|
|
857
|
-
### Регистрация глобальных трансформеров
|
|
858
|
-
|
|
859
|
-
Трансформером является функция, которая принимает значение свойства и возвращает
|
|
860
|
-
новое значение. Функция может быть как синхронной, так и асинхронной (возвращать
|
|
861
|
-
`Promise`).
|
|
862
|
-
|
|
863
|
-
Регистрация глобального трансформера выполняется методом `addTransformer`
|
|
864
|
-
сервиса `PropertyTransformerRegistry`, который принимает название трансформера
|
|
865
|
-
и саму функцию.
|
|
866
|
-
|
|
867
|
-
**Примеры**
|
|
868
|
-
|
|
869
|
-
Регистрация глобального трансформера для удаления HTML-тегов.
|
|
870
|
-
|
|
871
|
-
```js
|
|
872
|
-
import {PropertyTransformerRegistry} from '@e22m4u/js-repository';
|
|
873
|
-
|
|
874
|
-
// получение экземпляра сервиса
|
|
875
|
-
const ptr = dbs.getService(PropertyTransformerRegistry);
|
|
876
|
-
|
|
877
|
-
// регистрация глобального трансформера "stripTags"
|
|
878
|
-
ptr.addTransformer('stripTags', (value, options, context) => {
|
|
879
|
-
// value - трансформируемое значение;
|
|
880
|
-
// options - настройки трансформера (если переданы);
|
|
881
|
-
// context - информация о свойстве;
|
|
882
|
-
console.log(context);
|
|
883
|
-
// {
|
|
884
|
-
// transformerName: 'stripTags',
|
|
885
|
-
// modelName: 'comment',
|
|
886
|
-
// propName: 'text'
|
|
887
|
-
// }
|
|
888
|
-
|
|
889
|
-
if (typeof value !== 'string')
|
|
890
|
-
return value; // возвращаем как есть, если не строка
|
|
891
|
-
|
|
892
|
-
return value.replace(/<[^>]*>?/gm, '');
|
|
893
|
-
});
|
|
894
|
-
```
|
|
895
|
-
|
|
896
|
-
Использование глобального трансформера в определении модели.
|
|
897
|
-
|
|
898
|
-
```js
|
|
899
|
-
dbs.defineModel({
|
|
900
|
-
name: 'comment',
|
|
901
|
-
properties: {
|
|
902
|
-
text: {
|
|
903
|
-
type: DataType.STRING,
|
|
904
|
-
transform: 'stripTags',
|
|
905
|
-
},
|
|
906
|
-
},
|
|
907
|
-
});
|
|
908
|
-
```
|
|
909
|
-
|
|
910
|
-
### Локальные трансформеры
|
|
911
|
-
|
|
912
|
-
Функция-трансформер может быть передана непосредственно в определении свойства без предварительной регистрации. Для этого достаточно передать функцию в параметр `transform` в качестве значения или элемента массива.
|
|
913
|
-
|
|
914
|
-
**Примеры**
|
|
915
|
-
|
|
916
|
-
Использование локального трансформера для нормализации имен.
|
|
917
|
-
|
|
918
|
-
```js
|
|
919
|
-
// функция для нормализации имени
|
|
920
|
-
function normalizeName(value, options, context) {
|
|
921
|
-
// value - трансформируемое значение
|
|
922
|
-
// options - не используется
|
|
923
|
-
// context - информация о свойстве
|
|
924
|
-
if (!value || typeof value !== 'string') return value;
|
|
925
|
-
return value
|
|
926
|
-
.trim() // удаление пробелов в начале и конце
|
|
927
|
-
.toLowerCase() // перевод к нижнему регистру
|
|
928
|
-
.split(' ') // разделение на слова
|
|
929
|
-
// перевод к верхнему регистру первой буквы каждого слова
|
|
930
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
931
|
-
.join(' '); // сборка массива в строку
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
// определение модели "user"
|
|
935
|
-
dbs.defineModel({
|
|
936
|
-
name: 'user',
|
|
937
|
-
properties: {
|
|
938
|
-
firstName: {
|
|
939
|
-
type: DataType.STRING,
|
|
940
|
-
transform: normalizeName, // <=
|
|
941
|
-
},
|
|
942
|
-
lastName: {
|
|
943
|
-
type: DataType.STRING,
|
|
944
|
-
transform: normalizeName, // <=
|
|
945
|
-
},
|
|
946
|
-
},
|
|
947
|
-
});
|
|
948
|
-
```
|
|
949
|
-
|
|
950
|
-
Использование локального асинхронного трансформера для хэширования пароля.
|
|
951
|
-
|
|
952
|
-
```js
|
|
953
|
-
import * as bcrypt from 'bcrypt';
|
|
954
|
-
|
|
955
|
-
// асинхронная функция для хеширования значения
|
|
956
|
-
async function hash(value, options, context) {
|
|
957
|
-
// value - трансформируемое значение
|
|
958
|
-
// options - не используется
|
|
959
|
-
// context - информация о свойстве
|
|
960
|
-
console.log(context);
|
|
961
|
-
// {
|
|
962
|
-
// transformerName: 'hash',
|
|
963
|
-
// modelName: 'user',
|
|
964
|
-
// propName: 'password'
|
|
965
|
-
// }
|
|
966
|
-
const saltRounds = 10;
|
|
967
|
-
return bcrypt.hash(value, saltRounds);
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
// определение модели "user"
|
|
971
|
-
dbs.defineModel({
|
|
972
|
-
name: 'user',
|
|
973
|
-
properties: {
|
|
974
|
-
password: {
|
|
975
|
-
type: DataType.STRING,
|
|
976
|
-
transform: hash, // <=
|
|
977
|
-
// или
|
|
978
|
-
// transform: [hash, ...]
|
|
979
|
-
},
|
|
980
|
-
},
|
|
981
|
-
});
|
|
982
|
-
```
|
|
983
|
-
|
|
984
|
-
Использование анонимной функции-трансформера для коррекции слага.
|
|
985
|
-
|
|
986
|
-
```js
|
|
987
|
-
dbs.defineModel({
|
|
988
|
-
name: 'article',
|
|
989
|
-
properties: {
|
|
990
|
-
slug: {
|
|
991
|
-
type: DataType.STRING,
|
|
992
|
-
transform: (value) => {
|
|
993
|
-
if (typeof value !== 'string') return value;
|
|
994
|
-
return value.toLowerCase().replace(/\s+/g, '-');
|
|
995
|
-
},
|
|
996
|
-
},
|
|
997
|
-
},
|
|
998
|
-
});
|
|
999
|
-
```
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
495
|
## Пустые значения
|
|
1003
496
|
|
|
1004
497
|
Разные типы свойств имеют свои наборы пустых значений. Эти наборы используются
|
|
@@ -1029,26 +522,15 @@ dbs.defineModel({
|
|
|
1029
522
|
**EmptyValuesService**
|
|
1030
523
|
|
|
1031
524
|
Для переопределения пустых значений необходимо получить экземпляр класса
|
|
1032
|
-
`EmptyValuesService` из контейнера схемы и вызвать
|
|
1033
|
-
тип данных и массив новых значений.
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
* для определенного типа данных.
|
|
1042
|
-
*
|
|
1043
|
-
* @param dataType Тип данных.
|
|
1044
|
-
* @param emptyValues Массив новых пустых значений.
|
|
1045
|
-
*/
|
|
1046
|
-
setEmptyValuesOf(
|
|
1047
|
-
dataType: DataType,
|
|
1048
|
-
emptyValues: unknown[],
|
|
1049
|
-
): this;
|
|
1050
|
-
}
|
|
1051
|
-
```
|
|
525
|
+
`EmptyValuesService` из контейнера схемы и вызвать метод `setEmptyValuesOf`,
|
|
526
|
+
который принимает тип данных и массив новых значений.
|
|
527
|
+
|
|
528
|
+
Сигнатура:
|
|
529
|
+
|
|
530
|
+
- `setEmptyValuesOf(dataType, emptyValues)`
|
|
531
|
+
- `dataType: DataType`: строковый литерал типа;
|
|
532
|
+
- `emptyValues: *[]`: массив новых значений;
|
|
533
|
+
- результат: `this`;
|
|
1052
534
|
|
|
1053
535
|
**Пример**
|
|
1054
536
|
|
|
@@ -1071,8 +553,8 @@ emptyValuesService.setEmptyValuesOf(DataType.NUMBER, [undefined, null]);
|
|
|
1071
553
|
```
|
|
1072
554
|
|
|
1073
555
|
После этого, значение `0` для свойств типа `DataType.NUMBER` больше не будет
|
|
1074
|
-
считаться пустым и будет проходить
|
|
1075
|
-
заменяться значением по умолчанию.
|
|
556
|
+
считаться пустым и будет проходить проверку с опцией `required`, а также
|
|
557
|
+
не будет заменяться значением по умолчанию.
|
|
1076
558
|
|
|
1077
559
|
## Репозиторий
|
|
1078
560
|
|
|
@@ -1081,24 +563,24 @@ emptyValuesService.setEmptyValuesOf(DataType.NUMBER, [undefined, null]);
|
|
|
1081
563
|
|
|
1082
564
|
**Методы**
|
|
1083
565
|
|
|
1084
|
-
- [`create(data, filter
|
|
1085
|
-
- [`replaceById(id, data, filter
|
|
1086
|
-
- [`replaceOrCreate(data, filter
|
|
1087
|
-
- [`patchById(id, data, filter
|
|
1088
|
-
- [`patch(data, where
|
|
1089
|
-
- [`find(filter
|
|
1090
|
-
- [`findOne(filter
|
|
1091
|
-
- [`findById(id, filter
|
|
1092
|
-
- [`delete(where
|
|
566
|
+
- [`create(data, [filter])`](#repositorycreate) создать новый документ;
|
|
567
|
+
- [`replaceById(id, data, [filter])`](#repositoryreplacebyid) заменить документ полностью;
|
|
568
|
+
- [`replaceOrCreate(data, [filter])`](#repositoryreplaceorcreate) заменить или создать новый;
|
|
569
|
+
- [`patchById(id, data, [filter])`](#repositorypatchbyid) обновить документ частично;
|
|
570
|
+
- [`patch(data, [where])`](#repositorypatch) обновить все документы или по условию;
|
|
571
|
+
- [`find([filter])`](#repositoryfind) найти все документы или по условию;
|
|
572
|
+
- [`findOne([filter])`](#repositoryfindone) найти первый документ или по условию;
|
|
573
|
+
- [`findById(id, [filter])`](#repositoryfindbyid) найти документ по идентификатору;
|
|
574
|
+
- [`delete([where])`](#repositorydelete) удалить все документы или по условию;
|
|
1093
575
|
- [`deleteById(id)`](#repositorydeletebyid) удалить документ по идентификатору;
|
|
1094
576
|
- [`exists(id)`](#repositoryexists) проверить существование по идентификатору;
|
|
1095
|
-
- [`count(where
|
|
577
|
+
- [`count([where])`](#repositorycount) подсчет всех документов или по условию;
|
|
1096
578
|
|
|
1097
579
|
**Аргументы**
|
|
1098
580
|
|
|
1099
581
|
- `id: number|string` идентификатор (первичный ключ)
|
|
1100
582
|
- `data: object` данные документа (используется при записи)
|
|
1101
|
-
- `where: object` условия
|
|
583
|
+
- `where: object` условия выборки (см. [`where`](#where))
|
|
1102
584
|
- `filter: object` параметры выборки (см. [Фильтрация](#Фильтрация))
|
|
1103
585
|
|
|
1104
586
|
**Получение репозитория**
|
|
@@ -1138,12 +620,10 @@ const modelRep = dbs.getRepository('myModel');
|
|
|
1138
620
|
|
|
1139
621
|
Сигнатура:
|
|
1140
622
|
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
): Promise<FlatData>;
|
|
1146
|
-
```
|
|
623
|
+
- `create(data, [filter])`
|
|
624
|
+
- `data: object`: данные нового документа;
|
|
625
|
+
- `filter?: object`: настройки выборки (см. [Фильтрация](#фильтрация));
|
|
626
|
+
- результат: `Promise<object>`;
|
|
1147
627
|
|
|
1148
628
|
**Примеры**
|
|
1149
629
|
|
|
@@ -1204,13 +684,11 @@ console.log(product);
|
|
|
1204
684
|
|
|
1205
685
|
Сигнатура:
|
|
1206
686
|
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
): Promise<FlatData>;
|
|
1213
|
-
```
|
|
687
|
+
- `replaceById(id, data, [filter])`
|
|
688
|
+
- `id: number|string`: идентификатор документа;
|
|
689
|
+
- `data: object`: новые данные;
|
|
690
|
+
- `filter?: object`: настройки выборки (см. [Фильтрация](#фильтрация));
|
|
691
|
+
- результат: `Promise<object>`;
|
|
1214
692
|
|
|
1215
693
|
**Примеры**
|
|
1216
694
|
|
|
@@ -1246,12 +724,10 @@ console.log(updatedProduct);
|
|
|
1246
724
|
|
|
1247
725
|
Сигнатура:
|
|
1248
726
|
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
): Promise<FlatData>;
|
|
1254
|
-
```
|
|
727
|
+
- `replaceOrCreate(data, [filter])`
|
|
728
|
+
- `data: object`: данные документа;
|
|
729
|
+
- `filter?: object`: настройки выборки (см. [Фильтрация](#фильтрация));
|
|
730
|
+
- результат: `Promise<object>`;
|
|
1255
731
|
|
|
1256
732
|
**Примеры**
|
|
1257
733
|
|
|
@@ -1294,13 +770,11 @@ console.log(updatedProduct);
|
|
|
1294
770
|
|
|
1295
771
|
Сигнатура:
|
|
1296
772
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
): Promise<FlatData>;
|
|
1303
|
-
```
|
|
773
|
+
- `patchById(id, data, [filter])`
|
|
774
|
+
- `id: number|string`: идентификатор обновляемого документа;
|
|
775
|
+
- `data: object`: новые данные;
|
|
776
|
+
- `filter?: object`: настройки выборки (см. [Фильтрация](#фильтрация));
|
|
777
|
+
- результат: `Promise<object>`;
|
|
1304
778
|
|
|
1305
779
|
**Примеры**
|
|
1306
780
|
|
|
@@ -1334,12 +808,10 @@ console.log(updatedProduct);
|
|
|
1334
808
|
|
|
1335
809
|
Сигнатура:
|
|
1336
810
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
): Promise<number>;
|
|
1342
|
-
```
|
|
811
|
+
- `patch(data, [where])`
|
|
812
|
+
- `data: object`: новые данные;
|
|
813
|
+
- `where?: object`: условия выборки (см. [`where`](#where));
|
|
814
|
+
- результат: `Promise<number>`;
|
|
1343
815
|
|
|
1344
816
|
**Примеры**
|
|
1345
817
|
|
|
@@ -1369,9 +841,9 @@ const totalCount = await productRep.patch({
|
|
|
1369
841
|
|
|
1370
842
|
Сигнатура:
|
|
1371
843
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
844
|
+
- `find([filter])`
|
|
845
|
+
- `filter?: object`: настройки выборки (см. [Фильтрация](#фильтрация));
|
|
846
|
+
- результат: `Promise<object[]>`;
|
|
1375
847
|
|
|
1376
848
|
**Примеры**
|
|
1377
849
|
|
|
@@ -1405,11 +877,9 @@ const latestProducts = await productRep.find({
|
|
|
1405
877
|
|
|
1406
878
|
Сигнатура:
|
|
1407
879
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
): Promise<FlatData | undefined>;
|
|
1412
|
-
```
|
|
880
|
+
- `findOne([filter])`
|
|
881
|
+
- `filter?: object`: настройки выборки (см. [Фильтрация](#фильтрация));
|
|
882
|
+
- результат: `Promise<object|undefined>`;
|
|
1413
883
|
|
|
1414
884
|
**Примеры**
|
|
1415
885
|
|
|
@@ -1440,12 +910,10 @@ if (!product) {
|
|
|
1440
910
|
|
|
1441
911
|
Сигнатура:
|
|
1442
912
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
): Promise<FlatData>;
|
|
1448
|
-
```
|
|
913
|
+
- `findById(id, [filter])`
|
|
914
|
+
- `id: number|string`: идентификатор документа;
|
|
915
|
+
- `filter?: object`: настройки выборки (см. [Фильтрация](#фильтрация));
|
|
916
|
+
- результат: `Promise<object|undefined>`;
|
|
1449
917
|
|
|
1450
918
|
**Примеры**
|
|
1451
919
|
|
|
@@ -1476,9 +944,9 @@ const product = await productRep.findById(1, {
|
|
|
1476
944
|
|
|
1477
945
|
Сигнатура:
|
|
1478
946
|
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
947
|
+
- `delete([where])`
|
|
948
|
+
- `where?: object`: условия выборки (см. [`where`](#where));
|
|
949
|
+
- результат: `Promise<number>`;
|
|
1482
950
|
|
|
1483
951
|
**Примеры**
|
|
1484
952
|
|
|
@@ -1503,9 +971,15 @@ const totalCount = await productRep.delete();
|
|
|
1503
971
|
|
|
1504
972
|
Сигнатура:
|
|
1505
973
|
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
974
|
+
- `deleteById(id)`
|
|
975
|
+
- `id: number|string`: идентификатор документа;
|
|
976
|
+
- результат: `Promise<boolean>`;
|
|
977
|
+
|
|
978
|
+
Результат:
|
|
979
|
+
|
|
980
|
+
- `Promise<boolean>`: логическое значение;
|
|
981
|
+
- `true`: документ был найден и удален;
|
|
982
|
+
- `false`: документ не найден;
|
|
1509
983
|
|
|
1510
984
|
**Примеры**
|
|
1511
985
|
|
|
@@ -1527,9 +1001,15 @@ if (wasDeleted) {
|
|
|
1527
1001
|
|
|
1528
1002
|
Сигнатура:
|
|
1529
1003
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1004
|
+
- `exists(id)`
|
|
1005
|
+
- `id: number|string`: идентификатор документа;
|
|
1006
|
+
- результат: `Promise<boolean>`;
|
|
1007
|
+
|
|
1008
|
+
Результат:
|
|
1009
|
+
|
|
1010
|
+
- `Promise<boolean>`: логическое значение;
|
|
1011
|
+
- `true`: документ с таким идентификатором найден;
|
|
1012
|
+
- `false`: идентификатор не найден;
|
|
1533
1013
|
|
|
1534
1014
|
**Примеры**
|
|
1535
1015
|
|
|
@@ -1549,9 +1029,9 @@ if (productExists) {
|
|
|
1549
1029
|
|
|
1550
1030
|
Сигнатура:
|
|
1551
1031
|
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1032
|
+
- `count([where])`
|
|
1033
|
+
- `where?: object`: условия выборки (см. [`where`](#where));
|
|
1034
|
+
- результат: `Promise<number>`;
|
|
1555
1035
|
|
|
1556
1036
|
**Примеры**
|
|
1557
1037
|
|
|
@@ -1571,10 +1051,10 @@ const totalCount = await productRep.count();
|
|
|
1571
1051
|
|
|
1572
1052
|
## Фильтрация
|
|
1573
1053
|
|
|
1574
|
-
Некоторые методы репозитория принимают объект настроек
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1054
|
+
Некоторые методы репозитория принимают объект настроек возвращаемого
|
|
1055
|
+
результата. Максимально широкий набор таких настроек имеет первый
|
|
1056
|
+
параметр метода `find`, где ожидается объект, содержащий набор
|
|
1057
|
+
опций указанных ниже.
|
|
1578
1058
|
|
|
1579
1059
|
- `where: object` условия фильтрации по свойствам документа;
|
|
1580
1060
|
- `order: string|string[]` сортировка по указанным свойствам;
|
|
@@ -2443,7 +1923,7 @@ dbs.defineModel({
|
|
|
2443
1923
|
|
|
2444
1924
|
#### Has One (полиморфная версия)
|
|
2445
1925
|
|
|
2446
|
-
Обратная сторона
|
|
1926
|
+
Обратная сторона полиморфной связи `belongsTo` по принципу *"один к одному"*.
|
|
2447
1927
|
|
|
2448
1928
|
```
|
|
2449
1929
|
Текущая (company) <───────┐ Целевая (license)
|
|
@@ -2510,7 +1990,7 @@ dbs.defineModel({
|
|
|
2510
1990
|
|
|
2511
1991
|
#### Has Many (полиморфная версия)
|
|
2512
1992
|
|
|
2513
|
-
Обратная сторона
|
|
1993
|
+
Обратная сторона полиморфной связи `belongsTo` по принципу *"один ко многим"*.
|
|
2514
1994
|
|
|
2515
1995
|
```
|
|
2516
1996
|
Текущая (letter) <─────────┐ Целевая (file)
|
|
@@ -2623,56 +2103,9 @@ const rep = dbs.getRepository('model');
|
|
|
2623
2103
|
console.log(rep instanceof MyRepository); // true
|
|
2624
2104
|
```
|
|
2625
2105
|
|
|
2626
|
-
*i. Так как экземпляры репозитория
|
|
2106
|
+
*i. Так как экземпляры репозитория кэшируются, то замену конструктора
|
|
2627
2107
|
следует выполнять до обращения к методу `getRepository`.*
|
|
2628
2108
|
|
|
2629
|
-
## TypeScript
|
|
2630
|
-
|
|
2631
|
-
Получение типизированного репозитория с указанием интерфейса модели.
|
|
2632
|
-
|
|
2633
|
-
```ts
|
|
2634
|
-
import {DataType} from '@e22m4u/js-repository';
|
|
2635
|
-
import {RelationType} from '@e22m4u/js-repository';
|
|
2636
|
-
import {DatabaseSchema} from '@e22m4u/js-repository';
|
|
2637
|
-
|
|
2638
|
-
// const dbs = new DatabaseSchema();
|
|
2639
|
-
// dbs.defineDatasource ...
|
|
2640
|
-
|
|
2641
|
-
// определение модели "city"
|
|
2642
|
-
dbs.defineModel({
|
|
2643
|
-
name: 'city',
|
|
2644
|
-
datasource: 'myDatasource',
|
|
2645
|
-
properties: {
|
|
2646
|
-
name: DataType.STRING,
|
|
2647
|
-
timeZone: DataType.STRING,
|
|
2648
|
-
},
|
|
2649
|
-
});
|
|
2650
|
-
|
|
2651
|
-
// определение интерфейса "city"
|
|
2652
|
-
interface City {
|
|
2653
|
-
id: number;
|
|
2654
|
-
name?: string;
|
|
2655
|
-
timeZone?: string;
|
|
2656
|
-
}
|
|
2657
|
-
|
|
2658
|
-
// при получении репозитория нужной модели
|
|
2659
|
-
// можно указать тип документов
|
|
2660
|
-
const cityRep = dbs.getRepository<City>('city');
|
|
2661
|
-
|
|
2662
|
-
// теперь, методы репозитория возвращают
|
|
2663
|
-
// тип City вместо Record<string, unknown>
|
|
2664
|
-
const city: City = await cityRep.create({
|
|
2665
|
-
name: 'Moscow',
|
|
2666
|
-
timeZone: 'Europe/Moscow',
|
|
2667
|
-
});
|
|
2668
|
-
```
|
|
2669
|
-
|
|
2670
|
-
Для определения моделей с помощью TypeScript классов,
|
|
2671
|
-
рекомендуется использовать специальную версию данного модуля
|
|
2672
|
-
[@e22m4u/ts-repository](https://www.npmjs.com/package/@e22m4u/ts-repository),
|
|
2673
|
-
поставляемую с набором TypeScript декораторов и дополнительных
|
|
2674
|
-
инструментов для работы в TypeScript окружении.
|
|
2675
|
-
|
|
2676
2109
|
## Тесты
|
|
2677
2110
|
|
|
2678
2111
|
```bash
|