Awesome
[!WARNING] The repository is no longer being worked on, and the npm package has been deprecated. Feel free to fork and continue development.
svelte-query-pocketbase
TanStack Query wrappers around Pocketbase Realtime for Svelte.
Installation
npm i -D svelte-query-pocketbase
Record Query
Creates a TanStack Query that updates a Pocketbase record in realtime. View the JSDoc for the relevant functions for more documentation on their available options.
Simple Example
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createRecordQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someRecord = createRecordQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
'some_id'
);
</script>
{#if $someRecord.data}
<p>Fetched record:</p>
<pre>{JSON.stringify($someRecord.data, null, 2)}</pre>
{:else if $someRecord.error}
{#if $someRecord.error.status === 404}
<p>The record couldn't be found in the database.</p>
{:else}
<p>Something went wrong.</p>
<button on:click={() => $someRecord.refetch()}>Try again</button>
{/if}
{:else}
<p>Loading...</p>
{/if}
</details>
With Query Params
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createRecordQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someRecord = createRecordQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
'some_id',
{
queryParams: {
expand: 'some_field',
fields: 'some_field' // the library will internally add id and updated to this
}
}
);
</script>
{#if $someRecord.data}
<p>Fetched record, with some_field expanded:</p>
<pre>{JSON.stringify($someRecord.data, null, 2)}</pre>
{:else if $someRecord.error}
{#if $someRecord.error.status === 404}
<p>The record couldn't be found in the database.</p>
{:else}
<p>Something went wrong.</p>
<button on:click={() => $someRecord.refetch()}>Try again</button>
{/if}
{:else}
<p>Loading...</p>
{/if}
</details>
Using SSR
Read TanStack Query's docs on this first. The examples below are modified versions of the examples on that page.
Using initialData
<details>
<summary>View Code</summary>
src/routes/+page.ts
import type { PageLoad } from './$types';
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createRecordQueryInitialData } from 'svelte-query-pocketbase';
export const load: PageLoad = async () => {
const someIdInitialData = await createRecordQueryInitialData<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
'some_id'
);
return { someIdInitialData };
};
src/routes/+page.svelte
<script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import type { PageData } from './$types';
export let data: PageData;
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createRecordQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someRecord = createRecordQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
'some_id',
{
initialData: data.someIdInitialData
}
);
</script>
</details>
Using prefetchQuery
<details>
<summary>View Code</summary>
src/routes/+layout.ts
Same as TanStack Query's docs
src/routes/+layout.svelte
Same as TanStack Query's docs
src/routes/+page.ts
import type { PageLoad } from './$types';
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createRecordQueryPrefetch } from 'svelte-query-pocketbase';
export const load: PageLoad = async ({ parent }) => {
const { queryClient } = await parent();
// As long as the same collection, id, and queryParams are supplied to
// `createRecordQueryPrefetch` and `createRecordQuery`, the library will
// generate the same `queryKey`s for both functions, and you need not specify one
await queryClient.prefetchQuery(
createRecordQueryPrefetch<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
'some_id'
)
);
};
src/routes/+page.svelte
<script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import type { PageData } from './$types';
export let data: PageData;
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createRecordQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
// This data is cached by prefetchQuery in +page.ts so no fetch actually happens here
const someRecord = createRecordQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
'some_id'
);
</script>
</details>
Collection Query
Creates a TanStack Query that updates an array of Pocketbase records in realtime. View the JSDoc for the relevant functions for more documentation on their available options.
Simple Example
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someCollection = createCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
);
</script>
{#if $someCollection.data}
<p>Fetched collection:</p>
<pre>{JSON.stringify($someCollection.data, null, 2)}</pre>
{:else if $someCollection.error}
{#if $someCollection.error.status === 404}
<p>The collection couldn't be found in the database.</p>
{:else}
<p>Something went wrong.</p>
<button on:click={() => $someCollection.refetch()}>Try again</button>
{/if}
{:else}
<p>Loading...</p>
{/if}
</details>
With Query Params
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someCollection = createCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
{
queryParams: {
expand: 'some_field',
sort: '-created', // sort by date created, descending
filter: 'created >= "2022-01-01 00:00:00"',
fields: 'some_field' // the library will internally add id and updated to this
},
// sortFunction and filterFunction are applied after a realtime update is applied
sortFunction: (a, b) => new Date(a.created) - new Date(b.created) // sort by date created, descending
filterFunction: (record) => new Date(record.created) >= new Date("2022-01-01 00:00:00")
}
);
</script>
{#if $someCollection.data}
<p>
Fetched collection, with some_field expanded, sorted by date created (descending), and filtered
by date created after 2022-01-01 00:00:00:
</p>
<pre>{JSON.stringify($someCollection.data, null, 2)}</pre>
{:else if $someCollection.error}
{#if $someCollection.error.status === 404}
<p>The collection couldn't be found in the database.</p>
{:else}
<p>Something went wrong.</p>
<button on:click={() => $someCollection.refetch()}>Try again</button>
{/if}
{:else}
<p>Loading...</p>
{/if}
</details>
Using SSR
Read TanStack Query's docs on this first. The examples below are modified versions of the examples on that page.
Using initialData
<details>
<summary>View Code</summary>
src/routes/+page.ts
import type { PageLoad } from './$types';
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createCollectionQueryInitialData } from 'svelte-query-pocketbase';
export const load: PageLoad = async () => {
const someCollectionInitialData = await createCollectionQueryInitialData<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
);
return { someCollectionInitialData };
};
src/routes/+page.svelte
<script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import type { PageData } from './$types';
export let data: PageData;
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someCollection = createCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
{
initialData: data.someCollectionInitialData
}
);
</script>
</details>
Using prefetchQuery
<details>
<summary>View Code</summary>
src/routes/+layout.ts
Same as TanStack Query's docs
src/routes/+layout.svelte
Same as TanStack Query's docs
src/routes/+page.ts
import type { PageLoad } from './$types';
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createCollectionQueryPrefetch } from 'svelte-query-pocketbase';
export const load: PageLoad = async ({ parent }) => {
const { queryClient } = await parent();
// As long as the same collection, id, and queryParams are supplied to
// `createCollectionQueryPrefetch` and `createCollectionQuery`, the library will
// generate the same `queryKey`s for both functions, and you need not specify one
await queryClient.prefetchQuery(
createCollectionQueryPrefetch<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
)
);
};
src/routes/+page.svelte
<script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import type { PageData } from './$types';
export let data: PageData;
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
// This data is cached by prefetchQuery in +page.ts so no fetch actually happens here
const someCollection = createCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
);
</script>
</details>
Infinite Collection Query
Creates a TanStack Infinite Query that updates paginated Pocketbase records in realtime. View the JSDoc for the relevant functions for more documentation on their available options.
Simple Example
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createInfiniteCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someInfiniteCollection = createInfiniteCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
);
</script>
{#if $someInfiniteCollection.data}
<p>Fetched infinite collection:</p>
<pre>{JSON.stringify($someInfiniteCollection.data, null, 2)}</pre>
{#if $someInfiniteCollection.hasNextPage}
<button
on:click={() => $someInfiniteCollection.fetchNextPage()}
disabled={$someInfiniteCollection.isFetchingNextPage}
>{$someInfiniteCollection.isFetchingNextPage
? 'Fetching next page...'
: 'Fetch next page'}</button
>
{/if}
{:else if $someInfiniteCollection.error}
{#if $someInfiniteCollection.error.status === 404}
<p>The collection couldn't be found in the database.</p>
{:else}
<p>Something went wrong.</p>
<button on:click={() => $someInfiniteCollection.refetch()}>Try again</button>
{/if}
{:else}
<p>Loading...</p>
{/if}
</details>
With Query Params
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createInfiniteCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someInfiniteCollection = createInfiniteCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
{
queryParams: {
expand: 'some_field',
sort: '-created', // sort by date created, descending
filter: 'created >= "2022-01-01 00:00:00"',
fields: 'some_field' // the library will internally add id and updated to this
},
// sortFunction and filterFunction are applied after a realtime update is applied
sortFunction: (a, b) => new Date(a.created) - new Date(b.created) // sort by date created, descending
filterFunction: (record) => new Date(record.created) >= new Date("2022-01-01 00:00:00")
}
);
</script>
{#if $someInfiniteCollection.data}
<p>
Fetched infinite collection, with some_field expanded, sorted by date created (descending), and
filtered by date created after 2022-01-01 00:00:00:
</p>
<pre>{JSON.stringify($someInfiniteCollection.data, null, 2)}</pre>
{#if $someInfiniteCollection.hasNextPage}
<button
on:click={() => $someInfiniteCollection.fetchNextPage()}
disabled={$someInfiniteCollection.isFetchingNextPage}
>{$someInfiniteCollection.isFetchingNextPage
? 'Fetching next page...'
: 'Fetch next page'}</button
>
{/if}
{:else if $someInfiniteCollection.error}
{#if $someInfiniteCollection.error.status === 404}
<p>The collection couldn't be found in the database.</p>
{:else}
<p>Something went wrong.</p>
<button on:click={() => $someInfiniteCollection.refetch()}>Try again</button>
{/if}
{:else}
<p>Loading...</p>
{/if}
</details>
Using SSR
Read TanStack Query's docs on this first. The examples below are modified versions of the examples on that page.
Using initialData
<details>
<summary>View Code</summary>
src/routes/+page.ts
import type { PageLoad } from './$types';
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { infiniteCollectionQueryInitialData } from 'svelte-query-pocketbase';
export const load: PageLoad = async () => {
const someInfiniteCollectionInitialData =
await infiniteCollectionQueryInitialData<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
);
return { someInfiniteCollectionInitialData };
};
src/routes/+page.svelte
<script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import type { PageData } from './$types';
export let data: PageData;
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createInfiniteCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
const someInfiniteCollection = createInfiniteCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection),
{
initialData: data.someInfiniteCollectionInitialData
}
);
</script>
</details>
Using prefetchQuery
<details>
<summary>View Code</summary>
src/routes/+layout.ts
Same as TanStack Query's docs
src/routes/+layout.svelte
Same as TanStack Query's docs
src/routes/+page.ts
import type { PageLoad } from './$types';
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { infiniteCollectionQueryPrefetch } from 'svelte-query-pocketbase';
export const load: PageLoad = async ({ parent }) => {
const { queryClient } = await parent();
// As long as the same collection, id, and queryParams are supplied to
// `infiniteCollectionQueryPrefetch` and `createCollectionQuery`, the library will
// generate the same `queryKey`s for both functions, and you need not specify one
await queryClient.prefetchQuery(
infiniteCollectionQueryPrefetch<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
)
);
};
src/routes/+page.svelte
<script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import type { PageData } from './$types';
export let data: PageData;
// Types generated from https://github.com/patmood/pocketbase-typegen
import { Collections, type SomeCollectionResponse } from '$lib/collections';
import { createInfiniteCollectionQuery } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
// This data is cached by prefetchQuery in +page.ts so no fetch actually happens here
const someInfiniteCollection = createInfiniteCollectionQuery<SomeCollectionResponse>(
pocketbase.collection(Collections.SomeCollection)
);
</script>
</details>
User Store
Svelte store wrapper around the authenticated Pocketbase user that updates in realtime.
Using Default Auth Store
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import { userStore, type KnownUser } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL);
interface CustomKnownUser extends KnownUser {
id: string;
name: string;
username: string;
avatar?: string;
}
const user = userStore<CustomKnownUser>(pocketbase, (authStore) => ({
isLoggedIn: true,
id: authStore.model?.id ?? '',
avatar: authStore.model?.avatar,
username: authStore.model?.username ?? ''
name: authStore.model?.name ?? '',
}));
</script>
{#if $user.isLoggedIn}
<p>Welcome, {$user.name}:</p>
<pre>{JSON.stringify($user, null, 2)}</pre>
{:else}
<p>You are not logged in.</p>
{/if}
</details>
Using Local Auth Store
<details> <summary>View Code</summary><script lang="ts">
import Pocketbase, { LocalAuthStore } from 'pocketbase';
import { PUBLIC_POCKETBASE_URL } from '$env/static/public';
import { userStore, type KnownUser } from 'svelte-query-pocketbase';
const pocketbase = new Pocketbase(PUBLIC_POCKETBASE_URL, new LocalAuthStore("authInfo"));
interface CustomKnownUser extends KnownUser {
id: string;
name: string;
username: string;
avatar?: string;
}
const user = userStore<CustomKnownUser, LocalAuthStore>(pocketbase, (authStore) => ({
isLoggedIn: true,
id: authStore.model?.id ?? '',
avatar: authStore.model?.avatar,
username: authStore.model?.username ?? ''
name: authStore.model?.name ?? '',
}));
</script>
{#if $user.isLoggedIn}
<p>Welcome, {$user.name}:</p>
<pre>{JSON.stringify($user, null, 2)}</pre>
{:else}
<p>You are not logged in.</p>
{/if}
</details>