@lad-tech/nsc-toolkit 1.8.0 → 1.9.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +3 -2
  2. package/README.md +383 -48
  3. package/coverage/clover.xml +581 -426
  4. package/coverage/coverage-final.json +29 -21
  5. package/coverage/lcov-report/examples/LogicService/adapters/Configurator.ts.html +130 -0
  6. package/coverage/lcov-report/examples/LogicService/adapters/Repository.ts.html +136 -0
  7. package/coverage/lcov-report/examples/LogicService/adapters/index.html +146 -0
  8. package/coverage/lcov-report/examples/LogicService/adapters/index.ts.html +88 -0
  9. package/coverage/lcov-report/examples/LogicService/index.html +24 -9
  10. package/coverage/lcov-report/examples/LogicService/index.ts.html +54 -9
  11. package/coverage/lcov-report/examples/LogicService/inversion.types.ts.html +103 -0
  12. package/coverage/lcov-report/examples/LogicService/methods/GetUser.ts.html +151 -0
  13. package/coverage/lcov-report/examples/LogicService/methods/GetUserV2.ts.html +157 -0
  14. package/coverage/lcov-report/examples/LogicService/methods/WeirdSum.ts.html +14 -14
  15. package/coverage/lcov-report/examples/LogicService/methods/index.html +39 -9
  16. package/coverage/lcov-report/examples/LogicService/service.ts.html +78 -15
  17. package/coverage/lcov-report/examples/MathService/index.html +1 -1
  18. package/coverage/lcov-report/examples/MathService/index.ts.html +5 -5
  19. package/coverage/lcov-report/examples/MathService/methods/Fibonacci.ts.html +2 -2
  20. package/coverage/lcov-report/examples/MathService/methods/Sum.ts.html +2 -2
  21. package/coverage/lcov-report/examples/MathService/methods/SumStream.ts.html +6 -6
  22. package/coverage/lcov-report/examples/MathService/methods/index.html +1 -1
  23. package/coverage/lcov-report/examples/MathService/service.ts.html +2 -2
  24. package/coverage/lcov-report/index.html +45 -30
  25. package/coverage/lcov.info +1013 -734
  26. package/dist/Client.js +7 -7
  27. package/dist/Client.js.map +1 -1
  28. package/dist/Container.js +76 -0
  29. package/dist/Container.js.map +1 -0
  30. package/dist/Service.js +77 -36
  31. package/dist/Service.js.map +1 -1
  32. package/dist/index.js +1 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/injector.js +30 -4
  35. package/dist/injector.js.map +1 -1
  36. package/dist/interfaces.js +6 -0
  37. package/dist/interfaces.js.map +1 -1
  38. package/dist/types/Client.d.ts +1 -1
  39. package/dist/types/Container.d.ts +28 -0
  40. package/dist/types/Service.d.ts +5 -1
  41. package/dist/types/index.d.ts +1 -0
  42. package/dist/types/injector.d.ts +7 -4
  43. package/dist/types/interfaces.d.ts +7 -1
  44. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,6 +1,7 @@
1
- # [1.8.0](https://github.com/lad-tech/nsc-toolkit/compare/v1.7.1...v1.8.0) (2023-05-02)
1
+ # [1.9.0](https://github.com/lad-tech/nsc-toolkit/compare/v1.8.0...v1.9.0) (2023-05-24)
2
2
 
3
3
 
4
4
  ### Features
5
5
 
6
- * Сборка в монолит ([62efe31](https://github.com/lad-tech/nsc-toolkit/commit/62efe31ac698c05d92ab509c99e1fea4d10898e4))
6
+ * implement DI container and inject decorator ([94dedda](https://github.com/lad-tech/nsc-toolkit/commit/94deddabd798c7cde21208ceb745b350223d4d6d))
7
+ * inject можно использовать с параметрами конструктора ([aa65b34](https://github.com/lad-tech/nsc-toolkit/commit/aa65b341ca4a2f2fc85b05cafe9533300e212645))
package/README.md CHANGED
@@ -1,25 +1,101 @@
1
1
  [![Coverage Status](https://coveralls.io/repos/github/lad-tech/nsc-toolkit/badge.svg?branch=main)](https://coveralls.io/github/lad-tech/nsc-toolkit?branch=main)
2
2
  [![Known Vulnerabilities](https://snyk.io/test/github/lad-tech/nsc-toolkit/badge.svg)](https://snyk.io/test/github/lad-tech/nsc-toolkit)
3
3
 
4
- nsc-toolkit (NATS service creator toolkit) - это набор инструментов для создания сервис-ориентированная архитектуры вокруг брокера сообщений [NATS](https://nats.io/). Основная идеология тулкита - это простой инструмент с минимальным количеством зависимостей позволяющий создавать сервисы с помощью интсрументов кодогенерации на основе простого описания в JSON.
4
+ # nsc-toolkit
5
+
6
+ Содержание
7
+ - [nsc-toolkit](#nsc-toolkit)
8
+ - [О библиотеке](#о-библиотеке)
9
+ - [Возможности](#возможности)
10
+ - [Установка](#установка)
11
+ - [Быстрый старт](#быстрый-старт)
12
+ - [Переменные окружения](#переменные-окружения)
13
+ - [Основные компоненты библиотеки](#основные-компоненты-библиотеки)
14
+ - [Рекомендации](#рекомендации)
15
+ - [Пример использования](#пример-использования)
16
+ - [Описание каталога `examples`](#описание-каталога-examples)
17
+ - [Сворачивание сервисов в монолитное приложение](#сворачивание-сервисов-в-монолитное-приложение)
18
+ - [Инверсия зависимостей и DI-контейнер](#инверсия-зависимостей-и-di-контейнер)
19
+
20
+ ## О библиотеке
21
+
22
+ `nsc-toolkit (NATS service creator toolkit)` 一 это набор инструментов для создания сервис-ориентированной архитектуры.
23
+
24
+ Основная идеология тулкита заключается в установке минимального количества зависимостей, что позволяет создавать сервисы с помощью инструментов кодогенерации на основе простого описания в JSON-формате.
25
+
26
+ Основным средством коммуникации между сервисами в обычном режиме работы является брокер сообщений [NATS](https://nats.io/). Применяются четыре основных способа:
27
+
28
+ 1. Синхронный (`request`/`reply`) через брокер сообщений. Используется, если одному сервису, чтобы продолжать выполнять свою логику, требуются данные из другого сервиса.
29
+ 2. События (`pub`/`sub`). События используются, когда сервису необходимо оповестить другие сервисы о произошедшем событии, но кто слушает и обрабатывает эти события, сервису неизвестно. Это дает возможность строить независимые между собой сервисы для создания архитектуры на основе событий 一 Event-driven architecture (EDA).
30
+ 3. Web-потоки на основе `HTTP 1.1`. Этот метод используется, если сервису требуется передать в другой сервис поток данных. Например, список из миллиона пользователей или любые другие объемные данные, включая бинарные. Тогда брокер выступает только как средство для балансировки нагрузки и не участвует в передаче данных напрямую. Данные передаются с помощью web-потока из одного сервиса в другой через прямое соединение. Метод сервиса в качестве входных параметров может принимать поток данных и отдавать его в качестве ответа.
31
+ 4. Jet-streams используют возможности брокера NATS. Jet-streams похожи на `pub`/`sub`, но предоставляют возможность хранить сообщения на самом брокере. Такой тип коммуникации позволяет реализовывать более безопасный способ общения между сервисами на основе событий. События, если на них нет подписчиков на текущий момент, не пропадут, а сохранятся на самом брокере.
32
+
33
+ Все четыре способа коммуникации между сервисами реализуются средствами библиотеки и описываются в JSON.
5
34
 
6
35
  ## Возможности
7
36
 
8
- * Простота и минимальное количество зависимостей за счет снижения уровня вариативности.
9
- * Схема взаимодействия request/reply.
10
- * Схема взаимодействия pub/sub.
11
- * Сквозной таймаут для запросов.
12
- * Трассировки.
13
- * Использование Web-стримов.
14
- * Межсервисное кеширование.
15
- * Валидация входных и выходных параметров методов сервиса в рантайме на основе [JSON Schema](https://json-schema.org/).
16
- * Логирование с учетом контекста.
17
- * Сервисный http маршрут для проб. Поднимается вместе со стартом сервиса. Доступен **GET [host]/healthcheck HTTP/1.1**
18
- * Возможность собирать микросервисы в монолитном режиме через встроенную реализацию внутреннего брокера. Реализацию этого режима можно найти в папке **examples**. Для сборки проекта в виде микросервисов или монолитном режиме используются разные точки входа.
37
+ - Простота и минимальное количество зависимостей за счет снижения уровня вариативности
38
+ - Схема взаимодействия `request`/`reply`
39
+ - Схема взаимодействия `pub`/`sub`
40
+ - Использование Web-streams
41
+ - Использование Jet-streams
42
+ - Сквозной таймаут для запросов
43
+ - Трассировки
44
+ - Межсервисное кеширование
45
+ - Валидация входных и выходных параметров методов сервиса на основе [JSON Schema](https://json-schema.org/).
46
+ - Логирование с учетом контекста
47
+ - Декораторы для инъекции зависимостей в методы сервиса
48
+ - Сервисный http-маршрут для проб, который поднимается вместе со стартом сервиса (доступен `GET [host]/healthcheck HTTP/1.1`)
49
+ - Сворачивание написанных сервисов в монолитное приложение без использования брокера NATS с сохранением всего спектра перечисленных функциональностей. Разные типы архитектуры (микросервисы или монолит) собираются из одной кодовой базы. Это может происходить параллельно в одном пайплайне CI/CD.
50
+
51
+ ## Установка
52
+
53
+ ```
54
+ npm i @lad-tech/nsc-toolkit
55
+ ```
56
+
57
+ ## Быстрый старт
58
+
59
+ Для обзора возможностей библиотеки рекомендуется использовать пример из каталога `examples`, который состоит из 3-х сервисов. Подробно реализация логики описана в пункте [Пример использования](#пример-использования).
60
+
61
+ Чтобы запустить пример, необходимо:
62
+
63
+ 1. клонировать репозиторий с библиотекой и установить зависимости:
64
+
65
+ ```
66
+ npm i
67
+ ```
68
+
69
+ 2. дополнительно зайти в каталог `examples` с сервисом `HttpGate`
70
+
71
+ ```
72
+ cd ./examples/HttpGate
73
+ ```
74
+
75
+ и установить там зависимости, так как для реализации HTTP-API используется библиотека Fastify:
19
76
 
20
- ## Схема описания сервиса
77
+ ```
78
+ npm i
79
+ ```
80
+
81
+ 3. после установки зависимостей можно запустить сервисы.
82
+
83
+ Список всех зависимостей можно посмотреть [тут](https://www.npmjs.com/package/@lad-tech/nsc-toolkit?activeTab=dependencies).
84
+
85
+ ### Переменные окружения
86
+
87
+ - `DEFAUL_RESPONSE_TIMEOUT` 一 внешнее ограничение тайм-аута при запросе в секундах. Используется при первоначальном формировании времени тайм-аута в багаже по формуле `Date.now() + DEFAULT_RESPONSE_TIMEOUT`;
88
+ - `OTEL_AGENT` 一 хост агента по сбору распределенных трассировок.
21
89
 
22
- Сервисы описываются в JSON файле. Схема:
90
+ ## Основные компоненты библиотеки
91
+
92
+ Основные компоненты библиотеки хранятся в каталоге `src`. То, что не перечисленно в описании ниже, недоступно для использования и применяется только во внутреннем устройстве библиотеки.
93
+
94
+ Для реализации сервисов используются следующие компоненты.
95
+
96
+ 1. Файл `service.schema.json`. Каждый сервис описывается в формате json.
97
+
98
+ Ниже представлена схема описания.
23
99
 
24
100
  ```json
25
101
  {
@@ -43,23 +119,59 @@ nsc-toolkit (NATS service creator toolkit) - это набор инструме
43
119
  "request": { "type": "object" },
44
120
  "response": { "type": "object" }
45
121
  },
46
- "required": [ "action", "description", "options" ]
122
+ "required": ["action", "description", "options"]
47
123
  }
48
124
  },
49
125
  "events": {
50
126
  "type": "object",
51
- "additionalProperties": {
52
- "type": "object",
53
- "properties": {
54
- "name": { "type": "string" },
55
- "description": { "type": "string" },
56
- "message": { "type": "object" }
127
+ "properties": {
128
+ "list": {
129
+ "type": "object",
130
+ "additionalProperties": {
131
+ "type": "object",
132
+ "properties": {
133
+ "action": { "type": "string" },
134
+ "options": {
135
+ "type": "object",
136
+ "properties": {
137
+ "stream": { "type": "boolean" }
138
+ },
139
+ },
140
+ "description": { "type": "string" },
141
+ "event": { "type": "object" }
142
+ },
143
+ "required": ["action", "description", "event"]
144
+ },
57
145
  },
58
- "required": [ "action", "description", "options", "message" ]
59
- }
146
+ "streamOptions": {
147
+ "type": "object",
148
+ "properties": {
149
+ "prefix": { "type": "string" },
150
+ "actions": {
151
+ "type": "array",
152
+ "items": {
153
+ "type": "object",
154
+ "properties": {
155
+ "action": { "type": "string" },
156
+ "storage": { "type": "string" },
157
+ "retentionPolicy": { "type": "string" },
158
+ "discardPolicy": { "type": "string" },
159
+ "messageTTL": { "type": "number" },
160
+ "duplicateTrackingTime": { "type": "number" },
161
+ "replication": { "type": "number" },
162
+ "rollUps": { "type": "boolean" }
163
+ },
164
+ "required": ["action"]
165
+ }
166
+ }
167
+ },
168
+ "required": ["prefix", "actions"]
169
+ }
170
+ },
171
+ "required": ["list"]
60
172
  }
61
173
  },
62
- "required": [ "name", "description", "methods" ],
174
+ "required": ["name", "description", "methods"],
63
175
 
64
176
  "$defs": {
65
177
  "options": {
@@ -86,38 +198,261 @@ nsc-toolkit (NATS service creator toolkit) - это набор инструме
86
198
  }
87
199
  ```
88
200
 
89
- - **name** - Название сервиса.
90
- - **description** - Описание сервиса.
91
- - **methods** - Набор методов для реализации схемы request/reply
92
- - **action** - Идентификатор запроса.
93
- - **description** - Описание метода.
94
- - **request** - JSON Schema входных данных.
95
- - **response** - JSON Schema выходных данных.
96
- - **options** - Настройки метода.
97
- - **useStream** - Использование Web-стримов для входных и выходных данных.
98
- - **request** - Web-стрим на входе.
99
- - **response** - Web-стрим на выходе.
100
- - **cache** - Кешировать запрос. Задается в минутах.
101
- - **runTimeValidation** - Использовать run time валидацию параметров
102
- - **request** - Для входных данных.
103
- - **response** - Для выходных данных.
104
- - **events** - Набор событий генерируемый сервисом для реализации схемы pub/sub
105
- - **name** - Идентификатор события.
106
- - **description** - Описание события.
107
- - **event** - JSON Schema события.
201
+ Пояснения к схеме:
202
+ - `name` название сервиса;
203
+ - `description` описание сервиса;
204
+ - `methods` набор методов для реализации схемы `request`/`reply`;
205
+ - `action` идентификатор запроса;
206
+ - `description` описание метода;
207
+ - `request` JSON Schema входных данных;
208
+ - `response` JSON Schema выходных данных;
209
+ - `options` настройки метода;
210
+ - `useStream` использование Web-стримов для входных и выходных данных;
211
+ - `request` Web-стрим на входе;
212
+ - `response` Web-стрим на выходе;
213
+ - `cache` кеширование запроса (задается в минутах);
214
+ - `runTimeValidation` использование runtime для валидации параметров;
215
+ - `request` для входных данных;
216
+ - `response` для выходных данных;
217
+ - `events` набор событий, генерируемый сервисом для реализации схемы `pub`/`sub`;
218
+ - `list` массив объектов событий, генерируемых сервисом;
219
+ - `action` идентификатор события;
220
+ - `description` 一 описание события;
221
+ - `options` 一 необязательные настройки события;
222
+ - `stream` 一 булевый флаг, маркирующий, что событие является стримом;
223
+ - `event` 一 JSON Schema события;
224
+ - `name` 一 идентификатор события;
225
+ - `description` 一 описание события;
226
+ - `event` 一 JSON Schema события;
227
+ - `streamOptions` 一 настройки стрима;
228
+ - `prefix` 一 префикс ко всем темам, у которых включена опция `stream: true`;
229
+ - `actions` 一 массив объектов настроек стримов;
230
+ - `action` 一 паттерн для тем, на которые будут применяться данные настройки (если указана `*`, то применяется ко всем событиям с опцией `stream: true`);
231
+ - `storage` 一 хранилище для сообщений стрима (доступные варианты `file`|`memory`, по умолчанию `file`);
232
+ - `retentionPolicy` 一 по каким правилам будут удаляться сообщения из стрима (доступные варианты `limits`|`interest`|`workQueue`, по умолчанию `limits`);
233
+ - `discardPolicy` 一 определяет, какие сообщения будут отброшены при достижении лимита (доступные варианты `old`|`new`, по умолчанию `old`);
234
+ - `messageTTL` 一 срок жизни сообщения (задается в секундах, по умолчанию 2 недели);
235
+ - `duplicateTrackingTime` 一 временной отрезок, на котором работает дедубликация сообщений (задается в секундах, по умолчанию 1 день);
236
+ - `replication` 一 количество реплик стрима (по умолчанию 1);
237
+ - `rollUps` 一 флаг, разрешающий удалить все сообщения из стрима (по умолчанию `true`).
238
+
239
+ Файл позволяет описать все возможности создаваемого сервиса:
240
+ - синхронные методы;
241
+ - генерируемые сообщения;
242
+ - настройки стримов для сообщений.
243
+
244
+ Сервис предполагается создавать из описания с помощью кодогенерации. Используется библиотека для кодогенерации сервиса из описания [nsc-cli](https://github.com/lad-tech/nsc-cli).
245
+
246
+ 2. Класс `Service`. Чтобы создать сервис, необходимо создать экземпляр этого класса и вызвать метод `start`.
247
+
248
+ Принимаемые параметры при создании экземпляра:
249
+
250
+ - `name` 一 имя сервиса.
251
+ - `brokerConnection` 一 необязательный параметр для подключения к брокеру NATS. Если его не передать, то будет использоваться внутренняя реализация брокера, и приложение будет собираться в монолит.
252
+ - `methods` 一 массив методов. `BaseMethod` это один из базовых классов библиотеки, который необходимо расширить, чтобы создать метод с бизнес-логикой.
253
+ - `events` 一 описание генерируемых событий. Следует передать весь блок `events` из `service.schema.json`.
254
+ - `cache` 一 настройки межмикросервисного кеширования.
255
+ - `service` 一 реализация интерфейса для сервиса кеширования;
256
+ - `timeout` 一 время, в рамках которого необходимо ожидать ответа от кеша (задается в миллисекундах).
257
+ - `loggerOutputFormatter` 一 реализация класса форматера для логов. Для логирования используется библиотека [@lad-tech/toolbelt](https://github.com/lad-tech/toolbelt).
258
+ - `gracefulShutdown` 一 настройки по завершению работы сервиса.
259
+ - `additional` 一 массив дополнительных сервисов, которые могут завершать свою работу. Необходим, чтобы сервисы реализовывали нужный интерфейс.
260
+ - `timeout` 一 время, в рамках которого ожидается штатная остановка сервиса.
261
+
262
+ Публичные методы:
263
+
264
+ - `getRootBaggage` 一 получение корневого багажа для распределенной трассировки. Источником могут служить заголовки http-запроса. Если подобные источники отсутствуют, то создается новый корневой багаж.
265
+ - `endRootSpan` 一 завершение корневого `Span` по `id` трассировки. Необходим для внедрения распределенных трассировок.
266
+ - `buildService` 一 метод, чтобы создать экземпляр клиента. Все используемые при запросах клиенты (сервисы) должны создаваться через этот метод, если необходимо использовать полную функциональность библиотеки.
267
+ - `start` 一 запуск сервиса.
268
+ - `stop` 一 остановка сервиса.
269
+
270
+ 3. Класс `Client`. Чтобы создать клиент для сервиса, необходимо расширить класс `Client` и описать в нем все доступные извне вызовы методов. Для вызова метода используется приватный метод `CLient.request`. Пример создания клиента можно [посмотреть тут](./examples/MathService/index.ts).
271
+
272
+ Публичные методы:
273
+
274
+ - `getListener` 一 метод получения объекта `EventEmitter` для подписки на события сервиса.
275
+
276
+ 4. Класс `Container`. Реализует DI-контейнре. Сам класс не доступен для импорта, а доступен только его экземпляр, что позволяет реализовать шаблон Singlton. В микросервисном варианте контейнер один на сервис. В монолитном варианте использования контейнер один на все приложение. За счет использользования объектов Symbol в качестве ключей для привязки зависимостей исключены коллизии при привязки зависимостей в разных частях приложения через один контейнре. Для привязки зависимости к ключу необходимо указать тип зависимости. Это нужно чтобы библиотека могла корректно создать ээкземпляр зависимости. Всего существуют 3 вида зависимостей:
277
+
278
+ - `service` 一 сервис как зависимости.
279
+ - `adapter` 一 класс с набором асинхронных методов. Например репозиторий или фасад от стороннего API.
280
+ - `constant`一 обычный объект. Например объект с конфигурацией.
281
+
282
+ Публичные методы:
283
+
284
+ - `bind` 一 привязать реализацию к ключу.
285
+ - `unbind` 一 отвязать реализацию от ключа.
286
+ - `get` 一 получить реализацию по ключу.
287
+ - `getInstance` 一 получить экземпляр реализации. Для зависимости с типом `service` нельзя получить экземпляр через этот метод поскольку для создания экземпляра сервиса требуется контекст в рамках которого он будет работать. Для зависимости с типом `constant` вернется привязанный объект.
288
+
289
+ 5. Декораторы. Применение декораторов:
290
+ * `@service`:
291
+ - Если в методе сервиса вызывается метод другого сервиса, то клиент сервиса зависимости следует подключить через декоратор `@service`, а к самому классу метода применить декоратор `@related`. Тогда при вызове метода сервиса не пропадет контекст запроса и можно будет использовать распределенные трассировки.
292
+ - Инъекция через декоратор `@service` позволяет использовать функциональность сборки приложения в монолит.
293
+ * `@instance`:
294
+ - Используется для инъекции других зависимостей, например, объектов репозиториев. В него можно передать готовый объект с набором асинхронных методов. При вызове этих методов из его логики они будут видны в трассировках. Для получения таких зависимостей рекомендуется использовать DI-контейнеры.
295
+
296
+ ## Рекомендации
297
+
298
+ Библиотека задумана как инструмент, не диктующий жестких правил, однако предлагается следовать следующим рекомендациям.
299
+
300
+ - Использовать кодогенерацию на основе описания сервиса в файле `service.schema.json` с помощью библиотеки [nsc-cli](https://github.com/lad-tech/nsc-cli). На основе описания будут автоматически сгенерированы сервис, клиент, методы и все интерфейсы. В результате весь шаблонный код будет написан и можно сразу приступать к написанию бизнес-логики. Для изменения сервиса (например, добавления нового метода, события или параметров запроса) следует в первую очередь изменить файл описания `service.schema.json`, а затем перегенерировать сервис на его основе. Уже написанная логика не пропадет, но все изменения будут учтены в коде.
301
+
302
+ - Описывать структуру сервиса. Ниже представлена декларативная структура сервиса следующего вида.
303
+
304
+ ```
305
+ Service/
306
+ ├── domain/
307
+ │ ├── aggregates/
308
+ │ │ ├── Aggregate_1/
309
+ │ │ │ ├── fixtures/
310
+ │ │ │ │ ├── fixture_1.json
311
+ │ │ │ │ ├── fixture_1.json
312
+ │ │ │ │ └── ...
313
+ │ │ │ ├── Aggregate.ts
314
+ │ │ │ ├── Aggregate.interface.ts
315
+ │ │ │ ├── Aggregate.test.ts
316
+ │ │ │ └── index.ts
317
+ │ │ └── Aggregate_2/
318
+ │ │ ├── fixtures/
319
+ │ │ │ ├── fixture_1.json
320
+ │ │ │ ├── fixture_1.json
321
+ │ │ │ └── ...
322
+ │ │ ├── Aggregate.ts
323
+ │ │ ├── Aggregate.interface.ts
324
+ │ │ ├── Aggregate.test.ts
325
+ │ │ └── index.ts
326
+ │ └── ports/
327
+ │ ├── index.ts
328
+ │ └── repository.ts
329
+ ├── methods/
330
+ │ ├── Method_1/
331
+ │ │ ├── index.ts
332
+ │ │ ├── index.test.ts
333
+ │ │ └── ...
334
+ │ ├── Method_2/
335
+ │ │ ├── index.ts
336
+ │ │ ├── index.test.ts
337
+ │ │ └── ...
338
+ │ └── ...
339
+ ├── repository/
340
+ │ └── index.ts
341
+ ├── index.ts
342
+ ├── interfaces.ts
343
+ ├── service.ts
344
+ ├── start.ts
345
+ ├── inversion.types
346
+ ├── service.schema.json
347
+ ├── package.json
348
+ ├── package-lock.json
349
+ └── tsconfig.json
350
+ ```
351
+
352
+ Пояснения к структуре:
353
+
354
+ - `domain` 一 каталог, который содержит в себе все классы предметной области сервиса и интерфейсы портов, необходимых для ее работы;
355
+ - `aggregates` 一 каталог с агрегатами предметной области;
356
+ - `Aggregate` 一 каталог агрегата (например, `User`);
357
+ - `Aggregate.ts` 一 класс агрегата;
358
+ - `Aggregate.interface.ts` 一 интерфейсы агрегата (например, интерфейс параметров для создания экземпляра агрегата или интерфейс представления агрегата);
359
+ - `Aggregate.test.ts` 一 тесты для агрегата;
360
+ - `fixtures` 一 фикстуры для тестирования агрегата;
361
+ - `index.ts` 一 реэкспорт агрегата и его интерфейсов;
362
+ - `ports` 一 каталог, который содержит интерфейсы для всех необходимых логике портов;
363
+ - `repository.ts` 一 файл с интерфейсом необходимого репозитория для хранения агрегатов (для примера);
364
+ - `index.ts` 一 реэкспорт портов и его интерфейсов;
365
+ - `methods` 一 каталог с синхронными методами сервиса (генерируется автоматически);
366
+ - `Method_1` 一 каталог метода;
367
+ - `index.ts` 一 класс метода;
368
+ - `index.test.ts` 一 тесты для метода;
369
+ - `repository` 一 реализация репозитория на основе порта;
370
+ - `index.ts` 一 файл клиента сервиса (генерируется автоматически);
371
+ - `interfaces.ts` 一 интерфейсы сервиса (генерируется автоматически);
372
+ - `service.ts` 一 реализация сервиса (генерируется автоматически);
373
+ - `start.ts` 一 точка входа для запуска сервиса (генерируется автоматически);
374
+ - `inversion.types.ts` 一 Типы зависимостей используемые в логике сервиса. Типы используются для получения зависимости. Реализация требуемой зависимости привязывается к контейнеру через тип в файле сервиса. [Описание встроенных возможностей инверсии зависимостей](#инверсия-зависимостей-и-di-контейнер).
375
+ - `service.schema.json` 一 описание сервиса.
376
+
377
+ Вся бизнес-логика сконцентрирована в двух местах структуры:
378
+
379
+ - Агрегаты предметной области. В методах агрегатов содержится чистая бизнес-логика.
380
+ - Методы сервиса. Методы содержат часть бизнес-логики сервиса и конкретного метода сервиса, а также служат связующим звеном бизнес-логики агрегата и портов.
108
381
 
109
382
  ## Пример использования
110
383
 
111
- Пример использования инструментов тулкита находится в папке **exaples**
384
+ Пример использования инструментов тулкита находится в каталоге `examples`.
385
+
386
+ Все три сервиса созданы для реализации тестовой логики "Странная сумма":
387
+
388
+ 1. Во вход необходимо передать два числа `a` и `b`.
389
+ 2. На первом этапе логика сервисов сложит эти два числа между собой. Полученная сумма будет использована в качестве максимального количества чисел из ряда Фибоначчи.
390
+ 3. На последнем этапе, получив последовательность чисел, логика сложит их между собой и вернет ответ.
112
391
 
113
- В результате запросов к тестовым сервисам генерируются трассировки следующего вида
392
+ ### Описание каталога `examples`
393
+
394
+ 1. `HttpGate` 一 cервис предоставляет http api с одним маршрутом `POST /math/weird/sum`. В качестве тела запроса необходимо передать json. Например:
395
+
396
+ ```json
397
+ {
398
+ "a": 5,
399
+ "b": 5
400
+ }
401
+ ```
402
+
403
+ После получения запроса сервис `HttpGate` синхронно через брокер вызывает сервис `Logic` и, получив от него ответ, возвращает результат в качестве ответа на запрос.
404
+
405
+ 2. `LogicService` 一 сервис реализует логику "Странной суммы". Сам сервис ничего не вычисляет, а использует другой сервис `MathService`:
406
+
407
+ - Получив два числа от `HttpGate`, `LogicService` синхронно вызывает метод сервиса `Math.sum`, который складывает два переданных числа.
408
+ - Затем сервис вызывает метод `Math.Fibonnacci`, в который передает результат предыдущего действия и в качестве ответа получает поток с числами Фибоначчи.
409
+ - Получив поток чисел, сервис передает этот поток в метод `Math.SumStream`, который складывает все числа в потоке и в ответе возвращает одно число, которое и является "Странной суммой".
410
+ - В конце последней операции сервис генерирует событие `Elapsed`, в которое передает затраченное на выполнение вычислений время.
411
+
412
+ 3. `MathService` 一 сервис реализует 3 метода: `Sum`, `Fibonacci` и `SumStream`, описанные выше. Помимо этих методов, сервис генерирует также два события:
413
+
414
+ - При вызове метода `SumStream` сервис генерирует обычное событие `Notify`.
415
+ - После завершения вычислений сервис генерирует событие `Elapsed`, в которое передает затраченное на выполнение вычислений время. Событие `Elapsed` описано как Jet-stream.
416
+
417
+ В результате запросов к тестовым сервисам генерируются трассировки следующего вида:
114
418
 
115
419
  ![Таймлайн](./examples/misc/trace_1.png)
116
420
 
117
421
  ![Таймлайн](./examples/misc/trace_1.png)
118
422
 
119
- ## Описание переменных окружения
120
423
 
121
- - **DEFAUL_RESPONSE_TIMEOUT** - Внешнее ограничение таймаута при запросе в секундах. Используется при первоначальном формировании времени таймаута в багаже по формуле *Date.now() + DEFAULT_RESPONSE_TIMEOUT*
424
+ ## Сворачивание сервисов в монолитное приложение
425
+
426
+ Библиотека поддерживает возможность сворачивать микросервисы в одно монолитное приложение. Чтобы реализовать эту возможность, необходимо придерживаться [рекомендаций](#рекомендации).
427
+
428
+ Для сворачивания в монолит необходимо использовать отдельную точку входа в приложение. Она должна находиться в сервисе, предоставляющем внешнее API к методам приложения.
122
429
 
123
- - **OTEL_AGENT** - Хост агента по сбору распределенных трассировок.
430
+ Логика точки входа в монолитную версию приложения:
431
+ - Создается экземпляр сервиса без передачи в него подключения к NATS. В таком случае вместо NATS в качестве брокера будет использована внутренняя реализация брокера на основе встроенного объекта `EventEmitter`. Доступ в созданному брокеру можно получить через открытое свойство сервиса `broker`.
432
+ - После создания корневого сервиса необходимо запустить остальные сервисы, передав полученный брокер корневого сервиса. За счет этого все сервисы приложения будут использовать один внутренний брокер. При создании клиентов и при использовании инъекций также будет использован этот брокер. Единый внутренний брокер свяжет дерево сервисов в одно приложение и позволит запустить весь код сервисной архитектуры в монолитном режиме.
433
+
434
+ Пример точки входа для монолитного режима и скрипт сборки можно посмотреть в каталоге `examples`: [точка входа](./examples/HttpGate/start.mono.ts).
435
+
436
+ ```
437
+ ┌───────────┐
438
+ │ HTTP_GATE │
439
+ └─────┬─────┘
440
+ ┌─────────┴─────────┐
441
+ ┌───┴───┐ ┌─────┴─────┐
442
+ │ Logic │ │ Service_1 │
443
+ └───┬───┘ └─────┬─────┘
444
+ │ ┌──────┴───────┐
445
+ ┌──┴───┐ ┌─────┴─────┐ ┌─────┴─────┐
446
+ │ Math │ │ Service_2 │ │ Service_3 │
447
+ └──────┘ └───────────┘ └───────────┘
448
+ ```
449
+
450
+ ## Инверсия зависимостей и DI-контейнер
451
+
452
+ Библиотека реализует возможности по инверсии зависимостей через DI-контейнер. Экземпляр контейнера можно получить импортировав его из библиотеки. Для описания существующих ключей зависимостей рекомендуется использовать отдеьный файл `inversion.types.ts` в корне сервиса. [Пример файла](./examples/LogicService/inversion.types.ts). Для внедрения зависимостей используются свойства класса метода или параметры конструктора. Для описания зависимости используется декоратор `inject`, который можно испортировать из библиотеки. В декоратор необходимо передать символьный ключ из файла `inversion.types.ts`. Саму привязку реализаций к DI-контейнеру рекомендуется осуществлять в основном файле сервиса `service.ts`. Пример с глубоковложенными зависимостями разных типов можно [посмотреть в методе](./examples/LogicService/methods/GetUser.ts). Цепочка внедряемых зависимостей.
453
+
454
+ ```
455
+ ┌---------┐ ┌───────────-┐ ┌───────────---┐ ┌---------┐
456
+ | GetUser |--->│ Repository |--->| Configurator |--->| Storage |
457
+ └---------┘ └─────-─────-┘ └─────-─────---┘ └---------┘
458
+ ```