Skip to content
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

Closed
wants to merge 5 commits into from
Closed

Types for bridge events #3829

wants to merge 5 commits into from

Conversation

esanzgar
Copy link
Contributor

I have created type definitions for all the event names that are
sent across the different frames using various Bridges. 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.

@codecov
Copy link

codecov bot commented Oct 11, 2021

Codecov Report

Merging #3829 (f27cef3) into master (910b3da) will increase coverage by 0.00%.
The diff coverage is 100.00%.

❗ Current head f27cef3 differs from pull request most recent head adaf1f7. Consider uploading reports for the commit adaf1f7 to get more accurate results
Impacted file tree graph

@@           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           
Impacted Files Coverage Δ
src/annotator/cross-frame.js 100.00% <ø> (ø)
src/annotator/sidebar.js 98.13% <ø> (ø)
src/shared/bridge.js 100.00% <ø> (ø)
src/annotator/annotation-counts.js 100.00% <100.00%> (ø)
src/annotator/features.js 100.00% <100.00%> (ø)
src/sidebar/components/HypothesisApp.js 100.00% <100.00%> (ø)
src/sidebar/components/TopBar.js 100.00% <100.00%> (ø)
src/sidebar/components/UserMenu.js 100.00% <100.00%> (ø)
src/sidebar/services/features.js 100.00% <100.00%> (ø)
src/sidebar/services/frame-sync.js 100.00% <100.00%> (ø)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 910b3da...adaf1f7. Read the comment docs.

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.
@@ -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
Copy link
Contributor Author

@esanzgar esanzgar Oct 11, 2021

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.

Copy link
Member

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
Copy link
Contributor Author

@esanzgar esanzgar Oct 11, 2021

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?

Copy link
Member

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?)

/**
* The guest is asking the sidebar to create an annotation
*/
BEFORE_CREATE_ANNOTATION: 'beforeCreateAnnotation';
Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Member

@robertknight robertknight left a 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).

@@ -252,12 +251,13 @@ export default class Sidebar {
this.show();
});

/** @type{Array<[import('../types/bridge-events').BrideEvents, function]>} */
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Corrected.

/**
* Events that the sidebar sends to the host
*/
type SidebarToHostEvents = {
Copy link
Member

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.

Copy link
Contributor Author

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.

/**
* The guest is asking the sidebar to create an annotation
*/
BEFORE_CREATE_ANNOTATION: 'beforeCreateAnnotation';
Copy link
Member

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
Copy link
Member

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?)

TOGGLE_ANNOTATION_SELECTION: 'toggleAnnotationSelection';
};

export type BrideEvents =
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
export type BrideEvents =
export type BridgeEvents =

@@ -0,0 +1,150 @@
/**
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@@ -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
Copy link
Member

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.

@@ -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.
Copy link
Member

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.

Misspelled `BridgeEvents`
Instead of using an enum, I use an union.
@esanzgar
Copy link
Contributor Author

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.

@esanzgar esanzgar closed this Oct 12, 2021
@esanzgar esanzgar deleted the types-for-bridge-events branch October 12, 2021 13:03
esanzgar added a commit that referenced this pull request Oct 14, 2021
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
esanzgar added a commit that referenced this pull request Oct 14, 2021
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
esanzgar added a commit that referenced this pull request Oct 14, 2021
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
esanzgar added a commit that referenced this pull request Oct 14, 2021
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
esanzgar added a commit that referenced this pull request Oct 14, 2021
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
esanzgar added a commit that referenced this pull request Oct 14, 2021
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
esanzgar added a commit that referenced this pull request Oct 14, 2021
This is the event that creates the annotation, so it is better to name
it in a more obvious way.

Context:
#3829 (comment)
esanzgar added a commit that referenced this pull request Oct 15, 2021
This is the event that creates the annotation, so it is better to name
it in a more obvious way.

Context:
#3829 (comment)
esanzgar added a commit that referenced this pull request Oct 15, 2021
This is the event that creates the annotation, so it is better to name
it in a more obvious way.

Context:
#3829 (comment)
esanzgar added a commit that referenced this pull request Oct 15, 2021
This is the event that creates the annotation, so it is better to name
it in a more obvious way.

Context:
#3829 (comment)
esanzgar added a commit that referenced this pull request Oct 19, 2021
This is the event that creates the annotation, so it is better to name
it in a more obvious way.

Context:
#3829 (comment)
esanzgar added a commit that referenced this pull request Oct 19, 2021
This is the event that creates the annotation, so it is better to name
it in a more obvious way.

Context:
#3829 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants