UNPKG

svelte-firebase-state

Version:

Simplify Firebase integration in Svelte and SvelteKit with reactive state management for Firestore and Realtime Database.

148 lines (142 loc) 4.38 kB
import {} from "firebase/auth"; import { ref, onValue, set, get } from "firebase/database"; import { RealtimeDatabaseState } from "./RealtimeDatabaseState.svelte.js"; export class NodeState extends RealtimeDatabaseState { autosave; // private firstFetchDone: boolean = false; // private isUpdatingFromDB: boolean = true; // private cleanup: () => void; nodeRef; constructor({ auth, database, path: pathFunctionOrString, listen = false, autosave = false }) { super({ auth, database, listen, pathFunctionOrString }); this.autosave = autosave; // this.cleanup = this.initialize_effects(); } async init_ref() { const pathStr = await this.get_path_string(); if (!pathStr) { throw new Error("Path is not defined"); } this.nodeRef = ref(this.database, pathStr); } listen_data() { if (!this.nodeRef) { throw new Error("nodeRef is not set"); } this.unsub = onValue(this.nodeRef, (snapshot) => { // this.isUpdatingFromDB = true; this.dataState.value = snapshot.val(); // this.firstFetchDone = true; }, (error) => { console.error("NodeState.svelte | listen | error", error); }); } async fetch_data() { if (!this.nodeRef) { return null; } const snapshot = await get(this.nodeRef); this.dataState.value = snapshot.val(); return this.dataState.value; } /* // private initialize_effects(): () => void { // return () => {}; // return $effect.root(() => { // effect_deps( // () => { // console.log("effect_deps", this.data?.age); // this.save_data_to_firebase(); // // this.initialize_effects(); // }, // () => [(this.data as any)?.age] // ); $effect(() => { console.log(this.data?.age); }); $effect(() => { if (!this.data) { return () => console.log("$effect cleanup 1"); } console.log("$effect", this.data.age); if (!this.data || this.isUpdatingFromDB) { this.isUpdatingFromDB = false; return () => console.log("$effect cleanup 2"); } console.log("SAVE VALUE"); this.save_data_to_firebase(); // this.initialize_effects(); // return () => console.log("$effect cleanup 3"); }); // return () => console.log("$effect.root cleanup"); // }); // // return $effect.root(() => { // $effect(() => { // console.log("$effect", this.data, this.isUpdatingFromDB); // // // Watch all keys in the object // Object.keys(this.data || {}).forEach((key) => { // console.log("key", key); // }); // // if (!this.data || this.isUpdatingFromDB) { // this.isUpdatingFromDB = false; // return () => {}; // } // // console.log("SAVE VALUE"); // this.save_data_to_firebase(); // // return () => {}; // }); // // return () => {}; // }); // // return () => {}; // } */ save_data_to_firebase() { if (!this.nodeRef || !this.data) { return; } set(this.nodeRef, this.data); } set data(newValue) { this.dataState.value = newValue; if (this.autosave) { this.save_data_to_firebase(); } } //!\ If set data is defined, we need to defined get data here as well get data() { return this.dataState.value; } save(key, update) { if (!key) { this.save_data_to_firebase(); return; } if (!update || !this.nodeRef || !this.data) { return; } let newValue; if (typeof update === "function") { const updateFn = update; const prevValue = this.data[key]; newValue = updateFn(prevValue); } else { newValue = update; } this.data[key] = newValue; this.save_data_to_firebase(); } }