diff --git a/lib/permissions/minimally-encoded-raw-thread-info-validators.js b/lib/permissions/minimally-encoded-raw-thread-info-validators.js --- a/lib/permissions/minimally-encoded-raw-thread-info-validators.js +++ b/lib/permissions/minimally-encoded-raw-thread-info-validators.js @@ -12,6 +12,8 @@ ThreadCurrentUserInfo, RawThreadInfo, RoleInfo, + RoleInfoWithoutSpecialRole, + RawThreadInfoWithoutSpecialRole, } from '../types/minimally-encoded-thread-permissions-types.js'; import { type LegacyRawThreadInfo, @@ -28,11 +30,15 @@ permissions: tHexEncodedPermissionsBitmask, }); -const roleInfoValidator: TInterface = tShape({ +const roleInfoValidatorBase = { id: tID, name: t.String, minimallyEncoded: tBool(true), permissions: t.list(tHexEncodedRolePermission), +}; + +const roleInfoValidator: TInterface = tShape({ + ...roleInfoValidatorBase, specialRole: t.maybe(specialRoleValidator), }); @@ -72,8 +78,25 @@ }, ); -const mixedRawThreadInfoValidator: TUnion = - t.union([legacyRawThreadInfoValidator, rawThreadInfoValidator]); +const roleInfoWithoutSpecialRolesValidator: TInterface = + tShape({ + ...roleInfoValidatorBase, + isDefault: t.maybe(t.Boolean), + }); + +const rawThreadInfoWithoutSpecialRoles: TInterface = + tShape({ + ...rawThreadInfoValidator.meta.props, + roles: t.dict(tID, roleInfoWithoutSpecialRolesValidator), + }); + +const mixedRawThreadInfoValidator: TUnion< + LegacyRawThreadInfo | RawThreadInfo | RawThreadInfoWithoutSpecialRole, +> = t.union([ + legacyRawThreadInfoValidator, + rawThreadInfoValidator, + rawThreadInfoWithoutSpecialRoles, +]); export { memberInfoValidator, 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 @@ -893,29 +893,27 @@ if (!shouldMinimallyEncodePermissions) { return rawThreadInfo; - } else if (!shouldIncludeSpecialRoleFieldInRoles) { - return minimallyEncodeRawThreadInfo(rawThreadInfo); } - const rawThreadInfoWithoutSpecialRoles = - minimallyEncodeRawThreadInfo(rawThreadInfo); + const minimallyEncoded = minimallyEncodeRawThreadInfo(rawThreadInfo); + if (shouldIncludeSpecialRoleFieldInRoles) { + return minimallyEncoded; + } - const rolesWithSpecialRoleField = Object.fromEntries( - entries(rawThreadInfoWithoutSpecialRoles.roles).map(([key, role]) => [ + const minimallyEncodedRolesWithoutSpecialRoleField = Object.fromEntries( + entries(minimallyEncoded.roles).map(([key, role]) => [ key, { - ..._omit('isDefault')(role), - specialRole: rolesWithFilteredThreadPermissions[key]?.specialRole, + ..._omit('specialRole')(role), + isDefault: roleIsDefaultRole(role), }, ]), ); - const rawThreadInfoWithSpecialRolesPatchedIn = { - ...rawThreadInfoWithoutSpecialRoles, - roles: rolesWithSpecialRoleField, + return { + ...minimallyEncoded, + roles: minimallyEncodedRolesWithoutSpecialRoleField, }; - - return rawThreadInfoWithSpecialRolesPatchedIn; } function threadUIName(threadInfo: ThreadInfo): string | ThreadEntity { diff --git a/lib/types/minimally-encoded-thread-permissions-types.js b/lib/types/minimally-encoded-thread-permissions-types.js --- a/lib/types/minimally-encoded-thread-permissions-types.js +++ b/lib/types/minimally-encoded-thread-permissions-types.js @@ -22,11 +22,15 @@ import { roleIsAdminRole, roleIsDefaultRole } from '../shared/thread-utils.js'; import type { ThreadEntity } from '../utils/entity-text.js'; -export type RoleInfo = $ReadOnly<{ +type RoleInfoBase = $ReadOnly<{ +id: string, +name: string, +minimallyEncoded: true, +permissions: $ReadOnlyArray, +}>; + +export type RoleInfo = $ReadOnly<{ + ...RoleInfoBase, +specialRole?: ?SpecialRole, }>; @@ -171,6 +175,16 @@ }; }; +export type RoleInfoWithoutSpecialRole = $ReadOnly<{ + ...RoleInfoBase, + +isDefault?: boolean, +}>; + +export type RawThreadInfoWithoutSpecialRole = $ReadOnly<{ + ...RawThreadInfo, + +roles: { +[id: string]: RoleInfoWithoutSpecialRole }, +}>; + export type ThreadInfo = $ReadOnly<{ +minimallyEncoded: true, +id: string,