@verdaccio/store 9.0.0-next-9.21 → 9.0.0-next-9.22

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/build/storage.mjs CHANGED
@@ -18,6 +18,9 @@ import Search from "@verdaccio/search";
18
18
  import { convertDistRemoteToLocalTarballUrls, convertDistVersionToLocalTarballsUrl, getTarballDetails } from "@verdaccio/tarball";
19
19
  //#region src/storage.ts
20
20
  var debug = buildDebug("verdaccio:storage");
21
+ var noSuchFile = "ENOENT";
22
+ var resourceNotAvailable = "EAGAIN";
23
+ var PROTO_NAME = "__proto__";
21
24
  var Storage = class {
22
25
  localStorage;
23
26
  filters;
@@ -164,85 +167,105 @@ var Storage = class {
164
167
  if (cachedManifest?._distfiles && typeof cachedManifest?._distfiles[filename]?.url === "string") {
165
168
  debug("dist file found, using it %o", cachedManifest?._distfiles[filename].url);
166
169
  const distFile = cachedManifest._distfiles[filename];
167
- let current_length = 0;
168
- let expected_length;
169
- const passThroughRemoteStream = new PassThrough();
170
- const proxy = this.getUpLinkForDistFile(name, distFile);
171
- const remoteStream = proxy.fetchTarball(distFile.url, {});
172
- remoteStream.on("request", async () => {
173
- try {
174
- debug("remote stream request");
175
- const storage = this.getPrivatePackageStorage(name);
176
- if (proxy.config.cache === true && storage) await pipeline(remoteStream, passThroughRemoteStream, await storage.writeTarball(filename, { signal }), { signal });
177
- else await pipeline(remoteStream, passThroughRemoteStream, { signal });
178
- } catch (err) {
179
- debug("error on pipeline downloading tarball for package %o", name);
180
- passThroughRemoteStream.emit("error", err);
181
- }
182
- });
183
- remoteStream.on("response", async (res) => {
184
- if (res.statusCode === HTTP_STATUS.NOT_FOUND) {
185
- debug("remote stream response 404");
186
- passThroughRemoteStream.emit("error", errorUtils.getNotFound(errorUtils.API_ERROR.NOT_FILE_UPLINK));
187
- return;
188
- }
189
- if (res.statusCode === HTTP_STATUS.UNAUTHORIZED) {
190
- debug("remote stream response 401");
191
- passThroughRemoteStream.emit("error", errorUtils.getUnauthorized(errorUtils.API_ERROR.UNAUTHORIZED_ACCESS));
192
- return;
193
- }
194
- if (!(res.statusCode >= HTTP_STATUS.OK && res.statusCode < HTTP_STATUS.MULTIPLE_CHOICES)) {
195
- debug("remote stream response %o", res.statusCode);
196
- passThroughRemoteStream.emit("error", errorUtils.getInternalError(`bad uplink status code: ${res.statusCode}`));
197
- return;
198
- }
199
- if (res.headers[HEADER_TYPE.CONTENT_LENGTH]) {
200
- expected_length = res.headers[HEADER_TYPE.CONTENT_LENGTH];
201
- debug("remote stream response content length %o", expected_length);
202
- passThroughRemoteStream.emit(HEADER_TYPE.CONTENT_LENGTH, res.headers[HEADER_TYPE.CONTENT_LENGTH]);
203
- }
204
- }).on("downloadProgress", (progress) => {
205
- current_length = progress.transferred;
206
- if (typeof expected_length === "undefined" && progress.total) expected_length = progress.total;
207
- }).on("end", () => {
208
- if (expected_length && current_length != expected_length) {
209
- debug("stream end, but length mismatch %o %o", current_length, expected_length);
210
- passThroughRemoteStream.emit("error", errorUtils.getInternalError(API_ERROR.CONTENT_MISMATCH));
211
- }
212
- debug("remote stream end");
213
- }).on("error", (err) => {
214
- debug("remote stream error %o", err);
215
- passThroughRemoteStream.emit("error", err);
216
- });
217
- return passThroughRemoteStream;
170
+ return this.fetchTarballFromDistFile(name, filename, distFile, { signal });
218
171
  } else {
219
172
  debug("dist file not found, proceed update upstream");
220
- const passThroughRemoteStream = new PassThrough();
221
173
  const [updatedManifest] = await this.syncUplinksMetadata(name, cachedManifest, { uplinksLook: true });
222
174
  const distFile = updatedManifest?._distfiles?.[filename];
223
175
  if (updatedManifest === null || !distFile) {
224
176
  debug("remote tarball not found");
225
177
  throw errorUtils.getNotFound(API_ERROR.NO_SUCH_FILE);
226
178
  }
227
- const proxy = this.getUpLinkForDistFile(name, distFile);
228
- const remoteStream = proxy.fetchTarball(distFile.url, {});
229
- remoteStream.on("response", async () => {
179
+ return this.fetchTarballFromDistFile(name, filename, distFile, { signal });
180
+ }
181
+ }
182
+ fetchTarballFromDistFile(name, filename, distFile, { signal }) {
183
+ let current_length = 0;
184
+ let expected_length;
185
+ let uplinkStatusError = null;
186
+ const passThroughRemoteStream = new PassThrough();
187
+ const proxy = this.getUpLinkForDistFile(name, distFile);
188
+ const remoteStream = proxy.fetchTarball(distFile.url, { throwHttpErrors: false });
189
+ const readRemoteBody = () => new Promise((resolve) => {
190
+ const chunks = [];
191
+ remoteStream.on("data", (chunk) => chunks.push(chunk));
192
+ remoteStream.once("end", () => {
193
+ const raw = Buffer.concat(chunks);
194
+ if (raw.length === 0) {
195
+ resolve(void 0);
196
+ return;
197
+ }
230
198
  try {
231
- const storage = this.getPrivatePackageStorage(name);
232
- if (proxy.config.cache === true && storage) {
233
- debug("cache remote tarball enabled");
234
- await pipeline(remoteStream, passThroughRemoteStream, await storage.writeTarball(filename, { signal }), { signal });
235
- } else {
236
- debug("cache remote tarball disabled");
237
- await pipeline(remoteStream, passThroughRemoteStream, { signal });
238
- }
239
- } catch (err) {
240
- debug("error on pipeline downloading tarball for package %o", name);
241
- passThroughRemoteStream.emit("error", err);
199
+ resolve(JSON.parse(raw.toString("utf8")));
200
+ } catch {
201
+ resolve(void 0);
242
202
  }
243
203
  });
244
- return passThroughRemoteStream;
245
- }
204
+ remoteStream.once("error", () => resolve(void 0));
205
+ });
206
+ remoteStream.on("response", async (res) => {
207
+ if (res.statusCode === HTTP_STATUS.NOT_FOUND) {
208
+ debug("remote stream response 404");
209
+ remoteStream.resume();
210
+ uplinkStatusError = errorUtils.getNotFound(errorUtils.API_ERROR.NOT_FILE_UPLINK);
211
+ passThroughRemoteStream.emit("error", uplinkStatusError);
212
+ return;
213
+ }
214
+ if (res.statusCode === HTTP_STATUS.UNAUTHORIZED) {
215
+ debug("remote stream response 401");
216
+ remoteStream.resume();
217
+ uplinkStatusError = errorUtils.getUnauthorized(errorUtils.API_ERROR.UNAUTHORIZED_ACCESS);
218
+ passThroughRemoteStream.emit("error", uplinkStatusError);
219
+ return;
220
+ }
221
+ if (res.statusCode === HTTP_STATUS.FORBIDDEN) {
222
+ debug("remote stream response 403");
223
+ const body = await readRemoteBody();
224
+ const message = body?.detail || body?.title || body?.message || "tarball not available: forbidden by uplink";
225
+ uplinkStatusError = errorUtils.getForbidden(message);
226
+ passThroughRemoteStream.emit("error", uplinkStatusError);
227
+ return;
228
+ }
229
+ if (!(res.statusCode >= HTTP_STATUS.OK && res.statusCode < HTTP_STATUS.MULTIPLE_CHOICES)) {
230
+ debug("remote stream response %o", res.statusCode);
231
+ remoteStream.resume();
232
+ uplinkStatusError = errorUtils.getInternalError(`bad uplink status code: ${res.statusCode}`);
233
+ passThroughRemoteStream.emit("error", uplinkStatusError);
234
+ return;
235
+ }
236
+ if (res.headers[HEADER_TYPE.CONTENT_LENGTH]) {
237
+ expected_length = res.headers[HEADER_TYPE.CONTENT_LENGTH];
238
+ debug("remote stream response content length %o", expected_length);
239
+ passThroughRemoteStream.emit(HEADER_TYPE.CONTENT_LENGTH, res.headers[HEADER_TYPE.CONTENT_LENGTH]);
240
+ }
241
+ try {
242
+ debug("remote stream response ok, starting pipeline");
243
+ const storage = this.getPrivatePackageStorage(name);
244
+ if (proxy.config.cache === true && storage) {
245
+ const localStorageWriteStream = await storage.writeTarball(filename, { signal });
246
+ await pipeline(remoteStream, passThroughRemoteStream, localStorageWriteStream, { signal });
247
+ } else await pipeline(remoteStream, passThroughRemoteStream, { signal });
248
+ } catch (err) {
249
+ if (uplinkStatusError) return;
250
+ debug("error on pipeline downloading tarball for package %o", name);
251
+ passThroughRemoteStream.emit("error", err);
252
+ }
253
+ }).on("downloadProgress", (progress) => {
254
+ current_length = progress.transferred;
255
+ if (typeof expected_length === "undefined" && progress.total) expected_length = progress.total;
256
+ }).on("end", () => {
257
+ if (uplinkStatusError) return;
258
+ if (expected_length && current_length != expected_length) {
259
+ debug("stream end, but length mismatch %o %o", current_length, expected_length);
260
+ passThroughRemoteStream.emit("error", errorUtils.getInternalError(API_ERROR.CONTENT_MISMATCH));
261
+ }
262
+ debug("remote stream end");
263
+ }).on("error", (err) => {
264
+ if (uplinkStatusError) return;
265
+ debug("remote stream error %o", err);
266
+ passThroughRemoteStream.emit("error", err);
267
+ });
268
+ return passThroughRemoteStream;
246
269
  }
247
270
  /**
248
271
  *
@@ -1314,6 +1337,6 @@ var Storage = class {
1314
1337
  }
1315
1338
  };
1316
1339
  //#endregion
1317
- export { Storage };
1340
+ export { PROTO_NAME, Storage, noSuchFile, resourceNotAvailable };
1318
1341
 
1319
1342
  //# sourceMappingURL=storage.mjs.map