@edgedev/firebase 2.1.61 → 2.1.63

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.
package/edgeFirebase.ts CHANGED
@@ -606,9 +606,34 @@ export const EdgeFirebase = class {
606
606
  const userRef = doc(this.db, "staged-users", userRegister.registrationCode);
607
607
  userSnap = await getDoc(userRef);
608
608
  } catch (error) {
609
+ let errorMessage = error.message
610
+
611
+ switch (error.code) {
612
+ case 'permission-denied':
613
+ errorMessage = "This registration code is no longer valid or has already been used."
614
+ break
615
+ case 'unavailable':
616
+ errorMessage = "Your device or browser could not connect to the registration service. Please check your internet connection or try again using a different browser."
617
+ break
618
+ case 'not-found':
619
+ errorMessage = "This registration code does not exist. Please check for typos or contact support."
620
+ break
621
+ case 'deadline-exceeded':
622
+ errorMessage = "The request timed out. Please try again in a moment, or check your connection."
623
+ break
624
+ case 'internal':
625
+ errorMessage = "Something went wrong in your browser that prevented the registration from completing. Try refreshing or switching browsers."
626
+ break
627
+ case 'resource-exhausted':
628
+ errorMessage = "Too many requests from this device. Please wait a few minutes and try again."
629
+ break
630
+ case 'failed-precondition':
631
+ errorMessage = "Your browser is not supported or is blocking key features required for registration. Try updating or switching browsers."
632
+ break
633
+ }
609
634
  return this.sendResponse({
610
635
  success: false,
611
- message: "Registration code already used.",
636
+ message: errorMessage,
612
637
  meta: {}
613
638
  });
614
639
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgedev/firebase",
3
- "version": "2.1.61",
3
+ "version": "2.1.63",
4
4
  "description": "Vue 3 / Nuxt 3 Plugin or Nuxt 3 plugin for firebase authentication and firestore.",
5
5
  "main": "index.ts",
6
6
  "scripts": {
@@ -78,10 +78,14 @@ exports.fileDeleted = onObjectDeleted({ region: process.env.FIREBASE_STORAGE_BUC
78
78
  const docId = event.data.metadata?.fileDocId
79
79
  const toR2 = event.data.metadata?.toR2
80
80
  const cloudflareImageId = event.data.metadata?.cloudflareImageId
81
+ const cloudflareVideoId = event.data.metadata?.cloudflareVideoId
81
82
  const r2ProcessCompleted = event.data.metadata?.r2ProcessCompleted
82
83
  if (cloudflareImageId) {
83
84
  await deleteCloudflareImage(cloudflareImageId)
84
85
  }
86
+ if (cloudflareVideoId) {
87
+ await deleteCloudflareVideo(cloudflareVideoId)
88
+ }
85
89
  if (toR2) {
86
90
  if (r2ProcessCompleted === 'true') {
87
91
  await deleteR2File(event.data.metadata?.r2FilePath)
@@ -174,7 +178,7 @@ exports.toR2 = onObjectFinalized(
174
178
  r2ProcessCompleted: 'true',
175
179
  },
176
180
  }
177
- if (contentType.startsWith('image/')) {
181
+ if (contentType.startsWith('image/') && process.env.CF_IMAGES_TOKEN) {
178
182
  try {
179
183
  const cloudflareImage = await uploadToCloudflareImage({
180
184
  r2FilePath,
@@ -184,7 +188,6 @@ exports.toR2 = onObjectFinalized(
184
188
  fileName,
185
189
  fileSize,
186
190
  })
187
- console.log(cloudflareImage)
188
191
 
189
192
  updatedMetadata = {
190
193
  metadata: {
@@ -205,6 +208,37 @@ exports.toR2 = onObjectFinalized(
205
208
  }
206
209
  }
207
210
 
211
+ if (contentType.startsWith('video/') && process.env.CF_IMAGES_TOKEN) {
212
+ try {
213
+ const cloudflareVideo = await uploadToCloudflareVideo({
214
+ r2FilePath,
215
+ r2URL,
216
+ fileDocId,
217
+ orgId,
218
+ fileName,
219
+ fileSize,
220
+ })
221
+ console.log(cloudflareVideo)
222
+ updatedMetadata = {
223
+ metadata: {
224
+ ...event.data.metadata,
225
+ r2FilePath,
226
+ r2URL,
227
+ uploadCompletedToR2: 'true', // Add custom metadata after file save
228
+ r2ProcessCompleted: 'true',
229
+ cloudflareVideoId: cloudflareVideo.id,
230
+ cloudflareVideoPlayback: cloudflareVideo.playback,
231
+ cloudflareVideoThumbnail: cloudflareVideo.thumbnail,
232
+ cloudflareVideoPreview: cloudflareVideo.preview,
233
+ cloudflareUploadCompleted: true,
234
+ },
235
+ }
236
+ await docRef.set({ cloudflareVideoId: cloudflareVideo.id, cloudflareVideoPlayback: cloudflareVideo.playback, cloudflareVideoThumbnail: cloudflareVideo.thumbnail, cloudflareVideoPreview: cloudflareVideo.preview, cloudflareUploadCompleted: true }, { merge: true })
237
+ }
238
+ catch (e) {
239
+ console.error('Cloudflare Video Upload Failed', e)
240
+ }
241
+ }
208
242
  await fileRef.setMetadata(updatedMetadata)
209
243
  console.log(`File uploaded to Cloudflare R2: ${fileName}`)
210
244
  }
@@ -699,3 +733,79 @@ async function deleteCloudflareImage(imageId) {
699
733
 
700
734
  return true
701
735
  }
736
+
737
+ async function uploadToCloudflareVideo({ r2FilePath, r2URL, fileDocId, orgId, fileSize }) {
738
+ const API_TOKEN = process.env.CF_IMAGES_TOKEN
739
+ const ACCOUNT_ID = process.env.CF_ACCOUNT_ID
740
+
741
+ const cleanedr2FilePath = r2FilePath
742
+ .replaceAll('/', '-')
743
+ .replace('.firebasestorage.app-organizations', '')
744
+
745
+ const metadata = {
746
+ orgId,
747
+ fileDocId,
748
+ fileName: cleanedr2FilePath,
749
+ fileSize,
750
+ }
751
+
752
+ const body = {
753
+ url: r2URL,
754
+ meta: {
755
+ name: cleanedr2FilePath,
756
+ ...metadata,
757
+ },
758
+ allowDownloads: true,
759
+ }
760
+
761
+ const response = await fetch(
762
+ `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/stream/copy`,
763
+ {
764
+ method: 'POST',
765
+ headers: {
766
+ 'Authorization': `Bearer ${API_TOKEN}`,
767
+ 'Content-Type': 'application/json',
768
+ },
769
+ body: JSON.stringify(body),
770
+ },
771
+ )
772
+
773
+ const result = await response.json()
774
+
775
+ if (!result.success) {
776
+ const errorMessages = (result.errors || [])
777
+ .map(error => error.message || 'Unknown error')
778
+ .join('; ')
779
+ throw new Error(`Cloudflare Stream upload failed: ${errorMessages}`)
780
+ }
781
+ console.log(result.result)
782
+ const { uid, preview, playback, thumbnail } = result.result
783
+
784
+ return {
785
+ id: uid,
786
+ preview,
787
+ playback,
788
+ thumbnail,
789
+ }
790
+ }
791
+
792
+ async function deleteCloudflareVideo(videoId) {
793
+ const API_TOKEN = process.env.CF_IMAGES_TOKEN
794
+ const ACCOUNT_ID = process.env.CF_ACCOUNT_ID
795
+
796
+ const response = await fetch(
797
+ `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/stream/${videoId}`,
798
+ {
799
+ method: 'DELETE',
800
+ headers: {
801
+ Authorization: `Bearer ${API_TOKEN}`,
802
+ },
803
+ },
804
+ )
805
+
806
+ if (!response.ok) {
807
+ throw new Error(`Failed to delete Cloudflare video: ${response.statusText}`)
808
+ }
809
+
810
+ return true
811
+ }