Feature Request: Custom fetch function on Pocketbase initialization
Closed this issue · 3 comments
Hi team! from what I understand, under the hood, this sdk uses the native fetch api which is great, but there are frameworks like svelte who provides a modified fetch function that has additional features like passing cookies, authorization, etc (see on link).
The issue I am having now is because svelte operates both in client and server side, I am having mismatch of the authStore.
even when the client-side is authenticated (client-side svelte to pocketbase server), the server-side requests (server-side svelte to pocketbase server) isn't it (I'm not sure why, I am guessing the cookies are not being passed to the server when the server is making the request to pocketbase server...
The goal is when the user is on homepage, if he is authenticated,
he should be routed to/apps
if not, he should be routed to /
// src\routes\(default)\+page.ts
import { pb } from "$lib/database/pocketbase";
import { redirect } from "@sveltejs/kit";
import type { PageLoad } from "./$types";
// this is the +page.ts of the homepage "/"
export const load: PageLoad = async () => {
// if user is authenticated
const isLoggedIn = pb.authStore.isValid;
if (isLoggedIn) {
// I am gonna redirect him to /apps
redirect(303, "/apps");
}
return {};
};
// src\routes\(authenticated)\apps\+layout.ts
import { pb } from "$lib/database/pocketbase";
import { redirect } from "@sveltejs/kit";
import type { LayoutLoad } from "./$types";
export const csr = true;
export const ssr = false; // but if I remove this, it breaks and loops forever
// by loops I mean redirect loop
// this is the +layout.ts for my "/apps"
export const load: LayoutLoad = async () => {
// if the user is not logged in, redirect to the home page
const isLoggedIn = pb.authStore.isValid;
if (!isLoggedIn) {
// not logged in
pb.authStore.clear(); // clear any auth data if any
redirect(303, "/"); // redirect to "/"
}
return {};
};
// it continues for a redirect loop because there's a mismatch
// with the server and client...
// disabling the ssr will make it so that ALL requests will come from client-side
screen-capture.1.webm
Possible Solution: make it so that we can initialize Pocketbase with a custom fetch function so we can pass in authorizations on requests made on the server...
I understand that we can do something like this:
export const load: LayoutLoad = async ({ fetch }) => {
const [features, announcements] = await Promise.all([
pb.collection("features").getFullList({ fetch }), // adding fetch here
pb.collection("announcements").getFullList({ fetch }),
]);
return {
features: structuredClone(features),
announcements: structuredClone(announcements),
};
};
but when working on authstores..
export const load: LayoutLoad = async () => {
const isLoggedIn = pb.authStore.isValid; //Can't pass in the fetch function
if (!isLoggedIn) {
pb.authStore.clear();
redirect(303, "/");
}
return {};
};
there's a method I saw which is what I am working on to see if it fits my use-case. but I just submitted the feature request so that it's like it's gonna use the provided fetch function when available or something like that.. without much configurations for each operation
(method) BaseAuthStore.loadFromCookie(cookie: string, key?: string): void
Parses the provided cookie string and updates the store state with the cookie's token and model data.
NB! This function doesn't validate the token or its data. Usually this isn't a concern if you are interacting only with the PocketBase API because it has the proper server-side security checks in place, but if you are using the store isValid state for permission controls in a node server (eg. SSR), then it is recommended to call authRefresh()
after loading the cookie to ensure an up-to-date token and model state. For example:
pb.authStore.loadFromCookie("cookie string...");
try {
// get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)
pb.authStore.isValid && await pb.collection('users').authRefresh();
} catch (_) {
// clear the auth store on failed refresh
pb.authStore.clear();
}
The JS SDK uses whatever global fetch
implementation is available.
You can specify a fetch
using the beforeSendHook
or by passing it in the SendOptions for each request, aka:
await pb.collection("example").getList(1, 30, {
fetch: yourCustomFetch,
})
For everything else - I cannot help, but I don't recommend using PocketBase with JS SSR, especially if you are new to web development. Make sure to read pocketbase/pocketbase#5313.
Thanks man, I see and your point on pocketbase/pocketbase#5313 makes a lot of sense. I'm taking your advise :) I'm relatively new to the industry (about a year) I was able to create a full-stack app using sveltekit in cloudflare environment... but the dev time is so long, specially setting up D1, the queries.. the migrations, etc. so time consuming, but I saw this Pocketbase and was instantly amazed at how great it is! Thanks a lot for this magnificent application. I wish I could create something like this in the future. I am laying out my application as a SPA.. Thanks for entertaining my questions.