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

keeljs

v1.0.2

Published

State management for Javascript apps.

Downloads

8

Readme

Keel

Where do you keep your state? Typically state does not get the love that models do. State and state logic are often scattered in bindings, variables and objects. And that's a shame, because state can be slippery as hell, and ugly state-specific code can pollute core application logic.

Keel is declarative state management tool for javascript apps. It gathers application state into an encapsulated object that updates itself with clear, sentence-like rules.

keel = require("keel")
makeState = keel.makeState

let s = makeState({
    data: {
        foo: false,
        bar: false
    },
    rules: [
        "if foo is true then bar is true"
    ]
})

s.on("bar", (data) => {
    console.log("New bar is", data.bar)
})

s.update({foo: true})

In this short example:

  • State fields are defined and inited with configuration {foo: false, bar: false}.
  • State is updated with new values {foo: true}.
  • The rule if foo is true then bar is true is applied and bar is updated to true.
  • Because a listener has been added for bar changes, it is invoked and passed state data.

That's the entirety of the Keel process. It's simple--and remains so, even as your app grows more complex.

const s = makeState({
    data: {
        page: null,
        authenticated: false,
        instruction: null,
        emailValid: false,
        passwordValid: false,
        submitEnabled:false,
        modal: null
    },
    rules: [
        "if page is null and authenticated is true then set page home",
        "if page is not null and page is not login and authenticated is now false then set page login and set instructions goodbye",
        "if page is null and authenticated is false then set page login and set instructons signIn",
        "if emailValid is false then set submitEnabled false and set modal emailMistake",
        "if emailValid is true and passwordValid is false then set submitEnabled false and set modal passwordMistake",
        "if emailValid is true and passwordValid is true then set submitEnabled true",
        "if page is loading then set instruction wait",
        "if authenticated is now true then set page home and set instructions hello"
    ]
})

s.on("page", showPage)
s.on("instruction", showInstruction)
s.on("submitEnabled", showSubmit)
s.on("modal", showModal);

s.update({authenticated: getAuthenticated()})

The benefits of Keel are twofold:

  • State is gathered into one place and updated according to clear rules, all at once.
  • Non-state code no longer worries about state. Imagine how straightforward functions like showPage, showInstructionq, showSubmit and showModal can be now.

Expressions

When you create a state, you can specify expressions as well as fields and rules. Expressions make rules more expressive:

const s = makeState({
    data: {...},
    expressions: {
        rejected: "page was loading and page is login",
        logout: "authenticated is now false"
    }
    rules: [...]
})

Now you can create rules with these expressions:

if rejected then set instruction tryAgain
if logout then set instruction goodbye

Expressions can be used in other expressions:

clearInputs: rejected or logout

Just as listeners can be bound to state fields, they can be bound to state expressions:

s.on("clearInputs", clearInputs)

Expression literals can also be bound:

s.on("authenticated is now false or page is now login", clearInputs)

A mix:

s.on("logout and page is editor", saveNag)

Just as with field triggers, expression triggers work only when the underlying values change.

Grammar

Keel's Booleanese sugar rests on a rudimentary grammar. The verbs:

then, or, and, set, inc, was, was not, is, is not, is now, is not now, has changed, has not changed, greater than, less than

The sentences are triplets with the verb in the middle:

x is y
x was not 3
x is not now 3

Irregulars:

x has changed
set x y
inc x

Keel works on the simple sentence level and does not have clauses. It creates syntax trees by waiting to resolve the highest priority verbs last:

then > or > and > set > inc > was > was not > is > is not > is now > is not now > has changed > has not changed > greater than > less than

if x is 0 then set y 1

This is resolved into a syntax tree like this:

{x -> is <- 0} -> then <- {y -> set <- 1}

A sentence with two high-level thens could not be resolved into a single tree. If you need two thens, make sure one exists in an expression, because verb expressions are weaker and resolved first.

However, the point of Keel is to express your state logic in the simplest, clearest way possible. If your rules are bumping up against syntax, ask yourself if you need more rules rather than more complex syntax.