@e22m4u/js-repository 0.8.8 → 0.8.10

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 CHANGED
@@ -3,18 +3,21 @@
3
3
  ![npm version](https://badge.fury.io/js/@e22m4u%2Fjs-repository.svg)
4
4
  ![license](https://img.shields.io/badge/license-mit-blue.svg)
5
5
 
6
- Реализация паттерна «Репозиторий» для работы с базами данных.
6
+ ORM/ODM библиотека для Node.js, реализующая слой управления данными на основе
7
+ паттерна «Репозиторий». Унифицирует интерфейс различных баз данных, фильтрацию
8
+ и работу со связанными документами независимо от источника.
7
9
 
8
10
  ## Содержание
9
11
 
10
12
  - [Установка](#установка)
11
13
  - [Импорт](#импорт)
12
14
  - [Описание](#описание)
13
- - [Пример](#пример)
15
+ - [Терминология](#терминология)
16
+ - [Базовый пример](#пример)
14
17
  - [Схема баз данных](#схема-баз-данных)
15
18
  - [Источник данных](#источник-данных)
16
19
  - [Модель](#модель)
17
- - [Свойства](#свойства)
20
+ - [Свойства](#свойства)
18
21
  - [Репозиторий](#репозиторий)
19
22
  - [create](#repositorycreate)
20
23
  - [replaceById](#repositoryreplacebyid)
@@ -50,10 +53,15 @@ npm install @e22m4u/js-repository
50
53
 
51
54
  Опционально устанавливается нужный адаптер.
52
55
 
53
- | адаптер | описание | установка |
54
- |-----------|-------------------------------------------------|----------------------------------------------------------------------------|
55
- | `memory` | Виртуальная база в памяти процесса | *встроенный* |
56
- | `mongodb` | MongoDB - документо-ориентированная база данных | [npm](https://www.npmjs.com/package/@e22m4u/js-repository-mongodb-adapter) |
56
+ | адаптер | описание | |
57
+ |-----------|---------------------------------------------------|------------------------------------------------------------------------------------|
58
+ | `memory` | Виртуальная база данных в памяти процесса Node.js | *встроенный* |
59
+ | `mongodb` | MongoDB - документо-ориентированная база данных | [*установка*](https://www.npmjs.com/package/@e22m4u/js-repository-mongodb-adapter) |
60
+
61
+ **Утилиты**
62
+
63
+ - [@e22m4u/js-repository-json-schema](https://www.npmjs.com/package/@e22m4u/js-repository-json-schema)
64
+ *Генератор JSON Schema для моделей репозитория*
57
65
 
58
66
  ## Импорт
59
67
 
@@ -122,11 +130,49 @@ flowchart TD
122
130
  G-->K
123
131
  ```
124
132
 
133
+ ### Терминология
134
+
135
+ Описание ключевых понятий.
136
+
137
+ - **Схема баз данных** (*DatabaseSchema*) - хранит определения источников
138
+ данных и моделей. Связывает модели с источниками данных и предоставляет
139
+ доступ к экземплярам репозитория.
140
+
141
+ - **Источник данных** (*Datasource*) - именованная конфигурация подключения
142
+ к базе данных. Содержит название используемого адаптера и параметры соединения.
143
+
144
+ - **Адаптер** (*Adapter*) - низкоуровневая реализация для взаимодействия с
145
+ конкретной СУБД. Обеспечивает совместимость хранилища с унифицированным
146
+ интерфейсом репозитория.
147
+
148
+ - **Коллекция** (*Collection*) - физическая область хранения записей или
149
+ документов в базе данных, ассоциированная с конкретной моделью. В контексте
150
+ реляционных баз данных является эквивалентом таблицы.
151
+
152
+ - **Модель** (*Model*) - структурное описание коллекции базы данных. Содержит
153
+ определения свойств документа и отношений с другими моделями.
154
+
155
+ - **Свойство** (*Property*) - описание отдельного поля модели. Определяет тип
156
+ данных, значение по умолчанию, обязательность наличия и правила проверки
157
+ на уникальность.
158
+
159
+ - **Связь** (*Relation*) - абстракция отношений между моделями. Поддерживает
160
+ классические отношения и полиморфный режим динамического определения
161
+ целевой модели через поле дискриминатора.
162
+
163
+ - **Дискриминатор** (*Discriminator*) - свойство документа в рамках полиморфной
164
+ связи. Хранит строковое название целевой модели, что позволяет динамически
165
+ определять связанную коллекцию при выполнении запросов.
166
+
167
+ - **Репозиторий** (*Repository*) - абстрактный фасад для работы с данными
168
+ конкретной модели. Изолирует логику приложения от деталей реализации
169
+ базы данных. Выполняет операции записи, поиска, обновления и удаления.
170
+
125
171
  ## Пример
126
172
 
127
- Пример демонстрирует создание экземпляра схемы, объявление источника данных
128
- и модели `country`. После чего, с помощью репозитория данной модели, в коллекцию
129
- добавляется новый документ (страна), который выводится в консоль.
173
+ Пример демонстрирует создание экземпляра `DatabaseSchema`, объявление источника
174
+ данных `myDb` и модели `country`. Далее в коллекцию добавляется новый документ,
175
+ содержимого которого выводится в консоль.
130
176
 
131
177
  ```
132
178
  Страна (country)
@@ -351,8 +397,8 @@ dbs.defineDatasource({
351
397
  - `base: string` название наследуемой модели;
352
398
  - `tableName: string` название коллекции в базе;
353
399
  - `datasource: string` выбранный источник данных;
354
- - `properties: object` определения свойств (см. [Свойства](#Свойства));
355
- - `relations: object` определения связей (см. [Связи](#Связи));
400
+ - `properties: object` определения свойств (см. [Свойства](#свойства));
401
+ - `relations: object` определения связей (см. [Связи](#связи));
356
402
 
357
403
  **Примеры**
358
404
 
@@ -368,13 +414,32 @@ dbs.defineModel({
368
414
  });
369
415
  ```
370
416
 
371
- ## Свойства
417
+ ### Свойства
372
418
 
373
419
  Параметр `properties` находится в определении модели и принимает объект, ключи
374
420
  которого являются свойствами этой модели, а значением тип свойства или объект
375
- с дополнительными параметрами.
421
+ с дополнительными параметрами. Параметры свойства используется репозиторием
422
+ для проверки документов перед сохранением.
376
423
 
377
- **Тип данных**
424
+ ```js
425
+ dbs.defineModel({
426
+ name: 'user',
427
+ properties: {
428
+ // краткая форма (только тип)
429
+ name: DataType.STRING,
430
+ // расширенное определение (см. далее)
431
+ email: {
432
+ type: DataType.STRING,
433
+ unique: PropertyUniqueness.SPARSE,
434
+ default: '',
435
+ },
436
+ },
437
+ });
438
+ ```
439
+
440
+ *i. В контексте реляционных баз данных свойства отражают колонки таблицы.*
441
+
442
+ **Типы данных**
378
443
 
379
444
  - `DataType.ANY` разрешено любое значение;
380
445
  - `DataType.STRING` только значение типа `string`;
@@ -383,7 +448,12 @@ dbs.defineModel({
383
448
  - `DataType.ARRAY` только значение типа `array`;
384
449
  - `DataType.OBJECT` только значение типа `object`;
385
450
 
386
- **Параметры**
451
+ **Параметры свойства**
452
+
453
+ Объект с параметрами (расширенное определение) позволяет задавать значения
454
+ по умолчанию, правила проверки на уникальность и обязательность наличия данных.
455
+ Для массивов и вложенных объектов предусмотрено указание типа элемента
456
+ и название модели.
387
457
 
388
458
  - `type: string` тип допустимого значения (обязательно);
389
459
  - `itemType?: string` тип элемента массива (для `type: 'array'`);
@@ -9,8 +9,13 @@ var __glob = (map) => (path) => {
9
9
  if (fn) return fn();
10
10
  throw new Error("Module not found in bundle: " + path);
11
11
  };
12
- var __esm = (fn, res) => function __init() {
13
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ var __esm = (fn, res, err) => function __init() {
13
+ if (err) throw err[0];
14
+ try {
15
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
16
+ } catch (e) {
17
+ throw err = [e], e;
18
+ }
14
19
  };
15
20
  var __export = (target, all) => {
16
21
  for (var name in all)
@@ -419,24 +424,6 @@ var init_exclude_object_keys = __esm({
419
424
  }
420
425
  });
421
426
 
422
- // src/utils/model-name-to-model-key.js
423
- function modelNameToModelKey(modelName) {
424
- if (!modelName || typeof modelName !== "string" || /\s/.test(modelName)) {
425
- throw new InvalidArgumentError(
426
- "Model name must be a non-empty String without spaces, but %v was given.",
427
- modelName
428
- );
429
- }
430
- return modelName.toLowerCase().replace(/[-_]/g, "");
431
- }
432
- var init_model_name_to_model_key = __esm({
433
- "src/utils/model-name-to-model-key.js"() {
434
- "use strict";
435
- init_errors();
436
- __name(modelNameToModelKey, "modelNameToModelKey");
437
- }
438
- });
439
-
440
427
  // src/utils/index.js
441
428
  var init_utils = __esm({
442
429
  "src/utils/index.js"() {
@@ -452,7 +439,6 @@ var init_utils = __esm({
452
439
  init_get_value_by_path();
453
440
  init_select_object_keys();
454
441
  init_exclude_object_keys();
455
- init_model_name_to_model_key();
456
442
  }
457
443
  });
458
444
 
@@ -1833,17 +1819,65 @@ var init_property_uniqueness = __esm({
1833
1819
  }
1834
1820
  });
1835
1821
 
1822
+ // src/definition/datasource/datasource-definition-validator.js
1823
+ var import_js_service6, DatasourceDefinitionValidator;
1824
+ var init_datasource_definition_validator = __esm({
1825
+ "src/definition/datasource/datasource-definition-validator.js"() {
1826
+ "use strict";
1827
+ import_js_service6 = require("@e22m4u/js-service");
1828
+ init_errors();
1829
+ DatasourceDefinitionValidator = class extends import_js_service6.Service {
1830
+ static {
1831
+ __name(this, "DatasourceDefinitionValidator");
1832
+ }
1833
+ /**
1834
+ * Validate.
1835
+ *
1836
+ * @param {object} datasourceDef
1837
+ */
1838
+ validate(datasourceDef) {
1839
+ if (!datasourceDef || typeof datasourceDef !== "object") {
1840
+ throw new InvalidArgumentError(
1841
+ "Datasource definition must be an Object, but %v was given.",
1842
+ datasourceDef
1843
+ );
1844
+ }
1845
+ if (!datasourceDef.name || typeof datasourceDef.name !== "string") {
1846
+ throw new InvalidArgumentError(
1847
+ 'Datasource definition requires the option "name" as a non-empty String, but %v was given.',
1848
+ datasourceDef.name
1849
+ );
1850
+ }
1851
+ if (!datasourceDef.adapter || typeof datasourceDef.adapter !== "string") {
1852
+ throw new InvalidArgumentError(
1853
+ 'Datasource %v requires the option "adapter" as a non-empty String, but %v was given.',
1854
+ datasourceDef.name,
1855
+ datasourceDef.adapter
1856
+ );
1857
+ }
1858
+ }
1859
+ };
1860
+ }
1861
+ });
1862
+
1863
+ // src/definition/datasource/index.js
1864
+ var init_datasource = __esm({
1865
+ "src/definition/datasource/index.js"() {
1866
+ "use strict";
1867
+ init_datasource_definition_validator();
1868
+ }
1869
+ });
1870
+
1836
1871
  // src/definition/definition-registry.js
1837
- var import_js_service6, DefinitionRegistry;
1872
+ var import_js_service7, DefinitionRegistry;
1838
1873
  var init_definition_registry = __esm({
1839
1874
  "src/definition/definition-registry.js"() {
1840
1875
  "use strict";
1841
- import_js_service6 = require("@e22m4u/js-service");
1842
- init_utils();
1876
+ import_js_service7 = require("@e22m4u/js-service");
1843
1877
  init_errors();
1844
1878
  init_model();
1845
- init_definition();
1846
- DefinitionRegistry = class extends import_js_service6.Service {
1879
+ init_datasource();
1880
+ DefinitionRegistry = class extends import_js_service7.Service {
1847
1881
  static {
1848
1882
  __name(this, "DefinitionRegistry");
1849
1883
  }
@@ -1894,6 +1928,14 @@ var init_definition_registry = __esm({
1894
1928
  }
1895
1929
  return datasourceDef;
1896
1930
  }
1931
+ /**
1932
+ * Get datasource names.
1933
+ *
1934
+ * @returns {string[]}
1935
+ */
1936
+ getDatasourceNames() {
1937
+ return Object.keys(this._datasources);
1938
+ }
1897
1939
  /**
1898
1940
  * Add model.
1899
1941
  *
@@ -1901,14 +1943,11 @@ var init_definition_registry = __esm({
1901
1943
  */
1902
1944
  addModel(modelDef) {
1903
1945
  this.getService(ModelDefinitionValidator).validate(modelDef);
1904
- const modelKey = modelNameToModelKey(modelDef.name);
1905
- if (modelKey in this._models) {
1906
- throw new InvalidArgumentError(
1907
- "Model %v is already defined.",
1908
- modelDef.name
1909
- );
1946
+ const name = modelDef.name;
1947
+ if (name in this._models) {
1948
+ throw new InvalidArgumentError("Model %v is already defined.", name);
1910
1949
  }
1911
- this._models[modelKey] = modelDef;
1950
+ this._models[name] = modelDef;
1912
1951
  }
1913
1952
  /**
1914
1953
  * Has model.
@@ -1917,8 +1956,7 @@ var init_definition_registry = __esm({
1917
1956
  * @returns {boolean}
1918
1957
  */
1919
1958
  hasModel(name) {
1920
- const modelKey = modelNameToModelKey(name);
1921
- return Boolean(this._models[modelKey]);
1959
+ return Boolean(this._models[name]);
1922
1960
  }
1923
1961
  /**
1924
1962
  * Get model.
@@ -1927,29 +1965,36 @@ var init_definition_registry = __esm({
1927
1965
  * @returns {object}
1928
1966
  */
1929
1967
  getModel(name) {
1930
- const modelKey = modelNameToModelKey(name);
1931
- const modelDef = this._models[modelKey];
1968
+ const modelDef = this._models[name];
1932
1969
  if (!modelDef) {
1933
1970
  throw new InvalidArgumentError("Model %v is not defined.", name);
1934
1971
  }
1935
1972
  return modelDef;
1936
1973
  }
1974
+ /**
1975
+ * Get model names.
1976
+ *
1977
+ * @returns {string[]}
1978
+ */
1979
+ getModelNames() {
1980
+ return Object.keys(this._models);
1981
+ }
1937
1982
  };
1938
1983
  }
1939
1984
  });
1940
1985
 
1941
1986
  // src/definition/model/model-definition-utils.js
1942
- var import_js_service7, DEFAULT_PRIMARY_KEY_PROPERTY_NAME, ModelDefinitionUtils;
1987
+ var import_js_service8, DEFAULT_PRIMARY_KEY_PROPERTY_NAME, ModelDefinitionUtils;
1943
1988
  var init_model_definition_utils = __esm({
1944
1989
  "src/definition/model/model-definition-utils.js"() {
1945
1990
  "use strict";
1946
- import_js_service7 = require("@e22m4u/js-service");
1991
+ import_js_service8 = require("@e22m4u/js-service");
1947
1992
  init_properties();
1948
1993
  init_errors();
1949
1994
  init_definition_registry();
1950
1995
  init_utils();
1951
1996
  DEFAULT_PRIMARY_KEY_PROPERTY_NAME = "id";
1952
- ModelDefinitionUtils = class extends import_js_service7.Service {
1997
+ ModelDefinitionUtils = class extends import_js_service8.Service {
1953
1998
  static {
1954
1999
  __name(this, "ModelDefinitionUtils");
1955
2000
  }
@@ -2383,15 +2428,15 @@ var init_model_definition_utils = __esm({
2383
2428
  });
2384
2429
 
2385
2430
  // src/definition/model/properties/required-property-validator.js
2386
- var import_js_service8, RequiredPropertyValidator;
2431
+ var import_js_service9, RequiredPropertyValidator;
2387
2432
  var init_required_property_validator = __esm({
2388
2433
  "src/definition/model/properties/required-property-validator.js"() {
2389
2434
  "use strict";
2390
2435
  init_data_type();
2391
- import_js_service8 = require("@e22m4u/js-service");
2436
+ import_js_service9 = require("@e22m4u/js-service");
2392
2437
  init_errors();
2393
2438
  init_model_definition_utils();
2394
- RequiredPropertyValidator = class extends import_js_service8.Service {
2439
+ RequiredPropertyValidator = class extends import_js_service9.Service {
2395
2440
  static {
2396
2441
  __name(this, "RequiredPropertyValidator");
2397
2442
  }
@@ -2456,16 +2501,16 @@ var init_required_property_validator = __esm({
2456
2501
  });
2457
2502
 
2458
2503
  // src/definition/model/properties/property-uniqueness-validator.js
2459
- var import_js_service9, PropertyUniquenessValidator;
2504
+ var import_js_service10, PropertyUniquenessValidator;
2460
2505
  var init_property_uniqueness_validator = __esm({
2461
2506
  "src/definition/model/properties/property-uniqueness-validator.js"() {
2462
2507
  "use strict";
2463
- import_js_service9 = require("@e22m4u/js-service");
2508
+ import_js_service10 = require("@e22m4u/js-service");
2464
2509
  init_utils();
2465
2510
  init_property_uniqueness();
2466
2511
  init_errors();
2467
2512
  init_model_definition_utils();
2468
- PropertyUniquenessValidator = class extends import_js_service9.Service {
2513
+ PropertyUniquenessValidator = class extends import_js_service10.Service {
2469
2514
  static {
2470
2515
  __name(this, "PropertyUniquenessValidator");
2471
2516
  }
@@ -2588,14 +2633,14 @@ var init_property_uniqueness_validator = __esm({
2588
2633
  });
2589
2634
 
2590
2635
  // src/definition/model/properties/primary-keys-definition-validator.js
2591
- var import_js_service10, PrimaryKeysDefinitionValidator;
2636
+ var import_js_service11, PrimaryKeysDefinitionValidator;
2592
2637
  var init_primary_keys_definition_validator = __esm({
2593
2638
  "src/definition/model/properties/primary-keys-definition-validator.js"() {
2594
2639
  "use strict";
2595
- import_js_service10 = require("@e22m4u/js-service");
2640
+ import_js_service11 = require("@e22m4u/js-service");
2596
2641
  init_errors();
2597
2642
  init_model_definition_utils();
2598
- PrimaryKeysDefinitionValidator = class extends import_js_service10.Service {
2643
+ PrimaryKeysDefinitionValidator = class extends import_js_service11.Service {
2599
2644
  static {
2600
2645
  __name(this, "PrimaryKeysDefinitionValidator");
2601
2646
  }
@@ -2643,17 +2688,17 @@ var init_primary_keys_definition_validator = __esm({
2643
2688
  });
2644
2689
 
2645
2690
  // src/definition/model/properties/properties-definition-validator.js
2646
- var import_js_service11, PropertiesDefinitionValidator;
2691
+ var import_js_service12, PropertiesDefinitionValidator;
2647
2692
  var init_properties_definition_validator = __esm({
2648
2693
  "src/definition/model/properties/properties-definition-validator.js"() {
2649
2694
  "use strict";
2650
- import_js_service11 = require("@e22m4u/js-service");
2695
+ import_js_service12 = require("@e22m4u/js-service");
2651
2696
  init_data_type();
2652
2697
  init_utils();
2653
2698
  init_property_uniqueness();
2654
2699
  init_errors();
2655
2700
  init_primary_keys_definition_validator();
2656
- PropertiesDefinitionValidator = class extends import_js_service11.Service {
2701
+ PropertiesDefinitionValidator = class extends import_js_service12.Service {
2657
2702
  static {
2658
2703
  __name(this, "PropertiesDefinitionValidator");
2659
2704
  }
@@ -2908,14 +2953,14 @@ var init_model_definition = __esm({
2908
2953
  });
2909
2954
 
2910
2955
  // src/definition/model/model-data-sanitizer.js
2911
- var import_js_service12, ModelDataSanitizer;
2956
+ var import_js_service13, ModelDataSanitizer;
2912
2957
  var init_model_data_sanitizer = __esm({
2913
2958
  "src/definition/model/model-data-sanitizer.js"() {
2914
2959
  "use strict";
2915
- import_js_service12 = require("@e22m4u/js-service");
2960
+ import_js_service13 = require("@e22m4u/js-service");
2916
2961
  init_errors();
2917
2962
  init_model_definition_utils();
2918
- ModelDataSanitizer = class extends import_js_service12.Service {
2963
+ ModelDataSanitizer = class extends import_js_service13.Service {
2919
2964
  static {
2920
2965
  __name(this, "ModelDataSanitizer");
2921
2966
  }
@@ -2948,15 +2993,15 @@ var init_model_data_sanitizer = __esm({
2948
2993
  });
2949
2994
 
2950
2995
  // src/definition/model/model-definition-validator.js
2951
- var import_js_service13, ModelDefinitionValidator;
2996
+ var import_js_service14, ModelDefinitionValidator;
2952
2997
  var init_model_definition_validator = __esm({
2953
2998
  "src/definition/model/model-definition-validator.js"() {
2954
2999
  "use strict";
2955
- import_js_service13 = require("@e22m4u/js-service");
3000
+ import_js_service14 = require("@e22m4u/js-service");
2956
3001
  init_errors();
2957
3002
  init_relations();
2958
3003
  init_properties();
2959
- ModelDefinitionValidator = class extends import_js_service13.Service {
3004
+ ModelDefinitionValidator = class extends import_js_service14.Service {
2960
3005
  static {
2961
3006
  __name(this, "ModelDefinitionValidator");
2962
3007
  }
@@ -3043,55 +3088,6 @@ var init_model = __esm({
3043
3088
  }
3044
3089
  });
3045
3090
 
3046
- // src/definition/datasource/datasource-definition-validator.js
3047
- var import_js_service14, DatasourceDefinitionValidator;
3048
- var init_datasource_definition_validator = __esm({
3049
- "src/definition/datasource/datasource-definition-validator.js"() {
3050
- "use strict";
3051
- import_js_service14 = require("@e22m4u/js-service");
3052
- init_errors();
3053
- DatasourceDefinitionValidator = class extends import_js_service14.Service {
3054
- static {
3055
- __name(this, "DatasourceDefinitionValidator");
3056
- }
3057
- /**
3058
- * Validate.
3059
- *
3060
- * @param {object} datasourceDef
3061
- */
3062
- validate(datasourceDef) {
3063
- if (!datasourceDef || typeof datasourceDef !== "object") {
3064
- throw new InvalidArgumentError(
3065
- "Datasource definition must be an Object, but %v was given.",
3066
- datasourceDef
3067
- );
3068
- }
3069
- if (!datasourceDef.name || typeof datasourceDef.name !== "string") {
3070
- throw new InvalidArgumentError(
3071
- 'Datasource definition requires the option "name" as a non-empty String, but %v was given.',
3072
- datasourceDef.name
3073
- );
3074
- }
3075
- if (!datasourceDef.adapter || typeof datasourceDef.adapter !== "string") {
3076
- throw new InvalidArgumentError(
3077
- 'Datasource %v requires the option "adapter" as a non-empty String, but %v was given.',
3078
- datasourceDef.name,
3079
- datasourceDef.adapter
3080
- );
3081
- }
3082
- }
3083
- };
3084
- }
3085
- });
3086
-
3087
- // src/definition/datasource/index.js
3088
- var init_datasource = __esm({
3089
- "src/definition/datasource/index.js"() {
3090
- "use strict";
3091
- init_datasource_definition_validator();
3092
- }
3093
- });
3094
-
3095
3091
  // src/definition/index.js
3096
3092
  var init_definition = __esm({
3097
3093
  "src/definition/index.js"() {
@@ -4664,7 +4660,6 @@ var init_repository_registry = __esm({
4664
4660
  "use strict";
4665
4661
  import_js_service26 = require("@e22m4u/js-service");
4666
4662
  init_repository();
4667
- init_utils();
4668
4663
  init_errors();
4669
4664
  RepositoryRegistry = class extends import_js_service26.Service {
4670
4665
  static {
@@ -4704,13 +4699,12 @@ var init_repository_registry = __esm({
4704
4699
  * @returns {Repository}
4705
4700
  */
4706
4701
  getRepository(modelName) {
4707
- const modelKey = modelNameToModelKey(modelName);
4708
- let repository = this._repositories[modelKey];
4702
+ let repository = this._repositories[modelName];
4709
4703
  if (repository) {
4710
4704
  return repository;
4711
4705
  }
4712
4706
  repository = new this._repositoryCtor(this.container, modelName);
4713
- this._repositories[modelKey] = repository;
4707
+ this._repositories[modelName] = repository;
4714
4708
  return repository;
4715
4709
  }
4716
4710
  };
@@ -6073,7 +6067,6 @@ __export(index_exports, {
6073
6067
  isPlainObject: () => isPlainObject,
6074
6068
  isPromise: () => isPromise,
6075
6069
  likeToRegexp: () => likeToRegexp,
6076
- modelNameToModelKey: () => modelNameToModelKey,
6077
6070
  selectObjectKeys: () => selectObjectKeys,
6078
6071
  singularize: () => singularize,
6079
6072
  stringToRegexp: () => stringToRegexp
@@ -6171,7 +6164,6 @@ init_repository2();
6171
6164
  isPlainObject,
6172
6165
  isPromise,
6173
6166
  likeToRegexp,
6174
- modelNameToModelKey,
6175
6167
  selectObjectKeys,
6176
6168
  singularize,
6177
6169
  stringToRegexp
package/eslint.config.js CHANGED
@@ -2,7 +2,6 @@ import globals from 'globals';
2
2
  import eslintJs from '@eslint/js';
3
3
  import eslintJsdocPlugin from 'eslint-plugin-jsdoc';
4
4
  import eslintMochaPlugin from 'eslint-plugin-mocha';
5
- import eslintImportPlugin from 'eslint-plugin-import';
6
5
  import eslintPrettierConfig from 'eslint-config-prettier';
7
6
  import eslintChaiExpectPlugin from 'eslint-plugin-chai-expect';
8
7
 
@@ -18,19 +17,16 @@ export default [{
18
17
  plugins: {
19
18
  'jsdoc': eslintJsdocPlugin,
20
19
  'mocha': eslintMochaPlugin,
21
- 'import': eslintImportPlugin,
22
20
  'chai-expect': eslintChaiExpectPlugin,
23
21
  },
24
22
  rules: {
25
23
  ...eslintJs.configs.recommended.rules,
26
24
  ...eslintPrettierConfig.rules,
27
- ...eslintImportPlugin.flatConfigs.recommended.rules,
28
25
  ...eslintMochaPlugin.configs.recommended.rules,
29
26
  ...eslintChaiExpectPlugin.configs['recommended-flat'].rules,
30
27
  ...eslintJsdocPlugin.configs['flat/recommended-error'].rules,
31
28
  'curly': 'error',
32
29
  'no-duplicate-imports': 'error',
33
- 'import/export': 0,
34
30
  'jsdoc/reject-any-type': 0,
35
31
  'jsdoc/reject-function-type': 0,
36
32
  'jsdoc/require-param-description': 0,
package/package.json CHANGED
@@ -1,21 +1,22 @@
1
1
  {
2
2
  "name": "@e22m4u/js-repository",
3
- "version": "0.8.8",
4
- "description": "Реализация репозитория для работы с базами данных",
3
+ "version": "0.8.10",
4
+ "description": "ORM/ODM библиотека для работы с базами данных",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
7
7
  "keywords": [
8
- "Repository",
9
- "ORM",
10
- "ODM",
11
- "Database",
12
- "Datasource",
13
- "Relations"
8
+ "js-repository",
9
+ "orm",
10
+ "odm",
11
+ "database",
12
+ "datasource",
13
+ "repository",
14
+ "relations"
14
15
  ],
15
- "homepage": "https://gitverse.ru/e22m4u/js-repository",
16
+ "homepage": "https://github.com/e22m4u/js-repository",
16
17
  "repository": {
17
18
  "type": "git",
18
- "url": "git+https://gitverse.ru/e22m4u/js-repository.git"
19
+ "url": "git+https://github.com/e22m4u/js-repository.git"
19
20
  },
20
21
  "type": "module",
21
22
  "types": "./src/index.d.ts",
@@ -43,27 +44,26 @@
43
44
  "@e22m4u/js-service": "~0.6.2"
44
45
  },
45
46
  "devDependencies": {
46
- "@commitlint/cli": "~20.5.0",
47
- "@commitlint/config-conventional": "~20.5.0",
47
+ "@commitlint/cli": "~21.2.1",
48
+ "@commitlint/config-conventional": "~21.2.0",
48
49
  "@e22m4u/js-spy": "~0.3.6",
49
- "@eslint/js": "~9.39.2",
50
+ "@eslint/js": "~10.0.1",
50
51
  "@types/chai": "~5.2.3",
51
52
  "@types/chai-as-promised": "~8.0.2",
52
53
  "@types/mocha": "~10.0.10",
53
- "c8": "~11.0.0",
54
+ "c8": "~12.0.0",
54
55
  "chai": "~6.2.2",
55
56
  "chai-as-promised": "~8.0.2",
56
- "esbuild": "~0.27.4",
57
- "eslint": "~9.39.2",
57
+ "esbuild": "~0.28.1",
58
+ "eslint": "~10.7.0",
58
59
  "eslint-config-prettier": "~10.1.8",
59
- "eslint-plugin-chai-expect": "~4.0.0",
60
- "eslint-plugin-import": "~2.32.0",
61
- "eslint-plugin-jsdoc": "~62.8.0",
62
- "eslint-plugin-mocha": "~11.2.0",
60
+ "eslint-plugin-chai-expect": "~4.1.0",
61
+ "eslint-plugin-jsdoc": "~63.2.0",
62
+ "eslint-plugin-mocha": "~11.3.0",
63
63
  "husky": "~9.1.7",
64
- "mocha": "~11.7.5",
65
- "prettier": "~3.8.1",
64
+ "mocha": "~11.7.6",
65
+ "prettier": "~3.9.6",
66
66
  "rimraf": "~6.1.3",
67
- "typescript": "~5.9.3"
67
+ "typescript": "~7.0.2"
68
68
  }
69
69
  }
@@ -27,6 +27,11 @@ export declare class DefinitionRegistry extends Service {
27
27
  */
28
28
  getDatasource(name: string): DatasourceDefinition;
29
29
 
30
+ /**
31
+ * Get datasource names.
32
+ */
33
+ getDatasourceNames(): string[];
34
+
30
35
  /**
31
36
  * Add model.
32
37
  *
@@ -47,4 +52,9 @@ export declare class DefinitionRegistry extends Service {
47
52
  * @param name
48
53
  */
49
54
  getModel(name: string): ModelDefinition;
55
+
56
+ /**
57
+ * Get model names.
58
+ */
59
+ getModelNames(): string[];
50
60
  }
@@ -1,8 +1,7 @@
1
1
  import {Service} from '@e22m4u/js-service';
2
- import {modelNameToModelKey} from '../utils/index.js';
3
2
  import {InvalidArgumentError} from '../errors/index.js';
4
3
  import {ModelDefinitionValidator} from './model/index.js';
5
- import {DatasourceDefinitionValidator} from '../definition/index.js';
4
+ import {DatasourceDefinitionValidator} from './datasource/index.js';
6
5
 
7
6
  /**
8
7
  * Definition registry.
@@ -60,6 +59,15 @@ export class DefinitionRegistry extends Service {
60
59
  return datasourceDef;
61
60
  }
62
61
 
62
+ /**
63
+ * Get datasource names.
64
+ *
65
+ * @returns {string[]}
66
+ */
67
+ getDatasourceNames() {
68
+ return Object.keys(this._datasources);
69
+ }
70
+
63
71
  /**
64
72
  * Add model.
65
73
  *
@@ -67,14 +75,11 @@ export class DefinitionRegistry extends Service {
67
75
  */
68
76
  addModel(modelDef) {
69
77
  this.getService(ModelDefinitionValidator).validate(modelDef);
70
- const modelKey = modelNameToModelKey(modelDef.name);
71
- if (modelKey in this._models) {
72
- throw new InvalidArgumentError(
73
- 'Model %v is already defined.',
74
- modelDef.name,
75
- );
78
+ const name = modelDef.name;
79
+ if (name in this._models) {
80
+ throw new InvalidArgumentError('Model %v is already defined.', name);
76
81
  }
77
- this._models[modelKey] = modelDef;
82
+ this._models[name] = modelDef;
78
83
  }
79
84
 
80
85
  /**
@@ -84,8 +89,7 @@ export class DefinitionRegistry extends Service {
84
89
  * @returns {boolean}
85
90
  */
86
91
  hasModel(name) {
87
- const modelKey = modelNameToModelKey(name);
88
- return Boolean(this._models[modelKey]);
92
+ return Boolean(this._models[name]);
89
93
  }
90
94
 
91
95
  /**
@@ -95,11 +99,19 @@ export class DefinitionRegistry extends Service {
95
99
  * @returns {object}
96
100
  */
97
101
  getModel(name) {
98
- const modelKey = modelNameToModelKey(name);
99
- const modelDef = this._models[modelKey];
102
+ const modelDef = this._models[name];
100
103
  if (!modelDef) {
101
104
  throw new InvalidArgumentError('Model %v is not defined.', name);
102
105
  }
103
106
  return modelDef;
104
107
  }
108
+
109
+ /**
110
+ * Get model names.
111
+ *
112
+ * @returns {string[]}
113
+ */
114
+ getModelNames() {
115
+ return Object.keys(this._models);
116
+ }
105
117
  }
@@ -1,42 +1,33 @@
1
1
  import {expect} from 'chai';
2
- import {createSandbox} from '@e22m4u/js-spy';
2
+ import {createSpy} from '@e22m4u/js-spy';
3
3
  import {ModelDefinitionValidator} from './model/index.js';
4
4
  import {DefinitionRegistry} from './definition-registry.js';
5
5
  import {DatasourceDefinitionValidator} from '../definition/index.js';
6
6
 
7
- const sandbox = createSandbox();
8
-
9
7
  describe('DefinitionRegistry', function () {
10
- let S;
11
-
12
- beforeEach(function () {
13
- S = new DefinitionRegistry();
14
- });
15
-
16
- afterEach(function () {
17
- sandbox.restore();
18
- });
19
-
20
8
  describe('addDatasource', function () {
21
- it('adds the given datasource to the registry', function () {
9
+ it('should add the given datasource to the registry', function () {
22
10
  const datasource = {name: 'datasource', adapter: 'adapter'};
11
+ const S = new DefinitionRegistry();
23
12
  S.addDatasource(datasource);
24
13
  const result = S.getDatasource('datasource');
25
14
  expect(result).to.be.eql(datasource);
26
15
  });
27
16
 
28
- it('uses DatasourceDefinitionValidator to validate a given datasource', function () {
17
+ it('should use DatasourceDefinitionValidator to validate the given datasource', function () {
18
+ const S = new DefinitionRegistry();
29
19
  const V = S.getService(DatasourceDefinitionValidator);
30
- sandbox.on(V, 'validate');
20
+ createSpy(V, 'validate');
31
21
  const datasource = {name: 'datasource', adapter: 'adapter'};
32
22
  S.addDatasource(datasource);
33
23
  expect(V.validate).to.have.been.called.once;
34
24
  expect(V.validate).to.have.been.called.with(datasource);
35
25
  });
36
26
 
37
- it('throws an error if a given datasource is already defined', function () {
27
+ it('should throw an error when the given datasource is already defined', function () {
38
28
  const datasource1 = {name: 'datasource', adapter: 'adapter'};
39
29
  const datasource2 = {name: 'datasource', adapter: 'adapter'};
30
+ const S = new DefinitionRegistry();
40
31
  S.addDatasource(datasource1);
41
32
  const throwable = () => S.addDatasource(datasource2);
42
33
  expect(throwable).to.throw('Datasource "datasource" is already defined.');
@@ -44,8 +35,9 @@ describe('DefinitionRegistry', function () {
44
35
  });
45
36
 
46
37
  describe('hasDatasource', function () {
47
- it('should check the datasource registration by its name', function () {
38
+ it('should return true when the datasource name is registered', function () {
48
39
  const datasource = {name: 'datasource', adapter: 'adapter'};
40
+ const S = new DefinitionRegistry();
49
41
  expect(S.hasDatasource(datasource.name)).to.be.false;
50
42
  S.addDatasource(datasource);
51
43
  expect(S.hasDatasource(datasource.name)).to.be.true;
@@ -53,39 +45,62 @@ describe('DefinitionRegistry', function () {
53
45
  });
54
46
 
55
47
  describe('getDatasource', function () {
56
- it('returns the datasource by its name', function () {
48
+ it('should return the registered datasource for its name', function () {
57
49
  const datasource = {name: 'datasource', adapter: 'adapter'};
50
+ const S = new DefinitionRegistry();
58
51
  S.addDatasource(datasource);
59
52
  const result = S.getDatasource('datasource');
60
53
  expect(result).to.be.eql(datasource);
61
54
  });
62
55
 
63
- it('throws an error if ths datasource is not defined', function () {
56
+ it('should throw an error when the datasource name is not registered', function () {
57
+ const S = new DefinitionRegistry();
64
58
  const throwable = () => S.getDatasource('undefined');
65
59
  expect(throwable).to.throw('Datasource "undefined" is not defined.');
66
60
  });
67
61
  });
68
62
 
63
+ describe('getDatasourceNames', function () {
64
+ it('should return an array of datasource names in the definition order', function () {
65
+ const datasource1 = {name: 'datasource1', adapter: 'adapter'};
66
+ const datasource2 = {name: 'datasource2', adapter: 'adapter'};
67
+ const datasource3 = {name: 'datasource3', adapter: 'adapter'};
68
+ const S = new DefinitionRegistry();
69
+ expect(S.getDatasourceNames()).to.be.eql([]);
70
+ S.addDatasource(datasource1);
71
+ S.addDatasource(datasource2);
72
+ S.addDatasource(datasource3);
73
+ expect(S.getDatasourceNames()).to.be.eql([
74
+ datasource1.name,
75
+ datasource2.name,
76
+ datasource3.name,
77
+ ]);
78
+ });
79
+ });
80
+
69
81
  describe('addModel', function () {
70
- it('adds the given model to the registry', function () {
82
+ it('should add the given model to the registry', function () {
71
83
  const model = {name: 'model'};
84
+ const S = new DefinitionRegistry();
72
85
  S.addModel(model);
73
86
  const result = S.getModel('model');
74
87
  expect(result).to.be.eql(model);
75
88
  });
76
89
 
77
- it('uses ModelDefinitionValidator to validate a given model', function () {
90
+ it('should use ModelDefinitionValidator to validate the given model', function () {
91
+ const S = new DefinitionRegistry();
78
92
  const V = S.getService(ModelDefinitionValidator);
79
- sandbox.on(V, 'validate');
93
+ createSpy(V, 'validate');
80
94
  const model = {name: 'model'};
81
95
  S.addModel(model);
82
96
  expect(V.validate).to.have.been.called.once;
83
97
  expect(V.validate).to.have.been.called.with(model);
84
98
  });
85
99
 
86
- it('throws an error if a given model is already defined', function () {
100
+ it('should throw an error when the model name is already registered', function () {
87
101
  const model1 = {name: 'TestModel'};
88
102
  const model2 = {name: 'TestModel'};
103
+ const S = new DefinitionRegistry();
89
104
  S.addModel(model1);
90
105
  const throwable = () => S.addModel(model2);
91
106
  expect(throwable).to.throw('Model "TestModel" is already defined.');
@@ -93,112 +108,46 @@ describe('DefinitionRegistry', function () {
93
108
  });
94
109
 
95
110
  describe('hasModel', function () {
96
- it('should check the model registration by its name', function () {
111
+ it('should return true when the model name is registered', function () {
97
112
  const model = {name: 'model'};
113
+ const S = new DefinitionRegistry();
98
114
  expect(S.hasModel(model.name)).to.be.false;
99
115
  S.addModel(model);
100
116
  expect(S.hasModel(model.name)).to.be.true;
101
117
  });
102
-
103
- it('should ignore naming convention of the model name', function () {
104
- const model = {name: 'UserProfileDetails'};
105
- const modelNames = [
106
- 'userProfileDetails',
107
- 'UserProfileDetails',
108
- 'user-profile-details',
109
- 'user_profile_details',
110
- 'USER-PROFILE-DETAILS',
111
- 'USER_PROFILE_DETAILS',
112
- 'USERPROFILEDETAILS',
113
- 'userprofiledetails',
114
- ];
115
- modelNames.forEach(v => expect(S.hasModel(v)).to.be.false);
116
- S.addModel(model);
117
- modelNames.forEach(v => expect(S.hasModel(v)).to.be.true);
118
- });
119
-
120
- it('should respect numbers in the model name', function () {
121
- const model1 = {name: 'UserProfileDetails1'};
122
- const modelNames1 = [
123
- 'userProfileDetails1',
124
- 'UserProfileDetails1',
125
- 'user-profile-details-1',
126
- 'user_profile_details_1',
127
- 'USER-PROFILE-DETAILS-1',
128
- 'USER_PROFILE_DETAILS_1',
129
- 'USERPROFILEDETAILS1',
130
- 'userprofiledetails1',
131
- ];
132
- const modelNames2 = [
133
- 'userProfileDetails2',
134
- 'UserProfileDetails2',
135
- 'user-profile-details-2',
136
- 'user_profile_details_2',
137
- 'USER-PROFILE-DETAILS-2',
138
- 'USER_PROFILE_DETAILS_2',
139
- 'USERPROFILEDETAILS2',
140
- 'userprofiledetails2',
141
- ];
142
- S.addModel(model1);
143
- modelNames1.forEach(v => expect(S.hasModel(v)).to.be.true);
144
- modelNames2.forEach(v => expect(S.hasModel(v)).to.be.false);
145
- });
146
118
  });
147
119
 
148
120
  describe('getModel', function () {
149
- it('returns the model by its name', function () {
121
+ it('should return the model definition for the model name', function () {
150
122
  const model = {name: 'model'};
123
+ const S = new DefinitionRegistry();
151
124
  S.addModel(model);
152
125
  const result = S.getModel('model');
153
126
  expect(result).to.be.eql(model);
154
127
  });
155
128
 
156
- it('throws an error if the model is not defined', function () {
129
+ it('should throw an error when the model name is not registered', function () {
130
+ const S = new DefinitionRegistry();
157
131
  const throwable = () => S.getModel('undefined');
158
132
  expect(throwable).to.throw('Model "undefined" is not defined.');
159
133
  });
134
+ });
160
135
 
161
- it('should ignore naming convention of the model name', function () {
162
- const model = {name: 'userProfileDetails'};
163
- const modelNames = [
164
- 'userProfileDetails',
165
- 'UserProfileDetails',
166
- 'user-profile-details',
167
- 'user_profile_details',
168
- 'USER-PROFILE-DETAILS',
169
- 'USER_PROFILE_DETAILS',
170
- 'USERPROFILEDETAILS',
171
- 'userprofiledetails',
172
- ];
173
- S.addModel(model);
174
- modelNames.forEach(v => expect(S.getModel(v)).to.be.eq(model));
175
- });
176
-
177
- it('should respect numbers in the model name', function () {
178
- const model1 = {name: 'userProfileDetails1'};
179
- const modelNames1 = [
180
- 'userProfileDetails1',
181
- 'UserProfileDetails1',
182
- 'user-profile-details-1',
183
- 'user_profile_details_1',
184
- 'USER-PROFILE-DETAILS-1',
185
- 'USER_PROFILE_DETAILS_1',
186
- 'USERPROFILEDETAILS1',
187
- 'userprofiledetails1',
188
- ];
189
- const modelNames2 = [
190
- 'userProfileDetails2',
191
- 'UserProfileDetails2',
192
- 'user-profile-details-2',
193
- 'user_profile_details_2',
194
- 'USER-PROFILE-DETAILS-2',
195
- 'USER_PROFILE_DETAILS_2',
196
- 'USERPROFILEDETAILS2',
197
- 'userprofiledetails2',
198
- ];
136
+ describe('getModelNames', function () {
137
+ it('should return an array of model names in the definition order', function () {
138
+ const model1 = {name: 'model1'};
139
+ const model2 = {name: 'model2'};
140
+ const model3 = {name: 'model3'};
141
+ const S = new DefinitionRegistry();
142
+ expect(S.getModelNames()).to.be.eql([]);
199
143
  S.addModel(model1);
200
- modelNames1.forEach(v => expect(S.getModel(v)).to.be.eq(model1));
201
- modelNames2.forEach(v => expect(() => S.getModel(v)).to.throw(Error));
144
+ S.addModel(model2);
145
+ S.addModel(model3);
146
+ expect(S.getModelNames()).to.be.eql([
147
+ model1.name,
148
+ model2.name,
149
+ model3.name,
150
+ ]);
202
151
  });
203
152
  });
204
153
  });
@@ -1,6 +1,5 @@
1
1
  import {Service} from '@e22m4u/js-service';
2
2
  import {Repository} from './repository.js';
3
- import {modelNameToModelKey} from '../utils/index.js';
4
3
  import {InvalidArgumentError} from '../errors/index.js';
5
4
 
6
5
  /**
@@ -49,13 +48,12 @@ export class RepositoryRegistry extends Service {
49
48
  * @returns {Repository}
50
49
  */
51
50
  getRepository(modelName) {
52
- const modelKey = modelNameToModelKey(modelName);
53
- let repository = this._repositories[modelKey];
51
+ let repository = this._repositories[modelName];
54
52
  if (repository) {
55
53
  return repository;
56
54
  }
57
55
  repository = new this._repositoryCtor(this.container, modelName);
58
- this._repositories[modelKey] = repository;
56
+ this._repositories[modelName] = repository;
59
57
  return repository;
60
58
  }
61
59
  }
@@ -35,25 +35,6 @@ describe('RepositoryRegistry', function () {
35
35
  expect(repA2).to.be.not.eq(repB2);
36
36
  });
37
37
 
38
- it('should ignore naming convention of the model name', function () {
39
- const dbs = new DatabaseSchema();
40
- const modelName = 'userProfileDetails';
41
- dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
42
- dbs.defineModel({name: modelName, datasource: 'datasource'});
43
- const reg = dbs.getService(RepositoryRegistry);
44
- const rep = reg.getRepository(modelName);
45
- const modelNames = [
46
- 'UserProfileDetails',
47
- 'user-profile-details',
48
- 'user_profile_details',
49
- 'USER-PROFILE-DETAILS',
50
- 'USER_PROFILE_DETAILS',
51
- 'USERPROFILEDETAILS',
52
- 'userprofiledetails',
53
- ];
54
- modelNames.forEach(v => expect(reg.getRepository(v)).to.be.eq(rep));
55
- });
56
-
57
38
  it('should respect numbers in the model name', function () {
58
39
  const dbs = new DatabaseSchema();
59
40
  dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
@@ -9,4 +9,3 @@ export * from './string-to-regexp.js';
9
9
  export * from './get-value-by-path.js';
10
10
  export * from './select-object-keys.js';
11
11
  export * from './exclude-object-keys.js';
12
- export * from './model-name-to-model-key.js';
@@ -9,4 +9,3 @@ export * from './string-to-regexp.js';
9
9
  export * from './get-value-by-path.js';
10
10
  export * from './select-object-keys.js';
11
11
  export * from './exclude-object-keys.js';
12
- export * from './model-name-to-model-key.js';
@@ -1,6 +0,0 @@
1
- /**
2
- * Model name to model key.
3
- *
4
- * @param modelName
5
- */
6
- export function modelNameToModelKey(modelName: string): string;
@@ -1,18 +0,0 @@
1
- import {InvalidArgumentError} from '../errors/index.js';
2
-
3
- /**
4
- * Model name to model key.
5
- *
6
- * @param {string} modelName
7
- * @returns {string}
8
- */
9
- export function modelNameToModelKey(modelName) {
10
- if (!modelName || typeof modelName !== 'string' || /\s/.test(modelName)) {
11
- throw new InvalidArgumentError(
12
- 'Model name must be a non-empty String ' +
13
- 'without spaces, but %v was given.',
14
- modelName,
15
- );
16
- }
17
- return modelName.toLowerCase().replace(/[-_]/g, '');
18
- }
@@ -1,94 +0,0 @@
1
- import {expect} from 'chai';
2
- import {modelNameToModelKey} from './model-name-to-model-key.js';
3
-
4
- describe('modelNameToModelKey', function () {
5
- it('should return a simple lowercase string as is', function () {
6
- expect(modelNameToModelKey('user')).to.be.eq('user');
7
- });
8
-
9
- it('should convert to lowercase and remove hyphens and underscores', function () {
10
- const modelNames = [
11
- 'userProfileDetails',
12
- 'UserProfileDetails',
13
- 'user-profile-details',
14
- 'user_profile_details',
15
- 'User-Profile-Details',
16
- 'User_Profile_Details',
17
- 'USER-PROFILE-DETAILS',
18
- 'USER_PROFILE_DETAILS',
19
- 'USERPROFILEDETAILS',
20
- 'userprofiledetails',
21
- ];
22
- modelNames.forEach(v =>
23
- expect(modelNameToModelKey(v)).to.be.eq('userprofiledetails'),
24
- );
25
- });
26
-
27
- it('should handle a mixed string with uppercase, hyphens and underscores', function () {
28
- const modelName = 'User_Profile-Details';
29
- const expected = 'userprofiledetails';
30
- expect(modelNameToModelKey(modelName)).to.be.eq(expected);
31
- });
32
-
33
- it('should not remove numbers from the string', function () {
34
- const modelName = 'Type1-Model_2';
35
- const expected = 'type1model2';
36
- expect(modelNameToModelKey(modelName)).to.be.eq(expected);
37
- });
38
-
39
- it('should throw an error for an empty string', function () {
40
- const throwable = () => modelNameToModelKey('');
41
- expect(throwable).to.throw(
42
- 'Model name must be a non-empty String ' +
43
- 'without spaces, but "" was given.',
44
- );
45
- });
46
-
47
- it('should throw an error for a string with spaces', function () {
48
- const throwable = () => modelNameToModelKey('user profile');
49
- expect(throwable).to.throw(
50
- 'Model name must be a non-empty String ' +
51
- 'without spaces, but "user profile" was given.',
52
- );
53
- });
54
-
55
- it('should throw an error for null', function () {
56
- const throwable = () => modelNameToModelKey(null);
57
- expect(throwable).to.throw(
58
- 'Model name must be a non-empty String ' +
59
- 'without spaces, but null was given.',
60
- );
61
- });
62
-
63
- it('should throw an error for undefined', function () {
64
- const throwable = () => modelNameToModelKey(undefined);
65
- expect(throwable).to.throw(
66
- 'Model name must be a non-empty String ' +
67
- 'without spaces, but undefined was given.',
68
- );
69
- });
70
-
71
- it('should throw an error for a number', function () {
72
- const throwable = () => modelNameToModelKey(123);
73
- expect(throwable).to.throw(
74
- 'Model name must be a non-empty String ' +
75
- 'without spaces, but 123 was given.',
76
- );
77
- });
78
-
79
- it('should throw an error for an object', function () {
80
- const throwable = () => modelNameToModelKey({name: 'test'});
81
- expect(throwable).to.throw(
82
- 'Model name must be a non-empty String ' +
83
- 'without spaces, but Object was given.',
84
- );
85
- });
86
-
87
- it('should throw an error for an array', function () {
88
- const throwable = () => modelNameToModelKey(['test']);
89
- expect(throwable).to.throw(
90
- 'Model name must be a non-empty String ' +
91
- 'without spaces, but Array was given.',
92
- );
93
- });
94
- });