@dxos/plugin-sheet 0.6.11 → 0.6.12-main.5a87ad5

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 (263) hide show
  1. package/dist/lib/browser/SheetContainer-VISF3VUB.mjs +261 -0
  2. package/dist/lib/browser/SheetContainer-VISF3VUB.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-JRL5LGCE.mjs → chunk-QILRZNE5.mjs} +2 -5
  4. package/dist/lib/browser/chunk-QILRZNE5.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-FUAGSXA4.mjs → chunk-WZMOZKQZ.mjs} +9 -16
  6. package/dist/lib/browser/chunk-WZMOZKQZ.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-D5AGLXJP.mjs → chunk-Z2XOOC2R.mjs} +385 -678
  8. package/dist/lib/browser/chunk-Z2XOOC2R.mjs.map +7 -0
  9. package/dist/lib/browser/{SheetContainer-U4H5D34A.mjs → chunk-ZLJ2GRE2.mjs} +1151 -240
  10. package/dist/lib/browser/chunk-ZLJ2GRE2.mjs.map +7 -0
  11. package/dist/lib/browser/graph-4XFKIHRL.mjs +21 -0
  12. package/dist/lib/browser/graph-4XFKIHRL.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +74 -60
  14. package/dist/lib/browser/index.mjs.map +3 -3
  15. package/dist/lib/browser/meta.json +1 -1
  16. package/dist/lib/browser/meta.mjs +1 -1
  17. package/dist/lib/browser/types.mjs +4 -6
  18. package/dist/lib/node/SheetContainer-2MEALQWW.cjs +279 -0
  19. package/dist/lib/node/SheetContainer-2MEALQWW.cjs.map +7 -0
  20. package/dist/lib/node/{SheetContainer-AXQV3ZT5.cjs → chunk-6DQABRGJ.cjs} +1182 -279
  21. package/dist/lib/node/chunk-6DQABRGJ.cjs.map +7 -0
  22. package/dist/lib/node/{chunk-DSYKOI4E.cjs → chunk-AOP42UAA.cjs} +13 -21
  23. package/dist/lib/node/chunk-AOP42UAA.cjs.map +7 -0
  24. package/dist/lib/node/{chunk-BJ6ZD7MN.cjs → chunk-BNARJ5GM.cjs} +5 -18
  25. package/dist/lib/node/chunk-BNARJ5GM.cjs.map +7 -0
  26. package/dist/lib/node/{chunk-5KKJ4NPP.cjs → chunk-P5QYYEHQ.cjs} +388 -676
  27. package/dist/lib/node/chunk-P5QYYEHQ.cjs.map +7 -0
  28. package/dist/lib/node/graph-2LRDUXBZ.cjs +43 -0
  29. package/dist/lib/node/graph-2LRDUXBZ.cjs.map +7 -0
  30. package/dist/lib/node/index.cjs +86 -66
  31. package/dist/lib/node/index.cjs.map +3 -3
  32. package/dist/lib/node/meta.cjs +3 -3
  33. package/dist/lib/node/meta.cjs.map +1 -1
  34. package/dist/lib/node/meta.json +1 -1
  35. package/dist/lib/node/types.cjs +10 -12
  36. package/dist/lib/node/types.cjs.map +2 -2
  37. package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs +262 -0
  38. package/dist/lib/node-esm/SheetContainer-RPSUSXWS.mjs.map +7 -0
  39. package/dist/lib/node-esm/chunk-4MM7THJW.mjs +2944 -0
  40. package/dist/lib/node-esm/chunk-4MM7THJW.mjs.map +7 -0
  41. package/dist/lib/node-esm/chunk-5RLTCIE2.mjs +2684 -0
  42. package/dist/lib/node-esm/chunk-5RLTCIE2.mjs.map +7 -0
  43. package/dist/lib/node-esm/chunk-IU2L277A.mjs +17 -0
  44. package/dist/lib/node-esm/chunk-IU2L277A.mjs.map +7 -0
  45. package/dist/lib/node-esm/chunk-RR2AO4SM.mjs +76 -0
  46. package/dist/lib/node-esm/chunk-RR2AO4SM.mjs.map +7 -0
  47. package/dist/lib/node-esm/graph-WG5EKOMO.mjs +22 -0
  48. package/dist/lib/node-esm/graph-WG5EKOMO.mjs.map +7 -0
  49. package/dist/lib/node-esm/index.mjs +263 -0
  50. package/dist/lib/node-esm/index.mjs.map +7 -0
  51. package/dist/lib/node-esm/meta.json +1 -0
  52. package/dist/lib/node-esm/meta.mjs +10 -0
  53. package/dist/lib/node-esm/meta.mjs.map +7 -0
  54. package/dist/lib/node-esm/types.mjs +21 -0
  55. package/dist/lib/node-esm/types.mjs.map +7 -0
  56. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  57. package/dist/types/src/components/CellEditor/CellEditor.d.ts +23 -3
  58. package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +1 -1
  59. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts +2 -2
  60. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -1
  61. package/dist/types/src/components/CellEditor/extension.d.ts +1 -1
  62. package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -1
  63. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts +11 -0
  64. package/dist/types/src/components/ComputeGraph/ComputeGraphContextProvider.d.ts.map +1 -0
  65. package/dist/types/src/components/ComputeGraph/index.d.ts +1 -3
  66. package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
  67. package/dist/types/src/components/GridSheet/GridSheet.d.ts +10 -0
  68. package/dist/types/src/components/GridSheet/GridSheet.d.ts.map +1 -0
  69. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts +9 -0
  70. package/dist/types/src/components/GridSheet/GridSheet.stories.d.ts.map +1 -0
  71. package/dist/types/src/components/GridSheet/util.d.ts +7 -0
  72. package/dist/types/src/components/GridSheet/util.d.ts.map +1 -0
  73. package/dist/types/src/components/Sheet/Sheet.d.ts +1 -1
  74. package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
  75. package/dist/types/src/components/Sheet/Sheet.stories.d.ts +5 -6
  76. package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
  77. package/dist/types/src/components/Sheet/decorations.d.ts +24 -0
  78. package/dist/types/src/components/Sheet/decorations.d.ts.map +1 -0
  79. package/dist/types/src/components/Sheet/grid.d.ts +2 -2
  80. package/dist/types/src/components/Sheet/grid.d.ts.map +1 -1
  81. package/dist/types/src/components/Sheet/nav.d.ts +3 -3
  82. package/dist/types/src/components/Sheet/nav.d.ts.map +1 -1
  83. package/dist/types/src/components/Sheet/sheet-context.d.ts +8 -7
  84. package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
  85. package/dist/types/src/components/Sheet/threads.d.ts +2 -0
  86. package/dist/types/src/components/Sheet/threads.d.ts.map +1 -0
  87. package/dist/types/src/components/SheetContainer.d.ts +2 -3
  88. package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
  89. package/dist/types/src/components/Toolbar/Toolbar.d.ts +19 -3
  90. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  91. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +18 -13
  92. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  93. package/dist/types/src/components/index.d.ts +2 -2
  94. package/dist/types/src/components/index.d.ts.map +1 -1
  95. package/dist/types/src/defs/index.d.ts +3 -0
  96. package/dist/types/src/defs/index.d.ts.map +1 -0
  97. package/dist/types/src/{model → defs}/types.d.ts +8 -3
  98. package/dist/types/src/defs/types.d.ts.map +1 -0
  99. package/dist/types/src/defs/types.test.d.ts.map +1 -0
  100. package/dist/types/src/defs/util.d.ts +43 -0
  101. package/dist/types/src/defs/util.d.ts.map +1 -0
  102. package/dist/types/src/extensions/compute.d.ts +9 -0
  103. package/dist/types/src/extensions/compute.d.ts.map +1 -0
  104. package/dist/types/src/extensions/compute.stories.d.ts +26 -0
  105. package/dist/types/src/extensions/compute.stories.d.ts.map +1 -0
  106. package/dist/types/src/extensions/index.d.ts +2 -0
  107. package/dist/types/src/extensions/index.d.ts.map +1 -0
  108. package/dist/types/src/{components/ComputeGraph → graph}/async-function.d.ts +8 -2
  109. package/dist/types/src/graph/async-function.d.ts.map +1 -0
  110. package/dist/types/src/graph/compute-graph.d.ts +84 -0
  111. package/dist/types/src/graph/compute-graph.d.ts.map +1 -0
  112. package/dist/types/src/graph/compute-graph.stories.d.ts +10 -0
  113. package/dist/types/src/graph/compute-graph.stories.d.ts.map +1 -0
  114. package/dist/types/src/graph/compute-graph.test.d.ts +2 -0
  115. package/dist/types/src/graph/compute-graph.test.d.ts.map +1 -0
  116. package/dist/types/src/graph/compute-node.d.ts +26 -0
  117. package/dist/types/src/graph/compute-node.d.ts.map +1 -0
  118. package/dist/types/src/graph/edge-function.d.ts.map +1 -0
  119. package/dist/types/src/{model/functions.d.ts → graph/function-defs.d.ts} +1 -1
  120. package/dist/types/src/graph/function-defs.d.ts.map +1 -0
  121. package/dist/types/src/graph/hyperformula.test.d.ts +2 -0
  122. package/dist/types/src/graph/hyperformula.test.d.ts.map +1 -0
  123. package/dist/types/src/graph/index.d.ts +4 -0
  124. package/dist/types/src/graph/index.d.ts.map +1 -0
  125. package/dist/types/src/{components/ComputeGraph/custom.d.ts → graph/testing/custom-function.d.ts} +4 -2
  126. package/dist/types/src/graph/testing/custom-function.d.ts.map +1 -0
  127. package/dist/types/src/graph/testing/index.d.ts +2 -0
  128. package/dist/types/src/graph/testing/index.d.ts.map +1 -0
  129. package/dist/types/src/graph/util.d.ts +2 -0
  130. package/dist/types/src/graph/util.d.ts.map +1 -0
  131. package/dist/types/src/hooks/hooks.stories.d.ts +11 -0
  132. package/dist/types/src/hooks/hooks.stories.d.ts.map +1 -0
  133. package/dist/types/src/hooks/index.d.ts +4 -0
  134. package/dist/types/src/hooks/index.d.ts.map +1 -0
  135. package/dist/types/src/hooks/useComputeGraph.d.ts +7 -0
  136. package/dist/types/src/hooks/useComputeGraph.d.ts.map +1 -0
  137. package/dist/types/src/hooks/useFormattingModel.d.ts +3 -0
  138. package/dist/types/src/hooks/useFormattingModel.d.ts.map +1 -0
  139. package/dist/types/src/hooks/useSheetModel.d.ts +8 -0
  140. package/dist/types/src/hooks/useSheetModel.d.ts.map +1 -0
  141. package/dist/types/src/meta.d.ts +1 -4
  142. package/dist/types/src/meta.d.ts.map +1 -1
  143. package/dist/types/src/model/formatting-model.d.ts +16 -0
  144. package/dist/types/src/model/formatting-model.d.ts.map +1 -0
  145. package/dist/types/src/model/index.d.ts +2 -3
  146. package/dist/types/src/model/index.d.ts.map +1 -1
  147. package/dist/types/src/model/{model.d.ts → sheet-model.d.ts} +10 -65
  148. package/dist/types/src/model/sheet-model.d.ts.map +1 -0
  149. package/dist/types/src/sanity.test.d.ts +2 -0
  150. package/dist/types/src/sanity.test.d.ts.map +1 -0
  151. package/dist/types/src/testing/index.d.ts +2 -0
  152. package/dist/types/src/testing/index.d.ts.map +1 -0
  153. package/dist/types/src/testing/testing.d.ts +8 -0
  154. package/dist/types/src/testing/testing.d.ts.map +1 -0
  155. package/dist/types/src/translations.d.ts +17 -12
  156. package/dist/types/src/translations.d.ts.map +1 -1
  157. package/dist/types/src/types.d.ts +86 -5
  158. package/dist/types/src/types.d.ts.map +1 -1
  159. package/dist/vendor/hyperformula.mjs +37145 -0
  160. package/package.json +48 -41
  161. package/src/SheetPlugin.tsx +48 -73
  162. package/src/components/CellEditor/CellEditor.stories.tsx +5 -4
  163. package/src/components/CellEditor/CellEditor.tsx +59 -9
  164. package/src/components/CellEditor/extension.test.ts +4 -5
  165. package/src/components/CellEditor/extension.ts +1 -3
  166. package/src/components/ComputeGraph/ComputeGraphContextProvider.tsx +20 -0
  167. package/src/components/ComputeGraph/index.ts +1 -3
  168. package/src/components/GridSheet/GridSheet.stories.tsx +36 -0
  169. package/src/components/GridSheet/GridSheet.tsx +153 -0
  170. package/src/components/GridSheet/util.ts +108 -0
  171. package/src/components/Sheet/Sheet.stories.tsx +52 -88
  172. package/src/components/Sheet/Sheet.tsx +57 -18
  173. package/src/components/Sheet/decorations.ts +62 -0
  174. package/src/components/Sheet/grid.ts +3 -3
  175. package/src/components/Sheet/nav.ts +19 -19
  176. package/src/components/Sheet/sheet-context.tsx +18 -80
  177. package/src/components/Sheet/threads.tsx +205 -0
  178. package/src/components/SheetContainer.tsx +73 -19
  179. package/src/components/Toolbar/Toolbar.tsx +53 -12
  180. package/src/components/index.ts +1 -0
  181. package/src/defs/index.ts +6 -0
  182. package/src/{model → defs}/types.test.ts +8 -9
  183. package/src/{model → defs}/types.ts +24 -14
  184. package/src/defs/util.ts +151 -0
  185. package/src/extensions/compute.stories.tsx +153 -0
  186. package/src/extensions/compute.ts +131 -0
  187. package/src/extensions/index.ts +5 -0
  188. package/src/{components/ComputeGraph → graph}/async-function.ts +15 -6
  189. package/src/graph/compute-graph.stories.tsx +93 -0
  190. package/src/graph/compute-graph.test.ts +127 -0
  191. package/src/graph/compute-graph.ts +313 -0
  192. package/src/graph/compute-node.ts +62 -0
  193. package/src/{components/ComputeGraph → graph}/edge-function.ts +3 -3
  194. package/src/graph/hyperformula.test.ts +15 -0
  195. package/src/graph/index.ts +7 -0
  196. package/src/{components/ComputeGraph/custom.ts → graph/testing/custom-function.ts} +11 -7
  197. package/src/graph/testing/index.ts +5 -0
  198. package/src/graph/util.ts +8 -0
  199. package/src/hooks/hooks.stories.tsx +50 -0
  200. package/src/hooks/index.ts +7 -0
  201. package/src/hooks/useComputeGraph.ts +21 -0
  202. package/src/hooks/useFormattingModel.ts +11 -0
  203. package/src/hooks/useSheetModel.ts +40 -0
  204. package/src/meta.tsx +1 -5
  205. package/src/{components/Sheet/formatting.ts → model/formatting-model.ts} +20 -13
  206. package/src/model/index.ts +2 -3
  207. package/src/model/sheet-model.ts +414 -0
  208. package/src/sanity.test.ts +40 -0
  209. package/src/testing/index.ts +5 -0
  210. package/src/testing/testing.tsx +68 -0
  211. package/src/translations.ts +6 -1
  212. package/src/types.ts +31 -6
  213. package/dist/lib/browser/SheetContainer-U4H5D34A.mjs.map +0 -7
  214. package/dist/lib/browser/chunk-APHOLYUB.mjs +0 -175
  215. package/dist/lib/browser/chunk-APHOLYUB.mjs.map +0 -7
  216. package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +0 -7
  217. package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +0 -7
  218. package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +0 -7
  219. package/dist/lib/browser/chunk-NU4PBN33.mjs +0 -8
  220. package/dist/lib/browser/chunk-NU4PBN33.mjs.map +0 -7
  221. package/dist/lib/browser/testing.mjs +0 -92
  222. package/dist/lib/browser/testing.mjs.map +0 -7
  223. package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +0 -7
  224. package/dist/lib/node/chunk-5KKJ4NPP.cjs.map +0 -7
  225. package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +0 -7
  226. package/dist/lib/node/chunk-CN3RPESU.cjs +0 -202
  227. package/dist/lib/node/chunk-CN3RPESU.cjs.map +0 -7
  228. package/dist/lib/node/chunk-DSYKOI4E.cjs.map +0 -7
  229. package/dist/lib/node/chunk-PYXHNAAK.cjs +0 -40
  230. package/dist/lib/node/chunk-PYXHNAAK.cjs.map +0 -7
  231. package/dist/lib/node/testing.cjs +0 -111
  232. package/dist/lib/node/testing.cjs.map +0 -7
  233. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +0 -1
  234. package/dist/types/src/components/ComputeGraph/custom.d.ts.map +0 -1
  235. package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +0 -1
  236. package/dist/types/src/components/ComputeGraph/graph-context.d.ts +0 -12
  237. package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +0 -1
  238. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +0 -2
  239. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +0 -1
  240. package/dist/types/src/components/ComputeGraph/graph.d.ts +0 -26
  241. package/dist/types/src/components/ComputeGraph/graph.d.ts.map +0 -1
  242. package/dist/types/src/components/Sheet/formatting.d.ts +0 -14
  243. package/dist/types/src/components/Sheet/formatting.d.ts.map +0 -1
  244. package/dist/types/src/model/functions.d.ts.map +0 -1
  245. package/dist/types/src/model/model.browser.test.d.ts +0 -2
  246. package/dist/types/src/model/model.browser.test.d.ts.map +0 -1
  247. package/dist/types/src/model/model.d.ts.map +0 -1
  248. package/dist/types/src/model/types.d.ts.map +0 -1
  249. package/dist/types/src/model/types.test.d.ts.map +0 -1
  250. package/dist/types/src/model/util.d.ts +0 -15
  251. package/dist/types/src/model/util.d.ts.map +0 -1
  252. package/dist/types/src/testing.d.ts +0 -9
  253. package/dist/types/src/testing.d.ts.map +0 -1
  254. package/src/components/ComputeGraph/graph-context.tsx +0 -50
  255. package/src/components/ComputeGraph/graph.browser.test.ts +0 -50
  256. package/src/components/ComputeGraph/graph.ts +0 -62
  257. package/src/model/model.browser.test.ts +0 -100
  258. package/src/model/model.ts +0 -550
  259. package/src/model/util.ts +0 -36
  260. package/src/testing.ts +0 -50
  261. /package/dist/types/src/{model → defs}/types.test.d.ts +0 -0
  262. /package/dist/types/src/{components/ComputeGraph → graph}/edge-function.d.ts +0 -0
  263. /package/src/{model/functions.ts → graph/function-defs.ts} +0 -0
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { CellError, ErrorType, EmptyValue, FunctionPlugin, type HyperFormula } from 'hyperformula';
5
+ import { type SimpleCellAddress } from 'hyperformula/typings/Cell';
6
6
  import { type InterpreterState } from 'hyperformula/typings/interpreter/InterpreterState';
7
7
  import { type InterpreterValue } from 'hyperformula/typings/interpreter/InterpreterValue';
8
8
  import { type ProcedureAst } from 'hyperformula/typings/parser';
@@ -12,6 +12,8 @@ import { debounce, type UnsubscribeCallback } from '@dxos/async';
12
12
  import { type Space } from '@dxos/client/echo';
13
13
  import { log } from '@dxos/log';
14
14
 
15
+ import { CellError, ErrorType, EmptyValue, FunctionPlugin, type HyperFormula } from '#hyperformula';
16
+
15
17
  // TODO(burdon): API gateways!
16
18
  // https://publicapis.io
17
19
  // https://api-ninjas.com/api/cryptoprice
@@ -21,6 +23,11 @@ import { log } from '@dxos/log';
21
23
  // TODO(burdon): Create wrapper.
22
24
  export type AsyncFunction = (...args: any) => Promise<InterpreterValue>;
23
25
 
26
+ export type FunctionUpdateEvent = {
27
+ name: string;
28
+ cell: SimpleCellAddress;
29
+ };
30
+
24
31
  export type FunctionOptions = {
25
32
  ttl?: number;
26
33
  };
@@ -29,6 +36,7 @@ export type FunctionContextOptions = {
29
36
  defaultTtl: number;
30
37
  recalculationDelay: number;
31
38
  remoteFunctionUrl: string;
39
+ onUpdate?: (update: FunctionUpdateEvent) => void;
32
40
  };
33
41
 
34
42
  export const defaultFunctionContextOptions: FunctionContextOptions = {
@@ -65,20 +73,21 @@ export class FunctionContext {
65
73
  private _invocations: Record<string, number> = {};
66
74
 
67
75
  private readonly _options: FunctionContextOptions;
68
- private readonly _onUpdate: () => void;
76
+
77
+ // Debounced update handler.
78
+ private readonly _onUpdate: (update: FunctionUpdateEvent) => void;
69
79
 
70
80
  constructor(
71
81
  private readonly _hf: HyperFormula,
72
82
  private readonly _space: Space | undefined,
73
- onUpdate: (context: FunctionContext) => void,
74
83
  _options?: Partial<FunctionContextOptions>,
75
84
  ) {
76
85
  this._options = defaultsDeep(_options ?? {}, defaultFunctionContextOptions);
77
- this._onUpdate = debounce(() => {
86
+ this._onUpdate = debounce((update) => {
78
87
  // TODO(burdon): Better way to trigger recalculation?
79
88
  // NOTE: rebuildAndRecalculate resets the undo history.
80
89
  this._hf.resumeEvaluation();
81
- onUpdate(this);
90
+ this._options.onUpdate?.(update);
82
91
  }, this._options.recalculationDelay);
83
92
  }
84
93
 
@@ -134,7 +143,7 @@ export class FunctionContext {
134
143
  const value = await cb(...args);
135
144
  this._cache.set(invocationKey, { value, ts: Date.now() });
136
145
  log('set', { cell, value });
137
- this._onUpdate();
146
+ this._onUpdate({ name, cell });
138
147
  } catch (err) {
139
148
  // TODO(burdon): Show error to user.
140
149
  log.warn('failed', { cell, err });
@@ -0,0 +1,93 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import React, { useEffect, useRef, useState } from 'react';
8
+
9
+ import { FunctionType } from '@dxos/plugin-script/types';
10
+ import { create, useSpace, Filter } from '@dxos/react-client/echo';
11
+ import { withClientProvider } from '@dxos/react-client/testing';
12
+ import { Toolbar, Button, Input } from '@dxos/react-ui';
13
+ import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
14
+ import { withTheme } from '@dxos/storybook-utils';
15
+
16
+ import { testPlugins } from './testing';
17
+ import { createSheet } from '../defs';
18
+ import { useComputeGraph, useSheetModel } from '../hooks';
19
+ import { withComputeGraphDecorator } from '../testing';
20
+ import { SheetType } from '../types';
21
+
22
+ const FUNCTION_NAME = 'TEST';
23
+
24
+ const Story = () => {
25
+ const space = useSpace();
26
+ const graph = useComputeGraph(space);
27
+ const [sheet, setSheet] = useState<SheetType>();
28
+ const [text, setText] = useState(`${FUNCTION_NAME}(100)`);
29
+ const [result, setResult] = useState<any>();
30
+ const model = useSheetModel(graph, sheet);
31
+ useEffect(() => {
32
+ if (space) {
33
+ const sheet = space.db.add(createSheet());
34
+ setSheet(sheet);
35
+ }
36
+ }, [space]);
37
+
38
+ useEffect(() => {
39
+ if (space && graph) {
40
+ graph.update.on(() => {
41
+ const f1 = graph.getFunctions({ standard: true, echo: false });
42
+ const f2 = graph.getFunctions({ standard: false, echo: true });
43
+ setResult({ functions: { standard: f1.length, echo: f2.length } });
44
+ });
45
+
46
+ space.db.add(create(FunctionType, { version: 1, binding: FUNCTION_NAME }));
47
+ }
48
+ }, [space, graph]);
49
+
50
+ const inputRef = useRef<HTMLInputElement | null>(null);
51
+ const handleTest = async () => {
52
+ if (space && graph) {
53
+ const { objects } = await space.db.query(Filter.schema(FunctionType)).run();
54
+ const mapped = graph.mapFunctionBindingToId(text);
55
+ const unmapped = graph.mapFunctionBindingFromId(mapped);
56
+ const internal = graph.mapFormulaToNative(text);
57
+ setResult({ mapped, unmapped, internal, functions: objects.map((object) => object.id) });
58
+ }
59
+
60
+ inputRef.current?.focus();
61
+ };
62
+
63
+ return (
64
+ <div className='flex flex-col gap-2 '>
65
+ <Toolbar.Root>
66
+ <Input.Root>
67
+ <Input.TextInput
68
+ ref={inputRef}
69
+ placeholder='Formula'
70
+ value={text}
71
+ onChange={(ev) => setText(ev.target.value)}
72
+ />
73
+ </Input.Root>
74
+ <Button onClick={handleTest}>Test</Button>
75
+ </Toolbar.Root>
76
+ <SyntaxHighlighter language='json'>
77
+ {JSON.stringify({ space: space?.id, graph: graph?.id, sheet: sheet?.id, model: model?.id, result }, null, 2)}
78
+ </SyntaxHighlighter>
79
+ </div>
80
+ );
81
+ };
82
+
83
+ export default {
84
+ title: 'plugin-sheet/functions',
85
+ decorators: [
86
+ withClientProvider({ types: [FunctionType, SheetType], createIdentity: true, createSpace: true }),
87
+ withComputeGraphDecorator({ plugins: testPlugins }),
88
+ withTheme,
89
+ ],
90
+ render: (args: any) => <Story {...args} />,
91
+ };
92
+
93
+ export const Default = {};
@@ -0,0 +1,127 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type CellValue } from 'hyperformula';
6
+ import { afterEach, beforeEach, describe, expect, test } from 'vitest';
7
+
8
+ import { Trigger } from '@dxos/async';
9
+ import { Client } from '@dxos/client';
10
+ import { create, fullyQualifiedId } from '@dxos/client/echo';
11
+ import { Context } from '@dxos/context';
12
+ import { type S } from '@dxos/echo-schema';
13
+ import { FunctionType } from '@dxos/plugin-script/types';
14
+
15
+ import { ComputeGraphRegistry } from './compute-graph';
16
+ import { testPlugins } from './testing';
17
+ import { addressFromA1Notation, createSheet } from '../defs';
18
+ import { SheetModel } from '../model';
19
+ import { type CellScalarValue } from '../types';
20
+
21
+ /**
22
+ * NOTE: Browser test required for hyperformula due to raw translation files.
23
+ */
24
+ describe('compute graph', () => {
25
+ let ctx: Context;
26
+ beforeEach(() => {
27
+ ctx = new Context();
28
+ });
29
+ afterEach(async () => {
30
+ await ctx.dispose();
31
+ });
32
+
33
+ // TODO(burdon): Replace with builder.
34
+ const createModel = async (types?: S.Schema<any>[]) => {
35
+ const client = new Client();
36
+ if (types) {
37
+ // TODO(burdon): Add to config.
38
+ client.addTypes(types);
39
+ }
40
+ await client.initialize();
41
+ await client.halo.createIdentity();
42
+ const space = await client.spaces.create();
43
+ ctx.onDispose(() => client.destroy());
44
+
45
+ const registry = new ComputeGraphRegistry({ plugins: testPlugins });
46
+ await registry.open();
47
+ ctx.onDispose(() => registry.close());
48
+
49
+ const graph = await registry.createGraph(space);
50
+
51
+ const sheet = createSheet({ rows: 5, columns: 5 });
52
+ const model = new SheetModel(graph, sheet);
53
+ await model.open();
54
+
55
+ return { space, graph, model };
56
+ };
57
+
58
+ test('map functions', async () => {
59
+ const { space, graph } = await createModel([FunctionType]);
60
+
61
+ // Create script.
62
+ const trigger = new Trigger();
63
+ graph.update.once(() => trigger.wake());
64
+ const fn = space.db.add(create(FunctionType, { version: 1, binding: 'TEST' }));
65
+ await trigger.wait();
66
+ expect(graph.getFunctions({ echo: true })).to.toHaveLength(1);
67
+
68
+ const id = graph.mapFunctionBindingToId('TEST()');
69
+ expect(id).to.eq(`${fullyQualifiedId(fn)}()`);
70
+ });
71
+
72
+ test('cross-node references', async () => {
73
+ const { graph } = await createModel();
74
+
75
+ // Create nodes.
76
+ const node1 = await graph.getOrCreateNode('node-1');
77
+ const node2 = await graph.getOrCreateNode('node-2');
78
+
79
+ {
80
+ expect(graph.hf.getSheetNames()).to.toHaveLength(3);
81
+ node1.graph.hf.setCellContents({ sheet: node1.sheetId, row: 0, col: 0 }, [[100, 200, 300, '=SUM(A1:C1)']]);
82
+ node2.graph.hf.setCellContents({ sheet: node2.sheetId, row: 0, col: 0 }, "='node-1'!D1");
83
+ const value1 = node1.graph.hf.getCellValue({ sheet: node1.sheetId, col: 3, row: 0 });
84
+ const value2 = node2.graph.hf.getCellValue({ sheet: node2.sheetId, col: 0, row: 0 });
85
+ expect(value1).to.eq(value2);
86
+ }
87
+
88
+ // Get updated event.
89
+ const trigger = new Trigger<CellValue>();
90
+ node2.update.on(({ change }) => {
91
+ const value = node2.graph.hf.getCellValue({ sheet: node2.sheetId, col: 0, row: 0 });
92
+ expect(value).to.eq(change?.newValue);
93
+ trigger.wake(value);
94
+ });
95
+
96
+ {
97
+ node1.graph.hf.setCellContents({ sheet: node1.sheetId, row: 0, col: 0 }, 400);
98
+ const value1 = node1.graph.hf.getCellValue({ sheet: node1.sheetId, col: 3, row: 0 });
99
+ const value2 = await trigger.wait();
100
+ expect(value1).to.eq(value2);
101
+ }
102
+ });
103
+
104
+ test('async function', async () => {
105
+ const { graph, model } = await createModel();
106
+
107
+ // Triggers function.
108
+ model.setValue(addressFromA1Notation('A1'), '=TEST()');
109
+ const trigger = new Trigger<CellScalarValue>();
110
+ model.update.once(({ type }) => {
111
+ if (type === 'valuesUpdated') {
112
+ const value = model.getValue(addressFromA1Notation('A1'));
113
+ trigger.wake(value);
114
+ }
115
+ });
116
+
117
+ // Get initial value (null).
118
+ const v1 = model.getValue(addressFromA1Notation('A1'));
119
+ expect(v1).to.be.null;
120
+ expect(graph.context.info.invocations.TEST).to.eq(undefined);
121
+
122
+ // Wait until async update triggered.
123
+ const v2 = await trigger.wait();
124
+ expect(v2).not.to.be.null;
125
+ expect(graph.context.info.invocations.TEST).to.eq(1);
126
+ });
127
+ });
@@ -0,0 +1,313 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type FunctionPluginDefinition } from 'hyperformula';
6
+ import { type ConfigParams } from 'hyperformula/typings/ConfigParams';
7
+ import { type Listeners } from 'hyperformula/typings/Emitter';
8
+ import { type FunctionTranslationsPackage } from 'hyperformula/typings/interpreter';
9
+ import defaultsDeep from 'lodash.defaultsdeep';
10
+
11
+ import { Event } from '@dxos/async';
12
+ import { type SpaceId, type Space, Filter, fullyQualifiedId } from '@dxos/client/echo';
13
+ import { Resource } from '@dxos/context';
14
+ import { invariant } from '@dxos/invariant';
15
+ import { PublicKey } from '@dxos/keys';
16
+ import { log } from '@dxos/log';
17
+ import { FunctionType } from '@dxos/plugin-script/types';
18
+ import { nonNullable } from '@dxos/util';
19
+
20
+ import { ExportedCellChange, HyperFormula } from '#hyperformula';
21
+ import { FunctionContext, type FunctionContextOptions } from './async-function';
22
+ import { ComputeNode } from './compute-node';
23
+ import { EdgeFunctionPlugin, EdgeFunctionPluginTranslations } from './edge-function';
24
+ import { defaultFunctions, type FunctionDefinition } from './function-defs';
25
+
26
+ //
27
+ // NOTE: The package.json file defines the packaged #hyperformula module.
28
+ //
29
+
30
+ // TODO(wittjosiah): Factor out.
31
+ const OBJECT_ID_LENGTH = 60; // 33 (space id) + 26 (object id) + 1 (separator).
32
+
33
+ // TODO(burdon): Change to "DX".
34
+ const CUSTOM_FUNCTION = 'ECHO';
35
+
36
+ export type ComputeGraphPlugin = {
37
+ plugin: FunctionPluginDefinition;
38
+ translations: FunctionTranslationsPackage;
39
+ };
40
+
41
+ export type ComputeGraphOptions = {
42
+ plugins?: ComputeGraphPlugin[];
43
+ } & Partial<FunctionContextOptions> &
44
+ Partial<ConfigParams>;
45
+
46
+ export const defaultOptions: ComputeGraphOptions = {
47
+ licenseKey: 'gpl-v3',
48
+ };
49
+
50
+ export const defaultPlugins: ComputeGraphPlugin[] = [
51
+ {
52
+ plugin: EdgeFunctionPlugin,
53
+ translations: EdgeFunctionPluginTranslations,
54
+ },
55
+ ];
56
+
57
+ /**
58
+ * Marker for sheets that are managed by an ECHO object.
59
+ */
60
+ const PREFIX = '__';
61
+ export const createSheetName = (id: string) => `${PREFIX}${id}`;
62
+ export const getSheetId = (name: string): string | undefined =>
63
+ name.startsWith(PREFIX) ? name.slice(PREFIX.length) : undefined;
64
+
65
+ /**
66
+ * Manages a collection of ComputeGraph instances for each space.
67
+ *
68
+ * [ComputePlugin] => [ComputeGraphRegistry] => [ComputeGraph(Space)] => [ComputeNode(Object)]
69
+ *
70
+ * NOTE: The ComputeGraphRegistry manages the hierarchy of resources via its root Context.
71
+ */
72
+ // TODO(burdon): Move graph into separate plugin; isolate HF deps.
73
+ export class ComputeGraphRegistry extends Resource {
74
+ private readonly _graphs = new Map<SpaceId, ComputeGraph>();
75
+
76
+ private readonly _options: ComputeGraphOptions;
77
+
78
+ constructor(options: ComputeGraphOptions = { plugins: defaultPlugins }) {
79
+ super();
80
+ this._options = defaultsDeep({}, options, defaultOptions);
81
+ this._options.plugins?.forEach(({ plugin, translations }) => {
82
+ HyperFormula.registerFunctionPlugin(plugin, translations);
83
+ });
84
+ }
85
+
86
+ getGraph(spaceId: SpaceId): ComputeGraph | undefined {
87
+ return this._graphs.get(spaceId);
88
+ }
89
+
90
+ async getOrCreateGraph(space: Space): Promise<ComputeGraph> {
91
+ let graph = this.getGraph(space.id);
92
+ if (!graph) {
93
+ log.info('create graph', { space: space.id });
94
+ graph = await this.createGraph(space);
95
+ }
96
+
97
+ return graph;
98
+ }
99
+
100
+ async createGraph(space: Space): Promise<ComputeGraph> {
101
+ invariant(!this._graphs.has(space.id), `ComputeGraph already exists for space: ${space.id}`);
102
+ const hf = HyperFormula.buildEmpty(this._options);
103
+ const graph = new ComputeGraph(hf, space, this._options);
104
+ this._graphs.set(space.id, graph);
105
+ await graph.open();
106
+ return graph;
107
+ }
108
+
109
+ protected override async _close() {
110
+ for (const graph of this._graphs.values()) {
111
+ await graph.close();
112
+ }
113
+ }
114
+ }
115
+
116
+ export type ComputeGraphEvent = 'functionsUpdated';
117
+
118
+ /**
119
+ * Per-space compute and dependency graph.
120
+ * Consists of multiple ComputeNode (corresponding to a HyperFormula sheet).
121
+ * Manages the set of custom functions.
122
+ * HyperFormula manages the dependency graph.
123
+ */
124
+ export class ComputeGraph extends Resource {
125
+ public readonly id = `graph-${PublicKey.random().truncate()}`;
126
+
127
+ // Map of nodes indexed by sheet number.
128
+ private readonly _nodes = new Map<number, ComputeNode>();
129
+
130
+ // Cached function objects.
131
+ private _functions: FunctionType[] = [];
132
+
133
+ public readonly update = new Event<{ type: ComputeGraphEvent }>();
134
+
135
+ // The context is passed to all functions.
136
+ public readonly context = new FunctionContext(this._hf, this._space, this._options);
137
+
138
+ constructor(
139
+ private readonly _hf: HyperFormula,
140
+ private readonly _space?: Space,
141
+ private readonly _options?: Partial<FunctionContextOptions>,
142
+ ) {
143
+ super();
144
+ this._hf.updateConfig({ context: this.context });
145
+ // TODO(burdon): If debounce then aggregate changes.
146
+ const onValuesUpdate: Listeners['valuesUpdated'] = (changes) => {
147
+ for (const change of changes) {
148
+ if (change instanceof ExportedCellChange) {
149
+ const { sheet } = change;
150
+ const node = this._nodes.get(sheet);
151
+ if (node) {
152
+ node.update.emit({ type: 'valuesUpdated', change });
153
+ }
154
+ }
155
+ }
156
+ };
157
+
158
+ this._hf.on('valuesUpdated', onValuesUpdate);
159
+ this._ctx.onDispose(() => this._hf.off('valuesUpdated', onValuesUpdate));
160
+ }
161
+
162
+ get hf() {
163
+ return this._hf;
164
+ }
165
+
166
+ // refresh() {
167
+ // log('refresh', { id: this.id });
168
+ // this.update.emit();
169
+ // }
170
+
171
+ getFunctions(
172
+ { standard, echo }: { standard?: boolean; echo?: boolean } = { standard: true, echo: true },
173
+ ): FunctionDefinition[] {
174
+ return [
175
+ ...(standard
176
+ ? this._hf
177
+ .getRegisteredFunctionNames()
178
+ .map((name) => defaultFunctions.find((fn) => fn.name === name) ?? { name })
179
+ : []),
180
+ ...(echo ? this._functions.map((fn) => ({ name: fn.binding! })) : []),
181
+ ];
182
+ }
183
+
184
+ /**
185
+ * Get or create cell representing a sheet.
186
+ */
187
+ // TODO(burdon): Async (open node).
188
+ // The graph should be an extensible factory that plugins extend with model constructors.
189
+ // This would enable on-the-fly instantiation of new models when then are referenced.
190
+ // E.g., Cross-object reference would be stored as "ObjectId!A1"
191
+ // The graph would then load the object and create a ComputeNode (model) of the appropriate type.
192
+ async getOrCreateNode(name: string): Promise<ComputeNode> {
193
+ invariant(name.length);
194
+ if (!this._hf.doesSheetExist(name)) {
195
+ log.info('created node', { space: this._space?.id, name });
196
+ this._hf.addSheet(name);
197
+ // this.update.emit();
198
+ }
199
+
200
+ const sheetId = this._hf.getSheetId(name);
201
+ invariant(sheetId !== undefined);
202
+
203
+ const node = new ComputeNode(this, sheetId);
204
+ await node.open();
205
+ this._nodes.set(sheetId, node);
206
+ return node;
207
+ }
208
+
209
+ /**
210
+ * Map bound value to custom function invocation.
211
+ * E.g., "HELLO(...args)" => "EDGE("HELLO", ...args)".
212
+ */
213
+ mapFormulaToNative(formula: string): string {
214
+ return (
215
+ formula
216
+ // Sheet references.
217
+ // https://hyperformula.handsontable.com/guide/cell-references.html#cell-references
218
+ .replace(/['"]?([ \w]+)['"]?!/, (_match, name) => {
219
+ if (name) {
220
+ // TODO(burdon): What if not loaded?
221
+ const objects = this._hf
222
+ .getSheetNames()
223
+ .map((name) => {
224
+ const id = getSheetId(name);
225
+ return id ? this._space?.db.getObjectById(id) : undefined;
226
+ })
227
+ .filter(nonNullable);
228
+
229
+ for (const obj of objects) {
230
+ if (obj.name === name || obj.title === name) {
231
+ return `${createSheetName(obj.id)}!`;
232
+ }
233
+ }
234
+ }
235
+
236
+ return `${name}!`;
237
+ })
238
+
239
+ // Functions.
240
+ .replace(/(\w+)\((.*)\)/g, (match, binding, args) => {
241
+ const fn = this._functions.find((fn) => fn.binding === binding);
242
+ if (!fn) {
243
+ return match;
244
+ }
245
+
246
+ if (args.trim() === '') {
247
+ return `${CUSTOM_FUNCTION}("${binding}")`;
248
+ } else {
249
+ return `${CUSTOM_FUNCTION}("${binding}", ${args})`;
250
+ }
251
+ })
252
+ );
253
+ }
254
+
255
+ /**
256
+ * Map from binding to fully qualified ECHO ID (to store).
257
+ * E.g., HELLO() => spaceId:objectId()
258
+ */
259
+ mapFunctionBindingToId(formula: string) {
260
+ return formula.replace(/(\w+)\((.*)\)/g, (match, binding, args) => {
261
+ if (binding === CUSTOM_FUNCTION || defaultFunctions.find((fn) => fn.name === binding)) {
262
+ return match;
263
+ }
264
+
265
+ const fn = this._functions.find((fn) => fn.binding === binding);
266
+ if (fn) {
267
+ const id = fullyQualifiedId(fn);
268
+ return `${id}(${args})`;
269
+ } else {
270
+ return match;
271
+ }
272
+ });
273
+ }
274
+
275
+ /**
276
+ * Map from fully qualified ECHO ID to binding (from store).
277
+ * E.g., spaceId:objectId() => HELLO()
278
+ */
279
+ mapFunctionBindingFromId(formula: string) {
280
+ return formula.replace(/(\w+):([a-zA-Z0-9]+)\((.*)\)/g, (match, spaceId, objectId, args) => {
281
+ const id = `${spaceId}:${objectId}`;
282
+ if (id.length !== OBJECT_ID_LENGTH) {
283
+ return match;
284
+ }
285
+
286
+ const fn = this._functions.find((fn) => fullyQualifiedId(fn) === id);
287
+ if (fn?.binding) {
288
+ return `${fn.binding}(${args})`;
289
+ } else {
290
+ return match;
291
+ }
292
+ });
293
+ }
294
+
295
+ protected override async _open() {
296
+ if (this._space) {
297
+ // Subscribe to remote function definitions.
298
+ const query = this._space.db.query(Filter.schema(FunctionType));
299
+ const unsubscribe = query.subscribe(({ objects }) => {
300
+ this._functions = objects.filter(({ binding }) => binding);
301
+ this.update.emit({ type: 'functionsUpdated' });
302
+ });
303
+
304
+ this._ctx.onDispose(unsubscribe);
305
+ }
306
+ }
307
+
308
+ protected override async _close() {
309
+ for (const node of this._nodes.values()) {
310
+ await node.close();
311
+ }
312
+ }
313
+ }
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type Listeners } from 'hyperformula/typings/Emitter';
6
+ import { type ExportedCellChange } from 'hyperformula/typings/Exporter';
7
+
8
+ import { Event } from '@dxos/async';
9
+ import { Resource } from '@dxos/context';
10
+
11
+ import { DetailedCellError } from '#hyperformula';
12
+ import { type ComputeGraph } from './compute-graph';
13
+ import { type CellAddress } from '../defs';
14
+ import { type CellScalarValue } from '../types';
15
+
16
+ export type ComputeNodeEvent = {
17
+ type: keyof Listeners;
18
+ change?: ExportedCellChange;
19
+ };
20
+
21
+ /**
22
+ * Individual "sheet" (typically corresponds to an ECHO object).
23
+ */
24
+ // TODO(burdon): Factor out common HF wrapper from from SheetModel.
25
+ export class ComputeNode extends Resource {
26
+ public readonly update = new Event<ComputeNodeEvent>();
27
+
28
+ constructor(
29
+ private readonly _graph: ComputeGraph,
30
+ public readonly sheetId: number,
31
+ ) {
32
+ super();
33
+ }
34
+
35
+ get graph() {
36
+ return this._graph;
37
+ }
38
+
39
+ clear() {
40
+ this._graph.hf.clearSheet(this.sheetId);
41
+ }
42
+
43
+ getValue(cell: CellAddress): CellScalarValue {
44
+ const value = this._graph.hf.getCellValue({ sheet: this.sheetId, row: cell.row, col: cell.col });
45
+ if (value instanceof DetailedCellError) {
46
+ return null;
47
+ }
48
+
49
+ return value;
50
+ }
51
+
52
+ setValue(cell: CellAddress, value: CellScalarValue) {
53
+ const mappedValue =
54
+ typeof value === 'string' && value.charAt(0) === '=' ? this._graph.mapFormulaToNative(value) : value;
55
+ this._graph.hf.setCellContents({ sheet: this.sheetId, row: cell.row, col: cell.col }, [[mappedValue]]);
56
+ }
57
+
58
+ protected override async _open() {
59
+ // const unsubscribe = this._graph.update.on(this.update.emit);
60
+ // this._ctx.onDispose(unsubscribe);
61
+ }
62
+ }
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  import { effect } from '@preact/signals-core';
6
- import { CellError, ErrorType, FunctionArgumentType } from 'hyperformula';
7
6
  import { type InterpreterState } from 'hyperformula/typings/interpreter/InterpreterState';
8
7
  import { type ProcedureAst } from 'hyperformula/typings/parser';
9
8
 
@@ -13,6 +12,7 @@ import { getUserFunctionUrlInMetadata } from '@dxos/plugin-script/edge';
13
12
  import { FunctionType } from '@dxos/plugin-script/types';
14
13
  import { nonNullable } from '@dxos/util';
15
14
 
15
+ import { CellError, ErrorType, FunctionArgumentType } from '#hyperformula';
16
16
  import { type AsyncFunction, FunctionPluginAsync } from './async-function';
17
17
 
18
18
  const EDGE_FUNCTION_TTL = 10_000;
@@ -59,6 +59,7 @@ export class EdgeFunctionPlugin extends FunctionPluginAsync {
59
59
  headers: { 'Content-Type': 'application/json' },
60
60
  body: JSON.stringify({ args: args.filter(nonNullable) }),
61
61
  });
62
+
62
63
  return await result.text();
63
64
  };
64
65
 
@@ -73,8 +74,7 @@ EdgeFunctionPlugin.implementedFunctions = {
73
74
  // Binding
74
75
  { argumentType: FunctionArgumentType.STRING },
75
76
 
76
- // Remote function arguments (currently supporting up to 9).
77
- { argumentType: FunctionArgumentType.ANY, optionalArg: true },
77
+ // Remote function arguments (currently supporting up to 8).
78
78
  { argumentType: FunctionArgumentType.ANY, optionalArg: true },
79
79
  { argumentType: FunctionArgumentType.ANY, optionalArg: true },
80
80
  { argumentType: FunctionArgumentType.ANY, optionalArg: true },