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

feat(context): add strongly typed on and once methods #5668

Merged
merged 1 commit into from
Jun 11, 2020

Conversation

bajtos
Copy link
Member

@bajtos bajtos commented Jun 5, 2020

Declare on and once overload methods to describe event parameters in a strongly typed way:

context.on('bind' | 'unbind', ContextEventListener)
context.once('bind' | 'unbind', ContextEventListener)
binding.on('changed', BindingEventListener)
binding.once('changed', BindingEventListener)
view.on('refresh', listener);
view.once('refresh', listener);
// and so on

The change preserves the generic variant provided by EventEmitter too and thus is fully backwards compatible.

Checklist

👉 Read and sign the CLA (Contributor License Agreement) 👈

  • npm test passes on your machine
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • API Documentation in code was updated
  • Documentation in /docs/site was updated
  • Affected artifact templates in packages/cli were updated
  • Affected example projects in examples/* were updated

👉 Check out how to submit a PR 👈

@bajtos bajtos added feature IoC/Context @loopback/context: Dependency Injection, Inversion of Control labels Jun 5, 2020
@bajtos bajtos requested a review from raymondfeng June 5, 2020 06:42
@bajtos bajtos self-assigned this Jun 5, 2020
@bajtos
Copy link
Member Author

bajtos commented Jun 8, 2020

What’s the impact on tsdocs?

It looks like our tsdoc processor is not merging class + interface declarations correctly 😠 In http://127.0.0.1:4001/doc/en/lb4/apidocs.context.html, I see Binding listed under Classes and Interfaces sections. Both entries point to the same URL http://127.0.0.1:4001/doc/en/lb4/apidocs.context.binding.html where only the interface members are described.

Screen Shot 2020-06-08 at 10 52 45

I tried to swap the order in which the class & interface is defined, but that did not help.

I reported the problem to api-extractor, see microsoft/rushstack#1921

@bajtos bajtos force-pushed the feat/typed-context-events branch from 23f94b2 to 0060798 Compare June 8, 2020 10:08
@bajtos bajtos requested a review from raymondfeng June 8, 2020 10:08
@bajtos
Copy link
Member Author

bajtos commented Jun 8, 2020

I pushed a new version, can you @raymondfeng PTAL again please?

The impact of the api-extractor bug looks pretty major to me, I think we will have to wait with this pull request until a fix is available. WDYT?

@raymondfeng
Copy link
Contributor

The impact of the api-extractor bug looks pretty major to me, I think we will have to wait with this pull request until a fix is available. WDYT?

I agree. We should wait.

@bajtos bajtos force-pushed the feat/typed-context-events branch from 0060798 to 06abcdf Compare June 9, 2020 14:45
@bajtos
Copy link
Member Author

bajtos commented Jun 9, 2020

I found a workaround that preserves the current API docs for class members and excludes members that are added via the interface, see 06abcdf.

@raymondfeng LGTY? Are you good to proceed to landing this PR (after I squash commits)?

Screenshot from the rendered docs:

Screen Shot 2020-06-09 at 16 47 38

@raymondfeng
Copy link
Contributor

@bajtos Why don't we add the following the Context class itself? The following is working for me.

export class Context {
  // ...
  on(eventName: 'bind' | 'unbind', listener: ContextEventListener): this;
  on(event: string | symbol, listener: (...args: any[]) => void): this;
  on(event: string | symbol, listener: (...args: any[]) => void): this {
    return super.on(event, listener);
  }
}

@bajtos
Copy link
Member Author

bajtos commented Jun 11, 2020

Why don't we add the following the Context class itself? The following is working for me.

It didn't work for me, let me try again.

Declare `on` and `once` overload methods to describe event parameters
in a strongly typed way:

```ts
context.on('bind' | 'unbind', ContextEventListener)
context.once('bind' | 'unbind', ContextEventListener)
binding.on('changed', BindingEventListener)
binding.once('changed', BindingEventListener)
view.on('refresh', listener);
view.once('refresh', listener);
// and so on
```

The change preserves the generic variant provided by `EventEmitter` too
and thus is fully backwards compatible.

Signed-off-by: Miroslav Bajtoš <[email protected]>
@bajtos bajtos force-pushed the feat/typed-context-events branch from 06abcdf to 0ec740c Compare June 11, 2020 07:54
@bajtos
Copy link
Member Author

bajtos commented Jun 11, 2020

Nice, the proposed solution works 👍

I find it a bit suboptimal that we have to implement on/once methods calling super.on/super.once, but I guess it's the cost we have to accept now.

Here is a screenshot of API docs rendered for Binding class:

Screen Shot 2020-06-11 at 09 52 50

@raymondfeng LGTY now?

@raymondfeng raymondfeng merged commit 3f14bfa into master Jun 11, 2020
@raymondfeng raymondfeng deleted the feat/typed-context-events branch June 11, 2020 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature IoC/Context @loopback/context: Dependency Injection, Inversion of Control
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants