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

@manya-hael/weave

v1.0.0

Published

Interactive visualization substrate for the MANYA Intelligence OS — dependency graphs, knowledge graphs, event flows, layouts, filtering, search, export, live topology tracking, and pan/zoom exploration.

Readme

@manya/weave

Interactive visualization substrate for the MANYA Intelligence OS — dependency graphs, knowledge graphs, event flows, architecture diagrams, live system topology, and pan/zoom exploration with multi-format export.

@manya/weave is the visualization engine of the MANYA Intelligence OS — a sovereign, modular, local-first intelligence operating system conceived, directed, and owned by Uviwe Menyiwe (Azura Daemon), founder of the Manya Hael Foundation.

The package provides an in-memory directed/undirected graph model with cycle detection and topological sort, four deterministic layout algorithms (force-directed, hierarchical, radial, grid), graph filtering by label/type/component/depth, text and fuzzy search with BFS and Dijkstra path finding, export to JSON / Graphviz DOT / Mermaid / SVG, a configurable SVG renderer with arrow markers and labels, a live topology tracker with structural diffing, and interactive primitives (selection model, pan/zoom viewport).


Vision

The Manya Hael Foundation stewards the MANYA Intelligence OS as a long-horizon, mission-driven project. @manya/weave extends that sovereignty into the visualization domain: your graphs, your layouts, your topology history — yours alone.

  • Sovereign. No network calls, no DOM dependency, no external rendering service. Pure TypeScript that runs in Node or in the browser.
  • Deterministic. Every layout algorithm accepts a numeric seed and produces byte-identical output for byte-identical input.
  • Honest. No magic "auto-layout oracle" — algorithms are simple, well-known, and explicit. Force-directed uses Fruchterman-Reingold with a seeded PRNG.
  • Exportable. One graph, four formats (JSON, DOT, Mermaid, SVG) plus a full-featured SVG renderer.
  • Composable. Filter, search, layout, render — each step is a pure function on an immutable graph snapshot.

Features

| Area | What you get | | --- | --- | | Graph model | Graph class with directed/undirected modes, add/remove nodes & edges, O(1) adjacency queries, in/out degree, neighbors, predecessors, successors. | | Algorithms | Cycle detection (DFS for directed, union-find for undirected), topological sort (Kahn's, deterministic), connected components, BFS depths. | | Layouts | forceDirected (Fruchterman-Reingold, seeded), hierarchical (longest-path layering), radial (concentric rings), grid (regular grid). All return Map<nodeId, {x, y}>. | | Filtering | By label predicate, by node type, by edge type, by connected component, by BFS depth-from-root, by property predicate, plus generic filterNodes/filterEdges. | | Search | Exact text search across labels/types/properties, fuzzy search with Levenshtein-based token scoring, BFS shortest path, Dijkstra weighted shortest path. | | Export | toJSON, toDot (Graphviz), toMermaid (Mermaid flowchart), toSVG (basic positional). | | Render | renderToSVG with RenderConfig (width, height, nodeRadius, fontSize, colors, showLabels), arrow markers for directed graphs, edge label rendering. | | Topology | TopologySnapshot, diffSnapshots for added/removed nodes & edges, TopologyTracker with rolling history and diff(). | | Interactive | SelectionModel (toggle/select/clear nodes & edges), Viewport (centerX/centerY/zoom), applyViewport/inverseViewport/panTo/zoomAt. | | Logging | Logger interface, ConsoleLogger with secret-scrubbing, SilentLogger. |


Install

npm install @manya/weave

Requires Node.js 18+. No external runtime dependencies — only Node built-ins.


Quick start

1. Build and lay out a dependency graph

import { createGraph, hierarchical, renderToSVG } from '@manya/weave';

const graph = createGraph(
  [
    { id: 'web',  label: 'Web Client',   type: 'service' },
    { id: 'api',  label: 'API Gateway',  type: 'service' },
    { id: 'auth', label: 'Auth Service', type: 'service' },
    { id: 'db',   label: 'Database',     type: 'db' },
  ],
  [
    { id: 'e1', source: 'web',  target: 'api',  label: 'calls' },
    { id: 'e2', source: 'api',  target: 'auth', label: 'verifies' },
    { id: 'e3', source: 'api',  target: 'db',   label: 'queries' },
  ],
  true, // directed
);

const layout = hierarchical(graph, { width: 800, height: 600 });
const svg = renderToSVG(graph, layout, { nodeColor: '#5b8def' });
console.log(svg); // full <svg>...</svg> document

2. Detect cycles and topologically sort

import { createGraph } from '@manya/weave';

const dag = createGraph(
  [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }, { id: 'c', label: 'C' }],
  [
    { id: 'e1', source: 'a', target: 'b' },
    { id: 'e2', source: 'b', target: 'c' },
  ],
  true,
);

console.log(dag.hasCycle());             // false
console.log(dag.topologicalSort());      // ['a', 'b', 'c']

3. Filter, search, and find the shortest path

import { createGraph, filterByType, search, bfsPath, dijkstra } from '@manya/weave';

const graph = createGraph(
  [
    { id: 'auth',    label: 'Auth',    type: 'service' },
    { id: 'billing', label: 'Billing', type: 'service' },
    { id: 'db',      label: 'DB',      type: 'db' },
  ],
  [
    { id: 'e1', source: 'auth',    target: 'db', weight: 1 },
    { id: 'e2', source: 'billing', target: 'db', weight: 5 },
  ],
  false,
);

const services = filterByType(graph, 'service');   // 2 nodes, 0 edges (db dropped)
const hits = search(graph, 'DB');                  // [{ nodeId: 'db', score: 1, matchedField: 'label' }]
const path = bfsPath(graph, 'auth', 'db');         // ['auth', 'db']
const shortest = dijkstra(graph, 'billing', 'db'); // { path: ['billing', 'db'], distance: 5 }

4. Track live topology over time

import { createGraph, TopologyTracker } from '@manya/weave';

const tracker = new TopologyTracker(10);
const v1 = createGraph(
  [{ id: 'api', label: 'API' }, { id: 'db', label: 'DB' }],
  [{ id: 'e1', source: 'api', target: 'db' }],
);
tracker.snapshot(v1, '2024-01-01T00:00:00Z');

const v2 = v1.clone();
v2.addNode({ id: 'cache', label: 'Cache' });
v2.addEdge({ id: 'e2', source: 'api', target: 'cache' });
tracker.snapshot(v2, '2024-01-01T00:01:00Z');

const diff = tracker.diff()!;
console.log(diff.addedNodes.map(n => n.id));   // ['cache']
console.log(diff.addedEdges.map(e => e.id));   // ['e2']
console.log(diff.removedNodes);                // []

5. Export to Graphviz DOT, Mermaid, and JSON

import { createGraph, toDot, toMermaid, toJSON } from '@manya/weave';

const g = createGraph(
  [{ id: 'a', label: 'Alpha' }, { id: 'b', label: 'Beta' }],
  [{ id: 'e1', source: 'a', target: 'b', label: 'calls' }],
  true,
);

console.log(toDot(g));      // digraph G { ... "a" -> "b" [label="calls"]; }
console.log(toMermaid(g));  // flowchart TD \n  a["Alpha"] \n  b["Beta"] \n  a -- "calls" --> b
console.log(toJSON(g));     // { "directed": true, "nodes": [...], "edges": [...] }

Configuration

RenderConfig

export interface RenderConfig {
  width: number;            // SVG width, default 800
  height: number;           // SVG height, default 600
  nodeRadius: number;       // node circle radius, default 18
  fontSize: number;         // label font size, default 12
  nodeColor: string;        // node fill, default '#6ba8d6'
  edgeColor: string;        // edge stroke, default '#888888'
  backgroundColor: string;  // canvas fill, default '#ffffff'
  showLabels: boolean;      // render node & edge labels, default true
}

Pass a partial config to renderToSVG — unspecified fields fall back to DEFAULT_RENDER_CONFIG via mergeRenderConfig.

Layout options

All layouts accept { width?, height?, padding? }. Additionally:

| Function | Extra options | | --- | --- | | forceDirected | iterations?, seed?, idealLength?, repulsion? | | hierarchical | layerGap?, nodeGap?, root? | | radial | root?, ringGap? | | grid | columns?, cellWidth?, cellHeight? |

Viewport

export interface Viewport {
  centerX: number;
  centerY: number;
  zoom: number; // must be > 0
}

applyViewport(point, viewport) returns { x: (point.x - centerX) * zoom, y: (point.y - centerY) * zoom }. inverseViewport is the inverse. panTo(graphPoint, screenPoint, zoom) builds a viewport anchoring a graph point at a screen point. zoomAt(viewport, anchorScreenPoint, factor) zooms while keeping an anchor point fixed.


Extending

Add a custom layout algorithm

import type { Graph } from '@manya/weave';
import type { Layout, Point } from '@manya/weave';

export function circular(graph: Graph, radius = 200): Layout {
  const layout = new Map<string, Point>();
  const ids = graph.nodes.map(n => n.id).sort();
  const step = (2 * Math.PI) / ids.length;
  ids.forEach((id, i) => {
    layout.set(id, { x: radius * Math.cos(i * step), y: radius * Math.sin(i * step) });
  });
  return layout;
}

Layouts return a plain Map<NodeID, Point>, so custom algorithms drop in seamlessly with renderToSVG, toSVG, and any downstream consumer.


Security notes

  • Local-only. No data leaves the host process. No DOM, no network, no telemetry.
  • No secrets in logs. token, secret, apiKey, password, credentials, cookie fields are scrubbed by scrubMetadata.
  • Safe SVG output. renderToSVG and toSVG XML-escape all label text. Do not embed untrusted user input as raw SVG attributes without additional sanitization.
  • Reproducibility. Identical inputs + identical seeds → identical outputs.

For threat models, see SECURITY.md and the root SECURITY.md.


Documentation


License

Apache-2.0. Copyright 2024 Manya Hael Foundation. All rights reserved.

Conceived, directed, and owned by Uviwe Menyiwe (Azura Daemon), founder of the Manya Hael Foundation.