M Zeeshan
M Zeeshan4mo ago

Authentication in paginated query

How do I implement user authentication checks in paginated queries error:
Type '{ success: boolean; message: string; }' is missing the following properties from type 'PaginationResult<any>': page, isDone, continueCursor
Type '{ success: boolean; message: string; }' is missing the following properties from type 'PaginationResult<any>': page, isDone, continueCursor
server:
query({
handler: async () => {
const user = await ctx.auth.getUserIdentity();

if (!user) {
return {
success: false,
message: 'unauthenticated request',
};
}

return await queryBuilder
.order('desc')
.paginate(args.paginationOpts);
},
});
query({
handler: async () => {
const user = await ctx.auth.getUserIdentity();

if (!user) {
return {
success: false,
message: 'unauthenticated request',
};
}

return await queryBuilder
.order('desc')
.paginate(args.paginationOpts);
},
});
front-end:
const { results, loadMore, status, isLoading } = usePaginatedQuery(
api.hire_requests.getMultiple, // <---- EROR HERE
args,
{ initialNumItems: 20 },
);
const { results, loadMore, status, isLoading } = usePaginatedQuery(
api.hire_requests.getMultiple, // <---- EROR HERE
args,
{ initialNumItems: 20 },
);
38 Replies
M Zeeshan
M ZeeshanOP4mo ago
Is it valid to add props like this to resolve this error? Are there any potential issues with this approach?
if (!user) {
return {
success: false,
message: 'unauthenticated request',
page: [],
isDone: true,
continueCursor: '',
};
}
if (!user) {
return {
success: false,
message: 'unauthenticated request',
page: [],
isDone: true,
continueCursor: '',
};
}
Hmza
Hmza4mo ago
when you do this, is typescript happy on your front ?
M Zeeshan
M ZeeshanOP4mo ago
yep no errors
Hmza
Hmza4mo ago
then i don't see any reasons not todo it. great!
M Zeeshan
M ZeeshanOP4mo ago
what should i set isDone false/true
Hmza
Hmza4mo ago
it should be isDone: true to give an impression that pagination was done and there are no more pages to load. i see it can be confusing if you want to take a better approach you should type the error result and pagination result seperately and then return a union type.
M Zeeshan
M ZeeshanOP4mo ago
i explored usePaginatedHook code and there i see if i return undefined then typescript and hook internal both looks happy
Hmza
Hmza4mo ago
other then some ambuigty on api structure (if you plan to document later on for other users )(if you think of best practices) this would work totally fine. you mean usePaginatedQuery? or the validator ?
M Zeeshan
M ZeeshanOP4mo ago
usePaginatedQuery usePaginatedQuery uses for loop to iterate the result of useQuries() and if any query return undefined it breaks loop, keep old fetched restuls and nothing more.... from source code:
currResult = resultsObject[pageKey];
if (currResult === undefined) {
break;
}
currResult = resultsObject[pageKey];
if (currResult === undefined) {
break;
}
Hmza
Hmza4mo ago
yeah? are you expecting it to do something different?
M Zeeshan
M ZeeshanOP4mo ago
not at all. i looked at source code after posting this thread
Hmza
Hmza4mo ago
🎉
M Zeeshan
M ZeeshanOP4mo ago
i want some extra data from server using paginated query e.g.
return {
totalFound, // <-- This
...restuls,
}
return {
totalFound, // <-- This
...restuls,
}
i copied source code of usePaginatedQuery and modify it as i want
Hmza
Hmza4mo ago
results as in paginated query results?
M Zeeshan
M ZeeshanOP4mo ago
only a little problem of type i have in my useCustomPaginatedQuery usage:
const { results, loadMore, status, isLoading, data } =
useCustomPaginatedQuery(api.hire_requests.getMultiple, args, {
initialNumItems: 20,
});
const { results, loadMore, status, isLoading, data } =
useCustomPaginatedQuery(api.hire_requests.getMultiple, args, {
initialNumItems: 20,
});
where data is extra data passed from server
Hmza
Hmza4mo ago
what kind of data is it ? if you want to return from the same paginated function i suppose it can be included in page ?
M Zeeshan
M ZeeshanOP4mo ago
in page...? yes, in same function
Hmza
Hmza4mo ago
can you tell me more ? what does "data" hold ?
M Zeeshan
M ZeeshanOP4mo ago
when user apply filters server must return this data along paginated results
{
total: 200,
found: 120,
}
{
total: 200,
found: 120,
}
i know i need to get these values by myself
Hmza
Hmza4mo ago
const obj = { total: 200, found: 120, } return { ...results, obj} does this not work ?
M Zeeshan
M ZeeshanOP4mo ago
usePaginatedQuery does not give any data else results what the hell ts is doing with me... first when i returned undefined ts were ok but now give same error i must return paginated data or need to throw
throw new ConvexError('unauthenticated request');
throw new ConvexError('unauthenticated request');
how should i catch error on throw
jamalsoueidan
jamalsoueidan4mo ago
you always throw error @M Zeeshan and you catch the error in the frontend
M Zeeshan
M ZeeshanOP4mo ago
how... by using error boundary ?
jamalsoueidan
jamalsoueidan4mo ago
eaxctly
Hmza
Hmza4mo ago
i just checked and yeah usePaginatedQuery seems to avoid any extra obj from the return. what i would do is to keep these concerns seperate. for user authentication just return empty pagination result like you were doing before. no need to pass extra arguments. use seperate convex function to check authentication on page. and handle error on frontend. for the totals. maybe just cache them from db? idk how you are getting totals anyway but if you are using .collect() then again its bad practice.
M Zeeshan
M ZeeshanOP4mo ago
yeah with bad practice.... .collect().length
Hmza
Hmza4mo ago
you are touching all docs together. it'll use alot of your bandwidth
M Zeeshan
M ZeeshanOP4mo ago
what should i do?
Hmza
Hmza4mo ago
don't do it. imagine if you have 10,000 docs, it'll be slow and will use ton of bandwidth. i'm aggregating data using btree approach. but what is your case here for totals ? you can do something like. when you add or remove a doc from the db, patch the totals in a seperate table. and then just use a query to get those on page.
M Zeeshan
M ZeeshanOP4mo ago
yeah its great approach
Hmza
Hmza4mo ago
convex is working on some components they'll release soon to help with this but no timeline yet. similar btree approach helpers probably. i worked out this same solution i told you. its working pretty well.
M Zeeshan
M ZeeshanOP4mo ago
i will use it with my custom usePaginatedQuery
M Zeeshan
M ZeeshanOP4mo ago
Gist
convex custom usePaginatedQuery
convex custom usePaginatedQuery. GitHub Gist: instantly share code, notes, and snippets.
M Zeeshan
M ZeeshanOP4mo ago
it returns extra data passed from server in data variable and it gets overridden returned from last page
Hmza
Hmza4mo ago
i see this code is splitting pages and aggregating results too. i don't know your use case. but i'll still suggest to let things be handled by convex functions and queries. it'd be more optimised. did you check this ? https://www.npmjs.com/package/convex-helpers#manual-pagination does ton more things for you. also this article is great overview: https://stack.convex.dev/pagination good luck 🙂
Take Control of Pagination
Convex offers robust control over pagination with a powerful function, getPage, enabling complex edge cases. In this article, we go over how to use th...
npm
convex-helpers
A collection of useful code to complement the official convex package.. Latest version: 0.1.58, last published: 3 days ago. Start using convex-helpers in your project by running npm i convex-helpers. There are 2 other projects in the npm registry using convex-helpers.
M Zeeshan
M ZeeshanOP4mo ago
@Hmza i know there is getPage helper and i'v read "take control of pagination'. what i did in my gist is copy/paste original hook and only added data variable. all optimizations by convex team are there!
Hmza
Hmza4mo ago
got it. i hope that aggregating data suggestion was helpful. have a great day
M Zeeshan
M ZeeshanOP4mo ago
❤️

Did you find this page helpful?