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

@t-yamauchi/wireflow

v2.1.5

Published

DSL-based interactive flow, ER, component, class, and sequence diagram renderer.

Readme

Wireflow

Wireflow is a DSL-based JavaScript diagram renderer for flow diagrams, screen flows, ER diagrams, component diagrams, class diagrams, and sequence diagrams.

It can be used from npm, CDN, or a local bundled file.

Official site: https://wireflow.jp/

Stability

The stable DSL and API contract is maintained in SPEC.md. Public JavaScript APIs are summarized in API.md, and compatibility-sensitive changes are tracked in MIGRATION.md.

Install

Wireflow v1 remains on the npm latest tag. Install Wireflow v2 explicitly from the v2-latest dist-tag:

npm install @t-yamauchi/wireflow@v2-latest

Use npm install @t-yamauchi/wireflow only when you intentionally want the current latest tag.

import { Wireflow } from "@t-yamauchi/wireflow";

const wf = new Wireflow("#canvas", {
  autoFit: true,
});

wf.render(`
layout:
  mode: horizontal
  auto-fit: true

Start:
  Start
  ---
  kind: start

Review:
  Review
  ---
  kind: process

Done:
  Done
  ---
  kind: end

Start -> Review
Review -> Done
`);

Axis-specific fit is available when only one direction should determine the initial zoom. auto-fit-y: yes fits the diagram height to the current viewport and aligns the scene from its starting edge.

layout:
  auto-fit-y: yes

Large horizontal diagrams keep a readable minimum zoom while auto-fit is applied. Set auto-fit-min-scale in DSL or autoFitMinScale in JavaScript when a diagram should fit more aggressively or stay more readable.

layout:
  auto-fit: true
  auto-fit-min-scale: 0.45

You can also load DSL from a text-like file. Markdown files render the first fenced code block tagged wireflow.

const wf = new Wireflow("#canvas", { autoFit: true });
await wf.render("./flows/checkout.md");
await wf.renderFile("./flows/checkout.md");

For large diagrams, Wireflow bounds expensive routing work automatically. Tune smartAnchorLimit (default 32), routeObstacleFilterThreshold, routeObstaclePadding, gridFallbackObstacleLimit, bridgeDetectionLimit, and maxEdgeBends only when you need to trade render speed for more automatic edge cleanup or broader global detours.

For troubleshooting, pass { debug: true } to emit wireflow:debug events and console logs. Use { debug: "panel" } to show the latest render, layout, auto-fit, viewport, and drag steps inside the canvas.

Viewport pan is a view-only interaction. Dragging the whole flow updates the visible transform without rewriting DSL or triggering wireflow:dsl-change; write adjustments.viewport explicitly when an initial pan must be persisted.

For display or approval screens, use view-only: true in DSL or { viewOnly: true } in JavaScript. Pan and zoom remain available, but edge selection, anchor edits, edge movement, route clearing, and node movement are blocked. Add view-mode-toggle: true or { viewModeToggle: true } to show an optional in-canvas switch button for toggling between view-only mode and edit mode.

AI Quality Layer

Wireflow v2 can treat the DSL as a process-quality contract. Add quality: rules: and per-node contract: metadata, then run the checker from JavaScript or CI. kind: start nodes are treated as flow entry markers and are excluded from uncovered-node traceability counts unless you explicitly add contract metadata to them.

quality:
  rules:
    - db_write_requires_auth
    - external_api_requires_timeout
    - error_path_requires_log
  policies:
    - all_paths_before:effect=db-write,contract=auth

Auth:
  Auth check
  ---
  kind: process
  contract:
    type: auth

Save:
  Save order
  ---
  kind: process
  contract:
    effect: db-write
    req-id: R-001
    risk: data-loss
const report = Wireflow.check(dsl);
// or, after rendering, highlight issue nodes:
const report = wf.check();
wireflow check ./flows/checkout.dsl
wireflow report ./flows/checkout.dsl

Convert older YAML-like or brace DSL into the full YAML form with nodes:, view, and readable top-level arrow edge keys:

wireflow convert ./flows/legacy.dsl --out ./flows/legacy.yaml

At runtime, flow DSL written in older YAML-like or brace styles is also normalized into this full YAML form and stored in model.source. Renderer interactions such as drag-created coordinates and edge route edits use that cached YAML source from the first render onward. The original input is retained as model.originalSource for inspection. Automatic resize re-renders continue from the original input until an interaction changes the cached YAML, so responsive orientation is still resolved normally.

For deterministic source, annotation, DSL-contract, and test-contract review, use the guard command:

wireflow guard --cwd . --spec ./flows/spec.dsl --actual ./flows/actual.dsl --src ./src --tests ./tests

Recommended AI-development workflow:

  1. Ask the AI to output Wireflow DSL with contract: metadata for auth, validation, side effects, error handling, and logging.
  2. Review the rendered flow instead of reading every generated code path.
  3. Ask the AI to extract the implemented process as Wireflow DSL and compare it with the approved specification flow.
  4. Run wireflow check and wireflow compare in CI so rule violations and implementation drift fail the build.
  5. Use wireflow report to produce a human-readable quality, traceability, and risk summary for review artifacts.
  6. During execution tests, feed process events into the animation API to verify that the real process follows the approved flow.
wireflow compare ./flows/spec.dsl ./flows/actual.dsl

For language-independent implementation extraction, put @wireflow annotations next to the relevant code. Add evidence= so stale comments are detected when the implementation changes.

// @wireflow node Auth kind=process contract.type=auth evidence=requireAuth
await requireAuth(user);

// @wireflow node Save kind=process contract.effect=db-write contract.requires=auth evidence=db.order.create
await db.order.create(order);

// @wireflow edge Auth -> Save

Quality annotations can also seed the extracted DSL. Use rule= for built-in rules and policy= for compact policies with parameters:

// @wireflow quality rule=db_write_requires_auth,db_write_requires_validation
// @wireflow quality policy=all_paths_before:effect=db-write,contract=auth
wireflow extract ./src --out ./flows/actual.dsl

For repeatable AI-agent work, this repository includes a verified development kit under docs/ai/ and a repo-local Codex skill at .codex/skills/wireflow-verified-dev/. The kit gives agents a smaller, task-focused reference for the spec-first workflow, annotation rules, common mistakes, and a gate runner:

node docs/ai/scripts/verify-wireflow-cycle.mjs --cwd trial-projects/report-api --test "npm test"

The single Codex entry point is docs/ai/CODEX_WIREFLOW_FRAMEWORK.md. It defines the full requirements -> DSL -> implementation -> tests -> verification -> fix loop. For screen-based web apps, use docs/ai/PROMPT_WEB_APP_TEMPLATE.md so the agent contracts UI surfaces, user operations, client validation, loading/error states, accessibility, and visual proof before writing DSL or code. For new projects, start from templates/wireflow-verified-project/ or the archive templates/wireflow-verified-project.zip.

For existing systems, use docs/ai/WIREFLOW_EXISTING_SYSTEM_ADOPTION.md. Codex first inventories current code, tests, docs, and runtime behavior, classifies findings as observed, documented, assumed, unknown, or risky, asks human judgment questions for unknown/risky items, then creates a verified baseline before changing behavior. For modifications, requested changes are treated as a delta contract and compare differences are classified as intended change, implementation drift, spec gap, annotation gap, test gap, or accepted risk.

Before DSL generation, the kit requires a requirements contract: feature scope, normal paths, error paths, warning paths, auth/authz, validation, side effects, timeouts/retries, logging/redaction, risk, data, req-id, and test-id. If any of these are ambiguous, the agent should ask the user for a concrete decision instead of assuming one.

For stricter flows, add contract.test-id to quality-relevant DSL nodes and place @wireflow-test <id> outcome=success|error|warning route=NodeA->NodeB requires=... above the matching product tests. The deterministic guard then checks that contracts, implementation annotations, test routes, failure edges, and test assertions stay linked. The guard also compares spec DSL and actual DSL internally, validates risk / data against a known vocabulary, and rejects weak log checks such as asserting that a string literal exists instead of checking a logged event field.

For runtime route proof, instrument the implementation with a trace recorder, write a trace JSON file from product tests, and pass it to guard:

import { createWireflowTraceStore } from "@t-yamauchi/wireflow";
import fs from "node:fs";
import path from "node:path";

const tracePath = ".wireflow/runtime-traces.json";
const traceStore = createWireflowTraceStore({
  onChange(report) {
    fs.mkdirSync(path.dirname(tracePath), { recursive: true });
    fs.writeFileSync(tracePath, JSON.stringify(report, null, 2));
  },
});
const trace = traceStore.recorder("T-AUTH-FAIL");
trace.visit("Request").visit("Auth").visit("AuthFailedLog").visit("AuthError").finish("error");

Runtime traces can also record side-effect evidence:

trace
  .visit("SaveRequest")
  .effect("db-write", { nodeId: "SaveRequest", status: "failed" })
  .visit("FailureLog")
  .effect("log", { nodeId: "FailureLog", event: "processing_failed" })
  .finish("error");
wireflow guard --cwd . --spec ./flows/spec.dsl --actual ./flows/actual.dsl --src ./src --tests ./tests --trace .wireflow/runtime-traces.json

When --trace is supplied, guard verifies that each @wireflow-test route=... matches the route actually recorded while the test ran. The trace file format is specified in docs/ai/WIREFLOW_RUNTIME_TRACE_SPEC.md, and createWireflowTraceMiddleware(store) instruments connect/Express-style apps per request via an x-wireflow-test-id header.

For CI, wireflow guard --sarif guard.sarif exports findings as SARIF 2.1.0, and legacy projects can freeze existing findings with wireflow guard --baseline .wireflow/guard-baseline.json --update-baseline so only new violations fail afterwards.

For top-down proof from human/AI requirements to implementation and tests, write a structured requirements contract:

requirements:
  - id: REQ-DB-001
    title: Successful requests save a DB record and DB failures are exposed safely.
    req-id: R-005
    test-id: T-SUCCESS,T-DB-FAIL
    nodes: SaveRequest,FailureLog,ErrorResponse
    effect: db-write
    risk: data-loss
    data: internal
    paths: success,error
    assertions: db-completed,db-failed,status-500
    assert-effects: db-write:SaveRequest,log:processing_failed
    forbid-effects: file-write
    required-route: SaveRequest
    forbid-nodes: WriteFile
    runtime: required

Then run:

wireflow requirements requirements/main.requirements.dsl --cwd . --spec ./flows/spec.dsl --actual ./flows/actual.dsl --tests ./tests --trace .wireflow/runtime-traces.json

The requirements gate checks that each structured requirement links to Spec DSL, Actual DSL, @wireflow-test, and runtime trace evidence through stable req-id and test-id values. Optional logical fields move more of the review from AI judgement into deterministic checks:

  • assertions: required @wireflow-test requires= entries. Built-in assertions such as request-id, db-completed, db-failed, rejects, status-400, status-401, status-403, status-500, no-db, audit-log, retry-success, and log-* are checked against the test block. JavaScript tests are parsed with an AST first, with regex fallback for legacy and project-defined patterns.
  • assert-effects: runtime side effects that must be recorded by trace.effect(...), such as db-write:SaveRequest or log:processing_failed.
  • forbid-effects: runtime side effects that must not be recorded.
  • required-route: node ids that must appear in linked test routes and runtime traces.
  • forbid-nodes: node ids that must not appear in linked test routes or runtime traces.
  • runtime: required: at least one linked runtime trace must exist.

Projects can extend assertion vocabulary with wireflow.guard.json:

{
  "strictVerification": true,
  "strictSourceEffects": true,
  "sourceEffectWindow": 20,
  "assertionVocabulary": {
    "status-202": {
      "ast": {
        "assertCall": true,
        "identifiers": ["statusCode"],
        "literals": [202]
      }
    },
    "log-domain_event": {
      "event": "domain_event"
    }
  }
}

wireflow guard also parses JavaScript source with AST-based source gates. It fails on common secret fields in logger calls, public responses that expose stack, empty catch {} blocks, missing timeout markers for external-api contracts, and missing path-sanitization markers for file-write contracts. When "strictSourceEffects": true is enabled, detected DB/file/external source effects must have a nearby matching @wireflow node contract.effect=... annotation, turning unannotated implementation effects into CI failures. When "strictVerification": true is enabled, regex-only assertion proof and AST parse failures are treated as errors. Built-in assertions such as db-completed, db-failed, status-401, and no-db use semantic argument matching, so unrelated identifiers and literals in the same test block no longer count as proof.

Generate one route-animation DSL per contract-linked test with wireflow test-flows. Each file contains an animation.routes preset and auto-play for the test route, so the test case can be inspected visually in Wireflow:

wireflow test-flows --cwd . --spec ./flows/spec.dsl --tests ./tests --out ./flows/tests

When screenshots are available, pass --screenshots. Files named <test-id>_<node-id>.png are attached to the matching node as popup payloads:

wireflow test-flows --cwd . --spec ./flows/spec.dsl --tests ./tests --out ./flows/tests --screenshots ./screenshots

The verified project template includes a Playwright-based helper for capturing screen states from wireflow.visual.json:

npm run visual:capture
npm run visual:flows

For level-6 completion judgment, run wireflow verify. It runs product tests, extracts actual DSL, checks spec and actual, compares them, creates quality reports, runs guard, checks runtime traces when supplied, cross-checks trace claims against Istanbul/c8 coverage when --coverage is supplied, generates per-test route-animation DSLs, attaches screenshot evidence when supplied, and writes completion artifacts:

wireflow verify --cwd . --requirements requirements/main.requirements.dsl --spec ./flows/spec.dsl --actual ./flows/actual.dsl --src ./src --tests ./tests --test "npm test" --trace .wireflow/runtime-traces.json --coverage coverage/coverage-final.json

The result is written to .wireflow/verification/verification-result.json, .wireflow/verification/verification-report.md, .wireflow/verification/verification-report.html, plus CI-friendly verification-result.sarif (SARIF 2.1.0) and verification-junit.xml (one JUnit test case per gate). The HTML report is a single decision dashboard with a fixed menu and a consistent section order: approval summary, verified scope and limitations, requirement evidence, quality gates, and artifacts. It embeds Wireflow rendering, embeds screenshot evidence when available, and shows generated test route animations inside the related traceability rows instead of as a separate route list. The dashboard also lists every DSL req-id, explains why requirement counts and test-id counts may differ, and shows how each requirement is connected to structured requirements, implementation nodes, tests, runtime traces, risk nodes, and the final conclusion in one accordion-style traceability table. The traceability table keeps one compact record per requirement where possible. The closed row shows only the requirement id, status, and requirement text; conclusion, review points, creation/verification evidence, quality gates, and route animations are shown inside the expanded row. The list paginates in groups of 10 so projects with hundreds of requirements remain reviewable. Test ids and assertion keys are translated into Japanese human-readable explanations in the dashboard, while the stable ids remain as small trace hints for engineers. Route animations inside an expanded traceability row render automatically when the row is opened. The dashboard navigation is opened from a hamburger menu so the report remains usable on small screens. Per-test route DSLs are written under .wireflow/verification/test-flows/, and the visual review index is written to .wireflow/verification/visual-review.md.

wireflow verify also writes a requirement-centric specification document for human review: .wireflow/verification/spec-document.md and spec-document.html. It reorganizes the same deterministic artifacts (node contracts, gate results, @wireflow-test declarations, runtime traces) into a requirements list with verification status, per-requirement chapters with a highlighted flow diagram, a security-viewpoint matrix (authentication, authorization, input validation, audit logging, secret handling, external dependency resilience, failure-path consistency), a test list, and a remaining issues section. Every verdict in the document links back to a machine check; no judgment is generated by inference. Structured requirements may carry description: and rationale: fields whose prose is shown in the document. The document can be regenerated standalone:

wireflow spec-doc --cwd . --spec ./flows/spec.dsl --tests ./tests --trace .wireflow/runtime-traces.json

For stricter, deterministic source/test review gates, run the guard against a trial project such as invoice-workflow:

wireflow guard --cwd trial-projects/invoice-workflow --spec flows/specs/invoice-workflow.dsl --actual flows/actual/invoice-workflow.dsl --src src --tests tests

Rendered process flows can be animated from JavaScript. runRouteAnimation() is the canonical execution entry point. Display differences such as pending dimming, progress glow, speed, and final status are controlled through options. The legacy playRouteAnimation() and playRouteSteps() helpers remain as compatibility wrappers.

await wf.runRouteAnimation(["Start", "Review", "Done"], {
  terminalStatus: "success",
});

Reusable animation routes may be declared in the DSL and played by name.

animation:
  auto-play: normal
  routes:
    normal:
      nodes:
        Start: Success
        Review: Success
        Done: Success
await wf.runRouteAnimation("normal");

Step-based animation uses the same entry point with mode: "steps".

await wf.runRouteAnimation({
  mode: "steps",
  steps: ["Start", "Review", "Done"],
  terminalStatus: "success",
});

For live execution, create a session and add steps as each process starts or finishes:

const run = wf.createRouteAnimationSession({ duration: 700 });
await run.step("Start", { status: "success", wait: 5000 });
await run.step("Fetch", { status: "error", wait: 5000 });
await run.finish("error");

The process-style helper is terser for live applications:

const process = wf.createProcessAnimation();
await process.next("Start", "running");
await process.next("Fetch", "running"); // Start is auto-completed as success.
await process.next("Fetch", "error");

For DSL-defined process flows, start() and empty next() calls keep the host code short. Wireflow follows the outgoing DSL edge automatically, and next("error") follows the matching failure route:

const process = wf.createProcessAnimation();
process.start();
await fetchData();
process.next();
await saveData();
process.next("error");

If no matching outgoing route exists, Wireflow opens a route-not-found popup and emits wireflow:route-animation-missing-route.

When the host only needs to choose the terminal route status, run() can drive the process from the DSL and update a status element with DSL node labels:

const process = wf.createProcessAnimation({
  stepWait: 5000,
  statusTarget: "#status",
});
process.run("warning");

For interactive step-by-step playback, use the built-in controller:

const wf = new Wireflow("#canvas");
wf.render(dsl);

wf.process.run();
wf.process.result("success");
wf.process.result("error");

When the actual process already emits events, feed those events to wf.process.push(). Communication stays in the host app; Wireflow receives only the process status, optional log, and optional expect value for strict tests.

wf.process.configure({ strict: true });

wf.process.push({ status: "running", log: "Fetch started" });
wf.process.push({ status: "success", log: "Fetch completed" });
wf.process.push({ expect: "Check", status: "error", log: "Check failed" });

expect(wf.process.history()).toMatchObject([
  { nodeId: "Start", status: "success" },
  { nodeId: "Fetch", status: "success" },
  { nodeId: "Check", status: "error" },
]);

When auto-play is omitted, the normal route is played automatically if it exists. Use auto-play: false when the DSL should only define presets. The repository includes a runnable HTML sample at wireflow_examples/examples/route-animation.html.

Swimlanes normally follow the active layout direction. Use lane-orientation when the flow direction and lane direction need to be chosen explicitly.

layout:
  mode: horizontal
  lane-orientation: vertical
  lane-order: User, System, AI

lane-order places the listed lanes first in the given order. With horizontal lane orientation the first lane is shown at the top; with vertical lane orientation the first lane is shown at the left. Lanes omitted from the list use the normal stable automatic order after the listed lanes.

CDN

<div data-wireflow-viewport style="height: 420px">
  <div id="canvas"></div>
</div>

<script src="https://cdn.jsdelivr.net/npm/@t-yamauchi/wireflow/dist/wireflow.min.js"></script>
<script>
  const WF = window.WireflowLib;

  const wf = new WF.Wireflow("#canvas", {
    autoFit: true,
  });

  wf.render(`
layout:
  mode: horizontal
  auto-fit: true

Input:
  Input
  ---
  kind: screen
  state: accent

Validate:
  Validate
  ---
  kind: decision

Save:
  Save
  ---
  kind: process

Input -> Validate
Validate -> Save:
  on-success: true
`);
</script>

unpkg is also supported:

<script src="https://unpkg.com/@t-yamauchi/wireflow/dist/wireflow.min.js"></script>

DSL Basics

Wireflow accepts the original YAML-like DSL and a full YAML object form.

layout:
  mode: horizontal
  auto-fit: true

Home:
  Home
  ---
  kind: screen
  state: accent
  payload:
    title: Home
    desc: |
      Node details

Detail:
  Detail
  ---
  kind: screen

Home:right -> Detail:left:
  label: open

The text above --- is rendered as the node label. The lines below --- are attributes.

Full YAML can use nodes: and edges: as arrays or maps. Nested objects such as payload:, contract:, animation.routes, and adjustments: are parsed with the YAML parser before Wireflow normalizes them into the same model.

layout:
  mode: horizontal
  auto-fit: true
animation:
  auto-play: normal
  routes:
    normal:
      nodes: [Start, Check, Done]
nodes:
  - id: Start
    kind: start
    view: Start
    contract:
      req-id: REQ-1
      test-id: [T-1]
  - id: Check
    kind: decision
    view: |
      Check
      Input
    payload:
      title: Review
      desc: YAML object payload
  - id: Done
    kind: end
    view: Done
edges:
  - from: Start
    to: Check
    label: begin
  - from: Check
    to: Done
    from-anchor: right
    to-anchor: left
    label: ok
adjustments:
  Start:
    x: 10
    y: 20

When using full YAML, view is the preferred field for the node text shown in the diagram. text and label remain accepted aliases. Edge arrays are useful for generators, but the top-level arrow form also works when readability is more important:

nodes:
  Start:
    kind: start
    view: Start
  Check:
    kind: decision
    view: Check

Start -> Check:
  from: right
  to: left
  label: begin

For top-level arrow keys, from and to mean endpoint anchors. In edges: arrays they remain endpoint node ids, so use from-anchor and to-anchor there.

animation:
  auto-play: normal
  routes:
    normal:
      nodes: [Start, Check]
      duration: 500

Supported Diagram Types

  • Flow diagrams
  • Screen flows
  • ER diagrams
  • Component diagrams
  • Class diagrams
  • Sequence diagrams
  • Notes / comments

Node Attributes

Common node attributes:

| Attribute | Example | Description | |---|---|---| | kind | kind: screen | Node kind such as screen, process, file, database (db), decision, start, end, entity, note | | state | state: success | Visual preset: accent, success, warning, error, muted | | lane | lane: customer | Swimlane name | | x, y | x: 120 | Manual position | | dx, dy | dx: 16 | Position fine tuning | | payload | payload: + nested YAML-style fields | Data passed to interaction events. Nodes and edges with payload open the default popup by default | | popup | popup: CustomPopup | Optional explicit popup id override | | link | link: https://example.com | Opens a URL on click | | target | target: _blank | Link target | | flow-ref | flow-ref: checkout/main | Subflow reference badge and event |

Edge Syntax

A -> B
A --> B
A - B
A -- B
A:right! -> B:left!:
  label: forced ports

Common edge attributes:

| Attribute | Example | Description | |---|---|---| | label | label: submit | Edge label | | stroke | stroke: #15803d | Edge color | | stroke-width | stroke-width: 4 | Edge width | | marker-end | marker-end: none | Removes arrow marker | | route | route: perimeter | Route strategy | | on-success | on-success: true | Success path styling | | on-failure | on-failure: true | Failure path styling | | from-anchor-offset | from-anchor-offset: 8 | Moves the source anchor along the selected node side. from-offset is kept as a compatible alias. | | to-anchor-offset | to-anchor-offset: -6 | Moves the target anchor along the selected node side. to-offset is kept as a compatible alias. | | from-anchor-dx, from-anchor-dy | from-anchor-dy: 12 | Force-shifts the source anchor point by X/Y pixels. Useful when several lines share one side. | | to-anchor-dx, to-anchor-dy | to-anchor-dx: -10 | Force-shifts the target anchor point by X/Y pixels. | | parallel-group | parallel-group: stream-1 | Parallel edge separation | | bus | bus: api-bus | Shared bus routing |

Example:

Landing:right! -> Login:left!:
  label: Login
  from-anchor-dy: 12
  to-anchor-dy: -8

ER Diagram

layout:
  mode: horizontal
  auto-fit: true

User:
  PK id bigint
  email varchar(255) UNIQUE NOT NULL
  ---
  kind: entity

Order:
  PK id bigint
  FK user_id bigint NOT NULL
  status varchar(20) NOT NULL
  ---
  kind: entity

User 1--0< Order: "orders"

Field mapping can be written with repeated key: lines.

Order 1--0< OrderLog "audit":
  key: id--order_id
  key: user_id--user_id

Component Diagram

layout:
  mode: horizontal
  auto-fit: true

component Order:
  Order
  ---
  x: 80
  y: 170

component Product:
  Product
  ---
  x: 560
  y: 80

component Account:
  Account
  ---
  x: 560
  y: 300

Order:right! -|o- Product:left!:
  Item Code

Order:bottom! -|--o- Account:left!:
  Account Details

-|o- renders a provided interface connection. -|--o- renders an assembly-style connection where the middle segment is dashed.

Sequence Diagram

sequence:
  participants:
    - id: User
      kind: actor
      view: User
    - id: App
      kind: participant
      view: App
    - id: API
      kind: participant
      view: API
  steps:
    - from: User
      to: App
      label: Submit
    - from: App
      to: API
      label: POST /orders
    - from: API
      to: App
      arrow: -->
      label: 201 Created
    - from: App
      to: User
      arrow: -->
      label: Done

Notes

Input:
  Input
  ---
  kind: screen

Validate:
  Validate
  ---
  kind: process

note Rule:
  Required fields and format checks
  ---
  target: Validate
  state: warning

Input -> Validate

Public API

import {
  Wireflow,
  renderWireflow,
  parseDsl,
  createPopup,
  createDefaultPopupRenderer,
  popupHtml,
  escapeHtml,
  parseMdWireflow,
  createFlowNavigator,
  schema,
  listNodeKinds,
} from "@t-yamauchi/wireflow";

Browser global:

const {
  Wireflow,
  renderWireflow,
  parseDsl,
  createPopup,
  createDefaultPopupRenderer,
  popupHtml,
  escapeHtml,
  schema,
  listNodeKinds,
} = window.WireflowLib;

エディタ補完用スキーマ

schema は Wireflow DSL の補完候補として使える属性、列挙値、スニペットを公開します。schema.version はパッケージの version と同じ値です。

import { schema, listNodeKinds } from "@t-yamauchi/wireflow";

const kindValues = listNodeKinds();
const layoutAttributes = schema.attributes.filter((attr) => attr.scope === "layout");

Popup

For the shortest setup, let the static helper create the instance, inject styles, attach the default popup, and render immediately:

Wireflow.render("#canvas", dsl);

Disable the default popup only when you need full custom handling:

Wireflow.render("#canvas", dsl, { popup: false });
const wf = new Wireflow("#canvas", { defaultPopup: false });

The default popup reads payload fields such as title, desc, note, image, html, and imageAlt. If image or html is true, Wireflow derives the file name from the element/popup id in lowercase:

Test:
  Test
  ---
  payload:
    image: true
# -> images/test.svg

Review:
  Review
  ---
  payload:
    html: true
# -> htmls/review.html

If both image: true and html: true are set, html wins and the image is not shown.

Explicit media file names are also supported:

payload:
  title: Preview
  image: dashboard.svg
  htmlUrl: review.html

You can change those folders at initialization time:

Wireflow.render("#canvas", dsl, {
  popup: {
    imageBasePath: "/assets/images/",
    htmlBasePath: "/assets/htmls/",
    imageExtension: ".png",
    htmlExtension: ".html",
  },
});
createPopup("#canvas", {
  render: ({ id, data, html }) => html`
    <h2>${data.title ?? id}</h2>
    <p>${data.desc ?? ""}</p>
  `,
});

data is the normalized object payload, and html escapes interpolated values automatically. If you need raw HTML, return an Element instead.

Nodes with a payload emit popup events automatically. Use popup: CustomPopup only when you want to override the popup id.

Editor History

Wireflow supports undo/redo for DSL-changing interactions.

  • Undo: Ctrl + Z / Cmd + Z
  • Redo: Ctrl + Y / Cmd + Y / Ctrl + Shift + Z
  • Change event: wireflow:dsl-change

When a node is moved, manual route points on edges connected to that node are cleared so those routes can be recalculated from the new node position.

License

MIT