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

nisp

v0.13.8

Published

A language that for easily build cross-language language

Downloads

8,759

Readme

nisp

NPM version Build Status Deps Up to Date

The interesting part is that nisp is designed to be Turing incomplete.

You have the full control of the vm and ast, you can decide what the language will have, or how lazy the expression will be. for example, if you don't expose the if exp the user can never express if logic.

By default nisp only presents the meta data of the program itself. So by default it is used to exchange plain data.

You may ask what it really does? Yes, it does nothing. And that is exactly what a composable permission protocol needs. I use it to expose composable api.

The ast of nisp is plain JSON, the js implementation is only around 50 lines of code, so it will be very easy to port nisp to other languages. No closure or complex data type is required, even plain C can implement nisp easily.

Everything inside nisp is just function, so it's very easy to keep everything type safe, and with the composable nature, nisp is an ideal middle layer to carry query or RPC. Such as the Websocket RPC lib based on nisp: https://github.com/ysmood/nisper.

Quick Start

For more examples, read the unit test of this project.

Try it online: https://runkit.com/ysmood/nisp-demo

Implementaions

  • Golang: https://github.com/ysmood/gisp
  • Ruby: https://github.com/ysmood/ruby-nisp

Define your own function

For a simple example, here you can use it as a sum-only-calculator.

import nisp from 'nisp'

var sandbox = {
    '+': (a, b) => a + b
};

var exp = ['+', 1, ['+', 1, 1]];

nisp(exp, sandbox); // => 3

Encode and escape data

Sometimes you may want to separate nisp code and raw data, Here we provide encode function to reduce the pain of typing quotes and commas. The grammar is a subset of lisp.

import nisp from 'nisp'
import encode from 'nisp/lib/encode'
import $ from 'nisp/lib/$'

var sandbox = {
    $, // raw data
    "+": ns => ns.reduce((a, b) => a + b),
    "++": ns => ns.map(a => a + 1)
};

var data = [1, 2, 3]

var exp = encode`(+ (++ ${data}))`

nisp(exp, sandbox); // => 9

Composable RPC and safe by design

Commonly used RPC libs such as json-rpc, thrift and GRPC can only handle function per call, if you want to handle large amount of data with two procedures, you have to load all of them on each procedure, that is a big waste. With nisp, you can seamlessly compose multiple functions into one remote call.

We even used nisp to create a simple db query language, and it automatically helps us defense insertion attach by its nature.

import nisp, { error } from 'nisp'

var sandbox = {
    concat (...args) {
        return args.reduce((a, b) => a.concat(b));
    },

    getAnimals () {
        if (this.env.isZooKeeper)
            return ['cat', 'dog'];
        else
            error(this, "Not Allowed"); // it will log error stacks
    },

    getFruits () {
        return ['apple', 'banana'];
    }
};

var session = {
    user: 'Jack',
    isZooKeeper: true
}

var exp = ["concat", ["getAnimals"], ["getFruits"]];

nisp(exp, sandbox, session);

Full control the ast with macro

Here we implementation a if expression The if expression is very special, it cannot be achieved without ast manipulation.

import nisp from 'nisp'
import encode from 'nisp/lib/encode'
import $ from 'nisp/lib/$'
import args from 'nisp/lib/args'
import $do from 'nisp/lib/do'

var sandbox = {
    $,

    // Most times you don't want to use it.
    "non-lazy-if": (cond, a, b) => cond ? a : b,

    // Full lazy.
    if: args(v => v(0) ? v(1) : v(2)),

    // Even half lazy, you have the full control to how lazy the program will be.
    // No matter v(0) is true or false, v(1) will be calculated.
    "half-lazy-if": args(function (v) {
        var v1 = v(1);
        return v(0) ? v1 : v(2);
    }),

    do: $do,

    "+" (...args) {
        console.log('calc:', args);
        return args.reduce(function (s, n) { return s + n; });
    })
};

var exp = encode`(do
    (if           true  (+ 1 1) (+ 2 2))
    (non-lazy-if  false (+ 1 1) (+ 2 2))
    (half-lazy-if true  (+ 1 1) (+ 2 2))
)`;

nisp(exp, sandbox);

Make a complete async language

var nisp = require("nisp");
var async = require("nisp/lib/async");

function waitNumber (val) {
    return new Promise(function (r) {
        return setTimeout((function () {
            return r(val);
        }), 1000);
    });
};

var sandbox = {
    download: async(() => waitNumber(1))

    "+": async((a, b) => a + b)
};

// Here we can write async code a sync way.
var exp = ["+", ["download"], ["download"]];

nisp(exp, sandbox).then(function (out) {
    // It will take about 1 seconds to log out.
    console.log(out) // => 2
});

API

The project is written in typescript, all main APIs are typed and commented.