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 🙏

© 2026 – Pkg Stats / Ryan Hefner

jsr-script

v1.0.6

Published

Script execution.

Readme

Table of Contents

Script Execution Module

Script execution.

Experimental library that enables running scripts with the same semantics as EVAL, note that currently this uses synchronous JSON message passing, a later version may pass RESP messages via stdin and stdout to the child process.

Component of the jsr library.

Requires node and npm.

Install

npm i jsr-script

Compatibility

Whilst the script execution engine aims to be as compatible as possible with the redis script support there are some important differences. Primarily, scripts are javascript not lua as we are already using a scripting language, the other idiosyncrasies are:

  • Accessing the passed KEYS and ARGS start with index 0 not 1 as javascript arrays are zero-based.
  • Data type conversion differs, see data types.

Data Types

Data type conversion between javascript types and the RESP responses:

  • String: Simple string reply.
  • string: Bulk string reply.
  • number: Integers are returned as integer types, floating point numbers are returned as strings.
  • true: Coerced to the integer 1.
  • false: Coerced to the integer 0.
  • null: Null reply (nil).
  • Buffer: Coerced to string using toString and default encoding (utf8).
  • Error: Simple string error reply.
  • Array: Multi bulk reply.

In addition objects with the following structure are handled:

  • {ok: 'OK'}: Simple string reply.
  • {err: 'ERR'}: Simple string error reply.

Returning undefined or an object that does not conform to the data types described above will result in an error.

It is possible to return an error to the client by throwing the error, the following are equivalent scripts:

throw new Error('ERR');
return new Error('ERR');
return {err: 'ERR'};
return redis.error_reply('ERR');

Sandbox

The script execution sandbox exposes the following functions:

  • redis.sha1hex: Get the sha1 hex checksum of a string.
  • redis.status_reply: Return a status reply to the client.
  • redis.error_reply: Return an error reply to the client.
  • redis.call: Execute a command with arguments.
  • redis.log: Log a message.

In addition the following globals are exposed:

  • Error: Error class.
  • JSON: JSON parse and stringify.
  • Buffer: Buffer class.
  • util: The util module.
  • crypto: The crypto module.

Log

The redis.log method will log a message and return the message, it behaves almost identically to the redis version:

return redis.log(redis.LOG_DEBUG, "debug message");
return redis.log(redis.LOG_VERBOSE, "verbose message");
return redis.log(redis.LOG_NOTICE, "notice message");
return redis.log(redis.LOG_WARNING, "warning message");

But you may also pass replacement parameters:

return redis.log(redis.LOG_DEBUG, "args: %s", ARGS);

Or the full command using EVAL:

eval 'return redis.log(redis.LOG_DEBUG, "args: %s", ARGS);' 0 foo bar

Challenge

Designing the script execution engine posed some interesting challenges, for example, how to cope with infinite loops and bad function calls:

while(true){}
process.exit(1)

The former infinite loop would block the server if it were executed in the main process and there would be no way to catch a script execution timeout which would make it impossible to implement the semantics of SCRIPT KILL.

The latter would just exit the process and cause all sorts of problems.

The solution decided upon is to spawn a child process for script execution and use the vm module to create a sandbox for the compiled scripts. Using a child process for script execution allows the parent process to continue serving clients while long-running scripts are executing and using a vm sandbox for the script makes calling process.exit impossible as well as preventing global variable leak.

Using a child process for script execution posed some more interesting design challenges as the parent and child process' need to communicate. While the messaging is actually synchronous it is not possible to return a value from a call to the parent process as the communication is based on events. This is abstracted away so that invoking:

return redis.call("get", "foo");

Will return a function which instructs the script execution to wait for the result of the command execution from the parent process.

Because the calls to the parent process are synchronous it is still possible to block the parent process by issuing commands that would result in a large amount of data being converted to JSON and returned to the script execution process:

return redis.call("keys", "*");

Developer

Test

Tests are not included in the package, clone the repository:

npm test

Documentation

To generate all documentation:

npm run docs

Readme

To build the readme file from the partial definitions (requires mdp):

npm run readme

License

Everything is MIT. Read the license if you feel inclined.

Generated by mdp(1).