@gmag11/nodered-mcp-server 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +162 -0
  3. package/index.js +133 -0
  4. package/package.json +58 -0
  5. package/resources/skills/nodered-flow-builder/SKILL.md +659 -0
  6. package/resources/skills/nodered-flow-layout/SKILL.md +395 -0
  7. package/resources/skills/nodered-flowfuse-dashboard/SKILL.md +941 -0
  8. package/resources/skills/nodered-fundamentals/SKILL.md +323 -0
  9. package/resources/skills/nodered-jsonata/SKILL.md +1039 -0
  10. package/resources/skills/nodered-mustache/SKILL.md +588 -0
  11. package/resources/skills/nodered-node-reference/SKILL.md +1020 -0
  12. package/resources/skills/nodered-node-reference/examples/common.json +113 -0
  13. package/resources/skills/nodered-node-reference/examples/network.json +107 -0
  14. package/resources/skills/nodered-node-reference/examples/parser.json +147 -0
  15. package/resources/skills/nodered-node-reference/examples/sequence.json +141 -0
  16. package/resources/skills/nodered-node-reference/examples/storage.json +104 -0
  17. package/resources/skills/nodered-patterns/SKILL.md +414 -0
  18. package/resources/skills/nodered-patterns/examples/error-handler.json +72 -0
  19. package/resources/skills/nodered-patterns/examples/http-endpoint.json +42 -0
  20. package/resources/skills/nodered-patterns/examples/mqtt-subscriber.json +47 -0
  21. package/resources/skills/nodered-patterns/examples/timer-flow.json +50 -0
  22. package/resources/skills/nodered-subflows/SKILL.md +261 -0
  23. package/resources/skills/nodered-uibuilder/SKILL.md +500 -0
  24. package/src/auth/api-key-verifier.js +36 -0
  25. package/src/auth/composite-verifier.js +59 -0
  26. package/src/auth/config.js +106 -0
  27. package/src/auth/oauth-clients-store.js +107 -0
  28. package/src/auth/oauth-provider.js +149 -0
  29. package/src/auth/oauth-token-store.js +312 -0
  30. package/src/nodered/auth.js +158 -0
  31. package/src/nodered/client.js +199 -0
  32. package/src/nodered/comms-client.js +500 -0
  33. package/src/renderer/colors.js +161 -0
  34. package/src/renderer/geometry.js +115 -0
  35. package/src/renderer/html-builder.js +571 -0
  36. package/src/renderer/index.js +51 -0
  37. package/src/renderer/ir-builder.js +161 -0
  38. package/src/renderer/layout.js +126 -0
  39. package/src/renderer/mermaid-builder.js +109 -0
  40. package/src/renderer/svg-builder.js +228 -0
  41. package/src/schemas/responses.js +283 -0
  42. package/src/server.js +844 -0
  43. package/src/skills/loader.js +84 -0
  44. package/src/staging-store.js +258 -0
  45. package/src/tools/add-nodes-to-group.js +216 -0
  46. package/src/tools/connect-nodes.js +115 -0
  47. package/src/tools/constants.js +45 -0
  48. package/src/tools/create-flow.js +87 -0
  49. package/src/tools/create-node.js +126 -0
  50. package/src/tools/create-subflow-instance.js +123 -0
  51. package/src/tools/create-subflow.js +101 -0
  52. package/src/tools/delete-context.js +60 -0
  53. package/src/tools/delete-flow.js +81 -0
  54. package/src/tools/delete-group.js +116 -0
  55. package/src/tools/delete-node.js +73 -0
  56. package/src/tools/delete-subflow.js +103 -0
  57. package/src/tools/deploy.js +94 -0
  58. package/src/tools/disconnect-nodes.js +158 -0
  59. package/src/tools/export-flow.js +161 -0
  60. package/src/tools/export-subflow.js +78 -0
  61. package/src/tools/flow-utils.js +376 -0
  62. package/src/tools/get-config-nodes.js +86 -0
  63. package/src/tools/get-context.js +76 -0
  64. package/src/tools/get-flow-diagram.js +99 -0
  65. package/src/tools/get-flow-nodes.js +116 -0
  66. package/src/tools/get-flows.js +74 -0
  67. package/src/tools/get-node-detail.js +77 -0
  68. package/src/tools/get-node-type-detail.js +92 -0
  69. package/src/tools/get-palette-nodes.js +63 -0
  70. package/src/tools/get-staging-status.js +34 -0
  71. package/src/tools/get-subflow-detail.js +110 -0
  72. package/src/tools/get-subflows.js +105 -0
  73. package/src/tools/import-flow.js +310 -0
  74. package/src/tools/inject-message.js +117 -0
  75. package/src/tools/install-node.js +31 -0
  76. package/src/tools/read-debug-messages.js +155 -0
  77. package/src/tools/refresh-staging.js +62 -0
  78. package/src/tools/remove-nodes-from-group.js +162 -0
  79. package/src/tools/render-staging.js +69 -0
  80. package/src/tools/response-utils.js +42 -0
  81. package/src/tools/search-nodes.js +134 -0
  82. package/src/tools/uninstall-node.js +31 -0
  83. package/src/tools/update-flow.js +95 -0
  84. package/src/tools/update-group.js +77 -0
  85. package/src/tools/update-node.js +132 -0
  86. package/src/tools/update-subflow.js +84 -0
  87. package/src/transport/http.js +252 -0
  88. package/src/transport/stdio.js +16 -0
  89. package/src/transport/ws-server.js +223 -0
@@ -0,0 +1,113 @@
1
+ [
2
+ {
3
+ "id": "example-common-tab",
4
+ "type": "tab",
5
+ "label": "Common Nodes Example",
6
+ "disabled": false,
7
+ "info": "Demonstrates inject, debug, catch, comment, and complete nodes."
8
+ },
9
+ {
10
+ "id": "inject-common-1",
11
+ "type": "inject",
12
+ "z": "example-common-tab",
13
+ "name": "Trigger every 10s",
14
+ "props": [{ "p": "payload", "v": "Hello", "vt": "str" }],
15
+ "repeat": "10",
16
+ "crontab": "",
17
+ "once": false,
18
+ "topic": "test",
19
+ "payload": "Hello",
20
+ "payloadType": "str",
21
+ "x": 120,
22
+ "y": 100,
23
+ "wires": [["debug-common-1"]]
24
+ },
25
+ {
26
+ "id": "debug-common-1",
27
+ "type": "debug",
28
+ "z": "example-common-tab",
29
+ "name": "Show full msg",
30
+ "active": true,
31
+ "tosidebar": true,
32
+ "console": false,
33
+ "tostatus": false,
34
+ "complete": "true",
35
+ "targetType": "full",
36
+ "x": 340,
37
+ "y": 100,
38
+ "wires": []
39
+ },
40
+ {
41
+ "id": "comment-common-1",
42
+ "type": "comment",
43
+ "z": "example-common-tab",
44
+ "name": "This flow sends a test message every 10 seconds and displays it in the debug sidebar",
45
+ "info": "",
46
+ "x": 130,
47
+ "y": 60,
48
+ "wires": []
49
+ },
50
+ {
51
+ "id": "inject-error-trigger",
52
+ "type": "inject",
53
+ "z": "example-common-tab",
54
+ "name": "Trigger error test",
55
+ "props": [{ "p": "payload" }],
56
+ "repeat": "",
57
+ "crontab": "",
58
+ "once": false,
59
+ "topic": "",
60
+ "payload": "",
61
+ "payloadType": "date",
62
+ "x": 120,
63
+ "y": 200,
64
+ "wires": [["function-throw-error"]]
65
+ },
66
+ {
67
+ "id": "function-throw-error",
68
+ "type": "function",
69
+ "z": "example-common-tab",
70
+ "name": "Throw error",
71
+ "func": "node.error(\"Simulated error in function node\", msg);\nreturn null;",
72
+ "outputs": 1,
73
+ "x": 340,
74
+ "y": 200,
75
+ "wires": [[]]
76
+ },
77
+ {
78
+ "id": "catch-common-1",
79
+ "type": "catch",
80
+ "z": "example-common-tab",
81
+ "name": "Catch all errors",
82
+ "scope": [],
83
+ "uncaught": false,
84
+ "x": 340,
85
+ "y": 280,
86
+ "wires": [["debug-error-output"]]
87
+ },
88
+ {
89
+ "id": "debug-error-output",
90
+ "type": "debug",
91
+ "z": "example-common-tab",
92
+ "name": "Error debug",
93
+ "active": true,
94
+ "tosidebar": true,
95
+ "console": false,
96
+ "tostatus": false,
97
+ "complete": "payload",
98
+ "targetType": "msg",
99
+ "x": 560,
100
+ "y": 280,
101
+ "wires": []
102
+ },
103
+ {
104
+ "id": "comment-error-section",
105
+ "type": "comment",
106
+ "z": "example-common-tab",
107
+ "name": "Error handling: inject triggers function that throws → catch captures and displays",
108
+ "info": "",
109
+ "x": 130,
110
+ "y": 160,
111
+ "wires": []
112
+ }
113
+ ]
@@ -0,0 +1,107 @@
1
+ [
2
+ {
3
+ "id": "example-network-tab",
4
+ "type": "tab",
5
+ "label": "Network Nodes Example",
6
+ "disabled": false,
7
+ "info": "Demonstrates http in, http response, http request, and mqtt nodes."
8
+ },
9
+ {
10
+ "id": "httpin-example-1",
11
+ "type": "http in",
12
+ "z": "example-network-tab",
13
+ "name": "GET /api/hello",
14
+ "url": "/api/hello",
15
+ "method": "get",
16
+ "swaggerDoc": "",
17
+ "x": 120,
18
+ "y": 100,
19
+ "wires": [["function-api-handler"]]
20
+ },
21
+ {
22
+ "id": "function-api-handler",
23
+ "type": "function",
24
+ "z": "example-network-tab",
25
+ "name": "Build response",
26
+ "func": "// Build a JSON response\nmsg.payload = {\n message: \"Hello from Node-RED\",\n timestamp: Date.now(),\n query: msg.req.query\n};\nreturn msg;",
27
+ "outputs": 1,
28
+ "x": 340,
29
+ "y": 100,
30
+ "wires": [["httpresponse-example-1"]]
31
+ },
32
+ {
33
+ "id": "httpresponse-example-1",
34
+ "type": "http response",
35
+ "z": "example-network-tab",
36
+ "name": "Send JSON response",
37
+ "statusCode": 200,
38
+ "headers": { "content-type": "application/json" },
39
+ "x": 560,
40
+ "y": 100,
41
+ "wires": []
42
+ },
43
+ {
44
+ "id": "comment-api-section",
45
+ "type": "comment",
46
+ "z": "example-network-tab",
47
+ "name": "HTTP API: GET /api/hello → returns JSON with timestamp",
48
+ "info": "",
49
+ "x": 130,
50
+ "y": 60,
51
+ "wires": []
52
+ },
53
+ {
54
+ "id": "inject-http-request",
55
+ "type": "inject",
56
+ "z": "example-network-tab",
57
+ "name": "Fetch external API",
58
+ "props": [{ "p": "payload", "v": "", "vt": "str" }],
59
+ "repeat": "",
60
+ "crontab": "",
61
+ "once": false,
62
+ "topic": "",
63
+ "payload": "",
64
+ "payloadType": "date",
65
+ "x": 120,
66
+ "y": 220,
67
+ "wires": [["httprequest-example-1"]]
68
+ },
69
+ {
70
+ "id": "httprequest-example-1",
71
+ "type": "http request",
72
+ "z": "example-network-tab",
73
+ "name": "GET JSONPlaceholder",
74
+ "method": "GET",
75
+ "ret": "obj",
76
+ "url": "https://jsonplaceholder.typicode.com/posts/1",
77
+ "tls": "",
78
+ "x": 340,
79
+ "y": 220,
80
+ "wires": [["debug-http-result"]]
81
+ },
82
+ {
83
+ "id": "debug-http-result",
84
+ "type": "debug",
85
+ "z": "example-network-tab",
86
+ "name": "Show API result",
87
+ "active": true,
88
+ "tosidebar": true,
89
+ "console": false,
90
+ "tostatus": false,
91
+ "complete": "payload",
92
+ "targetType": "msg",
93
+ "x": 560,
94
+ "y": 220,
95
+ "wires": []
96
+ },
97
+ {
98
+ "id": "comment-http-section",
99
+ "type": "comment",
100
+ "z": "example-network-tab",
101
+ "name": "Outbound HTTP: inject → http request → debug (result displayed in sidebar)",
102
+ "info": "",
103
+ "x": 130,
104
+ "y": 180,
105
+ "wires": []
106
+ }
107
+ ]
@@ -0,0 +1,147 @@
1
+ [
2
+ {
3
+ "id": "example-parser-tab",
4
+ "type": "tab",
5
+ "label": "Data Parsing Example",
6
+ "disabled": false,
7
+ "info": "Demonstrates json, xml, csv, html, and yaml parser nodes."
8
+ },
9
+ {
10
+ "id": "inject-json-sample",
11
+ "type": "inject",
12
+ "z": "example-parser-tab",
13
+ "name": "Send JSON string",
14
+ "props": [
15
+ { "p": "payload", "v": "{\"name\":\"Alice\",\"age\":30,\"city\":\"NYC\"}", "vt": "str" }
16
+ ],
17
+ "repeat": "",
18
+ "crontab": "",
19
+ "once": false,
20
+ "topic": "",
21
+ "payload": "{\"name\":\"Alice\",\"age\":30,\"city\":\"NYC\"}",
22
+ "payloadType": "str",
23
+ "x": 120,
24
+ "y": 100,
25
+ "wires": [["json-parse-example"]]
26
+ },
27
+ {
28
+ "id": "comment-json-section",
29
+ "type": "comment",
30
+ "z": "example-parser-tab",
31
+ "name": "JSON: parse string → modify object → stringify → debug",
32
+ "info": "",
33
+ "x": 130,
34
+ "y": 60,
35
+ "wires": []
36
+ },
37
+ {
38
+ "id": "json-parse-example",
39
+ "type": "json",
40
+ "z": "example-parser-tab",
41
+ "name": "JSON → Object",
42
+ "property": "payload",
43
+ "action": "obj",
44
+ "pretty": false,
45
+ "x": 320,
46
+ "y": 100,
47
+ "wires": [["function-modify"]]
48
+ },
49
+ {
50
+ "id": "function-modify",
51
+ "type": "function",
52
+ "z": "example-parser-tab",
53
+ "name": "Add country field",
54
+ "func": "msg.payload.country = \"USA\";\nreturn msg;",
55
+ "outputs": 1,
56
+ "x": 520,
57
+ "y": 100,
58
+ "wires": [["json-stringify-example"]]
59
+ },
60
+ {
61
+ "id": "json-stringify-example",
62
+ "type": "json",
63
+ "z": "example-parser-tab",
64
+ "name": "Object → JSON",
65
+ "property": "payload",
66
+ "action": "str",
67
+ "pretty": true,
68
+ "x": 720,
69
+ "y": 100,
70
+ "wires": [["debug-json-result"]]
71
+ },
72
+ {
73
+ "id": "debug-json-result",
74
+ "type": "debug",
75
+ "z": "example-parser-tab",
76
+ "name": "Pretty JSON output",
77
+ "active": true,
78
+ "tosidebar": true,
79
+ "console": false,
80
+ "tostatus": false,
81
+ "complete": "payload",
82
+ "targetType": "msg",
83
+ "x": 920,
84
+ "y": 100,
85
+ "wires": []
86
+ },
87
+ {
88
+ "id": "comment-csv-section",
89
+ "type": "comment",
90
+ "z": "example-parser-tab",
91
+ "name": "CSV: parse → transform → stringify (round-trip example)",
92
+ "info": "",
93
+ "x": 130,
94
+ "y": 180,
95
+ "wires": []
96
+ },
97
+ {
98
+ "id": "inject-csv-sample",
99
+ "type": "inject",
100
+ "z": "example-parser-tab",
101
+ "name": "Send CSV string",
102
+ "props": [
103
+ { "p": "payload", "v": "name,age,city\nAlice,30,NYC\nBob,25,LA", "vt": "str" }
104
+ ],
105
+ "repeat": "",
106
+ "crontab": "",
107
+ "once": false,
108
+ "topic": "",
109
+ "payload": "name,age,city\nAlice,30,NYC\nBob,25,LA",
110
+ "payloadType": "str",
111
+ "x": 120,
112
+ "y": 240,
113
+ "wires": [["csv-parse-example"]]
114
+ },
115
+ {
116
+ "id": "csv-parse-example",
117
+ "type": "csv",
118
+ "z": "example-parser-tab",
119
+ "name": "CSV → Array",
120
+ "sep": ",",
121
+ "hdrin": true,
122
+ "hdrout": "all",
123
+ "multi": "one",
124
+ "ret": "\\n",
125
+ "temp": "",
126
+ "skip": 0,
127
+ "charset": "",
128
+ "x": 320,
129
+ "y": 240,
130
+ "wires": [["debug-csv-result"]]
131
+ },
132
+ {
133
+ "id": "debug-csv-result",
134
+ "type": "debug",
135
+ "z": "example-parser-tab",
136
+ "name": "CSV output",
137
+ "active": true,
138
+ "tosidebar": true,
139
+ "console": false,
140
+ "tostatus": false,
141
+ "complete": "payload",
142
+ "targetType": "msg",
143
+ "x": 520,
144
+ "y": 240,
145
+ "wires": []
146
+ }
147
+ ]
@@ -0,0 +1,141 @@
1
+ [
2
+ {
3
+ "id": "example-sequence-tab",
4
+ "type": "tab",
5
+ "label": "Sequence & Flow Control Example",
6
+ "disabled": false,
7
+ "info": "Demonstrates delay, split, join, switch, change, and trigger nodes in sequence."
8
+ },
9
+ {
10
+ "id": "inject-sequence-1",
11
+ "type": "inject",
12
+ "z": "example-sequence-tab",
13
+ "name": "Send array of names",
14
+ "props": [
15
+ { "p": "payload", "v": "[\"Alice\",\"Bob\",\"Charlie\",\"Diana\",\"Eve\"]", "vt": "json" }
16
+ ],
17
+ "repeat": "",
18
+ "crontab": "",
19
+ "once": false,
20
+ "topic": "",
21
+ "payload": "[\"Alice\",\"Bob\",\"Charlie\",\"Diana\",\"Eve\"]",
22
+ "payloadType": "json",
23
+ "x": 120,
24
+ "y": 100,
25
+ "wires": [["split-names"]]
26
+ },
27
+ {
28
+ "id": "comment-seq-intro",
29
+ "type": "comment",
30
+ "z": "example-sequence-tab",
31
+ "name": "Sequence: inject array → split → delay each → switch route → join → debug",
32
+ "info": "",
33
+ "x": 130,
34
+ "y": 60,
35
+ "wires": []
36
+ },
37
+ {
38
+ "id": "split-names",
39
+ "type": "split",
40
+ "z": "example-sequence-tab",
41
+ "name": "Split array to individual msgs",
42
+ "splt": "\\n",
43
+ "spltType": "arr",
44
+ "arraySplt": 1,
45
+ "stream": false,
46
+ "addname": "",
47
+ "x": 320,
48
+ "y": 100,
49
+ "wires": [["delay-each"]]
50
+ },
51
+ {
52
+ "id": "delay-each",
53
+ "type": "delay",
54
+ "z": "example-sequence-tab",
55
+ "name": "Delay 500ms per msg",
56
+ "pauseType": "delay",
57
+ "timeout": "0.5",
58
+ "timeoutUnits": "seconds",
59
+ "rate": 1,
60
+ "nbRateUnits": 1,
61
+ "rateUnits": "second",
62
+ "drop": false,
63
+ "x": 520,
64
+ "y": 100,
65
+ "wires": [["switch-route"]]
66
+ },
67
+ {
68
+ "id": "switch-route",
69
+ "type": "switch",
70
+ "z": "example-sequence-tab",
71
+ "name": "Route by first letter",
72
+ "rules": [
73
+ { "t": "lte", "v": "D", "vt": "str", "property": "payload" },
74
+ { "t": "else", "v": "", "vt": "str" }
75
+ ],
76
+ "property": "payload",
77
+ "propertyType": "msg",
78
+ "checkall": "false",
79
+ "repair": false,
80
+ "x": 720,
81
+ "y": 100,
82
+ "wires": [
83
+ ["change-tag-early"],
84
+ ["change-tag-late"]
85
+ ]
86
+ },
87
+ {
88
+ "id": "change-tag-early",
89
+ "type": "change",
90
+ "z": "example-sequence-tab",
91
+ "name": "Tag: early alpha",
92
+ "rules": [
93
+ { "t": "set", "p": "topic", "pt": "msg", "to": "early", "tot": "str" }
94
+ ],
95
+ "x": 920,
96
+ "y": 80,
97
+ "wires": [["debug-early"]]
98
+ },
99
+ {
100
+ "id": "debug-early",
101
+ "type": "debug",
102
+ "z": "example-sequence-tab",
103
+ "name": "Early names",
104
+ "active": true,
105
+ "tosidebar": true,
106
+ "console": false,
107
+ "tostatus": false,
108
+ "complete": "payload",
109
+ "targetType": "msg",
110
+ "x": 1100,
111
+ "y": 80,
112
+ "wires": []
113
+ },
114
+ {
115
+ "id": "change-tag-late",
116
+ "type": "change",
117
+ "z": "example-sequence-tab",
118
+ "name": "Tag: late alpha",
119
+ "rules": [
120
+ { "t": "set", "p": "topic", "pt": "msg", "to": "late", "tot": "str" }
121
+ ],
122
+ "x": 920,
123
+ "y": 140,
124
+ "wires": [["debug-late"]]
125
+ },
126
+ {
127
+ "id": "debug-late",
128
+ "type": "debug",
129
+ "z": "example-sequence-tab",
130
+ "name": "Late names",
131
+ "active": true,
132
+ "tosidebar": true,
133
+ "console": false,
134
+ "tostatus": false,
135
+ "complete": "payload",
136
+ "targetType": "msg",
137
+ "x": 1100,
138
+ "y": 140,
139
+ "wires": []
140
+ }
141
+ ]
@@ -0,0 +1,104 @@
1
+ [
2
+ {
3
+ "id": "example-storage-tab",
4
+ "type": "tab",
5
+ "label": "Storage & Context Example",
6
+ "disabled": false,
7
+ "info": "Demonstrates context read/write in function nodes, change node, and exec node."
8
+ },
9
+ {
10
+ "id": "inject-counter-inc",
11
+ "type": "inject",
12
+ "z": "example-storage-tab",
13
+ "name": "Increment counter",
14
+ "props": [{ "p": "payload", "v": "inc", "vt": "str" }],
15
+ "repeat": "",
16
+ "crontab": "",
17
+ "once": false,
18
+ "topic": "",
19
+ "payload": "inc",
20
+ "payloadType": "str",
21
+ "x": 120,
22
+ "y": 100,
23
+ "wires": [["function-counter"]]
24
+ },
25
+ {
26
+ "id": "function-counter",
27
+ "type": "function",
28
+ "z": "example-storage-tab",
29
+ "name": "Context counter",
30
+ "func": "// Increment flow-scoped counter\nlet count = flow.get(\"counter\") || 0;\ncount += 1;\nflow.set(\"counter\", count);\n\nmsg.payload = { counter: count, timestamp: Date.now() };\nreturn msg;",
31
+ "outputs": 1,
32
+ "x": 340,
33
+ "y": 100,
34
+ "wires": [["debug-counter"]]
35
+ },
36
+ {
37
+ "id": "debug-counter",
38
+ "type": "debug",
39
+ "z": "example-storage-tab",
40
+ "name": "Show counter",
41
+ "active": true,
42
+ "tosidebar": true,
43
+ "console": false,
44
+ "tostatus": false,
45
+ "complete": "payload",
46
+ "targetType": "msg",
47
+ "x": 560,
48
+ "y": 100,
49
+ "wires": []
50
+ },
51
+ {
52
+ "id": "inject-counter-reset",
53
+ "type": "inject",
54
+ "z": "example-storage-tab",
55
+ "name": "Reset counter",
56
+ "props": [{ "p": "payload", "v": "reset", "vt": "str" }],
57
+ "repeat": "",
58
+ "crontab": "",
59
+ "once": false,
60
+ "topic": "",
61
+ "payload": "reset",
62
+ "payloadType": "str",
63
+ "x": 120,
64
+ "y": 180,
65
+ "wires": [["change-reset"]]
66
+ },
67
+ {
68
+ "id": "change-reset",
69
+ "type": "change",
70
+ "z": "example-storage-tab",
71
+ "name": "Clear flow counter",
72
+ "rules": [
73
+ { "t": "set", "p": "counter", "pt": "flow", "to": "0", "tot": "num" }
74
+ ],
75
+ "x": 340,
76
+ "y": 180,
77
+ "wires": [["debug-reset-msg"]]
78
+ },
79
+ {
80
+ "id": "debug-reset-msg",
81
+ "type": "debug",
82
+ "z": "example-storage-tab",
83
+ "name": "Reset confirmed",
84
+ "active": true,
85
+ "tosidebar": true,
86
+ "console": false,
87
+ "tostatus": false,
88
+ "complete": "true",
89
+ "targetType": "full",
90
+ "x": 560,
91
+ "y": 180,
92
+ "wires": []
93
+ },
94
+ {
95
+ "id": "comment-context-section",
96
+ "type": "comment",
97
+ "z": "example-storage-tab",
98
+ "name": "Context: function node increments flow.counter + change node resets flow.counter to 0",
99
+ "info": "",
100
+ "x": 130,
101
+ "y": 60,
102
+ "wires": []
103
+ }
104
+ ]