Skip to content

Would you be up for an rxjs option? #23

Description

@DDtMM

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions