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

Async generator handler should follow text/event-stream protocol #742

Open
remorses opened this issue Jul 20, 2024 · 2 comments · May be fixed by #743
Open

Async generator handler should follow text/event-stream protocol #742

remorses opened this issue Jul 20, 2024 · 2 comments · May be fixed by #743
Labels
bug Something isn't working

Comments

@remorses
Copy link

remorses commented Jul 20, 2024

What version of Elysia.JS is running?

"elysia": "^1.1.3"

What platform is your computer?

Darwin 23.5.0 arm64 arm

What steps can reproduce the bug?

import { treaty } from '@elysiajs/eden'

import { Elysia } from 'elysia'

const app = new Elysia()
    .get('/', async function* generator() {
        await sleep(100)
        yield JSON.stringify({ body: 'Hello Elysia' })
        yield JSON.stringify({ body: 'Hello Elysia' })
        yield JSON.stringify({ body: 'Hello Elysia' })
        yield JSON.stringify({ body: 'Hello Elysia' })
        yield JSON.stringify({ body: 'Hello Elysia' })
    })
    .listen(3000, async () => {
        const app = treaty<App>('localhost:3000')

        {
            const { data: gen, error } = await app.index.get({})
            if (error) throw error

            for await (const res of gen) {
                console.log(res)
            }
        }
    })

export type App = typeof app

console.log(
    `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`,
)

function sleep(ms: number) {
    return new Promise(resolve => setTimeout(resolve, ms))
}

The output of this code will be:

{"body":"Hello Elysia"}{"body":"Hello Elysia"}{"body":"Hello Elysia"}
{
  body: "Hello Elysia",
}
{
  body: "Hello Elysia",
}

There are several problems with this code:

  1. In Eden some items will be objects, sometimes strings. This is because Elysia cannot distinguish what separate each yieled item. This is because the server does not separate yielded items with new lines
  2. The type inference of Eden is wrong because when you yield a string it will be converted to an object. The server should call JSON.stringify on all yielded items if the handler is an async generator. (also this is what the text/event-stream spec says)
  3. Elysia just calls .toString() on the yielded items, this will cause problems where when you yield objects you will get [object Object] Async generator yielding an object results in [object Object] output #741

controller.enqueue(Buffer.from(chunk.toString()))

What is the expected behavior?

Elysia should return a text/event-stream compatible output if the handler is an async generator:

  1. Separate each yielded object with a new line
  2. JSON.stringify each item

What do you see instead?

Elysia concatenates the outputs inline calling .toString() on each of them

Additional information

No response

@remorses remorses added the bug Something isn't working label Jul 20, 2024
@remorses remorses changed the title Async generator handler should add a new line between each yielded item and call JSON.stringify on items to follow text/event-stream Async generator handler should add a new line between each yielded item and call JSON.stringify on items to follow text/event-stream protocol Jul 20, 2024
@remorses remorses changed the title Async generator handler should add a new line between each yielded item and call JSON.stringify on items to follow text/event-stream protocol Async generator handler should follow text/event-stream protocol Jul 24, 2024
@macabeus
Copy link

I noticed that there are already two PRs fixing it, but it's stalled for a while...
Is there something that I can do to unblock them? I really would like to have it merged and released.

@remorses
Copy link
Author

I created an alternative framework called Spiceflow inspired by Elysia here: https://github.com/remorses/spiceflow

It has support for Zod, async generators using server sent events and a lot more

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants