iobroker.javascript 10.2.5 → 10.4.0

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 (205) hide show
  1. package/README.md +26 -23
  2. package/admin/assets/AiChatPanel-BjRIKaXG.js +27 -0
  3. package/admin/assets/{AiChatService-BOL3J2Jd.js → AiChatService-DP1EmVk2.js} +3 -3
  4. package/admin/assets/AiDiffView-DeynDw7L.js +1 -0
  5. package/admin/assets/{AiInlineProvider-BIlcrTkS.js → AiInlineProvider-jkEIJJJ-.js} +1 -1
  6. package/admin/assets/BlocklyEditor-DhwThchX.js +301 -0
  7. package/admin/assets/Compile-B0uHjrBE.css +1 -0
  8. package/admin/assets/Compile-e8N5zI-J.js +165 -0
  9. package/admin/assets/Debugger-BDQUKM1K.js +15 -0
  10. package/admin/assets/Diff--plofAtP.js +1 -0
  11. package/admin/assets/{Documentation-Bc0RmoEF.js → Documentation-D3E0U4AK.js} +4 -4
  12. package/admin/assets/ExpandMore-Dio4GeHC.js +1 -0
  13. package/admin/assets/FbEditor-B8S-mCvc.css +1 -0
  14. package/admin/assets/FbEditor-BjLPNzpK.js +15 -0
  15. package/admin/assets/History-Ewi5YEEn.js +1 -0
  16. package/admin/assets/Import-6Mm2vrM2.js +1 -0
  17. package/admin/assets/MonacoDiff-BYvG7IqB.js +1 -0
  18. package/admin/assets/NotificationsActive-CuNfWVJM.js +1 -0
  19. package/admin/assets/RulesEditor--YX6ETsU.js +1 -0
  20. package/admin/assets/{ScriptEditor-CEHpEFp7.js → ScriptEditor-BadPC8Mf.js} +2 -2
  21. package/admin/assets/ScriptEditorVanillaMonaco-BnAmy59d.js +3 -0
  22. package/admin/assets/Send-Pz1eveU5.js +1 -0
  23. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-Ceh8EDcF.js +1 -0
  24. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BRdHvuuG.js +1217 -0
  25. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DLWT3PGo.js +9 -0
  26. package/admin/assets/aiPromptBuilder-Co6AqZwx.js +1 -0
  27. package/admin/assets/{blockly-fcfyKYzp.js → blockly-B0t_IRJQ.js} +1 -1
  28. package/admin/assets/blocklyTheme-iZoge1S9.js +1 -0
  29. package/admin/assets/blocks_action-Ctn5A1AU.js +1 -0
  30. package/admin/assets/{blocks_convert-BP2RjhQH.js → blocks_convert-BI0lf0sf.js} +1 -1
  31. package/admin/assets/blocks_logic-o49klUX_.js +1 -0
  32. package/admin/assets/blocks_number-DZtyWFyR.js +1 -0
  33. package/admin/assets/blocks_object-BuzGCxVr.js +1 -0
  34. package/admin/assets/blocks_procedures-jn9sIYmR.js +3 -0
  35. package/admin/assets/blocks_sendto-Coui8w1H.js +5 -0
  36. package/admin/assets/blocks_switch-CeRZizTM.js +2 -0
  37. package/admin/assets/blocks_system-CaBPIC40.js +1 -0
  38. package/admin/assets/blocks_text-DeDtPYWf.js +1 -0
  39. package/admin/assets/blocks_time-CTXQH3Lm.js +1 -0
  40. package/admin/assets/blocks_timeout-D8IOKOb-.js +1 -0
  41. package/admin/assets/{blocks_trigger-CnmXLCUE.js → blocks_trigger-zuuXJbhb.js} +2 -2
  42. package/admin/assets/{cronHoverProvider-CcIFAhVy.js → cronHoverProvider-Curcjz4m.js} +1 -1
  43. package/admin/assets/dist-CzitsFi7.js +1 -0
  44. package/admin/assets/field_cron-RgLY53_S.js +1 -0
  45. package/admin/assets/field_oid-rBhotXJe.js +1 -0
  46. package/admin/assets/field_script-CU7g3-oB.js +1 -0
  47. package/admin/assets/helpers-BZgjFQNf.js +1 -0
  48. package/admin/assets/helpers-BwllSRzJ.js +1 -0
  49. package/admin/assets/hostInit-CrHjJGJJ.js +1 -0
  50. package/admin/assets/index-BHhhebRG.css +1 -0
  51. package/admin/assets/index-Bmmscq2G.js +157 -0
  52. package/admin/assets/{inlineChatWidget-N8xIkvxX.js → inlineChatWidget-ChchJD9a.js} +2 -2
  53. package/admin/assets/{inlineDiffController-BuqYsKKq.js → inlineDiffController-ly6qX4jk.js} +2 -2
  54. package/admin/assets/loadBlocks-BcFtthDb.js +117 -0
  55. package/admin/assets/loadMonaco-BVOEahNw.js +1 -0
  56. package/admin/assets/{mf-entry-bootstrap-0-a5a39621.js → mf-entry-bootstrap-0-6db6c4fc.js} +3 -3
  57. package/admin/assets/pendingShares-mBGPbRwZ.js +2 -0
  58. package/admin/assets/reactour.esm-Dk3aGxKn.js +137 -0
  59. package/admin/assets/{stateHoverProvider-BYAbe1Ay.js → stateHoverProvider-wAsP-THx.js} +1 -1
  60. package/admin/assets/tileFbd-CWAy7R7m.svg +85 -0
  61. package/admin/assets/utils-DUKzLJUz.js +4 -0
  62. package/admin/assets/vite-preload-helper-DjNwdemH.js +1 -0
  63. package/admin/custom/assets/Components-fDcxCyN4.js +1 -0
  64. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-BraOrMSu.js +1 -0
  65. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-DbKT6Hsb.js +1 -0
  66. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CVvbIPAy.js +1 -0
  67. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DVb0ZZ1Q.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BhZYie9-.js} +89 -89
  68. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-CV50dgj4.js +1 -0
  69. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__date_mf_2_fns__loadShare__.js-Djg9OMcQ.js +1 -0
  70. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__leaflet__loadShare__.js-D9EyCd42.js +1 -0
  71. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__shared-Hb6V6BnJ.js +2 -0
  72. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-BrY-nF2a.js +122 -0
  73. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__leaflet__prebuild__-CHjWtrkp.js +1 -0
  74. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DOkC-g0X.js +9 -0
  75. package/admin/custom/assets/dist-CzitsFi7.js +1 -0
  76. package/admin/custom/assets/helpers-BZgjFQNf.js +1 -0
  77. package/admin/custom/assets/hostInit-akwaQLq8.js +1 -0
  78. package/admin/custom/assets/index-BkItz-nL.js +1 -0
  79. package/admin/custom/assets/{lib-BmDlTzq2.js → lib-CADOx2YN.js} +1 -1
  80. package/admin/custom/assets/{mf-entry-bootstrap-0-ad1cd7d0.js → mf-entry-bootstrap-0-3c4565e0.js} +3 -3
  81. package/admin/custom/assets/pendingShares-TCMDgBLn.js +2 -0
  82. package/admin/custom/assets/utils-DUKzLJUz.js +4 -0
  83. package/admin/custom/assets/vite-preload-helper-DjNwdemH.js +1 -0
  84. package/admin/custom/customComponents.js +2 -2
  85. package/admin/custom/i18n/de.json +19 -1
  86. package/admin/custom/i18n/en.json +19 -1
  87. package/admin/custom/i18n/es.json +19 -1
  88. package/admin/custom/i18n/fr.json +19 -1
  89. package/admin/custom/i18n/it.json +19 -1
  90. package/admin/custom/i18n/nl.json +19 -1
  91. package/admin/custom/i18n/pl.json +19 -1
  92. package/admin/custom/i18n/pt.json +19 -1
  93. package/admin/custom/i18n/ru.json +19 -1
  94. package/admin/custom/i18n/uk.json +19 -1
  95. package/admin/custom/i18n/zh-cn.json +19 -1
  96. package/admin/i18n/de.json +13 -1
  97. package/admin/i18n/en.json +13 -1
  98. package/admin/i18n/es.json +13 -1
  99. package/admin/i18n/fr.json +13 -1
  100. package/admin/i18n/it.json +13 -1
  101. package/admin/i18n/nl.json +13 -1
  102. package/admin/i18n/pl.json +13 -1
  103. package/admin/i18n/pt.json +13 -1
  104. package/admin/i18n/ru.json +13 -1
  105. package/admin/i18n/uk.json +13 -1
  106. package/admin/i18n/zh-cn.json +13 -1
  107. package/admin/jsonConfig.json +274 -86
  108. package/admin/mf-manifest.json +1 -1
  109. package/admin/mf-stats.json +1 -1
  110. package/admin/remoteEntry.js +2 -2
  111. package/admin/tab.html +3 -7
  112. package/build/lib/aiProviderResolver.js +145 -25
  113. package/build/lib/aiProviderResolver.js.map +1 -1
  114. package/build/lib/anthropicAdapter.js +37 -0
  115. package/build/lib/anthropicAdapter.js.map +1 -1
  116. package/build/lib/fb/analyze.js +288 -0
  117. package/build/lib/fb/analyze.js.map +1 -0
  118. package/build/lib/fb/blocks.js +605 -0
  119. package/build/lib/fb/blocks.js.map +1 -0
  120. package/build/lib/fb/generate.js +326 -0
  121. package/build/lib/fb/generate.js.map +1 -0
  122. package/build/lib/fb/graph.js +240 -0
  123. package/build/lib/fb/graph.js.map +1 -0
  124. package/build/lib/fb/index.js +57 -0
  125. package/build/lib/fb/index.js.map +1 -0
  126. package/build/lib/fb/js.js +33 -0
  127. package/build/lib/fb/js.js.map +1 -0
  128. package/build/lib/fb/layout.js +205 -0
  129. package/build/lib/fb/layout.js.map +1 -0
  130. package/build/lib/fb/library.js +657 -0
  131. package/build/lib/fb/library.js.map +1 -0
  132. package/build/lib/fb/runtime.js +793 -0
  133. package/build/lib/fb/runtime.js.map +1 -0
  134. package/build/lib/fb/time.js +76 -0
  135. package/build/lib/fb/time.js.map +1 -0
  136. package/build/lib/fb/types.js +19 -0
  137. package/build/lib/fb/types.js.map +1 -0
  138. package/build/lib/fb/user.js +78 -0
  139. package/build/lib/fb/user.js.map +1 -0
  140. package/build/lib/inspect.js +66 -10
  141. package/build/lib/inspect.js.map +1 -1
  142. package/build/lib/javascript.d.ts +1 -1
  143. package/build/lib/mirror.js +28 -23
  144. package/build/lib/mirror.js.map +1 -1
  145. package/build/lib/sandbox.js +44 -0
  146. package/build/lib/sandbox.js.map +1 -1
  147. package/build/lib/scriptHistory.js +245 -0
  148. package/build/lib/scriptHistory.js.map +1 -0
  149. package/build/main.js +641 -32
  150. package/build/main.js.map +1 -1
  151. package/build/types.d.ts +20 -1
  152. package/docs/de/fbd.md +274 -0
  153. package/docs/en/fbd.md +260 -0
  154. package/io-package.json +55 -29
  155. package/package.json +7 -7
  156. package/admin/assets/AiChatPanel-oBeXbUFv.js +0 -27
  157. package/admin/assets/AiDiffView-C-KKjnJD.js +0 -1
  158. package/admin/assets/Debugger-DwHHsh9O.js +0 -15
  159. package/admin/assets/Error-DZ4vCykD.js +0 -1
  160. package/admin/assets/Import-Cu02ceLW.js +0 -1
  161. package/admin/assets/RulesEditor-QCbi1lV_.js +0 -1
  162. package/admin/assets/ScriptEditorVanillaMonaco-ChQmnk0p.js +0 -3
  163. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-CM95r358.js +0 -1
  164. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BEpNZh4U.js +0 -1217
  165. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-FeM77flT.js +0 -9
  166. package/admin/assets/aiPromptBuilder-DKler0UK.js +0 -1
  167. package/admin/assets/blocks_action-DywZVfRY.js +0 -1
  168. package/admin/assets/blocks_logic-CdTl5YZw.js +0 -1
  169. package/admin/assets/blocks_number-DXFd9Rva.js +0 -1
  170. package/admin/assets/blocks_object-by1uBDHi.js +0 -1
  171. package/admin/assets/blocks_procedures-BcJ7N70D.js +0 -3
  172. package/admin/assets/blocks_sendto-qIKzOAcV.js +0 -5
  173. package/admin/assets/blocks_switch-dLF6hSJl.js +0 -2
  174. package/admin/assets/blocks_system-DmX-SBy8.js +0 -1
  175. package/admin/assets/blocks_text-BI4zNU3o.js +0 -1
  176. package/admin/assets/blocks_time-BgYA4Y_4.js +0 -1
  177. package/admin/assets/blocks_timeout-DUzgMyAu.js +0 -1
  178. package/admin/assets/dist-D4uJqRBO.js +0 -4
  179. package/admin/assets/field_cron-Ba46q8Qc.js +0 -1
  180. package/admin/assets/field_oid-lWCjOzuq.js +0 -1
  181. package/admin/assets/field_script-BCWZHhnW.js +0 -1
  182. package/admin/assets/helpers-CnEjYAup.js +0 -1
  183. package/admin/assets/hostInit-CVybS7BB.js +0 -1
  184. package/admin/assets/index-B3s0zmWC.js +0 -871
  185. package/admin/assets/index-CXaeqPRy.css +0 -1
  186. package/admin/assets/pendingShares-DOAkyFMS.js +0 -1
  187. package/admin/assets/vite-preload-helper-CaC3yEL3.js +0 -1
  188. package/admin/custom/assets/Components-FkGDIlId.js +0 -1
  189. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Cs88NUCd.js +0 -1
  190. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-P-8ffWXw.js +0 -1
  191. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-ZVuRAEo5.js +0 -1
  192. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-Dna3WF04.js +0 -1
  193. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-DcjdCGAx.js +0 -1
  194. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__date_mf_2_fns__loadShare__.js-CnhNjamd.js +0 -1
  195. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__leaflet__loadShare__.js-Dz7BFJqH.js +0 -1
  196. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-B0olko2J.js +0 -1
  197. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-CzN4reh_.js +0 -122
  198. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__leaflet__prebuild__-xPcBaiTQ.js +0 -1
  199. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DuFBE5fh.js +0 -9
  200. package/admin/custom/assets/dist-D4uJqRBO.js +0 -4
  201. package/admin/custom/assets/hostInit-6oh4UY2k.js +0 -1
  202. package/admin/custom/assets/index-BrlyEy6J.js +0 -1
  203. package/admin/custom/assets/pendingShares-kV2kwejX.js +0 -1
  204. package/admin/custom/assets/vite-preload-helper-CaC3yEL3.js +0 -1
  205. /package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js} +0 -0
@@ -0,0 +1,793 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FbRuntime = exports.version = void 0;
40
+ exports.runtime = runtime;
41
+ exports.forScript = forScript;
42
+ /**
43
+ * fb-runtime: what the code generated from a function block diagram calls.
44
+ *
45
+ * The scripts get it with `require('@iobroker/fb-runtime')`. The blocks live here and not as copies
46
+ * in the generated code, so a fix reaches every diagram without generating it again.
47
+ *
48
+ * The module holds no state of its own - every diagram creates its instances and its runtime - and
49
+ * it touches nothing outside: states, subscriptions and timers go through the functions of the
50
+ * sandbox, which removes all of them when the script stops.
51
+ */
52
+ const blocks = __importStar(require("./blocks"));
53
+ const blocks_1 = require("./blocks");
54
+ const types_1 = require("./types");
55
+ // the blocks and the conversions are part of the module the generated code gets
56
+ __exportStar(require("./blocks"), exports);
57
+ exports.version = types_1.FB_RUNTIME_VERSION;
58
+ /** Changes of inputs that arrive within this time run in one cycle */
59
+ const COLLECT_MS = 20;
60
+ /** A cycle that took longer than the interval this many times in a row is reported once */
61
+ const OVERRUN_CYCLES = 10;
62
+ /** Snapshots for the online view come at most this often */
63
+ const PUBLISH_MS = 250;
64
+ /** ... and at least this often, even without a change */
65
+ const HEARTBEAT_MS = 2000;
66
+ /** The frames of a V8 stack: `at fn (file:line:column)` or `at file:line:column` */
67
+ function parseFrames(stack) {
68
+ const frames = [];
69
+ for (const text of (stack || '').split('\n')) {
70
+ const match = text.match(/^\s*at (?:.*? \()?(.*?):(\d+):\d+\)?$/);
71
+ if (match) {
72
+ frames.push({ file: match[1].replace(/\\/g, '/'), line: Number(match[2]) });
73
+ }
74
+ }
75
+ return frames;
76
+ }
77
+ /**
78
+ * A frame of this module. The adapter maps stacks through the source maps, so a frame of this file
79
+ * may name `runtime.ts` as well as `runtime.js`.
80
+ */
81
+ function isOwnFrame(frame) {
82
+ return /\/fb\/runtime\.[jt]s$/.test(frame.file);
83
+ }
84
+ /** An own property - the objects of the code come from another realm, and IDs must not find `constructor` */
85
+ function hasOwn(object, key) {
86
+ return Object.prototype.hasOwnProperty.call(object, key);
87
+ }
88
+ class FbRuntime {
89
+ sandbox;
90
+ hooks;
91
+ values = new Map();
92
+ outputs = new Map();
93
+ /** IDs whose value could not be converted - reported once each */
94
+ badInputs = new Set();
95
+ cycle = null;
96
+ options = null;
97
+ signals = null;
98
+ collectTimer = null;
99
+ lastRun = 0;
100
+ cycles = 0;
101
+ /** The first cycle ran - with `firstScan` */
102
+ scanned = false;
103
+ overruns = 0;
104
+ overrunReported = false;
105
+ lastError = '';
106
+ error = null;
107
+ started = false;
108
+ stopped = false;
109
+ /** Where the generated code runs: its file name in the stack, and how its lines are shifted there */
110
+ scriptFile = '';
111
+ lineOffset = 0;
112
+ /** What the online view got last; `null` while nobody watches */
113
+ sent = null;
114
+ sentError = 'null';
115
+ sentDebug = '';
116
+ sentPaths = '';
117
+ viewer = 0;
118
+ lastPublish = 0;
119
+ /** The breakpoints of the code (`B`), one entry per block in the order of `options.blocks` */
120
+ breaks = null;
121
+ /** The instances of the diagram (`I`) - an instance of a user block has its inside in `$I` and `$S` */
122
+ instances = null;
123
+ breakpoints = new Set();
124
+ /** Forced signals, and what their blocks computed meanwhile */
125
+ forced = new Map();
126
+ computed = new Map();
127
+ /** Set while the cycles wait for the online view */
128
+ halt = null;
129
+ unlisten = null;
130
+ /** The SCHEDULE blocks whose time the sandbox watches */
131
+ schedules = new Set();
132
+ /** The times of the sun events of `astroDay`, by `<event>|<offset>` */
133
+ astroTimes = new Map();
134
+ astroDay = '';
135
+ constructor(sandbox, hooks) {
136
+ this.sandbox = sandbox;
137
+ this.hooks = hooks;
138
+ // the sandbox removes timers and subscriptions itself; this only stops a start still reading
139
+ sandbox.onStop(() => {
140
+ this.stopped = true;
141
+ this.unlisten?.();
142
+ this.unlisten = null;
143
+ });
144
+ }
145
+ /** The value of a state, converted to the type the STATE_IN block puts out */
146
+ input(id, type) {
147
+ const value = this.values.get(id);
148
+ if (type === 'BOOL') {
149
+ return (0, blocks_1.toBool)(value);
150
+ }
151
+ if (type === 'STRING') {
152
+ if (value === null || value === undefined) {
153
+ return '';
154
+ }
155
+ // numbers and booleans come out the same as with String(), objects as JSON
156
+ return typeof value === 'string' ? value : JSON.stringify(value);
157
+ }
158
+ let number = (0, blocks_1.toNum)(value);
159
+ if (Number.isNaN(number)) {
160
+ if (value !== null && value !== undefined && !this.badInputs.has(id)) {
161
+ this.badInputs.add(id);
162
+ this.sandbox.log(`State "${id}" has the value ${JSON.stringify(value)}, which is no number - 0 is used`, 'warn');
163
+ }
164
+ number = 0;
165
+ }
166
+ return type === 'INT' ? Math.round(number) : number;
167
+ }
168
+ /**
169
+ * Writes a state, but only when the value changed. With `minInterval`, writes of one state are
170
+ * at least that many ms apart; the last value is written when the time is over.
171
+ */
172
+ output(id, value, ack, minInterval) {
173
+ const output = this.outputs.get(id) || { value: undefined, ts: 0 };
174
+ this.outputs.set(id, output);
175
+ const target = output.pending ? output.pending.value : output.value;
176
+ if (value === target) {
177
+ return;
178
+ }
179
+ if (value === output.value) {
180
+ // back to what was written last: nothing is left to write
181
+ output.pending = undefined;
182
+ if (output.timer) {
183
+ this.sandbox.clearTimeout(output.timer);
184
+ output.timer = null;
185
+ }
186
+ return;
187
+ }
188
+ const wait = minInterval > 0 ? output.ts + minInterval - Date.now() : 0;
189
+ if (wait <= 0) {
190
+ this.write(id, output, value, ack);
191
+ return;
192
+ }
193
+ output.pending = { value, ack };
194
+ output.timer ||= this.sandbox.setTimeout(() => {
195
+ output.timer = null;
196
+ if (output.pending) {
197
+ this.write(id, output, output.pending.value, output.pending.ack);
198
+ }
199
+ }, wait);
200
+ }
201
+ /**
202
+ * SCHEDULE: whether the time of the cron pattern came since the last cycle. The first call has the
203
+ * sandbox watch the time. When it comes, a cycle runs at once - and one after it, which ends the
204
+ * pulse, in the event mode as well.
205
+ */
206
+ cron(instance, pattern) {
207
+ if (!this.schedules.has(instance)) {
208
+ this.schedules.add(instance);
209
+ // an invalid pattern the sandbox reports itself
210
+ try {
211
+ this.sandbox.schedule?.(pattern, () => {
212
+ instance.pending++;
213
+ this.collect();
214
+ });
215
+ }
216
+ catch (error) {
217
+ this.sandbox.log(`SCHEDULE: cannot use "${pattern}": ${error}`, 'warn');
218
+ }
219
+ }
220
+ instance.run();
221
+ if (instance.Q) {
222
+ this.collect();
223
+ }
224
+ return instance.Q;
225
+ }
226
+ /**
227
+ * ASTRO: the time of day of a sun event today, moved by `offset` minutes. Reckoned once a day. A
228
+ * time that cannot be reckoned - the adapter has no position, the sun does not set - gives 0; the
229
+ * sandbox says why.
230
+ */
231
+ astro(event, offset) {
232
+ const now = new Date();
233
+ const day = now.toDateString();
234
+ if (day !== this.astroDay) {
235
+ this.astroDay = day;
236
+ this.astroTimes.clear();
237
+ }
238
+ const key = `${event}|${offset}`;
239
+ let time = this.astroTimes.get(key);
240
+ if (time === undefined) {
241
+ const date = this.sandbox.getAstroDate?.(event, now.getTime());
242
+ const ts = date ? date.getTime() : NaN;
243
+ time = Number.isFinite(ts) ? (0, blocks_1.timeOfDay)(ts + (offset || 0) * 60000) : 0;
244
+ this.astroTimes.set(key, time);
245
+ }
246
+ return time;
247
+ }
248
+ /** SENDTO: the text of the block to an adapter, in the fields the messengers read */
249
+ send(instance, target, command, title) {
250
+ if (instance.last) {
251
+ this.sandbox.log(`SENDTO ${target}: ${instance.note()}`, 'warn');
252
+ }
253
+ const message = { text: instance.text, message: instance.text };
254
+ if (title) {
255
+ message.title = title;
256
+ message.subject = title;
257
+ }
258
+ this.sandbox.sendTo?.(target, command || 'send', message);
259
+ }
260
+ /** NOTIFY: the text of the block as a notification of ioBroker; `alert` or `message` */
261
+ notify(instance, category) {
262
+ if (instance.last) {
263
+ this.sandbox.log(`NOTIFY: ${instance.note()}`, 'warn');
264
+ }
265
+ this.sandbox.registerNotification?.(instance.text, category === 'alert');
266
+ }
267
+ write(id, output, value, ack) {
268
+ if (output.timer) {
269
+ this.sandbox.clearTimeout(output.timer);
270
+ output.timer = null;
271
+ }
272
+ output.value = value;
273
+ output.ts = Date.now();
274
+ output.pending = undefined;
275
+ this.sandbox.setState(id, value, ack);
276
+ }
277
+ /**
278
+ * Reads the inputs, subscribes to them and runs the first cycle.
279
+ *
280
+ * @param cycle one run through all blocks
281
+ * @param options how and when to run
282
+ * @param signals the signals of the diagram (`S`), for the online view
283
+ * @param breaks the breakpoints of the code (`B`), since runtime 1.2
284
+ * @param instances the instances of the code (`I`), since runtime 1.3
285
+ */
286
+ start(cycle, options, signals, breaks, instances) {
287
+ if (this.started) {
288
+ throw new Error('The function block diagram is already running');
289
+ }
290
+ this.started = true;
291
+ this.cycle = cycle;
292
+ this.options = options;
293
+ this.signals = signals || null;
294
+ this.breaks = breaks && options.blocks ? breaks : null;
295
+ this.instances = instances || null;
296
+ // The first frame outside this file is the `rt.start()` call of the generated code. Its line
297
+ // there, against its line in the source, gives the shift of all lines - whatever the adapter
298
+ // put in front of the source.
299
+ const caller = parseFrames(new Error().stack).find(frame => !isOwnFrame(frame));
300
+ if (caller && options.lines) {
301
+ this.scriptFile = caller.file;
302
+ this.lineOffset = caller.line - options.lines.start;
303
+ }
304
+ if (this.hooks?.listen) {
305
+ this.unlisten = this.hooks.listen(command => this.command(command));
306
+ }
307
+ // what an editor set before the script started again - only while it still watches
308
+ const kept = this.hooks && this.hooks.watched() ? this.hooks.restore?.() : null;
309
+ if (kept) {
310
+ // a block or a signal that is gone since is left out
311
+ for (const block of kept.breakpoints) {
312
+ if (this.breaks && options.blocks.includes(block)) {
313
+ this.breakpoints.add(block);
314
+ }
315
+ }
316
+ this.updateBreaks();
317
+ for (const [signal, value] of Object.entries(kept.forced)) {
318
+ const target = this.holderOf(signal);
319
+ if (target && hasOwn(target.holder, target.key)) {
320
+ this.force(signal, value);
321
+ }
322
+ }
323
+ }
324
+ void this.init();
325
+ }
326
+ async init() {
327
+ const { inputs, outputs, mode, ms } = this.options;
328
+ await Promise.all([
329
+ ...inputs.map(async (id) => this.values.set(id, (await this.read(id))?.val)),
330
+ ...outputs.map(async (id) => this.outputs.set(id, { value: (await this.read(id))?.val, ts: 0 })),
331
+ ]);
332
+ if (this.stopped) {
333
+ return;
334
+ }
335
+ for (const id of inputs) {
336
+ this.sandbox.on({ id, change: 'ne' }, event => {
337
+ this.values.set(id, event.state?.val);
338
+ this.badInputs.delete(id);
339
+ this.collect();
340
+ });
341
+ }
342
+ this.lastRun = Date.now();
343
+ this.run(true);
344
+ if (mode === 'cyclic') {
345
+ this.sandbox.setInterval(() => this.run(false), ms);
346
+ }
347
+ if (this.hooks) {
348
+ this.sandbox.setInterval(() => this.publish(), PUBLISH_MS);
349
+ }
350
+ }
351
+ async read(id) {
352
+ try {
353
+ return await this.sandbox.getStateAsync(id);
354
+ }
355
+ catch (error) {
356
+ this.sandbox.log(`Cannot read state "${id}": ${error}`, 'warn');
357
+ return null;
358
+ }
359
+ }
360
+ /** Changes that come together run in one cycle */
361
+ collect() {
362
+ this.collectTimer ||= this.sandbox.setTimeout(() => {
363
+ this.collectTimer = null;
364
+ this.run(false);
365
+ }, COLLECT_MS);
366
+ }
367
+ /**
368
+ * The block whose line threw - the lines of `cycle()` are one block each. An error inside a user
369
+ * block comes from a line of its factory first; the frame that counts is the one in `cycle()`,
370
+ * the line of the instance.
371
+ */
372
+ blockOf(error) {
373
+ const { lines, blocks } = this.options || {};
374
+ if (!this.scriptFile || !lines || !blocks) {
375
+ return undefined;
376
+ }
377
+ for (const frame of parseFrames(error?.stack)) {
378
+ const index = frame.line - this.lineOffset - lines.body;
379
+ if (frame.file === this.scriptFile && index >= 0 && index < blocks.length) {
380
+ return blocks[index];
381
+ }
382
+ }
383
+ return undefined;
384
+ }
385
+ run(firstScan) {
386
+ if (this.collectTimer) {
387
+ this.sandbox.clearTimeout(this.collectTimer);
388
+ this.collectTimer = null;
389
+ }
390
+ if (this.halt) {
391
+ // the cycles wait for the online view; the inputs are read when they go on
392
+ return;
393
+ }
394
+ const now = Date.now();
395
+ const dt = firstScan ? 0 : now - this.lastRun;
396
+ this.lastRun = now;
397
+ this.cycles++;
398
+ this.scanned = true;
399
+ const stop = this.execute(dt, firstScan, 0, -1);
400
+ if (stop >= 0) {
401
+ this.stopAt(stop, dt, firstScan);
402
+ return;
403
+ }
404
+ const { mode, ms } = this.options;
405
+ if (mode === 'cyclic') {
406
+ if (Date.now() - now > ms) {
407
+ this.overruns++;
408
+ if (this.overruns >= OVERRUN_CYCLES && !this.overrunReported) {
409
+ this.overrunReported = true;
410
+ this.sandbox.log(`A cycle takes longer than the cycle time of ${ms} ms - consider a longer cycle time`, 'warn');
411
+ }
412
+ }
413
+ else {
414
+ this.overruns = 0;
415
+ }
416
+ }
417
+ }
418
+ /**
419
+ * Runs the blocks from `at` on, see `CycleFunction`. Returns the block it stopped in front of, or
420
+ * -1 when the cycle is over - also when a block failed, which ends the cycle.
421
+ */
422
+ execute(dt, firstScan, at, go) {
423
+ try {
424
+ const stop = this.cycle(dt, firstScan, at, go);
425
+ this.lastError = '';
426
+ this.error = null;
427
+ return typeof stop === 'number' ? stop : -1;
428
+ }
429
+ catch (error) {
430
+ // An error from the script comes from another realm, so `instanceof Error` does not work
431
+ const message = error?.message ?? String(error);
432
+ const blockId = this.blockOf(error);
433
+ this.error = blockId ? { message, blockId } : { message };
434
+ // A broken cycle would log at every run - once per error is enough. Not compared by the
435
+ // stack: the first cycle is called from elsewhere than the ones after it.
436
+ const key = `${blockId}|${message}`;
437
+ if (key !== this.lastError) {
438
+ this.lastError = key;
439
+ this.sandbox.log(`Error in the function block diagram${blockId ? ` in block ${blockId}` : ''}: ${error?.stack || String(error)}`, 'error');
440
+ }
441
+ return -1;
442
+ }
443
+ }
444
+ // ---- the online view: forced values, breakpoints, single steps
445
+ /** The cycles wait in front of block `stop` of the cycle that has `dt` and `firstScan` */
446
+ stopAt(stop, dt, firstScan) {
447
+ this.halt = { at: stop, inCycle: true, dt, firstScan };
448
+ this.publish();
449
+ }
450
+ /** A cycle started by hand: the time goes on by one cycle time - the time waited does not count */
451
+ begin() {
452
+ const firstScan = !this.scanned;
453
+ this.scanned = true;
454
+ this.cycles++;
455
+ this.lastRun = Date.now();
456
+ return { dt: firstScan ? 0 : this.options.ms, firstScan };
457
+ }
458
+ /** `all`: every block stops, for a single step */
459
+ updateBreaks(all = false) {
460
+ this.options?.blocks?.forEach((id, i) => {
461
+ if (this.breaks) {
462
+ this.breaks[i] = all || this.breakpoints.has(id) ? 1 : 0;
463
+ }
464
+ });
465
+ }
466
+ /** The signals inside an instance of a user block, by the path of the instance IDs: `b3/b7` */
467
+ instanceAt(path) {
468
+ let instances = this.instances;
469
+ let signals = null;
470
+ for (const id of path.split('/')) {
471
+ const instance = instances && hasOwn(instances, id)
472
+ ? instances[id]
473
+ : undefined;
474
+ if (!instance?.$S) {
475
+ return null;
476
+ }
477
+ signals = instance.$S;
478
+ instances = instance.$I || null;
479
+ }
480
+ return signals;
481
+ }
482
+ /** Where a signal lives: `S` of the diagram, or of the instance its path leads to */
483
+ holderOf(signal) {
484
+ const slash = signal.lastIndexOf('/');
485
+ if (slash === -1) {
486
+ return this.signals ? { holder: this.signals, key: signal } : null;
487
+ }
488
+ const holder = this.instanceAt(signal.substring(0, slash));
489
+ return holder ? { holder, key: signal.substring(slash + 1) } : null;
490
+ }
491
+ status() {
492
+ const status = {
493
+ breaks: !!this.breaks,
494
+ inside: !!this.instances,
495
+ paused: !!this.halt,
496
+ breakpoints: [...this.breakpoints],
497
+ forced: Object.fromEntries(this.forced),
498
+ };
499
+ const at = this.halt && this.options?.blocks?.[this.halt.at];
500
+ if (at) {
501
+ status.at = at;
502
+ }
503
+ return status;
504
+ }
505
+ /** A command of the online view; throws when it cannot be done */
506
+ command(command) {
507
+ switch (command?.command) {
508
+ case 'force':
509
+ this.force(command.signal, command.value);
510
+ break;
511
+ case 'release':
512
+ this.release(command.signal);
513
+ break;
514
+ case 'breakpoint':
515
+ this.setBreakpoint(command.block, command.on);
516
+ break;
517
+ case 'pause':
518
+ this.halt ||= { at: 0, inCycle: false, dt: 0, firstScan: false };
519
+ break;
520
+ case 'resume':
521
+ this.resume();
522
+ break;
523
+ case 'step':
524
+ this.step();
525
+ break;
526
+ case 'cycle':
527
+ this.runCycle();
528
+ break;
529
+ default:
530
+ throw new Error(`Unknown command ${JSON.stringify(command?.command)}`);
531
+ }
532
+ this.hooks?.keep?.(this.forced.size || this.breakpoints.size
533
+ ? { breakpoints: [...this.breakpoints], forced: Object.fromEntries(this.forced) }
534
+ : null);
535
+ this.publish();
536
+ return this.status();
537
+ }
538
+ /**
539
+ * Holds a signal at a value. Its block still computes, but what it writes is kept aside - the
540
+ * signal becomes a property with a getter, so the code needs nothing for it.
541
+ */
542
+ force(signal, value) {
543
+ if (!this.signals) {
544
+ throw new Error('The diagram was saved before values could be forced - save it once');
545
+ }
546
+ const target = this.holderOf(signal);
547
+ if (!target || !hasOwn(target.holder, target.key)) {
548
+ throw new Error(`Unknown signal ${signal}`);
549
+ }
550
+ const { holder, key } = target;
551
+ // the value gets the type the signal has
552
+ const current = this.forced.has(signal) ? this.computed.get(signal) : holder[key];
553
+ let typed;
554
+ if (typeof current === 'boolean') {
555
+ typed = (0, blocks_1.toBool)(value);
556
+ }
557
+ else if (typeof current === 'number') {
558
+ typed = (0, blocks_1.toNum)(value);
559
+ if (Number.isNaN(typed)) {
560
+ throw new Error(`${JSON.stringify(value)} is no number`);
561
+ }
562
+ }
563
+ else {
564
+ typed = value === null || value === undefined ? '' : String(value);
565
+ }
566
+ if (!this.forced.has(signal)) {
567
+ this.computed.set(signal, holder[key]);
568
+ Object.defineProperty(holder, key, {
569
+ configurable: true,
570
+ enumerable: true,
571
+ get: () => this.forced.get(signal),
572
+ set: (computed) => this.computed.set(signal, computed),
573
+ });
574
+ }
575
+ this.forced.set(signal, typed);
576
+ // the blocks behind it see the value in the next cycle - it comes at once
577
+ if (this.scanned) {
578
+ this.collect();
579
+ }
580
+ }
581
+ release(signal) {
582
+ const keys = signal === undefined ? [...this.forced.keys()] : [signal];
583
+ let released = false;
584
+ for (const key of keys) {
585
+ const target = this.holderOf(key);
586
+ if (target && this.forced.has(key)) {
587
+ this.forced.delete(key);
588
+ Object.defineProperty(target.holder, target.key, {
589
+ configurable: true,
590
+ enumerable: true,
591
+ writable: true,
592
+ value: this.computed.get(key),
593
+ });
594
+ this.computed.delete(key);
595
+ released = true;
596
+ }
597
+ }
598
+ if (released && this.scanned) {
599
+ this.collect();
600
+ }
601
+ }
602
+ setBreakpoint(block, on) {
603
+ if (!this.breaks) {
604
+ throw new Error('The diagram was saved before it could stop at blocks - save it once');
605
+ }
606
+ if (block === undefined) {
607
+ if (!on) {
608
+ this.breakpoints.clear();
609
+ }
610
+ }
611
+ else if (!this.options.blocks.includes(block)) {
612
+ throw new Error(`Unknown block ${block}`);
613
+ }
614
+ else if (on) {
615
+ this.breakpoints.add(block);
616
+ }
617
+ else {
618
+ this.breakpoints.delete(block);
619
+ }
620
+ this.updateBreaks();
621
+ }
622
+ /** Runs on: the rest of the cycle, then as usual - up to the next breakpoint */
623
+ resume() {
624
+ const halt = this.halt;
625
+ if (!halt) {
626
+ return;
627
+ }
628
+ this.halt = null;
629
+ if (halt.inCycle) {
630
+ const stop = this.execute(halt.dt, halt.firstScan, halt.at, halt.at);
631
+ if (stop >= 0) {
632
+ this.stopAt(stop, halt.dt, halt.firstScan);
633
+ return;
634
+ }
635
+ }
636
+ // the time waited does not count, and what came meanwhile is taken at once
637
+ this.lastRun = Date.now();
638
+ if (this.scanned) {
639
+ this.run(false);
640
+ }
641
+ }
642
+ /** Runs one block. Not paused yet: stops in front of the next cycle */
643
+ step() {
644
+ if (!this.breaks) {
645
+ throw new Error('The diagram was saved before it could stop at blocks - save it once');
646
+ }
647
+ const halt = this.halt;
648
+ if (!halt) {
649
+ this.halt = { at: 0, inCycle: false, dt: 0, firstScan: false };
650
+ return;
651
+ }
652
+ const { dt, firstScan } = halt.inCycle ? halt : this.begin();
653
+ const at = halt.inCycle ? halt.at : 0;
654
+ this.updateBreaks(true);
655
+ const stop = this.execute(dt, firstScan, at, at);
656
+ this.updateBreaks();
657
+ if (stop >= 0) {
658
+ this.stopAt(stop, dt, firstScan);
659
+ }
660
+ else {
661
+ this.halt = { at: 0, inCycle: false, dt: 0, firstScan: false };
662
+ }
663
+ }
664
+ /** Runs the rest of the cycle, or one whole cycle - up to a breakpoint. Not paused yet: pauses */
665
+ runCycle() {
666
+ const halt = this.halt;
667
+ if (!halt) {
668
+ this.halt = { at: 0, inCycle: false, dt: 0, firstScan: false };
669
+ return;
670
+ }
671
+ const { dt, firstScan } = halt.inCycle ? halt : this.begin();
672
+ const at = halt.inCycle ? halt.at : 0;
673
+ const stop = this.execute(dt, firstScan, at, halt.inCycle ? at : -1);
674
+ if (stop >= 0) {
675
+ this.stopAt(stop, dt, firstScan);
676
+ }
677
+ else {
678
+ this.halt = { at: 0, inCycle: false, dt: 0, firstScan: false };
679
+ }
680
+ }
681
+ /** Nobody watches any more: nothing stays forced, nothing waits */
682
+ endDebugging() {
683
+ if (!this.forced.size && !this.breakpoints.size && !this.halt) {
684
+ return;
685
+ }
686
+ this.release();
687
+ this.breakpoints.clear();
688
+ this.updateBreaks();
689
+ this.hooks?.keep?.(null);
690
+ this.sandbox.log('The online view of the diagram ended: forced values are released, breakpoints removed, the diagram runs on', 'info');
691
+ this.resume();
692
+ }
693
+ /** Sends the online view what changed - only while an editor watches */
694
+ publish() {
695
+ if (!this.hooks || !this.options) {
696
+ return;
697
+ }
698
+ const viewer = this.hooks.watched();
699
+ if (!viewer) {
700
+ this.sent = null;
701
+ this.endDebugging();
702
+ return;
703
+ }
704
+ const now = Date.now();
705
+ const full = !this.sent || viewer !== this.viewer;
706
+ if (full) {
707
+ this.sent = new Map();
708
+ this.viewer = viewer;
709
+ }
710
+ const sent = this.sent;
711
+ // The inside of the instances an editor shows comes as well. What was sent of an instance
712
+ // nobody looks into any more is forgotten, so it comes again in full when somebody does.
713
+ const paths = this.instances ? this.hooks.paths?.() || [] : [];
714
+ const pathsKey = [...paths].sort().join('|');
715
+ if (pathsKey !== this.sentPaths) {
716
+ for (const key of [...sent.keys()]) {
717
+ const slash = key.lastIndexOf('/');
718
+ if (slash !== -1 && !paths.includes(key.substring(0, slash))) {
719
+ sent.delete(key);
720
+ }
721
+ }
722
+ this.sentPaths = pathsKey;
723
+ }
724
+ const groups = [
725
+ ['', this.signals],
726
+ ...paths.map((path) => [`${path}/`, this.instanceAt(path)]),
727
+ ];
728
+ const values = {};
729
+ let changed = false;
730
+ for (const [prefix, signals] of groups) {
731
+ for (const [signal, value] of Object.entries(signals || {})) {
732
+ const key = `${prefix}${signal}`;
733
+ if (full || !sent.has(key) || !Object.is(sent.get(key), value)) {
734
+ values[key] = value;
735
+ sent.set(key, value);
736
+ changed = true;
737
+ }
738
+ }
739
+ }
740
+ const error = JSON.stringify(this.error);
741
+ const errorChanged = full || error !== this.sentError;
742
+ const status = this.status();
743
+ const debug = JSON.stringify(status);
744
+ const debugChanged = full || debug !== this.sentDebug;
745
+ if (!changed && !errorChanged && !debugChanged && now - this.lastPublish < HEARTBEAT_MS) {
746
+ return;
747
+ }
748
+ const snapshot = { ts: now, cycle: this.cycles, mode: this.options.mode };
749
+ if (changed || full) {
750
+ snapshot.values = values;
751
+ }
752
+ if (full) {
753
+ snapshot.full = true;
754
+ }
755
+ if (errorChanged) {
756
+ snapshot.error = this.error;
757
+ this.sentError = error;
758
+ }
759
+ if (debugChanged) {
760
+ snapshot.debug = status;
761
+ this.sentDebug = debug;
762
+ }
763
+ this.lastPublish = now;
764
+ this.hooks.publish(snapshot);
765
+ }
766
+ }
767
+ exports.FbRuntime = FbRuntime;
768
+ /** The runtime of one diagram */
769
+ function runtime(sandbox, requiredVersion, hooks) {
770
+ const [major, minor] = String(requiredVersion).split('.').map(Number);
771
+ const [ownMajor, ownMinor] = exports.version.split('.').map(Number);
772
+ if (major !== ownMajor) {
773
+ sandbox.log(`The diagram was generated for fb-runtime ${requiredVersion}, but ${exports.version} is installed - open and save it in the editor again`, 'warn');
774
+ }
775
+ else if (minor > ownMinor) {
776
+ // blocks of a newer library are missing here
777
+ sandbox.log(`The diagram was generated for fb-runtime ${requiredVersion}, but only ${exports.version} is installed - update the adapter`, 'warn');
778
+ }
779
+ return new FbRuntime(sandbox, hooks);
780
+ }
781
+ /**
782
+ * The module as one script gets it: its runtimes report to the online view of the editor through
783
+ * `hooks`, and take its commands from there. The generated code does not have to know about the
784
+ * online view - so the diagrams saved before it existed have most of it too.
785
+ */
786
+ function forScript(hooks) {
787
+ return {
788
+ ...blocks,
789
+ version: exports.version,
790
+ runtime: (sandbox, requiredVersion) => runtime(sandbox, requiredVersion, hooks),
791
+ };
792
+ }
793
+ //# sourceMappingURL=runtime.js.map