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

@sysdml/renderer

v0.1.2

Published

Vue 3 + Vite renderer for SysDML stock-and-flow diagrams. Consumes a compiled `@sysdml/ir` model and renders the diagram on an SVG canvas, with a Web Worker running `@sysdml/simulator` alongside so simulation output is available as reactive state.

Readme

@sysdml/renderer

Vue 3 + Vite renderer for SysDML stock-and-flow diagrams. Consumes a compiled @sysdml/ir model and renders the diagram on an SVG canvas, with a Web Worker running @sysdml/simulator alongside so simulation output is available as reactive state.

Part of the SysDML monorepo. See the root README for the overall architecture and how the packages fit together.

How it's embedded

The renderer is a self-contained Vite app that takes an IR from a transport and draws the diagram. Three transports ship today:

| Mode | Transport | How IR arrives | | ----------------------- | -------------------- | ------------------------------------------------------------------------------------------------------ | | VS Code webview | PostMessageAdapter | Extension fetches IR from the LSP server and postMessages {type:"update", ir} | | pnpm dev browser | WebSocketAdapter | Vite plugin sysdml-dev watches SYSDML_FILE, parses + compiles in Node, broadcasts over a WebSocket | | Headless / no transport | NullAdapter | Empty canvas |

Selection is automatic — createTransport() in src/transport/index.ts picks the right adapter based on the host environment.

Simulation

The renderer runs @sysdml/simulator in a dedicated Web Worker (src/simulation/worker.ts). The worker bundle form is chosen at build time:

| Build mode | Command | Worker form | Why | | ----------------- | ------------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Default (web) | pnpm build | ?worker — separate hashed same-origin asset, loaded via new Worker("/assets/worker-<hash>.js") | Hosted Monaco demo and any single-origin deployment; smaller main bundle; safe under strict require-trusted-types-for 'script' CSP. | | VS Code | pnpm build:vscode | ?worker&inline — worker code embedded in main bundle as a data: URL, constructed at runtime | The VS Code webview iframe origin (vscode-webview://[guid]) differs from where extension resources are served (https://file+.vscode-cdn.net/...). Worker constructors enforce same-origin, so the only working pattern is an inline URL that inherits the iframe origin. |

The selection is performed by a small workerInline Vite plugin (see vite.config.ts) that rewrites the ?worker import to ?worker&inline when --mode vscode is passed. Each build embeds only the variant it actually uses — no dead inline base64 leaks into the web bundle, and no unused worker chunk ships in the extension's renderer-dist.

Whenever a new IR arrives via the transport, App.vue calls simulator.simulate(ir) and the result lands in two reactive refs:

  • simulation: Ref<SimulationResult | null> — the simulator's output: rows (per-step values keyed by IR identifier) and diagnostics (warnings or halt codes from SimDiagnosticCode)
  • simulationError: Ref<string | null> — an unexpected JS exception thrown by the simulator (rare — programmer errors, malformed IR)

Halted simulations (e.g. MATH_DOMAIN_ERROR) appear as entries in simulation.value.diagnostics, not as simulationError. The simulator folds its own SimulationHaltedError into the diagnostics array internally.

Stale results from rapid IR updates are discarded by job ID — only the most recent simulation reaches the reactive state. This is handled inside SimulatorClient (src/simulation/client.ts).

Trusted Types policy

A Trusted Types default policy is registered at app boot (src/security/trusted-types.ts, called from main.ts) to validate every script URL that reaches new Worker(...) and similar APIs. The allowlist accepts blob:, same-origin https?://, vscode-webview-resource://, and relative paths ending in .js; everything else (including javascript: and data: not used by the inline worker) is rejected. blob: is accepted because URL.createObjectURL is same-origin-only, so an attacker would already need script execution in our origin to produce one — accepting blob: doesn't widen the attack surface. In environments without Trusted Types (most current browsers) the policy is a no-op; under enforced CSP it provides a runtime tripwire against any future code path that would try to load a worker from an untrusted URL.

Reusing the simulator outside the Vue app

The simulator client is decoupled from the transport, so the module is structured to be lifted into a standalone package (or into a future browser-only Monaco demo) without changes. Today there is no public exports entry — consumers inside the monorepo import from ./src/simulation/client.js directly; this path will be promoted to a proper subpath export once an external consumer materialises.

import { createDefaultSimulatorClient } from "./src/simulation/client.js";

const simulator = createDefaultSimulatorClient();
simulator.onResult((result) => {
	/* ... */
});
simulator.onError((message) => {
	/* ... */
});
simulator.simulate(ir);
// later:
simulator.dispose();

createDefaultSimulatorClient() instantiates the inlined worker; the underlying SimulatorClient class also accepts a custom WorkerFactory for testing.

Development

# build
pnpm --filter @sysdml/renderer build

# run dev server against an example model
SYSDML_FILE="$(pwd)/models/examples/population_growth.sysdml" pnpm --filter @sysdml/renderer dev

# tests (vitest)
pnpm --filter @sysdml/renderer test

The dev server serves the renderer at http://localhost:5173 and watches the configured SYSDML_FILE for changes, broadcasting IR updates over the WebSocket transport.


Credits

Code and documentation co-authored with Claude Sonnet and Claude Opus by Anthropic.