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

pmx-vm

v1.0.0

Published

TypeScript runtime for the PX/PMX language - load, decrypt and execute .pmx bytecode.

Downloads

391

Readme

pmx-vm

TypeScript runtime for the PX/PMX language — a small Pawn/SA:MP-flavored scripting language that compiles to encrypted .pmx bytecode. pmx-vm loads those .pmx files (AES-256-GCM with a key derived from a passphrase), verifies them, and executes them in a sandboxed stack VM that runs on Node.js 18+ and Bun.

Status: pre-1.0. The bytecode format is versioned; this release is v5.

Install

npm install pmx-vm
# or
bun add pmx-vm

Quick start

import {
  loadPmx,
  registerBuiltins,
  ref,
  PmxScriptException,
  VM,
  type Ref,
  type StructValue,
} from "pmx-vm";

const vm = new VM();
registerBuiltins(vm); // print / println / printf / format / strlen / strcat / exception

// Custom natives the script can call:
vm.registerNative("LogEvent", (tag: string, payload: string) => {
  console.log(`[${tag}] ${payload}`);
  return 1n;
});

// `&out` parameters arrive as a Ref<T> box that the host fills:
vm.registerNative("MakeNonce", (out: Ref<string>) => {
  out.value = crypto.randomUUID();
  return 1n;
});

// Whole-array struct refs are also supported (Ref<StructValue[]>).
vm.registerNative("ListUsers", (list: Ref<StructValue[]>) => {
  list.value = [
    { name: "ada", score: 100n, alive: 1n },
    { name: "grace", score:  90n, alive: 1n },
  ];
  return 1n;
});

const script = await loadPmx("./showcase.pmx", { vm, key: "demo" });
script.start();                                     // runs main() if present

// Call a public function and read a Ref<string> back:
const out = ref("");
script.callPublic("DumpInto", [out]);
console.log(out.value);

// Catch script-thrown exceptions:
try {
  script.callPublic("Boom", [42n, "kapow"]);
} catch (e) {
  if (e instanceof PmxScriptException) {
    console.log(e.code, e.message);
  }
}

What the VM gives you

  • Encrypted bytecode loader — AES-256-GCM payload, key derived from a passphrase via SHA-256. Tamper-evident through the GCM auth tag.
  • 64-bit stack VMcell, float, string, and bool types, with BigInt-backed integers and IEEE-754 floats stored as cell-bits.
  • Native function bridge — register host functions by name; they receive bigint | number | string arguments and may return any of the same.
  • Reference parameters (&) — for both PX-to-PX calls and host-callable publics. Scalars use a tiny Ref<T> box; struct rows use Ref<StructValue> (a JSON-shaped record keyed by struct tag strings); whole 2-D struct arrays use Ref<StructValue[]> with lenient writeback.
  • serialize / deserialize intrinsics — opcodes that round-trip struct rows and 2-D struct arrays through JSON, with strict and lenient modes.
  • PmxScriptException — script-thrown exceptions surface as a typed JavaScript error with .code: number and .message: string.
  • Per-call instruction limit — defaults to 1 000 000 ops, configurable per-VM to defend against infinite loops in untrusted bytecode.

Public API

// Loading
loadPmx(path: string, opts: LoadOptions): Promise<Script>;
loadPmxBytes(bytes: Uint8Array, opts: LoadOptions): Promise<Script>;

// Core
class VM {
  registerNative(name: string, fn: NativeFn): void;
  // ...
}
class Script {
  start(): Value;                                              // runs main()
  callPublic(name: string, args: (Value | Ref)[]): Value;
  serializeStruct(structName: string, base: number): StructValue;
  globalLayout(): { size: number; base: number }[];
  // ...
}

// Built-ins
registerBuiltins(vm: VM): void;       // print/println/printf/format/strlen/strcat/exception

// Helpers / types
ref<T>(initial: T): Ref<T>;
type Ref<T> = { value: T };
type Value = bigint | number | string;
type StructValue = Record<string, Value>;
type NativeFn = (...args: NativeArg[]) => Value | void;
class PmxScriptException extends Error { code: number; }

// Decoder primitives (advanced)
decodePayload(buf: Uint8Array): Module;
parseHeader(buf: Uint8Array): { version: number; encrypted: boolean; iv: Uint8Array; payloadLen: number; };
const PMX_VERSION: number;

Compiling .pmx files

pmx-vm only runs bytecode; it does not compile from source. Use the pxc Go compiler (separate project) to produce .pmx:

pxc build -o ./script.pmx --key demo -I . ./script.px

The bytecode version embedded in the file must match PMX_VERSION exposed by this package; otherwise loading throws.

Requirements

  • Node.js >=18 (uses node:fs/promises and globalThis.crypto.subtle)
  • Or Bun (any recent version).

License

Apache-2.0 © lenerotex