So i recently discovered socket cluster while browsing github, and I though it would be interesting to see as a react/websocket based chat demo. So using es6 i whipped up a simple demo and have published it on github and put up a demo.

Demo

https://chat.azerothian.net/ (you should also be able to interact with it on the bottom right hand of the web page)

Github

https://github.com/Azerothian/scchat

Notes

  • So when you run socketcluster create myapp it generates a relatively complex server.js for providing defaults and processing arguments, this seems to be handy for targeting container based setups. But for a basic projects this seems to be an overkill, though I decided i wanted the best of both worlds 😉 e.g. /src/server/utils/scluster.js
  • The control on the bottom right is the same code as the https://chat.azerothian.net/ it just looks for a html element on the page and if it cant be found then it switches to overlay mode using position fixed.
  • While building for production I currently have a enforced variable for my socket cluster server /src/react-app/app.jsx#L33

Dependencies

Building

Server

Client

Shared


// Babel 2015 - ES6
// Convert a complex JS Object to GraphQL Query, should handle most use cases as of 21/01/2016
const o = {
query: {
fields: {
complex: {
aliasFor: "Products",
processArgs: {
coupon: (value) => {
return `"${JSON.stringify(value).replace(/"/g, "\\\"")}"`; // passing json string as a argument
}
},
args: {
coupon: {
name: {
$eq: "Test",
}
},
complexCoupon: {
name: {
$eq: "Test",
}
}
},
fields: {
"...productFields": null
},
},
products: {
aliasFor: "Products",
args: {
coupon: "coupon",
buildingCode: "code"
},
fields: {
"...productFields": null
}
}
}
},
productFields: {
fragment: "Product",
fields: {
id: null,
"... @include": { // 5.4.1.2 Fragment Spread Type Existence
args: {
if: true
},
fields: {
name: null
},
},
"... on User": { // 5.4.1.2 Fragment Spread Type Existence
fields: {
name: null
},
},
name: null,
description: null,
options: {
fields: {
plan: {
fields: {
renew: null
},
},
},
},
}
}
}

export default function createGQLQuery(obj) {
let result = Object.keys(obj).map((k) => {
let query = `${k}`;
let element = obj[k];
if (element) {
if (element.aliasFor) {
query = `${k}:${element.aliasFor}`;
}
if (element.fragment) {
query = `fragment ${k} on ${element.fragment}`;
}
if (element.args) {
let args = Object.keys(element.args).map((argKey) => {
let argVar = "", processed = false;
if (element.processArgs) {
if (element.processArgs[argKey]) {
argVar = element.processArgs[argKey](element.args[argKey]);
processed = true;
}
}
if (!processed) {
if (typeof element.args[argKey] === "object") {
argVar = JSON.stringify(element.args[argKey]).replace(/\"([^(\")"]+)\":/g, "$1:");
} else {
argVar = `"${element.args[argKey]}"`;
}
}
return `${argKey}:${argVar}`;
}).join();
query = `${query}(${args})`;
}
if (element.fields) {
let fields = createGQLQuery(element.fields);
query = `${query}${fields}`;
}
}
return `${query}`;
}).join();
return `{${result}}`;
}

const query = createGQLQuery(o);
console.log(query);
document.body.innerHTML = query;

Sooooo,

old blog is gone, no backups etc…

sadface.