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

flow-ngx

v0.5.2

Published

FlowNGX — Visual process design and execution for Angular. Diagram canvas, typed process models, validation, step-by-step execution engine, undo/redo and JSON import/export.

Readme

FlowNGX

Visual process design and execution for Angular.

🚀 Live demo & docs → flw.136.67.40.6.nip.io — designer, telecom sample workflows (simple → very complex), runs portal with replays, and full documentation.

FlowNGX is an Angular-native library for drawing process diagrams and executing them step by step — a lightweight SVG canvas, strongly typed process models, a framework-independent execution engine, and signal-based state, with no external diagramming dependency.

npm install flow-ngx

Requires Angular ≥ 22.

Features

  • 🎨 Diagram canvas — SVG rendering, drag & drop, pan, zoom-to-cursor, configurable snap grid
  • 🧩 Node types — start, task, decision, end; connections with labels and branch conditions
  • 🔀 Edge routing — curved beziers or right-angle ("square") routing with circuit-style hop arcs where connections cross, switchable at runtime
  • 🖌 Style profiles — classic diagram-tool palettes and icon sets (default, telecom-flavoured telecom), selectable per node; themable via config or CSS custom properties (switching profiles never restyles an existing diagram)
  • ✅ Validation — structural rules with typed issue codes (missing start/end, dangling connections, unreachable nodes, ambiguous decision branches, …)
  • ▶️ Execution engine — pure TypeScript, run-all or step-by-step ("next"), pluggable node handlers and decision resolvers, per-node retry policies (data.retry), chunked batch progress (reportProgress), execution counts and timings
  • 🌐 Declarative HTTP tasks — put data.http ({ url, method, params, headers, body }) on a node with {{variable}} templating and the built-in handler executes the call (execution.httpTasks or createHttpTaskHandler())
  • 🔦 Runtime visuals — current-node highlight, per-state styling (idle / running / completed / failed / skipped), taken-path coloring, alternate flows dimmed or hidden via a toggle, count badges and progress bars
  • 📜 History & events — full execution history, typed event callbacks
  • ⏪ Runs vs replays — a live run produces a versioned run snapshot (process document + recorded context); a replay (replayContext) animates that recording without executing anything
  • 🔢 Content revisions — documents carry a workflow revision and per-layout revisions (BPM-deployment style); every run is stamped with the workflow revision it executed against
  • 🗺 Named multi-layouts — several arrangements of one workflow (presentations + activeLayout, BPMN-DI style); recordings embed only the active layout
  • 🎚 Feature switches — limit what users can do (features config: editing, execution, zoom/pan, undo, import/export, styling)
  • ↩️ Undo / redo, 🔒 read-only mode, 📄 JSON import/export with schema-validated, logic/presentation-separated documents

Quick start

import { Component } from '@angular/core';
import { FlowCanvasComponent, ProcessDefinition, provideFlowNgx } from 'flow-ngx';

@Component({
  selector: 'app-designer',
  imports: [FlowCanvasComponent],
  providers: [provideFlowNgx({ styleProfile: 'telecom' })],
  template: `<flow-canvas #canvas [definition]="process" (executionEvent)="log($event)" />`,
})
export class DesignerComponent {
  process: ProcessDefinition = {
    schemaVersion: 2,
    id: 'hello',
    name: 'Hello process',
    nodes: [
      { id: 'start', type: 'start', label: 'Start', position: { x: 40, y: 100 } },
      { id: 'work', type: 'task', label: 'Do work', position: { x: 220, y: 92 } },
      { id: 'end', type: 'end', label: 'Done', position: { x: 440, y: 100 } },
    ],
    connections: [
      { id: 'c1', sourceId: 'start', targetId: 'work' },
      { id: 'c2', sourceId: 'work', targetId: 'end' },
    ],
  };

  log(event: unknown) {
    console.log(event);
  }
}

The canvas exposes its per-instance services for full programmatic control:

@ViewChild(FlowCanvasComponent) canvas!: FlowCanvasComponent;

// Editing
this.canvas.diagram.addNode('task', { x: 100, y: 100 });
this.canvas.diagram.undo();
const json = this.canvas.diagram.exportJson();

// Execution
this.canvas.execution.registerTypeHandler('task', async (node, api) => {
  api.variables['result'] = await doRealWork(node);
});
await this.canvas.execution.runAll({ creditCheck: 'yes' });
this.canvas.execution.runtimeOf('work').executionCount; // how often it ran

Architecture

| Layer | Contents | Angular? | | ------------- | ----------------------------------------------------------------------- | ---------- | | core/ | models, JSON serialization, validator, execution engine, style profiles | none | | state/ | FlowDiagramService, FlowHistoryService, FlowExecutionService | signals | | components/ | flow-canvas, flow-node, flow-connection | standalone | | config/ | provideFlowNgx(), FLOW_NGX_CONFIG, theming | DI |

The core layer has no Angular or RxJS imports — the engine also runs in plain Node/worker contexts.

Configuration

provideFlowNgx({
  styleProfile: 'telecom', // or 'default', or a custom NodeStyleProfile
  grid: { visible: true, size: 20, snap: true },
  execution: { maxSteps: 1000, stepDelayMs: 600 },
  connections: { routing: 'orthogonal', crossingHops: true, cornerRadius: 8 },
  serialization: { separatePresentation: true, includePresentation: true },
  features: {
    editing: true,
    execution: true,
    zoomAndPan: true,
    undoRedo: true,
    importExport: true,
    styling: true,
  },
  showAlternateFlows: true, // dim (true) or hide (false) branches not taken
  readonly: false,
  theme: { connectionTakenColor: '#16a34a' /* …see FlowThemeConfig */ },
});

// Or per canvas — everything defaults, pass any partial:
// <flow-canvas [definition]="def" [config]="{ connections: { routing: 'orthogonal' } }" />

Every theme value is applied as a CSS custom property (--flow-*) on the canvas, so plain CSS overrides work too.

Process JSON (schema v2)

Documents separate logic from presentation, BPMN-style, and validate against schema/process-definition.schema.json (shipped in this package). definition is the executable part; presentation (layout, styling, preferred profile) is optional, replaceable, and independently versioned — a presentation from a newer version is ignored (nodes auto-lay-out) rather than failing the document. The legacy v1 inline format is still imported transparently, and exports can be switched to v1 or to logic-only via the serialization config.

{
  "schemaVersion": 2,
  "id": "sim-activation",
  "name": "SIM Activation",
  "definition": {
    "nodes": [
      { "id": "start", "type": "start", "label": "Start" },
      {
        "id": "credit-check",
        "type": "decision",
        "label": "Credit OK?",
        "data": { "variable": "creditCheck" }
      },
      { "id": "end", "type": "end", "label": "Done" }
    ],
    "connections": [
      { "id": "c1", "sourceId": "start", "targetId": "credit-check" },
      {
        "id": "c2",
        "sourceId": "credit-check",
        "targetId": "end",
        "label": "Approved",
        "condition": "yes"
      }
    ]
  },
  "presentation": {
    "version": 1,
    "profile": "telecom",
    "nodes": {
      "start": { "position": { "x": 60, "y": 220 } },
      "credit-check": {
        "position": { "x": 690, "y": 202 },
        "color": "orange",
        "icon": "question"
      },
      "end": { "position": { "x": 1380, "y": 220 } }
    }
  }
}

exportProcessLogic(definition) produces a logic-only document for backends; parseProcessDocument(json) returns the runtime model plus the preferred style profile.

Run snapshots

A recorded execution is its own document type (schema/run-snapshot.schema.json): { snapshotVersion, definition, context }. One format serves both verbs — a run (live, handlers execute) produces a snapshot via exportRunSnapshot(definition, context); a replay consumes one via parseRunSnapshot(json) + execution.replayContext(context), animating the recorded event history without executing anything. Snapshots embed their process document, so they replay faithfully even after the process changes.

Static replay is also fully declarative — one binding builds the whole view:

<!-- The canvas fetches, parses, draws and restores by itself: -->
<flow-canvas snapshotUrl="/api/runs/42" [readonlyMode]="true" />

<!-- Or bind the snapshot value directly; add [snapshotReplay] to animate: -->
<flow-canvas
  [snapshot]="snap()"
  [snapshotReplay]="{ stepDelayMs: 400 }"
  (snapshotError)="toast($event)"
/>

[snapshot] accepts the envelope object, a parsed { definition, context } pair, or the raw JSON string. Without [snapshotReplay] the final state is shown instantly (showContext); with it the history animates (replayContext). snapshotUrl fetches through your app's HttpClient when one is provided (interceptors, auth, XSRF apply) and falls back to plain fetch otherwise.

Decision semantics: the engine reads the variable named by the decision node's data.variable, stringifies its value and takes the outgoing connection whose condition matches. One condition-less branch per decision acts as the else-branch. A custom DecisionResolver can replace this behaviour.

License

Apache License 2.0 — see LICENSE.