feat: add server-side pagination to API endpoints#1464
feat: add server-side pagination to API endpoints#1464fabiovincenzi wants to merge 39 commits intofinos:mainfrom
Conversation
✅ Deploy Preview for endearing-brigadeiros-63f9d0 canceled.
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1464 +/- ##
==========================================
+ Coverage 89.66% 89.73% +0.06%
==========================================
Files 68 68
Lines 4869 5048 +179
Branches 888 931 +43
==========================================
+ Hits 4366 4530 +164
- Misses 485 500 +15
Partials 18 18 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
dcoric
left a comment
There was a problem hiding this comment.
Thanks for the solid work on server-side pagination. I have a few concerns - mostly around security and a couple of behavioral issues that should be addressed before merging.
…g on sensitive fields
There was a problem hiding this comment.
Oddly, the repo list sorting doesn't seem to be working right on my end - whenever I change the sorting order, the dropdown selector just resets (and only the default alphabetical order is shown regardless of which one I choose).
Related to that, when I move to another page the selected filter gets reset, which (might) be resetting the filter to alphabetical ascending order.
I don't get any error output on console, BTW 🤷🏼
src/db/file/helper.ts
Outdated
| }); | ||
| }); | ||
|
|
||
| return Promise.all([dataPromise, countPromise]).then(([data, total]) => ({ data, total })); |
There was a problem hiding this comment.
I'm wondering if we should change the data variable to something more descriptive... Right now, we end up calling response.data.data to fetch the repos/users/etc. which can trip up people/agents working with the code.
I'd suggest having the name of the entity { users, total }, etc. although we'd need to pass in the entity name to paginatedFind (unless it's already obtainable in the existing function parameters).
There was a problem hiding this comment.
Good point, the HTTP routes now return entity-specific keys (pushes, repos, users) instead of data. The data variable inside paginatedFind remains as a generic internal name but not exposed directly.
packages/git-proxy-cli/index.ts
Outdated
| try { | ||
| const cookies = JSON.parse(fs.readFileSync(GIT_PROXY_COOKIE_FILE, 'utf8')); | ||
| const { data } = await axios.get<Action[]>(`${baseUrl}/api/v1/push/`, { | ||
| const response = await axios.get<{ data: Action[]; total: number }>(`${baseUrl}/api/v1/push/`, { |
There was a problem hiding this comment.
Can use PaginatedResult type here
There was a problem hiding this comment.
the /push endpoint now returns pushes instead of data.
| type: 'push', | ||
| }; | ||
|
|
||
| const pushProjection = { |
There was a problem hiding this comment.
Perhaps this could be a constant (and potentially placed somewhere else)? Wondering if there are any other constants from the db module that we could wrap into a /db/constants.ts file.
On another note, I'm wondering why we have been doing manual projection at all - if we want to exclude certain fields, we could do post-processing just like we do with users (toPublicUser).
There was a problem hiding this comment.
Fixing this should also help simplify the tests that rely on projection 👍🏼
There was a problem hiding this comment.
I'm not sure about the reasons for projections here, filtering at the DB level avoids transferring data that is not needed, such as steps which can be quite large. Post-processing like toPublicUser, would work but at the cost of fetching full documents first. Not sure though if this is the reason
Would it be worth tracking in a separate issue/PR to keep this one focused?
src/service/routes/utils.ts
Outdated
| const skip = (page - 1) * limit; | ||
|
|
||
| const pagination: PaginationOptions = { skip, limit }; | ||
| if (req.query['search']) pagination.search = req.query['search'] as string; |
There was a problem hiding this comment.
Wondering if we could have stronger typing for req here - so we could do the following:
const { search, sortBy, sortOrder } = req.query;Extending the Request type can be a huge pain, but it's been done before with the user property for the passport strategies. This might be more appropriate for a separate PR if it requires too many extra changes!
There was a problem hiding this comment.
Done, introduced a PaginationQuery interface and cast req.query once at the top, allowing destructuring without repeated as string casts. I didn't make the global Request type since query params vary per route.
@jescalada Good catch. I tried to replicate the client side sorting behaviour we had before without verifying that |
This might be a breaking change unless you include a migration of some sort for existing DBs or at least some form of backwards compatibility.
much simpler and non-breaking. If opening a ticket ensure it covers migration/consideration of how to make the change non-breaking (which would usually involve the ability to roll back!). n.b. dates could possible be extracted from logs in existing records... |
…arsePaginationParams
…pting search request
…enzi/git-proxy into server-side-pagination
|
In this PR, list endpoints were changed from returning a plain array to returning For the rename (data → pushes/repos/users), we could keep data as an alias. For the array, the only clean backwards-compatible solution would be to keep the existing endpoints returning the plain array and add new paginated endpoints alongside them, but that means maintaining duplicate logic until the old ones are deprecated. Any thoughts? |
|
I think you've hit on the right answer there - you need to create new endpoints with the new behaviour then switch UI services and the UI itself over to them. Clearly mark the old ones are deprecated and consider where we can provide messaging about them being deprecated. If we'd got this into the v2 scope, we wouldn't need to do that I guess... WDYT @jescalada |
Fixes #1297
Implements server side pagination for
/push,/repoand/usersendpoints.Note: The list endpoints (
/push,/repo,/users) now return{ data, total }instead of a plain array to support pagination metadata.