import { Readable } from 'stream' import { Injectable, OnModuleInit } from '@nestjs/common' import { debug, Debugger } from 'debug' import { storage } from 'firebase-admin' import { nanoid } from 'nanoid' import { Firebender } from '../firebender' @Injectable() export class StorageService implements OnModuleInit { private debug: Debugger = debug(`http:${this.constructor.name}`) private firebender: Firebender onModuleInit(): void { this.firebender = new Firebender() } async upload(filePath: string, file: Buffer, contentType: string): Promise { const bucketFile = storage(this.firebender.firebaseAdmin) .bucket() .file(filePath) return new Promise((resolve, reject) => { this.getStreamFromBuffer(file) .pipe(bucketFile.createWriteStream({ contentType })) .on('error', err => reject(err)) .on('finish', async () => { await bucketFile.makePublic() resolve(bucketFile.publicUrl()) }) }) } async getFile(filePath: string): Promise { const id = nanoid() this.debug.extend('request')(JSON.stringify({ id, type: 'get_file', body: { filePath } })) const [file] = await storage(this.firebender.firebaseAdmin) .bucket() .file(filePath) .download() this.debug.extend('response')(JSON.stringify({ id, type: 'get_file', response: 'ok' })) return file } async moveFile(fromPath: string, toPath: string): Promise { const id = nanoid() this.debug.extend('request')(JSON.stringify({ id, type: 'move_file', body: { fromPath, toPath } })) await storage(this.firebender.firebaseAdmin) .bucket() .file(fromPath) .move(toPath) this.debug.extend('response')(JSON.stringify({ id, type: 'get_file', response: 'ok' })) } private getStreamFromBuffer(buffer: Buffer): Readable { const stream = new Readable() stream.push(buffer) stream.push(null) return stream } }