Svesta Demo

  • user avatar
    George Bluth george.bluth@reqres.in
  • user avatar
    Janet Weaver janet.weaver@reqres.in
  • user avatar
    Emma Wong emma.wong@reqres.in
  • user avatar
    Eve Holt eve.holt@reqres.in
  • user avatar
    Charles Morris charles.morris@reqres.in
  • user avatar
    Tracey Ramos tracey.ramos@reqres.in

Source code for svesta demo

+layout.ts

While Transport setup could be done within your view’s $effect or in your +page.[j|t]s, the recommended place to do the setup is the +layout.[j|t]s like below:


import { Transport } from "svesta";
// This is configured on the default context
Transport.configure({ BASE_URL: 'https://reqres.in/api' });
export const prerender = true;

+page.ts


// from sveltekit
import type { PageLoad } from './$types.js';

import { Transport } from 'svesta';
import { resultTransformer } from './demo-assets/transformer.js';

export const load:PageLoad = async ({ fetch }) => {

	// This is happening on the server and we have a ref to a fetch
	// implementation, let's use it by passing it to the configure
	// method of Transport

	// Note that we are using the default transport context here
	const transport  = Transport.instance({fetch});
	const { error , ...rest } = await transport.get('/users');
	return { ...resultTransformer(rest), error };

};

+page.svelte


<script>
	// svelte
	import type { PageData } from './$types.js';

	import { type StoreProps, useStore, Resource, Loader, type StoreResult } from 'svesta';
	import { resultTransformer } from "./demo-assets/transformer.js";

	import UserList from './demo-assets/users.svelte';
	import type { User, IngressType } from './demo-assets/types.js';

	type ViewData = { data: PageData; }
	const { data }: ViewData = $props();

	const usersProps: StoreProps<User> = {
		resultTransformer,
		initData: data as StoreState<User>,
		queryTransformer(raw:IngressType){
			return raw;  
		}
	};
	const users = useStore<User>( 'users', usersProps );

	
	
</script>


{#snippet resolve({ data, page, pages, loading }:StoreResult<User>)}

	<UserList users={data} />

	{#if loading}

		<Loader color='tomato'/>

	{/if}

	{#if data}

		<div class="buttons">
			<button onclick={ users.prev } disabled={ page === 1 }> 
				Previous page
			</button>
			<button onclick={ users.next } disabled={ page === pages }> 
				Next page
			</button>
			<button onclick={ users.more } disabled={ page === pages }>
				more(append to view)...
			</button>
		</div>

	{/if}

{/snippet}

<h1 class="header">
	<strong>Svesta</strong> Demo
</h1>

<Resource store={users} {resolve} />

transformer.js

import { type StoreResult } from 'svesta';
import type { IngressType, User } from './demo-assets/types.js';

export const resultTransformer = <User>(raw: IngressType): StoreResult<User> => {
	const { page, per_page: limit, total: recordCount, total_pages: pages, data } = raw;
	return { page, limit, recordCount, pages, data };
};

types.ts


export type User = {
	id: number;
	email: string;
	first_name: string;
	last_name: string;
	avatar: string;
};

export type IngressType = {
	page: number;
	per_page: number;
	total: number;
	total_pages: number;
	data: Params;
};

users.svelte


<script>

	import type { User } from './types.js';
	import Item from './item.svelte';

	let { users }:{ users:User[] } = $props();

</script>

<ul class="directories">

	{#if users}

		{#each users as user, i }
			<Item {...user} />
		{/each}

	{/if}

</ul>

item.svelte


<script>
	import type { User } from "./types.js";

	let { avatar, first_name, last_name, email }:User = $props();
</script>

<li class="directory">
	<div class="image">
		<img src={avatar} alt="user avatar" loading="lazy" />
	</div>
	<div class="detail">
		<strong>{first_name} {last_name}</strong>
		<em>{email}</em>
	</div>
</li>