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

triangulum

v3.1.0

Published

A lightweight reactive typescript API that makes the transfer of data as easy as possible

Downloads

22

Readme

Triangulum

Triangulum is a lightweight, reactive, type safe, typescript API that makes the transfer of data as easy as possible by removing the need to manually encode and decode and send data to where it's needed in your application.

How it works

Triangulum uses some simple concepts to make it as flexible as possible

A Registry is a class that stores the prototypes of various classes, so object's prototypes can be changed to that of the target class. It also stores the channel of each class. The channel is used to differentiate different incoming data types. It also stores the type checkers for that class, which are used to ensure arbitrary unknown data is the correct type. It can also store any arbitrary data you like for each class, typically functions that do extra decoding steps, but it can really be anything.

A ListenerManager is an interface that provides an API for sending classes around. You must implement the interface yourself, and the easiest way to do that is to extend AbstractListenerManager, which does much of the hard work that comes with implementing the APIs. You could also extend JSONListenerManager which includes the logic for encoding/decoding JSON, or InternalListenerManager which doesn't encode anything at all and can be used for sending data to web workers, or to other parts of your program, however it doesn't do type checking.

@MakeSendable is a decorator that registers a class to a registry, using it is much more convenient than registering the class yourself. It's usually a good idea to make your own decorator that calls @MakeSendable internally to add the extra convenience of not having to specify the registry, and also if you have your own class you want to make classes extend. You can do this easily with the makeCustomSendableDecorator function.

The strats object tries to make writing type checkers for all kinds of data as easy and convenient as possible by providing a bunch of default type checkers for all kinds of data, which can be combined to type check almost anything. If the options in strats are insufficient, you can still always just input your own predicates

Example

Here's an example using websockets:

import { Sendable, JSONListenerManager, MakeSendable, strats } from "triangulum"

// Create the registry that will be used to store all types that can be sent
const websiteRegistry = new Registry<Sendable, [(data: any) => boolean]>()

class ClientConnectionManager extends JSONListenerManager {
    constructor() {
        super(websiteRegistry)

        this.ws = new WebSocket(`ws://${location.host}/ws`)

        this.ws.onmessage = e => {
            if (!(typeof e.data === "string")) return

            // Tell the JSONListenerManager that some data has been received
            this.onData(e.data as string)
        }

        this.ws.onopen = e => {
            // Tell the JSONListenerManager that this instance is ready to send messages
            // This is neccessary because the parent class caches messages to allow for instantiating the class and sending stuff immediately after, which wouldn't be allowed otherwise
            this.ready()
        }
    }

    // Defines how the data should be sent over the network
    transmit(data: string) {
        this.ws.send(data)
    }

    ws
}

const clientConnectionManager = new ClientConnectionManager()

// @MakeSendable registers the class to the registry, it takes the channel the class should be sent through, as well as how the data should be type checked.
@MakeSendable(
    websiteRegistry,
    "Thingy",
    // The strats object contains helper methods to make writing type checkers easier.
    strats.class({
        value: strats.isString,
    })
)
class Thingy extends Sendable {
    constructor(value: string) {
        this.value = value
    }

    value: string
}

// Send some data
clientConnectionManager.send(new Thingy("Hello world"))

// Listen for some data
clientConnectionManager.listen(Thingy, data => {
    alert(data.value)
})