@kritzel/engine 0.4.31

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 (373) hide show
  1. package/LICENSE.md +50 -0
  2. package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
  3. package/dist/cjs/engine.constants-CakmdKMW.js +28206 -0
  4. package/dist/cjs/index-BbbWU2aN.js +1742 -0
  5. package/dist/cjs/index.cjs.js +4232 -0
  6. package/dist/cjs/kritzel-awareness-cursors_5.cjs.entry.js +28004 -0
  7. package/dist/cjs/loader.cjs.js +13 -0
  8. package/dist/cjs/stencil.cjs.js +25 -0
  9. package/dist/collection/classes/core/core.class.js +1389 -0
  10. package/dist/collection/classes/core/reviver.class.js +124 -0
  11. package/dist/collection/classes/core/store.class.js +337 -0
  12. package/dist/collection/classes/core/viewport.class.js +794 -0
  13. package/dist/collection/classes/core/workspace.class.js +112 -0
  14. package/dist/collection/classes/handlers/base.handler.js +20 -0
  15. package/dist/collection/classes/handlers/context-menu.handler.js +170 -0
  16. package/dist/collection/classes/handlers/hover.handler.js +35 -0
  17. package/dist/collection/classes/handlers/key.handler.js +162 -0
  18. package/dist/collection/classes/handlers/line-handle.handler.js +475 -0
  19. package/dist/collection/classes/handlers/move.handler.js +295 -0
  20. package/dist/collection/classes/handlers/resize.handler.js +327 -0
  21. package/dist/collection/classes/handlers/rotation.handler.js +174 -0
  22. package/dist/collection/classes/handlers/selection.handler.js +526 -0
  23. package/dist/collection/classes/managers/anchor.manager.js +1476 -0
  24. package/dist/collection/classes/managers/browser-permission.manager.js +64 -0
  25. package/dist/collection/classes/managers/clipboard.manager.js +346 -0
  26. package/dist/collection/classes/managers/clipboard.types.js +1 -0
  27. package/dist/collection/classes/managers/cursor.manager.js +139 -0
  28. package/dist/collection/classes/managers/license.manager.js +341 -0
  29. package/dist/collection/classes/managers/localization.manager.js +227 -0
  30. package/dist/collection/classes/managers/theme.manager.js +206 -0
  31. package/dist/collection/classes/objects/base-object.class.js +462 -0
  32. package/dist/collection/classes/objects/dynamic-object.class.js +437 -0
  33. package/dist/collection/classes/objects/group.class.js +590 -0
  34. package/dist/collection/classes/objects/image.class.js +500 -0
  35. package/dist/collection/classes/objects/line.class.js +789 -0
  36. package/dist/collection/classes/objects/path.class.js +578 -0
  37. package/dist/collection/classes/objects/selection-box.class.js +32 -0
  38. package/dist/collection/classes/objects/selection-group.class.js +752 -0
  39. package/dist/collection/classes/objects/shape.class.js +628 -0
  40. package/dist/collection/classes/objects/text.class.js +461 -0
  41. package/dist/collection/classes/providers/assets/asset-resolver.class.js +536 -0
  42. package/dist/collection/classes/providers/assets/http-asset-provider.class.js +111 -0
  43. package/dist/collection/classes/providers/assets/indexeddb-asset-provider.class.js +241 -0
  44. package/dist/collection/classes/providers/assets/presigned-asset-provider.class.js +86 -0
  45. package/dist/collection/classes/providers/paste-intent/event-paste-intent.provider.js +48 -0
  46. package/dist/collection/classes/providers/paste-intent/ios-paste-intent.provider.js +16 -0
  47. package/dist/collection/classes/providers/paste-intent/navigator-paste-intent.provider.js +86 -0
  48. package/dist/collection/classes/providers/sync/broadcast-sync-provider.class.js +100 -0
  49. package/dist/collection/classes/providers/sync/hocuspocus-sync-provider.class.js +333 -0
  50. package/dist/collection/classes/providers/sync/in-memory-sync-provider.class.js +69 -0
  51. package/dist/collection/classes/providers/sync/indexeddb-sync-provider.class.js +39 -0
  52. package/dist/collection/classes/providers/sync/websocket-sync-provider.class.js +110 -0
  53. package/dist/collection/classes/registries/dynamic-object-renderer.registry.js +52 -0
  54. package/dist/collection/classes/registries/font-registry.class.js +161 -0
  55. package/dist/collection/classes/registries/icon-registry.class.js +118 -0
  56. package/dist/collection/classes/registries/paste-intent-provider.registry.js +26 -0
  57. package/dist/collection/classes/registries/tool.registry.js +69 -0
  58. package/dist/collection/classes/structures/app-state-map.structure.js +461 -0
  59. package/dist/collection/classes/structures/object-map.structure.js +1103 -0
  60. package/dist/collection/classes/structures/quadtree.structure.js +251 -0
  61. package/dist/collection/classes/tools/base-tool.class.js +88 -0
  62. package/dist/collection/classes/tools/brush-tool.class.js +236 -0
  63. package/dist/collection/classes/tools/eraser-tool.class.js +133 -0
  64. package/dist/collection/classes/tools/image-tool.class.js +152 -0
  65. package/dist/collection/classes/tools/line-tool.class.js +249 -0
  66. package/dist/collection/classes/tools/selection-tool.class.js +611 -0
  67. package/dist/collection/classes/tools/shape-tool.class.js +251 -0
  68. package/dist/collection/classes/tools/text-tool.class.js +179 -0
  69. package/dist/collection/collection-manifest.json +17 -0
  70. package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.css +115 -0
  71. package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.js +380 -0
  72. package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.css +10 -0
  73. package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.js +153 -0
  74. package/dist/collection/components/kritzel-engine/kritzel-engine.css +81 -0
  75. package/dist/collection/components/kritzel-engine/kritzel-engine.js +6345 -0
  76. package/dist/collection/components/kritzel-icon/kritzel-icon.css +18 -0
  77. package/dist/collection/components/kritzel-icon/kritzel-icon.js +93 -0
  78. package/dist/collection/components/kritzel-watermark/kritzel-watermark.css +29 -0
  79. package/dist/collection/components/kritzel-watermark/kritzel-watermark.js +83 -0
  80. package/dist/collection/configs/default-asset-storage.config.js +9 -0
  81. package/dist/collection/configs/default-brush-tool.config.js +9 -0
  82. package/dist/collection/configs/default-engine-config.js +73 -0
  83. package/dist/collection/configs/default-line-tool.config.js +12 -0
  84. package/dist/collection/configs/default-shape-tool.config.js +15 -0
  85. package/dist/collection/configs/default-sync.config.js +6 -0
  86. package/dist/collection/configs/default-text-tool.config.js +12 -0
  87. package/dist/collection/constants/color-palette.constants.js +40 -0
  88. package/dist/collection/constants/core.constants.js +1 -0
  89. package/dist/collection/constants/engine.constants.js +4 -0
  90. package/dist/collection/constants/license.constants.js +25 -0
  91. package/dist/collection/constants/schema.constants.js +4 -0
  92. package/dist/collection/constants/storage.constants.js +1 -0
  93. package/dist/collection/constants/stroke-size.constants.js +2 -0
  94. package/dist/collection/constants/text-tool-fonts.constants.js +18 -0
  95. package/dist/collection/constants/version.js +6 -0
  96. package/dist/collection/enums/alignment.enum.js +9 -0
  97. package/dist/collection/enums/event-button.enum.js +6 -0
  98. package/dist/collection/enums/handle-type.enum.js +7 -0
  99. package/dist/collection/enums/shape-type.enum.js +6 -0
  100. package/dist/collection/events/active-workspace-change.event.js +1 -0
  101. package/dist/collection/events/editor-is-ready.event.js +1 -0
  102. package/dist/collection/events/login.event.js +1 -0
  103. package/dist/collection/helpers/alignment.helper.js +73 -0
  104. package/dist/collection/helpers/class.helper.js +5 -0
  105. package/dist/collection/helpers/color.helper.js +106 -0
  106. package/dist/collection/helpers/cursor.helper.js +57 -0
  107. package/dist/collection/helpers/devices.helper.js +28 -0
  108. package/dist/collection/helpers/event.helper.js +58 -0
  109. package/dist/collection/helpers/geometry.helper.js +149 -0
  110. package/dist/collection/helpers/html.helper.js +116 -0
  111. package/dist/collection/helpers/image-file.helper.js +6 -0
  112. package/dist/collection/helpers/keyboard.helper.js +55 -0
  113. package/dist/collection/helpers/localization.helper.js +25 -0
  114. package/dist/collection/helpers/math.helper.js +8 -0
  115. package/dist/collection/helpers/migration.helper.js +45 -0
  116. package/dist/collection/helpers/object.helper.js +29 -0
  117. package/dist/collection/helpers/svg-export.helper.js +655 -0
  118. package/dist/collection/helpers/theme.helper.js +77 -0
  119. package/dist/collection/helpers/tool-config.helper.js +63 -0
  120. package/dist/collection/helpers/wheel.helper.js +113 -0
  121. package/dist/collection/index.js +107 -0
  122. package/dist/collection/interfaces/anchor.interface.js +1 -0
  123. package/dist/collection/interfaces/arrow-head.interface.js +1 -0
  124. package/dist/collection/interfaces/asset-provider.interface.js +1 -0
  125. package/dist/collection/interfaces/asset-storage-config.interface.js +1 -0
  126. package/dist/collection/interfaces/asset.interface.js +1 -0
  127. package/dist/collection/interfaces/bounding-box.interface.js +1 -0
  128. package/dist/collection/interfaces/clonable.interface.js +1 -0
  129. package/dist/collection/interfaces/context-menu-item.interface.js +1 -0
  130. package/dist/collection/interfaces/context-menu-state.interface.js +1 -0
  131. package/dist/collection/interfaces/debug-info.interface.js +1 -0
  132. package/dist/collection/interfaces/dialog.interface.js +1 -0
  133. package/dist/collection/interfaces/document-metadata.interface.js +1 -0
  134. package/dist/collection/interfaces/dynamic-object-renderer.interface.js +1 -0
  135. package/dist/collection/interfaces/engine-state.interface.js +1 -0
  136. package/dist/collection/interfaces/font.interface.js +1 -0
  137. package/dist/collection/interfaces/localization.interface.js +1 -0
  138. package/dist/collection/interfaces/login-config.interface.js +1 -0
  139. package/dist/collection/interfaces/master-detail.interface.js +1 -0
  140. package/dist/collection/interfaces/menu-item.interface.js +1 -0
  141. package/dist/collection/interfaces/migration.interface.js +1 -0
  142. package/dist/collection/interfaces/notification.interface.js +1 -0
  143. package/dist/collection/interfaces/object-change-event.interface.js +1 -0
  144. package/dist/collection/interfaces/object-export.interface.js +1 -0
  145. package/dist/collection/interfaces/object.interface.js +1 -0
  146. package/dist/collection/interfaces/paste-intent-provider.interface.js +1 -0
  147. package/dist/collection/interfaces/point.interface.js +1 -0
  148. package/dist/collection/interfaces/polygon.interface.js +1 -0
  149. package/dist/collection/interfaces/remote-cursor.interface.js +1 -0
  150. package/dist/collection/interfaces/selection-state.interface.js +1 -0
  151. package/dist/collection/interfaces/serializable.interface.js +1 -0
  152. package/dist/collection/interfaces/settings.interface.js +1 -0
  153. package/dist/collection/interfaces/share.interface.js +1 -0
  154. package/dist/collection/interfaces/shortcut.interface.js +1 -0
  155. package/dist/collection/interfaces/sync-config.interface.js +21 -0
  156. package/dist/collection/interfaces/sync-provider.interface.js +1 -0
  157. package/dist/collection/interfaces/theme.interface.js +1 -0
  158. package/dist/collection/interfaces/tool-config.interface.js +1 -0
  159. package/dist/collection/interfaces/tool-type.interface.js +1 -0
  160. package/dist/collection/interfaces/tool.interface.js +1 -0
  161. package/dist/collection/interfaces/toolbar-item.interface.js +1 -0
  162. package/dist/collection/interfaces/undo-state.interface.js +1 -0
  163. package/dist/collection/interfaces/user.interface.js +1 -0
  164. package/dist/collection/interfaces/viewport-state.interface.js +1 -0
  165. package/dist/collection/locales/de-locale.js +119 -0
  166. package/dist/collection/locales/en-locale.js +120 -0
  167. package/dist/collection/locales/fr-locale.js +119 -0
  168. package/dist/collection/migrations/app-state.migrations.js +47 -0
  169. package/dist/collection/migrations/workspace.migrations.js +67 -0
  170. package/dist/collection/themes/dark-theme.js +340 -0
  171. package/dist/collection/themes/light-theme.js +346 -0
  172. package/dist/collection/types/deep-readonly.type.js +1 -0
  173. package/dist/collection/types/state.types.js +1 -0
  174. package/dist/components/index.d.ts +47 -0
  175. package/dist/components/index.js +4143 -0
  176. package/dist/components/kritzel-awareness-cursors.d.ts +11 -0
  177. package/dist/components/kritzel-awareness-cursors.js +6 -0
  178. package/dist/components/kritzel-cursor-trail.d.ts +11 -0
  179. package/dist/components/kritzel-cursor-trail.js +6 -0
  180. package/dist/components/kritzel-engine.d.ts +11 -0
  181. package/dist/components/kritzel-engine.js +52641 -0
  182. package/dist/components/kritzel-icon.d.ts +11 -0
  183. package/dist/components/kritzel-icon.js +6 -0
  184. package/dist/components/kritzel-watermark.d.ts +11 -0
  185. package/dist/components/kritzel-watermark.js +6 -0
  186. package/dist/components/p-B2Htv9ou.js +49 -0
  187. package/dist/components/p-BvRGQvVI.js +3456 -0
  188. package/dist/components/p-CfSx6HU_.js +1469 -0
  189. package/dist/components/p-YP8wAcF4.js +122 -0
  190. package/dist/components/p-fx6msYHJ.js +167 -0
  191. package/dist/esm/app-globals-DQuL1Twl.js +3 -0
  192. package/dist/esm/engine.constants-Bl5-pbq-.js +28143 -0
  193. package/dist/esm/index-BU9Mv7y0.js +1715 -0
  194. package/dist/esm/index.js +4134 -0
  195. package/dist/esm/kritzel-awareness-cursors_5.entry.js +27978 -0
  196. package/dist/esm/loader.js +11 -0
  197. package/dist/esm/stencil.js +21 -0
  198. package/dist/index.cjs.js +1 -0
  199. package/dist/index.js +1 -0
  200. package/dist/stencil/index.esm.js +4134 -0
  201. package/dist/stencil/p-BU9Mv7y0.js +1702 -0
  202. package/dist/stencil/p-Bl5-pbq-.js +28143 -0
  203. package/dist/stencil/p-DQuL1Twl.js +3 -0
  204. package/dist/stencil/p-f0a8b7af.entry.js +27978 -0
  205. package/dist/stencil/stencil.esm.js +21 -0
  206. package/dist/types/classes/core/core.class.d.ts +532 -0
  207. package/dist/types/classes/core/reviver.class.d.ts +32 -0
  208. package/dist/types/classes/core/store.class.d.ts +198 -0
  209. package/dist/types/classes/core/viewport.class.d.ts +256 -0
  210. package/dist/types/classes/core/workspace.class.d.ts +95 -0
  211. package/dist/types/classes/handlers/base.handler.d.ts +18 -0
  212. package/dist/types/classes/handlers/context-menu.handler.d.ts +67 -0
  213. package/dist/types/classes/handlers/hover.handler.d.ts +23 -0
  214. package/dist/types/classes/handlers/key.handler.d.ts +44 -0
  215. package/dist/types/classes/handlers/line-handle.handler.d.ts +115 -0
  216. package/dist/types/classes/handlers/move.handler.d.ts +94 -0
  217. package/dist/types/classes/handlers/resize.handler.d.ts +95 -0
  218. package/dist/types/classes/handlers/rotation.handler.d.ts +50 -0
  219. package/dist/types/classes/handlers/selection.handler.d.ts +153 -0
  220. package/dist/types/classes/managers/anchor.manager.d.ts +513 -0
  221. package/dist/types/classes/managers/browser-permission.manager.d.ts +41 -0
  222. package/dist/types/classes/managers/clipboard.manager.d.ts +71 -0
  223. package/dist/types/classes/managers/clipboard.types.d.ts +23 -0
  224. package/dist/types/classes/managers/cursor.manager.d.ts +66 -0
  225. package/dist/types/classes/managers/license.manager.d.ts +147 -0
  226. package/dist/types/classes/managers/localization.manager.d.ts +145 -0
  227. package/dist/types/classes/managers/theme.manager.d.ts +112 -0
  228. package/dist/types/classes/objects/base-object.class.d.ts +266 -0
  229. package/dist/types/classes/objects/dynamic-object.class.d.ts +148 -0
  230. package/dist/types/classes/objects/group.class.d.ts +231 -0
  231. package/dist/types/classes/objects/image.class.d.ts +246 -0
  232. package/dist/types/classes/objects/line.class.d.ts +285 -0
  233. package/dist/types/classes/objects/path.class.d.ts +220 -0
  234. package/dist/types/classes/objects/selection-box.class.d.ts +19 -0
  235. package/dist/types/classes/objects/selection-group.class.d.ts +267 -0
  236. package/dist/types/classes/objects/shape.class.d.ts +322 -0
  237. package/dist/types/classes/objects/text.class.d.ts +197 -0
  238. package/dist/types/classes/providers/assets/asset-resolver.class.d.ts +141 -0
  239. package/dist/types/classes/providers/assets/http-asset-provider.class.d.ts +79 -0
  240. package/dist/types/classes/providers/assets/indexeddb-asset-provider.class.d.ts +69 -0
  241. package/dist/types/classes/providers/assets/presigned-asset-provider.class.d.ts +69 -0
  242. package/dist/types/classes/providers/paste-intent/event-paste-intent.provider.d.ts +8 -0
  243. package/dist/types/classes/providers/paste-intent/ios-paste-intent.provider.d.ts +6 -0
  244. package/dist/types/classes/providers/paste-intent/navigator-paste-intent.provider.d.ts +9 -0
  245. package/dist/types/classes/providers/sync/broadcast-sync-provider.class.d.ts +23 -0
  246. package/dist/types/classes/providers/sync/hocuspocus-sync-provider.class.d.ts +163 -0
  247. package/dist/types/classes/providers/sync/in-memory-sync-provider.class.d.ts +39 -0
  248. package/dist/types/classes/providers/sync/indexeddb-sync-provider.class.d.ts +25 -0
  249. package/dist/types/classes/providers/sync/websocket-sync-provider.class.d.ts +63 -0
  250. package/dist/types/classes/registries/dynamic-object-renderer.registry.d.ts +32 -0
  251. package/dist/types/classes/registries/font-registry.class.d.ts +19 -0
  252. package/dist/types/classes/registries/icon-registry.class.d.ts +39 -0
  253. package/dist/types/classes/registries/paste-intent-provider.registry.d.ts +10 -0
  254. package/dist/types/classes/registries/tool.registry.d.ts +53 -0
  255. package/dist/types/classes/structures/app-state-map.structure.d.ts +171 -0
  256. package/dist/types/classes/structures/object-map.structure.d.ts +403 -0
  257. package/dist/types/classes/structures/quadtree.structure.d.ts +128 -0
  258. package/dist/types/classes/tools/base-tool.class.d.ts +72 -0
  259. package/dist/types/classes/tools/brush-tool.class.d.ts +68 -0
  260. package/dist/types/classes/tools/eraser-tool.class.d.ts +38 -0
  261. package/dist/types/classes/tools/image-tool.class.d.ts +74 -0
  262. package/dist/types/classes/tools/line-tool.class.d.ts +63 -0
  263. package/dist/types/classes/tools/selection-tool.class.d.ts +188 -0
  264. package/dist/types/classes/tools/shape-tool.class.d.ts +90 -0
  265. package/dist/types/classes/tools/text-tool.class.d.ts +66 -0
  266. package/dist/types/components/kritzel-awareness-cursors/kritzel-awareness-cursors.d.ts +29 -0
  267. package/dist/types/components/kritzel-cursor-trail/kritzel-cursor-trail.d.ts +19 -0
  268. package/dist/types/components/kritzel-engine/kritzel-engine.d.ts +695 -0
  269. package/dist/types/components/kritzel-icon/kritzel-icon.d.ts +6 -0
  270. package/dist/types/components/kritzel-watermark/kritzel-watermark.d.ts +20 -0
  271. package/dist/types/components.d.ts +981 -0
  272. package/dist/types/configs/default-asset-storage.config.d.ts +8 -0
  273. package/dist/types/configs/default-brush-tool.config.d.ts +2 -0
  274. package/dist/types/configs/default-engine-config.d.ts +2 -0
  275. package/dist/types/configs/default-line-tool.config.d.ts +2 -0
  276. package/dist/types/configs/default-shape-tool.config.d.ts +2 -0
  277. package/dist/types/configs/default-sync.config.d.ts +5 -0
  278. package/dist/types/configs/default-text-tool.config.d.ts +2 -0
  279. package/dist/types/constants/color-palette.constants.d.ts +31 -0
  280. package/dist/types/constants/core.constants.d.ts +0 -0
  281. package/dist/types/constants/engine.constants.d.ts +4 -0
  282. package/dist/types/constants/license.constants.d.ts +25 -0
  283. package/dist/types/constants/schema.constants.d.ts +4 -0
  284. package/dist/types/constants/storage.constants.d.ts +1 -0
  285. package/dist/types/constants/stroke-size.constants.d.ts +2 -0
  286. package/dist/types/constants/text-tool-fonts.constants.d.ts +3 -0
  287. package/dist/types/constants/version.d.ts +6 -0
  288. package/dist/types/enums/alignment.enum.d.ts +8 -0
  289. package/dist/types/enums/event-button.enum.d.ts +5 -0
  290. package/dist/types/enums/handle-type.enum.d.ts +6 -0
  291. package/dist/types/enums/shape-type.enum.d.ts +5 -0
  292. package/dist/types/events/active-workspace-change.event.d.ts +7 -0
  293. package/dist/types/events/editor-is-ready.event.d.ts +18 -0
  294. package/dist/types/events/login.event.d.ts +3 -0
  295. package/dist/types/helpers/alignment.helper.d.ts +21 -0
  296. package/dist/types/helpers/class.helper.d.ts +3 -0
  297. package/dist/types/helpers/color.helper.d.ts +34 -0
  298. package/dist/types/helpers/cursor.helper.d.ts +22 -0
  299. package/dist/types/helpers/devices.helper.d.ts +8 -0
  300. package/dist/types/helpers/event.helper.d.ts +6 -0
  301. package/dist/types/helpers/geometry.helper.d.ts +38 -0
  302. package/dist/types/helpers/html.helper.d.ts +8 -0
  303. package/dist/types/helpers/image-file.helper.d.ts +3 -0
  304. package/dist/types/helpers/keyboard.helper.d.ts +6 -0
  305. package/dist/types/helpers/localization.helper.d.ts +18 -0
  306. package/dist/types/helpers/math.helper.d.ts +4 -0
  307. package/dist/types/helpers/migration.helper.d.ts +30 -0
  308. package/dist/types/helpers/object.helper.d.ts +9 -0
  309. package/dist/types/helpers/svg-export.helper.d.ts +231 -0
  310. package/dist/types/helpers/theme.helper.d.ts +42 -0
  311. package/dist/types/helpers/tool-config.helper.d.ts +4 -0
  312. package/dist/types/helpers/wheel.helper.d.ts +9 -0
  313. package/dist/types/index.d.ts +109 -0
  314. package/dist/types/interfaces/anchor.interface.d.ts +147 -0
  315. package/dist/types/interfaces/arrow-head.interface.d.ts +27 -0
  316. package/dist/types/interfaces/asset-provider.interface.d.ts +88 -0
  317. package/dist/types/interfaces/asset-storage-config.interface.d.ts +40 -0
  318. package/dist/types/interfaces/asset.interface.d.ts +43 -0
  319. package/dist/types/interfaces/bounding-box.interface.d.ts +8 -0
  320. package/dist/types/interfaces/clonable.interface.d.ts +3 -0
  321. package/dist/types/interfaces/context-menu-item.interface.d.ts +25 -0
  322. package/dist/types/interfaces/context-menu-state.interface.d.ts +16 -0
  323. package/dist/types/interfaces/debug-info.interface.d.ts +7 -0
  324. package/dist/types/interfaces/dialog.interface.d.ts +4 -0
  325. package/dist/types/interfaces/document-metadata.interface.d.ts +6 -0
  326. package/dist/types/interfaces/dynamic-object-renderer.interface.d.ts +40 -0
  327. package/dist/types/interfaces/engine-state.interface.d.ts +82 -0
  328. package/dist/types/interfaces/font.interface.d.ts +15 -0
  329. package/dist/types/interfaces/localization.interface.d.ts +143 -0
  330. package/dist/types/interfaces/login-config.interface.d.ts +24 -0
  331. package/dist/types/interfaces/master-detail.interface.d.ts +14 -0
  332. package/dist/types/interfaces/menu-item.interface.d.ts +27 -0
  333. package/dist/types/interfaces/migration.interface.d.ts +16 -0
  334. package/dist/types/interfaces/notification.interface.d.ts +10 -0
  335. package/dist/types/interfaces/object-change-event.interface.d.ts +31 -0
  336. package/dist/types/interfaces/object-export.interface.d.ts +20 -0
  337. package/dist/types/interfaces/object.interface.d.ts +53 -0
  338. package/dist/types/interfaces/paste-intent-provider.interface.d.ts +10 -0
  339. package/dist/types/interfaces/point.interface.d.ts +4 -0
  340. package/dist/types/interfaces/polygon.interface.d.ts +7 -0
  341. package/dist/types/interfaces/remote-cursor.interface.d.ts +18 -0
  342. package/dist/types/interfaces/selection-state.interface.d.ts +7 -0
  343. package/dist/types/interfaces/serializable.interface.d.ts +5 -0
  344. package/dist/types/interfaces/settings.interface.d.ts +25 -0
  345. package/dist/types/interfaces/share.interface.d.ts +9 -0
  346. package/dist/types/interfaces/shortcut.interface.d.ts +10 -0
  347. package/dist/types/interfaces/sync-config.interface.d.ts +41 -0
  348. package/dist/types/interfaces/sync-provider.interface.d.ts +66 -0
  349. package/dist/types/interfaces/theme.interface.d.ts +553 -0
  350. package/dist/types/interfaces/tool-config.interface.d.ts +24 -0
  351. package/dist/types/interfaces/tool-type.interface.d.ts +1 -0
  352. package/dist/types/interfaces/tool.interface.d.ts +8 -0
  353. package/dist/types/interfaces/toolbar-item.interface.d.ts +66 -0
  354. package/dist/types/interfaces/undo-state.interface.d.ts +6 -0
  355. package/dist/types/interfaces/user.interface.d.ts +22 -0
  356. package/dist/types/interfaces/viewport-state.interface.d.ts +7 -0
  357. package/dist/types/locales/de-locale.d.ts +5 -0
  358. package/dist/types/locales/en-locale.d.ts +6 -0
  359. package/dist/types/locales/fr-locale.d.ts +5 -0
  360. package/dist/types/migrations/app-state.migrations.d.ts +11 -0
  361. package/dist/types/migrations/workspace.migrations.d.ts +11 -0
  362. package/dist/types/stencil-public-runtime.d.ts +1873 -0
  363. package/dist/types/themes/dark-theme.d.ts +5 -0
  364. package/dist/types/themes/light-theme.d.ts +5 -0
  365. package/dist/types/types/deep-readonly.type.d.ts +7 -0
  366. package/dist/types/types/state.types.d.ts +3 -0
  367. package/loader/cdn.js +1 -0
  368. package/loader/index.cjs.js +1 -0
  369. package/loader/index.d.ts +24 -0
  370. package/loader/index.es2017.js +1 -0
  371. package/loader/index.js +2 -0
  372. package/package.json +101 -0
  373. package/readme.md +11 -0
@@ -0,0 +1,4232 @@
1
+ 'use strict';
2
+
3
+ var engine_constants = require('./engine.constants-CakmdKMW.js');
4
+ var Y = require('yjs');
5
+ var yIndexeddb = require('y-indexeddb');
6
+ var yWebsocket = require('y-websocket');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var Y__namespace = /*#__PURE__*/_interopNamespace(Y);
27
+
28
+ class KritzelToolConfigHelper {
29
+ static getToolConfig(tool) {
30
+ switch (tool?.toolType) {
31
+ case 'selection':
32
+ return 'getToolConfig' in tool && typeof tool.getToolConfig === 'function'
33
+ ? tool.getToolConfig()
34
+ : null;
35
+ case 'brush':
36
+ return {
37
+ type: 'brush',
38
+ colorProperty: 'color',
39
+ sizeProperty: 'size',
40
+ opacityProperty: 'opacity',
41
+ paletteSource: 'palette',
42
+ sizesSource: 'sizes',
43
+ controls: [
44
+ { type: 'stroke-size', propertyName: 'size' },
45
+ ],
46
+ };
47
+ case 'line':
48
+ return {
49
+ type: 'line',
50
+ colorProperty: 'color',
51
+ sizeProperty: 'size',
52
+ opacityProperty: 'opacity',
53
+ paletteSource: 'palette',
54
+ sizesSource: 'sizes',
55
+ controls: [
56
+ { type: 'stroke-size', propertyName: 'size' },
57
+ { type: 'line-endings', propertyName: 'arrows', additionalProps: {} },
58
+ ],
59
+ };
60
+ case 'shape':
61
+ return {
62
+ type: 'shape',
63
+ colorProperty: 'strokeColor',
64
+ sizeProperty: 'strokeWidth',
65
+ opacityProperty: 'opacity',
66
+ paletteSource: 'palette',
67
+ sizesSource: 'sizes',
68
+ controls: [
69
+ { type: 'stroke-size', propertyName: 'strokeWidth' },
70
+ { type: 'shape-fill', propertyName: 'fillColor', additionalProps: {} },
71
+ ],
72
+ };
73
+ case 'text':
74
+ return {
75
+ type: 'text',
76
+ colorProperty: 'fontColor',
77
+ sizeProperty: 'fontSize',
78
+ opacityProperty: 'opacity',
79
+ paletteSource: 'palette',
80
+ sizesSource: 'sizes',
81
+ controls: [
82
+ { type: 'font-size', propertyName: 'fontSize', additionalProps: {} },
83
+ { type: 'font-family', propertyName: 'fontFamily' },
84
+ ],
85
+ };
86
+ default:
87
+ return null;
88
+ }
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Common Math expressions.
94
+ *
95
+ * @module math
96
+ */
97
+
98
+ const floor$2 = Math.floor;
99
+
100
+ /**
101
+ * @function
102
+ * @param {number} a
103
+ * @param {number} b
104
+ * @return {number} The smaller element of a and b
105
+ */
106
+ const min$2 = (a, b) => a < b ? a : b;
107
+
108
+ /**
109
+ * @function
110
+ * @param {number} a
111
+ * @param {number} b
112
+ * @return {number} The bigger element of a and b
113
+ */
114
+ const max$2 = (a, b) => a > b ? a : b;
115
+
116
+ /* eslint-env browser */
117
+
118
+ const BIT8$2 = 128;
119
+ const BITS7$2 = 127;
120
+
121
+ /**
122
+ * Utility helpers for working with numbers.
123
+ *
124
+ * @module number
125
+ */
126
+
127
+
128
+ const MAX_SAFE_INTEGER$2 = Number.MAX_SAFE_INTEGER;
129
+
130
+ /**
131
+ * Efficient schema-less binary encoding with support for variable length encoding.
132
+ *
133
+ * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
134
+ *
135
+ * Encodes numbers in little-endian order (least to most significant byte order)
136
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
137
+ * which is also used in Protocol Buffers.
138
+ *
139
+ * ```js
140
+ * // encoding step
141
+ * const encoder = encoding.createEncoder()
142
+ * encoding.writeVarUint(encoder, 256)
143
+ * encoding.writeVarString(encoder, 'Hello world!')
144
+ * const buf = encoding.toUint8Array(encoder)
145
+ * ```
146
+ *
147
+ * ```js
148
+ * // decoding step
149
+ * const decoder = decoding.createDecoder(buf)
150
+ * decoding.readVarUint(decoder) // => 256
151
+ * decoding.readVarString(decoder) // => 'Hello world!'
152
+ * decoding.hasContent(decoder) // => false - all data is read
153
+ * ```
154
+ *
155
+ * @module encoding
156
+ */
157
+
158
+
159
+ /**
160
+ * A BinaryEncoder handles the encoding to an Uint8Array.
161
+ */
162
+ let Encoder$1 = class Encoder {
163
+ constructor () {
164
+ this.cpos = 0;
165
+ this.cbuf = new Uint8Array(100);
166
+ /**
167
+ * @type {Array<Uint8Array>}
168
+ */
169
+ this.bufs = [];
170
+ }
171
+ };
172
+
173
+ /**
174
+ * @function
175
+ * @return {Encoder}
176
+ */
177
+ const createEncoder$1 = () => new Encoder$1();
178
+
179
+ /**
180
+ * The current length of the encoded data.
181
+ *
182
+ * @function
183
+ * @param {Encoder} encoder
184
+ * @return {number}
185
+ */
186
+ const length$2 = encoder => {
187
+ let len = encoder.cpos;
188
+ for (let i = 0; i < encoder.bufs.length; i++) {
189
+ len += encoder.bufs[i].length;
190
+ }
191
+ return len
192
+ };
193
+
194
+ /**
195
+ * Transform to Uint8Array.
196
+ *
197
+ * @function
198
+ * @param {Encoder} encoder
199
+ * @return {Uint8Array<ArrayBuffer>} The created ArrayBuffer.
200
+ */
201
+ const toUint8Array$1 = encoder => {
202
+ const uint8arr = new Uint8Array(length$2(encoder));
203
+ let curPos = 0;
204
+ for (let i = 0; i < encoder.bufs.length; i++) {
205
+ const d = encoder.bufs[i];
206
+ uint8arr.set(d, curPos);
207
+ curPos += d.length;
208
+ }
209
+ uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
210
+ return uint8arr
211
+ };
212
+
213
+ /**
214
+ * Write one byte to the encoder.
215
+ *
216
+ * @function
217
+ * @param {Encoder} encoder
218
+ * @param {number} num The byte that is to be encoded.
219
+ */
220
+ const write$2 = (encoder, num) => {
221
+ const bufferLen = encoder.cbuf.length;
222
+ if (encoder.cpos === bufferLen) {
223
+ encoder.bufs.push(encoder.cbuf);
224
+ encoder.cbuf = new Uint8Array(bufferLen * 2);
225
+ encoder.cpos = 0;
226
+ }
227
+ encoder.cbuf[encoder.cpos++] = num;
228
+ };
229
+
230
+ /**
231
+ * Write a variable length unsigned integer. Max encodable integer is 2^53.
232
+ *
233
+ * @function
234
+ * @param {Encoder} encoder
235
+ * @param {number} num The number that is to be encoded.
236
+ */
237
+ const writeVarUint$2 = (encoder, num) => {
238
+ while (num > BITS7$2) {
239
+ write$2(encoder, BIT8$2 | (BITS7$2 & num));
240
+ num = floor$2(num / 128); // shift >>> 7
241
+ }
242
+ write$2(encoder, BITS7$2 & num);
243
+ };
244
+
245
+ /**
246
+ * Append fixed-length Uint8Array to the encoder.
247
+ *
248
+ * @function
249
+ * @param {Encoder} encoder
250
+ * @param {Uint8Array} uint8Array
251
+ */
252
+ const writeUint8Array$2 = (encoder, uint8Array) => {
253
+ const bufferLen = encoder.cbuf.length;
254
+ const cpos = encoder.cpos;
255
+ const leftCopyLen = min$2(bufferLen - cpos, uint8Array.length);
256
+ const rightCopyLen = uint8Array.length - leftCopyLen;
257
+ encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
258
+ encoder.cpos += leftCopyLen;
259
+ if (rightCopyLen > 0) {
260
+ // Still something to write, write right half..
261
+ // Append new buffer
262
+ encoder.bufs.push(encoder.cbuf);
263
+ // must have at least size of remaining buffer
264
+ encoder.cbuf = new Uint8Array(max$2(bufferLen * 2, rightCopyLen));
265
+ // copy array
266
+ encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
267
+ encoder.cpos = rightCopyLen;
268
+ }
269
+ };
270
+
271
+ /**
272
+ * Append an Uint8Array to Encoder.
273
+ *
274
+ * @function
275
+ * @param {Encoder} encoder
276
+ * @param {Uint8Array} uint8Array
277
+ */
278
+ const writeVarUint8Array$2 = (encoder, uint8Array) => {
279
+ writeVarUint$2(encoder, uint8Array.byteLength);
280
+ writeUint8Array$2(encoder, uint8Array);
281
+ };
282
+
283
+ /**
284
+ * Error helpers.
285
+ *
286
+ * @module error
287
+ */
288
+
289
+ /**
290
+ * @param {string} s
291
+ * @return {Error}
292
+ */
293
+ /* c8 ignore next */
294
+ const create$4 = s => new Error(s);
295
+
296
+ /**
297
+ * Efficient schema-less binary decoding with support for variable length encoding.
298
+ *
299
+ * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
300
+ *
301
+ * Encodes numbers in little-endian order (least to most significant byte order)
302
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
303
+ * which is also used in Protocol Buffers.
304
+ *
305
+ * ```js
306
+ * // encoding step
307
+ * const encoder = encoding.createEncoder()
308
+ * encoding.writeVarUint(encoder, 256)
309
+ * encoding.writeVarString(encoder, 'Hello world!')
310
+ * const buf = encoding.toUint8Array(encoder)
311
+ * ```
312
+ *
313
+ * ```js
314
+ * // decoding step
315
+ * const decoder = decoding.createDecoder(buf)
316
+ * decoding.readVarUint(decoder) // => 256
317
+ * decoding.readVarString(decoder) // => 'Hello world!'
318
+ * decoding.hasContent(decoder) // => false - all data is read
319
+ * ```
320
+ *
321
+ * @module decoding
322
+ */
323
+
324
+
325
+ const errorUnexpectedEndOfArray$2 = create$4('Unexpected end of array');
326
+ const errorIntegerOutOfRange$2 = create$4('Integer out of Range');
327
+
328
+ /**
329
+ * A Decoder handles the decoding of an Uint8Array.
330
+ * @template {ArrayBufferLike} [Buf=ArrayBufferLike]
331
+ */
332
+ let Decoder$1 = class Decoder {
333
+ /**
334
+ * @param {Uint8Array<Buf>} uint8Array Binary data to decode
335
+ */
336
+ constructor (uint8Array) {
337
+ /**
338
+ * Decoding target.
339
+ *
340
+ * @type {Uint8Array<Buf>}
341
+ */
342
+ this.arr = uint8Array;
343
+ /**
344
+ * Current decoding position.
345
+ *
346
+ * @type {number}
347
+ */
348
+ this.pos = 0;
349
+ }
350
+ };
351
+
352
+ /**
353
+ * @function
354
+ * @template {ArrayBufferLike} Buf
355
+ * @param {Uint8Array<Buf>} uint8Array
356
+ * @return {Decoder<Buf>}
357
+ */
358
+ const createDecoder$1 = uint8Array => new Decoder$1(uint8Array);
359
+
360
+ /**
361
+ * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
362
+ *
363
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
364
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
365
+ *
366
+ * @function
367
+ * @template {ArrayBufferLike} Buf
368
+ * @param {Decoder<Buf>} decoder The decoder instance
369
+ * @param {number} len The length of bytes to read
370
+ * @return {Uint8Array<Buf>}
371
+ */
372
+ const readUint8Array$2 = (decoder, len) => {
373
+ const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
374
+ decoder.pos += len;
375
+ return view
376
+ };
377
+
378
+ /**
379
+ * Read variable length Uint8Array.
380
+ *
381
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
382
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
383
+ *
384
+ * @function
385
+ * @template {ArrayBufferLike} Buf
386
+ * @param {Decoder<Buf>} decoder
387
+ * @return {Uint8Array<Buf>}
388
+ */
389
+ const readVarUint8Array$2 = decoder => readUint8Array$2(decoder, readVarUint$2(decoder));
390
+
391
+ /**
392
+ * Read unsigned integer (32bit) with variable length.
393
+ * 1/8th of the storage is used as encoding overhead.
394
+ * * numbers < 2^7 is stored in one bytlength
395
+ * * numbers < 2^14 is stored in two bylength
396
+ *
397
+ * @function
398
+ * @param {Decoder} decoder
399
+ * @return {number} An unsigned integer.length
400
+ */
401
+ const readVarUint$2 = decoder => {
402
+ let num = 0;
403
+ let mult = 1;
404
+ const len = decoder.arr.length;
405
+ while (decoder.pos < len) {
406
+ const r = decoder.arr[decoder.pos++];
407
+ // num = num | ((r & binary.BITS7) << len)
408
+ num = num + (r & BITS7$2) * mult; // shift $r << (7*#iterations) and add it to num
409
+ mult *= 128; // next iteration, shift 7 "more" to the left
410
+ if (r < BIT8$2) {
411
+ return num
412
+ }
413
+ /* c8 ignore start */
414
+ if (num > MAX_SAFE_INTEGER$2) {
415
+ throw errorIntegerOutOfRange$2
416
+ }
417
+ /* c8 ignore stop */
418
+ }
419
+ throw errorUnexpectedEndOfArray$2
420
+ };
421
+
422
+ /**
423
+ * BroadcastChannel sync provider for cross-tab synchronization
424
+ * This is a lightweight alternative to y-webrtc for browser-tab-only sync
425
+ */
426
+ class BroadcastSyncProvider {
427
+ static type = 'local';
428
+ type = 'local';
429
+ doc;
430
+ channel;
431
+ _synced = false;
432
+ constructor(docName, doc, _options) {
433
+ this.doc = doc;
434
+ this.channel = new BroadcastChannel(docName);
435
+ // Handle incoming messages from other tabs
436
+ this.channel.onmessage = (event) => {
437
+ this.handleMessage(event.data);
438
+ };
439
+ // Listen to document updates and broadcast them
440
+ this.doc.on('update', this.handleDocUpdate);
441
+ // Send initial sync request
442
+ this.broadcastSync();
443
+ // Mark as synced after a short delay (to receive any pending updates)
444
+ setTimeout(() => {
445
+ this._synced = true;
446
+ }, 100);
447
+ if (!_options?.quiet) {
448
+ console.info(`BroadcastChannel Provider initialized: ${docName}`);
449
+ }
450
+ }
451
+ handleDocUpdate = (update, origin) => {
452
+ // Don't broadcast updates that came from other tabs (to prevent loops)
453
+ if (origin !== this) {
454
+ const encoder = createEncoder$1();
455
+ writeVarUint$2(encoder, 0); // Message type: sync update
456
+ writeVarUint8Array$2(encoder, update);
457
+ this.channel.postMessage(toUint8Array$1(encoder));
458
+ }
459
+ };
460
+ handleMessage(message) {
461
+ const decoder = createDecoder$1(new Uint8Array(message));
462
+ const messageType = readVarUint$2(decoder);
463
+ switch (messageType) {
464
+ case 0: // Sync update
465
+ const update = readVarUint8Array$2(decoder);
466
+ Y__namespace.applyUpdate(this.doc, update, this);
467
+ break;
468
+ case 1: // Sync request
469
+ this.broadcastSync();
470
+ break;
471
+ case 2: // Sync response
472
+ const stateVector = readVarUint8Array$2(decoder);
473
+ const updateResponse = Y__namespace.encodeStateAsUpdate(this.doc, stateVector);
474
+ if (updateResponse.length > 0) {
475
+ const encoder = createEncoder$1();
476
+ writeVarUint$2(encoder, 0); // Send as regular update
477
+ writeVarUint8Array$2(encoder, updateResponse);
478
+ this.channel.postMessage(toUint8Array$1(encoder));
479
+ }
480
+ break;
481
+ }
482
+ }
483
+ broadcastSync() {
484
+ // Broadcast our current state vector to request missing updates
485
+ const encoder = createEncoder$1();
486
+ writeVarUint$2(encoder, 2); // Message type: sync response
487
+ writeVarUint8Array$2(encoder, Y__namespace.encodeStateVector(this.doc));
488
+ this.channel.postMessage(toUint8Array$1(encoder));
489
+ }
490
+ async connect() {
491
+ // Wait for initial sync to complete
492
+ if (this._synced) {
493
+ return;
494
+ }
495
+ return new Promise((resolve) => {
496
+ const checkSync = () => {
497
+ if (this._synced) {
498
+ resolve();
499
+ }
500
+ else {
501
+ setTimeout(checkSync, 50);
502
+ }
503
+ };
504
+ checkSync();
505
+ });
506
+ }
507
+ disconnect() {
508
+ // BroadcastChannel doesn't have explicit disconnect
509
+ }
510
+ async reconnect() {
511
+ this.disconnect();
512
+ return this.connect();
513
+ }
514
+ destroy() {
515
+ this.doc.off('update', this.handleDocUpdate);
516
+ this.channel.close();
517
+ }
518
+ }
519
+
520
+ /**
521
+ * Module-scoped cache that survives component removal and remounting
522
+ * within the same JS runtime. Cleared on page reload.
523
+ */
524
+ const sessionCache = new Map();
525
+ /**
526
+ * In-memory sync provider for session-scoped persistence.
527
+ *
528
+ * State survives the component being removed from the DOM and later
529
+ * re-added within the same page session, but is lost on page reload.
530
+ * Intended for documentation demos where durable IndexedDB persistence
531
+ * is not desired.
532
+ */
533
+ class InMemorySyncProvider {
534
+ static type = 'local';
535
+ type = 'local';
536
+ doc;
537
+ cacheKey;
538
+ isConnected = false;
539
+ constructor(docName, doc, options) {
540
+ this.doc = doc;
541
+ this.cacheKey = options?.name ?? docName;
542
+ }
543
+ handleUpdate = (_update, origin) => {
544
+ // Skip updates that originated from connect() rehydration to avoid a
545
+ // redundant re-encode of the state we just applied.
546
+ if (origin === this) {
547
+ return;
548
+ }
549
+ sessionCache.set(this.cacheKey, Y__namespace.encodeStateAsUpdate(this.doc));
550
+ };
551
+ async connect() {
552
+ if (this.isConnected) {
553
+ return;
554
+ }
555
+ const cached = sessionCache.get(this.cacheKey);
556
+ if (cached) {
557
+ Y__namespace.applyUpdate(this.doc, cached, this);
558
+ }
559
+ this.doc.on('update', this.handleUpdate);
560
+ this.isConnected = true;
561
+ }
562
+ disconnect() {
563
+ this.isConnected = false;
564
+ }
565
+ async reconnect() {
566
+ this.disconnect();
567
+ return this.connect();
568
+ }
569
+ destroy() {
570
+ this.doc.off('update', this.handleUpdate);
571
+ this.isConnected = false;
572
+ }
573
+ /**
574
+ * Clears the in-memory cache.
575
+ *
576
+ * @param name - If provided, only the entry with this cache key is removed.
577
+ * If omitted, all entries are cleared.
578
+ */
579
+ static clear(name) {
580
+ if (name !== undefined) {
581
+ sessionCache.delete(name);
582
+ }
583
+ else {
584
+ sessionCache.clear();
585
+ }
586
+ }
587
+ }
588
+
589
+ /**
590
+ * IndexedDB sync provider for local persistence
591
+ */
592
+ class IndexedDBSyncProvider {
593
+ static type = 'local';
594
+ type = 'local';
595
+ provider;
596
+ isConnected = false;
597
+ constructor(docName, doc, options) {
598
+ const dbName = options?.name || docName;
599
+ this.provider = new yIndexeddb.IndexeddbPersistence(dbName, doc);
600
+ }
601
+ async connect() {
602
+ if (this.isConnected) {
603
+ return;
604
+ }
605
+ return new Promise(resolve => {
606
+ this.provider.on('synced', () => {
607
+ this.isConnected = true;
608
+ resolve();
609
+ });
610
+ });
611
+ }
612
+ disconnect() {
613
+ // IndexedDB doesn't need explicit disconnect
614
+ this.isConnected = false;
615
+ }
616
+ async reconnect() {
617
+ this.disconnect();
618
+ return this.connect();
619
+ }
620
+ destroy() {
621
+ if (this.provider) {
622
+ this.provider.destroy();
623
+ }
624
+ this.isConnected = false;
625
+ }
626
+ }
627
+
628
+ /**
629
+ * WebSocket sync provider for real-time collaboration
630
+ */
631
+ class WebSocketSyncProvider {
632
+ static type = 'network';
633
+ type = 'network';
634
+ provider;
635
+ isConnected = false;
636
+ _quiet = false;
637
+ get awareness() {
638
+ return this.provider.awareness;
639
+ }
640
+ get rawProvider() {
641
+ return this.provider;
642
+ }
643
+ constructor(docName, doc, options) {
644
+ const url = options?.url || 'ws://localhost:1234';
645
+ const roomName = options?.roomName || docName;
646
+ this.provider = new yWebsocket.WebsocketProvider(url, roomName, doc, {
647
+ params: options?.params,
648
+ protocols: options?.protocols,
649
+ WebSocketPolyfill: options?.WebSocketPolyfill,
650
+ awareness: options?.awareness,
651
+ maxBackoffTime: options?.maxBackoffTime,
652
+ disableBc: true,
653
+ });
654
+ this._quiet = options?.quiet ?? false;
655
+ this.setupEventListeners();
656
+ if (!this._quiet) {
657
+ console.info(`WebSocket Provider initialized: ${url}/${roomName}`);
658
+ }
659
+ }
660
+ /**
661
+ * Static factory method for creating WebSocketSyncProvider with configuration options
662
+ * Returns a ProviderFactory that can be used in sync configuration
663
+ */
664
+ static with(options) {
665
+ return {
666
+ type: 'network',
667
+ create: (docName, doc, runtimeOptions) => {
668
+ const mergedOptions = runtimeOptions ? { ...options, ...runtimeOptions } : options;
669
+ return new WebSocketSyncProvider(docName, doc, mergedOptions);
670
+ },
671
+ };
672
+ }
673
+ setupEventListeners() {
674
+ this.provider.on('status', ({ status }) => {
675
+ if (status === 'connected') {
676
+ this.isConnected = true;
677
+ if (!this._quiet) {
678
+ console.info('WebSocket connected');
679
+ }
680
+ }
681
+ else if (status === 'disconnected') {
682
+ this.isConnected = false;
683
+ if (!this._quiet) {
684
+ console.info('WebSocket disconnected');
685
+ }
686
+ }
687
+ });
688
+ this.provider.on('sync', (synced) => {
689
+ if (synced && !this._quiet) {
690
+ console.info('WebSocket synced');
691
+ }
692
+ });
693
+ }
694
+ async connect() {
695
+ if (this.isConnected) {
696
+ return;
697
+ }
698
+ return new Promise((resolve, reject) => {
699
+ const timeout = setTimeout(() => {
700
+ reject(new Error('WebSocket connection timeout'));
701
+ }, 10000); // 10 second timeout
702
+ const statusHandler = ({ status }) => {
703
+ if (status === 'connected') {
704
+ clearTimeout(timeout);
705
+ this.provider.off('status', statusHandler);
706
+ this.isConnected = true;
707
+ resolve();
708
+ }
709
+ };
710
+ this.provider.on('status', statusHandler);
711
+ // If already connected, resolve immediately
712
+ if (this.provider.wsconnected) {
713
+ clearTimeout(timeout);
714
+ this.provider.off('status', statusHandler);
715
+ this.isConnected = true;
716
+ resolve();
717
+ }
718
+ });
719
+ }
720
+ disconnect() {
721
+ if (this.provider) {
722
+ this.provider.disconnect();
723
+ }
724
+ this.isConnected = false;
725
+ }
726
+ async reconnect() {
727
+ this.disconnect();
728
+ return this.connect();
729
+ }
730
+ destroy() {
731
+ if (this.provider) {
732
+ this.provider.destroy();
733
+ }
734
+ this.isConnected = false;
735
+ }
736
+ }
737
+
738
+ /**
739
+ * Common Math expressions.
740
+ *
741
+ * @module math
742
+ */
743
+
744
+ const floor$1 = Math.floor;
745
+
746
+ /**
747
+ * @function
748
+ * @param {number} a
749
+ * @param {number} b
750
+ * @return {number} The smaller element of a and b
751
+ */
752
+ const min$1 = (a, b) => a < b ? a : b;
753
+
754
+ /**
755
+ * @function
756
+ * @param {number} a
757
+ * @param {number} b
758
+ * @return {number} The bigger element of a and b
759
+ */
760
+ const max$1 = (a, b) => a > b ? a : b;
761
+
762
+ /* eslint-env browser */
763
+
764
+ const BIT8$1 = 128;
765
+ const BITS7$1 = 127;
766
+
767
+ /**
768
+ * Utility helpers for working with numbers.
769
+ *
770
+ * @module number
771
+ */
772
+
773
+
774
+ const MAX_SAFE_INTEGER$1 = Number.MAX_SAFE_INTEGER;
775
+
776
+ /**
777
+ * @param {string} str
778
+ * @return {Uint8Array}
779
+ */
780
+ const _encodeUtf8Polyfill$1 = str => {
781
+ const encodedString = unescape(encodeURIComponent(str));
782
+ const len = encodedString.length;
783
+ const buf = new Uint8Array(len);
784
+ for (let i = 0; i < len; i++) {
785
+ buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
786
+ }
787
+ return buf
788
+ };
789
+
790
+ /* c8 ignore next */
791
+ const utf8TextEncoder$1 = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
792
+
793
+ /**
794
+ * @param {string} str
795
+ * @return {Uint8Array}
796
+ */
797
+ const _encodeUtf8Native$1 = str => utf8TextEncoder$1.encode(str);
798
+
799
+ /**
800
+ * @param {string} str
801
+ * @return {Uint8Array}
802
+ */
803
+ /* c8 ignore next */
804
+ const encodeUtf8$1 = utf8TextEncoder$1 ? _encodeUtf8Native$1 : _encodeUtf8Polyfill$1;
805
+
806
+ /* c8 ignore next */
807
+ let utf8TextDecoder$1 = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
808
+
809
+ /* c8 ignore start */
810
+ if (utf8TextDecoder$1 && utf8TextDecoder$1.decode(new Uint8Array()).length === 1) {
811
+ // Safari doesn't handle BOM correctly.
812
+ // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
813
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
814
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
815
+ // Another issue is that from then on no BOM chars are recognized anymore
816
+ /* c8 ignore next */
817
+ utf8TextDecoder$1 = null;
818
+ }
819
+
820
+ /**
821
+ * Efficient schema-less binary encoding with support for variable length encoding.
822
+ *
823
+ * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
824
+ *
825
+ * Encodes numbers in little-endian order (least to most significant byte order)
826
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
827
+ * which is also used in Protocol Buffers.
828
+ *
829
+ * ```js
830
+ * // encoding step
831
+ * const encoder = encoding.createEncoder()
832
+ * encoding.writeVarUint(encoder, 256)
833
+ * encoding.writeVarString(encoder, 'Hello world!')
834
+ * const buf = encoding.toUint8Array(encoder)
835
+ * ```
836
+ *
837
+ * ```js
838
+ * // decoding step
839
+ * const decoder = decoding.createDecoder(buf)
840
+ * decoding.readVarUint(decoder) // => 256
841
+ * decoding.readVarString(decoder) // => 'Hello world!'
842
+ * decoding.hasContent(decoder) // => false - all data is read
843
+ * ```
844
+ *
845
+ * @module encoding
846
+ */
847
+
848
+
849
+ /**
850
+ * Write one byte to the encoder.
851
+ *
852
+ * @function
853
+ * @param {Encoder} encoder
854
+ * @param {number} num The byte that is to be encoded.
855
+ */
856
+ const write$1 = (encoder, num) => {
857
+ const bufferLen = encoder.cbuf.length;
858
+ if (encoder.cpos === bufferLen) {
859
+ encoder.bufs.push(encoder.cbuf);
860
+ encoder.cbuf = new Uint8Array(bufferLen * 2);
861
+ encoder.cpos = 0;
862
+ }
863
+ encoder.cbuf[encoder.cpos++] = num;
864
+ };
865
+
866
+ /**
867
+ * Write a variable length unsigned integer. Max encodable integer is 2^53.
868
+ *
869
+ * @function
870
+ * @param {Encoder} encoder
871
+ * @param {number} num The number that is to be encoded.
872
+ */
873
+ const writeVarUint$1 = (encoder, num) => {
874
+ while (num > BITS7$1) {
875
+ write$1(encoder, BIT8$1 | (BITS7$1 & num));
876
+ num = floor$1(num / 128); // shift >>> 7
877
+ }
878
+ write$1(encoder, BITS7$1 & num);
879
+ };
880
+
881
+ /**
882
+ * A cache to store strings temporarily
883
+ */
884
+ const _strBuffer$1 = new Uint8Array(30000);
885
+ const _maxStrBSize$1 = _strBuffer$1.length / 3;
886
+
887
+ /**
888
+ * Write a variable length string.
889
+ *
890
+ * @function
891
+ * @param {Encoder} encoder
892
+ * @param {String} str The string that is to be encoded.
893
+ */
894
+ const _writeVarStringNative$1 = (encoder, str) => {
895
+ if (str.length < _maxStrBSize$1) {
896
+ // We can encode the string into the existing buffer
897
+ /* c8 ignore next */
898
+ const written = utf8TextEncoder$1.encodeInto(str, _strBuffer$1).written || 0;
899
+ writeVarUint$1(encoder, written);
900
+ for (let i = 0; i < written; i++) {
901
+ write$1(encoder, _strBuffer$1[i]);
902
+ }
903
+ } else {
904
+ writeVarUint8Array$1(encoder, encodeUtf8$1(str));
905
+ }
906
+ };
907
+
908
+ /**
909
+ * Write a variable length string.
910
+ *
911
+ * @function
912
+ * @param {Encoder} encoder
913
+ * @param {String} str The string that is to be encoded.
914
+ */
915
+ const _writeVarStringPolyfill$1 = (encoder, str) => {
916
+ const encodedString = unescape(encodeURIComponent(str));
917
+ const len = encodedString.length;
918
+ writeVarUint$1(encoder, len);
919
+ for (let i = 0; i < len; i++) {
920
+ write$1(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
921
+ }
922
+ };
923
+
924
+ /**
925
+ * Write a variable length string.
926
+ *
927
+ * @function
928
+ * @param {Encoder} encoder
929
+ * @param {String} str The string that is to be encoded.
930
+ */
931
+ /* c8 ignore next */
932
+ const writeVarString$1 = (utf8TextEncoder$1 && /** @type {any} */ (utf8TextEncoder$1).encodeInto) ? _writeVarStringNative$1 : _writeVarStringPolyfill$1;
933
+
934
+ /**
935
+ * Append fixed-length Uint8Array to the encoder.
936
+ *
937
+ * @function
938
+ * @param {Encoder} encoder
939
+ * @param {Uint8Array} uint8Array
940
+ */
941
+ const writeUint8Array$1 = (encoder, uint8Array) => {
942
+ const bufferLen = encoder.cbuf.length;
943
+ const cpos = encoder.cpos;
944
+ const leftCopyLen = min$1(bufferLen - cpos, uint8Array.length);
945
+ const rightCopyLen = uint8Array.length - leftCopyLen;
946
+ encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
947
+ encoder.cpos += leftCopyLen;
948
+ if (rightCopyLen > 0) {
949
+ // Still something to write, write right half..
950
+ // Append new buffer
951
+ encoder.bufs.push(encoder.cbuf);
952
+ // must have at least size of remaining buffer
953
+ encoder.cbuf = new Uint8Array(max$1(bufferLen * 2, rightCopyLen));
954
+ // copy array
955
+ encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
956
+ encoder.cpos = rightCopyLen;
957
+ }
958
+ };
959
+
960
+ /**
961
+ * Append an Uint8Array to Encoder.
962
+ *
963
+ * @function
964
+ * @param {Encoder} encoder
965
+ * @param {Uint8Array} uint8Array
966
+ */
967
+ const writeVarUint8Array$1 = (encoder, uint8Array) => {
968
+ writeVarUint$1(encoder, uint8Array.byteLength);
969
+ writeUint8Array$1(encoder, uint8Array);
970
+ };
971
+
972
+ /**
973
+ * Error helpers.
974
+ *
975
+ * @module error
976
+ */
977
+
978
+ /**
979
+ * @param {string} s
980
+ * @return {Error}
981
+ */
982
+ /* c8 ignore next */
983
+ const create$3 = s => new Error(s);
984
+
985
+ /**
986
+ * Efficient schema-less binary decoding with support for variable length encoding.
987
+ *
988
+ * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
989
+ *
990
+ * Encodes numbers in little-endian order (least to most significant byte order)
991
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
992
+ * which is also used in Protocol Buffers.
993
+ *
994
+ * ```js
995
+ * // encoding step
996
+ * const encoder = encoding.createEncoder()
997
+ * encoding.writeVarUint(encoder, 256)
998
+ * encoding.writeVarString(encoder, 'Hello world!')
999
+ * const buf = encoding.toUint8Array(encoder)
1000
+ * ```
1001
+ *
1002
+ * ```js
1003
+ * // decoding step
1004
+ * const decoder = decoding.createDecoder(buf)
1005
+ * decoding.readVarUint(decoder) // => 256
1006
+ * decoding.readVarString(decoder) // => 'Hello world!'
1007
+ * decoding.hasContent(decoder) // => false - all data is read
1008
+ * ```
1009
+ *
1010
+ * @module decoding
1011
+ */
1012
+
1013
+
1014
+ const errorUnexpectedEndOfArray$1 = create$3('Unexpected end of array');
1015
+ const errorIntegerOutOfRange$1 = create$3('Integer out of Range');
1016
+
1017
+ /**
1018
+ * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
1019
+ *
1020
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
1021
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
1022
+ *
1023
+ * @function
1024
+ * @param {Decoder} decoder The decoder instance
1025
+ * @param {number} len The length of bytes to read
1026
+ * @return {Uint8Array}
1027
+ */
1028
+ const readUint8Array$1 = (decoder, len) => {
1029
+ const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
1030
+ decoder.pos += len;
1031
+ return view
1032
+ };
1033
+
1034
+ /**
1035
+ * Read variable length Uint8Array.
1036
+ *
1037
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
1038
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
1039
+ *
1040
+ * @function
1041
+ * @param {Decoder} decoder
1042
+ * @return {Uint8Array}
1043
+ */
1044
+ const readVarUint8Array$1 = decoder => readUint8Array$1(decoder, readVarUint$1(decoder));
1045
+
1046
+ /**
1047
+ * Read one byte as unsigned integer.
1048
+ * @function
1049
+ * @param {Decoder} decoder The decoder instance
1050
+ * @return {number} Unsigned 8-bit integer
1051
+ */
1052
+ const readUint8$1 = decoder => decoder.arr[decoder.pos++];
1053
+
1054
+ /**
1055
+ * Read unsigned integer (32bit) with variable length.
1056
+ * 1/8th of the storage is used as encoding overhead.
1057
+ * * numbers < 2^7 is stored in one bytlength
1058
+ * * numbers < 2^14 is stored in two bylength
1059
+ *
1060
+ * @function
1061
+ * @param {Decoder} decoder
1062
+ * @return {number} An unsigned integer.length
1063
+ */
1064
+ const readVarUint$1 = decoder => {
1065
+ let num = 0;
1066
+ let mult = 1;
1067
+ const len = decoder.arr.length;
1068
+ while (decoder.pos < len) {
1069
+ const r = decoder.arr[decoder.pos++];
1070
+ // num = num | ((r & binary.BITS7) << len)
1071
+ num = num + (r & BITS7$1) * mult; // shift $r << (7*#iterations) and add it to num
1072
+ mult *= 128; // next iteration, shift 7 "more" to the left
1073
+ if (r < BIT8$1) {
1074
+ return num
1075
+ }
1076
+ /* c8 ignore start */
1077
+ if (num > MAX_SAFE_INTEGER$1) {
1078
+ throw errorIntegerOutOfRange$1
1079
+ }
1080
+ /* c8 ignore stop */
1081
+ }
1082
+ throw errorUnexpectedEndOfArray$1
1083
+ };
1084
+
1085
+ /**
1086
+ * We don't test this function anymore as we use native decoding/encoding by default now.
1087
+ * Better not modify this anymore..
1088
+ *
1089
+ * Transforming utf8 to a string is pretty expensive. The code performs 10x better
1090
+ * when String.fromCodePoint is fed with all characters as arguments.
1091
+ * But most environments have a maximum number of arguments per functions.
1092
+ * For effiency reasons we apply a maximum of 10000 characters at once.
1093
+ *
1094
+ * @function
1095
+ * @param {Decoder} decoder
1096
+ * @return {String} The read String.
1097
+ */
1098
+ /* c8 ignore start */
1099
+ const _readVarStringPolyfill$1 = decoder => {
1100
+ let remainingLen = readVarUint$1(decoder);
1101
+ if (remainingLen === 0) {
1102
+ return ''
1103
+ } else {
1104
+ let encodedString = String.fromCodePoint(readUint8$1(decoder)); // remember to decrease remainingLen
1105
+ if (--remainingLen < 100) { // do not create a Uint8Array for small strings
1106
+ while (remainingLen--) {
1107
+ encodedString += String.fromCodePoint(readUint8$1(decoder));
1108
+ }
1109
+ } else {
1110
+ while (remainingLen > 0) {
1111
+ const nextLen = remainingLen < 10000 ? remainingLen : 10000;
1112
+ // this is dangerous, we create a fresh array view from the existing buffer
1113
+ const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
1114
+ decoder.pos += nextLen;
1115
+ // Starting with ES5.1 we can supply a generic array-like object as arguments
1116
+ encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes));
1117
+ remainingLen -= nextLen;
1118
+ }
1119
+ }
1120
+ return decodeURIComponent(escape(encodedString))
1121
+ }
1122
+ };
1123
+ /* c8 ignore stop */
1124
+
1125
+ /**
1126
+ * @function
1127
+ * @param {Decoder} decoder
1128
+ * @return {String} The read String
1129
+ */
1130
+ const _readVarStringNative$1 = decoder =>
1131
+ /** @type any */ (utf8TextDecoder$1).decode(readVarUint8Array$1(decoder));
1132
+
1133
+ /**
1134
+ * Read string of variable length
1135
+ * * varUint is used to store the length of the string
1136
+ *
1137
+ * @function
1138
+ * @param {Decoder} decoder
1139
+ * @return {String} The read String
1140
+ *
1141
+ */
1142
+ /* c8 ignore next */
1143
+ const readVarString$1 = utf8TextDecoder$1 ? _readVarStringNative$1 : _readVarStringPolyfill$1;
1144
+
1145
+ var AuthMessageType;
1146
+ (function (AuthMessageType) {
1147
+ AuthMessageType[AuthMessageType["Token"] = 0] = "Token";
1148
+ AuthMessageType[AuthMessageType["PermissionDenied"] = 1] = "PermissionDenied";
1149
+ AuthMessageType[AuthMessageType["Authenticated"] = 2] = "Authenticated";
1150
+ })(AuthMessageType || (AuthMessageType = {}));
1151
+ const writeAuthentication = (encoder, auth) => {
1152
+ writeVarUint$1(encoder, AuthMessageType.Token);
1153
+ writeVarString$1(encoder, auth);
1154
+ };
1155
+ const readAuthMessage = (decoder, sendToken, permissionDeniedHandler, authenticatedHandler) => {
1156
+ switch (readVarUint$1(decoder)) {
1157
+ case AuthMessageType.Token: {
1158
+ sendToken();
1159
+ break;
1160
+ }
1161
+ case AuthMessageType.PermissionDenied: {
1162
+ permissionDeniedHandler(readVarString$1(decoder));
1163
+ break;
1164
+ }
1165
+ case AuthMessageType.Authenticated: {
1166
+ authenticatedHandler(readVarString$1(decoder));
1167
+ break;
1168
+ }
1169
+ }
1170
+ };
1171
+
1172
+ const awarenessStatesToArray = (states) => {
1173
+ return Array.from(states.entries()).map(([key, value]) => {
1174
+ return {
1175
+ clientId: key,
1176
+ ...value,
1177
+ };
1178
+ });
1179
+ };
1180
+
1181
+ /**
1182
+ * State of the WebSocket connection.
1183
+ * https://developer.mozilla.org/de/docs/Web/API/WebSocket/readyState
1184
+ */
1185
+ var WsReadyStates;
1186
+ (function (WsReadyStates) {
1187
+ WsReadyStates[WsReadyStates["Connecting"] = 0] = "Connecting";
1188
+ WsReadyStates[WsReadyStates["Open"] = 1] = "Open";
1189
+ WsReadyStates[WsReadyStates["Closing"] = 2] = "Closing";
1190
+ WsReadyStates[WsReadyStates["Closed"] = 3] = "Closed";
1191
+ })(WsReadyStates || (WsReadyStates = {}));
1192
+
1193
+ function applyDefaults(options) {
1194
+ if (!options) {
1195
+ options = {};
1196
+ }
1197
+ return {
1198
+ delay: (options.delay === undefined) ? 200 : options.delay,
1199
+ initialDelay: (options.initialDelay === undefined) ? 0 : options.initialDelay,
1200
+ minDelay: (options.minDelay === undefined) ? 0 : options.minDelay,
1201
+ maxDelay: (options.maxDelay === undefined) ? 0 : options.maxDelay,
1202
+ factor: (options.factor === undefined) ? 0 : options.factor,
1203
+ maxAttempts: (options.maxAttempts === undefined) ? 3 : options.maxAttempts,
1204
+ timeout: (options.timeout === undefined) ? 0 : options.timeout,
1205
+ jitter: (options.jitter === true),
1206
+ initialJitter: (options.initialJitter === true),
1207
+ handleError: (options.handleError === undefined) ? null : options.handleError,
1208
+ handleTimeout: (options.handleTimeout === undefined) ? null : options.handleTimeout,
1209
+ beforeAttempt: (options.beforeAttempt === undefined) ? null : options.beforeAttempt,
1210
+ calculateDelay: (options.calculateDelay === undefined) ? null : options.calculateDelay
1211
+ };
1212
+ }
1213
+ async function sleep(delay) {
1214
+ return new Promise((resolve) => setTimeout(resolve, delay));
1215
+ }
1216
+ function defaultCalculateDelay(context, options) {
1217
+ let delay = options.delay;
1218
+ if (delay === 0) {
1219
+ // no delay between attempts
1220
+ return 0;
1221
+ }
1222
+ if (options.factor) {
1223
+ delay *= Math.pow(options.factor, context.attemptNum - 1);
1224
+ if (options.maxDelay !== 0) {
1225
+ delay = Math.min(delay, options.maxDelay);
1226
+ }
1227
+ }
1228
+ if (options.jitter) {
1229
+ // Jitter will result in a random value between `minDelay` and
1230
+ // calculated delay for a given attempt.
1231
+ // See https://www.awsarchitectureblog.com/2015/03/backoff.html
1232
+ // We're using the "full jitter" strategy.
1233
+ const min = Math.ceil(options.minDelay);
1234
+ const max = Math.floor(delay);
1235
+ delay = Math.floor(Math.random() * (max - min + 1)) + min;
1236
+ }
1237
+ return Math.round(delay);
1238
+ }
1239
+ async function retry(attemptFunc, attemptOptions) {
1240
+ const options = applyDefaults(attemptOptions);
1241
+ for (const prop of [
1242
+ 'delay',
1243
+ 'initialDelay',
1244
+ 'minDelay',
1245
+ 'maxDelay',
1246
+ 'maxAttempts',
1247
+ 'timeout'
1248
+ ]) {
1249
+ const value = options[prop];
1250
+ if (!Number.isInteger(value) || (value < 0)) {
1251
+ throw new Error(`Value for ${prop} must be an integer greater than or equal to 0`);
1252
+ }
1253
+ }
1254
+ if ((options.factor.constructor !== Number) || (options.factor < 0)) {
1255
+ throw new Error(`Value for factor must be a number greater than or equal to 0`);
1256
+ }
1257
+ if (options.delay < options.minDelay) {
1258
+ throw new Error(`delay cannot be less than minDelay (delay: ${options.delay}, minDelay: ${options.minDelay}`);
1259
+ }
1260
+ const context = {
1261
+ attemptNum: 0,
1262
+ attemptsRemaining: options.maxAttempts ? options.maxAttempts : -1,
1263
+ aborted: false,
1264
+ abort() {
1265
+ context.aborted = true;
1266
+ }
1267
+ };
1268
+ const calculateDelay = options.calculateDelay || defaultCalculateDelay;
1269
+ async function makeAttempt() {
1270
+ if (options.beforeAttempt) {
1271
+ options.beforeAttempt(context, options);
1272
+ }
1273
+ if (context.aborted) {
1274
+ const err = new Error(`Attempt aborted`);
1275
+ err.code = 'ATTEMPT_ABORTED';
1276
+ throw err;
1277
+ }
1278
+ const onError = async (err) => {
1279
+ if (options.handleError) {
1280
+ await options.handleError(err, context, options);
1281
+ }
1282
+ if (context.aborted || (context.attemptsRemaining === 0)) {
1283
+ throw err;
1284
+ }
1285
+ // We are about to try again so increment attempt number
1286
+ context.attemptNum++;
1287
+ const delay = calculateDelay(context, options);
1288
+ if (delay) {
1289
+ await sleep(delay);
1290
+ }
1291
+ return makeAttempt();
1292
+ };
1293
+ if (context.attemptsRemaining > 0) {
1294
+ context.attemptsRemaining--;
1295
+ }
1296
+ if (options.timeout) {
1297
+ return new Promise((resolve, reject) => {
1298
+ const timer = setTimeout(() => {
1299
+ if (options.handleTimeout) {
1300
+ // If calling handleTimeout throws an error that is not wrapped in a promise
1301
+ // we want to catch the error and reject.
1302
+ try {
1303
+ resolve(options.handleTimeout(context, options));
1304
+ }
1305
+ catch (e) {
1306
+ reject(e);
1307
+ }
1308
+ }
1309
+ else {
1310
+ const err = new Error(`Retry timeout (attemptNum: ${context.attemptNum}, timeout: ${options.timeout})`);
1311
+ err.code = 'ATTEMPT_TIMEOUT';
1312
+ reject(err);
1313
+ }
1314
+ }, options.timeout);
1315
+ attemptFunc(context, options).then((result) => {
1316
+ clearTimeout(timer);
1317
+ resolve(result);
1318
+ }).catch((err) => {
1319
+ clearTimeout(timer);
1320
+ // Calling resolve with a Promise that rejects here will result
1321
+ // in an unhandled rejection. Calling `reject` with errors
1322
+ // does not result in an unhandled rejection
1323
+ onError(err).then(resolve).catch(reject);
1324
+ });
1325
+ });
1326
+ }
1327
+ else {
1328
+ // No timeout provided so wait indefinitely for the returned promise
1329
+ // to be resolved.
1330
+ return attemptFunc(context, options).catch(onError);
1331
+ }
1332
+ }
1333
+ const initialDelay = options.calculateDelay
1334
+ ? options.calculateDelay(context, options)
1335
+ : options.initialDelay;
1336
+ if (initialDelay) {
1337
+ await sleep(initialDelay);
1338
+ }
1339
+ if (context.attemptNum < 1 && options.initialJitter) {
1340
+ const delay = calculateDelay(context, options);
1341
+ if (delay) {
1342
+ await sleep(delay);
1343
+ }
1344
+ }
1345
+ return makeAttempt();
1346
+ }
1347
+
1348
+ /**
1349
+ * Common Math expressions.
1350
+ *
1351
+ * @module math
1352
+ */
1353
+
1354
+ const floor = Math.floor;
1355
+
1356
+ /**
1357
+ * @function
1358
+ * @param {number} a
1359
+ * @param {number} b
1360
+ * @return {number} The smaller element of a and b
1361
+ */
1362
+ const min = (a, b) => a < b ? a : b;
1363
+
1364
+ /**
1365
+ * @function
1366
+ * @param {number} a
1367
+ * @param {number} b
1368
+ * @return {number} The bigger element of a and b
1369
+ */
1370
+ const max = (a, b) => a > b ? a : b;
1371
+
1372
+ /* eslint-env browser */
1373
+
1374
+ const BIT7 = 64;
1375
+ const BIT8 = 128;
1376
+ const BITS6 = 63;
1377
+ const BITS7 = 127;
1378
+
1379
+ /**
1380
+ * Utility helpers for working with numbers.
1381
+ *
1382
+ * @module number
1383
+ */
1384
+
1385
+
1386
+ const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
1387
+
1388
+ /**
1389
+ * Utility module to work with sets.
1390
+ *
1391
+ * @module set
1392
+ */
1393
+
1394
+ const create$2 = () => new Set();
1395
+
1396
+ /**
1397
+ * Utility module to work with Arrays.
1398
+ *
1399
+ * @module array
1400
+ */
1401
+
1402
+
1403
+ /**
1404
+ * Transforms something array-like to an actual Array.
1405
+ *
1406
+ * @function
1407
+ * @template T
1408
+ * @param {ArrayLike<T>|Iterable<T>} arraylike
1409
+ * @return {T}
1410
+ */
1411
+ const from = Array.from;
1412
+
1413
+ /**
1414
+ * @param {string} str
1415
+ * @return {Uint8Array}
1416
+ */
1417
+ const _encodeUtf8Polyfill = str => {
1418
+ const encodedString = unescape(encodeURIComponent(str));
1419
+ const len = encodedString.length;
1420
+ const buf = new Uint8Array(len);
1421
+ for (let i = 0; i < len; i++) {
1422
+ buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
1423
+ }
1424
+ return buf
1425
+ };
1426
+
1427
+ /* c8 ignore next */
1428
+ const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
1429
+
1430
+ /**
1431
+ * @param {string} str
1432
+ * @return {Uint8Array}
1433
+ */
1434
+ const _encodeUtf8Native = str => utf8TextEncoder.encode(str);
1435
+
1436
+ /**
1437
+ * @param {string} str
1438
+ * @return {Uint8Array}
1439
+ */
1440
+ /* c8 ignore next */
1441
+ const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill;
1442
+
1443
+ /* c8 ignore next */
1444
+ let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
1445
+
1446
+ /* c8 ignore start */
1447
+ if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
1448
+ // Safari doesn't handle BOM correctly.
1449
+ // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
1450
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
1451
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
1452
+ // Another issue is that from then on no BOM chars are recognized anymore
1453
+ /* c8 ignore next */
1454
+ utf8TextDecoder = null;
1455
+ }
1456
+
1457
+ /**
1458
+ * Efficient schema-less binary encoding with support for variable length encoding.
1459
+ *
1460
+ * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
1461
+ *
1462
+ * Encodes numbers in little-endian order (least to most significant byte order)
1463
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
1464
+ * which is also used in Protocol Buffers.
1465
+ *
1466
+ * ```js
1467
+ * // encoding step
1468
+ * const encoder = encoding.createEncoder()
1469
+ * encoding.writeVarUint(encoder, 256)
1470
+ * encoding.writeVarString(encoder, 'Hello world!')
1471
+ * const buf = encoding.toUint8Array(encoder)
1472
+ * ```
1473
+ *
1474
+ * ```js
1475
+ * // decoding step
1476
+ * const decoder = decoding.createDecoder(buf)
1477
+ * decoding.readVarUint(decoder) // => 256
1478
+ * decoding.readVarString(decoder) // => 'Hello world!'
1479
+ * decoding.hasContent(decoder) // => false - all data is read
1480
+ * ```
1481
+ *
1482
+ * @module encoding
1483
+ */
1484
+
1485
+
1486
+ /**
1487
+ * A BinaryEncoder handles the encoding to an Uint8Array.
1488
+ */
1489
+ class Encoder {
1490
+ constructor () {
1491
+ this.cpos = 0;
1492
+ this.cbuf = new Uint8Array(100);
1493
+ /**
1494
+ * @type {Array<Uint8Array>}
1495
+ */
1496
+ this.bufs = [];
1497
+ }
1498
+ }
1499
+
1500
+ /**
1501
+ * @function
1502
+ * @return {Encoder}
1503
+ */
1504
+ const createEncoder = () => new Encoder();
1505
+
1506
+ /**
1507
+ * The current length of the encoded data.
1508
+ *
1509
+ * @function
1510
+ * @param {Encoder} encoder
1511
+ * @return {number}
1512
+ */
1513
+ const length$1 = encoder => {
1514
+ let len = encoder.cpos;
1515
+ for (let i = 0; i < encoder.bufs.length; i++) {
1516
+ len += encoder.bufs[i].length;
1517
+ }
1518
+ return len
1519
+ };
1520
+
1521
+ /**
1522
+ * Transform to Uint8Array.
1523
+ *
1524
+ * @function
1525
+ * @param {Encoder} encoder
1526
+ * @return {Uint8Array} The created ArrayBuffer.
1527
+ */
1528
+ const toUint8Array = encoder => {
1529
+ const uint8arr = new Uint8Array(length$1(encoder));
1530
+ let curPos = 0;
1531
+ for (let i = 0; i < encoder.bufs.length; i++) {
1532
+ const d = encoder.bufs[i];
1533
+ uint8arr.set(d, curPos);
1534
+ curPos += d.length;
1535
+ }
1536
+ uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
1537
+ return uint8arr
1538
+ };
1539
+
1540
+ /**
1541
+ * Write one byte to the encoder.
1542
+ *
1543
+ * @function
1544
+ * @param {Encoder} encoder
1545
+ * @param {number} num The byte that is to be encoded.
1546
+ */
1547
+ const write = (encoder, num) => {
1548
+ const bufferLen = encoder.cbuf.length;
1549
+ if (encoder.cpos === bufferLen) {
1550
+ encoder.bufs.push(encoder.cbuf);
1551
+ encoder.cbuf = new Uint8Array(bufferLen * 2);
1552
+ encoder.cpos = 0;
1553
+ }
1554
+ encoder.cbuf[encoder.cpos++] = num;
1555
+ };
1556
+
1557
+ /**
1558
+ * Write a variable length unsigned integer. Max encodable integer is 2^53.
1559
+ *
1560
+ * @function
1561
+ * @param {Encoder} encoder
1562
+ * @param {number} num The number that is to be encoded.
1563
+ */
1564
+ const writeVarUint = (encoder, num) => {
1565
+ while (num > BITS7) {
1566
+ write(encoder, BIT8 | (BITS7 & num));
1567
+ num = floor(num / 128); // shift >>> 7
1568
+ }
1569
+ write(encoder, BITS7 & num);
1570
+ };
1571
+
1572
+ /**
1573
+ * A cache to store strings temporarily
1574
+ */
1575
+ const _strBuffer = new Uint8Array(30000);
1576
+ const _maxStrBSize = _strBuffer.length / 3;
1577
+
1578
+ /**
1579
+ * Write a variable length string.
1580
+ *
1581
+ * @function
1582
+ * @param {Encoder} encoder
1583
+ * @param {String} str The string that is to be encoded.
1584
+ */
1585
+ const _writeVarStringNative = (encoder, str) => {
1586
+ if (str.length < _maxStrBSize) {
1587
+ // We can encode the string into the existing buffer
1588
+ /* c8 ignore next */
1589
+ const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
1590
+ writeVarUint(encoder, written);
1591
+ for (let i = 0; i < written; i++) {
1592
+ write(encoder, _strBuffer[i]);
1593
+ }
1594
+ } else {
1595
+ writeVarUint8Array(encoder, encodeUtf8(str));
1596
+ }
1597
+ };
1598
+
1599
+ /**
1600
+ * Write a variable length string.
1601
+ *
1602
+ * @function
1603
+ * @param {Encoder} encoder
1604
+ * @param {String} str The string that is to be encoded.
1605
+ */
1606
+ const _writeVarStringPolyfill = (encoder, str) => {
1607
+ const encodedString = unescape(encodeURIComponent(str));
1608
+ const len = encodedString.length;
1609
+ writeVarUint(encoder, len);
1610
+ for (let i = 0; i < len; i++) {
1611
+ write(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
1612
+ }
1613
+ };
1614
+
1615
+ /**
1616
+ * Write a variable length string.
1617
+ *
1618
+ * @function
1619
+ * @param {Encoder} encoder
1620
+ * @param {String} str The string that is to be encoded.
1621
+ */
1622
+ /* c8 ignore next */
1623
+ const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
1624
+
1625
+ /**
1626
+ * Append fixed-length Uint8Array to the encoder.
1627
+ *
1628
+ * @function
1629
+ * @param {Encoder} encoder
1630
+ * @param {Uint8Array} uint8Array
1631
+ */
1632
+ const writeUint8Array = (encoder, uint8Array) => {
1633
+ const bufferLen = encoder.cbuf.length;
1634
+ const cpos = encoder.cpos;
1635
+ const leftCopyLen = min(bufferLen - cpos, uint8Array.length);
1636
+ const rightCopyLen = uint8Array.length - leftCopyLen;
1637
+ encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
1638
+ encoder.cpos += leftCopyLen;
1639
+ if (rightCopyLen > 0) {
1640
+ // Still something to write, write right half..
1641
+ // Append new buffer
1642
+ encoder.bufs.push(encoder.cbuf);
1643
+ // must have at least size of remaining buffer
1644
+ encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen));
1645
+ // copy array
1646
+ encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
1647
+ encoder.cpos = rightCopyLen;
1648
+ }
1649
+ };
1650
+
1651
+ /**
1652
+ * Append an Uint8Array to Encoder.
1653
+ *
1654
+ * @function
1655
+ * @param {Encoder} encoder
1656
+ * @param {Uint8Array} uint8Array
1657
+ */
1658
+ const writeVarUint8Array = (encoder, uint8Array) => {
1659
+ writeVarUint(encoder, uint8Array.byteLength);
1660
+ writeUint8Array(encoder, uint8Array);
1661
+ };
1662
+
1663
+ /**
1664
+ * Error helpers.
1665
+ *
1666
+ * @module error
1667
+ */
1668
+
1669
+ /**
1670
+ * @param {string} s
1671
+ * @return {Error}
1672
+ */
1673
+ /* c8 ignore next */
1674
+ const create$1 = s => new Error(s);
1675
+
1676
+ /**
1677
+ * Efficient schema-less binary decoding with support for variable length encoding.
1678
+ *
1679
+ * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
1680
+ *
1681
+ * Encodes numbers in little-endian order (least to most significant byte order)
1682
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
1683
+ * which is also used in Protocol Buffers.
1684
+ *
1685
+ * ```js
1686
+ * // encoding step
1687
+ * const encoder = encoding.createEncoder()
1688
+ * encoding.writeVarUint(encoder, 256)
1689
+ * encoding.writeVarString(encoder, 'Hello world!')
1690
+ * const buf = encoding.toUint8Array(encoder)
1691
+ * ```
1692
+ *
1693
+ * ```js
1694
+ * // decoding step
1695
+ * const decoder = decoding.createDecoder(buf)
1696
+ * decoding.readVarUint(decoder) // => 256
1697
+ * decoding.readVarString(decoder) // => 'Hello world!'
1698
+ * decoding.hasContent(decoder) // => false - all data is read
1699
+ * ```
1700
+ *
1701
+ * @module decoding
1702
+ */
1703
+
1704
+
1705
+ const errorUnexpectedEndOfArray = create$1('Unexpected end of array');
1706
+ const errorIntegerOutOfRange = create$1('Integer out of Range');
1707
+
1708
+ /**
1709
+ * A Decoder handles the decoding of an Uint8Array.
1710
+ */
1711
+ class Decoder {
1712
+ /**
1713
+ * @param {Uint8Array} uint8Array Binary data to decode
1714
+ */
1715
+ constructor (uint8Array) {
1716
+ /**
1717
+ * Decoding target.
1718
+ *
1719
+ * @type {Uint8Array}
1720
+ */
1721
+ this.arr = uint8Array;
1722
+ /**
1723
+ * Current decoding position.
1724
+ *
1725
+ * @type {number}
1726
+ */
1727
+ this.pos = 0;
1728
+ }
1729
+ }
1730
+
1731
+ /**
1732
+ * @function
1733
+ * @param {Uint8Array} uint8Array
1734
+ * @return {Decoder}
1735
+ */
1736
+ const createDecoder = uint8Array => new Decoder(uint8Array);
1737
+
1738
+ /**
1739
+ * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
1740
+ *
1741
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
1742
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
1743
+ *
1744
+ * @function
1745
+ * @param {Decoder} decoder The decoder instance
1746
+ * @param {number} len The length of bytes to read
1747
+ * @return {Uint8Array}
1748
+ */
1749
+ const readUint8Array = (decoder, len) => {
1750
+ const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
1751
+ decoder.pos += len;
1752
+ return view
1753
+ };
1754
+
1755
+ /**
1756
+ * Read variable length Uint8Array.
1757
+ *
1758
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
1759
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
1760
+ *
1761
+ * @function
1762
+ * @param {Decoder} decoder
1763
+ * @return {Uint8Array}
1764
+ */
1765
+ const readVarUint8Array = decoder => readUint8Array(decoder, readVarUint(decoder));
1766
+
1767
+ /**
1768
+ * Read one byte as unsigned integer.
1769
+ * @function
1770
+ * @param {Decoder} decoder The decoder instance
1771
+ * @return {number} Unsigned 8-bit integer
1772
+ */
1773
+ const readUint8 = decoder => decoder.arr[decoder.pos++];
1774
+
1775
+ /**
1776
+ * Read unsigned integer (32bit) with variable length.
1777
+ * 1/8th of the storage is used as encoding overhead.
1778
+ * * numbers < 2^7 is stored in one bytlength
1779
+ * * numbers < 2^14 is stored in two bylength
1780
+ *
1781
+ * @function
1782
+ * @param {Decoder} decoder
1783
+ * @return {number} An unsigned integer.length
1784
+ */
1785
+ const readVarUint = decoder => {
1786
+ let num = 0;
1787
+ let mult = 1;
1788
+ const len = decoder.arr.length;
1789
+ while (decoder.pos < len) {
1790
+ const r = decoder.arr[decoder.pos++];
1791
+ // num = num | ((r & binary.BITS7) << len)
1792
+ num = num + (r & BITS7) * mult; // shift $r << (7*#iterations) and add it to num
1793
+ mult *= 128; // next iteration, shift 7 "more" to the left
1794
+ if (r < BIT8) {
1795
+ return num
1796
+ }
1797
+ /* c8 ignore start */
1798
+ if (num > MAX_SAFE_INTEGER) {
1799
+ throw errorIntegerOutOfRange
1800
+ }
1801
+ /* c8 ignore stop */
1802
+ }
1803
+ throw errorUnexpectedEndOfArray
1804
+ };
1805
+
1806
+ /**
1807
+ * Read signed integer (32bit) with variable length.
1808
+ * 1/8th of the storage is used as encoding overhead.
1809
+ * * numbers < 2^7 is stored in one bytlength
1810
+ * * numbers < 2^14 is stored in two bylength
1811
+ * @todo This should probably create the inverse ~num if number is negative - but this would be a breaking change.
1812
+ *
1813
+ * @function
1814
+ * @param {Decoder} decoder
1815
+ * @return {number} An unsigned integer.length
1816
+ */
1817
+ const readVarInt = decoder => {
1818
+ let r = decoder.arr[decoder.pos++];
1819
+ let num = r & BITS6;
1820
+ let mult = 64;
1821
+ const sign = (r & BIT7) > 0 ? -1 : 1;
1822
+ if ((r & BIT8) === 0) {
1823
+ // don't continue reading
1824
+ return sign * num
1825
+ }
1826
+ const len = decoder.arr.length;
1827
+ while (decoder.pos < len) {
1828
+ r = decoder.arr[decoder.pos++];
1829
+ // num = num | ((r & binary.BITS7) << len)
1830
+ num = num + (r & BITS7) * mult;
1831
+ mult *= 128;
1832
+ if (r < BIT8) {
1833
+ return sign * num
1834
+ }
1835
+ /* c8 ignore start */
1836
+ if (num > MAX_SAFE_INTEGER) {
1837
+ throw errorIntegerOutOfRange
1838
+ }
1839
+ /* c8 ignore stop */
1840
+ }
1841
+ throw errorUnexpectedEndOfArray
1842
+ };
1843
+
1844
+ /**
1845
+ * We don't test this function anymore as we use native decoding/encoding by default now.
1846
+ * Better not modify this anymore..
1847
+ *
1848
+ * Transforming utf8 to a string is pretty expensive. The code performs 10x better
1849
+ * when String.fromCodePoint is fed with all characters as arguments.
1850
+ * But most environments have a maximum number of arguments per functions.
1851
+ * For effiency reasons we apply a maximum of 10000 characters at once.
1852
+ *
1853
+ * @function
1854
+ * @param {Decoder} decoder
1855
+ * @return {String} The read String.
1856
+ */
1857
+ /* c8 ignore start */
1858
+ const _readVarStringPolyfill = decoder => {
1859
+ let remainingLen = readVarUint(decoder);
1860
+ if (remainingLen === 0) {
1861
+ return ''
1862
+ } else {
1863
+ let encodedString = String.fromCodePoint(readUint8(decoder)); // remember to decrease remainingLen
1864
+ if (--remainingLen < 100) { // do not create a Uint8Array for small strings
1865
+ while (remainingLen--) {
1866
+ encodedString += String.fromCodePoint(readUint8(decoder));
1867
+ }
1868
+ } else {
1869
+ while (remainingLen > 0) {
1870
+ const nextLen = remainingLen < 10000 ? remainingLen : 10000;
1871
+ // this is dangerous, we create a fresh array view from the existing buffer
1872
+ const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
1873
+ decoder.pos += nextLen;
1874
+ // Starting with ES5.1 we can supply a generic array-like object as arguments
1875
+ encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes));
1876
+ remainingLen -= nextLen;
1877
+ }
1878
+ }
1879
+ return decodeURIComponent(escape(encodedString))
1880
+ }
1881
+ };
1882
+ /* c8 ignore stop */
1883
+
1884
+ /**
1885
+ * @function
1886
+ * @param {Decoder} decoder
1887
+ * @return {String} The read String
1888
+ */
1889
+ const _readVarStringNative = decoder =>
1890
+ /** @type any */ (utf8TextDecoder).decode(readVarUint8Array(decoder));
1891
+
1892
+ /**
1893
+ * Read string of variable length
1894
+ * * varUint is used to store the length of the string
1895
+ *
1896
+ * @function
1897
+ * @param {Decoder} decoder
1898
+ * @return {String} The read String
1899
+ *
1900
+ */
1901
+ /* c8 ignore next */
1902
+ const readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill;
1903
+
1904
+ /**
1905
+ * Look ahead and read varString without incrementing position
1906
+ *
1907
+ * @function
1908
+ * @param {Decoder} decoder
1909
+ * @return {string}
1910
+ */
1911
+ const peekVarString = decoder => {
1912
+ const pos = decoder.pos;
1913
+ const s = readVarString(decoder);
1914
+ decoder.pos = pos;
1915
+ return s
1916
+ };
1917
+
1918
+ /**
1919
+ * Utility module to work with time.
1920
+ *
1921
+ * @module time
1922
+ */
1923
+
1924
+
1925
+ /**
1926
+ * Return current unix time.
1927
+ *
1928
+ * @return {number}
1929
+ */
1930
+ const getUnixTime = Date.now;
1931
+
1932
+ /**
1933
+ * Utility module to work with key-value stores.
1934
+ *
1935
+ * @module map
1936
+ */
1937
+
1938
+ /**
1939
+ * Creates a new Map instance.
1940
+ *
1941
+ * @function
1942
+ * @return {Map<any, any>}
1943
+ *
1944
+ * @function
1945
+ */
1946
+ const create = () => new Map();
1947
+
1948
+ /**
1949
+ * Get map property. Create T if property is undefined and set T on map.
1950
+ *
1951
+ * ```js
1952
+ * const listeners = map.setIfUndefined(events, 'eventName', set.create)
1953
+ * listeners.add(listener)
1954
+ * ```
1955
+ *
1956
+ * @function
1957
+ * @template {Map<any, any>} MAP
1958
+ * @template {MAP extends Map<any,infer V> ? function():V : unknown} CF
1959
+ * @param {MAP} map
1960
+ * @param {MAP extends Map<infer K,any> ? K : unknown} key
1961
+ * @param {CF} createT
1962
+ * @return {ReturnType<CF>}
1963
+ */
1964
+ const setIfUndefined = (map, key, createT) => {
1965
+ let set = map.get(key);
1966
+ if (set === undefined) {
1967
+ map.set(key, set = createT());
1968
+ }
1969
+ return set
1970
+ };
1971
+
1972
+ /**
1973
+ * Observable class prototype.
1974
+ *
1975
+ * @module observable
1976
+ */
1977
+
1978
+
1979
+ /* c8 ignore start */
1980
+ /**
1981
+ * Handles named events.
1982
+ *
1983
+ * @deprecated
1984
+ * @template N
1985
+ */
1986
+ class Observable {
1987
+ constructor () {
1988
+ /**
1989
+ * Some desc.
1990
+ * @type {Map<N, any>}
1991
+ */
1992
+ this._observers = create();
1993
+ }
1994
+
1995
+ /**
1996
+ * @param {N} name
1997
+ * @param {function} f
1998
+ */
1999
+ on (name, f) {
2000
+ setIfUndefined(this._observers, name, create$2).add(f);
2001
+ }
2002
+
2003
+ /**
2004
+ * @param {N} name
2005
+ * @param {function} f
2006
+ */
2007
+ once (name, f) {
2008
+ /**
2009
+ * @param {...any} args
2010
+ */
2011
+ const _f = (...args) => {
2012
+ this.off(name, _f);
2013
+ f(...args);
2014
+ };
2015
+ this.on(name, _f);
2016
+ }
2017
+
2018
+ /**
2019
+ * @param {N} name
2020
+ * @param {function} f
2021
+ */
2022
+ off (name, f) {
2023
+ const observers = this._observers.get(name);
2024
+ if (observers !== undefined) {
2025
+ observers.delete(f);
2026
+ if (observers.size === 0) {
2027
+ this._observers.delete(name);
2028
+ }
2029
+ }
2030
+ }
2031
+
2032
+ /**
2033
+ * Emit a named event. All registered event listeners that listen to the
2034
+ * specified name will receive the event.
2035
+ *
2036
+ * @todo This should catch exceptions
2037
+ *
2038
+ * @param {N} name The event name.
2039
+ * @param {Array<any>} args The arguments that are applied to the event listener.
2040
+ */
2041
+ emit (name, args) {
2042
+ // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
2043
+ return from((this._observers.get(name) || create()).values()).forEach(f => f(...args))
2044
+ }
2045
+
2046
+ destroy () {
2047
+ this._observers = create();
2048
+ }
2049
+ }
2050
+ /* c8 ignore end */
2051
+
2052
+ /**
2053
+ * Utility functions for working with EcmaScript objects.
2054
+ *
2055
+ * @module object
2056
+ */
2057
+
2058
+
2059
+ /**
2060
+ * @param {Object<string,any>} obj
2061
+ */
2062
+ const keys = Object.keys;
2063
+
2064
+ /**
2065
+ * @deprecated use object.size instead
2066
+ * @param {Object<string,any>} obj
2067
+ * @return {number}
2068
+ */
2069
+ const length = obj => keys(obj).length;
2070
+
2071
+ /**
2072
+ * Calls `Object.prototype.hasOwnProperty`.
2073
+ *
2074
+ * @param {any} obj
2075
+ * @param {string|symbol} key
2076
+ * @return {boolean}
2077
+ */
2078
+ const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
2079
+
2080
+ /**
2081
+ * Common functions and function call helpers.
2082
+ *
2083
+ * @module function
2084
+ */
2085
+
2086
+
2087
+ /**
2088
+ * @template T
2089
+ *
2090
+ * @param {T} a
2091
+ * @param {T} b
2092
+ * @return {boolean}
2093
+ */
2094
+ const equalityStrict = (a, b) => a === b;
2095
+
2096
+ /* c8 ignore start */
2097
+
2098
+ /**
2099
+ * @param {any} a
2100
+ * @param {any} b
2101
+ * @return {boolean}
2102
+ */
2103
+ const equalityDeep = (a, b) => {
2104
+ if (a == null || b == null) {
2105
+ return equalityStrict(a, b)
2106
+ }
2107
+ if (a.constructor !== b.constructor) {
2108
+ return false
2109
+ }
2110
+ if (a === b) {
2111
+ return true
2112
+ }
2113
+ switch (a.constructor) {
2114
+ case ArrayBuffer:
2115
+ a = new Uint8Array(a);
2116
+ b = new Uint8Array(b);
2117
+ // eslint-disable-next-line no-fallthrough
2118
+ case Uint8Array: {
2119
+ if (a.byteLength !== b.byteLength) {
2120
+ return false
2121
+ }
2122
+ for (let i = 0; i < a.length; i++) {
2123
+ if (a[i] !== b[i]) {
2124
+ return false
2125
+ }
2126
+ }
2127
+ break
2128
+ }
2129
+ case Set: {
2130
+ if (a.size !== b.size) {
2131
+ return false
2132
+ }
2133
+ for (const value of a) {
2134
+ if (!b.has(value)) {
2135
+ return false
2136
+ }
2137
+ }
2138
+ break
2139
+ }
2140
+ case Map: {
2141
+ if (a.size !== b.size) {
2142
+ return false
2143
+ }
2144
+ for (const key of a.keys()) {
2145
+ if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
2146
+ return false
2147
+ }
2148
+ }
2149
+ break
2150
+ }
2151
+ case Object:
2152
+ if (length(a) !== length(b)) {
2153
+ return false
2154
+ }
2155
+ for (const key in a) {
2156
+ if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
2157
+ return false
2158
+ }
2159
+ }
2160
+ break
2161
+ case Array:
2162
+ if (a.length !== b.length) {
2163
+ return false
2164
+ }
2165
+ for (let i = 0; i < a.length; i++) {
2166
+ if (!equalityDeep(a[i], b[i])) {
2167
+ return false
2168
+ }
2169
+ }
2170
+ break
2171
+ default:
2172
+ return false
2173
+ }
2174
+ return true
2175
+ };
2176
+
2177
+ /**
2178
+ * @module awareness-protocol
2179
+ */
2180
+
2181
+
2182
+ const outdatedTimeout = 30000;
2183
+
2184
+ /**
2185
+ * @typedef {Object} MetaClientState
2186
+ * @property {number} MetaClientState.clock
2187
+ * @property {number} MetaClientState.lastUpdated unix timestamp
2188
+ */
2189
+
2190
+ /**
2191
+ * The Awareness class implements a simple shared state protocol that can be used for non-persistent data like awareness information
2192
+ * (cursor, username, status, ..). Each client can update its own local state and listen to state changes of
2193
+ * remote clients. Every client may set a state of a remote peer to `null` to mark the client as offline.
2194
+ *
2195
+ * Each client is identified by a unique client id (something we borrow from `doc.clientID`). A client can override
2196
+ * its own state by propagating a message with an increasing timestamp (`clock`). If such a message is received, it is
2197
+ * applied if the known state of that client is older than the new state (`clock < newClock`). If a client thinks that
2198
+ * a remote client is offline, it may propagate a message with
2199
+ * `{ clock: currentClientClock, state: null, client: remoteClient }`. If such a
2200
+ * message is received, and the known clock of that client equals the received clock, it will override the state with `null`.
2201
+ *
2202
+ * Before a client disconnects, it should propagate a `null` state with an updated clock.
2203
+ *
2204
+ * Awareness states must be updated every 30 seconds. Otherwise the Awareness instance will delete the client state.
2205
+ *
2206
+ * @extends {Observable<string>}
2207
+ */
2208
+ class Awareness extends Observable {
2209
+ /**
2210
+ * @param {Y.Doc} doc
2211
+ */
2212
+ constructor (doc) {
2213
+ super();
2214
+ this.doc = doc;
2215
+ /**
2216
+ * @type {number}
2217
+ */
2218
+ this.clientID = doc.clientID;
2219
+ /**
2220
+ * Maps from client id to client state
2221
+ * @type {Map<number, Object<string, any>>}
2222
+ */
2223
+ this.states = new Map();
2224
+ /**
2225
+ * @type {Map<number, MetaClientState>}
2226
+ */
2227
+ this.meta = new Map();
2228
+ this._checkInterval = /** @type {any} */ (setInterval(() => {
2229
+ const now = getUnixTime();
2230
+ if (this.getLocalState() !== null && (outdatedTimeout / 2 <= now - /** @type {{lastUpdated:number}} */ (this.meta.get(this.clientID)).lastUpdated)) {
2231
+ // renew local clock
2232
+ this.setLocalState(this.getLocalState());
2233
+ }
2234
+ /**
2235
+ * @type {Array<number>}
2236
+ */
2237
+ const remove = [];
2238
+ this.meta.forEach((meta, clientid) => {
2239
+ if (clientid !== this.clientID && outdatedTimeout <= now - meta.lastUpdated && this.states.has(clientid)) {
2240
+ remove.push(clientid);
2241
+ }
2242
+ });
2243
+ if (remove.length > 0) {
2244
+ removeAwarenessStates(this, remove, 'timeout');
2245
+ }
2246
+ }, floor(outdatedTimeout / 10)));
2247
+ doc.on('destroy', () => {
2248
+ this.destroy();
2249
+ });
2250
+ this.setLocalState({});
2251
+ }
2252
+
2253
+ destroy () {
2254
+ this.emit('destroy', [this]);
2255
+ this.setLocalState(null);
2256
+ super.destroy();
2257
+ clearInterval(this._checkInterval);
2258
+ }
2259
+
2260
+ /**
2261
+ * @return {Object<string,any>|null}
2262
+ */
2263
+ getLocalState () {
2264
+ return this.states.get(this.clientID) || null
2265
+ }
2266
+
2267
+ /**
2268
+ * @param {Object<string,any>|null} state
2269
+ */
2270
+ setLocalState (state) {
2271
+ const clientID = this.clientID;
2272
+ const currLocalMeta = this.meta.get(clientID);
2273
+ const clock = currLocalMeta === undefined ? 0 : currLocalMeta.clock + 1;
2274
+ const prevState = this.states.get(clientID);
2275
+ if (state === null) {
2276
+ this.states.delete(clientID);
2277
+ } else {
2278
+ this.states.set(clientID, state);
2279
+ }
2280
+ this.meta.set(clientID, {
2281
+ clock,
2282
+ lastUpdated: getUnixTime()
2283
+ });
2284
+ const added = [];
2285
+ const updated = [];
2286
+ const filteredUpdated = [];
2287
+ const removed = [];
2288
+ if (state === null) {
2289
+ removed.push(clientID);
2290
+ } else if (prevState == null) {
2291
+ if (state != null) {
2292
+ added.push(clientID);
2293
+ }
2294
+ } else {
2295
+ updated.push(clientID);
2296
+ if (!equalityDeep(prevState, state)) {
2297
+ filteredUpdated.push(clientID);
2298
+ }
2299
+ }
2300
+ if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
2301
+ this.emit('change', [{ added, updated: filteredUpdated, removed }, 'local']);
2302
+ }
2303
+ this.emit('update', [{ added, updated, removed }, 'local']);
2304
+ }
2305
+
2306
+ /**
2307
+ * @param {string} field
2308
+ * @param {any} value
2309
+ */
2310
+ setLocalStateField (field, value) {
2311
+ const state = this.getLocalState();
2312
+ if (state !== null) {
2313
+ this.setLocalState({
2314
+ ...state,
2315
+ [field]: value
2316
+ });
2317
+ }
2318
+ }
2319
+
2320
+ /**
2321
+ * @return {Map<number,Object<string,any>>}
2322
+ */
2323
+ getStates () {
2324
+ return this.states
2325
+ }
2326
+ }
2327
+
2328
+ /**
2329
+ * Mark (remote) clients as inactive and remove them from the list of active peers.
2330
+ * This change will be propagated to remote clients.
2331
+ *
2332
+ * @param {Awareness} awareness
2333
+ * @param {Array<number>} clients
2334
+ * @param {any} origin
2335
+ */
2336
+ const removeAwarenessStates = (awareness, clients, origin) => {
2337
+ const removed = [];
2338
+ for (let i = 0; i < clients.length; i++) {
2339
+ const clientID = clients[i];
2340
+ if (awareness.states.has(clientID)) {
2341
+ awareness.states.delete(clientID);
2342
+ if (clientID === awareness.clientID) {
2343
+ const curMeta = /** @type {MetaClientState} */ (awareness.meta.get(clientID));
2344
+ awareness.meta.set(clientID, {
2345
+ clock: curMeta.clock + 1,
2346
+ lastUpdated: getUnixTime()
2347
+ });
2348
+ }
2349
+ removed.push(clientID);
2350
+ }
2351
+ }
2352
+ if (removed.length > 0) {
2353
+ awareness.emit('change', [{ added: [], updated: [], removed }, origin]);
2354
+ awareness.emit('update', [{ added: [], updated: [], removed }, origin]);
2355
+ }
2356
+ };
2357
+
2358
+ /**
2359
+ * @param {Awareness} awareness
2360
+ * @param {Array<number>} clients
2361
+ * @return {Uint8Array}
2362
+ */
2363
+ const encodeAwarenessUpdate = (awareness, clients, states = awareness.states) => {
2364
+ const len = clients.length;
2365
+ const encoder = createEncoder();
2366
+ writeVarUint(encoder, len);
2367
+ for (let i = 0; i < len; i++) {
2368
+ const clientID = clients[i];
2369
+ const state = states.get(clientID) || null;
2370
+ const clock = /** @type {MetaClientState} */ (awareness.meta.get(clientID)).clock;
2371
+ writeVarUint(encoder, clientID);
2372
+ writeVarUint(encoder, clock);
2373
+ writeVarString(encoder, JSON.stringify(state));
2374
+ }
2375
+ return toUint8Array(encoder)
2376
+ };
2377
+
2378
+ /**
2379
+ * @param {Awareness} awareness
2380
+ * @param {Uint8Array} update
2381
+ * @param {any} origin This will be added to the emitted change event
2382
+ */
2383
+ const applyAwarenessUpdate = (awareness, update, origin) => {
2384
+ const decoder = createDecoder(update);
2385
+ const timestamp = getUnixTime();
2386
+ const added = [];
2387
+ const updated = [];
2388
+ const filteredUpdated = [];
2389
+ const removed = [];
2390
+ const len = readVarUint(decoder);
2391
+ for (let i = 0; i < len; i++) {
2392
+ const clientID = readVarUint(decoder);
2393
+ let clock = readVarUint(decoder);
2394
+ const state = JSON.parse(readVarString(decoder));
2395
+ const clientMeta = awareness.meta.get(clientID);
2396
+ const prevState = awareness.states.get(clientID);
2397
+ const currClock = clientMeta === undefined ? 0 : clientMeta.clock;
2398
+ if (currClock < clock || (currClock === clock && state === null && awareness.states.has(clientID))) {
2399
+ if (state === null) {
2400
+ // never let a remote client remove this local state
2401
+ if (clientID === awareness.clientID && awareness.getLocalState() != null) {
2402
+ // remote client removed the local state. Do not remote state. Broadcast a message indicating
2403
+ // that this client still exists by increasing the clock
2404
+ clock++;
2405
+ } else {
2406
+ awareness.states.delete(clientID);
2407
+ }
2408
+ } else {
2409
+ awareness.states.set(clientID, state);
2410
+ }
2411
+ awareness.meta.set(clientID, {
2412
+ clock,
2413
+ lastUpdated: timestamp
2414
+ });
2415
+ if (clientMeta === undefined && state !== null) {
2416
+ added.push(clientID);
2417
+ } else if (clientMeta !== undefined && state === null) {
2418
+ removed.push(clientID);
2419
+ } else if (state !== null) {
2420
+ if (!equalityDeep(state, prevState)) {
2421
+ filteredUpdated.push(clientID);
2422
+ }
2423
+ updated.push(clientID);
2424
+ }
2425
+ }
2426
+ }
2427
+ if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
2428
+ awareness.emit('change', [{
2429
+ added, updated: filteredUpdated, removed
2430
+ }, origin]);
2431
+ }
2432
+ if (added.length > 0 || updated.length > 0 || removed.length > 0) {
2433
+ awareness.emit('update', [{
2434
+ added, updated, removed
2435
+ }, origin]);
2436
+ }
2437
+ };
2438
+
2439
+ class EventEmitter {
2440
+ constructor() {
2441
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
2442
+ this.callbacks = {};
2443
+ }
2444
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
2445
+ on(event, fn) {
2446
+ if (!this.callbacks[event]) {
2447
+ this.callbacks[event] = [];
2448
+ }
2449
+ this.callbacks[event].push(fn);
2450
+ return this;
2451
+ }
2452
+ emit(event, ...args) {
2453
+ const callbacks = this.callbacks[event];
2454
+ if (callbacks) {
2455
+ callbacks.forEach((callback) => callback.apply(this, args));
2456
+ }
2457
+ return this;
2458
+ }
2459
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
2460
+ off(event, fn) {
2461
+ const callbacks = this.callbacks[event];
2462
+ if (callbacks) {
2463
+ if (fn) {
2464
+ this.callbacks[event] = callbacks.filter((callback) => callback !== fn);
2465
+ }
2466
+ else {
2467
+ delete this.callbacks[event];
2468
+ }
2469
+ }
2470
+ return this;
2471
+ }
2472
+ removeAllListeners() {
2473
+ this.callbacks = {};
2474
+ }
2475
+ }
2476
+
2477
+ class IncomingMessage {
2478
+ constructor(data) {
2479
+ this.data = data;
2480
+ this.encoder = createEncoder();
2481
+ this.decoder = createDecoder(new Uint8Array(this.data));
2482
+ }
2483
+ peekVarString() {
2484
+ return peekVarString(this.decoder);
2485
+ }
2486
+ readVarUint() {
2487
+ return readVarUint(this.decoder);
2488
+ }
2489
+ readVarString() {
2490
+ return readVarString(this.decoder);
2491
+ }
2492
+ readVarUint8Array() {
2493
+ return readVarUint8Array(this.decoder);
2494
+ }
2495
+ writeVarUint(type) {
2496
+ return writeVarUint(this.encoder, type);
2497
+ }
2498
+ writeVarString(string) {
2499
+ return writeVarString(this.encoder, string);
2500
+ }
2501
+ writeVarUint8Array(data) {
2502
+ return writeVarUint8Array(this.encoder, data);
2503
+ }
2504
+ length() {
2505
+ return length$1(this.encoder);
2506
+ }
2507
+ }
2508
+
2509
+ var MessageType;
2510
+ (function (MessageType) {
2511
+ MessageType[MessageType["Sync"] = 0] = "Sync";
2512
+ MessageType[MessageType["Awareness"] = 1] = "Awareness";
2513
+ MessageType[MessageType["Auth"] = 2] = "Auth";
2514
+ MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
2515
+ MessageType[MessageType["Stateless"] = 5] = "Stateless";
2516
+ MessageType[MessageType["CLOSE"] = 7] = "CLOSE";
2517
+ MessageType[MessageType["SyncStatus"] = 8] = "SyncStatus";
2518
+ })(MessageType || (MessageType = {}));
2519
+ var WebSocketStatus;
2520
+ (function (WebSocketStatus) {
2521
+ WebSocketStatus["Connecting"] = "connecting";
2522
+ WebSocketStatus["Connected"] = "connected";
2523
+ WebSocketStatus["Disconnected"] = "disconnected";
2524
+ })(WebSocketStatus || (WebSocketStatus = {}));
2525
+
2526
+ class OutgoingMessage {
2527
+ constructor() {
2528
+ this.encoder = createEncoder();
2529
+ }
2530
+ get(args) {
2531
+ return args.encoder;
2532
+ }
2533
+ toUint8Array() {
2534
+ return toUint8Array(this.encoder);
2535
+ }
2536
+ }
2537
+
2538
+ class CloseMessage extends OutgoingMessage {
2539
+ constructor() {
2540
+ super(...arguments);
2541
+ this.type = MessageType.CLOSE;
2542
+ this.description = "Ask the server to close the connection";
2543
+ }
2544
+ get(args) {
2545
+ writeVarString(this.encoder, args.documentName);
2546
+ writeVarUint(this.encoder, this.type);
2547
+ return this.encoder;
2548
+ }
2549
+ }
2550
+
2551
+ class HocuspocusProviderWebsocket extends EventEmitter {
2552
+ constructor(configuration) {
2553
+ super();
2554
+ this.messageQueue = [];
2555
+ this.configuration = {
2556
+ url: "",
2557
+ autoConnect: true,
2558
+ preserveTrailingSlash: false,
2559
+ // @ts-ignore
2560
+ document: undefined,
2561
+ WebSocketPolyfill: undefined,
2562
+ // TODO: this should depend on awareness.outdatedTime
2563
+ messageReconnectTimeout: 30000,
2564
+ // 1 second
2565
+ delay: 1000,
2566
+ // instant
2567
+ initialDelay: 0,
2568
+ // double the delay each time
2569
+ factor: 2,
2570
+ // unlimited retries
2571
+ maxAttempts: 0,
2572
+ // wait at least 1 second
2573
+ minDelay: 1000,
2574
+ // at least every 30 seconds
2575
+ maxDelay: 30000,
2576
+ // randomize
2577
+ jitter: true,
2578
+ // retry forever
2579
+ timeout: 0,
2580
+ onOpen: () => null,
2581
+ onConnect: () => null,
2582
+ onMessage: () => null,
2583
+ onOutgoingMessage: () => null,
2584
+ onStatus: () => null,
2585
+ onDisconnect: () => null,
2586
+ onClose: () => null,
2587
+ onDestroy: () => null,
2588
+ onAwarenessUpdate: () => null,
2589
+ onAwarenessChange: () => null,
2590
+ handleTimeout: null,
2591
+ providerMap: new Map(),
2592
+ };
2593
+ this.webSocket = null;
2594
+ this.webSocketHandlers = {};
2595
+ this.shouldConnect = true;
2596
+ this.status = WebSocketStatus.Disconnected;
2597
+ this.lastMessageReceived = 0;
2598
+ this.identifier = 0;
2599
+ this.intervals = {
2600
+ connectionChecker: null,
2601
+ };
2602
+ this.connectionAttempt = null;
2603
+ this.receivedOnOpenPayload = undefined;
2604
+ this.closeTries = 0;
2605
+ this.setConfiguration(configuration);
2606
+ this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill
2607
+ ? configuration.WebSocketPolyfill
2608
+ : WebSocket;
2609
+ this.on("open", this.configuration.onOpen);
2610
+ this.on("open", this.onOpen.bind(this));
2611
+ this.on("connect", this.configuration.onConnect);
2612
+ this.on("message", this.configuration.onMessage);
2613
+ this.on("outgoingMessage", this.configuration.onOutgoingMessage);
2614
+ this.on("status", this.configuration.onStatus);
2615
+ this.on("disconnect", this.configuration.onDisconnect);
2616
+ this.on("close", this.configuration.onClose);
2617
+ this.on("destroy", this.configuration.onDestroy);
2618
+ this.on("awarenessUpdate", this.configuration.onAwarenessUpdate);
2619
+ this.on("awarenessChange", this.configuration.onAwarenessChange);
2620
+ this.on("close", this.onClose.bind(this));
2621
+ this.on("message", this.onMessage.bind(this));
2622
+ this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.configuration.messageReconnectTimeout / 10);
2623
+ if (this.shouldConnect) {
2624
+ this.connect();
2625
+ }
2626
+ }
2627
+ async onOpen(event) {
2628
+ this.status = WebSocketStatus.Connected;
2629
+ this.emit("status", { status: WebSocketStatus.Connected });
2630
+ this.cancelWebsocketRetry = undefined;
2631
+ this.receivedOnOpenPayload = event;
2632
+ }
2633
+ attach(provider) {
2634
+ this.configuration.providerMap.set(provider.configuration.name, provider);
2635
+ if (this.status === WebSocketStatus.Disconnected && this.shouldConnect) {
2636
+ this.connect();
2637
+ }
2638
+ if (this.receivedOnOpenPayload &&
2639
+ this.status === WebSocketStatus.Connected) {
2640
+ provider.onOpen(this.receivedOnOpenPayload);
2641
+ }
2642
+ }
2643
+ detach(provider) {
2644
+ if (this.configuration.providerMap.has(provider.configuration.name)) {
2645
+ provider.send(CloseMessage, {
2646
+ documentName: provider.configuration.name,
2647
+ });
2648
+ this.configuration.providerMap.delete(provider.configuration.name);
2649
+ }
2650
+ }
2651
+ setConfiguration(configuration = {}) {
2652
+ this.configuration = { ...this.configuration, ...configuration };
2653
+ if (!this.configuration.autoConnect) {
2654
+ this.shouldConnect = false;
2655
+ }
2656
+ }
2657
+ async connect() {
2658
+ if (this.status === WebSocketStatus.Connected) {
2659
+ return;
2660
+ }
2661
+ // Always cancel any previously initiated connection retryer instances
2662
+ if (this.cancelWebsocketRetry) {
2663
+ this.cancelWebsocketRetry();
2664
+ this.cancelWebsocketRetry = undefined;
2665
+ }
2666
+ this.receivedOnOpenPayload = undefined;
2667
+ this.shouldConnect = true;
2668
+ const abortableRetry = () => {
2669
+ let cancelAttempt = false;
2670
+ const retryPromise = retry(this.createWebSocketConnection.bind(this), {
2671
+ delay: this.configuration.delay,
2672
+ initialDelay: this.configuration.initialDelay,
2673
+ factor: this.configuration.factor,
2674
+ maxAttempts: this.configuration.maxAttempts,
2675
+ minDelay: this.configuration.minDelay,
2676
+ maxDelay: this.configuration.maxDelay,
2677
+ jitter: this.configuration.jitter,
2678
+ timeout: this.configuration.timeout,
2679
+ handleTimeout: this.configuration.handleTimeout,
2680
+ beforeAttempt: (context) => {
2681
+ if (!this.shouldConnect || cancelAttempt) {
2682
+ context.abort();
2683
+ }
2684
+ },
2685
+ }).catch((error) => {
2686
+ // If we aborted the connection attempt then don’t throw an error
2687
+ // ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136
2688
+ if (error && error.code !== "ATTEMPT_ABORTED") {
2689
+ throw error;
2690
+ }
2691
+ });
2692
+ return {
2693
+ retryPromise,
2694
+ cancelFunc: () => {
2695
+ cancelAttempt = true;
2696
+ },
2697
+ };
2698
+ };
2699
+ const { retryPromise, cancelFunc } = abortableRetry();
2700
+ this.cancelWebsocketRetry = cancelFunc;
2701
+ return retryPromise;
2702
+ }
2703
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
2704
+ attachWebSocketListeners(ws, reject) {
2705
+ const { identifier } = ws;
2706
+ const onMessageHandler = (payload) => this.emit("message", payload);
2707
+ const onCloseHandler = (payload) => this.emit("close", { event: payload });
2708
+ const onOpenHandler = (payload) => this.emit("open", payload);
2709
+ const onErrorHandler = (err) => {
2710
+ reject(err);
2711
+ };
2712
+ this.webSocketHandlers[identifier] = {
2713
+ message: onMessageHandler,
2714
+ close: onCloseHandler,
2715
+ open: onOpenHandler,
2716
+ error: onErrorHandler,
2717
+ };
2718
+ const handlers = this.webSocketHandlers[ws.identifier];
2719
+ Object.keys(handlers).forEach((name) => {
2720
+ ws.addEventListener(name, handlers[name]);
2721
+ });
2722
+ }
2723
+ cleanupWebSocket() {
2724
+ if (!this.webSocket) {
2725
+ return;
2726
+ }
2727
+ const { identifier } = this.webSocket;
2728
+ const handlers = this.webSocketHandlers[identifier];
2729
+ Object.keys(handlers).forEach((name) => {
2730
+ var _a;
2731
+ (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.removeEventListener(name, handlers[name]);
2732
+ delete this.webSocketHandlers[identifier];
2733
+ });
2734
+ this.webSocket.close();
2735
+ this.webSocket = null;
2736
+ }
2737
+ createWebSocketConnection() {
2738
+ return new Promise((resolve, reject) => {
2739
+ if (this.webSocket) {
2740
+ this.messageQueue = [];
2741
+ this.cleanupWebSocket();
2742
+ }
2743
+ this.lastMessageReceived = 0;
2744
+ this.identifier += 1;
2745
+ // Init the WebSocket connection
2746
+ const ws = new this.configuration.WebSocketPolyfill(this.url);
2747
+ ws.binaryType = "arraybuffer";
2748
+ ws.identifier = this.identifier;
2749
+ this.attachWebSocketListeners(ws, reject);
2750
+ this.webSocket = ws;
2751
+ // Reset the status
2752
+ this.status = WebSocketStatus.Connecting;
2753
+ this.emit("status", { status: WebSocketStatus.Connecting });
2754
+ // Store resolve/reject for later use
2755
+ this.connectionAttempt = {
2756
+ resolve,
2757
+ reject,
2758
+ };
2759
+ });
2760
+ }
2761
+ onMessage(event) {
2762
+ var _a;
2763
+ this.resolveConnectionAttempt();
2764
+ this.lastMessageReceived = getUnixTime();
2765
+ const message = new IncomingMessage(event.data);
2766
+ const documentName = message.peekVarString();
2767
+ (_a = this.configuration.providerMap.get(documentName)) === null || _a === void 0 ? void 0 : _a.onMessage(event);
2768
+ }
2769
+ resolveConnectionAttempt() {
2770
+ if (this.connectionAttempt) {
2771
+ this.connectionAttempt.resolve();
2772
+ this.connectionAttempt = null;
2773
+ this.status = WebSocketStatus.Connected;
2774
+ this.emit("status", { status: WebSocketStatus.Connected });
2775
+ this.emit("connect");
2776
+ this.messageQueue.forEach((message) => this.send(message));
2777
+ this.messageQueue = [];
2778
+ }
2779
+ }
2780
+ stopConnectionAttempt() {
2781
+ this.connectionAttempt = null;
2782
+ }
2783
+ rejectConnectionAttempt() {
2784
+ var _a;
2785
+ (_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.reject();
2786
+ this.connectionAttempt = null;
2787
+ }
2788
+ checkConnection() {
2789
+ var _a;
2790
+ // Don’t check the connection when it’s not even established
2791
+ if (this.status !== WebSocketStatus.Connected) {
2792
+ return;
2793
+ }
2794
+ // Don’t close the connection while waiting for the first message
2795
+ if (!this.lastMessageReceived) {
2796
+ return;
2797
+ }
2798
+ // Don’t close the connection when a message was received recently
2799
+ if (this.configuration.messageReconnectTimeout >=
2800
+ getUnixTime() - this.lastMessageReceived) {
2801
+ return;
2802
+ }
2803
+ // No message received in a long time, not even your own
2804
+ // Awareness updates, which are updated every 15 seconds
2805
+ // if awareness is enabled.
2806
+ this.closeTries += 1;
2807
+ // https://bugs.webkit.org/show_bug.cgi?id=247943
2808
+ if (this.closeTries > 2) {
2809
+ this.onClose({
2810
+ event: {
2811
+ code: 4408,
2812
+ reason: "forced",
2813
+ },
2814
+ });
2815
+ this.closeTries = 0;
2816
+ }
2817
+ else {
2818
+ (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close();
2819
+ this.messageQueue = [];
2820
+ }
2821
+ }
2822
+ get serverUrl() {
2823
+ if (this.configuration.preserveTrailingSlash) {
2824
+ return this.configuration.url;
2825
+ }
2826
+ // By default, ensure that the URL never ends with /
2827
+ let url = this.configuration.url;
2828
+ while (url[url.length - 1] === "/") {
2829
+ url = url.slice(0, url.length - 1);
2830
+ }
2831
+ return url;
2832
+ }
2833
+ get url() {
2834
+ return this.serverUrl;
2835
+ }
2836
+ disconnect() {
2837
+ this.shouldConnect = false;
2838
+ if (this.webSocket === null) {
2839
+ return;
2840
+ }
2841
+ try {
2842
+ this.webSocket.close();
2843
+ this.messageQueue = [];
2844
+ }
2845
+ catch (e) {
2846
+ console.error(e);
2847
+ }
2848
+ }
2849
+ send(message) {
2850
+ var _a;
2851
+ if (((_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.readyState) === WsReadyStates.Open) {
2852
+ this.webSocket.send(message);
2853
+ }
2854
+ else {
2855
+ this.messageQueue.push(message);
2856
+ }
2857
+ }
2858
+ onClose({ event }) {
2859
+ this.closeTries = 0;
2860
+ this.cleanupWebSocket();
2861
+ if (this.connectionAttempt) {
2862
+ // That connection attempt failed.
2863
+ this.rejectConnectionAttempt();
2864
+ }
2865
+ // Let’s update the connection status.
2866
+ this.status = WebSocketStatus.Disconnected;
2867
+ this.emit("status", { status: WebSocketStatus.Disconnected });
2868
+ this.emit("disconnect", { event });
2869
+ // trigger connect if no retry is running and we want to have a connection
2870
+ if (!this.cancelWebsocketRetry && this.shouldConnect) {
2871
+ setTimeout(() => {
2872
+ this.connect();
2873
+ }, this.configuration.delay);
2874
+ }
2875
+ }
2876
+ destroy() {
2877
+ this.emit("destroy");
2878
+ clearInterval(this.intervals.connectionChecker);
2879
+ // If there is still a connection attempt outstanding then we should stop
2880
+ // it before calling disconnect, otherwise it will be rejected in the onClose
2881
+ // handler and trigger a retry
2882
+ this.stopConnectionAttempt();
2883
+ this.disconnect();
2884
+ this.removeAllListeners();
2885
+ this.cleanupWebSocket();
2886
+ }
2887
+ }
2888
+
2889
+ /**
2890
+ * @module sync-protocol
2891
+ */
2892
+
2893
+
2894
+ /**
2895
+ * @typedef {Map<number, number>} StateMap
2896
+ */
2897
+
2898
+ /**
2899
+ * Core Yjs defines two message types:
2900
+ * • YjsSyncStep1: Includes the State Set of the sending client. When received, the client should reply with YjsSyncStep2.
2901
+ * • YjsSyncStep2: Includes all missing structs and the complete delete set. When received, the client is assured that it
2902
+ * received all information from the remote client.
2903
+ *
2904
+ * In a peer-to-peer network, you may want to introduce a SyncDone message type. Both parties should initiate the connection
2905
+ * with SyncStep1. When a client received SyncStep2, it should reply with SyncDone. When the local client received both
2906
+ * SyncStep2 and SyncDone, it is assured that it is synced to the remote client.
2907
+ *
2908
+ * In a client-server model, you want to handle this differently: The client should initiate the connection with SyncStep1.
2909
+ * When the server receives SyncStep1, it should reply with SyncStep2 immediately followed by SyncStep1. The client replies
2910
+ * with SyncStep2 when it receives SyncStep1. Optionally the server may send a SyncDone after it received SyncStep2, so the
2911
+ * client knows that the sync is finished. There are two reasons for this more elaborated sync model: 1. This protocol can
2912
+ * easily be implemented on top of http and websockets. 2. The server should only reply to requests, and not initiate them.
2913
+ * Therefore it is necessary that the client initiates the sync.
2914
+ *
2915
+ * Construction of a message:
2916
+ * [messageType : varUint, message definition..]
2917
+ *
2918
+ * Note: A message does not include information about the room name. This must to be handled by the upper layer protocol!
2919
+ *
2920
+ * stringify[messageType] stringifies a message definition (messageType is already read from the bufffer)
2921
+ */
2922
+
2923
+ const messageYjsSyncStep1 = 0;
2924
+ const messageYjsSyncStep2 = 1;
2925
+ const messageYjsUpdate = 2;
2926
+
2927
+ /**
2928
+ * Create a sync step 1 message based on the state of the current shared document.
2929
+ *
2930
+ * @param {encoding.Encoder} encoder
2931
+ * @param {Y.Doc} doc
2932
+ */
2933
+ const writeSyncStep1 = (encoder, doc) => {
2934
+ writeVarUint(encoder, messageYjsSyncStep1);
2935
+ const sv = Y__namespace.encodeStateVector(doc);
2936
+ writeVarUint8Array(encoder, sv);
2937
+ };
2938
+
2939
+ /**
2940
+ * @param {encoding.Encoder} encoder
2941
+ * @param {Y.Doc} doc
2942
+ * @param {Uint8Array} [encodedStateVector]
2943
+ */
2944
+ const writeSyncStep2 = (encoder, doc, encodedStateVector) => {
2945
+ writeVarUint(encoder, messageYjsSyncStep2);
2946
+ writeVarUint8Array(encoder, Y__namespace.encodeStateAsUpdate(doc, encodedStateVector));
2947
+ };
2948
+
2949
+ /**
2950
+ * Read SyncStep1 message and reply with SyncStep2.
2951
+ *
2952
+ * @param {decoding.Decoder} decoder The reply to the received message
2953
+ * @param {encoding.Encoder} encoder The received message
2954
+ * @param {Y.Doc} doc
2955
+ */
2956
+ const readSyncStep1 = (decoder, encoder, doc) =>
2957
+ writeSyncStep2(encoder, doc, readVarUint8Array(decoder));
2958
+
2959
+ /**
2960
+ * Read and apply Structs and then DeleteStore to a y instance.
2961
+ *
2962
+ * @param {decoding.Decoder} decoder
2963
+ * @param {Y.Doc} doc
2964
+ * @param {any} transactionOrigin
2965
+ */
2966
+ const readSyncStep2 = (decoder, doc, transactionOrigin) => {
2967
+ try {
2968
+ Y__namespace.applyUpdate(doc, readVarUint8Array(decoder), transactionOrigin);
2969
+ } catch (error) {
2970
+ // This catches errors that are thrown by event handlers
2971
+ console.error('Caught error while handling a Yjs update', error);
2972
+ }
2973
+ };
2974
+
2975
+ /**
2976
+ * @param {encoding.Encoder} encoder
2977
+ * @param {Uint8Array} update
2978
+ */
2979
+ const writeUpdate = (encoder, update) => {
2980
+ writeVarUint(encoder, messageYjsUpdate);
2981
+ writeVarUint8Array(encoder, update);
2982
+ };
2983
+
2984
+ /**
2985
+ * Read and apply Structs and then DeleteStore to a y instance.
2986
+ *
2987
+ * @param {decoding.Decoder} decoder
2988
+ * @param {Y.Doc} doc
2989
+ * @param {any} transactionOrigin
2990
+ */
2991
+ const readUpdate = readSyncStep2;
2992
+
2993
+ /**
2994
+ * @param {decoding.Decoder} decoder A message received from another client
2995
+ * @param {encoding.Encoder} encoder The reply message. Does not need to be sent if empty.
2996
+ * @param {Y.Doc} doc
2997
+ * @param {any} transactionOrigin
2998
+ */
2999
+ const readSyncMessage = (decoder, encoder, doc, transactionOrigin) => {
3000
+ const messageType = readVarUint(decoder);
3001
+ switch (messageType) {
3002
+ case messageYjsSyncStep1:
3003
+ readSyncStep1(decoder, encoder, doc);
3004
+ break
3005
+ case messageYjsSyncStep2:
3006
+ readSyncStep2(decoder, doc, transactionOrigin);
3007
+ break
3008
+ case messageYjsUpdate:
3009
+ readUpdate(decoder, doc, transactionOrigin);
3010
+ break
3011
+ default:
3012
+ throw new Error('Unknown message type')
3013
+ }
3014
+ return messageType
3015
+ };
3016
+
3017
+ class MessageReceiver {
3018
+ constructor(message) {
3019
+ this.message = message;
3020
+ }
3021
+ apply(provider, emitSynced) {
3022
+ const { message } = this;
3023
+ const type = message.readVarUint();
3024
+ const emptyMessageLength = message.length();
3025
+ switch (type) {
3026
+ case MessageType.Sync:
3027
+ this.applySyncMessage(provider, emitSynced);
3028
+ break;
3029
+ case MessageType.Awareness:
3030
+ this.applyAwarenessMessage(provider);
3031
+ break;
3032
+ case MessageType.Auth:
3033
+ this.applyAuthMessage(provider);
3034
+ break;
3035
+ case MessageType.QueryAwareness:
3036
+ this.applyQueryAwarenessMessage(provider);
3037
+ break;
3038
+ case MessageType.Stateless:
3039
+ provider.receiveStateless(readVarString(message.decoder));
3040
+ break;
3041
+ case MessageType.SyncStatus:
3042
+ this.applySyncStatusMessage(provider, readVarInt(message.decoder) === 1);
3043
+ break;
3044
+ case MessageType.CLOSE:
3045
+ // eslint-disable-next-line no-case-declarations
3046
+ const event = {
3047
+ code: 1000,
3048
+ reason: readVarString(message.decoder),
3049
+ // @ts-ignore
3050
+ target: provider.configuration.websocketProvider.webSocket,
3051
+ type: "close",
3052
+ };
3053
+ provider.onClose();
3054
+ provider.configuration.onClose({ event });
3055
+ provider.forwardClose({ event });
3056
+ break;
3057
+ default:
3058
+ throw new Error(`Can’t apply message of unknown type: ${type}`);
3059
+ }
3060
+ // Reply
3061
+ if (message.length() > emptyMessageLength + 1) {
3062
+ // length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)
3063
+ // @ts-ignore
3064
+ provider.send(OutgoingMessage, { encoder: message.encoder });
3065
+ }
3066
+ }
3067
+ applySyncMessage(provider, emitSynced) {
3068
+ const { message } = this;
3069
+ message.writeVarUint(MessageType.Sync);
3070
+ // Apply update
3071
+ const syncMessageType = readSyncMessage(message.decoder, message.encoder, provider.document, provider);
3072
+ // Synced once we receive Step2
3073
+ if (emitSynced && syncMessageType === messageYjsSyncStep2) {
3074
+ provider.synced = true;
3075
+ }
3076
+ }
3077
+ applySyncStatusMessage(provider, applied) {
3078
+ if (applied) {
3079
+ provider.decrementUnsyncedChanges();
3080
+ }
3081
+ }
3082
+ applyAwarenessMessage(provider) {
3083
+ if (!provider.awareness)
3084
+ return;
3085
+ const { message } = this;
3086
+ applyAwarenessUpdate(provider.awareness, message.readVarUint8Array(), provider);
3087
+ }
3088
+ applyAuthMessage(provider) {
3089
+ const { message } = this;
3090
+ readAuthMessage(message.decoder, provider.sendToken.bind(provider), provider.permissionDeniedHandler.bind(provider), provider.authenticatedHandler.bind(provider));
3091
+ }
3092
+ applyQueryAwarenessMessage(provider) {
3093
+ if (!provider.awareness)
3094
+ return;
3095
+ const { message } = this;
3096
+ message.writeVarUint(MessageType.Awareness);
3097
+ message.writeVarUint8Array(encodeAwarenessUpdate(provider.awareness, Array.from(provider.awareness.getStates().keys())));
3098
+ }
3099
+ }
3100
+
3101
+ class MessageSender {
3102
+ constructor(Message, args = {}) {
3103
+ this.message = new Message();
3104
+ this.encoder = this.message.get(args);
3105
+ }
3106
+ create() {
3107
+ return toUint8Array(this.encoder);
3108
+ }
3109
+ send(webSocket) {
3110
+ webSocket === null || webSocket === void 0 ? void 0 : webSocket.send(this.create());
3111
+ }
3112
+ }
3113
+
3114
+ class AuthenticationMessage extends OutgoingMessage {
3115
+ constructor() {
3116
+ super(...arguments);
3117
+ this.type = MessageType.Auth;
3118
+ this.description = "Authentication";
3119
+ }
3120
+ get(args) {
3121
+ if (typeof args.token === "undefined") {
3122
+ throw new Error("The authentication message requires `token` as an argument.");
3123
+ }
3124
+ writeVarString(this.encoder, args.documentName);
3125
+ writeVarUint(this.encoder, this.type);
3126
+ writeAuthentication(this.encoder, args.token);
3127
+ return this.encoder;
3128
+ }
3129
+ }
3130
+
3131
+ class AwarenessMessage extends OutgoingMessage {
3132
+ constructor() {
3133
+ super(...arguments);
3134
+ this.type = MessageType.Awareness;
3135
+ this.description = "Awareness states update";
3136
+ }
3137
+ get(args) {
3138
+ if (typeof args.awareness === "undefined") {
3139
+ throw new Error("The awareness message requires awareness as an argument");
3140
+ }
3141
+ if (typeof args.clients === "undefined") {
3142
+ throw new Error("The awareness message requires clients as an argument");
3143
+ }
3144
+ writeVarString(this.encoder, args.documentName);
3145
+ writeVarUint(this.encoder, this.type);
3146
+ let awarenessUpdate;
3147
+ if (args.states === undefined) {
3148
+ awarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients);
3149
+ }
3150
+ else {
3151
+ awarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients, args.states);
3152
+ }
3153
+ writeVarUint8Array(this.encoder, awarenessUpdate);
3154
+ return this.encoder;
3155
+ }
3156
+ }
3157
+
3158
+ class StatelessMessage extends OutgoingMessage {
3159
+ constructor() {
3160
+ super(...arguments);
3161
+ this.type = MessageType.Stateless;
3162
+ this.description = "A stateless message";
3163
+ }
3164
+ get(args) {
3165
+ var _a;
3166
+ writeVarString(this.encoder, args.documentName);
3167
+ writeVarUint(this.encoder, this.type);
3168
+ writeVarString(this.encoder, (_a = args.payload) !== null && _a !== void 0 ? _a : "");
3169
+ return this.encoder;
3170
+ }
3171
+ }
3172
+
3173
+ class SyncStepOneMessage extends OutgoingMessage {
3174
+ constructor() {
3175
+ super(...arguments);
3176
+ this.type = MessageType.Sync;
3177
+ this.description = "First sync step";
3178
+ }
3179
+ get(args) {
3180
+ if (typeof args.document === "undefined") {
3181
+ throw new Error("The sync step one message requires document as an argument");
3182
+ }
3183
+ writeVarString(this.encoder, args.documentName);
3184
+ writeVarUint(this.encoder, this.type);
3185
+ writeSyncStep1(this.encoder, args.document);
3186
+ return this.encoder;
3187
+ }
3188
+ }
3189
+
3190
+ class UpdateMessage extends OutgoingMessage {
3191
+ constructor() {
3192
+ super(...arguments);
3193
+ this.type = MessageType.Sync;
3194
+ this.description = "A document update";
3195
+ }
3196
+ get(args) {
3197
+ writeVarString(this.encoder, args.documentName);
3198
+ writeVarUint(this.encoder, this.type);
3199
+ writeUpdate(this.encoder, args.update);
3200
+ return this.encoder;
3201
+ }
3202
+ }
3203
+
3204
+ class AwarenessError extends Error {
3205
+ constructor() {
3206
+ super(...arguments);
3207
+ this.code = 1001;
3208
+ }
3209
+ }
3210
+ class HocuspocusProvider extends EventEmitter {
3211
+ constructor(configuration) {
3212
+ var _a, _b, _c;
3213
+ super();
3214
+ this.configuration = {
3215
+ name: "",
3216
+ // @ts-ignore
3217
+ document: undefined,
3218
+ // @ts-ignore
3219
+ awareness: undefined,
3220
+ token: null,
3221
+ forceSyncInterval: false,
3222
+ onAuthenticated: () => null,
3223
+ onAuthenticationFailed: () => null,
3224
+ onOpen: () => null,
3225
+ onConnect: () => null,
3226
+ onMessage: () => null,
3227
+ onOutgoingMessage: () => null,
3228
+ onSynced: () => null,
3229
+ onStatus: () => null,
3230
+ onDisconnect: () => null,
3231
+ onClose: () => null,
3232
+ onDestroy: () => null,
3233
+ onAwarenessUpdate: () => null,
3234
+ onAwarenessChange: () => null,
3235
+ onStateless: () => null,
3236
+ onUnsyncedChanges: () => null,
3237
+ };
3238
+ this.isSynced = false;
3239
+ this.unsyncedChanges = 0;
3240
+ this.isAuthenticated = false;
3241
+ this.authorizedScope = undefined;
3242
+ // @internal
3243
+ this.manageSocket = false;
3244
+ this._isAttached = false;
3245
+ this.intervals = {
3246
+ forceSync: null,
3247
+ };
3248
+ this.boundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);
3249
+ this.boundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);
3250
+ this.boundPageHide = this.pageHide.bind(this);
3251
+ this.boundOnOpen = this.onOpen.bind(this);
3252
+ this.boundOnClose = this.onClose.bind(this);
3253
+ this.forwardConnect = () => this.emit("connect");
3254
+ this.forwardStatus = (e) => this.emit("status", e);
3255
+ this.forwardClose = (e) => this.emit("close", e);
3256
+ this.forwardDisconnect = (e) => this.emit("disconnect", e);
3257
+ this.forwardDestroy = () => this.emit("destroy");
3258
+ this.setConfiguration(configuration);
3259
+ this.configuration.document = configuration.document
3260
+ ? configuration.document
3261
+ : new Y__namespace.Doc();
3262
+ this.configuration.awareness =
3263
+ configuration.awareness !== undefined
3264
+ ? configuration.awareness
3265
+ : new Awareness(this.document);
3266
+ this.on("open", this.configuration.onOpen);
3267
+ this.on("message", this.configuration.onMessage);
3268
+ this.on("outgoingMessage", this.configuration.onOutgoingMessage);
3269
+ this.on("synced", this.configuration.onSynced);
3270
+ this.on("destroy", this.configuration.onDestroy);
3271
+ this.on("awarenessUpdate", this.configuration.onAwarenessUpdate);
3272
+ this.on("awarenessChange", this.configuration.onAwarenessChange);
3273
+ this.on("stateless", this.configuration.onStateless);
3274
+ this.on("unsyncedChanges", this.configuration.onUnsyncedChanges);
3275
+ this.on("authenticated", this.configuration.onAuthenticated);
3276
+ this.on("authenticationFailed", this.configuration.onAuthenticationFailed);
3277
+ (_a = this.awareness) === null || _a === void 0 ? void 0 : _a.on("update", () => {
3278
+ this.emit("awarenessUpdate", {
3279
+ states: awarenessStatesToArray(this.awareness.getStates()),
3280
+ });
3281
+ });
3282
+ (_b = this.awareness) === null || _b === void 0 ? void 0 : _b.on("change", () => {
3283
+ this.emit("awarenessChange", {
3284
+ states: awarenessStatesToArray(this.awareness.getStates()),
3285
+ });
3286
+ });
3287
+ this.document.on("update", this.boundDocumentUpdateHandler);
3288
+ (_c = this.awareness) === null || _c === void 0 ? void 0 : _c.on("update", this.boundAwarenessUpdateHandler);
3289
+ this.registerEventListeners();
3290
+ if (this.configuration.forceSyncInterval &&
3291
+ typeof this.configuration.forceSyncInterval === "number") {
3292
+ this.intervals.forceSync = setInterval(this.forceSync.bind(this), this.configuration.forceSyncInterval);
3293
+ }
3294
+ if (this.manageSocket) {
3295
+ this.attach();
3296
+ }
3297
+ }
3298
+ setConfiguration(configuration = {}) {
3299
+ if (!configuration.websocketProvider) {
3300
+ this.manageSocket = true;
3301
+ this.configuration.websocketProvider = new HocuspocusProviderWebsocket(configuration);
3302
+ }
3303
+ this.configuration = { ...this.configuration, ...configuration };
3304
+ }
3305
+ get document() {
3306
+ return this.configuration.document;
3307
+ }
3308
+ get isAttached() {
3309
+ return this._isAttached;
3310
+ }
3311
+ get awareness() {
3312
+ return this.configuration.awareness;
3313
+ }
3314
+ get hasUnsyncedChanges() {
3315
+ return this.unsyncedChanges > 0;
3316
+ }
3317
+ resetUnsyncedChanges() {
3318
+ this.unsyncedChanges = 1;
3319
+ this.emit("unsyncedChanges", { number: this.unsyncedChanges });
3320
+ }
3321
+ incrementUnsyncedChanges() {
3322
+ this.unsyncedChanges += 1;
3323
+ this.emit("unsyncedChanges", { number: this.unsyncedChanges });
3324
+ }
3325
+ decrementUnsyncedChanges() {
3326
+ if (this.unsyncedChanges > 0) {
3327
+ this.unsyncedChanges -= 1;
3328
+ }
3329
+ if (this.unsyncedChanges === 0) {
3330
+ this.synced = true;
3331
+ }
3332
+ this.emit("unsyncedChanges", { number: this.unsyncedChanges });
3333
+ }
3334
+ forceSync() {
3335
+ this.resetUnsyncedChanges();
3336
+ this.send(SyncStepOneMessage, {
3337
+ document: this.document,
3338
+ documentName: this.configuration.name,
3339
+ });
3340
+ }
3341
+ pageHide() {
3342
+ if (this.awareness) {
3343
+ removeAwarenessStates(this.awareness, [this.document.clientID], "page hide");
3344
+ }
3345
+ }
3346
+ registerEventListeners() {
3347
+ if (typeof window === "undefined" || !("addEventListener" in window)) {
3348
+ return;
3349
+ }
3350
+ window.addEventListener("pagehide", this.boundPageHide);
3351
+ }
3352
+ sendStateless(payload) {
3353
+ this.send(StatelessMessage, {
3354
+ documentName: this.configuration.name,
3355
+ payload,
3356
+ });
3357
+ }
3358
+ async sendToken() {
3359
+ let token;
3360
+ try {
3361
+ token = await this.getToken();
3362
+ }
3363
+ catch (error) {
3364
+ this.permissionDeniedHandler(`Failed to get token during sendToken(): ${error}`);
3365
+ return;
3366
+ }
3367
+ this.send(AuthenticationMessage, {
3368
+ token: token !== null && token !== void 0 ? token : "",
3369
+ documentName: this.configuration.name,
3370
+ });
3371
+ }
3372
+ documentUpdateHandler(update, origin) {
3373
+ if (origin === this) {
3374
+ return;
3375
+ }
3376
+ this.incrementUnsyncedChanges();
3377
+ this.send(UpdateMessage, { update, documentName: this.configuration.name });
3378
+ }
3379
+ awarenessUpdateHandler({ added, updated, removed }, origin) {
3380
+ const changedClients = added.concat(updated).concat(removed);
3381
+ this.send(AwarenessMessage, {
3382
+ awareness: this.awareness,
3383
+ clients: changedClients,
3384
+ documentName: this.configuration.name,
3385
+ });
3386
+ }
3387
+ /**
3388
+ * Indicates whether a first handshake with the server has been established
3389
+ *
3390
+ * Note: this does not mean all updates from the client have been persisted to the backend. For this,
3391
+ * use `hasUnsyncedChanges`.
3392
+ */
3393
+ get synced() {
3394
+ return this.isSynced;
3395
+ }
3396
+ set synced(state) {
3397
+ if (this.isSynced === state) {
3398
+ return;
3399
+ }
3400
+ this.isSynced = state;
3401
+ if (state) {
3402
+ this.emit("synced", { state });
3403
+ }
3404
+ }
3405
+ receiveStateless(payload) {
3406
+ this.emit("stateless", { payload });
3407
+ }
3408
+ // not needed, but provides backward compatibility with e.g. lexical/yjs
3409
+ async connect() {
3410
+ if (this.manageSocket) {
3411
+ return this.configuration.websocketProvider.connect();
3412
+ }
3413
+ console.warn("HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.");
3414
+ }
3415
+ disconnect() {
3416
+ if (this.manageSocket) {
3417
+ return this.configuration.websocketProvider.disconnect();
3418
+ }
3419
+ console.warn("HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.");
3420
+ }
3421
+ async onOpen(event) {
3422
+ this.isAuthenticated = false;
3423
+ this.emit("open", { event });
3424
+ await this.sendToken();
3425
+ this.startSync();
3426
+ }
3427
+ async getToken() {
3428
+ if (typeof this.configuration.token === "function") {
3429
+ const token = await this.configuration.token();
3430
+ return token;
3431
+ }
3432
+ return this.configuration.token;
3433
+ }
3434
+ startSync() {
3435
+ this.resetUnsyncedChanges();
3436
+ this.send(SyncStepOneMessage, {
3437
+ document: this.document,
3438
+ documentName: this.configuration.name,
3439
+ });
3440
+ if (this.awareness && this.awareness.getLocalState() !== null) {
3441
+ this.send(AwarenessMessage, {
3442
+ awareness: this.awareness,
3443
+ clients: [this.document.clientID],
3444
+ documentName: this.configuration.name,
3445
+ });
3446
+ }
3447
+ }
3448
+ send(message, args) {
3449
+ if (!this._isAttached)
3450
+ return;
3451
+ const messageSender = new MessageSender(message, args);
3452
+ this.emit("outgoingMessage", { message: messageSender.message });
3453
+ messageSender.send(this.configuration.websocketProvider);
3454
+ }
3455
+ onMessage(event) {
3456
+ const message = new IncomingMessage(event.data);
3457
+ const documentName = message.readVarString();
3458
+ message.writeVarString(documentName);
3459
+ this.emit("message", { event, message: new IncomingMessage(event.data) });
3460
+ new MessageReceiver(message).apply(this, true);
3461
+ }
3462
+ onClose() {
3463
+ this.isAuthenticated = false;
3464
+ this.synced = false;
3465
+ // update awareness (all users except local left)
3466
+ if (this.awareness) {
3467
+ removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.document.clientID), this);
3468
+ }
3469
+ }
3470
+ destroy() {
3471
+ this.emit("destroy");
3472
+ if (this.intervals.forceSync) {
3473
+ clearInterval(this.intervals.forceSync);
3474
+ }
3475
+ if (this.awareness) {
3476
+ removeAwarenessStates(this.awareness, [this.document.clientID], "provider destroy");
3477
+ this.awareness.off("update", this.boundAwarenessUpdateHandler);
3478
+ this.awareness.destroy();
3479
+ }
3480
+ this.document.off("update", this.boundDocumentUpdateHandler);
3481
+ this.removeAllListeners();
3482
+ this.detach();
3483
+ if (this.manageSocket) {
3484
+ this.configuration.websocketProvider.destroy();
3485
+ }
3486
+ if (typeof window === "undefined" || !("removeEventListener" in window)) {
3487
+ return;
3488
+ }
3489
+ window.removeEventListener("pagehide", this.boundPageHide);
3490
+ }
3491
+ detach() {
3492
+ this.configuration.websocketProvider.off("connect", this.configuration.onConnect);
3493
+ this.configuration.websocketProvider.off("connect", this.forwardConnect);
3494
+ this.configuration.websocketProvider.off("status", this.forwardStatus);
3495
+ this.configuration.websocketProvider.off("status", this.configuration.onStatus);
3496
+ this.configuration.websocketProvider.off("open", this.boundOnOpen);
3497
+ this.configuration.websocketProvider.off("close", this.boundOnClose);
3498
+ this.configuration.websocketProvider.off("close", this.configuration.onClose);
3499
+ this.configuration.websocketProvider.off("close", this.forwardClose);
3500
+ this.configuration.websocketProvider.off("disconnect", this.configuration.onDisconnect);
3501
+ this.configuration.websocketProvider.off("disconnect", this.forwardDisconnect);
3502
+ this.configuration.websocketProvider.off("destroy", this.configuration.onDestroy);
3503
+ this.configuration.websocketProvider.off("destroy", this.forwardDestroy);
3504
+ this.configuration.websocketProvider.detach(this);
3505
+ this._isAttached = false;
3506
+ }
3507
+ attach() {
3508
+ if (this._isAttached)
3509
+ return;
3510
+ this.configuration.websocketProvider.on("connect", this.configuration.onConnect);
3511
+ this.configuration.websocketProvider.on("connect", this.forwardConnect);
3512
+ this.configuration.websocketProvider.on("status", this.configuration.onStatus);
3513
+ this.configuration.websocketProvider.on("status", this.forwardStatus);
3514
+ this.configuration.websocketProvider.on("open", this.boundOnOpen);
3515
+ this.configuration.websocketProvider.on("close", this.boundOnClose);
3516
+ this.configuration.websocketProvider.on("close", this.configuration.onClose);
3517
+ this.configuration.websocketProvider.on("close", this.forwardClose);
3518
+ this.configuration.websocketProvider.on("disconnect", this.configuration.onDisconnect);
3519
+ this.configuration.websocketProvider.on("disconnect", this.forwardDisconnect);
3520
+ this.configuration.websocketProvider.on("destroy", this.configuration.onDestroy);
3521
+ this.configuration.websocketProvider.on("destroy", this.forwardDestroy);
3522
+ this.configuration.websocketProvider.attach(this);
3523
+ this._isAttached = true;
3524
+ }
3525
+ permissionDeniedHandler(reason) {
3526
+ this.emit("authenticationFailed", { reason });
3527
+ this.isAuthenticated = false;
3528
+ }
3529
+ authenticatedHandler(scope) {
3530
+ this.isAuthenticated = true;
3531
+ this.authorizedScope = scope;
3532
+ this.emit("authenticated", { scope });
3533
+ }
3534
+ setAwarenessField(key, value) {
3535
+ if (!this.awareness) {
3536
+ throw new AwarenessError(`Cannot set awareness field "${key}" to ${JSON.stringify(value)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`);
3537
+ }
3538
+ this.awareness.setLocalStateField(key, value);
3539
+ }
3540
+ }
3541
+
3542
+ /**
3543
+ * Hocuspocus sync provider for real-time collaboration
3544
+ * Supports multiplexing - multiple documents can share the same WebSocket connection
3545
+ */
3546
+ class HocuspocusSyncProvider {
3547
+ static type = 'network';
3548
+ type = 'network';
3549
+ provider;
3550
+ isConnected = false;
3551
+ isSynced = false;
3552
+ usesSharedSocket = false;
3553
+ isDestroyed = false;
3554
+ connectTimeout = null;
3555
+ pendingConnectReject = null;
3556
+ connectionTimeoutMs;
3557
+ _connectionStatus = 'disconnected';
3558
+ visibilityHandler = null;
3559
+ onlineHandler = null;
3560
+ get awareness() {
3561
+ return this.provider.awareness;
3562
+ }
3563
+ get rawProvider() {
3564
+ return this.provider;
3565
+ }
3566
+ get connectionStatus() {
3567
+ return this._connectionStatus;
3568
+ }
3569
+ // Static shared WebSocket instance for multiplexing
3570
+ static sharedWebSocketProvider = null;
3571
+ constructor(docName, doc, options) {
3572
+ const name = options?.name || docName;
3573
+ const url = options?.url || 'ws://localhost:1234';
3574
+ this.connectionTimeoutMs = options?.connectionTimeout ?? 10000;
3575
+ // Use provided websocketProvider or the static shared one
3576
+ const websocketProvider = options?.websocketProvider || HocuspocusSyncProvider.sharedWebSocketProvider;
3577
+ // Build reconnect config from options
3578
+ const reconnectConfig = {};
3579
+ if (options?.delay !== undefined)
3580
+ reconnectConfig.delay = options.delay;
3581
+ if (options?.factor !== undefined)
3582
+ reconnectConfig.factor = options.factor;
3583
+ if (options?.maxAttempts !== undefined)
3584
+ reconnectConfig.maxAttempts = options.maxAttempts;
3585
+ if (options?.minDelay !== undefined)
3586
+ reconnectConfig.minDelay = options.minDelay;
3587
+ if (options?.maxDelay !== undefined)
3588
+ reconnectConfig.maxDelay = options.maxDelay;
3589
+ const onConnect = () => {
3590
+ if (this.isDestroyed) {
3591
+ return;
3592
+ }
3593
+ this.isConnected = true;
3594
+ this._connectionStatus = 'connected';
3595
+ if (!options?.quiet) {
3596
+ console.info(`Hocuspocus connected: ${name}`);
3597
+ }
3598
+ if (options?.onConnect) {
3599
+ options.onConnect();
3600
+ }
3601
+ };
3602
+ const onDisconnect = () => {
3603
+ if (this.isDestroyed) {
3604
+ return;
3605
+ }
3606
+ this.isConnected = false;
3607
+ this.isSynced = false;
3608
+ this._connectionStatus = 'disconnected';
3609
+ if (!options?.quiet) {
3610
+ console.info(`Hocuspocus disconnected: ${name}`);
3611
+ }
3612
+ if (options?.onDisconnect) {
3613
+ options.onDisconnect();
3614
+ }
3615
+ };
3616
+ const onSynced = () => {
3617
+ if (this.isDestroyed) {
3618
+ return;
3619
+ }
3620
+ this.isSynced = true;
3621
+ this._connectionStatus = 'synced';
3622
+ if (!options?.quiet) {
3623
+ console.info(`Hocuspocus synced: ${name}`);
3624
+ }
3625
+ if (options?.onSynced) {
3626
+ options.onSynced();
3627
+ }
3628
+ };
3629
+ const onStatus = (data) => {
3630
+ if (this.isDestroyed) {
3631
+ return;
3632
+ }
3633
+ if (data.status === 'connecting') {
3634
+ this._connectionStatus = 'connecting';
3635
+ }
3636
+ if (options?.onStatus) {
3637
+ options.onStatus(data);
3638
+ }
3639
+ };
3640
+ if (websocketProvider) {
3641
+ // Multiplexing mode - use shared WebSocket connection
3642
+ this.usesSharedSocket = true;
3643
+ const config = {
3644
+ websocketProvider,
3645
+ name,
3646
+ document: doc,
3647
+ token: options?.token || null,
3648
+ onStatus,
3649
+ onConnect,
3650
+ onDisconnect,
3651
+ onSynced,
3652
+ ...reconnectConfig,
3653
+ };
3654
+ // Add optional settings
3655
+ if (options?.forceSyncInterval !== undefined) {
3656
+ config.forceSyncInterval = options.forceSyncInterval;
3657
+ }
3658
+ if (options?.onAuthenticationFailed) {
3659
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
3660
+ }
3661
+ this.provider = new HocuspocusProvider(config);
3662
+ // Must call attach() explicitly when using shared socket
3663
+ this.provider.attach();
3664
+ if (!options?.quiet) {
3665
+ console.info(`Hocuspocus Provider initialized (multiplexed): ${name}`);
3666
+ }
3667
+ }
3668
+ else {
3669
+ // Standalone mode - create own WebSocket connection
3670
+ this.usesSharedSocket = false;
3671
+ const config = {
3672
+ url,
3673
+ name,
3674
+ document: doc,
3675
+ token: options?.token || null,
3676
+ autoConnect: false,
3677
+ onStatus,
3678
+ onConnect,
3679
+ onDisconnect,
3680
+ onSynced,
3681
+ ...reconnectConfig,
3682
+ };
3683
+ // Add optional settings
3684
+ if (options?.forceSyncInterval !== undefined) {
3685
+ config.forceSyncInterval = options.forceSyncInterval;
3686
+ }
3687
+ if (options?.onAuthenticationFailed) {
3688
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
3689
+ }
3690
+ if (options?.WebSocketPolyfill) {
3691
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
3692
+ }
3693
+ this.provider = new HocuspocusProvider(config);
3694
+ if (!options?.quiet) {
3695
+ console.info(`Hocuspocus Provider initialized: ${url}/${name}`);
3696
+ }
3697
+ }
3698
+ this.setupBrowserEventListeners();
3699
+ }
3700
+ setupBrowserEventListeners() {
3701
+ if (typeof document !== 'undefined') {
3702
+ this.visibilityHandler = () => {
3703
+ if (document.visibilityState === 'visible' && !this.isConnected && !this.isDestroyed) {
3704
+ this.provider.connect();
3705
+ }
3706
+ };
3707
+ document.addEventListener('visibilitychange', this.visibilityHandler);
3708
+ }
3709
+ if (typeof window !== 'undefined') {
3710
+ this.onlineHandler = () => {
3711
+ if (!this.isConnected && !this.isDestroyed) {
3712
+ this.provider.connect();
3713
+ }
3714
+ };
3715
+ window.addEventListener('online', this.onlineHandler);
3716
+ }
3717
+ }
3718
+ removeBrowserEventListeners() {
3719
+ if (this.visibilityHandler && typeof document !== 'undefined') {
3720
+ document.removeEventListener('visibilitychange', this.visibilityHandler);
3721
+ this.visibilityHandler = null;
3722
+ }
3723
+ if (this.onlineHandler && typeof window !== 'undefined') {
3724
+ window.removeEventListener('online', this.onlineHandler);
3725
+ this.onlineHandler = null;
3726
+ }
3727
+ }
3728
+ /**
3729
+ * Create a shared WebSocket connection for multiplexing
3730
+ * Call this once to create a shared connection that multiple providers can use
3731
+ */
3732
+ static createSharedWebSocket(options) {
3733
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
3734
+ console.warn('Shared WebSocket already exists. Returning existing instance.');
3735
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
3736
+ }
3737
+ const config = {
3738
+ url: options.url,
3739
+ };
3740
+ if (options.WebSocketPolyfill) {
3741
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
3742
+ }
3743
+ if (options.onConnect) {
3744
+ config.onConnect = options.onConnect;
3745
+ }
3746
+ if (options.onDisconnect) {
3747
+ config.onDisconnect = options.onDisconnect;
3748
+ }
3749
+ if (options.onStatus) {
3750
+ config.onStatus = options.onStatus;
3751
+ }
3752
+ HocuspocusSyncProvider.sharedWebSocketProvider = new HocuspocusProviderWebsocket(config);
3753
+ console.info(`Shared Hocuspocus WebSocket created: ${options.url}`);
3754
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
3755
+ }
3756
+ /**
3757
+ * Destroy the shared WebSocket connection
3758
+ * Call this when you're done with all multiplexed providers
3759
+ */
3760
+ static destroySharedWebSocket() {
3761
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
3762
+ HocuspocusSyncProvider.sharedWebSocketProvider.destroy();
3763
+ HocuspocusSyncProvider.sharedWebSocketProvider = null;
3764
+ console.info('Shared Hocuspocus WebSocket destroyed');
3765
+ }
3766
+ }
3767
+ /**
3768
+ * Get the shared WebSocket provider instance (if it exists)
3769
+ */
3770
+ static getSharedWebSocket() {
3771
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
3772
+ }
3773
+ /**
3774
+ * Static factory method for creating HocuspocusSyncProvider with configuration options
3775
+ * Returns a ProviderFactory that can be used in sync configuration
3776
+ */
3777
+ static with(options) {
3778
+ return {
3779
+ type: 'network',
3780
+ create: (docName, doc, runtimeOptions) => {
3781
+ const mergedOptions = runtimeOptions ? { ...options, ...runtimeOptions } : options;
3782
+ return new HocuspocusSyncProvider(docName, doc, mergedOptions);
3783
+ },
3784
+ };
3785
+ }
3786
+ async connect() {
3787
+ if (this.isSynced || this.isDestroyed) {
3788
+ return;
3789
+ }
3790
+ this._connectionStatus = 'connecting';
3791
+ return new Promise((resolve, reject) => {
3792
+ // Store reject function so we can cancel the connection if destroyed
3793
+ this.pendingConnectReject = reject;
3794
+ this.connectTimeout = setTimeout(() => {
3795
+ this.pendingConnectReject = null;
3796
+ this.connectTimeout = null;
3797
+ reject(new Error('Hocuspocus connection timeout'));
3798
+ }, this.connectionTimeoutMs);
3799
+ const syncHandler = () => {
3800
+ if (this.connectTimeout) {
3801
+ clearTimeout(this.connectTimeout);
3802
+ this.connectTimeout = null;
3803
+ }
3804
+ this.pendingConnectReject = null;
3805
+ this.provider.off('synced', syncHandler);
3806
+ if (!this.isDestroyed) {
3807
+ resolve();
3808
+ }
3809
+ };
3810
+ this.provider.on('synced', syncHandler);
3811
+ // If already synced, resolve immediately
3812
+ if (this.provider.isSynced) {
3813
+ if (this.connectTimeout) {
3814
+ clearTimeout(this.connectTimeout);
3815
+ this.connectTimeout = null;
3816
+ }
3817
+ this.pendingConnectReject = null;
3818
+ this.provider.off('synced', syncHandler);
3819
+ resolve();
3820
+ return;
3821
+ }
3822
+ // Connect if not already connected (standalone mode only)
3823
+ if (!this.isConnected && !this.usesSharedSocket) {
3824
+ this.provider.connect();
3825
+ }
3826
+ });
3827
+ }
3828
+ async reconnect() {
3829
+ this.disconnect();
3830
+ return this.connect();
3831
+ }
3832
+ disconnect() {
3833
+ // Cancel any pending connection attempt
3834
+ if (this.connectTimeout) {
3835
+ clearTimeout(this.connectTimeout);
3836
+ this.connectTimeout = null;
3837
+ }
3838
+ if (this.pendingConnectReject) {
3839
+ this.pendingConnectReject = null; // Don't reject, just abandon the promise
3840
+ }
3841
+ if (this.provider) {
3842
+ if (this.usesSharedSocket) {
3843
+ // Detach from shared socket instead of disconnecting
3844
+ this.provider.detach();
3845
+ }
3846
+ else {
3847
+ this.provider.disconnect();
3848
+ }
3849
+ }
3850
+ this.isConnected = false;
3851
+ this.isSynced = false;
3852
+ this._connectionStatus = 'disconnected';
3853
+ }
3854
+ destroy() {
3855
+ // Mark as destroyed first to prevent any callbacks from doing work
3856
+ this.isDestroyed = true;
3857
+ // Cancel any pending connection attempt
3858
+ if (this.connectTimeout) {
3859
+ clearTimeout(this.connectTimeout);
3860
+ this.connectTimeout = null;
3861
+ }
3862
+ if (this.pendingConnectReject) {
3863
+ this.pendingConnectReject = null; // Don't reject, just abandon the promise
3864
+ }
3865
+ this.removeBrowserEventListeners();
3866
+ if (this.provider) {
3867
+ this.provider.destroy();
3868
+ }
3869
+ this.isConnected = false;
3870
+ this.isSynced = false;
3871
+ this._connectionStatus = 'disconnected';
3872
+ }
3873
+ }
3874
+
3875
+ /**
3876
+ * Remote asset storage provider backed by a plain HTTP endpoint.
3877
+ *
3878
+ * The host application is responsible for exposing a REST-ish backend
3879
+ * that accepts a multipart upload and serves the stored asset at a
3880
+ * stable URL. Authentication is injected via `headers`.
3881
+ */
3882
+ class HttpAssetProvider {
3883
+ type = 'remote';
3884
+ name = 'HttpAssetProvider';
3885
+ _options;
3886
+ constructor(options) {
3887
+ this._options = options;
3888
+ }
3889
+ /**
3890
+ * Factory helper enabling use as `HttpAssetProvider.with({ ... })` inside
3891
+ * a `KritzelAssetStorageConfig.providers` array.
3892
+ */
3893
+ static with(options) {
3894
+ return { create: () => new HttpAssetProvider(options) };
3895
+ }
3896
+ async init() {
3897
+ if (!this._options.quiet) {
3898
+ console.info('HttpAssetProvider initialized');
3899
+ }
3900
+ }
3901
+ destroy() {
3902
+ // No-op; no resources to release.
3903
+ }
3904
+ canResolve(_id) {
3905
+ // Remote providers don't know without a round-trip; assume yes.
3906
+ return true;
3907
+ }
3908
+ async put(blob, metadata) {
3909
+ const id = metadata.id ?? this.generateUuid();
3910
+ const fullMetadata = { ...metadata, id };
3911
+ const headers = (await this._options.headers?.()) ?? {};
3912
+ const url = await this._options.uploadUrl(fullMetadata);
3913
+ const uploader = this._options.upload ?? this.defaultUpload;
3914
+ const response = await uploader(url, blob, fullMetadata, headers);
3915
+ return {
3916
+ id: response.id ?? id,
3917
+ kind: metadata.kind ?? 'file',
3918
+ mimeType: metadata.mimeType,
3919
+ size: blob.size,
3920
+ createdAt: Date.now(),
3921
+ width: metadata.width,
3922
+ height: metadata.height,
3923
+ durationMs: metadata.durationMs,
3924
+ originalFilename: metadata.originalFilename,
3925
+ };
3926
+ }
3927
+ async resolve(id) {
3928
+ return this._options.resolveUrl(id);
3929
+ }
3930
+ async fetch(id) {
3931
+ const url = await this._options.resolveUrl(id);
3932
+ const headers = (await this._options.headers?.()) ?? {};
3933
+ const res = await fetch(url, { headers });
3934
+ if (!res.ok) {
3935
+ throw new Error(`[HttpAssetProvider] Failed to fetch asset ${id}: ${res.status} ${res.statusText}`);
3936
+ }
3937
+ return res.blob();
3938
+ }
3939
+ async delete(id) {
3940
+ if (!this._options.deleteUrl)
3941
+ return;
3942
+ const url = await this._options.deleteUrl(id);
3943
+ const headers = (await this._options.headers?.()) ?? {};
3944
+ const res = await fetch(url, { method: 'DELETE', headers });
3945
+ if (!res.ok) {
3946
+ throw new Error(`[HttpAssetProvider] Failed to delete asset ${id}: ${res.status} ${res.statusText}`);
3947
+ }
3948
+ if (!this._options.quiet) {
3949
+ console.info(`HttpAssetProvider: deleted asset ${id}`);
3950
+ }
3951
+ }
3952
+ defaultUpload = async (url, blob, metadata, headers) => {
3953
+ const form = new FormData();
3954
+ form.append('metadata', JSON.stringify(metadata));
3955
+ form.append('file', blob, metadata.originalFilename || `${metadata.id}.${this.extensionFromMime(metadata.mimeType)}`);
3956
+ const res = await fetch(url, {
3957
+ method: 'POST',
3958
+ headers,
3959
+ body: form,
3960
+ });
3961
+ if (!res.ok) {
3962
+ throw new Error(`[HttpAssetProvider] Upload failed: ${res.status} ${res.statusText}`);
3963
+ }
3964
+ // Try to parse a JSON response; tolerate empty/plain-text bodies.
3965
+ const contentType = res.headers.get('content-type') || '';
3966
+ if (contentType.includes('application/json')) {
3967
+ return (await res.json());
3968
+ }
3969
+ return {};
3970
+ };
3971
+ extensionFromMime(mime) {
3972
+ const slash = mime.indexOf('/');
3973
+ return slash >= 0 ? mime.slice(slash + 1) : 'bin';
3974
+ }
3975
+ generateUuid() {
3976
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
3977
+ return crypto.randomUUID();
3978
+ }
3979
+ const bytes = crypto.getRandomValues(new Uint8Array(16));
3980
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
3981
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
3982
+ const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
3983
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
3984
+ }
3985
+ }
3986
+
3987
+ /**
3988
+ * Remote asset storage provider for pre-signed URL uploads (S3, GCS, ...).
3989
+ *
3990
+ * All auth and URL signing is performed by the host application via the
3991
+ * callbacks in {@link PresignedAssetProviderOptions}. The library simply
3992
+ * PUTs/POSTs bytes to the provided URL.
3993
+ */
3994
+ class PresignedAssetProvider {
3995
+ type = 'remote';
3996
+ name = 'PresignedAssetProvider';
3997
+ _options;
3998
+ constructor(options) {
3999
+ this._options = options;
4000
+ }
4001
+ static with(options) {
4002
+ return { create: () => new PresignedAssetProvider(options) };
4003
+ }
4004
+ async init() {
4005
+ if (!this._options.quiet) {
4006
+ console.info('PresignedAssetProvider initialized');
4007
+ }
4008
+ }
4009
+ destroy() {
4010
+ // No-op.
4011
+ }
4012
+ canResolve(_id) {
4013
+ return true;
4014
+ }
4015
+ async put(blob, metadata) {
4016
+ const descriptor = await this._options.getUploadDescriptor(metadata);
4017
+ const method = descriptor.method ?? 'PUT';
4018
+ const headers = { ...(descriptor.headers ?? {}) };
4019
+ if (!headers['Content-Type'] && !headers['content-type']) {
4020
+ headers['Content-Type'] = metadata.mimeType;
4021
+ }
4022
+ let body;
4023
+ if (method === 'POST' && descriptor.fields) {
4024
+ const form = new FormData();
4025
+ for (const [key, value] of Object.entries(descriptor.fields)) {
4026
+ form.append(key, value);
4027
+ }
4028
+ form.append('file', blob);
4029
+ body = form;
4030
+ // Browser sets multipart boundary; avoid forcing content-type.
4031
+ delete headers['Content-Type'];
4032
+ delete headers['content-type'];
4033
+ }
4034
+ else {
4035
+ body = blob;
4036
+ }
4037
+ const res = await fetch(descriptor.url, { method, headers, body });
4038
+ if (!res.ok) {
4039
+ throw new Error(`[PresignedAssetProvider] Upload failed: ${res.status} ${res.statusText}`);
4040
+ }
4041
+ return {
4042
+ id: descriptor.id,
4043
+ kind: metadata.kind ?? 'file',
4044
+ mimeType: metadata.mimeType,
4045
+ size: blob.size,
4046
+ createdAt: Date.now(),
4047
+ width: metadata.width,
4048
+ height: metadata.height,
4049
+ durationMs: metadata.durationMs,
4050
+ originalFilename: metadata.originalFilename,
4051
+ };
4052
+ }
4053
+ async resolve(id) {
4054
+ return this._options.getDownloadUrl(id);
4055
+ }
4056
+ async fetch(id) {
4057
+ const url = await this._options.getDownloadUrl(id);
4058
+ const res = await fetch(url);
4059
+ if (!res.ok) {
4060
+ throw new Error(`[PresignedAssetProvider] Failed to fetch asset ${id}: ${res.status} ${res.statusText}`);
4061
+ }
4062
+ return res.blob();
4063
+ }
4064
+ async delete(id) {
4065
+ if (!this._options.deleteAsset)
4066
+ return;
4067
+ await this._options.deleteAsset(id);
4068
+ if (!this._options.quiet) {
4069
+ console.info(`PresignedAssetProvider: deleted asset ${id}`);
4070
+ }
4071
+ }
4072
+ }
4073
+
4074
+ /**
4075
+ * Returns the provider type (`'local'` or `'network'`) for a given provider config entry.
4076
+ * Works for both class constructors (via a static `type` property) and
4077
+ * factory objects (via an optional `type` property on the factory).
4078
+ */
4079
+ function getProviderConfigType(config) {
4080
+ if (typeof config === 'function') {
4081
+ return config.type;
4082
+ }
4083
+ return config.type;
4084
+ }
4085
+ /**
4086
+ * Returns `true` when the given sync configuration contains at least one remote
4087
+ * (network) provider, meaning the share option should be available in the UI.
4088
+ */
4089
+ function hasRemoteSyncProvider(syncConfig) {
4090
+ if (!syncConfig?.providers?.length) {
4091
+ return false;
4092
+ }
4093
+ return syncConfig.providers.some(p => getProviderConfigType(p) === 'network');
4094
+ }
4095
+
4096
+ const DEFAULT_BRUSH_CONFIG = {
4097
+ color: engine_constants.DEFAULT_COLOR_PALETTE[0],
4098
+ size: 16,
4099
+ opacity: 1,
4100
+ palette: [...engine_constants.DEFAULT_COLOR_PALETTE],
4101
+ sizes: [...engine_constants.DEFAULT_STROKE_SIZES],
4102
+ };
4103
+
4104
+ const DEFAULT_TEXT_CONFIG = {
4105
+ color: engine_constants.DEFAULT_COLOR_PALETTE[0],
4106
+ size: 8,
4107
+ opacity: 1,
4108
+ fontFamily: 'Arial',
4109
+ availableFonts: [...engine_constants.DEFAULT_TEXT_TOOL_AVAILABLE_FONTS],
4110
+ palette: [...engine_constants.DEFAULT_COLOR_PALETTE],
4111
+ sizes: [...engine_constants.DEFAULT_FONT_SIZES],
4112
+ };
4113
+
4114
+ const DEFAULT_LINE_TOOL_CONFIG = {
4115
+ color: engine_constants.DEFAULT_COLOR_PALETTE[0],
4116
+ size: 4,
4117
+ opacity: 1,
4118
+ palette: [...engine_constants.DEFAULT_COLOR_PALETTE],
4119
+ sizes: [...engine_constants.DEFAULT_STROKE_SIZES],
4120
+ arrows: {
4121
+ end: { enabled: true, style: 'triangle' },
4122
+ },
4123
+ };
4124
+
4125
+ const DEFAULT_SHAPE_CONFIG = {
4126
+ shapeType: engine_constants.ShapeType.Rectangle,
4127
+ fillColor: { light: 'transparent', dark: 'transparent' },
4128
+ strokeColor: engine_constants.DEFAULT_COLOR_PALETTE[0],
4129
+ strokeWidth: 4,
4130
+ opacity: 1,
4131
+ fontColor: engine_constants.DEFAULT_COLOR_PALETTE[0],
4132
+ fontSize: 16,
4133
+ fontFamily: 'Arial',
4134
+ palette: [...engine_constants.DEFAULT_COLOR_PALETTE],
4135
+ sizes: [...engine_constants.DEFAULT_STROKE_SIZES],
4136
+ };
4137
+
4138
+ /**
4139
+ * Default asset storage configuration. Stores bytes in IndexedDB only,
4140
+ * which provides offline-friendly behavior out of the box. Applications
4141
+ * that sync Yjs over the network should also configure a remote provider
4142
+ * (e.g. HttpAssetProvider) so images are available across devices.
4143
+ */
4144
+ const DEFAULT_ASSET_STORAGE_CONFIG = {
4145
+ providers: [],
4146
+ };
4147
+
4148
+ /**
4149
+ * The current version of the Kritzel library.
4150
+ * This file is auto-generated by the version bump scripts.
4151
+ * Do not modify manually.
4152
+ */
4153
+ const KRITZEL_VERSION = '0.4.31';
4154
+
4155
+ exports.ABSOLUTE_SCALE_MAX = engine_constants.ABSOLUTE_SCALE_MAX;
4156
+ exports.ABSOLUTE_SCALE_MIN = engine_constants.ABSOLUTE_SCALE_MIN;
4157
+ exports.APP_STATE_MIGRATIONS = engine_constants.APP_STATE_MIGRATIONS;
4158
+ exports.AssetNotFoundError = engine_constants.AssetNotFoundError;
4159
+ exports.CURRENT_APP_STATE_SCHEMA_VERSION = engine_constants.CURRENT_APP_STATE_SCHEMA_VERSION;
4160
+ exports.CURRENT_WORKSPACE_SCHEMA_VERSION = engine_constants.CURRENT_WORKSPACE_SCHEMA_VERSION;
4161
+ exports.DEFAULT_COLOR_PALETTE = engine_constants.DEFAULT_COLOR_PALETTE;
4162
+ exports.DEFAULT_SYNC_CONFIG = engine_constants.DEFAULT_SYNC_CONFIG;
4163
+ exports.DEFAULT_TEXT_TOOL_AVAILABLE_FONTS = engine_constants.DEFAULT_TEXT_TOOL_AVAILABLE_FONTS;
4164
+ exports.DE_LOCALE = engine_constants.DE_LOCALE;
4165
+ exports.EN_LOCALE = engine_constants.EN_LOCALE;
4166
+ exports.FR_LOCALE = engine_constants.FR_LOCALE;
4167
+ exports.IndexedDBAssetProvider = engine_constants.IndexedDBAssetProvider;
4168
+ exports.KRITZEL_WEBSITE_URL = engine_constants.KRITZEL_WEBSITE_URL;
4169
+ Object.defineProperty(exports, "KritzelAlignment", {
4170
+ enumerable: true,
4171
+ get: function () { return engine_constants.KritzelAlignment; }
4172
+ });
4173
+ exports.KritzelAnchorManager = engine_constants.KritzelAnchorManager;
4174
+ exports.KritzelAssetResolver = engine_constants.KritzelAssetResolver;
4175
+ exports.KritzelBaseObject = engine_constants.KritzelBaseObject;
4176
+ exports.KritzelBaseTool = engine_constants.KritzelBaseTool;
4177
+ exports.KritzelBrushTool = engine_constants.KritzelBrushTool;
4178
+ exports.KritzelColorHelper = engine_constants.KritzelColorHelper;
4179
+ exports.KritzelCursorHelper = engine_constants.KritzelCursorHelper;
4180
+ exports.KritzelDevicesHelper = engine_constants.KritzelDevicesHelper;
4181
+ exports.KritzelDynamicObject = engine_constants.KritzelDynamicObject;
4182
+ exports.KritzelDynamicObjectRendererRegistry = engine_constants.KritzelDynamicObjectRendererRegistry;
4183
+ exports.KritzelEraserTool = engine_constants.KritzelEraserTool;
4184
+ exports.KritzelFontRegistry = engine_constants.KritzelFontRegistry;
4185
+ exports.KritzelGroup = engine_constants.KritzelGroup;
4186
+ exports.KritzelHTMLHelper = engine_constants.KritzelHTMLHelper;
4187
+ exports.KritzelIconRegistry = engine_constants.KritzelIconRegistry;
4188
+ exports.KritzelImage = engine_constants.KritzelImage;
4189
+ exports.KritzelImageTool = engine_constants.KritzelImageTool;
4190
+ exports.KritzelKeyboardHelper = engine_constants.KritzelKeyboardHelper;
4191
+ exports.KritzelLicenseManager = engine_constants.KritzelLicenseManager;
4192
+ exports.KritzelLine = engine_constants.KritzelLine;
4193
+ exports.KritzelLineTool = engine_constants.KritzelLineTool;
4194
+ exports.KritzelLocalizationManager = engine_constants.KritzelLocalizationManager;
4195
+ exports.KritzelPath = engine_constants.KritzelPath;
4196
+ exports.KritzelSelectionBox = engine_constants.KritzelSelectionBox;
4197
+ exports.KritzelSelectionGroup = engine_constants.KritzelSelectionGroup;
4198
+ exports.KritzelSelectionTool = engine_constants.KritzelSelectionTool;
4199
+ exports.KritzelShape = engine_constants.KritzelShape;
4200
+ exports.KritzelShapeTool = engine_constants.KritzelShapeTool;
4201
+ exports.KritzelText = engine_constants.KritzelText;
4202
+ exports.KritzelTextTool = engine_constants.KritzelTextTool;
4203
+ exports.KritzelThemeManager = engine_constants.KritzelThemeManager;
4204
+ exports.KritzelWorkspace = engine_constants.KritzelWorkspace;
4205
+ exports.ObjectHelper = engine_constants.ObjectHelper;
4206
+ Object.defineProperty(exports, "ShapeType", {
4207
+ enumerable: true,
4208
+ get: function () { return engine_constants.ShapeType; }
4209
+ });
4210
+ exports.ThemeHelper = engine_constants.ThemeHelper;
4211
+ exports.WORKSPACE_EXPORT_VERSION = engine_constants.WORKSPACE_EXPORT_VERSION;
4212
+ exports.WORKSPACE_MIGRATIONS = engine_constants.WORKSPACE_MIGRATIONS;
4213
+ exports.darkTheme = engine_constants.darkTheme;
4214
+ exports.lightTheme = engine_constants.lightTheme;
4215
+ exports.resolveColor = engine_constants.resolveColor;
4216
+ exports.resolveTextToolAvailableFonts = engine_constants.resolveTextToolAvailableFonts;
4217
+ exports.runMigrations = engine_constants.runMigrations;
4218
+ exports.BroadcastSyncProvider = BroadcastSyncProvider;
4219
+ exports.DEFAULT_ASSET_STORAGE_CONFIG = DEFAULT_ASSET_STORAGE_CONFIG;
4220
+ exports.DEFAULT_BRUSH_CONFIG = DEFAULT_BRUSH_CONFIG;
4221
+ exports.DEFAULT_LINE_TOOL_CONFIG = DEFAULT_LINE_TOOL_CONFIG;
4222
+ exports.DEFAULT_SHAPE_CONFIG = DEFAULT_SHAPE_CONFIG;
4223
+ exports.DEFAULT_TEXT_CONFIG = DEFAULT_TEXT_CONFIG;
4224
+ exports.HocuspocusSyncProvider = HocuspocusSyncProvider;
4225
+ exports.HttpAssetProvider = HttpAssetProvider;
4226
+ exports.InMemorySyncProvider = InMemorySyncProvider;
4227
+ exports.IndexedDBSyncProvider = IndexedDBSyncProvider;
4228
+ exports.KRITZEL_VERSION = KRITZEL_VERSION;
4229
+ exports.KritzelToolConfigHelper = KritzelToolConfigHelper;
4230
+ exports.PresignedAssetProvider = PresignedAssetProvider;
4231
+ exports.WebSocketSyncProvider = WebSocketSyncProvider;
4232
+ exports.hasRemoteSyncProvider = hasRemoteSyncProvider;