Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store based reactivity #48

Merged
merged 14 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion @example/src/lib/trpc/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ export const router = t.router({
.then((r) => r[0]);
}),

get: t.procedure.query(({ ctx: { db } }) => db.query.todo.findMany()),
get: t.procedure
.input(z.string().optional())
.query(({ input: filter, ctx: { db } }) =>
db.query.todo.findMany({
where: filter
? (todo, { like }) => like(todo.text, `%${filter}%`)
: undefined,
})
),

getPopular: t.procedure
.input(
Expand Down
7 changes: 7 additions & 0 deletions @example/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function debounce<T>(cb: (v: T) => void, durationMs: number) {
let timer: ReturnType<typeof setTimeout>;
return (v: T) => {
clearTimeout(timer);
timer = setTimeout(() => cb(v), durationMs);
};
}
39 changes: 37 additions & 2 deletions @example/src/routes/(app)/client-only/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,28 @@

import { X, Plus } from 'phosphor-svelte';

import { debounce } from '$lib/utils';
import { page } from '$app/stores';
import { trpc } from '$lib/trpc/client';
import { writable } from 'svelte/store';
import type { InferProcedureOpts } from 'trpc-svelte-query-adapter';

const api = trpc($page);
const utils = api.createUtils();

let todoInput: HTMLInputElement;

const todos = api.todos.get.createQuery();
const filter = writable<string | undefined>();
const opts = writable({
refetchInterval: Infinity,
} satisfies InferProcedureOpts<typeof api.todos.get.createQuery>);

const todos = api.todos.get.createQuery(filter, opts);

const popularTodos = api.todos.getPopular.createInfiniteQuery(
{},
{
getNextPageParam: (data) => data.nextCursor,
getNextPageParam: (lastPage) => lastPage.nextCursor,
}
);

Expand Down Expand Up @@ -81,6 +89,33 @@
{/if}
</form>

<form action="#" style="margin-top:0.5rem">
<!-- eslint-disable-next-line svelte/valid-compile -->
<!-- svelte-ignore a11y-no-redundant-roles -->
<fieldset role="group">
<input
type="text"
name="filter"
value={$filter ?? ''}
placeholder="Filter"
on:input|preventDefault={debounce((e) => {
if (!(e.target instanceof HTMLInputElement)) return;
$filter = e.target.value || undefined;
}, 500)}
/>
<input
style="width:15ch;"
type="number"
placeholder="Refetch"
value={$opts?.refetchInterval}
on:input|preventDefault={debounce((e) => {
if (!(e.target instanceof HTMLInputElement)) return;
$opts.refetchInterval = e.target.value ? +e.target.value : Infinity;
}, 500)}
/>
</fieldset>
</form>

<hr />

{#if $todos.isPending}
Expand Down
40 changes: 38 additions & 2 deletions @example/src/routes/(app)/ssr/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import Heading from '$lib/components/Heading.svelte';

import { X, Plus } from 'phosphor-svelte';
import { writable } from 'svelte/store';
import { debounce } from '$lib/utils';
import type { InferProcedureOpts } from 'trpc-svelte-query-adapter';

export let data;

Expand All @@ -10,7 +13,13 @@

let todoInput: HTMLInputElement;

const todos = data.todos();
const filter = writable<string | undefined>();
const opts = writable({
refetchInterval: Infinity,
} satisfies InferProcedureOpts<typeof api.todos.get.createQuery>);

const todos = data.todos(filter, opts);

const popularTodos = data.popularTodos();

const createTodo = api.todos.create.createMutation({
Expand All @@ -31,7 +40,7 @@
});
</script>

<Heading>Client-only</Heading>
<Heading>SSR</Heading>

<div id="content" style="margin-top:2rem">
<div>
Expand Down Expand Up @@ -74,6 +83,33 @@
{/if}
</form>

<form action="#" style="margin-top:0.5rem">
<!-- eslint-disable-next-line svelte/valid-compile -->
<!-- svelte-ignore a11y-no-redundant-roles -->
<fieldset role="group">
<input
type="text"
name="filter"
value={$filter ?? ''}
placeholder="Filter"
on:input|preventDefault={debounce((e) => {
if (!(e.target instanceof HTMLInputElement)) return;
$filter = e.target.value || undefined;
}, 500)}
/>
<input
style="width:15ch;"
type="number"
placeholder="Refetch"
value={$opts?.refetchInterval}
on:input|preventDefault={debounce((e) => {
if (!(e.target instanceof HTMLInputElement)) return;
$opts.refetchInterval = e.target.value ? +e.target.value : Infinity;
}, 500)}
/>
</fieldset>
</form>

<hr />

{#if $todos.isPending}
Expand Down
2 changes: 1 addition & 1 deletion @example/src/routes/(app)/ssr/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export async function load(event) {
popularTodos: await api.todos.getPopular.createServerInfiniteQuery(
{},
{
getNextPageParam: (data) => data.nextCursor,
getNextPageParam: (lastPage) => lastPage.nextCursor,
}
),
};
Expand Down
85 changes: 46 additions & 39 deletions @lib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
[![License][license-image]][license-url]
[![Last commit][last-commit-image]][repo-url]

> **NOTE:** The README on [npmjs](https://npmjs.com/trpc-svelte-query-adapter) might not be fully up to date. Please refer to the [README on the Github Repo](https://github.com/vishalbalaji/trpc-svelte-query-adapter/#readme) for the latest setup instructions.
> [!NOTE]
> The README on [npmjs](https://npmjs.com/trpc-svelte-query-adapter) might not be fully up to date. Please refer to
> the [README on the Github Repo](https://github.com/vishalbalaji/trpc-svelte-query-adapter/#readme) for the latest setup instructions.

This package provides an adapter to call `tRPC` procedures wrapped with <code>[@tanstack/svelte-query](https://tanstack.com/query/latest/docs/svelte/overview)</code>, similar to <code>[@trpc/react-query](https://trpc.io/docs/react-query)</code>. This is made possible using <code>[proxy-deep](https://www.npmjs.com/package/proxy-deep)</code>.
An adapter to call `tRPC` procedures wrapped with <code>[@tanstack/svelte-query](https://tanstack.com/query/latest/docs/svelte/overview)</code>, similar to <code>[@trpc/react-query](https://trpc.io/docs/react-query)</code>. This is made possible using <code>[proxy-deep](https://www.npmjs.com/package/proxy-deep)</code>.

## Installation

```console
```sh
# npm
npm install trpc-svelte-query-adapter @trpc/client @trpc/server @tanstack/svelte-query

Expand Down Expand Up @@ -202,7 +204,8 @@ By default, these 3 procedures will pre-fetch the data required to pre-render th

These procedures can be used as such:

> **NOTE:** [Gotta await top-level promises to pre-fetch data from SvelteKit v2](https://kit.svelte.dev/docs/migrating-to-sveltekit-2#top-level-promises-are-no-longer-awaited).
> [!NOTE]
> [Gotta await top-level promises to pre-fetch data from SvelteKit v2](https://kit.svelte.dev/docs/migrating-to-sveltekit-2#top-level-promises-are-no-longer-awaited).

```typescript
// +page.ts
Expand Down Expand Up @@ -258,58 +261,62 @@ Then, in the component:
{/each}
```

You can also optionally pass new inputs to the queries and infinite queries from the client side(see [#34](/../../issues/34)) like so:
You can also optionally pass new inputs to the queries and infinite queries from the client side(see [#34](/../../issues/34), [#47]( /../../issues/47 )) like so:

```svelte
<script lang="ts">
import { page } from "$app/stores";
import type { PageData } from "./$types";

import { derived, writable } from '@svelte/store';

export let data: PageData;

let name = 'foo';
let newNames: string[] = [];
const name = writable('foo');
const newNames = writable<string[]>([]);

$: foo = data.foo(name); // `$` label to make the query reactive to the input
const foo = data.foo($name);

// You can also access the default input if you pass in a callback as the new input:
// $: foo = data.foo((old) => old + name);
// const foo = data.foo((old) => derived(name, ($name) => old + name));

$: queries = data.queries((t, old) => [...old, ...newNames.map((name) => t.greeting(name))]);
const queries = data.queries((t, old) => derived(newNames, ($newNames) => [...old, ...$newNames.map((name) => t.greeting(name))]));
</script>

{#if $foo.isPending}
Loading...
{:else if $foo.isError}
{$foo.error}
{:else if $foo.data}
{$foo.data}
{/if}

<br />
<input bind:value={name} />

<br /><br />

{#each $queries as query}
{#if query.isPending}
<div>
{#if $foo.isPending}
Loading...
{:else if query.isError}
{query.error.message}
{:else if query.data}
{query.data}
{:else if $foo.isError}
{$foo.error}
{:else if $foo.data}
{$foo.data}
{/if}
<br />
{/each}
<input bind:value={$name} />
</div>

<br />

<form on:submit|preventDefault={(e) => {
const data = new FormData(e.currentTarget).get('name');
if (typeof data === 'string') newNames.push(data);
newNames = newNames;
}}>
<input name="name" />
<button type="submit">Submit</button>
</form>
<div>
{#each $queries as query}
{#if query.isPending}
Loading...
{:else if query.isError}
{query.error.message}
{:else if query.data}
{query.data}
{/if}
<br />
{/each}

<form on:submit|preventDefault={(e) => {
const data = new FormData(e.currentTarget).get('name');
if (typeof data === 'string') $newNames.push(data);
$newNames = $newNames;
}}>
<input name="name" />
<button type="submit">Submit</button>
</form>
</div>
```

[npm-url]: https://npmjs.org/package/trpc-svelte-query-adapter
Expand Down
4 changes: 2 additions & 2 deletions @lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "trpc-svelte-query-adapter",
"version": "2.3.7",
"version": "2.3.8",
"description": "A simple adapter to use `@tanstack/svelte-query` with trpc, similar to `@trpc/react-query`.",
"keywords": [
"trpc",
Expand Down Expand Up @@ -34,7 +34,7 @@
"import": "./src/index.ts"
},
"dependencies": {
"proxy-deep": "^3.1.1"
"proxy-deep": "^4.0.1"
},
"peerDependencies": {
"@tanstack/svelte-query": "^5.8.2",
Expand Down
Loading