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

@easy-nodes/nodes

v0.1.0

Published

Node definitions and operation registry for Graphly (@easy-nodes/core)

Downloads

52

Readme

@easy-nodes/nodes

Node definitions and operation registry for Graphly (@easy-nodes/core). This package provides a set of reusable nodes (JSON/data transforms, API calls, webhooks) that you can pass into GraphlyCanvas as nodeDefinitions and operations.

Installation

npm install @easy-nodes/core @easy-nodes/nodes

Peer dependency: @easy-nodes/core ^1.0.0.

Integration

import { GraphlyCanvas } from '@easy-nodes/core';
import { nodeDefinitions, getOperations } from '@easy-nodes/nodes';

// Merge with your app's definitions if needed
const allDefinitions = {
  ...nodeDefinitions,
  // myAppNode: { ... }
};

const operations = {
  ...getOperations({ fetch: window.fetch }), // or getOperations() for default fetch
  // myAppOperation: (inputs, state) => ({ ... })
};

<GraphlyCanvas
  nodeDefinitions={allDefinitions}
  operations={operations}
  evaluationMode="async"
  // ... other props
/>

Use evaluationMode="async" when using API Caller or any async registry operation.

getOperations(options?)

  • options.fetch — Custom fetch (e.g. for SSR or testing). Defaults to globalThis.fetch.
  • options.baseUrl — Prepended to relative URLs in API Caller.

Node catalog

Pure nodes (inline operationCode)

| defType | Label | Description | |--------|--------|-------------| | en_parse_json | Parse JSON | Input: JSON string. Output: parsed object (safe fallback on error). | | en_stringify_json | Stringify JSON | Input: any. Config: indent. Output: JSON string. | | en_get_path | Get path | Input: object. Config: dot path (e.g. user.address.city). Output: value at path. | | en_json_mapper | JSON Mapper | Input: array or object. Config: JS mapping expression (use item, get(item, 'path')). Output: mapped result. | | en_filter | Filter | Input: array. Config: JS criteria (use item, get(item, 'path')). Output: filtered array. | | en_merge | Merge | Inputs: A, B. Config: strategy (shallow / deep / concat). Output: merged value. | | en_compare | Compare | Inputs: A, B. Config: operator (eq, ne, gt, lt, gte, lte, contains). Output: boolean. | | en_condition | Condition | Input: value. Config: JS condition. Outputs: trueValue / falseValue (routes by truthiness). | | en_template | Template | Input: object. Config: template string with {{path}} placeholders. Output: filled string. |

Registry-based nodes (async / I/O)

| defType | Label | Description | |--------|--------|-------------| | en_api_caller | API Caller | Config: method, URL, headers (JSON). Input: optional body. Outputs: data, status, error. Requires evaluationMode="async". | | en_webhook | Webhook | Config: webhook ID. Outputs: payload, receivedAt. The app must expose the HTTP endpoint and inject received payload into the graph. See Webhook integration and How to trigger a webhook. |

Webhook integration

The Webhook node does not open a server. The host app is responsible for:

  1. Exposing an HTTP endpoint that receives POST (or GET) webhook calls from external services.
  2. Injecting the payload into the graph: when a webhook request arrives, update the Webhook node’s state (e.g. set state.config.webhookPayload and state.config.webhookReceivedAt for the node instance that matches the webhookId), then trigger a graph re-evaluation.

The package provides:

  • Node definition + operation — the Webhook node and en_webhook (reads state.config.webhookPayload / webhookReceivedAt).
  • Injection helpergetWebhookEventPatch(nodes, event) returns { nodeId, statePatch } for a given { webhookId, payload, receivedAt }; use it with your store’s updateNodeData.
  • React hookuseWebhookReceiver(wsUrl?) connects to a WebSocket that emits { type: 'webhook', webhookId, payload, receivedAt }, finds the matching node, and updates the graph (default ws://localhost:3001). Requires React and @easy-nodes/core.

Your app is responsible for the HTTP endpoint and transport (e.g. Express + WebSocket). The demo’s server in demo/server/ is an example; you can run it with npm run dev:server from demo/.

How to trigger a webhook

From outside (e.g. external service):
Send an HTTP request to the URL your app exposes for webhooks, including the Webhook ID that matches the node's config (e.g. path or query). Typically:

  • POST https://your-app.com/webhook/{webhookId} with the payload in the request body (JSON or form data).
  • Or GET with the webhook ID in the path/query; payload might be empty or in query params.

Example (curl):

curl -X POST https://your-app.com/webhook/my-webhook-id \
  -H "Content-Type: application/json" \
  -d '{"event": "order.created", "id": "123"}'

In your app (when the request arrives):

  1. Parse the incoming request and read the webhook ID (e.g. /webhook/:webhookId).
  2. Either push the event to the client (e.g. via WebSocket) and use useWebhookReceiver(wsUrl) so the package injects it into the graph, or call getWebhookEventPatch(nodes, { webhookId, payload, receivedAt }) and then your store’s updateNodeData(patch.nodeId, patch.statePatch). The graph re-evaluates when config changes.

Demo: real-project webhook setup

The demo in this repo implements the above pattern so you can try it locally:

  1. Run both the app and the webhook server (from the repo root or demo/):

    cd demo && npm run dev:all

    This starts Vite (frontend) and a small Express server (port 3001) that accepts POST /webhook/:webhookId and broadcasts to the frontend over WebSocket.

  2. Trigger the webhook (the default graph includes a Webhook node with ID demo):

    curl -X POST http://localhost:3001/webhook/demo \
      -H "Content-Type: application/json" \
      -d '{"event":"test","message":"Hello"}'

    The frontend receives the payload via WebSocket, updates the Webhook node's config, and the graph re-evaluates; the Webhook Output panel shows the new payload.

In a real project you would run the HTTP endpoint and WebSocket (or another push mechanism) in your own backend and use the same injection pattern: find the node by webhookId, set webhookPayload and webhookReceivedAt on its config, then let the graph re-evaluate (e.g. via your store’s updateNodeData as in the demo).

Conventions

  • All definition keys and operation types are prefixed with en_ to avoid clashes with your own nodes.
  • Pure nodes use operationCode (inline JS); registry nodes use operationType and are implemented in the registry returned by getOperations().

Demo

From the package root (or demo/): npm run dev runs the Vite app only. For webhooks, use npm run dev:all to run the app and the webhook server together; see Demo: real-project webhook setup above.

License

ISC