diff --git a/lib/shared/updates/bad-device-token-spec.js b/lib/shared/updates/bad-device-token-spec.js --- a/lib/shared/updates/bad-device-token-spec.js +++ b/lib/shared/updates/bad-device-token-spec.js @@ -1,5 +1,7 @@ // @flow +import t from 'tcomb'; + import type { UpdateSpec } from './update-spec.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { @@ -7,6 +9,7 @@ BadDeviceTokenUpdateData, BadDeviceTokenUpdateInfo, } from '../../types/update-types.js'; +import { tNumber, tShape } from '../../utils/validation-utils.js'; export const badDeviceTokenSpec: UpdateSpec< BadDeviceTokenUpdateInfo, @@ -36,4 +39,10 @@ }, deleteCondition: null, typesOfReplacedUpdatesForMatchingKey: null, + infoValidator: tShape({ + type: tNumber(updateTypes.BAD_DEVICE_TOKEN), + id: t.String, + time: t.Number, + deviceToken: t.String, + }), }); diff --git a/lib/shared/updates/delete-account-spec.js b/lib/shared/updates/delete-account-spec.js --- a/lib/shared/updates/delete-account-spec.js +++ b/lib/shared/updates/delete-account-spec.js @@ -1,5 +1,7 @@ // @flow +import t from 'tcomb'; + import type { UpdateSpec } from './update-spec.js'; import type { RawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; @@ -9,6 +11,7 @@ AccountDeletionUpdateInfo, } from '../../types/update-types.js'; import type { UserInfos } from '../../types/user-types.js'; +import { tNumber, tShape } from '../../utils/validation-utils.js'; export const deleteAccountSpec: UpdateSpec< AccountDeletionUpdateInfo, @@ -74,4 +77,10 @@ updateTypes.UPDATE_USER, ]), typesOfReplacedUpdatesForMatchingKey: 'all_types', + infoValidator: tShape({ + type: tNumber(updateTypes.DELETE_ACCOUNT), + id: t.String, + time: t.Number, + deletedUserID: t.String, + }), }); diff --git a/lib/shared/updates/delete-thread-spec.js b/lib/shared/updates/delete-thread-spec.js --- a/lib/shared/updates/delete-thread-spec.js +++ b/lib/shared/updates/delete-thread-spec.js @@ -1,5 +1,7 @@ // @flow +import t from 'tcomb'; + import type { UpdateSpec } from './update-spec.js'; import type { RawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; @@ -8,6 +10,7 @@ ThreadDeletionUpdateData, ThreadDeletionUpdateInfo, } from '../../types/update-types.js'; +import { tID, tNumber, tShape } from '../../utils/validation-utils.js'; export const deleteThreadSpec: UpdateSpec< ThreadDeletionUpdateInfo, @@ -62,4 +65,10 @@ }, deleteCondition: 'all_types', typesOfReplacedUpdatesForMatchingKey: 'all_types', + infoValidator: tShape({ + type: tNumber(updateTypes.DELETE_THREAD), + id: t.String, + time: t.Number, + threadID: tID, + }), }); diff --git a/lib/shared/updates/join-thread-spec.js b/lib/shared/updates/join-thread-spec.js --- a/lib/shared/updates/join-thread-spec.js +++ b/lib/shared/updates/join-thread-spec.js @@ -2,20 +2,32 @@ import invariant from 'invariant'; import _isEqual from 'lodash/fp/isEqual.js'; +import t from 'tcomb'; import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; -import type { RawEntryInfo } from '../../types/entry-types.js'; +import { + type RawEntryInfo, + rawEntryInfoValidator, +} from '../../types/entry-types.js'; import type { RawMessageInfo, MessageTruncationStatuses, } from '../../types/message-types.js'; -import type { RawThreadInfos } from '../../types/thread-types.js'; +import { + messageTruncationStatusValidator, + rawMessageInfoValidator, +} from '../../types/message-types.js'; +import { + type RawThreadInfos, + rawThreadInfoValidator, +} from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ThreadJoinUpdateInfo, ThreadJoinRawUpdateInfo, ThreadJoinUpdateData, } from '../../types/update-types.js'; +import { tNumber, tShape } from '../../utils/validation-utils.js'; import { combineTruncationStatuses } from '../message-utils.js'; import { threadInFilterList } from '../thread-utils.js'; @@ -141,4 +153,13 @@ }, deleteCondition: 'all_types', typesOfReplacedUpdatesForMatchingKey: 'all_types', + infoValidator: tShape({ + type: tNumber(updateTypes.JOIN_THREAD), + id: t.String, + time: t.Number, + threadInfo: rawThreadInfoValidator, + rawMessageInfos: t.list(rawMessageInfoValidator), + truncationStatus: messageTruncationStatusValidator, + rawEntryInfos: t.list(rawEntryInfoValidator), + }), }); diff --git a/lib/shared/updates/update-current-user-spec.js b/lib/shared/updates/update-current-user-spec.js --- a/lib/shared/updates/update-current-user-spec.js +++ b/lib/shared/updates/update-current-user-spec.js @@ -2,6 +2,7 @@ import invariant from 'invariant'; import _isEqual from 'lodash/fp/isEqual.js'; +import t from 'tcomb'; import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; import { updateTypes } from '../../types/update-types-enum.js'; @@ -10,7 +11,11 @@ CurrentUserRawUpdateInfo, CurrentUserUpdateData, } from '../../types/update-types.js'; -import type { CurrentUserInfo } from '../../types/user-types.js'; +import { + type CurrentUserInfo, + loggedInUserInfoValidator, +} from '../../types/user-types.js'; +import { tNumber, tShape } from '../../utils/validation-utils.js'; export const updateCurrentUserSpec: UpdateSpec< CurrentUserUpdateInfo, @@ -54,4 +59,10 @@ }, deleteCondition: new Set([updateTypes.UPDATE_CURRENT_USER]), typesOfReplacedUpdatesForMatchingKey: 'all_types', + infoValidator: tShape({ + type: tNumber(updateTypes.UPDATE_CURRENT_USER), + id: t.String, + time: t.Number, + currentUserInfo: loggedInUserInfoValidator, + }), }); diff --git a/lib/shared/updates/update-entry-spec.js b/lib/shared/updates/update-entry-spec.js --- a/lib/shared/updates/update-entry-spec.js +++ b/lib/shared/updates/update-entry-spec.js @@ -1,15 +1,20 @@ // @flow import invariant from 'invariant'; +import t from 'tcomb'; import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; -import type { RawEntryInfo } from '../../types/entry-types.js'; +import { + type RawEntryInfo, + rawEntryInfoValidator, +} from '../../types/entry-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { EntryUpdateInfo, EntryRawUpdateInfo, EntryUpdateData, } from '../../types/update-types.js'; +import { tNumber, tShape } from '../../utils/validation-utils.js'; export const updateEntrySpec: UpdateSpec< EntryUpdateInfo, @@ -70,4 +75,10 @@ }, deleteCondition: 'all_types', typesOfReplacedUpdatesForMatchingKey: 'all_types', + infoValidator: tShape({ + type: tNumber(updateTypes.UPDATE_ENTRY), + id: t.String, + time: t.Number, + entryInfo: rawEntryInfoValidator, + }), }); diff --git a/lib/shared/updates/update-spec.js b/lib/shared/updates/update-spec.js --- a/lib/shared/updates/update-spec.js +++ b/lib/shared/updates/update-spec.js @@ -1,5 +1,7 @@ // @flow +import type { TType } from 'tcomb'; + import type { ThreadStoreOperation } from '../../ops/thread-store-ops.js'; import type { FetchEntryInfosBase, @@ -90,4 +92,5 @@ ) => ?UpdateInfo, +deleteCondition: ?UpdateTypes, +typesOfReplacedUpdatesForMatchingKey: ?UpdateTypes, + +infoValidator: TType, }; diff --git a/lib/shared/updates/update-thread-read-status-spec.js b/lib/shared/updates/update-thread-read-status-spec.js --- a/lib/shared/updates/update-thread-read-status-spec.js +++ b/lib/shared/updates/update-thread-read-status-spec.js @@ -1,5 +1,7 @@ // @flow +import t from 'tcomb'; + import type { UpdateSpec } from './update-spec.js'; import type { RawThreadInfo, @@ -11,6 +13,7 @@ ThreadReadStatusRawUpdateInfo, ThreadReadStatusUpdateData, } from '../../types/update-types.js'; +import { tID, tNumber, tShape } from '../../utils/validation-utils.js'; export const updateThreadReadStatusSpec: UpdateSpec< ThreadReadStatusUpdateInfo, @@ -72,4 +75,11 @@ typesOfReplacedUpdatesForMatchingKey: new Set([ updateTypes.UPDATE_THREAD_READ_STATUS, ]), + infoValidator: tShape({ + type: tNumber(updateTypes.UPDATE_THREAD_READ_STATUS), + id: t.String, + time: t.Number, + threadID: tID, + unread: t.Boolean, + }), }); diff --git a/lib/shared/updates/update-thread-spec.js b/lib/shared/updates/update-thread-spec.js --- a/lib/shared/updates/update-thread-spec.js +++ b/lib/shared/updates/update-thread-spec.js @@ -1,15 +1,20 @@ // @flow import _isEqual from 'lodash/fp/isEqual.js'; +import t from 'tcomb'; import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; -import type { RawThreadInfos } from '../../types/thread-types.js'; +import { + type RawThreadInfos, + rawThreadInfoValidator, +} from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ThreadUpdateInfo, ThreadRawUpdateInfo, ThreadUpdateData, } from '../../types/update-types.js'; +import { tNumber, tShape } from '../../utils/validation-utils.js'; import { threadInFilterList } from '../thread-utils.js'; export const updateThreadSpec: UpdateSpec< @@ -91,4 +96,10 @@ typesOfReplacedUpdatesForMatchingKey: new Set([ updateTypes.UPDATE_THREAD_READ_STATUS, ]), + infoValidator: tShape({ + type: tNumber(updateTypes.UPDATE_THREAD), + id: t.String, + time: t.Number, + threadInfo: rawThreadInfoValidator, + }), }); diff --git a/lib/shared/updates/update-user-spec.js b/lib/shared/updates/update-user-spec.js --- a/lib/shared/updates/update-user-spec.js +++ b/lib/shared/updates/update-user-spec.js @@ -1,5 +1,7 @@ // @flow +import t from 'tcomb'; + import type { UpdateSpec } from './update-spec.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { @@ -7,6 +9,7 @@ UserRawUpdateInfo, UserUpdateData, } from '../../types/update-types.js'; +import { tNumber, tShape } from '../../utils/validation-utils.js'; export const updateUserSpec: UpdateSpec< UserUpdateInfo, @@ -41,4 +44,10 @@ }, deleteCondition: new Set([updateTypes.UPDATE_USER]), typesOfReplacedUpdatesForMatchingKey: null, + infoValidator: tShape({ + type: tNumber(updateTypes.UPDATE_USER), + id: t.String, + time: t.Number, + updatedUserID: t.String, + }), }); diff --git a/lib/types/update-types.js b/lib/types/update-types.js --- a/lib/types/update-types.js +++ b/lib/types/update-types.js @@ -2,24 +2,22 @@ import t, { type TUnion, type TInterface } from 'tcomb'; -import { type RawEntryInfo, rawEntryInfoValidator } from './entry-types.js'; +import { type RawEntryInfo } from './entry-types.js'; import { type RawMessageInfo, - rawMessageInfoValidator, type MessageTruncationStatus, - messageTruncationStatusValidator, } from './message-types.js'; -import { type RawThreadInfo, rawThreadInfoValidator } from './thread-types.js'; -import { updateTypes } from './update-types-enum.js'; +import { type RawThreadInfo } from './thread-types.js'; import { type UserInfo, userInfoValidator, type UserInfos, userInfosValidator, type LoggedInUserInfo, - loggedInUserInfoValidator, } from './user-types.js'; -import { tNumber, tShape, tID } from '../utils/validation-utils.js'; +import { updateSpecs } from '../shared/updates/update-specs.js'; +import { values } from '../utils/objects.js'; +import { tShape } from '../utils/validation-utils.js'; type AccountDeletionData = { +deletedUserID: string, @@ -180,13 +178,6 @@ +time: number, +deletedUserID: string, }; -export const accountDeletionUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.DELETE_ACCOUNT), - id: t.String, - time: t.Number, - deletedUserID: t.String, - }); export type ThreadUpdateInfo = { +type: 1, @@ -194,13 +185,7 @@ +time: number, +threadInfo: RawThreadInfo, }; -export const threadUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.UPDATE_THREAD), - id: t.String, - time: t.Number, - threadInfo: rawThreadInfoValidator, - }); + export type ThreadReadStatusUpdateInfo = { +type: 2, +id: string, @@ -208,27 +193,13 @@ +threadID: string, +unread: boolean, }; -export const threadReadStatusUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.UPDATE_THREAD_READ_STATUS), - id: t.String, - time: t.Number, - threadID: tID, - unread: t.Boolean, - }); + export type ThreadDeletionUpdateInfo = { +type: 3, +id: string, +time: number, +threadID: string, }; -export const threadDeletionUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.DELETE_THREAD), - id: t.String, - time: t.Number, - threadID: tID, - }); export type ThreadJoinUpdateInfo = { +type: 4, @@ -239,42 +210,21 @@ +truncationStatus: MessageTruncationStatus, +rawEntryInfos: $ReadOnlyArray, }; -export const threadJoinUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.JOIN_THREAD), - id: t.String, - time: t.Number, - threadInfo: rawThreadInfoValidator, - rawMessageInfos: t.list(rawMessageInfoValidator), - truncationStatus: messageTruncationStatusValidator, - rawEntryInfos: t.list(rawEntryInfoValidator), - }); + export type BadDeviceTokenUpdateInfo = { +type: 5, +id: string, +time: number, +deviceToken: string, }; -export const badDeviceTokenUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.BAD_DEVICE_TOKEN), - id: t.String, - time: t.Number, - deviceToken: t.String, - }); + export type EntryUpdateInfo = { +type: 6, +id: string, +time: number, +entryInfo: RawEntryInfo, }; -export const entryUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.UPDATE_ENTRY), - id: t.String, - time: t.Number, - entryInfo: rawEntryInfoValidator, - }); + export type CurrentUserUpdateInfo = { +type: 7, +id: string, @@ -288,13 +238,7 @@ // Updated UserInfo is already contained within the UpdatesResultWithUserInfos +updatedUserID: string, }; -export const userUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.UPDATE_USER), - id: t.String, - time: t.Number, - updatedUserID: t.String, - }); + export type ClientUpdateInfo = | AccountDeletionUpdateInfo | ThreadUpdateInfo @@ -306,40 +250,10 @@ | CurrentUserUpdateInfo | UserUpdateInfo; -type ServerCurrentUserUpdateInfo = { - +type: 7, - +id: string, - +time: number, - +currentUserInfo: LoggedInUserInfo, -}; -export const serverCurrentUserUpdateInfoValidator: TInterface = - tShape({ - type: tNumber(updateTypes.UPDATE_CURRENT_USER), - id: t.String, - time: t.Number, - currentUserInfo: loggedInUserInfoValidator, - }); -export type ServerUpdateInfo = - | AccountDeletionUpdateInfo - | ThreadUpdateInfo - | ThreadReadStatusUpdateInfo - | ThreadDeletionUpdateInfo - | ThreadJoinUpdateInfo - | BadDeviceTokenUpdateInfo - | EntryUpdateInfo - | ServerCurrentUserUpdateInfo - | UserUpdateInfo; -export const serverUpdateInfoValidator: TUnion = t.union([ - accountDeletionUpdateInfoValidator, - threadUpdateInfoValidator, - threadReadStatusUpdateInfoValidator, - threadDeletionUpdateInfoValidator, - threadJoinUpdateInfoValidator, - badDeviceTokenUpdateInfoValidator, - entryUpdateInfoValidator, - serverCurrentUserUpdateInfoValidator, - userUpdateInfoValidator, -]); +export type ServerUpdateInfo = ClientUpdateInfo; +export const serverUpdateInfoValidator: TUnion = t.union( + values(updateSpecs).map(spec => spec.infoValidator), +); export type ServerUpdatesResult = { +currentAsOf: number, diff --git a/lib/types/validation.test.js b/lib/types/validation.test.js --- a/lib/types/validation.test.js +++ b/lib/types/validation.test.js @@ -24,18 +24,9 @@ import { threadTypes } from './thread-types-enum.js'; import { rawThreadInfoValidator } from './thread-types.js'; import { updateTypes } from './update-types-enum.js'; -import { - accountDeletionUpdateInfoValidator, - badDeviceTokenUpdateInfoValidator, - entryUpdateInfoValidator, - serverCurrentUserUpdateInfoValidator, - threadDeletionUpdateInfoValidator, - threadJoinUpdateInfoValidator, - threadReadStatusUpdateInfoValidator, - threadUpdateInfoValidator, - userUpdateInfoValidator, -} from './update-types.js'; import { messageSpecs } from '../shared/messages/message-specs.js'; +import { updateSpecs } from '../shared/updates/update-specs.js'; +import { values } from '../utils/objects.js'; describe('media validation', () => { const photo = { @@ -733,21 +724,8 @@ ]; describe('server update validation', () => { - const validatorByUpdateType = { - [updateTypes.DELETE_ACCOUNT]: accountDeletionUpdateInfoValidator, - [updateTypes.UPDATE_THREAD]: threadUpdateInfoValidator, - [updateTypes.UPDATE_THREAD_READ_STATUS]: - threadReadStatusUpdateInfoValidator, - [updateTypes.DELETE_THREAD]: threadDeletionUpdateInfoValidator, - [updateTypes.JOIN_THREAD]: threadJoinUpdateInfoValidator, - [updateTypes.BAD_DEVICE_TOKEN]: badDeviceTokenUpdateInfoValidator, - [updateTypes.UPDATE_ENTRY]: entryUpdateInfoValidator, - [updateTypes.UPDATE_CURRENT_USER]: serverCurrentUserUpdateInfoValidator, - [updateTypes.UPDATE_USER]: userUpdateInfoValidator, - }; - - for (const validatorUpdateType in validatorByUpdateType) { - const validator = validatorByUpdateType[validatorUpdateType]; + for (const validatorUpdateType of values(updateTypes)) { + const validator = updateSpecs[validatorUpdateType].infoValidator; const validatorUpdateTypeName = _findKey( e => e === Number(validatorUpdateType), )(updateTypes);