@dxos/plugin-automation 0.8.4-main.70d3990 → 0.8.4-main.74a063c4e0

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 (282) hide show
  1. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  2. package/dist/lib/browser/chunk-POEIL4RN.mjs +44 -0
  3. package/dist/lib/browser/chunk-POEIL4RN.mjs.map +7 -0
  4. package/dist/lib/browser/chunk-WQLEMRPU.mjs +54 -0
  5. package/dist/lib/browser/chunk-WQLEMRPU.mjs.map +7 -0
  6. package/dist/lib/browser/cli/index.mjs +1122 -0
  7. package/dist/lib/browser/cli/index.mjs.map +7 -0
  8. package/dist/lib/browser/create-trigger-from-template-JPF5BFMX.mjs +77 -0
  9. package/dist/lib/browser/create-trigger-from-template-JPF5BFMX.mjs.map +7 -0
  10. package/dist/lib/browser/hooks/index.mjs +79 -7
  11. package/dist/lib/browser/hooks/index.mjs.map +4 -4
  12. package/dist/lib/browser/index.mjs +72 -112
  13. package/dist/lib/browser/index.mjs.map +4 -4
  14. package/dist/lib/browser/meta.json +1 -1
  15. package/dist/lib/browser/operations/index.mjs +14 -0
  16. package/dist/lib/browser/operations/index.mjs.map +7 -0
  17. package/dist/lib/browser/types/index.mjs +10 -4
  18. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  19. package/dist/lib/node-esm/{chunk-ECJKIUBO.mjs → chunk-JWZAVQLF.mjs} +24 -7
  20. package/dist/lib/node-esm/chunk-JWZAVQLF.mjs.map +7 -0
  21. package/dist/lib/node-esm/chunk-SP3P4OUI.mjs +45 -0
  22. package/dist/lib/node-esm/chunk-SP3P4OUI.mjs.map +7 -0
  23. package/dist/lib/node-esm/cli/index.mjs +1123 -0
  24. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  25. package/dist/lib/node-esm/create-trigger-from-template-FT75A4SF.mjs +78 -0
  26. package/dist/lib/node-esm/create-trigger-from-template-FT75A4SF.mjs.map +7 -0
  27. package/dist/lib/node-esm/hooks/index.mjs +79 -7
  28. package/dist/lib/node-esm/hooks/index.mjs.map +4 -4
  29. package/dist/lib/node-esm/index.mjs +72 -112
  30. package/dist/lib/node-esm/index.mjs.map +4 -4
  31. package/dist/lib/node-esm/meta.json +1 -1
  32. package/dist/lib/node-esm/operations/index.mjs +15 -0
  33. package/dist/lib/node-esm/operations/index.mjs.map +7 -0
  34. package/dist/lib/node-esm/types/index.mjs +10 -4
  35. package/dist/types/src/AutomationPlugin.d.ts +2 -1
  36. package/dist/types/src/AutomationPlugin.d.ts.map +1 -1
  37. package/dist/types/src/capabilities/app-graph-builder.d.ts +4 -2
  38. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  39. package/dist/types/src/capabilities/compute-runtime.d.ts +4 -3
  40. package/dist/types/src/capabilities/compute-runtime.d.ts.map +1 -1
  41. package/dist/types/src/capabilities/index.d.ts +6 -5
  42. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  43. package/dist/types/src/capabilities/node.d.ts +3 -0
  44. package/dist/types/src/capabilities/node.d.ts.map +1 -0
  45. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  46. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  47. package/dist/types/src/capabilities/react-surface.d.ts +3 -2
  48. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  49. package/dist/types/src/cli/commands/index.d.ts +2 -0
  50. package/dist/types/src/cli/commands/index.d.ts.map +1 -0
  51. package/dist/types/src/cli/commands/trigger/create/index.d.ts +25 -0
  52. package/dist/types/src/cli/commands/trigger/create/index.d.ts.map +1 -0
  53. package/dist/types/src/cli/commands/trigger/create/queue.d.ts +13 -0
  54. package/dist/types/src/cli/commands/trigger/create/queue.d.ts.map +1 -0
  55. package/dist/types/src/cli/commands/trigger/create/subscription.d.ts +15 -0
  56. package/dist/types/src/cli/commands/trigger/create/subscription.d.ts.map +1 -0
  57. package/dist/types/src/cli/commands/trigger/create/timer.d.ts +13 -0
  58. package/dist/types/src/cli/commands/trigger/create/timer.d.ts.map +1 -0
  59. package/dist/types/src/cli/commands/trigger/index.d.ts +57 -0
  60. package/dist/types/src/cli/commands/trigger/index.d.ts.map +1 -0
  61. package/dist/types/src/cli/commands/trigger/list.d.ts +7 -0
  62. package/dist/types/src/cli/commands/trigger/list.d.ts.map +1 -0
  63. package/dist/types/src/cli/commands/trigger/options.d.ts +11 -0
  64. package/dist/types/src/cli/commands/trigger/options.d.ts.map +1 -0
  65. package/dist/types/src/cli/commands/trigger/remove.d.ts +8 -0
  66. package/dist/types/src/cli/commands/trigger/remove.d.ts.map +1 -0
  67. package/dist/types/src/cli/commands/trigger/update/index.d.ts +28 -0
  68. package/dist/types/src/cli/commands/trigger/update/index.d.ts.map +1 -0
  69. package/dist/types/src/cli/commands/trigger/update/queue.d.ts +12 -0
  70. package/dist/types/src/cli/commands/trigger/update/queue.d.ts.map +1 -0
  71. package/dist/types/src/cli/commands/trigger/update/subscription.d.ts +13 -0
  72. package/dist/types/src/cli/commands/trigger/update/subscription.d.ts.map +1 -0
  73. package/dist/types/src/cli/commands/trigger/update/timer.d.ts +11 -0
  74. package/dist/types/src/cli/commands/trigger/update/timer.d.ts.map +1 -0
  75. package/dist/types/src/cli/commands/trigger/util.d.ts +46 -0
  76. package/dist/types/src/cli/commands/trigger/util.d.ts.map +1 -0
  77. package/dist/types/src/cli/index.d.ts +2 -0
  78. package/dist/types/src/cli/index.d.ts.map +1 -0
  79. package/dist/types/src/cli/plugin.d.ts +3 -0
  80. package/dist/types/src/cli/plugin.d.ts.map +1 -0
  81. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts +4 -5
  82. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts.map +1 -1
  83. package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts +28 -29
  84. package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts.map +1 -1
  85. package/dist/types/src/components/FunctionsPanel/FunctionsPanel.d.ts.map +1 -1
  86. package/dist/types/src/components/FunctionsRegistry/FunctionsRegistry.d.ts.map +1 -1
  87. package/dist/types/src/components/FunctionsRegistry/index.d.ts +3 -1
  88. package/dist/types/src/components/FunctionsRegistry/index.d.ts.map +1 -1
  89. package/dist/types/src/components/TriggerEditor/FunctionInputEditor.d.ts +12 -9
  90. package/dist/types/src/components/TriggerEditor/FunctionInputEditor.d.ts.map +1 -1
  91. package/dist/types/src/components/TriggerEditor/SpecSelector.d.ts +6 -3
  92. package/dist/types/src/components/TriggerEditor/SpecSelector.d.ts.map +1 -1
  93. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +7 -6
  94. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
  95. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts +98 -31
  96. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -1
  97. package/dist/types/src/components/index.d.ts +3 -4
  98. package/dist/types/src/components/index.d.ts.map +1 -1
  99. package/dist/types/src/containers/AutomationSettings/AutomationSettings.d.ts +4 -0
  100. package/dist/types/src/containers/AutomationSettings/AutomationSettings.d.ts.map +1 -0
  101. package/dist/types/src/containers/AutomationSettings/index.d.ts +2 -0
  102. package/dist/types/src/containers/AutomationSettings/index.d.ts.map +1 -0
  103. package/dist/types/src/{components → containers/FunctionsContainer}/FunctionsContainer.d.ts +0 -1
  104. package/dist/types/src/containers/FunctionsContainer/FunctionsContainer.d.ts.map +1 -0
  105. package/dist/types/src/containers/FunctionsContainer/index.d.ts +2 -0
  106. package/dist/types/src/containers/FunctionsContainer/index.d.ts.map +1 -0
  107. package/dist/types/src/containers/TriggerSettings/TriggerSettings.d.ts +6 -0
  108. package/dist/types/src/containers/TriggerSettings/TriggerSettings.d.ts.map +1 -0
  109. package/dist/types/src/containers/TriggerSettings/index.d.ts +3 -0
  110. package/dist/types/src/containers/TriggerSettings/index.d.ts.map +1 -0
  111. package/dist/types/src/containers/index.d.ts +5 -0
  112. package/dist/types/src/containers/index.d.ts.map +1 -0
  113. package/dist/types/src/hooks/index.d.ts +2 -0
  114. package/dist/types/src/hooks/index.d.ts.map +1 -1
  115. package/dist/types/src/hooks/useComputeRuntime.d.ts +7 -0
  116. package/dist/types/src/hooks/useComputeRuntime.d.ts.map +1 -0
  117. package/dist/types/src/hooks/useComputeRuntimeCallback.d.ts +4 -7
  118. package/dist/types/src/hooks/useComputeRuntimeCallback.d.ts.map +1 -1
  119. package/dist/types/src/hooks/useComputeRuntimeService.d.ts +5 -0
  120. package/dist/types/src/hooks/useComputeRuntimeService.d.ts.map +1 -0
  121. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +4 -3
  122. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -1
  123. package/dist/types/src/index.d.ts +2 -6
  124. package/dist/types/src/index.d.ts.map +1 -1
  125. package/dist/types/src/meta.d.ts +2 -2
  126. package/dist/types/src/meta.d.ts.map +1 -1
  127. package/dist/types/src/operations/create-trigger-from-template.d.ts +5 -0
  128. package/dist/types/src/operations/create-trigger-from-template.d.ts.map +1 -0
  129. package/dist/types/src/operations/definitions.d.ts +19 -0
  130. package/dist/types/src/operations/definitions.d.ts.map +1 -0
  131. package/dist/types/src/operations/index.d.ts +4 -0
  132. package/dist/types/src/operations/index.d.ts.map +1 -0
  133. package/dist/types/src/testing/test-functions.d.ts +204 -2
  134. package/dist/types/src/testing/test-functions.d.ts.map +1 -1
  135. package/dist/types/src/translations.d.ts +29 -30
  136. package/dist/types/src/translations.d.ts.map +1 -1
  137. package/dist/types/src/types/capabilities.d.ts +25 -0
  138. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  139. package/dist/types/src/types/events.d.ts +5 -0
  140. package/dist/types/src/types/events.d.ts.map +1 -0
  141. package/dist/types/src/types/index.d.ts +2 -0
  142. package/dist/types/src/types/index.d.ts.map +1 -1
  143. package/dist/types/src/types/schema.d.ts +11 -3
  144. package/dist/types/src/types/schema.d.ts.map +1 -1
  145. package/dist/types/tsconfig.tsbuildinfo +1 -1
  146. package/package.json +89 -50
  147. package/src/AutomationPlugin.tsx +18 -35
  148. package/src/capabilities/app-graph-builder.ts +54 -79
  149. package/src/capabilities/compute-runtime.ts +169 -52
  150. package/src/capabilities/index.ts +9 -7
  151. package/src/capabilities/node.ts +7 -0
  152. package/src/capabilities/operation-handler.ts +16 -0
  153. package/src/capabilities/react-surface.tsx +49 -46
  154. package/src/cli/commands/index.ts +5 -0
  155. package/src/cli/commands/trigger/create/index.ts +14 -0
  156. package/src/cli/commands/trigger/create/queue.ts +90 -0
  157. package/src/cli/commands/trigger/create/subscription.ts +129 -0
  158. package/src/cli/commands/trigger/create/timer.ts +94 -0
  159. package/src/cli/commands/trigger/index.ts +16 -0
  160. package/src/cli/commands/trigger/list.ts +68 -0
  161. package/src/cli/commands/trigger/options.ts +59 -0
  162. package/src/cli/commands/trigger/remove.ts +45 -0
  163. package/src/cli/commands/trigger/update/index.ts +14 -0
  164. package/src/cli/commands/trigger/update/queue.ts +195 -0
  165. package/src/cli/commands/trigger/update/subscription.ts +279 -0
  166. package/src/cli/commands/trigger/update/timer.ts +194 -0
  167. package/src/cli/commands/trigger/util.ts +409 -0
  168. package/src/cli/index.ts +5 -0
  169. package/src/cli/plugin.ts +23 -0
  170. package/src/components/AutomationPanel/AutomationPanel.stories.tsx +10 -8
  171. package/src/components/AutomationPanel/AutomationPanel.tsx +163 -71
  172. package/src/components/FunctionsPanel/FunctionsPanel.tsx +42 -41
  173. package/src/components/FunctionsRegistry/FunctionsRegistry.tsx +28 -41
  174. package/src/components/FunctionsRegistry/index.ts +4 -1
  175. package/src/components/TriggerEditor/FunctionInputEditor.tsx +34 -33
  176. package/src/components/TriggerEditor/SpecSelector.tsx +20 -9
  177. package/src/components/TriggerEditor/TriggerEditor.stories.tsx +79 -33
  178. package/src/components/TriggerEditor/TriggerEditor.tsx +89 -47
  179. package/src/components/index.ts +1 -2
  180. package/src/containers/AutomationSettings/AutomationSettings.tsx +28 -0
  181. package/src/containers/AutomationSettings/index.ts +5 -0
  182. package/src/containers/FunctionsContainer/FunctionsContainer.tsx +34 -0
  183. package/src/containers/FunctionsContainer/index.ts +5 -0
  184. package/src/containers/TriggerSettings/TriggerSettings.tsx +26 -0
  185. package/src/containers/TriggerSettings/index.ts +6 -0
  186. package/src/containers/index.ts +9 -0
  187. package/src/hooks/index.ts +3 -0
  188. package/src/hooks/useComputeRuntime.ts +16 -0
  189. package/src/hooks/useComputeRuntimeCallback.ts +8 -44
  190. package/src/hooks/useComputeRuntimeService.ts +24 -0
  191. package/src/hooks/useTriggerRuntimeControls.ts +28 -14
  192. package/src/index.ts +2 -7
  193. package/src/meta.ts +3 -3
  194. package/src/operations/create-trigger-from-template.ts +75 -0
  195. package/src/operations/definitions.ts +28 -0
  196. package/src/operations/index.ts +9 -0
  197. package/src/testing/test-functions.ts +8 -5
  198. package/src/translations.ts +35 -34
  199. package/src/types/capabilities.ts +56 -0
  200. package/src/types/events.ts +11 -0
  201. package/src/types/index.ts +2 -0
  202. package/src/types/schema.ts +5 -5
  203. package/dist/lib/browser/AutomationPanel-M4M77L4V.mjs +0 -11
  204. package/dist/lib/browser/AutomationSettings-4HCI6KJR.mjs +0 -68
  205. package/dist/lib/browser/AutomationSettings-4HCI6KJR.mjs.map +0 -7
  206. package/dist/lib/browser/FunctionsContainer-CDVBRQCT.mjs +0 -144
  207. package/dist/lib/browser/FunctionsContainer-CDVBRQCT.mjs.map +0 -7
  208. package/dist/lib/browser/FunctionsPanel-CRW6SJUN.mjs +0 -10
  209. package/dist/lib/browser/app-graph-builder-W7LLC6XW.mjs +0 -81
  210. package/dist/lib/browser/app-graph-builder-W7LLC6XW.mjs.map +0 -7
  211. package/dist/lib/browser/chunk-4MBM6C6A.mjs +0 -100
  212. package/dist/lib/browser/chunk-4MBM6C6A.mjs.map +0 -7
  213. package/dist/lib/browser/chunk-7W6QMY3L.mjs +0 -267
  214. package/dist/lib/browser/chunk-7W6QMY3L.mjs.map +0 -7
  215. package/dist/lib/browser/chunk-CZVA5NMD.mjs +0 -14
  216. package/dist/lib/browser/chunk-CZVA5NMD.mjs.map +0 -7
  217. package/dist/lib/browser/chunk-LZQFZO3B.mjs +0 -17
  218. package/dist/lib/browser/chunk-LZQFZO3B.mjs.map +0 -7
  219. package/dist/lib/browser/chunk-T6ZESHDY.mjs +0 -191
  220. package/dist/lib/browser/chunk-T6ZESHDY.mjs.map +0 -7
  221. package/dist/lib/browser/chunk-TWWFNOIR.mjs +0 -109
  222. package/dist/lib/browser/chunk-TWWFNOIR.mjs.map +0 -7
  223. package/dist/lib/browser/chunk-XAKZ4ANY.mjs +0 -15
  224. package/dist/lib/browser/chunk-XAKZ4ANY.mjs.map +0 -7
  225. package/dist/lib/browser/chunk-YBPJCY3F.mjs +0 -38
  226. package/dist/lib/browser/chunk-YBPJCY3F.mjs.map +0 -7
  227. package/dist/lib/browser/compute-runtime-B4XJVY4Y.mjs +0 -113
  228. package/dist/lib/browser/compute-runtime-B4XJVY4Y.mjs.map +0 -7
  229. package/dist/lib/browser/intent-resolver-5HR7M7T6.mjs +0 -77
  230. package/dist/lib/browser/intent-resolver-5HR7M7T6.mjs.map +0 -7
  231. package/dist/lib/browser/react-surface-TKU2EQ5A.mjs +0 -64
  232. package/dist/lib/browser/react-surface-TKU2EQ5A.mjs.map +0 -7
  233. package/dist/lib/node-esm/AutomationPanel-F5CTC6AT.mjs +0 -12
  234. package/dist/lib/node-esm/AutomationPanel-F5CTC6AT.mjs.map +0 -7
  235. package/dist/lib/node-esm/AutomationSettings-BQLJIFRT.mjs +0 -69
  236. package/dist/lib/node-esm/AutomationSettings-BQLJIFRT.mjs.map +0 -7
  237. package/dist/lib/node-esm/FunctionsContainer-ZHHJPQAZ.mjs +0 -145
  238. package/dist/lib/node-esm/FunctionsContainer-ZHHJPQAZ.mjs.map +0 -7
  239. package/dist/lib/node-esm/FunctionsPanel-RVVCS6VH.mjs +0 -11
  240. package/dist/lib/node-esm/FunctionsPanel-RVVCS6VH.mjs.map +0 -7
  241. package/dist/lib/node-esm/app-graph-builder-SLQOO7GH.mjs +0 -82
  242. package/dist/lib/node-esm/app-graph-builder-SLQOO7GH.mjs.map +0 -7
  243. package/dist/lib/node-esm/chunk-3IYSC75Z.mjs +0 -16
  244. package/dist/lib/node-esm/chunk-3IYSC75Z.mjs.map +0 -7
  245. package/dist/lib/node-esm/chunk-7B6NAAI6.mjs +0 -101
  246. package/dist/lib/node-esm/chunk-7B6NAAI6.mjs.map +0 -7
  247. package/dist/lib/node-esm/chunk-CEVIVRTY.mjs +0 -19
  248. package/dist/lib/node-esm/chunk-CEVIVRTY.mjs.map +0 -7
  249. package/dist/lib/node-esm/chunk-CF2SWXPW.mjs +0 -268
  250. package/dist/lib/node-esm/chunk-CF2SWXPW.mjs.map +0 -7
  251. package/dist/lib/node-esm/chunk-ECJKIUBO.mjs.map +0 -7
  252. package/dist/lib/node-esm/chunk-F76XVENA.mjs +0 -192
  253. package/dist/lib/node-esm/chunk-F76XVENA.mjs.map +0 -7
  254. package/dist/lib/node-esm/chunk-KB7NFEYY.mjs +0 -16
  255. package/dist/lib/node-esm/chunk-KB7NFEYY.mjs.map +0 -7
  256. package/dist/lib/node-esm/chunk-RVK52XGK.mjs +0 -110
  257. package/dist/lib/node-esm/chunk-RVK52XGK.mjs.map +0 -7
  258. package/dist/lib/node-esm/compute-runtime-JUWTQXOV.mjs +0 -114
  259. package/dist/lib/node-esm/compute-runtime-JUWTQXOV.mjs.map +0 -7
  260. package/dist/lib/node-esm/intent-resolver-KDRYB5BC.mjs +0 -78
  261. package/dist/lib/node-esm/intent-resolver-KDRYB5BC.mjs.map +0 -7
  262. package/dist/lib/node-esm/react-surface-7QROSEGH.mjs +0 -65
  263. package/dist/lib/node-esm/react-surface-7QROSEGH.mjs.map +0 -7
  264. package/dist/types/src/capabilities/capabilities.d.ts +0 -20
  265. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  266. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  267. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  268. package/dist/types/src/components/AutomationSettings.d.ts +0 -5
  269. package/dist/types/src/components/AutomationSettings.d.ts.map +0 -1
  270. package/dist/types/src/components/FunctionsContainer.d.ts.map +0 -1
  271. package/dist/types/src/components/TriggerSettings.d.ts +0 -6
  272. package/dist/types/src/components/TriggerSettings.d.ts.map +0 -1
  273. package/dist/types/src/events.d.ts +0 -4
  274. package/dist/types/src/events.d.ts.map +0 -1
  275. package/src/capabilities/capabilities.ts +0 -41
  276. package/src/capabilities/intent-resolver.ts +0 -72
  277. package/src/components/AutomationSettings.tsx +0 -30
  278. package/src/components/FunctionsContainer.tsx +0 -36
  279. package/src/components/TriggerSettings.tsx +0 -25
  280. package/src/events.ts +0 -11
  281. /package/dist/lib/browser/{AutomationPanel-M4M77L4V.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  282. /package/dist/lib/{browser/FunctionsPanel-CRW6SJUN.mjs.map → node-esm/chunk-HSLMI22Q.mjs.map} +0 -0
@@ -6,48 +6,53 @@ import * as Array from 'effect/Array';
6
6
  import * as EFn from 'effect/Function';
7
7
  import * as Match from 'effect/Match';
8
8
  import * as Schema from 'effect/Schema';
9
- import React, { useMemo, useState } from 'react';
9
+ import React, { useCallback, useMemo, useState } from 'react';
10
10
 
11
+ import { useTypeOptions } from '@dxos/app-toolkit/ui';
12
+ import { Context } from '@dxos/context';
11
13
  import { Filter, Obj, Tag } from '@dxos/echo';
12
- import { Function, Script, Trigger } from '@dxos/functions';
13
- import { useTypeOptions } from '@dxos/plugin-space';
14
+ import { Script, Trigger } from '@dxos/functions';
15
+ import { KEY_QUEUE_CURSOR } from '@dxos/functions-runtime';
16
+ import { FunctionsServiceClient } from '@dxos/functions-runtime/edge';
17
+ import { Operation } from '@dxos/operation';
14
18
  import { type Client, useClient } from '@dxos/react-client';
15
- import { type Space, getSpace, useQuery } from '@dxos/react-client/echo';
16
- import { Clipboard, IconButton, Input, Separator, type ThemedClassName, useTranslation } from '@dxos/react-ui';
17
- import { ControlItem, controlItemClasses } from '@dxos/react-ui-form';
19
+ import { type Space, useObject, useQuery } from '@dxos/react-client/echo';
20
+ import { Clipboard, IconButton, type IconButtonProps, Input, Separator, useTranslation } from '@dxos/react-ui';
21
+ import { Settings } from '@dxos/react-ui-form';
18
22
  import { List } from '@dxos/react-ui-list';
19
- import { ghostHover, mx } from '@dxos/react-ui-theme';
20
- import { Project } from '@dxos/types';
23
+ import { Pipeline } from '@dxos/types';
24
+ import { ghostHover, mx } from '@dxos/ui-theme';
21
25
  import { isNonNullable } from '@dxos/util';
22
26
 
23
- import { meta } from '../../meta';
27
+ import { meta } from '#meta';
28
+
24
29
  import { TriggerEditor, type TriggerEditorProps } from '../TriggerEditor';
25
30
 
26
- const grid = 'grid grid-cols-[40px_1fr_32px] min-bs-[2.5rem]';
31
+ const grid = 'grid grid-cols-[40px_1fr_32px_32px] min-h-[2.5rem]';
27
32
 
28
- export type AutomationPanelProps = ThemedClassName<{
33
+ export type AutomationPanelProps = {
29
34
  space: Space;
30
- object?: Obj.Any;
35
+ object?: Obj.Unknown;
31
36
  initialTrigger?: Trigger.Trigger;
32
37
  onDone?: () => void;
33
- }>;
38
+ };
34
39
 
35
40
  // TODO(burdon): Factor out common layout with ViewEditor.
36
- export const AutomationPanel = ({ classNames, space, object, initialTrigger, onDone }: AutomationPanelProps) => {
41
+ export const AutomationPanel = ({ space, object, initialTrigger, onDone }: AutomationPanelProps) => {
37
42
  const { t } = useTranslation(meta.id);
38
43
  const client = useClient();
39
- const functions = useQuery(space, Filter.type(Function.Function));
40
- const triggers = useQuery(space, Filter.type(Trigger.Trigger));
44
+ const functionsServiceClient = useMemo(() => FunctionsServiceClient.fromClient(client), [client]);
45
+ const functions = useQuery(space.db, Filter.type(Operation.PersistentOperation));
46
+ const triggers = useQuery(space.db, Filter.type(Trigger.Trigger));
41
47
  const filteredTriggers = useMemo(() => {
42
48
  return object ? triggers.filter(triggerMatch(object)) : triggers;
43
49
  }, [object, triggers]);
44
- const tags = useQuery(space, Filter.type(Tag.Tag));
50
+ const tags = useQuery(space.db, Filter.type(Tag.Tag));
45
51
  const types = useTypeOptions({
46
52
  space,
47
53
  annotation: {
48
54
  location: ['database', 'runtime'],
49
55
  kind: ['user'],
50
- registered: ['registered'],
51
56
  },
52
57
  });
53
58
 
@@ -72,7 +77,9 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
72
77
 
73
78
  const handleSave: TriggerEditorProps['onSave'] = (trigger) => {
74
79
  if (selected) {
75
- Object.assign(selected, trigger);
80
+ Obj.change(selected, (mutable) => {
81
+ Object.assign(mutable, trigger);
82
+ });
76
83
  } else {
77
84
  space.db.add(Trigger.make(trigger));
78
85
  }
@@ -87,11 +94,22 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
87
94
  onDone?.();
88
95
  };
89
96
 
97
+ const handleForceRunTrigger = async (trigger: Trigger.Trigger) => {
98
+ await functionsServiceClient.forceRunCronTrigger(Context.default(), space.id, trigger.id);
99
+ };
100
+
101
+ const handleResetCursor = async (trigger: Trigger.Trigger) => {
102
+ Obj.change(trigger, (obj) => {
103
+ Obj.deleteKeys(obj, KEY_QUEUE_CURSOR);
104
+ });
105
+ await space.db.flush({ indexes: true });
106
+ };
107
+
90
108
  if (trigger) {
91
109
  return (
92
- <ControlItem title={t('trigger editor title')}>
110
+ <Settings.Item title={t('trigger-editor.title')} description={t('trigger-editor.description')}>
93
111
  <TriggerEditor
94
- space={space}
112
+ db={space.db}
95
113
  trigger={trigger}
96
114
  readonlySpec={Boolean(object)}
97
115
  tags={tags}
@@ -99,12 +117,12 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
99
117
  onSave={handleSave}
100
118
  onCancel={handleCancel}
101
119
  />
102
- </ControlItem>
120
+ </Settings.Item>
103
121
  );
104
122
  }
105
123
 
106
124
  return (
107
- <div className={mx(controlItemClasses, classNames)}>
125
+ <Settings.Panel>
108
126
  {filteredTriggers.length > 0 && (
109
127
  <List.Root<Trigger.Trigger>
110
128
  items={filteredTriggers}
@@ -112,74 +130,148 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
112
130
  getId={(field) => field.id}
113
131
  >
114
132
  {({ items: filteredTriggers }) => (
115
- <div role='list' className='flex flex-col is-full'>
116
- {filteredTriggers?.map((trigger) => {
117
- const copyAction = getCopyAction(client, trigger);
118
- return (
119
- <List.Item<Trigger.Trigger>
120
- key={trigger.id}
121
- item={trigger}
122
- classNames={mx(grid, ghostHover, 'items-center', 'pli-2')}
123
- >
124
- <Input.Root>
125
- <Input.Switch
126
- checked={trigger.enabled}
127
- onCheckedChange={(checked) => (trigger.enabled = checked)}
128
- />
129
- </Input.Root>
130
-
131
- <div className={'flex'}>
132
- <List.ItemTitle
133
- classNames='pli-1 cursor-pointer is-0 shrink truncate'
134
- onClick={() => handleSelect(trigger)}
135
- >
136
- {getFunctionName(functions, trigger) ?? '∅'}
137
- </List.ItemTitle>
138
-
139
- {/* TODO: a better way to expose copy action */}
140
- {copyAction && (
141
- <Clipboard.IconButton
142
- label={t(copyAction.translationKey)}
143
- value={copyAction.contentProvider()}
144
- />
145
- )}
146
- </div>
147
-
148
- <List.ItemDeleteButton onClick={() => handleDelete(trigger)} />
149
- </List.Item>
150
- );
151
- })}
133
+ <div role='list' className='flex flex-col w-full'>
134
+ {filteredTriggers?.map((trigger) => (
135
+ <TriggerListItem
136
+ key={trigger.id}
137
+ trigger={trigger}
138
+ functions={functions}
139
+ onSelect={handleSelect}
140
+ onDelete={handleDelete}
141
+ onResetCursor={handleResetCursor}
142
+ onForceRun={handleForceRunTrigger}
143
+ />
144
+ ))}
152
145
  </div>
153
146
  )}
154
147
  </List.Root>
155
148
  )}
156
- {filteredTriggers.length > 0 && <Separator classNames='mlb-4' />}
157
- <IconButton icon='ph--plus--regular' label={t('new trigger label')} onClick={handleAdd} />
158
- </div>
149
+
150
+ {filteredTriggers.length > 0 && <Separator classNames='my-4' />}
151
+ <IconButton icon='ph--plus--regular' label={t('new-trigger.label')} onClick={handleAdd} />
152
+ </Settings.Panel>
153
+ );
154
+ };
155
+
156
+ const TriggerListItem = ({
157
+ trigger,
158
+ functions,
159
+ onSelect,
160
+ onDelete,
161
+ onResetCursor,
162
+ onForceRun,
163
+ }: {
164
+ trigger: Trigger.Trigger;
165
+ functions: Operation.PersistentOperation[];
166
+ onSelect?: (trigger: Trigger.Trigger) => void;
167
+ onDelete?: (trigger: Trigger.Trigger) => void;
168
+ onResetCursor?: (trigger: Trigger.Trigger) => void;
169
+ onForceRun?: (trigger: Trigger.Trigger) => void;
170
+ }) => {
171
+ const client = useClient();
172
+ const copyAction = getCopyAction(client, trigger);
173
+ const { t } = useTranslation(meta.id);
174
+ const cursor = Obj.getKeys(trigger, KEY_QUEUE_CURSOR).at(0)?.id;
175
+ const [snapshot, updateTrigger] = useObject(trigger);
176
+
177
+ const enabled = snapshot.enabled ?? false;
178
+ const onEnabledChange = (checked: boolean) => {
179
+ updateTrigger((trigger) => {
180
+ trigger.enabled = checked;
181
+ });
182
+ };
183
+
184
+ const handleSelect = useCallback(() => {
185
+ onSelect?.(trigger);
186
+ }, [onSelect, trigger]);
187
+
188
+ const handleDelete = useCallback(() => {
189
+ onDelete?.(trigger);
190
+ }, [onDelete, trigger]);
191
+
192
+ const handleResetCursor = useCallback(() => {
193
+ onResetCursor?.(trigger);
194
+ }, [onResetCursor, trigger]);
195
+
196
+ const handleForceRun = useCallback(() => {
197
+ onForceRun?.(trigger);
198
+ }, [onForceRun, trigger]);
199
+
200
+ const actionProps = useMemo<IconButtonProps | undefined>(() => {
201
+ if (trigger.spec?.kind === 'timer' && onForceRun) {
202
+ return {
203
+ disabled: !enabled || trigger.spec?.kind !== 'timer',
204
+ icon: 'ph--play--regular',
205
+ label: 'Force run',
206
+ onClick: handleForceRun,
207
+ };
208
+ }
209
+
210
+ if (trigger.spec?.kind === 'queue' && onResetCursor) {
211
+ return {
212
+ disabled: !cursor,
213
+ icon: 'ph--arrow-clockwise--regular',
214
+ label: 'Reset cursor',
215
+ onClick: handleResetCursor,
216
+ };
217
+ }
218
+ }, [enabled, trigger.spec?.kind, handleForceRun]);
219
+
220
+ return (
221
+ <List.Item<Obj.Snapshot<Trigger.Trigger>>
222
+ key={trigger.id}
223
+ item={snapshot}
224
+ classNames={mx(grid, ghostHover, 'items-center', 'px-2')}
225
+ >
226
+ <Input.Root>
227
+ <Input.Switch checked={enabled} onCheckedChange={onEnabledChange} />
228
+ </Input.Root>
229
+
230
+ <div className={'flex'}>
231
+ <List.ItemTitle classNames='px-1 cursor-pointer w-0 shrink truncate' onClick={handleSelect}>
232
+ {getFunctionName(functions, trigger) ?? '∅'}
233
+ {cursor && <div className='text-xs text-description truncate ml-4'>Position: {cursor}</div>}
234
+ </List.ItemTitle>
235
+
236
+ {copyAction && (
237
+ <Clipboard.IconButton label={t(copyAction.translationKey)} value={copyAction.contentProvider()} />
238
+ )}
239
+ </div>
240
+
241
+ {actionProps ? <List.ItemIconButton {...actionProps} autoHide={false} /> : <div />}
242
+
243
+ {onDelete && <List.ItemDeleteButton onClick={handleDelete} />}
244
+ </List.Item>
159
245
  );
160
246
  };
161
247
 
162
248
  const getCopyAction = (client: Client, trigger: Trigger.Trigger | undefined) => {
163
249
  if (trigger?.spec?.kind === 'email') {
164
- return { translationKey: 'trigger copy email', contentProvider: () => `${getSpace(trigger)!.id}@dxos.network` };
250
+ return {
251
+ translationKey: 'trigger copy email' as const,
252
+ contentProvider: () => `${Obj.getDatabase(trigger)!.spaceId}@dxos.network`,
253
+ };
165
254
  }
166
255
 
167
256
  if (trigger?.spec?.kind === 'webhook') {
168
- return { translationKey: 'trigger copy url', contentProvider: () => getWebhookUrl(client, trigger) };
257
+ return {
258
+ translationKey: 'trigger copy url' as const,
259
+ contentProvider: () => getWebhookUrl(client, trigger!),
260
+ };
169
261
  }
170
262
 
171
263
  return undefined;
172
264
  };
173
265
 
174
266
  const getWebhookUrl = (client: Client, trigger: Trigger.Trigger) => {
175
- const spaceId = getSpace(trigger)!.id;
267
+ const spaceId = Obj.getDatabase(trigger)!.spaceId;
176
268
  const edgeUrl = new URL(client.config.values.runtime!.services!.edge!.url!);
177
269
  const isSecure = edgeUrl.protocol.startsWith('https') || edgeUrl.protocol.startsWith('wss');
178
270
  edgeUrl.protocol = isSecure ? 'https' : 'http';
179
271
  return new URL(`/webhook/${spaceId}:${trigger.id}`, edgeUrl).toString();
180
272
  };
181
273
 
182
- const getFunctionName = (functions: Function.Function[], trigger: Trigger.Trigger) => {
274
+ const getFunctionName = (functions: Operation.PersistentOperation[], trigger: Trigger.Trigger) => {
183
275
  // TODO(wittjosiah): Truncation should be done in the UI.
184
276
  // Warning that the List component is currently a can of worms.
185
277
  const shortId = trigger.function && `${trigger.function.dxn.toString().slice(0, 16)}…`;
@@ -189,14 +281,14 @@ const getFunctionName = (functions: Function.Function[], trigger: Trigger.Trigge
189
281
 
190
282
  const scriptMatch = (script: Script.Script) => (trigger: Trigger.Trigger) => {
191
283
  const fn = trigger.function?.target;
192
- if (!Obj.instanceOf(Function.Function, fn)) {
284
+ if (!Obj.instanceOf(Operation.PersistentOperation, fn)) {
193
285
  return false;
194
286
  }
195
287
 
196
288
  return fn.source?.target === script;
197
289
  };
198
290
 
199
- const projectMatch = (project: Project.Project) => {
291
+ const projectMatch = (project: Pipeline.Pipeline) => {
200
292
  const viewQueries = EFn.pipe(
201
293
  project.columns,
202
294
  Array.map((column) => column.view.target),
@@ -216,14 +308,14 @@ const projectMatch = (project: Project.Project) => {
216
308
  };
217
309
  };
218
310
 
219
- const triggerMatch = Match.type<Obj.Any>().pipe(
311
+ const triggerMatch = Match.type<Obj.Unknown>().pipe(
220
312
  Match.withReturnType<(trigger: Trigger.Trigger) => boolean>(),
221
313
  Match.when(
222
314
  (obj) => Obj.instanceOf(Script.Script, obj),
223
315
  (obj) => scriptMatch(obj),
224
316
  ),
225
317
  Match.when(
226
- (obj) => Obj.instanceOf(Project.Project, obj),
318
+ (obj) => Obj.instanceOf(Pipeline.Pipeline, obj),
227
319
  (obj) => projectMatch(obj),
228
320
  ),
229
321
  Match.orElse((_obj) => () => true),
@@ -5,20 +5,18 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import React, { useCallback, useMemo } from 'react';
7
7
 
8
- import { LayoutAction, createIntent } from '@dxos/app-framework';
9
- import { useIntentDispatcher } from '@dxos/app-framework/react';
10
- import { Obj } from '@dxos/echo';
11
- import { Function, Script } from '@dxos/functions';
12
- import { SpaceAction } from '@dxos/plugin-space/types';
8
+ import { useOperationInvoker } from '@dxos/app-framework/ui';
9
+ import { LayoutOperation, getObjectPathFromObject } from '@dxos/app-toolkit';
10
+ import { Script } from '@dxos/functions';
11
+ import { Operation } from '@dxos/operation';
12
+ import { SpaceOperation } from '@dxos/plugin-space/operations';
13
13
  import { Filter, type Space, useQuery } from '@dxos/react-client/echo';
14
- import { Button, IconButton, useTranslation } from '@dxos/react-ui';
15
- import { controlItemClasses } from '@dxos/react-ui-form';
14
+ import { IconButton, useTranslation } from '@dxos/react-ui';
15
+ import { Settings } from '@dxos/react-ui-form';
16
16
  import { List } from '@dxos/react-ui-list';
17
- import { ghostHover, mx } from '@dxos/react-ui-theme';
17
+ import { ghostHover, mx } from '@dxos/ui-theme';
18
18
 
19
- import { meta } from '../../meta';
20
-
21
- const grid = 'grid grid-cols-[1fr_auto] min-bs-[2.5rem]';
19
+ import { meta } from '#meta';
22
20
 
23
21
  export type FunctionsPanelProps = {
24
22
  space: Space;
@@ -26,9 +24,9 @@ export type FunctionsPanelProps = {
26
24
 
27
25
  export const FunctionsPanel = ({ space }: FunctionsPanelProps) => {
28
26
  const { t } = useTranslation(meta.id);
29
- const functions = useQuery(space, Filter.type(Function.Function));
30
- const scripts = useQuery(space, Filter.type(Script.Script));
31
- const { dispatchPromise: dispatch } = useIntentDispatcher();
27
+ const functions = useQuery(space.db, Filter.type(Operation.PersistentOperation));
28
+ const scripts = useQuery(space.db, Filter.type(Script.Script));
29
+ const { invokePromise } = useOperationInvoker();
32
30
 
33
31
  const functionToScriptMap = useMemo(
34
32
  () =>
@@ -49,7 +47,7 @@ export const FunctionsPanel = ({ space }: FunctionsPanelProps) => {
49
47
  );
50
48
 
51
49
  const getScriptName = useCallback(
52
- (func: Function.Function) => {
50
+ (func: Operation.PersistentOperation) => {
53
51
  const script = functionToScriptMap[func.id];
54
52
  return script?.name;
55
53
  },
@@ -57,50 +55,55 @@ export const FunctionsPanel = ({ space }: FunctionsPanelProps) => {
57
55
  );
58
56
 
59
57
  const handleGoToScript = useCallback(
60
- (func: Function.Function) => {
58
+ (func: Operation.PersistentOperation) => {
61
59
  const script = functionToScriptMap[func.id];
62
60
  if (script) {
63
- void dispatch(
64
- createIntent(LayoutAction.Open, {
65
- part: 'main',
66
- subject: [Obj.getDXN(script).toString()],
67
- }),
68
- );
61
+ void invokePromise(LayoutOperation.Open, { subject: [getObjectPathFromObject(script)] });
69
62
  }
70
63
  },
71
- [functionToScriptMap, dispatch],
64
+ [functionToScriptMap, invokePromise],
72
65
  );
73
66
 
74
67
  const handleDelete = useCallback(
75
- (func: Function.Function) => dispatch(createIntent(SpaceAction.RemoveObjects, { objects: [func] })),
76
- [dispatch],
68
+ (func: Operation.PersistentOperation) => invokePromise(SpaceOperation.RemoveObjects, { objects: [func] }),
69
+ [invokePromise],
77
70
  );
78
71
 
79
72
  return (
80
- <div role='none' className={mx(controlItemClasses)}>
73
+ <Settings.Panel>
81
74
  {functions.length > 0 && (
82
- <List.Root<Function.Function> items={functions} isItem={Schema.is(Function.Function)} getId={(func) => func.id}>
75
+ <List.Root<Operation.PersistentOperation>
76
+ items={functions}
77
+ isItem={Schema.is(Operation.PersistentOperation)}
78
+ getId={(func) => func.id}
79
+ >
83
80
  {({ items }) => (
84
- <div role='list' className='flex flex-col is-full'>
81
+ <div role='list' className='flex flex-col w-full'>
85
82
  {items?.map((func) => (
86
- <List.Item<Function.Function>
83
+ <List.Item<Operation.PersistentOperation>
87
84
  key={func.id}
88
85
  item={func}
89
- classNames={mx(grid, ghostHover, 'items-center', 'pli-2', 'min-bs-[3rem]')}
86
+ classNames={mx(
87
+ 'grid grid-cols-[1fr_min-content_auto] min-h-[2.5rem] min-h-[3rem] px-2 items-center',
88
+ ghostHover,
89
+ )}
90
90
  >
91
91
  <div className='flex flex-col truncate'>
92
92
  <List.ItemTitle classNames='truncate'>{func.name}</List.ItemTitle>
93
- {getScriptName(func) && (
94
- <div className='text-xs text-description truncate'>{getScriptName(func)}</div>
95
- )}
93
+ {getScriptName(func) && <p className='text-xs text-description truncate'>{getScriptName(func)}</p>}
96
94
  </div>
97
- {functionToScriptMap[func.id] && (
98
- <Button onClick={() => handleGoToScript(func)}>{t('go to function source button label')}</Button>
99
- )}
95
+ {(functionToScriptMap[func.id] && (
96
+ <IconButton
97
+ icon='ph--arrow-square-out--regular'
98
+ iconOnly
99
+ label={t('show-source-button.label')}
100
+ onClick={() => handleGoToScript(func)}
101
+ />
102
+ )) || <div />}
100
103
  <IconButton
101
- iconOnly
102
104
  icon='ph--trash--regular'
103
- label={t('delete function button label')}
105
+ iconOnly
106
+ label={t('delete-function-button.label')}
104
107
  onClick={() => handleDelete(func)}
105
108
  />
106
109
  </List.Item>
@@ -109,8 +112,6 @@ export const FunctionsPanel = ({ space }: FunctionsPanelProps) => {
109
112
  )}
110
113
  </List.Root>
111
114
  )}
112
-
113
- {functions.length === 0 && <div className='text-center plb-4 text-gray-500'>{t('no functions found')}</div>}
114
- </div>
115
+ </Settings.Panel>
115
116
  );
116
117
  };
@@ -2,26 +2,23 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import * as Array from 'effect/Array';
6
- import * as EffectFunction from 'effect/Function';
7
- import * as Order from 'effect/Order';
8
5
  import * as Schema from 'effect/Schema';
9
6
  import { useState } from 'react';
10
7
  import React, { useCallback } from 'react';
11
8
 
12
- import { Function } from '@dxos/functions';
9
+ import { Context } from '@dxos/context';
13
10
  import { getDeployedFunctions } from '@dxos/functions-runtime/edge';
11
+ import * as OperationModule from '@dxos/operation';
14
12
  import { useClient } from '@dxos/react-client';
15
13
  import { Filter, Query, type Space, useQuery } from '@dxos/react-client/echo';
16
- import { useAsyncEffect } from '@dxos/react-ui';
17
- import { IconButton, useTranslation } from '@dxos/react-ui';
18
- import { controlItemClasses } from '@dxos/react-ui-form';
14
+ import { IconButton, useAsyncEffect, useTranslation } from '@dxos/react-ui';
15
+ import { Settings } from '@dxos/react-ui-form';
19
16
  import { List } from '@dxos/react-ui-list';
20
- import { ghostHover, mx } from '@dxos/react-ui-theme';
17
+ import { ghostHover, mx } from '@dxos/ui-theme';
21
18
 
22
- import { meta } from '../../meta';
19
+ import { meta } from '#meta';
23
20
 
24
- const grid = 'grid grid-cols-[1fr_1fr_auto] min-bs-[2.5rem]';
21
+ const grid = 'grid grid-cols-[1fr_1fr_auto] min-h-[2.5rem]';
25
22
 
26
23
  type FunctionsRegistryProps = {
27
24
  space: Space;
@@ -30,12 +27,12 @@ type FunctionsRegistryProps = {
30
27
  export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
31
28
  const client = useClient();
32
29
  const [loading, setLoading] = useState(true);
33
- const [functions, setFunctions] = useState<Function.Function[]>([]);
30
+ const [functions, setFunctions] = useState<OperationModule.Operation.PersistentOperation[]>([]);
34
31
  const { t } = useTranslation(meta.id);
35
32
 
36
- const dbFunctions = useQuery(space, Filter.type(Function.Function));
33
+ const dbFunctions = useQuery(space.db, Filter.type(OperationModule.Operation.PersistentOperation));
37
34
 
38
- const state = (func: Function.Function) => {
35
+ const state = (func: OperationModule.Operation.PersistentOperation) => {
39
36
  const dbFunction = dbFunctions.find((f) => f.key === func.key);
40
37
  if (!dbFunction) {
41
38
  return 'import';
@@ -48,48 +45,41 @@ export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
48
45
 
49
46
  useAsyncEffect(async () => {
50
47
  setLoading(true);
51
- const functions = await getDeployedFunctions(client);
48
+ const functions = await getDeployedFunctions(Context.default(), client, true);
52
49
  setFunctions(functions);
53
50
  setLoading(false);
54
51
  }, []);
55
52
 
56
- const dedupedFunctions = EffectFunction.pipe(
57
- functions,
58
- Array.filter((_) => _.key !== undefined),
59
- Array.sort(Order.reverse(Order.mapInput(Order.string, (_: Function.Function) => _.updated ?? ''))),
60
- Array.dedupeWith((self, that) => self.key === that.key),
61
- Array.sort(Order.mapInput(Order.string, (_: Function.Function) => _.key ?? '')),
62
- );
63
-
64
53
  const hanleImportOrUpdate = useCallback(
65
- async (func: Function.Function) => {
66
- const {
67
- objects: [existingFunc],
68
- } = await space.db.query(Query.type(Function.Function, { key: func.key })).run();
54
+ async (func: OperationModule.Operation.PersistentOperation) => {
55
+ const functions = await space.db
56
+ .query(Query.type(OperationModule.Operation.PersistentOperation, { key: func.key }))
57
+ .run();
58
+ const [existingFunc] = functions;
69
59
  if (!existingFunc) {
70
60
  space.db.add(func);
71
61
  return;
72
62
  }
73
- Function.setFrom(existingFunc, func);
63
+ OperationModule.Operation.setFrom(existingFunc, func);
74
64
  },
75
65
  [space],
76
66
  );
77
67
 
78
68
  return (
79
- <div role='none' className={mx(controlItemClasses)}>
80
- {dedupedFunctions.length > 0 && (
81
- <List.Root<Function.Function>
82
- items={dedupedFunctions}
83
- isItem={Schema.is(Function.Function)}
69
+ <Settings.Panel>
70
+ {functions.length > 0 && (
71
+ <List.Root<OperationModule.Operation.PersistentOperation>
72
+ items={functions}
73
+ isItem={Schema.is(OperationModule.Operation.PersistentOperation)}
84
74
  getId={(func) => func.id}
85
75
  >
86
76
  {({ items }) => (
87
- <div role='list' className='flex flex-col is-full'>
77
+ <div role='list' className='flex flex-col w-full'>
88
78
  {items?.map((func) => (
89
- <List.Item<Function.Function>
79
+ <List.Item<OperationModule.Operation.PersistentOperation>
90
80
  key={func.id}
91
81
  item={func}
92
- classNames={mx(grid, ghostHover, 'items-center', 'pli-2', 'min-bs-[3rem]')}
82
+ classNames={mx(grid, ghostHover, 'items-center', 'px-2', 'min-h-[3rem]')}
93
83
  >
94
84
  <div className='flex flex-col truncate'>
95
85
  <List.ItemTitle classNames='truncate'>{func.name}</List.ItemTitle>
@@ -106,7 +96,7 @@ export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
106
96
  iconOnly
107
97
  icon={state(func) === 'update' ? 'ph--arrows-clockwise--regular' : 'ph--download--regular'}
108
98
  label={
109
- state(func) === 'update' ? t('update function button label') : t('import function button label')
99
+ state(func) === 'update' ? t('update-function-button.label') : t('import-function-button.label')
110
100
  }
111
101
  disabled={state(func) === 'none'}
112
102
  onClick={() => hanleImportOrUpdate(func)}
@@ -118,10 +108,7 @@ export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
118
108
  </List.Root>
119
109
  )}
120
110
 
121
- {dedupedFunctions.length === 0 && !loading && (
122
- <div className='text-center plb-4 text-gray-500'>{t('no functions found')}</div>
123
- )}
124
- {loading && <div className='text-center plb-4 text-gray-500'>{t('loading functions')}</div>}
125
- </div>
111
+ {loading && <div className='text-center py-4 text-gray-500'>{t('loading-functions.message')}</div>}
112
+ </Settings.Panel>
126
113
  );
127
114
  };
@@ -2,4 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export { FunctionsRegistry } from './FunctionsRegistry';
5
+ import { FunctionsRegistry } from './FunctionsRegistry';
6
+
7
+ export { FunctionsRegistry };
8
+ export default FunctionsRegistry;