Share Objects Online with the power of websockets. Keys, Values AND references. Webject is short for Web Object and it really is a system for sharing objects on the web. Someone can host an object, and make authTokens for others online to share this objec


Keywords
web-object, websocket, websockets, object-sharing, sharing, data-sharing, object, object-oriented, object-oriented-programming, cyclic, api, data-storing, database, objects, shared-object, shared-object-library
License
Apache-2.0
Install
npm install webject@1.3.1

Documentation

webject

Share Objects Online with the power of websockets. Keys, Values AND references. Webject is short for Web Object and it really is a system for sharing objects on the web. Someone can host an object, and make authTokens for others online to share this object

  • Please note: Please ensure that the same version of webject is used across the different points/ends of your application that use it

Installation

Three ways

How it Works

  • For the serialisation/deserialisation recursive object cloner that I made for fun a while back I modified to return a "log" which can be translated to an object even with correct referencing
  • As for the logic of the sharing, the person who would serve objects is in control and can GRANT different levels of access to people who connect through a system of authTokens that the person who did the serve also has tools to manage
  • For sharing this object(the "medium"/method), I create a websocket using the nodejs module ws. It will try to use a server(a parameter you give) and if it fails(like if you gave no server parameter), it would then selfhost the socket
  • As to the datatypes shared, everything that JSON deals with AND undefined values AND circular objects
    Support for more data types coming soon
  • For the various parts of this system, do check out ILLUSTATIONS for examples :D

Usage

Using require to get webject.js is the main idea..
So it may vary from require('webject') if installed it as An NPMJS Package
OR require('path/to/webject.js') if you installed it as the Github Package
Example Usage
For examples of the different aspects of this and different ways to use it, check out these examples

You can even use the connect function from browser if you load a script tag from this url(look at the comments of webject.js for example)
You can go to a LIVE WEB EXAMPLE (which hosts the equivalent of an example) then paste the following code connect("wss://webject-example.paultaylor2.repl.co/",authToken).then(obj=>window.mySharedObj=obj) and mySharedObj would be the shared object

DO NOTE: This applies for all functions I have, that if you enter falsish values(like null,0,"",false,undefined), the default actions would be taken as if you never input anything into that argument(eg: serve(myObject,null) would have the same effect of serve(myObject))
Now there are TWO main functions that make up the usage: serve and connect but SIX in total, the other 4 being sync, desync, objToString, stringToObj
eg:let {serve,connect}=require('webject')

Modules

  • serve: This is a synchonous function that would take in two arguments(obj and server). If a server isn't provided, it will attempt to serve, however the obj argument is NECESSARY as it will be an object that you will share
    eg: let myWebject=serve(myObject)
    However, the addToken function is required to make a way for a client to share your object through a token you would give them
    Moreover you can addToken while passing in a different object to share that different object(each authToken can share a different object)
    eg:
let myToken=myWebject.addToken(1,someDifferentObject) //leaving out second parameter would addToken for myObject by default


Additionally, you can set a manual token with the addToken function using the third parameter called specificToken (because by default the token is a randomly generated string)
eg:

let myToken=myWebject.addToken(1,null,"my_key")
//null/no value/undefined would mean sharing the original object from the serve function and "my_key" would be the value returned IF that is a unique token
  • connect: This is an asynchronous function would take in two manditory arguments(location and authToken) and two optional arguments(onFail and object). For the manditory ones, as you must know where the object is being served AND must have a valid authToken to access it.
    For the first optional argument, onFail, it must be a function and it is called whenever the connection is closed/broken
    For the second optional argument, object, it is the object that you want the remote object to be(usually the function returns a new object for you)
    example usage of the optional arguments can be seen in onFailTesting.js
    eg:
let mySharedObject=await connect('wss://example.com:8009',myGivenAuthToken)
//port 8009 is the default port from this when the websocket is created(and the serve function isn't given a server parameter)
  • sync: This is a synchronous function with three arguments(obj, filePath, spacing). If the third argument is not provided, file saving from the object would be done without extra spacing(one chunked line). This function returns an interval ID for the interval it sets to write to specified filePath when the object changes
  • desync: This is a synchronous function that takes in one arguments(syncID). It clears the interval of ID syncID quite literally, however it does throw an error if it is an invalid syncID
  • objToString: This function is forwarded from serial.js and takes in an object and returns a stringified version of the object
    This is a synchronous function that takes in four arguments(obj, cmpStr, spacing, checkClone)
    If the second parameter is used, it will return only the difference from a previous objToString of the object(implemented to send only the changes of the object)
    The last 2 are optional, since one might only care about spacing for visual appeal, and when my system calls this function, it never uses the checkClone option, however you might want to use it for fun ;D
  • stringToObj: This function is forwarded from serial.js and takes in either a string and returns the object parsed from that string
    This is a synchronous function that takes in two arguments(string, obj). If the second parameter isn't used, it ONLY returns the object parsed from the string. However, if the second parameter is used(obj), it modifies obj into the parsed object from the string while still pointing to the nested objects that are still objects according to the string's information. See noRepointing.js as a code demonstration. As for the third parameter, it's a boolean and if true, it will assume that it is only receiving the difference and not the entire object

The AuthToken

The authToken is something(that can be activated from an instance of the serve function) that allows other users to connect with your object with different levels of permissions.
eg:

myWebject.addToken(1) //returns token of authLevel 1
//authLevels in general decide the amount of control the client has of your object(the one you share)
  • authLevel 1: Users who connect with this kind of authToken can only view the object that they are connecting to
  • authLevel 2: Users who connect with this kind of authToken can view and add, but they cannot modify(as in they can add new keys with data but not edit or delete existing ones)
  • authLevel 3: Users who connect with this kind of authToken can view, add AND modify the shared object(lots of power, kinda sus ngl so maybe just make these authTokens JUST for yourself if for some reason you wanna go on another process or device and have full control of the object)

However, as for the serve function itself, it returns some utility tools for managing tokens(for EACH call), namely:

  • authTokens: A list of all tokens existing in that serve instance(can be used to kick people(just closing a socket would trigger the cleanup of that socket))
    example structure
{
  ...,
  "webject_dfae":{ //one authToken object
    authToken:"webject_dfae",
    authLevel:1,
    clients:Map[someSocket1=>1,someSocket2=>1],
    object:theSharedObj,
    locked:false,
    string:objToString(theSharedObj)
  },
  ...,
}

Methods

serve is the only module that returns an object with methods

  • addToken: The correct way to create an authToken that takes in a parameter authLevel or an optional second parameter object and returns the authToken with that level of authorisation, then finally a third optional paremeter of specificToken. If you do use the second parameter, an that object would be shared since you can share a different object per token :D
    Needless to say, if you don't use the second parameter, it will default to the object chosen when the serve function was called
    The third optional parameter is for setting an authToken manually, which adds further flexibility to this function
  • endToken: The correct way to remove an authToken that takes in a parameter authToken to remove it and close all connections that were to that token(yes, it kicks everyone who is connected with that token)
  • lock: This takes in the parameter authToken and will prevent further connections to that authToken while NOT removing clients already connected
  • unlock: This takes in the parameter authToken and enables further connections to that authToken(by default when you make a key it's unlocked)
  • addListener: This takes in 2 parameters(event which is a string and yourReaction which is a function). yourReaction receives an object with several different properties, including the lock and unlock functions(except you can activate them without an authToken and it will apply the lock to the event's token)
    object given to yourReaction function when used in addListener upon an event dispatch
{
  token, //an authToken object
  socket, //a websocket object
  type, //event name(eg: "edit")
  lock, //function to lock a specified token or the event's authToken
  unlock, //function to unlock a specified token or the event's authToken
  preventDefault //function to stop event propogation(no other listeners get called after one listener activtes this)
}


eg: let myHandler=(ev)=>ev.lock(); myWebject.addListener("connect",myHandler) would end up locking each authToken upon connection
There are a total of THREE valid values for event right now, namely connect, disconnect and edit. See eventsTesting.js and lockTesting.js for examples

  • endListener: This takes in 2 parameters(event which is a string and yourReaction which is a function). If yourReaction exists in the array of event, it will be removed from the list
    eg: myWebject.removeListener("connect",myHandler)

Updates

  • heartbeat/ping logic: Basically, I had a repl server and sometimes I turned off my connection(from my pc) and the server still behaved as if the connection was live.. so I've implemented this logic
  • new object parameter in connect: This allows the user to connect to the remote object BUT with the user's object


Well if you're all the way down here, my email is paulrytaylor@gmail.com