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

Support for Sse decorator #398

Open
ninthsun91 opened this issue Jun 14, 2023 · 5 comments
Open

Support for Sse decorator #398

ninthsun91 opened this issue Jun 14, 2023 · 5 comments
Assignees
Labels
help wanted Extra attention is needed question Further information is requested

Comments

@ninthsun91
Copy link
Contributor

ninthsun91 commented Jun 14, 2023

TypedRoute is not supporting Sse decorator from @nestjs/common, thus cannot use Nestia for SSE endpoints.

For example, for the code something like below,

// original decorator used
// @Sse('/path/to')
// Nestia decorator used
@TypedRoute.Get('/path/to')
async waitQueue(
  @TypedQuery('id') queueId: string,
  @Req() req: Request,
) {
  const isCompleted = new Subject<void>();
  return interval(3000).pipe(
    takeUntil(isCompleted),
    mergeMap(async () => {
      // do stuffs
    }),
  );
}

if I use @TypedRoute.Get in place of @sse, this endpoint will work as a normal GET method.

Could you please add @sse decorator to TypedRoute, or is there any work around for SSE endpoints?

@samchon
Copy link
Owner

samchon commented Jun 15, 2023

Do you have a good idea that how SDK should be generated?

If you have insight about it, can you write an example SDK code about that?

@samchon samchon self-assigned this Jun 15, 2023
@samchon samchon added question Further information is requested help wanted Extra attention is needed labels Jun 15, 2023
@ninthsun91
Copy link
Contributor Author

Honestly, neither do I know how Nestia generates sdk internally yet, nor am I skilled enough to contribute to your project. So, if you think this issue is not part of your primary goals, it's fine to close the issue.

Maybe I'll re-open this issue when I get better understanding to this project and become ready to contribute.

@samchon
Copy link
Owner

samchon commented Jun 16, 2023

I mean just interface design goal of SDK what you want. Don't be burdened please.

@ninthsun91
Copy link
Contributor Author

ninthsun91 commented Jun 16, 2023

Sure.

Would this be what you are expecting?

/**
 * EventSource constructor:
 * new(url: string | URL, eventSourceInitDict?: EventSourceInit): EventSource;
 * 
 * interface EventSourceInit {
 *   withCredentials?: boolean;
 * }
 */
interface EventSourceConnection {
  url: string;
  withCredentials?: boolean;
}
interface EventSourceListener {
  /**
   * EventSource event type
   * pre-built types: 'message' | 'open' | 'error'
   * but, can be any string
   */
  type: string;

  /**
   * interface MessageEvent<T = any> extends Event {
   *  readonly data: T;
   * }
   * 
   * I'm not sure whether other properties are used.
   */
  listener: (this: EventSource, event: MessageEvent) => any;

  /**
   * Indicates whether the EventSource connection should be closed after the event.
   * 
   * For example, if true,
   * the listner should be wrapped with eventSource.close().
   * 
   * false, by default.
   */
  close?: boolean;
}

API.path.to.methodName(connection: EventSourceConnection, ...listener: EventSourceListener[])

Just wrote it similar to how normal requests are handled.
So, real use case might look like this.

API.path.to.methodName({
  url: 'http://localhost:3000',
}, {
  type: 'message',
  listener: messageHandler,
}, {
  type: 'error',
  listener: errorHandler,
  close: true,
}, {
  type: 'complete',
  listener: completeHandler,
  close: true,
});

or maybe, the interface can return the EventSource instance, so that the user can add listeners.

*edit

const eventSource = API.path.to.methodName({ url: 'http://localhost:3000' })
eventSource.addEventListener('message', messageHandler);
eventSource.addEventListener('error', errorHandler);
eventSource.addEventListener('complete', completeHandler);

@dev-dafab
Copy link

Hallo @samchon Thank you for the amazing work.
I've face the same struggle as described in this issue. I just ended up using https://github.com/Azure/fetch-event-source instead of the sdk for this particular SSE endpoint.

Also thinking about how it can be integrate in nestia:

  1. If you don't mind integrating fetch-event-source as peer-dependency in nestia fetcher. Then the workflow will be like this.
a. nestjs enpoint has sse decorator ?
b. use SseFetcher ( leverage fetchEventSource from fetch-event-source-package )
c. wrap onmessage, onerror, onopen and onclose in Promise.

I've tested this approch with react-native client and it work fine.

  1. Another option would be really just to generate something like this for SSE marked endpoint. and repeat the option 2.c
const eventSource = new EventSource('/sse');
eventSource.onmessage = ({ data }) => {
  console.log('New message', JSON.parse(data));
};

Again thank you for your amazing work.

Cheers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants