@sprocketbot/gql-stores
v0.1.0-beta.4
Published
Wrapper for @urql/core that presents a store-based API instead of a context-based API
Downloads
1
Readme
@sprocketbot/gql-stores
This package wraps @urql/core as an alternative to @urql/svelte.
Instead of the context based approach taken by urql; this package uses a store approach to make operations easier to abstract outside of your components.
Examples
Simple Query
People.store.ts
// Based on the GraphQL Zero API
// First, instantiate an urql client
import {Client} from "@urql/core";
export const client = new Client({url: "https://graphqlzero.almansi.me/api"});
// Create your return type (cannot be introspected)
type PeopleQueryValue = {
users: {
data: {
id: string;
name: string;
}[];
};
};
// Write your query; be careful that it matches the type your wrote
const query = gql<PeopleQueryValue>`
query {
users {
data {
name
id
}
}
}
`;
// Finally, instantiate your store:
export const PeopleQuery = new QueryStore(client, query, {});
+page.svelte
<script lang="ts">
import {PeopleQuery} from "./People.store";
</script>
<!-- Simple Rendering -->
<ul>
<!-- Wait for fetching to complete -->
<!-- Data is undefined until fetch completes -->
{#if $PeopleQuery.fetching}
<li>Loading...</li>
<!-- Check for success -->
{:else if $PeopleQuery.success}
<!-- Access query results -->
{#each $PeopleQuery.data.users.data as person}
<li>{person.name}</li>
{/each}
{/if}
</ul>
<!-- Checking for errors -->
{#if $PeopleQuery.errors}
{#if $PeopleQuery.errors.message}
<!-- Combines all other messages -->
{$PeopleQuery.errors.message}
{/if}
{#if $PeopleQuery.errors.graphQLErrors}
{#each $PeopleQuery.errors.graphQLErrors as err}
<!-- Access individual messages -->
<p>{err.message}</p>
{/each}
{/if}
{/if}
Paginated Query
Posts.store.ts
// Based on the GraphQL Zero API
// First, instantiate an urql client
import {Client} from "@urql/core";
export const client = new Client({url: "https://graphqlzero.almansi.me/api"});
// Define types
export type PostsValue = {
posts: {
links: {
prev?: {page: number};
next?: {page: number};
};
data: {
id: number;
user: {id: number; name: string};
title: string;
body: string;
}[];
};
};
export type PostsVariables = {
page: number;
};
// Define Query; note the variables generic
const query = gql<PostsValue, PostsVariables>`
query ($page: Int!) {
posts(options: {paginate: {limit: 5, page: $page}}) {
links {
prev {
page
}
next {
page
}
}
data {
user {
id
name
}
title
body
id
}
}
}
`;
// Instantiate store; initial variables state is required
export const Posts = new QueryStore(client, query, {page: 1});
+page.svelte
<script lang="ts">
import {Posts} from "./Posts.store";
// Helper functions
function prevPage() {
const data = $Posts.data
if (!data || !data.posts.links.prev) return;
// Update variables
// This triggers a requery
Posts.variables = { page: data.posts.links.prev.page}
}
function nextPage() {
const data = $Posts.data
if (!data || !data.posts.links.next) return;
// Update variables
// This triggers a requery
Posts.variables = { page: data.posts.links.next.page}
}
</script>
<!-- If we are fetching and don't have data; show loading -->
<!-- In this case, if we have data we will continue to show that -->
{#if $Posts.fetching && !$Posts.data}
Loading...
{:else if $Posts.data}
<!-- If we have data -->
<div>
<!-- Pagination -->
<button
disabled={!$Posts.data.posts.links.prev || $Posts.fetching}
on:click={prevPage}
>
{`< ${$Posts.data.posts.links.prev?.page ?? " "} -`}
</button>
<span>{$Posts.variables.page}</span>
<button
disabled={!$Posts.data.posts.links.next || $Posts.fetching}
on:click={nextPage}
>
{`- ${$Posts.data.posts.links.next?.page ?? " "} >`}
</button>
</div>
<!-- Render posts; this is the same as the people example -->
{#each $Posts.data.posts.data as post}
<div>
<h2>{post.title}</h2>
<h4>{post.user.name}</h4>
<p>{post.body}</p>
</div>
{/each}
{/if}
Mutation
CreateUser.mutation.ts
import {Mutation} from "$lib/Mutation";
import {gql} from "@urql/core";
import {client} from "../client";
export type CreatePersonValue = {
createUser: {
name: string;
email: string;
id: number;
};
};
export type CreatePersonVariables = {
input: {
name: string;
username: string;
email: string;
};
};
const mutation = gql<CreatePersonValue, CreatePersonVariables>`
mutation ($input: CreateUserInput!) {
createUser(input: $input) {
name
email
id
}
}
`;
export const CreatePerson = Mutation(client, mutation);
// Usage
let createUserInput: CreatePersonVariables["input"] = {
name: "Dave",
username: "dave4",
email: "[email protected]"
};
const createPerson = await CreatePerson({ input: createUserInput })