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

Would you be up for an rxjs option? #23

Open
DDtMM opened this issue Nov 3, 2019 · 1 comment
Open

Would you be up for an rxjs option? #23

DDtMM opened this issue Nov 3, 2019 · 1 comment

Comments

@DDtMM
Copy link

DDtMM commented Nov 3, 2019

I can't believe this project exists. Thanks for creating. I love NSwag and was just lamenting that there was no equivalent for SignalR when I found this.

Would you be up if I tried implementing an option to generate a client that wraps callbacks with observables, exposing them as read only fields? This would be an alternative to generating an interface for callbacks.

Proposed Output

The one drawback with the output below is that unlike your current method, callbacks can only be registered and unregistered once. I prefer this and don't see the is as an issue, but if it is a problem then it would be easy to implement register and deregister methods.

export class ChatHub {
  
  welcome$ = this.registerCallback<void>('Welcome');
  send$ = this.registerCallback<string>('Send');

  constructor(private connection: HubConnection) {
  }
  send(message: string): Promise<void> { /* ... */ }
  addPerson(person: person): Promise<void> { /* ... */ }
  getEvents(message: IStreamResult<Event> ): Promise<Event> { /* ... */ }

  private disposingSubject = new Subject();
  dispose() {
    if (!this.disposingSubject.closed) {
      this.disposingSubject.next();
      this.disposingSubject.complete();
    }
  }

  /* Registers a new observable callback, completing and unregistering when disposingSubject is fired. */
  private registerCallback<T>(eventName: string) {
    return new Observable<T>(obs => {
      this.connection.on(eventName, val => obs.next(val));
      const unregisterSub = this.disposingSubject.subscribe(() => {
        this.connection.off(eventName);
        obs.complete();
        listenerSub.unsubscribe();
       })
    });
  }
}

Questions

If I did this I need some clarifications. I'm having a hard time grasping all of the design choices, and I don't want to go in the wrong direction:

  • I imagine I'd need to add a property to settings (I'm thinking an Enum called CallbacksType). There seem to be two TypeScript settings classes. Which would be the correct one to alter?
  • Since I'd need the value of that setting in both the File and Hub templates, I'd need to add settings to both models. Is this okay, or do you see a cleaner way?
    • Adding to the File model is simple enough, but the I'd have to either create a new subclass Hub model or add SigSpecToTypeScriptGeneratorSettingsBase as a property on Hub. It doesn't feel clean, either way.
    • Maybe there is a way to reference the File model from the Hub template?
@RicoSuter
Copy link
Owner

Sounds good to me.

  • one setting (parent) is with sigspec client settings the other is for customizing typescript dto generation
  • cant you access the file properties from the hub template?

We also should add some unit tests to verify the output

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

No branches or pull requests

2 participants