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

luma-lang

v1.0.4

Published

The Embeddable Luma Language Compiler and Runtime

Readme

Introduction to Luma

Welcome to Luma!

Luma is a lightweight, high-performance scripting language designed to be embedded within any JavaScript or TypeScript application. It works seamlessly on both the server and client-side and in (Web)Workers, making it an ideal solution for game logic, modding systems, and rule engines.

Core Philosophy

  • Embeddable: Designed to live inside your host application, not replace it.
  • Secure: Runs in a strictly isolated sandbox. No access to the host's window, process, or global prototypes unless explicitly granted.
  • Familiar: Syntax inspired by Python (indentation-based) and JavaScript (dynamic typing).
  • Resumable: Scripts can be paused (wait), saved to disk, and resumed later.
  • Budgeted: Prevent infinite loops from freezing your app with tick-based execution limits.

Intuitive Syntax

Luma’s syntax utilizes an indentation-based structure to reduce visual clutter. It supports modern features like string interpolation, array comprehensions, and classes.

// A simple Luma script
class Greeter(name):
    name = name

    fn greet(times):
        // String interpolation
        print("Hello, {this.name}!")
        
        // Python-style array comprehension
        return [i * 10 for i in 0..times]

greeter = new Greeter("World")

// Call methods
result = greeter.greet(3)

Security & Sandboxing

One of Luma's strongest features is its security model. Luma scripts run in a virtualized environment that is completely isolated from the host.

  • No Global Leakage: Scripts cannot pollute the host's global scope.
  • Prototype Protection: Access to __proto__ and constructor is blocked at the VM level, preventing common sandbox escapes.
  • Controlled Interop: The script can only access functions and classes (fine-tuned to individual properties and methods) you explicitly expose.

Compilation & Binary Serialization

Scripts in Luma are compiled into bytecode before execution. This model ensures the scripts run efficiently and allows for binary caching.

Basic Compilation

To run a script, you compile source code into a Program object.

import { Compiler } from 'luma-lang';

// Compile a Luma script into a Program
const program = Compiler.compile(`print("Hello, Luma!")`);

Binary Export (Pre-compilation)

You can pre-compile Luma scripts to binary formats (Uint8Array) using the Writer and Reader APIs. This allows you to ship compiled assets and skip parsing at runtime.

import { Compiler, Reader, Writer } from 'luma-lang';

// 1. Serialize the Program to binary
const binary = Writer.write(program);

// 2. Deserialize from binary later
const loadedProgram = Reader.read(binary);

Performance Tip:

Although completely optional, pre-compiling scripts to binary format can significantly reduce load times, especially for large scripts or when loading multiple scripts at once. This becomes critical if you load scripts during a game loop.

Tick-based Execution & Time Travel

Luma uses a tick-based Virtual Machine. This allows for tight integration with host applications (like game loops) and enables the wait keyword directly in your scripts.

const vm = new VirtualMachine(program, {
    budget: 100, // Optional: Limit instructions per tick to prevent freezing
});

// In your application loop:
function gameLoop() {
    // Advances the VM by a frame (deltaTime in milliseconds)
    vm.run(deltaTime); 
    
    requestAnimationFrame(gameLoop); 
}

In your Luma script, you can pause execution without blocking the host:

print("Start")
wait(1000) // Pauses this script for 1 second, host keeps running!
print("End")

Native Async Interoperability

Luma supports asynchronous host functions out of the box. If you expose a host function that returns a Promise (such as a database query or a fetch request), Luma will pause the script execution until that Promise resolves.

This creates an "automatic await" behavior, allowing you to write synchronous-looking code in Luma that handles asynchronous tasks.

// Expose an async function to Luma
const vm = new VirtualMachine(program, {
    functions: {
        // The VM detects that this returns a Promise
        async fetchData(url: string): Promise<string> {
            const response = await fetch(url);
            return response.text();
        }
    }
});

In your Luma script, you call this function normally. The script halts at the function call:

// The script pauses here automatically
data = fetchData("https://example.com/data")

// This line runs only after the Promise resolves AND the host calls vm.run()
print("Fetched Data: " + data)

[!WARNING] The VM is Passive

When the script invokes an async function, the VM pauses and vm.run() returns immediately. The VM does not automatically resume itself when the Promise resolves. You must continue to call vm.run() in your host application's update loop (e.g., every frame).

  • If the Promise is still pending, vm.run() does nothing (returns immediately).
  • Once the Promise resolves, the next call to vm.run() will resume the script where it left off.

State Persistence

Luma allows you to snapshot the entire state of the Virtual Machine. This is critical for features like ** Save / Load ** in games or session resumption in interactive apps.

// Save the full state (variables, stack, instruction pointer)
const serializedState = vm.save();

// Restore the state later - the script continues exactly where it left off
vm.load(serializedState);

[!WARNING] Versioning Warning: Saved states are tightly coupled to the structure of the compiled Program. If you recompile the source code, the VM may not be able to load a state saved from a previous version.


Contributing

To set up the development environment, clone the repository and install dependencies:

npm install

Build the project using npm run build or npm run watch for continuous builds. Once built, you have two options to run the tests:

  • Run the entire suite once: npm run test
  • Run tests in watch mode: npm run watch:test