@biorate/nestjs-tools 2.4.0 → 2.5.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.
package/README.md
CHANGED
|
@@ -77,12 +77,12 @@ app.use(ResponseTimeMiddleware.create());
|
|
|
77
77
|
|
|
78
78
|
Config options:
|
|
79
79
|
|
|
80
|
-
| Path
|
|
81
|
-
|
|
82
|
-
| `app.middleware.ResponseTimeMiddleware.suffix` | `true`
|
|
83
|
-
| `app.middleware.ResponseTimeMiddleware.header` | `x-response-time`
|
|
84
|
-
| `app.middleware.ResponseTimeMiddleware.digits` | `3`
|
|
85
|
-
| `app.middleware.ResponseTimeMiddleware.log-base-url` | `false`
|
|
80
|
+
| Path | Default |
|
|
81
|
+
| ---------------------------------------------------- | ----------------------- |
|
|
82
|
+
| `app.middleware.ResponseTimeMiddleware.suffix` | `true` |
|
|
83
|
+
| `app.middleware.ResponseTimeMiddleware.header` | `x-response-time` |
|
|
84
|
+
| `app.middleware.ResponseTimeMiddleware.digits` | `3` |
|
|
85
|
+
| `app.middleware.ResponseTimeMiddleware.log-base-url` | `false` |
|
|
86
86
|
| `ResponseTimeMiddleware.histogram.buckets` | `[0.005, 0.01, … , 10]` |
|
|
87
87
|
|
|
88
88
|
### `ProxyPrometheusMiddleware`
|
|
@@ -92,13 +92,18 @@ Prometheus‑instrumented HTTP proxy via `http-proxy-middleware`.
|
|
|
92
92
|
```ts
|
|
93
93
|
import { ProxyPrometheusMiddleware } from '@biorate/nestjs-tools';
|
|
94
94
|
|
|
95
|
-
consumer
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
consumer
|
|
96
|
+
.apply(
|
|
97
|
+
ProxyPrometheusMiddleware.create({
|
|
98
|
+
target: 'http://upstream.service:8080',
|
|
99
|
+
changeOrigin: true,
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
.forRoutes('/api/v2/legacy');
|
|
99
103
|
```
|
|
100
104
|
|
|
101
105
|
Creates two metrics:
|
|
106
|
+
|
|
102
107
|
- `http_proxy_server_requests_seconds_count` (counter)
|
|
103
108
|
- `http_proxy_server_requests_seconds` (histogram)
|
|
104
109
|
|
|
@@ -145,7 +150,32 @@ incoming.response.data
|
|
|
145
150
|
incoming.response.errorCode
|
|
146
151
|
```
|
|
147
152
|
|
|
148
|
-
Config: `TracingInterceptor.excluded` — array of strings or RegExp to skip URLs
|
|
153
|
+
Config: `TracingInterceptor.excluded` — array of strings or RegExp to skip URLs
|
|
154
|
+
(string entries match by substring inclusion, RegExp entries by test).
|
|
155
|
+
|
|
156
|
+
#### Aspect exclusion
|
|
157
|
+
|
|
158
|
+
Granular control over which span attributes are written:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"TracingInterceptor": {
|
|
163
|
+
"excluded": ["/health"],
|
|
164
|
+
"excludedAttributes": ["response.data"],
|
|
165
|
+
"excludedByURL": [{ "url": "/files", "attributes": ["body", "response"] }]
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
- `TracingInterceptor.excludedAttributes` — string[] of aspects to skip globally.
|
|
171
|
+
- `TracingInterceptor.excludedByURL` — array of `{ url: string | RegExp, attributes: string[] }`
|
|
172
|
+
entries; aspects are skipped only for matching URLs (string entries match by
|
|
173
|
+
substring inclusion, RegExp entries by test).
|
|
174
|
+
- An excluded item also matches aspect groups by prefix: `response` excludes
|
|
175
|
+
`response.headers`, `response.statusCode`, `response.data` and `response.errorCode`.
|
|
176
|
+
- Accepted aliases: `url`, `method`, `headers`, `body`, `params`, `query`
|
|
177
|
+
(→ `incoming.request.*`), `statusCode`, `data`, `errorCode` (→ `incoming.response.*`);
|
|
178
|
+
full names (`request.body`, `response.data`, …) work as-is.
|
|
149
179
|
|
|
150
180
|
### `RoutesInterceptor`
|
|
151
181
|
|
|
@@ -164,7 +194,9 @@ HTTP Basic Authentication guard. Validates `Authorization: Basic …` against co
|
|
|
164
194
|
export class MyController {
|
|
165
195
|
@Get('/admin')
|
|
166
196
|
@AuthBasic()
|
|
167
|
-
public admin() {
|
|
197
|
+
public admin() {
|
|
198
|
+
return 'secret data';
|
|
199
|
+
}
|
|
168
200
|
}
|
|
169
201
|
```
|
|
170
202
|
|
|
@@ -173,13 +205,22 @@ export class MyController {
|
|
|
173
205
|
Bitmask‑based role guard. Use with `@Roles()` decorator:
|
|
174
206
|
|
|
175
207
|
```ts
|
|
208
|
+
import { Controller, Get } from '@nestjs/common';
|
|
176
209
|
import { Roles, UserRoles } from '@biorate/nestjs-tools';
|
|
177
210
|
|
|
178
|
-
@
|
|
179
|
-
|
|
180
|
-
|
|
211
|
+
@Controller()
|
|
212
|
+
export class AdminController {
|
|
213
|
+
@Roles(UserRoles.Admin, UserRoles.Basic)
|
|
214
|
+
@Get('/admin')
|
|
215
|
+
public admin() {
|
|
216
|
+
return 'ok';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
181
219
|
```
|
|
182
220
|
|
|
221
|
+
`Roles(...)` accepts a variadic list of roles (combined into a bitmask via
|
|
222
|
+
bitwise OR internally). Built-in `UserRoles`: `Basic` (`1 << 0`), `Admin` (`1 << 1`).
|
|
223
|
+
|
|
183
224
|
Override `getUser()` to load the user from your database:
|
|
184
225
|
|
|
185
226
|
```ts
|
|
@@ -202,10 +243,10 @@ app.use(BootstrapProvider.create());
|
|
|
202
243
|
|
|
203
244
|
## Decorators
|
|
204
245
|
|
|
205
|
-
| Decorator
|
|
206
|
-
|
|
207
|
-
| `@Roles(...)`
|
|
208
|
-
| `@AuthBasic()
|
|
246
|
+
| Decorator | Composition |
|
|
247
|
+
| -------------- | ------------------------------------------------- |
|
|
248
|
+
| `@Roles(...)` | `SetMetadata(ROLES_KEY, bitmask)` |
|
|
249
|
+
| `@AuthBasic()` | `ApiBasicAuth()` + `UseGuards(AuthGuardProvider)` |
|
|
209
250
|
|
|
210
251
|
## CORS
|
|
211
252
|
|
|
@@ -225,9 +266,9 @@ Exposes `GET /metrics` with Prometheus metrics from the shared registry.
|
|
|
225
266
|
|
|
226
267
|
### `ProbeController`
|
|
227
268
|
|
|
228
|
-
| Route
|
|
229
|
-
|
|
230
|
-
| `GET /probe`
|
|
269
|
+
| Route | Purpose |
|
|
270
|
+
| ------------ | ------------------ |
|
|
271
|
+
| `GET /probe` | Liveness/readiness |
|
|
231
272
|
|
|
232
273
|
### `LocalesController`
|
|
233
274
|
|
|
@@ -11,6 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
|
+
var TracingInterceptor_1;
|
|
14
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
16
|
exports.TracingInterceptor = void 0;
|
|
16
17
|
const json_stringify_safe_1 = __importDefault(require("json-stringify-safe"));
|
|
@@ -18,44 +19,78 @@ const rxjs_1 = require("rxjs");
|
|
|
18
19
|
const opentelemetry_1 = require("@biorate/opentelemetry");
|
|
19
20
|
const common_1 = require("@nestjs/common");
|
|
20
21
|
const inversion_1 = require("@biorate/inversion");
|
|
21
|
-
|
|
22
|
+
const lodash_es_1 = require("lodash-es");
|
|
23
|
+
let TracingInterceptor = TracingInterceptor_1 = class TracingInterceptor {
|
|
24
|
+
static normalizeAspect(name) {
|
|
25
|
+
const aliased = (0, lodash_es_1.get)(TracingInterceptor_1.aspectAliases, name);
|
|
26
|
+
if (aliased)
|
|
27
|
+
return aliased;
|
|
28
|
+
if (name.startsWith('request.'))
|
|
29
|
+
return name.slice('request.'.length);
|
|
30
|
+
return name;
|
|
31
|
+
}
|
|
22
32
|
stringify(data) {
|
|
23
33
|
return typeof data === 'object' ? (0, json_stringify_safe_1.default)(data) : String(data);
|
|
24
34
|
}
|
|
25
35
|
excluded(url) {
|
|
26
36
|
const excluded = this.config.get('TracingInterceptor.excluded', []);
|
|
27
37
|
for (const item of excluded) {
|
|
28
|
-
if (typeof item === 'string' && url.
|
|
38
|
+
if (typeof item === 'string' && url.includes(item))
|
|
29
39
|
return true;
|
|
30
40
|
if (item instanceof RegExp && item.test(url))
|
|
31
41
|
return true;
|
|
32
42
|
}
|
|
33
43
|
return false;
|
|
34
44
|
}
|
|
45
|
+
excludedAttribute(url, aspect) {
|
|
46
|
+
const canonical = TracingInterceptor_1.normalizeAspect(aspect);
|
|
47
|
+
const match = (list) => list.some((item) => {
|
|
48
|
+
const target = TracingInterceptor_1.normalizeAspect(item);
|
|
49
|
+
return canonical === target || canonical.startsWith(`${target}.`);
|
|
50
|
+
});
|
|
51
|
+
if (match(this.config.get('TracingInterceptor.excludedAttributes', [])))
|
|
52
|
+
return true;
|
|
53
|
+
const byUrl = this.config.get('TracingInterceptor.excludedByURL', []);
|
|
54
|
+
for (const entry of byUrl) {
|
|
55
|
+
const hit = typeof entry?.url === 'string'
|
|
56
|
+
? url.includes(entry.url)
|
|
57
|
+
: entry?.url instanceof RegExp && entry.url.test(url);
|
|
58
|
+
if (!hit)
|
|
59
|
+
continue;
|
|
60
|
+
if (match(entry?.attributes ?? []))
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
attr(span, url, aspect, value) {
|
|
66
|
+
if (this.excludedAttribute(url, aspect))
|
|
67
|
+
return;
|
|
68
|
+
span.setAttribute(TracingInterceptor_1.aspectKeys[aspect], this.stringify(value));
|
|
69
|
+
}
|
|
35
70
|
http(span, context, next) {
|
|
36
71
|
const host = context.switchToHttp();
|
|
37
72
|
const req = host.getRequest();
|
|
38
73
|
const res = host.getResponse();
|
|
39
74
|
if (this.excluded(req.url))
|
|
40
75
|
return next.handle();
|
|
41
|
-
|
|
42
|
-
span.
|
|
43
|
-
span.
|
|
44
|
-
span.
|
|
45
|
-
span.
|
|
46
|
-
span.
|
|
76
|
+
this.attr(span, req.url, 'url', req.url);
|
|
77
|
+
this.attr(span, req.url, 'body', req.body);
|
|
78
|
+
this.attr(span, req.url, 'headers', req.headers);
|
|
79
|
+
this.attr(span, req.url, 'method', req.method);
|
|
80
|
+
this.attr(span, req.url, 'params', req.params);
|
|
81
|
+
this.attr(span, req.url, 'query', req.query);
|
|
47
82
|
return next.handle().pipe((0, rxjs_1.catchError)((e) => {
|
|
48
|
-
span.
|
|
49
|
-
span.
|
|
50
|
-
span.
|
|
51
|
-
span.
|
|
83
|
+
this.attr(span, req.url, 'response.headers', res.headers);
|
|
84
|
+
this.attr(span, req.url, 'response.statusCode', res.statusCode);
|
|
85
|
+
this.attr(span, req.url, 'response.errorCode', e.code);
|
|
86
|
+
this.attr(span, req.url, 'response.data', e?.response?.data);
|
|
52
87
|
span.recordException(e);
|
|
53
88
|
span.setStatus({ code: opentelemetry_1.SpanStatusCode.ERROR });
|
|
54
89
|
throw e;
|
|
55
90
|
}), (0, rxjs_1.tap)((data) => {
|
|
56
|
-
span.
|
|
57
|
-
span.
|
|
58
|
-
span.
|
|
91
|
+
this.attr(span, req.url, 'response.headers', res.headers);
|
|
92
|
+
this.attr(span, req.url, 'response.statusCode', res.statusCode);
|
|
93
|
+
this.attr(span, req.url, 'response.data', data);
|
|
59
94
|
}));
|
|
60
95
|
}
|
|
61
96
|
ws(span, context, next) {
|
|
@@ -73,10 +108,33 @@ let TracingInterceptor = class TracingInterceptor {
|
|
|
73
108
|
}
|
|
74
109
|
};
|
|
75
110
|
exports.TracingInterceptor = TracingInterceptor;
|
|
111
|
+
TracingInterceptor.aspectAliases = {
|
|
112
|
+
'request.url': 'url',
|
|
113
|
+
'request.method': 'method',
|
|
114
|
+
'request.headers': 'headers',
|
|
115
|
+
'request.body': 'body',
|
|
116
|
+
'request.params': 'params',
|
|
117
|
+
'request.query': 'query',
|
|
118
|
+
statusCode: 'response.statusCode',
|
|
119
|
+
data: 'response.data',
|
|
120
|
+
errorCode: 'response.errorCode',
|
|
121
|
+
};
|
|
122
|
+
TracingInterceptor.aspectKeys = {
|
|
123
|
+
url: 'incoming.request.url',
|
|
124
|
+
method: 'incoming.request.method',
|
|
125
|
+
headers: 'incoming.request.headers',
|
|
126
|
+
body: 'incoming.request.body',
|
|
127
|
+
params: 'incoming.request.params',
|
|
128
|
+
query: 'incoming.request.query',
|
|
129
|
+
'response.headers': 'incoming.response.headers',
|
|
130
|
+
'response.statusCode': 'incoming.response.statusCode',
|
|
131
|
+
'response.data': 'incoming.response.data',
|
|
132
|
+
'response.errorCode': 'incoming.response.errorCode',
|
|
133
|
+
};
|
|
76
134
|
__decorate([
|
|
77
135
|
(0, inversion_1.inject)(inversion_1.Types.Config),
|
|
78
136
|
__metadata("design:type", Object)
|
|
79
137
|
], TracingInterceptor.prototype, "config", void 0);
|
|
80
|
-
exports.TracingInterceptor = TracingInterceptor = __decorate([
|
|
138
|
+
exports.TracingInterceptor = TracingInterceptor = TracingInterceptor_1 = __decorate([
|
|
81
139
|
(0, common_1.Injectable)()
|
|
82
140
|
], TracingInterceptor);
|
|
@@ -7,49 +7,84 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
+
var TracingInterceptor_1;
|
|
10
11
|
import stringify from 'json-stringify-safe';
|
|
11
12
|
import { tap, catchError } from 'rxjs';
|
|
12
13
|
import { trace, SpanStatusCode } from '@biorate/opentelemetry';
|
|
13
14
|
import { Injectable, } from '@nestjs/common';
|
|
14
15
|
import { inject, Types } from '@biorate/inversion';
|
|
15
|
-
|
|
16
|
+
import { get } from 'lodash-es';
|
|
17
|
+
let TracingInterceptor = TracingInterceptor_1 = class TracingInterceptor {
|
|
18
|
+
static normalizeAspect(name) {
|
|
19
|
+
const aliased = get(TracingInterceptor_1.aspectAliases, name);
|
|
20
|
+
if (aliased)
|
|
21
|
+
return aliased;
|
|
22
|
+
if (name.startsWith('request.'))
|
|
23
|
+
return name.slice('request.'.length);
|
|
24
|
+
return name;
|
|
25
|
+
}
|
|
16
26
|
stringify(data) {
|
|
17
27
|
return typeof data === 'object' ? stringify(data) : String(data);
|
|
18
28
|
}
|
|
19
29
|
excluded(url) {
|
|
20
30
|
const excluded = this.config.get('TracingInterceptor.excluded', []);
|
|
21
31
|
for (const item of excluded) {
|
|
22
|
-
if (typeof item === 'string' && url.
|
|
32
|
+
if (typeof item === 'string' && url.includes(item))
|
|
23
33
|
return true;
|
|
24
34
|
if (item instanceof RegExp && item.test(url))
|
|
25
35
|
return true;
|
|
26
36
|
}
|
|
27
37
|
return false;
|
|
28
38
|
}
|
|
39
|
+
excludedAttribute(url, aspect) {
|
|
40
|
+
const canonical = TracingInterceptor_1.normalizeAspect(aspect);
|
|
41
|
+
const match = (list) => list.some((item) => {
|
|
42
|
+
const target = TracingInterceptor_1.normalizeAspect(item);
|
|
43
|
+
return canonical === target || canonical.startsWith(`${target}.`);
|
|
44
|
+
});
|
|
45
|
+
if (match(this.config.get('TracingInterceptor.excludedAttributes', [])))
|
|
46
|
+
return true;
|
|
47
|
+
const byUrl = this.config.get('TracingInterceptor.excludedByURL', []);
|
|
48
|
+
for (const entry of byUrl) {
|
|
49
|
+
const hit = typeof entry?.url === 'string'
|
|
50
|
+
? url.includes(entry.url)
|
|
51
|
+
: entry?.url instanceof RegExp && entry.url.test(url);
|
|
52
|
+
if (!hit)
|
|
53
|
+
continue;
|
|
54
|
+
if (match(entry?.attributes ?? []))
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
attr(span, url, aspect, value) {
|
|
60
|
+
if (this.excludedAttribute(url, aspect))
|
|
61
|
+
return;
|
|
62
|
+
span.setAttribute(TracingInterceptor_1.aspectKeys[aspect], this.stringify(value));
|
|
63
|
+
}
|
|
29
64
|
http(span, context, next) {
|
|
30
65
|
const host = context.switchToHttp();
|
|
31
66
|
const req = host.getRequest();
|
|
32
67
|
const res = host.getResponse();
|
|
33
68
|
if (this.excluded(req.url))
|
|
34
69
|
return next.handle();
|
|
35
|
-
|
|
36
|
-
span.
|
|
37
|
-
span.
|
|
38
|
-
span.
|
|
39
|
-
span.
|
|
40
|
-
span.
|
|
70
|
+
this.attr(span, req.url, 'url', req.url);
|
|
71
|
+
this.attr(span, req.url, 'body', req.body);
|
|
72
|
+
this.attr(span, req.url, 'headers', req.headers);
|
|
73
|
+
this.attr(span, req.url, 'method', req.method);
|
|
74
|
+
this.attr(span, req.url, 'params', req.params);
|
|
75
|
+
this.attr(span, req.url, 'query', req.query);
|
|
41
76
|
return next.handle().pipe(catchError((e) => {
|
|
42
|
-
span.
|
|
43
|
-
span.
|
|
44
|
-
span.
|
|
45
|
-
span.
|
|
77
|
+
this.attr(span, req.url, 'response.headers', res.headers);
|
|
78
|
+
this.attr(span, req.url, 'response.statusCode', res.statusCode);
|
|
79
|
+
this.attr(span, req.url, 'response.errorCode', e.code);
|
|
80
|
+
this.attr(span, req.url, 'response.data', e?.response?.data);
|
|
46
81
|
span.recordException(e);
|
|
47
82
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
48
83
|
throw e;
|
|
49
84
|
}), tap((data) => {
|
|
50
|
-
span.
|
|
51
|
-
span.
|
|
52
|
-
span.
|
|
85
|
+
this.attr(span, req.url, 'response.headers', res.headers);
|
|
86
|
+
this.attr(span, req.url, 'response.statusCode', res.statusCode);
|
|
87
|
+
this.attr(span, req.url, 'response.data', data);
|
|
53
88
|
}));
|
|
54
89
|
}
|
|
55
90
|
ws(span, context, next) {
|
|
@@ -66,11 +101,34 @@ let TracingInterceptor = class TracingInterceptor {
|
|
|
66
101
|
return this[type](span, context, next);
|
|
67
102
|
}
|
|
68
103
|
};
|
|
104
|
+
TracingInterceptor.aspectAliases = {
|
|
105
|
+
'request.url': 'url',
|
|
106
|
+
'request.method': 'method',
|
|
107
|
+
'request.headers': 'headers',
|
|
108
|
+
'request.body': 'body',
|
|
109
|
+
'request.params': 'params',
|
|
110
|
+
'request.query': 'query',
|
|
111
|
+
statusCode: 'response.statusCode',
|
|
112
|
+
data: 'response.data',
|
|
113
|
+
errorCode: 'response.errorCode',
|
|
114
|
+
};
|
|
115
|
+
TracingInterceptor.aspectKeys = {
|
|
116
|
+
url: 'incoming.request.url',
|
|
117
|
+
method: 'incoming.request.method',
|
|
118
|
+
headers: 'incoming.request.headers',
|
|
119
|
+
body: 'incoming.request.body',
|
|
120
|
+
params: 'incoming.request.params',
|
|
121
|
+
query: 'incoming.request.query',
|
|
122
|
+
'response.headers': 'incoming.response.headers',
|
|
123
|
+
'response.statusCode': 'incoming.response.statusCode',
|
|
124
|
+
'response.data': 'incoming.response.data',
|
|
125
|
+
'response.errorCode': 'incoming.response.errorCode',
|
|
126
|
+
};
|
|
69
127
|
__decorate([
|
|
70
128
|
inject(Types.Config),
|
|
71
129
|
__metadata("design:type", Object)
|
|
72
130
|
], TracingInterceptor.prototype, "config", void 0);
|
|
73
|
-
TracingInterceptor = __decorate([
|
|
131
|
+
TracingInterceptor = TracingInterceptor_1 = __decorate([
|
|
74
132
|
Injectable()
|
|
75
133
|
], TracingInterceptor);
|
|
76
134
|
export { TracingInterceptor };
|
|
@@ -2,9 +2,14 @@ import { Span } from '@biorate/opentelemetry';
|
|
|
2
2
|
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
3
3
|
import { IConfig } from '@biorate/config';
|
|
4
4
|
export declare class TracingInterceptor implements NestInterceptor {
|
|
5
|
+
protected static aspectAliases: Record<string, string>;
|
|
6
|
+
protected static aspectKeys: Record<string, string>;
|
|
7
|
+
protected static normalizeAspect(name: string): string;
|
|
5
8
|
protected readonly config: IConfig;
|
|
6
9
|
protected stringify(data: unknown): string;
|
|
7
10
|
protected excluded(url: string): boolean;
|
|
11
|
+
protected excludedAttribute(url: string, aspect: string): boolean;
|
|
12
|
+
protected attr(span: Span, url: string, aspect: string, value: unknown): void;
|
|
8
13
|
protected http(span: Span, context: ExecutionContext, next: CallHandler): import("rxjs").Observable<any>;
|
|
9
14
|
protected ws(span: Span, context: ExecutionContext, next: CallHandler): import("rxjs").Observable<any>;
|
|
10
15
|
protected rpc(span: Span, context: ExecutionContext, next: CallHandler): import("rxjs").Observable<any>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@biorate/nestjs-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "NestJS tools",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"keywords": [],
|
|
46
46
|
"author": "llevkin",
|
|
47
47
|
"license": "MIT",
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "8c6857bfe61de7b03025b0d883c478045c14390a",
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@nestjs/common": ">=10.4.15",
|
|
51
51
|
"@nestjs/core": ">=10.4.15",
|