iobroker.javascript 9.0.17 → 9.1.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 (159) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +17 -10
  3. package/admin/assets/OpenAiDialog-Dx-XNET0.js +13 -0
  4. package/admin/assets/{Save-DXaUpIPM.js → Save-Cld9qv9i.js} +1 -1
  5. package/admin/assets/ScriptEditor-BVaX7Hcs.js +2 -0
  6. package/admin/assets/ScriptEditorVanillaMonaco-yq11eIYC.js +1 -0
  7. package/admin/assets/createSvgIcon-DPvF8xqu.js +8 -0
  8. package/admin/assets/hostInit-LzITLWDa.js +1 -0
  9. package/admin/assets/index-BkyLyaYT.js +8 -0
  10. package/admin/assets/index-CLJ6-h9Q.js +1 -0
  11. package/admin/assets/index-COZhHfBn.js +1230 -0
  12. package/admin/assets/index-CVZSzCXy.js +1 -0
  13. package/admin/assets/index-Cu-TydZj.js +5 -0
  14. package/admin/assets/index-D8iYqogF.js +16 -0
  15. package/admin/assets/index-DlDUIfpA.js +193 -0
  16. package/admin/assets/index-Dnbw7_L3.js +986 -0
  17. package/admin/assets/index-Dsh1HfIY.js +1 -0
  18. package/admin/assets/index-gIA8x-8f.js +1 -0
  19. package/admin/assets/inheritsLoose-B0Ba5G9z.js +29 -0
  20. package/admin/assets/iobroker_javascript__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-DkBjPSMw.js +1 -0
  21. package/admin/assets/iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-QWG5Arqe.js +1 -0
  22. package/admin/assets/iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js +1 -0
  23. package/admin/assets/iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js +1 -0
  24. package/admin/assets/iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js +1 -0
  25. package/admin/assets/iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs-DeVAS-oa.js +1 -0
  26. package/admin/assets/iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-RQRRZMX5.js +1 -0
  27. package/admin/assets/localSharedImportMap-AxgBkrOR.js +1 -0
  28. package/admin/assets/useTheme-hy6f3gra.js +1 -0
  29. package/admin/assets/virtualExposes-BPsCufin.js +1 -0
  30. package/admin/assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-C9suQF96.js +8 -0
  31. package/admin/custom/assets/Components-FfVbavBM.js +1 -0
  32. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-B7D2xOvV.js +1 -0
  33. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.mjs-ClsgYnEX.js +1 -0
  34. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_mui_mf_1_icons_mf_2_material__loadShare__.mjs-B551AMx-.js +1 -0
  35. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-KsT5vKjV.js +1 -0
  36. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.mjs-DgHZUNxn.js +1 -0
  37. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__leaflet__loadShare__.mjs-BYONkEgA.js +1 -0
  38. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs-0SjJESw9.js +1 -0
  39. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs_commonjs-proxy-CInLgMWW.js +1 -0
  40. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react_mf_2_dom__loadShare__.mjs-CL--xmjC.js +1 -0
  41. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-CorOEig8.js +1 -0
  42. package/admin/custom/assets/DefaultPropsProvider-CGb21NGY.js +1 -0
  43. package/admin/custom/assets/TextField-DNzklBSl.js +139 -0
  44. package/admin/custom/assets/ThemeProvider-B4G3jidj.js +29 -0
  45. package/admin/custom/assets/blue-CagzI6CQ.js +1 -0
  46. package/admin/custom/assets/createSvgIcon-ZdrQ8zSU.js +1 -0
  47. package/admin/custom/assets/createTheme-Wd4QxQE0.js +8 -0
  48. package/admin/custom/assets/defaultTheme-F2iJF2G2.js +1 -0
  49. package/admin/custom/assets/hostInit-iUL-wyj1.js +1 -0
  50. package/admin/custom/assets/index-AZB1OHDH.js +1 -0
  51. package/admin/custom/assets/index-Be7j5wvd.js +1523 -0
  52. package/admin/custom/assets/index-BptSiKBK.js +55 -0
  53. package/admin/custom/assets/index-Bvwv5H7k.js +1 -0
  54. package/admin/custom/assets/index-C0RmLaAj.js +1 -0
  55. package/admin/custom/assets/index-CYc31Gwg.js +960 -0
  56. package/admin/custom/assets/index-CmJ8HzSc.js +1 -0
  57. package/admin/custom/assets/index-D0iTiVVG.js +8 -0
  58. package/admin/custom/assets/index-DNdWk-cT.js +1 -0
  59. package/admin/custom/assets/index-Dp7A3XHd.js +7 -0
  60. package/admin/custom/assets/index-YBvFYuP6.js +31 -0
  61. package/admin/custom/assets/index-huvZQhZw.js +1 -0
  62. package/admin/custom/assets/index-iRHaQfi-.js +1 -0
  63. package/admin/custom/assets/isSameWeek-DDsSIa_t.js +1 -0
  64. package/admin/custom/assets/jsx-runtime-DfVU3AZG.js +1 -0
  65. package/admin/custom/assets/leaflet-src-k2rCV-Ix.js +1 -0
  66. package/admin/custom/assets/localSharedImportMap-BRxFonIn.js +1 -0
  67. package/admin/custom/assets/useTheme-BfhDdtAr.js +1 -0
  68. package/admin/custom/assets/useTheme-DWZ6jNyq.js +1 -0
  69. package/admin/custom/assets/virtualExposes-DyedJotb.js +2 -0
  70. package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-BtJxKB87.js +8 -0
  71. package/admin/custom/customComponents.js +1 -2
  72. package/admin/i18n/de.json +10 -1
  73. package/admin/i18n/en.json +10 -1
  74. package/admin/i18n/es.json +10 -1
  75. package/admin/i18n/fr.json +10 -1
  76. package/admin/i18n/it.json +10 -1
  77. package/admin/i18n/nl.json +10 -1
  78. package/admin/i18n/pl.json +10 -1
  79. package/admin/i18n/pt.json +10 -1
  80. package/admin/i18n/ru.json +10 -1
  81. package/admin/i18n/uk.json +10 -1
  82. package/admin/i18n/zh-cn.json +10 -1
  83. package/admin/jsonConfig.json +195 -130
  84. package/admin/mf-manifest.json +1 -1
  85. package/admin/remoteEntry.js +1 -2
  86. package/admin/tab.html +13 -8
  87. package/build/lib/javascript.d.ts +4 -2
  88. package/build/lib/mirror.js +21 -18
  89. package/build/lib/mirror.js.map +1 -1
  90. package/build/lib/nodeModulesManagement.js +3 -2
  91. package/build/lib/nodeModulesManagement.js.map +1 -1
  92. package/build/lib/protectFs.js +27 -12
  93. package/build/lib/protectFs.js.map +1 -1
  94. package/build/lib/sandbox.js +3 -3
  95. package/build/lib/sandbox.js.map +1 -1
  96. package/build/lib/tools.js +7 -2
  97. package/build/lib/tools.js.map +1 -1
  98. package/build/main.js +237 -20
  99. package/build/main.js.map +1 -1
  100. package/build/types.d.ts +6 -1
  101. package/docs/de/README.md +75 -0
  102. package/docs/en/README.md +75 -0
  103. package/io-package.json +32 -28
  104. package/package.json +14 -14
  105. package/admin/assets/OpenAiDialog-BX-z5kNr.js +0 -36
  106. package/admin/assets/ScriptEditor-DhkUQSDz.js +0 -2
  107. package/admin/assets/ScriptEditorVanillaMonaco-CJS71hoK.js +0 -1
  108. package/admin/assets/_commonjsHelpers-Cpj98o6Y.js +0 -1
  109. package/admin/assets/createSvgIcon-DlIk-fDn.js +0 -30
  110. package/admin/assets/hostInit-OBG53iVO.js +0 -2
  111. package/admin/assets/index-BWM5lJbO.js +0 -193
  112. package/admin/assets/index-Br_QjNUk.js +0 -942
  113. package/admin/assets/index-C3P3FHiC.js +0 -16
  114. package/admin/assets/index-Cjl4b70e.js +0 -5
  115. package/admin/assets/index-DBgNhNiJ.js +0 -1294
  116. package/admin/assets/index-DQiceR5U.js +0 -1
  117. package/admin/assets/index-DZ3lKVw8.js +0 -1
  118. package/admin/assets/index-Do-nCdWy.js +0 -9
  119. package/admin/assets/index-DwcZPzOL.js +0 -24
  120. package/admin/assets/index-VCnuVxRc.js +0 -1
  121. package/admin/assets/inheritsLoose-DNrhibGS.js +0 -36
  122. package/admin/assets/iobroker_javascript__loadShare__react__loadShare__-i8pXne9X.js +0 -1
  123. package/admin/assets/iobroker_javascript__mf_v__runtimeInit__mf_v__-DZdFIfoQ.js +0 -5
  124. package/admin/assets/useTheme-DakN8Abq.js +0 -1
  125. package/admin/assets/virtualExposes-BIHI7g3E.js +0 -1
  126. package/admin/custom/assets/Components-DjQ_LxKw.js +0 -1
  127. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__-DaN0pfsw.js +0 -1
  128. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_mui_mf_1_material__loadShare__-BqzgglHd.js +0 -1
  129. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react__loadShare__-BNbscXK6.js +0 -1
  130. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare__react_mf_2_dom__loadShare__-N2_tx_mJ.js +0 -1
  131. package/admin/custom/assets/ConfigCustomJavascriptSet__mf_v__runtimeInit__mf_v__-jdUmHa_i.js +0 -5
  132. package/admin/custom/assets/DefaultPropsProvider-B8ZCC-c2.js +0 -1
  133. package/admin/custom/assets/DefaultPropsProvider-DfdXSIBu.js +0 -1
  134. package/admin/custom/assets/FilledInput-CSjr0QT8.js +0 -2
  135. package/admin/custom/assets/Tabs-CiTQkBjL.js +0 -138
  136. package/admin/custom/assets/ThemeProvider-C50pIiW4.js +0 -29
  137. package/admin/custom/assets/_commonjsHelpers-CE1G-McA.js +0 -1
  138. package/admin/custom/assets/createSvgIcon-C7qUEvjp.js +0 -1
  139. package/admin/custom/assets/createTheme-Bm92JF8u.js +0 -8
  140. package/admin/custom/assets/defaultTheme-BlO0eCf6.js +0 -1
  141. package/admin/custom/assets/hostInit-BJ6gSofk.js +0 -2
  142. package/admin/custom/assets/index-4wMOc304.js +0 -1
  143. package/admin/custom/assets/index-5CTGLw4h.js +0 -55
  144. package/admin/custom/assets/index-BkjEWGjf.js +0 -1
  145. package/admin/custom/assets/index-Bym4WjyH.js +0 -908
  146. package/admin/custom/assets/index-COcxCdeX.js +0 -8
  147. package/admin/custom/assets/index-CnpybLRW.js +0 -1
  148. package/admin/custom/assets/index-Db8nkuMR.js +0 -7
  149. package/admin/custom/assets/index-DcK0RDrH.js +0 -1
  150. package/admin/custom/assets/index-Df6OaCxx.js +0 -1
  151. package/admin/custom/assets/index-Dx7rDE4p.js +0 -1
  152. package/admin/custom/assets/index-t-NMdeH5.js +0 -31
  153. package/admin/custom/assets/index-u8R8UVCf.js +0 -1393
  154. package/admin/custom/assets/jsx-runtime-C1csJtRx.js +0 -1
  155. package/admin/custom/assets/leaflet-src-DpWQqQWv.js +0 -1
  156. package/admin/custom/assets/useEnhancedEffect-aUb-5tTL.js +0 -1
  157. package/admin/custom/assets/useTheme-Cgjfsi-1.js +0 -1
  158. package/admin/custom/assets/useTheme-DFGylj2o.js +0 -1
  159. package/admin/custom/assets/virtualExposes-C_DtjFte.js +0 -2
@@ -133,7 +133,7 @@ export function promisifyNoError(fn: Function, context: any): (...args: any[]) =
133
133
  function hashSource(source) {
134
134
  return (0, node_crypto_1.createHash)('md5').update(source).digest('hex');
135
135
  }
136
- function getHttpRequestConfig(url, options) {
136
+ function getHttpRequestConfig(url, options, allowSelfSignedCerts) {
137
137
  options = options || {};
138
138
  const timeoutMs = options && !isNaN(options.timeout) ? options.timeout : 2000;
139
139
  const config = {
@@ -172,12 +172,17 @@ function getHttpRequestConfig(url, options) {
172
172
  'User-Agent': 'Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/121.0',
173
173
  ...options.headers,
174
174
  };
175
- // Certificate validation
175
+ // Certificate validation: per-request option takes priority, then adapter-level setting
176
176
  if (options && typeof options?.validateCertificate !== 'undefined') {
177
177
  config.httpsAgent = new node_https_1.Agent({
178
178
  rejectUnauthorized: options.validateCertificate,
179
179
  });
180
180
  }
181
+ else if (allowSelfSignedCerts) {
182
+ config.httpsAgent = new node_https_1.Agent({
183
+ rejectUnauthorized: false,
184
+ });
185
+ }
181
186
  return config;
182
187
  }
183
188
  //# sourceMappingURL=tools.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"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","sourcesContent":["// import { readdirSync, statSync } from 'node:fs';\n// import { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { Agent } from 'node:https';\nimport type { AxiosRequestConfig, ResponseType } from 'axios';\n\n/**\n * Tests whether the given variable is a real object and not an Array\n *\n * @param it The variable to test\n */\nexport function isObject(it: any): boolean {\n // This is necessary because:\n // typeof null === 'object'\n // typeof [] === 'object'\n // [] instanceof Object === true\n return Object.prototype.toString.call(it) === '[object Object]';\n}\n\n/**\n * Tests whether the given variable is really an Array\n *\n * @param it The variable to test\n */\nexport function isArray(it: any): boolean {\n return Array.isArray(it);\n}\n\n/**\n * Finds all matches of a regular expression and returns the matched groups\n *\n * @param regex The regular expression to match against the string\n * @param string The string to test\n */\nexport function matchAll(regex: RegExp, string: string): string[][] {\n const ret: string[][] = [];\n let match: RegExpExecArray | null;\n do {\n match = regex.exec(string);\n if (match) {\n ret.push(match.slice(1));\n }\n } while (match);\n\n return ret;\n}\n\n/**\n * Enumerates all files matching a given predicate\n *\n * @param rootDir The directory to start in\n * @param predicate A function that takes a filename and returns true if the file should be included\n */\n/*export function enumFilesRecursiveSync(rootDir: string, predicate: (filename: string) => boolean): string[] {\n const ret: string[] = [];\n try {\n const filesAndDirs = readdirSync(rootDir);\n for (const f of filesAndDirs) {\n const fullPath = join(rootDir, f);\n\n if (statSync(fullPath).isDirectory()) {\n Array.prototype.push.apply(ret, enumFilesRecursiveSync(fullPath, predicate));\n } else if (typeof predicate === 'function' && predicate(fullPath)) {\n ret.push(fullPath);\n }\n }\n } catch (err: unknown) {\n console.error(`Cannot read directory: \"${rootDir}\": ${err as Error}`);\n }\n\n return ret;\n}*/\n\n/**\n * Promisifies a callback-style function with parameters (err, result)\n *\n * @param fn The callback-style function to promisify\n * @param context The value of `this` in the function\n */\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport function promisify(fn: Function, context?: any): (...args: any[]) => Promise<any> {\n return function (...args) {\n // @ts-expect-error We want this behavior\n context = context || this;\n return new Promise((resolve, reject) => {\n try {\n fn.apply(context, [\n ...args,\n (error: Error | string | null, result: null) => {\n if (error) {\n if (typeof error === 'string') {\n return reject(new Error(error));\n }\n return reject(error);\n }\n return resolve(result);\n },\n ]);\n } catch (error: unknown) {\n reject(error as Error);\n }\n });\n };\n}\n\n/**\n * Promisifies a callback-style function without an error parameter\n *\n * @param fn The callback-style function to promisify\n * @param context The value of `this` in the function\n */\n/*\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport function promisifyNoError(fn: Function, context: any): (...args: any[]) => Promise<any> {\n return function (...args) {\n // @ts-expect-error We want this behavior\n context = context || this;\n return new Promise(resolve => {\n try {\n fn.apply(context, [...args, (result: any) => resolve(result)]);\n } catch {\n resolve(null); // what to do in this case??\n }\n });\n };\n}*/\n\n/**\n * Creates an MD5 hash of a script source which can be used to check whether the source of a compiled language changed\n *\n * @param source The source code to hash\n */\nexport function hashSource(source: string | Buffer): string {\n return createHash('md5').update(source).digest('hex');\n}\n\nexport function getHttpRequestConfig(\n url: string,\n options?: {\n timeout?: number;\n responseType?: ResponseType;\n headers?: Record<string, string>;\n basicAuth?: { user: string; password: string } | null;\n bearerAuth?: string;\n validateCertificate?: boolean;\n },\n): AxiosRequestConfig {\n options = options || {};\n const timeoutMs = options && !isNaN(options.timeout as number) ? options.timeout : 2000;\n\n const config: AxiosRequestConfig = {\n method: 'get',\n url,\n validateStatus: (status: number): boolean => status >= 200,\n responseType: options && options.responseType ? options.responseType : 'text',\n responseEncoding: 'utf8',\n timeout: timeoutMs,\n //signal: AbortSignal.timeout(timeoutMs), // connection related timeouts\n };\n\n options.headers = options.headers || {};\n\n if (options && options.basicAuth) {\n config.auth = {\n username: options.basicAuth.user,\n password: options.basicAuth.password,\n };\n } else if (options.bearerAuth) {\n options.headers.Authorization = `Bearer ${options.bearerAuth}`;\n } else {\n const uri = new URL(url);\n if (uri.username && uri.password) {\n const username = decodeURIComponent(uri.username);\n const password = decodeURIComponent(uri.password);\n\n config.url = (config.url || '').replace(`${uri.protocol}//${username}:${password}@`, `${uri.protocol}//`);\n config.auth = {\n username,\n password,\n };\n }\n }\n\n // Set default headers\n config.headers = {\n 'User-Agent': 'Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/121.0',\n ...options.headers,\n };\n\n // Certificate validation\n if (options && typeof options?.validateCertificate !== 'undefined') {\n config.httpsAgent = new Agent({\n rejectUnauthorized: options.validateCertificate,\n });\n }\n\n return config;\n}\n"]}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"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","sourcesContent":["// import { readdirSync, statSync } from 'node:fs';\n// import { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { Agent } from 'node:https';\nimport type { AxiosRequestConfig, ResponseType } from 'axios';\n\n/**\n * Tests whether the given variable is a real object and not an Array\n *\n * @param it The variable to test\n */\nexport function isObject(it: any): boolean {\n // This is necessary because:\n // typeof null === 'object'\n // typeof [] === 'object'\n // [] instanceof Object === true\n return Object.prototype.toString.call(it) === '[object Object]';\n}\n\n/**\n * Tests whether the given variable is really an Array\n *\n * @param it The variable to test\n */\nexport function isArray(it: any): boolean {\n return Array.isArray(it);\n}\n\n/**\n * Finds all matches of a regular expression and returns the matched groups\n *\n * @param regex The regular expression to match against the string\n * @param string The string to test\n */\nexport function matchAll(regex: RegExp, string: string): string[][] {\n const ret: string[][] = [];\n let match: RegExpExecArray | null;\n do {\n match = regex.exec(string);\n if (match) {\n ret.push(match.slice(1));\n }\n } while (match);\n\n return ret;\n}\n\n/**\n * Enumerates all files matching a given predicate\n *\n * @param rootDir The directory to start in\n * @param predicate A function that takes a filename and returns true if the file should be included\n */\n/*export function enumFilesRecursiveSync(rootDir: string, predicate: (filename: string) => boolean): string[] {\n const ret: string[] = [];\n try {\n const filesAndDirs = readdirSync(rootDir);\n for (const f of filesAndDirs) {\n const fullPath = join(rootDir, f);\n\n if (statSync(fullPath).isDirectory()) {\n Array.prototype.push.apply(ret, enumFilesRecursiveSync(fullPath, predicate));\n } else if (typeof predicate === 'function' && predicate(fullPath)) {\n ret.push(fullPath);\n }\n }\n } catch (err: unknown) {\n console.error(`Cannot read directory: \"${rootDir}\": ${err as Error}`);\n }\n\n return ret;\n}*/\n\n/**\n * Promisifies a callback-style function with parameters (err, result)\n *\n * @param fn The callback-style function to promisify\n * @param context The value of `this` in the function\n */\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport function promisify(fn: Function, context?: any): (...args: any[]) => Promise<any> {\n return function (...args) {\n // @ts-expect-error We want this behavior\n context = context || this;\n return new Promise((resolve, reject) => {\n try {\n fn.apply(context, [\n ...args,\n (error: Error | string | null, result: null) => {\n if (error) {\n if (typeof error === 'string') {\n return reject(new Error(error));\n }\n return reject(error);\n }\n return resolve(result);\n },\n ]);\n } catch (error: unknown) {\n reject(error as Error);\n }\n });\n };\n}\n\n/**\n * Promisifies a callback-style function without an error parameter\n *\n * @param fn The callback-style function to promisify\n * @param context The value of `this` in the function\n */\n/*\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport function promisifyNoError(fn: Function, context: any): (...args: any[]) => Promise<any> {\n return function (...args) {\n // @ts-expect-error We want this behavior\n context = context || this;\n return new Promise(resolve => {\n try {\n fn.apply(context, [...args, (result: any) => resolve(result)]);\n } catch {\n resolve(null); // what to do in this case??\n }\n });\n };\n}*/\n\n/**\n * Creates an MD5 hash of a script source which can be used to check whether the source of a compiled language changed\n *\n * @param source The source code to hash\n */\nexport function hashSource(source: string | Buffer): string {\n return createHash('md5').update(source).digest('hex');\n}\n\nexport function getHttpRequestConfig(\n url: string,\n options?: {\n timeout?: number;\n responseType?: ResponseType;\n headers?: Record<string, string>;\n basicAuth?: { user: string; password: string } | null;\n bearerAuth?: string;\n validateCertificate?: boolean;\n },\n allowSelfSignedCerts?: boolean,\n): AxiosRequestConfig {\n options = options || {};\n const timeoutMs = options && !isNaN(options.timeout as number) ? options.timeout : 2000;\n\n const config: AxiosRequestConfig = {\n method: 'get',\n url,\n validateStatus: (status: number): boolean => status >= 200,\n responseType: options && options.responseType ? options.responseType : 'text',\n responseEncoding: 'utf8',\n timeout: timeoutMs,\n //signal: AbortSignal.timeout(timeoutMs), // connection related timeouts\n };\n\n options.headers = options.headers || {};\n\n if (options && options.basicAuth) {\n config.auth = {\n username: options.basicAuth.user,\n password: options.basicAuth.password,\n };\n } else if (options.bearerAuth) {\n options.headers.Authorization = `Bearer ${options.bearerAuth}`;\n } else {\n const uri = new URL(url);\n if (uri.username && uri.password) {\n const username = decodeURIComponent(uri.username);\n const password = decodeURIComponent(uri.password);\n\n config.url = (config.url || '').replace(`${uri.protocol}//${username}:${password}@`, `${uri.protocol}//`);\n config.auth = {\n username,\n password,\n };\n }\n }\n\n // Set default headers\n config.headers = {\n 'User-Agent': 'Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/121.0',\n ...options.headers,\n };\n\n // Certificate validation: per-request option takes priority, then adapter-level setting\n if (options && typeof options?.validateCertificate !== 'undefined') {\n config.httpsAgent = new Agent({\n rejectUnauthorized: options.validateCertificate,\n });\n } else if (allowSelfSignedCerts) {\n config.httpsAgent = new Agent({\n rejectUnauthorized: false,\n });\n }\n\n return config;\n}\n"]}
package/build/main.js CHANGED
@@ -104,7 +104,7 @@ const isCI = !!process.env.CI;
104
104
  // ambient declarations for typescript
105
105
  let tsAmbient;
106
106
  // TypeScript's scripts are only recompiled if their source hash changes.
107
- // If an adapter update fixes the compilation bugs, a user won't notice until the changes and re-saves the script.
107
+ // If an adapter update fixes the compilation bugs, a user won't notice until the changes and re-save the script.
108
108
  // To avoid that, we also include the
109
109
  // adapter version and TypeScript version in the hash
110
110
  const tsSourceHashBase = `versions:adapter=${packageJson.version},typescript=${packageJson.dependencies.typescript}`;
@@ -213,7 +213,7 @@ function formatHoursMinutesSeconds(date) {
213
213
  const s = String(date.getSeconds());
214
214
  return `${h.padStart(2, '0')}:${m.padStart(2, '0')}:${s.padStart(2, '0')}`;
215
215
  }
216
- // Due to a npm bug, virtual-tsc may be hoisted to the top level node_modules but
216
+ // Due to a npm bug, virtual-tsc may be hoisted to the top level node_modules, but
217
217
  // TypeScript may still be in the adapter level (https://npm.community/t/packages-with-peerdependencies-are-incorrectly-hoisted/4794),
218
218
  // so we need to tell virtual-tsc where TypeScript is
219
219
  (0, virtual_tsc_1.setTypeScriptResolveOptions)({
@@ -290,7 +290,7 @@ class JavaScript extends adapter_core_1.Adapter {
290
290
  name: 'javascript', // adapter name
291
291
  useFormatDate: true,
292
292
  /**
293
- * If the JS-Controller catches an unhandled error, this will be called
293
+ * If the JS-Controller catches an unhandled error, this will be called,
294
294
  * so we have a chance to handle it ourselves.
295
295
  */
296
296
  error: (err) => {
@@ -408,6 +408,7 @@ class JavaScript extends adapter_core_1.Adapter {
408
408
  getAbsoluteDefaultDataDir: adapter_core_1.getAbsoluteDefaultDataDir,
409
409
  adapter: this,
410
410
  logError: this.logError.bind(this),
411
+ allowSelfSignedCerts: false,
411
412
  };
412
413
  this.tsServer = new virtual_tsc_1.Server(typescriptSettings_1.tsCompilerOptions, this.tsLog);
413
414
  }
@@ -457,7 +458,7 @@ class JavaScript extends adapter_core_1.Adapter {
457
458
  this.timeSettings.format12 = obj.native.format12 || false;
458
459
  this.timeSettings.leadingZeros = obj.native.leadingZeros === undefined ? true : obj.native.leadingZeros;
459
460
  }
460
- // send changes to disk mirror
461
+ // send changes to the disk mirror
461
462
  this.mirror?.onObjectChange(id, obj);
462
463
  const formerObj = this.objects[id];
463
464
  this.updateObjectContext(id, obj); // Update all Meta object data
@@ -526,7 +527,7 @@ class JavaScript extends adapter_core_1.Adapter {
526
527
  await this.createActiveObject(id, !!obj.common.enabled);
527
528
  await this.createProblemObject(id);
528
529
  if (obj.common.enabled) {
529
- // if enabled => Start script
530
+ // if enabled => Start a script
530
531
  await this.loadScriptById(id);
531
532
  }
532
533
  }
@@ -610,7 +611,7 @@ class JavaScript extends adapter_core_1.Adapter {
610
611
  common: { enabled: state.val },
611
612
  });
612
613
  }
613
- // monitor if adapter is alive and send all subscriptions once more, after adapter goes online
614
+ // monitor if the adapter is alive and send all subscriptions once more, after the adapter goes online
614
615
  if ( /*oldState && */oldState.val === false && state.val && id.endsWith('.alive')) {
615
616
  if (this.adapterSubs[id]) {
616
617
  const parts = id.split('.');
@@ -727,7 +728,7 @@ class JavaScript extends adapter_core_1.Adapter {
727
728
  `javascript.${obj.message.instance}` === this.namespace ||
728
729
  obj.message.instance === this.namespace)) {
729
730
  Object.keys(this.messageBusHandlers).forEach(name => {
730
- // script name could be script.js.xxx or only xxx
731
+ // the script name could be script.js.xxx or only xxx
731
732
  if ((!obj.message.script || obj.message.script === name) &&
732
733
  this.messageBusHandlers[name][obj.message.message]) {
733
734
  this.messageBusHandlers[name][obj.message.message].forEach(handler => {
@@ -903,6 +904,223 @@ class JavaScript extends adapter_core_1.Adapter {
903
904
  }
904
905
  break;
905
906
  }
907
+ case 'chatCompletion': {
908
+ // Proxy chat completion requests to an OpenAI-compatible API endpoint
909
+ if (obj.callback) {
910
+ const baseUrl = (obj.message?.baseUrl || '').trim();
911
+ const apiKey = (obj.message?.apiKey || '').trim();
912
+ const chatModel = (obj.message?.model || '').trim();
913
+ const messages = obj.message?.messages;
914
+ const provider = (obj.message?.provider || 'openai').trim();
915
+ // Anthropic, Gemini, and DeepSeek always require an API key; OpenAI-compatible allows empty key with custom base URL
916
+ if (!apiKey &&
917
+ (provider === 'anthropic' || provider === 'gemini' || provider === 'deepseek' || !baseUrl)) {
918
+ this.sendTo(obj.from, obj.command, { error: 'No API key provided' }, obj.callback);
919
+ break;
920
+ }
921
+ if (!chatModel || !messages) {
922
+ this.sendTo(obj.from, obj.command, { error: 'Model and messages are required' }, obj.callback);
923
+ break;
924
+ }
925
+ let url;
926
+ const chatHeaders = {
927
+ 'Content-Type': 'application/json',
928
+ };
929
+ let bodyObj;
930
+ if (provider === 'anthropic') {
931
+ url = 'https://api.anthropic.com/v1/messages';
932
+ chatHeaders['x-api-key'] = apiKey;
933
+ chatHeaders['anthropic-version'] = '2023-06-01';
934
+ const systemMessages = messages.filter((m) => m.role === 'system');
935
+ const nonSystemMessages = messages.filter((m) => m.role !== 'system');
936
+ const systemText = systemMessages.map((m) => m.content).join('\n\n');
937
+ bodyObj = {
938
+ model: chatModel,
939
+ max_tokens: 8192,
940
+ stream: false,
941
+ ...(systemText ? { system: systemText } : {}),
942
+ messages: nonSystemMessages,
943
+ };
944
+ }
945
+ else if (provider === 'gemini') {
946
+ url = 'https://generativelanguage.googleapis.com/v1beta/openai/chat/completions';
947
+ if (apiKey) {
948
+ chatHeaders.Authorization = `Bearer ${apiKey}`;
949
+ }
950
+ bodyObj = { model: chatModel, messages, stream: false };
951
+ }
952
+ else if (provider === 'deepseek') {
953
+ url = 'https://api.deepseek.com/chat/completions';
954
+ chatHeaders.Authorization = `Bearer ${apiKey}`;
955
+ bodyObj = { model: chatModel, messages, stream: false };
956
+ }
957
+ else {
958
+ url = `${baseUrl || 'https://api.openai.com/v1'}/chat/completions`;
959
+ if (apiKey) {
960
+ chatHeaders.Authorization = `Bearer ${apiKey}`;
961
+ }
962
+ bodyObj = { model: chatModel, messages, stream: false };
963
+ }
964
+ const body = JSON.stringify(bodyObj);
965
+ const bodyBuffer = Buffer.from(body, 'utf8');
966
+ chatHeaders['Content-Length'] = bodyBuffer.length;
967
+ let urlObj;
968
+ try {
969
+ urlObj = new URL(url);
970
+ }
971
+ catch {
972
+ this.sendTo(obj.from, obj.command, { error: `Invalid API URL: ${url}` }, obj.callback);
973
+ break;
974
+ }
975
+ const isHttps = urlObj.protocol === 'https:';
976
+ const requestModule = isHttps ? https : http;
977
+ const req = requestModule.request(url, {
978
+ method: 'POST',
979
+ headers: chatHeaders,
980
+ timeout: 600000,
981
+ ...(isHttps && this.config.allowSelfSignedCerts ? { rejectUnauthorized: false } : {}),
982
+ }, res => {
983
+ let data = '';
984
+ res.on('data', (chunk) => {
985
+ data += chunk.toString();
986
+ });
987
+ res.on('end', () => {
988
+ if (res.statusCode === 200) {
989
+ try {
990
+ const parsed = JSON.parse(data);
991
+ const content = provider === 'anthropic'
992
+ ? parsed.content?.[0]?.text || ''
993
+ : parsed.choices?.[0]?.message?.content || '';
994
+ if (!content) {
995
+ this.sendTo(obj.from, obj.command, { error: 'Empty response from API' }, obj.callback);
996
+ }
997
+ else {
998
+ this.sendTo(obj.from, obj.command, { success: true, content }, obj.callback);
999
+ }
1000
+ }
1001
+ catch {
1002
+ this.sendTo(obj.from, obj.command, { error: 'Invalid JSON response from API' }, obj.callback);
1003
+ }
1004
+ }
1005
+ else {
1006
+ let errorMsg = `API returned status ${res.statusCode}`;
1007
+ try {
1008
+ const parsed = JSON.parse(data);
1009
+ if (parsed.error?.message) {
1010
+ errorMsg = parsed.error.message;
1011
+ }
1012
+ }
1013
+ catch {
1014
+ // ignore parse error
1015
+ }
1016
+ this.sendTo(obj.from, obj.command, { error: errorMsg }, obj.callback);
1017
+ }
1018
+ });
1019
+ });
1020
+ req.on('error', (err) => {
1021
+ this.sendTo(obj.from, obj.command, { error: `Connection failed: ${err.message}` }, obj.callback);
1022
+ });
1023
+ req.on('timeout', () => {
1024
+ req.destroy();
1025
+ this.sendTo(obj.from, obj.command, { error: 'Connection timeout (600s)' }, obj.callback);
1026
+ });
1027
+ req.write(bodyBuffer);
1028
+ req.end();
1029
+ }
1030
+ break;
1031
+ }
1032
+ case 'testApiConnection': {
1033
+ // Test connection to an OpenAI-compatible API endpoint
1034
+ if (obj.callback) {
1035
+ const baseUrl = (obj.message?.baseUrl || '').trim();
1036
+ const apiKey = (obj.message?.apiKey || '').trim();
1037
+ const provider = (obj.message?.provider || 'openai').trim();
1038
+ // Anthropic, Gemini, and DeepSeek always require an API key; OpenAI-compatible allows empty key with custom base URL
1039
+ if (!apiKey &&
1040
+ (provider === 'anthropic' || provider === 'gemini' || provider === 'deepseek' || !baseUrl)) {
1041
+ this.sendTo(obj.from, obj.command, { error: 'No API key provided' }, obj.callback);
1042
+ break;
1043
+ }
1044
+ let url;
1045
+ const testHeaders = {
1046
+ 'Content-Type': 'application/json',
1047
+ };
1048
+ if (provider === 'anthropic') {
1049
+ url = 'https://api.anthropic.com/v1/models';
1050
+ testHeaders['x-api-key'] = apiKey;
1051
+ testHeaders['anthropic-version'] = '2023-06-01';
1052
+ }
1053
+ else if (provider === 'gemini') {
1054
+ url = 'https://generativelanguage.googleapis.com/v1beta/openai/models';
1055
+ if (apiKey) {
1056
+ testHeaders.Authorization = `Bearer ${apiKey}`;
1057
+ }
1058
+ }
1059
+ else if (provider === 'deepseek') {
1060
+ url = 'https://api.deepseek.com/models';
1061
+ testHeaders.Authorization = `Bearer ${apiKey}`;
1062
+ }
1063
+ else {
1064
+ url = `${baseUrl || 'https://api.openai.com/v1'}/models`;
1065
+ if (apiKey) {
1066
+ testHeaders.Authorization = `Bearer ${apiKey}`;
1067
+ }
1068
+ }
1069
+ let urlObj;
1070
+ try {
1071
+ urlObj = new URL(url);
1072
+ }
1073
+ catch {
1074
+ this.sendTo(obj.from, obj.command, { error: `Invalid API URL: ${url}` }, obj.callback);
1075
+ break;
1076
+ }
1077
+ const isHttps = urlObj.protocol === 'https:';
1078
+ const requestModule = isHttps ? https : http;
1079
+ const req = requestModule.request(url, {
1080
+ method: 'GET',
1081
+ headers: testHeaders,
1082
+ timeout: 10000,
1083
+ ...(isHttps && this.config.allowSelfSignedCerts ? { rejectUnauthorized: false } : {}),
1084
+ }, res => {
1085
+ let data = '';
1086
+ res.on('data', (chunk) => {
1087
+ data += chunk.toString();
1088
+ });
1089
+ res.on('end', () => {
1090
+ if (res.statusCode === 200) {
1091
+ try {
1092
+ const parsed = JSON.parse(data);
1093
+ const models = (parsed.data || [])
1094
+ .map((m) => m.id.startsWith('models/') ? m.id.substring(7) : m.id)
1095
+ .sort();
1096
+ this.sendTo(obj.from, obj.command, { success: true, models, count: models.length }, obj.callback);
1097
+ }
1098
+ catch {
1099
+ this.sendTo(obj.from, obj.command, { error: 'Invalid JSON response from API' }, obj.callback);
1100
+ }
1101
+ }
1102
+ else if (res.statusCode === 401) {
1103
+ this.sendTo(obj.from, obj.command, { error: 'Invalid API key (401)' }, obj.callback);
1104
+ }
1105
+ else if (res.statusCode === 403) {
1106
+ this.sendTo(obj.from, obj.command, { error: 'Access denied (403)' }, obj.callback);
1107
+ }
1108
+ else {
1109
+ this.sendTo(obj.from, obj.command, { error: `API returned status ${res.statusCode}` }, obj.callback);
1110
+ }
1111
+ });
1112
+ });
1113
+ req.on('error', (err) => {
1114
+ this.sendTo(obj.from, obj.command, { error: `Connection failed: ${err.message}` }, obj.callback);
1115
+ });
1116
+ req.on('timeout', () => {
1117
+ req.destroy();
1118
+ this.sendTo(obj.from, obj.command, { error: 'Connection timeout (10s)' }, obj.callback);
1119
+ });
1120
+ req.end();
1121
+ }
1122
+ break;
1123
+ }
906
1124
  case 'prettier': {
907
1125
  // Format the code with Prettier
908
1126
  if (obj.message && typeof obj.message.code === 'string') {
@@ -1058,10 +1276,9 @@ class JavaScript extends adapter_core_1.Adapter {
1058
1276
  await this.dayTimeSchedules();
1059
1277
  await this.sunTimeSchedules();
1060
1278
  await this.timeSchedule();
1061
- // Warning. It could have a side effect in compact mode, so all adapters will accept self-signed certificates
1062
- if (this.config.allowSelfSignedCerts) {
1063
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
1064
- }
1279
+ // Store allowSelfSignedCerts on the context, so sandbox HTTP functions can use it
1280
+ // without setting the global process.env.NODE_TLS_REJECT_UNAUTHORIZED (which affects all adapters in compact mode)
1281
+ this.context.allowSelfSignedCerts = this.config.allowSelfSignedCerts;
1065
1282
  const doc = await this.getObjectViewAsync('script', 'javascript', {});
1066
1283
  if (doc?.rows?.length) {
1067
1284
  // assemble global script
@@ -1180,7 +1397,7 @@ class JavaScript extends adapter_core_1.Adapter {
1180
1397
  }
1181
1398
  }
1182
1399
  }
1183
- if (this.config.mirrorPath) {
1400
+ if (this.config.mirrorPath?.trim()) {
1184
1401
  this.config.mirrorInstance = parseInt(this.config.mirrorInstance, 10) || 0;
1185
1402
  if (this.instance === this.config.mirrorInstance) {
1186
1403
  const ioBDataDir = (0, adapter_core_1.getAbsoluteDefaultDataDir)() + node_path_1.sep;
@@ -1204,7 +1421,7 @@ class JavaScript extends adapter_core_1.Adapter {
1204
1421
  }
1205
1422
  }
1206
1423
  }
1207
- // CHeck setState counter per minute and stop script if too high
1424
+ // CHeck setState counter per minute and stop a script if too high
1208
1425
  this.setStateCountCheckInterval = setInterval(() => {
1209
1426
  Object.keys(this.scripts).forEach(id => {
1210
1427
  if (!this.scripts[id]) {
@@ -1335,7 +1552,7 @@ class JavaScript extends adapter_core_1.Adapter {
1335
1552
  delete this.folderCreationVerifiedObjects[id];
1336
1553
  }
1337
1554
  if (!obj && this.objects[id]) {
1338
- // objects was deleted
1555
+ // objects were deleted
1339
1556
  this.removeFromNames(id);
1340
1557
  delete this.objects[id];
1341
1558
  }
@@ -1484,7 +1701,7 @@ class JavaScript extends adapter_core_1.Adapter {
1484
1701
  continue;
1485
1702
  }
1486
1703
  if (this.objects[res.rows[i].doc._id] === undefined) {
1487
- // If was already there ignore
1704
+ // If was already there, ignore
1488
1705
  this.objects[res.rows[i].doc._id] = res.rows[i].doc;
1489
1706
  }
1490
1707
  this.objects[res.rows[i].doc._id].type === 'enum' && this._enums.push(res.rows[i].doc._id);
@@ -1584,7 +1801,7 @@ class JavaScript extends adapter_core_1.Adapter {
1584
1801
  const intermediateStateValue = this.prepareStateObjectSimple(idActive, enabled, true);
1585
1802
  await this.setForeignStateAsync(idActive, enabled, true);
1586
1803
  if (enabled && !this.config.subscribe) {
1587
- this.interimStateValues[id] = intermediateStateValue;
1804
+ this.interimStateValues[idActive] = intermediateStateValue;
1588
1805
  }
1589
1806
  }
1590
1807
  }
@@ -1733,7 +1950,7 @@ class JavaScript extends adapter_core_1.Adapter {
1733
1950
  version = parts.pop() ?? 'latest';
1734
1951
  depName = parts.join('@');
1735
1952
  }
1736
- /** The real module name, because the dependency can be an url too */
1953
+ /** The real module name, because the dependency can be a URL too */
1737
1954
  let moduleName = depName;
1738
1955
  if (URL.canParse(depName)) {
1739
1956
  moduleName = await (0, nodeModulesManagement_1.requestModuleNameByUrl)(depName);
@@ -2470,10 +2687,10 @@ class JavaScript extends adapter_core_1.Adapter {
2470
2687
  * Add declarations for global scripts
2471
2688
  *
2472
2689
  * @param scriptID - The current script the declarations were generated from
2473
- * @param declarations - Declarations from script
2690
+ * @param declarations - Declarations from a script
2474
2691
  */
2475
2692
  provideDeclarationsForGlobalScript(scriptID, declarations) {
2476
- // Remember which declarations this global script had access to,
2693
+ // Remember which declarations this global script had access to;
2477
2694
  // we need this so the editor doesn't show a duplicate identifier error
2478
2695
  if (this.globalDeclarations != null && this.globalDeclarations !== '') {
2479
2696
  this.knownGlobalDeclarationsByScript[scriptID] = this.globalDeclarations;
@@ -2665,7 +2882,7 @@ function patternMatching(event, patternFunctions) {
2665
2882
  }
2666
2883
  return matched;
2667
2884
  }
2668
- // If started as allInOne mode => return function to create instance
2885
+ // If started as allInOne mode => return function to create an instance
2669
2886
  if (require.main !== module) {
2670
2887
  // Export the constructor in compact mode
2671
2888
  module.exports = (options) => new JavaScript(options);