Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/events/isRoomMemberEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ export interface RoomMemberEvent extends EventBase {
};
}

export const isRoomMemberEvent = (event: Pdu): event is RoomMemberEvent => {
export const isRoomMemberEvent = (event: Pdu): boolean => {
return event.type === 'm.room.member';
};
Comment on lines +68 to 70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify removal of type predicate doesn't break downstream type narrowing.

The function signature changed from a type predicate (event is RoomMemberEvent) to a plain boolean return. This removes compile-time type narrowing for callers who previously relied on TypeScript automatically treating event as RoomMemberEvent after this check.

While this may be intentional as part of the branded-types refactor, ensure that:

  1. Calling code that depended on the type predicate has been updated
  2. The Pdu type from @rocket.chat/federation-room now provides sufficient type safety that makes the predicate redundant or incompatible
  3. The simple event.type check is sufficient given that RoomMemberEvent has additional required fields (content.membership, state_key, etc.)

Run this script to find usages and assess impact:


🏁 Script executed:

#!/bin/bash
# Description: Find all usages of isRoomMemberEvent to check if type narrowing was relied upon

# Search for isRoomMemberEvent usage with context
rg -n -C 5 'isRoomMemberEvent' --type ts

Length of output: 3739


🏁 Script executed:

#!/bin/bash
sed -n '130,180p' packages/core/src/utils/pruneEventDict.ts

Length of output: 1174


Restore type predicate on isRoomMemberEvent (packages/core/src/events/isRoomMemberEvent.ts:68)
Change the signature back to isRoomMemberEvent(event: Pdu): event is RoomMemberEvent so that TS correctly narrows callers (e.g. in pruneEventDict.ts) and drop the @ts-ignore annotations.

🤖 Prompt for AI Agents
In packages/core/src/events/isRoomMemberEvent.ts around lines 68 to 70, the
function currently returns boolean but should be a TypeScript type predicate to
allow proper narrowing; change the signature from (event: Pdu): boolean to
(event: Pdu): event is RoomMemberEvent, ensure RoomMemberEvent is imported or
referenced correctly, and remove any @ts-ignore annotations that were added
downstream (e.g., in pruneEventDict.ts) once callers can rely on the narrowed
type.

17 changes: 10 additions & 7 deletions packages/federation-sdk/src/services/invite.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { EventBase, createLogger } from '@rocket.chat/federation-core';
import {
EventID,
PduForType,
PersistentEventBase,
PersistentEventFactory,
RoomID,
RoomVersion,
UserID,
} from '@rocket.chat/federation-room';
import { singleton } from 'tsyringe';
import { ConfigService } from './config.service';
Expand Down Expand Up @@ -33,14 +36,14 @@ export class InviteService {
* Invite a user to an existing room
*/
async inviteUserToRoom(
userId: string,
roomId: string,
sender: string,
userId: UserID,
roomId: RoomID,
sender: UserID,
isDirectMessage = false,
): Promise<{
event_id: string;
event_id: EventID;
event: PersistentEventBase<RoomVersion, 'm.room.member'>;
room_id: string;
room_id: RoomID;
}> {
this.logger.debug(`Inviting ${userId} to room ${roomId}`);

Expand Down Expand Up @@ -139,8 +142,8 @@ export class InviteService {

async processInvite(
event: PduForType<'m.room.member'>,
roomId: string,
eventId: string,
roomId: RoomID,
eventId: EventID,
roomVersion: RoomVersion,
) {
// SPEC: when a user invites another user on a different homeserver, a request to that homeserver to have the event signed and verified must be made
Expand Down
50 changes: 26 additions & 24 deletions packages/federation-sdk/src/services/message.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import {
type EventID,
type PersistentEventBase,
PersistentEventFactory,
RoomID,
type RoomVersion,
UserID,
} from '@rocket.chat/federation-room';
import { singleton } from 'tsyringe';
import { EventRepository } from '../repositories/event.repository';
Expand Down Expand Up @@ -64,10 +66,10 @@ export class MessageService {
) {}

async sendMessage(
roomId: string,
roomId: RoomID,
rawMessage: string,
formattedMessage: string,
senderUserId: string,
senderUserId: UserID,
): Promise<PersistentEventBase> {
const roomVersion = await this.stateService.getRoomVersion(roomId);
if (!roomVersion) {
Expand Down Expand Up @@ -106,11 +108,11 @@ export class MessageService {
}

async sendReplyToMessage(
roomId: string,
roomId: RoomID,
rawMessage: string,
formattedMessage: string,
eventToReplyTo: string,
senderUserId: string,
eventToReplyTo: EventID,
senderUserId: UserID,
): Promise<PersistentEventBase> {
const roomVersion = await this.stateService.getRoomVersion(roomId);
if (!roomVersion) {
Expand Down Expand Up @@ -154,9 +156,9 @@ export class MessageService {
}

async sendFileMessage(
roomId: string,
roomId: RoomID,
content: FileMessageContent,
senderUserId: string,
senderUserId: UserID,
): Promise<PersistentEventBase> {
const roomVersion = await this.stateService.getRoomVersion(roomId);
if (!roomVersion) {
Expand Down Expand Up @@ -190,12 +192,12 @@ export class MessageService {
}

async sendThreadMessage(
roomId: string,
roomId: RoomID,
rawMessage: string,
formattedMessage: string,
senderUserId: string,
threadRootEventId: string,
latestThreadEventId?: string,
senderUserId: UserID,
threadRootEventId: EventID,
latestThreadEventId?: EventID,
): Promise<PersistentEventBase> {
const roomVersion = await this.stateService.getRoomVersion(roomId);
if (!roomVersion) {
Expand Down Expand Up @@ -246,12 +248,12 @@ export class MessageService {
}

async sendReplyToInsideThreadMessage(
roomId: string,
roomId: RoomID,
rawMessage: string,
formattedMessage: string,
senderUserId: string,
threadRootEventId: string,
eventToReplyTo: string,
senderUserId: UserID,
threadRootEventId: EventID,
eventToReplyTo: EventID,
): Promise<PersistentEventBase> {
const roomVersion = await this.stateService.getRoomVersion(roomId);
if (!roomVersion) {
Expand Down Expand Up @@ -297,10 +299,10 @@ export class MessageService {
}

async sendReaction(
roomId: string,
eventId: string,
roomId: RoomID,
eventId: EventID,
emoji: string,
senderUserId: string,
senderUserId: UserID,
): Promise<string> {
const isTombstoned = await this.roomService.isRoomTombstoned(roomId);
if (isTombstoned) {
Expand Down Expand Up @@ -342,10 +344,10 @@ export class MessageService {
}

async unsetReaction(
roomId: string,
roomId: RoomID,
eventIdReactedTo: EventID,
_emoji: string,
senderUserId: string,
senderUserId: UserID,
): Promise<string> {
const roomInfo = await this.stateService.getRoomInformation(roomId);

Expand Down Expand Up @@ -375,11 +377,11 @@ export class MessageService {
}

async updateMessage(
roomId: string,
roomId: RoomID,
rawMessage: string,
formattedMessage: string,
senderUserId: string,
eventIdToReplace: string,
senderUserId: UserID,
eventIdToReplace: EventID,
): Promise<string> {
const roomInfo = await this.stateService.getRoomInformation(roomId);

Expand Down Expand Up @@ -420,7 +422,7 @@ export class MessageService {
}

async redactMessage(
roomId: string,
roomId: RoomID,
eventIdToRedact: EventID,
): Promise<string> {
const isTombstoned = await this.roomService.isRoomTombstoned(roomId);
Expand Down
14 changes: 8 additions & 6 deletions packages/federation-sdk/src/services/profiles.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {
Pdu,
PduForType,
PersistentEventFactory,
RoomID,
RoomVersion,
UserID,
} from '@rocket.chat/federation-room';
import { singleton } from 'tsyringe';
import { EventRepository } from '../repositories/event.repository';
Expand Down Expand Up @@ -69,12 +71,12 @@ export class ProfilesService {
}

async makeJoin(
roomId: string,
userId: string,
roomId: RoomID,
userId: UserID,
versions: RoomVersion[], // asking server supports these
): Promise<{
event: PduForType<'m.room.member'> & { origin: string };
room_version: string;
room_version: RoomVersion;
}> {
const stateService = this.stateService;
const roomInformation = await stateService.getRoomInformation(roomId);
Expand Down Expand Up @@ -110,7 +112,7 @@ export class ProfilesService {
}

async getMissingEvents(
roomId: string,
roomId: RoomID,
earliestEvents: EventID[],
latestEvents: EventID[],
limit = 10,
Expand All @@ -126,8 +128,8 @@ export class ProfilesService {
}

async eventAuth(
_roomId: string,
_eventId: string,
_roomId: RoomID,
_eventId: EventID,
): Promise<{ auth_chain: Record<string, string>[] }> {
return {
auth_chain: [],
Expand Down
Loading