sandboxedjs 0.1.95 → 0.1.97

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/dist/index.cjs CHANGED
@@ -20958,7 +20958,7 @@ var wheels_default = {
20958
20958
 
20959
20959
  // package.json
20960
20960
  var package_default = {
20961
- version: "0.1.95"};
20961
+ version: "0.1.97"};
20962
20962
 
20963
20963
  // src/python/extension-abi.ts
20964
20964
  var EXTENSION_ABI = {
@@ -23933,9 +23933,7 @@ async function installRequirements(options) {
23933
23933
  continue;
23934
23934
  }
23935
23935
  options.progress.downloading(distribution.name, distribution.version);
23936
- const bytes2 = await options.client.bytes(distribution.url, { timeoutMs: 12e4 });
23937
- requireArchive(distribution, bytes2);
23938
- verifyDigest(distribution, bytes2);
23936
+ const bytes2 = await download(options.client, distribution);
23939
23937
  const files = stageWheel(readZip(bytes2));
23940
23938
  staged.push(...distribution.kind === "substituted" ? substituteFiles(distribution.name, files, SITE_PACKAGES) : files);
23941
23939
  installed3.push({ name: distribution.name, version: distribution.version });
@@ -23951,18 +23949,41 @@ function requireArchive(distribution, bytes2) {
23951
23949
  `${distribution.filename} did not arrive as a wheel from ${distribution.url}: ` + (looksLikeMarkup ? "the server answered with an HTML page, which usually means the wheel is not published at that address and the server returned its index page instead" : `expected a zip archive, got ${bytes2.length} bytes beginning ${JSON.stringify(opening)}`)
23952
23950
  );
23953
23951
  }
23954
- function verifyDigest(distribution, bytes2) {
23952
+ async function download(client, distribution) {
23953
+ const bytes2 = await client.bytes(distribution.url, { timeoutMs: 12e4 });
23954
+ requireArchive(distribution, bytes2);
23955
+ const mismatch = digestMismatch(distribution, bytes2);
23956
+ if (!mismatch) return bytes2;
23957
+ const fresh = await refetch(client, distribution);
23958
+ if (fresh && !digestMismatch(distribution, fresh)) {
23959
+ requireArchive(distribution, fresh);
23960
+ return fresh;
23961
+ }
23962
+ throw new Error(
23963
+ `${mismatch} ${fresh ? "A retry past any cache returned the same bytes, so the index and the file it names disagree." : "A retry past any cache could not be made, so this may be a cached copy of an older build; clearing the cache, or asking the index's host to purge it, is worth trying before the index is blamed."}`
23964
+ );
23965
+ }
23966
+ async function refetch(client, distribution) {
23967
+ const separator = distribution.url.includes("?") ? "&" : "?";
23968
+ try {
23969
+ const bytes2 = await client.bytes(
23970
+ `${distribution.url}${separator}sha256=${distribution.sha256}`,
23971
+ { timeoutMs: 6e4 }
23972
+ );
23973
+ return bytes2.length > 1 && bytes2[0] === 80 && bytes2[1] === 75 ? bytes2 : null;
23974
+ } catch {
23975
+ return null;
23976
+ }
23977
+ }
23978
+ function digestMismatch(distribution, bytes2) {
23955
23979
  if (!distribution.sha256) {
23956
23980
  throw new Error(
23957
23981
  `${distribution.filename} was published without a sha256 digest, so it cannot be verified`
23958
23982
  );
23959
23983
  }
23960
23984
  const actual = [...sha256.sha256(bytes2)].map((b) => b.toString(16).padStart(2, "0")).join("");
23961
- if (actual !== distribution.sha256) {
23962
- throw new Error(
23963
- `${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}`
23964
- );
23965
- }
23985
+ if (actual === distribution.sha256) return null;
23986
+ return `${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}.`;
23966
23987
  }
23967
23988
  function stageWheel(entries, resolved) {
23968
23989
  const staged = [];
@@ -28043,12 +28064,19 @@ async function installRelease(ctx, index, release, seen, options) {
28043
28064
  const base2 = registryBase(ctx).replace(/\/$/, "");
28044
28065
  const url = `${base2}/${release.filename}`;
28045
28066
  ctx.line(`Fetching ${release.name} ${release.version}`);
28046
- const archive = await download(url);
28047
- const digest2 = await digestHex("sha256", archive);
28067
+ let archive = await download2(url);
28068
+ let digest2 = await digestHex("sha256", archive);
28048
28069
  if (digest2 !== release.sha256) {
28049
- throw new AppRegistryError(
28050
- `${release.filename} failed verification: the registry publishes sha256 ${release.sha256} but the download hashes to ${digest2}`
28051
- );
28070
+ const retried = await download2(`${url}${url.includes("?") ? "&" : "?"}sha256=${release.sha256}`).catch(() => null);
28071
+ const retriedDigest = retried && await digestHex("sha256", retried);
28072
+ if (retried && retriedDigest === release.sha256) {
28073
+ archive = retried;
28074
+ digest2 = retriedDigest;
28075
+ } else {
28076
+ throw new AppRegistryError(
28077
+ `${release.filename} failed verification: the registry publishes sha256 ${release.sha256} but the download hashes to ${digest2}. ` + (retried ? "A retry past any cache returned the same bytes, so the registry and the file it names disagree." : "A retry past any cache could not be made; a cached copy of an older build would look like this, so clearing the cache is worth trying before the registry is blamed.")
28078
+ );
28079
+ }
28052
28080
  }
28053
28081
  const verified = await verify(ctx, archive, release, options);
28054
28082
  const root = `${APPS_ROOT}/${release.name}`;
@@ -28075,7 +28103,7 @@ async function installRelease(ctx, index, release, seen, options) {
28075
28103
  }
28076
28104
  if (manifest.docs) ctx.line(` docs: ${root}/${manifest.docs}`);
28077
28105
  }
28078
- async function download(url) {
28106
+ async function download2(url) {
28079
28107
  const response = await fetch(url);
28080
28108
  if (!response.ok) {
28081
28109
  throw new AppRegistryError(`${url} answered ${response.status} ${response.statusText}`);
package/dist/index.js CHANGED
@@ -20941,7 +20941,7 @@ var wheels_default = {
20941
20941
 
20942
20942
  // package.json
20943
20943
  var package_default = {
20944
- version: "0.1.95"};
20944
+ version: "0.1.97"};
20945
20945
 
20946
20946
  // src/python/extension-abi.ts
20947
20947
  var EXTENSION_ABI = {
@@ -23916,9 +23916,7 @@ async function installRequirements(options) {
23916
23916
  continue;
23917
23917
  }
23918
23918
  options.progress.downloading(distribution.name, distribution.version);
23919
- const bytes2 = await options.client.bytes(distribution.url, { timeoutMs: 12e4 });
23920
- requireArchive(distribution, bytes2);
23921
- verifyDigest(distribution, bytes2);
23919
+ const bytes2 = await download(options.client, distribution);
23922
23920
  const files = stageWheel(readZip(bytes2));
23923
23921
  staged.push(...distribution.kind === "substituted" ? substituteFiles(distribution.name, files, SITE_PACKAGES) : files);
23924
23922
  installed3.push({ name: distribution.name, version: distribution.version });
@@ -23934,18 +23932,41 @@ function requireArchive(distribution, bytes2) {
23934
23932
  `${distribution.filename} did not arrive as a wheel from ${distribution.url}: ` + (looksLikeMarkup ? "the server answered with an HTML page, which usually means the wheel is not published at that address and the server returned its index page instead" : `expected a zip archive, got ${bytes2.length} bytes beginning ${JSON.stringify(opening)}`)
23935
23933
  );
23936
23934
  }
23937
- function verifyDigest(distribution, bytes2) {
23935
+ async function download(client, distribution) {
23936
+ const bytes2 = await client.bytes(distribution.url, { timeoutMs: 12e4 });
23937
+ requireArchive(distribution, bytes2);
23938
+ const mismatch = digestMismatch(distribution, bytes2);
23939
+ if (!mismatch) return bytes2;
23940
+ const fresh = await refetch(client, distribution);
23941
+ if (fresh && !digestMismatch(distribution, fresh)) {
23942
+ requireArchive(distribution, fresh);
23943
+ return fresh;
23944
+ }
23945
+ throw new Error(
23946
+ `${mismatch} ${fresh ? "A retry past any cache returned the same bytes, so the index and the file it names disagree." : "A retry past any cache could not be made, so this may be a cached copy of an older build; clearing the cache, or asking the index's host to purge it, is worth trying before the index is blamed."}`
23947
+ );
23948
+ }
23949
+ async function refetch(client, distribution) {
23950
+ const separator = distribution.url.includes("?") ? "&" : "?";
23951
+ try {
23952
+ const bytes2 = await client.bytes(
23953
+ `${distribution.url}${separator}sha256=${distribution.sha256}`,
23954
+ { timeoutMs: 6e4 }
23955
+ );
23956
+ return bytes2.length > 1 && bytes2[0] === 80 && bytes2[1] === 75 ? bytes2 : null;
23957
+ } catch {
23958
+ return null;
23959
+ }
23960
+ }
23961
+ function digestMismatch(distribution, bytes2) {
23938
23962
  if (!distribution.sha256) {
23939
23963
  throw new Error(
23940
23964
  `${distribution.filename} was published without a sha256 digest, so it cannot be verified`
23941
23965
  );
23942
23966
  }
23943
23967
  const actual = [...sha256(bytes2)].map((b) => b.toString(16).padStart(2, "0")).join("");
23944
- if (actual !== distribution.sha256) {
23945
- throw new Error(
23946
- `${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}`
23947
- );
23948
- }
23968
+ if (actual === distribution.sha256) return null;
23969
+ return `${distribution.filename} failed verification: the index published sha256 ${distribution.sha256} but the download hashes to ${actual}.`;
23949
23970
  }
23950
23971
  function stageWheel(entries, resolved) {
23951
23972
  const staged = [];
@@ -28026,12 +28047,19 @@ async function installRelease(ctx, index, release, seen, options) {
28026
28047
  const base2 = registryBase(ctx).replace(/\/$/, "");
28027
28048
  const url = `${base2}/${release.filename}`;
28028
28049
  ctx.line(`Fetching ${release.name} ${release.version}`);
28029
- const archive = await download(url);
28030
- const digest2 = await digestHex("sha256", archive);
28050
+ let archive = await download2(url);
28051
+ let digest2 = await digestHex("sha256", archive);
28031
28052
  if (digest2 !== release.sha256) {
28032
- throw new AppRegistryError(
28033
- `${release.filename} failed verification: the registry publishes sha256 ${release.sha256} but the download hashes to ${digest2}`
28034
- );
28053
+ const retried = await download2(`${url}${url.includes("?") ? "&" : "?"}sha256=${release.sha256}`).catch(() => null);
28054
+ const retriedDigest = retried && await digestHex("sha256", retried);
28055
+ if (retried && retriedDigest === release.sha256) {
28056
+ archive = retried;
28057
+ digest2 = retriedDigest;
28058
+ } else {
28059
+ throw new AppRegistryError(
28060
+ `${release.filename} failed verification: the registry publishes sha256 ${release.sha256} but the download hashes to ${digest2}. ` + (retried ? "A retry past any cache returned the same bytes, so the registry and the file it names disagree." : "A retry past any cache could not be made; a cached copy of an older build would look like this, so clearing the cache is worth trying before the registry is blamed.")
28061
+ );
28062
+ }
28035
28063
  }
28036
28064
  const verified = await verify(ctx, archive, release, options);
28037
28065
  const root = `${APPS_ROOT}/${release.name}`;
@@ -28058,7 +28086,7 @@ async function installRelease(ctx, index, release, seen, options) {
28058
28086
  }
28059
28087
  if (manifest.docs) ctx.line(` docs: ${root}/${manifest.docs}`);
28060
28088
  }
28061
- async function download(url) {
28089
+ async function download2(url) {
28062
28090
  const response = await fetch(url);
28063
28091
  if (!response.ok) {
28064
28092
  throw new AppRegistryError(`${url} answered ${response.status} ${response.statusText}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxedjs",
3
- "version": "0.1.95",
3
+ "version": "0.1.97",
4
4
  "description": "A Linux-like container that runs entirely inside Node.js — POSIX shell, ~140 coreutils, Node.js and Python runtimes, virtual filesystem and networking. No Docker, no VM, no native modules.",
5
5
  "type": "module",
6
6
  "license": "MIT",