"Svelte"

Svelte stores for Tether with reactive subscriptions.

Work in Progress: The Svelte SDK is currently under development. In the meantime, you can use the vanilla JavaScript client which works with any framework including Svelte and SvelteKit.

Using the vanilla client with Svelte

Whilst the dedicated Svelte SDK is in development, you can use @tthr/client directly:

npm install @tthr/client

Example setup

Create a Tether client module:

// src/lib/tether.ts
import { TetherClient } from '@tthr/client';

export const tether = new TetherClient({
  url: globalThis._importMeta_.env.VITE_TETHER_URL,
  projectId: globalThis._importMeta_.env.VITE_TETHER_PROJECT_ID,
  publishableKey: globalThis._importMeta_.env.VITE_TETHER_PK, // optional: for SPA auth
  authToken: () => getAuthToken(),
  verbose: globalThis._importMeta_.env.DEV, // Enable debug logging in development
});

Using in components

Import and use the client in your Svelte components:

<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import { tether } from '$lib/tether';

  let todos: Todo[] = [];
  let loading = true;
  let unsubscribe: (() => void) | null = null;

  onMount(() => {
    // Subscribe to realtime updates
    unsubscribe = tether.subscribe(
      'todos.list',
      { completed: false },
      (data) => {
        todos = data;
        loading = false;
      }
    );
  });

  onDestroy(() => {
    unsubscribe?.();
  });

  async function addTodo(title: string) {
    await tether.mutation('todos.create', { title });
  }
</script>

{#if loading}
  <p>Loading...</p>
{:else}
  <ul>
    {#each todos as todo}
      <li>{todo.title}</li>
    {/each}
  </ul>
{/if}

Creating a Svelte store

Wrap the client in a Svelte store for reactive updates:

// src/lib/stores/todos.ts
import { writable } from 'svelte/store';
import { tether } from '$lib/tether';

function createTodosStore() {
  const { subscribe, set } = writable<Todo[]>([]);

  let unsubscribe: (() => void) | null = null;

  return {
    subscribe,
    init: () => {
      unsubscribe = tether.subscribe(
        'todos.list',
        {},
        (data) => set(data)
      );
    },
    destroy: () => unsubscribe?.(),
    add: (title: string) => tether.mutation('todos.create', { title }),
    remove: (id: string) => tether.mutation('todos.delete', { id }),
  };
}

export const todos = createTodosStore();

Server-side usage (SvelteKit)

For SvelteKit server routes and load functions, use TetherServerClient:

// src/routes/api/webhook/+server.ts
import { TetherServerClient } from '@tthr/client';
import { json } from '@sveltejs/kit';
import { TETHER_URL, TETHER_PROJECT_ID, TETHER_API_KEY } from '$env/static/private';

const tether = new TetherServerClient({
  url: TETHER_URL,
  projectId: TETHER_PROJECT_ID,
  apiKey: TETHER_API_KEY,
});

export async function POST({ request }) {
  const body = await request.json();
  await tether.mutation('webhooks.process', body);
  return json({ ok: true });
}