@dxos/plugin-automation 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6

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 (259) hide show
  1. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  2. package/dist/lib/browser/chunk-NQY2QL47.mjs +44 -0
  3. package/dist/lib/browser/chunk-NQY2QL47.mjs.map +7 -0
  4. package/dist/lib/browser/{chunk-JOXPQ27I.mjs → chunk-WZKRIDQ6.mjs} +9 -38
  5. package/dist/lib/browser/chunk-WZKRIDQ6.mjs.map +7 -0
  6. package/dist/lib/browser/cli/index.mjs +96 -81
  7. package/dist/lib/browser/cli/index.mjs.map +3 -3
  8. package/dist/lib/browser/create-trigger-from-template-J2Z7AAHV.mjs +77 -0
  9. package/dist/lib/browser/create-trigger-from-template-J2Z7AAHV.mjs.map +7 -0
  10. package/dist/lib/browser/hooks/index.mjs +110 -6
  11. package/dist/lib/browser/hooks/index.mjs.map +4 -4
  12. package/dist/lib/browser/index.mjs +60 -92
  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 +4 -4
  18. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  19. package/dist/lib/node-esm/{chunk-RX52VKI2.mjs → chunk-POUAOKR5.mjs} +9 -37
  20. package/dist/lib/node-esm/chunk-POUAOKR5.mjs.map +7 -0
  21. package/dist/lib/node-esm/chunk-Z6J7TDVZ.mjs +45 -0
  22. package/dist/lib/node-esm/chunk-Z6J7TDVZ.mjs.map +7 -0
  23. package/dist/lib/node-esm/cli/index.mjs +96 -81
  24. package/dist/lib/node-esm/cli/index.mjs.map +3 -3
  25. package/dist/lib/node-esm/create-trigger-from-template-TRSHHYEB.mjs +78 -0
  26. package/dist/lib/node-esm/create-trigger-from-template-TRSHHYEB.mjs.map +7 -0
  27. package/dist/lib/node-esm/hooks/index.mjs +110 -6
  28. package/dist/lib/node-esm/hooks/index.mjs.map +4 -4
  29. package/dist/lib/node-esm/index.mjs +60 -92
  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 +4 -4
  35. package/dist/types/src/AutomationPlugin.d.ts.map +1 -1
  36. package/dist/types/src/capabilities/app-graph-builder.d.ts +6 -0
  37. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  38. package/dist/types/src/capabilities/compute-runtime.d.ts +6 -0
  39. package/dist/types/src/capabilities/compute-runtime.d.ts.map +1 -0
  40. package/dist/types/src/capabilities/index.d.ts +6 -4
  41. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  42. package/dist/types/src/capabilities/node.d.ts +3 -0
  43. package/dist/types/src/capabilities/node.d.ts.map +1 -0
  44. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  45. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  46. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  47. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  48. package/dist/types/src/cli/commands/trigger/create/index.d.ts +1 -1
  49. package/dist/types/src/cli/commands/trigger/create/queue.d.ts +1 -1
  50. package/dist/types/src/cli/commands/trigger/create/queue.d.ts.map +1 -1
  51. package/dist/types/src/cli/commands/trigger/create/subscription.d.ts +1 -1
  52. package/dist/types/src/cli/commands/trigger/create/subscription.d.ts.map +1 -1
  53. package/dist/types/src/cli/commands/trigger/create/timer.d.ts +1 -1
  54. package/dist/types/src/cli/commands/trigger/create/timer.d.ts.map +1 -1
  55. package/dist/types/src/cli/commands/trigger/list.d.ts +1 -1
  56. package/dist/types/src/cli/commands/trigger/list.d.ts.map +1 -1
  57. package/dist/types/src/cli/commands/trigger/remove.d.ts +1 -1
  58. package/dist/types/src/cli/commands/trigger/update/queue.d.ts.map +1 -1
  59. package/dist/types/src/cli/commands/trigger/update/subscription.d.ts.map +1 -1
  60. package/dist/types/src/cli/commands/trigger/update/timer.d.ts.map +1 -1
  61. package/dist/types/src/cli/commands/trigger/util.d.ts +2 -2
  62. package/dist/types/src/cli/commands/trigger/util.d.ts.map +1 -1
  63. package/dist/types/src/cli/plugin.d.ts.map +1 -1
  64. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts +3 -4
  65. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts.map +1 -1
  66. package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts +28 -30
  67. package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts.map +1 -1
  68. package/dist/types/src/components/FunctionsPanel/FunctionsPanel.d.ts.map +1 -1
  69. package/dist/types/src/components/FunctionsRegistry/FunctionsRegistry.d.ts.map +1 -1
  70. package/dist/types/src/components/FunctionsRegistry/index.d.ts +3 -1
  71. package/dist/types/src/components/FunctionsRegistry/index.d.ts.map +1 -1
  72. package/dist/types/src/components/TriggerEditor/FunctionInputEditor.d.ts +2 -2
  73. package/dist/types/src/components/TriggerEditor/FunctionInputEditor.d.ts.map +1 -1
  74. package/dist/types/src/components/TriggerEditor/SpecSelector.d.ts.map +1 -1
  75. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
  76. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts +90 -91
  77. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -1
  78. package/dist/types/src/components/index.d.ts +3 -4
  79. package/dist/types/src/components/index.d.ts.map +1 -1
  80. package/dist/types/src/containers/AutomationSettings/AutomationSettings.d.ts +4 -0
  81. package/dist/types/src/containers/AutomationSettings/AutomationSettings.d.ts.map +1 -0
  82. package/dist/types/src/containers/AutomationSettings/index.d.ts +3 -0
  83. package/dist/types/src/containers/AutomationSettings/index.d.ts.map +1 -0
  84. package/dist/types/src/{components → containers/FunctionsContainer}/FunctionsContainer.d.ts +0 -1
  85. package/dist/types/src/containers/FunctionsContainer/FunctionsContainer.d.ts.map +1 -0
  86. package/dist/types/src/containers/FunctionsContainer/index.d.ts +3 -0
  87. package/dist/types/src/containers/FunctionsContainer/index.d.ts.map +1 -0
  88. package/dist/types/src/containers/TriggerSettings/TriggerSettings.d.ts.map +1 -0
  89. package/dist/types/src/containers/TriggerSettings/index.d.ts +3 -0
  90. package/dist/types/src/containers/TriggerSettings/index.d.ts.map +1 -0
  91. package/dist/types/src/containers/index.d.ts +5 -0
  92. package/dist/types/src/containers/index.d.ts.map +1 -0
  93. package/dist/types/src/hooks/index.d.ts +2 -0
  94. package/dist/types/src/hooks/index.d.ts.map +1 -1
  95. package/dist/types/src/hooks/useComputeRuntime.d.ts +7 -0
  96. package/dist/types/src/hooks/useComputeRuntime.d.ts.map +1 -0
  97. package/dist/types/src/hooks/useComputeRuntimeCallback.d.ts +4 -3
  98. package/dist/types/src/hooks/useComputeRuntimeCallback.d.ts.map +1 -1
  99. package/dist/types/src/hooks/useComputeRuntimeService.d.ts +5 -0
  100. package/dist/types/src/hooks/useComputeRuntimeService.d.ts.map +1 -0
  101. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +2 -1
  102. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -1
  103. package/dist/types/src/index.d.ts +2 -5
  104. package/dist/types/src/index.d.ts.map +1 -1
  105. package/dist/types/src/operations/create-trigger-from-template.d.ts +5 -0
  106. package/dist/types/src/operations/create-trigger-from-template.d.ts.map +1 -0
  107. package/dist/types/src/operations/definitions.d.ts +19 -0
  108. package/dist/types/src/operations/definitions.d.ts.map +1 -0
  109. package/dist/types/src/operations/index.d.ts +4 -0
  110. package/dist/types/src/operations/index.d.ts.map +1 -0
  111. package/dist/types/src/testing/test-functions.d.ts +16 -14
  112. package/dist/types/src/testing/test-functions.d.ts.map +1 -1
  113. package/dist/types/src/translations.d.ts +29 -31
  114. package/dist/types/src/translations.d.ts.map +1 -1
  115. package/dist/types/src/types/capabilities.d.ts +5 -3
  116. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  117. package/dist/types/src/types/schema.d.ts +9 -30
  118. package/dist/types/src/types/schema.d.ts.map +1 -1
  119. package/dist/types/tsconfig.tsbuildinfo +1 -1
  120. package/package.json +73 -46
  121. package/src/AutomationPlugin.tsx +13 -10
  122. package/src/capabilities/app-graph-builder.ts +62 -0
  123. package/src/capabilities/{compute-runtime/compute-runtime.ts → compute-runtime.ts} +68 -21
  124. package/src/capabilities/index.ts +10 -4
  125. package/src/capabilities/operation-handler.ts +16 -0
  126. package/src/capabilities/{react-surface/react-surface.tsx → react-surface.tsx} +17 -20
  127. package/src/cli/commands/trigger/create/queue.ts +7 -6
  128. package/src/cli/commands/trigger/create/subscription.ts +7 -6
  129. package/src/cli/commands/trigger/create/timer.ts +7 -6
  130. package/src/cli/commands/trigger/list.ts +3 -2
  131. package/src/cli/commands/trigger/remove.ts +2 -2
  132. package/src/cli/commands/trigger/update/queue.ts +12 -12
  133. package/src/cli/commands/trigger/update/subscription.ts +12 -11
  134. package/src/cli/commands/trigger/update/timer.ts +12 -11
  135. package/src/cli/commands/trigger/util.ts +43 -29
  136. package/src/cli/plugin.ts +7 -6
  137. package/src/components/AutomationPanel/AutomationPanel.stories.tsx +9 -7
  138. package/src/components/AutomationPanel/AutomationPanel.tsx +147 -77
  139. package/src/components/FunctionsPanel/FunctionsPanel.tsx +37 -31
  140. package/src/components/FunctionsRegistry/FunctionsRegistry.tsx +27 -24
  141. package/src/components/FunctionsRegistry/index.ts +4 -1
  142. package/src/components/TriggerEditor/FunctionInputEditor.tsx +17 -8
  143. package/src/components/TriggerEditor/SpecSelector.tsx +12 -3
  144. package/src/components/TriggerEditor/TriggerEditor.stories.tsx +52 -9
  145. package/src/components/TriggerEditor/TriggerEditor.tsx +46 -17
  146. package/src/components/index.ts +1 -2
  147. package/src/containers/AutomationSettings/AutomationSettings.tsx +27 -0
  148. package/src/containers/AutomationSettings/index.ts +7 -0
  149. package/src/containers/FunctionsContainer/FunctionsContainer.tsx +33 -0
  150. package/src/containers/FunctionsContainer/index.ts +7 -0
  151. package/src/{components → containers/TriggerSettings}/TriggerSettings.tsx +8 -7
  152. package/src/containers/TriggerSettings/index.ts +6 -0
  153. package/src/containers/index.ts +9 -0
  154. package/src/hooks/index.ts +3 -0
  155. package/src/hooks/useComputeRuntime.ts +15 -0
  156. package/src/hooks/useComputeRuntimeCallback.ts +6 -6
  157. package/src/hooks/useComputeRuntimeService.ts +22 -0
  158. package/src/hooks/useTriggerRuntimeControls.ts +22 -8
  159. package/src/index.ts +2 -6
  160. package/src/meta.ts +1 -1
  161. package/src/operations/create-trigger-from-template.ts +74 -0
  162. package/src/operations/definitions.ts +27 -0
  163. package/src/operations/index.ts +9 -0
  164. package/src/testing/test-functions.ts +8 -5
  165. package/src/translations.ts +35 -36
  166. package/src/types/capabilities.ts +18 -6
  167. package/src/types/events.ts +2 -2
  168. package/src/types/schema.ts +3 -24
  169. package/dist/lib/browser/AutomationPanel-FAS6ADCW.mjs +0 -11
  170. package/dist/lib/browser/AutomationSettings-XN2OIYWL.mjs +0 -56
  171. package/dist/lib/browser/AutomationSettings-XN2OIYWL.mjs.map +0 -7
  172. package/dist/lib/browser/FunctionsContainer-6QLC7JP4.mjs +0 -129
  173. package/dist/lib/browser/FunctionsContainer-6QLC7JP4.mjs.map +0 -7
  174. package/dist/lib/browser/FunctionsPanel-ZX4J75UM.mjs +0 -10
  175. package/dist/lib/browser/app-graph-builder-LAQMEBMH.mjs +0 -84
  176. package/dist/lib/browser/app-graph-builder-LAQMEBMH.mjs.map +0 -7
  177. package/dist/lib/browser/chunk-54PANILA.mjs +0 -14
  178. package/dist/lib/browser/chunk-54PANILA.mjs.map +0 -7
  179. package/dist/lib/browser/chunk-BFUIVUQH.mjs +0 -102
  180. package/dist/lib/browser/chunk-BFUIVUQH.mjs.map +0 -7
  181. package/dist/lib/browser/chunk-BKFQBKYO.mjs +0 -8
  182. package/dist/lib/browser/chunk-BKFQBKYO.mjs.map +0 -7
  183. package/dist/lib/browser/chunk-JOXPQ27I.mjs.map +0 -7
  184. package/dist/lib/browser/chunk-PZNBEKO5.mjs +0 -17
  185. package/dist/lib/browser/chunk-PZNBEKO5.mjs.map +0 -7
  186. package/dist/lib/browser/chunk-QW3EM35H.mjs +0 -248
  187. package/dist/lib/browser/chunk-QW3EM35H.mjs.map +0 -7
  188. package/dist/lib/browser/chunk-RAF2FJST.mjs +0 -86
  189. package/dist/lib/browser/chunk-RAF2FJST.mjs.map +0 -7
  190. package/dist/lib/browser/chunk-YWLEY2FD.mjs +0 -200
  191. package/dist/lib/browser/chunk-YWLEY2FD.mjs.map +0 -7
  192. package/dist/lib/browser/compute-runtime-WTWLQ67J.mjs +0 -114
  193. package/dist/lib/browser/compute-runtime-WTWLQ67J.mjs.map +0 -7
  194. package/dist/lib/browser/operation-resolver-Q3MWOR7K.mjs +0 -82
  195. package/dist/lib/browser/operation-resolver-Q3MWOR7K.mjs.map +0 -7
  196. package/dist/lib/browser/react-surface-EV3AC62F.mjs +0 -65
  197. package/dist/lib/browser/react-surface-EV3AC62F.mjs.map +0 -7
  198. package/dist/lib/node-esm/AutomationPanel-B7NAGDFA.mjs +0 -12
  199. package/dist/lib/node-esm/AutomationPanel-B7NAGDFA.mjs.map +0 -7
  200. package/dist/lib/node-esm/AutomationSettings-M5PMZJ6P.mjs +0 -57
  201. package/dist/lib/node-esm/AutomationSettings-M5PMZJ6P.mjs.map +0 -7
  202. package/dist/lib/node-esm/FunctionsContainer-J4O2ULWR.mjs +0 -130
  203. package/dist/lib/node-esm/FunctionsContainer-J4O2ULWR.mjs.map +0 -7
  204. package/dist/lib/node-esm/FunctionsPanel-SS6GIVNU.mjs +0 -11
  205. package/dist/lib/node-esm/FunctionsPanel-SS6GIVNU.mjs.map +0 -7
  206. package/dist/lib/node-esm/app-graph-builder-4UCMXHYY.mjs +0 -85
  207. package/dist/lib/node-esm/app-graph-builder-4UCMXHYY.mjs.map +0 -7
  208. package/dist/lib/node-esm/chunk-2CKVH7JC.mjs +0 -201
  209. package/dist/lib/node-esm/chunk-2CKVH7JC.mjs.map +0 -7
  210. package/dist/lib/node-esm/chunk-5FXNN3MV.mjs +0 -19
  211. package/dist/lib/node-esm/chunk-5FXNN3MV.mjs.map +0 -7
  212. package/dist/lib/node-esm/chunk-7QRUPEHH.mjs +0 -16
  213. package/dist/lib/node-esm/chunk-7QRUPEHH.mjs.map +0 -7
  214. package/dist/lib/node-esm/chunk-HQLVREIX.mjs +0 -87
  215. package/dist/lib/node-esm/chunk-HQLVREIX.mjs.map +0 -7
  216. package/dist/lib/node-esm/chunk-K7GCM342.mjs +0 -10
  217. package/dist/lib/node-esm/chunk-K7GCM342.mjs.map +0 -7
  218. package/dist/lib/node-esm/chunk-KWKWOGS5.mjs +0 -103
  219. package/dist/lib/node-esm/chunk-KWKWOGS5.mjs.map +0 -7
  220. package/dist/lib/node-esm/chunk-LJAXQ6CX.mjs +0 -249
  221. package/dist/lib/node-esm/chunk-LJAXQ6CX.mjs.map +0 -7
  222. package/dist/lib/node-esm/chunk-RX52VKI2.mjs.map +0 -7
  223. package/dist/lib/node-esm/compute-runtime-ZHROOBLY.mjs +0 -115
  224. package/dist/lib/node-esm/compute-runtime-ZHROOBLY.mjs.map +0 -7
  225. package/dist/lib/node-esm/operation-resolver-R5GA4YNO.mjs +0 -83
  226. package/dist/lib/node-esm/operation-resolver-R5GA4YNO.mjs.map +0 -7
  227. package/dist/lib/node-esm/react-surface-S6VZJCEZ.mjs +0 -66
  228. package/dist/lib/node-esm/react-surface-S6VZJCEZ.mjs.map +0 -7
  229. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +0 -6
  230. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  231. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  232. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  233. package/dist/types/src/capabilities/compute-runtime/compute-runtime.d.ts +0 -6
  234. package/dist/types/src/capabilities/compute-runtime/compute-runtime.d.ts.map +0 -1
  235. package/dist/types/src/capabilities/compute-runtime/index.d.ts +0 -3
  236. package/dist/types/src/capabilities/compute-runtime/index.d.ts.map +0 -1
  237. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
  238. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  239. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
  240. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  241. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  242. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  243. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
  244. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  245. package/dist/types/src/components/AutomationSettings.d.ts +0 -5
  246. package/dist/types/src/components/AutomationSettings.d.ts.map +0 -1
  247. package/dist/types/src/components/FunctionsContainer.d.ts.map +0 -1
  248. package/dist/types/src/components/TriggerSettings.d.ts.map +0 -1
  249. package/src/capabilities/app-graph-builder/app-graph-builder.ts +0 -71
  250. package/src/capabilities/app-graph-builder/index.ts +0 -7
  251. package/src/capabilities/operation-resolver/index.ts +0 -7
  252. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -79
  253. package/src/capabilities/react-surface/index.ts +0 -7
  254. package/src/components/AutomationSettings.tsx +0 -30
  255. package/src/components/FunctionsContainer.tsx +0 -36
  256. /package/dist/lib/browser/{AutomationPanel-FAS6ADCW.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  257. /package/dist/lib/{browser/FunctionsPanel-ZX4J75UM.mjs.map → node-esm/chunk-HSLMI22Q.mjs.map} +0 -0
  258. /package/dist/types/src/{components → containers/TriggerSettings}/TriggerSettings.d.ts +0 -0
  259. /package/src/capabilities/{compute-runtime/index.ts → node.ts} +0 -0
@@ -6,39 +6,42 @@ 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 { Context } from '@dxos/context';
11
12
  import { Filter, Obj, Tag } from '@dxos/echo';
12
- import { Function, Script, Trigger } from '@dxos/functions';
13
+ import { Script, Trigger } from '@dxos/functions';
14
+ import { Operation } from '@dxos/operation';
15
+ import { KEY_QUEUE_CURSOR } from '@dxos/functions-runtime';
13
16
  import { FunctionsServiceClient } from '@dxos/functions-runtime/edge';
14
- import { useTypeOptions } from '@dxos/plugin-space';
17
+ import { useTypeOptions } from '@dxos/app-toolkit/ui';
15
18
  import { type Client, useClient } from '@dxos/react-client';
16
- import { type Space, useQuery } from '@dxos/react-client/echo';
17
- import { Clipboard, IconButton, Input, Separator, type ThemedClassName, useTranslation } from '@dxos/react-ui';
18
- 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';
19
22
  import { List } from '@dxos/react-ui-list';
20
- import { Project } from '@dxos/types';
23
+ import { Pipeline } from '@dxos/types';
21
24
  import { ghostHover, mx } from '@dxos/ui-theme';
22
25
  import { isNonNullable } from '@dxos/util';
23
26
 
24
- import { meta } from '../../meta';
27
+ import { meta } from '#meta';
25
28
  import { TriggerEditor, type TriggerEditorProps } from '../TriggerEditor';
26
29
 
27
- const grid = 'grid grid-cols-[40px_1fr_32px_32px] min-bs-[2.5rem]';
30
+ const grid = 'grid grid-cols-[40px_1fr_32px_32px] min-h-[2.5rem]';
28
31
 
29
- export type AutomationPanelProps = ThemedClassName<{
32
+ export type AutomationPanelProps = {
30
33
  space: Space;
31
34
  object?: Obj.Unknown;
32
35
  initialTrigger?: Trigger.Trigger;
33
36
  onDone?: () => void;
34
- }>;
37
+ };
35
38
 
36
39
  // TODO(burdon): Factor out common layout with ViewEditor.
37
- export const AutomationPanel = ({ classNames, space, object, initialTrigger, onDone }: AutomationPanelProps) => {
40
+ export const AutomationPanel = ({ space, object, initialTrigger, onDone }: AutomationPanelProps) => {
38
41
  const { t } = useTranslation(meta.id);
39
42
  const client = useClient();
40
43
  const functionsServiceClient = useMemo(() => FunctionsServiceClient.fromClient(client), [client]);
41
- const functions = useQuery(space.db, Filter.type(Function.Function));
44
+ const functions = useQuery(space.db, Filter.type(Operation.PersistentOperation));
42
45
  const triggers = useQuery(space.db, Filter.type(Trigger.Trigger));
43
46
  const filteredTriggers = useMemo(() => {
44
47
  return object ? triggers.filter(triggerMatch(object)) : triggers;
@@ -49,7 +52,6 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
49
52
  annotation: {
50
53
  location: ['database', 'runtime'],
51
54
  kind: ['user'],
52
- registered: ['registered'],
53
55
  },
54
56
  });
55
57
 
@@ -74,7 +76,9 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
74
76
 
75
77
  const handleSave: TriggerEditorProps['onSave'] = (trigger) => {
76
78
  if (selected) {
77
- Object.assign(selected, trigger);
79
+ Obj.change(selected, (mutable) => {
80
+ Object.assign(mutable, trigger);
81
+ });
78
82
  } else {
79
83
  space.db.add(Trigger.make(trigger));
80
84
  }
@@ -90,12 +94,19 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
90
94
  };
91
95
 
92
96
  const handleForceRunTrigger = async (trigger: Trigger.Trigger) => {
93
- await functionsServiceClient.forceRunCronTrigger(space.id, trigger.id);
97
+ await functionsServiceClient.forceRunCronTrigger(Context.default(), space.id, trigger.id);
98
+ };
99
+
100
+ const handleResetCursor = async (trigger: Trigger.Trigger) => {
101
+ Obj.change(trigger, (obj) => {
102
+ Obj.deleteKeys(obj, KEY_QUEUE_CURSOR);
103
+ });
104
+ await space.db.flush({ indexes: true });
94
105
  };
95
106
 
96
107
  if (trigger) {
97
108
  return (
98
- <ControlItem title={t('trigger editor title')}>
109
+ <Settings.Item title={t('trigger-editor.title')} description={t('trigger-editor.description')}>
99
110
  <TriggerEditor
100
111
  db={space.db}
101
112
  trigger={trigger}
@@ -105,12 +116,12 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
105
116
  onSave={handleSave}
106
117
  onCancel={handleCancel}
107
118
  />
108
- </ControlItem>
119
+ </Settings.Item>
109
120
  );
110
121
  }
111
122
 
112
123
  return (
113
- <div className={mx(controlItemClasses, classNames)}>
124
+ <Settings.Panel>
114
125
  {filteredTriggers.length > 0 && (
115
126
  <List.Root<Trigger.Trigger>
116
127
  items={filteredTriggers}
@@ -118,75 +129,134 @@ export const AutomationPanel = ({ classNames, space, object, initialTrigger, onD
118
129
  getId={(field) => field.id}
119
130
  >
120
131
  {({ items: filteredTriggers }) => (
121
- <div role='list' className='flex flex-col is-full'>
122
- {filteredTriggers?.map((trigger) => {
123
- const copyAction = getCopyAction(client, trigger);
124
- return (
125
- <List.Item<Trigger.Trigger>
126
- key={trigger.id}
127
- item={trigger}
128
- classNames={mx(grid, ghostHover, 'items-center', 'pli-2')}
129
- >
130
- <Input.Root>
131
- <Input.Switch
132
- checked={trigger.enabled}
133
- onCheckedChange={(checked) =>
134
- Obj.change(trigger, (t) => {
135
- t.enabled = checked;
136
- })
137
- }
138
- />
139
- </Input.Root>
140
-
141
- <div className={'flex'}>
142
- <List.ItemTitle
143
- classNames='pli-1 cursor-pointer is-0 shrink truncate'
144
- onClick={() => handleSelect(trigger)}
145
- >
146
- {getFunctionName(functions, trigger) ?? '∅'}
147
- </List.ItemTitle>
148
-
149
- {/* TODO: a better way to expose copy action */}
150
- {copyAction && (
151
- <Clipboard.IconButton
152
- label={t(copyAction.translationKey)}
153
- value={copyAction.contentProvider()}
154
- />
155
- )}
156
- </div>
157
-
158
- <List.ItemButton
159
- autoHide={false}
160
- disabled={!trigger.enabled || trigger.spec?.kind !== 'timer'}
161
- icon='ph--play--regular'
162
- label='Force run'
163
- onClick={() => handleForceRunTrigger(trigger)}
164
- />
165
-
166
- <List.ItemDeleteButton onClick={() => handleDelete(trigger)} />
167
- </List.Item>
168
- );
169
- })}
132
+ <div role='list' className='flex flex-col w-full'>
133
+ {filteredTriggers?.map((trigger) => (
134
+ <TriggerListItem
135
+ key={trigger.id}
136
+ trigger={trigger}
137
+ functions={functions}
138
+ onSelect={handleSelect}
139
+ onDelete={handleDelete}
140
+ onResetCursor={handleResetCursor}
141
+ onForceRun={handleForceRunTrigger}
142
+ />
143
+ ))}
170
144
  </div>
171
145
  )}
172
146
  </List.Root>
173
147
  )}
174
- {filteredTriggers.length > 0 && <Separator classNames='mlb-4' />}
175
- <IconButton icon='ph--plus--regular' label={t('new trigger label')} onClick={handleAdd} />
176
- </div>
148
+
149
+ {filteredTriggers.length > 0 && <Separator classNames='my-4' />}
150
+ <IconButton icon='ph--plus--regular' label={t('new-trigger.label')} onClick={handleAdd} />
151
+ </Settings.Panel>
152
+ );
153
+ };
154
+
155
+ const TriggerListItem = ({
156
+ trigger,
157
+ functions,
158
+ onSelect,
159
+ onDelete,
160
+ onResetCursor,
161
+ onForceRun,
162
+ }: {
163
+ trigger: Trigger.Trigger;
164
+ functions: Operation.PersistentOperation[];
165
+ onSelect?: (trigger: Trigger.Trigger) => void;
166
+ onDelete?: (trigger: Trigger.Trigger) => void;
167
+ onResetCursor?: (trigger: Trigger.Trigger) => void;
168
+ onForceRun?: (trigger: Trigger.Trigger) => void;
169
+ }) => {
170
+ const client = useClient();
171
+ const copyAction = getCopyAction(client, trigger);
172
+ const { t } = useTranslation(meta.id);
173
+ const cursor = Obj.getKeys(trigger, KEY_QUEUE_CURSOR).at(0)?.id;
174
+ const [snapshot, updateTrigger] = useObject(trigger);
175
+
176
+ const enabled = snapshot.enabled ?? false;
177
+ const onEnabledChange = (checked: boolean) => {
178
+ updateTrigger((trigger) => {
179
+ trigger.enabled = checked;
180
+ });
181
+ };
182
+
183
+ const handleSelect = useCallback(() => {
184
+ onSelect?.(trigger);
185
+ }, [onSelect, trigger]);
186
+
187
+ const handleDelete = useCallback(() => {
188
+ onDelete?.(trigger);
189
+ }, [onDelete, trigger]);
190
+
191
+ const handleResetCursor = useCallback(() => {
192
+ onResetCursor?.(trigger);
193
+ }, [onResetCursor, trigger]);
194
+
195
+ const handleForceRun = useCallback(() => {
196
+ onForceRun?.(trigger);
197
+ }, [onForceRun, trigger]);
198
+
199
+ const actionProps = useMemo<IconButtonProps | undefined>(() => {
200
+ if (trigger.spec?.kind === 'timer' && onForceRun) {
201
+ return {
202
+ disabled: !enabled || trigger.spec?.kind !== 'timer',
203
+ icon: 'ph--play--regular',
204
+ label: 'Force run',
205
+ onClick: handleForceRun,
206
+ };
207
+ }
208
+
209
+ if (trigger.spec?.kind === 'queue' && onResetCursor) {
210
+ return {
211
+ disabled: !cursor,
212
+ icon: 'ph--arrow-clockwise--regular',
213
+ label: 'Reset cursor',
214
+ onClick: handleResetCursor,
215
+ };
216
+ }
217
+ }, [enabled, trigger.spec?.kind, handleForceRun]);
218
+
219
+ return (
220
+ <List.Item<Obj.Snapshot<Trigger.Trigger>>
221
+ key={trigger.id}
222
+ item={snapshot}
223
+ classNames={mx(grid, ghostHover, 'items-center', 'px-2')}
224
+ >
225
+ <Input.Root>
226
+ <Input.Switch checked={enabled} onCheckedChange={onEnabledChange} />
227
+ </Input.Root>
228
+
229
+ <div className={'flex'}>
230
+ <List.ItemTitle classNames='px-1 cursor-pointer w-0 shrink truncate' onClick={handleSelect}>
231
+ {getFunctionName(functions, trigger) ?? '∅'}
232
+ {cursor && <div className='text-xs text-description truncate ml-4'>Position: {cursor}</div>}
233
+ </List.ItemTitle>
234
+
235
+ {copyAction && (
236
+ <Clipboard.IconButton label={t(copyAction.translationKey)} value={copyAction.contentProvider()} />
237
+ )}
238
+ </div>
239
+
240
+ {actionProps ? <List.ItemIconButton {...actionProps} autoHide={false} /> : <div />}
241
+
242
+ {onDelete && <List.ItemDeleteButton onClick={handleDelete} />}
243
+ </List.Item>
177
244
  );
178
245
  };
179
246
 
180
247
  const getCopyAction = (client: Client, trigger: Trigger.Trigger | undefined) => {
181
248
  if (trigger?.spec?.kind === 'email') {
182
249
  return {
183
- translationKey: 'trigger copy email',
250
+ translationKey: 'trigger copy email' as const,
184
251
  contentProvider: () => `${Obj.getDatabase(trigger)!.spaceId}@dxos.network`,
185
252
  };
186
253
  }
187
254
 
188
255
  if (trigger?.spec?.kind === 'webhook') {
189
- return { translationKey: 'trigger copy url', contentProvider: () => getWebhookUrl(client, trigger) };
256
+ return {
257
+ translationKey: 'trigger copy url' as const,
258
+ contentProvider: () => getWebhookUrl(client, trigger!),
259
+ };
190
260
  }
191
261
 
192
262
  return undefined;
@@ -200,7 +270,7 @@ const getWebhookUrl = (client: Client, trigger: Trigger.Trigger) => {
200
270
  return new URL(`/webhook/${spaceId}:${trigger.id}`, edgeUrl).toString();
201
271
  };
202
272
 
203
- const getFunctionName = (functions: Function.Function[], trigger: Trigger.Trigger) => {
273
+ const getFunctionName = (functions: Operation.PersistentOperation[], trigger: Trigger.Trigger) => {
204
274
  // TODO(wittjosiah): Truncation should be done in the UI.
205
275
  // Warning that the List component is currently a can of worms.
206
276
  const shortId = trigger.function && `${trigger.function.dxn.toString().slice(0, 16)}…`;
@@ -210,14 +280,14 @@ const getFunctionName = (functions: Function.Function[], trigger: Trigger.Trigge
210
280
 
211
281
  const scriptMatch = (script: Script.Script) => (trigger: Trigger.Trigger) => {
212
282
  const fn = trigger.function?.target;
213
- if (!Obj.instanceOf(Function.Function, fn)) {
283
+ if (!Obj.instanceOf(Operation.PersistentOperation, fn)) {
214
284
  return false;
215
285
  }
216
286
 
217
287
  return fn.source?.target === script;
218
288
  };
219
289
 
220
- const projectMatch = (project: Project.Project) => {
290
+ const projectMatch = (project: Pipeline.Pipeline) => {
221
291
  const viewQueries = EFn.pipe(
222
292
  project.columns,
223
293
  Array.map((column) => column.view.target),
@@ -244,7 +314,7 @@ const triggerMatch = Match.type<Obj.Unknown>().pipe(
244
314
  (obj) => scriptMatch(obj),
245
315
  ),
246
316
  Match.when(
247
- (obj) => Obj.instanceOf(Project.Project, obj),
317
+ (obj) => Obj.instanceOf(Pipeline.Pipeline, obj),
248
318
  (obj) => projectMatch(obj),
249
319
  ),
250
320
  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 { Common } from '@dxos/app-framework';
9
- import { useOperationInvoker } from '@dxos/app-framework/react';
10
- import { Obj } from '@dxos/echo';
11
- import { Function, Script } from '@dxos/functions';
12
- import { SpaceOperation } 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
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,7 +24,7 @@ export type FunctionsPanelProps = {
26
24
 
27
25
  export const FunctionsPanel = ({ space }: FunctionsPanelProps) => {
28
26
  const { t } = useTranslation(meta.id);
29
- const functions = useQuery(space.db, Filter.type(Function.Function));
27
+ const functions = useQuery(space.db, Filter.type(Operation.PersistentOperation));
30
28
  const scripts = useQuery(space.db, Filter.type(Script.Script));
31
29
  const { invokePromise } = useOperationInvoker();
32
30
 
@@ -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,45 +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 invokePromise(Common.LayoutOperation.Open, { subject: [Obj.getDXN(script).toString()] });
61
+ void invokePromise(LayoutOperation.Open, { subject: [getObjectPathFromObject(script)] });
64
62
  }
65
63
  },
66
64
  [functionToScriptMap, invokePromise],
67
65
  );
68
66
 
69
67
  const handleDelete = useCallback(
70
- (func: Function.Function) => invokePromise(SpaceOperation.RemoveObjects, { objects: [func] }),
68
+ (func: Operation.PersistentOperation) => invokePromise(SpaceOperation.RemoveObjects, { objects: [func] }),
71
69
  [invokePromise],
72
70
  );
73
71
 
74
72
  return (
75
- <div role='none' className={mx(controlItemClasses)}>
73
+ <Settings.Panel>
76
74
  {functions.length > 0 && (
77
- <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
+ >
78
80
  {({ items }) => (
79
- <div role='list' className='flex flex-col is-full'>
81
+ <div role='list' className='flex flex-col w-full'>
80
82
  {items?.map((func) => (
81
- <List.Item<Function.Function>
83
+ <List.Item<Operation.PersistentOperation>
82
84
  key={func.id}
83
85
  item={func}
84
- 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
+ )}
85
90
  >
86
91
  <div className='flex flex-col truncate'>
87
92
  <List.ItemTitle classNames='truncate'>{func.name}</List.ItemTitle>
88
- {getScriptName(func) && (
89
- <div className='text-xs text-description truncate'>{getScriptName(func)}</div>
90
- )}
93
+ {getScriptName(func) && <p className='text-xs text-description truncate'>{getScriptName(func)}</p>}
91
94
  </div>
92
- {functionToScriptMap[func.id] && (
93
- <Button onClick={() => handleGoToScript(func)}>{t('go to function source button label')}</Button>
94
- )}
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 />}
95
103
  <IconButton
96
- iconOnly
97
104
  icon='ph--trash--regular'
98
- label={t('delete function button label')}
105
+ iconOnly
106
+ label={t('delete-function-button.label')}
99
107
  onClick={() => handleDelete(func)}
100
108
  />
101
109
  </List.Item>
@@ -104,8 +112,6 @@ export const FunctionsPanel = ({ space }: FunctionsPanelProps) => {
104
112
  )}
105
113
  </List.Root>
106
114
  )}
107
-
108
- {functions.length === 0 && <div className='text-center plb-4 text-gray-500'>{t('no functions found')}</div>}
109
- </div>
115
+ </Settings.Panel>
110
116
  );
111
117
  };
@@ -6,19 +6,19 @@ import * as Schema from 'effect/Schema';
6
6
  import { useState } from 'react';
7
7
  import React, { useCallback } from 'react';
8
8
 
9
- import { Function } from '@dxos/functions';
9
+ import { Context } from '@dxos/context';
10
+ import * as OperationModule from '@dxos/operation';
10
11
  import { getDeployedFunctions } from '@dxos/functions-runtime/edge';
11
12
  import { useClient } from '@dxos/react-client';
12
13
  import { Filter, Query, type Space, useQuery } from '@dxos/react-client/echo';
13
- import { useAsyncEffect } from '@dxos/react-ui';
14
- import { IconButton, useTranslation } from '@dxos/react-ui';
15
- import { controlItemClasses } from '@dxos/react-ui-form';
14
+ import { IconButton, useAsyncEffect, useTranslation } from '@dxos/react-ui';
15
+ import { Settings } from '@dxos/react-ui-form';
16
16
  import { List } from '@dxos/react-ui-list';
17
17
  import { ghostHover, mx } from '@dxos/ui-theme';
18
18
 
19
- import { meta } from '../../meta';
19
+ import { meta } from '#meta';
20
20
 
21
- 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]';
22
22
 
23
23
  type FunctionsRegistryProps = {
24
24
  space: Space;
@@ -27,12 +27,12 @@ type FunctionsRegistryProps = {
27
27
  export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
28
28
  const client = useClient();
29
29
  const [loading, setLoading] = useState(true);
30
- const [functions, setFunctions] = useState<Function.Function[]>([]);
30
+ const [functions, setFunctions] = useState<OperationModule.Operation.PersistentOperation[]>([]);
31
31
  const { t } = useTranslation(meta.id);
32
32
 
33
- const dbFunctions = useQuery(space.db, Filter.type(Function.Function));
33
+ const dbFunctions = useQuery(space.db, Filter.type(OperationModule.Operation.PersistentOperation));
34
34
 
35
- const state = (func: Function.Function) => {
35
+ const state = (func: OperationModule.Operation.PersistentOperation) => {
36
36
  const dbFunction = dbFunctions.find((f) => f.key === func.key);
37
37
  if (!dbFunction) {
38
38
  return 'import';
@@ -45,35 +45,41 @@ export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
45
45
 
46
46
  useAsyncEffect(async () => {
47
47
  setLoading(true);
48
- const functions = await getDeployedFunctions(client, true);
48
+ const functions = await getDeployedFunctions(Context.default(), client, true);
49
49
  setFunctions(functions);
50
50
  setLoading(false);
51
51
  }, []);
52
52
 
53
53
  const hanleImportOrUpdate = useCallback(
54
- async (func: Function.Function) => {
55
- const functions = 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();
56
58
  const [existingFunc] = functions;
57
59
  if (!existingFunc) {
58
60
  space.db.add(func);
59
61
  return;
60
62
  }
61
- Function.setFrom(existingFunc, func);
63
+ OperationModule.Operation.setFrom(existingFunc, func);
62
64
  },
63
65
  [space],
64
66
  );
65
67
 
66
68
  return (
67
- <div role='none' className={mx(controlItemClasses)}>
69
+ <Settings.Panel>
68
70
  {functions.length > 0 && (
69
- <List.Root<Function.Function> items={functions} isItem={Schema.is(Function.Function)} getId={(func) => func.id}>
71
+ <List.Root<OperationModule.Operation.PersistentOperation>
72
+ items={functions}
73
+ isItem={Schema.is(OperationModule.Operation.PersistentOperation)}
74
+ getId={(func) => func.id}
75
+ >
70
76
  {({ items }) => (
71
- <div role='list' className='flex flex-col is-full'>
77
+ <div role='list' className='flex flex-col w-full'>
72
78
  {items?.map((func) => (
73
- <List.Item<Function.Function>
79
+ <List.Item<OperationModule.Operation.PersistentOperation>
74
80
  key={func.id}
75
81
  item={func}
76
- classNames={mx(grid, ghostHover, 'items-center', 'pli-2', 'min-bs-[3rem]')}
82
+ classNames={mx(grid, ghostHover, 'items-center', 'px-2', 'min-h-[3rem]')}
77
83
  >
78
84
  <div className='flex flex-col truncate'>
79
85
  <List.ItemTitle classNames='truncate'>{func.name}</List.ItemTitle>
@@ -90,7 +96,7 @@ export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
90
96
  iconOnly
91
97
  icon={state(func) === 'update' ? 'ph--arrows-clockwise--regular' : 'ph--download--regular'}
92
98
  label={
93
- 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')
94
100
  }
95
101
  disabled={state(func) === 'none'}
96
102
  onClick={() => hanleImportOrUpdate(func)}
@@ -102,10 +108,7 @@ export const FunctionsRegistry = ({ space }: FunctionsRegistryProps) => {
102
108
  </List.Root>
103
109
  )}
104
110
 
105
- {functions.length === 0 && !loading && (
106
- <div className='text-center plb-4 text-gray-500'>{t('no functions found')}</div>
107
- )}
108
- {loading && <div className='text-center plb-4 text-gray-500'>{t('loading functions')}</div>}
109
- </div>
111
+ {loading && <div className='text-center py-4 text-gray-500'>{t('loading-functions.message')}</div>}
112
+ </Settings.Panel>
110
113
  );
111
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;
@@ -5,17 +5,17 @@
5
5
  import type * as SchemaAST from 'effect/SchemaAST';
6
6
  import React, { useCallback, useMemo } from 'react';
7
7
 
8
- import { type Database, Ref, Type } from '@dxos/echo';
8
+ import { type Database, JsonSchema, Obj, Ref } from '@dxos/echo';
9
9
  import { type JsonPath } from '@dxos/echo/internal';
10
- import { type Function } from '@dxos/functions';
10
+ import { type Operation } from '@dxos/operation';
11
11
  import { useOnTransition, useTranslation } from '@dxos/react-ui';
12
12
  import { Form, type FormFieldStateProps, type FormRootProps, useFormValues } from '@dxos/react-ui-form';
13
13
 
14
- import { meta } from '../../meta';
14
+ import { meta } from '#meta';
15
15
 
16
16
  export type FunctionInputEditorProps = {
17
17
  type: SchemaAST.AST;
18
- functions: Function.Function[];
18
+ functions: Operation.PersistentOperation[];
19
19
  db?: Database.Database;
20
20
  } & FormFieldStateProps;
21
21
 
@@ -48,9 +48,12 @@ export const FunctionInputEditor = ({ type, functions, db, getValue, onValueChan
48
48
  );
49
49
 
50
50
  const inputSchema = useMemo(() => selectedFunction?.inputSchema, [selectedFunction]);
51
- const effectSchema = useMemo(() => (inputSchema ? Type.toEffectSchema(inputSchema) : undefined), [inputSchema]);
51
+ const effectSchema = useMemo(() => (inputSchema ? JsonSchema.toEffectSchema(inputSchema) : undefined), [inputSchema]);
52
52
  const propertyCount = inputSchema?.properties ? Object.keys(inputSchema.properties).length : 0;
53
- const values = useMemo(() => getValue() ?? {}, [getValue]);
53
+ const defaultValues = useMemo(() => {
54
+ const raw = getValue() ?? {};
55
+ return Obj.isObject(raw) ? { ...Obj.getSnapshot(raw) } : { ...raw };
56
+ }, [getValue]);
54
57
 
55
58
  const handleValuesChanged = useCallback<NonNullable<FormRootProps['onValuesChanged']>>(
56
59
  (values) => {
@@ -65,8 +68,14 @@ export const FunctionInputEditor = ({ type, functions, db, getValue, onValueChan
65
68
 
66
69
  return (
67
70
  <>
68
- <Form.Label label={t('function parameters label')} asChild />
69
- <Form.Root schema={effectSchema} values={values} db={db} onValuesChanged={handleValuesChanged}>
71
+ <Form.Label label={t('function-parameters.label')} asChild />
72
+ <Form.Root
73
+ key={selectedFunction.id}
74
+ schema={effectSchema}
75
+ defaultValues={defaultValues}
76
+ db={db}
77
+ onValuesChanged={handleValuesChanged}
78
+ >
70
79
  <Form.FieldSet />
71
80
  </Form.Root>
72
81
  </>