UNPKG

scrivito

Version:

Scrivito is a professional, yet easy to use SaaS Enterprise Content Management Service, built for digital agencies and medium to large businesses. It is completely maintenance-free, cost-effective, and has unprecedented performance and security.

308 lines (248 loc) 7.15 kB
import isEmpty from 'lodash-es/isEmpty'; import isEqual from 'lodash-es/isEqual'; import { BackendBinaryData, ObjSpaceId, cmsRetrieval, } from 'scrivito_sdk/client'; import { ArgumentError, InternalError, ScrivitoError, equals, isBlob, isFile, throwInvalidArgumentsError, } from 'scrivito_sdk/common'; import { assertNotUsingInMemoryTenant } from 'scrivito_sdk/data'; import { LoadableData, createLoadableCollection } from 'scrivito_sdk/loadable'; import { publishedSpace } from 'scrivito_sdk/models'; import { FutureBinary } from 'scrivito_sdk/models/future_binary'; import { MetadataCollection } from 'scrivito_sdk/models/metadata_collection'; type CollectionKey = [string, TransformationDefinition | undefined]; const loadableCollection = createLoadableCollection({ name: 'binary', loadElement: ( [binaryId, transformation]: CollectionKey, objSpaceId: ObjSpaceId ) => ({ loader: () => cmsRetrieval.retrieveBinaryUrls(binaryId, transformation, { accessVia: objSpaceId, }), }), }); // this is a small, 1x1 pixel, fully transparent GIF image const PLACEHOLDER_URL = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; export interface TransformationDefinition { height?: number; width?: number; } interface BinaryUploadOptions { filename?: string; contentType?: string; } interface BinaryStoreOptions extends BinaryUploadOptions { transformation?: TransformationDefinition; } // For test purpose only. export function storeBinary( binaryId: string, options: BinaryStoreOptions, response: BackendBinaryData ): Binary { const transformation = options.transformation; loadableCollection.get([binaryId, transformation]).set(response); const raw = new Binary(binaryId, publishedSpace()).raw(); if (transformation) { return raw.optimizeFor(transformation); } return raw; } /** @public */ export class Binary { static upload( source: Blob | File, options?: BinaryUploadOptions ): FutureBinary; /** @internal */ static upload( source: Blob | File, options?: BinaryUploadOptions ): FutureBinary { checkUpload(source, options); if (!isFile(source)) { if (!(options && options.filename)) { throw new ArgumentError( 'Expected a filename to be passed with Blob as the source.' ); } } return new FutureBinary({ source }, options); } /** @internal */ private _transformation?: TransformationDefinition; /** @internal */ private _loadableData: LoadableData<BackendBinaryData>; /** @internal */ constructor( /** @internal */ private readonly _id: string, /** @internal */ private readonly _objSpaceId: ObjSpaceId = publishedSpace(), transformation: TransformationDefinition | null = {} ) { this._transformation = transformation || undefined; this._loadableData = loadableCollection.get( [this._id, this._transformation], this._objSpaceId ); } /** @internal */ id(): string { return this._id; } copy(options?: BinaryUploadOptions): FutureBinary { return new FutureBinary({ idToCopy: this._id }, options); } isPrivate(): boolean { return !equals(this._objSpaceId, publishedSpace()); } optimizeFor(transformation: TransformationDefinition): Binary { return new Binary(this._id, this._objSpaceId, { ...this._transformation, ...transformation, }); } original(): Binary { return new Binary(this._id, this._objSpaceId, {}); } raw(): Binary { return new Binary(this._id, this._objSpaceId, null); } /** @internal */ isExplicitlyTransformed(): boolean { return this.isTransformed() && !isEmpty(this._transformation); } /** @internal */ isRaw(): boolean { return !this.isTransformed(); } url(): string { assertNotUsingInMemoryTenant('Binary#url'); return this.urlWithoutPlaceholder() || PLACEHOLDER_URL; } /** @internal */ urlWithoutPlaceholder(): string | undefined { const data = this._loadableData.get(); if (!data) { return; } const accessData = data[this.accessType()]; if (!accessData) { // Missing key in binary data throw new InternalError(); } return accessData.get.url; } filename(): string { const url = this.url(); if (!url || url.match(/^data:/)) { return ''; } return new URL(url, 'http://example.com').pathname.split('/').pop() || ''; } metadata(): MetadataCollection { this.assertNotTransformed('Metadata'); return new MetadataCollection(this._id, this._objSpaceId); } contentType(): string { this.assertNotTransformed('Content type'); return this.metadata().contentType(); } contentLength(): number { this.assertNotTransformed('Content length'); return this.metadata().contentLength(); } /** @internal */ extname(): string { if (this.raw().filename().indexOf('.') > -1) { const parts = this.raw() .filename() .split(/[.\\]+/); if (parts.length > 1) return parts[parts.length - 1].toLowerCase(); } return ''; } /** @internal */ equals(binary: Binary): boolean { return ( this.id() === binary.id() && equals(this._objSpaceId, binary.objSpaceId()) && isEqual(this.definition(), binary.definition()) ); } /** @internal */ isImage(): boolean { const rawContentType = this.raw().contentType(); if (rawContentType) { return rawContentType.split('/')[0] === 'image'; } return false; } /** * For test purpose only. * @internal */ definition(): TransformationDefinition | null { return this._transformation || null; } /** @internal */ objSpaceId(): ObjSpaceId { return this._objSpaceId; } /** @internal */ private accessType() { if (this.isPrivate()) { return 'private_access'; } return 'public_access'; } /** @internal */ private assertNotTransformed(fieldName: string) { if (this.isTransformed()) { throw new ScrivitoError( `"${fieldName}" is not available for transformed images.` + ' Use "Scrivito.Binary#raw" to access the untransformed version of the image.' ); } } /** @internal */ private isTransformed() { return !!this._transformation; } } function checkUpload(source: Blob | File, options?: BinaryUploadOptions) { if (!(isBlob(source) || isFile(source))) { throwInvalidArgumentsError( 'Binary.upload', "'source' must be a 'Blob' or a 'File'.", { docPermalink: 'js-sdk/Binary-static-upload' } ); } if (!['string', 'undefined'].includes(typeof options?.contentType)) { throwInvalidArgumentsError( 'Binary.upload', "'options.contentType' must be a 'String'.", { docPermalink: 'js-sdk/Binary-static-upload' } ); } if (!['string', 'undefined'].includes(typeof options?.filename)) { throwInvalidArgumentsError( 'Binary.upload', "'options.filename' must be a 'String'.", { docPermalink: 'js-sdk/Binary-static-upload' } ); } }