Skip to content

Instantly share code, notes, and snippets.

@zerkalica
Created May 7, 2025 13:18
Show Gist options
  • Save zerkalica/7936c9ac3c2a7ccdfc4161a33202bc32 to your computer and use it in GitHub Desktop.
Save zerkalica/7936c9ac3c2a7ccdfc4161a33202bc32 to your computer and use it in GitHub Desktop.
gql_ws.ts
namespace $ {
export class $mpk_gql_ws extends $yuf_ws_host {
override url() { return '/v1/graphql' }
override restart_delay() { return 60000 }
token() { return null as string | null | undefined }
@ $mol_mem
authorized(next?: boolean) {
// resend on token change
const token = this.token()
const ready = this.ready()
if (! token) return false
if (next === undefined && ready) {
this.send_object({
type: 'connection_init',
payload: {
'Authorization': `Bearer ${token}`,
headers: {
'Content-Type': 'application/json',
}
}
})
}
if (next) {
this.error(null)
}
return next ?? false
}
@ $mol_mem
override restarts( reset?: null ) {
// restart on token change
this.token()
return super.restarts(null)
}
protected subs() { return this.$.$mpk_gql_sub }
size() { return this.subs().size() }
send_authorized(payload: Object) {
// Resend on connection_ack change
if (! this.authorized()) return null
this.send_object(payload)
return null
}
pong() { this.send_object({ type: 'pong' }) }
override ping() { this.send_object({ type: 'ping' }) }
override heatbeat_enabled() { return false }
override enabled() { return Boolean(this.token()) && ! this.$.$yuf_browser_live.hidden() }
override protocols() { return [ 'graphql-ws' ] }
protected override on_object(obj:
// see https://habr.com/ru/articles/804641/
// https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md
| { type: 'connection_ack', payload?: Record<string, unknown> | null }
| {
type: 'data' | 'next' | 'error'
id: string
payload?: {
data?: unknown
errors?: readonly typeof $mpk_gql_error_dto.Value[]
}
}
| { type: 'complete', id: string }
| { type: 'ping', payload?: Record<string, unknown> | null }
| { type: 'pong' | 'ka', payload?: Record<string, unknown> | null }
) {
if (obj.type === 'ping') this.pong()
if (obj.type === 'pong' || obj.type === 'ka') this.watchdog(null)
if (obj.type === 'connection_ack') this.authorized(true)
if (obj.type === 'data' || obj.type === 'next' || obj.type === 'error') {
const req = this.subs().get(obj.id)
if (! req) return
const { data, errors } = obj.payload ?? {}
if (data) req.data(data)
if (errors) req.errors(errors.length ? errors : [ { message: JSON.stringify(obj.payload) } ] )
}
if (obj.type === 'complete') {
const req = this.subs().get(obj.id)
if (req) {
new $mol_after_timeout(this.sub_restart_timeout(), () => req.subscribed(null))
}
}
}
sub_restart_timeout() { return 5000 }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment