import { arrayRemove , arrayUnion , collection , deleteDoc , doc , getDoc , getFirestore , setDoc , updateDoc , } from "firebase/firestore/lite" ; import { deleteObject , getDownloadURL , getStorage , ref , uploadBytes } from "firebase/storage" ; import { FileInfo } from "../util/file-info" ; import FirebaseService from "./firebase" ; namespace FileService { param { File } file returns { string } export async function upload ( file ) { const uploadDate = new Date ( ) , uid = FirebaseService . userId$ . value , firestore = getFirestore ( ) ; async function generateWordCode ( ) { const { phrase } = await fetch ( "https://words-aas.vercel.app/api/a $adjective $noun" ) . then ( async ( v ) => v . json ( ) ) ; return ( await getDoc ( doc ( collection ( firestore , "files" ) , phrase ) ) ) . exists ( ) ? await generateWordCode ( ) : phrase ; } const wordCode = await generateWordCode ( ) ; await setDoc ( doc ( collection ( firestore , "files" ) , wordCode ) , { name : file . name , filetype : file . type , uploadDate , owner : uid , } as FileInfo ) ; await uploadBytes ( ref ( getStorage ( ) , `${ wordCode }/${ file . name }` ) , file ) ; await updateDoc ( doc ( collection ( firestore , "users" ) , uid ) , { files : arrayUnion ( wordCode ) , } ) ; return wordCode ; } param { string } wordCode param { string } filename export async function download ( wordCode , filename ) { const url = await getDownloadURL ( ref ( getStorage ( ) , `${ wordCode }/${ filename }` ) ) ; const file = await fetch ( url ) . then ( f => f . blob ( ) ) ; const a = document . createElement ( "a" ) ; a . href = window . URL . createObjectURL ( file ) ; a . download = filename ; document . body . appendChild ( a ) ; a . click ( ) ; window . URL . revokeObjectURL ( url ) ; a . remove ( ) ; } param { string } wordCode export async function doesExist ( wordCode ) { return await getDoc ( doc ( collection ( getFirestore ( ) , "files" ) , wordCode ) ) . then ( v => v . exists ( ) ) ; } /**
     * Get info of file.
     *
     * - Loads file data
     * - Throws an error if the file data doesn't exist.
     * - Transforms Firebase Timestamp datatype into native JavasSript  Date .
     * - Returns file data.
     *
     *  param { string } wordCode returns { FileInfo } export async function getInfo ( wordCode ) { let fileData = await getDoc ( doc ( collection ( getFirestore ( ) , "files" ) , wordCode ) ) . then ( v => v . data ( ) ) ; if ( ! fileData ) throw Error ( "Could not retrieve file metadata" ) ; fileData . uploadDate = ( fileData . uploadDate as import ( "@firebase/firestore" ) . Timestamp ) . toDate ( ) ; return fileData as FileInfo ; } param { string } wordCode param { string } filename export async function remove ( wordCode , filename ) { await deleteObject ( ref ( getStorage ( ) , `${ wordCode }/${ filename }` ) ) ; await updateDoc ( doc ( collection ( getFirestore ( ) , "users" ) , FirebaseService . userId$ . value ) , { files : arrayRemove ( wordCode ) , } ) ; await deleteDoc ( doc ( collection ( getFirestore ( ) , "files" ) , wordCode ) ) ; } } export default FileService ;