Skip to content

feat: add support to add/edit repositories in collections#1770

Merged
gaspergrom merged 3 commits intomainfrom
feat/collection-repositories
Mar 26, 2026
Merged

feat: add support to add/edit repositories in collections#1770
gaspergrom merged 3 commits intomainfrom
feat/collection-repositories

Conversation

@gaspergrom
Copy link
Copy Markdown
Collaborator

No description provided.

Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
@gaspergrom gaspergrom self-assigned this Mar 24, 2026
Copilot AI review requested due to automatic review settings March 24, 2026 09:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds repository URL support to community collections so collections can include repositories in addition to insights projects, and returns repository metadata alongside existing collection responses.

Changes:

  • Extend collection create/update flows to accept repositoryUrls and persist collection↔repository relations.
  • Include repositoryUrls / repositoryCount in collection read/query responses.
  • Include repository data in “liked collections” responses.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
frontend/server/repo/communityCollection.repo.ts Adds repository association persistence and returns repository URLs/counts in collection reads.
frontend/server/repo/collectionLike.repo.ts Enriches liked-collection results with repository URLs/counts and adjusts featured project selection.
frontend/server/api/collection/community/index.post.ts Accepts and validates repositoryUrls for collection creation.
frontend/server/api/collection/community/[id].put.ts Accepts and validates repositoryUrls for collection updates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (notFound.length > 0) {
throw createError({
statusCode: 400,
statusMessage: `Repository URLs not found: ${notFound.join(', ')}`,
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message for missing repositories includes the full list of user-provided URLs in statusMessage (potentially up to 1000 items). This can create extremely large responses/log lines and makes the HTTP error payload noisy. Consider using a short statusMessage (e.g., "Some repository URLs were not found") and move the detailed list (or a capped subset + count) into the error data field.

Suggested change
statusMessage: `Repository URLs not found: ${notFound.join(', ')}`,
statusMessage: 'Some repository URLs were not found',
data: {
notFoundUrls: notFound,
notFoundCount: notFound.length,
},

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +66
if (body.repositoryUrls !== undefined) {
if (
!Array.isArray(body.repositoryUrls) ||
body.repositoryUrls.some((u) => typeof u !== 'string' || !u)
) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls must be an array of non-empty strings',
});
}
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation for repositoryUrls allows whitespace-only strings (e.g., ' '), since it checks !u rather than !u.trim(). This will later fail the repository lookup with a less-direct error. Consider trimming each URL (and validating non-empty post-trim) before passing them to the repository layer.

Copilot uses AI. Check for mistakes.
Comment on lines +64 to +79
if (
!Array.isArray(body.repositoryUrls) ||
body.repositoryUrls.some((u) => typeof u !== 'string' || !u)
) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls must be an array of non-empty strings',
});
}

if (body.repositoryUrls.length > 1000) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls cannot exceed 1000 items',
});
}
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation for repositoryUrls allows whitespace-only strings (e.g., ' '), since it checks !u rather than !u.trim(). Consider trimming/normalizing each URL (and validating non-empty post-trim) before calling repo.update, so updates don’t silently fail with "not found" errors due to stray whitespace.

Suggested change
if (
!Array.isArray(body.repositoryUrls) ||
body.repositoryUrls.some((u) => typeof u !== 'string' || !u)
) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls must be an array of non-empty strings',
});
}
if (body.repositoryUrls.length > 1000) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls cannot exceed 1000 items',
});
}
if (!Array.isArray(body.repositoryUrls)) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls must be an array of non-empty strings',
});
}
const normalizedRepositoryUrls = body.repositoryUrls.map((u) =>
typeof u === 'string' ? u.trim() : u,
);
if (normalizedRepositoryUrls.some((u) => typeof u !== 'string' || !u)) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls must be an array of non-empty strings',
});
}
if (normalizedRepositoryUrls.length > 1000) {
throw createError({
statusCode: 400,
statusMessage: 'repositoryUrls cannot exceed 1000 items',
});
}
body.repositoryUrls = normalizedRepositoryUrls;

Copilot uses AI. Check for mistakes.
Comment on lines +178 to +185
featuredProjects: [...allProjects]
.sort((a, b) => a.name.localeCompare(b.name))
.slice(0, 5)
.map((p) => ({
name: p.name,
slug: p.slug,
logo: p.logoUrl,
})),
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

featuredProjects is computed by sorting the full allProjects array for each liked collection and then slicing to 5. If collections can have many projects, this is an avoidable O(n log n) cost per collection per request. Consider ordering in SQL (or using a window function / per-collection limit) so the API only processes the top 5 items needed.

Copilot uses AI. Check for mistakes.
Comment thread frontend/server/repo/communityCollection.repo.ts
Comment on lines +58 to +60
if (body.projects.length > 1000) {
throw createError({ statusCode: 400, statusMessage: 'projects cannot exceed 1000 items' });
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this limit?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed it

Comment thread frontend/server/repo/communityCollection.repo.ts
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
@gaspergrom gaspergrom merged commit f777eef into main Mar 26, 2026
9 checks passed
@gaspergrom gaspergrom deleted the feat/collection-repositories branch March 26, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants