react-cheminfo 0.76.0 → 0.78.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 (389) hide show
  1. package/README.md +141 -31
  2. package/lib/card/core/cardAddress.d.ts +19 -2
  3. package/lib/card/core/cardAddress.d.ts.map +1 -1
  4. package/lib/card/core/cardAddress.js +35 -2
  5. package/lib/card/core/cardAddress.js.map +1 -1
  6. package/lib/card/core/cardPageUrl.d.ts +7 -1
  7. package/lib/card/core/cardPageUrl.d.ts.map +1 -1
  8. package/lib/card/core/cardPageUrl.js +4 -2
  9. package/lib/card/core/cardPageUrl.js.map +1 -1
  10. package/lib/card/core/index.d.ts +1 -1
  11. package/lib/card/core/index.d.ts.map +1 -1
  12. package/lib/card/core/index.js +1 -1
  13. package/lib/card/core/index.js.map +1 -1
  14. package/lib/credits/core/credits.d.ts +30 -0
  15. package/lib/credits/core/credits.d.ts.map +1 -1
  16. package/lib/credits/core/credits.js +35 -0
  17. package/lib/credits/core/credits.js.map +1 -1
  18. package/lib/download/core/downloadFigure.d.ts +12 -1
  19. package/lib/download/core/downloadFigure.d.ts.map +1 -1
  20. package/lib/download/core/downloadFigure.js +21 -0
  21. package/lib/download/core/downloadFigure.js.map +1 -1
  22. package/lib/download/core/figureDpi.d.ts +59 -0
  23. package/lib/download/core/figureDpi.d.ts.map +1 -0
  24. package/lib/download/core/figureDpi.js +75 -0
  25. package/lib/download/core/figureDpi.js.map +1 -0
  26. package/lib/download/core/figurePng.d.ts +4 -1
  27. package/lib/download/core/figurePng.d.ts.map +1 -1
  28. package/lib/download/core/figurePng.js +11 -2
  29. package/lib/download/core/figurePng.js.map +1 -1
  30. package/lib/download/core/index.d.ts +4 -1
  31. package/lib/download/core/index.d.ts.map +1 -1
  32. package/lib/download/core/index.js +3 -1
  33. package/lib/download/core/index.js.map +1 -1
  34. package/lib/download/core/pngDpi.d.ts +22 -0
  35. package/lib/download/core/pngDpi.d.ts.map +1 -0
  36. package/lib/download/core/pngDpi.js +79 -0
  37. package/lib/download/core/pngDpi.js.map +1 -0
  38. package/lib/download/ui/FigureDownloadPanel.d.ts +13 -0
  39. package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
  40. package/lib/download/ui/FigureDownloadPanel.js +18 -34
  41. package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
  42. package/lib/download/ui/figureDownloadHint.d.ts +5 -0
  43. package/lib/download/ui/figureDownloadHint.d.ts.map +1 -1
  44. package/lib/download/ui/figureDownloadHint.js +8 -0
  45. package/lib/download/ui/figureDownloadHint.js.map +1 -1
  46. package/lib/download/ui/figureDownloadOptions.d.ts +84 -0
  47. package/lib/download/ui/figureDownloadOptions.d.ts.map +1 -0
  48. package/lib/download/ui/figureDownloadOptions.js +2 -0
  49. package/lib/download/ui/figureDownloadOptions.js.map +1 -0
  50. package/lib/download/ui/resolutionChoices.d.ts +27 -0
  51. package/lib/download/ui/resolutionChoices.d.ts.map +1 -0
  52. package/lib/download/ui/resolutionChoices.js +48 -0
  53. package/lib/download/ui/resolutionChoices.js.map +1 -0
  54. package/lib/download/ui/useFigureActions.d.ts +4 -1
  55. package/lib/download/ui/useFigureActions.d.ts.map +1 -1
  56. package/lib/download/ui/useFigureActions.js +17 -8
  57. package/lib/download/ui/useFigureActions.js.map +1 -1
  58. package/lib/download/ui/useFigureDownload.d.ts +2 -55
  59. package/lib/download/ui/useFigureDownload.d.ts.map +1 -1
  60. package/lib/download/ui/useFigureDownload.js +45 -13
  61. package/lib/download/ui/useFigureDownload.js.map +1 -1
  62. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  63. package/lib/ecosystem/core/sites.js +14 -0
  64. package/lib/ecosystem/core/sites.js.map +1 -1
  65. package/lib/ecosystem/core/types.d.ts +1 -1
  66. package/lib/ecosystem/core/types.d.ts.map +1 -1
  67. package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
  68. package/lib/ecosystem/ui/glyphs.js +3 -0
  69. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  70. package/lib/host/core/connectHost.js +1 -1
  71. package/lib/host/core/connectHost.js.map +1 -1
  72. package/lib/host/core/connectTool.d.ts +103 -0
  73. package/lib/host/core/connectTool.d.ts.map +1 -0
  74. package/lib/host/core/connectTool.js +169 -0
  75. package/lib/host/core/connectTool.js.map +1 -0
  76. package/lib/host/core/hostOutputs.d.ts +16 -3
  77. package/lib/host/core/hostOutputs.d.ts.map +1 -1
  78. package/lib/host/core/hostOutputs.js +38 -4
  79. package/lib/host/core/hostOutputs.js.map +1 -1
  80. package/lib/host/core/index.d.ts +8 -2
  81. package/lib/host/core/index.d.ts.map +1 -1
  82. package/lib/host/core/index.js +4 -1
  83. package/lib/host/core/index.js.map +1 -1
  84. package/lib/host/core/kinds.d.ts +31 -3
  85. package/lib/host/core/kinds.d.ts.map +1 -1
  86. package/lib/host/core/kinds.js +35 -4
  87. package/lib/host/core/kinds.js.map +1 -1
  88. package/lib/host/core/messageValues.d.ts +29 -0
  89. package/lib/host/core/messageValues.d.ts.map +1 -0
  90. package/lib/host/core/messageValues.js +57 -0
  91. package/lib/host/core/messageValues.js.map +1 -0
  92. package/lib/host/core/protocol.d.ts +2 -5
  93. package/lib/host/core/protocol.d.ts.map +1 -1
  94. package/lib/host/core/protocol.js +3 -37
  95. package/lib/host/core/protocol.js.map +1 -1
  96. package/lib/host/core/resultKinds.d.ts +74 -0
  97. package/lib/host/core/resultKinds.d.ts.map +1 -0
  98. package/lib/host/core/resultKinds.js +40 -0
  99. package/lib/host/core/resultKinds.js.map +1 -0
  100. package/lib/host/core/toolMessages.d.ts +24 -0
  101. package/lib/host/core/toolMessages.d.ts.map +1 -0
  102. package/lib/host/core/toolMessages.js +136 -0
  103. package/lib/host/core/toolMessages.js.map +1 -0
  104. package/lib/host/ui/index.d.ts +2 -0
  105. package/lib/host/ui/index.d.ts.map +1 -1
  106. package/lib/host/ui/index.js +1 -0
  107. package/lib/host/ui/index.js.map +1 -1
  108. package/lib/host/ui/useFramedTool.d.ts +74 -0
  109. package/lib/host/ui/useFramedTool.d.ts.map +1 -0
  110. package/lib/host/ui/useFramedTool.js +125 -0
  111. package/lib/host/ui/useFramedTool.js.map +1 -0
  112. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  113. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  114. package/lib/locales/de.json +30 -1
  115. package/lib/locales/en.json +30 -1
  116. package/lib/locales/es.json +30 -1
  117. package/lib/locales/fr.json +30 -1
  118. package/lib/locales/it.json +30 -1
  119. package/lib/molecule3d/ui/Molecule3DStage.d.ts +4 -33
  120. package/lib/molecule3d/ui/Molecule3DStage.d.ts.map +1 -1
  121. package/lib/molecule3d/ui/Molecule3DStage.js +3 -37
  122. package/lib/molecule3d/ui/Molecule3DStage.js.map +1 -1
  123. package/lib/molecule3d/ui/MoleculeCanvas3D.d.ts.map +1 -1
  124. package/lib/molecule3d/ui/MoleculeCanvas3D.js +10 -2
  125. package/lib/molecule3d/ui/MoleculeCanvas3D.js.map +1 -1
  126. package/lib/molecule3d/ui/exportMoleculeImage.d.ts +10 -0
  127. package/lib/molecule3d/ui/exportMoleculeImage.d.ts.map +1 -1
  128. package/lib/molecule3d/ui/exportMoleculeImage.js +17 -0
  129. package/lib/molecule3d/ui/exportMoleculeImage.js.map +1 -1
  130. package/lib/molecule3d/ui/index.d.ts +1 -1
  131. package/lib/molecule3d/ui/index.d.ts.map +1 -1
  132. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts +23 -0
  133. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts.map +1 -1
  134. package/lib/molecule3d/ui/useImageExport.d.ts +3 -0
  135. package/lib/molecule3d/ui/useImageExport.d.ts.map +1 -1
  136. package/lib/molecule3d/ui/useImageExport.js +21 -3
  137. package/lib/molecule3d/ui/useImageExport.js.map +1 -1
  138. package/lib/osiris/core/barGeometry.d.ts +42 -0
  139. package/lib/osiris/core/barGeometry.d.ts.map +1 -0
  140. package/lib/osiris/core/barGeometry.js +46 -0
  141. package/lib/osiris/core/barGeometry.js.map +1 -0
  142. package/lib/osiris/core/computeProperties.d.ts +42 -0
  143. package/lib/osiris/core/computeProperties.d.ts.map +1 -0
  144. package/lib/osiris/core/computeProperties.js +115 -0
  145. package/lib/osiris/core/computeProperties.js.map +1 -0
  146. package/lib/osiris/core/constants.d.ts +70 -0
  147. package/lib/osiris/core/constants.d.ts.map +1 -0
  148. package/lib/osiris/core/constants.js +99 -0
  149. package/lib/osiris/core/constants.js.map +1 -0
  150. package/lib/osiris/core/fitness.d.ts +32 -0
  151. package/lib/osiris/core/fitness.d.ts.map +1 -0
  152. package/lib/osiris/core/fitness.js +48 -0
  153. package/lib/osiris/core/fitness.js.map +1 -0
  154. package/lib/osiris/core/index.d.ts +29 -0
  155. package/lib/osiris/core/index.d.ts.map +1 -0
  156. package/lib/osiris/core/index.js +19 -0
  157. package/lib/osiris/core/index.js.map +1 -0
  158. package/lib/osiris/core/poolSize.d.ts +17 -0
  159. package/lib/osiris/core/poolSize.d.ts.map +1 -0
  160. package/lib/osiris/core/poolSize.js +22 -0
  161. package/lib/osiris/core/poolSize.js.map +1 -0
  162. package/lib/osiris/core/poolTypes.d.ts +140 -0
  163. package/lib/osiris/core/poolTypes.d.ts.map +1 -0
  164. package/lib/osiris/core/poolTypes.js +12 -0
  165. package/lib/osiris/core/poolTypes.js.map +1 -0
  166. package/lib/osiris/core/predictIdCode.d.ts +39 -0
  167. package/lib/osiris/core/predictIdCode.d.ts.map +1 -0
  168. package/lib/osiris/core/predictIdCode.js +54 -0
  169. package/lib/osiris/core/predictIdCode.js.map +1 -0
  170. package/lib/osiris/core/predictProtocol.d.ts +67 -0
  171. package/lib/osiris/core/predictProtocol.d.ts.map +1 -0
  172. package/lib/osiris/core/predictProtocol.js +29 -0
  173. package/lib/osiris/core/predictProtocol.js.map +1 -0
  174. package/lib/osiris/core/predictionPool.d.ts +23 -0
  175. package/lib/osiris/core/predictionPool.d.ts.map +1 -0
  176. package/lib/osiris/core/predictionPool.js +186 -0
  177. package/lib/osiris/core/predictionPool.js.map +1 -0
  178. package/lib/osiris/core/predictionQueue.d.ts +46 -0
  179. package/lib/osiris/core/predictionQueue.d.ts.map +1 -0
  180. package/lib/osiris/core/predictionQueue.js +57 -0
  181. package/lib/osiris/core/predictionQueue.js.map +1 -0
  182. package/lib/osiris/core/predictors.d.ts +62 -0
  183. package/lib/osiris/core/predictors.d.ts.map +1 -0
  184. package/lib/osiris/core/predictors.js +100 -0
  185. package/lib/osiris/core/predictors.js.map +1 -0
  186. package/lib/osiris/core/propertyKeys.d.ts +32 -0
  187. package/lib/osiris/core/propertyKeys.d.ts.map +1 -0
  188. package/lib/osiris/core/propertyKeys.js +44 -0
  189. package/lib/osiris/core/propertyKeys.js.map +1 -0
  190. package/lib/osiris/core/riskAppearance.d.ts +60 -0
  191. package/lib/osiris/core/riskAppearance.d.ts.map +1 -0
  192. package/lib/osiris/core/riskAppearance.js +59 -0
  193. package/lib/osiris/core/riskAppearance.js.map +1 -0
  194. package/lib/osiris/core/riskDetail.d.ts +22 -0
  195. package/lib/osiris/core/riskDetail.d.ts.map +1 -0
  196. package/lib/osiris/core/riskDetail.js +86 -0
  197. package/lib/osiris/core/riskDetail.js.map +1 -0
  198. package/lib/osiris/core/riskDetailRequest.d.ts +31 -0
  199. package/lib/osiris/core/riskDetailRequest.d.ts.map +1 -0
  200. package/lib/osiris/core/riskDetailRequest.js +49 -0
  201. package/lib/osiris/core/riskDetailRequest.js.map +1 -0
  202. package/lib/osiris/core/riskFindings.d.ts +26 -0
  203. package/lib/osiris/core/riskFindings.d.ts.map +1 -0
  204. package/lib/osiris/core/riskFindings.js +79 -0
  205. package/lib/osiris/core/riskFindings.js.map +1 -0
  206. package/lib/osiris/core/runPredictionJob.d.ts +20 -0
  207. package/lib/osiris/core/runPredictionJob.d.ts.map +1 -0
  208. package/lib/osiris/core/runPredictionJob.js +43 -0
  209. package/lib/osiris/core/runPredictionJob.js.map +1 -0
  210. package/lib/osiris/core/scales.d.ts +70 -0
  211. package/lib/osiris/core/scales.d.ts.map +1 -0
  212. package/lib/osiris/core/scales.js +185 -0
  213. package/lib/osiris/core/scales.js.map +1 -0
  214. package/lib/osiris/core/types.d.ts +91 -0
  215. package/lib/osiris/core/types.d.ts.map +1 -0
  216. package/lib/osiris/core/types.js +19 -0
  217. package/lib/osiris/core/types.js.map +1 -0
  218. package/lib/osiris/core/valuation.d.ts +28 -0
  219. package/lib/osiris/core/valuation.d.ts.map +1 -0
  220. package/lib/osiris/core/valuation.js +39 -0
  221. package/lib/osiris/core/valuation.js.map +1 -0
  222. package/lib/osiris/ui/PropertyBar.d.ts +27 -0
  223. package/lib/osiris/ui/PropertyBar.d.ts.map +1 -0
  224. package/lib/osiris/ui/PropertyBar.js +27 -0
  225. package/lib/osiris/ui/PropertyBar.js.map +1 -0
  226. package/lib/osiris/ui/PropertyPanel.d.ts +91 -0
  227. package/lib/osiris/ui/PropertyPanel.d.ts.map +1 -0
  228. package/lib/osiris/ui/PropertyPanel.js +77 -0
  229. package/lib/osiris/ui/PropertyPanel.js.map +1 -0
  230. package/lib/osiris/ui/PropertyRows.d.ts +40 -0
  231. package/lib/osiris/ui/PropertyRows.d.ts.map +1 -0
  232. package/lib/osiris/ui/PropertyRows.js +23 -0
  233. package/lib/osiris/ui/PropertyRows.js.map +1 -0
  234. package/lib/osiris/ui/RiskFindings.d.ts +43 -0
  235. package/lib/osiris/ui/RiskFindings.d.ts.map +1 -0
  236. package/lib/osiris/ui/RiskFindings.js +51 -0
  237. package/lib/osiris/ui/RiskFindings.js.map +1 -0
  238. package/lib/osiris/ui/RiskPanel.d.ts +46 -0
  239. package/lib/osiris/ui/RiskPanel.d.ts.map +1 -0
  240. package/lib/osiris/ui/RiskPanel.js +32 -0
  241. package/lib/osiris/ui/RiskPanel.js.map +1 -0
  242. package/lib/osiris/ui/RiskSquare.d.ts +51 -0
  243. package/lib/osiris/ui/RiskSquare.d.ts.map +1 -0
  244. package/lib/osiris/ui/RiskSquare.js +23 -0
  245. package/lib/osiris/ui/RiskSquare.js.map +1 -0
  246. package/lib/osiris/ui/index.d.ts +15 -0
  247. package/lib/osiris/ui/index.d.ts.map +1 -0
  248. package/lib/osiris/ui/index.js +8 -0
  249. package/lib/osiris/ui/index.js.map +1 -0
  250. package/lib/osiris/ui/usePredictions.d.ts +81 -0
  251. package/lib/osiris/ui/usePredictions.d.ts.map +1 -0
  252. package/lib/osiris/ui/usePredictions.js +102 -0
  253. package/lib/osiris/ui/usePredictions.js.map +1 -0
  254. package/lib/osiris-ui.d.ts +11 -0
  255. package/lib/osiris-ui.d.ts.map +1 -0
  256. package/lib/osiris-ui.js +11 -0
  257. package/lib/osiris-ui.js.map +1 -0
  258. package/lib/osiris.d.ts +17 -0
  259. package/lib/osiris.d.ts.map +1 -0
  260. package/lib/osiris.js +17 -0
  261. package/lib/osiris.js.map +1 -0
  262. package/lib/panel/ui/FilterInput.d.ts.map +1 -1
  263. package/lib/panel/ui/FilterInput.js +3 -1
  264. package/lib/panel/ui/FilterInput.js.map +1 -1
  265. package/lib/panel/ui/SidePanelItem.d.ts +39 -0
  266. package/lib/panel/ui/SidePanelItem.d.ts.map +1 -0
  267. package/lib/panel/ui/SidePanelItem.js +63 -0
  268. package/lib/panel/ui/SidePanelItem.js.map +1 -0
  269. package/lib/panel/ui/SidePanelStack.d.ts +11 -10
  270. package/lib/panel/ui/SidePanelStack.d.ts.map +1 -1
  271. package/lib/panel/ui/SidePanelStack.js +22 -15
  272. package/lib/panel/ui/SidePanelStack.js.map +1 -1
  273. package/lib/panel/ui/SpectrumColorSwatch.d.ts.map +1 -1
  274. package/lib/panel/ui/SpectrumColorSwatch.js +4 -2
  275. package/lib/panel/ui/SpectrumColorSwatch.js.map +1 -1
  276. package/lib/panel/ui/usePanelFolds.d.ts +35 -0
  277. package/lib/panel/ui/usePanelFolds.d.ts.map +1 -0
  278. package/lib/panel/ui/usePanelFolds.js +73 -0
  279. package/lib/panel/ui/usePanelFolds.js.map +1 -0
  280. package/lib/shared/ui/FullscreenStage.d.ts +43 -0
  281. package/lib/shared/ui/FullscreenStage.d.ts.map +1 -0
  282. package/lib/shared/ui/FullscreenStage.js +38 -0
  283. package/lib/shared/ui/FullscreenStage.js.map +1 -0
  284. package/lib/shared/ui/canFillScreen.d.ts +7 -0
  285. package/lib/shared/ui/canFillScreen.d.ts.map +1 -0
  286. package/lib/shared/ui/canFillScreen.js +9 -0
  287. package/lib/shared/ui/canFillScreen.js.map +1 -0
  288. package/lib/shared/ui/index.d.ts +3 -0
  289. package/lib/shared/ui/index.d.ts.map +1 -1
  290. package/lib/shared/ui/index.js +2 -0
  291. package/lib/shared/ui/index.js.map +1 -1
  292. package/lib/split/ui/splitPanes.d.ts +3 -3
  293. package/lib/split/ui/splitPanes.js +1 -1
  294. package/lib/structure/core/structureNotations.d.ts +8 -1
  295. package/lib/structure/core/structureNotations.d.ts.map +1 -1
  296. package/lib/structure/core/structureNotations.js +14 -8
  297. package/lib/structure/core/structureNotations.js.map +1 -1
  298. package/lib/structure/ui/StructureExportPanel.d.ts +8 -0
  299. package/lib/structure/ui/StructureExportPanel.d.ts.map +1 -1
  300. package/lib/structure/ui/StructureExportPanel.js +9 -4
  301. package/lib/structure/ui/StructureExportPanel.js.map +1 -1
  302. package/lib/structure/ui/index.d.ts +1 -0
  303. package/lib/structure/ui/index.d.ts.map +1 -1
  304. package/lib/structure/ui/index.js.map +1 -1
  305. package/package.json +4 -1
  306. package/src/card/core/cardAddress.ts +39 -3
  307. package/src/card/core/cardPageUrl.ts +10 -3
  308. package/src/card/core/index.ts +7 -1
  309. package/src/credits/core/credits.ts +40 -0
  310. package/src/download/core/downloadFigure.ts +26 -1
  311. package/src/download/core/figureDpi.ts +94 -0
  312. package/src/download/core/figurePng.ts +11 -2
  313. package/src/download/core/index.ts +13 -1
  314. package/src/download/core/pngDpi.ts +84 -0
  315. package/src/download/ui/FigureDownloadPanel.tsx +41 -51
  316. package/src/download/ui/figureDownloadHint.ts +13 -0
  317. package/src/download/ui/figureDownloadOptions.ts +85 -0
  318. package/src/download/ui/resolutionChoices.ts +67 -0
  319. package/src/download/ui/useFigureActions.ts +24 -9
  320. package/src/download/ui/useFigureDownload.tsx +57 -71
  321. package/src/ecosystem/core/sites.ts +14 -0
  322. package/src/ecosystem/core/types.ts +2 -1
  323. package/src/ecosystem/ui/glyphs.tsx +20 -0
  324. package/src/host/core/connectHost.ts +1 -1
  325. package/src/host/core/connectTool.ts +285 -0
  326. package/src/host/core/hostOutputs.ts +47 -5
  327. package/src/host/core/index.ts +20 -1
  328. package/src/host/core/kinds.ts +53 -8
  329. package/src/host/core/messageValues.ts +58 -0
  330. package/src/host/core/protocol.ts +5 -37
  331. package/src/host/core/resultKinds.ts +65 -0
  332. package/src/host/core/toolMessages.ts +160 -0
  333. package/src/host/ui/index.ts +6 -0
  334. package/src/host/ui/useFramedTool.ts +213 -0
  335. package/src/locales/de.json +30 -1
  336. package/src/locales/en.json +30 -1
  337. package/src/locales/es.json +30 -1
  338. package/src/locales/fr.json +30 -1
  339. package/src/locales/it.json +30 -1
  340. package/src/molecule3d/ui/Molecule3DStage.tsx +4 -88
  341. package/src/molecule3d/ui/MoleculeCanvas3D.tsx +10 -1
  342. package/src/molecule3d/ui/exportMoleculeImage.ts +22 -0
  343. package/src/molecule3d/ui/index.ts +4 -1
  344. package/src/molecule3d/ui/moleculeViewer3DProps.ts +24 -0
  345. package/src/molecule3d/ui/useImageExport.ts +28 -2
  346. package/src/osiris/core/barGeometry.ts +74 -0
  347. package/src/osiris/core/computeProperties.ts +175 -0
  348. package/src/osiris/core/constants.ts +110 -0
  349. package/src/osiris/core/fitness.ts +59 -0
  350. package/src/osiris/core/index.ts +78 -0
  351. package/src/osiris/core/poolSize.ts +24 -0
  352. package/src/osiris/core/poolTypes.ts +140 -0
  353. package/src/osiris/core/predictIdCode.ts +69 -0
  354. package/src/osiris/core/predictProtocol.ts +78 -0
  355. package/src/osiris/core/predictionPool.ts +237 -0
  356. package/src/osiris/core/predictionQueue.ts +89 -0
  357. package/src/osiris/core/predictors.ts +142 -0
  358. package/src/osiris/core/propertyKeys.ts +54 -0
  359. package/src/osiris/core/riskAppearance.ts +86 -0
  360. package/src/osiris/core/riskDetail.ts +120 -0
  361. package/src/osiris/core/riskDetailRequest.ts +64 -0
  362. package/src/osiris/core/riskFindings.ts +92 -0
  363. package/src/osiris/core/runPredictionJob.ts +49 -0
  364. package/src/osiris/core/scales.ts +236 -0
  365. package/src/osiris/core/types.ts +103 -0
  366. package/src/osiris/core/valuation.ts +44 -0
  367. package/src/osiris/ui/PropertyBar.tsx +77 -0
  368. package/src/osiris/ui/PropertyPanel.tsx +227 -0
  369. package/src/osiris/ui/PropertyRows.tsx +92 -0
  370. package/src/osiris/ui/RiskFindings.tsx +137 -0
  371. package/src/osiris/ui/RiskPanel.tsx +81 -0
  372. package/src/osiris/ui/RiskSquare.tsx +108 -0
  373. package/src/osiris/ui/index.ts +17 -0
  374. package/src/osiris/ui/usePredictions.ts +194 -0
  375. package/src/osiris-ui.ts +11 -0
  376. package/src/osiris.ts +17 -0
  377. package/src/panel/ui/FilterInput.tsx +4 -1
  378. package/src/panel/ui/SidePanelItem.tsx +162 -0
  379. package/src/panel/ui/SidePanelStack.tsx +29 -36
  380. package/src/panel/ui/SpectrumColorSwatch.tsx +5 -3
  381. package/src/panel/ui/usePanelFolds.ts +103 -0
  382. package/src/shared/ui/FullscreenStage.tsx +96 -0
  383. package/src/shared/ui/canFillScreen.ts +8 -0
  384. package/src/shared/ui/index.ts +6 -0
  385. package/src/split/ui/splitPanes.tsx +4 -4
  386. package/src/structure/core/structureNotations.ts +25 -8
  387. package/src/structure/ui/StructureExportPanel.tsx +23 -4
  388. package/src/structure/ui/index.ts +4 -0
  389. package/styles/osiris.css +339 -0
@@ -0,0 +1,285 @@
1
+ /**
2
+ * A host's side of the host protocol: answer the `hello` of the tool in a
3
+ * frame with a private port, hand it documents, hear the values it sends back,
4
+ * and ask it for others.
5
+ *
6
+ * Free of React and of the DOM — the frame and the window are handed in — so a
7
+ * test drives the whole exchange against a real tool side and a real
8
+ * `MessageChannel`.
9
+ */
10
+
11
+ import type {
12
+ HostError,
13
+ HostItem,
14
+ OutputMessage,
15
+ ResultMessage,
16
+ UsedItem,
17
+ } from './protocol.ts';
18
+ import { CONNECT_TYPE, PROTOCOL_VERSION } from './protocol.ts';
19
+ import type { ToolHello } from './toolMessages.ts';
20
+ import { readHello, readToolMessage } from './toolMessages.ts';
21
+
22
+ /** A message posted to this window, as far as a host reads it. */
23
+ export interface ToolWindowEvent {
24
+ data: unknown;
25
+ source: unknown;
26
+ origin: string;
27
+ }
28
+
29
+ /** The window of the frame the tool runs in. */
30
+ export interface ToolFrameWindow {
31
+ postMessage: (
32
+ message: unknown,
33
+ targetOrigin: string,
34
+ transfer: Transferable[],
35
+ ) => void;
36
+ }
37
+
38
+ /** A document handed to a tool: what it shows, and what it sends back unasked. */
39
+ export interface ToolDocument {
40
+ /** What the data belongs to; the tool applies the same document once. */
41
+ document: string;
42
+ /** The values, each with its kind. */
43
+ items: HostItem[];
44
+ /**
45
+ * The outputs the tool sends whenever they change, by key or by kind.
46
+ * @default undefined — nothing is sent unasked
47
+ */
48
+ accept?: string[];
49
+ }
50
+
51
+ /**
52
+ * What became of a document: shown, refused with the tool's reason, or never
53
+ * answered — another document took its place, the connection was closed, or
54
+ * the tool took too long.
55
+ */
56
+ export type LoadOutcome =
57
+ | { status: 'loaded'; used: UsedItem[] }
58
+ | { status: 'refused'; error: HostError }
59
+ | { status: 'dropped' };
60
+
61
+ /** Where the connection runs, and whom it talks to. */
62
+ export interface ToolConnectionOptions {
63
+ /** The window of the frame, once there is one: `hello` is taken from it alone. */
64
+ frame: () => ToolFrameWindow | null;
65
+ /** Where the tool is served from: a message from any other origin is ignored. */
66
+ origin: string;
67
+ /** How the host introduces itself in `connect`. */
68
+ host: { name: string };
69
+ /** Subscribe to this window's messages; the returned function unsubscribes. */
70
+ listen: (listener: (event: ToolWindowEvent) => void) => () => void;
71
+ /**
72
+ * Told each time the tool says `hello` — once per load of the frame — with
73
+ * what it takes and gives.
74
+ * @default undefined
75
+ */
76
+ onHello?: (tool: ToolHello) => void;
77
+ /**
78
+ * Told of every `output` the tool sends.
79
+ * @default undefined
80
+ */
81
+ onOutput?: (message: OutputMessage) => void;
82
+ /**
83
+ * How long a request may go unanswered, in milliseconds.
84
+ * @default REQUEST_TIMEOUT
85
+ */
86
+ timeout?: number;
87
+ }
88
+
89
+ /** A connection to a framed tool. */
90
+ export interface ToolConnection {
91
+ /**
92
+ * Show a document. One handed over before the tool has connected waits for
93
+ * it, and the latest is handed over again whenever the tool connects anew —
94
+ * after a reload of its frame.
95
+ */
96
+ load: (document: ToolDocument) => Promise<LoadOutcome>;
97
+ /** The current values of some outputs; rejects with the tool's reason. */
98
+ get: (keys: readonly string[]) => Promise<HostItem[]>;
99
+ /** Stop listening and close the port; what is pending is dropped. */
100
+ close: () => void;
101
+ }
102
+
103
+ /** How long a request may go unanswered, in milliseconds. */
104
+ export const REQUEST_TIMEOUT = 20_000;
105
+
106
+ type Abandon = 'timeout' | 'reconnected' | 'closed';
107
+
108
+ const ABANDONED: Record<Abandon, string> = {
109
+ timeout: 'The tool did not answer in time.',
110
+ reconnected: 'The tool was reloaded before it answered.',
111
+ closed: 'The tool is no longer connected.',
112
+ };
113
+
114
+ interface Waiting {
115
+ answer: (message: ResultMessage) => void;
116
+ abandon: (reason: Abandon) => void;
117
+ timer: ReturnType<typeof setTimeout>;
118
+ }
119
+
120
+ interface Shown {
121
+ document: ToolDocument;
122
+ /** Who waits for its first answer; `null` once told. */
123
+ settle: ((outcome: LoadOutcome) => void) | null;
124
+ }
125
+
126
+ /**
127
+ * Listen for the framed tool's `hello`, and talk to it once it has said it.
128
+ *
129
+ * A `hello` counts only from the frame's window and from the tool's origin —
130
+ * a frame that navigated elsewhere keeps its window — and `connect` is posted
131
+ * to that origin alone, so a page the frame later shows never receives the
132
+ * port, nor anything sent through it.
133
+ * @param options - The frame, the tool's origin, and what to tell.
134
+ * @returns The connection.
135
+ */
136
+ export function connectTool(options: ToolConnectionOptions): ToolConnection {
137
+ const { frame, origin, host, listen, onHello, onOutput } = options;
138
+ const { timeout = REQUEST_TIMEOUT } = options;
139
+ const waiting = new Map<string, Waiting>();
140
+ let port: MessagePort | null = null;
141
+ let shown: Shown | null = null;
142
+ let count = 0;
143
+ let closed = false;
144
+
145
+ function post(
146
+ body: Record<string, unknown>,
147
+ handlers: Omit<Waiting, 'timer'>,
148
+ ): void {
149
+ if (port === null) return;
150
+ count += 1;
151
+ const id = `h${count}`;
152
+ const timer = setTimeout(() => {
153
+ waiting.delete(id);
154
+ handlers.abandon('timeout');
155
+ }, timeout);
156
+ waiting.set(id, { ...handlers, timer });
157
+ port.postMessage({ ...body, id });
158
+ }
159
+
160
+ function abandonAll(reason: Abandon): void {
161
+ for (const entry of waiting.values()) {
162
+ clearTimeout(entry.timer);
163
+ entry.abandon(reason);
164
+ }
165
+ waiting.clear();
166
+ }
167
+
168
+ function settle(entry: Shown, outcome: LoadOutcome): void {
169
+ entry.settle?.(outcome);
170
+ entry.settle = null;
171
+ }
172
+
173
+ function send(entry: Shown): void {
174
+ const { document, items, accept } = entry.document;
175
+ post(
176
+ {
177
+ type: 'load',
178
+ document,
179
+ items,
180
+ ...(accept === undefined ? {} : { accept }),
181
+ },
182
+ {
183
+ answer: (message) => {
184
+ settle(entry, outcomeOf(message));
185
+ },
186
+ // Sent again to the reloaded tool, which answers then.
187
+ abandon: (reason) => {
188
+ if (reason !== 'reconnected') settle(entry, { status: 'dropped' });
189
+ },
190
+ },
191
+ );
192
+ }
193
+
194
+ function receive(data: unknown): void {
195
+ const message = readToolMessage(data);
196
+ if (message === null) return;
197
+ if (message.type === 'output') {
198
+ onOutput?.(message);
199
+ return;
200
+ }
201
+ const entry = waiting.get(message.id);
202
+ if (entry === undefined) return;
203
+ waiting.delete(message.id);
204
+ clearTimeout(entry.timer);
205
+ entry.answer(message);
206
+ }
207
+
208
+ const stopListening = listen((event) => {
209
+ if (closed || event.origin !== origin) return;
210
+ const target = frame();
211
+ if (target === null || event.source !== target) return;
212
+ const tool = readHello(event.data);
213
+ if (tool === null) return;
214
+ abandonAll('reconnected');
215
+ port?.close();
216
+ const channel = new MessageChannel();
217
+ port = channel.port1;
218
+ port.addEventListener('message', (message) => {
219
+ receive(message.data);
220
+ });
221
+ port.start();
222
+ target.postMessage(
223
+ { type: CONNECT_TYPE, version: PROTOCOL_VERSION, host },
224
+ origin,
225
+ [channel.port2],
226
+ );
227
+ onHello?.(tool);
228
+ if (shown !== null) send(shown);
229
+ });
230
+
231
+ return {
232
+ load(document) {
233
+ return new Promise((resolve) => {
234
+ if (shown !== null) settle(shown, { status: 'dropped' });
235
+ const entry: Shown = { document, settle: resolve };
236
+ shown = entry;
237
+ if (closed) settle(entry, { status: 'dropped' });
238
+ else send(entry);
239
+ });
240
+ },
241
+ get(keys) {
242
+ return new Promise((resolve, reject) => {
243
+ if (port === null) {
244
+ reject(
245
+ new Error(
246
+ closed
247
+ ? ABANDONED.closed
248
+ : 'The tool has not connected yet, so it has nothing to give.',
249
+ ),
250
+ );
251
+ return;
252
+ }
253
+ post(
254
+ { type: 'get', keys: [...keys] },
255
+ {
256
+ answer: (message) => {
257
+ if (!message.ok) {
258
+ reject(new Error(message.error.message, { cause: message }));
259
+ } else {
260
+ resolve('items' in message ? message.items : []);
261
+ }
262
+ },
263
+ abandon: (reason) => {
264
+ reject(new Error(ABANDONED[reason]));
265
+ },
266
+ },
267
+ );
268
+ });
269
+ },
270
+ close() {
271
+ if (closed) return;
272
+ closed = true;
273
+ stopListening();
274
+ abandonAll('closed');
275
+ if (shown !== null) settle(shown, { status: 'dropped' });
276
+ port?.close();
277
+ port = null;
278
+ },
279
+ };
280
+ }
281
+
282
+ function outcomeOf(message: ResultMessage): LoadOutcome {
283
+ if (!message.ok) return { status: 'refused', error: message.error };
284
+ return { status: 'loaded', used: 'used' in message ? message.used : [] };
285
+ }
@@ -6,6 +6,10 @@
6
6
  * already has: the values as they stood once its document was applied, then
7
7
  * every value sent since. Opening a document therefore never writes it back,
8
8
  * and a band picked on one spectrum of a sample leaves the others alone.
9
+ *
10
+ * A value that costs something to make — a picture rendered from the scene on
11
+ * screen — is not read with the others: it is rendered when a `get` names it,
12
+ * and never sent unasked.
9
13
  */
10
14
 
11
15
  import { kindAccepts } from './kinds.ts';
@@ -27,6 +31,14 @@ export interface HostOutputs {
27
31
  read: () => readonly HostItem[];
28
32
  /** Be told whenever they may have changed; the returned function stops it. */
29
33
  subscribe: (listener: () => void) => () => void;
34
+ /**
35
+ * The outputs made only when a host asks for them, by key: a `get` naming one
36
+ * waits for its value, which is never sent unasked. A function resolving to
37
+ * `undefined` has nothing to give yet; one that rejects answers the `get`
38
+ * with its error's message.
39
+ * @default undefined — every output is read by `read`
40
+ */
41
+ render?: Readonly<Record<string, () => Promise<HostItem | undefined>>>;
30
42
  }
31
43
 
32
44
  /**
@@ -37,17 +49,18 @@ export const OUTPUT_DELAY = 300;
37
49
 
38
50
  /**
39
51
  * Answer a `get` with the values it asks for — every output when it names
40
- * none.
52
+ * none — rendering those made on request.
41
53
  * @param request - The request.
42
54
  * @param tool - What the tool hands back.
43
55
  * @param outputs - Where the values are read, if anywhere.
44
- * @returns The values, or `no-output` when the tool has none of those asked.
56
+ * @returns The values, or `no-output` when the tool has none of those asked,
57
+ * or one could not be made.
45
58
  */
46
- export function answerGet(
59
+ export async function answerGet(
47
60
  request: GetRequest,
48
61
  tool: ToolInterface,
49
62
  outputs: HostOutputs | undefined,
50
- ): ResultMessage {
63
+ ): Promise<ResultMessage> {
51
64
  const { id, keys } = request;
52
65
  const declared = new Set<string>();
53
66
  for (const output of tool.outputs) declared.add(output.key);
@@ -66,11 +79,40 @@ export function answerGet(
66
79
  }
67
80
  const items: HostItem[] = [];
68
81
  for (const item of outputs.read()) {
69
- if (item.key !== undefined && wanted.has(item.key)) items.push(item);
82
+ if (item.key === undefined || !wanted.has(item.key)) continue;
83
+ if (renderOf(outputs, item.key) === undefined) items.push(item);
84
+ }
85
+ const renders: Array<() => Promise<HostItem | undefined>> = [];
86
+ const renderedKeys: string[] = [];
87
+ for (const key of wanted) {
88
+ const render = renderOf(outputs, key);
89
+ if (render === undefined) continue;
90
+ renders.push(render);
91
+ renderedKeys.push(key);
92
+ }
93
+ try {
94
+ const made = await Promise.all(renders.map((render) => render()));
95
+ for (let index = 0; index < made.length; index++) {
96
+ const item = made[index];
97
+ const key = renderedKeys[index];
98
+ if (item !== undefined && key !== undefined) items.push({ ...item, key });
99
+ }
100
+ } catch (error) {
101
+ return noOutput(id, error instanceof Error ? error.message : String(error));
70
102
  }
71
103
  return { type: 'result', id, ok: true, items };
72
104
  }
73
105
 
106
+ function renderOf(
107
+ outputs: HostOutputs,
108
+ key: string,
109
+ ): (() => Promise<HostItem | undefined>) | undefined {
110
+ const { render } = outputs;
111
+ return render !== undefined && Object.hasOwn(render, key)
112
+ ? render[key]
113
+ : undefined;
114
+ }
115
+
74
116
  /** What the connection tells the publisher, and the means to stop it. */
75
117
  export interface OutputPublisher {
76
118
  /** A document was applied: what the host has is what the tool now shows. */
@@ -1,5 +1,14 @@
1
1
  export type { HostConnectionOptions, HostMessageEvent } from './connectHost.ts';
2
2
  export { connectHost } from './connectHost.ts';
3
+ export type {
4
+ LoadOutcome,
5
+ ToolConnection,
6
+ ToolConnectionOptions,
7
+ ToolDocument,
8
+ ToolFrameWindow,
9
+ ToolWindowEvent,
10
+ } from './connectTool.ts';
11
+ export { REQUEST_TIMEOUT, connectTool } from './connectTool.ts';
3
12
  export type { HostOutputs, OutputPublisher } from './hostOutputs.ts';
4
13
  export {
5
14
  OUTPUT_DELAY,
@@ -17,13 +26,14 @@ export type { IrJdxValue, IrPeakValue, IrPeaksValue } from './irKinds.ts';
17
26
  export { IR_JDX_SCHEMA, IR_PEAKS_SCHEMA } from './irKinds.ts';
18
27
  export type {
19
28
  CheckOutcome,
29
+ CheckedOf,
20
30
  CheckedValue,
21
31
  KnownKind,
22
32
  MolfileValue,
23
33
  OclIdValue,
24
34
  SmilesValue,
25
35
  } from './kinds.ts';
26
- export { checkValue, isKnownKind, kindAccepts } from './kinds.ts';
36
+ export { checkValue, isKnownKind, kindAccepts, readOutput } from './kinds.ts';
27
37
  export type {
28
38
  GetRequest,
29
39
  HelloMessage,
@@ -48,5 +58,14 @@ export {
48
58
  isConnect,
49
59
  parseRequest,
50
60
  } from './protocol.ts';
61
+ export type {
62
+ NameValue,
63
+ SvgImageValue,
64
+ TableCell,
65
+ TableValue,
66
+ } from './resultKinds.ts';
67
+ export { NAME_SCHEMA, SVG_IMAGE_SCHEMA, TABLE_SCHEMA } from './resultKinds.ts';
51
68
  export type { InputSelection, LoadedInput } from './selectInputs.ts';
52
69
  export { selectInputs } from './selectInputs.ts';
70
+ export type { ToolHello } from './toolMessages.ts';
71
+ export { readHello, readToolMessage } from './toolMessages.ts';
@@ -4,8 +4,9 @@
4
4
  * name, a JSON Schema, and ajv.
5
5
  *
6
6
  * The names are pipeline's (`chem.molfile.2d`, `chem.ocl.id`…), plus
7
- * `chem.smiles`, which pipeline lists among its future schemas, and the two
8
- * infrared kinds of `./irKinds.ts`. A name with children is a category whose
7
+ * `chem.smiles`, which pipeline lists among its future schemas, the two
8
+ * infrared kinds of `./irKinds.ts`, and the kinds a tool hands back, of
9
+ * `./resultKinds.ts`. A name with children is a category whose
9
10
  * schema every child satisfies, so `chem.molfile` reads `chem.molfile.2d` and
10
11
  * `chem.molfile.3d.h.energy` alike; the fields a tool does not read are
11
12
  * stripped rather than refused, so a host sending more than it needs to is
@@ -17,6 +18,9 @@ import { Ajv } from 'ajv';
17
18
 
18
19
  import type { IrJdxValue, IrPeaksValue } from './irKinds.ts';
19
20
  import { IR_JDX_SCHEMA, IR_PEAKS_SCHEMA } from './irKinds.ts';
21
+ import type { HostItem } from './protocol.ts';
22
+ import type { NameValue, SvgImageValue, TableValue } from './resultKinds.ts';
23
+ import { NAME_SCHEMA, SVG_IMAGE_SCHEMA, TABLE_SCHEMA } from './resultKinds.ts';
20
24
 
21
25
  /** A molfile, V2000 or V3000. */
22
26
  export interface MolfileValue {
@@ -40,13 +44,19 @@ export type CheckedValue =
40
44
  | { kind: 'chem.ocl.id'; value: OclIdValue }
41
45
  | { kind: 'chem.smiles'; value: SmilesValue }
42
46
  | { kind: 'spectra.ir.jdx'; value: IrJdxValue }
43
- | { kind: 'spectra.ir.peaks'; value: IrPeaksValue };
47
+ | { kind: 'spectra.ir.peaks'; value: IrPeaksValue }
48
+ | { kind: 'image.svg'; value: SvgImageValue }
49
+ | { kind: 'chem.name'; value: NameValue }
50
+ | { kind: 'data.table'; value: TableValue };
44
51
 
45
- /** The name of a kind a tool can read. */
52
+ /** The name of a kind there is a schema for: one a tool reads, or one it hands back. */
46
53
  export type KnownKind = CheckedValue['kind'];
47
54
 
48
- /** The value a kind a tool can read carries. */
49
- type ValueOf<K extends KnownKind> = Extract<CheckedValue, { kind: K }>['value'];
55
+ /** A checked value of one kind. */
56
+ export type CheckedOf<K extends KnownKind> = Extract<CheckedValue, { kind: K }>;
57
+
58
+ /** The value a kind with a schema carries. */
59
+ type ValueOf<K extends KnownKind> = CheckedOf<K>['value'];
50
60
 
51
61
  /** What checking a value gave. */
52
62
  export type CheckOutcome =
@@ -100,6 +110,37 @@ export function checkValue(kind: KnownKind, value: unknown): CheckOutcome {
100
110
  return { valid: false, errors };
101
111
  }
102
112
 
113
+ /**
114
+ * Read the value a tool handed back under an output, as the kind the host
115
+ * asked for: the item must be of that kind or one under it, and pass that
116
+ * kind's schema.
117
+ * @param items - What the tool handed back.
118
+ * @param key - The output.
119
+ * @param kind - The kind it is read as.
120
+ * @returns The value tagged with the kind, or `undefined` when the tool handed
121
+ * nothing back under that key.
122
+ * @throws {Error} When the item is of another kind, or not of its shape.
123
+ */
124
+ export function readOutput<K extends KnownKind>(
125
+ items: readonly HostItem[],
126
+ key: string,
127
+ kind: K,
128
+ ): CheckedOf<K> | undefined {
129
+ const item = items.find((entry) => entry.key === key);
130
+ if (item === undefined) return undefined;
131
+ if (!kindAccepts(kind, item.kind)) {
132
+ throw new Error(`The ${key} handed back is a ${item.kind}, not a ${kind}.`);
133
+ }
134
+ const outcome = checkValue(kind, item.value);
135
+ if (!outcome.valid) {
136
+ throw new Error(
137
+ `The ${key} handed back is not shaped as a ${kind}: ${outcome.errors.join('; ')}.`,
138
+ );
139
+ }
140
+ // The validator of `kind` just vouched for the shape of the value.
141
+ return outcome.checked as CheckedOf<K>;
142
+ }
143
+
103
144
  const MOLFILE_SCHEMA: JSONSchemaType<MolfileValue> = {
104
145
  type: 'object',
105
146
  properties: { molfile: { type: 'string' } },
@@ -124,8 +165,9 @@ const SMILES_SCHEMA: JSONSchemaType<SmilesValue> = {
124
165
  additionalProperties: false,
125
166
  };
126
167
 
127
- // `removeAdditional` strips what `additionalProperties: false` would refuse.
128
- const ajv = new Ajv({ removeAdditional: true });
168
+ // `removeAdditional` strips what `additionalProperties: false` would refuse;
169
+ // a table's cell is a string, a number or null, which is a union of types.
170
+ const ajv = new Ajv({ removeAdditional: true, allowUnionTypes: true });
129
171
 
130
172
  const VALIDATORS: { [K in KnownKind]: ValidateFunction<ValueOf<K>> } = {
131
173
  'chem.molfile': ajv.compile(MOLFILE_SCHEMA),
@@ -135,4 +177,7 @@ const VALIDATORS: { [K in KnownKind]: ValidateFunction<ValueOf<K>> } = {
135
177
  // `nullable` on every optional field and so let a `null` band through.
136
178
  'spectra.ir.jdx': ajv.compile<IrJdxValue>(IR_JDX_SCHEMA),
137
179
  'spectra.ir.peaks': ajv.compile<IrPeaksValue>(IR_PEAKS_SCHEMA),
180
+ 'image.svg': ajv.compile<SvgImageValue>(SVG_IMAGE_SCHEMA),
181
+ 'chem.name': ajv.compile<NameValue>(NAME_SCHEMA),
182
+ 'data.table': ajv.compile<TableValue>(TABLE_SCHEMA),
138
183
  };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The values inside a protocol message, read as the untrusted input they are,
3
+ * on either side of the frame boundary.
4
+ */
5
+
6
+ import type { HostItem } from './protocol.ts';
7
+
8
+ /** How many items one message may carry; the rest are dropped. */
9
+ export const MAX_ITEMS = 64;
10
+
11
+ /** How long a label may be, in characters; a longer one is cut. */
12
+ export const MAX_LABEL_LENGTH = 80;
13
+
14
+ /**
15
+ * Read the items of a message, dropping those without a string `kind`, at
16
+ * most {@link MAX_ITEMS} of them, each label cut to {@link MAX_LABEL_LENGTH}.
17
+ * @param values - The items as they arrived.
18
+ * @returns The items.
19
+ */
20
+ export function readItems(values: readonly unknown[]): HostItem[] {
21
+ const items: HostItem[] = [];
22
+ const count = Math.min(values.length, MAX_ITEMS);
23
+ for (let index = 0; index < count; index++) {
24
+ const value = values[index];
25
+ if (!isRecord(value) || typeof value.kind !== 'string') continue;
26
+ const item: HostItem = { kind: value.kind, value: value.value };
27
+ if (typeof value.id === 'string') item.id = value.id;
28
+ if (typeof value.key === 'string') item.key = value.key;
29
+ if (typeof value.label === 'string') {
30
+ item.label = value.label.slice(0, MAX_LABEL_LENGTH);
31
+ }
32
+ items.push(item);
33
+ }
34
+ return items;
35
+ }
36
+
37
+ /**
38
+ * Read a list of strings, dropping anything else.
39
+ * @param value - The list as it arrived.
40
+ * @returns Its strings, or none when it is not a list.
41
+ */
42
+ export function readStrings(value: unknown): string[] {
43
+ if (!Array.isArray(value)) return [];
44
+ const strings: string[] = [];
45
+ for (const entry of value) {
46
+ if (typeof entry === 'string') strings.push(entry);
47
+ }
48
+ return strings;
49
+ }
50
+
51
+ /**
52
+ * Whether a value is a plain object, as every message is.
53
+ * @param value - The value.
54
+ * @returns `true` for an object that is not an array.
55
+ */
56
+ export function isRecord(value: unknown): value is Record<string, unknown> {
57
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
58
+ }
@@ -10,6 +10,10 @@
10
10
  * arrives as the untrusted input it is.
11
11
  */
12
12
 
13
+ import { isRecord, readItems, readStrings } from './messageValues.ts';
14
+
15
+ export { MAX_ITEMS, MAX_LABEL_LENGTH } from './messageValues.ts';
16
+
13
17
  /** The version a tool speaks; a `connect` naming another is ignored. */
14
18
  export const PROTOCOL_VERSION = 1;
15
19
 
@@ -19,12 +23,6 @@ export const HELLO_TYPE = 'cheminfo:hello';
19
23
  /** The host's answer to `hello`, carrying the port the rest goes through. */
20
24
  export const CONNECT_TYPE = 'cheminfo:connect';
21
25
 
22
- /** How many items one request may carry; the rest are dropped. */
23
- export const MAX_ITEMS = 64;
24
-
25
- /** How long a label may be, in characters; a longer one is cut. */
26
- export const MAX_LABEL_LENGTH = 80;
27
-
28
26
  /** One typed value crossing the frame boundary. */
29
27
  export interface HostItem {
30
28
  /** A kind name, e.g. `'chem.molfile.2d'`. */
@@ -170,7 +168,7 @@ export interface OutputMessage {
170
168
  * Anything that is not a well-formed `load` or `get` is `null`, and goes
171
169
  * unanswered: an unknown request is a newer host talking, not an error. An item
172
170
  * without a string `kind` is dropped, a label is cut to
173
- * {@link MAX_LABEL_LENGTH}, and a `load` without `accept` takes nothing back.
171
+ * `MAX_LABEL_LENGTH`, and a `load` without `accept` takes nothing back.
174
172
  * @param data - What the port delivered.
175
173
  * @returns The request, or `null`.
176
174
  */
@@ -207,33 +205,3 @@ export function isConnect(data: unknown): boolean {
207
205
  data.version === PROTOCOL_VERSION
208
206
  );
209
207
  }
210
-
211
- function readItems(values: readonly unknown[]): HostItem[] {
212
- const items: HostItem[] = [];
213
- const count = Math.min(values.length, MAX_ITEMS);
214
- for (let index = 0; index < count; index++) {
215
- const value = values[index];
216
- if (!isRecord(value) || typeof value.kind !== 'string') continue;
217
- const item: HostItem = { kind: value.kind, value: value.value };
218
- if (typeof value.id === 'string') item.id = value.id;
219
- if (typeof value.key === 'string') item.key = value.key;
220
- if (typeof value.label === 'string') {
221
- item.label = value.label.slice(0, MAX_LABEL_LENGTH);
222
- }
223
- items.push(item);
224
- }
225
- return items;
226
- }
227
-
228
- function readStrings(value: unknown): string[] {
229
- if (!Array.isArray(value)) return [];
230
- const strings: string[] = [];
231
- for (const entry of value) {
232
- if (typeof entry === 'string') strings.push(entry);
233
- }
234
- return strings;
235
- }
236
-
237
- function isRecord(value: unknown): value is Record<string, unknown> {
238
- return typeof value === 'object' && value !== null && !Array.isArray(value);
239
- }