From 0f3ba5c8cc5a072863a1ca3955c271385c58fd99 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Sat, 1 Mar 2025 19:47:11 +0100 Subject: [PATCH 1/4] fix: properly error for invalid tarballs --- api/src/tarball.rs | 23 ++++++++++++++++------- frontend/docs/publishing-packages.md | 27 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/api/src/tarball.rs b/api/src/tarball.rs index 45651539..dbc5c70d 100644 --- a/api/src/tarball.rs +++ b/api/src/tarball.rs @@ -102,7 +102,7 @@ pub async fn process_tarball( let async_read = stream.into_async_read(); let mut tar = async_tar::Archive::new(async_read) .entries() - .map_err(PublishError::UntarError)?; + .map_err(from_tarball_io_error)?; let mut files = HashMap::new(); let mut case_insensitive_paths = HashSet::::new(); @@ -126,7 +126,7 @@ pub async fn process_tarball( }; while let Some(res) = tar.next().await { - let mut entry = res.map_err(PublishError::UntarError)?; + let mut entry = res.map_err(from_tarball_io_error)?; let header = entry.header(); let path = String::from_utf8_lossy(&entry.path_bytes()).into_owned(); @@ -158,7 +158,7 @@ pub async fn process_tarball( }); } - let size = header.size().map_err(PublishError::UntarError)?; + let size = header.size().map_err(from_tarball_io_error)?; if size > max_file_size { return Err(PublishError::FileTooLarge { path, @@ -180,7 +180,7 @@ pub async fn process_tarball( entry .read_to_end(&mut bytes) .await - .map_err(PublishError::UntarError)?; + .map_err(from_tarball_io_error)?; // sha256 hash the bytes let hash = sha2::Sha256::digest(&bytes); @@ -479,8 +479,8 @@ pub enum PublishError { #[error("gcs upload error: {0}")] GcsUploadError(GcsError), - #[error("untar error: {0}")] - UntarError(io::Error), + #[error("invalid tarball: {0}")] + InvalidTarball(io::Error), #[error("database error")] DatabaseError(#[from] sqlx::Error), @@ -630,9 +630,9 @@ impl PublishError { match self { PublishError::GcsDownloadError(_) => None, PublishError::GcsUploadError(_) => None, - PublishError::UntarError(_) => None, PublishError::MissingTarball => None, PublishError::DatabaseError(_) => None, + PublishError::InvalidTarball(_) => Some("invalidTarball"), PublishError::LinkInTarball { .. } => Some("linkInTarball"), PublishError::InvalidEntryType { .. } => Some("invalidEntryType"), PublishError::InvalidPath { .. } => Some("invalidPath"), @@ -686,6 +686,15 @@ impl PublishError { } } +fn from_tarball_io_error(err: io::Error) -> PublishError { + match err.downcast::() { + Ok(err) => { + return PublishError::GcsDownloadError(GcsError::Reqwest(err)); + } + Err(err) => PublishError::InvalidTarball(err), + } +} + pub struct FileInfo { pub path: PackagePath, pub size: u64, diff --git a/frontend/docs/publishing-packages.md b/frontend/docs/publishing-packages.md index 44851c85..169b1c78 100644 --- a/frontend/docs/publishing-packages.md +++ b/frontend/docs/publishing-packages.md @@ -182,6 +182,33 @@ export { greet } from "@luca/greet"; export { join } from "@std/path"; ``` +### Peer dependencies + +In JSR, there is no need to specify peer dependencies separately from regular +dependencies. In JSR, dependencies are not per package — they are traced per +file. For example: a package that has both an entrypoint for `react`, and one +for `vue`, a user importing the `@foo/bar/react` entrypoint will not have to +download the `vue` dependency. This is because the `vue` dependency is only +needed for the `@foo/bar/vue` entrypoint. + +When using `deno.json` to specify dependencies, you can just specify peer +dependencies as regular dependencies. You should specify a wide range of +versions for peer dependencies to ensure that you do not cause duplicate copies +of the same dependency to be downloaded. + +```json +// deno.json +{ + "name": "@luca/greet", + "version": "1.0.0", + "exports": "./mod.ts", + "dependencies": { + "react": "npm:react@18", + "vue": "npm:vue@*" + } +} +``` + ### Preventing slow types When writing TypeScript, you should ensure that your code does not use "slow From b704ac3ebf03a35f7c996ed244f43a3111455b7c Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Sat, 1 Mar 2025 20:25:07 +0100 Subject: [PATCH 2/4] Fix --- frontend/docs/publishing-packages.md | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/frontend/docs/publishing-packages.md b/frontend/docs/publishing-packages.md index 169b1c78..44851c85 100644 --- a/frontend/docs/publishing-packages.md +++ b/frontend/docs/publishing-packages.md @@ -182,33 +182,6 @@ export { greet } from "@luca/greet"; export { join } from "@std/path"; ``` -### Peer dependencies - -In JSR, there is no need to specify peer dependencies separately from regular -dependencies. In JSR, dependencies are not per package — they are traced per -file. For example: a package that has both an entrypoint for `react`, and one -for `vue`, a user importing the `@foo/bar/react` entrypoint will not have to -download the `vue` dependency. This is because the `vue` dependency is only -needed for the `@foo/bar/vue` entrypoint. - -When using `deno.json` to specify dependencies, you can just specify peer -dependencies as regular dependencies. You should specify a wide range of -versions for peer dependencies to ensure that you do not cause duplicate copies -of the same dependency to be downloaded. - -```json -// deno.json -{ - "name": "@luca/greet", - "version": "1.0.0", - "exports": "./mod.ts", - "dependencies": { - "react": "npm:react@18", - "vue": "npm:vue@*" - } -} -``` - ### Preventing slow types When writing TypeScript, you should ensure that your code does not use "slow From a4ab600f9559b751b51cb416f4e853e13c151f6c Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Sat, 1 Mar 2025 20:25:45 +0100 Subject: [PATCH 3/4] Update tarball.rs --- api/src/tarball.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/tarball.rs b/api/src/tarball.rs index dbc5c70d..509a52b9 100644 --- a/api/src/tarball.rs +++ b/api/src/tarball.rs @@ -689,7 +689,7 @@ impl PublishError { fn from_tarball_io_error(err: io::Error) -> PublishError { match err.downcast::() { Ok(err) => { - return PublishError::GcsDownloadError(GcsError::Reqwest(err)); + PublishError::GcsDownloadError(GcsError::Reqwest(err)) } Err(err) => PublishError::InvalidTarball(err), } From 8d4abb2a8b8e43f4924863f930b35c7327d88929 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Sun, 2 Mar 2025 00:00:31 +0100 Subject: [PATCH 4/4] fmt --- api/src/tarball.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/src/tarball.rs b/api/src/tarball.rs index 509a52b9..260ca3bc 100644 --- a/api/src/tarball.rs +++ b/api/src/tarball.rs @@ -688,9 +688,7 @@ impl PublishError { fn from_tarball_io_error(err: io::Error) -> PublishError { match err.downcast::() { - Ok(err) => { - PublishError::GcsDownloadError(GcsError::Reqwest(err)) - } + Ok(err) => PublishError::GcsDownloadError(GcsError::Reqwest(err)), Err(err) => PublishError::InvalidTarball(err), } }