diff --git a/app/actions/app/global.ts b/app/actions/app/global.ts index 81d83458b..b5aa1f40b 100644 --- a/app/actions/app/global.ts +++ b/app/actions/app/global.ts @@ -12,7 +12,7 @@ export const storeDeviceToken = async (token: string, prepareRecordsOnly = false } return operator.handleGlobal({ - global: [{id: GLOBAL_IDENTIFIERS.DEVICE_TOKEN, value: token}], + globals: [{id: GLOBAL_IDENTIFIERS.DEVICE_TOKEN, value: token}], prepareRecordsOnly, }); }; @@ -25,7 +25,7 @@ export const storeMultiServerTutorial = async (prepareRecordsOnly = false) => { } return operator.handleGlobal({ - global: [{id: GLOBAL_IDENTIFIERS.MULTI_SERVER_TUTORIAL, value: 'true'}], + globals: [{id: GLOBAL_IDENTIFIERS.MULTI_SERVER_TUTORIAL, value: 'true'}], prepareRecordsOnly, }); }; diff --git a/app/actions/local/channel.ts b/app/actions/local/channel.ts index b03dcda46..8b4c7b804 100644 --- a/app/actions/local/channel.ts +++ b/app/actions/local/channel.ts @@ -309,14 +309,14 @@ export const updateChannelInfoFromChannel = async (serverUrl: string, channel: C return {error: `${serverUrl} database not found`}; } - const newInfo = (await operator.handleChannelInfo({channelInfos: [{ + const newInfo = await operator.handleChannelInfo({channelInfos: [{ header: channel.header, purpose: channel.purpose, id: channel.id, }], - prepareRecordsOnly: true}))[0]; + prepareRecordsOnly: true}); if (!prepareRecordsOnly) { - operator.batchRecords([newInfo]); + operator.batchRecords(newInfo); } return {model: newInfo}; }; diff --git a/app/actions/local/thread.ts b/app/actions/local/thread.ts index 579de4db0..d75d4d15d 100644 --- a/app/actions/local/thread.ts +++ b/app/actions/local/thread.ts @@ -122,17 +122,13 @@ export const createThreadFromNewPost = async (serverUrl: string, post: Post, pre prepareRecordsOnly: true, skipSync: true, }); - if (threadParticipantModels?.length) { - models.push(...threadParticipantModels); - } + models.push(...threadParticipantModels); } else { // If the post is a root post, then we need to add it to the thread table const threadModels = await prepareThreadsFromReceivedPosts(operator, [post]); - if (threadModels?.length) { - models.push(...threadModels); - } + models.push(...threadModels); } - if (models.length && !prepareRecordsOnly) { + if (!prepareRecordsOnly) { await operator.batchRecords(models); } @@ -146,8 +142,6 @@ export const processReceivedThreads = async (serverUrl: string, threads: Thread[ return {error: `${serverUrl} database not found`}; } - const models: Model[] = []; - const posts: Post[] = []; const users: UserProfile[] = []; @@ -165,10 +159,6 @@ export const processReceivedThreads = async (serverUrl: string, threads: Thread[ prepareRecordsOnly: true, }); - if (postModels.length) { - models.push(...postModels); - } - const threadModels = await operator.handleThreads({ threads, teamId, @@ -176,20 +166,14 @@ export const processReceivedThreads = async (serverUrl: string, threads: Thread[ loadedInGlobalThreads, }); - if (threadModels.length) { - models.push(...threadModels); - } - const userModels = await operator.handleUsers({ users, prepareRecordsOnly: true, }); - if (userModels.length) { - models.push(...userModels); - } + const models = [...postModels, ...threadModels, ...userModels]; - if (models.length && !prepareRecordsOnly) { + if (!prepareRecordsOnly) { await operator.batchRecords(models); } return {models}; diff --git a/app/actions/remote/channel.ts b/app/actions/remote/channel.ts index 687e67277..aeef35e44 100644 --- a/app/actions/remote/channel.ts +++ b/app/actions/remote/channel.ts @@ -60,12 +60,10 @@ export const addMembersToChannel = async (serverUrl: string, channelId: string, if (!fetchOnly) { const modelPromises: Array> = []; - if (users) { - modelPromises.push(operator.handleUsers({ - users, - prepareRecordsOnly: true, - })); - } + modelPromises.push(operator.handleUsers({ + users, + prepareRecordsOnly: true, + })); modelPromises.push(operator.handleChannelMembership({ channelMemberships, prepareRecordsOnly: true, @@ -376,7 +374,7 @@ export const fetchMissingSidebarInfo = async (serverUrl: string, directChannels: if (result.data) { result.data.forEach((data) => { - if (data.users) { + if (data.users?.length) { users.push(...data.users); if (data.users.length > 1) { displayNameByChannel[data.channelId] = displayGroupMessageName(data.users, locale, teammateDisplayNameSetting, currentUserId); @@ -394,7 +392,6 @@ export const fetchMissingSidebarInfo = async (serverUrl: string, directChannels: } }); - const filteredUserIds = new Set(users.map((u) => u.id)); if (currentUserId) { const ownDirectChannel = directChannels.find((dm) => dm.name === getDirectChannelName(currentUserId, currentUserId)); const database = DatabaseManager.serverDatabases[serverUrl]?.database; @@ -402,30 +399,23 @@ export const fetchMissingSidebarInfo = async (serverUrl: string, directChannels: const currentUser = await getCurrentUser(database); ownDirectChannel.display_name = displayUsername(currentUser, locale, teammateDisplayNameSetting, false); } - filteredUserIds.add(currentUserId); } - const profiles = users.reduce((acc: UserProfile[], u) => { - if (!filteredUserIds.has(u.id)) { - acc.push(u); - } - return acc; - }, []); - if (!fetchOnly) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (operator) { const modelPromises: Array> = []; if (users.length) { - modelPromises.push(operator.handleUsers({users: profiles, prepareRecordsOnly: true})); + modelPromises.push(operator.handleUsers({users, prepareRecordsOnly: true})); + modelPromises.push(operator.handleChannel({channels: directChannels, prepareRecordsOnly: true})); } - modelPromises.push(operator.handleChannel({channels: directChannels, prepareRecordsOnly: true})); + const models = await Promise.all(modelPromises); await operator.batchRecords(models.flat()); } } - return {directChannels, users: profiles}; + return {directChannels, users}; }; export const joinChannel = async (serverUrl: string, userId: string, teamId: string, channelId?: string, channelName?: string, fetchOnly = false) => { @@ -721,9 +711,7 @@ export const createDirectChannel = async (serverUrl: string, userId: string, dis models.push(...userModels); } - if (models.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); fetchRolesIfNeeded(serverUrl, member.roles.split(' ')); return {data: created}; } catch (error) { @@ -846,17 +834,14 @@ export const createGroupChannel = async (serverUrl: string, userIds: string[]) = if (channelPromises.length) { const channelModels = await Promise.all(channelPromises); const models: Model[] = channelModels.flat(); + const userModels = await operator.handleUsers({users, prepareRecordsOnly: true}); const categoryModels = await addChannelToDefaultCategory(serverUrl, created, true); if (categoryModels.models?.length) { models.push(...categoryModels.models); } - if (users?.length) { - const userModels = await operator.handleUsers({users, prepareRecordsOnly: true}); - models.push(...userModels); - } - if (models.length) { - operator.batchRecords(models); - } + + models.push(...userModels); + operator.batchRecords(models); } } fetchRolesIfNeeded(serverUrl, member.roles.split(' ')); diff --git a/app/actions/remote/custom_emoji.ts b/app/actions/remote/custom_emoji.ts index f726486b5..b713ccf0f 100644 --- a/app/actions/remote/custom_emoji.ts +++ b/app/actions/remote/custom_emoji.ts @@ -23,12 +23,10 @@ export const fetchCustomEmojis = async (serverUrl: string, page = 0, perPage = G try { const data = await client.getCustomEmojis(page, perPage, sort); - if (data.length) { - await operator.handleCustomEmojis({ - emojis: data, - prepareRecordsOnly: false, - }); - } + await operator.handleCustomEmojis({ + emojis: data, + prepareRecordsOnly: false, + }); return {data}; } catch (error) { @@ -57,12 +55,10 @@ export const searchCustomEmojis = async (serverUrl: string, term: string) => { const exist = await queryCustomEmojisByName(operator.database, names).fetch(); const existingNames = new Set(exist.map((e) => e.name)); const emojis = data.filter((d) => !existingNames.has(d.name)); - if (emojis.length) { - await operator.handleCustomEmojis({ - emojis, - prepareRecordsOnly: false, - }); - } + await operator.handleCustomEmojis({ + emojis, + prepareRecordsOnly: false, + }); } return {data}; } catch (error) { diff --git a/app/actions/remote/entry/app.ts b/app/actions/remote/entry/app.ts index cabff6bf4..9c2265dfd 100644 --- a/app/actions/remote/entry/app.ts +++ b/app/actions/remote/entry/app.ts @@ -73,9 +73,7 @@ export const appEntry = async (serverUrl: string, since = 0) => { modelPromises.push(operator.handleRole({roles: rolesData.roles, prepareRecordsOnly: true})); } const models = await Promise.all(modelPromises); - if (models.length) { - await operator.batchRecords(models.flat()); - } + await operator.batchRecords(models.flat()); const {id: currentUserId, locale: currentUserLocale} = meData.user || (await getCurrentUser(database))!; const {config, license} = await getCommonSystemValues(database); diff --git a/app/actions/remote/entry/login.ts b/app/actions/remote/entry/login.ts index d2f019c4f..eff90c422 100644 --- a/app/actions/remote/entry/login.ts +++ b/app/actions/remote/entry/login.ts @@ -1,8 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Model} from '@nozbe/watermelondb'; - import {fetchMyChannelsForTeam, MyChannelsRequest} from '@actions/remote/channel'; import {MyPreferencesRequest, fetchMyPreferences} from '@actions/remote/preference'; import {fetchRolesIfNeeded, RolesRequest} from '@actions/remote/role'; @@ -167,9 +165,7 @@ export const loginEntry = async ({serverUrl, user, deviceToken}: AfterLoginArgs) } const models = await Promise.all(modelPromises); - if (models.length) { - await operator.batchRecords(models.flat() as Model[]); - } + await operator.batchRecords(models.flat()); const config = clData.config || {} as ClientConfig; const license = clData.license || {} as ClientLicense; diff --git a/app/actions/remote/entry/notification.ts b/app/actions/remote/entry/notification.ts index b98138cdb..8081f39a1 100644 --- a/app/actions/remote/entry/notification.ts +++ b/app/actions/remote/entry/notification.ts @@ -1,8 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Model} from '@nozbe/watermelondb'; - import {switchToChannel} from '@actions/local/channel'; import {markChannelAsRead} from '@actions/remote/channel'; import {fetchRoles} from '@actions/remote/role'; @@ -130,9 +128,7 @@ export const pushNotificationEntry = async (serverUrl: string, notification: Not } const models = await Promise.all(modelPromises); - if (models.length) { - await operator.batchRecords(models.flat() as Model[]); - } + await operator.batchRecords(models.flat()); const {id: currentUserId, locale: currentUserLocale} = meData.user || (await getCurrentUser(operator.database))!; const {config, license} = await getCommonSystemValues(operator.database); diff --git a/app/actions/remote/post.ts b/app/actions/remote/post.ts index faa510740..e901d1c92 100644 --- a/app/actions/remote/post.ts +++ b/app/actions/remote/post.ts @@ -102,9 +102,7 @@ export const createPost = async (serverUrl: string, post: Partial, files: const initialPostModels: Model[] = []; const filesModels = await operator.handleFiles({files, prepareRecordsOnly: true}); - if (filesModels.length) { - initialPostModels.push(...filesModels); - } + initialPostModels.push(...filesModels); const postModels = await operator.handlePosts({ actionType: ActionType.POSTS.RECEIVED_NEW, @@ -112,9 +110,7 @@ export const createPost = async (serverUrl: string, post: Partial, files: posts: [databasePost], prepareRecordsOnly: true, }); - if (postModels.length) { - initialPostModels.push(...postModels); - } + initialPostModels.push(...postModels); const customEmojis = await queryAllCustomEmojis(database).fetch(); const emojisInMessage = matchEmoticons(newPost.message); @@ -129,7 +125,7 @@ export const createPost = async (serverUrl: string, post: Partial, files: try { const created = await client.createPost(newPost); - const models: Model[] = await operator.handlePosts({ + const models = await operator.handlePosts({ actionType: ActionType.POSTS.RECEIVED_NEW, order: [created.id], posts: [created], @@ -163,7 +159,7 @@ export const createPost = async (serverUrl: string, post: Partial, files: ) { await removePost(serverUrl, databasePost); } else { - const models: Model[] = await operator.handlePosts({ + const models = await operator.handlePosts({ actionType: ActionType.POSTS.RECEIVED_NEW, order: [errorPost.id], posts: [errorPost], @@ -234,14 +230,11 @@ export const fetchPostsForChannel = async (serverUrl: string, channelId: string, previousPostId: data.previousPostId, prepareRecordsOnly: true, }); - if (postModels) { - models.push(...postModels); - } + models.push(...postModels); + if (authors.length) { const userModels = await operator.handleUsers({users: authors, prepareRecordsOnly: true}); - if (userModels.length) { - models.push(...userModels); - } + models.push(...userModels); } let lastPostAt = 0; @@ -318,9 +311,7 @@ export const fetchPosts = async (serverUrl: string, channelId: string, page = 0, models.push(...threadModels); } } - if (models.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); } return result; } catch (error) { @@ -425,9 +416,7 @@ export const fetchPostsSince = async (serverUrl: string, channelId: string, sinc models.push(...threadModels); } } - if (models.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); } return result; } catch (error) { @@ -536,9 +525,7 @@ export const fetchPostThread = async (serverUrl: string, postId: string, fetchOn models.push(...threadModels); } } - if (models.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); } return result; } catch (error) { @@ -737,6 +724,7 @@ export const fetchPostById = async (serverUrl: string, postId: string, fetchOnly prepareRecordsOnly: true, }); models.push(...posts); + if (authors?.length) { const users = await operator.handleUsers({ users: authors, @@ -969,9 +957,7 @@ export async function fetchSavedPosts(serverUrl: string, teamId?: string, channe return mdls; }); - if (models.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); return { order, diff --git a/app/actions/remote/reactions.ts b/app/actions/remote/reactions.ts index 30876d572..b7819dce0 100644 --- a/app/actions/remote/reactions.ts +++ b/app/actions/remote/reactions.ts @@ -52,9 +52,7 @@ export const addReaction = async (serverUrl: string, postId: string, emojiName: models.push(...recent); } - if (models.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); return {reaction}; } diff --git a/app/actions/remote/role.ts b/app/actions/remote/role.ts index 5f3c282f8..8a903a6dc 100644 --- a/app/actions/remote/role.ts +++ b/app/actions/remote/role.ts @@ -42,7 +42,7 @@ export const fetchRolesIfNeeded = async (serverUrl: string, updatedRoles: string try { const roles = await client.getRolesByNames(newRoles); - if (!fetchOnly && roles.length) { + if (!fetchOnly) { await operator.handleRole({ roles, prepareRecordsOnly: false, diff --git a/app/actions/remote/search.ts b/app/actions/remote/search.ts index f43968fac..70e7c8fb1 100644 --- a/app/actions/remote/search.ts +++ b/app/actions/remote/search.ts @@ -104,9 +104,7 @@ export async function fetchRecentMentions(serverUrl: string): Promise u.id !== excludeUserId)); - if (prepare) { + if (memberships.length) { + modelPromises.push(operator.handleChannelMembership({ + channelMemberships: memberships, + prepareRecordsOnly: true, + })); + } + if (users.size) { + const prepare = prepareUsers(operator, Array.from(users).filter((u) => u.id !== excludeUserId)); modelPromises.push(prepare); } - if (modelPromises.length) { - const models = await Promise.all(modelPromises); - await operator.batchRecords(models.flat()); - } + const models = await Promise.all(modelPromises); + await operator.batchRecords(models.flat()); } return {data}; @@ -195,9 +191,7 @@ export const updateMe = async (serverUrl: string, user: Partial) => operator.handleUsers({prepareRecordsOnly: false, users: [data]}); const updatedRoles: string[] = data.roles.split(' '); - if (updatedRoles.length) { - await fetchRolesIfNeeded(serverUrl, updatedRoles); - } + await fetchRolesIfNeeded(serverUrl, updatedRoles); } return {data}; @@ -323,6 +317,10 @@ export const fetchUsersByUsernames = async (serverUrl: string, usernames: string return result; }, {}); const usersToLoad = usernames.filter((username) => (username !== currentUser?.username && !exisitingUsersMap[username])); + if (!usersToLoad.length) { + return {users: []}; + } + const users = await client.getProfilesByUsernames([...new Set(usersToLoad)]); if (!fetchOnly) { @@ -507,9 +505,7 @@ export const updateAllUsersSince = async (serverUrl: string, since: number, fetc modelsToBatch.push(...models); } - if (modelsToBatch.length) { - await operator.batchRecords(modelsToBatch); - } + await operator.batchRecords(modelsToBatch); } } catch { // Do nothing diff --git a/app/actions/websocket/channel.ts b/app/actions/websocket/channel.ts index cc21594d7..ef981f05a 100644 --- a/app/actions/websocket/channel.ts +++ b/app/actions/websocket/channel.ts @@ -95,7 +95,7 @@ export async function handleChannelUpdatedEvent(serverUrl: string, msg: any) { const models: Model[] = await operator.handleChannel({channels: [updatedChannel], prepareRecordsOnly: true}); const infoModel = await updateChannelInfoFromChannel(serverUrl, updatedChannel, true); if (infoModel.model) { - models.push(infoModel.model); + models.push(...infoModel.model); } operator.batchRecords(models); } catch { @@ -188,14 +188,12 @@ export async function handleDirectAddedEvent(serverUrl: string, msg: any) { models.push(...categoryModels.models); } - if (users?.length) { + if (users.length) { const userModels = await operator.handleUsers({users, prepareRecordsOnly: true}); models.push(...userModels); } - if (models.length) { - operator.batchRecords(models); - } + operator.batchRecords(models); } catch { // do nothing } @@ -235,7 +233,7 @@ export async function handleUserAddedToChannelEvent(serverUrl: string, msg: any) } const {posts, order, authors, actionType, previousPostId} = await fetchPostsForChannel(serverUrl, channelId, true); - if (posts?.length && order && actionType) { + if (actionType) { models.push(...await operator.handlePosts({ actionType, order, @@ -253,9 +251,7 @@ export async function handleUserAddedToChannelEvent(serverUrl: string, msg: any) if (!addedUser) { // TODO Potential improvement https://mattermost.atlassian.net/browse/MM-40581 const {users} = await fetchUsersByIds(serverUrl, [userId], true); - if (users) { - models.push(...await operator.handleUsers({users, prepareRecordsOnly: true})); - } + models.push(...await operator.handleUsers({users, prepareRecordsOnly: true})); } const channel = await getChannelById(database, channelId); if (channel) { diff --git a/app/actions/websocket/posts.ts b/app/actions/websocket/posts.ts index 34462cd05..9ca64ede2 100644 --- a/app/actions/websocket/posts.ts +++ b/app/actions/websocket/posts.ts @@ -59,9 +59,7 @@ export async function handleNewPostEvent(serverUrl: string, msg: WebSocketMessag prepareRecordsOnly: true, }); - if (postModels?.length) { - models.push(...postModels); - } + models.push(...postModels); const isCRTEnabled = await getIsCRTEnabled(database); if (isCRTEnabled) { @@ -120,9 +118,7 @@ export async function handleNewPostEvent(serverUrl: string, msg: WebSocketMessag const {authors} = await fetchPostAuthors(serverUrl, [post], true); if (authors?.length) { const authorsModels = await operator.handleUsers({users: authors, prepareRecordsOnly: true}); - if (authorsModels.length) { - models.push(...authorsModels); - } + models.push(...authorsModels); } if (!shouldIgnorePost(post)) { @@ -191,9 +187,7 @@ export async function handlePostEdited(serverUrl: string, msg: WebSocketMessage) const {authors} = await fetchPostAuthors(serverUrl, [post], true); if (authors?.length) { const authorsModels = await operator.handleUsers({users: authors, prepareRecordsOnly: true}); - if (authorsModels.length) { - models.push(...authorsModels); - } + models.push(...authorsModels); } const postModels = await operator.handlePosts({ @@ -202,13 +196,9 @@ export async function handlePostEdited(serverUrl: string, msg: WebSocketMessage) posts: [post], prepareRecordsOnly: true, }); - if (postModels.length) { - models.push(...postModels); - } + models.push(...postModels); - if (models.length) { - operator.batchRecords(models); - } + operator.batchRecords(models); } export async function handlePostDeleted(serverUrl: string, msg: WebSocketMessage) { diff --git a/app/actions/websocket/roles.ts b/app/actions/websocket/roles.ts index 40a1f84e2..ed7433feb 100644 --- a/app/actions/websocket/roles.ts +++ b/app/actions/websocket/roles.ts @@ -54,9 +54,7 @@ export async function handleUserRoleUpdatedEvent(serverUrl: string, msg: WebSock prepareRecordsOnly: true, }); - if (preparedRoleModels.length) { - models.push(...preparedRoleModels); - } + models.push(...preparedRoleModels); } // update User Table record @@ -68,9 +66,7 @@ export async function handleUserRoleUpdatedEvent(serverUrl: string, msg: WebSock models.push(user); } - if (models?.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); } export async function handleTeamMemberRoleUpdatedEvent(serverUrl: string, msg: WebSocketMessage): Promise { @@ -113,13 +109,9 @@ export async function handleTeamMemberRoleUpdatedEvent(serverUrl: string, msg: W myTeams, }); - if (myTeamRecords.length) { - models.push(...myTeamRecords); - } + models.push(...myTeamRecords); - if (models?.length) { - await operator.batchRecords(models); - } + await operator.batchRecords(models); } catch { // do nothing } diff --git a/app/actions/websocket/teams.ts b/app/actions/websocket/teams.ts index 7c5cd2b5d..cb6c142e1 100644 --- a/app/actions/websocket/teams.ts +++ b/app/actions/websocket/teams.ts @@ -101,9 +101,9 @@ export async function handleUserAddedToTeamEvent(serverUrl: string, msg: WebSock rolesToLoad.add(role); } const serverRoles = await fetchRolesIfNeeded(serverUrl, Array.from(rolesToLoad), true); - if (serverRoles.roles!.length) { + if (serverRoles.roles?.length) { const preparedRoleModels = database.operator.handleRole({ - roles: serverRoles.roles!, + roles: serverRoles.roles, prepareRecordsOnly: true, }); modelPromises.push(preparedRoleModels); @@ -115,10 +115,8 @@ export async function handleUserAddedToTeamEvent(serverUrl: string, msg: WebSock modelPromises.push(...prepareMyTeams(database.operator, teams, teamMemberships)); } - if (modelPromises.length) { - const models = await Promise.all(modelPromises); - await database.operator.batchRecords(models.flat()); - } + const models = await Promise.all(modelPromises); + await database.operator.batchRecords(models.flat()); delete addingTeam[teamId]; } diff --git a/app/database/exceptions/data_operator_exception.ts b/app/database/exceptions/data_operator_exception.ts deleted file mode 100644 index 5e3ac68e1..000000000 --- a/app/database/exceptions/data_operator_exception.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -/** - * DataOperatorException: This exception can be used whenever an issue arises at the operator level. For example, if a required field is missing. - */ -class DataOperatorException extends Error { - error: Error | undefined; - constructor(message: string, error?: Error) { - super(message); - this.name = 'DatabaseOperatorException'; - this.error = error; - } -} -export default DataOperatorException; diff --git a/app/database/operator/app_data_operator/index.test.ts b/app/database/operator/app_data_operator/index.test.ts index a10442a21..68edcfdd6 100644 --- a/app/database/operator/app_data_operator/index.test.ts +++ b/app/database/operator/app_data_operator/index.test.ts @@ -66,17 +66,17 @@ describe('** APP DATA OPERATOR **', () => { expect(appOperator).toBeTruthy(); const spyOnHandleRecords = jest.spyOn(appOperator as any, 'handleRecords'); - const global: IdValue[] = [{id: 'global-1-name', value: 'global-1-value'}]; + const globals: IdValue[] = [{id: 'global-1-name', value: 'global-1-value'}]; await appOperator?.handleGlobal({ - global, + globals, prepareRecordsOnly: false, }); expect(spyOnHandleRecords).toHaveBeenCalledWith({ fieldName: 'id', transformer: transformGlobalRecord, - createOrUpdateRawValues: global, + createOrUpdateRawValues: globals, tableName: 'Global', prepareRecordsOnly: false, }); diff --git a/app/database/operator/app_data_operator/index.ts b/app/database/operator/app_data_operator/index.ts index 2d41c0cdc..c0b72aaec 100644 --- a/app/database/operator/app_data_operator/index.ts +++ b/app/database/operator/app_data_operator/index.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import {buildAppInfoKey} from '@database/operator/app_data_operator/comparator'; import {transformInfoRecord, transformGlobalRecord} from '@database/operator/app_data_operator/transformers'; import BaseDataOperator from '@database/operator/base_data_operator'; @@ -13,11 +12,13 @@ import type {HandleInfoArgs, HandleGlobalArgs} from '@typings/database/database' const {APP: {INFO, GLOBAL}} = MM_TABLES; export default class AppDataOperator extends BaseDataOperator { - handleInfo = ({info, prepareRecordsOnly = true}: HandleInfoArgs) => { - if (!info.length) { - throw new DataOperatorException( - 'An empty "values" array has been passed to the handleInfo', + handleInfo = async ({info, prepareRecordsOnly = true}: HandleInfoArgs) => { + if (!info?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "info" array has been passed to the handleInfo', ); + return []; } return this.handleRecords({ @@ -30,18 +31,20 @@ export default class AppDataOperator extends BaseDataOperator { }); }; - handleGlobal = async ({global, prepareRecordsOnly = true}: HandleGlobalArgs) => { - if (!global.length) { - throw new DataOperatorException( - 'An empty "values" array has been passed to the handleGlobal', + handleGlobal = async ({globals, prepareRecordsOnly = true}: HandleGlobalArgs) => { + if (!globals?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "globals" array has been passed to the handleGlobal', ); + return []; } return this.handleRecords({ fieldName: 'id', transformer: transformGlobalRecord, prepareRecordsOnly, - createOrUpdateRawValues: getUniqueRawsBy({raws: global, key: 'id'}), + createOrUpdateRawValues: getUniqueRawsBy({raws: globals, key: 'id'}), tableName: GLOBAL, }); }; diff --git a/app/database/operator/base_data_operator/index.ts b/app/database/operator/base_data_operator/index.ts index 6046f2bec..99f237cc2 100644 --- a/app/database/operator/base_data_operator/index.ts +++ b/app/database/operator/base_data_operator/index.ts @@ -3,7 +3,6 @@ import {Database, Q} from '@nozbe/watermelondb'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import { getRangeOfValues, getValidRecordsForUpdate, @@ -52,7 +51,7 @@ export default class BaseDataOperator { const columnValues: string[] = getRangeOfValues({fieldName, raws: rawValues}); if (!columnValues.length && rawValues.length) { - throw new DataOperatorException( + throw new Error( `Invalid "fieldName" or "tableName" has been passed to the processRecords method for tableName ${tableName} fieldName ${fieldName}`, ); } @@ -131,7 +130,9 @@ export default class BaseDataOperator { */ prepareRecords = async ({tableName, createRaws, deleteRaws, updateRaws, transformer}: OperationArgs): Promise => { if (!this.database) { - throw new DataOperatorException('Database not defined'); + // eslint-disable-next-line no-console + console.warn('Database not defined in prepareRecords'); + return []; } let preparedRecords: Array> = []; @@ -194,7 +195,8 @@ export default class BaseDataOperator { }); } } catch (e) { - throw new DataOperatorException('batchRecords error ', e as Error); + // eslint-disable-next-line no-console + console.warn('batchRecords error ', e as Error); } }; @@ -211,9 +213,11 @@ export default class BaseDataOperator { */ handleRecords = async ({buildKeyRecordBy, fieldName, transformer, createOrUpdateRawValues, deleteRawValues = [], tableName, prepareRecordsOnly = true}: HandleRecordsArgs): Promise => { if (!createOrUpdateRawValues.length) { - throw new DataOperatorException( + // eslint-disable-next-line no-console + console.warn( `An empty "rawValues" array has been passed to the handleRecords method for tableName ${tableName}`, ); + return []; } const {createRaws, deleteRaws, updateRaws} = await this.processRecords({ diff --git a/app/database/operator/server_data_operator/handlers/category.ts b/app/database/operator/server_data_operator/handlers/category.ts index d4400acaa..db2c6f044 100644 --- a/app/database/operator/server_data_operator/handlers/category.ts +++ b/app/database/operator/server_data_operator/handlers/category.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import { transformCategoryChannelRecord, transformCategoryRecord, @@ -36,10 +35,12 @@ const CategoryHandler = (superclass: any) => class extends superclass { * @returns {Promise} */ handleCategories = async ({categories, prepareRecordsOnly = true}: HandleCategoryArgs): Promise => { - if (!categories.length) { - throw new DataOperatorException( - 'An empty "categories" array has been passed to the handleCategories method', + if (!categories?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "categories" array has been passed to the handleCategories method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: categories, key: 'id'}); @@ -62,10 +63,13 @@ const CategoryHandler = (superclass: any) => class extends superclass { * @returns {Promise} */ handleCategoryChannels = async ({categoryChannels, prepareRecordsOnly = true}: HandleCategoryChannelArgs): Promise => { - if (!categoryChannels.length) { - throw new DataOperatorException( - 'An empty "categoryChannels" array has been passed to the handleCategories method', + if (!categoryChannels?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "categoryChannels" array has been passed to the handleCategories method', ); + + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: categoryChannels, key: 'id'}); diff --git a/app/database/operator/server_data_operator/handlers/channel.ts b/app/database/operator/server_data_operator/handlers/channel.ts index 5d1a65466..72b0cafe3 100644 --- a/app/database/operator/server_data_operator/handlers/channel.ts +++ b/app/database/operator/server_data_operator/handlers/channel.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import { buildMyChannelKey, buildChannelMembershipKey, @@ -48,11 +47,13 @@ const ChannelHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleChannel = ({channels, prepareRecordsOnly = true}: HandleChannelArgs): Promise => { - if (!channels.length) { - throw new DataOperatorException( - 'An empty "channels" array has been passed to the handleChannel method', + handleChannel = async ({channels, prepareRecordsOnly = true}: HandleChannelArgs): Promise => { + if (!channels?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "channels" array has been passed to the handleChannel method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: channels, key: 'id'}); @@ -74,11 +75,14 @@ const ChannelHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleMyChannelSettings = ({settings, prepareRecordsOnly = true}: HandleMyChannelSettingsArgs): Promise => { - if (!settings.length) { - throw new DataOperatorException( - 'An empty "settings" array has been passed to the handleMyChannelSettings method', + handleMyChannelSettings = async ({settings, prepareRecordsOnly = true}: HandleMyChannelSettingsArgs): Promise => { + if (!settings?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "settings" array has been passed to the handleMyChannelSettings method', ); + + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: settings, key: 'id'}); @@ -101,11 +105,14 @@ const ChannelHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleChannelInfo = ({channelInfos, prepareRecordsOnly = true}: HandleChannelInfoArgs): Promise => { - if (!channelInfos.length) { - throw new DataOperatorException( + handleChannelInfo = async ({channelInfos, prepareRecordsOnly = true}: HandleChannelInfoArgs): Promise => { + if (!channelInfos?.length) { + // eslint-disable-next-line no-console + console.warn( 'An empty "channelInfos" array has been passed to the handleMyChannelSettings method', ); + + return []; } const createOrUpdateRawValues = getUniqueRawsBy({ @@ -130,11 +137,23 @@ const ChannelHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleMyChannel = ({channels, myChannels, prepareRecordsOnly = true}: HandleMyChannelArgs): Promise => { - if (!myChannels.length) { - throw new DataOperatorException( - 'An empty "myChannels" array has been passed to the handleMyChannel method', + handleMyChannel = async ({channels, myChannels, prepareRecordsOnly = true}: HandleMyChannelArgs): Promise => { + if (!myChannels?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "myChannels" array has been passed to the handleMyChannel method', ); + + return []; + } + + if (!channels?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "channels" array has been passed to the handleMyChannel method', + ); + + return []; } const channelMap = channels.reduce((result: Record, channel) => { @@ -173,11 +192,14 @@ const ChannelHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleChannelMembership = ({channelMemberships, prepareRecordsOnly = true}: HandleChannelMembershipArgs): Promise => { - if (!channelMemberships.length) { - throw new DataOperatorException( + handleChannelMembership = async ({channelMemberships, prepareRecordsOnly = true}: HandleChannelMembershipArgs): Promise => { + if (!channelMemberships?.length) { + // eslint-disable-next-line no-console + console.warn( 'An empty "channelMemberships" array has been passed to the handleChannelMembership method', ); + + return []; } const memberships: ChannelMember[] = channelMemberships.map((m) => ({ diff --git a/app/database/operator/server_data_operator/handlers/index.test.ts b/app/database/operator/server_data_operator/handlers/index.test.ts index 4fd016dfa..1f8ab18c4 100644 --- a/app/database/operator/server_data_operator/handlers/index.test.ts +++ b/app/database/operator/server_data_operator/handlers/index.test.ts @@ -1,7 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import DataOperatorException from '@database/exceptions/data_operator_exception'; import DatabaseManager from '@database/manager'; import { transformCustomEmojiRecord, @@ -115,6 +114,6 @@ describe('*** DataOperator: Base Handlers tests ***', () => { createOrUpdateRawValues: [{id: 'tos-1', value: '1'}], prepareRecordsOnly: false, }), - ).rejects.toThrow(DataOperatorException); + ).rejects.toThrow(Error); }); }); diff --git a/app/database/operator/server_data_operator/handlers/index.ts b/app/database/operator/server_data_operator/handlers/index.ts index 8347e6cd8..348072513 100644 --- a/app/database/operator/server_data_operator/handlers/index.ts +++ b/app/database/operator/server_data_operator/handlers/index.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import BaseDataOperator from '@database/operator/base_data_operator'; import { transformCustomEmojiRecord, @@ -20,11 +19,13 @@ import type SystemModel from '@typings/database/models/servers/system'; const {SERVER: {CUSTOM_EMOJI, ROLE, SYSTEM}} = MM_TABLES; export default class ServerDataOperatorBase extends BaseDataOperator { - handleRole = ({roles, prepareRecordsOnly = true}: HandleRoleArgs) => { - if (!roles.length) { - throw new DataOperatorException( - 'An empty "values" array has been passed to the handleRole', + handleRole = async ({roles, prepareRecordsOnly = true}: HandleRoleArgs) => { + if (!roles?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "roles" array has been passed to the handleRole', ); + return []; } return this.handleRecords({ @@ -36,11 +37,13 @@ export default class ServerDataOperatorBase extends BaseDataOperator { }) as Promise; }; - handleCustomEmojis = ({emojis, prepareRecordsOnly = true}: HandleCustomEmojiArgs) => { - if (!emojis.length) { - throw new DataOperatorException( - 'An empty "values" array has been passed to the handleCustomEmojis', + handleCustomEmojis = async ({emojis, prepareRecordsOnly = true}: HandleCustomEmojiArgs) => { + if (!emojis?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "emojis" array has been passed to the handleCustomEmojis', ); + return []; } return this.handleRecords({ @@ -52,11 +55,13 @@ export default class ServerDataOperatorBase extends BaseDataOperator { }) as Promise; }; - handleSystem = ({systems, prepareRecordsOnly = true}: HandleSystemArgs) => { - if (!systems.length) { - throw new DataOperatorException( - 'An empty "values" array has been passed to the handleSystem', + handleSystem = async ({systems, prepareRecordsOnly = true}: HandleSystemArgs) => { + if (!systems?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "systems" array has been passed to the handleSystem', ); + return []; } return this.handleRecords({ diff --git a/app/database/operator/server_data_operator/handlers/post.ts b/app/database/operator/server_data_operator/handlers/post.ts index 5820c4b78..a9fea5b0f 100644 --- a/app/database/operator/server_data_operator/handlers/post.ts +++ b/app/database/operator/server_data_operator/handlers/post.ts @@ -5,7 +5,6 @@ import {Q} from '@nozbe/watermelondb'; import {ActionType} from '@constants'; import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import {buildDraftKey} from '@database/operator/server_data_operator/comparators'; import { transformDraftRecord, @@ -48,11 +47,13 @@ const PostHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleDraft = ({drafts, prepareRecordsOnly = true}: HandleDraftArgs): Promise => { - if (!drafts.length) { - throw new DataOperatorException( - 'An empty "drafts" array has been passed to the handleDraft method', + handleDraft = async ({drafts, prepareRecordsOnly = true}: HandleDraftArgs): Promise => { + if (!drafts?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "drafts" array has been passed to the handleDraft method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: drafts, key: 'channel_id'}); @@ -81,7 +82,11 @@ const PostHandler = (superclass: any) => class extends superclass { const tableName = POST; // We rely on the posts array; if it is empty, we stop processing - if (!posts.length) { + if (!posts?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "posts" array has been passed to the handlePosts method', + ); return []; } @@ -229,7 +234,11 @@ const PostHandler = (superclass: any) => class extends superclass { * @returns {Promise} */ handleFiles = async ({files, prepareRecordsOnly}: HandleFilesArgs): Promise => { - if (!files.length) { + if (!files?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "files" array has been passed to the handleFiles method', + ); return []; } @@ -264,6 +273,10 @@ const PostHandler = (superclass: any) => class extends superclass { */ handlePostsInThread = async (postsMap: Record, actionType: never, prepareRecordsOnly = false): Promise => { if (!postsMap || !Object.keys(postsMap).length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "postsMap" object has been passed to the handlePostsInThread method', + ); return []; } switch (actionType) { @@ -291,6 +304,10 @@ const PostHandler = (superclass: any) => class extends superclass { const permittedActions = Object.values(ActionType.POSTS); if (!posts.length || !permittedActions.includes(actionType)) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "posts" array or an non-supported actionType has been passed to the handlePostsInChannel method', + ); return []; } diff --git a/app/database/operator/server_data_operator/handlers/posts_in_channel.ts b/app/database/operator/server_data_operator/handlers/posts_in_channel.ts index 11acb478c..22374cc59 100644 --- a/app/database/operator/server_data_operator/handlers/posts_in_channel.ts +++ b/app/database/operator/server_data_operator/handlers/posts_in_channel.ts @@ -56,8 +56,12 @@ const PostsInChannelHandler = (superclass: any) => class extends superclass { return result; }; - handleReceivedPostsInChannel = async (posts: Post[], prepareRecordsOnly = false): Promise => { - if (!posts.length) { + handleReceivedPostsInChannel = async (posts?: Post[], prepareRecordsOnly = false): Promise => { + if (!posts?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "posts" array has been passed to the handleReceivedPostsInChannel method', + ); return []; } @@ -120,7 +124,11 @@ const PostsInChannelHandler = (superclass: any) => class extends superclass { }; handleReceivedPostsInChannelSince = async (posts: Post[], prepareRecordsOnly = false): Promise => { - if (!posts.length) { + if (!posts?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "posts" array has been passed to the handleReceivedPostsInChannelSince method', + ); return []; } @@ -167,7 +175,11 @@ const PostsInChannelHandler = (superclass: any) => class extends superclass { }; handleReceivedPostsInChannelBefore = async (posts: Post[], prepareRecordsOnly = false): Promise => { - if (!posts.length) { + if (!posts?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "posts" array has been passed to the handleReceivedPostsInChannelBefore method', + ); return []; } @@ -217,7 +229,11 @@ const PostsInChannelHandler = (superclass: any) => class extends superclass { }; handleReceivedPostForChannel = async (posts: Post[], prepareRecordsOnly = false): Promise => { - if (!posts.length) { + if (!posts?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "posts" array has been passed to the handleReceivedPostForChannel method', + ); return []; } diff --git a/app/database/operator/server_data_operator/handlers/posts_in_thread.ts b/app/database/operator/server_data_operator/handlers/posts_in_thread.ts index a546adeeb..413303f38 100644 --- a/app/database/operator/server_data_operator/handlers/posts_in_thread.ts +++ b/app/database/operator/server_data_operator/handlers/posts_in_thread.ts @@ -19,7 +19,11 @@ const {POSTS_IN_THREAD} = Database.MM_TABLES.SERVER; const PostsInThreadHandler = (superclass: any) => class extends superclass { handleReceivedPostsInThread = async (postsMap: Record, prepareRecordsOnly = false): Promise => { - if (!Object.keys(postsMap).length) { + if (!postsMap || !Object.keys(postsMap).length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "postsMap" object has been passed to the handleReceivedPostsInThread method', + ); return []; } diff --git a/app/database/operator/server_data_operator/handlers/reaction.ts b/app/database/operator/server_data_operator/handlers/reaction.ts index c9eabc268..4c98612f1 100644 --- a/app/database/operator/server_data_operator/handlers/reaction.ts +++ b/app/database/operator/server_data_operator/handlers/reaction.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import {transformReactionRecord} from '@database/operator/server_data_operator/transformers/reaction'; import {sanitizeReactions} from '@database/operator/utils/reaction'; @@ -29,10 +28,12 @@ const ReactionHandler = (superclass: any) => class extends superclass { handleReactions = async ({postsReactions, prepareRecordsOnly, skipSync}: HandleReactionsArgs): Promise => { const batchRecords: ReactionModel[] = []; - if (!postsReactions.length) { - throw new DataOperatorException( - 'An empty "reactions" array has been passed to the handleReactions method', + if (!postsReactions?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "postsReactions" array has been passed to the handleReactions method', ); + return []; } for await (const postReactions of postsReactions) { diff --git a/app/database/operator/server_data_operator/handlers/team.ts b/app/database/operator/server_data_operator/handlers/team.ts index 19d6e099e..61853c734 100644 --- a/app/database/operator/server_data_operator/handlers/team.ts +++ b/app/database/operator/server_data_operator/handlers/team.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import { buildTeamMembershipKey, buildTeamSearchHistoryKey, @@ -51,11 +50,13 @@ const TeamHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleTeamMemberships = ({teamMemberships, prepareRecordsOnly = true}: HandleTeamMembershipArgs): Promise => { - if (!teamMemberships.length) { - throw new DataOperatorException( - 'An empty "teamMemberships" array has been passed to the handleTeamMemberships method', + handleTeamMemberships = async ({teamMemberships, prepareRecordsOnly = true}: HandleTeamMembershipArgs): Promise => { + if (!teamMemberships?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "teamMemberships" array has been passed to the handleTeamMemberships method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: teamMemberships, key: 'team_id'}); @@ -78,11 +79,13 @@ const TeamHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleTeam = ({teams, prepareRecordsOnly = true}: HandleTeamArgs): Promise => { - if (!teams.length) { - throw new DataOperatorException( - 'An empty "teams" array has been passed to the handleTeam method', + handleTeam = async ({teams, prepareRecordsOnly = true}: HandleTeamArgs): Promise => { + if (!teams?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "teams" array has been passed to the handleTeam method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: teams, key: 'id'}); @@ -104,11 +107,13 @@ const TeamHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleTeamChannelHistory = ({teamChannelHistories, prepareRecordsOnly = true}: HandleTeamChannelHistoryArgs): Promise => { - if (!teamChannelHistories.length) { - throw new DataOperatorException( - 'An empty "teamChannelHistories" array has been passed to the handleTeamChannelHistory method', + handleTeamChannelHistory = async ({teamChannelHistories, prepareRecordsOnly = true}: HandleTeamChannelHistoryArgs): Promise => { + if (!teamChannelHistories?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "teamChannelHistories" array has been passed to the handleTeamChannelHistory method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: teamChannelHistories, key: 'id'}); @@ -130,11 +135,13 @@ const TeamHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleTeamSearchHistory = ({teamSearchHistories, prepareRecordsOnly = true}: HandleTeamSearchHistoryArgs): Promise => { - if (!teamSearchHistories.length) { - throw new DataOperatorException( - 'An empty "teamSearchHistories" array has been passed to the handleTeamSearchHistory method', + handleTeamSearchHistory = async ({teamSearchHistories, prepareRecordsOnly = true}: HandleTeamSearchHistoryArgs): Promise => { + if (!teamSearchHistories?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "teamSearchHistories" array has been passed to the handleTeamSearchHistory method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: teamSearchHistories, key: 'term'}); @@ -157,11 +164,13 @@ const TeamHandler = (superclass: any) => class extends superclass { * @throws DataOperatorException * @returns {Promise} */ - handleMyTeam = ({myTeams, prepareRecordsOnly = true}: HandleMyTeamArgs): Promise => { - if (!myTeams.length) { - throw new DataOperatorException( - 'An empty "myTeams" array has been passed to the handleSlashCommand method', + handleMyTeam = async ({myTeams, prepareRecordsOnly = true}: HandleMyTeamArgs): Promise => { + if (!myTeams?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "myTeams" array has been passed to the handleMyTeam method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: myTeams, key: 'id'}); diff --git a/app/database/operator/server_data_operator/handlers/thread.ts b/app/database/operator/server_data_operator/handlers/thread.ts index 35793f4ff..c64a11429 100644 --- a/app/database/operator/server_data_operator/handlers/thread.ts +++ b/app/database/operator/server_data_operator/handlers/thread.ts @@ -4,7 +4,6 @@ import Model from '@nozbe/watermelondb/Model'; import {Database} from '@constants'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import { transformThreadRecord, transformThreadParticipantRecord, @@ -36,10 +35,12 @@ const ThreadHandler = (superclass: any) => class extends superclass { * @returns {Promise} */ handleThreads = async ({threads, teamId, loadedInGlobalThreads, prepareRecordsOnly = false}: HandleThreadsArgs): Promise => { - if (!threads.length) { - throw new DataOperatorException( - 'An empty "threads" array has been passed to the handleThreads method', + if (!threads?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "threads" array has been passed to the handleThreads method', ); + return []; } // Get unique threads in case they are duplicated @@ -105,10 +106,12 @@ const ThreadHandler = (superclass: any) => class extends superclass { handleThreadParticipants = async ({threadsParticipants, prepareRecordsOnly, skipSync = false}: HandleThreadParticipantsArgs): Promise => { const batchRecords: ThreadParticipantModel[] = []; - if (!threadsParticipants.length) { - throw new DataOperatorException( - 'An empty "thread participants" array has been passed to the handleThreadParticipants method', + if (!threadsParticipants?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "threadParticipants" array has been passed to the handleThreadParticipants method', ); + return []; } for await (const threadParticipant of threadsParticipants) { diff --git a/app/database/operator/server_data_operator/handlers/thread_in_team.ts b/app/database/operator/server_data_operator/handlers/thread_in_team.ts index a9118e2e8..95a28a9a1 100644 --- a/app/database/operator/server_data_operator/handlers/thread_in_team.ts +++ b/app/database/operator/server_data_operator/handlers/thread_in_team.ts @@ -18,7 +18,11 @@ const {THREADS_IN_TEAM} = MM_TABLES.SERVER; const ThreadInTeamHandler = (superclass: any) => class extends superclass { handleThreadInTeam = async ({threadsMap, loadedInGlobalThreads, prepareRecordsOnly = false}: HandleThreadInTeamArgs): Promise => { - if (!Object.keys(threadsMap).length) { + if (!threadsMap || !Object.keys(threadsMap).length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "threadsMap" object has been passed to the handleReceivedPostForChannel method', + ); return []; } diff --git a/app/database/operator/server_data_operator/handlers/user.ts b/app/database/operator/server_data_operator/handlers/user.ts index 089d5da63..5a4e78520 100644 --- a/app/database/operator/server_data_operator/handlers/user.ts +++ b/app/database/operator/server_data_operator/handlers/user.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; import {buildPreferenceKey} from '@database/operator/server_data_operator/comparators'; import { transformPreferenceRecord, @@ -34,10 +33,12 @@ const UserHandler = (superclass: any) => class extends superclass { * @returns {Promise} */ handlePreferences = async ({preferences, prepareRecordsOnly = true, sync = false}: HandlePreferencesArgs): Promise => { - if (!preferences.length) { - throw new DataOperatorException( - 'An empty "preferences" array has been passed to the handlePreferences method', + if (!preferences?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "preferences" array has been passed to the handlePreferences method', ); + return []; } // WE NEED TO SYNC THE PREFS FROM WHAT WE GOT AND WHAT WE HAVE @@ -86,10 +87,12 @@ const UserHandler = (superclass: any) => class extends superclass { * @returns {Promise} */ handleUsers = async ({users, prepareRecordsOnly = true}: HandleUsersArgs): Promise => { - if (!users.length) { - throw new DataOperatorException( - 'An empty "users" array has been passed to the handleUsers method', + if (!users?.length) { + // eslint-disable-next-line no-console + console.warn( + 'An empty or undefined "users" array has been passed to the handleUsers method', ); + return []; } const createOrUpdateRawValues = getUniqueRawsBy({raws: users, key: 'id'}); diff --git a/app/database/operator/utils/post.ts b/app/database/operator/utils/post.ts index 300f1227a..e81f972b5 100644 --- a/app/database/operator/utils/post.ts +++ b/app/database/operator/utils/post.ts @@ -38,7 +38,7 @@ export const sanitizePosts = ({posts, orders}: SanitizePostsArgs) => { * @param {string} chainPosts.previousPostId * @returns {Post[]} */ -export const createPostsChain = ({order, posts, previousPostId = ''}: ChainPostsArgs) => { +export const createPostsChain = ({order = [], posts, previousPostId = ''}: ChainPostsArgs) => { const postsByIds = posts.reduce((result: Record, p) => { result[p.id] = p; return result; diff --git a/app/queries/servers/categories.ts b/app/queries/servers/categories.ts index 6c7a37998..be3f974d1 100644 --- a/app/queries/servers/categories.ts +++ b/app/queries/servers/categories.ts @@ -51,11 +51,7 @@ export async function prepareCategoryChannels( }); }); - if (categoryChannels.length) { - return operator.handleCategoryChannels({categoryChannels, prepareRecordsOnly: true}); - } - - return []; + return operator.handleCategoryChannels({categoryChannels, prepareRecordsOnly: true}); } catch (e) { return []; } diff --git a/app/queries/servers/preference.ts b/app/queries/servers/preference.ts index 0112ef6fb..7d19c80d6 100644 --- a/app/queries/servers/preference.ts +++ b/app/queries/servers/preference.ts @@ -15,15 +15,11 @@ import type PreferenceModel from '@typings/database/models/servers/preference'; const {SERVER: {PREFERENCE}} = MM_TABLES; export async function prepareMyPreferences(operator: ServerDataOperator, preferences: PreferenceType[], sync = false): Promise { - try { - return operator.handlePreferences({ - prepareRecordsOnly: true, - preferences, - sync, - }); - } catch { - return []; - } + return operator.handlePreferences({ + prepareRecordsOnly: true, + preferences, + sync, + }); } export const queryPreferencesByCategoryAndName = (database: Database, category: string, name?: string, value?: string) => { diff --git a/app/queries/servers/thread.ts b/app/queries/servers/thread.ts index e6b78d27a..43ccdb0a7 100644 --- a/app/queries/servers/thread.ts +++ b/app/queries/servers/thread.ts @@ -83,9 +83,7 @@ export const prepareThreadsFromReceivedPosts = async (operator: ServerDataOperat }); if (threads.length) { const threadModels = await operator.handleThreads({threads, prepareRecordsOnly: true}); - if (threadModels.length) { - models.push(...threadModels); - } + models.push(...threadModels); } return models; diff --git a/app/queries/servers/user.ts b/app/queries/servers/user.ts index 884e74123..39d63d861 100644 --- a/app/queries/servers/user.ts +++ b/app/queries/servers/user.ts @@ -59,15 +59,7 @@ export const queryUsersByUsername = (database: Database, usernames: string[]) => }; export async function prepareUsers(operator: ServerDataOperator, users: UserProfile[]): Promise { - try { - if (users.length) { - return operator.handleUsers({users, prepareRecordsOnly: true}); - } - - return []; - } catch { - return []; - } + return operator.handleUsers({users, prepareRecordsOnly: true}); } export const observeTeammateNameDisplay = (database: Database) => { diff --git a/package-lock.json b/package-lock.json index d8bb44f48..c91c44669 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "requires": true, "packages": { "": { - "name": "mattermost-mobile", "version": "2.0.0", "hasInstallScript": true, "license": "Apache 2.0", diff --git a/types/database/database.d.ts b/types/database/database.d.ts index 45bc3150a..8d3d2df5c 100644 --- a/types/database/database.d.ts +++ b/types/database/database.d.ts @@ -71,25 +71,25 @@ export type CreateServerDatabaseArgs = { export type HandleReactionsArgs = { prepareRecordsOnly: boolean; - postsReactions: ReactionsPerPost[]; + postsReactions?: ReactionsPerPost[]; skipSync?: boolean; }; export type HandleFilesArgs = { - files: FileInfo[]; + files?: FileInfo[]; prepareRecordsOnly: boolean; }; export type HandlePostsArgs = { actionType: string; - order: string[]; + order?: string[]; previousPostId?: string; - posts: Post[]; + posts?: Post[]; prepareRecordsOnly?: boolean; }; export type HandleThreadsArgs = { - threads: Thread[]; + threads?: Thread[]; prepareRecordsOnly?: boolean; teamId?: string; loadedInGlobalThreads?: boolean; @@ -98,11 +98,11 @@ export type HandleThreadsArgs = { export type HandleThreadParticipantsArgs = { prepareRecordsOnly: boolean; skipSync?: boolean; - threadsParticipants: ParticipantsPerThread[]; + threadsParticipants?: ParticipantsPerThread[]; }; export type HandleThreadInTeamArgs = { - threadsMap: Record; + threadsMap?: Record; prepareRecordsOnly?: boolean; loadedInGlobalThreads?: boolean; }; @@ -122,7 +122,7 @@ export type SanitizeThreadParticipantsArgs = { } export type ChainPostsArgs = { - order: string[]; + order?: string[]; previousPostId: string; posts: Post[]; }; @@ -177,85 +177,85 @@ type PrepareOnly = { } export type HandleInfoArgs = PrepareOnly & { - info: AppInfo[]; + info?: AppInfo[]; } export type HandleGlobalArgs = PrepareOnly & { - global: IdValue[]; + globals?: IdValue[]; } export type HandleRoleArgs = PrepareOnly & { - roles: Role[]; + roles?: Role[]; } export type HandleCustomEmojiArgs = PrepareOnly & { - emojis: CustomEmoji[]; + emojis?: CustomEmoji[]; } export type HandleSystemArgs = PrepareOnly & { - systems: IdValue[]; + systems?: IdValue[]; } export type HandleMyChannelArgs = PrepareOnly & { - channels: Channel[]; - myChannels: ChannelMembership[]; + channels?: Channel[]; + myChannels?: ChannelMembership[]; }; export type HandleChannelInfoArgs = PrepareOnly &{ - channelInfos: Array>; + channelInfos?: Array>; }; export type HandleMyChannelSettingsArgs = PrepareOnly & { - settings: ChannelMembership[]; + settings?: ChannelMembership[]; }; export type HandleChannelArgs = PrepareOnly & { - channels: Channel[]; + channels?: Channel[]; }; export type HandleCategoryArgs = PrepareOnly & { - categories: Category[]; + categories?: Category[]; }; export type HandleCategoryChannelArgs = PrepareOnly & { - categoryChannels: CategoryChannel[]; + categoryChannels?: CategoryChannel[]; }; export type HandleMyTeamArgs = PrepareOnly & { - myTeams: MyTeam[]; + myTeams?: MyTeam[]; }; export type HandleTeamSearchHistoryArgs = PrepareOnly &{ - teamSearchHistories: TeamSearchHistory[]; + teamSearchHistories?: TeamSearchHistory[]; }; export type HandleTeamChannelHistoryArgs = PrepareOnly & { - teamChannelHistories: TeamChannelHistory[]; + teamChannelHistories?: TeamChannelHistory[]; }; export type HandleTeamArgs = PrepareOnly & { - teams: Team[]; + teams?: Team[]; }; export type HandleChannelMembershipArgs = PrepareOnly & { - channelMemberships: Array>; + channelMemberships?: Array>; }; export type HandleTeamMembershipArgs = PrepareOnly & { - teamMemberships: TeamMembership[]; + teamMemberships?: TeamMembership[]; }; export type HandlePreferencesArgs = PrepareOnly & { - preferences: PreferenceType[]; + preferences?: PreferenceType[]; sync?: boolean; }; export type HandleUsersArgs = PrepareOnly & { - users: UserProfile[]; + users?: UserProfile[]; }; export type HandleDraftArgs = PrepareOnly & { - drafts: Draft[]; + drafts?: Draft[]; }; export type LoginArgs = {