pubnub
Version:
Publish & Subscribe Real-time Messaging with PubNub
227 lines (226 loc) • 10.6 kB
JavaScript
;
/**
* Fetch messages REST API module.
*
* @internal
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FetchMessagesRequest = void 0;
const request_1 = require("../components/request");
const operations_1 = __importDefault(require("../constants/operations"));
const History = __importStar(require("../types/api/history"));
const utils_1 = require("../utils");
// --------------------------------------------------------
// ---------------------- Defaults ------------------------
// --------------------------------------------------------
// region Defaults
/**
* Whether verbose logging enabled or not.
*/
const LOG_VERBOSITY = false;
/**
* Whether message type should be returned or not.
*/
const INCLUDE_MESSAGE_TYPE = true;
/**
* Whether timetokens should be returned as strings by default or not.
*/
const STRINGIFY_TIMETOKENS = false;
/**
* Whether message publisher `uuid` should be returned or not.
*/
const INCLUDE_UUID = true;
/**
* Default number of messages which can be returned for single channel, and it is maximum as well.
*/
const SINGLE_CHANNEL_MESSAGES_COUNT = 100;
/**
* Default number of messages which can be returned for multiple channels or when fetched
* message actions.
*/
const MULTIPLE_CHANNELS_MESSAGES_COUNT = 25;
// endregion
/**
* Fetch messages from channels request.
*
* @internal
*/
class FetchMessagesRequest extends request_1.AbstractRequest {
constructor(parameters) {
var _a, _b, _c, _d, _e;
super();
this.parameters = parameters;
// Apply defaults.
const includeMessageActions = (_a = parameters.includeMessageActions) !== null && _a !== void 0 ? _a : false;
const defaultCount = parameters.channels.length > 1 || includeMessageActions
? MULTIPLE_CHANNELS_MESSAGES_COUNT
: SINGLE_CHANNEL_MESSAGES_COUNT;
if (!parameters.count)
parameters.count = defaultCount;
else
parameters.count = Math.min(parameters.count, defaultCount);
if (parameters.includeUuid)
parameters.includeUUID = parameters.includeUuid;
else
(_b = parameters.includeUUID) !== null && _b !== void 0 ? _b : (parameters.includeUUID = INCLUDE_UUID);
(_c = parameters.stringifiedTimeToken) !== null && _c !== void 0 ? _c : (parameters.stringifiedTimeToken = STRINGIFY_TIMETOKENS);
(_d = parameters.includeMessageType) !== null && _d !== void 0 ? _d : (parameters.includeMessageType = INCLUDE_MESSAGE_TYPE);
(_e = parameters.logVerbosity) !== null && _e !== void 0 ? _e : (parameters.logVerbosity = LOG_VERBOSITY);
}
operation() {
return operations_1.default.PNFetchMessagesOperation;
}
validate() {
const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters;
if (!subscribeKey)
return 'Missing Subscribe Key';
if (!channels)
return 'Missing channels';
if (includeMessageActions !== undefined && includeMessageActions && channels.length > 1)
return ('History can return actions data for a single channel only. Either pass a single channel ' +
'or disable the includeMessageActions flag.');
}
parse(response) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const serviceResponse = this.deserializeResponse(response);
const responseChannels = (_a = serviceResponse.channels) !== null && _a !== void 0 ? _a : {};
const channels = {};
Object.keys(responseChannels).forEach((channel) => {
// Map service response to expected data object type structure.
channels[channel] = responseChannels[channel].map((payload) => {
// `null` message type means regular message.
if (payload.message_type === null)
payload.message_type = History.PubNubMessageType.Message;
const processedPayload = this.processPayload(channel, payload);
const item = Object.assign(Object.assign({ channel, timetoken: payload.timetoken, message: processedPayload.payload, messageType: payload.message_type }, (payload.custom_message_type ? { customMessageType: payload.custom_message_type } : {})), { uuid: payload.uuid });
if (payload.actions) {
const itemWithActions = item;
itemWithActions.actions = payload.actions;
// Backward compatibility for existing users.
// TODO: Remove in next release.
itemWithActions.data = payload.actions;
}
if (payload.meta)
item.meta = payload.meta;
if (processedPayload.error)
item.error = processedPayload.error;
return item;
});
});
if (serviceResponse.more)
return { channels, more: serviceResponse.more };
return { channels };
});
}
get path() {
const { keySet: { subscribeKey }, channels, includeMessageActions, } = this.parameters;
const endpoint = !includeMessageActions ? 'history' : 'history-with-actions';
return `/v3/${endpoint}/sub-key/${subscribeKey}/channel/${(0, utils_1.encodeNames)(channels)}`;
}
get queryParameters() {
const { start, end, count, includeCustomMessageType, includeMessageType, includeMeta, includeUUID, stringifiedTimeToken, } = this.parameters;
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ max: count }, (start ? { start } : {})), (end ? { end } : {})), (stringifiedTimeToken ? { string_message_token: 'true' } : {})), (includeMeta !== undefined && includeMeta ? { include_meta: 'true' } : {})), (includeUUID ? { include_uuid: 'true' } : {})), (includeCustomMessageType !== undefined && includeCustomMessageType !== null
? { include_custom_message_type: includeCustomMessageType ? 'true' : 'false' }
: {})), (includeMessageType ? { include_message_type: 'true' } : {}));
}
/**
* Parse single channel data entry.
*
* @param channel - Channel for which {@link payload} should be processed.
* @param payload - Source payload which should be processed and parsed to expected type.
*
* @returns
*/
processPayload(channel, payload) {
const { crypto, logVerbosity } = this.parameters;
if (!crypto || typeof payload.message !== 'string')
return { payload: payload.message };
let decryptedPayload;
let error;
try {
const decryptedData = crypto.decrypt(payload.message);
decryptedPayload =
decryptedData instanceof ArrayBuffer
? JSON.parse(FetchMessagesRequest.decoder.decode(decryptedData))
: decryptedData;
}
catch (err) {
if (logVerbosity)
console.log(`decryption error`, err.message);
decryptedPayload = payload.message;
error = `Error while decrypting message content: ${err.message}`;
}
if (!error &&
decryptedPayload &&
payload.message_type == History.PubNubMessageType.Files &&
typeof decryptedPayload === 'object' &&
this.isFileMessage(decryptedPayload)) {
const fileMessage = decryptedPayload;
return {
payload: {
message: fileMessage.message,
file: Object.assign(Object.assign({}, fileMessage.file), { url: this.parameters.getFileUrl({ channel, id: fileMessage.file.id, name: fileMessage.file.name }) }),
},
error,
};
}
return { payload: decryptedPayload, error };
}
/**
* Check whether `payload` potentially represents file message.
*
* @param payload - Fetched message payload.
*
* @returns `true` if payload can be {@link History#FileMessage|FileMessage}.
*/
isFileMessage(payload) {
return payload.file !== undefined;
}
}
exports.FetchMessagesRequest = FetchMessagesRequest;