svelte-firekit 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/auth/reset-password.svelte +1 -1
  2. package/dist/auth/sign-in.svelte +2 -2
  3. package/dist/auth/sign-in.svelte.d.ts +1 -1
  4. package/dist/components/auth/google-sign-in.svelte +15 -1
  5. package/dist/components/auth/reset-password-form.svelte +16 -17
  6. package/dist/components/auth/sign-in-form.svelte +24 -23
  7. package/dist/components/auth/sign-up-form.svelte +52 -45
  8. package/dist/{auth → components/auth}/user-button.svelte +35 -34
  9. package/dist/{auth → components/auth}/user-button.svelte.d.ts +2 -2
  10. package/dist/components/firestore/collection.svelte +45 -0
  11. package/dist/components/firestore/collection.svelte.d.ts +25 -0
  12. package/dist/components/firestore/doc.svelte +39 -0
  13. package/dist/components/firestore/doc.svelte.d.ts +25 -0
  14. package/dist/components/nav/app-sidebar.svelte +46 -0
  15. package/dist/components/nav/app-sidebar.svelte.d.ts +8 -0
  16. package/dist/components/nav/breadcrumb.svelte +42 -0
  17. package/dist/components/nav/breadcrumb.svelte.d.ts +19 -0
  18. package/dist/components/nav/dark-mode-toggle.svelte +16 -0
  19. package/dist/components/nav/dark-mode-toggle.svelte.d.ts +18 -0
  20. package/dist/components/nav/nav.d.ts +11 -0
  21. package/dist/components/nav/nav.js +157 -0
  22. package/dist/components/nav/search-form.svelte +21 -0
  23. package/dist/components/nav/search-form.svelte.d.ts +4 -0
  24. package/dist/components/nav/version-switcher.svelte +48 -0
  25. package/dist/components/nav/version-switcher.svelte.d.ts +5 -0
  26. package/dist/components/storage/upload.svelte +134 -0
  27. package/dist/components/storage/upload.svelte.d.ts +11 -0
  28. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +23 -0
  29. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte.d.ts +4 -0
  30. package/dist/components/ui/breadcrumb/breadcrumb-item.svelte +16 -0
  31. package/dist/components/ui/breadcrumb/breadcrumb-item.svelte.d.ts +4 -0
  32. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +31 -0
  33. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte.d.ts +10 -0
  34. package/dist/components/ui/breadcrumb/breadcrumb-list.svelte +23 -0
  35. package/dist/components/ui/breadcrumb/breadcrumb-list.svelte.d.ts +4 -0
  36. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +23 -0
  37. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte.d.ts +4 -0
  38. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +27 -0
  39. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte.d.ts +4 -0
  40. package/dist/components/ui/breadcrumb/breadcrumb.svelte +15 -0
  41. package/dist/components/ui/breadcrumb/breadcrumb.svelte.d.ts +4 -0
  42. package/dist/components/ui/breadcrumb/index.d.ts +8 -0
  43. package/dist/components/ui/breadcrumb/index.js +10 -0
  44. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +10 -7
  45. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +4 -3
  46. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +1 -0
  47. package/dist/components/ui/input/input.svelte.d.ts +1 -1
  48. package/dist/components/ui/separator/index.d.ts +2 -0
  49. package/dist/components/ui/separator/index.js +4 -0
  50. package/dist/components/ui/separator/separator.svelte +22 -0
  51. package/dist/components/ui/separator/separator.svelte.d.ts +3 -0
  52. package/dist/components/ui/sheet/index.js +14 -0
  53. package/dist/components/ui/sheet/sheet-content.svelte +52 -0
  54. package/dist/components/ui/sheet/sheet-content.svelte.d.ts +59 -0
  55. package/dist/components/ui/sheet/sheet-description.svelte +16 -0
  56. package/dist/components/ui/sheet/sheet-description.svelte.d.ts +3 -0
  57. package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
  58. package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +4 -0
  59. package/dist/components/ui/sheet/sheet-header.svelte +20 -0
  60. package/dist/components/ui/sheet/sheet-header.svelte.d.ts +4 -0
  61. package/dist/components/ui/sheet/sheet-overlay.svelte +19 -0
  62. package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +3 -0
  63. package/dist/components/ui/sheet/sheet-title.svelte +16 -0
  64. package/dist/components/ui/sheet/sheet-title.svelte.d.ts +3 -0
  65. package/dist/components/ui/sidebar/constants.d.ts +6 -0
  66. package/dist/components/ui/sidebar/constants.js +6 -0
  67. package/dist/components/ui/sidebar/context.svelte.d.ts +42 -0
  68. package/dist/components/ui/sidebar/context.svelte.js +54 -0
  69. package/dist/components/ui/sidebar/index.d.ts +25 -0
  70. package/dist/components/ui/sidebar/index.js +27 -0
  71. package/dist/components/ui/sidebar/sidebar-content.svelte +24 -0
  72. package/dist/components/ui/sidebar/sidebar-content.svelte.d.ts +4 -0
  73. package/dist/components/ui/sidebar/sidebar-footer.svelte +21 -0
  74. package/dist/components/ui/sidebar/sidebar-footer.svelte.d.ts +4 -0
  75. package/dist/components/ui/sidebar/sidebar-group-action.svelte +36 -0
  76. package/dist/components/ui/sidebar/sidebar-group-action.svelte.d.ts +10 -0
  77. package/dist/components/ui/sidebar/sidebar-group-content.svelte +21 -0
  78. package/dist/components/ui/sidebar/sidebar-group-content.svelte.d.ts +4 -0
  79. package/dist/components/ui/sidebar/sidebar-group-label.svelte +34 -0
  80. package/dist/components/ui/sidebar/sidebar-group-label.svelte.d.ts +10 -0
  81. package/dist/components/ui/sidebar/sidebar-group.svelte +21 -0
  82. package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +4 -0
  83. package/dist/components/ui/sidebar/sidebar-header.svelte +21 -0
  84. package/dist/components/ui/sidebar/sidebar-header.svelte.d.ts +4 -0
  85. package/dist/components/ui/sidebar/sidebar-input.svelte +23 -0
  86. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +4 -0
  87. package/dist/components/ui/sidebar/sidebar-inset.svelte +24 -0
  88. package/dist/components/ui/sidebar/sidebar-inset.svelte.d.ts +4 -0
  89. package/dist/components/ui/sidebar/sidebar-menu-action.svelte +43 -0
  90. package/dist/components/ui/sidebar/sidebar-menu-action.svelte.d.ts +11 -0
  91. package/dist/components/ui/sidebar/sidebar-menu-badge.svelte +29 -0
  92. package/dist/components/ui/sidebar/sidebar-menu-badge.svelte.d.ts +4 -0
  93. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +97 -0
  94. package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +91 -0
  95. package/dist/components/ui/sidebar/sidebar-menu-item.svelte +21 -0
  96. package/dist/components/ui/sidebar/sidebar-menu-item.svelte.d.ts +4 -0
  97. package/dist/components/ui/sidebar/sidebar-menu-skeleton.svelte +36 -0
  98. package/dist/components/ui/sidebar/sidebar-menu-skeleton.svelte.d.ts +7 -0
  99. package/dist/components/ui/sidebar/sidebar-menu-sub-button.svelte +43 -0
  100. package/dist/components/ui/sidebar/sidebar-menu-sub-button.svelte.d.ts +12 -0
  101. package/dist/components/ui/sidebar/sidebar-menu-sub-item.svelte +14 -0
  102. package/dist/components/ui/sidebar/sidebar-menu-sub-item.svelte.d.ts +4 -0
  103. package/dist/components/ui/sidebar/sidebar-menu-sub.svelte +25 -0
  104. package/dist/components/ui/sidebar/sidebar-menu-sub.svelte.d.ts +4 -0
  105. package/dist/components/ui/sidebar/sidebar-menu.svelte +21 -0
  106. package/dist/components/ui/sidebar/sidebar-menu.svelte.d.ts +4 -0
  107. package/dist/components/ui/sidebar/sidebar-provider.svelte +59 -0
  108. package/dist/components/ui/sidebar/sidebar-provider.svelte.d.ts +9 -0
  109. package/dist/components/ui/sidebar/sidebar-rail.svelte +36 -0
  110. package/dist/components/ui/sidebar/sidebar-rail.svelte.d.ts +4 -0
  111. package/dist/components/ui/sidebar/sidebar-separator.svelte +18 -0
  112. package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +12 -0
  113. package/dist/components/ui/sidebar/sidebar-trigger.svelte +34 -0
  114. package/dist/components/ui/sidebar/sidebar-trigger.svelte.d.ts +9 -0
  115. package/dist/components/ui/sidebar/sidebar.svelte +98 -0
  116. package/dist/components/ui/sidebar/sidebar.svelte.d.ts +9 -0
  117. package/dist/components/ui/skeleton/index.d.ts +2 -0
  118. package/dist/components/ui/skeleton/index.js +4 -0
  119. package/dist/components/ui/skeleton/skeleton.svelte +17 -0
  120. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +4 -0
  121. package/dist/components/ui/tooltip/index.js +8 -0
  122. package/dist/components/ui/tooltip/tooltip-content.svelte +21 -0
  123. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +3 -0
  124. package/dist/firebase/auth/auth-guard.svelte.d.ts +25 -0
  125. package/dist/firebase/auth/auth-guard.svelte.js +79 -0
  126. package/dist/firebase/auth/auth.d.ts +21 -0
  127. package/dist/firebase/auth/auth.js +71 -0
  128. package/dist/firebase/auth/user.svelte.d.ts +50 -0
  129. package/dist/firebase/auth/user.svelte.js +115 -0
  130. package/dist/firebase/config.js +44 -0
  131. package/dist/firebase/firebase.d.ts +28 -0
  132. package/dist/firebase/firebase.js +86 -0
  133. package/dist/firebase/firestore/awaitable-doc.svelte.d.ts +15 -0
  134. package/dist/firebase/firestore/awaitable-doc.svelte.js +57 -0
  135. package/dist/firebase/firestore/collection.svelte.d.ts +17 -0
  136. package/dist/firebase/firestore/collection.svelte.js +58 -0
  137. package/dist/firebase/firestore/doc.svelte.d.ts +16 -0
  138. package/dist/firebase/firestore/doc.svelte.js +56 -0
  139. package/dist/firebase/firestore/document-mutations.svelte.d.ts +18 -0
  140. package/dist/firebase/firestore/document-mutations.svelte.js +58 -0
  141. package/dist/firebase/storage/download-url.svelte.d.ts +14 -0
  142. package/dist/firebase/storage/download-url.svelte.js +45 -0
  143. package/dist/firebase/storage/storage-list.svelte.d.ts +17 -0
  144. package/dist/firebase/storage/storage-list.svelte.js +51 -0
  145. package/dist/firebase/storage/upload-task.svelte.d.ts +22 -0
  146. package/dist/firebase/storage/upload-task.svelte.js +65 -0
  147. package/dist/hooks/is-mobile.svelte.d.ts +5 -0
  148. package/dist/hooks/is-mobile.svelte.js +23 -0
  149. package/dist/index.d.ts +22 -2
  150. package/dist/index.js +29 -3
  151. package/dist/types/docs.d.ts +50 -0
  152. package/dist/utils.d.ts +27 -1
  153. package/dist/utils.js +85 -9
  154. package/package.json +9 -7
  155. package/dist/auth/uid.js +0 -7
  156. package/dist/auth/user.svelte.d.ts +0 -10
  157. package/dist/auth/user.svelte.js +0 -21
  158. package/dist/auth.d.ts +0 -39
  159. package/dist/auth.js +0 -100
  160. package/dist/config.js +0 -39
  161. package/dist/firebase.d.ts +0 -43
  162. package/dist/firebase.js +0 -110
  163. package/dist/firestore/Collection.svelte +0 -148
  164. package/dist/firestore/Collection.svelte.d.ts +0 -27
  165. package/dist/firestore/collection.svelte.js +0 -207
  166. package/dist/firestore/doc.svelte.d.ts +0 -1
  167. package/dist/firestore/doc.svelte.js +0 -1
  168. package/dist/firestore/firestore.d.ts +0 -31
  169. package/dist/firestore/firestore.js +0 -100
  170. package/dist/firestore/perf.d.ts +0 -3
  171. package/dist/firestore/perf.js +0 -12
  172. /package/dist/{config.d.ts → firebase/config.d.ts} +0 -0
  173. /package/dist/{auth/uid.d.ts → types/docs.js} +0 -0
@@ -0,0 +1,21 @@
1
+ declare class FirekitAuth {
2
+ private static instance;
3
+ private auth;
4
+ private firestore;
5
+ private constructor();
6
+ static getInstance(): FirekitAuth;
7
+ signInWithGoogle(): Promise<void>;
8
+ signInWithEmail(email: string, password: string): Promise<void>;
9
+ registerWithEmail(email: string, password: string, displayName: string): Promise<void>;
10
+ private updateUserInFirestore;
11
+ logOut(): Promise<void>;
12
+ sendPasswordReset(email: string): Promise<void>;
13
+ sendEmailVerificationToUser(): Promise<void>;
14
+ updateUserProfile(profile: {
15
+ displayName?: string;
16
+ photoURL?: string;
17
+ }): Promise<void>;
18
+ updateUserPassword(newPassword: string): Promise<void>;
19
+ }
20
+ export declare const firekitAuth: FirekitAuth;
21
+ export {};
@@ -0,0 +1,71 @@
1
+ import { GoogleAuthProvider, sendPasswordResetEmail, signInWithEmailAndPassword, signInWithPopup, signOut, createUserWithEmailAndPassword, sendEmailVerification, updateProfile, updatePassword } from 'firebase/auth';
2
+ import { doc, setDoc } from 'firebase/firestore';
3
+ import { firebaseService } from '../firebase.js';
4
+ class FirekitAuth {
5
+ static instance;
6
+ auth = firebaseService.getAuthInstance();
7
+ firestore = firebaseService.getDb();
8
+ constructor() { }
9
+ static getInstance() {
10
+ if (!FirekitAuth.instance) {
11
+ FirekitAuth.instance = new FirekitAuth();
12
+ }
13
+ return FirekitAuth.instance;
14
+ }
15
+ async signInWithGoogle() {
16
+ const provider = new GoogleAuthProvider();
17
+ const result = await signInWithPopup(this.auth, provider);
18
+ await this.updateUserInFirestore(result.user);
19
+ }
20
+ async signInWithEmail(email, password) {
21
+ const result = await signInWithEmailAndPassword(this.auth, email, password);
22
+ await this.updateUserInFirestore(result.user);
23
+ }
24
+ async registerWithEmail(email, password, displayName) {
25
+ const result = await createUserWithEmailAndPassword(this.auth, email, password);
26
+ const user = result.user;
27
+ if (user) {
28
+ await updateProfile(user, { displayName });
29
+ await this.updateUserInFirestore(user);
30
+ await sendEmailVerification(user);
31
+ }
32
+ }
33
+ async updateUserInFirestore(user) {
34
+ const ref = doc(this.firestore, 'users', user.uid);
35
+ const userData = {
36
+ uid: user.uid,
37
+ email: user.email,
38
+ emailVerified: user.emailVerified,
39
+ displayName: user.displayName,
40
+ photoURL: user.photoURL,
41
+ isAnonymous: user.isAnonymous,
42
+ providerId: user.providerId,
43
+ phoneNumber: user.phoneNumber,
44
+ providerData: user.providerData
45
+ };
46
+ await setDoc(ref, userData, { merge: true });
47
+ }
48
+ async logOut() {
49
+ await signOut(this.auth);
50
+ }
51
+ async sendPasswordReset(email) {
52
+ await sendPasswordResetEmail(this.auth, email);
53
+ }
54
+ async sendEmailVerificationToUser() {
55
+ if (this.auth.currentUser) {
56
+ await sendEmailVerification(this.auth.currentUser);
57
+ }
58
+ }
59
+ async updateUserProfile(profile) {
60
+ if (this.auth.currentUser) {
61
+ await updateProfile(this.auth.currentUser, profile);
62
+ await this.updateUserInFirestore(this.auth.currentUser);
63
+ }
64
+ }
65
+ async updateUserPassword(newPassword) {
66
+ if (this.auth.currentUser) {
67
+ await updatePassword(this.auth.currentUser, newPassword);
68
+ }
69
+ }
70
+ }
71
+ export const firekitAuth = FirekitAuth.getInstance();
@@ -0,0 +1,50 @@
1
+ import { type User } from "firebase/auth";
2
+ import { type DocumentData } from 'firebase/firestore';
3
+ interface UserClaims {
4
+ [key: string]: any;
5
+ admin?: boolean;
6
+ premium?: boolean;
7
+ }
8
+ interface UserData extends DocumentData {
9
+ displayName?: string;
10
+ email?: string;
11
+ photoURL?: string;
12
+ createdAt?: Date;
13
+ updatedAt?: Date;
14
+ isProfileComplete?: boolean;
15
+ role?: string;
16
+ settings?: Record<string, any>;
17
+ [key: string]: any;
18
+ }
19
+ export declare class FirekitUser {
20
+ private static instance;
21
+ private _user;
22
+ private _userData;
23
+ private _claims;
24
+ readonly isLoggedIn: boolean;
25
+ readonly uid: string | undefined;
26
+ readonly email: string | null | undefined;
27
+ readonly displayName: string | null | undefined;
28
+ readonly photoURL: string | null | undefined;
29
+ readonly emailVerified: boolean | undefined;
30
+ readonly claims: UserClaims;
31
+ readonly data: UserData | null;
32
+ constructor();
33
+ static getInstance(): FirekitUser;
34
+ private loadUserData;
35
+ private loadUserClaims;
36
+ get user(): User | null | undefined;
37
+ updateEmail(email: string): Promise<void>;
38
+ updatePassword(password: string): Promise<void>;
39
+ updateProfile({ displayName, photoURL }: {
40
+ displayName?: string;
41
+ photoURL?: string;
42
+ }): Promise<void>;
43
+ updateUserData(data: Partial<UserData>): Promise<void>;
44
+ saveUserData(data: UserData): Promise<void>;
45
+ hasRequiredClaims(requiredClaims: string[]): boolean;
46
+ isAdmin(): boolean;
47
+ isPremium(): boolean;
48
+ }
49
+ export declare const firekitUser: FirekitUser;
50
+ export {};
@@ -0,0 +1,115 @@
1
+ import { firebaseService } from '../firebase.js';
2
+ import { onAuthStateChanged, updateCurrentUser, updateEmail, updatePassword } from "firebase/auth";
3
+ import { doc, getDoc, setDoc, updateDoc } from 'firebase/firestore';
4
+ export class FirekitUser {
5
+ static instance;
6
+ _user = $state();
7
+ _userData = $state(null);
8
+ _claims = $state({});
9
+ isLoggedIn = $derived(Boolean(this._user));
10
+ uid = $derived(this._user?.uid);
11
+ email = $derived(this._user?.email);
12
+ displayName = $derived(this._user?.displayName);
13
+ photoURL = $derived(this._user?.photoURL);
14
+ emailVerified = $derived(this._user?.emailVerified);
15
+ claims = $derived(this._claims);
16
+ data = $derived(this._userData);
17
+ constructor() {
18
+ onAuthStateChanged(firebaseService.getAuthInstance(), async (user) => {
19
+ this._user = user;
20
+ if (user) {
21
+ await Promise.all([
22
+ this.loadUserData(),
23
+ this.loadUserClaims()
24
+ ]);
25
+ }
26
+ else {
27
+ this._userData = null;
28
+ this._claims = {};
29
+ }
30
+ });
31
+ }
32
+ static getInstance() {
33
+ if (!FirekitUser.instance) {
34
+ FirekitUser.instance = new FirekitUser();
35
+ }
36
+ return FirekitUser.instance;
37
+ }
38
+ async loadUserData() {
39
+ if (!this._user?.uid)
40
+ return;
41
+ const docRef = doc(firebaseService.getDb(), 'users', this._user.uid);
42
+ const docSnap = await getDoc(docRef);
43
+ if (docSnap.exists()) {
44
+ this._userData = docSnap.data();
45
+ }
46
+ else {
47
+ // Initialize user document if it doesn't exist
48
+ const initialData = {
49
+ displayName: this._user.displayName || '',
50
+ email: this._user.email || '',
51
+ photoURL: this._user.photoURL || '',
52
+ createdAt: new Date(),
53
+ updatedAt: new Date(),
54
+ isProfileComplete: false
55
+ };
56
+ await this.saveUserData(initialData);
57
+ }
58
+ }
59
+ async loadUserClaims() {
60
+ if (!this._user)
61
+ return;
62
+ const tokenResult = await this._user.getIdTokenResult();
63
+ this._claims = tokenResult.claims;
64
+ }
65
+ get user() {
66
+ return this._user;
67
+ }
68
+ async updateEmail(email) {
69
+ if (!this._user)
70
+ throw new Error('No authenticated user');
71
+ await updateEmail(this._user, email);
72
+ }
73
+ async updatePassword(password) {
74
+ if (!this._user)
75
+ throw new Error('No authenticated user');
76
+ await updatePassword(this._user, password);
77
+ }
78
+ async updateProfile({ displayName, photoURL }) {
79
+ if (!this._user)
80
+ throw new Error('No authenticated user');
81
+ }
82
+ async updateUserData(data) {
83
+ if (!this._user?.uid)
84
+ throw new Error('No authenticated user');
85
+ const docRef = doc(firebaseService.getDb(), 'users', this._user.uid);
86
+ const updateData = {
87
+ ...data,
88
+ updatedAt: new Date()
89
+ };
90
+ await updateDoc(docRef, updateData);
91
+ await this.loadUserData(); // Reload user data
92
+ }
93
+ async saveUserData(data) {
94
+ if (!this._user?.uid)
95
+ throw new Error('No authenticated user');
96
+ const docRef = doc(firebaseService.getDb(), 'users', this._user.uid);
97
+ const saveData = {
98
+ ...data,
99
+ createdAt: data.createdAt || new Date(),
100
+ updatedAt: new Date()
101
+ };
102
+ await setDoc(docRef, saveData);
103
+ await this.loadUserData(); // Reload user data
104
+ }
105
+ hasRequiredClaims(requiredClaims) {
106
+ return requiredClaims.every(claim => this._claims[claim]);
107
+ }
108
+ isAdmin() {
109
+ return Boolean(this._claims.admin);
110
+ }
111
+ isPremium() {
112
+ return Boolean(this._claims.premium);
113
+ }
114
+ }
115
+ export const firekitUser = new FirekitUser();
@@ -0,0 +1,44 @@
1
+ import { PUBLIC_FIREBASE_API_KEY, PUBLIC_FIREBASE_AUTH_DOMAIN, PUBLIC_FIREBASE_PROJECT_ID, PUBLIC_FIREBASE_STORAGE_BUCKET, PUBLIC_FIREBASE_MESSAGING_SENDER_ID, PUBLIC_FIREBASE_APP_ID, PUBLIC_FIREBASE_MEASUREMENT_ID } from '$env/static/public';
2
+ class FirebaseConfig {
3
+ static instance;
4
+ config;
5
+ constructor() {
6
+ const missingVars = this.getMissingFirebaseConfigVars();
7
+ if (missingVars.length > 0) {
8
+ throw Error(`The following Firebase configuration variables are missing: ${missingVars.join(', ')}`);
9
+ }
10
+ this.config = {
11
+ apiKey: PUBLIC_FIREBASE_API_KEY,
12
+ authDomain: PUBLIC_FIREBASE_AUTH_DOMAIN,
13
+ projectId: PUBLIC_FIREBASE_PROJECT_ID,
14
+ storageBucket: PUBLIC_FIREBASE_STORAGE_BUCKET,
15
+ messagingSenderId: PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
16
+ appId: PUBLIC_FIREBASE_APP_ID,
17
+ measurementId: PUBLIC_FIREBASE_MEASUREMENT_ID
18
+ };
19
+ }
20
+ getMissingFirebaseConfigVars() {
21
+ const requiredVars = {
22
+ 'PUBLIC_FIREBASE_API_KEY': PUBLIC_FIREBASE_API_KEY,
23
+ 'PUBLIC_FIREBASE_AUTH_DOMAIN': PUBLIC_FIREBASE_AUTH_DOMAIN,
24
+ 'PUBLIC_FIREBASE_PROJECT_ID': PUBLIC_FIREBASE_PROJECT_ID,
25
+ 'PUBLIC_FIREBASE_STORAGE_BUCKET': PUBLIC_FIREBASE_STORAGE_BUCKET,
26
+ 'PUBLIC_FIREBASE_MESSAGING_SENDER_ID': PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
27
+ 'PUBLIC_FIREBASE_APP_ID': PUBLIC_FIREBASE_APP_ID,
28
+ 'PUBLIC_FIREBASE_MEASUREMENT_ID': PUBLIC_FIREBASE_MEASUREMENT_ID
29
+ };
30
+ return Object.entries(requiredVars)
31
+ .filter(([_, value]) => !value)
32
+ .map(([key]) => key);
33
+ }
34
+ static getInstance() {
35
+ if (!FirebaseConfig.instance) {
36
+ FirebaseConfig.instance = new FirebaseConfig();
37
+ }
38
+ return FirebaseConfig.instance;
39
+ }
40
+ getConfig() {
41
+ return this.config;
42
+ }
43
+ }
44
+ export const firebaseConfig = FirebaseConfig.getInstance().getConfig();
@@ -0,0 +1,28 @@
1
+ import { type FirebaseApp } from 'firebase/app';
2
+ import { type Firestore } from 'firebase/firestore';
3
+ import { type Auth } from 'firebase/auth';
4
+ import { type Functions } from 'firebase/functions';
5
+ import { type Database } from 'firebase/database';
6
+ import { type FirebaseStorage } from 'firebase/storage';
7
+ declare class FirebaseService {
8
+ private static instance;
9
+ private firebaseApp;
10
+ private db;
11
+ private auth;
12
+ private functions;
13
+ private database;
14
+ private storage;
15
+ private readonly isBrowser;
16
+ private constructor();
17
+ static getInstance(): FirebaseService;
18
+ getFirebaseApp(): FirebaseApp;
19
+ private initializeFirestoreInstance;
20
+ getDb(): Firestore;
21
+ getAuthInstance(): Auth;
22
+ getFunctionsInstance(): Functions;
23
+ getDatabaseInstance(): Database;
24
+ getStorageInstance(): FirebaseStorage;
25
+ getBatch(): import("@firebase/firestore").WriteBatch;
26
+ }
27
+ export declare const firebaseService: FirebaseService;
28
+ export {};
@@ -0,0 +1,86 @@
1
+ import { initializeApp, getApps } from 'firebase/app';
2
+ import { initializeFirestore, CACHE_SIZE_UNLIMITED, persistentLocalCache, persistentMultipleTabManager, enablePersistentCacheIndexAutoCreation, getPersistentCacheIndexManager, writeBatch } from 'firebase/firestore';
3
+ import { getAuth } from 'firebase/auth';
4
+ import { getFunctions } from 'firebase/functions';
5
+ import { getDatabase } from 'firebase/database';
6
+ import { getStorage } from 'firebase/storage';
7
+ import { firebaseConfig } from './config.js';
8
+ class FirebaseService {
9
+ static instance;
10
+ firebaseApp = null;
11
+ db = null;
12
+ auth = null;
13
+ functions = null;
14
+ database = null;
15
+ storage = null;
16
+ isBrowser = typeof window !== 'undefined';
17
+ constructor() {
18
+ }
19
+ static getInstance() {
20
+ if (!FirebaseService.instance) {
21
+ FirebaseService.instance = new FirebaseService();
22
+ }
23
+ return FirebaseService.instance;
24
+ }
25
+ getFirebaseApp() {
26
+ if (this.firebaseApp)
27
+ return this.firebaseApp;
28
+ const existingApps = getApps();
29
+ if (existingApps.length) {
30
+ this.firebaseApp = existingApps[0];
31
+ }
32
+ else {
33
+ this.firebaseApp = initializeApp(firebaseConfig);
34
+ console.log(`${firebaseConfig.projectId} initialized on ${this.isBrowser ? 'client' : 'server'}`);
35
+ }
36
+ this.initializeFirestoreInstance();
37
+ return this.firebaseApp;
38
+ }
39
+ initializeFirestoreInstance() {
40
+ if (this.db || !this.isBrowser)
41
+ return;
42
+ this.db = initializeFirestore(this.firebaseApp, {
43
+ localCache: persistentLocalCache({
44
+ cacheSizeBytes: CACHE_SIZE_UNLIMITED,
45
+ tabManager: persistentMultipleTabManager()
46
+ }),
47
+ });
48
+ const indexManager = getPersistentCacheIndexManager(this.db);
49
+ if (indexManager) {
50
+ enablePersistentCacheIndexAutoCreation(indexManager);
51
+ console.log('Firestore persistent cache indexing is enabled');
52
+ }
53
+ else {
54
+ console.warn('Failed to initialize the Firestore cache index manager');
55
+ }
56
+ }
57
+ getDb() {
58
+ if (!this.db)
59
+ this.getFirebaseApp();
60
+ return this.db;
61
+ }
62
+ getAuthInstance() {
63
+ if (!this.auth)
64
+ this.auth = getAuth(this.getFirebaseApp());
65
+ return this.auth;
66
+ }
67
+ getFunctionsInstance() {
68
+ if (!this.functions)
69
+ this.functions = getFunctions(this.getFirebaseApp());
70
+ return this.functions;
71
+ }
72
+ getDatabaseInstance() {
73
+ if (!this.database)
74
+ this.database = getDatabase(this.getFirebaseApp());
75
+ return this.database;
76
+ }
77
+ getStorageInstance() {
78
+ if (!this.storage)
79
+ this.storage = getStorage(this.getFirebaseApp());
80
+ return this.storage;
81
+ }
82
+ getBatch() {
83
+ return writeBatch(this.getDb());
84
+ }
85
+ }
86
+ export const firebaseService = FirebaseService.getInstance();
@@ -0,0 +1,15 @@
1
+ import { type DocumentReference, type DocumentData } from "firebase/firestore";
2
+ declare class FirekitAwaitableDoc<T> {
3
+ private _data;
4
+ private _loading;
5
+ private _error;
6
+ private docRef;
7
+ constructor(ref: string | DocumentReference<T>, startWith?: T);
8
+ private initializeDoc;
9
+ getData(): Promise<T | null>;
10
+ get data(): T | null;
11
+ get loading(): boolean;
12
+ get error(): Error | null;
13
+ }
14
+ export declare function firekitAwaitableDoc<T extends DocumentData>(path: string, startWith?: T): FirekitAwaitableDoc<T>;
15
+ export {};
@@ -0,0 +1,57 @@
1
+ import { doc, getDoc, onSnapshot } from "firebase/firestore";
2
+ import { firebaseService } from "../firebase.js";
3
+ import { browser } from "$app/environment";
4
+ class FirekitAwaitableDoc {
5
+ _data = $state(null);
6
+ _loading = $state(true);
7
+ _error = $state(null);
8
+ docRef = null;
9
+ constructor(ref, startWith) {
10
+ this._data = startWith ?? null;
11
+ if (browser) {
12
+ this.initializeDoc(ref);
13
+ }
14
+ }
15
+ async initializeDoc(ref) {
16
+ try {
17
+ const firestore = firebaseService.getDb();
18
+ this.docRef = typeof ref === "string"
19
+ ? doc(firestore, ref)
20
+ : ref;
21
+ // Initial fetch
22
+ const snapshot = await getDoc(this.docRef);
23
+ this._data = snapshot.exists() ? { id: snapshot.id, ...snapshot.data() } : null;
24
+ // Setup real-time updates
25
+ onSnapshot(this.docRef, (snapshot) => {
26
+ this._data = snapshot.exists() ? { id: snapshot.id, ...snapshot.data() } : null;
27
+ this._loading = false;
28
+ this._error = null;
29
+ }, (error) => {
30
+ this._error = error;
31
+ this._loading = false;
32
+ });
33
+ }
34
+ catch (error) {
35
+ this._error = error;
36
+ this._loading = false;
37
+ }
38
+ }
39
+ async getData() {
40
+ if (!this.docRef)
41
+ return null;
42
+ const snapshot = await getDoc(this.docRef);
43
+ return snapshot.exists() ? { id: snapshot.id, ...snapshot.data() } : null;
44
+ }
45
+ get data() {
46
+ return this._data;
47
+ }
48
+ get loading() {
49
+ return this._loading;
50
+ }
51
+ get error() {
52
+ return this._error;
53
+ }
54
+ }
55
+ export function firekitAwaitableDoc(path, startWith) {
56
+ return new FirekitAwaitableDoc(path, startWith);
57
+ }
@@ -0,0 +1,17 @@
1
+ import { type CollectionReference, type DocumentData, type QueryConstraint } from "firebase/firestore";
2
+ declare class FirekitCollection<T> {
3
+ private _data;
4
+ private _loading;
5
+ private _error;
6
+ private colRef;
7
+ private queryRef;
8
+ constructor(path: string, ...queryConstraints: QueryConstraint[]);
9
+ get data(): T[];
10
+ get loading(): boolean;
11
+ get error(): Error | null;
12
+ get empty(): boolean;
13
+ get size(): number;
14
+ get ref(): CollectionReference<T, DocumentData>;
15
+ }
16
+ export declare function firekitCollection<T extends DocumentData>(path: string, ...queryConstraints: QueryConstraint[]): FirekitCollection<T>;
17
+ export {};
@@ -0,0 +1,58 @@
1
+ import { collection, query, onSnapshot } from "firebase/firestore";
2
+ import { firebaseService } from "../firebase.js";
3
+ import { browser } from "$app/environment";
4
+ class FirekitCollection {
5
+ _data = $state([]);
6
+ _loading = $state(true);
7
+ _error = $state(null);
8
+ colRef = null;
9
+ queryRef = null;
10
+ constructor(path, ...queryConstraints) {
11
+ if (browser) {
12
+ try {
13
+ const firestore = firebaseService.getDb();
14
+ this.colRef = collection(firestore, path);
15
+ this.queryRef = query(this.colRef, ...queryConstraints);
16
+ onSnapshot(this.queryRef, (snapshot) => {
17
+ this._data = snapshot.docs.map(doc => ({
18
+ id: doc.id,
19
+ ...doc.data()
20
+ }));
21
+ this._loading = false;
22
+ this._error = null;
23
+ }, (error) => {
24
+ this._error = error;
25
+ this._loading = false;
26
+ });
27
+ }
28
+ catch (error) {
29
+ this._error = error;
30
+ this._loading = false;
31
+ }
32
+ }
33
+ }
34
+ get data() {
35
+ return this._data;
36
+ }
37
+ get loading() {
38
+ return this._loading;
39
+ }
40
+ get error() {
41
+ return this._error;
42
+ }
43
+ get empty() {
44
+ return this._data.length === 0;
45
+ }
46
+ get size() {
47
+ return this._data.length;
48
+ }
49
+ get ref() {
50
+ if (!this.colRef) {
51
+ throw new Error("Collection reference is not available");
52
+ }
53
+ return this.colRef;
54
+ }
55
+ }
56
+ export function firekitCollection(path, ...queryConstraints) {
57
+ return new FirekitCollection(path, ...queryConstraints);
58
+ }
@@ -0,0 +1,16 @@
1
+ import { DocumentReference } from "firebase/firestore";
2
+ declare class FirekitDoc<T> {
3
+ private _data;
4
+ private _loading;
5
+ private _error;
6
+ private docRef;
7
+ constructor(ref: string | DocumentReference<T>, startWith?: T);
8
+ get data(): T | null;
9
+ get id(): string;
10
+ get loading(): boolean;
11
+ get error(): Error | null;
12
+ get ref(): DocumentReference<T, import("@firebase/firestore").DocumentData>;
13
+ get exists(): boolean;
14
+ }
15
+ export declare function firekitDoc<T>(ref: string | DocumentReference<T>, startWith?: T): FirekitDoc<T>;
16
+ export {};
@@ -0,0 +1,56 @@
1
+ import { doc, DocumentReference, onSnapshot } from "firebase/firestore";
2
+ import { firebaseService } from "../firebase.js";
3
+ import { browser } from "$app/environment";
4
+ class FirekitDoc {
5
+ _data = $state(null);
6
+ _loading = $state(true);
7
+ _error = $state(null);
8
+ docRef = null;
9
+ constructor(ref, startWith) {
10
+ this._data = startWith ?? null;
11
+ if (browser) {
12
+ try {
13
+ const firestore = firebaseService.getDb();
14
+ this.docRef = typeof ref === "string"
15
+ ? doc(firestore, ref)
16
+ : ref;
17
+ onSnapshot(this.docRef, (snapshot) => {
18
+ this._data = snapshot.data() ?? null;
19
+ this._loading = false;
20
+ this._error = null;
21
+ }, (error) => {
22
+ this._error = error;
23
+ this._loading = false;
24
+ });
25
+ }
26
+ catch (error) {
27
+ this._error = error;
28
+ this._loading = false;
29
+ }
30
+ }
31
+ }
32
+ get data() {
33
+ return this._data;
34
+ }
35
+ get id() {
36
+ return this.docRef?.id ?? '';
37
+ }
38
+ get loading() {
39
+ return this._loading;
40
+ }
41
+ get error() {
42
+ return this._error;
43
+ }
44
+ get ref() {
45
+ if (this.docRef === null) {
46
+ throw new Error("Document reference is not available yet.");
47
+ }
48
+ return this.docRef;
49
+ }
50
+ get exists() {
51
+ return this._data !== null;
52
+ }
53
+ }
54
+ export function firekitDoc(ref, startWith) {
55
+ return new FirekitDoc(ref, startWith);
56
+ }
@@ -0,0 +1,18 @@
1
+ import { type DocumentData, type WithFieldValue, type PartialWithFieldValue } from "firebase/firestore";
2
+ declare class FirekitDocumentMutations {
3
+ constructor();
4
+ add<T extends DocumentData>(collectionPath: string, data: WithFieldValue<T>, options?: {
5
+ timestamps?: boolean;
6
+ }): Promise<import("@firebase/firestore").DocumentReference<DocumentData, DocumentData>>;
7
+ set<T extends DocumentData>(path: string, data: WithFieldValue<T>, options?: {
8
+ merge?: boolean;
9
+ timestamps?: boolean;
10
+ }): Promise<void>;
11
+ update<T extends DocumentData>(path: string, data: PartialWithFieldValue<T>, options?: {
12
+ timestamps?: boolean;
13
+ }): Promise<void>;
14
+ delete(path: string): Promise<void>;
15
+ exists(path: string): Promise<boolean>;
16
+ }
17
+ export declare const firekitDocMutations: FirekitDocumentMutations;
18
+ export {};