react-cheminfo 0.64.0 → 0.65.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 (640) hide show
  1. package/README.md +282 -0
  2. package/lib/card/core/cardAddress.d.ts +70 -0
  3. package/lib/card/core/cardAddress.d.ts.map +1 -0
  4. package/lib/card/core/cardAddress.js +59 -0
  5. package/lib/card/core/cardAddress.js.map +1 -0
  6. package/lib/card/core/cardPageUrl.d.ts +49 -0
  7. package/lib/card/core/cardPageUrl.d.ts.map +1 -0
  8. package/lib/card/core/cardPageUrl.js +59 -0
  9. package/lib/card/core/cardPageUrl.js.map +1 -0
  10. package/lib/card/core/index.d.ts +7 -0
  11. package/lib/card/core/index.d.ts.map +1 -0
  12. package/lib/card/core/index.js +4 -0
  13. package/lib/card/core/index.js.map +1 -0
  14. package/lib/card/core/panelRoom.d.ts +40 -0
  15. package/lib/card/core/panelRoom.d.ts.map +1 -0
  16. package/lib/card/core/panelRoom.js +40 -0
  17. package/lib/card/core/panelRoom.js.map +1 -0
  18. package/lib/card/ui/CardDetailsButton.d.ts +38 -0
  19. package/lib/card/ui/CardDetailsButton.d.ts.map +1 -0
  20. package/lib/card/ui/CardDetailsButton.js +50 -0
  21. package/lib/card/ui/CardDetailsButton.js.map +1 -0
  22. package/lib/card/ui/CardFigure.d.ts +51 -0
  23. package/lib/card/ui/CardFigure.d.ts.map +1 -0
  24. package/lib/card/ui/CardFigure.js +27 -0
  25. package/lib/card/ui/CardFigure.js.map +1 -0
  26. package/lib/card/ui/CardFrame.d.ts +30 -0
  27. package/lib/card/ui/CardFrame.d.ts.map +1 -0
  28. package/lib/card/ui/CardFrame.js +20 -0
  29. package/lib/card/ui/CardFrame.js.map +1 -0
  30. package/lib/card/ui/CopyTableButton.d.ts +37 -0
  31. package/lib/card/ui/CopyTableButton.d.ts.map +1 -0
  32. package/lib/card/ui/CopyTableButton.js +19 -0
  33. package/lib/card/ui/CopyTableButton.js.map +1 -0
  34. package/lib/card/ui/cardTooltip.d.ts +14 -0
  35. package/lib/card/ui/cardTooltip.d.ts.map +1 -0
  36. package/lib/card/ui/cardTooltip.js +15 -0
  37. package/lib/card/ui/cardTooltip.js.map +1 -0
  38. package/lib/card/ui/embed.d.ts +15 -0
  39. package/lib/card/ui/embed.d.ts.map +1 -0
  40. package/lib/card/ui/embed.js +24 -0
  41. package/lib/card/ui/embed.js.map +1 -0
  42. package/lib/card/ui/fitCardToFrame.d.ts +31 -0
  43. package/lib/card/ui/fitCardToFrame.d.ts.map +1 -0
  44. package/lib/card/ui/fitCardToFrame.js +66 -0
  45. package/lib/card/ui/fitCardToFrame.js.map +1 -0
  46. package/lib/card/ui/holdRoomForPanels.d.ts +16 -0
  47. package/lib/card/ui/holdRoomForPanels.d.ts.map +1 -0
  48. package/lib/card/ui/holdRoomForPanels.js +76 -0
  49. package/lib/card/ui/holdRoomForPanels.js.map +1 -0
  50. package/lib/card/ui/index.d.ts +11 -0
  51. package/lib/card/ui/index.d.ts.map +1 -0
  52. package/lib/card/ui/index.js +7 -0
  53. package/lib/card/ui/index.js.map +1 -0
  54. package/lib/card/ui/openPanels.d.ts +25 -0
  55. package/lib/card/ui/openPanels.d.ts.map +1 -0
  56. package/lib/card/ui/openPanels.js +85 -0
  57. package/lib/card/ui/openPanels.js.map +1 -0
  58. package/lib/card.d.ts +13 -0
  59. package/lib/card.d.ts.map +1 -0
  60. package/lib/card.js +13 -0
  61. package/lib/card.js.map +1 -0
  62. package/lib/conformers.d.ts +1 -0
  63. package/lib/conformers.d.ts.map +1 -1
  64. package/lib/conformers.js +1 -0
  65. package/lib/conformers.js.map +1 -1
  66. package/lib/core.d.ts +4 -0
  67. package/lib/core.d.ts.map +1 -1
  68. package/lib/core.js +5 -0
  69. package/lib/core.js.map +1 -1
  70. package/lib/fetch/core/apiError.d.ts +56 -0
  71. package/lib/fetch/core/apiError.d.ts.map +1 -0
  72. package/lib/fetch/core/apiError.js +43 -0
  73. package/lib/fetch/core/apiError.js.map +1 -0
  74. package/lib/fetch/core/fetchJson.d.ts +47 -0
  75. package/lib/fetch/core/fetchJson.d.ts.map +1 -0
  76. package/lib/fetch/core/fetchJson.js +109 -0
  77. package/lib/fetch/core/fetchJson.js.map +1 -0
  78. package/lib/fetch/core/index.d.ts +5 -0
  79. package/lib/fetch/core/index.d.ts.map +1 -0
  80. package/lib/fetch/core/index.js +3 -0
  81. package/lib/fetch/core/index.js.map +1 -0
  82. package/lib/formula/core/formulaText.d.ts +46 -0
  83. package/lib/formula/core/formulaText.d.ts.map +1 -0
  84. package/lib/formula/core/formulaText.js +74 -0
  85. package/lib/formula/core/formulaText.js.map +1 -0
  86. package/lib/formula/core/index.d.ts +6 -0
  87. package/lib/formula/core/index.d.ts.map +1 -0
  88. package/lib/formula/core/index.js +4 -0
  89. package/lib/formula/core/index.js.map +1 -0
  90. package/lib/formula/core/normalizeFormula.d.ts +22 -0
  91. package/lib/formula/core/normalizeFormula.d.ts.map +1 -0
  92. package/lib/formula/core/normalizeFormula.js +46 -0
  93. package/lib/formula/core/normalizeFormula.js.map +1 -0
  94. package/lib/formula/core/readFormula.d.ts +73 -0
  95. package/lib/formula/core/readFormula.d.ts.map +1 -0
  96. package/lib/formula/core/readFormula.js +132 -0
  97. package/lib/formula/core/readFormula.js.map +1 -0
  98. package/lib/formula/ui/CopyableFormula.d.ts +31 -0
  99. package/lib/formula/ui/CopyableFormula.d.ts.map +1 -0
  100. package/lib/formula/ui/CopyableFormula.js +19 -0
  101. package/lib/formula/ui/CopyableFormula.js.map +1 -0
  102. package/lib/formula/ui/FormulaInput.d.ts +29 -0
  103. package/lib/formula/ui/FormulaInput.d.ts.map +1 -0
  104. package/lib/formula/ui/FormulaInput.js +16 -0
  105. package/lib/formula/ui/FormulaInput.js.map +1 -0
  106. package/lib/formula/ui/QuestionFormula.d.ts +14 -0
  107. package/lib/formula/ui/QuestionFormula.d.ts.map +1 -0
  108. package/lib/formula/ui/QuestionFormula.js +13 -0
  109. package/lib/formula/ui/QuestionFormula.js.map +1 -0
  110. package/lib/formula/ui/index.d.ts +7 -0
  111. package/lib/formula/ui/index.d.ts.map +1 -0
  112. package/lib/formula/ui/index.js +4 -0
  113. package/lib/formula/ui/index.js.map +1 -0
  114. package/lib/formula.d.ts +11 -0
  115. package/lib/formula.d.ts.map +1 -0
  116. package/lib/formula.js +11 -0
  117. package/lib/formula.js.map +1 -0
  118. package/lib/hooks/ui/index.d.ts +1 -0
  119. package/lib/hooks/ui/index.d.ts.map +1 -1
  120. package/lib/hooks/ui/index.js.map +1 -1
  121. package/lib/hooks/ui/keyTargets.d.ts +4 -2
  122. package/lib/hooks/ui/keyTargets.d.ts.map +1 -1
  123. package/lib/hooks/ui/keyTargets.js +5 -3
  124. package/lib/hooks/ui/keyTargets.js.map +1 -1
  125. package/lib/hooks/ui/useAsync.d.ts +20 -5
  126. package/lib/hooks/ui/useAsync.d.ts.map +1 -1
  127. package/lib/hooks/ui/useAsync.js +29 -14
  128. package/lib/hooks/ui/useAsync.js.map +1 -1
  129. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  130. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  131. package/lib/locales/de.json +37 -0
  132. package/lib/locales/en.json +37 -0
  133. package/lib/locales/es.json +37 -0
  134. package/lib/locales/fr.json +37 -0
  135. package/lib/locales/it.json +37 -0
  136. package/lib/molecule3d/core/highlight.d.ts.map +1 -1
  137. package/lib/molecule3d/core/highlight.js +2 -8
  138. package/lib/molecule3d/core/highlight.js.map +1 -1
  139. package/lib/molecule3d/core/index.d.ts +1 -1
  140. package/lib/molecule3d/core/index.d.ts.map +1 -1
  141. package/lib/molecule3d/core/index.js +1 -1
  142. package/lib/molecule3d/core/index.js.map +1 -1
  143. package/lib/molecule3d/core/measurement.d.ts +17 -0
  144. package/lib/molecule3d/core/measurement.d.ts.map +1 -1
  145. package/lib/molecule3d/core/measurement.js +43 -0
  146. package/lib/molecule3d/core/measurement.js.map +1 -1
  147. package/lib/molecule3d/ui/drawScene.d.ts +4 -2
  148. package/lib/molecule3d/ui/drawScene.d.ts.map +1 -1
  149. package/lib/molecule3d/ui/drawScene.js +1 -1
  150. package/lib/molecule3d/ui/drawScene.js.map +1 -1
  151. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts +3 -1
  152. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts.map +1 -1
  153. package/lib/molecule3d/ui/sceneDrawer.d.ts +47 -0
  154. package/lib/molecule3d/ui/sceneDrawer.d.ts.map +1 -0
  155. package/lib/molecule3d/ui/sceneDrawer.js +103 -0
  156. package/lib/molecule3d/ui/sceneDrawer.js.map +1 -0
  157. package/lib/molecule3d/ui/useMoleculeScene.d.ts +2 -1
  158. package/lib/molecule3d/ui/useMoleculeScene.d.ts.map +1 -1
  159. package/lib/molecule3d/ui/useMoleculeScene.js +13 -22
  160. package/lib/molecule3d/ui/useMoleculeScene.js.map +1 -1
  161. package/lib/molecule3d/ui/useSharedCamera.d.ts +1 -3
  162. package/lib/molecule3d/ui/useSharedCamera.d.ts.map +1 -1
  163. package/lib/molecule3d/ui/useSharedCamera.js.map +1 -1
  164. package/lib/moleculesClient/core/index.d.ts +5 -0
  165. package/lib/moleculesClient/core/index.d.ts.map +1 -0
  166. package/lib/moleculesClient/core/index.js +3 -0
  167. package/lib/moleculesClient/core/index.js.map +1 -0
  168. package/lib/moleculesClient/core/moleculesClient.d.ts +12 -0
  169. package/lib/moleculesClient/core/moleculesClient.d.ts.map +1 -0
  170. package/lib/moleculesClient/core/moleculesClient.js +105 -0
  171. package/lib/moleculesClient/core/moleculesClient.js.map +1 -0
  172. package/lib/moleculesClient/core/moleculesClientApi.d.ts +100 -0
  173. package/lib/moleculesClient/core/moleculesClientApi.d.ts.map +1 -0
  174. package/lib/moleculesClient/core/moleculesClientApi.js +20 -0
  175. package/lib/moleculesClient/core/moleculesClientApi.js.map +1 -0
  176. package/lib/moleculesClient/core/moleculesTypes.d.ts +154 -0
  177. package/lib/moleculesClient/core/moleculesTypes.d.ts.map +1 -0
  178. package/lib/moleculesClient/core/moleculesTypes.js +2 -0
  179. package/lib/moleculesClient/core/moleculesTypes.js.map +1 -0
  180. package/lib/moleculesClient/core/requestRetry.d.ts +50 -0
  181. package/lib/moleculesClient/core/requestRetry.d.ts.map +1 -0
  182. package/lib/moleculesClient/core/requestRetry.js +108 -0
  183. package/lib/moleculesClient/core/requestRetry.js.map +1 -0
  184. package/lib/molstar/core/camera.d.ts +2 -1
  185. package/lib/molstar/core/camera.d.ts.map +1 -1
  186. package/lib/molstar/core/camera.js +3 -2
  187. package/lib/molstar/core/camera.js.map +1 -1
  188. package/lib/molstar/core/framing.d.ts +102 -0
  189. package/lib/molstar/core/framing.d.ts.map +1 -0
  190. package/lib/molstar/core/framing.js +120 -0
  191. package/lib/molstar/core/framing.js.map +1 -0
  192. package/lib/molstar/core/hover.d.ts +16 -0
  193. package/lib/molstar/core/hover.d.ts.map +1 -1
  194. package/lib/molstar/core/hover.js +14 -0
  195. package/lib/molstar/core/hover.js.map +1 -1
  196. package/lib/molstar/core/index.d.ts +4 -1
  197. package/lib/molstar/core/index.d.ts.map +1 -1
  198. package/lib/molstar/core/index.js +2 -1
  199. package/lib/molstar/core/index.js.map +1 -1
  200. package/lib/pedagogy/core/answers.d.ts +46 -0
  201. package/lib/pedagogy/core/answers.d.ts.map +1 -0
  202. package/lib/pedagogy/core/answers.js +77 -0
  203. package/lib/pedagogy/core/answers.js.map +1 -0
  204. package/lib/pedagogy/core/attempts.d.ts +86 -0
  205. package/lib/pedagogy/core/attempts.d.ts.map +1 -0
  206. package/lib/pedagogy/core/attempts.js +117 -0
  207. package/lib/pedagogy/core/attempts.js.map +1 -0
  208. package/lib/pedagogy/core/index.d.ts +8 -0
  209. package/lib/pedagogy/core/index.d.ts.map +1 -1
  210. package/lib/pedagogy/core/index.js +4 -0
  211. package/lib/pedagogy/core/index.js.map +1 -1
  212. package/lib/pedagogy/core/progressController.d.ts +64 -0
  213. package/lib/pedagogy/core/progressController.d.ts.map +1 -0
  214. package/lib/pedagogy/core/progressController.js +56 -0
  215. package/lib/pedagogy/core/progressController.js.map +1 -0
  216. package/lib/pedagogy/core/seed.d.ts +96 -0
  217. package/lib/pedagogy/core/seed.d.ts.map +1 -0
  218. package/lib/pedagogy/core/seed.js +128 -0
  219. package/lib/pedagogy/core/seed.js.map +1 -0
  220. package/lib/pedagogy/core/series.d.ts +77 -0
  221. package/lib/pedagogy/core/series.d.ts.map +1 -0
  222. package/lib/pedagogy/core/series.js +10 -0
  223. package/lib/pedagogy/core/series.js.map +1 -0
  224. package/lib/pedagogy/ui/AnswerFields.d.ts +21 -0
  225. package/lib/pedagogy/ui/AnswerFields.d.ts.map +1 -0
  226. package/lib/pedagogy/ui/AnswerFields.js +24 -0
  227. package/lib/pedagogy/ui/AnswerFields.js.map +1 -0
  228. package/lib/pedagogy/ui/ExerciseList.d.ts +82 -0
  229. package/lib/pedagogy/ui/ExerciseList.d.ts.map +1 -0
  230. package/lib/pedagogy/ui/ExerciseList.js +53 -0
  231. package/lib/pedagogy/ui/ExerciseList.js.map +1 -0
  232. package/lib/pedagogy/ui/ExerciseSeries.d.ts +95 -0
  233. package/lib/pedagogy/ui/ExerciseSeries.d.ts.map +1 -0
  234. package/lib/pedagogy/ui/ExerciseSeries.js +74 -0
  235. package/lib/pedagogy/ui/ExerciseSeries.js.map +1 -0
  236. package/lib/pedagogy/ui/QuestionCard.d.ts +64 -0
  237. package/lib/pedagogy/ui/QuestionCard.d.ts.map +1 -0
  238. package/lib/pedagogy/ui/QuestionCard.js +73 -0
  239. package/lib/pedagogy/ui/QuestionCard.js.map +1 -0
  240. package/lib/pedagogy/ui/index.d.ts +10 -0
  241. package/lib/pedagogy/ui/index.d.ts.map +1 -1
  242. package/lib/pedagogy/ui/index.js +6 -0
  243. package/lib/pedagogy/ui/index.js.map +1 -1
  244. package/lib/pedagogy/ui/seriesCounts.d.ts +17 -0
  245. package/lib/pedagogy/ui/seriesCounts.d.ts.map +1 -0
  246. package/lib/pedagogy/ui/seriesCounts.js +27 -0
  247. package/lib/pedagogy/ui/seriesCounts.js.map +1 -0
  248. package/lib/pedagogy/ui/seriesParts.d.ts +55 -0
  249. package/lib/pedagogy/ui/seriesParts.d.ts.map +1 -0
  250. package/lib/pedagogy/ui/seriesParts.js +38 -0
  251. package/lib/pedagogy/ui/seriesParts.js.map +1 -0
  252. package/lib/pedagogy/ui/useAttemptRecords.d.ts +10 -0
  253. package/lib/pedagogy/ui/useAttemptRecords.d.ts.map +1 -0
  254. package/lib/pedagogy/ui/useAttemptRecords.js +11 -0
  255. package/lib/pedagogy/ui/useAttemptRecords.js.map +1 -0
  256. package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
  257. package/lib/periodic/ui/PeriodicTable.js +6 -3
  258. package/lib/periodic/ui/PeriodicTable.js.map +1 -1
  259. package/lib/property/core/copyableText.d.ts +14 -0
  260. package/lib/property/core/copyableText.d.ts.map +1 -0
  261. package/lib/property/core/copyableText.js +21 -0
  262. package/lib/property/core/copyableText.js.map +1 -0
  263. package/lib/property/core/index.d.ts +2 -0
  264. package/lib/property/core/index.d.ts.map +1 -0
  265. package/lib/property/core/index.js +2 -0
  266. package/lib/property/core/index.js.map +1 -0
  267. package/lib/property/ui/PropertyTable.d.ts +43 -0
  268. package/lib/property/ui/PropertyTable.d.ts.map +1 -0
  269. package/lib/property/ui/PropertyTable.js +19 -0
  270. package/lib/property/ui/PropertyTable.js.map +1 -0
  271. package/lib/property/ui/index.d.ts +3 -0
  272. package/lib/property/ui/index.d.ts.map +1 -0
  273. package/lib/property/ui/index.js +2 -0
  274. package/lib/property/ui/index.js.map +1 -0
  275. package/lib/router/core/history.d.ts +24 -3
  276. package/lib/router/core/history.d.ts.map +1 -1
  277. package/lib/router/core/history.js +55 -7
  278. package/lib/router/core/history.js.map +1 -1
  279. package/lib/router/core/index.d.ts +3 -3
  280. package/lib/router/core/index.d.ts.map +1 -1
  281. package/lib/router/core/index.js +2 -2
  282. package/lib/router/core/index.js.map +1 -1
  283. package/lib/router/core/languageRoute.d.ts +61 -0
  284. package/lib/router/core/languageRoute.d.ts.map +1 -0
  285. package/lib/router/core/languageRoute.js +96 -0
  286. package/lib/router/core/languageRoute.js.map +1 -0
  287. package/lib/router/core/siteAddresses.d.ts +23 -0
  288. package/lib/router/core/siteAddresses.d.ts.map +1 -1
  289. package/lib/router/core/siteAddresses.js +26 -0
  290. package/lib/router/core/siteAddresses.js.map +1 -1
  291. package/lib/router/core/tabRouter.d.ts +2 -108
  292. package/lib/router/core/tabRouter.d.ts.map +1 -1
  293. package/lib/router/core/tabRouter.js +38 -5
  294. package/lib/router/core/tabRouter.js.map +1 -1
  295. package/lib/router/core/tabRouterTypes.d.ts +154 -0
  296. package/lib/router/core/tabRouterTypes.d.ts.map +1 -0
  297. package/lib/router/core/tabRouterTypes.js +2 -0
  298. package/lib/router/core/tabRouterTypes.js.map +1 -0
  299. package/lib/seo/core/fitDescription.d.ts +40 -0
  300. package/lib/seo/core/fitDescription.d.ts.map +1 -0
  301. package/lib/seo/core/fitDescription.js +45 -0
  302. package/lib/seo/core/fitDescription.js.map +1 -0
  303. package/lib/seo/core/index.d.ts +7 -0
  304. package/lib/seo/core/index.d.ts.map +1 -1
  305. package/lib/seo/core/index.js +4 -0
  306. package/lib/seo/core/index.js.map +1 -1
  307. package/lib/seo/core/limits.d.ts +24 -0
  308. package/lib/seo/core/limits.d.ts.map +1 -0
  309. package/lib/seo/core/limits.js +24 -0
  310. package/lib/seo/core/limits.js.map +1 -0
  311. package/lib/seo/core/pageContent.d.ts +25 -0
  312. package/lib/seo/core/pageContent.d.ts.map +1 -0
  313. package/lib/seo/core/pageContent.js +25 -0
  314. package/lib/seo/core/pageContent.js.map +1 -0
  315. package/lib/seo/core/plainDescription.d.ts.map +1 -1
  316. package/lib/seo/core/plainDescription.js +3 -2
  317. package/lib/seo/core/plainDescription.js.map +1 -1
  318. package/lib/seo/core/routeProblems.d.ts.map +1 -1
  319. package/lib/seo/core/routeProblems.js +1 -6
  320. package/lib/seo/core/routeProblems.js.map +1 -1
  321. package/lib/seo/core/routeTable.d.ts +31 -0
  322. package/lib/seo/core/routeTable.d.ts.map +1 -0
  323. package/lib/seo/core/routeTable.js +96 -0
  324. package/lib/seo/core/routeTable.js.map +1 -0
  325. package/lib/seo/vite/index.d.ts +2 -0
  326. package/lib/seo/vite/index.d.ts.map +1 -1
  327. package/lib/seo/vite/index.js +1 -0
  328. package/lib/seo/vite/index.js.map +1 -1
  329. package/lib/seo/vite/prerender.d.ts +10 -0
  330. package/lib/seo/vite/prerender.d.ts.map +1 -1
  331. package/lib/seo/vite/prerender.js +12 -1
  332. package/lib/seo/vite/prerender.js.map +1 -1
  333. package/lib/seo/vite/routeTable.d.ts +40 -0
  334. package/lib/seo/vite/routeTable.d.ts.map +1 -0
  335. package/lib/seo/vite/routeTable.js +44 -0
  336. package/lib/seo/vite/routeTable.js.map +1 -0
  337. package/lib/server/answerAddresses.d.ts +51 -0
  338. package/lib/server/answerAddresses.d.ts.map +1 -0
  339. package/lib/server/answerAddresses.js +72 -0
  340. package/lib/server/answerAddresses.js.map +1 -0
  341. package/lib/server/cardMeta.d.ts +57 -0
  342. package/lib/server/cardMeta.d.ts.map +1 -0
  343. package/lib/server/cardMeta.js +52 -0
  344. package/lib/server/cardMeta.js.map +1 -0
  345. package/lib/server/config.d.ts +72 -0
  346. package/lib/server/config.d.ts.map +1 -0
  347. package/lib/server/config.js +67 -0
  348. package/lib/server/config.js.map +1 -0
  349. package/lib/server/envNumber.d.ts +35 -0
  350. package/lib/server/envNumber.d.ts.map +1 -0
  351. package/lib/server/envNumber.js +42 -0
  352. package/lib/server/envNumber.js.map +1 -0
  353. package/lib/server/healthRoute.d.ts +26 -0
  354. package/lib/server/healthRoute.d.ts.map +1 -0
  355. package/lib/server/healthRoute.js +22 -0
  356. package/lib/server/healthRoute.js.map +1 -0
  357. package/lib/server/listenSite.d.ts +38 -0
  358. package/lib/server/listenSite.d.ts.map +1 -0
  359. package/lib/server/listenSite.js +60 -0
  360. package/lib/server/listenSite.js.map +1 -0
  361. package/lib/server/mcpServer.d.ts +8 -0
  362. package/lib/server/mcpServer.d.ts.map +1 -0
  363. package/lib/server/mcpServer.js +11 -0
  364. package/lib/server/mcpServer.js.map +1 -0
  365. package/lib/server/repositoryVersion.d.ts +16 -0
  366. package/lib/server/repositoryVersion.d.ts.map +1 -0
  367. package/lib/server/repositoryVersion.js +33 -0
  368. package/lib/server/repositoryVersion.js.map +1 -0
  369. package/lib/server/routeOptions.d.ts +23 -0
  370. package/lib/server/routeOptions.d.ts.map +1 -0
  371. package/lib/server/routeOptions.js +20 -0
  372. package/lib/server/routeOptions.js.map +1 -0
  373. package/lib/server/routeTable.d.ts +14 -0
  374. package/lib/server/routeTable.d.ts.map +1 -0
  375. package/lib/server/routeTable.js +32 -0
  376. package/lib/server/routeTable.js.map +1 -0
  377. package/lib/server/siteView.d.ts +29 -0
  378. package/lib/server/siteView.d.ts.map +1 -0
  379. package/lib/server/siteView.js +21 -0
  380. package/lib/server/siteView.js.map +1 -0
  381. package/lib/server/spaPages.d.ts +32 -0
  382. package/lib/server/spaPages.d.ts.map +1 -0
  383. package/lib/server/spaPages.js +126 -0
  384. package/lib/server/spaPages.js.map +1 -0
  385. package/lib/server/spaSite.d.ts +30 -0
  386. package/lib/server/spaSite.d.ts.map +1 -0
  387. package/lib/server/spaSite.js +170 -0
  388. package/lib/server/spaSite.js.map +1 -0
  389. package/lib/server/spaSiteOptions.d.ts +126 -0
  390. package/lib/server/spaSiteOptions.d.ts.map +1 -0
  391. package/lib/server/spaSiteOptions.js +2 -0
  392. package/lib/server/spaSiteOptions.js.map +1 -0
  393. package/lib/server/staticSite.d.ts +9 -0
  394. package/lib/server/staticSite.d.ts.map +1 -1
  395. package/lib/server/staticSite.js +41 -19
  396. package/lib/server/staticSite.js.map +1 -1
  397. package/lib/server/toolSiteServer.d.ts +77 -0
  398. package/lib/server/toolSiteServer.d.ts.map +1 -0
  399. package/lib/server/toolSiteServer.js +58 -0
  400. package/lib/server/toolSiteServer.js.map +1 -0
  401. package/lib/server/trustProxy.d.ts +20 -0
  402. package/lib/server/trustProxy.d.ts.map +1 -0
  403. package/lib/server/trustProxy.js +32 -0
  404. package/lib/server/trustProxy.js.map +1 -0
  405. package/lib/server/types.d.ts +13 -0
  406. package/lib/server/types.d.ts.map +1 -0
  407. package/lib/server/types.js +2 -0
  408. package/lib/server/types.js.map +1 -0
  409. package/lib/server.d.ts +22 -0
  410. package/lib/server.d.ts.map +1 -1
  411. package/lib/server.js +12 -0
  412. package/lib/server.js.map +1 -1
  413. package/lib/share/core/config.d.ts +18 -0
  414. package/lib/share/core/config.d.ts.map +1 -1
  415. package/lib/share/core/config.js +33 -2
  416. package/lib/share/core/config.js.map +1 -1
  417. package/lib/share/core/index.d.ts +3 -1
  418. package/lib/share/core/index.d.ts.map +1 -1
  419. package/lib/share/core/index.js +2 -1
  420. package/lib/share/core/index.js.map +1 -1
  421. package/lib/share/core/keySetParam.d.ts +40 -0
  422. package/lib/share/core/keySetParam.d.ts.map +1 -0
  423. package/lib/share/core/keySetParam.js +60 -0
  424. package/lib/share/core/keySetParam.js.map +1 -0
  425. package/lib/share/core/vocabulary.d.ts +8 -0
  426. package/lib/share/core/vocabulary.d.ts.map +1 -1
  427. package/lib/shell/ui/ShareControl.d.ts +75 -0
  428. package/lib/shell/ui/ShareControl.d.ts.map +1 -0
  429. package/lib/shell/ui/ShareControl.js +40 -0
  430. package/lib/shell/ui/ShareControl.js.map +1 -0
  431. package/lib/shell/ui/ShellFrame.d.ts +14 -0
  432. package/lib/shell/ui/ShellFrame.d.ts.map +1 -0
  433. package/lib/shell/ui/ShellFrame.js +45 -0
  434. package/lib/shell/ui/ShellFrame.js.map +1 -0
  435. package/lib/shell/ui/SiteShell.d.ts +251 -0
  436. package/lib/shell/ui/SiteShell.d.ts.map +1 -0
  437. package/lib/shell/ui/SiteShell.js +39 -0
  438. package/lib/shell/ui/SiteShell.js.map +1 -0
  439. package/lib/shell/ui/index.d.ts +5 -0
  440. package/lib/shell/ui/index.d.ts.map +1 -0
  441. package/lib/shell/ui/index.js +3 -0
  442. package/lib/shell/ui/index.js.map +1 -0
  443. package/lib/state/core/index.d.ts +1 -0
  444. package/lib/state/core/index.d.ts.map +1 -1
  445. package/lib/state/core/index.js.map +1 -1
  446. package/lib/state/core/legacyEntries.d.ts +30 -0
  447. package/lib/state/core/legacyEntries.d.ts.map +1 -0
  448. package/lib/state/core/legacyEntries.js +51 -0
  449. package/lib/state/core/legacyEntries.js.map +1 -0
  450. package/lib/state/core/persistBucket.d.ts +26 -2
  451. package/lib/state/core/persistBucket.d.ts.map +1 -1
  452. package/lib/state/core/persistBucket.js +26 -9
  453. package/lib/state/core/persistBucket.js.map +1 -1
  454. package/lib/state/core/persistSignalBucket.d.ts +26 -0
  455. package/lib/state/core/persistSignalBucket.d.ts.map +1 -1
  456. package/lib/state/core/persistSignalBucket.js +31 -0
  457. package/lib/state/core/persistSignalBucket.js.map +1 -1
  458. package/lib/state/core/storageEntry.d.ts +15 -0
  459. package/lib/state/core/storageEntry.d.ts.map +1 -1
  460. package/lib/state/core/storageEntry.js +33 -0
  461. package/lib/state/core/storageEntry.js.map +1 -1
  462. package/lib/structure/ui/StructureExportButton.d.ts +27 -0
  463. package/lib/structure/ui/StructureExportButton.d.ts.map +1 -0
  464. package/lib/structure/ui/StructureExportButton.js +21 -0
  465. package/lib/structure/ui/StructureExportButton.js.map +1 -0
  466. package/lib/structure/ui/index.d.ts +4 -0
  467. package/lib/structure/ui/index.d.ts.map +1 -1
  468. package/lib/structure/ui/index.js +2 -0
  469. package/lib/structure/ui/index.js.map +1 -1
  470. package/lib/structure/ui/useStructureDraft.d.ts +32 -0
  471. package/lib/structure/ui/useStructureDraft.d.ts.map +1 -0
  472. package/lib/structure/ui/useStructureDraft.js +20 -0
  473. package/lib/structure/ui/useStructureDraft.js.map +1 -0
  474. package/lib/ui.d.ts +2 -0
  475. package/lib/ui.d.ts.map +1 -1
  476. package/lib/ui.js +2 -0
  477. package/lib/ui.js.map +1 -1
  478. package/lib/worker/core/index.d.ts +1 -1
  479. package/lib/worker/core/index.d.ts.map +1 -1
  480. package/lib/worker/core/messages.d.ts +4 -2
  481. package/lib/worker/core/messages.d.ts.map +1 -1
  482. package/lib/worker/core/messages.js.map +1 -1
  483. package/lib/worker/core/oclResourcesUrl.d.ts +16 -0
  484. package/lib/worker/core/oclResourcesUrl.d.ts.map +1 -0
  485. package/lib/worker/core/oclResourcesUrl.js +19 -0
  486. package/lib/worker/core/oclResourcesUrl.js.map +1 -0
  487. package/lib/worker/core/serveWorkerRequests.d.ts +8 -0
  488. package/lib/worker/core/serveWorkerRequests.d.ts.map +1 -1
  489. package/lib/worker/core/serveWorkerRequests.js +15 -2
  490. package/lib/worker/core/serveWorkerRequests.js.map +1 -1
  491. package/lib/worker/core/workerChannel.d.ts +3 -4
  492. package/lib/worker/core/workerChannel.d.ts.map +1 -1
  493. package/lib/worker/core/workerChannel.js +72 -67
  494. package/lib/worker/core/workerChannel.js.map +1 -1
  495. package/lib/worker/core/workerChannelParts.d.ts +17 -6
  496. package/lib/worker/core/workerChannelParts.d.ts.map +1 -1
  497. package/lib/worker/core/workerChannelParts.js +20 -4
  498. package/lib/worker/core/workerChannelParts.js.map +1 -1
  499. package/lib/worker/core/workerChannelTypes.d.ts +46 -2
  500. package/lib/worker/core/workerChannelTypes.d.ts.map +1 -1
  501. package/lib/worker/core/workerSlot.d.ts +66 -0
  502. package/lib/worker/core/workerSlot.d.ts.map +1 -0
  503. package/lib/worker/core/workerSlot.js +107 -0
  504. package/lib/worker/core/workerSlot.js.map +1 -0
  505. package/package.json +16 -1
  506. package/src/card/core/cardAddress.ts +100 -0
  507. package/src/card/core/cardPageUrl.ts +97 -0
  508. package/src/card/core/index.ts +6 -0
  509. package/src/card/core/panelRoom.ts +66 -0
  510. package/src/card/ui/CardDetailsButton.tsx +104 -0
  511. package/src/card/ui/CardFigure.tsx +86 -0
  512. package/src/card/ui/CardFrame.tsx +46 -0
  513. package/src/card/ui/CopyTableButton.tsx +81 -0
  514. package/src/card/ui/cardTooltip.ts +18 -0
  515. package/src/card/ui/embed.ts +27 -0
  516. package/src/card/ui/fitCardToFrame.ts +76 -0
  517. package/src/card/ui/holdRoomForPanels.ts +83 -0
  518. package/src/card/ui/index.ts +14 -0
  519. package/src/card/ui/openPanels.ts +106 -0
  520. package/src/card.ts +13 -0
  521. package/src/conformers.ts +4 -0
  522. package/src/core.ts +5 -0
  523. package/src/fetch/core/apiError.ts +65 -0
  524. package/src/fetch/core/fetchJson.ts +129 -0
  525. package/src/fetch/core/index.ts +4 -0
  526. package/src/formula/core/formulaText.ts +96 -0
  527. package/src/formula/core/index.ts +20 -0
  528. package/src/formula/core/normalizeFormula.ts +50 -0
  529. package/src/formula/core/readFormula.ts +211 -0
  530. package/src/formula/ui/CopyableFormula.tsx +51 -0
  531. package/src/formula/ui/FormulaInput.tsx +50 -0
  532. package/src/formula/ui/QuestionFormula.tsx +20 -0
  533. package/src/formula/ui/index.ts +6 -0
  534. package/src/formula.ts +11 -0
  535. package/src/hooks/ui/index.ts +1 -0
  536. package/src/hooks/ui/keyTargets.ts +5 -3
  537. package/src/hooks/ui/useAsync.ts +50 -14
  538. package/src/locales/de.json +37 -0
  539. package/src/locales/en.json +37 -0
  540. package/src/locales/es.json +37 -0
  541. package/src/locales/fr.json +37 -0
  542. package/src/locales/it.json +37 -0
  543. package/src/molecule3d/core/highlight.ts +2 -8
  544. package/src/molecule3d/core/index.ts +1 -0
  545. package/src/molecule3d/core/measurement.ts +47 -0
  546. package/src/molecule3d/ui/drawScene.ts +13 -2
  547. package/src/molecule3d/ui/moleculeViewer3DProps.ts +3 -1
  548. package/src/molecule3d/ui/sceneDrawer.ts +132 -0
  549. package/src/molecule3d/ui/useMoleculeScene.ts +16 -26
  550. package/src/molecule3d/ui/useSharedCamera.ts +1 -3
  551. package/src/moleculesClient/core/index.ts +19 -0
  552. package/src/moleculesClient/core/moleculesClient.ts +175 -0
  553. package/src/moleculesClient/core/moleculesClientApi.ts +120 -0
  554. package/src/moleculesClient/core/moleculesTypes.ts +163 -0
  555. package/src/moleculesClient/core/requestRetry.ts +118 -0
  556. package/src/molstar/core/camera.ts +3 -2
  557. package/src/molstar/core/framing.ts +200 -0
  558. package/src/molstar/core/hover.ts +26 -0
  559. package/src/molstar/core/index.ts +21 -1
  560. package/src/pedagogy/core/answers.ts +94 -0
  561. package/src/pedagogy/core/attempts.ts +205 -0
  562. package/src/pedagogy/core/index.ts +36 -0
  563. package/src/pedagogy/core/progressController.ts +116 -0
  564. package/src/pedagogy/core/seed.ts +177 -0
  565. package/src/pedagogy/core/series.ts +82 -0
  566. package/src/pedagogy/ui/AnswerFields.tsx +63 -0
  567. package/src/pedagogy/ui/ExerciseList.tsx +202 -0
  568. package/src/pedagogy/ui/ExerciseSeries.tsx +250 -0
  569. package/src/pedagogy/ui/QuestionCard.tsx +231 -0
  570. package/src/pedagogy/ui/index.ts +18 -0
  571. package/src/pedagogy/ui/seriesCounts.ts +34 -0
  572. package/src/pedagogy/ui/seriesParts.tsx +127 -0
  573. package/src/pedagogy/ui/useAttemptRecords.ts +16 -0
  574. package/src/periodic/ui/PeriodicTable.tsx +6 -3
  575. package/src/property/core/copyableText.ts +20 -0
  576. package/src/property/core/index.ts +1 -0
  577. package/src/property/ui/PropertyTable.tsx +83 -0
  578. package/src/property/ui/index.ts +2 -0
  579. package/src/router/core/history.ts +61 -7
  580. package/src/router/core/index.ts +3 -2
  581. package/src/router/core/languageRoute.ts +136 -0
  582. package/src/router/core/siteAddresses.ts +38 -0
  583. package/src/router/core/tabRouter.ts +59 -117
  584. package/src/router/core/tabRouterTypes.ts +158 -0
  585. package/src/seo/core/fitDescription.ts +74 -0
  586. package/src/seo/core/index.ts +17 -0
  587. package/src/seo/core/limits.ts +27 -0
  588. package/src/seo/core/pageContent.ts +42 -0
  589. package/src/seo/core/plainDescription.ts +4 -2
  590. package/src/seo/core/routeProblems.ts +1 -7
  591. package/src/seo/core/routeTable.ts +103 -0
  592. package/src/seo/vite/index.ts +2 -0
  593. package/src/seo/vite/prerender.ts +26 -1
  594. package/src/seo/vite/routeTable.ts +79 -0
  595. package/src/server/answerAddresses.ts +92 -0
  596. package/src/server/cardMeta.ts +88 -0
  597. package/src/server/config.ts +125 -0
  598. package/src/server/envNumber.ts +65 -0
  599. package/src/server/healthRoute.ts +42 -0
  600. package/src/server/listenSite.ts +90 -0
  601. package/src/server/mcpServer.ts +14 -0
  602. package/src/server/repositoryVersion.ts +33 -0
  603. package/src/server/routeOptions.ts +26 -0
  604. package/src/server/routeTable.ts +35 -0
  605. package/src/server/siteView.ts +42 -0
  606. package/src/server/spaPages.ts +179 -0
  607. package/src/server/spaSite.ts +216 -0
  608. package/src/server/spaSiteOptions.ts +133 -0
  609. package/src/server/staticSite.ts +65 -35
  610. package/src/server/toolSiteServer.ts +127 -0
  611. package/src/server/trustProxy.ts +32 -0
  612. package/src/server/types.ts +25 -0
  613. package/src/server.ts +40 -0
  614. package/src/share/core/config.ts +45 -2
  615. package/src/share/core/index.ts +4 -0
  616. package/src/share/core/keySetParam.ts +92 -0
  617. package/src/share/core/vocabulary.ts +8 -0
  618. package/src/shell/ui/ShareControl.tsx +150 -0
  619. package/src/shell/ui/ShellFrame.tsx +180 -0
  620. package/src/shell/ui/SiteShell.tsx +297 -0
  621. package/src/shell/ui/index.ts +9 -0
  622. package/src/state/core/index.ts +1 -0
  623. package/src/state/core/legacyEntries.ts +76 -0
  624. package/src/state/core/persistBucket.ts +50 -10
  625. package/src/state/core/persistSignalBucket.ts +52 -0
  626. package/src/state/core/storageEntry.ts +32 -0
  627. package/src/structure/ui/StructureExportButton.tsx +57 -0
  628. package/src/structure/ui/index.ts +4 -0
  629. package/src/structure/ui/useStructureDraft.ts +47 -0
  630. package/src/ui.ts +2 -0
  631. package/src/worker/core/index.ts +1 -0
  632. package/src/worker/core/messages.ts +4 -3
  633. package/src/worker/core/oclResourcesUrl.ts +21 -0
  634. package/src/worker/core/serveWorkerRequests.ts +30 -2
  635. package/src/worker/core/workerChannel.ts +74 -74
  636. package/src/worker/core/workerChannelParts.ts +33 -13
  637. package/src/worker/core/workerChannelTypes.ts +47 -2
  638. package/src/worker/core/workerSlot.ts +181 -0
  639. package/styles/card.css +145 -0
  640. package/styles/chrome.css +248 -0
@@ -0,0 +1,47 @@
1
+ import { useCallback, useState } from 'react';
2
+
3
+ /** What a structure editor is drawing, and how a page reloads it. */
4
+ export interface StructureDraft<TValue> {
5
+ /** What the canvas holds: the structure last loaded or last drawn. */
6
+ value: TValue;
7
+ /**
8
+ * What `StructureEditor` takes as `revision`: it reloads `value` into the
9
+ * canvas each time this changes, and only then.
10
+ */
11
+ revision: number;
12
+ /**
13
+ * Put a structure in the canvas, replacing what is drawn: an example, the
14
+ * query a dialog is opened on, a Clear button loading the empty string.
15
+ * @param value - The structure, as the editor's `inputFormat` reads it.
16
+ */
17
+ load: (value: TValue) => void;
18
+ /**
19
+ * Keep what the editor drew, without reloading the canvas: what its
20
+ * `onChange` hands over. The same value twice changes nothing.
21
+ * @param value - The structure the editor reports.
22
+ */
23
+ update: (value: TValue) => void;
24
+ }
25
+
26
+ /**
27
+ * The draft a `StructureEditor` is fed: what it draws, and the revision that
28
+ * makes it reload. The editor is uncontrolled, so feeding every stroke back
29
+ * into it would replace the structure under the pen; this keeps the drawing
30
+ * out of the canvas until the page means to load one.
31
+ * @param initial - What the canvas opens on.
32
+ * @returns The draft, and the two ways to change it.
33
+ */
34
+ export function useStructureDraft<TValue = string>(
35
+ initial: TValue,
36
+ ): StructureDraft<TValue> {
37
+ const [draft, setDraft] = useState({ value: initial, revision: 0 });
38
+ const load = useCallback((value: TValue) => {
39
+ setDraft((previous) => ({ value, revision: previous.revision + 1 }));
40
+ }, []);
41
+ const update = useCallback((value: TValue) => {
42
+ setDraft((previous) =>
43
+ Object.is(previous.value, value) ? previous : { ...previous, value },
44
+ );
45
+ }, []);
46
+ return { value: draft.value, revision: draft.revision, load, update };
47
+ }
package/src/ui.ts CHANGED
@@ -27,12 +27,14 @@ export * from './parallel/ui/index.ts';
27
27
  export * from './pedagogy/ui/index.ts';
28
28
  export * from './periodic/ui/index.ts';
29
29
  export * from './projection/ui/index.ts';
30
+ export * from './property/ui/index.ts';
30
31
  export * from './range/ui/index.ts';
31
32
  export * from './router/ui/index.ts';
32
33
  export * from './scatter/ui/index.ts';
33
34
  export * from './scatter3d/ui/index.ts';
34
35
  export * from './share/ui/index.ts';
35
36
  export * from './shared/ui/index.ts';
37
+ export * from './shell/ui/index.ts';
36
38
  export * from './split/ui/index.ts';
37
39
  export * from './taxonomy/ui/index.ts';
38
40
  // The conformer table, from the structure module's file rather than its
@@ -18,6 +18,7 @@ export { createWorkerChannel } from './workerChannel.ts';
18
18
  export type {
19
19
  WorkerChannel,
20
20
  WorkerChannelOptions,
21
+ WorkerFailure,
21
22
  WorkerJobContext,
22
23
  WorkerRequestOptions,
23
24
  WorkerSchedule,
@@ -27,12 +27,13 @@ export interface WorkerProgressMessage<TProgress> {
27
27
 
28
28
  /**
29
29
  * What a worker posts once a job is over. An `Error` does not survive the
30
- * boundary, so a failure travels as its message and becomes an `Error` again
31
- * on this side.
30
+ * boundary, so a failure travels as its message — plus, when the worker was
31
+ * told how, a `detail` the page reads to say it in its own words — and becomes
32
+ * an `Error` again on this side.
32
33
  */
33
34
  export type WorkerResponseMessage<TResponse> =
34
35
  | { id: number; ok: true; response: TResponse }
35
- | { id: number; ok: false; message: string };
36
+ | { id: number; ok: false; message: string; detail?: unknown };
36
37
 
37
38
  /**
38
39
  * As much of a `Worker` as a channel uses. A real `Worker` satisfies it, and so
@@ -0,0 +1,21 @@
1
+ /** The file OpenChemLib's static resources are served as, at the site's root. */
2
+ export const OCL_RESOURCES_FILE = 'openchemlib-resources.json';
3
+
4
+ /**
5
+ * Where OpenChemLib's static resources sit, as this page is mounted.
6
+ *
7
+ * A worker fetches them, but a worker has no `document` and so cannot read the
8
+ * `<base>` the page carries, and its own script address is no help either: it
9
+ * sits under `assets/` in the build and under `src/` in development. So the
10
+ * page resolves the address and posts it with the job — the argument
11
+ * `registerResources` needs in a worker.
12
+ * @param file - The file, relative to the site's own root.
13
+ * @returns The absolute address, or `undefined` outside a page, where
14
+ * `registerResources` reads the file from the installed package instead.
15
+ */
16
+ export function oclResourcesUrl(
17
+ file: string = OCL_RESOURCES_FILE,
18
+ ): string | undefined {
19
+ const baseUri = globalThis.document?.baseURI;
20
+ return baseUri ? new URL(file, baseUri).href : undefined;
21
+ }
@@ -37,6 +37,14 @@ export interface ServeWorkerRequestsOptions<TRequest, TResponse> {
37
37
  * @default undefined — every answer is copied
38
38
  */
39
39
  transfer?: (response: TResponse) => Transferable[];
40
+ /**
41
+ * What a failed answer carries besides its message, for the page's channel
42
+ * to word the failure in its own language — the key of a translatable
43
+ * message and its values, say. It must survive being posted; answering
44
+ * `undefined` adds nothing.
45
+ * @default undefined — a failure carries its message alone
46
+ */
47
+ detail?: (error: unknown) => unknown;
40
48
  }
41
49
 
42
50
  /**
@@ -59,7 +67,7 @@ export function serveWorkerRequests<TRequest, TResponse, TProgress = never>(
59
67
  ) => TResponse | Promise<TResponse>,
60
68
  options: ServeWorkerRequestsOptions<TRequest, TResponse> = {},
61
69
  ): boolean {
62
- const { accepts, transfer } = options;
70
+ const { accepts, transfer, detail } = options;
63
71
  const scope = options.scope ?? dedicatedWorkerScope();
64
72
  if (scope === undefined) return false;
65
73
  const running = new Map<number, AbortController>();
@@ -99,7 +107,15 @@ export function serveWorkerRequests<TRequest, TResponse, TProgress = never>(
99
107
  answer(scope, { id, ok: true, response }, transfer);
100
108
  },
101
109
  (error: unknown) => {
102
- answer(scope, { id, ok: false, message: errorMessage(error) });
110
+ const message = errorMessage(error);
111
+ const extra =
112
+ detail === undefined ? undefined : describe(detail, error);
113
+ answer(
114
+ scope,
115
+ extra === undefined
116
+ ? { id, ok: false, message }
117
+ : { id, ok: false, message, detail: extra },
118
+ );
103
119
  },
104
120
  )
105
121
  .finally(() => {
@@ -127,6 +143,18 @@ function answer<TResponse>(
127
143
  }
128
144
  }
129
145
 
146
+ function describe(
147
+ detail: (error: unknown) => unknown,
148
+ error: unknown,
149
+ ): unknown {
150
+ try {
151
+ return detail(error);
152
+ } catch {
153
+ // A detail that cannot be worked out leaves the message to say it all.
154
+ return undefined;
155
+ }
156
+ }
157
+
130
158
  function dedicatedWorkerScope(): WorkerScopeLike | undefined {
131
159
  const candidate = globalThis as {
132
160
  postMessage?: unknown;
@@ -1,7 +1,7 @@
1
1
  import { toError } from '../../error/core/toError.ts';
2
2
 
3
3
  import { CancelledRequestError, RequestTimeoutError } from './errors.ts';
4
- import type { WorkerLike, WorkerRequestMessage } from './messages.ts';
4
+ import type { WorkerRequestMessage } from './messages.ts';
5
5
  import type {
6
6
  Outcome,
7
7
  PendingRequest,
@@ -12,7 +12,6 @@ import {
12
12
  positiveMilliseconds,
13
13
  postCancel,
14
14
  runJobInProcess,
15
- subscribeToWorker,
16
15
  watchRequest,
17
16
  } from './workerChannelParts.ts';
18
17
  import type {
@@ -21,6 +20,7 @@ import type {
21
20
  WorkerRequestOptions,
22
21
  WorkerSource,
23
22
  } from './workerChannelTypes.ts';
23
+ import { createWorkerSlot } from './workerSlot.ts';
24
24
 
25
25
  /**
26
26
  * Turn a worker into something a page can await.
@@ -30,10 +30,9 @@ import type {
30
30
  * — cancelled, superseded, timed out, or failed — drops out of the pending map
31
31
  * at that moment. The worker may post progress about a job while it runs.
32
32
  *
33
- * Handed a worker, the channel posts to it and terminates it when asked, but
34
- * never creates one. Handed a function, it creates the worker on the first
35
- * request, replaces one that failed or was terminated, and can fall back to an
36
- * in-process run where there is no `Worker`.
33
+ * Handed a worker, the channel posts to it and terminates it when asked. Handed
34
+ * a function, it creates the worker when needed and can run the job in-process
35
+ * instead; see `createWorkerSlot`.
37
36
  * @param source - The worker, or the function that creates it.
38
37
  * @param options - See {@link WorkerChannelOptions}.
39
38
  * @returns The channel.
@@ -43,38 +42,44 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
43
42
  source: WorkerSource,
44
43
  options: WorkerChannelOptions<TRequest, TResponse, TProgress> = {},
45
44
  ): WorkerChannel<TRequest, TResponse, TProgress> {
46
- const {
47
- name = 'worker',
48
- schedule = 'parallel',
49
- cooperativeCancel = false,
50
- defaultTimeoutMs,
51
- runInProcess,
52
- } = options;
45
+ const { name = 'worker', schedule = 'parallel' } = options;
46
+ const { cooperativeCancel = false, retryAfterWorkerFailure } = options;
47
+ const { defaultTimeoutMs, runInProcess, failure } = options;
53
48
  const fallbackTimeoutMs = positiveMilliseconds(
54
49
  defaultTimeoutMs,
55
50
  DEFAULT_TIMEOUT_MS,
56
51
  );
57
- const factory = typeof source === 'function' ? source : undefined;
58
- if (schedule === 'restart' && factory === undefined) {
52
+ if (schedule === 'restart' && typeof source !== 'function') {
59
53
  throw new Error(`${name}: the restart schedule needs a worker factory`);
60
54
  }
61
- const hasNoWorker = !('Worker' in globalThis);
62
- const runLocally = factory && hasNoWorker ? runInProcess : undefined;
55
+ const retries = typeof source === 'function' && retryAfterWorkerFailure;
63
56
 
64
57
  const pending = new Map<number, PendingRequest<TResponse, TProgress>>();
65
- let worker: WorkerLike | null = null;
58
+ const posted = new Map<number, QueuedRequest<TRequest>>();
59
+ const retried = new Set<number>();
66
60
  let closed = false;
67
61
  let nextId = 0;
68
62
  let activeId: number | null = null;
69
63
  let queued: QueuedRequest<TRequest> | null = null;
70
- if (typeof source !== 'function') {
71
- worker = source;
72
- listen(source);
73
- }
64
+ const slot = createWorkerSlot<TRequest, TResponse, TProgress>(source, {
65
+ name,
66
+ runInProcess,
67
+ failure,
68
+ isWaited: (id) => pending.has(id),
69
+ report: {
70
+ progress: (id, progress) => {
71
+ pending.get(id)?.onProgress?.(progress as TProgress);
72
+ },
73
+ answer: (id, outcome) => complete(id, outcome),
74
+ failure: (error) => workerFailed(error),
75
+ },
76
+ });
74
77
 
75
78
  function take(id: number): PendingRequest<TResponse, TProgress> | undefined {
76
79
  const entry = pending.get(id);
77
80
  pending.delete(id);
81
+ posted.delete(id);
82
+ retried.delete(id);
78
83
  entry?.dispose();
79
84
  return entry;
80
85
  }
@@ -93,7 +98,7 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
93
98
  const entry = take(id);
94
99
  if (entry === undefined) return false;
95
100
  entry.controller?.abort();
96
- if (cooperativeCancel && entry.dispatched) postCancel(worker, id);
101
+ if (cooperativeCancel && entry.dispatched) postCancel(slot.current, id);
97
102
  entry.reject(error);
98
103
  return true;
99
104
  }
@@ -106,22 +111,18 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
106
111
  }
107
112
 
108
113
  function rejectAll(error: Error): void {
109
- for (const entry of pending.values()) {
110
- entry.dispose();
114
+ for (const [id, entry] of pending) {
115
+ take(id);
111
116
  entry.controller?.abort();
112
117
  entry.reject(error);
113
118
  }
114
- pending.clear();
115
119
  activeId = null;
116
120
  queued = null;
117
121
  }
118
122
 
119
123
  function abandonActive(): void {
120
124
  activeId = null;
121
- if (factory !== undefined && worker !== null) {
122
- worker.terminate();
123
- worker = null;
124
- }
125
+ slot.abandon();
125
126
  }
126
127
 
127
128
  function startQueued(): void {
@@ -135,55 +136,55 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
135
136
  if (entry === undefined) return;
136
137
  entry.dispatched = true;
137
138
  if (schedule !== 'parallel') activeId = id;
138
- if (runLocally !== undefined) {
139
- entry.controller = runJobInProcess(
140
- runLocally,
141
- payload,
142
- (progress) => pending.get(id)?.onProgress?.(progress),
143
- (outcome) => complete(id, outcome),
144
- );
145
- return;
146
- }
147
- const message: WorkerRequestMessage<TRequest> = { id, request: payload };
148
139
  try {
149
- const target = currentWorker();
150
- if (transfer === undefined) target.postMessage(message);
151
- else target.postMessage(message, transfer);
140
+ const target = slot.acquire();
141
+ if (target !== null) {
142
+ if (retries && transfer === undefined) {
143
+ posted.set(id, { id, payload, transfer });
144
+ }
145
+ const message: WorkerRequestMessage<TRequest> = {
146
+ id,
147
+ request: payload,
148
+ };
149
+ if (transfer === undefined) target.postMessage(message);
150
+ else target.postMessage(message, transfer);
151
+ return;
152
+ }
152
153
  } catch (error) {
153
154
  complete(id, { ok: false, error: toError(error) });
155
+ return;
154
156
  }
157
+ entry.controller = runJobInProcess(
158
+ slot.runLocally,
159
+ payload,
160
+ (progress) => pending.get(id)?.onProgress?.(progress),
161
+ (outcome) => complete(id, outcomeOf(outcome)),
162
+ );
155
163
  }
156
164
 
157
- function currentWorker(): WorkerLike {
158
- if (worker === null) {
159
- if (factory === undefined) {
160
- throw new CancelledRequestError(`${name} was terminated`);
161
- }
162
- worker = factory();
163
- listen(worker);
164
- }
165
- return worker;
165
+ function outcomeOf(outcome: Outcome<TResponse>): Outcome<TResponse> {
166
+ return outcome.ok
167
+ ? outcome
168
+ : { ok: false, error: slot.jobFailed(outcome.error) };
166
169
  }
167
170
 
168
- function listen(target: WorkerLike): void {
169
- subscribeToWorker(target, {
170
- progress: (id, progress) => {
171
- if (target !== worker) return;
172
- pending.get(id)?.onProgress?.(progress as TProgress);
173
- },
174
- answer: (id, outcome) => {
175
- if (target === worker) complete(id, outcome as Outcome<TResponse>);
176
- },
177
- failure: (detail) => {
178
- if (target !== worker) return;
179
- if (factory !== undefined) {
180
- target.terminate();
181
- worker = null;
182
- }
183
- const suffix = detail === '' ? '' : `: ${detail}`;
184
- rejectAll(new Error(`${name} failed${suffix}`));
185
- },
186
- });
171
+ function workerFailed(error: Error): void {
172
+ if (!retries) {
173
+ rejectAll(error);
174
+ return;
175
+ }
176
+ activeId = null;
177
+ for (const [id, entry] of pending) {
178
+ if (!entry.dispatched) continue;
179
+ const job = posted.get(id);
180
+ if (job === undefined || retried.has(id)) {
181
+ drop(id, error);
182
+ continue;
183
+ }
184
+ retried.add(id);
185
+ dispatch(id, job.payload);
186
+ }
187
+ if (activeId === null) startQueued();
187
188
  }
188
189
 
189
190
  function expire(id: number, budget: number): void {
@@ -242,9 +243,8 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
242
243
  cancel: () => dropAll('was cancelled'),
243
244
  terminate: () => {
244
245
  rejectAll(new CancelledRequestError(`${name} was terminated`));
245
- worker?.terminate();
246
- if (factory === undefined) closed = true;
247
- else worker = null;
246
+ slot.terminate();
247
+ if (!slot.hasFactory) closed = true;
248
248
  },
249
249
  };
250
250
  }
@@ -1,8 +1,12 @@
1
1
  import { toError } from '../../error/core/toError.ts';
2
2
 
3
- import type { WorkerLike } from './messages.ts';
3
+ import type {
4
+ WorkerEventLike,
5
+ WorkerLike,
6
+ WorkerResponseMessage,
7
+ } from './messages.ts';
4
8
  import { isProgressMessage, isResponseMessage } from './messages.ts';
5
- import type { WorkerJobContext } from './workerChannelTypes.ts';
9
+ import type { WorkerFailure, WorkerJobContext } from './workerChannelTypes.ts';
6
10
 
7
11
  /** How long a request waits when neither the call nor the channel says. */
8
12
  export const DEFAULT_TIMEOUT_MS = 120_000;
@@ -62,10 +66,13 @@ export type Outcome<TResponse> =
62
66
  interface WorkerMessageHandlers {
63
67
  /** News about a running job. */
64
68
  progress: (id: number, progress: unknown) => void;
65
- /** The end of a job. */
66
- answer: (id: number, outcome: Outcome<unknown>) => void;
67
- /** The worker failed outright, with what it said, possibly nothing. */
68
- failure: (detail: string) => void;
69
+ /** The end of a job, as the worker posted it. */
70
+ answer: (id: number, message: WorkerResponseMessage<unknown>) => void;
71
+ /**
72
+ * The worker failed outright, with what it said — possibly nothing — and
73
+ * the error event itself.
74
+ */
75
+ failure: (detail: string, event: WorkerEventLike) => void;
69
76
  }
70
77
 
71
78
  /**
@@ -121,19 +128,32 @@ export function subscribeToWorker(
121
128
  if (isProgressMessage(message)) {
122
129
  handlers.progress(message.id, message.progress);
123
130
  } else if (isResponseMessage(message)) {
124
- handlers.answer(
125
- message.id,
126
- message.ok
127
- ? { ok: true, response: message.response }
128
- : { ok: false, error: new Error(message.message) },
129
- );
131
+ handlers.answer(message.id, message);
130
132
  }
131
133
  });
132
134
  target.addEventListener('error', (event) => {
133
- handlers.failure(event.message ?? '');
135
+ handlers.failure(event.message ?? '', event);
134
136
  });
135
137
  }
136
138
 
139
+ /**
140
+ * The error a failure rejects its requests with when the channel is given no
141
+ * `failure` of its own: the job's own error or message, `<name> failed: …` for
142
+ * a worker that died, and what creating the worker threw.
143
+ * @param failure - What went wrong.
144
+ * @returns The error.
145
+ */
146
+ export function defaultFailureError(failure: WorkerFailure): Error {
147
+ if (failure.kind === 'worker') {
148
+ const suffix = failure.message === '' ? '' : `: ${failure.message}`;
149
+ return new Error(`${failure.name} failed${suffix}`);
150
+ }
151
+ if (failure.cause instanceof Error) return failure.cause;
152
+ return failure.kind === 'job'
153
+ ? new Error(failure.message)
154
+ : toError(failure.cause);
155
+ }
156
+
137
157
  /**
138
158
  * Run one job on this thread as a worker would: with a signal the channel
139
159
  * aborts, progress routed back, and every outcome — a throw included —
@@ -63,14 +63,59 @@ export interface WorkerChannelOptions<TRequest, TResponse, TProgress = never> {
63
63
  cooperativeCancel?: boolean;
64
64
  /**
65
65
  * The same job run on this thread, used instead of the worker where the page
66
- * has no `Worker` at all — Node.js, a unit test. Only a channel built from a
67
- * function that creates the worker falls back to it.
66
+ * has no `Worker` at all — Node.js, a unit test — or where creating one
67
+ * throws, as a browser refuses a page framed under an opaque origin a worker
68
+ * from its own server; every later job then runs here too. Only a channel
69
+ * built from a function that creates the worker falls back to it.
68
70
  * @default undefined — every job goes to the worker
69
71
  */
70
72
  runInProcess?: (
71
73
  request: TRequest,
72
74
  context: WorkerJobContext<TProgress>,
73
75
  ) => Promise<TResponse>;
76
+ /**
77
+ * Turn what went wrong into the error the requests reject with, so a page
78
+ * can say it in its own words — a translated message, an error class of its
79
+ * own. Answering `undefined` keeps the default error. Cancellations and
80
+ * timeouts are not failures: they keep their own error classes.
81
+ * @default undefined — the job's message, or `<name> failed: …`
82
+ */
83
+ failure?: (failure: WorkerFailure) => Error | undefined;
84
+ /**
85
+ * Post a job again, once, on a fresh worker when its worker failed before
86
+ * answering, rather than reporting the failure: a worker whose module graph
87
+ * was still loading when the channel replaced it dies without having run
88
+ * anything. A job posted with buffers to transfer is not posted twice. Only
89
+ * a channel built from a function that creates the worker can do it.
90
+ * @default false
91
+ */
92
+ retryAfterWorkerFailure?: boolean;
93
+ }
94
+
95
+ /** What went wrong, before it becomes the error a request rejects with. */
96
+ export interface WorkerFailure {
97
+ /**
98
+ * `job`: the job failed — its worker answered with a failure, or its
99
+ * in-process run threw. `worker`: the worker itself failed outright; an
100
+ * empty `message` means it never ran at all, its module graph not loading.
101
+ * `start`: creating the worker threw, and no in-process run stood in.
102
+ */
103
+ kind: 'job' | 'worker' | 'start';
104
+ /** The channel's name, e.g. `conformers`. */
105
+ name: string;
106
+ /** What was said: the job's message, the error event's, or the thrown error's. */
107
+ message: string;
108
+ /**
109
+ * The `detail` a failed answer carried, as `serveWorkerRequests` was told to
110
+ * write it — the key of a translatable message, say.
111
+ * @default undefined
112
+ */
113
+ detail?: unknown;
114
+ /**
115
+ * What the failure came with: the failed answer the worker posted, the error
116
+ * the in-process run threw, the error event, or what the factory threw.
117
+ */
118
+ cause: unknown;
74
119
  }
75
120
 
76
121
  /** What one call may ask of the channel. */