Skip to content

Commit a95b627

Browse files
committed
feat: add firebase realtime database
1 parent fc380cd commit a95b627

File tree

12 files changed

+231
-56
lines changed

12 files changed

+231
-56
lines changed

firebase.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
"firestore": {
77
"port": 8080
88
},
9+
"database": {
10+
"port": 9000
11+
},
912
"hosting": {
1013
"port": 5000
1114
},
@@ -16,10 +19,6 @@
1619
},
1720
"hosting": {
1821
"public": "docs/dist",
19-
"ignore": [
20-
"firebase.json",
21-
"**/.*",
22-
"**/node_modules/**"
23-
]
22+
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
2423
}
2524
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/components/DataList.svelte

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script lang="ts">
2+
import { listStore } from "../stores/realtimeDatabase.js";
3+
import { getFirebaseContext } from "../stores/sdk.js";
4+
import type { DatabaseReference, Database } from "firebase/database";
5+
6+
export let path: string;
7+
export let startWith: any[] = [];
8+
9+
const { rtdb } = getFirebaseContext();
10+
let store = listStore(rtdb!, path, startWith);
11+
12+
interface $$Slots {
13+
default: {
14+
data: any[];
15+
ref: DatabaseReference | null;
16+
count: number;
17+
rtdb?: Database;
18+
};
19+
loading: {};
20+
}
21+
</script>
22+
23+
{#if $store !== undefined}
24+
<slot data={$store} ref={store.ref} count={$store?.length ?? 0} {rtdb} />
25+
{:else}
26+
<slot name="loading" />
27+
{/if}

src/lib/components/DataRef.svelte

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script lang="ts">
2+
import { refStore } from "../stores/realtimeDatabase.js";
3+
import { getFirebaseContext } from "../stores/sdk.js";
4+
import type { DatabaseReference, Database } from "firebase/database";
5+
6+
export let path: string;
7+
export let startWith: any = undefined;
8+
9+
const { rtdb } = getFirebaseContext();
10+
let store = refStore(rtdb!, path, startWith);
11+
12+
interface $$Slots {
13+
default: { data: any; ref: DatabaseReference | null; rtdb?: Database };
14+
loading: {};
15+
}
16+
</script>
17+
18+
{#if $store !== undefined}
19+
<slot data={$store} ref={store.ref} {rtdb} />
20+
{:else}
21+
<slot name="loading" />
22+
{/if}

src/lib/components/FirebaseApp.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
import { setFirebaseContext } from "$lib/stores/sdk.js";
33
import type { Auth } from "firebase/auth";
44
import type { Firestore } from "firebase/firestore";
5+
import type { Database } from "firebase/database";
56
67
export let firestore: Firestore;
8+
export let rtdb: Database;
79
export let auth: Auth;
810
9-
setFirebaseContext({ firestore, auth });
11+
setFirebaseContext({ firestore, rtdb, auth });
1012
</script>
1113

1214
<slot />

src/lib/index.js

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
// Reexport your entry components here
2-
import User from './components/User.svelte';
3-
import Collection from './components/Collection.svelte';
4-
import Doc from './components/Doc.svelte';
5-
import FirebaseApp from './components/FirebaseApp.svelte';
6-
import SignedIn from './components/SignedIn.svelte';
7-
import SignedOut from './components/SignedOut.svelte';
8-
import { userStore } from './stores/auth.js';
9-
import { docStore, collectionStore } from './stores/firestore.js';
10-
import { getFirebaseContext } from './stores/sdk.js';
11-
2+
import User from "./components/User.svelte";
3+
import Collection from "./components/Collection.svelte";
4+
import Doc from "./components/Doc.svelte";
5+
import DataRef from './components/DataRef.svelte';
6+
import DataList from './components/DataList.svelte';
7+
import FirebaseApp from "./components/FirebaseApp.svelte";
8+
import SignedIn from "./components/SignedIn.svelte";
9+
import SignedOut from "./components/SignedOut.svelte";
10+
import { userStore } from "./stores/auth.js";
11+
import { docStore, collectionStore } from "./stores/firestore.js";
12+
import { refStore, listStore } from './stores/realtimeDatabase.js';
13+
import { getFirebaseContext } from "./stores/sdk.js";
14+
1215
export {
13-
Doc,
14-
User,
15-
Collection,
16-
FirebaseApp,
17-
SignedOut,
18-
SignedIn,
19-
docStore,
20-
collectionStore,
21-
userStore,
22-
getFirebaseContext
23-
}
16+
Doc,
17+
User,
18+
Collection,
19+
DataRef,
20+
DataList,
21+
FirebaseApp,
22+
SignedOut,
23+
SignedIn,
24+
docStore,
25+
collectionStore,
26+
refStore,
27+
listStore,
28+
userStore,
29+
getFirebaseContext,
30+
};

src/lib/stores/realtimeDatabase.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { writable } from "svelte/store";
2+
import { onValue, ref as dbRef } from "firebase/database";
3+
import type { Database } from "firebase/database";
4+
5+
/**
6+
* @param {Database} rtdb - Firebase Realtime Database instance.
7+
* @param {string} path - Path to the database reference.
8+
* @param {T | undefined} startWith - Optional default data.
9+
* @returns a store with realtime updates on individual database reference data.
10+
*/
11+
export function refStore<T = any>(rtdb: Database, path: string, startWith?: T) {
12+
const dataRef = dbRef(rtdb, path);
13+
14+
const { subscribe } = writable<T | null>(startWith, (set) => {
15+
const unsubscribe = onValue(dataRef, (snapshot) => {
16+
set(snapshot.val() as T);
17+
});
18+
19+
return unsubscribe;
20+
});
21+
22+
return {
23+
subscribe,
24+
ref: dataRef,
25+
};
26+
}
27+
28+
/**
29+
* @param {Database} rtdb - Firebase Realtime Database instance.
30+
* @param {string} path - Path to the database reference.
31+
* @param {T[]} startWith - Optional default data.
32+
* @returns a store with realtime updates on lists of data.
33+
*/
34+
export function listStore<T = any>(
35+
rtdb: Database,
36+
path: string,
37+
startWith: T[] = []
38+
) {
39+
const listRef = dbRef(rtdb, path);
40+
41+
const { subscribe } = writable<T[]>(startWith, (set) => {
42+
const unsubscribe = onValue(listRef, (snapshot) => {
43+
const dataArr: T[] = [];
44+
snapshot.forEach((childSnapshot) => {
45+
dataArr.push({
46+
key: childSnapshot.ref.key,
47+
...(childSnapshot.val() as T),
48+
});
49+
});
50+
set(dataArr);
51+
});
52+
53+
return unsubscribe;
54+
});
55+
56+
return {
57+
subscribe,
58+
ref: listRef,
59+
};
60+
}

src/lib/stores/sdk.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { writable } from "svelte/store";
21
import type { Firestore } from "firebase/firestore";
2+
import type { Database } from "firebase/database";
33
import type { Auth } from "firebase/auth";
44
import { getContext, setContext } from "svelte";
55

6-
76
export interface FirebaseSDKContext {
87
auth?: Auth;
98
firestore?: Firestore;
9+
rtdb?: Database;
1010
}
1111

1212
export const contextKey = "firebase";

src/routes/+layout.svelte

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
<script lang="ts">
2-
import FirebaseApp from '$lib/components/FirebaseApp.svelte';
3-
import { db as firestore, auth } from './firebase.js';
4-
2+
import FirebaseApp from "$lib/components/FirebaseApp.svelte";
3+
import { db as firestore, auth, rtdb } from "./firebase.js";
54
</script>
65

7-
<FirebaseApp {auth} {firestore}>
8-
9-
<slot />
6+
<FirebaseApp {auth} {firestore} {rtdb}>
7+
<slot />
108
</FirebaseApp>

src/routes/+page.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
<script lang="ts">
22
import { getFirebaseContext } from "$lib/stores/sdk.js";
33
4-
54
const ctx = getFirebaseContext();
6-
75
</script>
86

97
<h1>Welcome to SvelteFire</h1>
108

119
<ul>
1210
<li><a href="/auth-test">Auth Test</a></li>
1311
<li><a href="/firestore-test">Firestore Test</a></li>
12+
<li><a href="/rtdb-test">Realtime Database Test</a></li>
1413
<li><a href="/ssr-test">SSR Test</a></li>
1514
</ul>
1615
<ul>

0 commit comments

Comments
 (0)