From 83bfba3bc85c1da694bb0f83a30bb41081fe52ed Mon Sep 17 00:00:00 2001
From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com>
Date: Mon, 10 Feb 2025 21:32:56 +0100
Subject: [PATCH 1/7] feat(user page): Recently published
---
api/src/api/users.rs | 19 +++++++++++++++++++
api/src/db/database.rs | 20 ++++++++++++++++++++
frontend/routes/user/[id].tsx | 33 +++++++++++++++++++++++----------
3 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/api/src/api/users.rs b/api/src/api/users.rs
index 975cfb4a6..dd6604985 100644
--- a/api/src/api/users.rs
+++ b/api/src/api/users.rs
@@ -13,6 +13,7 @@ use crate::util::ApiResult;
use crate::util::RequestIdExt;
use super::ApiError;
+use super::ApiPackage;
use super::ApiScope;
use super::ApiUser;
@@ -20,6 +21,7 @@ pub fn users_router() -> Router
{
Router::builder()
.get("/:id", util::json(get_handler))
.get("/:id/scopes", util::json(get_scopes_handler))
+ .get("/:id/packages", util::json(get_packages_handler))
.build()
.unwrap()
}
@@ -54,3 +56,20 @@ pub async fn get_scopes_handler(
Ok(scopes.into_iter().map(ApiScope::from).collect())
}
+
+#[instrument(name = "GET /api/users/:id/packages", skip(req), err, fields(id))]
+pub async fn get_packages_handler(
+ req: Request,
+) -> ApiResult> {
+ let id = req.param_uuid("id")?;
+ Span::current().record("id", field::display(id));
+
+ let db = req.data::().unwrap();
+ db.get_user_public(id)
+ .await?
+ .ok_or(ApiError::UserNotFound)?;
+
+ let packages = db.get_recent_packages_by_user(&id).await?;
+
+ Ok(packages.into_iter().map(ApiPackage::from).collect())
+}
diff --git a/api/src/db/database.rs b/api/src/db/database.rs
index 9be634d35..5eaf64f7e 100644
--- a/api/src/db/database.rs
+++ b/api/src/db/database.rs
@@ -3173,6 +3173,26 @@ impl Database {
.fetch_all(&self.pool)
.await
}
+
+ pub async fn get_recent_packages_by_user(
+ &self,
+ user_id: &uuid::Uuid,
+ ) -> Result> {
+ let packages = sqlx::query_as!(
+ Package,
+ r#"
+ SELECT * FROM packages
+ WHERE owner_id = $1
+ ORDER BY published_at DESC
+ LIMIT 10
+ "#,
+ user_id
+ )
+ .fetch_all(&self.pool)
+ .await?;
+
+ Ok(packages)
+ }
}
async fn finalize_package_creation(
diff --git a/frontend/routes/user/[id].tsx b/frontend/routes/user/[id].tsx
index 75580dd2f..17f8f3438 100644
--- a/frontend/routes/user/[id].tsx
+++ b/frontend/routes/user/[id].tsx
@@ -2,7 +2,7 @@
import { HttpError } from "fresh";
import { define } from "../../util.ts";
import { path } from "../../utils/api.ts";
-import { FullUser, Scope, User } from "../../utils/api_types.ts";
+import { FullUser, Package, Scope, User } from "../../utils/api_types.ts";
import { ListPanel } from "../../components/ListPanel.tsx";
import { AccountLayout } from "../account/(_components)/AccountLayout.tsx";
@@ -31,14 +31,24 @@ export default define.page(function UserPage({ data, state }) {
)}
- {
- /*
-
Recently published
-
- TODO: all packages recently published by this user
-
-
*/
- }
+ {data.packages.length > 0
+ ? (
+ ({
+ value: pkg.name,
+ href: `/packages/${pkg.id}`,
+ }))}
+ />
+ )
+ : (
+
+ {state.user?.id === data.user.id ? "You have" : "This user has"}
+ {" "}
+ not published any packages recently.
+
+ )}
);
@@ -46,10 +56,11 @@ export default define.page(function UserPage({ data, state }) {
export const handler = define.handlers({
async GET(ctx) {
- const [currentUser, userRes, scopesRes] = await Promise.all([
+ const [currentUser, userRes, scopesRes, packagesRes] = await Promise.all([
ctx.state.userPromise,
ctx.state.api.get(path`/users/${ctx.params.id}`),
ctx.state.api.get(path`/users/${ctx.params.id}/scopes`),
+ ctx.state.api.get(path`/users/${ctx.params.id}/packages`),
]);
if (currentUser instanceof Response) return currentUser;
@@ -61,6 +72,7 @@ export const handler = define.handlers({
throw userRes; // gracefully handle errors
}
if (!scopesRes.ok) throw scopesRes; // gracefully handle errors
+ if (!packagesRes.ok) throw packagesRes; // gracefully handle errors
let user: User | FullUser = userRes.data;
if (ctx.params.id === currentUser?.id) {
@@ -74,6 +86,7 @@ export const handler = define.handlers({
data: {
user,
scopes: scopesRes.data,
+ packages: packagesRes.data,
},
};
},
From 960e2a05a1b81439707eb39a2fffb5bbcf770811 Mon Sep 17 00:00:00 2001
From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com>
Date: Mon, 10 Feb 2025 21:40:20 +0100
Subject: [PATCH 2/7] FIx: wrong link
---
frontend/routes/user/[id].tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/frontend/routes/user/[id].tsx b/frontend/routes/user/[id].tsx
index 17f8f3438..90c4b417d 100644
--- a/frontend/routes/user/[id].tsx
+++ b/frontend/routes/user/[id].tsx
@@ -38,7 +38,8 @@ export default define.page(function UserPage({ data, state }) {
subtitle="Packages recently published by this user"
children={data.packages.map((pkg) => ({
value: pkg.name,
- href: `/packages/${pkg.id}`,
+ //@am/neuralnetwork
+ href: `/${pkg.scope}/${pkg.name}`,
}))}
/>
)
From 751dd9ebd49c41cd675a3b6ddb1fcd12581d4747 Mon Sep 17 00:00:00 2001
From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com>
Date: Mon, 10 Feb 2025 21:50:27 +0100
Subject: [PATCH 3/7] fix: rs build ?
---
api/src/api/users.rs | 2 +-
api/src/db/database.rs | 36 +++++++++++++++++++++++++++---------
2 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/api/src/api/users.rs b/api/src/api/users.rs
index dd6604985..0eab90fb6 100644
--- a/api/src/api/users.rs
+++ b/api/src/api/users.rs
@@ -13,9 +13,9 @@ use crate::util::ApiResult;
use crate::util::RequestIdExt;
use super::ApiError;
-use super::ApiPackage;
use super::ApiScope;
use super::ApiUser;
+use super::ApiPackage;
pub fn users_router() -> Router {
Router::builder()
diff --git a/api/src/db/database.rs b/api/src/db/database.rs
index 5eaf64f7e..f4f585de7 100644
--- a/api/src/db/database.rs
+++ b/api/src/db/database.rs
@@ -3174,25 +3174,43 @@ impl Database {
.await
}
- pub async fn get_recent_packages_by_user(
- &self,
- user_id: &uuid::Uuid,
- ) -> Result> {
+ pub async fn get_recent_packages_by_user(&self, user_id: &uuid::Uuid) -> Result, PackageVersionMeta)>> {
let packages = sqlx::query_as!(
- Package,
- r#"
+ Package,
+ r#"
SELECT * FROM packages
WHERE owner_id = $1
ORDER BY published_at DESC
LIMIT 10
"#,
- user_id
+ user_id
)
.fetch_all(&self.pool)
.await?;
- Ok(packages)
- }
+ let mut result = Vec::new();
+ for package in packages {
+ let repo = sqlx::query_as!(
+ GithubRepository,
+ "SELECT * FROM github_repositories WHERE package_id = $1",
+ package.id
+ )
+ .fetch_optional(&self.pool)
+ .await?;
+
+ let meta = sqlx::query_as!(
+ PackageVersionMeta,
+ "SELECT * FROM package_version_meta WHERE package_id = $1",
+ package.id
+ )
+ .fetch_one(&self.pool)
+ .await?;
+
+ result.push((package, repo, meta));
+ }
+
+ Ok(result)
+}
}
async fn finalize_package_creation(
From 187f498d416827de1b6a4e9e720a17edd6091dc3 Mon Sep 17 00:00:00 2001
From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com>
Date: Mon, 10 Feb 2025 22:52:02 +0100
Subject: [PATCH 4/7] refracto
---
api/src/api/users.rs | 9 +++++--
api/src/db/database.rs | 54 ++++++++++++++++--------------------------
2 files changed, 27 insertions(+), 36 deletions(-)
diff --git a/api/src/api/users.rs b/api/src/api/users.rs
index 0eab90fb6..3b394168a 100644
--- a/api/src/api/users.rs
+++ b/api/src/api/users.rs
@@ -13,9 +13,9 @@ use crate::util::ApiResult;
use crate::util::RequestIdExt;
use super::ApiError;
+use super::ApiPackage;
use super::ApiScope;
use super::ApiUser;
-use super::ApiPackage;
pub fn users_router() -> Router {
Router::builder()
@@ -71,5 +71,10 @@ pub async fn get_packages_handler(
let packages = db.get_recent_packages_by_user(&id).await?;
- Ok(packages.into_iter().map(ApiPackage::from).collect())
+ Ok(
+ packages
+ .into_iter()
+ .map(|package| ApiPackage::from((package, None, Default::default())))
+ .collect(),
+ )
}
diff --git a/api/src/db/database.rs b/api/src/db/database.rs
index f4f585de7..3a7da5b8a 100644
--- a/api/src/db/database.rs
+++ b/api/src/db/database.rs
@@ -1145,7 +1145,7 @@ impl Database {
let newest = sqlx::query!(
r#"SELECT packages.scope "package_scope: ScopeName", packages.name "package_name: PackageName", packages.description "package_description", packages.github_repository_id "package_github_repository_id", packages.runtime_compat as "package_runtime_compat: RuntimeCompat", packages.when_featured "package_when_featured", packages.is_archived "package_is_archived", packages.updated_at "package_updated_at", packages.created_at "package_created_at",
(SELECT COUNT(created_at) FROM package_versions WHERE scope = packages.scope AND name = packages.name) as "package_version_count!",
- (SELECT version FROM package_versions WHERE scope = packages.scope AND name = packages.name AND version NOT LIKE '%-%' AND is_yanked = false ORDER BY version DESC LIMIT 1) as "package_latest_version",
+ (SELECT version FROM package_versions WHERE scope = packages.scope AND name = packages.name AND is_yanked = false AND version IS NOT NULL ORDER BY version DESC LIMIT 1) as "package_latest_version",
(SELECT meta FROM package_versions WHERE scope = packages.scope AND name = packages.name AND version NOT LIKE '%-%' AND is_yanked = false ORDER BY version DESC LIMIT 1) as "package_version_meta: PackageVersionMeta",
github_repositories.id "github_repository_id?", github_repositories.owner "github_repository_owner?", github_repositories.name "github_repository_name?", github_repositories.updated_at "github_repository_updated_at?", github_repositories.created_at "github_repository_created_at?"
FROM packages
@@ -3174,43 +3174,29 @@ impl Database {
.await
}
- pub async fn get_recent_packages_by_user(&self, user_id: &uuid::Uuid) -> Result, PackageVersionMeta)>> {
- let packages = sqlx::query_as!(
- Package,
- r#"
- SELECT * FROM packages
- WHERE owner_id = $1
- ORDER BY published_at DESC
- LIMIT 10
- "#,
- user_id
- )
- .fetch_all(&self.pool)
- .await?;
-
- let mut result = Vec::new();
- for package in packages {
- let repo = sqlx::query_as!(
- GithubRepository,
- "SELECT * FROM github_repositories WHERE package_id = $1",
- package.id
- )
- .fetch_optional(&self.pool)
- .await?;
+ pub async fn get_recent_packages_by_user(
+ &self,
+ user_id: &uuid::Uuid,
+ ) -> Result> {
+ // need to fetch all scopes where user is in
+ // then fetch all packages in those scopes
+ // then sort by created_at
+ // then limit 10
+ let scopes = self.get_member_scopes_by_user(user_id).await?;
- let meta = sqlx::query_as!(
- PackageVersionMeta,
- "SELECT * FROM package_version_meta WHERE package_id = $1",
- package.id
- )
- .fetch_one(&self.pool)
+ let mut packages = Vec::new();
+ for scope in scopes {
+ let (_, scope_packages) = self
+ .list_packages_by_scope(&scope.scope, true, 0, 100)
.await?;
-
- result.push((package, repo, meta));
+ packages.extend(scope_packages.into_iter().map(|(p, _, _)| p));
}
- Ok(result)
-}
+ packages.sort_by(|a, b| b.created_at.cmp(&a.created_at));
+ packages.truncate(10);
+
+ Ok(packages)
+ }
}
async fn finalize_package_creation(
From e5b29428e4a28282f9350fa1ca0cf4cad43ce341 Mon Sep 17 00:00:00 2001
From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com>
Date: Tue, 11 Feb 2025 11:15:28 +0100
Subject: [PATCH 5/7] revert useless changes
---
api/src/db/database.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/api/src/db/database.rs b/api/src/db/database.rs
index 3a7da5b8a..aa0f6799e 100644
--- a/api/src/db/database.rs
+++ b/api/src/db/database.rs
@@ -1145,7 +1145,7 @@ impl Database {
let newest = sqlx::query!(
r#"SELECT packages.scope "package_scope: ScopeName", packages.name "package_name: PackageName", packages.description "package_description", packages.github_repository_id "package_github_repository_id", packages.runtime_compat as "package_runtime_compat: RuntimeCompat", packages.when_featured "package_when_featured", packages.is_archived "package_is_archived", packages.updated_at "package_updated_at", packages.created_at "package_created_at",
(SELECT COUNT(created_at) FROM package_versions WHERE scope = packages.scope AND name = packages.name) as "package_version_count!",
- (SELECT version FROM package_versions WHERE scope = packages.scope AND name = packages.name AND is_yanked = false AND version IS NOT NULL ORDER BY version DESC LIMIT 1) as "package_latest_version",
+ (SELECT version FROM package_versions WHERE scope = packages.scope AND name = packages.name AND version NOT LIKE '%-%' AND is_yanked = false ORDER BY version DESC LIMIT 1) as "package_latest_version",
(SELECT meta FROM package_versions WHERE scope = packages.scope AND name = packages.name AND version NOT LIKE '%-%' AND is_yanked = false ORDER BY version DESC LIMIT 1) as "package_version_meta: PackageVersionMeta",
github_repositories.id "github_repository_id?", github_repositories.owner "github_repository_owner?", github_repositories.name "github_repository_name?", github_repositories.updated_at "github_repository_updated_at?", github_repositories.created_at "github_repository_created_at?"
FROM packages
From 4f011c1bab63826228545771a09eb3e8ed19aef7 Mon Sep 17 00:00:00 2001
From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com>
Date: Tue, 11 Feb 2025 20:40:35 +0100
Subject: [PATCH 6/7] fix + clean
---
api/src/db/database.rs | 41 +++++++++++++++++++++--------------
frontend/routes/user/[id].tsx | 2 +-
2 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/api/src/db/database.rs b/api/src/db/database.rs
index aa0f6799e..0f29c4a94 100644
--- a/api/src/db/database.rs
+++ b/api/src/db/database.rs
@@ -3178,22 +3178,31 @@ impl Database {
&self,
user_id: &uuid::Uuid,
) -> Result> {
- // need to fetch all scopes where user is in
- // then fetch all packages in those scopes
- // then sort by created_at
- // then limit 10
- let scopes = self.get_member_scopes_by_user(user_id).await?;
-
- let mut packages = Vec::new();
- for scope in scopes {
- let (_, scope_packages) = self
- .list_packages_by_scope(&scope.scope, true, 0, 100)
- .await?;
- packages.extend(scope_packages.into_iter().map(|(p, _, _)| p));
- }
-
- packages.sort_by(|a, b| b.created_at.cmp(&a.created_at));
- packages.truncate(10);
+ let packages = sqlx::query_as!(
+ Package,
+ r#"
+ SELECT DISTINCT ON (packages.scope, packages.name)
+ packages.scope as "scope: ScopeName",
+ packages.name as "name: PackageName",
+ packages.description,
+ packages.github_repository_id,
+ packages.runtime_compat as "runtime_compat: RuntimeCompat",
+ packages.when_featured,
+ packages.is_archived,
+ packages.updated_at,
+ packages.created_at,
+ (SELECT COUNT(created_at) FROM package_versions WHERE scope = packages.scope AND name = packages.name) as "version_count!",
+ (SELECT version FROM package_versions WHERE scope = packages.scope AND name = packages.name AND version NOT LIKE '%-%' AND is_yanked = false ORDER BY version DESC LIMIT 1) as "latest_version"
+ FROM packages
+ JOIN scope_members ON packages.scope = scope_members.scope
+ WHERE scope_members.user_id = $1
+ ORDER BY packages.scope, packages.name, packages.created_at DESC
+ LIMIT 10;
+ "#,
+ user_id
+ )
+ .fetch_all(&self.pool)
+ .await?;
Ok(packages)
}
diff --git a/frontend/routes/user/[id].tsx b/frontend/routes/user/[id].tsx
index 90c4b417d..df8d4bf30 100644
--- a/frontend/routes/user/[id].tsx
+++ b/frontend/routes/user/[id].tsx
@@ -37,7 +37,7 @@ export default define.page(function UserPage({ data, state }) {
title="Recently published"
subtitle="Packages recently published by this user"
children={data.packages.map((pkg) => ({
- value: pkg.name,
+ value: `@${pkg.scope}/${pkg.name}`,
//@am/neuralnetwork
href: `/${pkg.scope}/${pkg.name}`,
}))}
From 23071eb6269599e5df752882f16769bbd797c488 Mon Sep 17 00:00:00 2001
From: Augustin Mauroy <97875033+AugustinMauroy@users.noreply.github.com>
Date: Tue, 11 Mar 2025 21:37:10 +0100
Subject: [PATCH 7/7] fix: lint
---
frontend/routes/user/[id].tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/frontend/routes/user/[id].tsx b/frontend/routes/user/[id].tsx
index 669fa0325..45cc840fb 100644
--- a/frontend/routes/user/[id].tsx
+++ b/frontend/routes/user/[id].tsx
@@ -37,6 +37,7 @@ export default define.page(function UserPage({ data, state }) {
({
value: `@${pkg.scope}/${pkg.name}`,
//@am/neuralnetwork