UNPKG

@paperbits/common

Version:
189 lines (154 loc) 6.27 kB
import * as Utils from "../utils"; import * as Constants from "./constants"; import { IObjectStorage, IBlobStorage, Query, Operator, Page } from "../persistence"; import { IMediaService, MediaContract } from "./"; import { Logger } from "../logging"; import { UserError } from "../errors"; export class MediaService implements IMediaService { constructor( private readonly objectStorage: IObjectStorage, private readonly blobStorage: IBlobStorage, private readonly logger: Logger ) { } public async getMediaByPermalink(permalink: string): Promise<MediaContract> { if (!permalink) { throw new Error(`Parameter "permalink" not specified.`); } const query = Query .from<MediaContract>() .where("permalink", Operator.equals, permalink); const pageOfObjects = await this.objectStorage.searchObjects<MediaContract>(Constants.mediaRoot, query); const result = pageOfObjects.value; const uploads = Object.values(result); return uploads.length > 0 ? uploads[0] : null; } public async getMediaByKey(key: string): Promise<MediaContract> { if (!key) { throw new Error(`Parameter "key" not specified.`); } const media = await this.objectStorage.getObject<MediaContract>(key); if (!media) { console.warn(`Media with key ${key} not found.`); return null; } if (media.blobKey) { const downloadUrl = await this.getDownloadUrlFromBlobKey(media.blobKey); media.downloadUrl = downloadUrl || media.downloadUrl; } return media; } private async getDownloadUrlFromBlobKey(blobKey: string): Promise<string> { try { return await this.blobStorage.getDownloadUrl(blobKey); } catch (error) { // TODO: Check for 404 } return undefined; } private async convertPage(pageOfMedia: Page<MediaContract>): Promise<Page<MediaContract>> { for (const media of pageOfMedia.value) { if (!media.blobKey) { continue; } media.downloadUrl = await this.getDownloadUrlFromBlobKey(media.blobKey); } const resultPage: Page<MediaContract> = { value: pageOfMedia.value, takeNext: async (): Promise<Page<MediaContract>> => { const nextPage = await pageOfMedia.takeNext(); return this.convertPage(nextPage); } }; if (!pageOfMedia.takeNext) { resultPage.takeNext = null; } return resultPage; } public async search(query: Query<MediaContract>): Promise<Page<MediaContract>> { if (!query) { throw new Error(`Parameter "query" not specified.`); } try { const pageOfResults = await this.objectStorage.searchObjects<MediaContract>(Constants.mediaRoot, query); const pageOfMedia = this.convertPage(pageOfResults); return pageOfMedia; } catch (error) { throw new Error(`Unable to search media: ${error.stack || error.message}`); } } public async deleteMedia(media: MediaContract): Promise<void> { if (!media) { throw new Error(`Parameter "media" not specified.`); } try { await this.objectStorage.deleteObject(media.key); await this.blobStorage.deleteBlob(media.blobKey); this.logger.trackEvent("MediaDeleted", { key: media.key }); } catch (error) { // TODO: Do proper handling. console.warn(error); } } public createMedia(name: string, content: Uint8Array, mimeType?: string): Promise<MediaContract> { const blobKey = Utils.guid(); const mediaKey = `${Constants.mediaRoot}/${blobKey}`; const media: MediaContract = { key: mediaKey, fileName: name, blobKey: blobKey, description: "", keywords: "", permalink: `/content/${name}`, mimeType: mimeType }; return this.uploadContent(content, media); } public async createMediaUrl(name: string, downloadUrl: string, mimeType?: string): Promise<MediaContract> { const blobKey = Utils.guid(); const mediaKey = `${Constants.mediaRoot}/${blobKey}`; const media: MediaContract = { key: mediaKey, fileName: name, blobKey: undefined, downloadUrl: downloadUrl, description: "", keywords: "", permalink: `/content/${name}`, mimeType: mimeType }; await this.updateMedia(media); return media; } private async uploadContent(content: Uint8Array, media: MediaContract): Promise<MediaContract> { await this.blobStorage.uploadBlob(media.blobKey, content, media.mimeType); await this.objectStorage.updateObject(media.key, media); this.logger.trackEvent("MediaAdded", { key: media.key }); return media; } public updateMedia(media: MediaContract): Promise<void> { if (!media) { throw new Error(`Parameter "media" not specified.`); } if (!!media.blobKey) { delete media.downloadUrl; // explicitly delete download URL when blob key specified. } if (media.variants) { media.variants.forEach(variant => { delete variant.downloadUrl; }); } return this.objectStorage.updateObject(media.key, media); } public updateMediaContent(media: MediaContract, content: Uint8Array): Promise<MediaContract> { if (!media) { throw new Error(`Parameter "media" not specified.`); } if (!content) { throw new Error(`Parameter "content" not specified.`); } return this.uploadContent(content, media); } }