-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor CallCapabilities #1170
base: main
Are you sure you want to change the base?
Conversation
|
@jpsantosbh could you please check the CI? Also, the event emits the capabilities from here: https://github.com/signalwire/signalwire-js/blob/main/packages/js/src/fabric/workers/callJoinWorker.ts#L83 The TS interface does not understand it since the server returns an array of strings. That is why the consumer has been facing the TS mismatch issue. We need to find out a way to fix the TS interface for the event. |
@@ -506,7 +507,7 @@ export interface CallJoinedEventParams { | |||
member_id: string | |||
node_id?: string | |||
origin_call_id: string | |||
capabilities: string[] // TODO: More stronger type is required through server | |||
capabilities: CallCapabilities |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the interface for the server event. The type of the capabilities on the server event is an array of string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't 2 distinct interfaces one "from the server" and another "to emit".
Since we want SDK exposed events to have the interface we're emitting we need to define it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The interfaces you see within this types
folder are for the events from the server. We used the same interface for both (receiving and emitting) since what we receive is exactly what we emit.
Now, only because of this capability change, we need to create two interfaces. One for the event received by the server, the other for the event emitted by the SDK.
@@ -74,10 +74,10 @@ export const callJoinWorker = function* ( | |||
}) | |||
|
|||
cfRoomSession.member = get<FabricRoomSessionMember>(payload.member_id) | |||
cfRoomSession.capabilities = mapCapabilityPayload(payload.capabilities || []) | |||
// the server send the capabilities payload as an array of string | |||
cfRoomSession.capabilities = mapCapabilityPayload(payload.capabilities as unknown as string[] || []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above mentioned interface is the issue why we need to use this "as unknown as string[]" here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but when that is defined as string[], then we get a type error in the emit call.
since the two payloads are different, IMO the SDK should expose the type for the mapped payload,
while here we just do the cast intentionally (that's why I added the comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do not need to do type casting if we have two different interfaces, one for receiving and the other for emitting.
With this change right now, we have broken the server event interface.
screenshare?: true | ||
self: MemberCapability | ||
member: MemberCapability | ||
end: boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be not present in the docs, probably a typo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think we should be adding an unnecessary inconsistency in the SDK. Some of the capabilities are not inconsistent with what we get from the server.
It will become harder to debug and understand which capability (from the server) is translated to which capability (by the SDK).
I would suggest either of the below options:
- Expose a well defined array of string with proper TS. In the FabricRoomSession class, we can convert that into a JS Set so that the retrieval is log(1) - constant.
- Expose object with the same path as the server string.
I think it's easier to do the step 1, if there is no real benefit of the option 2.
Honestly, I don't like both suggestions.(We discussed this previously when the feature was introduced in the SDK) This PR is about fixing the emitted payload type and changing from |
I discussed it with the consumer, and the consumer is fine with the object. So, I guess it's fine to have it. I value more consumer feedback. So, apologies, if I caused any confusion, let's target creating a new interface for the SDK emit and merge this PR. You may create the event interface in this file and then update the For the server capability string to SDK object, maybe we can write some documents later on. So that, we remember these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good to me. These are minor suggestions for TS interface and types export.
@@ -506,7 +506,7 @@ export interface CallJoinedEventParams { | |||
member_id: string | |||
node_id?: string | |||
origin_call_id: string | |||
capabilities: string[] // TODO: More stronger type is required through server | |||
capabilities: string[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please add back this todo? So that we remember to update this later.
interface CapabilityOnOffState { | ||
on?: true | ||
off?: true | ||
export interface CapabilityOnOffState { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mind moving this to the js/src/fabric
folder since it's only required in Fabric and is not associated with any SDK event?
We can probably create a new file here packages/js/src/fabric/interfaces. We also need to export the CallCapabilities
type from the JS package.
'self.raisehand.off': { | ||
self: { raisehand: { off: true } }, | ||
} as CallCapabilities, | ||
class CapabilityOnOffStateImpl implements CapabilityOnOffState { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This thing can also be moved to a dedicated CallCapabilities file inside the js/src/fabric.
} | ||
} | ||
|
||
class MemberCapabilityImpl implements MemberCapability { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using the suffix "Impl", you can create a class with the normal name such as "MemberCapability" and use the suffix "Contract" for the TS interface such as "MemberCapabilityContract".
That's what the SDK does with other classes.
return this._flags.some((flag) => | ||
/^(.*\.on|(?:(?!.*\.off$).*))$/.test(flag) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be updated into simpler JS?
return this._flags.some((flag) => | |
/^(.*\.on|(?:(?!.*\.off$).*))$/.test(flag) | |
) | |
return this._flags.some(flag => !flag.endsWith('.off')); |
? !this.capabilities?.self?.muteAudio?.off | ||
: !this.capabilities?.member?.muteAudio?.off |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we have the list of capabilities, the SDK makes sure to include all the properties, right?
Then we can update this a bit:
? !this.capabilities?.self?.muteAudio?.off | |
: !this.capabilities?.member?.muteAudio?.off | |
? !this.capabilities?.self.muteAudio.off | |
: !this.capabilities?.member.muteAudio.off |
// FIXME: Capabilities type is incompatible. | ||
// @ts-expect-error | ||
cfRoomSession.emit('call.joined', { | ||
const fabricEvent: FabricCallJoinedEventParams = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not need type casting anymore:
const fabricEvent: FabricCallJoinedEventParams = { | |
const fabricEvent = { |
capabilities: cfRoomSession.capabilities, | ||
}) | ||
capabilities: cfRoomSession.capabilities | ||
} as FabricCallJoinedEventParams |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not need type casting anymore:
} as FabricCallJoinedEventParams | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without it, the result will have capabilities unknown
.
This is a TS, I believe, because we are spreading the payload
and in there capabilities have a distinct type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I actually tried this again, and it seems to be not throwing any error.
const fabricEvent = {
...payload,
capabilities: cfRoomSession.capabilities,
}
cfRoomSession.emit('call.joined', fabricEvent)
Maybe we can connect over the call and go through this if required. Just make sure you are re-running the TS; sometimes it shows error, and re-running solves it.
@@ -73,6 +74,11 @@ export type FabricMemberListUpdatedParams = { | |||
members: InternalFabricMemberEntity[] | |||
} | |||
|
|||
export type FabricCallJoinedEventParams = { | |||
capabilities: CallCapabilities | |||
} & Omit<CallJoinedEventParams, 'capabilities'> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe later on, we will need to use some standard names. Maybe prefix it with "Internal" that are only consumed by the SDK not available for the public. For now it's fine though.
@@ -73,6 +74,11 @@ export type FabricMemberListUpdatedParams = { | |||
members: InternalFabricMemberEntity[] | |||
} | |||
|
|||
export type FabricCallJoinedEventParams = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to export this from here as well: packages/js/src/fabric/interfaces/index.ts
, so that consumer can access this from the Fabric SDK.
Same for CallCapabilities types.
Description
This
true | undefined
=>boolean
Type of change
Code snippets
In case of new feature or breaking changes, please include code snippets.