@powerhousedao/reactor-browser 6.0.0-dev.23 → 6.0.0-dev.230

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 (543) hide show
  1. package/README.md +6 -3
  2. package/dist/client-DfoxBz8A.js +862 -0
  3. package/dist/client-DfoxBz8A.js.map +1 -0
  4. package/dist/client-DhQo2Vi9.d.ts +804 -0
  5. package/dist/client-DhQo2Vi9.d.ts.map +1 -0
  6. package/dist/document-by-id-CDLUqru5.js +441 -0
  7. package/dist/document-by-id-CDLUqru5.js.map +1 -0
  8. package/dist/index-Ce4S7Kk1.d.ts +726 -0
  9. package/dist/index-Ce4S7Kk1.d.ts.map +1 -0
  10. package/dist/index-DgwLcoI3.d.ts +343 -0
  11. package/dist/index-DgwLcoI3.d.ts.map +1 -0
  12. package/dist/index.d.ts +1507 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +3249 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/make-ph-event-functions-Cr4GqOTT.js +57 -0
  17. package/dist/make-ph-event-functions-Cr4GqOTT.js.map +1 -0
  18. package/dist/relational-jwreqDwz.js +123 -0
  19. package/dist/relational-jwreqDwz.js.map +1 -0
  20. package/dist/renown-CV_45Xc1.js +1014 -0
  21. package/dist/renown-CV_45Xc1.js.map +1 -0
  22. package/dist/src/analytics/index.d.ts +112 -2
  23. package/dist/src/analytics/index.d.ts.map +1 -1
  24. package/dist/src/analytics/index.js +342 -2
  25. package/dist/src/analytics/index.js.map +1 -1
  26. package/dist/src/graphql/client.d.ts +2 -0
  27. package/dist/src/graphql/client.js +2 -0
  28. package/dist/src/relational/index.d.ts +2 -3
  29. package/dist/src/relational/index.js +2 -3
  30. package/dist/src/renown/index.d.ts +2 -3
  31. package/dist/src/renown/index.js +2 -3
  32. package/dist/types-BmR60pPN.d.ts +22 -0
  33. package/dist/types-BmR60pPN.d.ts.map +1 -0
  34. package/package.json +58 -48
  35. package/dist/src/actions/dispatch.d.ts +0 -18
  36. package/dist/src/actions/dispatch.d.ts.map +0 -1
  37. package/dist/src/actions/dispatch.js +0 -47
  38. package/dist/src/actions/dispatch.js.map +0 -1
  39. package/dist/src/actions/document.d.ts +0 -20
  40. package/dist/src/actions/document.d.ts.map +0 -1
  41. package/dist/src/actions/document.js +0 -711
  42. package/dist/src/actions/document.js.map +0 -1
  43. package/dist/src/actions/drive.d.ts +0 -12
  44. package/dist/src/actions/drive.d.ts.map +0 -1
  45. package/dist/src/actions/drive.js +0 -256
  46. package/dist/src/actions/drive.js.map +0 -1
  47. package/dist/src/actions/index.d.ts +0 -4
  48. package/dist/src/actions/index.d.ts.map +0 -1
  49. package/dist/src/actions/index.js +0 -4
  50. package/dist/src/actions/index.js.map +0 -1
  51. package/dist/src/actions/queue.d.ts +0 -10
  52. package/dist/src/actions/queue.d.ts.map +0 -1
  53. package/dist/src/actions/queue.js +0 -160
  54. package/dist/src/actions/queue.js.map +0 -1
  55. package/dist/src/actions/sign.d.ts +0 -5
  56. package/dist/src/actions/sign.d.ts.map +0 -1
  57. package/dist/src/actions/sign.js +0 -71
  58. package/dist/src/actions/sign.js.map +0 -1
  59. package/dist/src/analytics/context.d.ts +0 -33
  60. package/dist/src/analytics/context.d.ts.map +0 -1
  61. package/dist/src/analytics/context.js +0 -148
  62. package/dist/src/analytics/context.js.map +0 -1
  63. package/dist/src/analytics/hooks/analytics-query.d.ts +0 -31
  64. package/dist/src/analytics/hooks/analytics-query.d.ts.map +0 -1
  65. package/dist/src/analytics/hooks/analytics-query.js +0 -157
  66. package/dist/src/analytics/hooks/analytics-query.js.map +0 -1
  67. package/dist/src/analytics/hooks/document-timeline.d.ts +0 -19
  68. package/dist/src/analytics/hooks/document-timeline.d.ts.map +0 -1
  69. package/dist/src/analytics/hooks/document-timeline.js +0 -10
  70. package/dist/src/analytics/hooks/document-timeline.js.map +0 -1
  71. package/dist/src/analytics/hooks/index.d.ts +0 -4
  72. package/dist/src/analytics/hooks/index.d.ts.map +0 -1
  73. package/dist/src/analytics/hooks/index.js +0 -4
  74. package/dist/src/analytics/hooks/index.js.map +0 -1
  75. package/dist/src/analytics/hooks/timeline-items.d.ts +0 -25
  76. package/dist/src/analytics/hooks/timeline-items.d.ts.map +0 -1
  77. package/dist/src/analytics/hooks/timeline-items.js +0 -104
  78. package/dist/src/analytics/hooks/timeline-items.js.map +0 -1
  79. package/dist/src/analytics/store/browser.d.ts +0 -2
  80. package/dist/src/analytics/store/browser.d.ts.map +0 -1
  81. package/dist/src/analytics/store/browser.js +0 -2
  82. package/dist/src/analytics/store/browser.js.map +0 -1
  83. package/dist/src/analytics/store/memory.d.ts +0 -2
  84. package/dist/src/analytics/store/memory.d.ts.map +0 -1
  85. package/dist/src/analytics/store/memory.js +0 -2
  86. package/dist/src/analytics/store/memory.js.map +0 -1
  87. package/dist/src/analytics/types.d.ts +0 -9
  88. package/dist/src/analytics/types.d.ts.map +0 -1
  89. package/dist/src/analytics/types.js +0 -2
  90. package/dist/src/analytics/types.js.map +0 -1
  91. package/dist/src/analytics.d.ts +0 -3
  92. package/dist/src/analytics.d.ts.map +0 -1
  93. package/dist/src/analytics.js +0 -3
  94. package/dist/src/analytics.js.map +0 -1
  95. package/dist/src/connect.d.ts +0 -2
  96. package/dist/src/connect.d.ts.map +0 -1
  97. package/dist/src/connect.js +0 -2
  98. package/dist/src/connect.js.map +0 -1
  99. package/dist/src/constants.d.ts +0 -3
  100. package/dist/src/constants.d.ts.map +0 -1
  101. package/dist/src/constants.js +0 -3
  102. package/dist/src/constants.js.map +0 -1
  103. package/dist/src/context/index.d.ts +0 -2
  104. package/dist/src/context/index.d.ts.map +0 -1
  105. package/dist/src/context/index.js +0 -2
  106. package/dist/src/context/index.js.map +0 -1
  107. package/dist/src/context/read-mode.d.ts +0 -14
  108. package/dist/src/context/read-mode.d.ts.map +0 -1
  109. package/dist/src/context/read-mode.js +0 -177
  110. package/dist/src/context/read-mode.js.map +0 -1
  111. package/dist/src/document-cache.d.ts +0 -17
  112. package/dist/src/document-cache.d.ts.map +0 -1
  113. package/dist/src/document-cache.js +0 -143
  114. package/dist/src/document-cache.js.map +0 -1
  115. package/dist/src/document-model.d.ts +0 -4
  116. package/dist/src/document-model.d.ts.map +0 -1
  117. package/dist/src/document-model.js +0 -6
  118. package/dist/src/document-model.js.map +0 -1
  119. package/dist/src/errors.d.ts +0 -16
  120. package/dist/src/errors.d.ts.map +0 -1
  121. package/dist/src/errors.js +0 -27
  122. package/dist/src/errors.js.map +0 -1
  123. package/dist/src/global/core.d.ts +0 -5
  124. package/dist/src/global/core.d.ts.map +0 -1
  125. package/dist/src/global/core.js +0 -22
  126. package/dist/src/global/core.js.map +0 -1
  127. package/dist/src/global/index.d.ts +0 -2
  128. package/dist/src/global/index.d.ts.map +0 -1
  129. package/dist/src/global/index.js +0 -2
  130. package/dist/src/global/index.js.map +0 -1
  131. package/dist/src/global/types.d.ts +0 -17
  132. package/dist/src/global/types.d.ts.map +0 -1
  133. package/dist/src/global/types.js +0 -2
  134. package/dist/src/global/types.js.map +0 -1
  135. package/dist/src/hooks/add-ph-event-handlers.d.ts +0 -2
  136. package/dist/src/hooks/add-ph-event-handlers.d.ts.map +0 -1
  137. package/dist/src/hooks/add-ph-event-handlers.js +0 -109
  138. package/dist/src/hooks/add-ph-event-handlers.js.map +0 -1
  139. package/dist/src/hooks/allowed-document-model-modules.d.ts +0 -2
  140. package/dist/src/hooks/allowed-document-model-modules.d.ts.map +0 -1
  141. package/dist/src/hooks/allowed-document-model-modules.js +0 -10
  142. package/dist/src/hooks/allowed-document-model-modules.js.map +0 -1
  143. package/dist/src/hooks/child-nodes.d.ts +0 -4
  144. package/dist/src/hooks/child-nodes.d.ts.map +0 -1
  145. package/dist/src/hooks/child-nodes.js +0 -15
  146. package/dist/src/hooks/child-nodes.js.map +0 -1
  147. package/dist/src/hooks/config/connect.d.ts +0 -96
  148. package/dist/src/hooks/config/connect.d.ts.map +0 -1
  149. package/dist/src/hooks/config/connect.js +0 -210
  150. package/dist/src/hooks/config/connect.js.map +0 -1
  151. package/dist/src/hooks/config/editor.d.ts +0 -32
  152. package/dist/src/hooks/config/editor.d.ts.map +0 -1
  153. package/dist/src/hooks/config/editor.js +0 -43
  154. package/dist/src/hooks/config/editor.js.map +0 -1
  155. package/dist/src/hooks/config/set-config-by-key.d.ts +0 -5
  156. package/dist/src/hooks/config/set-config-by-key.d.ts.map +0 -1
  157. package/dist/src/hooks/config/set-config-by-key.js +0 -15
  158. package/dist/src/hooks/config/set-config-by-key.js.map +0 -1
  159. package/dist/src/hooks/config/set-config-by-object.d.ts +0 -31
  160. package/dist/src/hooks/config/set-config-by-object.d.ts.map +0 -1
  161. package/dist/src/hooks/config/set-config-by-object.js +0 -84
  162. package/dist/src/hooks/config/set-config-by-object.js.map +0 -1
  163. package/dist/src/hooks/config/use-value-by-key.d.ts +0 -13
  164. package/dist/src/hooks/config/use-value-by-key.d.ts.map +0 -1
  165. package/dist/src/hooks/config/use-value-by-key.js +0 -23
  166. package/dist/src/hooks/config/use-value-by-key.js.map +0 -1
  167. package/dist/src/hooks/config/utils.d.ts +0 -3
  168. package/dist/src/hooks/config/utils.d.ts.map +0 -1
  169. package/dist/src/hooks/config/utils.js +0 -6
  170. package/dist/src/hooks/config/utils.js.map +0 -1
  171. package/dist/src/hooks/connect.d.ts +0 -16
  172. package/dist/src/hooks/connect.d.ts.map +0 -1
  173. package/dist/src/hooks/connect.js +0 -16
  174. package/dist/src/hooks/connect.js.map +0 -1
  175. package/dist/src/hooks/crypto.d.ts +0 -9
  176. package/dist/src/hooks/crypto.d.ts.map +0 -1
  177. package/dist/src/hooks/crypto.js +0 -13
  178. package/dist/src/hooks/crypto.js.map +0 -1
  179. package/dist/src/hooks/did.d.ts +0 -2
  180. package/dist/src/hooks/did.d.ts.map +0 -1
  181. package/dist/src/hooks/did.js +0 -3
  182. package/dist/src/hooks/did.js.map +0 -1
  183. package/dist/src/hooks/dispatch.d.ts +0 -9
  184. package/dist/src/hooks/dispatch.d.ts.map +0 -1
  185. package/dist/src/hooks/dispatch.js +0 -20
  186. package/dist/src/hooks/dispatch.js.map +0 -1
  187. package/dist/src/hooks/document-by-id.d.ts +0 -6
  188. package/dist/src/hooks/document-by-id.d.ts.map +0 -1
  189. package/dist/src/hooks/document-by-id.js +0 -13
  190. package/dist/src/hooks/document-by-id.js.map +0 -1
  191. package/dist/src/hooks/document-cache.d.ts +0 -76
  192. package/dist/src/hooks/document-cache.d.ts.map +0 -1
  193. package/dist/src/hooks/document-cache.js +0 -124
  194. package/dist/src/hooks/document-cache.js.map +0 -1
  195. package/dist/src/hooks/document-model-modules.d.ts +0 -4
  196. package/dist/src/hooks/document-model-modules.d.ts.map +0 -1
  197. package/dist/src/hooks/document-model-modules.js +0 -10
  198. package/dist/src/hooks/document-model-modules.js.map +0 -1
  199. package/dist/src/hooks/document-of-type.d.ts +0 -5
  200. package/dist/src/hooks/document-of-type.d.ts.map +0 -1
  201. package/dist/src/hooks/document-of-type.js +0 -22
  202. package/dist/src/hooks/document-of-type.js.map +0 -1
  203. package/dist/src/hooks/document-types.d.ts +0 -7
  204. package/dist/src/hooks/document-types.d.ts.map +0 -1
  205. package/dist/src/hooks/document-types.js +0 -13
  206. package/dist/src/hooks/document-types.js.map +0 -1
  207. package/dist/src/hooks/drive-by-id.d.ts +0 -4
  208. package/dist/src/hooks/drive-by-id.d.ts.map +0 -1
  209. package/dist/src/hooks/drive-by-id.js +0 -12
  210. package/dist/src/hooks/drive-by-id.js.map +0 -1
  211. package/dist/src/hooks/drives.d.ts +0 -9
  212. package/dist/src/hooks/drives.d.ts.map +0 -1
  213. package/dist/src/hooks/drives.js +0 -9
  214. package/dist/src/hooks/drives.js.map +0 -1
  215. package/dist/src/hooks/editor-modules.d.ts +0 -9
  216. package/dist/src/hooks/editor-modules.d.ts.map +0 -1
  217. package/dist/src/hooks/editor-modules.js +0 -43
  218. package/dist/src/hooks/editor-modules.js.map +0 -1
  219. package/dist/src/hooks/features.d.ts +0 -5
  220. package/dist/src/hooks/features.d.ts.map +0 -1
  221. package/dist/src/hooks/features.js +0 -6
  222. package/dist/src/hooks/features.js.map +0 -1
  223. package/dist/src/hooks/folder-by-id.d.ts +0 -3
  224. package/dist/src/hooks/folder-by-id.d.ts.map +0 -1
  225. package/dist/src/hooks/folder-by-id.js +0 -6
  226. package/dist/src/hooks/folder-by-id.js.map +0 -1
  227. package/dist/src/hooks/import-script-modules.d.ts +0 -3
  228. package/dist/src/hooks/import-script-modules.d.ts.map +0 -1
  229. package/dist/src/hooks/import-script-modules.js +0 -6
  230. package/dist/src/hooks/import-script-modules.js.map +0 -1
  231. package/dist/src/hooks/index.d.ts +0 -41
  232. package/dist/src/hooks/index.d.ts.map +0 -1
  233. package/dist/src/hooks/index.js +0 -41
  234. package/dist/src/hooks/index.js.map +0 -1
  235. package/dist/src/hooks/items-in-selected-drive.d.ts +0 -13
  236. package/dist/src/hooks/items-in-selected-drive.d.ts.map +0 -1
  237. package/dist/src/hooks/items-in-selected-drive.js +0 -35
  238. package/dist/src/hooks/items-in-selected-drive.js.map +0 -1
  239. package/dist/src/hooks/items-in-selected-folder.d.ts +0 -11
  240. package/dist/src/hooks/items-in-selected-folder.d.ts.map +0 -1
  241. package/dist/src/hooks/items-in-selected-folder.js +0 -33
  242. package/dist/src/hooks/items-in-selected-folder.js.map +0 -1
  243. package/dist/src/hooks/loading.d.ts +0 -2
  244. package/dist/src/hooks/loading.d.ts.map +0 -1
  245. package/dist/src/hooks/loading.js +0 -3
  246. package/dist/src/hooks/loading.js.map +0 -1
  247. package/dist/src/hooks/login-status.d.ts +0 -2
  248. package/dist/src/hooks/login-status.d.ts.map +0 -1
  249. package/dist/src/hooks/login-status.js +0 -3
  250. package/dist/src/hooks/login-status.js.map +0 -1
  251. package/dist/src/hooks/make-ph-event-functions.d.ts +0 -7
  252. package/dist/src/hooks/make-ph-event-functions.d.ts.map +0 -1
  253. package/dist/src/hooks/make-ph-event-functions.js +0 -46
  254. package/dist/src/hooks/make-ph-event-functions.js.map +0 -1
  255. package/dist/src/hooks/modals.d.ts +0 -17
  256. package/dist/src/hooks/modals.d.ts.map +0 -1
  257. package/dist/src/hooks/modals.js +0 -26
  258. package/dist/src/hooks/modals.js.map +0 -1
  259. package/dist/src/hooks/node-actions.d.ts +0 -12
  260. package/dist/src/hooks/node-actions.d.ts.map +0 -1
  261. package/dist/src/hooks/node-actions.js +0 -108
  262. package/dist/src/hooks/node-actions.js.map +0 -1
  263. package/dist/src/hooks/node-by-id.d.ts +0 -4
  264. package/dist/src/hooks/node-by-id.d.ts.map +0 -1
  265. package/dist/src/hooks/node-by-id.js +0 -7
  266. package/dist/src/hooks/node-by-id.js.map +0 -1
  267. package/dist/src/hooks/node-path.d.ts +0 -6
  268. package/dist/src/hooks/node-path.d.ts.map +0 -1
  269. package/dist/src/hooks/node-path.js +0 -23
  270. package/dist/src/hooks/node-path.js.map +0 -1
  271. package/dist/src/hooks/parent-folder.d.ts +0 -4
  272. package/dist/src/hooks/parent-folder.d.ts.map +0 -1
  273. package/dist/src/hooks/parent-folder.js +0 -13
  274. package/dist/src/hooks/parent-folder.js.map +0 -1
  275. package/dist/src/hooks/processor-manager.d.ts +0 -9
  276. package/dist/src/hooks/processor-manager.d.ts.map +0 -1
  277. package/dist/src/hooks/processor-manager.js +0 -9
  278. package/dist/src/hooks/processor-manager.js.map +0 -1
  279. package/dist/src/hooks/processor-modules.d.ts +0 -4
  280. package/dist/src/hooks/processor-modules.d.ts.map +0 -1
  281. package/dist/src/hooks/processor-modules.js +0 -12
  282. package/dist/src/hooks/processor-modules.js.map +0 -1
  283. package/dist/src/hooks/reactor.d.ts +0 -42
  284. package/dist/src/hooks/reactor.d.ts.map +0 -1
  285. package/dist/src/hooks/reactor.js +0 -44
  286. package/dist/src/hooks/reactor.js.map +0 -1
  287. package/dist/src/hooks/renown.d.ts +0 -8
  288. package/dist/src/hooks/renown.d.ts.map +0 -1
  289. package/dist/src/hooks/renown.js +0 -9
  290. package/dist/src/hooks/renown.js.map +0 -1
  291. package/dist/src/hooks/revision-history.d.ts +0 -11
  292. package/dist/src/hooks/revision-history.d.ts.map +0 -1
  293. package/dist/src/hooks/revision-history.js +0 -17
  294. package/dist/src/hooks/revision-history.js.map +0 -1
  295. package/dist/src/hooks/selected-document.d.ts +0 -12
  296. package/dist/src/hooks/selected-document.d.ts.map +0 -1
  297. package/dist/src/hooks/selected-document.js +0 -35
  298. package/dist/src/hooks/selected-document.js.map +0 -1
  299. package/dist/src/hooks/selected-drive.d.ts +0 -13
  300. package/dist/src/hooks/selected-drive.d.ts.map +0 -1
  301. package/dist/src/hooks/selected-drive.js +0 -63
  302. package/dist/src/hooks/selected-drive.js.map +0 -1
  303. package/dist/src/hooks/selected-folder.d.ts +0 -4
  304. package/dist/src/hooks/selected-folder.d.ts.map +0 -1
  305. package/dist/src/hooks/selected-folder.js +0 -10
  306. package/dist/src/hooks/selected-folder.js.map +0 -1
  307. package/dist/src/hooks/selected-node.d.ts +0 -9
  308. package/dist/src/hooks/selected-node.d.ts.map +0 -1
  309. package/dist/src/hooks/selected-node.js +0 -54
  310. package/dist/src/hooks/selected-node.js.map +0 -1
  311. package/dist/src/hooks/selected-timeline-item.d.ts +0 -7
  312. package/dist/src/hooks/selected-timeline-item.d.ts.map +0 -1
  313. package/dist/src/hooks/selected-timeline-item.js +0 -9
  314. package/dist/src/hooks/selected-timeline-item.js.map +0 -1
  315. package/dist/src/hooks/subgraph-modules.d.ts +0 -3
  316. package/dist/src/hooks/subgraph-modules.d.ts.map +0 -1
  317. package/dist/src/hooks/subgraph-modules.js +0 -6
  318. package/dist/src/hooks/subgraph-modules.js.map +0 -1
  319. package/dist/src/hooks/supported-document-types.d.ts +0 -3
  320. package/dist/src/hooks/supported-document-types.d.ts.map +0 -1
  321. package/dist/src/hooks/supported-document-types.js +0 -7
  322. package/dist/src/hooks/supported-document-types.js.map +0 -1
  323. package/dist/src/hooks/timeline-revision.d.ts +0 -7
  324. package/dist/src/hooks/timeline-revision.d.ts.map +0 -1
  325. package/dist/src/hooks/timeline-revision.js +0 -9
  326. package/dist/src/hooks/timeline-revision.js.map +0 -1
  327. package/dist/src/hooks/toast.d.ts +0 -7
  328. package/dist/src/hooks/toast.d.ts.map +0 -1
  329. package/dist/src/hooks/toast.js +0 -9
  330. package/dist/src/hooks/toast.js.map +0 -1
  331. package/dist/src/hooks/use-feature-flags.d.ts +0 -36
  332. package/dist/src/hooks/use-feature-flags.d.ts.map +0 -1
  333. package/dist/src/hooks/use-feature-flags.js +0 -73
  334. package/dist/src/hooks/use-feature-flags.js.map +0 -1
  335. package/dist/src/hooks/use-get-switchboard-link.d.ts +0 -14
  336. package/dist/src/hooks/use-get-switchboard-link.d.ts.map +0 -1
  337. package/dist/src/hooks/use-get-switchboard-link.js +0 -38
  338. package/dist/src/hooks/use-get-switchboard-link.js.map +0 -1
  339. package/dist/src/hooks/use-on-drop-file.d.ts +0 -3
  340. package/dist/src/hooks/use-on-drop-file.d.ts.map +0 -1
  341. package/dist/src/hooks/use-on-drop-file.js +0 -21
  342. package/dist/src/hooks/use-on-drop-file.js.map +0 -1
  343. package/dist/src/hooks/user-permissions.d.ts +0 -5
  344. package/dist/src/hooks/user-permissions.d.ts.map +0 -1
  345. package/dist/src/hooks/user-permissions.js +0 -17
  346. package/dist/src/hooks/user-permissions.js.map +0 -1
  347. package/dist/src/hooks/user.d.ts +0 -8
  348. package/dist/src/hooks/user.d.ts.map +0 -1
  349. package/dist/src/hooks/user.js +0 -9
  350. package/dist/src/hooks/user.js.map +0 -1
  351. package/dist/src/hooks/vetra-packages.d.ts +0 -8
  352. package/dist/src/hooks/vetra-packages.d.ts.map +0 -1
  353. package/dist/src/hooks/vetra-packages.js +0 -17
  354. package/dist/src/hooks/vetra-packages.js.map +0 -1
  355. package/dist/src/index.d.ts +0 -15
  356. package/dist/src/index.d.ts.map +0 -1
  357. package/dist/src/index.js +0 -15
  358. package/dist/src/index.js.map +0 -1
  359. package/dist/src/pglite/drop.d.ts +0 -3
  360. package/dist/src/pglite/drop.d.ts.map +0 -1
  361. package/dist/src/pglite/drop.js +0 -19
  362. package/dist/src/pglite/drop.js.map +0 -1
  363. package/dist/src/pglite/hooks/index.d.ts +0 -2
  364. package/dist/src/pglite/hooks/index.d.ts.map +0 -1
  365. package/dist/src/pglite/hooks/index.js +0 -2
  366. package/dist/src/pglite/hooks/index.js.map +0 -1
  367. package/dist/src/pglite/hooks/usePGlite.d.ts +0 -11
  368. package/dist/src/pglite/hooks/usePGlite.d.ts.map +0 -1
  369. package/dist/src/pglite/hooks/usePGlite.js +0 -37
  370. package/dist/src/pglite/hooks/usePGlite.js.map +0 -1
  371. package/dist/src/pglite/index.d.ts +0 -3
  372. package/dist/src/pglite/index.d.ts.map +0 -1
  373. package/dist/src/pglite/index.js +0 -3
  374. package/dist/src/pglite/index.js.map +0 -1
  375. package/dist/src/reactor-client-document-cache.d.ts +0 -31
  376. package/dist/src/reactor-client-document-cache.d.ts.map +0 -1
  377. package/dist/src/reactor-client-document-cache.js +0 -142
  378. package/dist/src/reactor-client-document-cache.js.map +0 -1
  379. package/dist/src/reactor.d.ts +0 -18
  380. package/dist/src/reactor.d.ts.map +0 -1
  381. package/dist/src/reactor.js +0 -162
  382. package/dist/src/reactor.js.map +0 -1
  383. package/dist/src/relational/hooks/index.d.ts +0 -3
  384. package/dist/src/relational/hooks/index.d.ts.map +0 -1
  385. package/dist/src/relational/hooks/index.js +0 -3
  386. package/dist/src/relational/hooks/index.js.map +0 -1
  387. package/dist/src/relational/hooks/useRelationalDb.d.ts +0 -12
  388. package/dist/src/relational/hooks/useRelationalDb.d.ts.map +0 -1
  389. package/dist/src/relational/hooks/useRelationalDb.js +0 -36
  390. package/dist/src/relational/hooks/useRelationalDb.js.map +0 -1
  391. package/dist/src/relational/hooks/useRelationalQuery.d.ts +0 -15
  392. package/dist/src/relational/hooks/useRelationalQuery.d.ts.map +0 -1
  393. package/dist/src/relational/hooks/useRelationalQuery.js +0 -76
  394. package/dist/src/relational/hooks/useRelationalQuery.js.map +0 -1
  395. package/dist/src/relational/index.d.ts.map +0 -1
  396. package/dist/src/relational/index.js.map +0 -1
  397. package/dist/src/relational/utils/createProcessorQuery.d.ts +0 -17
  398. package/dist/src/relational/utils/createProcessorQuery.d.ts.map +0 -1
  399. package/dist/src/relational/utils/createProcessorQuery.js +0 -24
  400. package/dist/src/relational/utils/createProcessorQuery.js.map +0 -1
  401. package/dist/src/relational/utils/index.d.ts +0 -2
  402. package/dist/src/relational/utils/index.d.ts.map +0 -1
  403. package/dist/src/relational/utils/index.js +0 -2
  404. package/dist/src/relational/utils/index.js.map +0 -1
  405. package/dist/src/renown/constants.d.ts +0 -130
  406. package/dist/src/renown/constants.d.ts.map +0 -1
  407. package/dist/src/renown/constants.js +0 -40
  408. package/dist/src/renown/constants.js.map +0 -1
  409. package/dist/src/renown/index.d.ts.map +0 -1
  410. package/dist/src/renown/index.js.map +0 -1
  411. package/dist/src/renown/utils.d.ts +0 -6
  412. package/dist/src/renown/utils.d.ts.map +0 -1
  413. package/dist/src/renown/utils.js +0 -56
  414. package/dist/src/renown/utils.js.map +0 -1
  415. package/dist/src/storage/index.d.ts +0 -2
  416. package/dist/src/storage/index.d.ts.map +0 -1
  417. package/dist/src/storage/index.js +0 -2
  418. package/dist/src/storage/index.js.map +0 -1
  419. package/dist/src/storage/types.d.ts +0 -6
  420. package/dist/src/storage/types.d.ts.map +0 -1
  421. package/dist/src/storage/types.js +0 -2
  422. package/dist/src/storage/types.js.map +0 -1
  423. package/dist/src/types/config.d.ts +0 -96
  424. package/dist/src/types/config.d.ts.map +0 -1
  425. package/dist/src/types/config.js +0 -2
  426. package/dist/src/types/config.js.map +0 -1
  427. package/dist/src/types/documents.d.ts +0 -26
  428. package/dist/src/types/documents.d.ts.map +0 -1
  429. package/dist/src/types/documents.js +0 -2
  430. package/dist/src/types/documents.js.map +0 -1
  431. package/dist/src/types/global.d.ts +0 -56
  432. package/dist/src/types/global.d.ts.map +0 -1
  433. package/dist/src/types/global.js +0 -2
  434. package/dist/src/types/global.js.map +0 -1
  435. package/dist/src/types/index.d.ts +0 -10
  436. package/dist/src/types/index.d.ts.map +0 -1
  437. package/dist/src/types/index.js +0 -2
  438. package/dist/src/types/index.js.map +0 -1
  439. package/dist/src/types/modals.d.ts +0 -34
  440. package/dist/src/types/modals.d.ts.map +0 -1
  441. package/dist/src/types/modals.js +0 -2
  442. package/dist/src/types/modals.js.map +0 -1
  443. package/dist/src/types/reactor.d.ts +0 -2
  444. package/dist/src/types/reactor.d.ts.map +0 -1
  445. package/dist/src/types/reactor.js +0 -2
  446. package/dist/src/types/reactor.js.map +0 -1
  447. package/dist/src/types/timeline.d.ts +0 -24
  448. package/dist/src/types/timeline.d.ts.map +0 -1
  449. package/dist/src/types/timeline.js +0 -2
  450. package/dist/src/types/timeline.js.map +0 -1
  451. package/dist/src/types/toast.d.ts +0 -9
  452. package/dist/src/types/toast.d.ts.map +0 -1
  453. package/dist/src/types/toast.js +0 -2
  454. package/dist/src/types/toast.js.map +0 -1
  455. package/dist/src/types/upload.d.ts +0 -16
  456. package/dist/src/types/upload.d.ts.map +0 -1
  457. package/dist/src/types/upload.js +0 -2
  458. package/dist/src/types/upload.js.map +0 -1
  459. package/dist/src/types/vetra.d.ts +0 -60
  460. package/dist/src/types/vetra.d.ts.map +0 -1
  461. package/dist/src/types/vetra.js +0 -2
  462. package/dist/src/types/vetra.js.map +0 -1
  463. package/dist/src/utils/documents.d.ts +0 -2
  464. package/dist/src/utils/documents.d.ts.map +0 -1
  465. package/dist/src/utils/documents.js +0 -20
  466. package/dist/src/utils/documents.js.map +0 -1
  467. package/dist/src/utils/drive-url.d.ts +0 -2
  468. package/dist/src/utils/drive-url.d.ts.map +0 -1
  469. package/dist/src/utils/drive-url.js +0 -3
  470. package/dist/src/utils/drive-url.js.map +0 -1
  471. package/dist/src/utils/drives.d.ts +0 -36
  472. package/dist/src/utils/drives.d.ts.map +0 -1
  473. package/dist/src/utils/drives.js +0 -142
  474. package/dist/src/utils/drives.js.map +0 -1
  475. package/dist/src/utils/export-document.d.ts +0 -3
  476. package/dist/src/utils/export-document.d.ts.map +0 -1
  477. package/dist/src/utils/export-document.js +0 -18
  478. package/dist/src/utils/export-document.js.map +0 -1
  479. package/dist/src/utils/get-revision-from-date.d.ts +0 -3
  480. package/dist/src/utils/get-revision-from-date.d.ts.map +0 -1
  481. package/dist/src/utils/get-revision-from-date.js +0 -10
  482. package/dist/src/utils/get-revision-from-date.js.map +0 -1
  483. package/dist/src/utils/index.d.ts +0 -12
  484. package/dist/src/utils/index.d.ts.map +0 -1
  485. package/dist/src/utils/index.js +0 -12
  486. package/dist/src/utils/index.js.map +0 -1
  487. package/dist/src/utils/nodes.d.ts +0 -8
  488. package/dist/src/utils/nodes.d.ts.map +0 -1
  489. package/dist/src/utils/nodes.js +0 -17
  490. package/dist/src/utils/nodes.js.map +0 -1
  491. package/dist/src/utils/switchboard.d.ts +0 -7
  492. package/dist/src/utils/switchboard.d.ts.map +0 -1
  493. package/dist/src/utils/switchboard.js +0 -76
  494. package/dist/src/utils/switchboard.js.map +0 -1
  495. package/dist/src/utils/url.d.ts +0 -29
  496. package/dist/src/utils/url.d.ts.map +0 -1
  497. package/dist/src/utils/url.js +0 -77
  498. package/dist/src/utils/url.js.map +0 -1
  499. package/dist/src/utils/user.d.ts +0 -5
  500. package/dist/src/utils/user.d.ts.map +0 -1
  501. package/dist/src/utils/user.js +0 -15
  502. package/dist/src/utils/user.js.map +0 -1
  503. package/dist/src/utils/validate-document.d.ts +0 -3
  504. package/dist/src/utils/validate-document.d.ts.map +0 -1
  505. package/dist/src/utils/validate-document.js +0 -38
  506. package/dist/src/utils/validate-document.js.map +0 -1
  507. package/dist/src/utils/vetra.d.ts +0 -7
  508. package/dist/src/utils/vetra.d.ts.map +0 -1
  509. package/dist/src/utils/vetra.js +0 -86
  510. package/dist/src/utils/vetra.js.map +0 -1
  511. package/dist/test/analytics.test.d.ts +0 -2
  512. package/dist/test/analytics.test.d.ts.map +0 -1
  513. package/dist/test/analytics.test.js +0 -263
  514. package/dist/test/analytics.test.js.map +0 -1
  515. package/dist/test/document-cache.test.d.ts +0 -2
  516. package/dist/test/document-cache.test.d.ts.map +0 -1
  517. package/dist/test/document-cache.test.js +0 -457
  518. package/dist/test/document-cache.test.js.map +0 -1
  519. package/dist/test/drop.test.d.ts +0 -2
  520. package/dist/test/drop.test.d.ts.map +0 -1
  521. package/dist/test/drop.test.js +0 -86
  522. package/dist/test/drop.test.js.map +0 -1
  523. package/dist/test/getSwitchboardUrl.test.d.ts +0 -2
  524. package/dist/test/getSwitchboardUrl.test.d.ts.map +0 -1
  525. package/dist/test/getSwitchboardUrl.test.js +0 -107
  526. package/dist/test/getSwitchboardUrl.test.js.map +0 -1
  527. package/dist/test/hooks/document-cache.test.d.ts +0 -2
  528. package/dist/test/hooks/document-cache.test.d.ts.map +0 -1
  529. package/dist/test/hooks/document-cache.test.js +0 -642
  530. package/dist/test/hooks/document-cache.test.js.map +0 -1
  531. package/dist/test/reactor.test.d.ts +0 -2
  532. package/dist/test/reactor.test.d.ts.map +0 -1
  533. package/dist/test/reactor.test.js +0 -26
  534. package/dist/test/reactor.test.js.map +0 -1
  535. package/dist/test/switchboard.test.d.ts +0 -2
  536. package/dist/test/switchboard.test.d.ts.map +0 -1
  537. package/dist/test/switchboard.test.js +0 -27
  538. package/dist/test/switchboard.test.js.map +0 -1
  539. package/dist/tsconfig.tsbuildinfo +0 -1
  540. package/dist/vitest.config.d.ts +0 -3
  541. package/dist/vitest.config.d.ts.map +0 -1
  542. package/dist/vitest.config.js +0 -24
  543. package/dist/vitest.config.js.map +0 -1
package/dist/index.js ADDED
@@ -0,0 +1,3249 @@
1
+ import { C as uploadOperations, S as queueOperations, _ as clearGlobal, a as setDocumentCache, b as dispatchActions, c as useDocuments, d as useGetDocuments, f as DocumentCache, g as getAnalyticsStore, h as createAnalyticsStore, i as addDocumentCacheEventHandler, l as useGetDocument, m as readPromiseState, n as useDocumentsByIds, o as useDocument, p as addPromiseState, r as useDispatch, s as useDocumentCache, t as useDocumentById, u as useGetDocumentAsync, v as getGlobal, x as queueActions, y as setGlobal } from "./document-by-id-CDLUqru5.js";
2
+ import { n as GetDocumentWithOperationsDocument, r as PropagationMode, t as createClient } from "./client-DfoxBz8A.js";
3
+ import { t as makePHEventFunctions } from "./make-ph-event-functions-Cr4GqOTT.js";
4
+ import { A as useLoginStatus, C as RENOWN_CHAIN_ID, D as addRenownEventHandler, E as VERIFIABLE_CREDENTIAL_EIP712_TYPE, F as setLoading, I as useLoading, M as useUser, N as addLoadingEventHandler, O as setRenown, P as loading, S as ISSUER_TYPE, T as RENOWN_URL, _ as openRenown, a as RenownAuthButton, b as CREDENTIAL_TYPES, c as ChevronDownIcon, d as RenownLogo, f as SpinnerIcon, g as logout, h as login, i as initRenownCrypto, j as useRenown, k as useDid, l as CopyIcon, m as useRenownAuth, n as useRenownInit, o as RenownUserButton, p as UserIcon, r as initConnectCrypto, s as RenownLoginButton, t as Renown, u as DisconnectIcon, v as CREDENTIAL_SCHEMA_EIP712_TYPE, w as RENOWN_NETWORK_ID, x as DOMAIN_TYPE, y as CREDENTIAL_SUBJECT_TYPE } from "./renown-CV_45Xc1.js";
5
+ import { n as useRelationalQuery, r as useRelationalDb, t as createProcessorQuery } from "./relational-jwreqDwz.js";
6
+ import { documentModelDocumentModelModule, logger } from "document-model";
7
+ import { baseLoadFromInput, baseSaveToFileHandle, createPresignedHeader, createZip, documentModelDocumentType, generateId, replayDocument, setName, validateInitialState, validateModules, validateStateSchemaName } from "@powerhousedao/shared/document-model";
8
+ import { DriveDocumentSchema, addFolder as addFolder$1, copyNode, driveCreateDocument, generateNodesCopy, handleTargetNameCollisions, isFileNode, isFolderNode, moveNode, setAvailableOffline, setSharingType, updateNode } from "@powerhousedao/shared/document-drive";
9
+ import { ChannelScheme, DocumentChangeType, DocumentIntegrityService, DuplicateManifestError, DuplicateModuleError, GqlRequestChannel, InMemoryQueue, IntervalPollTimer, ModuleNotFoundError, PollBehavior, REACTOR_SCHEMA, REACTOR_SCHEMA as REACTOR_SCHEMA$1, ReactorBuilder, ReactorClientBuilder, RelationalDbProcessor, SyncOperationStatus, SyncStatus, driveCollectionId, driveCollectionId as driveCollectionId$1, driveIdFromUrl, parseDriveUrl } from "@powerhousedao/reactor";
10
+ import { filter, forEach, forEachObj, funnel, isIncludedIn, isStrictEqual, isTruthy, map, mapToObj, pipe, prop, unique } from "remeda";
11
+ import { z } from "zod";
12
+ import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
13
+ import slug from "slug";
14
+ import * as lzString from "lz-string";
15
+ //#region src/errors.ts
16
+ var UnsupportedDocumentTypeError = class extends Error {
17
+ constructor(documentType) {
18
+ super(`Document type ${documentType} is not supported`);
19
+ this.name = "UnsupportedDocumentTypeError";
20
+ }
21
+ static isError(error) {
22
+ return Error.isError(error) && error.name === "UnsupportedDocumentTypeError";
23
+ }
24
+ };
25
+ var DocumentModelNotFoundError = class extends Error {
26
+ documentType;
27
+ name = "DocumentModelNotFoundError";
28
+ constructor(documentType) {
29
+ super(`Document model module for type ${documentType} not found`);
30
+ this.documentType = documentType;
31
+ }
32
+ static isError(error) {
33
+ return Error.isError(error) && error.name === "DocumentModelNotFoundError";
34
+ }
35
+ };
36
+ var DocumentTypeMismatchError = class extends Error {
37
+ constructor(documentId, expectedType, actualType) {
38
+ super(`Document ${documentId} is not of type ${expectedType}. Actual type: ${actualType}`);
39
+ }
40
+ };
41
+ var NoSelectedDocumentError = class extends Error {
42
+ constructor() {
43
+ super("There is no selected document. Did you mean to call 'useSelectedDocumentSafe' instead?");
44
+ }
45
+ };
46
+ //#endregion
47
+ //#region src/utils/documents.ts
48
+ function isDocumentTypeSupported(documentType, supportedDocuments) {
49
+ if (!supportedDocuments?.length) return true;
50
+ return supportedDocuments.some((pattern) => {
51
+ if (pattern.endsWith("/*")) {
52
+ const prefix = pattern.slice(0, -2);
53
+ return documentType.startsWith(prefix + "/");
54
+ }
55
+ if (pattern.endsWith("*") && !pattern.endsWith("/*")) {
56
+ const prefix = pattern.slice(0, -1);
57
+ return documentType.startsWith(prefix);
58
+ }
59
+ return pattern === documentType;
60
+ });
61
+ }
62
+ //#endregion
63
+ //#region src/utils/user.ts
64
+ function getUserPermissions() {
65
+ const user = window.ph?.renown?.user;
66
+ const allowList = window.ph?.allowList;
67
+ if (!allowList) return {
68
+ isAllowedToCreateDocuments: true,
69
+ isAllowedToEditDocuments: true
70
+ };
71
+ return {
72
+ isAllowedToCreateDocuments: allowList.includes(user?.address ?? ""),
73
+ isAllowedToEditDocuments: allowList.includes(user?.address ?? "")
74
+ };
75
+ }
76
+ //#endregion
77
+ //#region src/actions/document.ts
78
+ const BASE_STATE_KEYS = new Set(["auth"]);
79
+ const NON_DOMAIN_SCOPES = new Set(["auth", "document"]);
80
+ async function isDocumentInLocation(document, driveId, parentFolder) {
81
+ const reactorClient = window.ph?.reactorClient;
82
+ if (!reactorClient) return { isDuplicate: false };
83
+ let drive;
84
+ try {
85
+ drive = await reactorClient.get(driveId);
86
+ } catch {
87
+ return { isDuplicate: false };
88
+ }
89
+ const nodeById = drive.state.global.nodes.find((node) => node.id === document.header.id);
90
+ if (nodeById && nodeById.parentFolder === (parentFolder ?? null)) return {
91
+ isDuplicate: true,
92
+ duplicateType: "id",
93
+ nodeId: nodeById.id
94
+ };
95
+ const nodeByNameAndType = drive.state.global.nodes.find((node) => isFileNode(node) && node.name === document.header.name && node.documentType === document.header.documentType && node.parentFolder === (parentFolder ?? null));
96
+ if (nodeByNameAndType) return {
97
+ isDuplicate: true,
98
+ duplicateType: "name",
99
+ nodeId: nodeByNameAndType.id
100
+ };
101
+ return { isDuplicate: false };
102
+ }
103
+ function getDocumentTypeIcon(document) {
104
+ switch (document.header.documentType) {
105
+ case "powerhouse/document-model": return "document-model";
106
+ case "powerhouse/app": return "app";
107
+ case "powerhouse/document-editor": return "editor";
108
+ case "powerhouse/subgraph": return "subgraph";
109
+ case "powerhouse/package": return "package";
110
+ case "powerhouse/processor": {
111
+ const processorType = document.state.global?.type;
112
+ if (processorType === "analytics") return "analytics-processor";
113
+ if (processorType === "relational") return "relational-processor";
114
+ if (processorType === "codegen") return "codegen-processor";
115
+ return;
116
+ }
117
+ default: return;
118
+ }
119
+ }
120
+ async function downloadFile(document, fileName) {
121
+ (await createZip(document)).generateAsync({ type: "blob" }).then((blob) => {
122
+ const link = window.document.createElement("a");
123
+ link.style.display = "none";
124
+ link.href = URL.createObjectURL(blob);
125
+ link.download = fileName;
126
+ window.document.body.appendChild(link);
127
+ link.click();
128
+ window.document.body.removeChild(link);
129
+ }).catch(logger.error);
130
+ }
131
+ async function getDocumentExtension(document) {
132
+ const documentType = document.header.documentType;
133
+ let rawExtension;
134
+ if (documentType === documentModelDocumentType) rawExtension = document.state.global?.extension;
135
+ else {
136
+ const reactorClient = window.ph?.reactorClient;
137
+ if (reactorClient) {
138
+ const { results: documentModelModules } = await reactorClient.getDocumentModelModules();
139
+ rawExtension = documentModelModules.find((m) => m.documentModel.global.id === documentType)?.utils.fileExtension;
140
+ }
141
+ }
142
+ return (rawExtension ?? "").replace(/^\.+|\.+$/g, "");
143
+ }
144
+ /**
145
+ * Fetches all operations for a document using cursor-based pagination.
146
+ * The reactor client handles multi-scope cursors transparently via
147
+ * composite cursors, so all scopes are fetched in a single paginated stream.
148
+ */
149
+ async function fetchDocumentOperations(reactorClient, document, pageSize = 100) {
150
+ const scopes = Object.keys(document.state).filter((k) => !BASE_STATE_KEYS.has(k));
151
+ const operations = {};
152
+ for (const scope of scopes) operations[scope] = [];
153
+ let cursor = "";
154
+ do {
155
+ const page = await reactorClient.getOperations(document.header.id, { scopes }, void 0, {
156
+ cursor,
157
+ limit: pageSize
158
+ });
159
+ for (const op of page.results) {
160
+ const scope = op.action.scope ?? "global";
161
+ if (operations[scope]) operations[scope].push(op);
162
+ }
163
+ cursor = page.nextCursor ?? "";
164
+ } while (cursor);
165
+ return operations;
166
+ }
167
+ function extractInitialState(documentScopeOps) {
168
+ const upgradeOp = documentScopeOps.find((op) => op.action.type === "UPGRADE_DOCUMENT");
169
+ if (!upgradeOp) throw new Error("No UPGRADE_DOCUMENT operation found — document is invalid");
170
+ const input = upgradeOp.action.input;
171
+ const initialState = input.initialState ?? input.state;
172
+ if (!initialState) throw new Error("UPGRADE_DOCUMENT operation has no initialState — document is invalid");
173
+ return initialState;
174
+ }
175
+ function filterDomainOperations(operations) {
176
+ return Object.fromEntries(Object.entries(operations).filter(([scope]) => !NON_DOMAIN_SCOPES.has(scope)));
177
+ }
178
+ async function exportFile(document, suggestedName) {
179
+ const reactorClient = window.ph?.reactorClient;
180
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
181
+ const operations = await fetchDocumentOperations(reactorClient, document);
182
+ const initialState = extractInitialState(operations["document"] ?? []);
183
+ const documentWithOps = {
184
+ ...document,
185
+ operations,
186
+ initialState
187
+ };
188
+ const extension = await getDocumentExtension(documentWithOps);
189
+ const baseName = suggestedName || documentWithOps.header.name || "Untitled";
190
+ const name = extension ? `${baseName}.${extension}.phd` : `${baseName}.phd`;
191
+ if (!window.showSaveFilePicker) return await downloadFile(documentWithOps, name);
192
+ try {
193
+ const fileHandle = await window.showSaveFilePicker({ suggestedName: name });
194
+ await baseSaveToFileHandle(documentWithOps, fileHandle);
195
+ return fileHandle;
196
+ } catch (e) {
197
+ if (!(e instanceof DOMException && e.name === "AbortError")) throw e;
198
+ }
199
+ }
200
+ async function loadFile(path) {
201
+ const baseDocument = await baseLoadFromInput(path, (state) => state, { checkHashes: true });
202
+ const reactorClient = window.ph?.reactorClient;
203
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
204
+ const { results: documentModelModules } = await reactorClient.getDocumentModelModules();
205
+ const documentModelModule = documentModelModules.find((module) => module.documentModel.global.id === baseDocument.header.documentType);
206
+ if (!documentModelModule) throw new DocumentModelNotFoundError(baseDocument.header.documentType);
207
+ return documentModelModule.utils.loadFromInput(path);
208
+ }
209
+ async function addDocument(driveId, name, documentType, parentFolder, document, id, preferredEditor) {
210
+ const { isAllowedToCreateDocuments } = getUserPermissions();
211
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to create documents");
212
+ const reactorClient = window.ph?.reactorClient;
213
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
214
+ const documentModelModule = await reactorClient.getDocumentModelModule(documentType);
215
+ const newDocument = document ?? documentModelModule.utils.createDocument();
216
+ newDocument.header.name = name;
217
+ if (preferredEditor) newDocument.header.meta = {
218
+ ...newDocument.header.meta,
219
+ preferredEditor
220
+ };
221
+ let newDoc;
222
+ try {
223
+ newDoc = await reactorClient.drives.addFile(driveId, newDocument, parentFolder);
224
+ } catch (e) {
225
+ logger.error("Error adding document", e);
226
+ throw new Error("There was an error adding document");
227
+ }
228
+ return {
229
+ id: newDoc.header.id,
230
+ name: newDoc.header.name,
231
+ documentType,
232
+ parentFolder: parentFolder ?? null,
233
+ kind: "file"
234
+ };
235
+ }
236
+ async function addFile(file, driveId, name, parentFolder) {
237
+ logger.verbose(`addFile(drive: ${driveId}, name: ${name}, folder: ${parentFolder})`);
238
+ const { isAllowedToCreateDocuments } = getUserPermissions();
239
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to create files");
240
+ const document = await loadFile(file);
241
+ let duplicateId = false;
242
+ const reactorClient = window.ph?.reactorClient;
243
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
244
+ try {
245
+ await reactorClient.get(document.header.id);
246
+ duplicateId = true;
247
+ } catch {}
248
+ const documentId = duplicateId ? generateId() : document.header.id;
249
+ const header = createPresignedHeader(documentId, document.header.documentType);
250
+ header.lastModifiedAtUtcIso = document.header.createdAtUtcIso;
251
+ header.meta = document.header.meta;
252
+ header.name = name || document.header.name;
253
+ const initialDocument = {
254
+ ...document,
255
+ header,
256
+ state: document.initialState,
257
+ operations: Object.keys(document.operations).reduce((acc, key) => {
258
+ acc[key] = [];
259
+ return acc;
260
+ }, {})
261
+ };
262
+ await addDocument(driveId, name || document.header.name, document.header.documentType, parentFolder, initialDocument, documentId, document.header.meta?.preferredEditor);
263
+ await uploadOperations(documentId, filterDomainOperations(document.operations), queueOperations);
264
+ }
265
+ async function addFileWithProgress(file, driveId, name, parentFolder, onProgress, documentTypes, resolveConflict) {
266
+ logger.verbose(`addFileWithProgress(drive: ${driveId}, name: ${name}, folder: ${parentFolder})`);
267
+ const reactor = window.ph?.reactorClient;
268
+ if (!reactor) return;
269
+ const { isAllowedToCreateDocuments } = getUserPermissions();
270
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to create files");
271
+ try {
272
+ onProgress?.({
273
+ stage: "loading",
274
+ progress: 0
275
+ });
276
+ let document;
277
+ try {
278
+ document = await loadFile(file);
279
+ } catch (loadError) {
280
+ const discoveryService = window.ph?.packageDiscoveryService;
281
+ if (discoveryService && DocumentModelNotFoundError.isError(loadError)) {
282
+ retryAfterDiscovery(discoveryService, loadError.documentType, file, driveId, name, parentFolder, onProgress, documentTypes, resolveConflict);
283
+ return;
284
+ }
285
+ throw loadError;
286
+ }
287
+ const duplicateCheck = await isDocumentInLocation(document, driveId, parentFolder);
288
+ if (duplicateCheck.isDuplicate && !resolveConflict) {
289
+ onProgress?.({
290
+ stage: "conflict",
291
+ progress: 0,
292
+ duplicateType: duplicateCheck.duplicateType
293
+ });
294
+ return;
295
+ }
296
+ if (duplicateCheck.isDuplicate && resolveConflict === "replace" && duplicateCheck.nodeId) await deleteNode(driveId, duplicateCheck.nodeId);
297
+ const documentType = getDocumentTypeIcon(document);
298
+ if (documentType) onProgress?.({
299
+ stage: "loading",
300
+ progress: 10,
301
+ documentType
302
+ });
303
+ else onProgress?.({
304
+ stage: "loading",
305
+ progress: 10
306
+ });
307
+ if (!isDocumentTypeSupported(document.header.documentType, documentTypes)) {
308
+ onProgress?.({
309
+ stage: "unsupported-document-type",
310
+ progress: 100,
311
+ error: `Document type ${document.header.documentType} is not supported`
312
+ });
313
+ throw new UnsupportedDocumentTypeError(document.header.documentType);
314
+ }
315
+ await reactor.getDocumentModelModule(document.header.documentType);
316
+ onProgress?.({
317
+ stage: "initializing",
318
+ progress: 10
319
+ });
320
+ let duplicateId = false;
321
+ try {
322
+ await reactor.get(document.header.id);
323
+ duplicateId = true;
324
+ } catch {}
325
+ const documentId = duplicateId ? generateId() : document.header.id;
326
+ const header = createPresignedHeader(documentId, document.header.documentType);
327
+ header.lastModifiedAtUtcIso = document.header.createdAtUtcIso;
328
+ header.meta = document.header.meta;
329
+ header.name = name || document.header.name;
330
+ const initialDocument = {
331
+ ...document,
332
+ header,
333
+ state: document.initialState,
334
+ operations: Object.keys(document.operations).reduce((acc, key) => {
335
+ acc[key] = [];
336
+ return acc;
337
+ }, {})
338
+ };
339
+ const fileNode = await addDocument(driveId, name || document.header.name, document.header.documentType, parentFolder, initialDocument, documentId, document.header.meta?.preferredEditor);
340
+ if (!fileNode) throw new Error("There was an error adding file");
341
+ onProgress?.({
342
+ stage: "initializing",
343
+ progress: 20
344
+ });
345
+ await reactor.get(documentId);
346
+ console.log("Document created, starting upload of operations");
347
+ await uploadOperations(documentId, filterDomainOperations(document.operations), queueOperations, { onProgress: (uploadProgress) => {
348
+ if (uploadProgress.totalOperations && uploadProgress.uploadedOperations !== void 0) {
349
+ const uploadPercent = uploadProgress.totalOperations > 0 ? uploadProgress.uploadedOperations / uploadProgress.totalOperations : 0;
350
+ const overallProgress = 20 + Math.round(uploadPercent * 80);
351
+ onProgress?.({
352
+ stage: "uploading",
353
+ progress: overallProgress,
354
+ totalOperations: uploadProgress.totalOperations,
355
+ uploadedOperations: uploadProgress.uploadedOperations
356
+ });
357
+ }
358
+ } });
359
+ onProgress?.({
360
+ stage: "complete",
361
+ progress: 100,
362
+ fileNode
363
+ });
364
+ return fileNode;
365
+ } catch (error) {
366
+ if (!UnsupportedDocumentTypeError.isError(error)) {
367
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
368
+ onProgress?.({
369
+ stage: "failed",
370
+ progress: 100,
371
+ error: errorMessage
372
+ });
373
+ }
374
+ throw error;
375
+ }
376
+ }
377
+ async function retryAfterDiscovery(discoveryService, documentType, file, driveId, name, parentFolder, onProgress, documentTypes, resolveConflict) {
378
+ if (!discoveryService) return;
379
+ try {
380
+ await discoveryService.load(documentType);
381
+ } catch {
382
+ onProgress?.({
383
+ stage: "unsupported-document-type",
384
+ progress: 100,
385
+ error: `Document type ${documentType} is not supported`
386
+ });
387
+ return;
388
+ }
389
+ await addFileWithProgress(file, driveId, name, parentFolder, onProgress, documentTypes, resolveConflict);
390
+ }
391
+ async function addFolder(driveId, name, parentFolder) {
392
+ const { isAllowedToCreateDocuments } = getUserPermissions();
393
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to create folders");
394
+ const reactorClient = window.ph?.reactorClient;
395
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
396
+ await reactorClient.get(driveId);
397
+ const folderId = generateId();
398
+ const node = (await reactorClient.execute(driveId, "main", [addFolder$1({
399
+ id: folderId,
400
+ name,
401
+ parentFolder
402
+ })])).state.global.nodes.find((node) => node.id === folderId);
403
+ if (!node || !isFolderNode(node)) throw new Error("There was an error adding folder");
404
+ return node;
405
+ }
406
+ async function deleteNode(driveId, nodeId) {
407
+ const { isAllowedToCreateDocuments } = getUserPermissions();
408
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to delete documents");
409
+ const reactorClient = window.ph?.reactorClient;
410
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
411
+ await reactorClient.drives.removeNode(driveId, nodeId);
412
+ }
413
+ async function renameNode(driveId, nodeId, name) {
414
+ const { isAllowedToCreateDocuments } = getUserPermissions();
415
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to rename documents");
416
+ const reactorClient = window.ph?.reactorClient;
417
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
418
+ if ((await reactorClient.execute(nodeId, "main", [setName({ name })])).header.name !== name) throw new Error("There was an error renaming the node");
419
+ const node = (await reactorClient.execute(driveId, "main", [updateNode({
420
+ id: nodeId,
421
+ name
422
+ })])).state.global.nodes.find((n) => n.id === nodeId);
423
+ if (!node) throw new Error("There was an error renaming node in the drive");
424
+ return node;
425
+ }
426
+ async function renameDriveNode(driveId, nodeId, name) {
427
+ const { isAllowedToCreateDocuments } = getUserPermissions();
428
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to rename documents");
429
+ const reactorClient = window.ph?.reactorClient;
430
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
431
+ if ((await reactorClient.execute(nodeId, "main", [setName({ name })])).header.name !== name) throw new Error("There was an error renaming the node");
432
+ await reactorClient.execute(driveId, "main", [updateNode({
433
+ id: nodeId,
434
+ name
435
+ })]);
436
+ return (await reactorClient.get(driveId)).state.global.nodes.find((n) => n.id === nodeId);
437
+ }
438
+ async function moveNode$1(driveId, src, target) {
439
+ const { isAllowedToCreateDocuments } = getUserPermissions();
440
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to move documents");
441
+ const reactorClient = window.ph?.reactorClient;
442
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
443
+ return await reactorClient.execute(driveId, "main", [moveNode({
444
+ srcFolder: src.id,
445
+ targetParentFolder: target?.id
446
+ })]);
447
+ }
448
+ async function _duplicateDocument(reactor, document, newId = generateId()) {
449
+ const documentModule = await reactor.getDocumentModelModule(document.header.documentType);
450
+ return replayDocument(document.initialState, document.operations, documentModule.reducer, createPresignedHeader(newId, document.header.documentType));
451
+ }
452
+ async function copyNode$1(driveId, src, target) {
453
+ const reactor = window.ph?.reactorClient;
454
+ if (!reactor) return;
455
+ const { isAllowedToCreateDocuments } = getUserPermissions();
456
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to copy documents");
457
+ const drive = await reactor.get(driveId);
458
+ const copyNodesInput = generateNodesCopy({
459
+ srcId: src.id,
460
+ targetParentFolder: target?.id,
461
+ targetName: src.name
462
+ }, () => generateId(), drive.state.global.nodes);
463
+ const resolvedNamesMap = /* @__PURE__ */ new Map();
464
+ for (const copyNodeInput of copyNodesInput) {
465
+ const node = drive.state.global.nodes.find((n) => n.id === copyNodeInput.srcId);
466
+ if (node) {
467
+ const resolvedName = handleTargetNameCollisions({
468
+ nodes: drive.state.global.nodes,
469
+ srcName: copyNodeInput.targetName || node.name,
470
+ srcKind: isFileNode(node) ? "file" : "folder",
471
+ targetParentFolder: copyNodeInput.targetParentFolder || null
472
+ });
473
+ resolvedNamesMap.set(copyNodeInput.targetId, resolvedName);
474
+ }
475
+ }
476
+ const fileNodesToCopy = copyNodesInput.filter((copyNodeInput) => {
477
+ const node = drive.state.global.nodes.find((node) => node.id === copyNodeInput.srcId);
478
+ return node !== void 0 && isFileNode(node);
479
+ });
480
+ for (const fileNodeToCopy of fileNodesToCopy) try {
481
+ const duplicatedDocument = await _duplicateDocument(reactor, await reactor.get(fileNodeToCopy.srcId), fileNodeToCopy.targetId);
482
+ const resolvedName = resolvedNamesMap.get(fileNodeToCopy.targetId);
483
+ if (resolvedName) duplicatedDocument.header.name = resolvedName;
484
+ await reactor.drives.addFile(driveId, duplicatedDocument, target?.id);
485
+ } catch (e) {
486
+ logger.error(`Error copying document ${fileNodeToCopy.srcId}: ${String(e)}`);
487
+ }
488
+ return await queueActions(drive, copyNodesInput.map((copyNodeInput) => copyNode(copyNodeInput)));
489
+ }
490
+ //#endregion
491
+ //#region src/actions/drive.ts
492
+ async function addDrive(input, preferredEditor) {
493
+ const { isAllowedToCreateDocuments } = getUserPermissions();
494
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to create drives");
495
+ const reactorClient = window.ph?.reactorClient;
496
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
497
+ const driveDoc = driveCreateDocument({ global: {
498
+ name: input.global.name || "",
499
+ icon: input.global.icon ?? null,
500
+ nodes: []
501
+ } });
502
+ if (preferredEditor) driveDoc.header.meta = { preferredEditor };
503
+ return await reactorClient.create(driveDoc);
504
+ }
505
+ async function addRemoteDrive(url, driveId, options) {
506
+ if (!window.ph?.reactorClient) throw new Error("ReactorClient not initialized");
507
+ const sync = window.ph?.reactorClientModule?.reactorModule?.syncModule?.syncManager;
508
+ if (!sync) throw new Error("Sync not initialized");
509
+ const response = await fetch(url);
510
+ if (!response.ok) throw new Error(`Failed to resolve drive info from ${url}`);
511
+ const driveInfo = await response.json();
512
+ const resolvedDriveId = driveId ?? driveInfo.id;
513
+ const collectionId = driveCollectionId$1("main", resolvedDriveId);
514
+ if (sync.list().find((remote) => remote.collectionId === collectionId)) return resolvedDriveId;
515
+ const remoteName = crypto.randomUUID();
516
+ await sync.add(remoteName, collectionId, {
517
+ type: "gql",
518
+ parameters: { url: driveInfo.graphqlEndpoint }
519
+ }, void 0, options?.pollBehavior ? { pollBehavior: options.pollBehavior } : void 0);
520
+ return resolvedDriveId;
521
+ }
522
+ async function deleteDrive(driveId) {
523
+ const { isAllowedToCreateDocuments } = getUserPermissions();
524
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to delete drives");
525
+ const reactorClient = window.ph?.reactorClient;
526
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
527
+ await reactorClient.deleteDocument(driveId);
528
+ }
529
+ async function renameDrive(driveId, name) {
530
+ const { isAllowedToCreateDocuments } = getUserPermissions();
531
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to rename drives");
532
+ const reactorClient = window.ph?.reactorClient;
533
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
534
+ return await reactorClient.rename(driveId, name);
535
+ }
536
+ async function setDriveAvailableOffline(driveId, availableOffline) {
537
+ const { isAllowedToCreateDocuments } = getUserPermissions();
538
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to change drive availability");
539
+ const reactorClient = window.ph?.reactorClient;
540
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
541
+ return await reactorClient.execute(driveId, "main", [setAvailableOffline({ availableOffline })]);
542
+ }
543
+ async function setDriveSharingType(driveId, sharingType) {
544
+ const { isAllowedToCreateDocuments } = getUserPermissions();
545
+ if (!isAllowedToCreateDocuments) throw new Error("User is not allowed to change drive sharing type");
546
+ const reactorClient = window.ph?.reactorClient;
547
+ if (!reactorClient) throw new Error("ReactorClient not initialized");
548
+ return await reactorClient.execute(driveId, "main", [setSharingType({ type: sharingType })]);
549
+ }
550
+ //#endregion
551
+ //#region src/constants.ts
552
+ const DEFAULT_DRIVE_EDITOR_ID = "powerhouse/generic-drive-explorer";
553
+ const COMMON_PACKAGE_ID = "powerhouse/common";
554
+ //#endregion
555
+ //#region src/document-model.ts
556
+ const baseDocumentModelsMap = { DocumentModel: documentModelDocumentModelModule };
557
+ const baseDocumentModels = Object.values(baseDocumentModelsMap);
558
+ //#endregion
559
+ //#region src/graphql/adapters.ts
560
+ function phDocumentFromQuery(document, documentSchema) {
561
+ const phDocument = {
562
+ header: phDocumentHeaderFromQuery(document),
563
+ state: phDocumentStateFromQuery(document),
564
+ initialState: phDocumentStateFromQuery(document),
565
+ operations: phDocumentOperationsFromGetDocumentWithOperationsQuery(document),
566
+ clipboard: []
567
+ };
568
+ if (documentSchema !== void 0) documentSchema.parse(phDocument);
569
+ return phDocument;
570
+ }
571
+ function phDocumentsFromQuery(items, documentSchema) {
572
+ return pipe(items, map((document) => phDocumentFromQuery(document, documentSchema)));
573
+ }
574
+ function phDocumentHeaderFromQuery(queryDocument) {
575
+ return {
576
+ branch: "main",
577
+ id: queryDocument.id,
578
+ name: queryDocument.name,
579
+ documentType: queryDocument.documentType,
580
+ createdAtUtcIso: queryDocument.createdAtUtcIso instanceof Date ? queryDocument.createdAtUtcIso.toUTCString() : queryDocument.createdAtUtcIso,
581
+ lastModifiedAtUtcIso: queryDocument.lastModifiedAtUtcIso instanceof Date ? queryDocument.lastModifiedAtUtcIso.toUTCString() : queryDocument.lastModifiedAtUtcIso,
582
+ slug: queryDocument.slug ?? ""
583
+ };
584
+ }
585
+ function phDocumentStateFromQuery(queryDocument, documentSchema) {
586
+ if (documentSchema !== void 0) return documentSchema.shape.state.parse(queryDocument.state);
587
+ return queryDocument.state;
588
+ }
589
+ function phDocumentOperationsFromGetDocumentWithOperationsQuery(queryDocument) {
590
+ if (queryDocument.operations === null || queryDocument.operations === void 0) return { global: [] };
591
+ return { global: [...queryDocument.operations.items] };
592
+ }
593
+ function identifierFromMutateDocumentOperationVariables(variables) {
594
+ return z.object({ documentIdentifier: z.string() }).parse(variables).documentIdentifier;
595
+ }
596
+ //#endregion
597
+ //#region src/graphql/constants.ts
598
+ const DEFAULT_DRIVE_ID = "powerhouse";
599
+ const DEFAULT_SWITCHBOARD_URL = "http://localhost:4001/graphql";
600
+ const graphqlEventsToSyncDrive = [
601
+ "CreateEmptyDocument",
602
+ "CreateDocument",
603
+ "AddChildren",
604
+ "RemoveChildren",
605
+ "MoveChildren",
606
+ "DeleteDocument",
607
+ "DeleteDocuments"
608
+ ];
609
+ const graphqlDocumentEvents = [
610
+ "MutateDocument",
611
+ "MutateDocumentAsync",
612
+ "DeleteDocument"
613
+ ];
614
+ const graphqlDocumentsEvents = ["DeleteDocuments"];
615
+ //#endregion
616
+ //#region src/graphql/fetchers.ts
617
+ async function reactorGraphqlFetchDocument(identifier, documentSchema) {
618
+ const client = window.ph?.reactorGraphQLClient;
619
+ if (!client) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
620
+ try {
621
+ const document = (await client.GetDocument({ identifier })).document?.document;
622
+ if (!document) return void 0;
623
+ return phDocumentFromQuery(document, documentSchema);
624
+ } catch (error) {
625
+ return;
626
+ }
627
+ }
628
+ async function reactorGraphqlBatchFetchDocuments(identifiers) {
629
+ if (!window.ph?.reactorGraphQLClient) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
630
+ const promises = map(identifiers, (identifier) => reactorGraphqlFetchDocument(identifier));
631
+ return await Promise.all(promises);
632
+ }
633
+ //#endregion
634
+ //#region src/graphql/batch.ts
635
+ /**
636
+ * A reference implementation for an async batching utility function built on
637
+ * top of the `funnel` general purpose execution utility function. It will
638
+ * accumulate all params passed to an async `call` method within the defined
639
+ * burst duration and then use an async executor to process them in one
640
+ * invocation. It then extracts an individual result for each call which is
641
+ * used to resolve the original call.
642
+ *
643
+ * This allows synchronizing multiple async calls while keeping each call site
644
+ * isolated from the rest (for example, as react components).
645
+ *
646
+ * This reference implementation can be copied into your project as-is, or you
647
+ * can use it as the basis for a more complex implementation with additional
648
+ * features.
649
+ *
650
+ * @param callback - The main function that takes a batch and returns an
651
+ * aggregated response. The typing for the it's parameters will derive the
652
+ * typing for the extractor and the `call` method.
653
+ * @param extractor - A function that takes the aggregated response and extracts
654
+ * from it the result for each individual call. The function is called with both
655
+ * the index in the batch, and the params passed to the `call` method. This
656
+ * allows handling APIs that return batch results as both objects and arrays.
657
+ * @param maxBurstDurationMs - The period of time where the batcher would
658
+ * collect params before triggering the executor. When set to 0 the batcher
659
+ * does not incur any additional delays to the execution and would trigger at
660
+ * the next tick, just like a regular async function would. This is also the
661
+ * default value.
662
+ * @returns A Funnel object with the `call` method augmented to support async
663
+ * response.
664
+ */
665
+ function batch(callback, extractor, maxBurstDurationMs = 0) {
666
+ const batchFunnel = funnel((requests) => {
667
+ callback(requests.map(({ params }) => params)).then((response) => {
668
+ for (const [index, { params, promiseCallbacks: [resolve, reject] }] of requests.entries()) try {
669
+ resolve(extractor(response, index, ...params));
670
+ } catch (error) {
671
+ reject(error);
672
+ }
673
+ }).catch((error) => {
674
+ for (const { promiseCallbacks: [, reject] } of requests) reject(error);
675
+ });
676
+ }, {
677
+ reducer: (requests, request) => [...requests ?? [], request],
678
+ maxBurstDurationMs,
679
+ triggerAt: "end"
680
+ });
681
+ return {
682
+ ...batchFunnel,
683
+ call: (...params) => new Promise((...promiseCallbacks) => {
684
+ batchFunnel.call({
685
+ promiseCallbacks,
686
+ params
687
+ });
688
+ })
689
+ };
690
+ }
691
+ //#endregion
692
+ //#region src/graphql/document-fetcher.ts
693
+ function makeDocumentsById(documents = []) {
694
+ return pipe(documents, filter(isTruthy), mapToObj((document) => [document.header.id, document]));
695
+ }
696
+ var DocumentFetcher = class {
697
+ batchGetDocuments;
698
+ constructor() {
699
+ this.batchGetDocuments = batch(async (requests) => {
700
+ return makeDocumentsById(await reactorGraphqlBatchFetchDocuments(unique(map(requests, ([id]) => id))));
701
+ }, (documentsById, _, id) => {
702
+ return prop(documentsById, id);
703
+ });
704
+ }
705
+ get(id) {
706
+ return this.batchGetDocuments.call(id);
707
+ }
708
+ getBatch(ids) {
709
+ return Promise.all(map(ids, (id) => this.get(id)));
710
+ }
711
+ };
712
+ //#endregion
713
+ //#region src/graphql/graphql-client-document-cache.ts
714
+ var GraphQLClientDocumentCache = class {
715
+ fetcher;
716
+ documents = /* @__PURE__ */ new Map();
717
+ batchPromises = /* @__PURE__ */ new Map();
718
+ listeners = /* @__PURE__ */ new Map();
719
+ constructor() {
720
+ this.fetcher = new DocumentFetcher();
721
+ window.addEventListener("MutateDocument", (event) => {
722
+ this.handleDocumentMutated(event.detail.identifier).catch(console.error);
723
+ });
724
+ window.addEventListener("MutateDocumentAsync", (event) => {
725
+ this.handleDocumentMutated(event.detail.identifier).catch(console.error);
726
+ });
727
+ }
728
+ get(id, refetch) {
729
+ const current = this.documents.get(id);
730
+ if (current) {
731
+ if (current.status === "pending") return current;
732
+ if (!refetch) return current;
733
+ }
734
+ const promise = addPromiseState(this.fetcher.get(id).then((document) => {
735
+ this.invalidateBatchesContaining(id);
736
+ return document;
737
+ }));
738
+ this.documents.set(id, promise);
739
+ return promise;
740
+ }
741
+ getBatch(ids) {
742
+ const key = ids.join(",");
743
+ const cached = this.batchPromises.get(key);
744
+ const currentPromises = ids.map((id) => this.get(id));
745
+ if (cached) {
746
+ if (currentPromises.every((promise, index) => promise === cached.promises[index])) return cached.promise;
747
+ }
748
+ const states = currentPromises.map((promise) => readPromiseState(promise));
749
+ if (states.every((state) => state.status === "fulfilled")) {
750
+ const values = states.map((state) => state.value);
751
+ const batchPromise = Promise.resolve(values);
752
+ batchPromise.status = "fulfilled";
753
+ batchPromise.value = values;
754
+ this.batchPromises.set(key, {
755
+ promises: currentPromises,
756
+ promise: batchPromise
757
+ });
758
+ return batchPromise;
759
+ }
760
+ const batchPromise = addPromiseState(Promise.all(currentPromises));
761
+ this.batchPromises.set(key, {
762
+ promises: currentPromises,
763
+ promise: batchPromise
764
+ });
765
+ return batchPromise;
766
+ }
767
+ invalidateBatchesContaining(documentId) {
768
+ for (const key of this.batchPromises.keys()) if (key.split(",").includes(documentId)) this.batchPromises.delete(key);
769
+ }
770
+ subscribe(id, callback) {
771
+ const ids = Array.isArray(id) ? id : [id];
772
+ for (const documentId of ids) {
773
+ const listeners = this.listeners.get(documentId) ?? [];
774
+ this.listeners.set(documentId, [...listeners, callback]);
775
+ }
776
+ return () => {
777
+ for (const documentId of ids) {
778
+ const listeners = this.listeners.get(documentId) ?? [];
779
+ this.listeners.set(documentId, listeners.filter((listener) => listener !== callback));
780
+ }
781
+ };
782
+ }
783
+ notify(id) {
784
+ const listeners = this.listeners.get(id) ?? [];
785
+ for (const listener of listeners) listener();
786
+ }
787
+ async handleDocumentMutated(id) {
788
+ this.invalidateBatchesContaining(id);
789
+ await this.get(id);
790
+ this.notify(id);
791
+ }
792
+ handleDocumentDeleted(id) {
793
+ this.documents.delete(id);
794
+ this.invalidateBatchesContaining(id);
795
+ this.notify(id);
796
+ }
797
+ handleDocumentsDeleted(ids) {
798
+ forEach(ids, (id) => this.handleDocumentDeleted(id));
799
+ }
800
+ };
801
+ //#endregion
802
+ //#region src/graphql/mutators.ts
803
+ async function reactorGraphqlCreateDocument(document, parentIdentifier = DEFAULT_DRIVE_ID) {
804
+ const client = window.ph?.reactorGraphQLClient;
805
+ if (!client) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
806
+ return await client.CreateDocument({
807
+ document,
808
+ parentIdentifier
809
+ });
810
+ }
811
+ async function reactorGraphqlDeleteDocument(identifier) {
812
+ const client = window.ph?.reactorGraphQLClient;
813
+ if (!client) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
814
+ return await client.DeleteDocument({ identifier });
815
+ }
816
+ async function reactorGraphqlDeleteDocuments(identifiers) {
817
+ const client = window.ph?.reactorGraphQLClient;
818
+ if (!client) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
819
+ return await client.DeleteDocuments({ identifiers });
820
+ }
821
+ async function reactorGraphqlMutateDocument(documentIdentifier, ...actions) {
822
+ const client = window.ph?.reactorGraphQLClient;
823
+ if (!client) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
824
+ return await client.MutateDocument({
825
+ documentIdentifier,
826
+ actions
827
+ });
828
+ }
829
+ //#endregion
830
+ //#region src/hooks/config/editor.ts
831
+ const isExternalControlsEnabledEventFunctions = makePHEventFunctions("isExternalControlsEnabled");
832
+ /** Sets whether external controls are enabled for a given editor. */
833
+ const setIsExternalControlsEnabled = isExternalControlsEnabledEventFunctions.setValue;
834
+ /** Gets whether external controls are enabled for a given editor. */
835
+ const useIsExternalControlsEnabled = isExternalControlsEnabledEventFunctions.useValue;
836
+ /** Adds an event handler for when the external controls enabled state changes. */
837
+ const addIsExternalControlsEnabledEventHandler = isExternalControlsEnabledEventFunctions.addEventHandler;
838
+ const isDragAndDropEnabledEventFunctions = makePHEventFunctions("isDragAndDropEnabled");
839
+ /** Sets whether drag and drop is enabled for a given app. */
840
+ const setIsDragAndDropEnabled = isDragAndDropEnabledEventFunctions.setValue;
841
+ /** Gets whether drag and drop is enabled for a given app. */
842
+ const useIsDragAndDropEnabled = isDragAndDropEnabledEventFunctions.useValue;
843
+ /** Adds an event handler for when the drag and drop enabled state changes. */
844
+ const addIsDragAndDropEnabledEventHandler = isDragAndDropEnabledEventFunctions.addEventHandler;
845
+ const allowedDocumentTypesEventFunctions = makePHEventFunctions("allowedDocumentTypes");
846
+ /** Sets the allowed document types for a given app. */
847
+ const setAllowedDocumentTypes = allowedDocumentTypesEventFunctions.setValue;
848
+ /** Defines the document types a drive supports.
849
+ *
850
+ * Defaults to all of the document types registered in the reactor.
851
+ */
852
+ function useAllowedDocumentTypes() {
853
+ return allowedDocumentTypesEventFunctions.useValue();
854
+ }
855
+ /** Adds an event handler for when the allowed document types for a given app changes. */
856
+ const addAllowedDocumentTypesEventHandler = allowedDocumentTypesEventFunctions.addEventHandler;
857
+ const phAppConfigSetters = {
858
+ allowedDocumentTypes: setAllowedDocumentTypes,
859
+ isDragAndDropEnabled: setIsDragAndDropEnabled
860
+ };
861
+ const phDocumentEditorConfigSetters = { isExternalControlsEnabled: setIsExternalControlsEnabled };
862
+ const phAppConfigHooks = {
863
+ allowedDocumentTypes: useAllowedDocumentTypes,
864
+ isDragAndDropEnabled: useIsDragAndDropEnabled
865
+ };
866
+ const phDocumentEditorConfigHooks = { isExternalControlsEnabled: useIsExternalControlsEnabled };
867
+ //#endregion
868
+ //#region src/hooks/config/connect.ts
869
+ const { useValue: useRouterBasename, setValue: setRouterBasename, addEventHandler: addRouterBasenameEventHandler } = makePHEventFunctions("routerBasename");
870
+ const { useValue: useVersion, setValue: setVersion, addEventHandler: addVersionEventHandler } = makePHEventFunctions("version");
871
+ const { useValue: useRequiresHardRefresh, setValue: setRequiresHardRefresh, addEventHandler: addRequiresHardRefreshEventHandler } = makePHEventFunctions("requiresHardRefresh");
872
+ const { useValue: useWarnOutdatedApp, setValue: setWarnOutdatedApp, addEventHandler: addWarnOutdatedAppEventHandler } = makePHEventFunctions("warnOutdatedApp");
873
+ const { useValue: useStudioMode, setValue: setStudioMode, addEventHandler: addStudioModeEventHandler } = makePHEventFunctions("studioMode");
874
+ const { useValue: useBasePath, setValue: setBasePath, addEventHandler: addBasePathEventHandler } = makePHEventFunctions("basePath");
875
+ const { useValue: useVersionCheckInterval, setValue: setVersionCheckInterval, addEventHandler: addVersionCheckIntervalEventHandler } = makePHEventFunctions("versionCheckInterval");
876
+ const { useValue: useCliVersion, setValue: setCliVersion, addEventHandler: addCliVersionEventHandler } = makePHEventFunctions("cliVersion");
877
+ const { useValue: useFileUploadOperationsChunkSize, setValue: setFileUploadOperationsChunkSize, addEventHandler: addFileUploadOperationsChunkSizeEventHandler } = makePHEventFunctions("fileUploadOperationsChunkSize");
878
+ const { useValue: useIsDocumentModelSelectionSettingsEnabled, setValue: setIsDocumentModelSelectionSettingsEnabled, addEventHandler: addIsDocumentModelSelectionSettingsEnabledEventHandler } = makePHEventFunctions("isDocumentModelSelectionSettingsEnabled");
879
+ const { useValue: useGaTrackingId, setValue: setGaTrackingId, addEventHandler: addGaTrackingIdEventHandler } = makePHEventFunctions("gaTrackingId");
880
+ const { useValue: useDefaultDrivesUrl, setValue: setDefaultDrivesUrl, addEventHandler: addDefaultDrivesUrlEventHandler } = makePHEventFunctions("defaultDrivesUrl");
881
+ const { useValue: useDrivesPreserveStrategy, setValue: setDrivesPreserveStrategy, addEventHandler: addDrivesPreserveStrategyEventHandler } = makePHEventFunctions("drivesPreserveStrategy");
882
+ const { useValue: useIsLocalDrivesEnabled, setValue: setIsLocalDrivesEnabled, addEventHandler: addIsLocalDrivesEnabledEventHandler } = makePHEventFunctions("isLocalDrivesEnabled");
883
+ const { useValue: useIsAddDriveEnabled, setValue: setIsAddDriveEnabled, addEventHandler: addIsAddDriveEnabledEventHandler } = makePHEventFunctions("isAddDriveEnabled");
884
+ const { useValue: useIsPublicDrivesEnabled, setValue: setIsPublicDrivesEnabled, addEventHandler: addIsPublicDrivesEnabledEventHandler } = makePHEventFunctions("isPublicDrivesEnabled");
885
+ const { useValue: useIsAddPublicDrivesEnabled, setValue: setIsAddPublicDrivesEnabled, addEventHandler: addIsAddPublicDrivesEnabledEventHandler } = makePHEventFunctions("isAddPublicDrivesEnabled");
886
+ const { useValue: useIsDeletePublicDrivesEnabled, setValue: setIsDeletePublicDrivesEnabled, addEventHandler: addIsDeletePublicDrivesEnabledEventHandler } = makePHEventFunctions("isDeletePublicDrivesEnabled");
887
+ const { useValue: useIsCloudDrivesEnabled, setValue: setIsCloudDrivesEnabled, addEventHandler: addIsCloudDrivesEnabledEventHandler } = makePHEventFunctions("isCloudDrivesEnabled");
888
+ const { useValue: useIsAddCloudDrivesEnabled, setValue: setIsAddCloudDrivesEnabled, addEventHandler: addIsAddCloudDrivesEnabledEventHandler } = makePHEventFunctions("isAddCloudDrivesEnabled");
889
+ const { useValue: useIsDeleteCloudDrivesEnabled, setValue: setIsDeleteCloudDrivesEnabled, addEventHandler: addIsDeleteCloudDrivesEnabledEventHandler } = makePHEventFunctions("isDeleteCloudDrivesEnabled");
890
+ const { useValue: useLocalDrivesEnabled, setValue: setLocalDrivesEnabled, addEventHandler: addLocalDrivesEnabledEventHandler } = makePHEventFunctions("isLocalDrivesEnabled");
891
+ const { useValue: useIsAddLocalDrivesEnabled, setValue: setIsAddLocalDrivesEnabled, addEventHandler: addIsAddLocalDrivesEnabledEventHandler } = makePHEventFunctions("isAddLocalDrivesEnabled");
892
+ const { useValue: useIsDeleteLocalDrivesEnabled, setValue: setIsDeleteLocalDrivesEnabled, addEventHandler: addIsDeleteLocalDrivesEnabledEventHandler } = makePHEventFunctions("isDeleteLocalDrivesEnabled");
893
+ const { useValue: useIsEditorDebugModeEnabled, setValue: setIsEditorDebugModeEnabled, addEventHandler: addIsEditorDebugModeEnabledEventHandler } = makePHEventFunctions("isEditorDebugModeEnabled");
894
+ const { useValue: useIsEditorReadModeEnabled, setValue: setIsEditorReadModeEnabled, addEventHandler: addIsEditorReadModeEnabledEventHandler } = makePHEventFunctions("isEditorReadModeEnabled");
895
+ const { useValue: useIsAnalyticsDatabaseWorkerEnabled, setValue: setIsAnalyticsDatabaseWorkerEnabled, addEventHandler: addIsAnalyticsDatabaseWorkerEnabledEventHandler } = makePHEventFunctions("isAnalyticsDatabaseWorkerEnabled");
896
+ const { useValue: useIsDiffAnalyticsEnabled, setValue: setIsDiffAnalyticsEnabled, addEventHandler: addIsDiffAnalyticsEnabledEventHandler } = makePHEventFunctions("isDiffAnalyticsEnabled");
897
+ const { useValue: useIsDriveAnalyticsEnabled, setValue: setIsDriveAnalyticsEnabled, addEventHandler: addIsDriveAnalyticsEnabledEventHandler } = makePHEventFunctions("isDriveAnalyticsEnabled");
898
+ const { useValue: useRenownUrl, setValue: setRenownUrl, addEventHandler: addRenownUrlEventHandler } = makePHEventFunctions("renownUrl");
899
+ const { useValue: useRenownNetworkId, setValue: setRenownNetworkId, addEventHandler: addRenownNetworkIdEventHandler } = makePHEventFunctions("renownNetworkId");
900
+ const { useValue: useRenownChainId, setValue: setRenownChainId, addEventHandler: addRenownChainIdEventHandler } = makePHEventFunctions("renownChainId");
901
+ const { useValue: useSentryRelease, setValue: setSentryRelease, addEventHandler: addSentryReleaseEventHandler } = makePHEventFunctions("sentryRelease");
902
+ const { useValue: useSentryDsn, setValue: setSentryDsn, addEventHandler: addSentryDsnEventHandler } = makePHEventFunctions("sentryDsn");
903
+ const { useValue: useSentryEnv, setValue: setSentryEnv, addEventHandler: addSentryEnvEventHandler } = makePHEventFunctions("sentryEnv");
904
+ const { useValue: useIsSentryTracingEnabled, setValue: setIsSentryTracingEnabled, addEventHandler: addIsSentryTracingEnabledEventHandler } = makePHEventFunctions("isSentryTracingEnabled");
905
+ const { useValue: useIsExternalProcessorsEnabled, setValue: setIsExternalProcessorsEnabled, addEventHandler: addIsExternalProcessorsEnabledEventHandler } = makePHEventFunctions("isExternalProcessorsEnabled");
906
+ const { useValue: useIsExternalPackagesEnabled, setValue: setIsExternalPackagesEnabled, addEventHandler: addIsExternalPackagesEnabledEventHandler } = makePHEventFunctions("isExternalPackagesEnabled");
907
+ const enabledEditorsEventFunctions = makePHEventFunctions("enabledEditors");
908
+ /** Sets the enabled editors for Connect. */
909
+ const setEnabledEditors = enabledEditorsEventFunctions.setValue;
910
+ /** Gets the enabled editors for Connect. */
911
+ const useEnabledEditors = enabledEditorsEventFunctions.useValue;
912
+ /** Adds an event handler for when the enabled editors for Connect changes. */
913
+ const addEnabledEditorsEventHandler = enabledEditorsEventFunctions.addEventHandler;
914
+ const disabledEditorsEventFunctions = makePHEventFunctions("disabledEditors");
915
+ /** Sets the disabled editors for Connect. */
916
+ const setDisabledEditors = disabledEditorsEventFunctions.setValue;
917
+ /** Gets the disabled editors for Connect. */
918
+ const useDisabledEditors = disabledEditorsEventFunctions.useValue;
919
+ /** Adds an event handler for when the disabled editors for Connect changes. */
920
+ const addDisabledEditorsEventHandler = disabledEditorsEventFunctions.addEventHandler;
921
+ const isRelationalProcessorsEnabled = makePHEventFunctions("isRelationalProcessorsEnabled");
922
+ /** Sets the isRelationalProcessorsEnabled for Connect. */
923
+ const setIsRelationalProcessorsEnabled = isRelationalProcessorsEnabled.setValue;
924
+ /** Gets the isRelationalProcessorsEnabled for Connect. */
925
+ const useIsRelationalProcessorsEnabled = isRelationalProcessorsEnabled.useValue;
926
+ /** Adds an event handler for when the isRelationalProcessorsEnabled for Connect changes. */
927
+ const addIsRelationalProcessorsEnabledEventHandler = isRelationalProcessorsEnabled.addEventHandler;
928
+ const isExternalRelationalProcessorsEnabled = makePHEventFunctions("isExternalRelationalProcessorsEnabled");
929
+ /** Sets the isExternalRelationalProcessorsEnabled for Connect. */
930
+ const setIsExternalRelationalProcessorsEnabled = isExternalRelationalProcessorsEnabled.setValue;
931
+ /** Gets the isExternalRelationalProcessorsEnabled for Connect. */
932
+ const useIsExternalRelationalProcessorsEnabled = isExternalRelationalProcessorsEnabled.useValue;
933
+ /** Adds an event handler for when the isExternalRelationalProcessorsEnabled for Connect changes. */
934
+ const addIsExternalRelationalProcessorsEnabledEventHandler = isExternalRelationalProcessorsEnabled.addEventHandler;
935
+ const isAnalyticsEnabledEventFunctions = makePHEventFunctions("isAnalyticsEnabled");
936
+ /** Sets the isAnalyticsEnabled for Connect. */
937
+ const setIsAnalyticsEnabled = isAnalyticsEnabledEventFunctions.setValue;
938
+ /** Gets the isAnalyticsEnabled for Connect. */
939
+ const useIsAnalyticsEnabled = isAnalyticsEnabledEventFunctions.useValue;
940
+ /** Adds an event handler for when the isAnalyticsEnabled for Connect changes. */
941
+ const addIsAnalyticsEnabledEventHandler = isAnalyticsEnabledEventFunctions.addEventHandler;
942
+ const isAnalyticsExternalProcessorsEnabled = makePHEventFunctions("isAnalyticsExternalProcessorsEnabled");
943
+ /** Sets the isAnalyticsExternalProcessorsEnabled for Connect. */
944
+ const setIsAnalyticsExternalProcessorsEnabled = isAnalyticsExternalProcessorsEnabled.setValue;
945
+ /** Gets the isAnalyticsExternalProcessorsEnabled for Connect. */
946
+ const useIsAnalyticsExternalProcessorsEnabled = isAnalyticsExternalProcessorsEnabled.useValue;
947
+ /** Adds an event handler for when the isAnalyticsExternalProcessorsEnabled for Connect changes. */
948
+ const addIsAnalyticsExternalProcessorsEnabledEventHandler = isAnalyticsExternalProcessorsEnabled.addEventHandler;
949
+ const analyticsDatabaseNameEventFunctions = makePHEventFunctions("analyticsDatabaseName");
950
+ /** Sets the analytics database name for Connect. */
951
+ const setAnalyticsDatabaseName = analyticsDatabaseNameEventFunctions.setValue;
952
+ /** Gets the analytics database name for Connect. */
953
+ const useAnalyticsDatabaseName = analyticsDatabaseNameEventFunctions.useValue;
954
+ /** Adds an event handler for when the analytics database name for Connect changes. */
955
+ const addAnalyticsDatabaseNameEventHandler = analyticsDatabaseNameEventFunctions.addEventHandler;
956
+ const logLevelEventFunctions = makePHEventFunctions("logLevel");
957
+ /** Sets the log level for Connect. */
958
+ const setLogLevel = logLevelEventFunctions.setValue;
959
+ /** Gets the log level for Connect. */
960
+ const useLogLevel = logLevelEventFunctions.useValue;
961
+ /** Adds an event handler for when the log level for Connect changes. */
962
+ const addLogLevelEventHandler = logLevelEventFunctions.addEventHandler;
963
+ const allowListEventFunctions = makePHEventFunctions("allowList");
964
+ /** Sets the allow list for Connect. */
965
+ const setAllowList = allowListEventFunctions.setValue;
966
+ /** Gets the allow list for Connect. */
967
+ const useAllowList = allowListEventFunctions.useValue;
968
+ /** Adds an event handler for when the allow list for Connect changes. */
969
+ const addAllowListEventHandler = allowListEventFunctions.addEventHandler;
970
+ const nonUserConfigSetters = {
971
+ routerBasename: setRouterBasename,
972
+ version: setVersion,
973
+ requiresHardRefresh: setRequiresHardRefresh,
974
+ warnOutdatedApp: setWarnOutdatedApp,
975
+ studioMode: setStudioMode,
976
+ basePath: setBasePath,
977
+ versionCheckInterval: setVersionCheckInterval,
978
+ cliVersion: setCliVersion,
979
+ fileUploadOperationsChunkSize: setFileUploadOperationsChunkSize,
980
+ isDocumentModelSelectionSettingsEnabled: setIsDocumentModelSelectionSettingsEnabled,
981
+ gaTrackingId: setGaTrackingId,
982
+ defaultDrivesUrl: setDefaultDrivesUrl,
983
+ drivesPreserveStrategy: setDrivesPreserveStrategy,
984
+ isLocalDrivesEnabled: setIsLocalDrivesEnabled,
985
+ isAddDriveEnabled: setIsAddDriveEnabled,
986
+ isPublicDrivesEnabled: setIsPublicDrivesEnabled,
987
+ isAddPublicDrivesEnabled: setIsAddPublicDrivesEnabled,
988
+ isDeletePublicDrivesEnabled: setIsDeletePublicDrivesEnabled,
989
+ isCloudDrivesEnabled: setIsCloudDrivesEnabled,
990
+ isAddCloudDrivesEnabled: setIsAddCloudDrivesEnabled,
991
+ isDeleteCloudDrivesEnabled: setIsDeleteCloudDrivesEnabled,
992
+ isAddLocalDrivesEnabled: setIsAddLocalDrivesEnabled,
993
+ isDeleteLocalDrivesEnabled: setIsDeleteLocalDrivesEnabled,
994
+ isEditorDebugModeEnabled: setIsEditorDebugModeEnabled,
995
+ isEditorReadModeEnabled: setIsEditorReadModeEnabled,
996
+ isRelationalProcessorsEnabled: setIsRelationalProcessorsEnabled,
997
+ isExternalRelationalProcessorsEnabled: setIsExternalRelationalProcessorsEnabled,
998
+ isAnalyticsEnabled: setIsAnalyticsEnabled,
999
+ analyticsDatabaseName: setAnalyticsDatabaseName,
1000
+ isAnalyticsExternalProcessorsEnabled: setIsAnalyticsExternalProcessorsEnabled,
1001
+ isAnalyticsDatabaseWorkerEnabled: setIsAnalyticsDatabaseWorkerEnabled,
1002
+ isDiffAnalyticsEnabled: setIsDiffAnalyticsEnabled,
1003
+ isDriveAnalyticsEnabled: setIsDriveAnalyticsEnabled,
1004
+ renownUrl: setRenownUrl,
1005
+ renownNetworkId: setRenownNetworkId,
1006
+ renownChainId: setRenownChainId,
1007
+ sentryRelease: setSentryRelease,
1008
+ sentryDsn: setSentryDsn,
1009
+ sentryEnv: setSentryEnv,
1010
+ isSentryTracingEnabled: setIsSentryTracingEnabled,
1011
+ isExternalProcessorsEnabled: setIsExternalProcessorsEnabled,
1012
+ isExternalPackagesEnabled: setIsExternalPackagesEnabled,
1013
+ allowList: setAllowList,
1014
+ logLevel: setLogLevel,
1015
+ disabledEditors: setDisabledEditors,
1016
+ enabledEditors: setEnabledEditors
1017
+ };
1018
+ const phGlobalConfigSetters = {
1019
+ ...phAppConfigSetters,
1020
+ ...phDocumentEditorConfigSetters,
1021
+ ...nonUserConfigSetters
1022
+ };
1023
+ const nonUserConfigHooks = {
1024
+ routerBasename: useRouterBasename,
1025
+ version: useVersion,
1026
+ requiresHardRefresh: useRequiresHardRefresh,
1027
+ warnOutdatedApp: useWarnOutdatedApp,
1028
+ studioMode: useStudioMode,
1029
+ basePath: useBasePath,
1030
+ versionCheckInterval: useVersionCheckInterval,
1031
+ cliVersion: useCliVersion,
1032
+ fileUploadOperationsChunkSize: useFileUploadOperationsChunkSize,
1033
+ isDocumentModelSelectionSettingsEnabled: useIsDocumentModelSelectionSettingsEnabled,
1034
+ gaTrackingId: useGaTrackingId,
1035
+ defaultDrivesUrl: useDefaultDrivesUrl,
1036
+ drivesPreserveStrategy: useDrivesPreserveStrategy,
1037
+ isAddDriveEnabled: useIsAddDriveEnabled,
1038
+ isPublicDrivesEnabled: useIsPublicDrivesEnabled,
1039
+ isAddPublicDrivesEnabled: useIsAddPublicDrivesEnabled,
1040
+ isDeletePublicDrivesEnabled: useIsDeletePublicDrivesEnabled,
1041
+ isCloudDrivesEnabled: useIsCloudDrivesEnabled,
1042
+ isAddCloudDrivesEnabled: useIsAddCloudDrivesEnabled,
1043
+ isDeleteCloudDrivesEnabled: useIsDeleteCloudDrivesEnabled,
1044
+ isLocalDrivesEnabled: useIsLocalDrivesEnabled,
1045
+ isAddLocalDrivesEnabled: useIsAddLocalDrivesEnabled,
1046
+ isDeleteLocalDrivesEnabled: useIsDeleteLocalDrivesEnabled,
1047
+ isEditorDebugModeEnabled: useIsEditorDebugModeEnabled,
1048
+ isEditorReadModeEnabled: useIsEditorReadModeEnabled,
1049
+ isAnalyticsDatabaseWorkerEnabled: useIsAnalyticsDatabaseWorkerEnabled,
1050
+ isDiffAnalyticsEnabled: useIsDiffAnalyticsEnabled,
1051
+ isDriveAnalyticsEnabled: useIsDriveAnalyticsEnabled,
1052
+ renownUrl: useRenownUrl,
1053
+ renownNetworkId: useRenownNetworkId,
1054
+ renownChainId: useRenownChainId,
1055
+ sentryRelease: useSentryRelease,
1056
+ sentryDsn: useSentryDsn,
1057
+ sentryEnv: useSentryEnv,
1058
+ isSentryTracingEnabled: useIsSentryTracingEnabled,
1059
+ isExternalProcessorsEnabled: useIsExternalProcessorsEnabled,
1060
+ isExternalPackagesEnabled: useIsExternalPackagesEnabled,
1061
+ allowList: useAllowList,
1062
+ isAnalyticsEnabled: useIsAnalyticsEnabled,
1063
+ isAnalyticsExternalProcessorsEnabled: useIsAnalyticsExternalProcessorsEnabled,
1064
+ isRelationalProcessorsEnabled: useIsRelationalProcessorsEnabled,
1065
+ isExternalRelationalProcessorsEnabled: useIsExternalRelationalProcessorsEnabled,
1066
+ analyticsDatabaseName: useAnalyticsDatabaseName,
1067
+ logLevel: useLogLevel,
1068
+ disabledEditors: useDisabledEditors,
1069
+ enabledEditors: useEnabledEditors
1070
+ };
1071
+ const phGlobalConfigHooks = {
1072
+ ...phAppConfigHooks,
1073
+ ...phDocumentEditorConfigHooks,
1074
+ ...nonUserConfigHooks
1075
+ };
1076
+ //#endregion
1077
+ //#region src/hooks/features.ts
1078
+ const featuresEventFunctions = makePHEventFunctions("features");
1079
+ const useFeatures = featuresEventFunctions.useValue;
1080
+ const setFeatures = featuresEventFunctions.setValue;
1081
+ const addFeaturesEventHandler = featuresEventFunctions.addEventHandler;
1082
+ //#endregion
1083
+ //#region src/hooks/drives.ts
1084
+ const drivesEventFunctions = makePHEventFunctions("drives");
1085
+ /** Returns all of the drives in the reactor */
1086
+ const useDrives = drivesEventFunctions.useValue;
1087
+ /** Sets the drives in the reactor */
1088
+ const setDrives = drivesEventFunctions.setValue;
1089
+ /** Adds an event handler for the drives */
1090
+ const addDrivesEventHandler = drivesEventFunctions.addEventHandler;
1091
+ //#endregion
1092
+ //#region src/hooks/graphql-reactor-client.ts
1093
+ const graphQLReactorClientEventFunctions = makePHEventFunctions("reactorGraphQLClient");
1094
+ const useGraphQLReactorClient = graphQLReactorClientEventFunctions.useValue;
1095
+ const setGraphQLReactorClient = graphQLReactorClientEventFunctions.setValue;
1096
+ const addGraphQLReactorClientEventHandler = graphQLReactorClientEventFunctions.addEventHandler;
1097
+ //#endregion
1098
+ //#region src/hooks/modals.ts
1099
+ const modalEventFunctions = makePHEventFunctions("modal");
1100
+ /** Returns the current modal */
1101
+ const usePHModal = modalEventFunctions.useValue;
1102
+ /** Sets the current modal */
1103
+ const setPHModal = modalEventFunctions.setValue;
1104
+ /** Adds an event handler for the modal */
1105
+ const addModalEventHandler = modalEventFunctions.addEventHandler;
1106
+ /** Shows a modal */
1107
+ function showPHModal(modal) {
1108
+ setPHModal(modal);
1109
+ }
1110
+ /** Closes the current modal */
1111
+ function closePHModal() {
1112
+ setPHModal(void 0);
1113
+ }
1114
+ /** Shows the create document modal */
1115
+ function showCreateDocumentModal(documentType) {
1116
+ setPHModal({
1117
+ type: "createDocument",
1118
+ documentType
1119
+ });
1120
+ }
1121
+ /** Shows the delete node modal */
1122
+ function showDeleteNodeModal(nodeOrId) {
1123
+ setPHModal({
1124
+ type: "deleteItem",
1125
+ id: typeof nodeOrId === "string" ? nodeOrId : nodeOrId.id
1126
+ });
1127
+ }
1128
+ //#endregion
1129
+ //#region src/hooks/package-discovery.ts
1130
+ const packageDiscoveryFunctions = makePHEventFunctions("packageDiscoveryService");
1131
+ const usePackageDiscoveryService = packageDiscoveryFunctions.useValue;
1132
+ const setPackageDiscoveryService = packageDiscoveryFunctions.setValue;
1133
+ const addPackageDiscoveryServiceEventHandler = packageDiscoveryFunctions.addEventHandler;
1134
+ //#endregion
1135
+ //#region src/hooks/reactor.ts
1136
+ const reactorClientModuleEventFunctions = makePHEventFunctions("reactorClientModule");
1137
+ const reactorClientEventFunctions = makePHEventFunctions("reactorClient");
1138
+ /** Returns the reactor client module */
1139
+ const useReactorClientModule = reactorClientModuleEventFunctions.useValue;
1140
+ /** Sets the reactor client module */
1141
+ const setReactorClientModule = reactorClientModuleEventFunctions.setValue;
1142
+ /** Adds an event handler for the reactor client module */
1143
+ const addReactorClientModuleEventHandler = reactorClientModuleEventFunctions.addEventHandler;
1144
+ /** Returns the reactor client */
1145
+ const useReactorClient = reactorClientEventFunctions.useValue;
1146
+ /** Sets the reactor client */
1147
+ const setReactorClient = reactorClientEventFunctions.setValue;
1148
+ /** Adds an event handler for the reactor client */
1149
+ const addReactorClientEventHandler = reactorClientEventFunctions.addEventHandler;
1150
+ const useSync = () => useReactorClientModule()?.reactorModule?.syncModule?.syncManager;
1151
+ const useSyncList = () => {
1152
+ return useSync()?.list() ?? [];
1153
+ };
1154
+ const useModelRegistry = () => useReactorClientModule()?.reactorModule?.documentModelRegistry;
1155
+ const useDatabase = () => useReactorClientModule()?.reactorModule?.database;
1156
+ const usePGlite = () => useReactorClientModule()?.pg;
1157
+ //#endregion
1158
+ //#region src/hooks/revision-history.ts
1159
+ const revisionHistoryEventFunctions = makePHEventFunctions("revisionHistoryVisible");
1160
+ /** Returns whether revision history is visible */
1161
+ const useRevisionHistoryVisible = revisionHistoryEventFunctions.useValue;
1162
+ /** Sets revision history visibility */
1163
+ const setRevisionHistoryVisible = revisionHistoryEventFunctions.setValue;
1164
+ /** Adds event handler for revision history visibility */
1165
+ const addRevisionHistoryVisibleEventHandler = revisionHistoryEventFunctions.addEventHandler;
1166
+ /** Shows the revision history */
1167
+ function showRevisionHistory() {
1168
+ setRevisionHistoryVisible(true);
1169
+ }
1170
+ /** Hides the revision history */
1171
+ function hideRevisionHistory() {
1172
+ setRevisionHistoryVisible(false);
1173
+ }
1174
+ //#endregion
1175
+ //#region src/utils/url.ts
1176
+ function resolveUrlPathname(path) {
1177
+ return new URL(path.replace(/^\/+/, ""), window.location.origin + (window.ph?.basePath ?? "/")).pathname;
1178
+ }
1179
+ /** Returns the current path without the base path */
1180
+ function getPathWithoutBase(path) {
1181
+ const basePath = window.ph?.basePath ?? "/";
1182
+ return path.replace(basePath, basePath.endsWith("/") ? "/" : "");
1183
+ }
1184
+ /** Makes a URL component for a drive. */
1185
+ function makeDriveUrlComponent(drive) {
1186
+ if (!drive) return "";
1187
+ return `/d/${slug(drive.header.slug)}`;
1188
+ }
1189
+ /** Makes a URL component for a node. */
1190
+ function makeNodeSlug(node) {
1191
+ if (!node) return "";
1192
+ const nodeName = node.name;
1193
+ if (!nodeName) return slug(node.id);
1194
+ return slug(`${nodeName}-${node.id}`);
1195
+ }
1196
+ /** Extracts the node slug from a path.
1197
+ *
1198
+ * The path is expected to be in the format `/d/<drive-slug>/<node-slug>`.
1199
+ */
1200
+ function extractNodeSlugFromPath(path) {
1201
+ const currentPath = getPathWithoutBase(path);
1202
+ return /^\/d\/[^/]+\/([^/]+)$/.exec(currentPath)?.[1];
1203
+ }
1204
+ /** Finds a UUID in a string, used for extracting node ids from node slugs in the URL. */
1205
+ function findUuid(input) {
1206
+ if (!input) return void 0;
1207
+ return /\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/.exec(input)?.[0];
1208
+ }
1209
+ function extractNodeIdFromSlug(nodeSlug) {
1210
+ return findUuid(nodeSlug);
1211
+ }
1212
+ function extractNodeIdFromPath(path) {
1213
+ return extractNodeIdFromSlug(extractNodeSlugFromPath(path));
1214
+ }
1215
+ /** Extracts the drive slug from a path.
1216
+ * Used for extracting drive ids from drive slugs in the URL.
1217
+ * Expects the path to be in the format `/d/<drive-slug>`.
1218
+ */
1219
+ function extractDriveSlugFromPath(path) {
1220
+ const currentPath = getPathWithoutBase(path);
1221
+ return /^\/d\/([^/]+)/.exec(currentPath)?.[1] ?? "";
1222
+ }
1223
+ function extractDriveIdFromSlug(driveSlug) {
1224
+ return findUuid(driveSlug);
1225
+ }
1226
+ function extractDriveIdFromPath(path) {
1227
+ return extractDriveIdFromSlug(extractDriveSlugFromPath(path));
1228
+ }
1229
+ /**
1230
+ * Creates a URL string with the given pathname while preserving existing query parameters.
1231
+ */
1232
+ function createUrlWithPreservedParams(pathname) {
1233
+ const search = window.location.search;
1234
+ return search ? `${pathname}${search}` : pathname;
1235
+ }
1236
+ //#endregion
1237
+ //#region src/hooks/selected-drive.ts
1238
+ const selectedDriveIdEventFunctions = makePHEventFunctions("selectedDriveId");
1239
+ /** Returns the selected drive id */
1240
+ const useSelectedDriveId = selectedDriveIdEventFunctions.useValue;
1241
+ /** Sets the selected drive id */
1242
+ const setSelectedDriveId = selectedDriveIdEventFunctions.setValue;
1243
+ /** Adds an event handler for the selected drive id */
1244
+ const addSelectedDriveIdEventHandler = selectedDriveIdEventFunctions.addEventHandler;
1245
+ /** Returns the selected drive */
1246
+ function useSelectedDrive() {
1247
+ const drive = useSelectedDriveSafe();
1248
+ if (!drive[0]) throw new Error("There is no drive selected. Did you mean to call 'useSelectedDriveSafe'?");
1249
+ return drive;
1250
+ }
1251
+ /** Returns the selected drive, or undefined if no drive is selected */
1252
+ function useSelectedDriveSafe() {
1253
+ const selectedDriveId = useSelectedDriveId();
1254
+ const selectedDrive = useDrives()?.find((drive) => drive.header.id === selectedDriveId);
1255
+ const [drive, dispatch] = useDispatch(selectedDrive);
1256
+ if (!selectedDrive) return [void 0, void 0];
1257
+ return [drive, dispatch];
1258
+ }
1259
+ function setSelectedDrive(driveOrDriveSlug) {
1260
+ const driveSlug = typeof driveOrDriveSlug === "string" ? driveOrDriveSlug : driveOrDriveSlug?.header.slug;
1261
+ const driveId = (window.ph?.drives?.find((d) => d.header.slug === driveSlug))?.header.id;
1262
+ setSelectedDriveId(driveId);
1263
+ if (!driveId) {
1264
+ const pathname = resolveUrlPathname("/");
1265
+ if (pathname === window.location.pathname) return;
1266
+ window.history.pushState(null, "", createUrlWithPreservedParams(pathname));
1267
+ return;
1268
+ }
1269
+ const pathname = resolveUrlPathname(`/d/${driveSlug}`);
1270
+ if (pathname === window.location.pathname) return;
1271
+ window.history.pushState(null, "", createUrlWithPreservedParams(pathname));
1272
+ }
1273
+ function addSetSelectedDriveOnPopStateEventHandler() {
1274
+ window.addEventListener("popstate", () => {
1275
+ const pathname = window.location.pathname;
1276
+ const driveId = extractDriveIdFromPath(pathname);
1277
+ if (driveId !== window.ph?.selectedDriveId) setSelectedDrive(driveId);
1278
+ });
1279
+ }
1280
+ //#endregion
1281
+ //#region src/utils/nodes.ts
1282
+ /** Sorts nodes by name. */
1283
+ function sortNodesByName(nodes) {
1284
+ return nodes.toSorted((a, b) => a.name.localeCompare(b.name));
1285
+ }
1286
+ /** Returns whether a node is a file. */
1287
+ function isFileNodeKind(node) {
1288
+ if (!node) return false;
1289
+ return node.kind.toUpperCase() === "FILE";
1290
+ }
1291
+ /** Returns whether a node is a folder. */
1292
+ function isFolderNodeKind(node) {
1293
+ if (!node) return false;
1294
+ return node.kind.toUpperCase() === "FOLDER";
1295
+ }
1296
+ //#endregion
1297
+ //#region src/hooks/items-in-selected-drive.ts
1298
+ /** Returns the nodes in the selected drive. */
1299
+ function useNodesInSelectedDrive() {
1300
+ const [selectedDrive] = useSelectedDriveSafe();
1301
+ return selectedDrive?.state.global.nodes;
1302
+ }
1303
+ /** Returns the file nodes in the selected drive. */
1304
+ function useFileNodesInSelectedDrive() {
1305
+ return useNodesInSelectedDrive()?.filter((n) => isFileNodeKind(n));
1306
+ }
1307
+ /** Returns the folder nodes in the selected drive. */
1308
+ function useFolderNodesInSelectedDrive() {
1309
+ return useNodesInSelectedDrive()?.filter((n) => isFolderNodeKind(n));
1310
+ }
1311
+ /** Returns the documents in the selected drive. */
1312
+ function useDocumentsInSelectedDrive() {
1313
+ const fileNodeIds = useFileNodesInSelectedDrive()?.map((node) => node.id);
1314
+ return useDocumentsByIds(fileNodeIds);
1315
+ }
1316
+ /** Returns the document types supported by the selected drive, as defined by the document model documents present in the drive */
1317
+ function useDocumentTypesInSelectedDrive() {
1318
+ return (useDocumentsInSelectedDrive()?.filter(isDocumentModelDocument))?.map((doc) => doc.state.global.id);
1319
+ }
1320
+ function isDocumentModelDocument(document) {
1321
+ return document.header.documentType === "powerhouse/document-model";
1322
+ }
1323
+ //#endregion
1324
+ //#region src/hooks/selected-node.ts
1325
+ const selectedNodeIdEventFunctions = makePHEventFunctions("selectedNodeId");
1326
+ const useSelectedNodeId = selectedNodeIdEventFunctions.useValue;
1327
+ const setSelectedNodeId = selectedNodeIdEventFunctions.setValue;
1328
+ const addSelectedNodeIdEventHandler = selectedNodeIdEventFunctions.addEventHandler;
1329
+ /** Returns the selected node. */
1330
+ function useSelectedNode() {
1331
+ const selectedNodeId = useSelectedNodeId();
1332
+ return useNodesInSelectedDrive()?.find((n) => n.id === selectedNodeId);
1333
+ }
1334
+ /** Sets the selected node (file or folder). */
1335
+ function setSelectedNode(nodeOrNodeSlug) {
1336
+ const nodeSlug = typeof nodeOrNodeSlug === "string" ? nodeOrNodeSlug : makeNodeSlug(nodeOrNodeSlug);
1337
+ setSelectedNodeId(extractNodeIdFromSlug(nodeSlug));
1338
+ const driveSlugFromPath = extractDriveSlugFromPath(window.location.pathname);
1339
+ if (!driveSlugFromPath) return;
1340
+ if (!nodeSlug) {
1341
+ const pathname = resolveUrlPathname(`/d/${driveSlugFromPath}`);
1342
+ if (pathname === window.location.pathname) return;
1343
+ window.history.pushState(null, "", createUrlWithPreservedParams(pathname));
1344
+ return;
1345
+ }
1346
+ const pathname = resolveUrlPathname(`/d/${driveSlugFromPath}/${nodeSlug}`);
1347
+ if (pathname === window.location.pathname) return;
1348
+ window.history.pushState(null, "", createUrlWithPreservedParams(pathname));
1349
+ }
1350
+ function addResetSelectedNodeEventHandler() {
1351
+ window.addEventListener("ph:selectedDriveIdUpdated", () => {
1352
+ setSelectedNodeId(void 0);
1353
+ });
1354
+ }
1355
+ function addSetSelectedNodeOnPopStateEventHandler() {
1356
+ window.addEventListener("popstate", () => {
1357
+ const pathname = window.location.pathname;
1358
+ const nodeSlug = extractNodeSlugFromPath(pathname);
1359
+ if (nodeSlug !== window.ph?.selectedNodeId) setSelectedNode(nodeSlug);
1360
+ });
1361
+ }
1362
+ //#endregion
1363
+ //#region src/hooks/selected-timeline-item.ts
1364
+ const selectedTimelineItemEventFunctions = makePHEventFunctions("selectedTimelineItem");
1365
+ /** Returns the selected timeline item */
1366
+ const useSelectedTimelineItem = selectedTimelineItemEventFunctions.useValue;
1367
+ /** Sets the selected timeline item */
1368
+ const setSelectedTimelineItem = selectedTimelineItemEventFunctions.setValue;
1369
+ /** Adds event handler for selected timeline item */
1370
+ const addSelectedTimelineItemEventHandler = selectedTimelineItemEventFunctions.addEventHandler;
1371
+ //#endregion
1372
+ //#region src/hooks/timeline-revision.ts
1373
+ const selectedTimelineRevisionEventFunctions = makePHEventFunctions("selectedTimelineRevision");
1374
+ /** Returns the selected timeline revision. */
1375
+ const useSelectedTimelineRevision = selectedTimelineRevisionEventFunctions.useValue;
1376
+ /** Sets the selected timeline revision. */
1377
+ const setSelectedTimelineRevision = selectedTimelineRevisionEventFunctions.setValue;
1378
+ /** Adds an event handler for the selected timeline revision. */
1379
+ const addSelectedTimelineRevisionEventHandler = selectedTimelineRevisionEventFunctions.addEventHandler;
1380
+ //#endregion
1381
+ //#region src/hooks/toast.ts
1382
+ const toastEventFunctions = makePHEventFunctions("toast");
1383
+ /** Returns the toast function */
1384
+ const usePHToast = toastEventFunctions.useValue;
1385
+ /** Sets the toast function */
1386
+ const setPHToast = toastEventFunctions.setValue;
1387
+ /** Adds an event handler for the toast */
1388
+ const addToastEventHandler = toastEventFunctions.addEventHandler;
1389
+ //#endregion
1390
+ //#region src/hooks/vetra-packages.ts
1391
+ const vetraPackageManagerFunctions = makePHEventFunctions("vetraPackageManager");
1392
+ const useVetraPackageManager = vetraPackageManagerFunctions.useValue;
1393
+ /** Returns all of the Vetra packages loaded by the Connect instance */
1394
+ const useVetraPackages = () => {
1395
+ const packageManager = useVetraPackageManager();
1396
+ return useSyncExternalStore((cb) => packageManager ? packageManager.subscribe(cb) : () => {}, () => packageManager?.packages ?? []);
1397
+ };
1398
+ /** Adds the Vetra package manager event handler */
1399
+ const addVetraPackageManagerEventHandler = vetraPackageManagerFunctions.addEventHandler;
1400
+ /** Sets the Vetra package manager and registers its packages */
1401
+ function setVetraPackageManager(packageManager) {
1402
+ vetraPackageManagerFunctions.setValue(packageManager);
1403
+ updateReactorClientDocumentModels(packageManager.packages);
1404
+ updateReactorClientUpgradeManifests(packageManager.packages);
1405
+ packageManager.subscribe(({ packages }) => {
1406
+ updateReactorClientDocumentModels(packages);
1407
+ updateReactorClientUpgradeManifests(packages);
1408
+ });
1409
+ }
1410
+ function updateReactorClientDocumentModels(packages) {
1411
+ const documentModelModules = packages.flatMap((pkg) => pkg.documentModels);
1412
+ const registry = window.ph?.reactorClientModule?.reactorModule?.documentModelRegistry;
1413
+ if (!registry || documentModelModules.length === 0) return;
1414
+ const results = registry.registerModules(...documentModelModules);
1415
+ const duplicates = [];
1416
+ for (const result of results) if (result.status === "error") if (DuplicateModuleError.isError(result.error)) duplicates.push(result);
1417
+ else console.error("Failed to register document model module:", result.error);
1418
+ if (duplicates.length > 0) {
1419
+ const duplicateTypes = duplicates.map((r) => r.item.documentModel.global.id);
1420
+ registry.unregisterModules(...duplicateTypes);
1421
+ registry.registerModules(...duplicates.map((r) => r.item));
1422
+ }
1423
+ }
1424
+ function updateReactorClientUpgradeManifests(packages) {
1425
+ const upgradeManifests = packages.flatMap((pkg) => pkg.upgradeManifests).filter((u) => u !== void 0);
1426
+ const registry = window.ph?.reactorClientModule?.reactorModule?.documentModelRegistry;
1427
+ if (!registry || upgradeManifests.length === 0) return;
1428
+ const results = registry.registerUpgradeManifests(...upgradeManifests);
1429
+ const duplicates = [];
1430
+ for (const result of results) if (result.status === "error") if (DuplicateManifestError.isError(result.error)) duplicates.push(result);
1431
+ else console.error("Failed to register upgrade manifest:", result.error);
1432
+ if (duplicates.length > 0) {
1433
+ const duplicateTypes = duplicates.map((r) => r.item.documentType).filter((t) => !!t);
1434
+ registry.unregisterUpgradeManifests(...duplicateTypes);
1435
+ registry.registerUpgradeManifests(...duplicates.map((r) => r.item));
1436
+ }
1437
+ }
1438
+ //#endregion
1439
+ //#region src/hooks/add-ph-event-handlers.ts
1440
+ const commonGlobalEventHandlerFunctions = {
1441
+ loading: addLoadingEventHandler,
1442
+ drives: addDrivesEventHandler,
1443
+ selectedDriveId: () => {
1444
+ addSelectedDriveIdEventHandler();
1445
+ addSetSelectedDriveOnPopStateEventHandler();
1446
+ addResetSelectedNodeEventHandler();
1447
+ },
1448
+ selectedNodeId: () => {
1449
+ addSelectedNodeIdEventHandler();
1450
+ addSetSelectedNodeOnPopStateEventHandler();
1451
+ },
1452
+ documentCache: addDocumentCacheEventHandler,
1453
+ reactorGraphQLClient: addGraphQLReactorClientEventHandler
1454
+ };
1455
+ const phGlobalEventHandlerRegisterFunctions = {
1456
+ ...commonGlobalEventHandlerFunctions,
1457
+ reactorClientModule: addReactorClientModuleEventHandler,
1458
+ reactorClient: addReactorClientEventHandler,
1459
+ features: addFeaturesEventHandler,
1460
+ modal: addModalEventHandler,
1461
+ renown: addRenownEventHandler,
1462
+ vetraPackageManager: addVetraPackageManagerEventHandler,
1463
+ packageDiscoveryService: addPackageDiscoveryServiceEventHandler,
1464
+ selectedTimelineRevision: addSelectedTimelineRevisionEventHandler,
1465
+ revisionHistoryVisible: addRevisionHistoryVisibleEventHandler,
1466
+ selectedTimelineItem: addSelectedTimelineItemEventHandler,
1467
+ routerBasename: addRouterBasenameEventHandler,
1468
+ version: addVersionEventHandler,
1469
+ logLevel: addLogLevelEventHandler,
1470
+ requiresHardRefresh: addRequiresHardRefreshEventHandler,
1471
+ warnOutdatedApp: addWarnOutdatedAppEventHandler,
1472
+ studioMode: addStudioModeEventHandler,
1473
+ basePath: addBasePathEventHandler,
1474
+ versionCheckInterval: addVersionCheckIntervalEventHandler,
1475
+ cliVersion: addCliVersionEventHandler,
1476
+ fileUploadOperationsChunkSize: addFileUploadOperationsChunkSizeEventHandler,
1477
+ isDocumentModelSelectionSettingsEnabled: addIsDocumentModelSelectionSettingsEnabledEventHandler,
1478
+ gaTrackingId: addGaTrackingIdEventHandler,
1479
+ allowList: addAllowListEventHandler,
1480
+ defaultDrivesUrl: addDefaultDrivesUrlEventHandler,
1481
+ drivesPreserveStrategy: addDrivesPreserveStrategyEventHandler,
1482
+ allowedDocumentTypes: addAllowedDocumentTypesEventHandler,
1483
+ enabledEditors: addEnabledEditorsEventHandler,
1484
+ disabledEditors: addDisabledEditorsEventHandler,
1485
+ isAddDriveEnabled: addIsAddDriveEnabledEventHandler,
1486
+ isLocalDrivesEnabled: addIsLocalDrivesEnabledEventHandler,
1487
+ isPublicDrivesEnabled: addIsPublicDrivesEnabledEventHandler,
1488
+ isAddPublicDrivesEnabled: addIsAddPublicDrivesEnabledEventHandler,
1489
+ isDeletePublicDrivesEnabled: addIsDeletePublicDrivesEnabledEventHandler,
1490
+ isCloudDrivesEnabled: addIsCloudDrivesEnabledEventHandler,
1491
+ isAddCloudDrivesEnabled: addIsAddCloudDrivesEnabledEventHandler,
1492
+ isDeleteCloudDrivesEnabled: addIsDeleteCloudDrivesEnabledEventHandler,
1493
+ isAddLocalDrivesEnabled: addIsAddLocalDrivesEnabledEventHandler,
1494
+ isDeleteLocalDrivesEnabled: addIsDeleteLocalDrivesEnabledEventHandler,
1495
+ isDragAndDropEnabled: addIsDragAndDropEnabledEventHandler,
1496
+ isExternalControlsEnabled: addIsExternalControlsEnabledEventHandler,
1497
+ isEditorDebugModeEnabled: addIsEditorDebugModeEnabledEventHandler,
1498
+ isEditorReadModeEnabled: addIsEditorReadModeEnabledEventHandler,
1499
+ isRelationalProcessorsEnabled: addIsRelationalProcessorsEnabledEventHandler,
1500
+ isExternalRelationalProcessorsEnabled: addIsExternalRelationalProcessorsEnabledEventHandler,
1501
+ isAnalyticsEnabled: addIsAnalyticsEnabledEventHandler,
1502
+ isAnalyticsExternalProcessorsEnabled: addIsAnalyticsExternalProcessorsEnabledEventHandler,
1503
+ analyticsDatabaseName: addAnalyticsDatabaseNameEventHandler,
1504
+ isAnalyticsDatabaseWorkerEnabled: addIsAnalyticsDatabaseWorkerEnabledEventHandler,
1505
+ isDiffAnalyticsEnabled: addIsDiffAnalyticsEnabledEventHandler,
1506
+ isDriveAnalyticsEnabled: addIsDriveAnalyticsEnabledEventHandler,
1507
+ renownUrl: addRenownUrlEventHandler,
1508
+ renownNetworkId: addRenownNetworkIdEventHandler,
1509
+ renownChainId: addRenownChainIdEventHandler,
1510
+ sentryRelease: addSentryReleaseEventHandler,
1511
+ sentryDsn: addSentryDsnEventHandler,
1512
+ sentryEnv: addSentryEnvEventHandler,
1513
+ isSentryTracingEnabled: addIsSentryTracingEnabledEventHandler,
1514
+ isExternalProcessorsEnabled: addIsExternalProcessorsEnabledEventHandler,
1515
+ isExternalPackagesEnabled: addIsExternalPackagesEnabledEventHandler,
1516
+ toast: addToastEventHandler
1517
+ };
1518
+ function addPHEventHandlers() {
1519
+ callEventHandlerRegisterFunctions(phGlobalEventHandlerRegisterFunctions);
1520
+ }
1521
+ function callEventHandlerRegisterFunctions(registerFunctions) {
1522
+ forEachObj(registerFunctions, (fn) => fn());
1523
+ }
1524
+ //#endregion
1525
+ //#region src/hooks/document-model-modules.ts
1526
+ function useDocumentModelModules() {
1527
+ return useVetraPackages().flatMap((pkg) => pkg.documentModels).filter((module, index, modules) => modules.findIndex((m) => m.documentModel.global.id === module.documentModel.global.id && m.version === module.version) === index);
1528
+ }
1529
+ function useDocumentModelModuleById(id) {
1530
+ return useDocumentModelModules()?.find((module) => module.documentModel.global.id === id);
1531
+ }
1532
+ //#endregion
1533
+ //#region src/hooks/allowed-document-model-modules.ts
1534
+ function useAllowedDocumentModelModules() {
1535
+ const documentModelModules = useDocumentModelModules();
1536
+ const allowedDocumentTypes = useAllowedDocumentTypes();
1537
+ if (!allowedDocumentTypes?.length) return documentModelModules;
1538
+ return documentModelModules?.filter((module) => allowedDocumentTypes.includes(module.documentModel.global.id));
1539
+ }
1540
+ //#endregion
1541
+ //#region src/hooks/selected-folder.ts
1542
+ /** Returns the selected folder. */
1543
+ function useSelectedFolder() {
1544
+ const selectedNode = useSelectedNode();
1545
+ if (isFolderNodeKind(selectedNode)) return selectedNode;
1546
+ }
1547
+ //#endregion
1548
+ //#region src/hooks/child-nodes.ts
1549
+ /** Returns the child nodes for the selected drive or folder. */
1550
+ function useNodesInSelectedDriveOrFolder() {
1551
+ const nodes = useNodesInSelectedDrive();
1552
+ const selectedFolderId = useSelectedFolder()?.id;
1553
+ if (!nodes) return [];
1554
+ if (!selectedFolderId) return sortNodesByName(nodes.filter((n) => !n.parentFolder));
1555
+ return sortNodesByName(nodes.filter((n) => n.parentFolder === selectedFolderId));
1556
+ }
1557
+ //#endregion
1558
+ //#region src/hooks/config/set-config-by-key.ts
1559
+ function setPHGlobalConfigByKey(key, value) {
1560
+ const setter = phGlobalConfigSetters[key];
1561
+ setter(value);
1562
+ }
1563
+ function setPHAppConfigByKey(key, value) {
1564
+ const setter = phAppConfigSetters[key];
1565
+ setter(value);
1566
+ }
1567
+ function setPHDocumentEditorConfigByKey(key, value) {
1568
+ const setter = phDocumentEditorConfigSetters[key];
1569
+ setter(value);
1570
+ }
1571
+ //#endregion
1572
+ //#region src/hooks/config/utils.ts
1573
+ function callGlobalSetterForKey(key, value) {
1574
+ const setter = phGlobalConfigSetters[key];
1575
+ setter(value);
1576
+ }
1577
+ //#endregion
1578
+ //#region src/hooks/config/set-config-by-object.ts
1579
+ function setDefaultPHGlobalConfig(config) {
1580
+ for (const key of Object.keys(config)) callGlobalSetterForKey(key, config[key]);
1581
+ }
1582
+ function useSetDefaultPHGlobalConfig(config) {
1583
+ const [isInitialized, setIsInitialized] = useState(false);
1584
+ useEffect(() => {
1585
+ if (isInitialized) return;
1586
+ setDefaultPHGlobalConfig(config);
1587
+ setIsInitialized(true);
1588
+ }, [config, isInitialized]);
1589
+ }
1590
+ function useResetPHGlobalConfig(defaultConfigForReset) {
1591
+ return function reset() {
1592
+ setPHGlobalConfig(defaultConfigForReset);
1593
+ };
1594
+ }
1595
+ function setPHGlobalConfig(config) {
1596
+ for (const key of Object.keys(config)) callGlobalSetterForKey(key, config[key]);
1597
+ }
1598
+ function useSetPHGlobalConfig(config) {
1599
+ const [isInitialized, setIsInitialized] = useState(false);
1600
+ useEffect(() => {
1601
+ if (isInitialized) return;
1602
+ setPHGlobalConfig(config);
1603
+ setIsInitialized(true);
1604
+ }, [config, isInitialized]);
1605
+ }
1606
+ /** Sets the global drive config.
1607
+ *
1608
+ * Pass in a partial object of the global drive config to set.
1609
+ */
1610
+ function setPHAppConfig(config) {
1611
+ for (const key of Object.keys(config)) callGlobalSetterForKey(key, config[key]);
1612
+ }
1613
+ /** Sets the global document config.
1614
+ *
1615
+ * Pass in a partial object of the global document config to set.
1616
+ */
1617
+ function setPHDocumentEditorConfig(config) {
1618
+ for (const key of Object.keys(config)) callGlobalSetterForKey(key, config[key]);
1619
+ }
1620
+ /** Wrapper hook for setting the global app config.
1621
+ *
1622
+ * Automatically sets the global app config when the component mounts.
1623
+ *
1624
+ * Pass in a partial object of the global app config to set.
1625
+ */
1626
+ function useSetPHAppConfig(config) {
1627
+ const [isInitialized, setIsInitialized] = useState(false);
1628
+ useEffect(() => {
1629
+ if (isInitialized) return;
1630
+ setPHAppConfig(config);
1631
+ setIsInitialized(true);
1632
+ }, [config, isInitialized]);
1633
+ }
1634
+ /** Wrapper hook for setting the global document editor config.
1635
+ *
1636
+ * Automatically sets the global document editor config when the component mounts.
1637
+ *
1638
+ * Pass in a partial object of the global document editor config to set.
1639
+ */
1640
+ function useSetPHDocumentEditorConfig(config) {
1641
+ const [isInitialized, setIsInitialized] = useState(false);
1642
+ useEffect(() => {
1643
+ if (isInitialized) return;
1644
+ setPHDocumentEditorConfig(config);
1645
+ setIsInitialized(true);
1646
+ }, [config, isInitialized]);
1647
+ }
1648
+ //#endregion
1649
+ //#region src/hooks/config/use-value-by-key.ts
1650
+ function usePHGlobalConfigByKey(key) {
1651
+ const useValueHook = phGlobalConfigHooks[key];
1652
+ return useValueHook();
1653
+ }
1654
+ /** Gets the value of an item in the global drive config for a given key.
1655
+ *
1656
+ * Strongly typed, inferred from type definition for the key.
1657
+ */
1658
+ function usePHAppConfigByKey(key) {
1659
+ const useValueHook = phAppConfigHooks[key];
1660
+ return useValueHook();
1661
+ }
1662
+ /** Gets the value of an item in the global document config for a given key.
1663
+ *
1664
+ * Strongly typed, inferred from type definition for the key.
1665
+ */
1666
+ function usePHDocumentEditorConfigByKey(key) {
1667
+ const useValueHook = phDocumentEditorConfigHooks[key];
1668
+ return useValueHook();
1669
+ }
1670
+ //#endregion
1671
+ //#region src/hooks/connection-state.ts
1672
+ /**
1673
+ * Returns a map of remote name to connection state snapshot for all remotes.
1674
+ * Re-renders when any remote's connection state changes.
1675
+ */
1676
+ function useConnectionStates() {
1677
+ const syncManager = useSync();
1678
+ const [states, setStates] = useState(() => buildSnapshot(syncManager));
1679
+ const unsubscribesRef = useRef([]);
1680
+ useEffect(() => {
1681
+ if (!syncManager) return;
1682
+ function subscribe() {
1683
+ for (const unsub of unsubscribesRef.current) unsub();
1684
+ unsubscribesRef.current = [];
1685
+ const remotes = syncManager.list();
1686
+ for (const remote of remotes) {
1687
+ const unsub = remote.channel.onConnectionStateChange(() => {
1688
+ setStates(buildSnapshot(syncManager));
1689
+ });
1690
+ unsubscribesRef.current.push(unsub);
1691
+ }
1692
+ setStates(buildSnapshot(syncManager));
1693
+ }
1694
+ subscribe();
1695
+ const interval = setInterval(subscribe, 5e3);
1696
+ return () => {
1697
+ clearInterval(interval);
1698
+ for (const unsub of unsubscribesRef.current) unsub();
1699
+ unsubscribesRef.current = [];
1700
+ };
1701
+ }, [syncManager]);
1702
+ return states;
1703
+ }
1704
+ /**
1705
+ * Returns the connection state snapshot for a specific remote by name.
1706
+ */
1707
+ function useConnectionState(remoteName) {
1708
+ return useConnectionStates().get(remoteName);
1709
+ }
1710
+ function buildSnapshot(syncManager) {
1711
+ const map = /* @__PURE__ */ new Map();
1712
+ if (!syncManager) return map;
1713
+ for (const remote of syncManager.list()) map.set(remote.name, remote.channel.getConnectionState());
1714
+ return map;
1715
+ }
1716
+ //#endregion
1717
+ //#region src/hooks/document-of-type.ts
1718
+ /** Returns a document of a specific type, throws an error if the found document has a different type */
1719
+ function useDocumentOfType(documentId, documentType) {
1720
+ const [document, dispatch] = useDocumentById(documentId);
1721
+ const documentModelModule = useDocumentModelModuleById(documentType);
1722
+ if (!documentId || !documentType) return [];
1723
+ if (!document) throw new Error(`Document not found: ${documentId}`);
1724
+ if (!documentModelModule) throw new ModuleNotFoundError(documentType);
1725
+ if (document.header.documentType !== documentType) throw new DocumentTypeMismatchError(documentId, documentType, document.header.documentType);
1726
+ return [document, dispatch];
1727
+ }
1728
+ //#endregion
1729
+ //#region src/hooks/document-operations.ts
1730
+ /**
1731
+ * Hook to fetch document operations via the reactor client.
1732
+ * Operations are no longer auto-populated on documents and must be fetched explicitly.
1733
+ *
1734
+ * @param documentId - The document ID to fetch operations for
1735
+ * @returns Object containing globalOperations, localOperations, isLoading, and error
1736
+ */
1737
+ function useDocumentOperations(documentId) {
1738
+ const reactorClient = useReactorClient();
1739
+ const hasFetchedRef = useRef(false);
1740
+ const [state, setState] = useState(() => ({
1741
+ globalOperations: [],
1742
+ localOperations: [],
1743
+ isLoading: !!documentId,
1744
+ error: void 0
1745
+ }));
1746
+ const fetchOperations = useCallback(async (retryCount = 0) => {
1747
+ const MAX_RETRIES = 5;
1748
+ const RETRY_DELAY_MS = 500;
1749
+ if (!documentId || !reactorClient) {
1750
+ setState({
1751
+ globalOperations: [],
1752
+ localOperations: [],
1753
+ isLoading: false,
1754
+ error: void 0
1755
+ });
1756
+ return;
1757
+ }
1758
+ setState((prev) => ({
1759
+ ...prev,
1760
+ isLoading: true,
1761
+ error: void 0
1762
+ }));
1763
+ let globalOps = [];
1764
+ let localOps = [];
1765
+ let fetchError;
1766
+ try {
1767
+ globalOps = (await reactorClient.getOperations(documentId, { scopes: ["global"] })).results;
1768
+ } catch (err) {
1769
+ fetchError = err instanceof Error ? err : new Error(String(err));
1770
+ }
1771
+ if (!fetchError) try {
1772
+ localOps = (await reactorClient.getOperations(documentId, { scopes: ["local"] })).results;
1773
+ } catch (err) {
1774
+ fetchError = err instanceof Error ? err : new Error(String(err));
1775
+ }
1776
+ if (!fetchError && globalOps.length === 0 && localOps.length === 0 && retryCount < MAX_RETRIES) {
1777
+ await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));
1778
+ return fetchOperations(retryCount + 1);
1779
+ }
1780
+ setState({
1781
+ globalOperations: globalOps,
1782
+ localOperations: localOps,
1783
+ isLoading: false,
1784
+ error: fetchError
1785
+ });
1786
+ hasFetchedRef.current = true;
1787
+ }, [documentId, reactorClient]);
1788
+ useEffect(() => {
1789
+ if (documentId && reactorClient) fetchOperations();
1790
+ else if (!documentId) {
1791
+ setState({
1792
+ globalOperations: [],
1793
+ localOperations: [],
1794
+ isLoading: false,
1795
+ error: void 0
1796
+ });
1797
+ hasFetchedRef.current = false;
1798
+ }
1799
+ }, [
1800
+ documentId,
1801
+ reactorClient,
1802
+ fetchOperations
1803
+ ]);
1804
+ const refetch = useCallback(() => {
1805
+ fetchOperations(0);
1806
+ }, [fetchOperations]);
1807
+ return {
1808
+ ...state,
1809
+ refetch
1810
+ };
1811
+ }
1812
+ //#endregion
1813
+ //#region src/hooks/supported-document-types.ts
1814
+ /** Returns the supported document types for the reactor (derived from the document model modules) */
1815
+ function useSupportedDocumentTypesInReactor() {
1816
+ return useDocumentModelModules()?.map((module) => module.documentModel.global.id);
1817
+ }
1818
+ //#endregion
1819
+ //#region src/hooks/document-types.ts
1820
+ /** Returns the document types a app supports.
1821
+ *
1822
+ * If present, uses the `allowedDocumentTypes` config value.
1823
+ * Otherwise, uses the supported document types from the reactor.
1824
+ */
1825
+ function useDocumentTypes() {
1826
+ const allowedDocumentTypes = useAllowedDocumentTypes();
1827
+ const supportedDocumentTypes = useSupportedDocumentTypesInReactor();
1828
+ return allowedDocumentTypes ?? supportedDocumentTypes;
1829
+ }
1830
+ //#endregion
1831
+ //#region src/hooks/drive-by-id.ts
1832
+ function useDriveById(driveId) {
1833
+ const foundDrive = useDrives()?.find((drive) => drive.header.id === driveId);
1834
+ const [drive, dispatch] = useDispatch(foundDrive);
1835
+ if (!foundDrive) throw new Error(`Drive with id ${driveId} not found`);
1836
+ return [drive, dispatch];
1837
+ }
1838
+ //#endregion
1839
+ //#region src/hooks/editor-modules.ts
1840
+ function useEditorModules() {
1841
+ return useVetraPackages().flatMap((pkg) => pkg.editors).filter((module) => !module.documentTypes.includes("powerhouse/document-drive"));
1842
+ }
1843
+ function useAppModules() {
1844
+ return useVetraPackages().flatMap((pkg) => pkg.editors).filter((module) => module.documentTypes.includes("powerhouse/document-drive"));
1845
+ }
1846
+ function useFallbackEditorModule(documentType) {
1847
+ const editorModules = useEditorModules();
1848
+ if (!documentType) return void 0;
1849
+ if (editorModules?.length === 0) return void 0;
1850
+ return (editorModules?.filter((module) => module.documentTypes.includes(documentType)))?.[0];
1851
+ }
1852
+ function useAppModuleById(id) {
1853
+ return useAppModules()?.find((module) => module.config.id === id);
1854
+ }
1855
+ function useDefaultAppModule() {
1856
+ return useAppModuleById(DEFAULT_DRIVE_EDITOR_ID);
1857
+ }
1858
+ function useEditorModuleById(id) {
1859
+ return useEditorModules()?.find((module) => module.config.id === id);
1860
+ }
1861
+ function useEditorModulesForDocumentType(documentType) {
1862
+ const editorModules = useEditorModules();
1863
+ if (!documentType) return void 0;
1864
+ return editorModules?.filter((module) => module.documentTypes.includes(documentType));
1865
+ }
1866
+ //#endregion
1867
+ //#region src/hooks/folder-by-id.ts
1868
+ function useFolderById(id) {
1869
+ return useFolderNodesInSelectedDrive()?.find((n) => n.id === id);
1870
+ }
1871
+ //#endregion
1872
+ //#region src/graphql/events.ts
1873
+ function dispatchGraphQLClientDocumentEvent(operationName, identifier) {
1874
+ const event = new CustomEvent(operationName, { detail: { identifier } });
1875
+ window.dispatchEvent(event);
1876
+ }
1877
+ //#endregion
1878
+ //#region src/graphql/document-cache-client-middleware.ts
1879
+ const documentCacheClientMiddleware = async (action, operationName, operationType, variables) => {
1880
+ console.log({
1881
+ operationName,
1882
+ operationType,
1883
+ variables
1884
+ });
1885
+ const result = await action();
1886
+ if (isIncludedIn(operationName, graphqlEventsToSyncDrive)) window.dispatchEvent(new CustomEvent(operationName));
1887
+ if (isStrictEqual(operationName, "MutateDocument")) dispatchGraphQLClientDocumentEvent(operationName, identifierFromMutateDocumentOperationVariables(variables));
1888
+ return result;
1889
+ };
1890
+ //#endregion
1891
+ //#region src/hooks/init-graphql-reactor-client.ts
1892
+ function useInitReactorGraphqlClient(switchboardUrl = DEFAULT_SWITCHBOARD_URL, driveId = DEFAULT_DRIVE_ID) {
1893
+ const [hasInit, setHasInit] = useState(false);
1894
+ useEffect(() => {
1895
+ if (hasInit) return;
1896
+ initGraphQLReactorClientWithDocumentCache(switchboardUrl, driveId).then(() => setHasInit(true)).catch(console.error);
1897
+ }, [hasInit]);
1898
+ return hasInit;
1899
+ }
1900
+ async function reactorGraphqlFetchDrive(identifier) {
1901
+ const client = window.ph?.reactorGraphQLClient;
1902
+ if (!client) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
1903
+ const result = await client.GetDocument({ identifier });
1904
+ if (!result.document?.document) throw new Error("Could not fetch drive with id: " + identifier);
1905
+ return phDocumentFromQuery(result.document.document, DriveDocumentSchema);
1906
+ }
1907
+ async function reactorGraphqlSyncDrive(driveId) {
1908
+ if (!window.ph?.reactorGraphQLClient) throw new Error("Please call `useInitReactorGraphqlClient` to use its functions");
1909
+ const drive = await reactorGraphqlFetchDrive(driveId);
1910
+ setDrives([drive]);
1911
+ setSelectedDrive(drive);
1912
+ }
1913
+ async function initGraphQLReactorClientWithDocumentCache(switchboardUrl, driveId) {
1914
+ if (!window.ph) window.ph = {};
1915
+ callEventHandlerRegisterFunctions(commonGlobalEventHandlerFunctions);
1916
+ setGraphQLReactorClient(createClient(switchboardUrl, documentCacheClientMiddleware));
1917
+ await reactorGraphqlSyncDrive(driveId);
1918
+ setSelectedNode(void 0);
1919
+ setDocumentCache(new GraphQLClientDocumentCache());
1920
+ forEach(graphqlEventsToSyncDrive, (name) => {
1921
+ window.addEventListener(name, () => {
1922
+ reactorGraphqlSyncDrive(driveId).catch(console.error);
1923
+ });
1924
+ });
1925
+ }
1926
+ //#endregion
1927
+ //#region src/hooks/items-in-selected-folder.ts
1928
+ /** Returns the nodes in the selected folder. */
1929
+ function useNodesInSelectedFolder() {
1930
+ const selectedFolder = useSelectedFolder();
1931
+ const nodes = useNodesInSelectedDrive();
1932
+ if (!selectedFolder || !nodes) return void 0;
1933
+ return nodes.filter((n) => n.parentFolder === selectedFolder.id);
1934
+ }
1935
+ /** Returns the file nodes in the selected folder. */
1936
+ function useFileNodesInSelectedFolder() {
1937
+ const nodes = useNodesInSelectedFolder();
1938
+ if (!nodes) return void 0;
1939
+ return nodes.filter((n) => isFileNodeKind(n));
1940
+ }
1941
+ /** Returns the folder nodes in the selected folder. */
1942
+ function useFolderNodesInSelectedFolder() {
1943
+ const nodes = useNodesInSelectedFolder();
1944
+ if (!nodes) return void 0;
1945
+ return nodes.filter((n) => isFolderNodeKind(n));
1946
+ }
1947
+ /** Returns the documents in the selected folder. */
1948
+ function useDocumentsInSelectedFolder() {
1949
+ const documents = useDocumentsInSelectedDrive();
1950
+ const fileNodeIds = useFileNodesInSelectedFolder()?.map((node) => node.id);
1951
+ return documents?.filter((d) => fileNodeIds?.includes(d.header.id));
1952
+ }
1953
+ //#endregion
1954
+ //#region src/hooks/node-actions.ts
1955
+ function resolveNode(driveId, node) {
1956
+ return node?.id !== driveId ? node : void 0;
1957
+ }
1958
+ function useNodeActions() {
1959
+ const [selectedDrive] = useSelectedDriveSafe();
1960
+ const selectedFolder = useSelectedFolder();
1961
+ const selectedParentFolder = useFolderById(useSelectedNode()?.parentFolder);
1962
+ const selectedDriveId = selectedDrive?.header.id;
1963
+ const drives = useDrives();
1964
+ async function onAddFile(file, parent) {
1965
+ if (!selectedDriveId) return;
1966
+ return addFile(file, selectedDriveId, file.name.replace(/\..+/gim, ""), resolveNode(selectedDriveId, parent)?.id);
1967
+ }
1968
+ async function onAddFolder(name, parent) {
1969
+ if (!selectedDriveId) return;
1970
+ return addFolder(selectedDriveId, name, resolveNode(selectedDriveId, parent)?.id);
1971
+ }
1972
+ async function onRenameNode(newName, node) {
1973
+ if (!selectedDriveId) return;
1974
+ if (!resolveNode(selectedDriveId, node)) {
1975
+ console.error(`Node ${node.id} not found`);
1976
+ return;
1977
+ }
1978
+ return await renameNode(selectedDriveId, node.id, newName);
1979
+ }
1980
+ async function onCopyNode(src, target) {
1981
+ if (!selectedDriveId) return;
1982
+ const resolvedSrc = resolveNode(selectedDriveId, src);
1983
+ if (!resolvedSrc) {
1984
+ console.error(`Node ${src.id} not found`);
1985
+ return;
1986
+ }
1987
+ await copyNode$1(selectedDriveId, resolvedSrc, resolveNode(selectedDriveId, target));
1988
+ }
1989
+ async function onMoveNode(src, target) {
1990
+ if (!selectedDriveId) return;
1991
+ const resolvedSrc = resolveNode(selectedDriveId, src);
1992
+ if (!resolvedSrc) {
1993
+ console.error(`Node ${src.id} not found`);
1994
+ return;
1995
+ }
1996
+ const resolvedTarget = resolveNode(selectedDriveId, target);
1997
+ if (!resolvedTarget?.id && !src.parentFolder || resolvedTarget?.id === src.parentFolder) return;
1998
+ await moveNode$1(selectedDriveId, resolvedSrc, resolvedTarget);
1999
+ }
2000
+ async function onDuplicateNode(src) {
2001
+ if (!selectedDriveId) return;
2002
+ const resolvedSrc = resolveNode(selectedDriveId, src);
2003
+ if (!resolvedSrc) {
2004
+ console.error(`Node ${src.id} not found`);
2005
+ return;
2006
+ }
2007
+ await copyNode$1(selectedDriveId, resolvedSrc, resolveNode(selectedDriveId, selectedFolder ?? selectedParentFolder));
2008
+ }
2009
+ async function onAddAndSelectNewFolder(name) {
2010
+ if (!name) return;
2011
+ if (!selectedDriveId) return;
2012
+ const resolvedTarget = resolveNode(selectedDriveId, selectedFolder ?? selectedParentFolder);
2013
+ if (!resolvedTarget) return;
2014
+ const newFolder = await onAddFolder(name, resolvedTarget);
2015
+ if (newFolder) setSelectedNode(newFolder);
2016
+ }
2017
+ async function onRenameDriveNodes(newName, nodeId) {
2018
+ if (!drives) return;
2019
+ const drivesWithNode = drives.filter((drive) => drive.state.global.nodes.some((n) => n.id === nodeId));
2020
+ await Promise.all(drivesWithNode.map((drive) => renameDriveNode(drive.header.id, nodeId, newName)));
2021
+ }
2022
+ return {
2023
+ onAddFile,
2024
+ onAddFolder,
2025
+ onRenameNode,
2026
+ onCopyNode,
2027
+ onMoveNode,
2028
+ onDuplicateNode,
2029
+ onAddAndSelectNewFolder,
2030
+ onRenameDriveNodes
2031
+ };
2032
+ }
2033
+ //#endregion
2034
+ //#region src/hooks/node-by-id.ts
2035
+ /** Returns a node in the selected drive by id. */
2036
+ function useNodeById(id) {
2037
+ return useNodesInSelectedDrive()?.find((n) => n.id === id);
2038
+ }
2039
+ //#endregion
2040
+ //#region src/hooks/node-path.ts
2041
+ /** Returns the path to a node in the selected drive */
2042
+ function useNodePathById(id) {
2043
+ const nodes = useNodesInSelectedDrive();
2044
+ if (!nodes) return [];
2045
+ const path = [];
2046
+ let current = nodes.find((n) => n.id === id);
2047
+ while (current) {
2048
+ path.push(current);
2049
+ if (!current.parentFolder) break;
2050
+ current = nodes.find((n) => n.id === current?.parentFolder);
2051
+ }
2052
+ return path.reverse();
2053
+ }
2054
+ /** Returns the path to the currently selected node in the selected drive. */
2055
+ function useSelectedNodePath() {
2056
+ return useNodePathById(useSelectedNode()?.id);
2057
+ }
2058
+ //#endregion
2059
+ //#region src/hooks/parent-folder.ts
2060
+ function useNodeParentFolderById(id) {
2061
+ return useFolderById(useNodeById(id)?.parentFolder);
2062
+ }
2063
+ function useParentFolderForSelectedNode() {
2064
+ return useNodeParentFolderById(useSelectedNode()?.id);
2065
+ }
2066
+ //#endregion
2067
+ //#region src/hooks/selected-document.ts
2068
+ /** Returns the selected document id */
2069
+ function useSelectedDocumentId() {
2070
+ const selectedNode = useSelectedNode();
2071
+ return selectedNode && isFileNode(selectedNode) ? selectedNode.id : void 0;
2072
+ }
2073
+ /** Returns the selected document. */
2074
+ function useSelectedDocument() {
2075
+ const [document, dispatch] = useDocumentById(useSelectedDocumentId());
2076
+ if (!document) throw new NoSelectedDocumentError();
2077
+ return [document, dispatch];
2078
+ }
2079
+ /** Returns the selected document. */
2080
+ function useSelectedDocumentSafe() {
2081
+ return useDocumentById(useSelectedDocumentId());
2082
+ }
2083
+ function useSelectedDocumentOfType(documentType) {
2084
+ const documentId = useSelectedDocumentId();
2085
+ if (!documentType) return [];
2086
+ if (!documentId) throw new NoSelectedDocumentError();
2087
+ return useDocumentOfType(documentId, documentType);
2088
+ }
2089
+ //#endregion
2090
+ //#region src/hooks/subgraph-modules.ts
2091
+ function useSubgraphModules() {
2092
+ return useVetraPackages().flatMap((pkg) => pkg.subgraphs || []);
2093
+ }
2094
+ //#endregion
2095
+ //#region src/hooks/use-drive-system-info.ts
2096
+ function deriveSystemUrl(channelUrl) {
2097
+ try {
2098
+ const url = new URL(channelUrl);
2099
+ url.search = "";
2100
+ url.hash = "";
2101
+ if (url.pathname.endsWith("/graphql/r")) url.pathname = url.pathname.slice(0, -10) + "/graphql/system";
2102
+ else url.pathname = "/graphql/system";
2103
+ return url.toString();
2104
+ } catch {
2105
+ return null;
2106
+ }
2107
+ }
2108
+ const cache = /* @__PURE__ */ new Map();
2109
+ function useDriveSystemInfo(drive) {
2110
+ const remotes = useSyncList();
2111
+ const driveId = drive?.header.id;
2112
+ const systemUrl = useMemo(() => {
2113
+ if (!driveId) return null;
2114
+ const channelUrl = (remotes.find((r) => r.collectionId === driveCollectionId$1("main", driveId))?.channel)?.config.url;
2115
+ if (typeof channelUrl !== "string") return null;
2116
+ return deriveSystemUrl(channelUrl);
2117
+ }, [remotes, driveId]);
2118
+ const [state, setState] = useState(() => systemUrl ? cache.get(systemUrl) ?? { status: "loading" } : { status: "local" });
2119
+ useEffect(() => {
2120
+ if (!systemUrl) {
2121
+ setState({ status: "local" });
2122
+ return;
2123
+ }
2124
+ const cached = cache.get(systemUrl);
2125
+ if (cached && cached.status !== "loading") {
2126
+ setState(cached);
2127
+ return;
2128
+ }
2129
+ setState({ status: "loading" });
2130
+ cache.set(systemUrl, { status: "loading" });
2131
+ const controller = new AbortController();
2132
+ fetch(systemUrl, {
2133
+ method: "POST",
2134
+ headers: { "Content-Type": "application/json" },
2135
+ body: JSON.stringify({ query: "{ system { version gitHash gitUrl } }" }),
2136
+ signal: controller.signal
2137
+ }).then(async (res) => {
2138
+ const json = await res.json();
2139
+ if (json.errors?.length) throw new Error(json.errors.map((e) => e.message).join("; "));
2140
+ const sys = json.data?.system;
2141
+ if (!sys) throw new Error("Missing system in response");
2142
+ const next = {
2143
+ status: "ready",
2144
+ version: sys.version,
2145
+ gitHash: sys.gitHash,
2146
+ gitUrl: sys.gitUrl ?? null,
2147
+ host: new URL(systemUrl).host
2148
+ };
2149
+ cache.set(systemUrl, next);
2150
+ setState(next);
2151
+ }).catch((err) => {
2152
+ if (controller.signal.aborted) return;
2153
+ const message = err instanceof Error ? err.message : String(err);
2154
+ console.error(message);
2155
+ const next = {
2156
+ status: "error",
2157
+ message
2158
+ };
2159
+ cache.set(systemUrl, next);
2160
+ setState(next);
2161
+ });
2162
+ return () => controller.abort();
2163
+ }, [systemUrl]);
2164
+ return state;
2165
+ }
2166
+ //#endregion
2167
+ //#region src/utils/drives.ts
2168
+ const syncStatusToUI = {
2169
+ [SyncStatus.Synced]: "SUCCESS",
2170
+ [SyncStatus.Outgoing]: "SYNCING",
2171
+ [SyncStatus.Incoming]: "SYNCING",
2172
+ [SyncStatus.OutgoingAndIncoming]: "SYNCING",
2173
+ [SyncStatus.Error]: "ERROR"
2174
+ };
2175
+ async function getDrives(reactor) {
2176
+ return (await reactor.find({ type: "powerhouse/document-drive" })).results;
2177
+ }
2178
+ function getSyncStatus(documentId, sharingType) {
2179
+ return Promise.resolve(getSyncStatusSync(documentId, sharingType));
2180
+ }
2181
+ function getSyncStatusSync(documentId, sharingType) {
2182
+ if (sharingType === "LOCAL") return;
2183
+ const syncManager = window.ph?.reactorClientModule?.reactorModule?.syncModule?.syncManager;
2184
+ if (!syncManager) return;
2185
+ const status = syncManager.getSyncStatus(documentId);
2186
+ if (status === void 0) return;
2187
+ return syncStatusToUI[status];
2188
+ }
2189
+ //#endregion
2190
+ //#region src/utils/validate-document.ts
2191
+ const validateDocument = (document) => {
2192
+ const errors = [];
2193
+ if (document.header.documentType !== "powerhouse/document-model") return errors;
2194
+ const doc = document;
2195
+ const specs = doc.state.global.specifications[0];
2196
+ const initialStateErrors = Object.keys(specs.state).reduce((acc, scopeKey) => {
2197
+ const scope = scopeKey;
2198
+ return [...acc, ...validateInitialState(specs.state[scope].initialValue, scope !== "global").map((err) => ({
2199
+ ...err,
2200
+ message: `${err.message}. Scope: ${scope}`,
2201
+ details: {
2202
+ ...err.details,
2203
+ scope
2204
+ }
2205
+ }))];
2206
+ }, []);
2207
+ const schemaStateErrors = Object.keys(specs.state).reduce((acc, scopeKey) => {
2208
+ const scope = scopeKey;
2209
+ const isGlobalScope = scope === "global";
2210
+ return [...acc, ...validateStateSchemaName(specs.state[scope].schema, doc.state.global?.name || doc.header.name || "", !isGlobalScope ? scope : "", !isGlobalScope).map((err) => ({
2211
+ ...err,
2212
+ message: `${err.message}. Scope: ${scope}`,
2213
+ details: {
2214
+ ...err.details,
2215
+ scope
2216
+ }
2217
+ }))];
2218
+ }, []);
2219
+ const modulesErrors = validateModules(specs.modules);
2220
+ return [
2221
+ ...initialStateErrors,
2222
+ ...schemaStateErrors,
2223
+ ...modulesErrors
2224
+ ];
2225
+ };
2226
+ //#endregion
2227
+ //#region src/utils/export-document.ts
2228
+ const exportDocument = (document) => {
2229
+ if (!document) return;
2230
+ if (validateDocument(document).length) showPHModal({
2231
+ type: "exportDocumentWithErrors",
2232
+ documentId: document.header.id
2233
+ });
2234
+ else return exportFile(document);
2235
+ };
2236
+ //#endregion
2237
+ //#region src/utils/get-revision-from-date.ts
2238
+ const getRevisionFromDate = (startDate, endDate, operations = []) => {
2239
+ if (!startDate || !endDate) return 0;
2240
+ const operation = operations.find((operation) => {
2241
+ const operationDate = new Date(operation.timestampUtcMs);
2242
+ return operationDate >= startDate && operationDate <= endDate;
2243
+ });
2244
+ return operation ? operation.index : 0;
2245
+ };
2246
+ //#endregion
2247
+ //#region src/utils/switchboard.ts
2248
+ async function getDriveIdBySlug(driveUrl, slug) {
2249
+ if (!driveUrl) return;
2250
+ const urlParts = driveUrl.split("/");
2251
+ urlParts.pop();
2252
+ urlParts.pop();
2253
+ urlParts.push("drives");
2254
+ const drivesUrl = urlParts.join("/");
2255
+ return (await (await fetch(drivesUrl, {
2256
+ method: "POST",
2257
+ headers: { "Content-Type": "application/json" },
2258
+ body: JSON.stringify({
2259
+ query: `
2260
+ query getDriveIdBySlug($slug: String!) {
2261
+ driveIdBySlug(slug: $slug)
2262
+ }
2263
+ `,
2264
+ variables: { slug }
2265
+ })
2266
+ })).json()).data.driveIdBySlug;
2267
+ }
2268
+ function getSlugFromDriveUrl(driveUrl) {
2269
+ return driveUrl.split("/").pop();
2270
+ }
2271
+ function getSwitchboardGatewayUrlFromDriveUrl(driveUrl) {
2272
+ const urlParts = driveUrl.split("/");
2273
+ urlParts.pop();
2274
+ urlParts.pop();
2275
+ urlParts.push("graphql");
2276
+ return urlParts.join("/");
2277
+ }
2278
+ function getDocumentGraphqlQuery() {
2279
+ const loc = GetDocumentWithOperationsDocument.loc;
2280
+ if (!loc) throw new Error("GetDocumentWithOperationsDocument is misconfigured, loc is missing.");
2281
+ return loc.source.body;
2282
+ }
2283
+ function buildDocumentSubgraphQuery(identifier, authToken) {
2284
+ const query = getDocumentGraphqlQuery();
2285
+ const variables = { identifier };
2286
+ const headers = authToken ? { Authorization: `Bearer ${authToken}` } : void 0;
2287
+ const payload = {
2288
+ document: query.trim(),
2289
+ variables: JSON.stringify(variables, null, 2)
2290
+ };
2291
+ if (headers) payload.headers = JSON.stringify(headers);
2292
+ return lzString.compressToEncodedURIComponent(JSON.stringify(payload));
2293
+ }
2294
+ function buildDocumentSubgraphUrl(driveUrl, identifier, authToken) {
2295
+ return `${driveUrl}?explorerURLState=${buildDocumentSubgraphQuery(identifier, authToken)}`;
2296
+ }
2297
+ //#endregion
2298
+ //#region src/hooks/use-get-switchboard-link.ts
2299
+ /**
2300
+ * Hook that returns a function to generate a document's switchboard URL.
2301
+ * Only returns a function for documents in remote drives.
2302
+ * Returns null for local drives or when the document/drive cannot be determined.
2303
+ *
2304
+ * The returned function generates a fresh bearer token and builds the switchboard URL
2305
+ * with authentication when called.
2306
+ *
2307
+ * @param document - The document to create a switchboard URL generator for
2308
+ * @returns An async function that returns the switchboard URL, or null if not applicable
2309
+ */
2310
+ function useGetSwitchboardLink(document) {
2311
+ const [drive] = useSelectedDrive();
2312
+ const remotes = useSyncList();
2313
+ const isRemoteDrive = useMemo(() => {
2314
+ return remotes.some((remote) => remote.collectionId === driveCollectionId$1("main", drive.header.id));
2315
+ }, [remotes, drive]);
2316
+ const remoteUrl = useMemo(() => {
2317
+ try {
2318
+ const channelUrl = (remotes.find((remote) => remote.collectionId === driveCollectionId$1("main", drive.header.id))?.channel)?.config.url;
2319
+ if (typeof channelUrl === "string") return channelUrl;
2320
+ return null;
2321
+ } catch (error) {
2322
+ console.error("Error determining remote URL:", error);
2323
+ return null;
2324
+ }
2325
+ }, [remotes, drive]);
2326
+ const renown = useRenown();
2327
+ const user = useUser();
2328
+ return useMemo(() => {
2329
+ if (!isRemoteDrive || !document?.header.id || !remoteUrl) return null;
2330
+ return async () => {
2331
+ const token = user?.address ? await renown?.getBearerToken({
2332
+ expiresIn: 600,
2333
+ aud: remoteUrl
2334
+ }) : void 0;
2335
+ return buildDocumentSubgraphUrl(remoteUrl, document.header.id, token);
2336
+ };
2337
+ }, [
2338
+ isRemoteDrive,
2339
+ remoteUrl,
2340
+ document,
2341
+ user,
2342
+ renown
2343
+ ]);
2344
+ }
2345
+ //#endregion
2346
+ //#region src/hooks/use-on-drop-file.ts
2347
+ const useOnDropFile = (documentTypesOverride) => {
2348
+ const selectedDriveId = useSelectedDriveId();
2349
+ const selectedFolder = useSelectedFolder();
2350
+ const documentTypes = useDocumentTypes();
2351
+ const onDropFile = async (file, onProgress, resolveConflict) => {
2352
+ if (!selectedDriveId) {
2353
+ console.warn("No selected drive - upload skipped");
2354
+ return;
2355
+ }
2356
+ const fileName = file.name.replace(/\..+/gim, "");
2357
+ const targetNodeId = selectedFolder?.id;
2358
+ return await addFileWithProgress(file, selectedDriveId, fileName, targetNodeId, onProgress, documentTypesOverride ?? documentTypes, resolveConflict);
2359
+ };
2360
+ return onDropFile;
2361
+ };
2362
+ //#endregion
2363
+ //#region src/hooks/user-permissions.ts
2364
+ function useUserPermissions() {
2365
+ const user = useUser();
2366
+ const allowList = useAllowList();
2367
+ if (!allowList) return {
2368
+ isAllowedToCreateDocuments: true,
2369
+ isAllowedToEditDocuments: true
2370
+ };
2371
+ return {
2372
+ isAllowedToCreateDocuments: allowList.includes(user?.address ?? ""),
2373
+ isAllowedToEditDocuments: allowList.includes(user?.address ?? "")
2374
+ };
2375
+ }
2376
+ //#endregion
2377
+ //#region src/pglite/drop.ts
2378
+ async function dropTablesInSchema(pg, schema) {
2379
+ await pg.exec(`
2380
+ DO $$
2381
+ DECLARE
2382
+ _schemaname text := '${schema}';
2383
+ _tablename text;
2384
+ BEGIN
2385
+ FOR _tablename IN SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = _schemaname LOOP
2386
+ RAISE INFO 'Dropping table %.%', _schemaname, _tablename;
2387
+ EXECUTE format('DROP TABLE %I.%I CASCADE;', _schemaname, _tablename);
2388
+ END LOOP;
2389
+ IF NOT FOUND THEN
2390
+ RAISE WARNING 'Schema % does not exist', _schemaname;
2391
+ END IF;
2392
+ END $$;
2393
+ `);
2394
+ }
2395
+ async function truncateAllTables(pg, schema = REACTOR_SCHEMA$1) {
2396
+ await dropTablesInSchema(pg, schema);
2397
+ }
2398
+ async function dropAllReactorStorage(pg) {
2399
+ await dropTablesInSchema(pg, REACTOR_SCHEMA$1);
2400
+ await dropTablesInSchema(pg, "public");
2401
+ }
2402
+ //#endregion
2403
+ //#region src/reactor.ts
2404
+ const DEFAULT_DEBOUNCE_DELAY_MS = 200;
2405
+ const DEFAULT_IMMEDIATE_THRESHOLD_MS = 1e3;
2406
+ async function _refreshReactorData(reactor) {
2407
+ setDrives(await getDrives(reactor));
2408
+ }
2409
+ async function _refreshReactorDataClient(reactor) {
2410
+ if (!reactor) return;
2411
+ setDrives((await reactor.find({ type: "powerhouse/document-drive" })).results);
2412
+ }
2413
+ function createDebouncedRefreshReactorData(debounceDelayMs = DEFAULT_DEBOUNCE_DELAY_MS, immediateThresholdMs = DEFAULT_IMMEDIATE_THRESHOLD_MS) {
2414
+ let timeout = null;
2415
+ let lastRefreshTime = 0;
2416
+ return (reactor, immediate = false) => {
2417
+ const now = Date.now();
2418
+ const timeSinceLastRefresh = now - lastRefreshTime;
2419
+ if (timeout !== null) clearTimeout(timeout);
2420
+ if (immediate || timeSinceLastRefresh >= immediateThresholdMs) {
2421
+ lastRefreshTime = now;
2422
+ return _refreshReactorData(reactor);
2423
+ }
2424
+ return new Promise((resolve) => {
2425
+ timeout = setTimeout(() => {
2426
+ lastRefreshTime = Date.now();
2427
+ _refreshReactorData(reactor).then(resolve);
2428
+ }, debounceDelayMs);
2429
+ });
2430
+ };
2431
+ }
2432
+ function createDebouncedRefreshReactorDataClient(debounceDelayMs = DEFAULT_DEBOUNCE_DELAY_MS, immediateThresholdMs = DEFAULT_IMMEDIATE_THRESHOLD_MS) {
2433
+ let timeout = null;
2434
+ let lastRefreshTime = 0;
2435
+ return (reactor, immediate = false) => {
2436
+ const now = Date.now();
2437
+ const timeSinceLastRefresh = now - lastRefreshTime;
2438
+ if (timeout !== null) clearTimeout(timeout);
2439
+ if (immediate || timeSinceLastRefresh >= immediateThresholdMs) {
2440
+ lastRefreshTime = now;
2441
+ return _refreshReactorDataClient(reactor);
2442
+ }
2443
+ return new Promise((resolve) => {
2444
+ timeout = setTimeout(() => {
2445
+ lastRefreshTime = Date.now();
2446
+ _refreshReactorDataClient(reactor).then(resolve);
2447
+ }, debounceDelayMs);
2448
+ });
2449
+ };
2450
+ }
2451
+ const refreshReactorData = createDebouncedRefreshReactorData();
2452
+ const refreshReactorDataClient = createDebouncedRefreshReactorDataClient();
2453
+ //#endregion
2454
+ //#region src/registry/fetchers.ts
2455
+ function trimTrailingSlash(url) {
2456
+ return url.endsWith("/") ? url.slice(0, -1) : url;
2457
+ }
2458
+ async function getPackages(registryUrl) {
2459
+ const res = await fetch(`${trimTrailingSlash(registryUrl)}/packages`);
2460
+ if (!res.ok) throw new Error(`Registry error: HTTP ${res.status}`);
2461
+ return await res.json();
2462
+ }
2463
+ async function getPackagesByDocumentType(registryUrl, documentType) {
2464
+ const encodedType = encodeURIComponent(documentType);
2465
+ const res = await fetch(`${trimTrailingSlash(registryUrl)}/packages/by-document-type?type=${encodedType}`);
2466
+ if (!res.ok) throw new Error(`Registry error: HTTP ${res.status}`);
2467
+ return await res.json();
2468
+ }
2469
+ //#endregion
2470
+ //#region src/registry/client.ts
2471
+ function cdnUrlToApiUrl(cdnUrl) {
2472
+ return cdnUrl.replace(/\/-\/cdn\/?$/, "");
2473
+ }
2474
+ var RegistryClient = class {
2475
+ apiUrl;
2476
+ constructor(cdnUrl) {
2477
+ this.apiUrl = cdnUrlToApiUrl(cdnUrl);
2478
+ }
2479
+ async getPackages() {
2480
+ return await getPackages(this.apiUrl);
2481
+ }
2482
+ async getPackagesByDocumentType(documentType) {
2483
+ return await getPackagesByDocumentType(this.apiUrl, documentType);
2484
+ }
2485
+ async searchPackages(query) {
2486
+ const packages = await this.getPackages();
2487
+ if (!query) return packages;
2488
+ const lowerQuery = query.toLowerCase();
2489
+ return packages.filter((pkg) => pkg.name.toLowerCase().includes(lowerQuery) || pkg.manifest?.description?.toLowerCase().includes(lowerQuery));
2490
+ }
2491
+ onPublish(callback) {
2492
+ const eventSource = new EventSource(`${this.apiUrl}/-/events`);
2493
+ eventSource.addEventListener("publish", (e) => {
2494
+ callback(JSON.parse(e.data));
2495
+ });
2496
+ return () => {
2497
+ eventSource.close();
2498
+ };
2499
+ }
2500
+ };
2501
+ //#endregion
2502
+ //#region src/remote-controller/action-tracker.ts
2503
+ /**
2504
+ * Tracks pending actions with their operation context (prevOpHash, prevOpIndex).
2505
+ * Actions are accumulated until flushed (on push).
2506
+ */
2507
+ var ActionTracker = class {
2508
+ pending = [];
2509
+ /** Track a new action with its operation context. */
2510
+ track(action, prevOpHash, prevOpIndex) {
2511
+ this.pending.push({
2512
+ action,
2513
+ prevOpHash,
2514
+ prevOpIndex
2515
+ });
2516
+ }
2517
+ /** Flush all pending actions and return them. Clears the internal queue. */
2518
+ flush() {
2519
+ const actions = this.pending;
2520
+ this.pending = [];
2521
+ return actions;
2522
+ }
2523
+ /** Number of pending actions. */
2524
+ get count() {
2525
+ return this.pending.length;
2526
+ }
2527
+ /** Prepend previously flushed actions back to the queue (for retry on failure). */
2528
+ restore(actions) {
2529
+ this.pending = [...actions, ...this.pending];
2530
+ }
2531
+ /** Clear all pending actions without returning them. */
2532
+ clear() {
2533
+ this.pending = [];
2534
+ }
2535
+ };
2536
+ //#endregion
2537
+ //#region src/remote-controller/remote-client.ts
2538
+ /**
2539
+ * Thin facade over the GraphQL SDK for remote document operations.
2540
+ */
2541
+ const DEFAULT_PAGE_SIZE = 100;
2542
+ var RemoteClient = class {
2543
+ pageSize;
2544
+ constructor(client, pageSize) {
2545
+ this.client = client;
2546
+ this.pageSize = pageSize ?? DEFAULT_PAGE_SIZE;
2547
+ }
2548
+ /** Fetch a document by identifier. Returns null if not found. */
2549
+ async getDocument(identifier, branch) {
2550
+ return (await this.client.GetDocument({
2551
+ identifier,
2552
+ view: branch ? { branch } : void 0
2553
+ })).document ?? null;
2554
+ }
2555
+ /**
2556
+ * Fetch a document and its operations.
2557
+ *
2558
+ * When scopes are provided and BatchGetDocumentWithOperations is available,
2559
+ * fetches the document and per-scope operations in a single HTTP request.
2560
+ * Otherwise falls back to GetDocumentWithOperations for the first page,
2561
+ * then paginates remaining operations per scope.
2562
+ */
2563
+ async getDocumentWithOperations(identifier, branch, sinceRevision, scopes) {
2564
+ if (this.client.BatchGetDocumentWithOperations && scopes && scopes.length > 0) return this.batchGetDocumentWithOperations(identifier, branch, sinceRevision, scopes);
2565
+ const result = await this.client.GetDocumentWithOperations({
2566
+ identifier,
2567
+ view: branch ? { branch } : void 0,
2568
+ operationsPaging: {
2569
+ limit: this.pageSize,
2570
+ cursor: null
2571
+ }
2572
+ });
2573
+ if (!result.document) return null;
2574
+ const doc = result.document.document;
2575
+ const opsPage = doc.operations;
2576
+ const operationsByScope = {};
2577
+ if (opsPage) for (const op of opsPage.items) (operationsByScope[op.action.scope] ??= []).push(op);
2578
+ const expectedTotal = doc.revisionsList.reduce((sum, r) => sum + r.revision, 0);
2579
+ if ((opsPage?.items.length ?? 0) >= expectedTotal) return {
2580
+ document: doc,
2581
+ childIds: result.document.childIds,
2582
+ operations: { operationsByScope }
2583
+ };
2584
+ const allScopes = doc.revisionsList.map((r) => r.scope);
2585
+ const allOps = await this.getAllOperations(doc.id, branch, sinceRevision, allScopes);
2586
+ return {
2587
+ document: doc,
2588
+ childIds: result.document.childIds,
2589
+ operations: allOps
2590
+ };
2591
+ }
2592
+ /**
2593
+ * Fetch document + per-scope operations in a single HTTP request
2594
+ * via BatchGetDocumentWithOperations, then paginate any remaining pages.
2595
+ */
2596
+ async batchGetDocumentWithOperations(identifier, branch, sinceRevision, scopes) {
2597
+ const view = branch ? { branch } : void 0;
2598
+ const filters = scopes.map((scope) => ({
2599
+ documentId: identifier,
2600
+ branch: branch ?? null,
2601
+ sinceRevision: sinceRevision?.[scope] ?? 0,
2602
+ scopes: [scope]
2603
+ }));
2604
+ const pagings = scopes.map(() => ({
2605
+ limit: this.pageSize,
2606
+ cursor: null
2607
+ }));
2608
+ const result = await this.client.BatchGetDocumentWithOperations(identifier, view, filters, pagings);
2609
+ if (!result.document) return null;
2610
+ const operationsByScope = {};
2611
+ let pending = [];
2612
+ for (let i = 0; i < scopes.length; i++) {
2613
+ const page = result.operations[i];
2614
+ for (const op of page.items) (operationsByScope[op.action.scope] ??= []).push(op);
2615
+ if (page.hasNextPage && page.cursor) pending.push({
2616
+ scope: scopes[i],
2617
+ filter: filters[i],
2618
+ cursor: page.cursor
2619
+ });
2620
+ }
2621
+ while (pending.length > 0) {
2622
+ const pages = await this.fetchOperationPages(pending.map((p) => p.filter), pending.map((p) => ({
2623
+ limit: this.pageSize,
2624
+ cursor: p.cursor
2625
+ })));
2626
+ const nextPending = [];
2627
+ for (let i = 0; i < pending.length; i++) {
2628
+ const page = pages[i];
2629
+ for (const op of page.items) (operationsByScope[op.action.scope] ??= []).push(op);
2630
+ if (page.hasNextPage && page.cursor) nextPending.push({
2631
+ ...pending[i],
2632
+ cursor: page.cursor
2633
+ });
2634
+ }
2635
+ pending = nextPending;
2636
+ }
2637
+ return {
2638
+ document: result.document.document,
2639
+ childIds: result.document.childIds,
2640
+ operations: { operationsByScope }
2641
+ };
2642
+ }
2643
+ /**
2644
+ * Fetch all operations for a document, paginating through all pages.
2645
+ * Each scope is queried individually because the API only returns
2646
+ * pagination cursors for single-scope queries.
2647
+ */
2648
+ async getAllOperations(documentId, branch, sinceRevision, scopes) {
2649
+ if (scopes && scopes.length > 0) {
2650
+ const operationsByScope = {};
2651
+ let pending = scopes.map((scope) => ({
2652
+ scope,
2653
+ filter: {
2654
+ documentId,
2655
+ branch: branch ?? null,
2656
+ sinceRevision: sinceRevision?.[scope] ?? 0,
2657
+ scopes: [scope]
2658
+ },
2659
+ cursor: null
2660
+ }));
2661
+ while (pending.length > 0) {
2662
+ const pages = await this.fetchOperationPages(pending.map((p) => p.filter), pending.map((p) => ({
2663
+ limit: this.pageSize,
2664
+ cursor: p.cursor
2665
+ })));
2666
+ const nextPending = [];
2667
+ for (let i = 0; i < pending.length; i++) {
2668
+ const page = pages[i];
2669
+ for (const op of page.items) (operationsByScope[op.action.scope] ??= []).push(op);
2670
+ if (page.hasNextPage && page.cursor) nextPending.push({
2671
+ ...pending[i],
2672
+ cursor: page.cursor
2673
+ });
2674
+ }
2675
+ pending = nextPending;
2676
+ }
2677
+ return { operationsByScope };
2678
+ }
2679
+ return this.fetchOperationsForScope(documentId, branch);
2680
+ }
2681
+ /**
2682
+ * Fetch one page of operations per filter.
2683
+ * Uses the composed query (single HTTP request) when available,
2684
+ * otherwise falls back to parallel individual requests.
2685
+ */
2686
+ async fetchOperationPages(filters, pagings) {
2687
+ if (this.client.BatchGetDocumentOperations) return this.client.BatchGetDocumentOperations(filters, pagings);
2688
+ return Promise.all(filters.map((filter, i) => this.client.GetDocumentOperations({
2689
+ filter,
2690
+ paging: pagings[i]
2691
+ }).then((r) => r.documentOperations)));
2692
+ }
2693
+ /** Fetch all pages of operations for a single scope (or all scopes if none specified). */
2694
+ async fetchOperationsForScope(documentId, branch, sinceRevision, scope) {
2695
+ const operationsByScope = {};
2696
+ let cursor;
2697
+ let hasNextPage = true;
2698
+ while (hasNextPage) {
2699
+ const page = (await this.client.GetDocumentOperations({
2700
+ filter: {
2701
+ documentId,
2702
+ branch: branch ?? null,
2703
+ sinceRevision: sinceRevision ?? 0,
2704
+ scopes: scope ? [scope] : null
2705
+ },
2706
+ paging: {
2707
+ limit: this.pageSize,
2708
+ cursor: cursor ?? null
2709
+ }
2710
+ })).documentOperations;
2711
+ for (const op of page.items) {
2712
+ const s = op.action.scope;
2713
+ (operationsByScope[s] ??= []).push(op);
2714
+ }
2715
+ hasNextPage = page.hasNextPage;
2716
+ cursor = page.cursor;
2717
+ }
2718
+ return { operationsByScope };
2719
+ }
2720
+ /** Push actions to an existing document via MutateDocument. */
2721
+ async pushActions(documentIdentifier, actions, branch) {
2722
+ return (await this.client.MutateDocument({
2723
+ documentIdentifier,
2724
+ actions,
2725
+ view: branch ? { branch } : void 0
2726
+ })).mutateDocument;
2727
+ }
2728
+ /** Create a new document on the remote. */
2729
+ async createDocument(document, parentIdentifier) {
2730
+ return (await this.client.CreateDocument({
2731
+ document,
2732
+ parentIdentifier: parentIdentifier ?? null
2733
+ })).createDocument;
2734
+ }
2735
+ /** Create an empty document of a given type on the remote. */
2736
+ async createEmptyDocument(documentType, parentIdentifier) {
2737
+ return (await this.client.CreateEmptyDocument({
2738
+ documentType,
2739
+ parentIdentifier: parentIdentifier ?? null
2740
+ })).createEmptyDocument;
2741
+ }
2742
+ /** Delete a document on the remote. Returns true if successful. */
2743
+ async deleteDocument(identifier, propagate) {
2744
+ return (await this.client.DeleteDocument({
2745
+ identifier,
2746
+ propagate
2747
+ })).deleteDocument;
2748
+ }
2749
+ };
2750
+ //#endregion
2751
+ //#region src/remote-controller/utils.ts
2752
+ /** Convert SCREAMING_SNAKE_CASE to camelCase (e.g. "SET_MODEL_NAME" → "setModelName"). */
2753
+ function screamingSnakeToCamel(s) {
2754
+ return s.toLowerCase().replace(/_([a-z])/g, (_, c) => c.toUpperCase());
2755
+ }
2756
+ /** Error thrown when a push conflict is detected with the "reject" strategy. */
2757
+ var ConflictError = class extends Error {
2758
+ constructor(conflict) {
2759
+ super("Push conflict: remote has new operations since last pull");
2760
+ this.conflict = conflict;
2761
+ this.name = "ConflictError";
2762
+ }
2763
+ };
2764
+ /** Convert a remote operation to the local Operation type. */
2765
+ function remoteOperationToLocal(remote) {
2766
+ return {
2767
+ id: remote.id ?? "",
2768
+ index: remote.index,
2769
+ skip: remote.skip,
2770
+ timestampUtcMs: remote.timestampUtcMs,
2771
+ hash: remote.hash,
2772
+ error: remote.error ?? void 0,
2773
+ action: {
2774
+ id: remote.action.id,
2775
+ type: remote.action.type,
2776
+ timestampUtcMs: remote.action.timestampUtcMs,
2777
+ input: remote.action.input,
2778
+ scope: remote.action.scope,
2779
+ attachments: remote.action.attachments?.map((a) => ({
2780
+ data: a.data,
2781
+ mimeType: a.mimeType,
2782
+ hash: a.hash,
2783
+ extension: a.extension ?? void 0,
2784
+ fileName: a.fileName ?? void 0
2785
+ })),
2786
+ context: remote.action.context?.signer ? { signer: {
2787
+ user: remote.action.context.signer.user ?? {
2788
+ address: "",
2789
+ networkId: "",
2790
+ chainId: 0
2791
+ },
2792
+ app: remote.action.context.signer.app ?? {
2793
+ name: "",
2794
+ key: ""
2795
+ },
2796
+ signatures: remote.action.context.signer.signatures.map((s) => deserializeSignature(s))
2797
+ } } : void 0
2798
+ }
2799
+ };
2800
+ }
2801
+ /**
2802
+ * Deserialize a signature string back to a 5-element tuple.
2803
+ * The server serializes tuples via `tuple.join(", ")`.
2804
+ */
2805
+ function deserializeSignature(s) {
2806
+ const parts = s.split(", ");
2807
+ return [
2808
+ parts[0] ?? "",
2809
+ parts[1] ?? "",
2810
+ parts[2] ?? "",
2811
+ parts[3] ?? "",
2812
+ parts[4] ?? ""
2813
+ ];
2814
+ }
2815
+ /** Convert remote operations to local DocumentOperations format. */
2816
+ function convertRemoteOperations(operationsByScope) {
2817
+ const operations = {};
2818
+ for (const [scope, remoteOps] of Object.entries(operationsByScope)) operations[scope] = remoteOps.map((op) => remoteOperationToLocal(op));
2819
+ return operations;
2820
+ }
2821
+ /** Reconstruct a PHDocument from remote document data and operations. */
2822
+ function buildPulledDocument(remoteDoc, operations, initialDoc, branch) {
2823
+ return {
2824
+ header: {
2825
+ ...initialDoc.header,
2826
+ id: remoteDoc.id,
2827
+ name: remoteDoc.name,
2828
+ slug: remoteDoc.slug ?? "",
2829
+ documentType: remoteDoc.documentType,
2830
+ createdAtUtcIso: typeof remoteDoc.createdAtUtcIso === "string" ? remoteDoc.createdAtUtcIso : remoteDoc.createdAtUtcIso.toISOString(),
2831
+ lastModifiedAtUtcIso: typeof remoteDoc.lastModifiedAtUtcIso === "string" ? remoteDoc.lastModifiedAtUtcIso : remoteDoc.lastModifiedAtUtcIso.toISOString(),
2832
+ revision: Object.fromEntries(remoteDoc.revisionsList.map((r) => [r.scope, r.revision])),
2833
+ branch
2834
+ },
2835
+ state: remoteDoc.state,
2836
+ initialState: initialDoc.initialState,
2837
+ operations,
2838
+ clipboard: []
2839
+ };
2840
+ }
2841
+ /** Extract revision map from a remote document's revisionsList. */
2842
+ function extractRevisionMap(revisionsList) {
2843
+ return Object.fromEntries(revisionsList.map((r) => [r.scope, r.revision]));
2844
+ }
2845
+ /**
2846
+ * Check if any scope in currentRevision is ahead of knownRevision.
2847
+ * When `scopes` is provided, only those scopes are checked.
2848
+ */
2849
+ function hasRevisionConflict(currentRevision, knownRevision, scopes) {
2850
+ for (const scope in currentRevision) {
2851
+ if (scopes && !scopes.has(scope)) continue;
2852
+ if ((currentRevision[scope] ?? 0) > (knownRevision[scope] ?? 0)) return true;
2853
+ }
2854
+ return false;
2855
+ }
2856
+ //#endregion
2857
+ //#region src/remote-controller/remote-controller.ts
2858
+ /**
2859
+ * A controller that wraps a PHDocumentController with remote push/pull capabilities.
2860
+ * Composes a local controller and adds GraphQL-based sync with a reactor server.
2861
+ */
2862
+ var RemoteDocumentController = class RemoteDocumentController {
2863
+ inner;
2864
+ remoteClient;
2865
+ tracker = new ActionTracker();
2866
+ options;
2867
+ documentId;
2868
+ remoteRevision = {};
2869
+ hasPulled = false;
2870
+ pushScheduled = false;
2871
+ pushQueue = Promise.resolve();
2872
+ listeners = [];
2873
+ constructor(inner, options) {
2874
+ this.inner = inner;
2875
+ this.options = options;
2876
+ this.documentId = options.documentId ?? "";
2877
+ this.remoteClient = new RemoteClient(options.client, options.operationsPageSize);
2878
+ this.setupActionInterceptors();
2879
+ }
2880
+ get header() {
2881
+ return this.inner.header;
2882
+ }
2883
+ get state() {
2884
+ return this.inner.state;
2885
+ }
2886
+ get operations() {
2887
+ return this.inner.operations;
2888
+ }
2889
+ get document() {
2890
+ return this.inner.document;
2891
+ }
2892
+ get status() {
2893
+ return {
2894
+ pendingActionCount: this.tracker.count,
2895
+ connected: this.documentId !== "",
2896
+ documentId: this.documentId,
2897
+ remoteRevision: { ...this.remoteRevision }
2898
+ };
2899
+ }
2900
+ /** Register a listener for document changes. Returns an unsubscribe function. */
2901
+ onChange(listener) {
2902
+ this.listeners.push(listener);
2903
+ return () => {
2904
+ this.listeners = this.listeners.filter((l) => l !== listener);
2905
+ };
2906
+ }
2907
+ notifyListeners(source) {
2908
+ if (this.listeners.length === 0) return;
2909
+ const event = {
2910
+ source,
2911
+ document: this.document
2912
+ };
2913
+ for (const listener of this.listeners) listener(event);
2914
+ }
2915
+ /** Push all pending actions to remote, then pull latest state. */
2916
+ async push() {
2917
+ let tracked = this.tracker.flush();
2918
+ if (tracked.length === 0 && this.documentId !== "") return {
2919
+ remoteDocument: await this.pull(),
2920
+ actionCount: 0,
2921
+ operations: []
2922
+ };
2923
+ try {
2924
+ await this.ensureRemoteDocument();
2925
+ if (this.options.onConflict && tracked.length > 0) tracked = await this.handleConflicts(tracked, this.options.onConflict);
2926
+ } catch (error) {
2927
+ this.tracker.restore(tracked);
2928
+ throw error;
2929
+ }
2930
+ let pushedActions = [];
2931
+ try {
2932
+ if (tracked.length > 0) {
2933
+ const actions = await this.prepareActionsForPush(tracked);
2934
+ pushedActions = actions;
2935
+ await this.remoteClient.pushActions(this.documentId, actions, this.options.branch);
2936
+ }
2937
+ } catch (error) {
2938
+ this.tracker.restore(tracked);
2939
+ throw error;
2940
+ }
2941
+ return {
2942
+ remoteDocument: await this.pull(),
2943
+ actionCount: tracked.length,
2944
+ operations: pushedActions
2945
+ };
2946
+ }
2947
+ /** Delete the document on the remote. */
2948
+ async delete(propagate) {
2949
+ if (this.documentId === "") throw new Error("Cannot delete: no document ID set");
2950
+ return await this.remoteClient.deleteDocument(this.documentId, propagate);
2951
+ }
2952
+ /** Pull latest state from remote, replacing local document. Returns the remote document data. */
2953
+ async pull() {
2954
+ if (this.documentId === "") throw new Error("Cannot pull: no document ID set");
2955
+ const { remoteDoc, operations } = await this.fetchDocumentAndOperations();
2956
+ const pulledDocument = buildPulledDocument(remoteDoc, operations, this.inner.module.utils.createDocument(), this.options.branch ?? "main");
2957
+ const ControllerClass = this.inner.constructor;
2958
+ this.inner = new ControllerClass(pulledDocument);
2959
+ this.setupActionInterceptors();
2960
+ this.tracker.clear();
2961
+ this.remoteRevision = extractRevisionMap(remoteDoc.revisionsList);
2962
+ this.notifyListeners("pull");
2963
+ return remoteDoc;
2964
+ }
2965
+ /**
2966
+ * Pull an existing document from remote and create a controller for it.
2967
+ */
2968
+ static async pull(ControllerClass, options) {
2969
+ const remote = new RemoteDocumentController(new ControllerClass(), options);
2970
+ if (options.documentId) await remote.pull();
2971
+ return remote;
2972
+ }
2973
+ /**
2974
+ * Wrap an existing controller instance with remote capabilities.
2975
+ * Pending local actions on the inner controller are NOT tracked
2976
+ * (only new actions through the remote controller are tracked).
2977
+ */
2978
+ static from(controller, options) {
2979
+ return new RemoteDocumentController(controller, options);
2980
+ }
2981
+ /** Create the document on the remote if it doesn't exist yet. */
2982
+ async ensureRemoteDocument() {
2983
+ if (this.documentId !== "") return;
2984
+ this.documentId = (await this.remoteClient.createEmptyDocument(this.inner.header.documentType, this.options.parentIdentifier)).id;
2985
+ }
2986
+ /** Set up interceptors for all action methods on the inner controller. */
2987
+ setupActionInterceptors() {
2988
+ const module = this.inner["module"];
2989
+ for (const actionType in module.actions) {
2990
+ if (actionType in RemoteDocumentController.prototype) continue;
2991
+ Object.defineProperty(this, actionType, {
2992
+ value: (input) => {
2993
+ const opCountsBefore = {};
2994
+ for (const scope in this.inner.operations) opCountsBefore[scope] = this.inner.operations[scope].length;
2995
+ this.inner[actionType](input);
2996
+ const newOp = this.findNewOperation(opCountsBefore);
2997
+ const prevOp = newOp ? this.getLastOperationInScope(newOp.action.scope, newOp) : void 0;
2998
+ const prevOpHash = prevOp?.hash ?? "";
2999
+ const prevOpIndex = prevOp?.index ?? -1;
3000
+ if (!newOp) return this;
3001
+ this.tracker.track(newOp.action, prevOpHash, prevOpIndex);
3002
+ this.notifyListeners("action");
3003
+ if (this.options.mode === "streaming") this.schedulePush();
3004
+ return this;
3005
+ },
3006
+ enumerable: true,
3007
+ configurable: true
3008
+ });
3009
+ }
3010
+ }
3011
+ /**
3012
+ * Find the new operation added after applying an action,
3013
+ * by comparing current operation counts against a previous snapshot.
3014
+ */
3015
+ findNewOperation(opCountsBefore) {
3016
+ const ops = this.inner.operations;
3017
+ for (const scope in ops) {
3018
+ const scopeOps = ops[scope];
3019
+ const prevCount = opCountsBefore[scope] ?? 0;
3020
+ if (scopeOps.length > prevCount) return scopeOps[scopeOps.length - 1];
3021
+ }
3022
+ }
3023
+ /**
3024
+ * Get the last operation in a specific scope, optionally excluding
3025
+ * a given operation (e.g. the one just added).
3026
+ */
3027
+ getLastOperationInScope(scope, excludeOp) {
3028
+ const scopeOps = this.inner.operations[scope];
3029
+ if (scopeOps.length === 0) return void 0;
3030
+ for (let i = scopeOps.length - 1; i >= 0; i--) if (scopeOps[i] !== excludeOp) return scopeOps[i];
3031
+ }
3032
+ /**
3033
+ * Detect and handle conflicts between local pending actions and remote state.
3034
+ * Returns the (possibly rebased) tracked actions to push.
3035
+ */
3036
+ async handleConflicts(localTracked, strategy) {
3037
+ const remoteResult = await this.remoteClient.getDocument(this.documentId, this.options.branch);
3038
+ if (!remoteResult) throw new Error(`Document "${this.documentId}" not found on remote`);
3039
+ const currentRevision = extractRevisionMap(remoteResult.document.revisionsList);
3040
+ const localScopes = new Set(localTracked.map((t) => t.action.scope));
3041
+ if (!hasRevisionConflict(currentRevision, this.remoteRevision, localScopes)) return localTracked;
3042
+ const conflictingScopes = [...localScopes].filter((scope) => (currentRevision[scope] ?? 0) > (this.remoteRevision[scope] ?? 0));
3043
+ const { operationsByScope } = await this.remoteClient.getAllOperations(this.documentId, this.options.branch, this.remoteRevision, conflictingScopes);
3044
+ const remoteOperations = {};
3045
+ for (const [scope, ops] of Object.entries(operationsByScope)) remoteOperations[scope] = ops;
3046
+ const conflictInfo = {
3047
+ remoteOperations,
3048
+ localActions: localTracked,
3049
+ knownRevision: { ...this.remoteRevision },
3050
+ currentRevision: { ...currentRevision }
3051
+ };
3052
+ if (strategy === "reject") throw new ConflictError(conflictInfo);
3053
+ if (strategy === "rebase") return this.pullAndReplay(localTracked.map((t) => t.action));
3054
+ const mergedActions = await strategy(conflictInfo);
3055
+ return this.pullAndReplay(mergedActions);
3056
+ }
3057
+ /**
3058
+ * Pull latest remote state and replay actions through interceptors.
3059
+ * Returns newly tracked actions with correct prevOpHash values.
3060
+ */
3061
+ async pullAndReplay(actions) {
3062
+ await this.pull();
3063
+ for (const action of actions) {
3064
+ const methodName = screamingSnakeToCamel(action.type);
3065
+ const method = this[methodName];
3066
+ if (typeof method === "function") method.call(this, action.input);
3067
+ }
3068
+ return this.tracker.flush();
3069
+ }
3070
+ /** Prepare actions for push, optionally signing them. */
3071
+ async prepareActionsForPush(tracked) {
3072
+ const actions = [];
3073
+ for (const { action, prevOpHash, prevOpIndex } of tracked) {
3074
+ let prepared = {
3075
+ ...action,
3076
+ context: {
3077
+ ...action.context,
3078
+ prevOpHash,
3079
+ prevOpIndex
3080
+ }
3081
+ };
3082
+ if (this.options.signer) prepared = await this.signAction(prepared);
3083
+ actions.push(prepared);
3084
+ }
3085
+ return actions;
3086
+ }
3087
+ /** Sign an action using the configured signer, preserving existing signatures. */
3088
+ async signAction(action) {
3089
+ const signer = this.options.signer;
3090
+ const signature = await signer.signAction(action);
3091
+ const existingSignatures = action.context?.signer?.signatures ?? [];
3092
+ return {
3093
+ ...action,
3094
+ context: {
3095
+ ...action.context,
3096
+ signer: {
3097
+ user: signer.user,
3098
+ app: signer.app,
3099
+ signatures: [...existingSignatures, signature]
3100
+ }
3101
+ }
3102
+ };
3103
+ }
3104
+ /**
3105
+ * Fetch document and operations from the remote.
3106
+ *
3107
+ * On the first pull, uses the combined document+operations query.
3108
+ * On subsequent pulls, fetches only new operations per scope using
3109
+ * sinceRevision, then merges with existing local operations.
3110
+ * Falls back to a full fetch if the merge produces a count mismatch.
3111
+ */
3112
+ async fetchDocumentAndOperations() {
3113
+ if (this.hasPulled) return this.incrementalFetch();
3114
+ const result = await this.remoteClient.getDocumentWithOperations(this.documentId, this.options.branch);
3115
+ if (!result) throw new Error(`Document "${this.documentId}" not found on remote`);
3116
+ this.hasPulled = true;
3117
+ return {
3118
+ remoteDoc: result.document,
3119
+ operations: convertRemoteOperations(result.operations.operationsByScope)
3120
+ };
3121
+ }
3122
+ /**
3123
+ * Incremental fetch: fetches the document and only new operations per scope
3124
+ * using sinceRevision in a single request when possible.
3125
+ * Falls back to a full fetch on count mismatch.
3126
+ */
3127
+ async incrementalFetch() {
3128
+ const scopes = Object.keys(this.remoteRevision);
3129
+ const result = await this.remoteClient.getDocumentWithOperations(this.documentId, this.options.branch, this.remoteRevision, scopes.length > 0 ? scopes : void 0);
3130
+ if (!result) throw new Error(`Document "${this.documentId}" not found on remote`);
3131
+ const remoteDoc = result.document;
3132
+ const expectedRevision = extractRevisionMap(remoteDoc.revisionsList);
3133
+ const newOps = convertRemoteOperations(result.operations.operationsByScope);
3134
+ const merged = this.mergeOperations(this.inner.operations, newOps);
3135
+ if (this.hasExpectedOperationCounts(merged, expectedRevision)) return {
3136
+ remoteDoc,
3137
+ operations: merged
3138
+ };
3139
+ return this.fullFetch(remoteDoc);
3140
+ }
3141
+ /**
3142
+ * Full fetch fallback: fetches all operations from the beginning.
3143
+ * Used when an incremental fetch produces a count mismatch.
3144
+ */
3145
+ async fullFetch(remoteDoc) {
3146
+ const { operationsByScope } = await this.remoteClient.getAllOperations(this.documentId, this.options.branch);
3147
+ return {
3148
+ remoteDoc,
3149
+ operations: convertRemoteOperations(operationsByScope)
3150
+ };
3151
+ }
3152
+ /**
3153
+ * Validate that the merged operations match the expected revision per scope.
3154
+ * Each scope's operation count should equal its revision number.
3155
+ */
3156
+ hasExpectedOperationCounts(operations, expectedRevision) {
3157
+ for (const [scope, revision] of Object.entries(expectedRevision)) if ((scope in operations ? operations[scope].length : 0) !== revision) return false;
3158
+ return true;
3159
+ }
3160
+ /**
3161
+ * Merge existing local operations with newly fetched operations.
3162
+ * Appends new operations to existing ones per scope.
3163
+ */
3164
+ mergeOperations(existingOps, newOps) {
3165
+ const merged = {};
3166
+ for (const [scope, ops] of Object.entries(existingOps)) if (ops.length > 0) merged[scope] = [...ops];
3167
+ for (const [scope, ops] of Object.entries(newOps)) if (ops.length > 0) (merged[scope] ??= []).push(...ops);
3168
+ return merged;
3169
+ }
3170
+ /** Schedule a push via microtask (for streaming mode coalescing). */
3171
+ schedulePush() {
3172
+ if (this.pushScheduled) return;
3173
+ this.pushScheduled = true;
3174
+ queueMicrotask(() => {
3175
+ this.pushScheduled = false;
3176
+ this.pushQueue = this.pushQueue.then(async () => {
3177
+ try {
3178
+ await this.push();
3179
+ } catch (error) {
3180
+ this.options.onPushError?.(error);
3181
+ }
3182
+ });
3183
+ });
3184
+ }
3185
+ };
3186
+ //#endregion
3187
+ //#region src/storage/base-storage.ts
3188
+ var BaseStorage = class {
3189
+ [Symbol.iterator]() {
3190
+ return this.entries();
3191
+ }
3192
+ forEach(callback) {
3193
+ for (const [key, value] of this) callback(value, key, this);
3194
+ }
3195
+ };
3196
+ //#endregion
3197
+ //#region src/storage/local-storage.ts
3198
+ var BrowserLocalStorage = class extends BaseStorage {
3199
+ #namespace;
3200
+ #storage = window.localStorage;
3201
+ constructor(namespace) {
3202
+ super();
3203
+ this.#namespace = namespace;
3204
+ }
3205
+ #readMap() {
3206
+ const raw = this.#storage.getItem(this.#namespace);
3207
+ if (!raw) return /* @__PURE__ */ new Map();
3208
+ return new Map(JSON.parse(raw));
3209
+ }
3210
+ #writeMap(map) {
3211
+ this.#storage.setItem(this.#namespace, JSON.stringify(Array.from(map.entries())));
3212
+ }
3213
+ get(key) {
3214
+ return this.#readMap().get(key);
3215
+ }
3216
+ set(key, value) {
3217
+ const map = this.#readMap();
3218
+ map.set(key, value);
3219
+ this.#writeMap(map);
3220
+ }
3221
+ delete(key) {
3222
+ const map = this.#readMap();
3223
+ const deleted = map.delete(key);
3224
+ if (deleted) this.#writeMap(map);
3225
+ return deleted;
3226
+ }
3227
+ has(key) {
3228
+ return this.#readMap().has(key);
3229
+ }
3230
+ clear() {
3231
+ this.#storage.removeItem(this.#namespace);
3232
+ }
3233
+ entries() {
3234
+ return this.#readMap().entries();
3235
+ }
3236
+ keys() {
3237
+ return this.#readMap().keys();
3238
+ }
3239
+ values() {
3240
+ return this.#readMap().values();
3241
+ }
3242
+ [Symbol.iterator]() {
3243
+ return this.#readMap().entries();
3244
+ }
3245
+ };
3246
+ //#endregion
3247
+ export { ActionTracker, BaseStorage, BrowserLocalStorage, COMMON_PACKAGE_ID, CREDENTIAL_SCHEMA_EIP712_TYPE, CREDENTIAL_SUBJECT_TYPE, CREDENTIAL_TYPES, ChannelScheme, ChevronDownIcon, ConflictError, CopyIcon, DEFAULT_DRIVE_EDITOR_ID, DEFAULT_DRIVE_ID, DEFAULT_SWITCHBOARD_URL, DOMAIN_TYPE, DisconnectIcon, DocumentCache, DocumentChangeType, DocumentIntegrityService, GqlRequestChannel, GraphQLClientDocumentCache, ISSUER_TYPE, InMemoryQueue, IntervalPollTimer, PollBehavior, PropagationMode, REACTOR_SCHEMA, RENOWN_CHAIN_ID, RENOWN_NETWORK_ID, RENOWN_URL, ReactorBuilder, ReactorClientBuilder, RegistryClient, RelationalDbProcessor, RemoteClient, RemoteDocumentController, Renown, RenownAuthButton, RenownLoginButton, RenownLogo, RenownUserButton, SpinnerIcon, SyncOperationStatus, UserIcon, VERIFIABLE_CREDENTIAL_EIP712_TYPE, addAllowListEventHandler, addAllowedDocumentTypesEventHandler, addAnalyticsDatabaseNameEventHandler, addBasePathEventHandler, addCliVersionEventHandler, addDefaultDrivesUrlEventHandler, addDisabledEditorsEventHandler, addDocument, addDocumentCacheEventHandler, addDrive, addDrivesEventHandler, addDrivesPreserveStrategyEventHandler, addEnabledEditorsEventHandler, addFeaturesEventHandler, addFileUploadOperationsChunkSizeEventHandler, addFolder, addGaTrackingIdEventHandler, addGraphQLReactorClientEventHandler, addIsAddCloudDrivesEnabledEventHandler, addIsAddDriveEnabledEventHandler, addIsAddLocalDrivesEnabledEventHandler, addIsAddPublicDrivesEnabledEventHandler, addIsAnalyticsDatabaseWorkerEnabledEventHandler, addIsAnalyticsEnabledEventHandler, addIsAnalyticsExternalProcessorsEnabledEventHandler, addIsCloudDrivesEnabledEventHandler, addIsDeleteCloudDrivesEnabledEventHandler, addIsDeleteLocalDrivesEnabledEventHandler, addIsDeletePublicDrivesEnabledEventHandler, addIsDiffAnalyticsEnabledEventHandler, addIsDocumentModelSelectionSettingsEnabledEventHandler, addIsDragAndDropEnabledEventHandler, addIsDriveAnalyticsEnabledEventHandler, addIsEditorDebugModeEnabledEventHandler, addIsEditorReadModeEnabledEventHandler, addIsExternalControlsEnabledEventHandler, addIsExternalPackagesEnabledEventHandler, addIsExternalProcessorsEnabledEventHandler, addIsExternalRelationalProcessorsEnabledEventHandler, addIsLocalDrivesEnabledEventHandler, addIsPublicDrivesEnabledEventHandler, addIsRelationalProcessorsEnabledEventHandler, addIsSentryTracingEnabledEventHandler, addLoadingEventHandler, addLocalDrivesEnabledEventHandler, addLogLevelEventHandler, addModalEventHandler, addPHEventHandlers, addPackageDiscoveryServiceEventHandler, addPromiseState, addReactorClientEventHandler, addReactorClientModuleEventHandler, addRemoteDrive, addRenownChainIdEventHandler, addRenownEventHandler, addRenownNetworkIdEventHandler, addRenownUrlEventHandler, addRequiresHardRefreshEventHandler, addResetSelectedNodeEventHandler, addRevisionHistoryVisibleEventHandler, addRouterBasenameEventHandler, addSelectedDriveIdEventHandler, addSelectedNodeIdEventHandler, addSelectedTimelineItemEventHandler, addSelectedTimelineRevisionEventHandler, addSentryDsnEventHandler, addSentryEnvEventHandler, addSentryReleaseEventHandler, addSetSelectedDriveOnPopStateEventHandler, addSetSelectedNodeOnPopStateEventHandler, addStudioModeEventHandler, addToastEventHandler, addVersionCheckIntervalEventHandler, addVersionEventHandler, addVetraPackageManagerEventHandler, addWarnOutdatedAppEventHandler, baseDocumentModels, baseDocumentModelsMap, buildDocumentSubgraphQuery, buildDocumentSubgraphUrl, callEventHandlerRegisterFunctions, callGlobalSetterForKey, clearGlobal, closePHModal, commonGlobalEventHandlerFunctions, convertRemoteOperations, createAnalyticsStore, createClient, createProcessorQuery, createUrlWithPreservedParams, deleteDrive, deleteNode, deriveSystemUrl, dispatchActions, driveCollectionId, driveIdFromUrl, dropAllReactorStorage, exportDocument, exportFile, extractDriveIdFromPath, extractDriveIdFromSlug, extractDriveSlugFromPath, extractNodeIdFromPath, extractNodeIdFromSlug, extractNodeSlugFromPath, findUuid, getAnalyticsStore, getDocumentGraphqlQuery, getDriveIdBySlug, getDrives, getGlobal, getPackages, getPackagesByDocumentType, getPathWithoutBase, getRevisionFromDate, getSlugFromDriveUrl, getSwitchboardGatewayUrlFromDriveUrl, getSyncStatus, getSyncStatusSync, getUserPermissions, graphqlDocumentEvents, graphqlDocumentsEvents, graphqlEventsToSyncDrive, hideRevisionHistory, identifierFromMutateDocumentOperationVariables, initConnectCrypto, initRenownCrypto, isDocumentTypeSupported, isExternalControlsEnabledEventFunctions, isFileNodeKind, isFolderNodeKind, loading, login, logout, makeDriveUrlComponent, makeNodeSlug, makePHEventFunctions, openRenown, parseDriveUrl, phAppConfigHooks, phAppConfigSetters, phDocumentEditorConfigHooks, phDocumentEditorConfigSetters, phDocumentFromQuery, phDocumentsFromQuery, phGlobalConfigHooks, phGlobalConfigSetters, reactorGraphqlBatchFetchDocuments, reactorGraphqlCreateDocument, reactorGraphqlDeleteDocument, reactorGraphqlDeleteDocuments, reactorGraphqlFetchDocument, reactorGraphqlMutateDocument, readPromiseState, refreshReactorData, refreshReactorDataClient, renameDrive, renameDriveNode, resolveUrlPathname, setAllowList, setAllowedDocumentTypes, setAnalyticsDatabaseName, setBasePath, setCliVersion, setDefaultDrivesUrl, setDefaultPHGlobalConfig, setDisabledEditors, setDocumentCache, setDriveAvailableOffline, setDriveSharingType, setDrives, setDrivesPreserveStrategy, setEnabledEditors, setFeatures, setFileUploadOperationsChunkSize, setGaTrackingId, setGlobal, setGraphQLReactorClient, setIsAddCloudDrivesEnabled, setIsAddDriveEnabled, setIsAddLocalDrivesEnabled, setIsAddPublicDrivesEnabled, setIsAnalyticsDatabaseWorkerEnabled, setIsAnalyticsEnabled, setIsAnalyticsExternalProcessorsEnabled, setIsCloudDrivesEnabled, setIsDeleteCloudDrivesEnabled, setIsDeleteLocalDrivesEnabled, setIsDeletePublicDrivesEnabled, setIsDiffAnalyticsEnabled, setIsDocumentModelSelectionSettingsEnabled, setIsDragAndDropEnabled, setIsDriveAnalyticsEnabled, setIsEditorDebugModeEnabled, setIsEditorReadModeEnabled, setIsExternalControlsEnabled, setIsExternalPackagesEnabled, setIsExternalProcessorsEnabled, setIsExternalRelationalProcessorsEnabled, setIsLocalDrivesEnabled, setIsPublicDrivesEnabled, setIsRelationalProcessorsEnabled, setIsSentryTracingEnabled, setLoading, setLocalDrivesEnabled, setLogLevel, setPHAppConfig, setPHAppConfigByKey, setPHDocumentEditorConfig, setPHDocumentEditorConfigByKey, setPHGlobalConfig, setPHGlobalConfigByKey, setPHModal, setPHToast, setPackageDiscoveryService, setReactorClient, setReactorClientModule, setRenown, setRenownChainId, setRenownNetworkId, setRenownUrl, setRequiresHardRefresh, setRevisionHistoryVisible, setRouterBasename, setSelectedDrive, setSelectedDriveId, setSelectedNode, setSelectedTimelineItem, setSelectedTimelineRevision, setSentryDsn, setSentryEnv, setSentryRelease, setStudioMode, setVersion, setVersionCheckInterval, setVetraPackageManager, setWarnOutdatedApp, showCreateDocumentModal, showDeleteNodeModal, showPHModal, showRevisionHistory, sortNodesByName, truncateAllTables, useAllowList, useAllowedDocumentModelModules, useAllowedDocumentTypes, useAnalyticsDatabaseName, useAppModuleById, useAppModules, useBasePath, useCliVersion, useConnectionState, useConnectionStates, useDatabase, useDefaultAppModule, useDefaultDrivesUrl, useDid, useDisabledEditors, useDispatch, useDocument, useDocumentById, useDocumentCache, useDocumentModelModuleById, useDocumentModelModules, useDocumentOfType, useDocumentOperations, useDocumentTypes, useDocumentTypesInSelectedDrive, useDocuments, useDocumentsByIds, useDocumentsInSelectedDrive, useDocumentsInSelectedFolder, useDriveById, useDriveSystemInfo, useDrives, useDrivesPreserveStrategy, useEditorModuleById, useEditorModules, useEditorModulesForDocumentType, useEnabledEditors, useFallbackEditorModule, useFeatures, useFileNodesInSelectedDrive, useFileNodesInSelectedFolder, useFileUploadOperationsChunkSize, useFolderById, useFolderNodesInSelectedDrive, useFolderNodesInSelectedFolder, useGaTrackingId, useGetDocument, useGetDocumentAsync, useGetDocuments, useGetSwitchboardLink, useGraphQLReactorClient, useInitReactorGraphqlClient, useIsAddCloudDrivesEnabled, useIsAddDriveEnabled, useIsAddLocalDrivesEnabled, useIsAddPublicDrivesEnabled, useIsAnalyticsDatabaseWorkerEnabled, useIsAnalyticsEnabled, useIsAnalyticsExternalProcessorsEnabled, useIsCloudDrivesEnabled, useIsDeleteCloudDrivesEnabled, useIsDeleteLocalDrivesEnabled, useIsDeletePublicDrivesEnabled, useIsDiffAnalyticsEnabled, useIsDocumentModelSelectionSettingsEnabled, useIsDragAndDropEnabled, useIsDriveAnalyticsEnabled, useIsEditorDebugModeEnabled, useIsEditorReadModeEnabled, useIsExternalControlsEnabled, useIsExternalPackagesEnabled, useIsExternalProcessorsEnabled, useIsExternalRelationalProcessorsEnabled, useIsLocalDrivesEnabled, useIsPublicDrivesEnabled, useIsRelationalProcessorsEnabled, useIsSentryTracingEnabled, useLoading, useLocalDrivesEnabled, useLogLevel, useLoginStatus, useModelRegistry, useNodeActions, useNodeById, useNodeParentFolderById, useNodePathById, useNodesInSelectedDrive, useNodesInSelectedDriveOrFolder, useNodesInSelectedFolder, useOnDropFile, usePGlite, usePHAppConfigByKey, usePHDocumentEditorConfigByKey, usePHGlobalConfigByKey, usePHModal, usePHToast, usePackageDiscoveryService, useParentFolderForSelectedNode, useReactorClient, useReactorClientModule, useRelationalDb, useRelationalQuery, useRenown, useRenownAuth, useRenownChainId, useRenownInit, useRenownNetworkId, useRenownUrl, useRequiresHardRefresh, useResetPHGlobalConfig, useRevisionHistoryVisible, useRouterBasename, useSelectedDocument, useSelectedDocumentId, useSelectedDocumentOfType, useSelectedDocumentSafe, useSelectedDrive, useSelectedDriveId, useSelectedDriveSafe, useSelectedFolder, useSelectedNode, useSelectedNodePath, useSelectedTimelineItem, useSelectedTimelineRevision, useSentryDsn, useSentryEnv, useSentryRelease, useSetDefaultPHGlobalConfig, useSetPHAppConfig, useSetPHDocumentEditorConfig, useSetPHGlobalConfig, useStudioMode, useSubgraphModules, useSupportedDocumentTypesInReactor, useSync, useSyncList, useUser, useUserPermissions, useVersion, useVersionCheckInterval, useVetraPackageManager, useVetraPackages, useWarnOutdatedApp, validateDocument };
3248
+
3249
+ //# sourceMappingURL=index.js.map