node-red-contrib-room-tools 1.8.4 → 1.8.8
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.
- package/CONTROL_PANEL_AI_GUIDE.md +156 -39
- package/README.md +10 -0
- package/control-catalog.js +7 -6
- package/control-panel.js +5 -5
- package/control-policy.js +36 -478
- package/control-type-model.js +30 -31
- package/gateway.cjs +13 -261
- package/managed-bridge-admin.js +5 -11
- package/native-binding-plan.js +1 -1
- package/npm-shrinkwrap.json +433 -0
- package/package.json +8 -5
- package/panel-binding-editor.js +25 -36
- package/panel-editor-auth.js +3 -39
- package/panel-http.js +69 -0
- package/panel-visual-apply.js +19 -13
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node-red-contrib-room-tools",
|
|
3
|
+
"version": "1.8.8",
|
|
4
|
+
"lockfileVersion": 2,
|
|
5
|
+
"requires": true,
|
|
6
|
+
"packages": {
|
|
7
|
+
"": {
|
|
8
|
+
"name": "node-red-contrib-room-tools",
|
|
9
|
+
"version": "1.8.8",
|
|
10
|
+
"license": "UNLICENSED",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@vue/compiler-sfc": "3.5.42",
|
|
13
|
+
"acorn": "8.18.0",
|
|
14
|
+
"escodegen": "2.1.0"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18.16.0"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"node_modules/@babel/helper-string-parser": {
|
|
21
|
+
"version": "7.29.7",
|
|
22
|
+
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
|
|
23
|
+
"integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=6.9.0"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"node_modules/@babel/helper-validator-identifier": {
|
|
29
|
+
"version": "7.29.7",
|
|
30
|
+
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
|
|
31
|
+
"integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=6.9.0"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"node_modules/@babel/parser": {
|
|
37
|
+
"version": "7.29.9",
|
|
38
|
+
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz",
|
|
39
|
+
"integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@babel/types": "^7.29.8"
|
|
42
|
+
},
|
|
43
|
+
"bin": {
|
|
44
|
+
"parser": "bin/babel-parser.js"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=6.0.0"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"node_modules/@babel/types": {
|
|
51
|
+
"version": "7.29.8",
|
|
52
|
+
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
|
|
53
|
+
"integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@babel/helper-string-parser": "^7.29.7",
|
|
56
|
+
"@babel/helper-validator-identifier": "^7.29.7"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=6.9.0"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"node_modules/@jridgewell/sourcemap-codec": {
|
|
63
|
+
"version": "1.6.0",
|
|
64
|
+
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
|
|
65
|
+
"integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw=="
|
|
66
|
+
},
|
|
67
|
+
"node_modules/@vue/compiler-core": {
|
|
68
|
+
"version": "3.5.42",
|
|
69
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.42.tgz",
|
|
70
|
+
"integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==",
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@babel/parser": "^7.29.8",
|
|
73
|
+
"@vue/shared": "3.5.42",
|
|
74
|
+
"entities": "^7.0.1",
|
|
75
|
+
"estree-walker": "^2.0.2",
|
|
76
|
+
"source-map-js": "^1.2.1"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"node_modules/@vue/compiler-dom": {
|
|
80
|
+
"version": "3.5.42",
|
|
81
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz",
|
|
82
|
+
"integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==",
|
|
83
|
+
"dependencies": {
|
|
84
|
+
"@vue/compiler-core": "3.5.42",
|
|
85
|
+
"@vue/shared": "3.5.42"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"node_modules/@vue/compiler-sfc": {
|
|
89
|
+
"version": "3.5.42",
|
|
90
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz",
|
|
91
|
+
"integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==",
|
|
92
|
+
"dependencies": {
|
|
93
|
+
"@babel/parser": "^7.29.8",
|
|
94
|
+
"@vue/compiler-core": "3.5.42",
|
|
95
|
+
"@vue/compiler-dom": "3.5.42",
|
|
96
|
+
"@vue/compiler-ssr": "3.5.42",
|
|
97
|
+
"@vue/shared": "3.5.42",
|
|
98
|
+
"estree-walker": "^2.0.2",
|
|
99
|
+
"magic-string": "^0.30.21",
|
|
100
|
+
"postcss": "^8.5.19",
|
|
101
|
+
"source-map-js": "^1.2.1"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"node_modules/@vue/compiler-ssr": {
|
|
105
|
+
"version": "3.5.42",
|
|
106
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz",
|
|
107
|
+
"integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==",
|
|
108
|
+
"dependencies": {
|
|
109
|
+
"@vue/compiler-dom": "3.5.42",
|
|
110
|
+
"@vue/shared": "3.5.42"
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"node_modules/@vue/shared": {
|
|
114
|
+
"version": "3.5.42",
|
|
115
|
+
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.42.tgz",
|
|
116
|
+
"integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g=="
|
|
117
|
+
},
|
|
118
|
+
"node_modules/acorn": {
|
|
119
|
+
"version": "8.18.0",
|
|
120
|
+
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
|
|
121
|
+
"integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
|
|
122
|
+
"bin": {
|
|
123
|
+
"acorn": "bin/acorn"
|
|
124
|
+
},
|
|
125
|
+
"engines": {
|
|
126
|
+
"node": ">=0.4.0"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"node_modules/entities": {
|
|
130
|
+
"version": "7.0.1",
|
|
131
|
+
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
|
132
|
+
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
|
|
133
|
+
"engines": {
|
|
134
|
+
"node": ">=0.12"
|
|
135
|
+
},
|
|
136
|
+
"funding": {
|
|
137
|
+
"url": "https://github.com/fb55/entities?sponsor=1"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"node_modules/escodegen": {
|
|
141
|
+
"version": "2.1.0",
|
|
142
|
+
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
|
|
143
|
+
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
|
|
144
|
+
"dependencies": {
|
|
145
|
+
"esprima": "^4.0.1",
|
|
146
|
+
"estraverse": "^5.2.0",
|
|
147
|
+
"esutils": "^2.0.2"
|
|
148
|
+
},
|
|
149
|
+
"bin": {
|
|
150
|
+
"escodegen": "bin/escodegen.js",
|
|
151
|
+
"esgenerate": "bin/esgenerate.js"
|
|
152
|
+
},
|
|
153
|
+
"engines": {
|
|
154
|
+
"node": ">=6.0"
|
|
155
|
+
},
|
|
156
|
+
"optionalDependencies": {
|
|
157
|
+
"source-map": "~0.6.1"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"node_modules/esprima": {
|
|
161
|
+
"version": "4.0.1",
|
|
162
|
+
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
|
163
|
+
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
|
164
|
+
"bin": {
|
|
165
|
+
"esparse": "bin/esparse.js",
|
|
166
|
+
"esvalidate": "bin/esvalidate.js"
|
|
167
|
+
},
|
|
168
|
+
"engines": {
|
|
169
|
+
"node": ">=4"
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"node_modules/estraverse": {
|
|
173
|
+
"version": "5.3.0",
|
|
174
|
+
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
|
175
|
+
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
|
176
|
+
"engines": {
|
|
177
|
+
"node": ">=4.0"
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"node_modules/estree-walker": {
|
|
181
|
+
"version": "2.0.2",
|
|
182
|
+
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
|
183
|
+
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
|
184
|
+
},
|
|
185
|
+
"node_modules/esutils": {
|
|
186
|
+
"version": "2.0.3",
|
|
187
|
+
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
|
188
|
+
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
|
189
|
+
"engines": {
|
|
190
|
+
"node": ">=0.10.0"
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"node_modules/magic-string": {
|
|
194
|
+
"version": "0.30.21",
|
|
195
|
+
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
|
196
|
+
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
|
197
|
+
"dependencies": {
|
|
198
|
+
"@jridgewell/sourcemap-codec": "^1.5.5"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
"node_modules/nanoid": {
|
|
202
|
+
"version": "3.3.19",
|
|
203
|
+
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
|
|
204
|
+
"integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
|
|
205
|
+
"funding": [
|
|
206
|
+
{
|
|
207
|
+
"type": "github",
|
|
208
|
+
"url": "https://github.com/sponsors/ai"
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
"bin": {
|
|
212
|
+
"nanoid": "bin/nanoid.cjs"
|
|
213
|
+
},
|
|
214
|
+
"engines": {
|
|
215
|
+
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
"node_modules/picocolors": {
|
|
219
|
+
"version": "1.1.1",
|
|
220
|
+
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
221
|
+
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
|
222
|
+
},
|
|
223
|
+
"node_modules/postcss": {
|
|
224
|
+
"version": "8.5.28",
|
|
225
|
+
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
|
|
226
|
+
"integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
|
|
227
|
+
"funding": [
|
|
228
|
+
{
|
|
229
|
+
"type": "opencollective",
|
|
230
|
+
"url": "https://opencollective.com/postcss/"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"type": "tidelift",
|
|
234
|
+
"url": "https://tidelift.com/funding/github/npm/postcss"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"type": "github",
|
|
238
|
+
"url": "https://github.com/sponsors/ai"
|
|
239
|
+
}
|
|
240
|
+
],
|
|
241
|
+
"dependencies": {
|
|
242
|
+
"nanoid": "^3.3.18",
|
|
243
|
+
"picocolors": "^1.1.1",
|
|
244
|
+
"source-map-js": "^1.2.1"
|
|
245
|
+
},
|
|
246
|
+
"engines": {
|
|
247
|
+
"node": "^10 || ^12 || >=14"
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
"node_modules/source-map": {
|
|
251
|
+
"version": "0.6.1",
|
|
252
|
+
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
|
253
|
+
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
|
254
|
+
"optional": true,
|
|
255
|
+
"engines": {
|
|
256
|
+
"node": ">=0.10.0"
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
"node_modules/source-map-js": {
|
|
260
|
+
"version": "1.2.1",
|
|
261
|
+
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
262
|
+
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
|
263
|
+
"engines": {
|
|
264
|
+
"node": ">=0.10.0"
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
"dependencies": {
|
|
269
|
+
"@babel/helper-string-parser": {
|
|
270
|
+
"version": "7.29.7",
|
|
271
|
+
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
|
|
272
|
+
"integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="
|
|
273
|
+
},
|
|
274
|
+
"@babel/helper-validator-identifier": {
|
|
275
|
+
"version": "7.29.7",
|
|
276
|
+
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
|
|
277
|
+
"integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="
|
|
278
|
+
},
|
|
279
|
+
"@babel/parser": {
|
|
280
|
+
"version": "7.29.9",
|
|
281
|
+
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz",
|
|
282
|
+
"integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==",
|
|
283
|
+
"requires": {
|
|
284
|
+
"@babel/types": "^7.29.8"
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
"@babel/types": {
|
|
288
|
+
"version": "7.29.8",
|
|
289
|
+
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
|
|
290
|
+
"integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
|
|
291
|
+
"requires": {
|
|
292
|
+
"@babel/helper-string-parser": "^7.29.7",
|
|
293
|
+
"@babel/helper-validator-identifier": "^7.29.7"
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
"@jridgewell/sourcemap-codec": {
|
|
297
|
+
"version": "1.6.0",
|
|
298
|
+
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
|
|
299
|
+
"integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw=="
|
|
300
|
+
},
|
|
301
|
+
"@vue/compiler-core": {
|
|
302
|
+
"version": "3.5.42",
|
|
303
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.42.tgz",
|
|
304
|
+
"integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==",
|
|
305
|
+
"requires": {
|
|
306
|
+
"@babel/parser": "^7.29.8",
|
|
307
|
+
"@vue/shared": "3.5.42",
|
|
308
|
+
"entities": "^7.0.1",
|
|
309
|
+
"estree-walker": "^2.0.2",
|
|
310
|
+
"source-map-js": "^1.2.1"
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
"@vue/compiler-dom": {
|
|
314
|
+
"version": "3.5.42",
|
|
315
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz",
|
|
316
|
+
"integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==",
|
|
317
|
+
"requires": {
|
|
318
|
+
"@vue/compiler-core": "3.5.42",
|
|
319
|
+
"@vue/shared": "3.5.42"
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
"@vue/compiler-sfc": {
|
|
323
|
+
"version": "3.5.42",
|
|
324
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz",
|
|
325
|
+
"integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==",
|
|
326
|
+
"requires": {
|
|
327
|
+
"@babel/parser": "^7.29.8",
|
|
328
|
+
"@vue/compiler-core": "3.5.42",
|
|
329
|
+
"@vue/compiler-dom": "3.5.42",
|
|
330
|
+
"@vue/compiler-ssr": "3.5.42",
|
|
331
|
+
"@vue/shared": "3.5.42",
|
|
332
|
+
"estree-walker": "^2.0.2",
|
|
333
|
+
"magic-string": "^0.30.21",
|
|
334
|
+
"postcss": "^8.5.19",
|
|
335
|
+
"source-map-js": "^1.2.1"
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
"@vue/compiler-ssr": {
|
|
339
|
+
"version": "3.5.42",
|
|
340
|
+
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz",
|
|
341
|
+
"integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==",
|
|
342
|
+
"requires": {
|
|
343
|
+
"@vue/compiler-dom": "3.5.42",
|
|
344
|
+
"@vue/shared": "3.5.42"
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"@vue/shared": {
|
|
348
|
+
"version": "3.5.42",
|
|
349
|
+
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.42.tgz",
|
|
350
|
+
"integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g=="
|
|
351
|
+
},
|
|
352
|
+
"acorn": {
|
|
353
|
+
"version": "8.18.0",
|
|
354
|
+
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
|
|
355
|
+
"integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="
|
|
356
|
+
},
|
|
357
|
+
"entities": {
|
|
358
|
+
"version": "7.0.1",
|
|
359
|
+
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
|
360
|
+
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="
|
|
361
|
+
},
|
|
362
|
+
"escodegen": {
|
|
363
|
+
"version": "2.1.0",
|
|
364
|
+
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
|
|
365
|
+
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
|
|
366
|
+
"requires": {
|
|
367
|
+
"esprima": "^4.0.1",
|
|
368
|
+
"estraverse": "^5.2.0",
|
|
369
|
+
"esutils": "^2.0.2",
|
|
370
|
+
"source-map": "~0.6.1"
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
"esprima": {
|
|
374
|
+
"version": "4.0.1",
|
|
375
|
+
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
|
376
|
+
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
|
377
|
+
},
|
|
378
|
+
"estraverse": {
|
|
379
|
+
"version": "5.3.0",
|
|
380
|
+
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
|
381
|
+
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
|
|
382
|
+
},
|
|
383
|
+
"estree-walker": {
|
|
384
|
+
"version": "2.0.2",
|
|
385
|
+
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
|
386
|
+
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
|
387
|
+
},
|
|
388
|
+
"esutils": {
|
|
389
|
+
"version": "2.0.3",
|
|
390
|
+
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
|
391
|
+
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
|
|
392
|
+
},
|
|
393
|
+
"magic-string": {
|
|
394
|
+
"version": "0.30.21",
|
|
395
|
+
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
|
396
|
+
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
|
397
|
+
"requires": {
|
|
398
|
+
"@jridgewell/sourcemap-codec": "^1.5.5"
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
"nanoid": {
|
|
402
|
+
"version": "3.3.19",
|
|
403
|
+
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
|
|
404
|
+
"integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug=="
|
|
405
|
+
},
|
|
406
|
+
"picocolors": {
|
|
407
|
+
"version": "1.1.1",
|
|
408
|
+
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
409
|
+
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
|
410
|
+
},
|
|
411
|
+
"postcss": {
|
|
412
|
+
"version": "8.5.28",
|
|
413
|
+
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
|
|
414
|
+
"integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
|
|
415
|
+
"requires": {
|
|
416
|
+
"nanoid": "^3.3.18",
|
|
417
|
+
"picocolors": "^1.1.1",
|
|
418
|
+
"source-map-js": "^1.2.1"
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
"source-map": {
|
|
422
|
+
"version": "0.6.1",
|
|
423
|
+
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
|
424
|
+
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
|
425
|
+
"optional": true
|
|
426
|
+
},
|
|
427
|
+
"source-map-js": {
|
|
428
|
+
"version": "1.2.1",
|
|
429
|
+
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
430
|
+
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-room-tools",
|
|
3
|
-
"version": "1.8.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.8.8",
|
|
4
|
+
"description": "Authenticated visual control panel binding for Node-RED and MUSE Automator",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
|
+
"engines": { "node": ">=18.16.0" },
|
|
6
7
|
"keywords": [
|
|
7
8
|
"node-red"
|
|
8
9
|
],
|
|
9
10
|
"dependencies": {
|
|
10
|
-
"@vue/compiler-sfc": "
|
|
11
|
-
"acorn": "
|
|
12
|
-
"escodegen": "
|
|
11
|
+
"@vue/compiler-sfc": "3.5.42",
|
|
12
|
+
"acorn": "8.18.0",
|
|
13
|
+
"escodegen": "2.1.0"
|
|
13
14
|
},
|
|
14
15
|
"files": [
|
|
15
16
|
"assets/panel-login-bg.png",
|
|
@@ -24,12 +25,14 @@
|
|
|
24
25
|
"panel-visual-bindings.js",
|
|
25
26
|
"panel-visual-apply.js",
|
|
26
27
|
"panel-editor-auth.js",
|
|
28
|
+
"panel-http.js",
|
|
27
29
|
"panel-binding-editor.js",
|
|
28
30
|
"native-binding-plan.js",
|
|
29
31
|
"managed-native-bridge.js",
|
|
30
32
|
"managed-bridge-revision.js",
|
|
31
33
|
"managed-bridge-admin.js",
|
|
32
34
|
"control-policy.js",
|
|
35
|
+
"npm-shrinkwrap.json",
|
|
33
36
|
"CONTROL_PANEL_AI_GUIDE.md",
|
|
34
37
|
"README.md"
|
|
35
38
|
],
|
package/panel-binding-editor.js
CHANGED
|
@@ -2,6 +2,7 @@ function initializeVisualBinding () {
|
|
|
2
2
|
const component = this
|
|
3
3
|
const config = this.__boundPanelConfig()?.visual
|
|
4
4
|
if (!config || !this.$el || typeof document === 'undefined') return
|
|
5
|
+
const matcher = component.__createTargetMatcher(config.contract)
|
|
5
6
|
const root = this.$el
|
|
6
7
|
const base = config.editorEndpoint
|
|
7
8
|
const saved = new Map(Object.entries(config.bindings || {}))
|
|
@@ -47,43 +48,18 @@ function initializeVisualBinding () {
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
async function request (path, method = 'GET', body) {
|
|
50
|
-
const response = await
|
|
51
|
+
const response = await component.__panelFetch(base + path, {
|
|
51
52
|
method, credentials: 'same-origin',
|
|
52
53
|
headers: method === 'POST'
|
|
53
54
|
? { 'Content-Type': 'application/json', 'X-Panel-CSRF': editSession?.csrf || '' }
|
|
54
55
|
: undefined,
|
|
55
|
-
body: method === 'POST' ? JSON.stringify(body || {}) : undefined
|
|
56
|
-
|
|
57
|
-
})
|
|
56
|
+
body: method === 'POST' ? JSON.stringify(body || {}) : undefined
|
|
57
|
+
}, path === '/apply' ? 120000 : 12000)
|
|
58
58
|
const result = await response.json().catch(() => ({}))
|
|
59
59
|
if (!response.ok) throw new Error(result.error || `Request failed (${response.status})`)
|
|
60
60
|
return result
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
if (target.controlSchemaVersion !== config.contract.schemaVersion) return null
|
|
64
|
-
const known = config.contract.types[String(target.controlType || '').toLowerCase()]
|
|
65
|
-
if (!known) return null
|
|
66
|
-
const type = target.type
|
|
67
|
-
if (known.family === 'number' && ['integer', 'float'].includes(type)) return 'number'
|
|
68
|
-
if (known.family === 'boolean' && (type === 'boolean' ||
|
|
69
|
-
(type === 'integer' && target.booleanEncoding === 'integer01' &&
|
|
70
|
-
target.min === 0 && target.max === 1))) return 'boolean'
|
|
71
|
-
if (known.family === 'text' && ['string', 'dstring'].includes(type)) return 'text'
|
|
72
|
-
if (known.family === 'enum' && ['enum', 'integer', 'string'].includes(type)) return 'enum'
|
|
73
|
-
return null
|
|
74
|
-
}
|
|
75
|
-
function compatible (adapter, target, direction, candidate) {
|
|
76
|
-
const families = {
|
|
77
|
-
range: ['number'], switch: ['boolean'], meter: ['number'],
|
|
78
|
-
'text-display': ['number', 'boolean', 'text', 'enum'],
|
|
79
|
-
'text-input': ['text'], select: ['enum']
|
|
80
|
-
}
|
|
81
|
-
if (target.kind !== 'param' || !families[adapter]?.includes(family(target))) return false
|
|
82
|
-
if (direction === 'write' && ['meter', 'text-display'].includes(adapter)) return false
|
|
83
|
-
if (candidate?.unit && candidate.unit !== target.unit) return false
|
|
84
|
-
return direction === 'write' ? ['wo', 'rw'].includes(target.access) : ['ro', 'rw'].includes(target.access)
|
|
85
|
-
}
|
|
86
|
-
function numericRange (binding, node) {
|
|
62
|
+
function numericRange (binding, node) {
|
|
87
63
|
if (binding.uiRange) return binding.uiRange
|
|
88
64
|
const tag = node.tagName?.toLowerCase()
|
|
89
65
|
const type = node.type?.toLowerCase()
|
|
@@ -390,7 +366,7 @@ function initializeVisualBinding () {
|
|
|
390
366
|
}
|
|
391
367
|
function loginView () {
|
|
392
368
|
showLoginForm('ControlPanel editor', async (username, password) => {
|
|
393
|
-
const response = await
|
|
369
|
+
const response = await component.__panelFetch(base + '/login', {
|
|
394
370
|
method: 'POST', credentials: 'same-origin',
|
|
395
371
|
headers: { 'Content-Type': 'application/json' },
|
|
396
372
|
body: JSON.stringify({ username, password })
|
|
@@ -456,9 +432,11 @@ function initializeVisualBinding () {
|
|
|
456
432
|
const message = element('p', '', 'cpv-message')
|
|
457
433
|
form.append(message)
|
|
458
434
|
let targets = []
|
|
435
|
+
let targetGeneration = 0
|
|
459
436
|
function updateTargets () {
|
|
460
|
-
const
|
|
461
|
-
const
|
|
437
|
+
const sameDevice = existing?.device === device.value
|
|
438
|
+
const oldWrite = write.value || (sameDevice ? existing?.writePath : '')
|
|
439
|
+
const oldRead = read.value || (sameDevice ? existing?.readPath || existing?.writePath : '')
|
|
462
440
|
clear(write); clear(read)
|
|
463
441
|
write.append(new Option('Choose...', ''))
|
|
464
442
|
read.append(new Option('Choose...', ''))
|
|
@@ -466,11 +444,11 @@ function initializeVisualBinding () {
|
|
|
466
444
|
let readCount = 0
|
|
467
445
|
for (const target of targets) {
|
|
468
446
|
const label = `${target.path} (${target.type})`
|
|
469
|
-
if (compatible(candidate.adapter, target, 'write', candidate)) {
|
|
447
|
+
if (matcher.compatible(candidate.adapter, target, 'write', candidate)) {
|
|
470
448
|
write.append(new Option(label, target.path))
|
|
471
449
|
writeCount++
|
|
472
450
|
}
|
|
473
|
-
if (compatible(candidate.adapter, target, 'read', candidate)) {
|
|
451
|
+
if (matcher.compatible(candidate.adapter, target, 'read', candidate)) {
|
|
474
452
|
read.append(new Option(label, target.path))
|
|
475
453
|
readCount++
|
|
476
454
|
}
|
|
@@ -485,11 +463,22 @@ function initializeVisualBinding () {
|
|
|
485
463
|
: targets.length ? '' : 'No points available'
|
|
486
464
|
}
|
|
487
465
|
device.addEventListener('change', async () => {
|
|
466
|
+
const generation = ++targetGeneration
|
|
467
|
+
const selectedDevice = device.value
|
|
468
|
+
targets = []
|
|
469
|
+
write.value = ''; read.value = ''
|
|
470
|
+
updateTargets()
|
|
488
471
|
message.textContent = 'Loading points...'
|
|
489
472
|
try {
|
|
490
|
-
|
|
473
|
+
const result = selectedDevice
|
|
474
|
+
? (await request('/targets?device=' + encodeURIComponent(selectedDevice))).targets : []
|
|
475
|
+
if (generation !== targetGeneration) return
|
|
476
|
+
targets = result
|
|
491
477
|
updateTargets()
|
|
492
|
-
} catch (error) {
|
|
478
|
+
} catch (error) {
|
|
479
|
+
if (generation !== targetGeneration) return
|
|
480
|
+
targets = []; updateTargets(); message.textContent = error.message
|
|
481
|
+
}
|
|
493
482
|
})
|
|
494
483
|
write.addEventListener('change', () => { read.value = write.value })
|
|
495
484
|
mode.addEventListener('change', updateTargets)
|
package/panel-editor-auth.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const crypto = require('node:crypto')
|
|
2
|
+
const { readJsonBody, replyJson: reply, sameOrigin } = require('./panel-http')
|
|
2
3
|
|
|
3
4
|
function createPanelEditor ({ panelId, username, password, secureCookie, getConfig, getDevices, getTargets, apply, restoredSessions }) {
|
|
4
5
|
if (!username || !password) return null
|
|
@@ -20,47 +21,10 @@ function createPanelEditor ({ panelId, username, password, secureCookie, getConf
|
|
|
20
21
|
const ttl = 30 * 60 * 1000
|
|
21
22
|
let closed = false
|
|
22
23
|
|
|
23
|
-
function reply (res, status, data, headers = {}) {
|
|
24
|
-
res.writeHead(status, {
|
|
25
|
-
'Content-Type': 'application/json; charset=utf-8',
|
|
26
|
-
'Cache-Control': 'no-store',
|
|
27
|
-
'X-Content-Type-Options': 'nosniff',
|
|
28
|
-
...headers
|
|
29
|
-
})
|
|
30
|
-
res.end(JSON.stringify(data))
|
|
31
|
-
}
|
|
32
|
-
|
|
33
24
|
function cookie (value, age, req) {
|
|
34
25
|
return `${cookieName}=${value}; Path=${prefix}; HttpOnly; SameSite=Strict; Max-Age=${age}${secureCookie && req.socket.encrypted ? '; Secure' : ''}`
|
|
35
26
|
}
|
|
36
27
|
|
|
37
|
-
function sameOrigin (req) {
|
|
38
|
-
const origin = req.headers.origin
|
|
39
|
-
if (!origin) return false
|
|
40
|
-
try {
|
|
41
|
-
const parsed = new URL(origin)
|
|
42
|
-
return parsed.host === req.headers.host &&
|
|
43
|
-
parsed.protocol === (req.socket.encrypted ? 'https:' : 'http:')
|
|
44
|
-
} catch (_) { return false }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function jsonBody (req) {
|
|
48
|
-
if (!String(req.headers['content-type'] || '').startsWith('application/json')) {
|
|
49
|
-
throw new Error('JSON body required')
|
|
50
|
-
}
|
|
51
|
-
if (req.body !== undefined) {
|
|
52
|
-
if (Buffer.isBuffer(req.body)) return JSON.parse(req.body.toString('utf8'))
|
|
53
|
-
if (typeof req.body === 'string') return JSON.parse(req.body)
|
|
54
|
-
if (typeof req.body === 'object' && req.body !== null && Object.keys(req.body).length) return req.body
|
|
55
|
-
}
|
|
56
|
-
let raw = ''
|
|
57
|
-
for await (const chunk of req) {
|
|
58
|
-
raw += chunk
|
|
59
|
-
if (Buffer.byteLength(raw) > 65536) throw new Error('Request too large')
|
|
60
|
-
}
|
|
61
|
-
return JSON.parse(raw)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
28
|
async function handler (req, res) {
|
|
65
29
|
const path = new URL(req.url, 'http://localhost').pathname
|
|
66
30
|
if (!path.startsWith(prefix + '/')) return false
|
|
@@ -82,7 +46,7 @@ function createPanelEditor ({ panelId, username, password, secureCookie, getConf
|
|
|
82
46
|
}
|
|
83
47
|
attempt.count++
|
|
84
48
|
attempts.set(ip, attempt)
|
|
85
|
-
const body = await
|
|
49
|
+
const body = await readJsonBody(req, 65536)
|
|
86
50
|
const supplied = String(body.password || '')
|
|
87
51
|
if (supplied.length > 256) { reply(res, 401, { error: 'Invalid credentials' }); return true }
|
|
88
52
|
const test = await new Promise((resolve, reject) => crypto.scrypt(supplied, salt, 32,
|
|
@@ -120,7 +84,7 @@ function createPanelEditor ({ panelId, username, password, secureCookie, getConf
|
|
|
120
84
|
const device = new URL(req.url, 'http://localhost').searchParams.get('device')
|
|
121
85
|
reply(res, 200, { targets: await getTargets(req, device) })
|
|
122
86
|
} else if (path === prefix + '/apply' && req.method === 'POST') {
|
|
123
|
-
reply(res, 200, await apply(req, await
|
|
87
|
+
reply(res, 200, await apply(req, await readJsonBody(req, 65536)))
|
|
124
88
|
} else {
|
|
125
89
|
reply(res, 404, { error: 'Not found' })
|
|
126
90
|
}
|