-
Notifications
You must be signed in to change notification settings - Fork 684
🚀 Add GraphQL subscriptions support for wasmJs target #6637
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
Conversation
… functions, clarify binary data handling constraints, and add comprehensive documentation
@aryapreetam: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks you so much for looking into this and providing a nice sample app!
A few comments from an early look at the pull request. I'll also work on adding tests in the repo.
val stringData = data.toString() | ||
listener.onMessage(stringData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have more details why binary data wouldn't work? I'm assuming the browser has some kind of Buffer
type that we could potentially use here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wasmJs platform limitation - cannot handle binary WebSocket messages due to:
Limited interop with JavaScript binary types:
Kotlin/Wasm JavaScript interop documentation explains that only primitive types and strings can be passed directly between Kotlin/Wasm and JavaScript
as you can see here https://kotlinlang.org/docs/wasm-js-interop.html#type-correspondence, only premitive types are supported.
we could have considered something like Buffer
type but it should have its equivalent js object as given here https://kotlinlang.org/docs/wasm-js-interop.html#jsany-type. considering Buffer
to be of just JsAny
may not be a good option(but we can experiment with it of course).
please let me know your inputs on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Long term, we could probably do something with ByteArray
like there: https://kotlinlang.org/docs/wasm-js-interop.html#array-interoperability.
But for now, can we throw if binary data is received? There is little chance calling toString()
on binarry data will work. I'd rather have a proper error message than undefined behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me do a quick experiment with binary data. I didn't look into it before since I didn't need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martinbonnin I have added binary data support for wasmJs
. You can check the demo source and web app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still uses Text
websocket frames so it didn't test all the paths. I've just pushed a few changes to add an integration test as well as fix binary frames for both wasm and JS (turns out this wasn't working either)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried adding ByteArray
as custom scalar type, but it didn't work. Do you have a sample server that uses binary data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's implementation dependent. I'm not 100% sure I have seen one TBH, which is why it was probably fine to leave it out and throw. But if we're doing it, might as well do it right. The echo test server is using plain WebSockets, without GraphQL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the demo app, but the binary support only works for development build(wasmJsBrowserDevelopmentExecutableDistribution
), and it will give error if binary data used in production(wasmJsBrowserDistribution
)
Below, I ran it with wasmJsBrowserProductionRun

It fails at listener.onMessage(byteArray)
. I think wherever this listener is used, the binary data is not handled properly there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://youtrack.jetbrains.com/issue/KT-79673/, this seems to be a wasm optimization issue or something like so. I just relaunched the tests. If everything passes, I'll merge this PR.
...e/src/wasmJsMain/kotlin/com/apollographql/apollo/network/websocket/WebSocketEngine.wasmJs.kt
Outdated
Show resolved
Hide resolved
...e/src/wasmJsMain/kotlin/com/apollographql/apollo/network/websocket/WebSocketEngine.wasmJs.kt
Outdated
Show resolved
Hide resolved
...e/src/wasmJsMain/kotlin/com/apollographql/apollo/network/websocket/WebSocketEngine.wasmJs.kt
Outdated
Show resolved
Hide resolved
...e/src/wasmJsMain/kotlin/com/apollographql/apollo/network/websocket/WebSocketEngine.wasmJs.kt
Show resolved
Hide resolved
...-runtime/src/wasmJsMain/kotlin/com/apollographql/apollo/network/ws/WebSocketEngine.wasmJs.kt
Outdated
Show resolved
Hide resolved
… ArrayBufferView and Uint8Array, improving binary message support and documentation
Thanks for the contribution! |
thanks for all the support! |
🚀 Add GraphQL subscriptions support for wasmJs target
📋 Summary
This PR implements complete WebSocket support for the wasmJs platform(in Compose Multiplatform), enabling GraphQL subscriptions to work seamlessly in WebAssembly JavaScript environments. This addresses the missing functionality preventing wasmJs applications from using real-time GraphQL subscriptions.
🔗 Fixes: #5862
✨ What's New
🛠️ Technical Implementation
Files Added/Modified:
libraries/apollo-runtime/src/wasmJsMain/kotlin/com/apollographql/apollo/network/ws/WebSocketEngine.wasmJs.kt
- Legacy coroutine-based APIlibraries/apollo-runtime/src/wasmJsMain/kotlin/com/apollographql/apollo/network/websocket/WebSocketEngine.wasmJs.kt
- Modern listener-based APIKey Features:
/ws/
(legacy) and/websocket/
(modern) APIs consistently📹 Demo Video
apollo-kotlin-demo-720p.mp4
🔗 Demo Repository
Working Demo: apollo-kotlin-demo - Complete Compose Multiplatform app showcasing wasmJs GraphQL subscriptions
🧪 Platform Support
Binary Data support:
apollo-kotlin-demo-with-binary_1080p.mov
Browser WebSocket API Constraints:
connectionPayload
or URL-based methods)Security & Performance:
🚀 Getting Started
✅ Testing
🎯 Impact
This implementation unlocks real-time GraphQL capabilities for wasmJs applications, enabling:
🔄 Breaking Changes
None - This is a pure addition that doesn't affect existing functionality.
📚 Additional Context
This implementation required careful navigation of wasmJs platform constraints including:
js()
function callsThe solution maintains full compatibility with existing Apollo Kotlin APIs while providing robust, production-ready WebSocket support for wasmJs environments.
Ready for Review 🚀 This PR brings GraphQL subscriptions to the wasmJs ecosystem, completing Apollo Kotlin's multiplatform story!