diff options
Diffstat (limited to 'src/lib/stores')
| -rw-r--r-- | src/lib/stores/apollo.ts | 62 | ||||
| -rw-r--r-- | src/lib/stores/forums.ts | 21 | ||||
| -rw-r--r-- | src/lib/stores/posts.ts | 24 | ||||
| -rw-r--r-- | src/lib/stores/response_builder.ts | 37 | ||||
| -rw-r--r-- | src/lib/stores/supabase.ts | 38 | ||||
| -rw-r--r-- | src/lib/stores/tags.ts | 13 | ||||
| -rw-r--r-- | src/lib/stores/topics.ts | 33 | ||||
| -rw-r--r-- | src/lib/stores/users.ts | 13 |
8 files changed, 162 insertions, 79 deletions
diff --git a/src/lib/stores/apollo.ts b/src/lib/stores/apollo.ts deleted file mode 100644 index c75dd87..0000000 --- a/src/lib/stores/apollo.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { ApolloError } from '@apollo/client/core'; -import { readable } from 'svelte/store'; -import { client } from '$lib/config/apollo'; -import type { DocumentNode, ApolloQueryResult } from '@apollo/client/core'; - -import type { Readable } from 'svelte/store'; - -/* - * This is a generic store for use with apollo - */ - -type ApolloStoreConfiguration<Type> = { - key: string; - query: DocumentNode; - initialValue?: Type | void; - variables?: object; -}; - -type ApolloStoreState<Type> = { - loading: boolean; - data: Type | void; - error: Error | void; -}; - -export const store = function store<Type>({ - key, - query, - initialValue = null, - variables = {} -}: ApolloStoreConfiguration<Type>): Readable<ApolloStoreState<Type>> { - const initialState: ApolloStoreState<Type> = { - loading: true, - data: initialValue, - error: undefined - }; - - return readable(initialState, (set) => { - const handleError = function (error: Error) { - return set({ - loading: false, - data: initialValue, - error - }); - }; - - client.watchQuery({ query, variables }).subscribe( - (result: ApolloQueryResult<Type>) => { - if (result.errors) { - const error = new ApolloError({ graphQLErrors: result.errors }); - return handleError(error); - } - - set({ - loading: false, - data: result.data[key].edges.map((item) => item.node), - error: undefined - }); - }, - (error: Error) => handleError(error) - ); - }); -}; diff --git a/src/lib/stores/forums.ts b/src/lib/stores/forums.ts index 0ff09f7..40a3f2c 100644 --- a/src/lib/stores/forums.ts +++ b/src/lib/stores/forums.ts @@ -1,9 +1,18 @@ -import { store } from './apollo'; -import { GET_FORUM, GET_FORUMS } from '$lib/data/queries'; +import { createClient } from '@supabase/supabase-js' +import { single, collection } from './supabase'; +import { supabase } from '$lib/config/config'; import type { Forum } from '$lib/data/types'; -export const getForum = (id: string) => - store<Forum>({ key: 'forum', query: GET_FORUM, variables: { id } }); -export const getForums = () => - store<Forum[]>({ key: 'forumsCollection', query: GET_FORUMS, initialValue: [] }); +const client = createClient(supabase.url, supabase.key); + +export const forum = (id: string, withTopics = false) => single<Forum>(client + .from('forums') + .select(withTopics ? `*, + topics ( + * + ) + `: '*' ) + .eq('id', id), + null); +export const forums = collection<Forum>(client.from('forums').select('*'), []); diff --git a/src/lib/stores/posts.ts b/src/lib/stores/posts.ts index 718e1e5..f592dca 100644 --- a/src/lib/stores/posts.ts +++ b/src/lib/stores/posts.ts @@ -1,7 +1,23 @@ -import { store } from './apollo'; -import { GET_POST } from '$lib/data/queries'; +import { createClient } from '@supabase/supabase-js' +import { single, collection } from './supabase'; +import { supabase } from '$lib/config/config'; import type { Post } from '$lib/data/types'; -export const getPost = (id: string) => - store<Post>({ key: 'post', query: GET_POST, variables: { id } }); +const client = createClient(supabase.url, supabase.key); + +export const post = (id: string, withTopic = false) => single<Post>(client + .from('posts') + .select(withTopic ? `*, + topic:topic_id ( + * + ) + `: '*' ) + .eq('id', id), + null); +export const postsForTopic = (id: string) => collection<Post>(client + .from('posts') + .select('*') + .eq('topic_id', id) + .order('created_at', { ascending: true }), + []); diff --git a/src/lib/stores/response_builder.ts b/src/lib/stores/response_builder.ts new file mode 100644 index 0000000..1e12243 --- /dev/null +++ b/src/lib/stores/response_builder.ts @@ -0,0 +1,37 @@ +/** + * Utilities to build responses + */ + +interface AnyError { + message: string +}; + +export type StoreState<Type> = { + loading: boolean; + data: Type | void; + error: AnyError | void; +}; + +export function initialResponse<T> (initialState: T): StoreState<T> { + return { + loading: true, + data: initialState, + error: undefined + }; +} + +export function errorResponse<T> (error: AnyError): StoreState<T> { + return { + loading: false, + data: undefined, + error + }; +} + +export function response<T> (data: T): StoreState<T> { + return { + loading: false, + data, + error: undefined + }; +} diff --git a/src/lib/stores/supabase.ts b/src/lib/stores/supabase.ts new file mode 100644 index 0000000..804141f --- /dev/null +++ b/src/lib/stores/supabase.ts @@ -0,0 +1,38 @@ +import { readable } from 'svelte/store'; +import { initialResponse, errorResponse, response } from './response_builder'; + +import type { Readable } from 'svelte/store'; +import type { PostgrestFilterBuilder } from '@supabase/postgrest-js'; +import type { StoreState } from './response_builder'; + +export function collection<T> (query: PostgrestFilterBuilder<T>, initialValue: T[]): Readable<StoreState<T[]>> { + + return readable(initialResponse<T[]>(initialValue), (set) => { + + (async function() { + const { data, error } = await query; + + if (error) { + return set(errorResponse<T[]>(error)); + } + + set(response<T[]>(data)); + })() + }); +} + +export function single<T> (query: PostgrestFilterBuilder<T>, initialValue: T): Readable<StoreState<T>> { + + return readable(initialResponse<T>(initialValue), (set) => { + + (async function() { + const { data, error } = await query.single(); + + if (error) { + return set(errorResponse<T>(error)); + } + + set(response<T>(data)); + })() + }); +} diff --git a/src/lib/stores/tags.ts b/src/lib/stores/tags.ts index c96da2d..0b528e8 100644 --- a/src/lib/stores/tags.ts +++ b/src/lib/stores/tags.ts @@ -1,6 +1,13 @@ -import { store } from './apollo'; -import { GET_TAG } from '$lib/data/queries'; +import { createClient } from '@supabase/supabase-js' +import { collection } from './supabase'; +import { supabase } from '$lib/config/config'; import type { Tag } from '$lib/data/types'; -export const getTag = (id: string) => store<Tag>({ key: 'tag', query: GET_TAG, variables: { id } }); +const client = createClient(supabase.url, supabase.key); + +export const tagsForTopic = (id: string) => collection<Tag>(client + .from('topic_tags') + .select('*') + .eq('topic_id', id), + []); diff --git a/src/lib/stores/topics.ts b/src/lib/stores/topics.ts index 0e39769..04c1e9e 100644 --- a/src/lib/stores/topics.ts +++ b/src/lib/stores/topics.ts @@ -1,7 +1,32 @@ -import { store } from './apollo'; -import { GET_TOPIC } from '$lib/data/queries'; +import { createClient } from '@supabase/supabase-js' +import { single, collection } from './supabase'; +import { supabase } from '$lib/config/config'; import type { Topic } from '$lib/data/types'; -export const getTopic = (id: string) => - store<Topic>({ key: 'topic', query: GET_TOPIC, variables: { id } }); +const client = createClient(supabase.url, supabase.key); + +export const topic = (id: string, withPosts = false) => single<Topic>(client + .from('topics') + .select(withPosts ? `*, + forum: forums (*), + tags: topic_tags (*), + posts ( + *, + author:author_id (*) + ) + `: '*' ) + .eq('id', id), + null); +export const topicsForForum = (id: string) => collection<Topic>(client + .from('topics') + .select('*') + .eq('forum_id', id), + []); +export const topicsForTag = (id: string) => collection<Topic>(client + .from('topics') + .select(` + *,tags!inner(*) + `) + .eq('tags.tag', id), + []); diff --git a/src/lib/stores/users.ts b/src/lib/stores/users.ts new file mode 100644 index 0000000..2a56cb5 --- /dev/null +++ b/src/lib/stores/users.ts @@ -0,0 +1,13 @@ +import { createClient } from '@supabase/supabase-js' +import { single } from './supabase'; +import { supabase } from '$lib/config/config'; + +import type { User } from '$lib/data/types'; + +const client = createClient(supabase.url, supabase.key); + +export const user = (id: string) => single<User>(client + .from('users') + .select('*') + .eq('id', id), + null); |