Implementing Pagination with Effect and RequestResolver in Nuxt

class NoPostsError extends Error {
    readonly _tag = "NoPostsError";
    constructor() {
        super("All of posts are already displayed?!");
    }
}

interface FetchPosts extends Request.Request<PostsCollectionItem[], Error> {
    readonly _tag: "FetchPosts";
    readonly page: number;
    readonly pageSize: number;
}

const FetchPosts = Request.tagged<FetchPosts>("FetchPosts");

const FetchPostsResolver = RequestResolver.fromEffect(
    (request: FetchPosts): Effect.Effect<PostsCollectionItem[], Error> => {
        const skip = (request.page - 1) * request.pageSize;
        const limit = request.pageSize;

        return Effect.tryPromise({
            try: async () => {
                return await queryCollection("posts")
                    .limit(limit)
                    .skip(skip)
                    .all();
            },
            catch: (error) =>
                new Error(`Error fetching posts: ${String(error)}`),
        });
    },
);

const fetchPostsEffect = (
    page: number,
    pageSize: number,
): Effect.Effect<PostsCollectionItem[], Error> => {
    return pipe(
        Effect.request(FetchPosts({ page, pageSize }), FetchPostsResolver),
        Effect.flatMap((posts) =>
            posts?.length > 0
                ? Effect.succeed(posts)
                : Effect.fail(new NoPostsError()),
        ),
    );
};

//Pagination stuff
const currentPage = ref(1);
const postsPerPage = 2;

const {
    data: posts,
    error,
    refresh,
} = await useAsyncData(
    "posts-page",
    async () =>
        await Effect.runPromise(
            fetchPostsEffect(currentPage.value, postsPerPage),
        ),
);

const nextPage = () => {
    if (posts.value && posts.value.length >= postsPerPage) {
        currentPage.value++;
    }
};

const prevPage = () => {
    if (currentPage.value > 1) {
        currentPage.value--;
    }
};

watch(currentPage, () => refresh());


is this a good approach to follow on nuxt?
Was this page helpful?