UNPKG

@thebigcrunch/sdk

Version:
228 lines (202 loc) 6.75 kB
import EventEmitter from "events"; import { getConfig } from "./config"; import { createCrunchSocket, getSpaceListener, addSpaceListener, getCrunchSocket } from "./globalVars"; const getSocket = function getSocket() { let crunchSocket = getCrunchSocket(); if (!crunchSocket) { const url = getConfig().spacesSocketUrl; crunchSocket = createCrunchSocket(url); crunchSocket.on("update", (value, space) => { // Bug here - If you're listening to the same cell on tbc_x_y and uuid this will only send it to one. const spaceListener = getSpaceListener(atob(space.location)) || getSpaceListener(space.encodedUuid); if (spaceListener) { spaceListener.lastValue = value; spaceListener.lastSpace = space; spaceListener.emitter.emit("spaceUpdate", value, space); } else { // This happens if a connection has been closed and there is no longer a callback for it. //We should leave the room in this case perhaps. console.error( "Received a space value we were not listening to: ", space.value ); } }); crunchSocket.on("spaceNotFound", spaceId => { const spaceListener = getSpaceListener(spaceId) || getSpaceListener(atob(spaceId)); if (spaceListener) { spaceListener.emitter.emit("spaceNotFound", "invalid space"); } }); crunchSocket.on("user", (user, spaceId) => { const spaceListener = getSpaceListener(spaceId) || getSpaceListener(atob(spaceId)); if (spaceListener) { spaceListener.emitter.emit("user", user); } }); } else { // reusing existing crunch sockets } return crunchSocket; }; // Listens to changes in the whole space (for SDK users) const listenToSpace = ( spaceId, sectorId, callback, errorCallback, userCallback ) => { const crunchSocket = getSocket(); let spaceListener = getSpaceListener(spaceId); if (!spaceListener) { spaceListener = addSpaceListener(spaceId, new EventEmitter(), "", {}); crunchSocket.emit("join", spaceId, sectorId); } else { callback(spaceListener.lastValue, spaceListener.lastSpace); } spaceListener.emitter.on("spaceUpdate", callback); spaceListener.emitter.on("spaceNotFound", errorCallback); if (userCallback !== undefined) { crunchSocket.emit("get_user", spaceId, sectorId, userCallback); } return { close: () => { spaceListener.emitter.removeListener("spaceUpdate", callback); spaceListener.emitter.removeListener( "spaceNotFound", errorCallback ); } }; }; function readSpaceId(encodedSpaceId) { if (!encodedSpaceId) { return; } if (encodedSpaceId.slice(0, 3) === "tbc") { // Old school format tbc_x_y return encodedSpaceId; } try { const decodedString = atob(encodedSpaceId); // Middle school format ascii encoded tbc_x_y if (decodedString.slice(0, 3) === "tbc") { return atob(encodedSpaceId); } else { // Current model nothing to do here. return encodedSpaceId; } } catch (e) { // Not a valid base64 string // Current model nothing to do here. return encodedSpaceId; } } function createCallBacks(callback, errorCallback, userCallback) { const changeCall = typeof callback === "function" ? callback : undefined; const errorChangeCallback = typeof errorCallback === "function" ? errorCallback : () => {}; const userArrivesCallback = typeof userCallback === "function" ? userCallback : undefined; return { changeCall, errorChangeCallback, userArrivesCallback }; } // Register for updates to the specified space ID. // - callback: function will be invoked with native values and the end-user friendly space object export function crunch(encodedSpaceId, callback, errorCallback, userCallback) { const spaceId = readSpaceId(encodedSpaceId); const callbacks = createCallBacks(callback, errorCallback, userCallback); if (!callbacks.changeCall) { console.error( "The Big Crunch: You must supply a callback function to TBC.crunch()" ); return; } if (!spaceId) { console.error("Cell ID not provided to TBC.crunch"); return; } return listenToSpace( spaceId, undefined, callbacks.changeCall, callbacks.errorChangeCallback, callbacks.userArrivesCallback ); } // This is more performant export function crunchWithSectorId( encodedSpaceId, sectorId, callback, errorCallback, userCallback ) { const spaceId = readSpaceId(encodedSpaceId); const callbacks = createCallBacks(callback, errorCallback, userCallback); if (!callbacks.changeCall) { console.error( "The Big Crunch: You must supply a callback function to TBC.crunch()" ); return; } if (!spaceId) { console.error("Cell ID not provided to TBC.crunch"); return; } if (!sectorId) { console.error("Sector ID not provided to TBC.crunch"); return; } return listenToSpace( spaceId, sectorId, callbacks.changeCall, callbacks.errorChangeCallback, callbacks.userArrivesCallback ); } export function crunchBySpaceName(spaceId, name, callback, errorCallback) { if (!spaceId || !name) { console.error( "The Big Crunch: You must supply a spaceId and a name to TBC.crunchBySpaceName" ); } crunchSocket = getSocket(); let spaceListenerId; crunchSocket.emit( "get_space_uuid_from_name_space", { spaceId, name }, cellUuid => { spaceListenerId = cellUuid; // Hacky, we need to return this close function. return crunch(cellUuid, callback, errorCallback).close; } ); const listener = { close: () => { let spaceListener = getSpaceListener(spaceListenerId); spaceListener.emitter.removeListener("spaceUpdate", callback); if (errorCallback) { spaceListener.emitter.removeListener( "spaceNotFound", errorCallback ); } } }; return listener; }