svelte-firekit 0.2.4 → 0.2.5

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.
@@ -210,7 +210,19 @@ export class FirekitChat {
210
210
  // Seed history from initialHistory
211
211
  for (const turn of initialHistory) {
212
212
  const text = turn.parts
213
- .map((p) => ('text' in p ? p.text : ''))
213
+ .map((p) => {
214
+ if ('text' in p)
215
+ return p.text;
216
+ if ('inlineData' in p)
217
+ return '[image]';
218
+ if ('fileData' in p)
219
+ return '[file]';
220
+ if ('functionCall' in p)
221
+ return `[function: ${p.functionCall.name}]`;
222
+ if ('functionResponse' in p)
223
+ return `[function response: ${p.functionResponse.name}]`;
224
+ return '[unknown part]';
225
+ })
214
226
  .filter(Boolean)
215
227
  .join('');
216
228
  this._history.push({
@@ -41,7 +41,11 @@ class FirekitAnalytics {
41
41
  if (!supported)
42
42
  return;
43
43
  this._analytics = getAnalytics(getApp());
44
- })();
44
+ })().catch((err) => {
45
+ // Reset so next call retries instead of returning a rejected promise forever
46
+ this._initPromise = null;
47
+ throw err;
48
+ });
45
49
  return this._initPromise;
46
50
  }
47
51
  async _get() {
@@ -18,8 +18,8 @@ declare class FirekitAuth {
18
18
  private recaptchaVerifiers;
19
19
  private constructor();
20
20
  static getInstance(): FirekitAuth;
21
- private bootstrap;
22
21
  private getAuth;
22
+ private getFirestore;
23
23
  private syncToFirestore;
24
24
  private profile;
25
25
  signInWithEmail(email: string, password: string): Promise<SignInResult>;
@@ -20,9 +20,8 @@ class FirekitAuth {
20
20
  firestore = null;
21
21
  recaptchaVerifiers = new Map();
22
22
  constructor() {
23
- if (typeof window !== 'undefined') {
24
- this.bootstrap();
25
- }
23
+ // Do NOT bootstrap here — Firebase config may not be set yet.
24
+ // Auth and Firestore instances are resolved lazily via getAuth() / getFirestore().
26
25
  }
27
26
  static getInstance() {
28
27
  if (!FirekitAuth.instance) {
@@ -30,20 +29,6 @@ class FirekitAuth {
30
29
  }
31
30
  return FirekitAuth.instance;
32
31
  }
33
- bootstrap() {
34
- try {
35
- this.auth = firebaseService.getAuthInstance();
36
- try {
37
- this.firestore = firebaseService.getDbInstance();
38
- }
39
- catch {
40
- this.firestore = null;
41
- }
42
- }
43
- catch {
44
- // Firebase not yet configured — services will be accessed lazily
45
- }
46
- }
47
32
  getAuth() {
48
33
  if (!this.auth) {
49
34
  this.auth = firebaseService.getAuthInstance();
@@ -53,10 +38,22 @@ class FirekitAuth {
53
38
  }
54
39
  return this.auth;
55
40
  }
41
+ getFirestore() {
42
+ if (!this.firestore) {
43
+ try {
44
+ this.firestore = firebaseService.getDbInstance();
45
+ }
46
+ catch {
47
+ this.firestore = null;
48
+ }
49
+ }
50
+ return this.firestore;
51
+ }
56
52
  async syncToFirestore(user) {
57
- if (!this.firestore)
53
+ const fs = this.getFirestore();
54
+ if (!fs)
58
55
  return;
59
- await updateUserInFirestore(this.firestore, user);
56
+ await updateUserInFirestore(fs, user);
60
57
  }
61
58
  profile(user) {
62
59
  return mapFirebaseUserToProfile(user);
@@ -327,9 +324,10 @@ class FirekitAuth {
327
324
  if (currentPassword)
328
325
  await this.reauthenticate(currentPassword);
329
326
  // Soft-delete record in Firestore before removing auth
330
- if (this.firestore) {
327
+ const fs = this.getFirestore();
328
+ if (fs) {
331
329
  try {
332
- await setDoc(doc(this.firestore, 'users', user.uid), { deleted: true, deletedAt: serverTimestamp() }, { merge: true });
330
+ await setDoc(doc(fs, 'users', user.uid), { deleted: true, deletedAt: serverTimestamp() }, { merge: true });
333
331
  }
334
332
  catch {
335
333
  // Non-blocking
@@ -560,16 +558,22 @@ class FirekitAuth {
560
558
  }
561
559
  // ─── Utility getters ─────────────────────────────────────────────────────────
562
560
  getCurrentUser() {
563
- return this.auth?.currentUser ?? null;
561
+ try {
562
+ return this.getAuth().currentUser;
563
+ }
564
+ catch {
565
+ return null;
566
+ }
564
567
  }
565
568
  isAuthenticated() {
566
- return this.auth?.currentUser !== null && !this.auth?.currentUser?.isAnonymous;
569
+ const user = this.getCurrentUser();
570
+ return user !== null && !user.isAnonymous;
567
571
  }
568
572
  isAnonymous() {
569
- return this.auth?.currentUser?.isAnonymous ?? false;
573
+ return this.getCurrentUser()?.isAnonymous ?? false;
570
574
  }
571
575
  isEmailVerified() {
572
- return this.auth?.currentUser?.emailVerified ?? false;
576
+ return this.getCurrentUser()?.emailVerified ?? false;
573
577
  }
574
578
  async cleanup() {
575
579
  this.recaptchaVerifiers.forEach((v) => v.clear());
@@ -33,6 +33,7 @@ declare class FirekitMessaging {
33
33
  private _messaging;
34
34
  private _unsubscribeMessage;
35
35
  private _requesting;
36
+ private _listening;
36
37
  private constructor();
37
38
  static getInstance(): FirekitMessaging;
38
39
  get token(): string | null;
@@ -40,6 +40,7 @@ class FirekitMessaging {
40
40
  _messaging = null;
41
41
  _unsubscribeMessage = null;
42
42
  _requesting = false;
43
+ _listening = false;
43
44
  constructor() {
44
45
  this._initPermissionState();
45
46
  }
@@ -161,7 +162,10 @@ class FirekitMessaging {
161
162
  }
162
163
  // ── Foreground messages ───────────────────────────────────────────────────
163
164
  _listenForMessages(msg) {
165
+ if (this._listening)
166
+ return;
164
167
  this._unsubscribeMessage?.();
168
+ this._listening = true;
165
169
  this._unsubscribeMessage = onMessage(msg, (payload) => {
166
170
  this._lastMessage = payload;
167
171
  this._messages = [...this._messages, payload];
@@ -185,6 +189,7 @@ class FirekitMessaging {
185
189
  dispose() {
186
190
  this._unsubscribeMessage?.();
187
191
  this._unsubscribeMessage = null;
192
+ this._listening = false;
188
193
  }
189
194
  }
190
195
  export const firekitMessaging = FirekitMessaging.getInstance();
@@ -46,7 +46,7 @@ async function withRetry(fn, retryConfig) {
46
46
  }
47
47
  }
48
48
  }
49
- throw lastError;
49
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
50
50
  }
51
51
  /**
52
52
  * Firestore document mutations — add, set, update, delete, batch, transaction.
@@ -23,6 +23,7 @@ declare class FirekitPresence {
23
23
  private _geo;
24
24
  private _connectedUnsub;
25
25
  private _currentUser;
26
+ private _visibilityListenerAdded;
26
27
  private constructor();
27
28
  static getInstance(): FirekitPresence;
28
29
  get initialized(): boolean;
@@ -174,9 +174,11 @@ class FirekitPresence {
174
174
  _geo = null;
175
175
  _connectedUnsub = null;
176
176
  _currentUser = null;
177
+ _visibilityListenerAdded = false;
177
178
  constructor() {
178
179
  if (typeof window !== 'undefined') {
179
180
  document.addEventListener('visibilitychange', this._onVisibilityChange);
181
+ this._visibilityListenerAdded = true;
180
182
  }
181
183
  }
182
184
  static getInstance() {
@@ -236,10 +238,15 @@ class FirekitPresence {
236
238
  if (!db)
237
239
  throw new PresenceError(PresenceErrorCode.DATABASE_ERROR, 'Realtime Database is not initialized.');
238
240
  const connectedRef = ref(db, '.info/connected');
239
- this._connectedUnsub = onValue(connectedRef, async (snap) => {
241
+ this._connectedUnsub = onValue(connectedRef, (snap) => {
240
242
  if (snap.val() === true) {
241
- await this.setPresence('online');
242
- await this._setupDisconnectHandler();
243
+ this.setPresence('online')
244
+ .then(() => this._setupDisconnectHandler())
245
+ .catch((err) => {
246
+ this._error = err instanceof PresenceError
247
+ ? err
248
+ : new PresenceError(PresenceErrorCode.DATABASE_ERROR, err.message, err);
249
+ });
243
250
  }
244
251
  else {
245
252
  this._status = 'offline';
@@ -377,8 +384,9 @@ class FirekitPresence {
377
384
  this._geo?.dispose();
378
385
  this._connectedUnsub?.();
379
386
  this._connectedUnsub = null;
380
- if (typeof document !== 'undefined') {
387
+ if (this._visibilityListenerAdded) {
381
388
  document.removeEventListener('visibilitychange', this._onVisibilityChange);
389
+ this._visibilityListenerAdded = false;
382
390
  }
383
391
  this._initialized = false;
384
392
  this._status = 'offline';
@@ -92,6 +92,9 @@ export class FirekitRemoteConfig {
92
92
  },
93
93
  error: (err) => {
94
94
  this._error = err instanceof Error ? err : new Error(String(err));
95
+ // Clean up the broken subscription so it doesn't keep firing errors
96
+ this._unsubscribe?.();
97
+ this._unsubscribe = null;
95
98
  },
96
99
  complete: () => { }
97
100
  });
@@ -197,6 +197,7 @@ export class FirekitUploadTask {
197
197
  if (this._storageRef) {
198
198
  this._downloadURL = await getDownloadURL(this._storageRef);
199
199
  }
200
+ this._error = null;
200
201
  this._state = 'success';
201
202
  this._progress = 100;
202
203
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-firekit",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "A Svelte library for Firebase integration",
5
5
  "license": "MIT",
6
6
  "author": "Giovani Rodriguez",