Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

leancloud-realtime

Package Overview
Dependencies
Maintainers
4
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

leancloud-realtime - npm Package Compare versions

Comparing version 4.0.0-alpha.2 to 4.0.0-alpha.3

2

bower.json
{
"name": "leancloud-realtime",
"version": "4.0.0-alpha.2",
"version": "4.0.0-alpha.3",
"homepage": "https://github.com/leancloud/js-realtime-sdk/",

@@ -5,0 +5,0 @@ "description": "LeanCloud JavaScript Realtime SDK",

@@ -0,1 +1,16 @@

<a name="4.0.0-alpha.3"></a>
# 4.0.0-alpha.3 (2017-11-02)
### BREAKING CHANGES
* 重新设计了对话与消息的序列化方法。现在在小程序中能够直接将 Conversation 与 Message 实例作为 data 设置给视图层使用了。
* `AVMessage` 接口原有的用来获取消息内容的 `toJSON` 方法现在改名为 `getPayload`。内置的 `Message` 类及其子类均已更新,如果使用富文本消息插件(leancloud-realtime-plugin-typed-messages),需要更新插件至 v3.0.0。
* `Message` 类及其子类重新实现了 `toJSON` 方法用于获取该消息的有效信息。
* `Conversation` 类增加了 `toJSON` 方法用于获取该对话的有效信息。
### Bug Fixes
* 解决了与序列化 Conversation 抛循环引用异常相关的问题,包括小程序中无法 `console.log` Conversation 的问题。
<a name="4.0.0-alpha.2"></a>

@@ -198,3 +213,3 @@ # 4.0.0-alpha.2 (2017-09-22)

SDK 内置了对单聊的已读回执支持。`Conversation` 增加了 `lastDeliveredAt` 与 `lastReadAt` 属性标记了该对话中最后一条已送达与已读的消息时间戳,可以通过 `Conversation#fetchReceiptTimestamps` 方法获取到这两个属性。对于在单聊中发送的需要回执的消息,当对方收到消息时,`lastDeliveredAt` 属性会得到更新,当对方标记会话已读时,`lastReadAt` 属性会得到更新。此外,由于 `reciept` 的含义发生了变化,我们还废弃了 `Conversation` 的 `reciept` 事件(请用 `lastdeliveredatupdate` 事件代替)。与之相关的 API 变化有:
SDK 内置了对单聊的已读回执支持。`Conversation` 增加了 `lastDeliveredAt` 与 `lastReadAt` 属性标记了该对话中最后一条已送达与已读的消息时间戳,可以通过 `Conversation#fetchReceiptTimestamps` 方法获取到这两个属性。对于在单聊中发送的需要回执的消息,当对方收到消息时,`lastDeliveredAt` 属性会得到更新,当对方标记会话已读时,`lastReadAt` 属性会得到更新。此外,由于 `receipt` 的含义发生了变化,我们还废弃了 `Conversation` 的 `receipt` 事件(请用 `lastdeliveredatupdate` 事件代替)。与之相关的 API 变化有:

@@ -204,3 +219,3 @@ - 增加 `Conversation#fetchReceiptTimestamps` 方法

- 增加 `Conversation` `lastReadAt` 属性与 `lastreadatupdate` 事件
- 废弃 `Conversation` `reciept` 事件,请使用 `lastdeliveredatupdate` 事件
- 废弃 `Conversation` `receipt` 事件,请使用 `lastdeliveredatupdate` 事件

@@ -207,0 +222,0 @@ 群聊的已读回执的支持需要使用 [leancloud-realtime-plugin-groupchat-receipts](https://www.npmjs.com/package/leancloud-realtime-plugin-groupchat-receipts) 插件,详细的使用说明请参见其 [API 文档](https://url.leanapp.cn/groupchat-receipts-apidocs)。

{
"name": "leancloud-realtime",
"version": "4.0.0-alpha.2",
"version": "4.0.0-alpha.3",
"description": "LeanCloud Realtime Message JavaScript SDK",

@@ -16,3 +16,3 @@ "main": "./dist/realtime.js",

"test:browser": "grunt test-browser --stack",
"docs": "jsdoc src README.md package.json -d docs -c .jsdocrc.json && jsdoc plugins/typed-messages/src plugins/typed-messages/package.json src/messages/**message.js -d plugins/typed-messages/docs -c .jsdocrc.json && jsdoc plugins/webrtc/src plugins/webrtc/package.json -d plugins/webrtc/docs -c .jsdocrc.json && jsdoc plugins/groupchat-receipts/src plugins/groupchat-receipts/package.json -d plugins/groupchat-receipts/docs -c .jsdocrc.json",
"docs": "jsdoc src README.md package.json -d docs -c .jsdocrc.json && jsdoc plugins/typed-messages/src plugins/typed-messages/package.json src/messages/message.js src/messages/typed-message.js -d plugins/typed-messages/docs -c .jsdocrc.json && jsdoc plugins/webrtc/src plugins/webrtc/package.json -d plugins/webrtc/docs -c .jsdocrc.json && jsdoc plugins/groupchat-receipts/src plugins/groupchat-receipts/package.json -d plugins/groupchat-receipts/docs -c .jsdocrc.json",
"build": "grunt build --stack",

@@ -19,0 +19,0 @@ "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",

@@ -22,2 +22,4 @@ declare module LeanCloudRealtime {

ping(clientIds: string[]): Promise<Array<string>>;
parseMessage(json: Object): Promise<AVMessage>;
parseConversation(json: Object): Promise<Conversation>;
}

@@ -95,2 +97,4 @@

recall(message: MessagePointer): Promise<RecalledMessage>;
toJSON(): Object;
toFullJSON(): Object;
}

@@ -101,3 +105,3 @@

export interface AVMessage {
toJSON(): any;
getPayload(): Object | String | ArrayBuffer;
}

@@ -119,3 +123,5 @@

static validate(): boolean;
getPayload(): Object | String | ArrayBuffer;
toJSON(): Object;
toFullJSON(): Object;
setMentionList(mentionList: string[]): Message;

@@ -122,0 +128,0 @@ getMentionList(): string[];

import EventEmitter from 'eventemitter3';
import isEmpty from 'lodash/isEmpty';
import cloneDeep from 'lodash/cloneDeep';
import { decode as decodeBase64 } from 'base64-arraybuffer';
import d from 'debug';
import { decodeDate, keyRemap, union, difference, internal, setValue } from './utils';
import { decodeDate, decode, encode, getTime, keyRemap, union, difference, internal, setValue } from './utils';
import { applyDecorators } from './plugin';

@@ -28,3 +27,3 @@ import IMClient from './im-client';

const serializeMessage = (message) => {
const content = message.toJSON();
const content = message.getPayload();
let msg;

@@ -75,2 +74,5 @@ let binaryMsg;

lastMessage,
lastDeliveredAt,
lastReadAt,
unreadMessagesCount = 0,
mutedMembers = [],

@@ -156,3 +158,3 @@ members = [],

});
this._attributes = attributes;
this._attributes = decode(attributes);
this._reset();

@@ -162,5 +164,5 @@ this.members = Array.from(new Set(this.members));

messagesWaitingForReceipt: {},
lastDeliveredAt: null,
lastReadAt: null,
unreadMessagesCount: 0,
lastDeliveredAt,
lastReadAt,
unreadMessagesCount,
mentioned,

@@ -350,2 +352,65 @@ });

/**
* 返回 JSON 格式的对话,与 toJSON 不同的是,该对象包含了完整的信息,可以通过 {@link IMClient#parseConversation} 反序列化。
* @return {Object} 返回值是一个 plain Object
* @since 4.0.0
*/
toFullJSON() {
const {
id, name, members, creator, system, transient,
createdAt, updatedAt, lastMessageAt, lastDeliveredAt, lastReadAt,
lastMessage, unreadMessagesCount,
_attributes,
} = this;
return {
id,
name,
members,
creator,
system,
transient,
createdAt: getTime(createdAt),
updatedAt: getTime(updatedAt),
lastMessageAt: getTime(lastMessageAt),
lastDeliveredAt: getTime(lastDeliveredAt),
lastReadAt: getTime(lastReadAt),
lastMessage: lastMessage ? lastMessage.toFullJSON() : undefined,
unreadMessagesCount,
..._attributes,
};
}
/**
* 返回 JSON 格式的对话
* @return {Object} 返回值是一个 plain Object
* @since 4.0.0
*/
toJSON() {
const {
id, name, members, creator, system, transient, muted, mutedMembers,
createdAt, updatedAt, lastMessageAt, lastDeliveredAt, lastReadAt,
lastMessage, unreadMessagesCount, unreadMessagesMentioned,
_attributes,
} = this;
return {
id,
name,
members,
creator,
system,
transient,
muted,
mutedMembers,
createdAt,
updatedAt,
lastMessageAt,
lastDeliveredAt,
lastReadAt,
lastMessage: lastMessage ? lastMessage.toJSON() : undefined,
unreadMessagesCount,
unreadMessagesMentioned,
..._attributes,
};
}
_reset() {

@@ -388,3 +453,3 @@ internal(this).pendingAttributes = {};

attr: new JsonObjectMessage({
data: JSON.stringify(attr),
data: JSON.stringify(encode(attr)),
}),

@@ -631,3 +696,3 @@ });

id: uid,
timestamp: new Date(t.toNumber()),
timestamp: t,
});

@@ -811,18 +876,15 @@ this.lastMessage = message;

}) => {
const content = bin ? decodeBase64(data) : data;
const message = await this._client._messageParser.parse(content);
const messageProps = {
const messageData = {
data,
bin,
id: msgId,
cid: this.id,
timestamp: new Date(timestamp.toNumber()),
timestamp,
from,
deliveredAt: ackAt,
updatedAt: patchTimestamp,
mentionList: mentionPids,
mentionedAll: mentionAll,
};
if (patchTimestamp) {
messageProps.updatedAt = new Date(patchTimestamp.toNumber());
}
Object.assign(message, messageProps);
message._updateMentioned(this._client.id);
const message = await this._client.parseMessage(messageData);
let status = MessageStatus.SENT;

@@ -829,0 +891,0 @@ if (this.members.length === 2) {

import EventEmitter from 'eventemitter3';
import { decode as decodeBase64 } from 'base64-arraybuffer';
import d from 'debug';

@@ -17,3 +18,3 @@ import Conversation from './conversation';

import { ErrorCode, createError } from './error';
import { Expirable, Cache, keyRemap, union, difference, trim, internal, throttle } from './utils';
import { Expirable, Cache, keyRemap, union, difference, trim, internal, throttle, encode, decode } from './utils';
import { applyDecorators, applyDispatcher } from './plugin';

@@ -26,2 +27,3 @@ import runSignatureFactory from './signature-factory-runner';

export default class IMClient extends EventEmitter {

@@ -176,7 +178,5 @@ /**

timestamp,
updatedAt: patchTimestamp,
from,
};
if (patchTimestamp) {
messageProps.updatedAt = new Date(patchTimestamp.toNumber());
}
Object.assign(message, messageProps);

@@ -242,4 +242,4 @@ conversation.lastMessage = message; // eslint-disable-line no-param-reassign

cid,
timestamp: new Date(timestamp.toNumber()),
updatedAt: new Date(patchTime),
timestamp,
updatedAt: patchTime,
from,

@@ -431,3 +431,4 @@ mentionList: mentionPids,

cid,
timestamp: new Date(timestamp.toNumber()),
timestamp,
updatedAt: patchTimestamp,
from: fromPeerId,

@@ -437,5 +438,2 @@ mentionList: mentionPids,

};
if (patchTimestamp) {
messageProps.updatedAt = new Date(patchTimestamp.toNumber());
}
Object.assign(message, messageProps);

@@ -708,3 +706,3 @@ message._updateMentioned(this.id);

queryJSON.where = new JsonObjectMessage({
data: JSON.stringify(queryJSON.where),
data: JSON.stringify(encode(queryJSON.where)),
});

@@ -719,3 +717,3 @@ const command = new GenericCommand({

try {
conversations = JSON.parse(resCommand.convMessage.results.data);
conversations = JSON.parse(decode(resCommand.convMessage.results.data));
} catch (error) {

@@ -756,2 +754,35 @@ const commandString = JSON.stringify(trim(resCommand));

/**
* 反序列化消息,与 {@link Message#toFullJSON} 相对。
* @param {Object}
* @return {AVMessage} 解析后的消息
* @since 4.0.0
*/
async parseMessage({
data,
bin = false,
...properties
}) {
const content = bin ? decodeBase64(data) : data;
const message = await this._messageParser.parse(content);
Object.assign(message, properties);
message._updateMentioned(this.id);
return message;
}
/**
* 反序列化对话,与 {@link Conversation#toFullJSON} 相对。
* @param {Object}
* @return {Conversation} 解析后的对话
* @since 4.0.0
*/
async parseConversation(json) {
const data = { ...json };
if (data.lastMessage) {
data.lastMessage = await this.parseMessage(data.lastMessage);
}
const conversation = new Conversation(data, this);
return conversation;
}
async _parseConversationFromRawData(rawData) {

@@ -773,2 +804,5 @@ const data = keyRemap({

if (data.lastMessage) {
if (data.bin) {
data.lastMessage = decodeBase64(data.lastMessage);
}
const message = await this._messageParser.parse(data.lastMessage);

@@ -778,6 +812,4 @@ data.lastMessage = message;

message.id = data.lastMessageId;
message.timestamp = new Date(data.lastMessageTimestamp);
if (data.lastMessagePatchTimestamp) {
message.updatedAt = new Date(data.lastMessagePatchTimestamp);
}
message.timestamp = data.lastMessageTimestamp;
message.updatedAt = data.lastMessagePatchTimestamp;
message._setStatus(MessageStatus.SENT);

@@ -823,3 +855,3 @@ delete data.lastMessageFrom;

attr = new JsonObjectMessage({
data: JSON.stringify(attr),
data: JSON.stringify(encode(attr)),
});

@@ -826,0 +858,0 @@

@@ -47,3 +47,3 @@ import d from 'debug';

messageClass.prototype &&
messageClass.prototype.toJSON
messageClass.prototype.getPayload
) {

@@ -50,0 +50,0 @@ this._messageClasses.unshift(messageClass);

@@ -44,5 +44,5 @@ /**

/**
* 将当前消息序列化为 JSON 对象 (AVMessage -> JSON)
* 获取当前消息的内容,与 parse 相对 (AVMessage -> JSON)
* <p>
* 在这个方法中,应该先调用父类的 toJSON 方法,得到 JSON 对象,
* 在这个方法中,应该先调用父类的 getPayload 方法,得到 JSON 对象,
* 然后,将当前消息实例的信息修改 JSON 对象后返回

@@ -52,4 +52,4 @@ * (当然,你也可以不管父类返回的 JSON)。

* @function
* @name AVMessage#toJSON
* @name AVMessage#getPayload
* @return {Object} JSON 格式的消息内容
*/

@@ -0,1 +1,2 @@

import { encode as encodeBase64 } from 'base64-arraybuffer';
import Message from './message';

@@ -30,2 +31,17 @@

}
toJSON() {
return {
...super._toJSON(),
data: encodeBase64(this.content),
};
}
toFullJSON() {
return {
...super.toFullJSON(),
bin: true,
data: encodeBase64(this.content),
};
}
}
import uuid from 'uuid/v4';
import { ensureArray } from '../utils';
import { ensureArray, decodeDate, compact } from '../utils';

@@ -66,7 +66,2 @@

/**
* @var deliveredAt {?Date} 消息送达时间
* @memberof Message#
*/
// deliveredAt,
/**
* 消息提及的用户

@@ -91,11 +86,77 @@ * @since 4.0.0

/**
* 将当前消息序列化为 JSON 对象
* @protected
* 将当前消息的内容序列化为 JSON 对象
* @private
* @return {Object}
*/
toJSON() {
getPayload() {
return this.content;
}
_toJSON() {
const {
id,
cid,
from,
timestamp,
deliveredAt,
updatedAt,
mentionList,
mentionedAll,
mentioned,
} = this;
return {
id,
cid,
from,
timestamp,
deliveredAt,
updatedAt,
mentionList,
mentionedAll,
mentioned,
};
}
/**
* 返回 JSON 格式的消息
* @return {Object} 返回值是一个 plain Object
*/
toJSON() {
return {
...this._toJSON(),
data: this.content,
};
}
/**
* 返回 JSON 格式的消息,与 toJSON 不同的是,该对象包含了完整的信息,可以通过 {@link IMClient#parseMessage} 反序列化。
* @return {Object} 返回值是一个 plain Object
* @since 4.0.0
*/
toFullJSON() {
const {
content,
id,
cid,
from,
timestamp,
deliveredAt,
_updatedAt,
mentionList,
mentionedAll,
} = this;
return compact({
data: content,
id,
cid,
from,
timestamp,
deliveredAt,
updatedAt: _updatedAt,
mentionList,
mentionedAll,
});
}
/**
* 消息状态,值为 {@link module:leancloud-realtime.MessageStatus} 之一

@@ -117,3 +178,21 @@ * @type {Symbol}

get timestamp() {
return this._timestamp;
}
set timestamp(value) {
this._timestamp = decodeDate(value);
}
/**
* 消息送达时间
* @type {?Date}
*/
get deliveredAt() {
return this._deliveredAt;
}
set deliveredAt(value) {
this._deliveredAt = decodeDate(value);
}
/**
* 消息修改或撤回时间,可以通过比较其与消息的 timestamp 是否相等判断消息是否被修改过或撤回过。

@@ -127,3 +206,3 @@ * @type {Date}

set updatedAt(value) {
this._updatedAt = value;
this._updatedAt = decodeDate(value);
}

@@ -177,3 +256,3 @@

* 该方法始终返回 true
* @protected
* @private
* @returns {Boolean}

@@ -191,3 +270,3 @@ * @implements AVMessage.validate

* 如果没有提供,将 json 作为 content 实例化一个 Message
* @protected
* @private
* @param {Object} json json 格式的消息内容

@@ -194,0 +273,0 @@ * @param {Message} message 子类提供的 message

import Message from './message';
import { messageField } from './helpers';
import { getStaticProperty, isIE10 } from '../utils';
import { getStaticProperty, isIE10, compact } from '../utils';

@@ -8,13 +8,8 @@ // jsdoc-ignore-start

// jsdoc-ignore-end
export default class TypedMessage extends Message {
/**
* 所有内置的富媒体消息均继承自本类
* @extends Message
*/
class TypedMessage extends Message {
/**
* 所有内置的富媒体消息均继承自本类
* @extends Message
*/
constructor() {
super();
this._ = {};
}
/**
* @type {Number}

@@ -100,9 +95,32 @@ * @readonly

toJSON() {
return Object.assign({
getPayload() {
return compact(Object.assign({
_lctext: this.getText(),
_lcattrs: this.getAttributes(),
}, this._getCustomFields(), this._getType());
}, this._getCustomFields(), this._getType()));
}
toJSON() {
const {
type,
text,
attributes,
summary,
} = this;
return {
...super._toJSON(),
type,
text,
attributes,
summary,
};
}
toFullJSON() {
return {
...super.toFullJSON(),
data: this.getPayload(),
};
}
/**

@@ -134,1 +152,3 @@ * 解析处理消息内容

}
export default TypedMessage;

@@ -70,3 +70,3 @@ /* eslint-disable max-len */

* <p>
* 接受一个参数为原始消息,是某个消息 JSON 化(<code>message.toJSON()</code>)的返回值,一般是一个 JSON 对象。
* 接受一个参数为原始消息,是某个消息的内容,一般是一个 JSON 对象。
* 该方法需要返回一个 JSON 对象。如果这个结果是异步得到的,也可以返回一个 Promise(fulfilled with a JSON)。

@@ -73,0 +73,0 @@ *

@@ -19,5 +19,10 @@ import isPlainObject from 'lodash/isPlainObject';

/**
* 将对象转换为 Date,支持 string、number、ProtoBuf Long 以及 LeanCloud 的 Date 类型,
* 其他情况下(包括对象为 falsy)返回原值。
* @private
*/
export const decodeDate = (date) => {
if (!date) return date;
if (typeof date === 'string') {
if (typeof date === 'string' || typeof date === 'number') {
return new Date(date);

@@ -34,3 +39,42 @@ }

};
/**
* 获取 Date 的毫秒数,如果不是一个 Date 返回 undefined。
* @private
*/
export const getTime = date => ((date && date.getTime) ? date.getTime() : undefined);
/**
* 解码对象中的 LeanCloud 数据结构。
* 目前仅会处理 Date 类型。
* @private
*/
export const decode = (value) => {
if (!value) return value;
if (value.__type === 'Date' && value.iso) {
return new Date(value.iso);
}
if (isPlainObject(value)) {
return Object.keys(value).reduce((result, key) => ({
...result,
[key]: decode(value[key]),
}), {});
}
return value;
};
/**
* 将对象中的特殊类型编码为 LeanCloud 数据结构。
* 目前仅会处理 Date 类型。
* @private
*/
export const encode = (value) => {
if (value instanceof Date) return { __type: 'Date', iso: value.toJSON() };
if (isPlainObject(value)) {
return Object.keys(value).reduce((result, key) => ({
...result,
[key]: encode(value[key]),
}), {});
}
return value;
};
export const keyRemap = (keymap, obj) =>

@@ -69,4 +113,3 @@ Object.keys(obj).reduce((newObj, key) => {

// debug utility
const removeNull = (obj) => {
export const compact = (obj, filter) => {
if (!isPlainObject(obj)) return obj;

@@ -78,6 +121,6 @@ const object = Object.assign({}, obj);

const value = object[prop];
if (value === null) {
if (value === filter) {
delete object[prop];
} else {
object[prop] = removeNull(value);
object[prop] = compact(value, filter);
}

@@ -88,2 +131,5 @@ }

};
// debug utility
const removeNull = obj => compact(obj, null);
export const trim = message => removeNull(JSON.parse(JSON.stringify(message)));

@@ -90,0 +136,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc