Skip to content

Commit e2736a0

Browse files
authored
chore(mongo-adapter): Move update filter logic into the package (#36312)
1 parent b10ce3b commit e2736a0

File tree

26 files changed

+3470
-2237
lines changed

26 files changed

+3470
-2237
lines changed

apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { IMessage, IRoom } from '@rocket.chat/core-typings';
22
import { Emitter } from '@rocket.chat/emitter';
33
import { createPredicateFromFilter } from '@rocket.chat/mongo-adapter';
4-
import type { Filter } from '@rocket.chat/mongo-adapter';
4+
import type { Filter } from 'mongodb';
55

66
import { upsertMessage, RoomHistoryManager } from './RoomHistoryManager';
77
import { RoomManager } from '../../../../client/lib/RoomManager';

apps/meteor/client/hooks/lists/useStreamUpdatesForMessageList.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings';
2-
import type { FieldExpression, Filter } from '@rocket.chat/mongo-adapter';
32
import { createPredicateFromFilter } from '@rocket.chat/mongo-adapter';
43
import { useStream } from '@rocket.chat/ui-contexts';
4+
import type { Condition, Filter } from 'mongodb';
55
import { useEffect } from 'react';
66

77
import type { MessageList } from '../../lib/lists/MessageList';
@@ -10,7 +10,7 @@ type NotifyRoomRidDeleteMessageBulkEvent = {
1010
rid: IMessage['rid'];
1111
excludePinned: boolean;
1212
ignoreDiscussion: boolean;
13-
ts: FieldExpression<Date>;
13+
ts: Condition<Date>;
1414
users: string[];
1515
ids?: string[]; // message ids have priority over ts
1616
showDeletedStatus?: boolean;
@@ -36,7 +36,7 @@ const createDeleteCriteria = (params: NotifyRoomRidDeleteMessageBulkEvent): ((me
3636
query['u.username'] = { $in: params.users };
3737
}
3838

39-
return createPredicateFromFilter<IMessage>(query);
39+
return createPredicateFromFilter(query);
4040
};
4141

4242
export const useStreamUpdatesForMessageList = (messageList: MessageList, uid: IUser['_id'] | null, rid: IRoom['_id'] | null): void => {

apps/meteor/client/lib/cachedCollections/Cursor.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { createComparatorFromSort, createPredicateFromFilter, type Filter, type Sort } from '@rocket.chat/mongo-adapter';
1+
import { createComparatorFromSort, createPredicateFromFilter } from '@rocket.chat/mongo-adapter';
22
import { Tracker } from 'meteor/tracker';
3+
import type { Filter, Sort } from 'mongodb';
34

45
import { DiffSequence } from './DiffSequence';
56
import { IdMap } from './IdMap';
@@ -8,7 +9,7 @@ import { MinimongoError } from './MinimongoError';
89
import { ObserveHandle, ReactiveObserveHandle } from './ObserveHandle';
910
import { OrderedDict } from './OrderedDict';
1011
import type { Query, OrderedQuery, UnorderedQuery } from './Query';
11-
import { _isPlainObject, clone, hasOwn } from './common';
12+
import { isPlainObject, clone, hasOwn } from './common';
1213
import type { OrderedObserver, UnorderedObserver } from './observers';
1314

1415
type Transform<T> = ((doc: T) => any) | null | undefined;
@@ -83,7 +84,7 @@ export class Cursor<T extends { _id: string }, TOptions extends Options<T>> {
8384
selector: Filter<T> | T['_id'],
8485
options?: TOptions,
8586
) {
86-
this.predicate = createPredicateFromFilter(typeof selector === 'string' ? ({ _id: selector } as Filter<T>) : selector);
87+
this.predicate = createPredicateFromFilter<T>(typeof selector === 'string' ? ({ _id: selector } as Filter<T>) : selector);
8788
this.comparator = options?.sort ? createComparatorFromSort(options.sort) : null;
8889
this.skip = options?.skip ?? 0;
8990
this.limit = options?.limit;
@@ -253,7 +254,7 @@ export class Cursor<T extends { _id: string }, TOptions extends Options<T>> {
253254

254255
const transformed = Tracker.nonreactive(() => transform(doc));
255256

256-
if (!_isPlainObject(transformed)) {
257+
if (!isPlainObject(transformed)) {
257258
throw new MinimongoError('transform must return object');
258259
}
259260

apps/meteor/client/lib/cachedCollections/DiffSequence.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { IdMap } from './IdMap';
2-
import { clone, entriesOf, hasOwn, isEqual } from './common';
2+
import { clone, entriesOf, hasOwn, equals } from './common';
33
import type { Observer, OrderedObserver, UnorderedObserver } from './observers';
44

55
function isObjEmpty(obj: Record<string, unknown>): boolean {
@@ -65,7 +65,7 @@ export class DiffSequence {
6565
newResults.forEach((newDoc, id) => {
6666
const oldDoc = oldResults.get(id);
6767
if (oldDoc) {
68-
if (observer.changed && !isEqual(oldDoc, newDoc as any)) {
68+
if (observer.changed && !equals(oldDoc, newDoc as any)) {
6969
const projectedNew = projectionFn(newDoc);
7070
const projectedOld = projectionFn(oldDoc);
7171
const changedFields = DiffSequence.makeChangedFields(projectedNew, projectedOld);
@@ -223,7 +223,7 @@ export class DiffSequence {
223223
fields[key] = value;
224224
},
225225
both(key, leftValue, rightValue) {
226-
if (!isEqual(leftValue, rightValue)) fields[key] = rightValue;
226+
if (!equals(leftValue, rightValue)) fields[key] = rightValue;
227227
},
228228
});
229229
return fields;

apps/meteor/client/lib/cachedCollections/LocalCollection.ts

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
import { createPredicateFromFilter } from '@rocket.chat/mongo-adapter';
2-
import type { FieldExpression, Filter } from '@rocket.chat/mongo-adapter';
1+
import {
2+
createDocumentMatcherFromFilter,
3+
createPredicateFromFilter,
4+
createTransformFromUpdateFilter,
5+
createUpsertDocument,
6+
} from '@rocket.chat/mongo-adapter';
7+
import type { ArrayIndices } from '@rocket.chat/mongo-adapter';
38
import { Meteor } from 'meteor/meteor';
4-
import type { CountDocumentsOptions } from 'mongodb';
9+
import type { CountDocumentsOptions, FilterOperators, Filter, UpdateFilter } from 'mongodb';
510
import type { StoreApi, UseBoundStore } from 'zustand';
611

712
import { Cursor } from './Cursor';
813
import type { Options } from './Cursor';
914
import { DiffSequence } from './DiffSequence';
1015
import type { IdMap } from './IdMap';
11-
import { Matcher } from './Matcher';
1216
import { MinimongoError } from './MinimongoError';
1317
import type { Query } from './Query';
1418
import { SynchronousQueue } from './SynchronousQueue';
15-
import type { UpdateFilter } from './Updater';
16-
import { Updater } from './Updater';
17-
import type { ArrayIndices } from './common';
18-
import { hasOwn, _selectorIsId, clone, assertHasValidFieldNames } from './common';
19+
import { clone, assertHasValidFieldNames } from './common';
1920

2021
/**
2122
* Forked from Meteor's Mongo.Collection, this class implements a local collection over a Zustand store.
@@ -209,7 +210,7 @@ export class LocalCollection<T extends { _id: string }> {
209210
}
210211

211212
private prepareRemove(selector: Filter<T>) {
212-
const predicate = createPredicateFromFilter(selector);
213+
const predicate = createPredicateFromFilter<T>(selector);
213214
const remove = new Set<T>();
214215

215216
this._eachPossiblyMatchingDoc(selector, (doc) => {
@@ -430,7 +431,7 @@ export class LocalCollection<T extends { _id: string }> {
430431
const callback = !_callback && typeof _options === 'function' ? _options : _callback;
431432
const options = typeof _options === 'object' && _options !== null ? _options : {};
432433

433-
const matcher = new Matcher(selector);
434+
const matchDocument = createDocumentMatcherFromFilter<T>(selector);
434435

435436
const queriesToOriginalResults = this.prepareUpdate(selector);
436437

@@ -439,7 +440,7 @@ export class LocalCollection<T extends { _id: string }> {
439440
let updateCount = 0;
440441

441442
await this._eachPossiblyMatchingDocAsync(selector, async (doc, id) => {
442-
const queryResult = matcher.documentMatches(doc);
443+
const queryResult = matchDocument(doc);
443444

444445
if (queryResult.result) {
445446
this._saveOriginal(id, doc);
@@ -508,7 +509,7 @@ export class LocalCollection<T extends { _id: string }> {
508509
const callback = !_callback && typeof _options === 'function' ? _options : _callback;
509510
const options = typeof _options === 'object' && _options !== null ? _options : {};
510511

511-
const matcher = new Matcher(selector);
512+
const matchDocument = createDocumentMatcherFromFilter(selector);
512513

513514
const queriesToOriginalResults = this.prepareUpdate(selector);
514515

@@ -517,7 +518,7 @@ export class LocalCollection<T extends { _id: string }> {
517518
let updateCount = 0;
518519

519520
this._eachPossiblyMatchingDoc(selector, (doc, id) => {
520-
const queryResult = matcher.documentMatches(doc);
521+
const queryResult = matchDocument(doc);
521522

522523
if (queryResult.result) {
523524
this._saveOriginal(id, doc);
@@ -680,8 +681,8 @@ export class LocalCollection<T extends { _id: string }> {
680681
const matchedBefore = this._getMatchedDocAndModify(doc);
681682

682683
const oldDoc = clone(doc);
683-
const updater = new Updater(clone(mod));
684-
doc = updater.modify(doc, { arrayIndices });
684+
const updater = createTransformFromUpdateFilter(clone(mod));
685+
doc = updater(doc, { arrayIndices });
685686
this.store.setState((state) => {
686687
const records = new Map(state.records);
687688
records.set(doc._id, doc);
@@ -715,8 +716,8 @@ export class LocalCollection<T extends { _id: string }> {
715716
const matchedBefore = this._getMatchedDocAndModify(doc);
716717

717718
const oldDoc = clone(doc);
718-
const updater = new Updater(clone(mod));
719-
doc = updater.modify(doc, { arrayIndices });
719+
const updater = createTransformFromUpdateFilter(clone(mod));
720+
doc = updater(doc, { arrayIndices });
720721
this.store.setState((state) => {
721722
const records = new Map(state.records);
722723
records.set(doc._id, doc);
@@ -797,8 +798,7 @@ export class LocalCollection<T extends { _id: string }> {
797798
}
798799

799800
private _createUpsertDocument(selector: Filter<T>, modifier: UpdateFilter<T>): T {
800-
const updater = new Updater(modifier);
801-
return updater.createUpsertDocument(selector);
801+
return createUpsertDocument(selector, modifier);
802802
}
803803

804804
private _findInOrderedResults(query: Query<T>, doc: T): number {
@@ -815,27 +815,27 @@ export class LocalCollection<T extends { _id: string }> {
815815
throw new MinimongoError('object missing from query');
816816
}
817817

818-
private _idsMatchedBySelector(selector: Filter<T> | T['_id']): T['_id'][] | null {
819-
if (_selectorIsId(selector)) {
818+
private _idsMatchedBySelector(selector: Filter<T> | T['_id']): readonly T['_id'][] | null {
819+
if (typeof selector === 'string') {
820820
return [selector];
821821
}
822822

823823
if (!selector) {
824824
return null;
825825
}
826826

827-
if (hasOwn.call(selector, '_id')) {
828-
if (_selectorIsId(selector._id)) {
827+
if ('_id' in selector) {
828+
if (typeof selector._id === 'string') {
829829
return [selector._id];
830830
}
831831

832832
if (
833833
selector._id &&
834-
Array.isArray((selector._id as FieldExpression<T['_id']>).$in) &&
835-
(selector._id as FieldExpression<T['_id']>).$in?.length &&
836-
(selector._id as FieldExpression<T['_id']>).$in?.every(_selectorIsId)
834+
Array.isArray((selector._id as FilterOperators<T['_id']>).$in) &&
835+
(selector._id as FilterOperators<T['_id']>).$in?.length &&
836+
(selector._id as FilterOperators<T['_id']>).$in?.every((id) => typeof id === 'string')
837837
) {
838-
return (selector._id as FieldExpression<T['_id']>).$in!;
838+
return (selector._id as FilterOperators<T['_id']>).$in!;
839839
}
840840

841841
return null;

0 commit comments

Comments
 (0)