UNPKG

9.66 kBJavaScriptView Raw
1import d from 'debug';
2
3const debug = d('LC:ConversationQuery');
4
5export default class ConversationQuery {
6 static _encode(value) {
7 if (value instanceof Date) {
8 return { __type: 'Date', iso: value.toJSON() };
9 }
10 if (value instanceof RegExp) {
11 return value.source;
12 }
13 return value;
14 }
15
16 static _quote(s) {
17 return `\\Q${s.replace('\\E', '\\E\\\\E\\Q')}\\E`;
18 }
19
20 static _calculateFlag(options) {
21 return ['withLastMessagesRefreshed', 'compact'].reduce(
22 // eslint-disable-next-line no-bitwise
23 (prev, key) => (prev << 1) + Boolean(options[key]),
24 0
25 );
26 }
27
28 /**
29 * Create a ConversationQuery
30 * @param {IMClient} client
31 */
32 constructor(client) {
33 this._client = client;
34 this._where = {};
35 this._extraOptions = {};
36 }
37
38 _addCondition(key, condition, value) {
39 // Check if we already have a condition
40 if (!this._where[key]) {
41 this._where[key] = {};
42 }
43 this._where[key][condition] = this.constructor._encode(value);
44 return this;
45 }
46
47 toJSON() {
48 const json = {
49 where: this._where,
50 flag: this.constructor._calculateFlag(this._extraOptions),
51 };
52 if (typeof this._skip !== 'undefined') json.skip = this._skip;
53 if (typeof this._limit !== 'undefined') json.limit = this._limit;
54 if (typeof this._order !== 'undefined') json.sort = this._order;
55 debug(json);
56 return json;
57 }
58
59 /**
60 * 增加查询条件,指定聊天室的组员包含某些成员即可返回
61 * @param {string[]} peerIds - 成员 ID 列表
62 * @return {ConversationQuery} self
63 */
64 containsMembers(peerIds) {
65 return this.containsAll('m', peerIds);
66 }
67
68 /**
69 * 增加查询条件,指定聊天室的组员条件满足条件的才返回
70 *
71 * @param {string[]} - 成员 ID 列表
72 * @param {Boolean} includeSelf - 是否包含自己
73 * @return {ConversationQuery} self
74 */
75 withMembers(peerIds, includeSelf) {
76 const peerIdsSet = new Set(peerIds);
77 if (includeSelf) {
78 peerIdsSet.add(this._client.id);
79 }
80 this.sizeEqualTo('m', peerIdsSet.size);
81 return this.containsMembers(Array.from(peerIdsSet));
82 }
83
84 /**
85 * 增加查询条件,当 conversation 的属性中对应的字段满足等于条件时即可返回
86 *
87 * @param {string} key
88 * @param value
89 * @return {ConversationQuery} self
90 */
91 equalTo(key, value) {
92 this._where[key] = this.constructor._encode(value);
93 return this;
94 }
95
96 /**
97 * 增加查询条件,当 conversation 的属性中对应的字段满足小于条件时即可返回
98 * @param {string} key
99 * @param value
100 * @return {ConversationQuery} self
101 */
102 lessThan(key, value) {
103 return this._addCondition(key, '$lt', value);
104 }
105
106 /**
107 * 增加查询条件,当 conversation 的属性中对应的字段满足小于等于条件时即可返回
108
109 * @param {string} key
110 * @param value
111 * @return {ConversationQuery} self
112 */
113 lessThanOrEqualTo(key, value) {
114 return this._addCondition(key, '$lte', value);
115 }
116
117 /**
118 * 增加查询条件,当 conversation 的属性中对应的字段满足大于条件时即可返回
119 *
120 * @param {string} key
121 * @param value
122 * @return {ConversationQuery} self
123 */
124
125 greaterThan(key, value) {
126 return this._addCondition(key, '$gt', value);
127 }
128
129 /**
130 * 增加查询条件,当 conversation 的属性中对应的字段满足大于等于条件时即可返回
131 *
132 * @param {string} key
133 * @param value
134 * @return {ConversationQuery} self
135 */
136
137 greaterThanOrEqualTo(key, value) {
138 return this._addCondition(key, '$gte', value);
139 }
140
141 /**
142 * 增加查询条件,当 conversation 的属性中对应的字段满足不等于条件时即可返回
143 *
144 * @param {string} key
145 * @param value
146 * @return {ConversationQuery} self
147 */
148 notEqualTo(key, value) {
149 return this._addCondition(key, '$ne', value);
150 }
151
152 /**
153 * 增加查询条件,当 conversation 存在指定的字段时即可返回
154 *
155 * @since 3.5.0
156 * @param {string} key
157 * @return {ConversationQuery} self
158 */
159 exists(key) {
160 return this._addCondition(key, '$exists', true);
161 }
162
163 /**
164 * 增加查询条件,当 conversation 不存在指定的字段时即可返回
165 *
166 * @since 3.5.0
167 * @param {string} key
168 * @return {ConversationQuery} self
169 */
170 doesNotExist(key) {
171 return this._addCondition(key, '$exists', false);
172 }
173
174 /**
175 * 增加查询条件,当 conversation 的属性中对应的字段对应的值包含在指定值中时即可返回
176 *
177 * @param {string} key
178 * @param values
179 * @return {ConversationQuery} self
180 */
181 containedIn(key, values) {
182 return this._addCondition(key, '$in', values);
183 }
184
185 /**
186 * 增加查询条件,当 conversation 的属性中对应的字段对应的值不包含在指定值中时即可返回
187 *
188 * @param {string} key
189 * @param values
190 * @return {ConversationQuery} self
191 */
192 notContainsIn(key, values) {
193 return this._addCondition(key, '$nin', values);
194 }
195
196 /**
197 * 增加查询条件,当conversation的属性中对应的字段中的元素包含所有的值才可返回
198 *
199 * @param {string} key
200 * @param values
201 * @return {ConversationQuery} self
202 */
203 containsAll(key, values) {
204 return this._addCondition(key, '$all', values);
205 }
206
207 /**
208 * 增加查询条件,当 conversation 的属性中对应的字段对应的值包含此字符串即可返回
209 *
210 * @param {string} key
211 * @param {string} subString
212 * @return {ConversationQuery} self
213 */
214 contains(key, subString) {
215 return this._addCondition(
216 key,
217 '$regex',
218 ConversationQuery._quote(subString)
219 );
220 }
221
222 /**
223 * 增加查询条件,当 conversation 的属性中对应的字段对应的值以此字符串起始即可返回
224 *
225 * @param {string} key
226 * @param {string} prefix
227 * @return {ConversationQuery} self
228 */
229 startsWith(key, prefix) {
230 return this._addCondition(
231 key,
232 '$regex',
233 `^${ConversationQuery._quote(prefix)}`
234 );
235 }
236
237 /**
238 * 增加查询条件,当 conversation 的属性中对应的字段对应的值以此字符串结束即可返回
239 *
240 * @param {string} key
241 * @param {string} suffix
242 * @return {ConversationQuery} self
243 */
244 endsWith(key, suffix) {
245 return this._addCondition(
246 key,
247 '$regex',
248 `${ConversationQuery._quote(suffix)}$`
249 );
250 }
251
252 /**
253 * 增加查询条件,当 conversation 的属性中对应的字段对应的值满足提供的正则表达式即可返回
254 *
255 * @param {string} key
256 * @param {RegExp} regex
257 * @return {ConversationQuery} self
258 */
259 matches(key, regex) {
260 this._addCondition(key, '$regex', regex);
261 // Javascript regex options support mig as inline options but store them
262 // as properties of the object. We support mi & should migrate them to
263 // modifiers
264 let _modifiers = '';
265 if (regex.ignoreCase) {
266 _modifiers += 'i';
267 }
268 if (regex.multiline) {
269 _modifiers += 'm';
270 }
271
272 if (_modifiers && _modifiers.length) {
273 this._addCondition(key, '$options', _modifiers);
274 }
275 return this;
276 }
277
278 /**
279 * 添加查询约束条件,查找 key 类型是数组,该数组的长度匹配提供的数值
280 *
281 * @param {string} key
282 * @param {Number} length
283 * @return {ConversationQuery} self
284 */
285 sizeEqualTo(key, length) {
286 return this._addCondition(key, '$size', length);
287 }
288
289 /**
290 * 设置返回集合的大小上限
291 *
292 * @param {Number} limit - 上限
293 * @return {ConversationQuery} self
294 */
295 limit(limit) {
296 this._limit = limit;
297 return this;
298 }
299
300 /**
301 * 设置返回集合的起始位置,一般用于分页
302 *
303 * @param {Number} skip - 起始位置跳过几个对象
304 * @return {ConversationQuery} self
305 */
306 skip(skip) {
307 this._skip = skip;
308 return this;
309 }
310
311 /**
312 * 设置返回集合按照指定key进行增序排列
313 *
314 * @param {string} key
315 * @return {ConversationQuery} self
316 */
317 ascending(key) {
318 this._order = key;
319 return this;
320 }
321
322 /**
323 * 设置返回集合按照指定key进行增序排列,如果已设置其他排序,原排序的优先级较高
324 *
325 * @param {string} key
326 * @return {ConversationQuery} self
327 */
328 addAscending(key) {
329 if (this._order) {
330 this._order += `,${key}`;
331 } else {
332 this._order = key;
333 }
334 return this;
335 }
336
337 /**
338 * 设置返回集合按照指定 key 进行降序排列
339 *
340 * @param {string} key
341 * @return {ConversationQuery} self
342 */
343 descending(key) {
344 this._order = `-${key}`;
345 return this;
346 }
347
348 /**
349 * 设置返回集合按照指定 key 进行降序排列,如果已设置其他排序,原排序的优先级较高
350 *
351 * @param {string} key
352 * @return {ConversationQuery} self
353 */
354 addDescending(key) {
355 if (this._order) {
356 this._order += `,-${key}`;
357 } else {
358 this._order = `-${key}`;
359 }
360 return this;
361 }
362
363 /**
364 * 设置返回的 conversations 刷新最后一条消息
365 * @param {Boolean} [enabled=true]
366 * @return {ConversationQuery} self
367 */
368 withLastMessagesRefreshed(enabled = true) {
369 this._extraOptions.withLastMessagesRefreshed = enabled;
370 return this;
371 }
372
373 /**
374 * 设置返回的 conversations 为精简模式,即不含成员列表
375 * @param {Boolean} [enabled=true]
376 * @return {ConversationQuery} self
377 */
378 compact(enabled = true) {
379 this._extraOptions.compact = enabled;
380 return this;
381 }
382
383 /**
384 * 执行查询
385 * @return {Promise.<ConversationBase[]>}
386 */
387 async find() {
388 return this._client._executeQuery(this);
389 }
390}