Skip to content

Instantly share code, notes, and snippets.

@bastiW
Created July 5, 2025 19:31
Show Gist options
  • Save bastiW/c31046a016bbefd8a5fb81fc012b7803 to your computer and use it in GitHub Desktop.
Save bastiW/c31046a016bbefd8a5fb81fc012b7803 to your computer and use it in GitHub Desktop.
Ash GraphQL Subscription.js
const subscription = {
ws: null,
joinRef: 0,
messageRef: 0,
controlJoinRef: null,
subscriptionId: null
};
function connect() {
const ws = new WebSocket('ws://localhost:4000/ws/gql/websocket');
subscription.ws = ws;
ws.onopen = () => {
console.log('✅ Connected');
joinAbsintheChannel();
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.event === "phx_reply") {
if (message.payload.status === "ok") {
if (message.topic === "__absinthe__:control") {
// Check if this is the join response (empty response object)
if (Object.keys(message.payload.response || {}).length === 0) {
console.log('✅ Joined control channel');
subscribe();
} else if (message.payload.response?.subscriptionId) {
subscription.subscriptionId = message.payload.response.subscriptionId;
console.log('✅ Subscription active:', subscription.subscriptionId);
// Don't join a separate doc channel - data comes through control channel
}
}
} else {
console.error('❌ Phoenix error:', message);
}
} else if (message.event === "subscription:data") {
handleSubscriptionData(message.payload);
}
};
ws.onerror = (error) => {
console.error('❌ WebSocket error:', error);
};
ws.onclose = () => {
console.log('🔌 Disconnected');
};
}
function sendMessage(topic, event, payload, joinRef = null) {
const ref = String(++subscription.messageRef);
const message = { topic, event, payload, ref };
if (joinRef) message.join_ref = joinRef;
subscription.ws.send(JSON.stringify(message));
return ref;
}
function joinAbsintheChannel() {
subscription.controlJoinRef = String(++subscription.joinRef);
sendMessage("__absinthe__:control", "phx_join", {}, subscription.controlJoinRef);
}
function subscribe() {
const query = `subscription PostChanged {
postChanged {
created {
id
title
}
updated {
id
title
}
}
}`;
sendMessage("__absinthe__:control", "doc", { query, variables: {} }, subscription.controlJoinRef);
}
function handleSubscriptionData(payload) {
const data = payload.result?.data?.postChanged;
if (!data) return;
if (data.created) {
console.log('📝 Post Created:', data.created);
}
if (data.updated) {
console.log('📝 Post Updated:', data.updated);
}
}
// Connect on load
connect();
// Expose for debugging
window.subscription = subscription;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment