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

@voidwalkers/void-cli

v0.1.20

Published

CLI for Void Walkers Void

Readme

@voidwalkers/void-cli

Command-line interface for Void Walkers Void — a backend platform for serverless functions, static websites, MongoDB databases, object storage and project management.

The CLI lets you bootstrap a project, enable platform components, manage settings and configs, and deploy your code and assets.

Requirements

  • Node.js 18+ (the CLI uses ES modules, top-level await and JSON import attributes)
  • Access to the Void platform. There are no self-service accounts: an administrator uses an admin secret to manage users, projects and per-project access tokens. To work on a specific project you need its private/public token pair (issued by the admin and stored in void.json).

Installation

npm i -g @voidwalkers/void-cli

After installation the void-cli binary is available globally.

void-cli --help
void-cli --version

Quick start

# 1. Initialize a project in the current directory
void-cli init

# 2. (optional) Enable extra components later
void-cli enable mongo

# 3. Deploy your functions and websites
void-cli deploy

init creates a void.json config file in the current directory. It contains your project slug and secret tokens, so make sure to add it to .gitignore:

void.json

Configuration

void.json

The project config is stored in void.json in the working directory. It is created and maintained by the CLI (init, enable, mongo database create, storage buckets create, websites domains set/remove, etc.). A typical file looks like:

{
  "project": {
    "slug": "my-project",
    "tokenPrivate": "<base64 private token>",
    "tokenPublic": "<base64 public token>",
    "functions": {
      "entryPoint": "./src/index.js",
      "include": ["src"]
    },
    "websites": {
      "items": [
        {
          "name": "default",
          "public": "./dist",
          "customDomain": { "root": "void-walkers.com", "subdomain": "shop" }
        }
      ]
    },
    "mongo": {
      "databases": [
        { "name": "default", "password": "...", "accessRules": {} }
      ]
    },
    "storage": {
      "buckets": [
        { "name": "uploads", "type": "protected", "accessRules": {} }
      ]
    }
  }
}
  • tokenPrivate — used for privileged operations (deploy, configs, settings, rules).
  • tokenPublic — safe to embed in client applications.
  • mongo.databases[].accessRules and storage.buckets[].accessRules — declarative access control, deployed with void-cli mongo rules deploy / void-cli storage rules deploy. See Access rules for the full schema.

Global admin config

Admin authentication is stored separately in ~/.void.json (managed by void-cli admin login / logout). It holds your admin secret and is not tied to a project directory.

Environment variables

The CLI talks to the Void platform at https://void.void-walkers.com by default. You can override the endpoints (e.g. for staging or self-hosted installs):

| Variable | Default | Purpose | | --------------- | --------------------------------- | ------------------------------ | | BASE_URL | https://void.void-walkers.com | Base URL for all services | | BASE_URL_API | value of BASE_URL | API endpoint | | BASE_URL_CDN | value of BASE_URL | CDN / file upload endpoint |

Companion libraries

The CLI is the deploy/management tool; your project's runtime code uses two npm packages. Together they cover both sides of a Void project: functions you deploy, and a client SDK you call from browsers, functions or other backends.

| Package | Where it runs | Purpose | | --------------------------- | ------------------------------------- | ----------------------------------------------------------------- | | @voidwalkers/void-functions | inside functions/ (deployed code) | Register serverless functions and read project configs | | @voidwalkers/void-client | browsers / functions / any backend | SDK for auth, MongoDB, object storage, realtime and function calls |

@voidwalkers/void-functions

Used inside the functions/ package (the one the CLI scaffolds and deploys). It exposes the registration entry points the Void runtime calls into:

import {registerHttpFunction, registerCallFunction, getConfigValue} from '@voidwalkers/void-functions';

// HTTP function — invoked over HTTP, gets Express-like (req, res)
registerHttpFunction('hello-world', (req, res) => {
  res.send('Hello World!');
});

// Call function — invoked via the client SDK's voidClient.function(name)(data)
registerCallFunction('echo', (data, context) => {
  // context.projectUser === {id} of the authenticated user (or null)
  return {context, data};
});

// Read a project config value set with `void-cli config set <key> <value>`
const flag = await getConfigValue('featureFlag', false); // second arg = default

The optional third options argument controls how a function is exposed (this is where the exported enums are used):

import {registerCallFunction, FunctionSystemRole, FunctionTriggerSubject, FunctionTriggerEvent}
  from '@voidwalkers/void-functions';

registerCallFunction('auth', handler, {systemRole: FunctionSystemRole.UserAuth});      // user-auth handler
registerCallFunction('on-write', handler, {                                            // event-triggered
  trigger: {subject: FunctionTriggerSubject.MongoDocument, event: FunctionTriggerEvent.Write}
});
registerHttpFunction('internal', handler, {isPrivate: true});                          // not client-callable

Setting any of isPrivate, systemRole or trigger makes the function private (deployed but not directly callable by clients). Call vs Http is chosen by which register function you call — not via options.

| Export | Purpose | | ------------------------------------------- | ------------------------------------------------------------------- | | registerHttpFunction(name, fn, options?) | Register an HTTP-triggered function (req, res) => … | | registerCallFunction(name, fn, options?) | Register a callable function (data, context) => result | | getConfigValue(key, defaultValue?) | Read a project config (throws if missing and no default given) | | FunctionSystemRole | Enum for options.systemRole — e.g. UserAuth | | FunctionTriggerEvent / FunctionTriggerSubject | Enums for options.trigger (create/update/delete/write/schedule; auth_user/mongo_document/schedule) | | ProjectUserCredentialsType | Enum — Custom / Email |

See the void-functions README for the full options reference.

Deploy registered functions by name (or all of them):

void-cli deploy -F                # all functions
void-cli deploy -F echo hello-world

@voidwalkers/void-client

The client SDK. Construct it with the project's public token (safe to ship to browsers); get the snippet via void-cli credentials print client.

import {VoidClient} from '@voidwalkers/void-client';

const voidClient = new VoidClient({
  project: {slug: 'my-project', tokenPublic: '<public token>'}
});

// Auth
await voidClient.auth.signInCustom({email: '[email protected]', password: 'secret'});
const user = await voidClient.auth.getCurrentUser(); // {id: 'UUID'}

// MongoDB (queries are subject to the database access rules below)
await voidClient.mongo.collection('items').insertOne({type: 'box', name: 'empty box'});
const {data} = await voidClient.mongo.collection('items').find({type: 'box'}, {limit: 50});
voidClient.mongo.collection('items').watch({type: 'box'}, ({type, data}) => { /* realtime */ });

// Object storage (subject to bucket access rules below)
await voidClient.storage.bucket('photos').createFile(blobOrStream, 'kitten.jpg', ['kittens']);
await voidClient.storage.bucket('photos').listFiles({prefix: ['kittens'], limit: 100});

// Call a registered call-function
const result = await voidClient.function('echo')({hello: 'world'});

Surface: voidClient.auth, voidClient.mongo (.collection(name) / .db(name).collection(name)), voidClient.storage.bucket(name), voidClient.function(name). See the void-client README for the full method list and option shapes.

Access from the client is gated by the access rules you deploy with the CLI. Read Access rules before writing rules — the client cannot do anything the rules don't permit.

Commands

Run void-cli <command> --help for detailed, up-to-date usage of any command.

init

Initialize a Void project in the current directory. Prompts for a project slug, private token and public token, then creates void.json and scaffolds the selected components.

void-cli init
void-cli init -c functions websites          # only enable specific components

| Option | Description | | ------------------------------- | ---------------------------------------------------------------- | | -c, --components [components…] | Components to enable: functions, websites, mongo (all by default) |

Fails if void.json already exists.

enable

Enable one or more components in an already-initialized project. Components that are already enabled are skipped.

void-cli enable functions
void-cli enable mongo websites

Accepted components: functions, websites, mongo.

deploy

Deploy project parts to the platform. With no flags, deploys everything (functions and websites). Deploying functions runs npm run lint and npm run test in the functions/ directory first (when those scripts exist).

void-cli deploy                          # deploy all functions and websites
void-cli deploy -F                       # deploy all functions
void-cli deploy -F hello-world api       # deploy specific functions
void-cli deploy -W                       # deploy all websites
void-cli deploy -W default               # deploy a specific website

| Option | Description | | ------------------------------- | -------------------------------------------- | | -F, --functions [functions…] | Deploy functions (optionally by name) | | -W, --websites [websites…] | Deploy websites (optionally by name) |

config

Manage project key/value configs (read by your functions at runtime).

void-cli config set <key> [value]
void-cli config set featureFlag true -t boolean
void-cli config set maxItems 50 -t number
void-cli config set apiKeys '["a","b"]' -t array
void-cli config set someKey              # omit value to set null

| Option | Description | | ------------------- | --------------------------------------------------------------------- | | -t, --type <type> | Value type: boolean, number, string, object, array |

settings

Manage built-in project settings (e.g. authentication providers).

void-cli settings list                          # show all settings, types and defaults
void-cli settings set auth.email.isEnabled true
void-cli settings set auth.email.providers.resend.apiKey "re_xxx"

| Subcommand | Description | | -------------------- | -------------------------------------------- | | list | List available settings with types/defaults | | set <key> [value] | Set a setting value (omit value to set null) |

Setting keys are dot-paths, e.g. auth.email.provider. Values are validated against the type declared for each setting.

credentials

Print project credentials from void.json in different formats.

void-cli credentials print            # client format (default)
void-cli credentials print client     # slug + public token (safe for clients)
void-cli credentials print server     # slug + private token
void-cli credentials print raw        # entire void.json

mongo

Manage the project's MongoDB instance.

# Databases
void-cli mongo database create <name>
void-cli mongo database drop <name>

# Connection credentials
void-cli mongo credentials print                       # internal connection string
void-cli mongo credentials print internal -d default
void-cli mongo credentials print internal --pretty     # JS snippet
void-cli mongo credentials print external              # (not implemented yet)

# Access rules
void-cli mongo rules deploy                 # deploy rules for "default" database
void-cli mongo rules deploy -d analytics

| Subcommand | Options | Description | | -------------------------------- | --------------------------------------------------- | -------------------------------------------- | | database create <name> | | Create a MongoDB database | | database drop <name> | | Drop a MongoDB database | | credentials print [variant] | -d, --database <name>, -p, --pretty | Print connection string (internal/external) | | rules deploy | -d, --database <name> | Deploy access rules from void.json |

Access rules are read from project.mongo.databases[].accessRules in void.json and pushed to the platform. See Access rules for the full schema, the expression language and the available context variables.

storage

Manage object storage buckets and files.

# Buckets
void-cli storage buckets create <name>
void-cli storage buckets create uploads -t public

# Upload files
void-cli storage buckets upload <bucket> <file>
void-cli storage buckets upload uploads ./logo.png -n logo.png -p images

# Access rules
void-cli storage rules deploy                       # all buckets
void-cli storage rules deploy -b uploads avatars    # specific buckets

| Subcommand | Options | Description | | ----------------------------------- | ----------------------------------------------- | ------------------------------------ | | buckets create <name> | -t, --type <type> (private/protected/public, default protected) | Create a bucket | | buckets upload <bucket> <file> | -n, --name <name>, -p, --prefix <prefix> | Upload a local file to a bucket | | rules deploy | -b, --buckets <buckets…> | Deploy bucket access rules |

Access rules are read from project.storage.buckets[].accessRules in void.json. See Access rules for the full schema and the available context variables.

websites

Add websites and manage their custom domains. Custom domains are managed only via these commands — deploy never touches them.

# Add a new website
void-cli websites add <slug>
void-cli websites add shop

# Custom domains
void-cli websites domains set <website> <subdomain>.<root>
void-cli websites domains set default shop.void-walkers.com
void-cli websites domains remove <website>
void-cli websites domains list

| Subcommand | Description | | ---------------------------------- | ----------------------------------------------------------- | | add <slug> | Add a new website: scaffold websites/<slug>/dist/index.html and register it in void.json | | domains set <website> <domain> | Set a custom domain (<subdomain>.<root>) for a website | | domains remove <website> | Remove the custom domain from a website | | domains list | List each website's default and custom domain (void.json) |

  • <slug> is used as a Kubernetes pod name during website initialization, so it must be K8s-safe: lowercase alphanumeric characters or -, starting and ending with an alphanumeric character, no dots, and at most 120 characters.

  • The website is appended to websites.items in void.json with public: "./dist". If the websites/<slug>/dist directory already exists it is left untouched.

  • Requires the websites component to be enabled (void-cli enable websites or void-cli init).

  • The <domain> argument is split on the first dot: the first label is the subdomain, the remainder is the root. It is stored in void.json as customDomain: { root, subdomain }.

  • One custom subdomain per website (enforced by the API).

  • Allowed roots: void-walkers.com, ribogdanova.com.

  • The website must be deployed first before a custom domain can be set; otherwise the API returns 404 and the CLI hints you to run void-cli deploy -W <website>.

  • list reads only void.json (no API call) and shows each website's default domain (void-<slug>[-<name>].void-walkers.com) plus its custom domain when set.

admin

Administrative tasks. Requires an admin secret stored via admin login (kept in ~/.void.json).

# Authentication
void-cli admin login
void-cli admin logout

# Users
void-cli admin users create [email]
void-cli admin users list

# Projects
void-cli admin projects create <slug> -u <userId>
void-cli admin projects create my-app -u 123 --tokens          # also create default tokens
void-cli admin projects create my-app -u 123 --private-token "My token"
void-cli admin projects list -u <userId>

| Subcommand | Options | Description | | ------------------------------ | --------------------------------------------------------- | ------------------------------------ | | login | | Store the admin secret | | logout | | Remove the stored admin secret | | users create [email] | | Create a user (prompts for email if omitted) | | users list | | List all users | | projects create <slug> | -u, --user <id> (required), --private-token [name], --public-token [name], -t, --tokens | Create a project for a user | | projects list | -u, --user <id> (required) | List a user's projects |

Access rules

Access rules are declarative authorization for MongoDB and object storage. They are authored in void.json, then pushed to the platform with void-cli mongo rules deploy / void-cli storage rules deploy. Every query a client makes through @voidwalkers/void-client is evaluated against them server-side — there is no way for a client to bypass them.

The CLI translates the friendly void.json form into the platform's wire format on deploy (see src/lib/rules.js, src/lib/components/mongo.js, src/lib/components/storage.js), so you only ever write the form documented here.

The rule expression language

A rule is a small boolean expression. The CLI accepts a MongoDB-like syntax and converts it before deploying:

| Form | Meaning | | --------------------------- | ------------------------------------------------------------------- | | {"$and": [r1, r2, …]} | all sub-rules must be true (1+ items) | | {"$or": [r1, r2, …]} | at least one sub-rule true (1+ items) | | {"$eq": [a, b]} | a equals b (exactly 2 items) | | "$$name.path.0" | a variable reference$$ + dotted path; numeric segments index arrays | | any literal (true, 42, "x") | a constant value |

You may also write the already-converted raw form directly, e.g. a constant allow/deny:

{"rule": {"type": "value", "value": true}}    // always allow
{"rule": {"type": "value", "value": false}}   // always deny

Important: this rule engine only understands $and / $or / $eq / $$var / literals (see src/lib/rules.js). It is not full MongoDB query/aggregation. The richer MongoDB aggregation syntax is only available inside pipeline, lookup and redact stages (described below), which actually run in MongoDB.

Context variables

The variables available to a rule depend on the operation:

| Variable | Available in | Shape | | -------------------- | --------------------------------------------- | ------------------------------------------------------------ | | $$voidProjectUser | all operations | {id} of the authenticated user, or null if anonymous | | $$voidDoc | mongo create | the document being inserted | | $$voidResult | mongo create, all bucket ops | the array returned by the operation's pipeline (or null) | | $$voidUpdate | mongo update (inside redact) | the update doc with $ stripped, e.g. {set: {…}, unset: {…}} | | $$voidFile | all bucket operations | {name, prefix}prefix is the path-segment array |

MongoDB rules

void.json shape — keyed by collection name, then by operation:

"mongo": {
  "databases": [
    {
      "name": "default",
      "accessRules": {
        "<collectionName>": {
          "create": { "collection": "...", "pipeline": [ … ], "rule": { … } },
          "read":   { "lookup": [ … ], "redact": { … } },
          "update": { "lookup": [ … ], "redact": { … } },
          "delete": { "lookup": [ … ], "redact": { … } }
        }
      }
    }
  ]
}

Operations map to the client methods on voidClient.mongo.collection(name):

| Operation | Triggered by | How the rule is enforced | | --------- | ----------------------------------------- | ---------------------------------------------------------------------------------------- | | create | insertOne / insertMany | optional pipeline runs against collection$$voidResult; then rule must be true | | read | find / findOne / watch | redact is a MongoDB $redact stage deciding $$KEEP / $$PRUNE per document | | update | findOneAndUpdate / updateOne / … | same $redact mechanism; $$voidUpdate exposes the requested changes | | delete | deleteOne / deleteMany | same $redact mechanism |

Per-operation fields:

  • create
    • collection (optional) — another collection to look something up in first.
    • pipeline (optional) — a MongoDB aggregation pipeline run against collection; it can reference $$voidDoc and $$voidProjectUser. Its output becomes $$voidResult.
    • rule — the boolean expression; insertion is allowed only if it evaluates truthy. Can use $$voidDoc, $$voidProjectUser, $$voidResult.
  • read / update / delete
    • redact — a MongoDB $redact expression returning $$KEEP / $$PRUNE / $$DESCEND. Runs inside MongoDB, so it uses full aggregation syntax and can reference document fields ($field), $$voidProjectUser, and (for update) $$voidUpdate.
    • lookup (optional) — an array of $lookup stage bodies injected before the redact stage (joined fields are projected back out afterwards).

A collection with no rule for an operation rejects that operation by default — start by writing rules for every operation a client needs.

Object storage rules

void.json shape — keyed directly by operation:

"storage": {
  "buckets": [
    {
      "name": "user-files",
      "type": "protected",
      "accessRules": {
        "create": { "rule": { … } },
        "read":   { "collection": "...", "database": "...", "pipeline": [ … ], "rule": { … } },
        "update": { "rule": { … } },
        "delete": { "rule": { … } },
        "list":   { "rule": { … } }
      }
    }
  ]
}

Bucket types (-t on storage buckets create):

| Type | Behaviour | | ----------- | --------------------------------------------------------------------------------- | | public | files served publicly by URL; no per-request access rules | | protected | every operation is gated by the access rules below (default) | | private | no direct client access — reachable only from server-side / privileged code |

Operations: create, read, update, delete, list (mapping to voidClient.storage.bucket(name) methods). Per-operation fields:

  • rule — boolean expression; the operation is allowed only if it evaluates truthy. Can use $$voidFile, $$voidProjectUser, and $$voidResult.
  • collection + pipeline (optional) — run a MongoDB aggregation (against database, default default) before evaluating rule; the pipeline can reference $$voidFile and $$voidProjectUser, and its output becomes $$voidResult.
  • database (optional) — which MongoDB database the lookup collection lives in; defaults to default when collection or a non-empty pipeline is present.

Worked example

A user-files bucket where each user may only read files under a prefix equal to their own id, and an items collection where users only see and mutate their own rows:

{
  "project": {
    "mongo": {
      "databases": [
        {
          "name": "default",
          "accessRules": {
            "items": {
              "create": {
                "collection": "users",
                "pipeline": [
                  {"$match": {"$expr": {"$eq": ["$voidId", "$$voidDoc.userId"]}}}
                ],
                "rule": {
                  "$and": [
                    {"$eq": ["$$voidDoc.userId", "$$voidProjectUser.id"]},
                    {"$eq": ["$$voidResult.length", 1]}
                  ]
                }
              },
              "read": {
                "redact": {
                  "$cond": {
                    "if": {"$eq": ["$$voidProjectUser.id", "$userId"]},
                    "then": "$$KEEP",
                    "else": "$$PRUNE"
                  }
                }
              }
            }
          }
        }
      ]
    },
    "storage": {
      "buckets": [
        {
          "name": "user-files",
          "type": "protected",
          "accessRules": {
            "create": {"rule": {"type": "value", "value": true}},
            "read": {
              "collection": "users",
              "pipeline": [
                {"$match": {"$expr": {"$eq": ["$voidId", "$$voidProjectUser.id"]}}}
              ],
              "rule": {
                "$and": [
                  {"$eq": ["$$voidResult.length", 1]},
                  {"$eq": ["$$voidFile.prefix.length", 1]},
                  {"$eq": ["$$voidFile.prefix.0", "$$voidProjectUser.id"]}
                ]
              }
            },
            "list": {"rule": {"type": "value", "value": true}}
          }
        }
      ]
    }
  }
}

Deploy after editing:

void-cli mongo rules deploy                 # database "default"
void-cli storage rules deploy -b user-files  # one or more buckets (all if omitted)

Project layout

After init, a typical project looks like:

.
├── void.json            # project config (gitignored — contains tokens)
├── functions/           # serverless functions package (its own package.json)
│   └── src/index.js
└── websites/
    └── default/
        └── dist/
            └── index.html
  • functions/ is a standalone Node package using @voidwalkers/void-functions. The CLI runs npm install there on init, and npm run lint / npm run test on deploy.
  • websites/ holds one directory per website; the public sub-path (default ./dist) is what gets deployed.

Development

npm install
npm run start      # run the CLI from source (node ./src/app.js)
npm run lint       # eslint
npm test           # mocha

License

UNLICENSED — © Andrey Bogdanov. Internal Void Walkers project.