@rshval/back-kit 1.1.3 → 1.1.5

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
@@ -1,148 +1,187 @@
1
1
  # @rshval/back-kit
2
2
 
3
- Публичный npm-пакет `@rshval/back-kit` с серверными утилитами для Node.js/TypeScript проектов.
3
+ Public npm package `@rshval/back-kit` with server-side utilities for Node.js/TypeScript projects.
4
4
 
5
- > Репозиторий используется для внутренних проектов автора. Любое использование третьими лицами выполняется на их страх и риск.
5
+ > This repository is used for the author's internal projects. Any third-party usage is at your own risk.
6
6
 
7
- ## Установка
7
+ ## Installation
8
8
 
9
9
  ```bash
10
10
  npm i @rshval/back-kit
11
11
  ```
12
12
 
13
- Пакет ESM-only (`"type": "module"`). Для CommonJS используйте динамический `import()`.
13
+ The package is ESM-only (`"type": "module"`). For CommonJS, use dynamic `import()`.
14
+
15
+ ## Quick navigation
16
+
17
+ - [Email](#1-email)
18
+ - [Config and JWT](#2-config-and-jwt)
19
+ - [Helper utilities](#3-helper-utilities)
20
+ - [Validation](#4-validation)
21
+ - [Builders](#5-builders-config-bound)
22
+ - [Database](#6-database)
23
+ - [Cache](#7-cache)
24
+ - [Logging](#8-logging)
25
+ - [WebSocket client](#9-websocket-client)
26
+ - [Paymaster](#10-paymaster)
27
+ - [Mail templates](#11-mail-templates)
28
+ - [Audit changes](#12-audit-changes)
29
+ - [Seed functions](#13-seed-functions)
30
+ - [API client](#14-api-client)
14
31
 
15
32
  ---
16
33
 
17
- ## Все экспортируемые функции и примеры использования
34
+ ## API and usage examples
18
35
 
19
- Ниже перечислены все публичные экспорты из пакета (через `src/index.ts`) и короткие примеры.
36
+ Below are the public exports from the package (via `src/index.ts`) with short examples. For key APIs, there are separate **production examples** that show practical integration patterns for real services.
20
37
 
21
38
  ### 1) Email
22
39
 
23
40
  #### `createMailOptions({ from, to, subject, text })`
24
- Создаёт объект параметров письма для nodemailer. Поддерживает `to` как строку (обычная отправка) или объект формы (`MailOptionsBody`) для заявок/обратной связи.
41
+
42
+ Creates a nodemailer mail options object. Supports `to` as a string (regular send) or a form object (`MailOptionsBody`) for requests/feedback scenarios.
25
43
 
26
44
  ```ts
27
- import { createMailOptions } from '@rshval/back-kit'
45
+ import { createMailOptions } from '@rshval/back-kit';
28
46
 
29
47
  const options = createMailOptions({
30
48
  from: 'robot@example.com',
31
49
  to: 'user@example.com',
32
50
  subject: 'Hello',
33
- text: 'Welcome!'
34
- })
51
+ text: 'Welcome!',
52
+ });
35
53
  ```
36
54
 
37
55
  #### `sendEmailWithConfig({ nodemailerConfig, to, subject, text })`
38
- Создаёт transport через nodemailer, отправляет письмо и возвращает строку с результатом отправки.
56
+
57
+ Creates a nodemailer transport, sends an email, and returns a string with the send result.
39
58
 
40
59
  ```ts
41
- import { sendEmailWithConfig } from '@rshval/back-kit'
60
+ import { sendEmailWithConfig } from '@rshval/back-kit';
42
61
 
43
62
  await sendEmailWithConfig({
44
63
  nodemailerConfig: {
45
64
  host: 'smtp.example.com',
46
65
  port: 465,
47
66
  secure: true,
48
- auth: { user: 'robot@example.com', pass: '***' }
67
+ auth: { user: 'robot@example.com', pass: '***' },
49
68
  },
50
69
  to: 'user@example.com',
51
70
  subject: 'Reset password',
52
- text: 'Code: 123456'
53
- })
71
+ text: 'Code: 123456',
72
+ });
73
+ ```
74
+
75
+ **Production example**:
76
+
77
+ ```ts
78
+ import { buildSendEmail } from '@rshval/back-kit';
79
+
80
+ const sendEmailWithConfig = buildSendEmail(runtimeConfig);
81
+ await sendEmailWithConfig(to, subject, text);
54
82
  ```
55
83
 
56
84
  ---
57
85
 
58
- ### 2) Конфиг и JWT
86
+ ### 2) Config and JWT
59
87
 
60
88
  #### `getBaseUrlByConfig(config, baseUrl?)`
61
- Строит base URL по конфигу приложения. В `development` добавляет `:port`.
89
+
90
+ Builds a base URL from app config. In `development`, adds `:port`.
62
91
 
63
92
  ```ts
64
- import { getBaseUrlByConfig } from '@rshval/back-kit'
93
+ import { getBaseUrlByConfig } from '@rshval/back-kit';
65
94
 
66
95
  const base = getBaseUrlByConfig(
67
96
  {
68
97
  NODE_ENV: 'development',
69
98
  server: { domain: 'localhost', port: 3000 },
70
- jwt: {}
99
+ jwt: {},
71
100
  },
72
- '/api'
73
- )
101
+ '/api',
102
+ );
74
103
  // //localhost:3000/api
75
104
  ```
76
105
 
77
106
  #### `createTokenByConfig({ config, user, expiresIn })`
78
- Создаёт JWT-токен на основе `config.jwt.JWT_KEY` (или `JWT_KEY_NO_ENV`).
107
+
108
+ Creates a JWT token based on `config.jwt.JWT_KEY` (or `JWT_KEY_NO_ENV`).
79
109
 
80
110
  ```ts
81
- import { createTokenByConfig } from '@rshval/back-kit'
111
+ import { createTokenByConfig } from '@rshval/back-kit';
82
112
 
83
113
  const token = createTokenByConfig({
84
114
  config: {
85
115
  server: { domain: 'example.com' },
86
- jwt: { JWT_KEY: 'super-secret' }
116
+ jwt: { JWT_KEY: 'super-secret' },
87
117
  },
88
118
  user: { _id: '64a...' },
89
- expiresIn: '7d'
90
- })
119
+ expiresIn: '7d',
120
+ });
91
121
  ```
92
122
 
93
123
  ---
94
124
 
95
- ### 3) Вспомогательные утилиты
125
+ ### 3) Helper utilities
96
126
 
97
127
  #### `createPinCode(min?, max?)`
98
- Генерирует случайный числовой PIN в диапазоне (`10000..99990` по умолчанию).
128
+
129
+ Generates a random numeric PIN in range (`10000..99990` by default).
99
130
 
100
131
  ```ts
101
- import { createPinCode } from '@rshval/back-kit'
132
+ import { createPinCode } from '@rshval/back-kit';
102
133
 
103
- const pin = createPinCode()
134
+ const pin = createPinCode();
104
135
  ```
105
136
 
106
137
  #### `getIp(req)`
107
- Пытается определить IP клиента из `req.ip`, сокетов и `x-forwarded-for`.
138
+
139
+ Attempts to detect client IP from `req.ip`, sockets, and `x-forwarded-for`.
108
140
 
109
141
  ```ts
110
- import { getIp } from '@rshval/back-kit'
142
+ import { getIp } from '@rshval/back-kit';
111
143
 
112
- const ip = await getIp(req)
144
+ const ip = await getIp(req);
113
145
  ```
114
146
 
115
147
  #### `translitUrl(str)`
116
- Транслитерирует строку в URL-friendly slug (`-`, lower-case).
148
+
149
+ Transliterates a string into a URL-friendly slug (`-`, lower-case).
117
150
 
118
151
  ```ts
119
- import { translitUrl } from '@rshval/back-kit'
152
+ import { translitUrl } from '@rshval/back-kit';
120
153
 
121
- const slug = translitUrl('Пример страницы')
154
+ const slug = translitUrl('Page example');
122
155
  // primer-stranicy
123
156
  ```
124
157
 
125
158
  ---
126
159
 
127
- ### 4) Валидация
160
+ ### 4) Validation
128
161
 
129
162
  #### `patternEmail()`
130
- Возвращает RegExp для проверки email.
163
+
164
+ Returns a RegExp for email validation.
131
165
 
132
166
  #### `patternPassword()`
133
- Возвращает RegExp для пароля (минимум 8 символов, буквы + цифры).
167
+
168
+ Returns a RegExp for password validation (at least 8 chars, letters + digits).
134
169
 
135
170
  #### `isValidEmail(val)`
136
- Проверяет корректность email.
171
+
172
+ Checks whether an email is valid.
137
173
 
138
174
  #### `isValidPhoneNumber(val)`
139
- Проверяет номер телефона через `libphonenumber-js`.
175
+
176
+ Validates a phone number via `libphonenumber-js`.
140
177
 
141
178
  #### `isValidCode(code, length)`
142
- Проверяет длину кода.
179
+
180
+ Checks code length.
143
181
 
144
182
  #### `isEmpty(val)`
145
- Проверяет пустую строку (`trim`) или пустой объект.
183
+
184
+ Checks for an empty string (`trim`) or an empty object.
146
185
 
147
186
  ```ts
148
187
  import {
@@ -151,152 +190,196 @@ import {
151
190
  isValidEmail,
152
191
  isValidPhoneNumber,
153
192
  isValidCode,
154
- isEmpty
155
- } from '@rshval/back-kit'
193
+ isEmpty,
194
+ } from '@rshval/back-kit';
156
195
 
157
- const emailRegex = patternEmail()
158
- const passwordRegex = patternPassword()
196
+ const emailRegex = patternEmail();
197
+ const passwordRegex = patternPassword();
159
198
 
160
- isValidEmail('user@example.com') // true
161
- isValidPhoneNumber('+79991234567') // true/false
162
- isValidCode('123456', 6) // true
163
- isEmpty(' ') // true
164
- isEmpty({}) // true
199
+ isValidEmail('user@example.com'); // true
200
+ isValidPhoneNumber('+79991234567'); // true/false
201
+ isValidCode('123456', 6); // true
202
+ isEmpty(' '); // true
203
+ isEmpty({}); // true
165
204
  ```
166
205
 
167
206
  ---
168
207
 
169
- ### 5) Билдеры (привязка к конфигу)
208
+ ### 5) Builders (config-bound)
170
209
 
171
210
  #### `buildGetBaseUrl(config)`
172
- Возвращает функцию `(baseUrl?) => string`.
211
+
212
+ Returns a function `(baseUrl?) => string`.
173
213
 
174
214
  #### `buildCreateToken(config)`
175
- Возвращает функцию создания JWT с уже «зашитым» конфигом.
215
+
216
+ Returns a JWT creator function with pre-bound config.
176
217
 
177
218
  #### `buildSendEmail(nodemailerConfig)`
178
- Возвращает функцию отправки email с уже «зашитым» SMTP-конфигом.
219
+
220
+ Returns an email sender function with pre-bound SMTP config.
179
221
 
180
222
  ```ts
181
223
  import {
182
224
  buildGetBaseUrl,
183
225
  buildCreateToken,
184
- buildSendEmail
185
- } from '@rshval/back-kit'
226
+ buildSendEmail,
227
+ } from '@rshval/back-kit';
186
228
 
187
229
  const getBaseUrl = buildGetBaseUrl({
188
230
  NODE_ENV: 'production',
189
231
  server: { domain: 'example.com' },
190
- jwt: { JWT_KEY: 'secret' }
191
- })
232
+ jwt: { JWT_KEY: 'secret' },
233
+ });
192
234
 
193
235
  const createToken = buildCreateToken({
194
236
  server: { domain: 'example.com' },
195
- jwt: { JWT_KEY: 'secret' }
196
- })
237
+ jwt: { JWT_KEY: 'secret' },
238
+ });
197
239
 
198
240
  const sendEmail = buildSendEmail({
199
241
  host: 'smtp.example.com',
200
242
  port: 465,
201
243
  secure: true,
202
- auth: { user: 'robot@example.com', pass: '***' }
203
- })
244
+ auth: { user: 'robot@example.com', pass: '***' },
245
+ });
204
246
  ```
205
247
 
206
248
  ---
207
249
 
208
- ### 6) База данных
250
+ ### 6) Database
209
251
 
210
252
  #### `startMongoDatabase(options)`
211
- Запускает подключение к MongoDB через mongoose, логирует статусы и умеет ретраить подключение.
253
+
254
+ Starts MongoDB connection via mongoose, logs statuses, and supports connection retries.
212
255
 
213
256
  ```ts
214
- import { startMongoDatabase } from '@rshval/back-kit'
257
+ import { startMongoDatabase } from '@rshval/back-kit';
215
258
 
216
259
  await startMongoDatabase({
217
260
  config: {
218
261
  name: 'main',
219
262
  connect: process.env.MONGO_URI,
220
- params: {}
263
+ params: {},
221
264
  },
222
- logger: console
223
- })
265
+ logger: console,
266
+ });
267
+ ```
268
+
269
+ **Production example**:
270
+
271
+ ```ts
272
+ await startMongoDatabase({
273
+ config: config.database,
274
+ logger,
275
+ setCacheStatus: (status) =>
276
+ cache.set(cacheIdDatabase, { status }, undefined, undefined, cacheTtl30m),
277
+ });
224
278
  ```
225
279
 
226
280
  ---
227
281
 
228
- ### 7) Кэш
282
+ ### 7) Cache
229
283
 
230
284
  #### `createCacheService(options?)`
231
- Создаёт LRU cache-сервис с методами:
285
+
286
+ Creates an LRU cache service with methods:
287
+
232
288
  - `get(key)`
233
289
  - `set(key, data, compareKey?, compareValue?, ttlMs?)`
234
290
  - `delete(key)`
235
291
  - `getId(val)`
236
292
  - `keys()`
237
293
  - `clear()`
238
- - `entries()` *(если `exposeEntries: true`)*
239
- - `values()` *(если `exposeValues: true`)*
294
+ - `entries()` _(if `exposeEntries: true`)_
295
+ - `values()` _(if `exposeValues: true`)_
240
296
 
241
297
  ```ts
242
- import { createCacheService } from '@rshval/back-kit'
298
+ import { createCacheService } from '@rshval/back-kit';
243
299
 
244
- const cache = createCacheService({ ttl: 60_000 })
245
- const key = cache.getId({ service: 'users', page: 1 })
246
- await cache.set(key, [{ s: 'state', data: [1, 2, 3] }])
247
- const value = await cache.get(key)
300
+ const cache = createCacheService({ ttl: 60_000 });
301
+ const key = cache.getId({ service: 'users', page: 1 });
302
+ await cache.set(key, [{ s: 'state', data: [1, 2, 3] }]);
303
+ const value = await cache.get(key);
248
304
  ```
249
305
 
250
306
  #### `createCacheMiddleware({ cache, ... })`
251
- Создаёт middleware-обёртку над cache-сервисом с методами:
307
+
308
+ Creates a middleware wrapper over the cache service with methods:
309
+
252
310
  - `get(id)`
253
311
  - `set(id, data, expDataTime)`
254
312
  - `del(id)`
255
- - `delByPrefix(prefix)` *(если `includeDelByPrefix: true`)*
313
+ - `delByPrefix(prefix)` _(if `includeDelByPrefix: true`)_
256
314
 
257
315
  ```ts
258
- import { createCacheService, createCacheMiddleware } from '@rshval/back-kit'
316
+ import { createCacheService, createCacheMiddleware } from '@rshval/back-kit';
259
317
 
260
- const cache = createCacheService({ supportTtlInSet: true })
318
+ const cache = createCacheService({ supportTtlInSet: true });
261
319
  const cm = createCacheMiddleware({
262
320
  cache,
263
321
  passTtlToCacheSet: true,
264
- includeDelByPrefix: true
265
- })
322
+ includeDelByPrefix: true,
323
+ });
266
324
 
267
- await cm.set('users:list', [{ id: 1 }], 60_000)
268
- const cached = await cm.get('users:list')
269
- await cm.delByPrefix?.('users:')
325
+ await cm.set('users:list', [{ id: 1 }], 60_000);
326
+ const cached = await cm.get('users:list');
327
+ await cm.delByPrefix?.('users:');
328
+ ```
329
+
330
+ **Production example**:
331
+
332
+ ```ts
333
+ const cache = createCacheService({ supportTtlInSet: true });
334
+ const cacheMiddleware = createCacheMiddleware({
335
+ cache,
336
+ passTtlToCacheSet: true,
337
+ includeDelByPrefix: true,
338
+ });
339
+
340
+ export const { get, set, del } = cacheMiddleware;
341
+ export const delByPrefix = cacheMiddleware.delByPrefix!;
270
342
  ```
271
343
 
272
344
  ---
273
345
 
274
- ### 8) Логирование
346
+ ### 8) Logging
275
347
 
276
348
  #### `createLoggerService({ rootdir? })`
277
- Возвращает фабрику логгеров. Для каждого namespace (`std`) пишет:
349
+
350
+ Returns a logger factory. For each namespace (`std`) it writes:
351
+
278
352
  - `logs/<std>/stdout.log`
279
353
  - `logs/<std>/stderr.log`
280
354
 
281
355
  ```ts
282
- import { createLoggerService } from '@rshval/back-kit'
356
+ import { createLoggerService } from '@rshval/back-kit';
283
357
 
284
- const makeLogger = createLoggerService({ rootdir: process.cwd() })
285
- const logger = makeLogger('api')
286
- logger.log('started')
358
+ const makeLogger = createLoggerService({ rootdir: process.cwd() });
359
+ const logger = makeLogger('api');
360
+ logger.log('started');
361
+ ```
362
+
363
+ **Production example**:
364
+
365
+ ```ts
366
+ const loggerService = createLoggerService();
367
+ const logger = loggerService('api');
287
368
  ```
288
369
 
289
370
  ---
290
371
 
291
- ### 9) WebSocket клиент
372
+ ### 9) WebSocket client
292
373
 
293
374
  #### `createSocketClientService(options)`
294
- Создаёт сервис клиента `socket.io` с методами:
295
- - `doSocketClient()` старт подключения
296
- - `getSocketClient()` — вернуть текущий инстанс
375
+
376
+ Creates a `socket.io` client service with methods:
377
+
378
+ - `doSocketClient()` — start connection
379
+ - `getSocketClient()` — return current instance
297
380
 
298
381
  ```ts
299
- import { createSocketClientService } from '@rshval/back-kit'
382
+ import { createSocketClientService } from '@rshval/back-kit';
300
383
 
301
384
  const ws = createSocketClientService({
302
385
  wsName: 'worker',
@@ -304,10 +387,24 @@ const ws = createSocketClientService({
304
387
  logger: console,
305
388
  runWorkers: () => {
306
389
  // jobs
307
- }
308
- })
390
+ },
391
+ });
392
+
393
+ ws.doSocketClient();
394
+ ```
309
395
 
310
- ws.doSocketClient()
396
+ **Production example**:
397
+
398
+ ```ts
399
+ const socketClientService = createSocketClientService({
400
+ wsName: config.ws.name,
401
+ socketBase: SOCKET_BASE,
402
+ logger,
403
+ runWorkers: socketClientWorkers,
404
+ socketClientInterval: config.settings.socketClientInterval,
405
+ });
406
+
407
+ socketClientService.doSocketClient();
311
408
  ```
312
409
 
313
410
  ---
@@ -315,44 +412,58 @@ ws.doSocketClient()
315
412
  ### 10) Paymaster
316
413
 
317
414
  #### `createPaymasterService({ paymaster, clientServer, serverBaseUrl })`
318
- Создаёт сервис с методами:
319
- - `createPaymentLink({...})` сформировать ссылку на оплату
320
- - `validateCallback(payload, rawBody?)` — проверить подпись callback
321
- - `parseCallback(payload)` — нормализовать callback в удобный объект
415
+
416
+ Creates a service with methods:
417
+
418
+ - `createPaymentLink({...})` — build payment URL
419
+ - `validateCallback(payload, rawBody?)` — verify callback signature
420
+ - `parseCallback(payload)` — normalize callback into a convenient object
322
421
 
323
422
  ```ts
324
- import { createPaymasterService } from '@rshval/back-kit'
423
+ import { createPaymasterService } from '@rshval/back-kit';
325
424
 
326
425
  const paymaster = createPaymasterService({
327
426
  paymaster: {
328
427
  merchantId: 'merchant-id',
329
428
  secretKey: 'secret',
330
429
  checkoutUrl: 'https://paymaster.ru/Payment/Init',
331
- checkSignature: true
430
+ checkSignature: true,
332
431
  },
333
432
  clientServer: 'https://site.example.com',
334
- serverBaseUrl: 'https://api.example.com'
335
- })
433
+ serverBaseUrl: 'https://api.example.com',
434
+ });
336
435
 
337
436
  const link = paymaster.createPaymentLink({
338
437
  requestId: 'order_123',
339
438
  amount: 1499,
340
- description: 'Order #123'
341
- })
439
+ description: 'Order #123',
440
+ });
441
+ ```
442
+
443
+ **Production example**:
444
+
445
+ ```ts
446
+ export const paymasterService = createPaymasterService({
447
+ paymaster: config.platforms.paymaster,
448
+ clientServer: config.clientServer,
449
+ serverBaseUrl: config.server.baseUrl,
450
+ });
342
451
  ```
343
452
 
344
453
  ---
345
454
 
346
- ### 11) Почтовые шаблоны
455
+ ### 11) Mail templates
347
456
 
348
457
  #### `createMailTemplateService({ findTemplate, sendEmail })`
349
- Создаёт сервис шаблонов email с методами:
350
- - `extractVariables(template)` список `{{variables}}`
351
- - `renderTemplate(template, context?)` — рендер subject/body
352
- - `sendByKey({ key, to, context? })` — найти шаблон, отрендерить и отправить
458
+
459
+ Creates an email template service with methods:
460
+
461
+ - `extractVariables(template)` — list of `{{variables}}`
462
+ - `renderTemplate(template, context?)` — render subject/body
463
+ - `sendByKey({ key, to, context? })` — find template, render, and send
353
464
 
354
465
  ```ts
355
- import { createMailTemplateService } from '@rshval/back-kit'
466
+ import { createMailTemplateService } from '@rshval/back-kit';
356
467
 
357
468
  const mailTemplates = createMailTemplateService({
358
469
  findTemplate: async ({ key }) =>
@@ -360,36 +471,49 @@ const mailTemplates = createMailTemplateService({
360
471
  ? { subject: 'Hi, {{user.name}}', bodyText: 'Hello {{user.name}}!' }
361
472
  : null,
362
473
  sendEmail: async (to, subject, text) => {
363
- console.log('send', to, subject, text)
364
- }
365
- })
474
+ console.log('send', to, subject, text);
475
+ },
476
+ });
366
477
 
367
478
  await mailTemplates.sendByKey({
368
479
  key: 'welcome',
369
480
  to: 'user@example.com',
370
- context: { user: { name: 'Alex' } }
371
- })
481
+ context: { user: { name: 'Alex' } },
482
+ });
483
+ ```
484
+
485
+ **Production example**:
486
+
487
+ ```ts
488
+ const sendEmailWithConfig = buildSendEmail(runtimeConfig);
489
+
490
+ export const mailTemplateService = createMailTemplateService({
491
+ findTemplate: ({ key }) => MailTemplate.findOne({ key, isActive: true }),
492
+ sendEmail: sendEmailWithConfig,
493
+ });
372
494
  ```
373
495
 
374
496
  ---
375
497
 
376
- ### 12) Аудит изменений
498
+ ### 12) Audit changes
377
499
 
378
500
  #### `buildAuditChanges({ beforeData, afterData, fieldsToCheck, protectedFields? })`
379
- Сравнивает данные «до/после» и возвращает массив изменений по выбранным полям.
501
+
502
+ Compares before/after data and returns an array of changes for selected fields.
380
503
 
381
504
  #### `createAuditLog({ ..., save })`
382
- Создаёт запись аудита через переданную функцию `save`. Если изменений нет — возвращает `null`.
505
+
506
+ Creates an audit record via provided `save` function. Returns `null` when no changes exist.
383
507
 
384
508
  ```ts
385
- import { buildAuditChanges, createAuditLog } from '@rshval/back-kit'
509
+ import { buildAuditChanges, createAuditLog } from '@rshval/back-kit';
386
510
 
387
511
  const changes = buildAuditChanges({
388
512
  beforeData: { name: 'Old', role: 'user' },
389
513
  afterData: { name: 'New', role: 'user' },
390
514
  fieldsToCheck: ['name', 'role'],
391
- protectedFields: ['role']
392
- })
515
+ protectedFields: ['role'],
516
+ });
393
517
 
394
518
  await createAuditLog({
395
519
  entityType: 'user',
@@ -397,34 +521,60 @@ await createAuditLog({
397
521
  action: 'update',
398
522
  changedBy: '507f191e810c19729de860ea',
399
523
  changes,
400
- save: async (payload) => payload
401
- })
524
+ save: async (payload) => payload,
525
+ });
526
+ ```
527
+
528
+ **Production example**:
529
+
530
+ ```ts
531
+ await createAuditLog({
532
+ entityType,
533
+ entityId,
534
+ action,
535
+ changedBy,
536
+ changes,
537
+ meta,
538
+ save: async (payload) => AuditLog.create(payload),
539
+ });
402
540
  ```
403
541
 
404
542
  ---
405
543
 
406
- ### 13) Seed-функции
544
+ ### 13) Seed functions
407
545
 
408
546
  #### `createSeedFunctions({ cache, retryDelayMs? })`
409
- Возвращает методы:
410
- - `checkDatabaseIsConnected()` — проверяет состояние БД через кэш
411
- - `setSeedData(SeedModel, arr)` — добавляет seed-данные после подтверждения подключения
547
+
548
+ Returns methods:
549
+
550
+ - `checkDatabaseIsConnected()` — checks DB state via cache
551
+ - `setSeedData(SeedModel, arr)` — inserts seed data after connection check
412
552
 
413
553
  ```ts
414
- import { createSeedFunctions, createCacheService } from '@rshval/back-kit'
554
+ import { createSeedFunctions, createCacheService } from '@rshval/back-kit';
415
555
 
416
- const cache = createCacheService()
417
- const { setSeedData } = createSeedFunctions({ cache })
556
+ const cache = createCacheService();
557
+ const { setSeedData } = createSeedFunctions({ cache });
418
558
 
419
559
  // await setSeedData(UserModel, [{ name: 'Admin' }])
420
560
  ```
421
561
 
562
+ **Production example**:
563
+
564
+ ```ts
565
+ export const { checkDatabaseIsConnected, setSeedData } = createSeedFunctions({
566
+ cache,
567
+ });
568
+ ```
569
+
422
570
  ---
423
571
 
424
- ### 14) API-клиент
572
+ ### 14) API client
425
573
 
426
574
  #### `createApiService({ userAgent, logger? })`
427
- Возвращает HTTP-клиент с методами:
575
+
576
+ Returns an HTTP client with methods:
577
+
428
578
  - `get(path, token?)`
429
579
  - `getXml(path, token?)`
430
580
  - `del(path, token?)`
@@ -432,53 +582,77 @@ const { setSeedData } = createSeedFunctions({ cache })
432
582
  - `put(path, data, token)`
433
583
 
434
584
  ```ts
435
- import { createApiService } from '@rshval/back-kit'
585
+ import { createApiService } from '@rshval/back-kit';
436
586
 
437
- const api = createApiService({ userAgent: 'my-service/1.0.0', logger: console })
587
+ const api = createApiService({
588
+ userAgent: 'my-service/1.0.0',
589
+ logger: console,
590
+ });
438
591
 
439
- const users = await api.get('https://api.example.com/users')
440
- const created = await api.post('https://api.example.com/users', { name: 'Alex' })
592
+ const users = await api.get('https://api.example.com/users');
593
+ const created = await api.post('https://api.example.com/users', {
594
+ name: 'Alex',
595
+ });
441
596
  ```
442
597
 
443
- Также экспортируется тип токена:
598
+ **Production example**:
444
599
 
445
600
  ```ts
446
- import type { Token } from '@rshval/back-kit'
601
+ const apiService = createApiService({
602
+ userAgent: config.api.userAgent,
603
+ logger,
604
+ });
605
+
606
+ export const { get, getXml, del, post, put } = apiService;
607
+ ```
608
+
609
+ Token type is also exported:
610
+
611
+ ```ts
612
+ import type { Token } from '@rshval/back-kit';
447
613
  ```
448
614
 
449
615
  ---
450
616
 
451
- ### 15) Прочие экспортированные утилиты
617
+ ### 15) Other exported utilities
452
618
 
453
619
  #### `add(a, b)`
454
- Возвращает сумму двух чисел.
620
+
621
+ Returns the sum of two numbers.
455
622
 
456
623
  #### `test2()`
457
- Логирует `99` и возвращает `8`.
624
+
625
+ Logs `99` and returns `8`.
458
626
 
459
627
  ```ts
460
- import { add, test2 } from '@rshval/back-kit'
628
+ import { add, test2 } from '@rshval/back-kit';
461
629
 
462
- add(2, 3) // 5
463
- test2() // 8
630
+ add(2, 3); // 5
631
+ test2(); // 8
464
632
  ```
465
633
 
466
634
  ---
467
635
 
468
- ## Подготовка к публикации в npm
636
+ ## Preparing for npm publication
637
+
638
+ See detailed guide: [`docs/publishing.md`](docs/publishing.md).
639
+
640
+ Short wording for npm description:
469
641
 
470
- См. подробную инструкцию: [`docs/publishing.md`](docs/publishing.md).
642
+ - A set of service factories (`create*`, `build*`) and ready-to-use utilities/validators.
643
+ - DI-friendly API: dependencies are injected externally (`logger`, `cache`, `save`, `findTemplate`).
644
+ - Important behavior options (`supportTtlInSet`, `passTtlToCacheSet`, `includeDelByPrefix`) should be documented near examples.
471
645
 
472
646
  ---
473
647
 
474
- ## Разработка (standalone)
648
+ ## Development (standalone)
475
649
 
476
650
  ```bash
477
651
  npm install
478
652
  npm run build
479
653
  ```
480
654
 
481
- ## Экспорты
655
+ ## Exports
482
656
 
483
657
  - ESM: `dist/index.js`
484
- - Типы: `dist/index.d.ts`
658
+ - Types: `dist/index.d.ts`
@@ -1 +1 @@
1
- {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,KAAK,EAAE,MAAM,UAAU,CAAC;AAExD,UAAU,gBAAgB;IACxB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,MAAM,CAAC;IAC1C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CACpC;AAED,UAAU,0BAA0B;IAClC,KAAK,EAAE,gBAAgB,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,mBAAmB,GAAI,0BAGjC,0BAA0B;;6BAwBd,OAAO,KAAK,OAClB,MAAM,EAAE,KACZ,OAAO,CAAC,IAAI,CAAC;CAkDjB,CAAC"}
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,KAAK,EAAE,MAAM,UAAU,CAAC;AAExD,UAAU,gBAAgB;IACxB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,MAAM,CAAC;IAC1C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CACpC;AAED,UAAU,0BAA0B;IAClC,KAAK,EAAE,gBAAgB,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,mBAAmB,GAAI,0BAGjC,0BAA0B;;6BAwBd,OAAO,KAAK,OAClB,MAAM,EAAE,KACZ,OAAO,CAAC,IAAI,CAAC;CAmDjB,CAAC"}
package/dist/seed.js CHANGED
@@ -20,7 +20,10 @@ export const createSeedFunctions = ({ cache, retryDelayMs = 1000, }) => {
20
20
  const setSeedData = async (SeedModel, arr) => {
21
21
  const databaseIsConnected = await checkDatabaseIsConnected();
22
22
  if (databaseIsConnected) {
23
- const spinner = ora(chalk.gray('add seed data - ' + SeedModel.modelName)).start();
23
+ const spinner = ora({
24
+ text: chalk.gray('add seed data - ' + SeedModel.modelName),
25
+ stream: process.stdout,
26
+ }).start();
24
27
  const arrs = [];
25
28
  let done2 = 0;
26
29
  for (let i = 0; i < arr.length; i++) {
package/dist/seed.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"seed.js","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AAatB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,KAAK,EACL,YAAY,GAAG,IAAI,GACQ,EAAE,EAAE;IAC/B,MAAM,wBAAwB,GAAG,KAAK,IAAI,EAAE;QAC1C,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC;YAClC,OAAO,EAAE,UAAU;SACpB,CAAC,CAAC;QAEH,IAAI,kBAAuB,CAAC;QAE5B,IAAI,eAAe,EAAE,CAAC;YACpB,kBAAkB,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACxD,CAAC;QAED,IACE,kBAAkB;YAClB,kBAAkB,CAAC,MAAM;YACzB,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,EAC5C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,EACvB,SAAuB,EACvB,GAAa,EACE,EAAE;QACjB,MAAM,mBAAmB,GAAG,MAAM,wBAAwB,EAAE,CAAC;QAE7D,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,GAAG,CACjB,KAAK,CAAC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC,SAAS,CAAC,CACrD,CAAC,KAAK,EAAE,CAAC;YAIV,MAAM,IAAI,GAAU,EAAE,CAAC;YACvB,IAAI,KAAK,GAAG,CAAC,CAAC;YAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,MAAM,GAAG,GAAQ,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAEf,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;oBAC3B,IAAI,IAAI,GAAG,CAAC,CAAC;oBAEb,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;wBACxB,MAAM,IAAI;6BACP,IAAI,EAAE;6BACN,IAAI,CAAC,GAAG,EAAE;4BACT,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gCAC3B,OAAO,IAAI,CAAC;4BACd,CAAC;wBACH,CAAC,CAAC;6BACD,KAAK,CAAC,GAAG,EAAE;4BACV,OAAO,IAAI,CAAC;wBACd,CAAC,CAAC,CAAC;oBACP,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,OAAO,EAAE,CAAC;YAElB,OAAO;QACT,CAAC;QAED,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;QAE1B,OAAO,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC,CAAC;IAEF,OAAO;QACL,wBAAwB;QACxB,WAAW;KACZ,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"seed.js","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AAatB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,KAAK,EACL,YAAY,GAAG,IAAI,GACQ,EAAE,EAAE;IAC/B,MAAM,wBAAwB,GAAG,KAAK,IAAI,EAAE;QAC1C,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC;YAClC,OAAO,EAAE,UAAU;SACpB,CAAC,CAAC;QAEH,IAAI,kBAAuB,CAAC;QAE5B,IAAI,eAAe,EAAE,CAAC;YACpB,kBAAkB,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACxD,CAAC;QAED,IACE,kBAAkB;YAClB,kBAAkB,CAAC,MAAM;YACzB,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,EAC5C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,EACvB,SAAuB,EACvB,GAAa,EACE,EAAE;QACjB,MAAM,mBAAmB,GAAG,MAAM,wBAAwB,EAAE,CAAC;QAE7D,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,GAAG,CAAC;gBAClB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC,SAAS,CAAC;gBAC1D,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC,KAAK,EAAE,CAAC;YAIX,MAAM,IAAI,GAAU,EAAE,CAAC;YACvB,IAAI,KAAK,GAAG,CAAC,CAAC;YAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,MAAM,GAAG,GAAQ,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAEf,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;oBAC3B,IAAI,IAAI,GAAG,CAAC,CAAC;oBAEb,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;wBACxB,MAAM,IAAI;6BACP,IAAI,EAAE;6BACN,IAAI,CAAC,GAAG,EAAE;4BACT,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gCAC3B,OAAO,IAAI,CAAC;4BACd,CAAC;wBACH,CAAC,CAAC;6BACD,KAAK,CAAC,GAAG,EAAE;4BACV,OAAO,IAAI,CAAC;wBACd,CAAC,CAAC,CAAC;oBACP,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,OAAO,EAAE,CAAC;YAElB,OAAO;QACT,CAAC;QAED,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;QAE1B,OAAO,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC,CAAC;IAEF,OAAO;QACL,wBAAwB;QACxB,WAAW;KACZ,CAAC;AACJ,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rshval/back-kit",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "author": "",
27
27
  "license": "MIT",
28
- "description": "Backend utilities for Node.js services used in rshval monorepos",
28
+ "description": "Backend toolkit of service factories (create*/build*), validators and Node.js API utilities with DI-friendly patterns",
29
29
  "devDependencies": {
30
30
  "@arethetypeswrong/cli": "^0.18.2",
31
31
  "@types/jsonwebtoken": "^9.0.10",