@itwin/core-backend 4.7.0-dev.4 → 4.7.0-dev.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/CHANGELOG.md CHANGED
@@ -1,6 +1,26 @@
1
1
  # Change Log - @itwin/core-backend
2
2
 
3
- This log was last generated on Tue, 16 Apr 2024 14:47:36 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 15 May 2024 21:32:22 GMT and should not be manually modified.
4
+
5
+ ## 4.6.0
6
+ Mon, 13 May 2024 20:32:51 GMT
7
+
8
+ ### Updates
9
+
10
+ - Improve ChangesetConflictArgs & SqliteChangeSetReader API
11
+ - Add awareness to legacy Channels created by Batch Connectors. Update tests and documentation regarding creation of Channels against Partitions instead of Subjects. Remove sharedChannel from the list of allowedChannels by default.
12
+ - add test logic to extract fb from iModel
13
+ - Remove @alpha BackendLoggerCategory.Editing
14
+ - change signature to updateElement to be Partial<ElementProps>. Also update documentation that model and classFullName may not be changed.
15
+ - Add metadata to errors thrown by `insertElement`, `updateElement` and `deleteElement` in `IModelDb`
16
+ - Don't save to lock-database when inserting elements if their Model is locked
17
+ - Promote ClassRegistry.register to public.
18
+ - Change SpanKind of RPC requests to Internal
19
+ - Fix text annotation rotation around anchor point.
20
+ - Add TextAnnotation APIs.
21
+ - allow pushing changes from a briefcase opened readonly
22
+ - deleteElementTree handles DefinitionContainers
23
+ - log only an info message on no aspects
4
24
 
5
25
  ## 4.5.2
6
26
  Tue, 16 Apr 2024 14:46:21 GMT
@@ -1 +1 @@
1
- {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../../src/rpc/web/response.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAKlB,qBAAqB,EAGrB,oBAAoB,EAEpB,iBAAiB,EAElB,MAAM,oBAAoB,CAAC;AA6D5B,gBAAgB;AAChB,wBAAsB,YAAY,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,qBAAqB,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,kBAAkB,iBAuCjL"}
1
+ {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../../src/rpc/web/response.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAKlB,qBAAqB,EAGrB,oBAAoB,EAEpB,iBAAiB,EAElB,MAAM,oBAAoB,CAAC;AA4F5B,gBAAgB;AAChB,wBAAsB,YAAY,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,qBAAqB,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,kBAAkB,iBAiCjL"}
@@ -10,6 +10,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.sendResponse = void 0;
11
11
  const core_bentley_1 = require("@itwin/core-bentley");
12
12
  const core_common_1 = require("@itwin/core-common");
13
+ const node_stream_1 = require("node:stream");
14
+ const node_util_1 = require("node:util");
15
+ const node_zlib_1 = require("node:zlib");
13
16
  /* eslint-disable deprecation/deprecation */
14
17
  function configureResponse(protocol, request, fulfillment, res) {
15
18
  const success = protocol.getStatus(fulfillment.status) === core_common_1.RpcRequestStatus.Resolved;
@@ -64,6 +67,27 @@ function configureStream(fulfillment) {
64
67
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
65
68
  return fulfillment.result.stream;
66
69
  }
70
+ async function configureEncoding(req, res, responseBody) {
71
+ const acceptedEncodings = req.header("Accept-Encoding")?.split(", ");
72
+ if (!acceptedEncodings)
73
+ return responseBody;
74
+ const encoding = acceptedEncodings.includes("br") ? "br" : acceptedEncodings.includes("gzip") ? "gzip" : undefined;
75
+ if (!encoding)
76
+ return responseBody;
77
+ res.set("Content-Encoding", encoding);
78
+ const brotliOptions = {
79
+ params: {
80
+ // Experimentation revealed that the default compression quality significantly increases the compression time for larger texts.
81
+ // Reducing the quality improves speed substantially without a significant loss in the compression ratio.
82
+ [node_zlib_1.constants.BROTLI_PARAM_QUALITY]: 3,
83
+ },
84
+ };
85
+ if (responseBody instanceof node_stream_1.Stream) {
86
+ const compressStream = encoding === "br" ? (0, node_zlib_1.createBrotliCompress)(brotliOptions) : (0, node_zlib_1.createGzip)();
87
+ return responseBody.pipe(compressStream);
88
+ }
89
+ return encoding === "br" ? (0, node_util_1.promisify)(node_zlib_1.brotliCompress)(responseBody, brotliOptions) : (0, node_util_1.promisify)(node_zlib_1.gzip)(responseBody);
90
+ }
67
91
  /** @internal */
68
92
  async function sendResponse(protocol, request, fulfillment, req, res) {
69
93
  logResponse(request, fulfillment.status, fulfillment.rawResult);
@@ -71,9 +95,6 @@ async function sendResponse(protocol, request, fulfillment, req, res) {
71
95
  if (versionHeader && core_common_1.RpcProtocol.protocolVersion) {
72
96
  res.set(versionHeader, core_common_1.RpcProtocol.protocolVersion.toString());
73
97
  }
74
- // eslint-disable-next-line @typescript-eslint/naming-convention
75
- const { Readable, Stream } = await Promise.resolve().then(() => require(/* webpackIgnore: true */ "stream"));
76
- const { createGzip } = await Promise.resolve().then(() => require(/* webpackIgnore: true */ "zlib"));
77
98
  const transportType = core_common_1.WebAppRpcRequest.computeTransportType(fulfillment.result, fulfillment.rawResult);
78
99
  let responseBody;
79
100
  if (transportType === core_common_1.RpcContentType.Binary) {
@@ -90,14 +111,11 @@ async function sendResponse(protocol, request, fulfillment, req, res) {
90
111
  }
91
112
  configureResponse(protocol, request, fulfillment, res);
92
113
  res.status(fulfillment.status);
93
- if (fulfillment.allowCompression && req.header("Accept-Encoding")?.includes("gzip")) {
94
- res.set("Content-Encoding", "gzip");
95
- const readableResponseBody = (responseBody instanceof Stream) ? responseBody : Readable.from(responseBody);
96
- responseBody = readableResponseBody.pipe(createGzip());
97
- }
114
+ if (fulfillment.allowCompression)
115
+ responseBody = await configureEncoding(req, res, responseBody);
98
116
  // This check should in theory look for instances of Readable, but that would break backend implementation at
99
117
  // core/backend/src/RpcBackend.ts
100
- if (responseBody instanceof Stream) {
118
+ if (responseBody instanceof node_stream_1.Stream) {
101
119
  responseBody.pipe(res);
102
120
  }
103
121
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../../src/rpc/web/response.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,sDAA6C;AAC7C,oDAe4B;AAE5B,4CAA4C;AAE5C,SAAS,iBAAiB,CAAC,QAA2B,EAAE,OAA6B,EAAE,WAAkC,EAAE,GAAuB;IAChJ,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,8BAAgB,CAAC,QAAQ,CAAC;IACrF,iJAAiJ;IACjJ,kJAAkJ;IAElJ,yFAAyF;IACzF,MAAM,gBAAgB,GAAG,IAAI,CAAC;IAC9B,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,qCAAuB,CAAC,SAAS,EAAE,CAAC;QACrE,gDAAgD;QAChD,IAAI,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACvD,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,OAAO,CAAC,SAAS,CAAC,aAAa,KAAK,qBAAqB,EAAE,CAAC;YACrE,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,OAAO,CAAC,SAAS,CAAC,aAAa,KAAK,oBAAoB,EAAE,CAAC;YACpE,qKAAqK;YACrK,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,YAAY,gBAAgB,GAAG,EAAE,wBAAwB,CAAC,CAAC;QACtF,CAAC;aAAM,IAAI,OAAO,CAAC,SAAS,CAAC,aAAa,KAAK,0BAA0B,EAAE,CAAC;YAC1E,yHAAyH;YACzH,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,YAAY,gBAAgB,GAAG,EAAE,aAAa,gBAAgB,GAAG,EAAE,aAAa,CAAC,CAAC;QAC7G,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,YAAY,gBAAgB,GAAG,EAAE,aAAa,gBAAgB,GAAG,EAAE,aAAa,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IAED,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,WAAkC,EAAE,GAAuB;IAChF,GAAG,CAAC,GAAG,CAAC,+BAAiB,CAAC,OAAO,EAAE,+BAAiB,CAAC,IAAI,CAAC,CAAC;IAC3D,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC;AACxE,CAAC;AAED,SAAS,eAAe,CAAC,WAAkC,EAAE,GAAuB;IAClF,GAAG,CAAC,GAAG,CAAC,+BAAiB,CAAC,OAAO,EAAE,+BAAiB,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,kBAAkB,CAAC,WAAkC,EAAE,GAAuB;IACrF,MAAM,QAAQ,GAAG,0BAAY,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;IACtC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,eAAe,CAAC,WAAkC;IACzD,oEAAoE;IACpE,OAAO,WAAW,CAAC,MAAM,CAAC,MAAO,CAAC;AACpC,CAAC;AAED,gBAAgB;AACT,KAAK,UAAU,YAAY,CAAC,QAA2B,EAAE,OAA6B,EAAE,WAAkC,EAAE,GAAsB,EAAE,GAAuB;IAChL,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IAEhE,MAAM,aAAa,GAAG,QAAQ,CAAC,yBAAyB,CAAC;IACzD,IAAI,aAAa,IAAI,yBAAW,CAAC,eAAe,EAAE,CAAC;QACjD,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,yBAAW,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,gEAAgE;IAChE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,2CAAa,yBAAyB,CAAC,QAAQ,EAAC,CAAC;IAC9E,MAAM,EAAE,UAAU,EAAE,GAAG,2CAAa,yBAAyB,CAAC,MAAM,EAAC,CAAC;IAEtE,MAAM,aAAa,GAAG,8BAAgB,CAAC,oBAAoB,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACvG,IAAI,YAAY,CAAC;IACjB,IAAI,aAAa,KAAK,4BAAc,CAAC,MAAM,EAAE,CAAC;QAC5C,YAAY,GAAG,eAAe,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACnD,CAAC;SAAM,IAAI,aAAa,KAAK,4BAAc,CAAC,SAAS,EAAE,CAAC;QACtD,YAAY,GAAG,kBAAkB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACtD,CAAC;SAAM,IAAI,aAAa,KAAK,4BAAc,CAAC,MAAM,EAAE,CAAC;QACnD,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,aAAa,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;IAED,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;IACvD,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAE/B,IAAI,WAAW,CAAC,gBAAgB,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACpF,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,oBAAoB,GAAG,CAAC,YAAY,YAAY,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3G,YAAY,GAAG,oBAAoB,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,6GAA6G;IAC7G,iCAAiC;IACjC,IAAI,YAAY,YAAY,MAAM,EAAE,CAAC;QACnC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,CAAC;AACH,CAAC;AAvCD,oCAuCC;AAED,SAAS,WAAW,CAAC,OAA6B,EAAE,UAAkB,EAAE,SAAkB;IACxF,MAAM,QAAQ,GAAG;QACf,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE,2DAA2D;QACnF,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU;QACV,KAAK,EAAE,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;KAC1D,CAAC;IAEF,IAAI,UAAU,GAAG,GAAG;QAClB,qBAAM,CAAC,OAAO,CAAC,kCAAoB,CAAC,mBAAmB,EAAE,gCAAgC,EAAE,QAAQ,CAAC,CAAC;;QAErG,qBAAM,CAAC,QAAQ,CAAC,kCAAoB,CAAC,mBAAmB,EAAE,gCAAgC,EAAE,QAAQ,CAAC,CAAC;AAC1G,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module RpcInterface\r\n */\r\n\r\nimport { Logger } from \"@itwin/core-bentley\";\r\nimport {\r\n CommonLoggerCategory,\r\n HttpServerRequest,\r\n HttpServerResponse,\r\n ReadableFormData,\r\n RpcContentType,\r\n RpcMultipart,\r\n RpcProtocol,\r\n RpcRequestFulfillment,\r\n RpcRequestStatus,\r\n RpcResponseCacheControl,\r\n SerializedRpcRequest,\r\n WEB_RPC_CONSTANTS,\r\n WebAppRpcProtocol,\r\n WebAppRpcRequest,\r\n} from \"@itwin/core-common\";\r\n\r\n/* eslint-disable deprecation/deprecation */\r\n\r\nfunction configureResponse(protocol: WebAppRpcProtocol, request: SerializedRpcRequest, fulfillment: RpcRequestFulfillment, res: HttpServerResponse) {\r\n const success = protocol.getStatus(fulfillment.status) === RpcRequestStatus.Resolved;\r\n // TODO: Use stale-while-revalidate in cache headers. This needs to be tested, and does not currently have support in the router/caching-service.\r\n // This will allow browsers to use stale cached responses while also revalidating with the router, allowing us to start up a backend if necessary.\r\n\r\n // RPC Caching Service uses the s-maxage header to determine the TTL for the redis cache.\r\n const oneHourInSeconds = 3600;\r\n if (success && request.caching === RpcResponseCacheControl.Immutable) {\r\n // If response size is > 50 MB, do not cache it.\r\n if (fulfillment.result.objects.length > (50 * 10 ** 7)) {\r\n res.set(\"Cache-Control\", \"no-store\");\r\n } else if (request.operation.operationName === \"generateTileContent\") {\r\n res.set(\"Cache-Control\", \"no-store\");\r\n } else if (request.operation.operationName === \"getConnectionProps\") {\r\n // GetConnectionprops can't be cached on the browser longer than the lifespan of the backend. The lifespan of backend may shrink too. Keep it at 1 second to be safe.\r\n res.set(\"Cache-Control\", `s-maxage=${oneHourInSeconds * 24}, max-age=1, immutable`);\r\n } else if (request.operation.operationName === \"getTileCacheContainerUrl\") {\r\n // getTileCacheContainerUrl returns a SAS with an expiry of 23:59:59. We can't exceed that time when setting the max-age.\r\n res.set(\"Cache-Control\", `s-maxage=${oneHourInSeconds * 23}, max-age=${oneHourInSeconds * 23}, immutable`);\r\n } else {\r\n res.set(\"Cache-Control\", `s-maxage=${oneHourInSeconds * 24}, max-age=${oneHourInSeconds * 48}, immutable`);\r\n }\r\n }\r\n\r\n if (fulfillment.retry) {\r\n res.set(\"Retry-After\", fulfillment.retry);\r\n }\r\n}\r\n\r\nfunction configureText(fulfillment: RpcRequestFulfillment, res: HttpServerResponse): string {\r\n res.set(WEB_RPC_CONSTANTS.CONTENT, WEB_RPC_CONSTANTS.TEXT);\r\n return (fulfillment.status === 204) ? \"\" : fulfillment.result.objects;\r\n}\r\n\r\nfunction configureBinary(fulfillment: RpcRequestFulfillment, res: HttpServerResponse): Buffer {\r\n res.set(WEB_RPC_CONSTANTS.CONTENT, WEB_RPC_CONSTANTS.BINARY);\r\n const data = fulfillment.result.data[0];\r\n return Buffer.isBuffer(data) ? data : Buffer.from(data);\r\n}\r\n\r\nfunction configureMultipart(fulfillment: RpcRequestFulfillment, res: HttpServerResponse): ReadableFormData {\r\n const response = RpcMultipart.createStream(fulfillment.result);\r\n const headers = response.getHeaders();\r\n for (const header in headers) {\r\n if (headers.hasOwnProperty(header)) {\r\n res.set(header, headers[header]);\r\n }\r\n }\r\n\r\n return response;\r\n}\r\n\r\nfunction configureStream(fulfillment: RpcRequestFulfillment) {\r\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\r\n return fulfillment.result.stream!;\r\n}\r\n\r\n/** @internal */\r\nexport async function sendResponse(protocol: WebAppRpcProtocol, request: SerializedRpcRequest, fulfillment: RpcRequestFulfillment, req: HttpServerRequest, res: HttpServerResponse) {\r\n logResponse(request, fulfillment.status, fulfillment.rawResult);\r\n\r\n const versionHeader = protocol.protocolVersionHeaderName;\r\n if (versionHeader && RpcProtocol.protocolVersion) {\r\n res.set(versionHeader, RpcProtocol.protocolVersion.toString());\r\n }\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const { Readable, Stream } = await import(/* webpackIgnore: true */ \"stream\");\r\n const { createGzip } = await import(/* webpackIgnore: true */ \"zlib\");\r\n\r\n const transportType = WebAppRpcRequest.computeTransportType(fulfillment.result, fulfillment.rawResult);\r\n let responseBody;\r\n if (transportType === RpcContentType.Binary) {\r\n responseBody = configureBinary(fulfillment, res);\r\n } else if (transportType === RpcContentType.Multipart) {\r\n responseBody = configureMultipart(fulfillment, res);\r\n } else if (transportType === RpcContentType.Stream) {\r\n responseBody = configureStream(fulfillment);\r\n } else {\r\n responseBody = configureText(fulfillment, res);\r\n }\r\n\r\n configureResponse(protocol, request, fulfillment, res);\r\n res.status(fulfillment.status);\r\n\r\n if (fulfillment.allowCompression && req.header(\"Accept-Encoding\")?.includes(\"gzip\")) {\r\n res.set(\"Content-Encoding\", \"gzip\");\r\n const readableResponseBody = (responseBody instanceof Stream) ? responseBody : Readable.from(responseBody);\r\n responseBody = readableResponseBody.pipe(createGzip());\r\n }\r\n\r\n // This check should in theory look for instances of Readable, but that would break backend implementation at\r\n // core/backend/src/RpcBackend.ts\r\n if (responseBody instanceof Stream) {\r\n responseBody.pipe(res);\r\n } else {\r\n res.send(responseBody);\r\n }\r\n}\r\n\r\nfunction logResponse(request: SerializedRpcRequest, statusCode: number, resultObj: unknown) {\r\n const metadata = {\r\n ActivityId: request.id, // eslint-disable-line @typescript-eslint/naming-convention\r\n method: request.method,\r\n path: request.path,\r\n operation: request.operation,\r\n statusCode,\r\n error: resultObj instanceof Error ? resultObj : undefined,\r\n };\r\n\r\n if (statusCode < 400)\r\n Logger.logInfo(CommonLoggerCategory.RpcInterfaceBackend, \"RPC over HTTP success response\", metadata);\r\n else\r\n Logger.logError(CommonLoggerCategory.RpcInterfaceBackend, \"RPC over HTTP failure response\", metadata);\r\n}\r\n"]}
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../../src/rpc/web/response.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module RpcInterface\r\n */\r\n\r\nimport { Logger } from \"@itwin/core-bentley\";\r\nimport {\r\n CommonLoggerCategory,\r\n HttpServerRequest,\r\n HttpServerResponse,\r\n ReadableFormData,\r\n RpcContentType,\r\n RpcMultipart,\r\n RpcProtocol,\r\n RpcRequestFulfillment,\r\n RpcRequestStatus,\r\n RpcResponseCacheControl,\r\n SerializedRpcRequest,\r\n WEB_RPC_CONSTANTS,\r\n WebAppRpcProtocol,\r\n WebAppRpcRequest,\r\n} from \"@itwin/core-common\";\r\n\r\nimport { Readable, Stream } from \"node:stream\";\r\nimport { promisify } from \"node:util\";\r\nimport { brotliCompress, BrotliOptions, createBrotliCompress, createGzip, gzip, constants as zlibConstants } from \"node:zlib\";\r\n\r\n/* eslint-disable deprecation/deprecation */\r\n\r\nfunction configureResponse(protocol: WebAppRpcProtocol, request: SerializedRpcRequest, fulfillment: RpcRequestFulfillment, res: HttpServerResponse) {\r\n const success = protocol.getStatus(fulfillment.status) === RpcRequestStatus.Resolved;\r\n // TODO: Use stale-while-revalidate in cache headers. This needs to be tested, and does not currently have support in the router/caching-service.\r\n // This will allow browsers to use stale cached responses while also revalidating with the router, allowing us to start up a backend if necessary.\r\n\r\n // RPC Caching Service uses the s-maxage header to determine the TTL for the redis cache.\r\n const oneHourInSeconds = 3600;\r\n if (success && request.caching === RpcResponseCacheControl.Immutable) {\r\n // If response size is > 50 MB, do not cache it.\r\n if (fulfillment.result.objects.length > (50 * 10 ** 7)) {\r\n res.set(\"Cache-Control\", \"no-store\");\r\n } else if (request.operation.operationName === \"generateTileContent\") {\r\n res.set(\"Cache-Control\", \"no-store\");\r\n } else if (request.operation.operationName === \"getConnectionProps\") {\r\n // GetConnectionprops can't be cached on the browser longer than the lifespan of the backend. The lifespan of backend may shrink too. Keep it at 1 second to be safe.\r\n res.set(\"Cache-Control\", `s-maxage=${oneHourInSeconds * 24}, max-age=1, immutable`);\r\n } else if (request.operation.operationName === \"getTileCacheContainerUrl\") {\r\n // getTileCacheContainerUrl returns a SAS with an expiry of 23:59:59. We can't exceed that time when setting the max-age.\r\n res.set(\"Cache-Control\", `s-maxage=${oneHourInSeconds * 23}, max-age=${oneHourInSeconds * 23}, immutable`);\r\n } else {\r\n res.set(\"Cache-Control\", `s-maxage=${oneHourInSeconds * 24}, max-age=${oneHourInSeconds * 48}, immutable`);\r\n }\r\n }\r\n\r\n if (fulfillment.retry) {\r\n res.set(\"Retry-After\", fulfillment.retry);\r\n }\r\n}\r\n\r\nfunction configureText(fulfillment: RpcRequestFulfillment, res: HttpServerResponse): string {\r\n res.set(WEB_RPC_CONSTANTS.CONTENT, WEB_RPC_CONSTANTS.TEXT);\r\n return (fulfillment.status === 204) ? \"\" : fulfillment.result.objects;\r\n}\r\n\r\nfunction configureBinary(fulfillment: RpcRequestFulfillment, res: HttpServerResponse): Buffer {\r\n res.set(WEB_RPC_CONSTANTS.CONTENT, WEB_RPC_CONSTANTS.BINARY);\r\n const data = fulfillment.result.data[0];\r\n return Buffer.isBuffer(data) ? data : Buffer.from(data);\r\n}\r\n\r\nfunction configureMultipart(fulfillment: RpcRequestFulfillment, res: HttpServerResponse): ReadableFormData {\r\n const response = RpcMultipart.createStream(fulfillment.result);\r\n const headers = response.getHeaders();\r\n for (const header in headers) {\r\n if (headers.hasOwnProperty(header)) {\r\n res.set(header, headers[header]);\r\n }\r\n }\r\n\r\n return response;\r\n}\r\n\r\nfunction configureStream(fulfillment: RpcRequestFulfillment) {\r\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\r\n return fulfillment.result.stream!;\r\n}\r\n\r\nasync function configureEncoding(req: HttpServerRequest, res: HttpServerResponse, responseBody: string | Buffer | Readable): Promise<string | Buffer | Readable> {\r\n const acceptedEncodings = req.header(\"Accept-Encoding\")?.split(\", \");\r\n if (!acceptedEncodings)\r\n return responseBody;\r\n\r\n const encoding = acceptedEncodings.includes(\"br\") ? \"br\" : acceptedEncodings.includes(\"gzip\") ? \"gzip\" : undefined;\r\n if (!encoding)\r\n return responseBody;\r\n\r\n res.set(\"Content-Encoding\", encoding);\r\n\r\n const brotliOptions: BrotliOptions = {\r\n params: {\r\n // Experimentation revealed that the default compression quality significantly increases the compression time for larger texts.\r\n // Reducing the quality improves speed substantially without a significant loss in the compression ratio.\r\n [zlibConstants.BROTLI_PARAM_QUALITY]: 3,\r\n },\r\n };\r\n\r\n if (responseBody instanceof Stream) {\r\n const compressStream = encoding === \"br\" ? createBrotliCompress(brotliOptions) : createGzip();\r\n return responseBody.pipe(compressStream);\r\n }\r\n\r\n return encoding === \"br\" ? promisify(brotliCompress)(responseBody, brotliOptions) : promisify(gzip)(responseBody);\r\n}\r\n\r\n/** @internal */\r\nexport async function sendResponse(protocol: WebAppRpcProtocol, request: SerializedRpcRequest, fulfillment: RpcRequestFulfillment, req: HttpServerRequest, res: HttpServerResponse) {\r\n logResponse(request, fulfillment.status, fulfillment.rawResult);\r\n\r\n const versionHeader = protocol.protocolVersionHeaderName;\r\n if (versionHeader && RpcProtocol.protocolVersion) {\r\n res.set(versionHeader, RpcProtocol.protocolVersion.toString());\r\n }\r\n\r\n const transportType = WebAppRpcRequest.computeTransportType(fulfillment.result, fulfillment.rawResult);\r\n let responseBody;\r\n if (transportType === RpcContentType.Binary) {\r\n responseBody = configureBinary(fulfillment, res);\r\n } else if (transportType === RpcContentType.Multipart) {\r\n responseBody = configureMultipart(fulfillment, res);\r\n } else if (transportType === RpcContentType.Stream) {\r\n responseBody = configureStream(fulfillment);\r\n } else {\r\n responseBody = configureText(fulfillment, res);\r\n }\r\n\r\n configureResponse(protocol, request, fulfillment, res);\r\n res.status(fulfillment.status);\r\n\r\n if (fulfillment.allowCompression)\r\n responseBody = await configureEncoding(req, res, responseBody);\r\n\r\n // This check should in theory look for instances of Readable, but that would break backend implementation at\r\n // core/backend/src/RpcBackend.ts\r\n if (responseBody instanceof Stream) {\r\n responseBody.pipe(res);\r\n } else {\r\n res.send(responseBody);\r\n }\r\n}\r\n\r\nfunction logResponse(request: SerializedRpcRequest, statusCode: number, resultObj: unknown) {\r\n const metadata = {\r\n ActivityId: request.id, // eslint-disable-line @typescript-eslint/naming-convention\r\n method: request.method,\r\n path: request.path,\r\n operation: request.operation,\r\n statusCode,\r\n error: resultObj instanceof Error ? resultObj : undefined,\r\n };\r\n\r\n if (statusCode < 400)\r\n Logger.logInfo(CommonLoggerCategory.RpcInterfaceBackend, \"RPC over HTTP success response\", metadata);\r\n else\r\n Logger.logError(CommonLoggerCategory.RpcInterfaceBackend, \"RPC over HTTP failure response\", metadata);\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/core-backend",
3
- "version": "4.7.0-dev.4",
3
+ "version": "4.7.0-dev.5",
4
4
  "description": "iTwin.js backend components",
5
5
  "main": "lib/cjs/core-backend.js",
6
6
  "typings": "lib/cjs/core-backend",
@@ -25,9 +25,9 @@
25
25
  "url": "http://www.bentley.com"
26
26
  },
27
27
  "peerDependencies": {
28
- "@itwin/core-bentley": "^4.7.0-dev.4",
29
- "@itwin/core-common": "^4.7.0-dev.4",
30
- "@itwin/core-geometry": "^4.7.0-dev.4",
28
+ "@itwin/core-bentley": "^4.7.0-dev.5",
29
+ "@itwin/core-common": "^4.7.0-dev.5",
30
+ "@itwin/core-geometry": "^4.7.0-dev.5",
31
31
  "@opentelemetry/api": "^1.0.4"
32
32
  },
33
33
  "peerDependenciesMeta": {
@@ -69,12 +69,12 @@
69
69
  "ts-node": "^10.8.2",
70
70
  "typescript": "~5.3.3",
71
71
  "webpack": "^5.76.0",
72
- "@itwin/build-tools": "4.7.0-dev.4",
73
- "@itwin/core-common": "4.7.0-dev.4",
74
- "@itwin/core-bentley": "4.7.0-dev.4",
75
- "@itwin/core-geometry": "4.7.0-dev.4",
76
- "@itwin/ecsql-common": "4.7.0-dev.4",
77
- "@itwin/core-webpack-tools": "4.7.0-dev.4",
72
+ "@itwin/build-tools": "4.7.0-dev.5",
73
+ "@itwin/core-bentley": "4.7.0-dev.5",
74
+ "@itwin/core-common": "4.7.0-dev.5",
75
+ "@itwin/core-geometry": "4.7.0-dev.5",
76
+ "@itwin/ecsql-common": "4.7.0-dev.5",
77
+ "@itwin/core-webpack-tools": "4.7.0-dev.5",
78
78
  "internal-tools": "3.0.0-dev.69"
79
79
  },
80
80
  "dependencies": {
@@ -91,7 +91,7 @@
91
91
  "semver": "^7.3.5",
92
92
  "touch": "^3.1.0",
93
93
  "ws": "^7.5.3",
94
- "@itwin/core-telemetry": "4.7.0-dev.4"
94
+ "@itwin/core-telemetry": "4.7.0-dev.5"
95
95
  },
96
96
  "nyc": {
97
97
  "extends": "./node_modules/@itwin/build-tools/.nycrc"