-
Notifications
You must be signed in to change notification settings - Fork 200
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
Types for bridge events #3829
Types for bridge events #3829
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3829 +/- ##
=======================================
Coverage 99.02% 99.02%
=======================================
Files 211 212 +1
Lines 7797 7808 +11
Branches 1757 1757
=======================================
+ Hits 7721 7732 +11
Misses 76 76
Continue to review full report at Codecov.
|
I have created type definitions for all the names of events that are sent across the different frames using various `Bridge`s. It is based on the previous `bridge-events.js`. I broke down the events in four sections based on the direction of the messages: * host -> sidebar events * sidebar -> host events * sidebar -> guest/s events * guest -> sidebar events For those events that didn't have a description I added one. This is more stringent and less verbose than the previous lookup system.
According to our conventions.
f27cef3
to
429048a
Compare
src/sidebar/services/frame-sync.js
Outdated
@@ -282,7 +278,7 @@ export class FrameSyncService { | |||
/** | |||
* Send an RPC message to the host frame. | |||
* | |||
* @param {string} method | |||
* @param {import('../../types/bridge-events').BrideEvents} method |
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 could make it more strict by allowing only to use only the SidebarToHost
events.
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.
Yeah, I think we do want to use the more specific type here to make it easier for the reader to see what the allowed values are.
SHOW_ANNOTATIONS: 'showAnnotations'; | ||
|
||
/** | ||
* The guest is asking the sidebar to sync the annotations |
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 description could be better here. Any help?
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 event is used by the guest to notify the sidebar about the anchoring status of annotations (did we find it in the page). More generally we might in future want to use this event to relay information about the annotation that is only available after anchoring, such as the matched text if we didn't find an exact match for the stored quote, or the location in the document where the match was found (eg. what page number?)
src/types/bridge-events.d.ts
Outdated
/** | ||
* The guest is asking the sidebar to create an annotation | ||
*/ | ||
BEFORE_CREATE_ANNOTATION: 'beforeCreateAnnotation'; |
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 would suggest to change the name to this event to: createAnnotation
.
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 event that creates the annotation.
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 think that would make sense too. I think the original name may have been intended to mean that the annotation is not fully created until it is saved on the server. createAnnotation
seems more obvious.
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 found a typo (BrideEvents
) and had some suggestions regarding the structure of the types (they can just be a union rather than a map). Adding types to describe the events that are allowed in the different channels (guest <-> sidebar, guest <-> host, sidebar <-> host) etc. seems useful.
Enabling support for writing type-only modules in .d.ts
files is good with me. It does mean adding an additional extension/format, but tools (formatting, syntax highlighting etc.) have better support for it. I had a question about the effects of using .d.ts
vs .ts
. My understanding is that the main difference is that .d.ts
files don't generate any JS output and can't be used in non-type contexts. Is there anything else we should be aware of?
One practical disadvantage I realized of changing from an enum to a union is that because the values are just strings rather than imported symbols, you can't use go-to-definition or find-references for them. Instead you have to first look at the definition of the parameter (eg. for notifyHost
or call
or on
) and then look at the definition of that type. I suppose that's the same as any other context where we are using a union of string literals. Modern TS does support a way of defining enums with objects that can be used in JSDoc as of TS 4.5 (next, but not current release).
I think here we just need to make a decision/have some guidelines about when to use one or the other of these options (enum vs union).
src/annotator/sidebar.js
Outdated
@@ -252,12 +251,13 @@ export default class Sidebar { | |||
this.show(); | |||
}); | |||
|
|||
/** @type{Array<[import('../types/bridge-events').BrideEvents, function]>} */ |
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.
There is a typo here - BrideEvents
. Also there should be a space after @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.
Corrected.
src/types/bridge-events.d.ts
Outdated
/** | ||
* Events that the sidebar sends to the host | ||
*/ | ||
type SidebarToHostEvents = { |
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 think this could be a union rather than an object, avoiding the need for the unused ALL_CAPS names for events. I believe this will still allow you to add comments for individual entries.
type SidebarToHostEvents = 'closeSidebar' | 'openSidebar' ...
Also, I think it would be more idiomatic to use a singular name for unions. ie. SidebarToHostEvent
, BridgeEvent
, because an individual value is only one of those possibilities. On the other hand if the value was a bitmask (eg. what modifiers were held down when a key was pressed) then plural would be appropriate.
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 agree. I reused the bridge-event.js
file does why I keep the structure. I will change the name of the type to be singular.
src/types/bridge-events.d.ts
Outdated
/** | ||
* The guest is asking the sidebar to create an annotation | ||
*/ | ||
BEFORE_CREATE_ANNOTATION: 'beforeCreateAnnotation'; |
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 think that would make sense too. I think the original name may have been intended to mean that the annotation is not fully created until it is saved on the server. createAnnotation
seems more obvious.
SHOW_ANNOTATIONS: 'showAnnotations'; | ||
|
||
/** | ||
* The guest is asking the sidebar to sync the annotations |
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 event is used by the guest to notify the sidebar about the anchoring status of annotations (did we find it in the page). More generally we might in future want to use this event to relay information about the annotation that is only available after anchoring, such as the matched text if we didn't find an exact match for the stored quote, or the location in the document where the match was found (eg. what page number?)
src/types/bridge-events.d.ts
Outdated
TOGGLE_ANNOTATION_SELECTION: 'toggleAnnotationSelection'; | ||
}; | ||
|
||
export type BrideEvents = |
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.
export type BrideEvents = | |
export type BridgeEvents = |
@@ -0,0 +1,150 @@ | |||
/** |
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.
What effects does using a .d.ts
extension have over using .ts
? My understanding is that the main distinction is that .d.ts
files can't contain any executable code.
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.
Correct and because they can contain executable code are meant to define types.
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 won't recommend using *.ts
because this is a JavaScript project with types. If we introduce *.ts
files we are giving the impression that it's a mix JavaScript-TypeScript project where you can choose in what language to write your code.
src/sidebar/services/frame-sync.js
Outdated
@@ -282,7 +278,7 @@ export class FrameSyncService { | |||
/** | |||
* Send an RPC message to the host frame. | |||
* | |||
* @param {string} method | |||
* @param {import('../../types/bridge-events').BrideEvents} method |
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.
Yeah, I think we do want to use the more specific type here to make it easier for the reader to see what the allowed values are.
src/shared/bridge.js
Outdated
@@ -66,7 +66,7 @@ export class Bridge { | |||
* Make a method call on all channels, collect the results and pass them to a | |||
* callback when all results are collected. | |||
* | |||
* @param {string} method - Name of remote method to call. | |||
* @param {import('../types/bridge-events').BrideEvents} method - Name of remote method to call. |
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 makes Bridge
a little less general but on the other hand it will catch things like typos in method names. If we wanted an added layer of checking we could make the method names template parameter(s) of the class.
Instead of using an enum, I use an union.
We have decided that event thought JavaScript enum are a little bit more verbose, they provide a level of indirection that is useful for documentation. I will close this and replace it for another PR. |
In contrast to #3829, we have decided to re-enforce the use of the lookup enums for the event names used by `Bridge`. I have added definitions for all the events that are sent across the different frames using various `Bridge`s. I broke down the events into four sections based on the direction of the messages: * guest -> sidebar events * host -> sidebar events * sidebar -> guest/s events * sidebar -> host events
In contrast to #3829, we have decided to re-enforce the use of the lookup enums for the event names used by `Bridge`. I have added definitions for all the events that are sent across the different frames using various `Bridge`s. I broke down the events into four sections based on the direction of the messages: * guest -> sidebar events * host -> sidebar events * sidebar -> guest/s events * sidebar -> host events
In contrast to #3829, we have decided to re-enforce the use of the lookup enums for the event names used by `Bridge`. I have added definitions for all the events that are sent across the different frames using various `Bridge`s. I broke down the events into four sections based on the direction of the messages: * guest -> sidebar events * host -> sidebar events * sidebar -> guest/s events * sidebar -> host events
In contrast to #3829, we have decided to re-enforce the use of the lookup enums for the event names used by `Bridge`. I have added definitions for all the events that are sent across the different frames using various `Bridge`s. I broke down the events into four sections based on the direction of the messages: * guest -> sidebar events * host -> sidebar events * sidebar -> guest/s events * sidebar -> host events
In contrast to #3829, we have decided to re-enforce the use of the lookup enums for the event names used by `Bridge`. I have added definitions for all the events that are sent across the different frames using various `Bridge`s. I broke down the events into four sections based on the direction of the messages: * guest -> sidebar events * host -> sidebar events * sidebar -> guest/s events * sidebar -> host events
In contrast to #3829, we have decided to re-enforce the use of the lookup enums for the event names used by `Bridge`. I have added definitions for all the events that are sent across the different frames using various `Bridge`s. I broke down the events into four sections based on the direction of the messages: * guest -> sidebar events * host -> sidebar events * sidebar -> guest/s events * sidebar -> host events
This is the event that creates the annotation, so it is better to name it in a more obvious way. Context: #3829 (comment)
This is the event that creates the annotation, so it is better to name it in a more obvious way. Context: #3829 (comment)
This is the event that creates the annotation, so it is better to name it in a more obvious way. Context: #3829 (comment)
This is the event that creates the annotation, so it is better to name it in a more obvious way. Context: #3829 (comment)
This is the event that creates the annotation, so it is better to name it in a more obvious way. Context: #3829 (comment)
This is the event that creates the annotation, so it is better to name it in a more obvious way. Context: #3829 (comment)
I have created type definitions for all the event names that are
sent across the different frames using various
Bridge
s. It is based onthe previous
bridge-events.js
. I broke down the events in foursections based on the direction of the messages:
For those events that didn't have a description I added one.
This is more stringent and less verbose than the previous lookup system.