Browse Source

chore: updates README.md

e22m4u 7 months ago
parent
commit
c2101b8b8f
3 changed files with 380 additions and 1344 deletions
  1. 0 962
      README-ru.md
  2. 379 381
      README.md
  3. 1 1
      package.json

+ 0 - 962
README-ru.md

@@ -1,962 +0,0 @@
-## @e22m4u/js-repository
-
-*[English](README.md) | Русский*
-
-Реализация паттерна «Репозиторий» для Node.js
-
-- [Установка](#Установка)
-- [Импорт](#Импорт)
-- [Описание](#Описание)
-- [Пример](#Пример)
-- [Схема](#Схема)
-- [Источник данных](#Источник-данных)
-- [Модель](#Модель)
-- [Свойства](#Свойства)
-- [Валидаторы](#Валидаторы)
-- [Трансформеры](#Трансформеры)
-- [Пустые значения](#Пустые-значения)
-- [Репозиторий](#Репозиторий)
-- [Фильтрация](#Фильтрация)
-- [Связи](#Связи)
-- [Расширение](#Расширение)
-- [TypeScript](#TypeScript)
-- [Тесты](#Тесты)
-- [Лицензия](#Лицензия)
-
-## Установка
-
-```bash
-npm install @e22m4u/js-repository
-```
-
-Опционально устанавливаем адаптер.
-
-|           | описание                                                                                                                       |
-|-----------|--------------------------------------------------------------------------------------------------------------------------------|
-| `memory`  | виртуальная база в памяти процесса (не требует установки)                                                                      |
-| `mongodb` | MongoDB - система управления NoSQL базами (*[установка](https://www.npmjs.com/package/@e22m4u/js-repository-mongodb-adapter))* |
-
-## Импорт
-
-Модуль поддерживает ESM и CommonJS стандарты.
-
-*ESM*
-
-```js
-import {Schema} from '@e22m4u/js-repository';
-```
-
-*CommonJS*
-
-```js
-const {Schema} = require('@e22m4u/js-repository');
-```
-
-## Описание
-
-Модуль позволяет абстрагироваться от различных интерфейсов баз данных,
-представляя их как именованные *источники данных*, подключаемые к *моделям*.
-*Модель* же описывает таблицу базы, колонки которой являются свойствами
-модели. Свойства модели могут иметь определенный *тип* допустимого значения,
-набор *валидаторов* и *трансформеров*, через которые проходят данные перед
-записью в базу. Кроме того, *модель* может определять классические связи
-«один к одному», «один ко многим» и другие типы отношений между моделями.
-
-Непосредственно чтение и запись данных производится с помощью *репозитория*,
-который имеет каждая модель с объявленным *источником данных*. Репозиторий
-может фильтровать запрашиваемые документы, выполнять валидацию свойств
-согласно определению модели, и встраивать связанные данные в результат
-выборки.
-
-- *Источник данных* - определяет способ подключения к базе
-- *Модель* - описывает структуру документа и связи к другим моделям
-- *Репозиторий* - выполняет операции чтения и записи документов модели
-
-```mermaid
-flowchart TD
-
-  A[Схема]
-  subgraph Базы данных
-    B[Источник данных 1]
-    C[Источник данных 2]
-  end
-  A-->B
-  A-->C
-
-  subgraph Коллекции
-    D[Модель A]
-    E[Модель Б]
-    F[Модель В]
-    G[Модель Г]
-  end
-  B-->D
-  B-->E
-  C-->F
-  C-->G
-
-  H[Репозиторий A]
-  I[Репозиторий Б]
-  J[Репозиторий В]
-  K[Репозиторий Г]
-  D-->H
-  E-->I
-  F-->J
-  G-->K
-```
-
-## Пример
-
-Объявление источника данных, модели и добавление нового документа в коллекцию.
-
-```js
-import {Schema} from '@e22m4u/js-repository';
-import {DataType} from '@e22m4u/js-repository';
-
-// создание экземпляра Schema
-const schema = new Schema();
-
-// объявление источника "myMemory"
-schema.defineDatasource({
-  name: 'myMemory', // название нового источника
-  adapter: 'memory', // выбранный адаптер
-});
-
-// объявление модели "country"
-schema.defineModel({
-  name: 'country', // название новой модели
-  datasource: 'myMemory', // выбранный источник
-  properties: { // свойства модели
-    name: DataType.STRING, // тип "string"
-    population: DataType.NUMBER, // тип "number"
-  },
-})
-
-// получение репозитория модели "country"
-const countryRep = schema.getRepository('country');
-
-// добавление нового документа в коллекцию "country"
-const country = await countryRep.create({
-  name: 'Russia',
-  population: 143400000,
-});
-
-// вывод нового документа
-console.log(country);
-// {
-//   "id": 1,
-//   "name": "Russia",
-//   "population": 143400000,
-// }
-```
-
-## Схема
-
-Экземпляр класса `Schema` хранит определения источников данных и моделей.
-
-**Методы**
-
-- `defineDatasource(datasourceDef: object): this` - добавить источник
-- `defineModel(modelDef: object): this` - добавить модель
-- `getRepository(modelName: string): Repository` - получить репозиторий
-
-**Примеры**
-
-Импорт класса и создание экземпляра схемы.
-
-```js
-import {Schema} from '@e22m4u/js-repository';
-
-const schema = new Schema();
-```
-
-Определение нового источника.
-
-```js
-schema.defineDatasource({
-  name: 'myMemory', // название нового источника
-  adapter: 'memory', // выбранный адаптер
-});
-```
-
-Определение новой модели.
-
-```js
-schema.defineModel({
-  name: 'product', // название новой модели
-  datasource: 'myMemory', // выбранный источник
-  properties: { // свойства модели
-    name: DataType.STRING,
-    weight: DataType.NUMBER,
-  },
-});
-```
-
-Получение репозитория по названию модели.
-
-```js
-const productRep = schema.getRepository('product');
-```
-
-## Источник данных
-
-Источник хранит название выбранного адаптера и его настройки. Определение
-нового источника выполняется методом `defineDatasource` экземпляра схемы.
-
-**Параметры**
-
-- `name: string` уникальное название
-- `adapter: string` выбранный адаптер
-- параметры адаптера (если имеются)
-
-**Примеры**
-
-Определение нового источника.
-
-```js
-schema.defineDatasource({
-  name: 'myMemory', // название нового источника
-  adapter: 'memory', // выбранный адаптер
-});
-```
-
-Передача дополнительных параметров адаптера.
-
-```js
-schema.defineDatasource({
-  name: 'myMongodb',
-  adapter: 'mongodb',
-  // параметры адаптера "mongodb"
-  host: '127.0.0.1',
-  port: 27017,
-  database: 'myDatabase',
-});
-```
-
-## Модель
-
-Описывает структуру документа коллекции и связи к другим моделям. Определение
-новой модели выполняется методом `defineModel` экземпляра схемы.
-
-**Параметры**
-
-- `name: string` название модели (обязательно)
-- `base: string` название наследуемой модели
-- `tableName: string` название коллекции в базе
-- `datasource: string` выбранный источник данных
-- `properties: object` определения свойств (см. [Свойства](#Свойства))
-- `relations: object` определения связей (см. [Связи](#Связи))
-
-**Примеры**
-
-Определение модели со свойствами указанного типа.
-
-```js
-schema.defineModel({
-  name: 'user', // название новой модели
-  properties: { // свойства модели
-    name: DataType.STRING,
-    age: DataType.NUMBER,
-  },
-});
-```
-
-## Свойства
-
-Параметр `properties` находится в определении модели и принимает объект, ключи
-которого являются свойствами этой модели, а значением тип свойства или объект
-с дополнительными параметрами.
-
-**Тип данных**
-
-- `DataType.ANY` разрешено любое значение
-- `DataType.STRING` только значение типа `string`
-- `DataType.NUMBER` только значение типа `number`
-- `DataType.BOOLEAN` только значение типа `boolean`
-- `DataType.ARRAY` только значение типа `array`
-- `DataType.OBJECT` только значение типа `object`
-
-**Параметры**
-
-- `type: string` тип допустимого значения (обязательно)
-- `itemType: string` тип элемента массива (для `type: 'array'`)
-- `model: string` модель объекта (для `type: 'object'`)
-- `primaryKey: boolean` объявить свойство первичным ключом
-- `columnName: string` переопределение названия колонки
-- `columnType: string` тип колонки (определяется адаптером)
-- `required: boolean` объявить свойство обязательным
-- `default: any` значение по умолчанию
-- `validate: string | array | object` см. [Валидаторы](#Валидаторы)
-- `unique: boolean | string` проверять значение на уникальность
-
-**Параметр `unique`**
-
-Если значением параметра `unique` является `true` или `'strict'`, то выполняется
-строгая проверка на уникальность. В этом режиме [пустые значения](#Пустые-значения)
-так же подлежат проверке, где `null` и `undefined` не могут повторяться более одного
-раза.
-
-Режим `'sparse'` проверяет только значения с полезной нагрузкой, исключая
-[пустые значения](#Пустые-значения), список которых отличается в зависимости
-от типа свойства. Например, для типа `string` пустым значением будет `undefined`,
-`null` и `''` (пустая строка).
-
-- `unique: true | 'strict'` строгая проверка на уникальность
-- `unique: 'sparse'` исключить из проверки [пустые значения](#Пустые-значения)
-- `unique: false | 'nonUnique'` не проверять на уникальность (по умолчанию)
-
-В качестве значений параметра `unique` можно использовать предопределенные
-константы как эквивалент строковых значений `strict`, `sparse` и `nonUnique`.
-
-- `PropertyUniqueness.STRICT`
-- `PropertyUniqueness.SPARSE`
-- `PropertyUniqueness.NON_UNIQUE`
-
-**Примеры**
-
-Краткое определение свойств модели.
-
-```js
-schema.defineModel({
-  name: 'city',
-  properties: { // свойства модели
-    name: DataType.STRING, // тип свойства "string"
-    population: DataType.NUMBER, // тип свойства "number"
-  },
-});
-```
-
-Расширенное определение свойств модели.
-
-```js
-schema.defineModel({
-  name: 'city',
-  properties: { // свойства модели
-    name: {
-      type: DataType.STRING, // тип свойства "string" (обязательно)
-      required: true, // исключение значений undefined и null
-    },
-    population: {
-      type: DataType.NUMBER, // тип свойства "number" (обязательно)
-      default: 0, // значение по умолчанию
-    },
-    code: {
-      type: DataType.NUMBER, // тип свойства "number" (обязательно)
-      unique: PropertyUniqueness.UNIQUE, // проверять уникальность
-    },
-  },
-});
-```
-
-Фабричное значение по умолчанию. Возвращаемое значение функции будет
-определено в момент записи документа.
-
-```js
-schema.defineModel({
-  name: 'article',
-  properties: { // свойства модели
-    tags: {
-      type: DataType.ARRAY, // тип свойства "array" (обязательно)
-      itemType: DataType.STRING, // тип элемента "string"
-      default: () => [], // фабричное значение
-    },
-    createdAt: {
-      type: DataType.STRING, // тип свойства "string" (обязательно)
-      default: () => new Date().toISOString(), // фабричное значение
-    },
-  },
-});
-```
-
-## Валидаторы
-
-Кроме проверки типа, дополнительные условия можно задать с помощью
-валидаторов, через которые будет проходить значение свойства перед
-записью в базу. Исключением являются [пустые значения](#Пустые-значения),
-которые не подлежат проверке.
-
-- `minLength: number` минимальная длинна строки или массива
-- `maxLength: number` максимальная длинна строки или массива
-- `regexp: string | RegExp` проверка по регулярному выражению
-
-**Пример**
-
-Валидаторы указываются в объявлении свойства модели параметром
-`validate`, который принимает объект с их названиями и настройками.
-
-```js
-schema.defineModel({
-  name: 'user',
-  properties: {
-    name: {
-      type: DataType.STRING,
-      validate: { // валидаторы свойства "name"
-        minLength: 2, // минимальная длинна строки
-        maxLength: 24, // максимальная длинна строки
-      },
-    },
-  },
-});
-```
-
-### Пользовательские валидаторы
-
-Валидатором является функция, в которую передается значение соответствующего
-поля перед записью в базу. Если во время проверки функция возвращает `false`,
-то выбрасывается стандартная ошибка. Подмена стандартной ошибки возможна
-с помощью выброса пользовательской ошибки непосредственно внутри функции.
-
-Регистрация пользовательского валидатора выполняется методом `addValidator`
-сервиса `PropertyValidatorRegistry`, который принимает новое название
-и функцию для проверки значения.
-
-**Пример**
-
-```js
-// создание валидатора для запрета
-// всех символов кроме чисел
-const numericValidator = (input) => {
-  return /^[0-9]+$/.test(String(input));
-}
-
-// регистрация валидатора "numeric"
-schema
-  .get(PropertyValidatorRegistry)
-  .addValidator('numeric', numericValidator);
-
-// использование валидатора в определении
-// свойства "code" для новой модели
-schema.defineModel({
-  name: 'document',
-  properties: {
-    code: {
-      type: DataType.STRING,
-      validate: 'numeric',
-    },
-  },
-});
-```
-
-## Трансформеры
-
-С помощью трансформеров производится модификация значений определенных
-полей перед записью в базу. Трансформеры позволяют указать какие изменения
-нужно производить с входящими данными. Исключением являются
-[пустые значения](#Пустые-значения), которые не подлежат трансформации.
-
-- `trim` удаление пробельных символов с начала и конца строки
-- `toUpperCase` перевод строки в верхний регистр
-- `toLowerCase` перевод строки в нижний регистр
-- `toTitleCase` перевод строки в регистр заголовка
-
-**Пример**
-
-Трансформеры указываются в объявлении свойства модели параметром
-`transform`, который принимает название трансформера. Если требуется
-указать несколько названий, то используется массив. Если трансформер
-имеет настройки, то используется объект, где ключом является название
-трансформера, а значением его параметры.
-
-```js
-schema.defineModel({
-  name: 'user',
-  properties: {
-    name: {
-      type: DataType.STRING,
-      transform: [ // трансформеры свойства "name"
-        'trim', // удалить пробелы в начале и конце строки
-        'toTitleCase', // перевод строки в регистр заголовка
-      ],
-    },
-  },
-});
-```
-
-## Пустые значения
-
-Разные типы свойств имеют свои наборы пустых значений. Эти наборы
-используются для определения наличия полезной нагрузки в значении
-свойства. Например, параметр `default` в определении свойства
-устанавливает значение по умолчанию, только если входящее значение
-является пустым. Параметр `required` исключает пустые значения
-выбрасывая ошибку. А параметр `unique` в режиме `sparse` наоборот
-допускает дублирование пустых значений уникального свойства.
-
-| тип         | пустые значения           |
-|-------------|---------------------------|
-| `'any'`     | `undefined`, `null`       |
-| `'string'`  | `undefined`, `null`, `''` |
-| `'number'`  | `undefined`, `null`, `0`  |
-| `'boolean'` | `undefined`, `null`       |
-| `'array'`   | `undefined`, `null`, `[]` |
-| `'object'`  | `undefined`, `null`, `{}` |
-
-## Репозиторий
-
-Выполняет операции чтения и записи документов определенной модели.
-Получить репозиторий можно методом `getRepository` экземпляра схемы.
-
-**Методы**
-
-- `create(data, filter = undefined)` добавить новый документ
-- `replaceById(id, data, filter = undefined)` заменить весь документ
-- `replaceOrCreate(data, filter = undefined)` заменить или создать новый
-- `patchById(id, data, filter = undefined)` частично обновить документ
-- `patch(data, where = undefined)` обновить все документы или по условию
-- `find(filter = undefined)` найти все документы или по условию
-- `findOne(filter = undefined)` найти первый документ или по условию
-- `findById(id, filter = undefined)` найти документ по идентификатору
-- `delete(where = undefined)` удалить все документы или по условию
-- `deleteById(id)` удалить документ по идентификатору
-- `exists(id)` проверить существование по идентификатору
-- `count(where = undefined)` подсчет всех документов или по условию
-
-**Аргументы**
-
-- `id: number|string` идентификатор (первичный ключ)
-- `data: object` объект отражающий состав документа
-- `where: object` параметры выборки (см. [Фильтрация](#Фильтрация))
-- `filter: object` параметры возвращаемого результата (см. [Фильтрация](#Фильтрация))
-
-**Примеры**
-
-Получение репозитория по названию модели.
-
-```js
-const countryRep = schema.getRepository('country');
-```
-
-Добавление нового документа в коллекцию.
-
-```js
-const res = await countryRep.create({
-  name: 'Russia',
-  population: 143400000,
-});
-
-console.log(res);
-// {
-//   "id": 1,
-//   "name": "Russia",
-//   "population": 143400000,
-// }
-```
-
-Поиск документа по идентификатору.
-
-```js
-const res = await countryRep.findById(1);
-
-console.log(res);
-// {
-//   "id": 1,
-//   "name": "Russia",
-//   "population": 143400000,
-// }
-```
-
-Удаление документа по идентификатору.
-
-```js
-const res = await countryRep.deleteById(1);
-
-console.log(res); // true
-```
-
-## Фильтрация
-
-Некоторые методы репозитория принимают объект настроек влияющий
-на возвращаемый результат. Максимально широкий набор таких настроек
-имеет первый параметр метода `find`, где ожидается объект содержащий
-набор опций указанных ниже.
-
-- `where: object` объект выборки
-- `order: string[]` указание порядка
-- `limit: number` ограничение количества документов
-- `skip: number` пропуск документов
-- `fields: string[]` выбор необходимых свойств модели
-- `include: object` включение связанных данных в результат
-
-### where
-
-Параметр принимает объект с условиями выборки и поддерживает широкий
-набор операторов сравнения.
-
-`{foo: 'bar'}` поиск по значению свойства `foo`  
-`{foo: {eq: 'bar'}}` оператор равенства `eq`  
-`{foo: {neq: 'bar'}}` оператор неравенства `neq`  
-`{foo: {gt: 5}}` оператор "больше" `gt`  
-`{foo: {lt: 10}}` оператор "меньше" `lt`  
-`{foo: {gte: 5}}` оператор "больше или равно" `gte`  
-`{foo: {lte: 10}}` оператор "меньше или равно" `lte`  
-`{foo: {inq: ['bar', 'baz']}}` равенство одного из значений `inq`  
-`{foo: {nin: ['bar', 'baz']}}` исключение значений массива `nin`  
-`{foo: {between: [5, 10]}}` оператор диапазона `between`  
-`{foo: {exists: true}}` оператор наличия значения `exists`  
-`{foo: {like: 'bar'}}` оператор поиска подстроки `like`  
-`{foo: {ilike: 'BaR'}}` регистронезависимая версия `ilike`  
-`{foo: {nlike: 'bar'}}` оператор исключения подстроки `nlike`  
-`{foo: {nilike: 'BaR'}}` регистронезависимая версия `nilike`  
-`{foo: {regexp: 'ba.+'}}` оператор регулярного выражения `regexp`  
-`{foo: {regexp: 'ba.+', flags: 'i'}}` флаги регулярного выражения
-
-*i. Условия можно объединять операторами `and`, `or` и `nor`.*
-
-**Примеры**
-
-Применение условий выборки при подсчете документов.
-
-```js
-const res = await rep.count({
-  authorId: 251,
-  publishedAt: {
-    lte: '2023-12-02T14:00:00.000Z',
-  },
-});
-```
-
-Применение оператора `or` при удалении документов.
-
-```js
-const res = await rep.delete({
-  or: [
-    {draft: true},
-    {title: {like: 'draft'}},
-  ],
-});
-```
-
-### order
-
-Параметр упорядочивает выборку по указанным свойствам модели. Обратное
-направление порядка можно задать постфиксом `DESC` в названии свойства.
-
-**Примеры**
-
-Упорядочить по полю `createdAt`
-
-```js
-const res = await rep.find({
-  order: 'createdAt',
-});
-```
-
-Упорядочить по полю `createdAt` в обратном порядке.
-
-```js
-const res = await rep.find({
-  order: 'createdAt DESC',
-});
-```
-
-Упорядочить по нескольким свойствам в разных направлениях.
-
-```js
-const res = await rep.find({
-  order: [
-    'title',
-    'price ASC',
-    'featured DESC',
-  ],
-});
-```
-
-*i. Направление порядка `ASC` указывать необязательно.*
-
-### include
-
-Параметр включает связанные документы в результат вызываемого метода.
-Названия включаемых связей должны быть определены в текущей модели.
-(см. [Связи](#Связи))
-
-**Примеры**
-
-Включение связи по названию.
-
-```js
-const res = await rep.find({
-  include: 'city',
-});
-```
-
-Включение вложенных связей.
-
-```js
-const res = await rep.find({
-  include: {
-    city: 'country',
-  },
-});
-```
-
-Включение нескольких связей массивом.
-
-```js
-const res = await rep.find({
-  include: [
-    'city',
-    'address',
-    'employees'
-  ],
-});
-```
-
-Использование фильтрации включаемых документов.
-
-```js
-const res = await rep.find({
-  include: {
-    relation: 'employees', // название связи
-    scope: { // фильтрация документов "employees"
-      where: {hidden: false}, // условия выборки
-      order: 'id', // порядок документов
-      limit: 10, // ограничение количества
-      skip: 5, // пропуск документов
-      fields: ['name', 'surname'], // только указанные поля
-      include: 'city', // включение связей для "employees"
-    },
-  },
-});
-```
-
-## Связи
-
-Параметр `relations` находится в определении модели и принимает
-объект, ключ которого является названием связи, а значением объект
-с параметрами.
-
-**Параметры**
-
-- `type: string` тип связи
-- `model: string` название целевой модели
-- `foreignKey: string` свойство текущей модели для идентификатора цели
-- `polymorphic: boolean|string` объявить связь полиморфной*
-- `discriminator: string` свойство текущей модели для названия целевой*
-
-*i. Полиморфный режим позволяет динамически определять целевую модель
-по ее названию, которое хранит документ в свойстве-дискриминаторе.*
-
-**Тип связи**
-
-- `belongsTo` - текущая модель содержит свойство для идентификатора цели
-- `hasOne` - обратная сторона `belongsTo` по принципу "один к одному"
-- `hasMany` - обратная сторона `belongsTo` по принципу "один ко многим"
-- `referencesMany` - документ содержит массив с идентификаторами целевой модели
-
-**Примеры**
-
-Объявление связи `belongsTo`
-
-```js
-schema.defineModel({
-  name: 'user',
-  relations: {
-    role: { // название связи
-      type: RelationType.BELONGS_TO, // текущая модель ссылается на целевую
-      model: 'role', // название целевой модели
-      foreignKey: 'roleId', // внешний ключ (необязательно)
-      // если "foreignKey" не указан, то свойство внешнего
-      // ключа формируется согласно названию связи
-      // с добавлением постфикса "Id"
-    },
-  },
-});
-```
-
-Объявление связи `hasMany`
-
-```js
-schema.defineModel({
-  name: 'role',
-  relations: {
-    users: { // название связи
-      type: RelationType.HAS_MANY, // целевая модель ссылается на текущую
-      model: 'user', // название целевой модели
-      foreignKey: 'roleId', // внешний ключ из целевой модели на текущую
-    },
-  },
-});
-```
-
-Объявление связи `referencesMany`
-
-```js
-schema.defineModel({
-  name: 'article',
-  relations: {
-    categories: { // название связи
-      type: RelationType.REFERENCES_MANY, // связь через массив идентификаторов
-      model: 'category', // название целевой модели
-      foreignKey: 'categoryIds', // внешний ключ (необязательно)
-      // если "foreignKey" не указан, то свойство внешнего
-      // ключа формируется согласно названию связи
-      // с добавлением постфикса "Ids"
-    },
-  },
-});
-```
-
-Полиморфная версия `belongsTo`
-
-```js
-schema.defineModel({
-  name: 'file',
-  relations: {
-    reference: { // название связи
-      type: RelationType.BELONGS_TO, // текущая модель ссылается на целевую
-      // полиморфный режим позволяет хранить название целевой модели
-      // в свойстве-дискриминаторе, которое формируется согласно
-      // названию связи с постфиксом "Type", и в данном случае
-      // название целевой модели хранит "referenceType",
-      // а идентификатор документа "referenceId"
-      polymorphic: true,
-    },
-  },
-});
-```
-
-Полиморфная версия `belongsTo` с указанием свойств.
-
-```js
-schema.defineModel({
-  name: 'file',
-  relations: {
-    reference: { // название связи
-      type: RelationType.BELONGS_TO, // текущая модель ссылается на целевую
-      polymorphic: true, // название целевой модели хранит дискриминатор
-      foreignKey: 'referenceId', // свойство для идентификатора цели
-      discriminator: 'referenceType', // свойство для названия целевой модели
-    },
-  },
-});
-```
-
-Полиморфная версия `hasMany` с указанием названия связи целевой модели.
-
-```js
-schema.defineModel({
-  name: 'letter',
-  relations: {
-    attachments: { // название связи
-      type: RelationType.HAS_MANY, // целевая модель ссылается на текущую
-      model: 'file', // название целевой модели
-      polymorphic: 'reference', // название полиморфной связи целевой модели
-    },
-  },
-});
-```
-
-Полиморфная версия `hasMany` с указанием свойств целевой модели.
-
-```js
-schema.defineModel({
-  name: 'letter',
-  relations: {
-    attachments: { // название связи
-      type: RelationType.HAS_MANY, // целевая модель ссылается на текущую
-      model: 'file', // название целевой модели
-      polymorphic: true, // название текущей модели находится в дискриминаторе
-      foreignKey: 'referenceId', // свойство целевой модели для идентификатора
-      discriminator: 'referenceType', // свойство целевой модели для названия текущей
-    },
-  },
-});
-```
-
-## Расширение
-
-Метод `getRepository` экземпляра схемы проверяет наличие существующего
-репозитория для указанной модели и возвращает его. В противном случае
-создается новый экземпляр, который будет сохранен для последующих
-обращений к методу.
-
-```js
-import {Schema} from '@e22m4u/js-repository';
-import {Repository} from '@e22m4u/js-repository';
-
-// const schema = new Schema();
-// schema.defineDatasource ...
-// schema.defineModel ...
-
-const rep1 = schema.getRepository('model');
-const rep2 = schema.getRepository('model');
-console.log(rep1 === rep2); // true
-```
-
-Подмена стандартного конструктора репозитория выполняется методом
-`setRepositoryCtor` сервиса `RepositoryRegistry`, который находится
-в контейнере экземпляра схемы. После чего все новые репозитории будут
-создаваться указанным конструктором вместо стандартного.
-
-```js
-import {Schema} from '@e22m4u/js-repository';
-import {Repository} from '@e22m4u/js-repository';
-import {RepositoryRegistry} from '@e22m4u/js-repository';
-
-class MyRepository extends Repository {
-  /*...*/
-}
-
-// const schema = new Schema();
-// schema.defineDatasource ...
-// schema.defineModel ...
-
-schema.get(RepositoryRegistry).setRepositoryCtor(MyRepository);
-const rep = schema.getRepository('model');
-console.log(rep instanceof MyRepository); // true
-```
-
-*i. Так как экземпляры репозитория кэшируется, то замену конструктора
-следует выполнять до обращения к методу `getRepository`.*
-
-## TypeScript
-
-Получение типизированного репозитория с указанием интерфейса модели.
-
-```ts
-import {Schema} from '@e22m4u/js-repository';
-import {DataType} from '@e22m4u/js-repository';
-import {RelationType} from '@e22m4u/js-repository';
-
-// const schema = new Schema();
-// schema.defineDatasource ...
-// schema.defineModel ...
-
-// определение модели "city"
-schema.defineModel({
-  name: 'city',
-  datasource: 'myDatasource',
-  properties: {
-    title: DataType.STRING,
-    timeZone: DataType.STRING,
-  },
-  relations: {
-    country: {
-      type: RelationType.BELONGS_TO,
-      model: 'country',
-    },
-  },
-});
-
-// определение интерфейса "city"
-interface City {
-  id: number;
-  title?: string;
-  timeZone?: string;
-  countryId?: number;
-  country?: Country;
-}
-
-// получаем репозиторий по названию модели
-// указывая ее тип и тип идентификатора
-const cityRep = schema.getRepository<City, number>('city');
-```
-
-## Тесты
-
-```bash
-npm run test
-```
-
-## Лицензия
-
-MIT

File diff suppressed because it is too large
+ 379 - 381
README.md


+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "name": "@e22m4u/js-repository",
   "version": "0.2.5",
-  "description": "Repository pattern implementation for Node.js",
+  "description": "Реализация репозитория для работы с базами данных в Node.js",
   "author": "e22m4u <e22m4u@yandex.ru>",
   "license": "MIT",
   "keywords": [

Some files were not shown because too many files changed in this diff