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

@niloc/core

v0.5.1

Published

Niloc is designed to give the tools to build a networking system, with a very modular approach. The core library does not ship any transport, however some have been implemented, such as Socket.IO and WebRTC. There are also some features available through

Downloads

425

Readme

Niloc - a library to build collaborative applications

Niloc is designed to give the tools to build a networking system, with a very modular approach. The core library does not ship any transport, however some have been implemented, such as Socket.IO and WebRTC. There are also some features available through the base Router or through other pluggable components :

  • Create channels and route messages to any connected peer to your network
  • Synchronize data structures through a Model
  • Send RPCs to connected peers with a RPCHandler

Installation

yarn add niloc-core

Getting started

Create a router

The first thing you'll need to do is create a Network, which is your transport layer. You can implement yours, or take one of the available implementations (soon available on npm). After that, you'll need to create a Router to receive and send messages :

import { Router } from 'niloc-core'

const network = new MyNetwork()
const router = new Router({ 
    network,
    id: "myId", // This will be your id on the network
    host: true // This will be useful to be targeted by some messages, or with some modules like RPCs. Usually, you'll want only one host in the network
})

Create channels

To send / receive messages after that, you can create channels on the router, with an index. This will be useful as you will want different modules to use different channels

import { Address } from "niloc-core"

const helloChannel = router.channel<string>(0)

// Send message to the peer with the id "myFriendId"
helloChannel.post(Address.to("myFriendId"), Date.now())

// Send message to everyone
helloChannel.post(Address.broadcast(), "Hello guys")

// Send message to network host
helloChannel.post(Address.host(), "Hello my kind host")

helloChannel.addListener((message) => {
    console.log(`"${message.originId}" sent us a hello message: ${message.data}`)
})

Syncing objects

To synchronize objects, we will use a model. The model is designed to keep in sync objects that inherit from SyncObject. Every field of those classes that extend Field will be synchronized and bounded to those objects.

Defining SyncObjects

Let's define an example SyncObject named Person with two simple fields age and name

import { SyncObject, Template } from "niloc-core"

class Person extends SyncObject {

    // Will be useful for the model later on
    public static template = Template.create("Person", Person)

    // The first value of the AnyField constructor is the default value
    public readonly age = new AnyField(0)
    public readonly name = new AnyField("noname")

}

To register an object type to the model, we will need a Template. There is a helper function Tempalte.create that creates a template with a SyncObject constructor.

Create the model and register types

To create a model, we'll need a channel from the previously created router.

import { Model } from "niloc-core"

// Get a channel for the model
// We assume we didn't previously create "helloChannel", so the index 0 is free
const channel = router.channel(0)
const model = new Model({ channel })

// Register our type Person
model.register(Person.template)

Later on, we will be able to instantiate Person instances like so:

const person = model.instantiate(Person.template)

To make changes to the fields, we can use the methods available

// Time to drink
person.age.set(21)
person.name.set("John")
model.tick()

Don't forget to call model.tick()! By default, the model doesn't send the changes until you tell it to. Calling this methods lets the model collect all the changes and send it through its channel.

Complex fields

SyncObjectField

Useful when you have nested data structures, but you don't want to synchronize the whole struct with a single change.

import { SyncObjectField } from "niloc-core"

class Point extends SyncObject {

    static template = Template.create("Point", Point)

    readonly x = new AnyField(0)
    readonly y = new AnyField(0)

}

class Segment extends SyncObject {

    static template = Template.create("Segment", Segment)

    readonly a = new SyncObjectField(Point.template)
    readonly b = new SyncObjectField(Point.template)

}

model.register(Segment.template)

const segment = model.instantiate(Segment.template)

const pointA = segment.a.get()
const pointB = segment.a.get()

pointA.x.set(10)
pointA.y.set(-1)

pointB.x.set(20)
pointB.y.set(-7)

model.tick()

This example is not really what should be done in this case, but gives you a good example on how to use it.

SyncObjectRefField

Similar to SyncObjectField, but only stores a reference to the given sub structure. This is useful if you have a parent / children system, or a composing system


class Folder extends SyncObject {

    static template = Template.create("Folder", Folder)

    readonly name = new AnyField("")

}

class File extends SyncObject {

    static template = Template.create("File", File)

    readonly folder = new SyncObjectRefField(File.template)
    readonly name = new AnyField("")

}

model.register(Folder.template)
model.register(File.template)

const root = model.instantiate(Folder.template)
root.name.set("root")

const file = model.instantiate(File.template)
file.name.set("HowToMakeMoney.ppt")
file.folder.set(root)

model.tick()

RPCs