@easy-nodes/nodes
v0.1.0
Published
Node definitions and operation registry for Graphly (@easy-nodes/core)
Downloads
52
Maintainers
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/nodesPeer 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 toglobalThis.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:
- Exposing an HTTP endpoint that receives POST (or GET) webhook calls from external services.
- Injecting the payload into the graph: when a webhook request arrives, update the Webhook node’s state (e.g. set
state.config.webhookPayloadandstate.config.webhookReceivedAtfor the node instance that matches thewebhookId), then trigger a graph re-evaluation.
The package provides:
- Node definition + operation — the Webhook node and
en_webhook(readsstate.config.webhookPayload/webhookReceivedAt). - Injection helper —
getWebhookEventPatch(nodes, event)returns{ nodeId, statePatch }for a given{ webhookId, payload, receivedAt }; use it with your store’supdateNodeData. - React hook —
useWebhookReceiver(wsUrl?)connects to a WebSocket that emits{ type: 'webhook', webhookId, payload, receivedAt }, finds the matching node, and updates the graph (defaultws://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):
- Parse the incoming request and read the webhook ID (e.g.
/webhook/:webhookId). - Either push the event to the client (e.g. via WebSocket) and use
useWebhookReceiver(wsUrl)so the package injects it into the graph, or callgetWebhookEventPatch(nodes, { webhookId, payload, receivedAt })and then your store’supdateNodeData(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:
Run both the app and the webhook server (from the repo root or
demo/):cd demo && npm run dev:allThis starts Vite (frontend) and a small Express server (port 3001) that accepts
POST /webhook/:webhookIdand broadcasts to the frontend over WebSocket.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 useoperationTypeand are implemented in the registry returned bygetOperations().
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
