UNPKG

pubnub

Version:

Publish & Subscribe Real-time Messaging with PubNub

137 lines (116 loc) 3.91 kB
/** * Publish File Message REST API module. * * @internal */ import { TransportResponse } from '../../types/transport-response'; import { ICryptoModule } from '../../interfaces/crypto-module'; import { AbstractRequest } from '../../components/request'; import * as FileSharing from '../../types/api/file-sharing'; import RequestOperation from '../../constants/operations'; import { KeySet, Payload, Query } from '../../types/api'; import { encode } from '../../components/base64_codec'; import { encodeString } from '../../utils'; // -------------------------------------------------------- // ----------------------- Defaults ----------------------- // -------------------------------------------------------- // region Defaults /** * Whether published file messages should be stored in the channel's history. */ const STORE_IN_HISTORY = true; // endregion // -------------------------------------------------------- // ------------------------ Types ------------------------- // -------------------------------------------------------- // region Types /** * Request configuration parameters. */ type RequestParameters = FileSharing.PublishFileMessageParameters & { /** * PubNub REST API access key set. */ keySet: KeySet; /** * Published data encryption module. */ crypto?: ICryptoModule; }; /** * Service success response. */ type ServiceResponse = [0 | 1, string, string]; // endregion /** * Publish shared file information request. * * @internal */ export class PublishFileMessageRequest extends AbstractRequest< FileSharing.PublishFileMessageResponse, ServiceResponse > { constructor(private readonly parameters: RequestParameters) { super(); // Apply default request parameters. this.parameters.storeInHistory ??= STORE_IN_HISTORY; } operation(): RequestOperation { return RequestOperation.PNPublishFileMessageOperation; } validate(): string | undefined { const { channel, fileId, fileName } = this.parameters; if (!channel) return "channel can't be empty"; if (!fileId) return "file id can't be empty"; if (!fileName) return "file name can't be empty"; } async parse(response: TransportResponse): Promise<FileSharing.PublishFileMessageResponse> { return { timetoken: this.deserializeResponse(response)[2] }; } protected get path(): string { const { message, channel, keySet: { publishKey, subscribeKey }, fileId, fileName, } = this.parameters; const fileMessage = { file: { name: fileName, id: fileId, }, ...(message ? { message } : {}), }; return `/v1/files/publish-file/${publishKey}/${subscribeKey}/0/${encodeString(channel)}/0/${encodeString( this.prepareMessagePayload(fileMessage), )}`; } protected get queryParameters(): Query { const { customMessageType, storeInHistory, ttl, meta } = this.parameters; return { store: storeInHistory! ? '1' : '0', ...(customMessageType ? { custom_message_type: customMessageType } : {}), ...(ttl ? { ttl } : {}), ...(meta && typeof meta === 'object' ? { meta: JSON.stringify(meta) } : {}), }; } /** * Pre-process provided data. * * Data will be "normalized" and encrypted if `cryptoModule` has been provided. * * @param payload - User-provided data which should be pre-processed before use. * * @returns Payload which can be used as part of request URL or body. * * @throws {Error} in case if provided `payload` or results of `encryption` can't be stringified. */ private prepareMessagePayload(payload: Payload): string { const { crypto } = this.parameters; if (!crypto) return JSON.stringify(payload) || ''; const encrypted = crypto.encrypt(JSON.stringify(payload)); return JSON.stringify(typeof encrypted === 'string' ? encrypted : encode(encrypted)); } }