@rsdk/grpc.clients 5.0.0-next.2 → 5.0.0-next.3
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/CHANGELOG.md +10 -0
- package/dist/middleware/{request-metadata.middleware.d.ts → tracing.middleware.d.ts} +1 -1
- package/dist/middleware/{request-metadata.middleware.js → tracing.middleware.js} +9 -10
- package/dist/middleware/tracing.middleware.js.map +1 -0
- package/dist/repository/grpc-client.repository.js +2 -4
- package/dist/repository/grpc-client.repository.js.map +1 -1
- package/package.json +4 -7
- package/src/middleware/{request-metadata.middleware.ts → tracing.middleware.ts} +8 -9
- package/src/repository/grpc-client.repository.ts +2 -4
- package/dist/middleware/opentelemetry.middleware.d.ts +0 -5
- package/dist/middleware/opentelemetry.middleware.js +0 -28
- package/dist/middleware/opentelemetry.middleware.js.map +0 -1
- package/dist/middleware/request-metadata.middleware.js.map +0 -1
- package/src/middleware/opentelemetry.middleware.ts +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [5.0.0-next.3](https://github.com/R-Vision/rsdk/compare/v5.0.0-next.2...v5.0.0-next.3) (2024-07-11)
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
* generalize tracing headers (#247)
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* generalize tracing headers ([#247](https://github.com/R-Vision/rsdk/issues/247)) ([cee2ea6](https://github.com/R-Vision/rsdk/commit/cee2ea65c964705faf133397e285c051672c7512)), closes [#2](https://github.com/R-Vision/rsdk/issues/2) [#3](https://github.com/R-Vision/rsdk/issues/3) [#4](https://github.com/R-Vision/rsdk/issues/4) [#5](https://github.com/R-Vision/rsdk/issues/5)
|
|
15
|
+
|
|
6
16
|
## [5.0.0-next.2](https://github.com/R-Vision/rsdk/compare/v5.0.0-next.1...v5.0.0-next.2) (2024-07-10)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @rsdk/grpc.clients
|
|
@@ -2,4 +2,4 @@ import type { ClientMiddleware } from 'nice-grpc';
|
|
|
2
2
|
/**
|
|
3
3
|
* Мидл варя для клиента GRPC, для проброса **requestId** из текущего приложения в стороннее через Metadata
|
|
4
4
|
*/
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const tracingMiddleware: () => ClientMiddleware;
|
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.tracingMiddleware = void 0;
|
|
4
4
|
const core_1 = require("@rsdk/core");
|
|
5
|
-
const tracing_1 = require("@rsdk/tracing");
|
|
6
5
|
const nice_grpc_1 = require("nice-grpc");
|
|
7
6
|
/**
|
|
8
7
|
* Мидл варя для клиента GRPC, для проброса **requestId** из текущего приложения в стороннее через Metadata
|
|
9
8
|
*/
|
|
10
|
-
const
|
|
9
|
+
const tracingMiddleware = () =>
|
|
11
10
|
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
12
11
|
async function* (call, options) {
|
|
13
|
-
const
|
|
14
|
-
if (
|
|
12
|
+
const headers = core_1.TracingHeaders.get();
|
|
13
|
+
if (!headers) {
|
|
15
14
|
return yield* call.next(call.request, {
|
|
16
15
|
...options,
|
|
17
16
|
});
|
|
18
17
|
}
|
|
19
18
|
const metadata = options.metadata ?? new nice_grpc_1.Metadata();
|
|
20
|
-
|
|
21
|
-
metadata.append(
|
|
19
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
20
|
+
metadata.append(key, value);
|
|
22
21
|
}
|
|
23
|
-
options.metadata = metadata;
|
|
24
22
|
return yield* call.next(call.request, {
|
|
25
23
|
...options,
|
|
24
|
+
metadata,
|
|
26
25
|
});
|
|
27
26
|
};
|
|
28
|
-
exports.
|
|
29
|
-
//# sourceMappingURL=
|
|
27
|
+
exports.tracingMiddleware = tracingMiddleware;
|
|
28
|
+
//# sourceMappingURL=tracing.middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.middleware.js","sourceRoot":"","sources":["../../src/middleware/tracing.middleware.ts"],"names":[],"mappings":";;;AAAA,qCAA4C;AAE5C,yCAAqC;AAErC;;GAEG;AACI,MAAM,iBAAiB,GAAG,GAAqB,EAAE;AACtD,+DAA+D;AAC/D,KAAK,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO;IAC5B,MAAM,OAAO,GAAG,qBAAc,CAAC,GAAG,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACpC,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,oBAAQ,EAAE,CAAC;IAEpD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QACpC,GAAG,OAAO;QACV,QAAQ;KACT,CAAC,CAAC;AACL,CAAC,CAAC;AApBS,QAAA,iBAAiB,qBAoB1B"}
|
|
@@ -16,8 +16,7 @@ exports.GrpcClientRepository = void 0;
|
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const nice_grpc_1 = require("nice-grpc");
|
|
18
18
|
const exception_mapper_middleware_1 = require("../middleware/exception-mapper.middleware");
|
|
19
|
-
const
|
|
20
|
-
const request_metadata_middleware_1 = require("../middleware/request-metadata.middleware");
|
|
19
|
+
const tracing_middleware_1 = require("../middleware/tracing.middleware");
|
|
21
20
|
const di_1 = require("../options/di");
|
|
22
21
|
/**
|
|
23
22
|
* Простое кеш хранилище внутри DI для кеширования на замену статике
|
|
@@ -30,8 +29,7 @@ let GrpcClientRepository = class GrpcClientRepository {
|
|
|
30
29
|
constructor(options) {
|
|
31
30
|
this.factory = (0, nice_grpc_1.createClientFactory)()
|
|
32
31
|
.use((0, exception_mapper_middleware_1.exceptionMapperMiddleware)())
|
|
33
|
-
.use((0,
|
|
34
|
-
.use((0, request_metadata_middleware_1.requestMetadataMiddleware)());
|
|
32
|
+
.use((0, tracing_middleware_1.tracingMiddleware)());
|
|
35
33
|
const { middleware } = options || {};
|
|
36
34
|
if (middleware) {
|
|
37
35
|
for (const x of middleware)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc-client.repository.js","sourceRoot":"","sources":["../../src/repository/grpc-client.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAA8D;AAE9D,yCAImB;AAGnB,2FAAsF;AACtF,
|
|
1
|
+
{"version":3,"file":"grpc-client.repository.js","sourceRoot":"","sources":["../../src/repository/grpc-client.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAA8D;AAE9D,yCAImB;AAGnB,2FAAsF;AACtF,yEAAqE;AACrE,sCAAqD;AAGrD;;GAEG;AAGI,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IACd,OAAO,CAAgB;IAExC,SAAS;IACQ,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IACtC,OAAO,GAAG,IAAI,GAAG,EAA2C,CAAC;IAE9E,YAC4C,OAA4B;QAEtE,IAAI,CAAC,OAAO,GAAG,IAAA,+BAAmB,GAAE;aACjC,GAAG,CAAC,IAAA,uDAAyB,GAAE,CAAC;aAChC,GAAG,CAAC,IAAA,sCAAiB,GAAE,CAAC,CAAC;QAE5B,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAErC,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,MAAM,CAAC,IAAI,UAAU;gBAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,YAAoB;QAClD,uFAAuF;QACvF,sFAAsF;QACtF,kFAAkF;QAElF,MAAM,OAAO,GACX,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC;YAC/B,IAAA,yBAAa,EAAC,OAAO,EAAE,8BAAkB,CAAC,cAAc,EAAE,EAAE;gBAC1D,YAAY;gBACZ,iCAAiC,EAAE,CAAC,CAAC;aACtC,CAAC,CAAC;QAEL,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAEzC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,aAAa,CACX,UAAmC,EACnC,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,OAAO,GACX,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAE5E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAEvC,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAA;AAlDY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;IASR,WAAA,IAAA,iBAAQ,GAAE,CAAA;IAAE,WAAA,IAAA,eAAM,EAAC,yBAAoB,CAAC,CAAA;;GARhC,oBAAoB,CAkDhC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsdk/grpc.clients",
|
|
3
|
-
"version": "5.0.0-next.
|
|
3
|
+
"version": "5.0.0-next.3",
|
|
4
4
|
"description": "Grpc clients infrastructure",
|
|
5
5
|
"license": "Apache License 2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -11,12 +11,10 @@
|
|
|
11
11
|
},
|
|
12
12
|
"main": "dist/index.js",
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"@grpc/grpc-js": "^1.
|
|
14
|
+
"@grpc/grpc-js": "^1.10.9",
|
|
15
15
|
"@nestjs/common": "^10.0.0",
|
|
16
16
|
"@nestjs/core": "^10.0.0",
|
|
17
17
|
"@nestjs/microservices": "^10.0.0",
|
|
18
|
-
"@opentelemetry/propagator-b3": "1.18.1",
|
|
19
|
-
"@opentelemetry/sdk-node": "0.45.1",
|
|
20
18
|
"@rsdk/autodoc.protocol": "*",
|
|
21
19
|
"@rsdk/builtin-contract": "*",
|
|
22
20
|
"@rsdk/common": "*",
|
|
@@ -24,10 +22,9 @@
|
|
|
24
22
|
"@rsdk/grpc.common": "*",
|
|
25
23
|
"@rsdk/logging": "*",
|
|
26
24
|
"@rsdk/metadata": "*",
|
|
27
|
-
"
|
|
28
|
-
"nice-grpc": "^2.1.4",
|
|
25
|
+
"nice-grpc": "^2.1.9",
|
|
29
26
|
"reflect-metadata": "^0.1.12 || ^0.2.0",
|
|
30
27
|
"rxjs": "^7.8.1"
|
|
31
28
|
},
|
|
32
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "c75ce1d8983ba69a6f855ba19536d28be0a9c519"
|
|
33
30
|
}
|
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { RequestIdProvider } from '@rsdk/tracing';
|
|
1
|
+
import { TracingHeaders } from '@rsdk/core';
|
|
3
2
|
import type { ClientMiddleware } from 'nice-grpc';
|
|
4
3
|
import { Metadata } from 'nice-grpc';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Мидл варя для клиента GRPC, для проброса **requestId** из текущего приложения в стороннее через Metadata
|
|
8
7
|
*/
|
|
9
|
-
export const
|
|
8
|
+
export const tracingMiddleware = (): ClientMiddleware =>
|
|
10
9
|
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
11
10
|
async function* (call, options) {
|
|
12
|
-
const
|
|
13
|
-
if (
|
|
11
|
+
const headers = TracingHeaders.get();
|
|
12
|
+
if (!headers) {
|
|
14
13
|
return yield* call.next(call.request, {
|
|
15
14
|
...options,
|
|
16
15
|
});
|
|
17
16
|
}
|
|
17
|
+
|
|
18
18
|
const metadata = options.metadata ?? new Metadata();
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
metadata.append(
|
|
20
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
21
|
+
metadata.append(key, value);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
options.metadata = metadata;
|
|
25
|
-
|
|
26
24
|
return yield* call.next(call.request, {
|
|
27
25
|
...options,
|
|
26
|
+
metadata,
|
|
28
27
|
});
|
|
29
28
|
};
|
|
@@ -9,8 +9,7 @@ import {
|
|
|
9
9
|
import type { CompatServiceDefinition } from 'nice-grpc/lib/service-definitions';
|
|
10
10
|
|
|
11
11
|
import { exceptionMapperMiddleware } from '../middleware/exception-mapper.middleware';
|
|
12
|
-
import {
|
|
13
|
-
import { requestMetadataMiddleware } from '../middleware/request-metadata.middleware';
|
|
12
|
+
import { tracingMiddleware } from '../middleware/tracing.middleware';
|
|
14
13
|
import { GRPC_CLIENTS_OPTIONS } from '../options/di';
|
|
15
14
|
import { GrpcClientsOptions } from '../options/types';
|
|
16
15
|
|
|
@@ -31,8 +30,7 @@ export class GrpcClientRepository {
|
|
|
31
30
|
) {
|
|
32
31
|
this.factory = createClientFactory()
|
|
33
32
|
.use(exceptionMapperMiddleware())
|
|
34
|
-
.use(
|
|
35
|
-
.use(requestMetadataMiddleware());
|
|
33
|
+
.use(tracingMiddleware());
|
|
36
34
|
|
|
37
35
|
const { middleware } = options || {};
|
|
38
36
|
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.opentelemetryMiddleware = void 0;
|
|
4
|
-
const propagator_b3_1 = require("@opentelemetry/propagator-b3");
|
|
5
|
-
const sdk_node_1 = require("@opentelemetry/sdk-node");
|
|
6
|
-
const nice_grpc_1 = require("nice-grpc");
|
|
7
|
-
/**
|
|
8
|
-
* Middleware для клиента GRPC, который пробрасывает **traceId** и **spanId** из текущего приложения в стороннее через Metadata
|
|
9
|
-
*/
|
|
10
|
-
const opentelemetryMiddleware = () =>
|
|
11
|
-
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
12
|
-
async function* (call, options) {
|
|
13
|
-
const metadata = options.metadata ?? new nice_grpc_1.Metadata();
|
|
14
|
-
const traceId = sdk_node_1.api.trace?.getActiveSpan()?.spanContext().traceId;
|
|
15
|
-
if (traceId) {
|
|
16
|
-
metadata.append(propagator_b3_1.X_B3_TRACE_ID, traceId);
|
|
17
|
-
}
|
|
18
|
-
const spanId = sdk_node_1.api.trace?.getActiveSpan()?.spanContext().spanId;
|
|
19
|
-
if (spanId) {
|
|
20
|
-
metadata.append(propagator_b3_1.X_B3_PARENT_SPAN_ID, spanId);
|
|
21
|
-
}
|
|
22
|
-
options.metadata = metadata;
|
|
23
|
-
return yield* call.next(call.request, {
|
|
24
|
-
...options,
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
exports.opentelemetryMiddleware = opentelemetryMiddleware;
|
|
28
|
-
//# sourceMappingURL=opentelemetry.middleware.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opentelemetry.middleware.js","sourceRoot":"","sources":["../../src/middleware/opentelemetry.middleware.ts"],"names":[],"mappings":";;;AAAA,gEAGsC;AACtC,sDAA8C;AAE9C,yCAAqC;AAErC;;GAEG;AACI,MAAM,uBAAuB,GAAG,GAAqB,EAAE;AAC5D,+DAA+D;AAC/D,KAAK,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,oBAAQ,EAAE,CAAC;IAEpD,MAAM,OAAO,GAAG,cAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC;IAClE,IAAI,OAAO,EAAE,CAAC;QACZ,QAAQ,CAAC,MAAM,CAAC,6BAAa,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,MAAM,GAAG,cAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,MAAM,CAAC;IAChE,IAAI,MAAM,EAAE,CAAC;QACX,QAAQ,CAAC,MAAM,CAAC,mCAAmB,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAE5B,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QACpC,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC,CAAC;AApBS,QAAA,uBAAuB,2BAoBhC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request-metadata.middleware.js","sourceRoot":"","sources":["../../src/middleware/request-metadata.middleware.ts"],"names":[],"mappings":";;;AAAA,qCAA0C;AAC1C,2CAAkD;AAElD,yCAAqC;AAErC;;GAEG;AACI,MAAM,yBAAyB,GAAG,GAAqB,EAAE;AAC9D,+DAA+D;AAC/D,KAAK,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO;IAC5B,MAAM,SAAS,GAAG,2BAAiB,CAAC,GAAG,EAAE,CAAC;IAC1C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACpC,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,oBAAQ,EAAE,CAAC;IAEpD,IAAI,SAAS,EAAE,CAAC;QACd,QAAQ,CAAC,MAAM,CAAC,mBAAY,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAE5B,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QACpC,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC,CAAC;AApBS,QAAA,yBAAyB,6BAoBlC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
X_B3_PARENT_SPAN_ID,
|
|
3
|
-
X_B3_TRACE_ID,
|
|
4
|
-
} from '@opentelemetry/propagator-b3';
|
|
5
|
-
import { api } from '@opentelemetry/sdk-node';
|
|
6
|
-
import type { ClientMiddleware } from 'nice-grpc';
|
|
7
|
-
import { Metadata } from 'nice-grpc';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Middleware для клиента GRPC, который пробрасывает **traceId** и **spanId** из текущего приложения в стороннее через Metadata
|
|
11
|
-
*/
|
|
12
|
-
export const opentelemetryMiddleware = (): ClientMiddleware =>
|
|
13
|
-
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
14
|
-
async function* (call, options) {
|
|
15
|
-
const metadata = options.metadata ?? new Metadata();
|
|
16
|
-
|
|
17
|
-
const traceId = api.trace?.getActiveSpan()?.spanContext().traceId;
|
|
18
|
-
if (traceId) {
|
|
19
|
-
metadata.append(X_B3_TRACE_ID, traceId);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const spanId = api.trace?.getActiveSpan()?.spanContext().spanId;
|
|
23
|
-
if (spanId) {
|
|
24
|
-
metadata.append(X_B3_PARENT_SPAN_ID, spanId);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
options.metadata = metadata;
|
|
28
|
-
|
|
29
|
-
return yield* call.next(call.request, {
|
|
30
|
-
...options,
|
|
31
|
-
});
|
|
32
|
-
};
|