@lad-tech/nsc-toolkit 1.12.1 → 1.13.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 (45) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/README.md +167 -158
  3. package/dist/Container.js +30 -4
  4. package/dist/Container.js.map +1 -1
  5. package/dist/interfaces.js.map +1 -1
  6. package/dist/types/Container.d.ts +14 -3
  7. package/dist/types/interfaces.d.ts +3 -0
  8. package/package.json +1 -1
  9. package/.eslintrc.json +0 -104
  10. package/.github/workflows/main_workflow.yml +0 -40
  11. package/.prettierrc.json +0 -9
  12. package/.releaserc +0 -12
  13. package/coverage/clover.xml +0 -1014
  14. package/coverage/coverage-final.json +0 -36
  15. package/coverage/lcov-report/base.css +0 -224
  16. package/coverage/lcov-report/block-navigation.js +0 -87
  17. package/coverage/lcov-report/examples/LogicService/adapters/AuthToolkit.ts.html +0 -130
  18. package/coverage/lcov-report/examples/LogicService/adapters/Configurator.ts.html +0 -130
  19. package/coverage/lcov-report/examples/LogicService/adapters/Repository.ts.html +0 -136
  20. package/coverage/lcov-report/examples/LogicService/adapters/index.html +0 -161
  21. package/coverage/lcov-report/examples/LogicService/adapters/index.ts.html +0 -91
  22. package/coverage/lcov-report/examples/LogicService/index.html +0 -146
  23. package/coverage/lcov-report/examples/LogicService/index.ts.html +0 -208
  24. package/coverage/lcov-report/examples/LogicService/inversion.types.ts.html +0 -106
  25. package/coverage/lcov-report/examples/LogicService/methods/GetUser.ts.html +0 -151
  26. package/coverage/lcov-report/examples/LogicService/methods/GetUserV2.ts.html +0 -160
  27. package/coverage/lcov-report/examples/LogicService/methods/RegisterNewUser.ts.html +0 -148
  28. package/coverage/lcov-report/examples/LogicService/methods/WeirdSum.ts.html +0 -148
  29. package/coverage/lcov-report/examples/LogicService/methods/index.html +0 -161
  30. package/coverage/lcov-report/examples/LogicService/service.ts.html +0 -202
  31. package/coverage/lcov-report/examples/MathService/index.html +0 -131
  32. package/coverage/lcov-report/examples/MathService/index.ts.html +0 -148
  33. package/coverage/lcov-report/examples/MathService/methods/Fibonacci.ts.html +0 -169
  34. package/coverage/lcov-report/examples/MathService/methods/Sum.ts.html +0 -133
  35. package/coverage/lcov-report/examples/MathService/methods/SumStream.ts.html +0 -190
  36. package/coverage/lcov-report/examples/MathService/methods/index.html +0 -146
  37. package/coverage/lcov-report/examples/MathService/service.ts.html +0 -145
  38. package/coverage/lcov-report/favicon.png +0 -0
  39. package/coverage/lcov-report/index.html +0 -236
  40. package/coverage/lcov-report/prettify.css +0 -1
  41. package/coverage/lcov-report/prettify.js +0 -2
  42. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  43. package/coverage/lcov-report/sorter.js +0 -196
  44. package/coverage/lcov.info +0 -1919
  45. package/tsconfig.json +0 -19
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- ## [1.12.1](https://github.com/lad-tech/nsc-toolkit/compare/v1.12.0...v1.12.1) (2023-08-07)
1
+ # [1.13.0](https://github.com/lad-tech/nsc-toolkit/compare/v1.12.1...v1.13.0) (2023-08-09)
2
2
 
3
3
 
4
- ### Bug Fixes
4
+ ### Features
5
5
 
6
- * Обработка строковых форматов сообщений ([#63](https://github.com/lad-tech/nsc-toolkit/issues/63)) ([8f89cd7](https://github.com/lad-tech/nsc-toolkit/commit/8f89cd78bd35babd58951103e366dcdcb0dc26fc))
6
+ * New options for adapter dependency ([#65](https://github.com/lad-tech/nsc-toolkit/issues/65)) ([49f0239](https://github.com/lad-tech/nsc-toolkit/commit/49f02393cadda967626542b14a72087a3d684b4e))
package/README.md CHANGED
@@ -95,203 +95,212 @@ npm i
95
95
 
96
96
  1. Файл `service.schema.json`. Каждый сервис описывается в формате json.
97
97
 
98
- Ниже представлена схема описания.
98
+ Ниже представлена схема описания.
99
99
 
100
- ```json
101
- {
102
- "$schema": "http://json-schema.org/draft-04/schema#",
103
- "type": "object",
104
- "properties": {
105
- "name": {
106
- "type": "string"
107
- },
108
- "description": {
109
- "type": "string"
110
- },
111
- "methods": {
112
- "type": "object",
113
- "additionalProperties": {
114
- "type": "object",
115
- "properties": {
116
- "action": { "type": "string" },
117
- "description": { "type": "string" },
118
- "options": { "$ref": "#/$defs/options" },
119
- "request": { "type": "object" },
120
- "response": { "type": "object" }
121
- },
122
- "required": ["action", "description", "options"]
123
- }
124
- },
125
- "events": {
100
+ ```json
101
+ {
102
+ "$schema": "http://json-schema.org/draft-04/schema#",
126
103
  "type": "object",
127
104
  "properties": {
128
- "list": {
105
+ "name": {
106
+ "type": "string"
107
+ },
108
+ "description": {
109
+ "type": "string"
110
+ },
111
+ "methods": {
129
112
  "type": "object",
130
113
  "additionalProperties": {
131
114
  "type": "object",
132
115
  "properties": {
133
116
  "action": { "type": "string" },
134
- "options": {
135
- "type": "object",
136
- "properties": {
137
- "stream": { "type": "boolean" }
138
- },
139
- },
140
117
  "description": { "type": "string" },
141
- "event": { "type": "object" }
118
+ "options": { "$ref": "#/$defs/options" },
119
+ "request": { "type": "object" },
120
+ "response": { "type": "object" }
142
121
  },
143
- "required": ["action", "description", "event"]
144
- },
122
+ "required": ["action", "description", "options"]
123
+ }
145
124
  },
146
- "streamOptions": {
125
+ "events": {
147
126
  "type": "object",
148
127
  "properties": {
149
- "prefix": { "type": "string" },
150
- "actions": {
151
- "type": "array",
152
- "items": {
128
+ "list": {
129
+ "type": "object",
130
+ "additionalProperties": {
153
131
  "type": "object",
154
132
  "properties": {
155
133
  "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" }
134
+ "options": {
135
+ "type": "object",
136
+ "properties": {
137
+ "stream": { "type": "boolean" }
138
+ },
139
+ },
140
+ "description": { "type": "string" },
141
+ "event": { "type": "object" }
163
142
  },
164
- "required": ["action"]
165
- }
143
+ "required": ["action", "description", "event"]
144
+ },
145
+ },
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"]
166
169
  }
167
170
  },
168
- "required": ["prefix", "actions"]
171
+ "required": ["list"]
169
172
  }
170
173
  },
171
- "required": ["list"]
172
- }
173
- },
174
- "required": ["name", "description", "methods"],
174
+ "required": ["name", "description", "methods"],
175
175
 
176
- "$defs": {
177
- "options": {
178
- "type": "object",
179
- "properties": {
180
- "useStream": {
176
+ "$defs": {
177
+ "options": {
181
178
  "type": "object",
182
179
  "properties": {
183
- "request": { "type": "boolean" },
184
- "response": { "type": "boolean" }
185
- }
186
- },
187
- "cache": { "type": "number" },
188
- "runTimeValidation": {
189
- "type": "object",
190
- "properties": {
191
- "request": { "type": "boolean" },
192
- "response": { "type": "boolean" }
180
+ "useStream": {
181
+ "type": "object",
182
+ "properties": {
183
+ "request": { "type": "boolean" },
184
+ "response": { "type": "boolean" }
185
+ }
186
+ },
187
+ "cache": { "type": "number" },
188
+ "runTimeValidation": {
189
+ "type": "object",
190
+ "properties": {
191
+ "request": { "type": "boolean" },
192
+ "response": { "type": "boolean" }
193
+ }
194
+ }
193
195
  }
194
196
  }
195
197
  }
196
198
  }
197
- }
198
- }
199
- ```
200
-
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
- - настройки стримов для сообщений.
199
+ ```
200
+
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
243
 
244
- Сервис предполагается создавать из описания с помощью кодогенерации. Используется библиотека для кодогенерации сервиса из описания [nsc-cli](https://github.com/lad-tech/nsc-cli).
244
+ Сервис предполагается создавать из описания с помощью кодогенерации. Используется библиотека для кодогенерации сервиса из описания [nsc-cli](https://github.com/lad-tech/nsc-cli).
245
245
 
246
- 2. Класс `Service`. Чтобы создать сервис, необходимо создать экземпляр этого класса и вызвать метод `start`.
246
+ 1. Класс `Service`. Чтобы создать сервис, необходимо создать экземпляр этого класса и вызвать метод `start`.
247
247
 
248
- Принимаемые параметры при создании экземпляра:
248
+ Принимаемые параметры при создании экземпляра:
249
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` 一 время, в рамках которого ожидается штатная остановка сервиса.
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
261
 
262
- Публичные методы:
262
+ Публичные методы:
263
263
 
264
- - `getRootBaggage` 一 получение корневого багажа для распределенной трассировки. Источником могут служить заголовки http-запроса. Если подобные источники отсутствуют, то создается новый корневой багаж.
265
- - `endRootSpan` 一 завершение корневого `Span` по `id` трассировки. Необходим для внедрения распределенных трассировок.
266
- - `buildService` 一 метод, чтобы создать экземпляр клиента. Все используемые при запросах клиенты (сервисы) должны создаваться через этот метод, если необходимо использовать полную функциональность библиотеки.
267
- - `start` 一 запуск сервиса.
268
- - `stop` 一 остановка сервиса.
264
+ - `getRootBaggage` 一 получение корневого багажа для распределенной трассировки. Источником могут служить заголовки http-запроса. Если подобные источники отсутствуют, то создается новый корневой багаж.
265
+ - `endRootSpan` 一 завершение корневого `Span` по `id` трассировки. Необходим для внедрения распределенных трассировок.
266
+ - `buildService` 一 метод, чтобы создать экземпляр клиента. Все используемые при запросах клиенты (сервисы) должны создаваться через этот метод, если необходимо использовать полную функциональность библиотеки.
267
+ - `start` 一 запуск сервиса.
268
+ - `stop` 一 остановка сервиса.
269
269
 
270
- 3. Класс `Client`. Чтобы создать клиент для сервиса, необходимо расширить класс `Client` и описать в нем все доступные извне вызовы методов. Для вызова метода используется приватный метод `CLient.request`. Пример создания клиента можно [посмотреть тут](./examples/MathService/index.ts).
270
+ 2. Класс `Client`. Чтобы создать клиент для сервиса, необходимо расширить класс `Client` и описать в нем все доступные извне вызовы методов. Для вызова метода используется приватный метод `CLient.request`. Пример создания клиента можно [посмотреть тут](./examples/MathService/index.ts).
271
271
 
272
- Публичные методы:
272
+ Публичные методы:
273
273
 
274
- - `getListener` 一 метод получения объекта `EventEmitter` для подписки на события сервиса.
274
+ - `getListener` 一 метод получения объекта `EventEmitter` для подписки на события сервиса.
275
275
 
276
- 4. Класс `Container`. Реализует DI-контейнре. Сам класс не доступен для импорта, а доступен только его экземпляр, что позволяет реализовать шаблон Singlton. В микросервисном варианте контейнер один на сервис. В монолитном варианте использования контейнер один на все приложение. За счет использользования объектов Symbol в качестве ключей для привязки зависимостей исключены коллизии при привязки зависимостей в разных частях приложения через один контейнре. Для привязки зависимости к ключу необходимо указать тип зависимости. Это нужно чтобы библиотека могла корректно создать ээкземпляр зависимости. Всего существуют 3 вида зависимостей:
276
+ 3. Класс `Container`. Реализует DI-контейнре. Сам класс не доступен для импорта, а доступен только его экземпляр, что позволяет реализовать шаблон Singlton. В микросервисном варианте контейнер один на сервис. В монолитном варианте использования контейнер один на все приложение. За счет использользования объектов Symbol в качестве ключей для привязки зависимостей исключены коллизии при привязки зависимостей в разных частях приложения через один контейнре. Для привязки зависимости к ключу необходимо указать тип зависимости. Это нужно чтобы библиотека могла корректно создать ээкземпляр зависимости. Всего существуют 3 вида зависимостей:
277
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-контейнеры.
278
+ - `service` 一 сервис как зависимости.
279
+ - `adapter` 一 класс с набором синхронных или асинхронных методов. Например репозиторий или фасад от стороннего API. Этот тип зависимости можно настроить с помощью необязательного объекта настроек. У опций адаптера могут быть следующие настройки:
280
+ - `singlton` Булевое значение. Если передать `true` то адаптер станет singlton'ом. Объект будет создан один раз и дальше будет всегда использоваться один экземпляр.
281
+ - `init` 一 Булевое значение. Для того что бы использовать этот флаг адаптер должен реализовывать следующий интерфейс
282
+ ```js
283
+ {
284
+ init: () => Promise<any>;
285
+ close: () => Promise<any>;
286
+ }
287
+ ```
288
+ Если адаптер реализует требуемые методы и при передачи флага `init` при привязки адаптера адаптер можно будет инициализировать через контейнер использую метод контейнера `init`. Если к контейнеру было привязано несколько адаптеров, которые необходимо инициализировать, то после вызова метода контейнера `init` все адаптеры будут инициализированны последовательно. Метод инициализации вернет массив инициализированных экземпляров адаптеров. Каждый адаптер с настройкой `init` также становится singlton'ом.
289
+ - `constant`一 обычный объект. Например объект с конфигурацией.
290
+
291
+ Публичные методы:
292
+
293
+ - `bind` 一 привязать реализацию к ключу.
294
+ - `unbind` отвязать реализацию от ключа.
295
+ - `get` 一 получить реализацию по ключу.
296
+ - `getInstance` 一 получить экземпляр реализации. Для зависимости с типом `service` нельзя получить экземпляр через этот метод поскольку для создания экземпляра сервиса требуется контекст в рамках которого он будет работать. Для зависимости с типом `constant` вернется привязанный объект.
297
+
298
+ 4. Декораторы. Применение декораторов:
299
+ * `@service`:
300
+ - Если в методе сервиса вызывается метод другого сервиса, то клиент сервиса зависимости следует подключить через декоратор `@service`, а к самому классу метода применить декоратор `@related`. Тогда при вызове метода сервиса не пропадет контекст запроса и можно будет использовать распределенные трассировки.
301
+ - Инъекция через декоратор `@service` позволяет использовать функциональность сборки приложения в монолит.
302
+ * `@instance`:
303
+ - Используется для инъекции других зависимостей, например, объектов репозиториев. В него можно передать готовый объект с набором асинхронных методов. При вызове этих методов из его логики они будут видны в трассировках. Для получения таких зависимостей рекомендуется использовать DI-контейнеры.
295
304
 
296
305
  ## Рекомендации
297
306
 
package/dist/Container.js CHANGED
@@ -5,6 +5,7 @@ const _1 = require(".");
5
5
  class Container {
6
6
  constructor() {
7
7
  this.container = new Map();
8
+ this.singltons = new Map();
8
9
  }
9
10
  buildDependency(key) {
10
11
  const deepDependency = this.get(key);
@@ -45,11 +46,16 @@ class Container {
45
46
  isConstantDependency(dependency) {
46
47
  return dependency.type === _1.DependencyType.CONSTANT;
47
48
  }
48
- bind(key, type, value) {
49
- this.container.set(key, { type, value });
49
+ bind(key, type, value, options) {
50
+ this.container.set(key, { type, value, options });
50
51
  }
51
- unbind(key) {
52
+ async unbind(key) {
52
53
  this.container.delete(key);
54
+ const instance = this.singltons.get(key);
55
+ if (instance === null || instance === void 0 ? void 0 : instance.init) {
56
+ await instance.value.close();
57
+ }
58
+ this.singltons.delete(key);
53
59
  }
54
60
  get(key) {
55
61
  const dependency = this.container.get(key);
@@ -59,6 +65,7 @@ class Container {
59
65
  return this.inject(dependency);
60
66
  }
61
67
  getInstance(key) {
68
+ var _a, _b, _c;
62
69
  const { dependency, constructor } = this.get(key);
63
70
  if (this.isServiceDependency(dependency)) {
64
71
  throw new Error(`Unable to get service instance`);
@@ -67,10 +74,29 @@ class Container {
67
74
  return dependency.value;
68
75
  }
69
76
  if (this.isAdapterDependency(dependency)) {
70
- return new dependency.value(...constructor);
77
+ if (this.singltons.has(key)) {
78
+ return this.singltons.get(key).value;
79
+ }
80
+ const adapter = new dependency.value(...constructor);
81
+ if (((_a = dependency.options) === null || _a === void 0 ? void 0 : _a.singlton) || ((_b = dependency.options) === null || _b === void 0 ? void 0 : _b.init)) {
82
+ this.singltons.set(key, { value: adapter, init: (_c = dependency.options) === null || _c === void 0 ? void 0 : _c.init });
83
+ }
84
+ return adapter;
71
85
  }
72
86
  return null;
73
87
  }
88
+ async initDependencies() {
89
+ var _a;
90
+ const initialized = [];
91
+ for await (const [key, dependency] of this.container) {
92
+ if (this.isAdapterDependency(dependency) && ((_a = dependency.options) === null || _a === void 0 ? void 0 : _a.init) && !this.singltons.has(key)) {
93
+ const instance = this.getInstance(key);
94
+ await (instance === null || instance === void 0 ? void 0 : instance.init());
95
+ initialized.push(instance);
96
+ }
97
+ }
98
+ return initialized;
99
+ }
74
100
  }
75
101
  exports.container = new Container();
76
102
  //# sourceMappingURL=Container.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Container.js","sourceRoot":"","sources":["../src/Container.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Container.js","sourceRoot":"","sources":["../src/Container.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";AAAA,SAAS;;;AAuKI,QAAA,cAAc,GAAG;IAC5B,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU,EAAE,iBAAiB;CAC/B,CAAC"}
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";AAAA,SAAS;;;AA2KI,QAAA,cAAc,GAAG;IAC5B,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU,EAAE,iBAAiB;CAC/B,CAAC"}
@@ -1,28 +1,39 @@
1
- import { DependencyType, ClientService } from '.';
1
+ import { DependencyType, ClientService, InitializableService } from '.';
2
2
  type Constant = Record<string, any>;
3
3
  type Service<R extends Constant = Constant> = ClientService<R>;
4
4
  export type Adapter<R extends Constant = Constant> = new (...args: any[]) => R;
5
+ export type Singlton = {
6
+ singlton: true;
7
+ };
8
+ export type NeedInit = {
9
+ init: true;
10
+ };
11
+ export type AdapterOptions = Singlton | NeedInit;
5
12
  type Dependency = Service | Adapter | Constant;
6
13
  type ContainerValue = {
7
14
  type: DependencyType;
8
15
  value: Dependency;
16
+ options?: AdapterOptions;
9
17
  };
10
18
  declare class Container {
11
19
  private readonly container;
20
+ private readonly singltons;
12
21
  private buildDependency;
13
22
  private inject;
14
23
  private isServiceDependency;
15
24
  private isAdapterDependency;
16
25
  private isConstantDependency;
17
26
  bind<R extends Record<string, any>>(key: symbol, type: typeof DependencyType.SERVICE, value: ClientService<R>): void;
18
- bind<R extends Record<string, any>>(key: symbol, type: typeof DependencyType.ADAPTER, value: Adapter<R>): void;
27
+ bind<R extends Record<string, any>>(key: symbol, type: typeof DependencyType.ADAPTER, value: Adapter<R>, options?: Singlton): void;
28
+ bind<R extends Record<string, any>>(key: symbol, type: typeof DependencyType.ADAPTER, value: Adapter<R & InitializableService>, options?: NeedInit): void;
19
29
  bind<R extends Record<string, any>>(key: symbol, type: typeof DependencyType.CONSTANT, value: R): void;
20
- unbind(key: symbol): void;
30
+ unbind(key: symbol): Promise<void>;
21
31
  get(key: symbol): {
22
32
  dependency: ContainerValue;
23
33
  constructor: unknown[];
24
34
  };
25
35
  getInstance<R = Constant>(key: symbol): R | null;
36
+ initDependencies(): Promise<InitializableService[]>;
26
37
  }
27
38
  export declare const container: Container;
28
39
  export {};
@@ -134,6 +134,9 @@ export interface CacheService {
134
134
  get: (key: string) => Promise<string | undefined>;
135
135
  delete: (key: string) => Promise<void>;
136
136
  }
137
+ export type InitializableService = GracefulShutdownAdditionalService & {
138
+ init: () => Promise<any>;
139
+ };
137
140
  export type DependencyType = typeof DependencyType[keyof typeof DependencyType];
138
141
  export declare const DependencyType: {
139
142
  readonly SERVICE: "service";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lad-tech/nsc-toolkit",
3
- "version": "1.12.1",
3
+ "version": "1.13.0",
4
4
  "description": "Toolkit for create microservices around NATS",
5
5
  "main": "dist/index.js",
6
6
  "types": "./dist/types/index.d.ts",