{"id":13800363,"url":"https://github.com/Steveorevo/node-red-contrib-actionflows","last_synced_at":"2025-05-13T09:31:35.454Z","repository":{"id":27714319,"uuid":"113907797","full_name":"Steveorevo/node-red-contrib-actionflows","owner":"Steveorevo","description":"Provides a set of nodes to enable an extendable design pattern for flows.","archived":false,"fork":false,"pushed_at":"2022-02-07T07:43:09.000Z","size":1371,"stargazers_count":45,"open_issues_count":6,"forks_count":12,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-12T22:20:55.283Z","etag":null,"topics":["benchmark","extensible-flows","flow","loop","node-red","oop","scope","subflow"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Steveorevo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-11T20:58:00.000Z","updated_at":"2024-07-06T04:03:43.000Z","dependencies_parsed_at":"2022-07-21T03:02:41.434Z","dependency_job_id":null,"html_url":"https://github.com/Steveorevo/node-red-contrib-actionflows","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Steveorevo%2Fnode-red-contrib-actionflows","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Steveorevo%2Fnode-red-contrib-actionflows/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Steveorevo%2Fnode-red-contrib-actionflows/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Steveorevo%2Fnode-red-contrib-actionflows/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Steveorevo","download_url":"https://codeload.github.com/Steveorevo/node-red-contrib-actionflows/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253913116,"owners_count":21983260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmark","extensible-flows","flow","loop","node-red","oop","scope","subflow"],"created_at":"2024-08-04T00:01:11.848Z","updated_at":"2025-05-13T09:31:32.168Z","avatar_url":"https://github.com/Steveorevo.png","language":"JavaScript","readme":"# node-red-contrib-actionflows\nActionFlows brings easy to use loops and OOP (object oriented programming)\nfeatures to Node-RED's flow programming paradigm. Three nodes allow you to\ncreate extensible, scoped, looped, and prioritized flows. Utilities include\nperformance benchmarks with nanosecond precision. Advanced use enables the\nability to group flows into \"libraries\" using Node-RED's native subflow\ncapabilities and invocation via JavaScript. You can organize flows for\nreadability and create extendable design patterns. To understand ActionFlows,\nreview each section starting with Basics below and each section's examples.\n\n## Basics\nThe following example of ActionFlows' `action` node does nothing! \"Hello\nWorld\" is placed in the `msg.payload` and passes through the `action` node and\ncan be seen in the debug output; but it's use and versatility can be illustrated\nwith the followup descriptions.\n\n![Action Node Basics](/actionflows/demo/basic.png?raw=true \"The Action Node\")\n\nActionFlows' initial purpose was to allow for \"after market\" flow extendability.\nComplex flows can be customized without modifying the original author's flow.\nThis technique can also be used to organize your existing flows for readability,\nbut links and subflows maybe better suited for that single purpose. ActionFlows\nprovide additional key functionality (described later in this document):\n\n* \"Late binding\"; extend complex flows without modifying the original flow\n* Looping; call flow segments repeatedly with conditional iteration\n* Create OOP-like \"classes\" (subflows) with public/private flows\n* Prioritize flows; allow for OOP-like overrides \u0026 inheritance\n* Flow scopes; private, protected, and global flows\n\nSimply include the `action` flow inline at specific points where you would like\nto enable vendor customization. Like Node-RED's native subflows, a description\nfield allows you to create optional API (application programming interface)\ndocumentation. The `action` node works like a subflow, allowing you to define a\nreusable flow segment between the nodes `action in` and `action out`. Flow\nexecution resumes like Node-RED's native `links` node with \"virtual wires\" at\nthe `action in` node and returns to the calling `action` node after encountering\nthe `action out` node.\n\n![Action In/Out Basics](/actionflows/demo/basic2.png?raw=true \"The Action In and Action Out Nodes\")\n\nUnlike the `links` node, the `action` node invokes the `action in` node by a\nprefix naming schema; allowing for multiple add-on flow segments to be appended\nto the original flow. An `action` node's name determines the name of the\ncorresponding `action in` node that will be activated. Use the `action` node's\nname as a prefix for all subsequent `action in` nodes that you wish to be\ncallable by the `action` node. For instance, an `action` node named \"Sample\",\nwill call any `action in` nodes with names like \"Sample in\", \"Sample-in\",\n\"Sample_Exercise\", or \"sample.acme.com\".\n\n```\nA prefix is an existing `action` node's name followed by\na space, hyphen, underscore, or a period.\n```\n\nIf present, ActionFlows will invoke *multiple* matching prefix named nodes\nsequentially. By default, the sequence order is by creation order but can be\nchanged using the `action in` node's Priority property.\n\n![ActionFlows Sequence](/actionflows/demo/basic3.png?raw=true \"Sequential Flow Segments\")\n\nIn the example above:\n\n1) The `action` node is encountered with `msg.payload` containing \"Hello World\".\n2) The `action in` node (named \"action in\") is called, changing \"World\" into \"World, and Solar System!\".\n3) The `action in` node (named \"action 2\") is called after the last `action out` node and \"World\" is replaced with \"Mars\".\n\nThe versatility of ActionFlows allows the adding of additional flow sequences\nafter the original flow has been authored. The `action in` node's flow segments\ncan be created or imported dynamically (such as with the `flowman` node). Flows\ncan be defined on other tabs or within subflows (see the \"Libraries and Scope\"\nsection below) or restricted to the same tab or subflow where the calling\n`action` node has been defined.\n\nFlow sequence order can also be changed by the `action in` node's settings (see\nthe \"Priorities\" section).\n\n[Download the Basic example flow here.](/actionflows/demo/basic.json)\n\n### Benchmarks and Debugging\n\nBenchmarks in the `action` node allow you to see how long all `action in` flow\nsequences take to execute. Use the checkbox labelled \"Debug action cycle\nexecution time\" to see debug output indicating how long it took to run all of\nthe corresponding `action in/out` flow segments before returning to the calling\naction.\n\n![ActionFlows Benchmarks](/actionflows/demo/bench2.jpg?raw=true \"Debug Execution Time\")\n\n\u003e Note: Benchmarks report how long it takes to run all matching `action in/out`\n\u003e flows for one given iteration. Loops return to the `action` node before\n\u003e repeating and may generate multiple debug outputs.\n\nUse the \"Debug invocation sequence\" checkbox to reveal the name of each\n`action in` that is called, it's sequence order, and node id in the debug tab.\n\n### Priorities\nPriorities allow you to define ActionFlows that take precedence over other\nActionFlows. Inspired by [WordPress' core actions and filters API](https://codex.wordpress.org/Plugin_API#Hooks:_Actions_and_Filters),\nPriorities are at the heart of manageable extendability. In our Basic example\nsequence we see that two `action in/out` flow segments have been defined; each\nchanging the \"Hello World\" in `msg.payload` to eventually become \"Hello Mars,\nand Solar System!\". However, if we simply change the `action in/out` flow\nsequences, we end up with \"Hello Mars\" in the `msg.payload`.\n\n![ActionFlows Priorities](/actionflows/demo/priority2.png?raw=true \"Flow Priorities\")\n\nHere we modify the node \"action in\" and \"action 2\" to execute in the reverse\norder thus changing the debug output message. Open the settings for the nodes\nand change the Priority for \"action 2\" to 45 and leave \"action in\" with Priority\n50 (the default). Now when the `action` node is encountered, it will seek out\nthe `action in/out` flows and run them in a different sequence; the lower the\nPriority number the earlier the flow order will be executed. Two flows with the\nsame Priority number will execute sequentially starting with whichever flow was\ndefined first.\n\nPriority numbers can vary between 1 to 99. The lower the number, the earlier a\ndefined flow segment will execute. I.e. An `action in` node with #1 priority\nexecutes before a #2 priority, etc. It is recommended that you leave the\npriority numbers at their default of 50 to allow overrides by other authors\n(if need be). Often times, multiple vendors or \"plugin\" authors may provide\nfuture functionality that are priority dependent. For example, a\nlocalization/translation service plugin may want to change their Priority\nfor their `action in/out` flow to 95 to ensure that their flow sequence runs\nlast. Thereby ensuring that they have all messages at hand that might need to\nbe translated from one spoken language to another; even if other plugin authors\ninclude their `action in/out` flows leveraging the same `action` node.\n\n### Nesting\nActionFlows can be nested whereby a flow segment can include an `action` node\nthat in turn, invokes additional `action in/out` flow segments. One way to trace\nan ActionFlows' sequence is to use the \"Debug invocation sequence\" checkbox or,\n(as illustrated below) by using the `delay` node. Be sure to set the delay\nto above 2 seconds to see the blue dot appear in the `action in/out` flow path\nand for the green dot and \"running\" indicator under the active `action` node.\nPlease see the animated gif below.\n\n![ActionFlows Nesting](/actionflows/demo/nested.gif?raw=true \"ActionFlows Nesting\")\n\nIn this simple animation, the main `action` node calls two defined flows; one\n`action in/out` node called \"action in\" and another called \"action in 2\". The\n\"action in 2\" flow contains an `action` node called \"nested\" that invokes the\n`action in/out` node named \"nested in\". The first action node waits until all\nother flows and nested flows complete their sequence. Watch the end of the\nanimation above to view an overlay showing the complete flow path.\n\n[Download the Nesting example flow here.](/actionflows/demo/nested.json)\n\n## Loops\nThe `action` node allows execution of `action in/out` node segments based on a\nconditional loop. The default loop mode for an `action` node is \"none\" for no\nlooping. Use the Looping drop down combobox to select the loop type.\n\n![ActionFlows Looping](/actionflows/demo/loop2.jpg?raw=true \"ActionFlows Looping\")\n\n\u003e Note: The `action` node icon will change from a lightening bolt\n\u003e to a circular arrow to indicate the `action` is in loop mode.\n\nIn our example below, we will select the option \"Increment from zero\". This\noption is followed by the variable we'd like to use in our conditional loop.\nThe \"...from zero\" ensures that the variable will be initialized to contain the\nnumeric value 0 when the `action` node is first encountered in the given flow.\nThe variable will be incremented by a numeric 1 each time all corresponding\n`action in/out` nodes have completed. An initial check of the condition occurs\nbefore each iteration. In this case, we will check if the variable `msg.loop` is\ngreater than 2; causing the loop to iterate three times (0, 1, 2).\n\n![ActionFlows Increment from zero](/actionflows/demo/loop.png?raw=true \"ActionFlows Increment from zero\")\n\nThe `msg.loop` variable is accessible to our `change` node allowing us to inject\nit into a string and output the count to the debug window. When the flow is run,\nthe debug window should show three separate outputs; \"Testing 0\", \"Testing 1\",\nand \"Testing 2\" before execution of the flow is stopped.\n\n[Download the Loops example flow here.](/actionflows/demo/loop.json)\n\n### Looping Modes\nThe Looping options in the drop down combobox are defined as follows:\n\n#### None\nNo Looping. The `action` node will seek out any defined `action in` nodes and\nwill call them sequentially, one time only.\n\n#### Watch\nWatch the given variable and compare it using the set logic operator with the\ncomparison variable/value; sequentially invoke each of the defined `action in`\nnodes until the set logic operator evaluates to true. Note: the variable should\nalready exist prior to encountering this node. The logic condition is checked\nbefore the first loop iteration.\n\n#### Decrement\nDecrement the given variable after each loop iteration. Note: the variable should\nalready exist prior to encountering this node. The logic condition is checked\nbefore the first loop iteration, followed by calling each defined `action in`\nflow. The decrement operation occurs after all defined `action in` flows have\ncompleted.\n\n#### Increment\nIncrement the given variable after each loop iteration. Note: the variable should\nalready exist prior to encountering this node. The logic condition is checked\nbefore the first loop iteration, followed by calling each defined `action in`\nflow. The increment operation occurs after all defined `action in` flows have\ncompleted.\n\n#### Increment From Zero\nWhen a flow initially invokes the `action` node, the given variable will be\nreset to zero. If the variable does not exist, it will be created. The logic\ncondition is checked before the first loop iteration, followed by calling each\ndefined `action in` flow. The increment operation occurs after all defined\n`action in` flows have completed. The looping will continue until the logic\ncondition evaluates to a logical true.\n\n### Until Conditional Logic Operator\nThe loop mode will continue until the given conditional logic operator evaluates\nto a logical true. The Until options in the drop down combobox are defined as\nfollows:\n\n#### == (equals)\nChecks if the given variable is equal to the comparison variable or value.\n\n#### != (not equals)\nChecks if the given variable is not equal to the comparison variable or value.\n\n#### \u003c (less than)\nChecks if the given variable is less than the comparison variable or value.\nNote: the given variable and comparison variable/value should contain numeric\nvalues.\n\n#### \u003c= (less than or equal to)\nChecks if the given variable is less than or equal to the comparison variable\nor value. Note: the given variable and comparison variable/value should contain\nnumeric values.\n\n#### \u003e (greater than)\nChecks if the given variable is greater than the comparison variable or value.\nNote: the given variable and comparison variable/value should contain numeric\nvalues.\n\n#### \u003e= (greater than or equal to)\nChecks if the given variable is greater than or equal to the comparison variable\nor value. Note: the given variable and comparison variable/value should contain\nnumeric values.\n\n#### contains\nChecks if the given variable contains the value in the comparison variable/value.\nNote: the given variable and comparison variable/value should contain string\ndata.\n\n#### not contains\nChecks if the given variable does not contain the value in the comparison\nvariable/value. Note: the given variable and comparison variable/value should\ncontain string data.\n\n\n## Libraries and Scope\nScope provides functionality for flows that are more commonly found in OOP\n(object oriented programming) environments. Using scopes with ActionFlows allows\nyou to build reusable flow libraries that may act as a base for other flows.\nRegardless of the scope setting, `action` nodes will invoke all matching\n`action in` flows that are on the same \"z plane\" (same tab or within the same\nsubflow). However, there are many benefits to using the different scope modes\nand in different combinations. Here are the three main levels of scope which\ndefine ActionFlows' behaviors:\n\n#### global\nThe \"global\" scope is the default mode. The \"global\" setting allows you to use\nActionFlows across multiple tabs or within different subflows. An `action` node\nwill invoke any `action in` flow segment across the system, regardless of where\nthey are defined (within subflows or other tabs). Flows will be invoked if the\n`action in` node's name begins with the name of the corresponding `action` node.\nUse the global scope to allow other developers to extend a flow on their own tab\nor without having to modify an existing flow no matter where it is located\n(i.e. deep within a subflows). Placing a group of global ActionFlows within a\nsubflow is an easy way to distribute modular behaviors or add vendor specific\nfunctionality.\n\n#### protected\nUsing the \"protected\" scope setting for ActionFlows allows you to group\nfunctionality while avoiding conflicts with common names that could occur with\nglobal scope. Unlike global scope, protected scope restricts `action` and\ncorresponding `action in` nodes to the same tab. Furthermore, protected scope\nplaces restrictions on accessing ActionFlows within a subflow; you may still\naccess them but must first declare a prefix that is the subflow's name. This\nallows you to work with multiple subflows as **object instances** in a similar\nfashion that OOP developers use classes and objects with public or private\nmethods.\n\n\n![ActionFlows Scope: Protected](/actionflows/demo/protected.jpg?raw=true \"ActionFlows Scope: Protected\")\n\nActionFlows can address other ActionFlows within subflows using an explicit\nprefix to identify the subflow location of other ActionFlows nodes. The prefix\nis the name of the subflow where the corresponding `action` or `action in` node\nexists. In the screenshot above we have two examples:\n\n**An example of an `action` node calling a flow segment defined outside the subflow.**\n  1a) The subflow is defined on the tab with the name \"acme\", it is invoked with\nan injector supplying the string \"Hello\".\n  1b) The injector activates the subflow's `action` node named \"action\".\n  1c) The flow segment outside the subflow is found by the name `acme.action`\nbecause the `action in` node's name starts with the subflow name and the\n`action` node's name within it \"action\".\n\nThe flow segment contains a change node that alters the \"Hello\" and changes it\nto \"Hi\".\n\n\n**An example of a flow segment defined inside a subflow and accessed from outside.**\n  2a) The `action` node named \"acme.sample in\" finds the defined flow segment\ninside the subflow named \"acme\".\n  2b) Within the \"acme\" subflow is the `action in` node named \"sample in\".\n\nThe flow segment has a change node that changes the injector's \"Hello\"\nstring to \"Good bye\".\n\n[Download the Protected Scope example flow here.](/actionflows/demo/protected.json)\n\nThe following namespace-like rules apply to using ActionFlows with \"protected\"\nscope inside of subflows:\n\n* Both `action` and `action in` names must match within a subflow. I.e. an\n`action` named \"sample\" will invoke any `action in` beginning with the name\n\"sample\". The subflow name as a prefix is not necessary from inside the subflow.\n* ActionFlows defined outside of the subflow must declare the subflow name as\napart of the prefix. For example, an `action` node named \"apple\" within\na subflow named \"fruits\" could invoke an `action in` node at the tab level if\nthe `action in` node's name begins with the subflow name, i.e. \"fruits.apple\".\nLikewise, sub-subflows (subflows that exist within subflows) would require\nadditional prefixes to address the innermost node.\n* Protected scope nodes can only invoke one another within the same tab.\n\n```\nNote: Changing the name of a subflow may require a \"Full Deploy\" to update\nActionFlows' internal namespace map changes.\n```\n\n#### private\nPrivate flows are useful if your actions have a commonly used name and/or you\nwish to restrict extendability to within a subflow or tab. Unlike protected\nscope, private scope inhibits the ability to invoke or respond to ActionFlows\nthat are defined outside of the given subflow or tab where the ActionFlows\nexists. Using private scope helps avoid naming conflicts but prevents\nextensibility.\n\n### Mixed Scope Modes\nNote that both `action` and `action in` nodes have a scope setting. For example\nwithin a subflow, a global scope `action` next to private scope `action in` will\nhave a unique ability; this pattern ensures that the internal private\n`action in` is always invoked once within the subflow and only for that subflow\ninstance. Any other `action in` nodes of the same name elsewhere could also be\ncalled but the internal `action in` can never be invoked from other instances\nof the subflow.\n\n### Scope Icons\nScope settings are reflected in the ActionFlows node icons. The icons for\n`action in` nodes, `action` nodes (in single or loop mode) will depict a small\n\"hint\" icon in the upper right hand corner to indicate the scope setting.\n\n![Scope Hint Icons](/actionflows/demo/scope-icons.jpg?raw=true \"Scope Hint Icons\")\n\n## ActionFlows and JavaScript\nActionFlows creates a global object called \"actionflows\" that you can obtain a\nreference to in JavaScript. The object contains a number of data structures and\nmethods that determine the runtime behavior of ActionFlows. For instance, the\nActionFlows' `action in` nodes can be pragmatically invoked using Node-RED's\nnative JavaScript function node. To invoke a given `action in` node, you will\nneed to obtain a reference to the \"actionflows\" global object. Line 1 in the\nscreenshot below shows how to get a reference to \"actionflows\" in the\nvariable `af`. From there you may use the `af` object's `invoke` method to call\nan existing `action in` node (line 2). The `invoke` method expects two\nparameters; the first should be a string representing the name that any matching\n`action in` node should begin with. The second should be the `msg` object to be\npassed into the matching `action in` node.\n\n![JavaScript invoke](/actionflows/demo/invoke.jpg?raw=true \"JavaScript Invoke\")\n\nIn the given screenshot, the JavaScript function node invokes the `action in`\nnode with the name \"action\". The flow is executed and appends the string\n\" World\" to the injector node's \"Hello\" resulting in \"Hello World\" in the debug\nwindow.\n\n[Download the JavaScript Invoke example flow here.](/actionflows/demo/invoke.json)\n*Note: the JavaScript Invoke example requires the [string](https://flows.nodered.org/node/node-red-contrib-string) node.*\n\nThe `actionflows` global object contains the following methods and properties of\ninterest:\n\n### Methods\n**invoke** - Invokes any matching `action in` nodes with the name found in the\nfirst parameter. The second parameter should be the `msg` object to be passed\ninto the flow segment. A promise object is returned with a single incoming\nparameter containing the returned `msg` object. Note: the invoke method ignores\nscope settings and can be used to invoke any `action in` node by name.\n\n**map** - The map method processes all the found `action` and `action in` nodes\nand builds an associative map. This method is called once internally at\ndeployment and determines the order in which each `action in` node is called\nfor it's corresponding `action` node. The results are updated in the `actions`\nproperty (see below).\n\n### Properties\n**actions** - An object containing the calculated associative map from the `map`\nmethod (defined above) that is used internally by ActionFlows. The map is a list\nof enabled `action` node instances with a special `ins` property containing\ncorresponding, `action in` node instances based on their priority and scope\nsettings. The map allows ActionFlows to quickly execute sequential flows at\nruntime. Editing this list will alter the ActionFlows behavior (use with\ncaution). The object can be reset by recalling the `map` method or re-deploying\nto restore the original design-time flow settings.\n\n**afs** - An object containing all the `action` nodes in the system. This property\nis used internally by the `map` method to determine the runtime behavior of\nActionFlows. Altering this list prior to calling the `map` method will\npermanently change the runtime behavior of ActionFlows. Alteration is not\nrecommended as this will disable the ability to reset the behavior until\nre-deployment.\n\n**ins** - An object containing all the `action in` nodes in the system. This\nproperty is used internally by the `map` method to determine the runtime\nbehavior of ActionFlows. Altering this list prior to calling the `map` method\nwill permanently change the runtime behavior of ActionFlows. Alteration is not\nrecommended as this will disable the ability to reset the behavior until\nre-deployment.\n\n### Reserved Action Names\nCurrently, ActionFlows has only one reserved `action in` node name:\n\n```\n#deployed\n```\nAny `action in` nodes that start with \"#deployed\" in their name will be invoked\nat deployment. This would be the equivalent of pairing an inject node with the\noption for \"Inject once at start\" set to invoke a flow segment defined by\nActionFlows. The `action in` node named \"#deployed\" will also contain a\nmsg.payload object property that references the *parent container* the\n`action in` node lives in (i.e. a tab or subflow).\n\n![#deployed Event](/actionflows/demo/deployed.jpg?raw=true \"#deployed Event\")\n\nThis feature can be used to obtain the subflow instance name should you require\na reference to it within your subflow object instance. In addition, the Node-RED\nruntime instance's settings are exposed in `msg.settings` allowing your flows to\nknow the uiPort, settingsFile folder, httpRoot, etc.\n\n[Download the #deployed event example flow here.](/actionflows/demo/deployed.json)\n\n## Installation\nRun the following command in your Node-RED user directory (typically ~/.node-red):\n\n    npm install node-red-contrib-actionflows\n\nThe ActionFlows' nodes will appear in the palette under the advanced group as\nthe nodes `action`, `action in`, and `action out`.\n","funding_links":[],"categories":["Nodes"],"sub_categories":["Utility"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSteveorevo%2Fnode-red-contrib-actionflows","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSteveorevo%2Fnode-red-contrib-actionflows","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSteveorevo%2Fnode-red-contrib-actionflows/lists"}