@milaboratories/pl-drivers 1.8.2 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-drivers",
3
- "version": "1.8.2",
3
+ "version": "1.9.0",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },
@@ -22,21 +22,21 @@
22
22
  "dependencies": {
23
23
  "decompress": "^4.2.1",
24
24
  "@grpc/grpc-js": "~1.13.4",
25
- "@protobuf-ts/grpc-transport": "2.11.0",
26
- "@protobuf-ts/runtime": "2.11.0",
27
- "@protobuf-ts/runtime-rpc": "2.11.0",
28
- "@protobuf-ts/plugin": "2.11.0",
25
+ "@protobuf-ts/grpc-transport": "2.11.1",
26
+ "@protobuf-ts/runtime": "2.11.1",
27
+ "@protobuf-ts/runtime-rpc": "2.11.1",
28
+ "@protobuf-ts/plugin": "2.11.1",
29
29
  "denque": "^2.1.0",
30
30
  "tar-fs": "^3.0.9",
31
- "undici": "~7.10.0",
31
+ "undici": "~7.13.0",
32
32
  "zod": "~3.23.8",
33
33
  "upath": "^2.0.1",
34
- "@milaboratories/ts-helpers": "^1.4.3",
35
34
  "@milaboratories/helpers": "^1.6.19",
35
+ "@milaboratories/ts-helpers": "^1.4.3",
36
+ "@milaboratories/pl-tree": "^1.7.5",
37
+ "@milaboratories/pl-model-common": "^1.19.4",
36
38
  "@milaboratories/computable": "^2.6.3",
37
- "@milaboratories/pl-client": "^2.11.6",
38
- "@milaboratories/pl-model-common": "^1.19.3",
39
- "@milaboratories/pl-tree": "^1.7.5"
39
+ "@milaboratories/pl-client": "^2.11.7"
40
40
  },
41
41
  "devDependencies": {
42
42
  "eslint": "^9.25.1",
@@ -76,11 +76,32 @@ export class ClientUpload {
76
76
  const chunk = await readFileChunk(path, info.chunkStart, info.chunkEnd);
77
77
  await checkExpectedMTime(path, expectedMTimeUnix);
78
78
 
79
+ const contentLength = Number(info.chunkEnd - info.chunkStart);
80
+ if (chunk.length !== contentLength) {
81
+ throw new Error(
82
+ `Chunk size mismatch: expected ${contentLength} bytes, but read ${chunk.length} bytes from file`,
83
+ );
84
+ }
85
+
86
+ const headers = Object.fromEntries(info.headers.map(({ name, value }) => [name, value]));
87
+
88
+ const contentLengthKey = Object.keys(headers).find((key) => key.toLowerCase() === 'content-length');
89
+ if (contentLengthKey) {
90
+ const existingContentLength = Number(headers[contentLengthKey]);
91
+ if (existingContentLength !== contentLength) {
92
+ throw new Error(
93
+ `Content-Length mismatch: expected ${contentLength}, but got ${existingContentLength} in headers`,
94
+ );
95
+ }
96
+ }
97
+
98
+ // content length will be automatically added by undici, so we don't need to set it here
99
+
79
100
  try {
80
101
  const {
81
102
  body: rawBody,
82
103
  statusCode,
83
- headers,
104
+ headers: responseHeaders,
84
105
  } = await request(info.uploadUrl, {
85
106
  dispatcher: this.httpClient,
86
107
  body: chunk,
@@ -90,13 +111,17 @@ export class ClientUpload {
90
111
  // that's why we got big timeout here.
91
112
  headersTimeout: 60000,
92
113
  bodyTimeout: 60000,
93
- headers: Object.fromEntries(info.headers.map(({ name, value }) => [name, value])),
114
+ // Prevent connection reuse by setting "Connection: close" header.
115
+ // This works around an issue with the backend's built-in S3 implementation
116
+ // that caused HTTP/1.1 protocol lines to be included in the uploaded file content.
117
+ reset: true,
118
+ headers,
94
119
  method: info.method.toUpperCase() as Dispatcher.HttpMethod,
95
120
  });
96
121
 
97
122
  // always read the body for resources to be garbage collected.
98
123
  const body = await rawBody.text();
99
- checkStatusCodeOk(statusCode, body, headers, info);
124
+ checkStatusCodeOk(statusCode, body, responseHeaders, info);
100
125
  } catch (e: unknown) {
101
126
  if (e instanceof NetworkError)
102
127
  throw e;