npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mandarin-socketserver

v1.0.0

Published

## About This Proof of Concept is a cleaned up skecth for a personal project that is created to explore simple ways to * Create two-way databinding in the front end * Make any change in the page visible on other browsers on other computers, using events s

Downloads

4

Readme

Real time, cross browser interactons with simple socket server and web client

About

This Proof of Concept is a cleaned up skecth for a personal project that is created to explore simple ways to

  • Create two-way databinding in the front end
  • Make any change in the page visible on other browsers on other computers, using events sent as messages via websockets

It is written as a personal exploration of what can be done with simple means and straight forward code.

Creating a component

To create a component, you define the template HTML and the component-specific settings. In this case, we have some sub components.

// Imports...
// Render-method, so we keep the component itself clean.
const renderPersonHtml=(component:BaseComponent,person:Person)=>{

    // PersonDirective simply returns rendered HTML, based on the input
    let personDirective=new PersonDirective();

    // Template. The attributes object-type and obect-reference will be used as starting points for 2-way data binding
    // The data-binding attributes on the input-elements will tell the framework what fields to bind to on the object
    // Directives are simple sub-templates that can be re-used
    // When we update this from outside, we replace parts of the HTML via databinding. 
    // If we present another person, we simply re-render the entire html of this component
    let html=`<div 
        object-type="Person" 
        object-reference="${person.personId}">
        ${personDirective.render(person)}
        <!-- Assets, rendered with a sub-component! -->
        <div inject="assets" data-model=""></div>
        <!--Show popup from code in component!-->
        <button click="component.showPopup(${person.personId});">Popup!</button>
        <!-- Input! -->
        <p><input type="text" data-binding="firstname"><input type="text" data-binding="lastname"></p>
    </div>`

    // This will create and return a Dom-object and inject the HTML into our parent component
    return component.injectIntoTargetElement(html);
}

export class PersonComponent extends BaseComponent{

    personService:PersonService;

    constructor(parentId:string,renderTarget?:string){

        super({ 
                parentId, // Who is the parent?
                renderTarget, // Where do we render ourselves?
                objects:[Person], // What object(s) are we rendering?
                subcomponents:[// Where do we wish to bind subcomponents?
                    ["assets", AssetsComponent]
                ]
            }
        ); 

        // Define the data service and other bindings
        this.personService=new PersonService();
    }

    // Render this module and all submodules
    public render( model:IRenderModel){
        this.personService.getPersonById(model.personId).then((person:Person)=>{

            // Update anything on screen, store in datastore
            this.dataBinding.process([person],Person);

            // Render, using the private method 
            // This will already create the 2-way bindings
            const component=renderPersonHtml(this,person);

            // This will render subcompoment
            this.sub<AssetsComponent>("assets").target(component).render(person);
        })
    }

    // Method we call from the template HTML
    public showPopup(personId){
        alert("personId="+personId);
    }
}

Binding the component to our static HTML page

Once defined, it can be bound to HTML in the following way, assuming that we have an elemnt in our HTML with the ID "myHtmlElementId":

        // Create and bind module
        const personComponent = new PersonComponent("myHtmlElementId");

        // Render the content
        personComponent.render({personId:"1"});

Sharing objects

To create the websocket connection on the client side, and to receive and handle specific (user)event messages, you can use:

const socketClient=new WebSocketConnector(["item:mousemove","item:textinput","person:change"],"socketclientA");
// Open socket client and bind events from other clients to concrete actions
socketClient
    .openWebsocket('ws://localhost:2222')
    // Capture specific event
    .on("person:change",(message:WebSocketMessage)=>{
        // Define object type
        const type={name:"Person", primaryKey:"personId"}
        // Update the data store and update the HTML. Input is a list of objects, 
        // in this case message.body contains the person that was sent
        DataBinding.process(DataStore.get("myDatastore"), [message.body], type);
    })

To dispatch (user)event messages, to be received by any other connected client that is subscribed to the subject(s), you simply add the following code (example) to the constructor of your component:

    // Get socket client
    this.socketClient=WebSocketConnector.getConnector("socketclientA");

    // Send user-created event (in this case: on key up) from databinding-object that is part of component
    this.dataBinding.onChange=(person:Person)=>{
        this.socketClient.send({
            body:person,
            subjects:["person:change"],
            toId:"" // We will not send it to one specific client, but to all
        })
    }

Code

The code is broken into three parts:

  • lib/client: A small client side framework to render HTML and do 2-way databinding with data objects
  • lib/server: A small server side framework using websockets to share events between different browser clients
  • lib/shared: A set of shared classes, written for convenience and as exploration of certain concepts