diff --git a/lib/components/chat-mention-provider.react.js b/lib/components/chat-mention-provider.react.js --- a/lib/components/chat-mention-provider.react.js +++ b/lib/components/chat-mention-provider.react.js @@ -78,7 +78,7 @@ communityThreadIDForGenesisThreads: { +[id: string]: string }, } { const result: { [string]: { [string]: ResolvedThreadInfo } } = {}; - const visitedGenesisThreads = new Set(); + const visitedGenesisThreads = new Set(); const communityThreadIDForGenesisThreads: { [string]: string } = {}; for (const currentThreadID in threadInfos) { const currentThreadInfo = threadInfos[currentThreadID]; diff --git a/lib/components/thread-draft-updater.react.js b/lib/components/thread-draft-updater.react.js --- a/lib/components/thread-draft-updater.react.js +++ b/lib/components/thread-draft-updater.react.js @@ -18,7 +18,7 @@ const cachedThreadIDsRef = React.useRef>(); if (!cachedThreadIDsRef.current) { - const newCachedThreadIDs = new Set(); + const newCachedThreadIDs = new Set(); for (const realizedThreadID of pendingToRealizedThreadIDs.values()) { newCachedThreadIDs.add(realizedThreadID); } diff --git a/lib/hooks/child-threads.js b/lib/hooks/child-threads.js --- a/lib/hooks/child-threads.js +++ b/lib/hooks/child-threads.js @@ -35,9 +35,9 @@ const childThreads = useSelector(state => childThreadInfos(state)[threadID]); const subchannelIDs = React.useMemo(() => { if (!childThreads) { - return new Set(); + return new Set(); } - return new Set( + return new Set( childThreads.filter(predicate).map(threadInfo => threadInfo.id), ); }, [childThreads, predicate]); diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js --- a/lib/reducers/message-reducer.js +++ b/lib/reducers/message-reducer.js @@ -1633,13 +1633,13 @@ // Store message IDs already contained within threads so that we // do not insert duplicates - const existingMessageIDs = new Set(); + const existingMessageIDs = new Set(); for (const threadID in threads) { threads[threadID].messageIDs.forEach(msgID => { existingMessageIDs.add(msgID); }); } - const threadsNeedMsgIDsResorting = new Set(); + const threadsNeedMsgIDsResorting = new Set(); const actionPayloadMessages = messageStoreOpsHandlers.translateClientDBData(payloadMessages); diff --git a/lib/reducers/thread-reducer.js b/lib/reducers/thread-reducer.js --- a/lib/reducers/thread-reducer.js +++ b/lib/reducers/thread-reducer.js @@ -191,7 +191,7 @@ threadStoreOperations, }; } else if (action.type === saveMessagesActionType) { - const threadIDToMostRecentTime = new Map(); + const threadIDToMostRecentTime = new Map(); for (const messageInfo of action.payload.rawMessageInfos) { const current = threadIDToMostRecentTime.get(messageInfo.threadID); if (!current || current < messageInfo.time) { diff --git a/lib/selectors/nav-selectors.js b/lib/selectors/nav-selectors.js --- a/lib/selectors/nav-selectors.js +++ b/lib/selectors/nav-selectors.js @@ -15,6 +15,7 @@ import type { BaseNavInfo } from '../types/nav-types.js'; import type { BaseAppState } from '../types/redux-types.js'; import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js'; +import type { UserInfo } from '../types/user-types.js'; import { getConfig } from '../utils/config.js'; import { values } from '../utils/objects.js'; import { useSelector } from '../utils/redux-utils.js'; @@ -85,7 +86,7 @@ state => state.currentUserInfo && state.currentUserInfo.id, ); const nonViewerMembers = React.useMemo(() => { - const allMembersOfAllThreads = new Map(); + const allMembersOfAllThreads = new Map(); for (const threadInfo of threadInfos) { for (const member of threadInfo.members) { const isParentAdmin = memberHasAdminPowers(member); @@ -112,7 +113,7 @@ ); const memberMap = React.useMemo(() => { - const result = new Map(); + const result = new Map(); for (const userInfo of nonViewerMembersWithENSNames) { result.set(userInfo.id, userInfo); } diff --git a/lib/selectors/thread-selectors.js b/lib/selectors/thread-selectors.js --- a/lib/selectors/thread-selectors.js +++ b/lib/selectors/thread-selectors.js @@ -413,7 +413,7 @@ }) => $ReadOnlyMap = createSelector( (rawThreadInfos: { +[id: string]: RawThreadInfo }) => rawThreadInfos, (rawThreadInfos: { +[id: string]: RawThreadInfo }) => { - const result = new Map(); + const result = new Map(); for (const threadID in rawThreadInfos) { const rawThreadInfo = rawThreadInfos[threadID]; if ( diff --git a/lib/selectors/user-selectors.js b/lib/selectors/user-selectors.js --- a/lib/selectors/user-selectors.js +++ b/lib/selectors/user-selectors.js @@ -207,7 +207,7 @@ state => state.currentUserInfo && state.currentUserInfo.id, state => state.threadStore.threadInfos, (viewerID, threadInfos) => { - const personalThreadMembers = new Set(); + const personalThreadMembers = new Set(); for (const threadID in threadInfos) { const thread = threadInfos[threadID]; diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js --- a/lib/shared/message-utils.js +++ b/lib/shared/message-utils.js @@ -196,7 +196,7 @@ function usersInMessageInfos( messageInfos: $ReadOnlyArray, ): string[] { - const userIDs = new Set(); + const userIDs = new Set(); for (const messageInfo of messageInfos) { if (messageInfo.creatorID) { userIDs.add(messageInfo.creatorID); diff --git a/lib/shared/radix-tree.js b/lib/shared/radix-tree.js --- a/lib/shared/radix-tree.js +++ b/lib/shared/radix-tree.js @@ -91,7 +91,7 @@ } getAllMatchingPrefix(prefix: string): V[] { - const result = new Set(); + const result = new Set(); const stack = [{ node: this.root, partLeft: prefix }]; while (stack.length > 0) { const { node, partLeft: prevPartLeft } = stack.pop(); diff --git a/lib/shared/search-utils.js b/lib/shared/search-utils.js --- a/lib/shared/search-utils.js +++ b/lib/shared/search-utils.js @@ -20,8 +20,9 @@ import type { ChatMessageInfoItem, MessageListData, -} from '../selectors/chat-selectors'; -import type { MessageInfo, RawMessageInfo } from '../types/message-types'; + ChatMessageItem, +} from '../selectors/chat-selectors.js'; +import type { MessageInfo, RawMessageInfo } from '../types/message-types.js'; import { isComposableMessageType } from '../types/message-types.js'; import { userRelationshipStatus } from '../types/relationship-types.js'; import { threadPermissions } from '../types/thread-permission-types.js'; @@ -319,7 +320,7 @@ isComposableMessageType(item.messageInfo.type), ); - const uniqueChatMessageInfoItemsMap = new Map(); + const uniqueChatMessageInfoItemsMap = new Map(); chatMessageInfoItems.forEach( item => item.messageInfo && diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -433,7 +433,7 @@ function memberLowercaseUsernameMap( members: $ReadOnlyArray, ): Map { - const memberMap = new Map(); + const memberMap = new Map(); for (const member of members) { const { id, role, username } = member; if (!role || !username) { @@ -452,7 +452,7 @@ const memberMap = memberLowercaseUsernameMap(threadInfo.members); const mentions = extractUserMentionsFromText(text); - const mentionedMembers = new Map(); + const mentionedMembers = new Map(); for (const mention of mentions) { const userInfo = memberMap.get(mention.toLowerCase()); if (userInfo) { @@ -503,7 +503,7 @@ const { color, type: parentThreadType } = parentThreadInfo; const threadName = trimText(messageTitle, 30); - const initialMembers = new Map(); + const initialMembers = new Map(); const { id: viewerID, username: viewerUsername } = loggedInUserInfo; initialMembers.set(viewerID, { id: viewerID, username: viewerUsername }); @@ -1018,7 +1018,7 @@ function identifyInvalidatedThreads( updateInfos: $ReadOnlyArray, ): Set { - const invalidated = new Set(); + const invalidated = new Set(); for (const updateInfo of updateInfos) { if (updateInfo.type === updateTypes.DELETE_THREAD) { invalidated.add(updateInfo.threadID); @@ -1411,7 +1411,7 @@ ); const [threadSearchResults, setThreadSearchResults] = React.useState( - new Set(), + new Set(), ); const [usersSearchResults, setUsersSearchResults] = React.useState< $ReadOnlyArray, @@ -1420,7 +1420,7 @@ React.useEffect(() => { (async () => { const results = threadSearchIndex.getSearchResults(searchText); - setThreadSearchResults(new Set(results)); + setThreadSearchResults(new Set(results)); const usersResults = await searchUsers(searchText); setUsersSearchResults(usersResults); })(); @@ -1601,7 +1601,7 @@ Object.keys(threadInfo.roles).forEach(roleID => { const roleName = threadInfo.roles[roleID].name; const rolePermissions = Object.keys(threadInfo.roles[roleID].permissions); - const setOfUserSurfacedPermissions = new Set(); + const setOfUserSurfacedPermissions = new Set(); rolePermissions.forEach(rolePermission => { const userSurfacedPermission = Object.keys( diff --git a/lib/socket/api-request-handler.react.js b/lib/socket/api-request-handler.react.js --- a/lib/socket/api-request-handler.react.js +++ b/lib/socket/api-request-handler.react.js @@ -11,6 +11,7 @@ serverSocketMessageTypes, type ClientSocketMessageWithoutID, type ConnectionInfo, + type APIResponseServerSocketMessage, } from '../types/socket-types.js'; import { registerActiveSocket } from '../utils/action-utils.js'; import { SocketOffline } from '../utils/errors.js'; @@ -83,10 +84,11 @@ type: clientSocketMessageTypes.API_REQUEST, payload: request, }); - const response = await inflightRequests.fetchResponse( - messageID, - serverSocketMessageTypes.API_RESPONSE, - ); + const response = + await inflightRequests.fetchResponse( + messageID, + serverSocketMessageTypes.API_RESPONSE, + ); return response.payload; }; } diff --git a/lib/socket/socket.react.js b/lib/socket/socket.react.js --- a/lib/socket/socket.react.js +++ b/lib/socket/socket.react.js @@ -62,6 +62,9 @@ type ConnectionStatus, setLateResponseActionType, type CommTransportLayer, + type ActivityUpdateResponseServerSocketMessage, + type ClientStateSyncServerSocketMessage, + type PongServerSocketMessage, } from '../types/socket-types.js'; import { actionLogger } from '../utils/action-logger.js'; import type { DispatchActionPromise } from '../utils/action-utils.js'; @@ -566,10 +569,11 @@ type: serverRequestTypes.INITIAL_ACTIVITY_UPDATES, activityUpdates: queuedActivityUpdates, }); - activityUpdatePromise = inflightRequests.fetchResponse( - messageID, - serverSocketMessageTypes.ACTIVITY_UPDATE_RESPONSE, - ); + activityUpdatePromise = + inflightRequests.fetchResponse( + messageID, + serverSocketMessageTypes.ACTIVITY_UPDATE_RESPONSE, + ); } const sessionState = this.props.sessionStateFunc(); @@ -586,10 +590,11 @@ this.initializedWithUserState = this.props.preRequestUserState; this.sendMessage(initialMessage); - const stateSyncPromise = inflightRequests.fetchResponse( - messageID, - serverSocketMessageTypes.STATE_SYNC, - ); + const stateSyncPromise = + inflightRequests.fetchResponse( + messageID, + serverSocketMessageTypes.STATE_SYNC, + ); // https://flow.org/try/#1N4Igxg9gdgZglgcxALlAJwKYEMwBcD6aArlLnALYYrgA2WAzvXGCADQgYAeOBARgJ74AJhhhYiNXClzEM7DFCLl602e0hQhcMtCw18ufgAcqyGUTkhyWIyaEHjp85cMn8CIljRCVZ2QF91CBFqBn4oMAACGBI8OGhIozQIcjh6DABBGhoAHgAVZEjgSIBtAGsMfkL6GTgoBABdQtTODCFI-wA+AAoAHShIyLqjIlxCgBIAJWwhAHkoGn58ztZ+gEpCgAVk1PSc8dneACsAWRt81kjXDAgYSPGsAHcsbU7Oov7BjRrEnbSMeiRAC8pQaAG5PpFvrhIhV+ICQYcjhg8AA6OH0brDUZrCEDaIQNCRbo0DAwuDAyIABjBQ0iOVhlXoqNJ9VwAAtaXAANTctYffFfaA-OGUjElODgyFCqA-JIpf6U7G4cqVKWC34K9LMkb0dndeW7DC4yH+SHQyKYegSXAIyJPF4w7ZajCovQ0A1-bUm-EWgQAOSwlAmSLORguV0ct3uDtelOA-jxgxghOJpPJlJpdIZGJZCgQHK5vP5wGlUOFMNFIPFkqTg0iAaDGFV-AalKtNvoEvVgzN+MwuCIaAGjcoeL7-TCEWisR0A3SmgAklBtHA9CcAfQsAgMN0S5D01cAbhnUa63A7n0QOyMNkIL0QKial5bQB1bT6h9lB9rfca3DHqeiogkB6SolaEA0AAbruzg+r2-SQrGMKGv8WQesUAE1KBGAdD6-hsCAMFoEw0DUFBVKogATAAjAAzKiVIgP4QA // $FlowFixMe fixed in Flow 0.214 @@ -749,7 +754,7 @@ this.state.inflightRequests, 'inflightRequests falsey inside sendPing', ); - await this.state.inflightRequests.fetchResponse( + await this.state.inflightRequests.fetchResponse( messageID, serverSocketMessageTypes.PONG, ); diff --git a/lib/types/filter-types.js b/lib/types/filter-types.js --- a/lib/types/filter-types.js +++ b/lib/types/filter-types.js @@ -17,14 +17,15 @@ +type: 'threads', +threadIDs: $ReadOnlyArray, }; -export type CalendarFilter = { +type: 'not_deleted' } | CalendarThreadFilter; +type NotDeletedFilter = { +type: 'not_deleted' }; +export type CalendarFilter = NotDeletedFilter | CalendarThreadFilter; export const calendarFilterValidator: TUnion = t.union([ tShape({ type: tString('threads'), threadIDs: t.list(tID), }), - tShape({ type: tString('not_deleted') }), + tShape({ type: tString('not_deleted') }), ]); export const defaultCalendarFilters: $ReadOnlyArray = [ diff --git a/lib/types/request-types.js b/lib/types/request-types.js --- a/lib/types/request-types.js +++ b/lib/types/request-types.js @@ -96,37 +96,41 @@ ...EntryInconsistencyReportShape, }; +type FailUnmentioned = Shape<{ + +threadInfos: boolean, + +entryInfos: boolean, + +userInfos: boolean, +}>; + +type StateChanges = Shape<{ + +rawThreadInfos: RawThreadInfo[], + +rawEntryInfos: RawEntryInfo[], + +currentUserInfo: CurrentUserInfo, + +userInfos: AccountUserInfo[], + +deleteThreadIDs: string[], + +deleteEntryIDs: string[], + +deleteUserInfoIDs: string[], +}>; + export type ServerCheckStateServerRequest = { +type: 6, +hashesToCheck: { +[key: string]: number }, - +failUnmentioned?: Shape<{ - +threadInfos: boolean, - +entryInfos: boolean, - +userInfos: boolean, - }>, - +stateChanges?: Shape<{ - +rawThreadInfos: RawThreadInfo[], - +rawEntryInfos: RawEntryInfo[], - +currentUserInfo: CurrentUserInfo, - +userInfos: AccountUserInfo[], - +deleteThreadIDs: string[], - +deleteEntryIDs: string[], - +deleteUserInfoIDs: string[], - }>, + +failUnmentioned?: FailUnmentioned, + +stateChanges?: StateChanges, }; const serverCheckStateServerRequestValidator = tShape({ type: tNumber(serverRequestTypes.CHECK_STATE), hashesToCheck: t.dict(t.String, t.Number), failUnmentioned: t.maybe( - tShape({ + tShape({ threadInfos: t.maybe(t.Boolean), entryInfos: t.maybe(t.Boolean), userInfos: t.maybe(t.Boolean), }), ), stateChanges: t.maybe( - tShape({ + tShape({ rawThreadInfos: t.maybe(t.list(rawThreadInfoValidator)), rawEntryInfos: t.maybe(t.list(rawEntryInfoValidator)), currentUserInfo: t.maybe(currentUserInfoValidator), diff --git a/lib/types/socket-types.js b/lib/types/socket-types.js --- a/lib/types/socket-types.js +++ b/lib/types/socket-types.js @@ -302,18 +302,19 @@ payload: serverStateSyncSocketPayloadValidator, }); +type ServerRequestsServerSocketMessagePayload = { + +serverRequests: $ReadOnlyArray, +}; export type ServerRequestsServerSocketMessage = { +type: 1, +responseTo?: number, - +payload: { - +serverRequests: $ReadOnlyArray, - }, + +payload: ServerRequestsServerSocketMessagePayload, }; export const serverRequestsServerSocketMessageValidator: TInterface = tShape({ type: tNumber(serverSocketMessageTypes.REQUESTS), responseTo: t.maybe(t.Number), - payload: tShape({ + payload: tShape({ serverRequests: t.list(serverServerRequestValidator), }), }); @@ -332,16 +333,18 @@ payload: t.maybe(t.Object), }); +type SessionChange = { + +cookie: string, + +currentUserInfo: LoggedOutUserInfo, +}; + export type AuthErrorServerSocketMessage = { - type: 3, - responseTo: number, - message: string, + +type: 3, + +responseTo: number, + +message: string, // If unspecified, it is because the client is using cookieSources.HEADER, // which means the server can't update the cookie from a socket message. - sessionChange?: { - cookie: string, - currentUserInfo: LoggedOutUserInfo, - }, + +sessionChange?: SessionChange, }; export const authErrorServerSocketMessageValidator: TInterface = tShape({ @@ -349,7 +352,10 @@ responseTo: t.Number, message: t.String, sessionChange: t.maybe( - tShape({ cookie: t.String, currentUserInfo: loggedOutUserInfoValidator }), + tShape({ + cookie: t.String, + currentUserInfo: loggedOutUserInfoValidator, + }), ), }); diff --git a/lib/utils/comm-config.js b/lib/utils/comm-config.js --- a/lib/utils/comm-config.js +++ b/lib/utils/comm-config.js @@ -19,7 +19,7 @@ return `${configName.folder}/${configName.name}.json`; } -const cachedJSON = new Map(); +const cachedJSON = new Map(); // This function checks for an env var named COMM_JSONCONFIG_{folder}_{name} // If it doesn't find one, it then looks for keyserver/{folder}/{name}.json @@ -28,13 +28,13 @@ const key = getKeyForConfigName(configName); const cached = cachedJSON.get(key); if (cached !== undefined) { - return cached; + return (cached: any); } - const json = await getJSON(configName); + const json = await getJSON(configName); if (!cachedJSON.has(key)) { cachedJSON.set(key, json); } - return cachedJSON.get(key); + return (cachedJSON.get(key): any); } async function getJSON(configName: ConfigName): Promise { diff --git a/lib/utils/conversion-utils.test.js b/lib/utils/conversion-utils.test.js --- a/lib/utils/conversion-utils.test.js +++ b/lib/utils/conversion-utils.test.js @@ -9,9 +9,11 @@ } from './conversion-utils.js'; import { tShape, tID, idSchemaRegex } from './validation-utils.js'; +type ComplexType = { +ids: { +[string]: $ReadOnlyArray } }; + describe('id conversion', () => { it('should convert string id', () => { - const validator = tShape({ id: tID }); + const validator = tShape<{ +id: string }>({ id: tID }); const serverData = { id: '1' }; const clientData = { id: '0|1' }; @@ -24,7 +26,7 @@ }); it('should convert a complex type', () => { - const validator = tShape({ ids: t.dict(tID, t.list(tID)) }); + const validator = tShape({ ids: t.dict(tID, t.list(tID)) }); const serverData = { ids: { '1': ['11', '12'], '2': [], '3': ['13'] } }; const clientData = { ids: { '0|1': ['0|11', '0|12'], '0|2': [], '0|3': ['0|13'] }, diff --git a/lib/utils/ens-cache.js b/lib/utils/ens-cache.js --- a/lib/utils/ens-cache.js +++ b/lib/utils/ens-cache.js @@ -200,10 +200,10 @@ ensNames = raceResult; } catch (e) { console.log(e); - ensNames = new Array(needFetch.length).fill(null); + ensNames = new Array(needFetch.length).fill(null); } - const resultMap = new Map(); + const resultMap = new Map(); for (let i = 0; i < needFetch.length; i++) { const ethAddress = needFetch[i]; let ensName = ensNames[i]; diff --git a/lib/utils/ens-helpers.js b/lib/utils/ens-helpers.js --- a/lib/utils/ens-helpers.js +++ b/lib/utils/ens-helpers.js @@ -40,7 +40,7 @@ }) .filter(Boolean); - const ensNames = new Map(); + const ensNames = new Map(); if (needFetch.length > 0) { const results = await ensCache.getNamesForAddresses(needFetch); for (let i = 0; i < needFetch.length; i++) { diff --git a/lib/utils/pkcs7-padding.test.js b/lib/utils/pkcs7-padding.test.js --- a/lib/utils/pkcs7-padding.test.js +++ b/lib/utils/pkcs7-padding.test.js @@ -114,7 +114,7 @@ // 2 blocks of data + 2 blocks of padding = 4 blocks total (1 superblock) const padded = new Uint8Array([ ...generateRandomArray(2 * 16), - ...new Array(2 * 16).fill(2), + ...new Array(2 * 16).fill(2), ]); const unpadded = superblockUnpad(padded, blockSizeBytes); @@ -127,7 +127,7 @@ const blockSizeBytes = 16; const padded = new Uint8Array([ ...generateRandomArray(2 * 16), - ...new Array(2 * 16).fill(0), + ...new Array(2 * 16).fill(0), ]); expect(() => superblockUnpad(padded, blockSizeBytes)).toThrow(); }); @@ -137,7 +137,7 @@ // 4 blocks total, but filled with 5s const padded = new Uint8Array([ ...generateRandomArray(2 * 16), - ...new Array(2 * 16).fill(5), + ...new Array(2 * 16).fill(5), ]); expect(() => superblockUnpad(padded, blockSizeBytes)).toThrow(); }); @@ -243,5 +243,5 @@ } function generateRandomArray(length: number): Array { - return new Array(length).map(() => Math.floor(Math.random() * 256)); + return new Array(length).map(() => Math.floor(Math.random() * 256)); } diff --git a/lib/utils/role-utils.js b/lib/utils/role-utils.js --- a/lib/utils/role-utils.js +++ b/lib/utils/role-utils.js @@ -98,7 +98,7 @@ community ? threadInfoSelector(state)[community] : null, ); const topMostThreadInfo = communityThreadInfo || threadInfo; - const roleMap = new Map(); + const roleMap = new Map(); if (topMostThreadInfo.type === threadTypes.GENESIS) { memberInfos.forEach(memberInfo =>