diff --git a/docs/src/pages/firestore/doc-component.md b/docs/src/pages/firestore/doc-component.md index 4860040..f829923 100644 --- a/docs/src/pages/firestore/doc-component.md +++ b/docs/src/pages/firestore/doc-component.md @@ -18,6 +18,7 @@ The `Doc` component is a wrapper around the `docStore`. It renders the document - `default` - The document data - `loading` - Loading state +- `notExist` - A document does not exist for the provided ref ### Slot Props @@ -36,5 +37,6 @@ The `Doc` component is a wrapper around the `docStore`. It renders the document

{data?.title}

Loading...

+

Post does not exist

``` \ No newline at end of file diff --git a/docs/src/pages/firestore/doc-store.md b/docs/src/pages/firestore/doc-store.md index caf2c30..6563f26 100644 --- a/docs/src/pages/firestore/doc-store.md +++ b/docs/src/pages/firestore/doc-store.md @@ -55,4 +55,27 @@ With TypeScript: {$post?.title} -``` \ No newline at end of file +``` + +Check if post does not exist: + +```svelte + + +{#if !$postState.loading && !$postState.exists} + Post does not exist +{:else} + {$post?.title} +{/if} +``` + + diff --git a/src/lib/components/Doc.svelte b/src/lib/components/Doc.svelte index 4feac31..2fcbf00 100644 --- a/src/lib/components/Doc.svelte +++ b/src/lib/components/Doc.svelte @@ -13,6 +13,7 @@ const { firestore } = getFirebaseContext(); let store = docStore(firestore!, ref, startWith); + let state = store.stateStore; interface $$Slots { default: { @@ -21,11 +22,14 @@ firestore?: Firestore; }; loading: {}; + notExist: {}; } -{#if $store !== undefined && $store !== null} - -{:else} +{#if $state.loading} +{:else if !$state.exists} + +{:else if $store !== undefined && $store !== null} + {/if} diff --git a/src/lib/stores/firestore.ts b/src/lib/stores/firestore.ts index 6bdd771..5b7eafa 100644 --- a/src/lib/stores/firestore.ts +++ b/src/lib/stores/firestore.ts @@ -7,8 +7,16 @@ import type { Firestore, } from "firebase/firestore"; +interface DocState { + loading: boolean; + exists: boolean | null; +} + interface DocStore { subscribe: (cb: (value: T | null) => void) => void | (() => void); + stateStore: { + subscribe: (cb: (value: DocState) => void) => void | (() => void); + }; ref: DocumentReference | null; id: string; } @@ -26,27 +34,34 @@ export function docStore( ): DocStore { let unsubscribe: () => void; - // Fallback for SSR - if (!globalThis.window) { + function noopStore() { const { subscribe } = writable(startWith); + const { subscribe: existsSubscribe } = writable({ + loading: true, + exists: null, + }); + return { subscribe, + stateStore: { + subscribe: existsSubscribe, + }, ref: null, id: "", }; } + // Fallback for SSR + if (!globalThis.window) { + return noopStore(); + } + // Fallback for missing SDK if (!firestore) { console.warn( "Firestore is not initialized. Are you missing FirebaseApp as a parent component?" ); - const { subscribe } = writable(null); - return { - subscribe, - ref: null, - id: "", - }; + return noopStore(); } const docRef = @@ -54,8 +69,17 @@ export function docStore( ? (doc(firestore, ref) as DocumentReference) : ref; + const state = writable({ + loading: true, + exists: null, + }); + const { subscribe } = writable(startWith, (set) => { unsubscribe = onSnapshot(docRef, (snapshot) => { + state.set({ + loading: false, + exists: snapshot.exists(), + }); set((snapshot.data() as T) ?? null); }); @@ -64,6 +88,9 @@ export function docStore( return { subscribe, + stateStore: { + subscribe: state.subscribe, + }, ref: docRef, id: docRef.id, };