iobroker.javascript 9.3.0 → 10.0.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 (220) hide show
  1. package/README.md +8 -9
  2. package/admin/assets/AiChatPanel-p0KAg6Cs.js +237 -0
  3. package/admin/assets/AiDatapointProvider-DzFpUKkT.js +2 -0
  4. package/admin/assets/AiDiffView-BPTLnNx1.js +1 -0
  5. package/admin/assets/AiInlineProvider-CaHd2G2Q.js +5 -0
  6. package/admin/assets/AiScriptAnalyzer--BHML2rN.js +9 -0
  7. package/admin/assets/BlocklyEditor-CAjVMhYT.js +81 -0
  8. package/admin/assets/ContextWrapper-BVc8wTK_.css +1 -0
  9. package/admin/assets/ContextWrapper-D9CrnNKs.js +127 -0
  10. package/admin/assets/Debugger-SjROokFI.js +15 -0
  11. package/admin/assets/Error-DDfrxAt2.js +1 -0
  12. package/admin/assets/Import-DpTg1Jow.js +1 -0
  13. package/admin/assets/RulesEditor-BSRFWpEm.css +1 -0
  14. package/admin/assets/RulesEditor-D0hgrcBc.js +1 -0
  15. package/admin/assets/ScriptEditor-BGIuoNei.js +2 -0
  16. package/admin/assets/ScriptEditorVanillaMonaco-DyMQtoTQ.js +3 -0
  17. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-DWJotR1B.js +1 -0
  18. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-CxICLr5Z.js +1243 -0
  19. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-BBAXJaqI.js +9 -0
  20. package/admin/assets/aiCodeLensProvider-hyAmut0e.js +4 -0
  21. package/admin/assets/aiPromptBuilder-Bs27qOHT.js +7 -0
  22. package/admin/assets/applyCodeEdit-D3nb7erO.js +1 -0
  23. package/admin/assets/blocklyDarkTheme-DEiAX5DT.js +1 -0
  24. package/admin/assets/cronHoverProvider-pKJkSevo.js +2 -0
  25. package/admin/assets/dist-uw5orDgd.js +4 -0
  26. package/admin/assets/{docs-compact-CKNGiYh2.js → docs-compact-D7rpMc7r.js} +2 -2
  27. package/admin/assets/hostInit-BFg5u9hY.js +1 -0
  28. package/admin/assets/index-B1gICjdq.js +192 -0
  29. package/admin/assets/index-BHhhebRG.css +1 -0
  30. package/admin/assets/inlineChatWidget-ZaisTOLh.js +2 -0
  31. package/admin/assets/inlineDiffController-hTwHHqcc.js +16 -0
  32. package/admin/assets/mf-entry-bootstrap-0-d6052b31.js +36 -0
  33. package/admin/assets/mjs-DWqivHEk.js +90 -0
  34. package/admin/assets/rolldown-runtime-C0FnF6B9.js +1 -0
  35. package/admin/assets/stateHoverProvider-C7DawIs-.js +9 -0
  36. package/admin/assets/virtualExposes-Ed0lGq7k.js +1 -0
  37. package/admin/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__iobroker_javascript__remoteEntry_js-BYs71IQF.js +1 -0
  38. package/admin/assets/virtual_mf-exposes___mfe_internal__iobroker_javascript__remoteEntry_js-DnnXQRkG.js +1 -0
  39. package/admin/assets/vite-preload-helper-B7qeedMF.js +1 -0
  40. package/admin/custom/assets/Components-BrDyDHXh.js +1 -0
  41. package/admin/custom/assets/Components-DftM8alF.css +1 -0
  42. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-CyYJM2-v.js +1 -0
  43. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-BdzCssLn.js +1 -0
  44. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CGb5Cofy.js +1 -0
  45. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BVCIAgbo.js +1243 -0
  46. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-BkB0anQX.js +1494 -0
  47. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare__leaflet__loadShare__.js-h-rCw3iz.js +1 -0
  48. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-BotqDuw-.js +9 -0
  49. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__prebuild__date_mf_2_fns__prebuild__-Cb5TR7FB.js +1 -0
  50. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__prebuild__leaflet__prebuild__-DARUoA03.js +1 -0
  51. package/admin/custom/assets/hostInit-DJx2uXXy.js +1 -0
  52. package/admin/custom/assets/index-uEKAoVT7.js +1 -0
  53. package/admin/custom/assets/lib-Yj8cfN0A.js +3 -0
  54. package/admin/custom/assets/mf-entry-bootstrap-0-77793feb.js +36 -0
  55. package/admin/custom/assets/rolldown-runtime-BcKkbAw3.js +1 -0
  56. package/admin/custom/assets/setYear-DJ9FbdkO.js +1 -0
  57. package/admin/custom/assets/virtualExposes-CxDjLoYu.js +1 -0
  58. package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-BU-ugy_7.js +1 -0
  59. package/admin/custom/assets/virtual_mf-exposes-ssr___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-BEfZbrf7.js +2 -0
  60. package/admin/custom/assets/virtual_mf-exposes___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-CTeZ0Jpm.js +2 -0
  61. package/admin/custom/assets/vite-preload-helper-B7qeedMF.js +1 -0
  62. package/admin/custom/customComponents.js +1 -1
  63. package/admin/jsonConfig.json +1 -1
  64. package/admin/mf-manifest.json +1 -1
  65. package/admin/mf-stats.json +1 -0
  66. package/admin/remoteEntry.js +1 -1
  67. package/admin/tab.html +12 -17
  68. package/build/lib/debugger.js +1 -1
  69. package/build/lib/debugger.js.map +1 -1
  70. package/build/lib/eventObj.js.map +1 -1
  71. package/build/lib/inspect.js.map +1 -1
  72. package/build/lib/javascript.d.ts +18 -19
  73. package/build/lib/nodeModulesManagement.js +3 -1
  74. package/build/lib/nodeModulesManagement.js.map +1 -1
  75. package/build/lib/protectFs.js.map +1 -1
  76. package/build/lib/sandbox.js +104 -43
  77. package/build/lib/sandbox.js.map +1 -1
  78. package/build/lib/scheduler.js.map +1 -1
  79. package/build/lib/tools.js +1 -1
  80. package/build/lib/tools.js.map +1 -1
  81. package/build/lib/typescriptSettings.js +16 -10
  82. package/build/lib/typescriptSettings.js.map +1 -1
  83. package/build/lib/typescriptTools.js +2 -2
  84. package/build/lib/typescriptTools.js.map +1 -1
  85. package/build/main.js +41 -29
  86. package/build/main.js.map +1 -1
  87. package/build/src/lib/aiProviderResolver.js +107 -0
  88. package/build/src/lib/aiProviderResolver.js.map +1 -0
  89. package/build/src/lib/anthropicAdapter.js +175 -0
  90. package/build/src/lib/anthropicAdapter.js.map +1 -0
  91. package/build/src/lib/consts.js +346 -0
  92. package/build/src/lib/consts.js.map +1 -0
  93. package/build/src/lib/convert.js +121 -0
  94. package/build/src/lib/convert.js.map +1 -0
  95. package/build/src/lib/crypto.js +32 -0
  96. package/build/src/lib/crypto.js.map +1 -0
  97. package/build/src/lib/debug.js +163 -0
  98. package/build/src/lib/debug.js.map +1 -0
  99. package/build/src/lib/debugger.js +1135 -0
  100. package/build/src/lib/debugger.js.map +1 -0
  101. package/build/src/lib/eventObj.js +194 -0
  102. package/build/src/lib/eventObj.js.map +1 -0
  103. package/build/src/lib/inspect.js +728 -0
  104. package/build/src/lib/inspect.js.map +1 -0
  105. package/build/src/lib/mirror.js +634 -0
  106. package/build/src/lib/mirror.js.map +1 -0
  107. package/build/src/lib/nodeModulesManagement.js +26 -0
  108. package/build/src/lib/nodeModulesManagement.js.map +1 -0
  109. package/build/src/lib/patternCompareFunctions.js +293 -0
  110. package/build/src/lib/patternCompareFunctions.js.map +1 -0
  111. package/build/src/lib/protectFs.js +554 -0
  112. package/build/src/lib/protectFs.js.map +1 -0
  113. package/build/src/lib/sandbox.js +4897 -0
  114. package/build/src/lib/sandbox.js.map +1 -0
  115. package/build/src/lib/scheduler.js +555 -0
  116. package/build/src/lib/scheduler.js.map +1 -0
  117. package/build/src/lib/tools.js +188 -0
  118. package/build/src/lib/tools.js.map +1 -0
  119. package/build/src/lib/typescriptSettings.js +39 -0
  120. package/build/src/lib/typescriptSettings.js.map +1 -0
  121. package/build/src/lib/typescriptTools.js +435 -0
  122. package/build/src/lib/typescriptTools.js.map +1 -0
  123. package/build/src/lib/utils.js +66 -0
  124. package/build/src/lib/utils.js.map +1 -0
  125. package/build/src/lib/words.js +76 -0
  126. package/build/src/lib/words.js.map +1 -0
  127. package/build/src/main.js +3414 -0
  128. package/build/src/main.js.map +1 -0
  129. package/build/types.d.ts +6 -14
  130. package/io-package.json +28 -28
  131. package/package.json +16 -17
  132. package/admin/assets/AiChatPanel-BvND3KNP.js +0 -317
  133. package/admin/assets/AiDatapointProvider-B0i3I5Fm.js +0 -2
  134. package/admin/assets/AiDiffView-RPozjjHf.js +0 -1
  135. package/admin/assets/AiInlineProvider-DkgjVSFQ.js +0 -7
  136. package/admin/assets/Save-CkuNSiWL.js +0 -1
  137. package/admin/assets/ScriptEditor-1BwI9a_X.js +0 -2
  138. package/admin/assets/ScriptEditorVanillaMonaco-BPK75VNu.js +0 -3
  139. package/admin/assets/applyCodeEdit-BdRnbz2g.js +0 -1
  140. package/admin/assets/createSvgIcon-DYs_tNrE.js +0 -8
  141. package/admin/assets/cronHoverProvider-Bg0Vz-1E.js +0 -2
  142. package/admin/assets/hostInit-LzITLWDa.js +0 -1
  143. package/admin/assets/index-45IwpC7_.js +0 -1
  144. package/admin/assets/index-BCK6q-N6.css +0 -1
  145. package/admin/assets/index-BTsjunTt.css +0 -1
  146. package/admin/assets/index-Be9Zg6aF.js +0 -990
  147. package/admin/assets/index-BkyLyaYT.js +0 -8
  148. package/admin/assets/index-CVZSzCXy.js +0 -1
  149. package/admin/assets/index-CxRhXAwi.js +0 -1267
  150. package/admin/assets/index-DUMiVB6k.js +0 -16
  151. package/admin/assets/index-Dsh1HfIY.js +0 -1
  152. package/admin/assets/index-dN73sbyQ.js +0 -193
  153. package/admin/assets/index-fS-54-pB.js +0 -1
  154. package/admin/assets/index-wHNMOf-c.js +0 -5
  155. package/admin/assets/inheritsLoose-CIXm_zPk.js +0 -29
  156. package/admin/assets/inlineChatWidget-Cu6rb4Ar.js +0 -2
  157. package/admin/assets/inlineDiffController-DBLpPOe2.js +0 -16
  158. package/admin/assets/iobroker_javascript__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-DkBjPSMw.js +0 -1
  159. package/admin/assets/iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js +0 -1
  160. package/admin/assets/iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js +0 -1
  161. package/admin/assets/iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js +0 -1
  162. package/admin/assets/iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js +0 -1
  163. package/admin/assets/iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs-DeVAS-oa.js +0 -1
  164. package/admin/assets/iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-RQRRZMX5.js +0 -1
  165. package/admin/assets/localSharedImportMap-Cs4ibnCv.js +0 -1
  166. package/admin/assets/preload-helper-BDBacUwf.js +0 -1
  167. package/admin/assets/stateHoverProvider-dvzAyUDH.js +0 -9
  168. package/admin/assets/useTheme-DuTJsNQ-.js +0 -1
  169. package/admin/assets/virtualExposes-BPsCufin.js +0 -1
  170. package/admin/assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-Dus28I2g.js +0 -8
  171. package/admin/custom/assets/Components-BOms95_F.css +0 -1
  172. package/admin/custom/assets/Components-CGiJE5Zh.js +0 -1
  173. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_emotion_mf_1_react__loadShare__.mjs-sg07E3QA.js +0 -1
  174. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_emotion_mf_1_styled__loadShare__.mjs-CwjI4A-J.js +0 -1
  175. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-B7D2xOvV.js +0 -1
  176. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.mjs-ClsgYnEX.js +0 -1
  177. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_mui_mf_1_icons_mf_2_material__loadShare__.mjs-B551AMx-.js +0 -1
  178. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-KsT5vKjV.js +0 -1
  179. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.mjs-DgHZUNxn.js +0 -1
  180. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__leaflet__loadShare__.mjs-BYONkEgA.js +0 -1
  181. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs-BW9Qbxx5.js +0 -1
  182. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs_commonjs-proxy-2W2BYT2K.js +0 -1
  183. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react_mf_2_dom__loadShare__.mjs-CL--xmjC.js +0 -1
  184. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-D8zcZsJo.js +0 -1
  185. package/admin/custom/assets/DefaultPropsProvider-CfKHPa-G.js +0 -1
  186. package/admin/custom/assets/TextField-CxPfV5Sr.js +0 -139
  187. package/admin/custom/assets/ThemeProvider-DSTCckLJ.js +0 -29
  188. package/admin/custom/assets/blue-CagzI6CQ.js +0 -1
  189. package/admin/custom/assets/createSvgIcon-b2B2NI3g.js +0 -1
  190. package/admin/custom/assets/createTheme-MsdB8zt7.js +0 -8
  191. package/admin/custom/assets/defaultTheme-CmVP-QNF.js +0 -1
  192. package/admin/custom/assets/emotion-cache.browser.esm-BgJfNZJN.js +0 -1
  193. package/admin/custom/assets/emotion-react.browser.esm-chZAeh_-.js +0 -1
  194. package/admin/custom/assets/emotion-serialize.esm-BUa21YfQ.js +0 -1
  195. package/admin/custom/assets/emotion-styled.browser.esm-Yi13plpH.js +0 -1
  196. package/admin/custom/assets/emotion-use-insertion-effect-with-fallbacks.browser.esm-CEPeBbh9.js +0 -1
  197. package/admin/custom/assets/extends-CF3RwP-h.js +0 -1
  198. package/admin/custom/assets/hostInit-iUL-wyj1.js +0 -1
  199. package/admin/custom/assets/index-17vbGv00.js +0 -1
  200. package/admin/custom/assets/index-B5DqCD_a.js +0 -1
  201. package/admin/custom/assets/index-BVOepGI5.js +0 -1
  202. package/admin/custom/assets/index-Bvwv5H7k.js +0 -1
  203. package/admin/custom/assets/index-C8_qJ4Y6.js +0 -1523
  204. package/admin/custom/assets/index-CzRngQHl.js +0 -31
  205. package/admin/custom/assets/index-DLNtxshy.js +0 -1
  206. package/admin/custom/assets/index-DSGXVHGh.js +0 -964
  207. package/admin/custom/assets/index-DV76KW3-.js +0 -7
  208. package/admin/custom/assets/index-D_5kZmfw.js +0 -1
  209. package/admin/custom/assets/index-DlQbqHom.js +0 -8
  210. package/admin/custom/assets/index-DpJ18x6R.js +0 -1
  211. package/admin/custom/assets/index-FTmk0JJx.js +0 -55
  212. package/admin/custom/assets/isSameWeek-DDsSIa_t.js +0 -1
  213. package/admin/custom/assets/jsx-runtime-BplTyRFk.js +0 -1
  214. package/admin/custom/assets/leaflet-src-B472P7Y1.js +0 -1
  215. package/admin/custom/assets/localSharedImportMap-C-8wOKN2.js +0 -1
  216. package/admin/custom/assets/preload-helper-BDBacUwf.js +0 -1
  217. package/admin/custom/assets/useTheme-BV4xOYIL.js +0 -1
  218. package/admin/custom/assets/useTheme-ldICnlmf.js +0 -1
  219. package/admin/custom/assets/virtualExposes-D402kVGY.js +0 -2
  220. package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-CO2hfDx_.js +0 -8
@@ -0,0 +1,634 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Mirror = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const MODE_0777 = 511;
7
+ class Mirror {
8
+ adapter;
9
+ diskRoot;
10
+ from;
11
+ lastSyncID;
12
+ log;
13
+ watchedFolder = {};
14
+ diskList;
15
+ dbList = {};
16
+ ready = false;
17
+ constructor(options) {
18
+ if (!options.adapter) {
19
+ throw new Error('No adapter defined');
20
+ }
21
+ this.adapter = options.adapter;
22
+ this.diskRoot = (0, node_path_1.normalize)(options.diskRoot || '').replace(/\\/g, '/');
23
+ this.from = `system.adapter.${this.adapter.namespace}`;
24
+ this.lastSyncID = `${this.from}.lastSync`;
25
+ this.diskList = {};
26
+ if (options.log) {
27
+ this.log = options.log;
28
+ this.log.log = this.log.log || ((text) => console.log(text));
29
+ }
30
+ else {
31
+ this.log = {
32
+ silly: text => console.log(text),
33
+ debug: text => console.log(text),
34
+ info: text => console.log(text),
35
+ log: text => console.log(text),
36
+ warn: text => console.warn(text),
37
+ error: text => console.error(text),
38
+ };
39
+ }
40
+ if (!options.diskRoot?.trim() || this.adapter.namespace !== 'javascript.0') {
41
+ // only instance 0 can sync objects
42
+ return;
43
+ }
44
+ if (!(0, node_fs_1.existsSync)(this.diskRoot)) {
45
+ try {
46
+ (0, node_fs_1.mkdirSync)(this.diskRoot);
47
+ }
48
+ catch (err) {
49
+ this.log.error(`Cannot create directory ${this.diskRoot}: ${err}`);
50
+ return;
51
+ }
52
+ }
53
+ this.diskList = this.scanDisk();
54
+ this.checkLastSyncObject(lastSyncTime => this.scanDB(list => {
55
+ this.dbList = list;
56
+ this.sync(lastSyncTime);
57
+ this.adapter.setForeignState(this.lastSyncID, Date.now(), true);
58
+ this.ready = true;
59
+ // monitor all folders
60
+ this.watchFolders(this.diskRoot);
61
+ }));
62
+ }
63
+ watchFolders(root_) {
64
+ root_ = root_.endsWith('/') ? root_ : `${root_}/`;
65
+ // ignore all .xxx folders, like ".git", ".idea", so users may not have scripts starting with "."
66
+ try {
67
+ const files = (0, node_fs_1.readdirSync)(root_).filter(name => !name.startsWith('.'));
68
+ files.forEach(file => {
69
+ const name = (0, node_path_1.join)(root_, file).replace(/\\/g, '/');
70
+ const stat = (0, node_fs_1.statSync)(name);
71
+ if (stat.isDirectory()) {
72
+ this.watchFolders(name);
73
+ }
74
+ else {
75
+ const lstat = (0, node_fs_1.lstatSync)(name);
76
+ if (!lstat.isSymbolicLink()) {
77
+ return;
78
+ }
79
+ const linkTarget = (0, node_fs_1.realpathSync)(name);
80
+ this.log.info(`Watch symlinked file ${name} -> ${linkTarget}`);
81
+ (0, node_fs_1.watch)(linkTarget, (eventType /*, _filename*/) => {
82
+ // Pretend the symlink source was changed.
83
+ this.log.debug(`File ${name} ${eventType}`);
84
+ this.onFileChange(eventType, name);
85
+ });
86
+ }
87
+ });
88
+ }
89
+ catch (err) {
90
+ return this.log.warn(`Error while trying to watch folder ${root_}: ${err}`);
91
+ }
92
+ if (!this.watchedFolder[root_]) {
93
+ this.log.info(`Watch ${root_}`);
94
+ try {
95
+ this.watchedFolder[root_] = (0, node_fs_1.watch)(root_, (eventType, fileName) => {
96
+ this.log.debug(`File ${root_}${fileName} ${eventType}`);
97
+ this.onFileChange(eventType, root_ + fileName);
98
+ });
99
+ }
100
+ catch (err) {
101
+ this.log.error(`Could not watch folder ${root_}: ${err.message}`);
102
+ this.log.error(`Please check that no other processes change data in the mirror directory!`);
103
+ }
104
+ this.watchedFolder[root_].on('error', () => {
105
+ this.log.debug(`Folder ${root_} was deleted`);
106
+ try {
107
+ this.watchedFolder[root_] && this.watchedFolder[root_].close();
108
+ }
109
+ catch {
110
+ // ignore error
111
+ }
112
+ if (this.watchedFolder[root_]) {
113
+ delete this.watchedFolder[root_];
114
+ }
115
+ });
116
+ }
117
+ }
118
+ checkLastSyncObject(cb) {
119
+ void this.adapter.getForeignObject(this.lastSyncID, (_err, obj) => {
120
+ if (!obj) {
121
+ // create variable
122
+ const obj = {
123
+ _id: this.lastSyncID,
124
+ common: {
125
+ name: 'Last sync time',
126
+ type: 'number',
127
+ role: 'timestamp',
128
+ write: false,
129
+ min: 0,
130
+ read: true,
131
+ },
132
+ type: 'state',
133
+ native: {},
134
+ };
135
+ this.adapter.setForeignObject(this.lastSyncID, obj, () => this.adapter.setForeignState(this.lastSyncID, 0, true, () => cb?.(0)));
136
+ }
137
+ else {
138
+ void this.adapter.getForeignState(this.lastSyncID, (_err, state) => cb?.(state?.val));
139
+ }
140
+ });
141
+ }
142
+ static getDBFolder(id) {
143
+ const parts = id.split('.');
144
+ parts.pop();
145
+ return parts.join('.');
146
+ }
147
+ static isBlockly(data) {
148
+ const pos = data.lastIndexOf('\n');
149
+ if (pos !== -1) {
150
+ data = data.substring(pos + 1);
151
+ if (data[0] === '/' && data[1] === '/') {
152
+ data = Buffer.from(data.substring(2), 'base64').toString('utf8');
153
+ if (data.startsWith('%3Cxml')) {
154
+ return true;
155
+ }
156
+ }
157
+ }
158
+ return false;
159
+ }
160
+ static isRules(data) {
161
+ const pos = data.lastIndexOf('\n');
162
+ if (pos !== -1) {
163
+ data = data.substring(pos + 1);
164
+ if (data.startsWith('//{"') && data.endsWith('}')) {
165
+ return true;
166
+ }
167
+ }
168
+ return false;
169
+ }
170
+ static detectType(fileName, data) {
171
+ if (fileName.endsWith('.ts')) {
172
+ return 'TypeScript/ts';
173
+ }
174
+ return Mirror.isBlockly(data) ? 'Blockly' : Mirror.isRules(data) ? 'Rules' : 'Javascript/js';
175
+ }
176
+ updateFolderTime(id) {
177
+ this.dbList[id].ts = Date.now();
178
+ this.dbList[id].from = this.from;
179
+ void this.adapter.setForeignObject(id, this.dbList[id]);
180
+ }
181
+ _getDiskPath(pathDisk) {
182
+ return (0, node_path_1.join)(this.diskRoot, pathDisk.join('/')).replace(/\\/g, '/');
183
+ }
184
+ static _getDbPath(pathDB) {
185
+ if (!pathDB || !pathDB.length) {
186
+ return 'script.js';
187
+ }
188
+ return `script.js.${pathDB.join('.')}`;
189
+ }
190
+ _getFilesInPath(pathDisk) {
191
+ pathDisk = pathDisk.substring(this.diskRoot.length + 1);
192
+ const id = pathDisk.replace(/\./g, '\\.').replace(/[/\\]/g, '\\.');
193
+ const reg = new RegExp(`script\\.js${id ? `.${id}` : ''}\\.[^.]+$`);
194
+ return Object.keys(this.diskList)
195
+ .filter(file => reg.test(file))
196
+ .map(id => id.split('.').pop() || '');
197
+ }
198
+ _getObjectsInPath(pathDB) {
199
+ const reg = new RegExp(`${pathDB.replace(/\./g, '\\.')}\\.[^.]+$`);
200
+ return Object.keys(this.dbList)
201
+ .filter(id => reg.test(id))
202
+ .map(id => id.split('.').pop() || '');
203
+ }
204
+ /**
205
+ * Write file to disk, synchron, catch (and print) error.
206
+ *
207
+ * @param id of script
208
+ * @returns true if write was successful
209
+ */
210
+ _writeFile(id) {
211
+ const diskListEntry = this.diskList[id];
212
+ try {
213
+ //check if the directory exists and create if not:
214
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(diskListEntry.name), { recursive: true, mode: MODE_0777 });
215
+ (0, node_fs_1.writeFileSync)(diskListEntry.name, diskListEntry.source, { mode: MODE_0777 });
216
+ diskListEntry.ts = Date.now();
217
+ return true;
218
+ }
219
+ catch (err) {
220
+ this.log.error(`Cannot write file ${diskListEntry ? diskListEntry.name : id}: ${err}`);
221
+ return false;
222
+ }
223
+ }
224
+ sync(lastSyncTime, pathDisk, pathDB) {
225
+ lastSyncTime = lastSyncTime || 0;
226
+ pathDisk = pathDisk || [];
227
+ pathDB = pathDB || [];
228
+ const dirDisk = this._getDiskPath(pathDisk);
229
+ const dirDB = Mirror._getDbPath(pathDB);
230
+ const files = this._getFilesInPath(dirDisk);
231
+ const objects = this._getObjectsInPath(dirDB);
232
+ for (let o = objects.length - 1; o >= 0; o--) {
233
+ // if folder
234
+ if (this.dbList[`${dirDB}.${objects[o]}`] && this.dbList[`${dirDB}.${objects[o]}`].type === 'channel') {
235
+ // dive into
236
+ const nextPathDisk = JSON.parse(JSON.stringify(pathDisk));
237
+ nextPathDisk.push(objects[o]);
238
+ const nextPathDB = JSON.parse(JSON.stringify(pathDB));
239
+ nextPathDB.push(objects[o]);
240
+ objects.splice(o, 1);
241
+ this.sync(lastSyncTime, nextPathDisk, nextPathDB);
242
+ }
243
+ else {
244
+ // try to find this DB script on disk
245
+ for (let f = files.length - 1; f >= 0; f--) {
246
+ if (objects[o] === files[f]) {
247
+ const id = `${dirDB}.${objects[o]}`;
248
+ if (!this.diskList[id]) {
249
+ continue;
250
+ }
251
+ if (!this.dbList[id].ts ||
252
+ (this.dbList[id].ts > this.diskList[id].ts &&
253
+ this.dbList[id].ts - this.diskList[id].ts > 2000)) {
254
+ // copy text to file
255
+ this.dbList[id].ts = Date.now();
256
+ this.diskList[id].source = this.dbList[id].common.source;
257
+ this.log.debug(`Update disk with ${this.diskList[id].name}`);
258
+ this._writeFile(id);
259
+ }
260
+ else if (this.dbList[id].ts && this.diskList[id].ts - this.dbList[id].ts > 2000) {
261
+ // copy file to DB
262
+ this.dbList[id].common.source = this.diskList[id].source;
263
+ this.dbList[id].ts = this.diskList[id].ts;
264
+ this.dbList[id].from = this.from;
265
+ this.log.debug(`Update DB with ${id}`);
266
+ void this.adapter.setForeignObject(id, this.dbList[id]);
267
+ }
268
+ files.splice(f, 1);
269
+ objects.splice(o, 1);
270
+ break;
271
+ }
272
+ }
273
+ }
274
+ }
275
+ // go through objects, that does not exist on disk
276
+ for (let o = objects.length - 1; o >= 0; o--) {
277
+ const fileName = this._scriptId2FileName(`${dirDB}.${objects[o]}`, this.dbList[`${dirDB}.${objects[o]}`].common.engineType);
278
+ this.log.info(`Created script file on disk ${fileName}`);
279
+ const f = `script.js.${fileName
280
+ .substring(this.diskRoot.length)
281
+ .replace(/[\\/]/g, '.')
282
+ .replace(/\.js$|\.ts$/g, '')}`;
283
+ this.diskList[f] = { name: fileName, source: this.dbList[`${dirDB}.${objects[o]}`].common.source, ts: 0 };
284
+ this._writeFile(f);
285
+ }
286
+ // go through files, that does not exist in DB
287
+ for (let f = files.length - 1; f >= 0; f--) {
288
+ // read creation time
289
+ const id = `${dirDB}.${files[f]}`;
290
+ if (this.diskList[id] && this.diskList[id].ts > lastSyncTime) {
291
+ // The file was created after last sync. So create it in DB too
292
+ this.dbList[id] = {
293
+ _id: id,
294
+ common: {
295
+ name: files[f],
296
+ enabled: false,
297
+ source: this.diskList[id].source,
298
+ engine: `system.adapter.${this.adapter.namespace}`,
299
+ engineType: Mirror.detectType(this.diskList[id].name, this.diskList[id].source),
300
+ debug: false,
301
+ verbose: false,
302
+ },
303
+ type: 'script',
304
+ ts: this.diskList[id].ts,
305
+ native: {},
306
+ };
307
+ this.log.debug(`Create script in DB with ${id}`);
308
+ // ensure that every script has a folder and if not, then create it
309
+ this._checkIfAllFoldersAreExist(id, this.dbList);
310
+ void this.adapter.setForeignObject(id, this.dbList[id]);
311
+ }
312
+ else {
313
+ this.log.warn(`Please delete file ${(0, node_path_1.join)(dirDisk, files[f])}`);
314
+ }
315
+ }
316
+ }
317
+ _scriptId2FileName(id, type) {
318
+ id = id.substring('script.js.'.length);
319
+ const parts = id.split('.');
320
+ return ((0, node_path_1.join)(this.diskRoot, parts.join('/')).replace(/\\/g, '/') +
321
+ (type && type.toLowerCase() === 'typescript/ts' ? '.ts' : '.js'));
322
+ }
323
+ _fileName2scriptId(file) {
324
+ file = file.substring(this.diskRoot.length).replace(/\.js$/g, '').replace(/\.ts$/g, '');
325
+ const parts = file.replace(/\\/g, '/').split('/');
326
+ if (!parts[0] && parts.length) {
327
+ parts.shift();
328
+ }
329
+ return `script.js.${parts.join('.')}`;
330
+ }
331
+ removeScriptsInFolder(folder) {
332
+ // get all files in this folder
333
+ const folderId = this._fileName2scriptId(folder);
334
+ for (const id in this.dbList) {
335
+ if (Object.prototype.hasOwnProperty.call(this.dbList, id) &&
336
+ (id.startsWith(folderId) || id === folderId.replace(/\.$/, ''))) {
337
+ // delete it
338
+ if (this.dbList[id]) {
339
+ this.log.debug(`Delete script ${id} in DB`);
340
+ delete this.dbList[id];
341
+ this.adapter.delForeignObject(id);
342
+ }
343
+ if (this.diskList[id]) {
344
+ delete this.diskList[id];
345
+ }
346
+ }
347
+ }
348
+ }
349
+ onFileChange(event, file) {
350
+ if (!this.ready) {
351
+ return;
352
+ }
353
+ let stats;
354
+ const exists = (0, node_fs_1.existsSync)(file);
355
+ if (exists) {
356
+ try {
357
+ stats = (0, node_fs_1.statSync)(file);
358
+ }
359
+ catch (err) {
360
+ this.log.error(`Cannot read file ${file}: ${err}`);
361
+ }
362
+ if (stats?.isDirectory()) {
363
+ file = file.endsWith('/') ? file : `${file}/`;
364
+ if (exists) {
365
+ !this.watchedFolder[file] && this.watchFolders(file);
366
+ try {
367
+ // scan folder anew
368
+ const files = (0, node_fs_1.readdirSync)(file).filter(name => !name.startsWith('.'));
369
+ // update all files in this directory
370
+ files.forEach(f => this.onFileChange('change', (0, node_path_1.join)(file, f).replace(/\\/g, '/')));
371
+ }
372
+ catch (err) {
373
+ this.log.error(`Error while checking files in directory ${file}: ${err}`);
374
+ }
375
+ }
376
+ else {
377
+ if (this.watchedFolder[file]) {
378
+ this.watchedFolder[file].close();
379
+ delete this.watchedFolder[file];
380
+ }
381
+ this.removeScriptsInFolder(file);
382
+ }
383
+ return;
384
+ }
385
+ }
386
+ else if (this.watchedFolder[file]) {
387
+ if (!exists) {
388
+ try {
389
+ if (this.watchedFolder[file]) {
390
+ this.watchedFolder[file].close();
391
+ delete this.watchedFolder[file];
392
+ }
393
+ }
394
+ catch {
395
+ // ignore error
396
+ }
397
+ this.removeScriptsInFolder(file);
398
+ }
399
+ return;
400
+ }
401
+ else if (this.watchedFolder[`${file}/`]) {
402
+ if (!exists) {
403
+ file = `${file}/`;
404
+ // delete all files in this folder
405
+ try {
406
+ if (this.watchedFolder[file]) {
407
+ this.watchedFolder[file].close();
408
+ delete this.watchedFolder[file];
409
+ }
410
+ }
411
+ catch {
412
+ // ignore error
413
+ }
414
+ this.removeScriptsInFolder(file);
415
+ }
416
+ return;
417
+ }
418
+ if (!file.match(/\.ts$|\.js$/)) {
419
+ return;
420
+ }
421
+ const id = this._fileName2scriptId(file);
422
+ if (exists && (event === 'change' || event === 'create')) {
423
+ try {
424
+ stats = stats || (0, node_fs_1.statSync)(file);
425
+ const source = (0, node_fs_1.readFileSync)(file).toString();
426
+ const ts = stats?.mtime.getTime() || 0;
427
+ this.diskList[id] = { ts, source, name: file };
428
+ if (this.dbList[id]) {
429
+ if (this.dbList[id].common.source !== source) {
430
+ this.dbList[id].common.source = source;
431
+ this.dbList[id].ts = ts;
432
+ this.log.debug(`Update script ${id} in DB`);
433
+ this.dbList[id].from = this.from;
434
+ void this.adapter.setForeignObject(id, this.dbList[id]);
435
+ }
436
+ else {
437
+ this.dbList[id].ts = ts;
438
+ }
439
+ }
440
+ else {
441
+ this.log.debug(`Create script ${id} in DB`);
442
+ const parts = id.split('.');
443
+ // new script
444
+ this.dbList[id] = {
445
+ _id: id,
446
+ common: {
447
+ name: parts.pop(),
448
+ engineType: Mirror.detectType(file, source),
449
+ source,
450
+ enabled: false,
451
+ engine: `system.adapter.${this.adapter.namespace}`,
452
+ debug: false,
453
+ verbose: false,
454
+ },
455
+ type: 'script',
456
+ native: {},
457
+ ts: ts,
458
+ };
459
+ this._checkIfAllFoldersAreExist(id, this.dbList);
460
+ void this.adapter.setForeignObject(id, this.dbList[id]);
461
+ }
462
+ }
463
+ catch (err) {
464
+ this.log.error(`Cannot read file ${file}: ${err}`);
465
+ }
466
+ }
467
+ else if (event === 'delete' || event === 'rename') {
468
+ // there is a bug: just after creation of a script on disk from ioBroker, "rename" event is generated!
469
+ if (event === 'rename' && this.diskList[id] && Date.now() - this.diskList[id].ts < 200) {
470
+ console.log(`Interval: ${Date.now() - this.diskList[id].ts}`);
471
+ // 'rename' is ignored
472
+ this.log.debug(`Rename event for ${id} is ignored`);
473
+ }
474
+ else {
475
+ if (this.dbList[id]) {
476
+ this.log.debug(`Delete script ${id} in DB`);
477
+ delete this.dbList[id];
478
+ this.adapter.delForeignObject(id);
479
+ }
480
+ if (this.diskList[id]) {
481
+ delete this.diskList[id];
482
+ }
483
+ }
484
+ }
485
+ this.adapter.setForeignState(this.lastSyncID, Date.now(), true);
486
+ }
487
+ onObjectChange(id, obj) {
488
+ if (!this.dbList || !id || !this.ready) {
489
+ return;
490
+ }
491
+ const file = this._scriptId2FileName(id, obj?.common?.engineType);
492
+ if (!obj?.common) {
493
+ // File was deleted
494
+ if (this.dbList[id]) {
495
+ delete this.dbList[id];
496
+ const folderId = Mirror.getDBFolder(id);
497
+ if (this.dbList[folderId]) {
498
+ this.updateFolderTime(folderId);
499
+ }
500
+ if ((0, node_fs_1.existsSync)(file)) {
501
+ try {
502
+ this.log.debug(`Delete ${file} on disk`);
503
+ (0, node_fs_1.unlinkSync)(file);
504
+ }
505
+ catch (err) {
506
+ this.log.error(`Cannot delete ${file}: ${err}`);
507
+ }
508
+ }
509
+ if (this.diskList[id]) {
510
+ delete this.diskList[id];
511
+ }
512
+ }
513
+ }
514
+ else if (obj.type === 'script' && id.startsWith('script.js.')) {
515
+ if (this.dbList[id]) {
516
+ // File changed
517
+ if (this.dbList[id].common.source !== obj.common.source) {
518
+ this.dbList[id] = obj;
519
+ this.log.debug(`Update ${file} on disk`);
520
+ this.diskList[id] = { ts: 0, source: obj.common.source, name: file };
521
+ this._writeFile(id);
522
+ }
523
+ else if (!this.diskList[id] || this.diskList[id].source !== obj.common.source) {
524
+ this.log.debug(`Update ${file} on disk`);
525
+ this.diskList[id] = { ts: 0, source: obj.common.source, name: file };
526
+ this._writeFile(id);
527
+ }
528
+ }
529
+ else {
530
+ // new script
531
+ this.dbList[id] = obj;
532
+ if (!this.diskList[id] || this.diskList[id].source !== obj.common.source) {
533
+ this.log.debug(`Create ${file} on disk`);
534
+ this.diskList[id] = { ts: 0, source: obj.common.source, name: file };
535
+ this._writeFile(id);
536
+ }
537
+ }
538
+ this.dbList[id].ts = Date.now();
539
+ }
540
+ this.adapter.setForeignState(this.lastSyncID, Date.now(), true);
541
+ }
542
+ scanDisk(dirPath, list) {
543
+ dirPath = dirPath || this.diskRoot;
544
+ list = list || {};
545
+ try {
546
+ if (dirPath && !dirPath.startsWith('.') && (0, node_fs_1.existsSync)(dirPath)) {
547
+ const files = (0, node_fs_1.readdirSync)(dirPath).filter(name => !name.startsWith('.'));
548
+ for (const file of files) {
549
+ const fullName = (0, node_path_1.join)(dirPath, file);
550
+ const stats = (0, node_fs_1.statSync)(fullName);
551
+ if (stats.isDirectory()) {
552
+ this.scanDisk(fullName.replace(/\\/g, '/'), list);
553
+ }
554
+ else if (file.match(/\.js$|\.ts$/)) {
555
+ const f = this._fileName2scriptId(fullName);
556
+ list[f] = {
557
+ ts: stats.mtime.getTime(),
558
+ source: (0, node_fs_1.readFileSync)(fullName).toString(),
559
+ name: fullName,
560
+ };
561
+ }
562
+ }
563
+ }
564
+ }
565
+ catch (err) {
566
+ this.log.error(`Error while checking files in directory ${dirPath}: ${err}`);
567
+ }
568
+ return list;
569
+ }
570
+ _checkIfAllFoldersAreExist(id, list) {
571
+ const parts = id.split('.');
572
+ for (let i = parts.length - 1; i >= 2; i--) {
573
+ parts.pop();
574
+ const folderId = parts.join('.');
575
+ if (!list[folderId]) {
576
+ const obj = {
577
+ _id: folderId,
578
+ common: {
579
+ name: parts[parts.length - 1],
580
+ },
581
+ type: 'channel',
582
+ native: {},
583
+ };
584
+ list[folderId] = obj;
585
+ try {
586
+ this.adapter.setForeignObject(folderId, obj, err => {
587
+ if (err) {
588
+ this.log.warn(`Error while checking script folder ${folderId} for id "${id}": ${err}`);
589
+ }
590
+ });
591
+ }
592
+ catch (err) {
593
+ this.log.warn(`Error while checking script folder ${folderId} for id "${id}": ${err}`);
594
+ }
595
+ }
596
+ }
597
+ }
598
+ scanDB(cb) {
599
+ this.adapter.getObjectView('system', 'channel', { startkey: 'script.js.', endkey: 'script.js.\u9999' }, (err, res) => {
600
+ // this is not required, because JavaScript subscribes on ALL objects
601
+ // adapter.subscribeForeignObjects('script.js.*');
602
+ const list = {};
603
+ if (err) {
604
+ this.log.error(`Error while checking scripts channel from objects database: ${err}`);
605
+ }
606
+ if (res?.rows) {
607
+ for (let i = 0; i < res.rows.length; i++) {
608
+ const value = res.rows[i].value;
609
+ if (value?._id && value.common) {
610
+ list[res.rows[i].value._id] = res.rows[i].value;
611
+ }
612
+ }
613
+ }
614
+ this.adapter.getObjectView('script', 'javascript', { startkey: 'script.js.', endkey: 'script.js.\u9999' }, (err, res) => {
615
+ if (err) {
616
+ this.log.error(`Error while checking scripts javascript from objects database: ${err}`);
617
+ }
618
+ if (res?.rows) {
619
+ for (let i = 0; i < res.rows.length; i++) {
620
+ const value = res.rows[i].value;
621
+ if (value?._id && value.common) {
622
+ list[res.rows[i].value._id] = res.rows[i].value;
623
+ // ensure that every script has a folder and if not, then create it
624
+ this._checkIfAllFoldersAreExist(res.rows[i].value._id, list);
625
+ }
626
+ }
627
+ }
628
+ cb?.(list);
629
+ });
630
+ });
631
+ }
632
+ }
633
+ exports.Mirror = Mirror;
634
+ //# sourceMappingURL=mirror.js.map