@dxos/plugin-script 0.8.4-main.2c6827d → 0.8.4-main.3c1ae3b

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 (168) hide show
  1. package/dist/lib/browser/DeploymentDialog-FIHD4UVK.mjs +15 -0
  2. package/dist/lib/browser/{NotebookContainer-RTESC4OV.mjs → NotebookContainer-GL2Z5I5Q.mjs} +26 -26
  3. package/dist/lib/browser/NotebookContainer-GL2Z5I5Q.mjs.map +7 -0
  4. package/dist/lib/browser/{ScriptContainer-T2BAZDJ4.mjs → ScriptContainer-F4OK3OG6.mjs} +9 -7
  5. package/dist/lib/browser/ScriptContainer-F4OK3OG6.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-4M7U2WVT.mjs → chunk-2SXDKBM7.mjs} +7 -7
  7. package/dist/lib/browser/chunk-2SXDKBM7.mjs.map +7 -0
  8. package/dist/lib/browser/{chunk-M6KJPUJK.mjs → chunk-6X7QVTRB.mjs} +4 -3
  9. package/dist/lib/browser/{chunk-M6KJPUJK.mjs.map → chunk-6X7QVTRB.mjs.map} +2 -2
  10. package/dist/lib/browser/{chunk-3IJASGG5.mjs → chunk-75RTLLH4.mjs} +2 -2
  11. package/dist/lib/browser/{chunk-GAFCKEII.mjs → chunk-7WFISUBY.mjs} +11 -10
  12. package/dist/lib/browser/chunk-7WFISUBY.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-LNNCD2H4.mjs → chunk-MQHBMJLH.mjs} +7 -6
  14. package/dist/lib/browser/chunk-MQHBMJLH.mjs.map +7 -0
  15. package/dist/lib/browser/{chunk-2G2NA6DQ.mjs → chunk-S22N3BUR.mjs} +5 -5
  16. package/dist/lib/browser/chunk-S22N3BUR.mjs.map +7 -0
  17. package/dist/lib/browser/{chunk-5JSNQYZZ.mjs → chunk-UGDRMROB.mjs} +147 -122
  18. package/dist/lib/browser/chunk-UGDRMROB.mjs.map +7 -0
  19. package/dist/lib/browser/compiler-2HV5KXV4.mjs +143 -0
  20. package/dist/lib/browser/compiler-2HV5KXV4.mjs.map +7 -0
  21. package/dist/lib/browser/index.mjs +40 -58
  22. package/dist/lib/browser/index.mjs.map +4 -4
  23. package/dist/lib/browser/{intent-resolver-AFJ575VK.mjs → intent-resolver-3B4ESSCU.mjs} +9 -8
  24. package/dist/lib/browser/meta.json +1 -1
  25. package/dist/lib/browser/{react-surface-QEQ3QUQA.mjs → react-surface-ASV2KBRA.mjs} +15 -15
  26. package/dist/lib/browser/react-surface-ASV2KBRA.mjs.map +7 -0
  27. package/dist/lib/browser/{settings-LNLSTZM4.mjs → settings-4NKLTJTT.mjs} +3 -3
  28. package/dist/lib/browser/templates/index.mjs +1 -1
  29. package/dist/lib/browser/types/index.mjs +2 -2
  30. package/dist/lib/node-esm/{DeploymentDialog-GL5AUWMR.mjs → DeploymentDialog-5EN2KZE5.mjs} +6 -5
  31. package/dist/lib/node-esm/{NotebookContainer-SVD3A3D6.mjs → NotebookContainer-7RCEXND7.mjs} +26 -26
  32. package/dist/lib/node-esm/NotebookContainer-7RCEXND7.mjs.map +7 -0
  33. package/dist/lib/node-esm/{ScriptContainer-2CE3H3JJ.mjs → ScriptContainer-763IAKOD.mjs} +9 -7
  34. package/dist/lib/node-esm/ScriptContainer-763IAKOD.mjs.map +7 -0
  35. package/dist/lib/node-esm/{chunk-57JA6XL5.mjs → chunk-2S43VHAM.mjs} +5 -5
  36. package/dist/lib/node-esm/chunk-2S43VHAM.mjs.map +7 -0
  37. package/dist/lib/node-esm/{chunk-NNHWLRHT.mjs → chunk-32AMTGGN.mjs} +7 -6
  38. package/dist/lib/node-esm/chunk-32AMTGGN.mjs.map +7 -0
  39. package/dist/lib/node-esm/{chunk-IQTBVH4L.mjs → chunk-4VVV5L5A.mjs} +147 -122
  40. package/dist/lib/node-esm/chunk-4VVV5L5A.mjs.map +7 -0
  41. package/dist/lib/node-esm/{chunk-RIE676OW.mjs → chunk-535YDI5V.mjs} +2 -2
  42. package/dist/lib/node-esm/{chunk-HDKR5WCD.mjs → chunk-6H4FYMCX.mjs} +4 -3
  43. package/dist/lib/node-esm/{chunk-HDKR5WCD.mjs.map → chunk-6H4FYMCX.mjs.map} +2 -2
  44. package/dist/lib/node-esm/{chunk-KJKZ4KNO.mjs → chunk-DKS2EQW6.mjs} +11 -10
  45. package/dist/lib/node-esm/chunk-DKS2EQW6.mjs.map +7 -0
  46. package/dist/lib/node-esm/{chunk-YRTA4EHU.mjs → chunk-NQN3JE2R.mjs} +7 -7
  47. package/dist/lib/node-esm/chunk-NQN3JE2R.mjs.map +7 -0
  48. package/dist/lib/node-esm/compiler-KPEZKEHC.mjs +144 -0
  49. package/dist/lib/node-esm/compiler-KPEZKEHC.mjs.map +7 -0
  50. package/dist/lib/node-esm/index.mjs +40 -58
  51. package/dist/lib/node-esm/index.mjs.map +4 -4
  52. package/dist/lib/node-esm/{intent-resolver-A5VVK746.mjs → intent-resolver-GIACMXI4.mjs} +9 -8
  53. package/dist/lib/{browser/intent-resolver-AFJ575VK.mjs.map → node-esm/intent-resolver-GIACMXI4.mjs.map} +1 -1
  54. package/dist/lib/node-esm/meta.json +1 -1
  55. package/dist/lib/node-esm/{react-surface-U77YT7VF.mjs → react-surface-NXBO7VYB.mjs} +15 -15
  56. package/dist/lib/node-esm/react-surface-NXBO7VYB.mjs.map +7 -0
  57. package/dist/lib/node-esm/{settings-IUFMOCXY.mjs → settings-PW5NXWLW.mjs} +3 -3
  58. package/dist/lib/node-esm/templates/index.mjs +1 -1
  59. package/dist/lib/node-esm/types/index.mjs +2 -2
  60. package/dist/types/src/ScriptPlugin.d.ts.map +1 -1
  61. package/dist/types/src/capabilities/compiler.d.ts.map +1 -1
  62. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  63. package/dist/types/src/compiler/compiler.d.ts +1 -1
  64. package/dist/types/src/compiler/compiler.d.ts.map +1 -1
  65. package/dist/types/src/components/DeploymentDialog/DeploymentDialog.stories.d.ts +3 -0
  66. package/dist/types/src/components/DeploymentDialog/DeploymentDialog.stories.d.ts.map +1 -1
  67. package/dist/types/src/components/FrameContainer/FrameContainer.d.ts.map +1 -1
  68. package/dist/types/src/components/NotebookContainer.d.ts.map +1 -1
  69. package/dist/types/src/components/NotebookContainer.stories.d.ts +3 -0
  70. package/dist/types/src/components/NotebookContainer.stories.d.ts.map +1 -1
  71. package/dist/types/src/components/NotebookStack/NotebookCell.d.ts.map +1 -1
  72. package/dist/types/src/components/NotebookStack/NotebookStack.stories.d.ts +3 -0
  73. package/dist/types/src/components/NotebookStack/NotebookStack.stories.d.ts.map +1 -1
  74. package/dist/types/src/components/QueryEditor/QueryEditor.d.ts +5 -0
  75. package/dist/types/src/components/QueryEditor/QueryEditor.d.ts.map +1 -0
  76. package/dist/types/src/components/QueryEditor/QueryEditor.stories.d.ts +13 -0
  77. package/dist/types/src/components/QueryEditor/QueryEditor.stories.d.ts.map +1 -0
  78. package/dist/types/src/components/QueryEditor/index.d.ts +2 -0
  79. package/dist/types/src/components/QueryEditor/index.d.ts.map +1 -0
  80. package/dist/types/src/components/ScriptContainer.d.ts.map +1 -1
  81. package/dist/types/src/components/ScriptToolbar/ScriptToolbar.stories.d.ts +3 -0
  82. package/dist/types/src/components/ScriptToolbar/ScriptToolbar.stories.d.ts.map +1 -1
  83. package/dist/types/src/components/Settings/ScriptObjectSettings.d.ts.map +1 -1
  84. package/dist/types/src/e2e/deploy.test.d.ts +2 -0
  85. package/dist/types/src/e2e/deploy.test.d.ts.map +1 -0
  86. package/dist/types/src/hooks/deploy.d.ts +3 -21
  87. package/dist/types/src/hooks/deploy.d.ts.map +1 -1
  88. package/dist/types/src/hooks/index.d.ts +1 -0
  89. package/dist/types/src/hooks/index.d.ts.map +1 -1
  90. package/dist/types/src/hooks/useCompiler.d.ts +7 -0
  91. package/dist/types/src/hooks/useCompiler.d.ts.map +1 -0
  92. package/dist/types/src/templates/chess.d.ts +6 -1
  93. package/dist/types/src/templates/chess.d.ts.map +1 -1
  94. package/dist/types/src/templates/forex-effect.d.ts +4 -1
  95. package/dist/types/src/templates/forex-effect.d.ts.map +1 -1
  96. package/dist/types/src/templates/forex.d.ts +4 -1
  97. package/dist/types/src/templates/forex.d.ts.map +1 -1
  98. package/dist/types/src/testing/deploy.test.d.ts +2 -0
  99. package/dist/types/src/testing/deploy.test.d.ts.map +1 -0
  100. package/dist/types/src/testing/simulator.test.d.ts +2 -0
  101. package/dist/types/src/testing/simulator.test.d.ts.map +1 -0
  102. package/dist/types/src/translations.d.ts +2 -0
  103. package/dist/types/src/translations.d.ts.map +1 -1
  104. package/dist/types/src/types/Notebook.d.ts +7 -7
  105. package/dist/types/src/types/Notebook.d.ts.map +1 -1
  106. package/dist/types/src/types/actions.d.ts +3 -3
  107. package/dist/types/src/util/deploy.d.ts.map +1 -1
  108. package/dist/types/src/util/functions.d.ts.map +1 -1
  109. package/dist/types/tsconfig.tsbuildinfo +1 -1
  110. package/package.json +63 -59
  111. package/src/ScriptPlugin.tsx +13 -28
  112. package/src/capabilities/artifact-definition.ts +11 -11
  113. package/src/capabilities/compiler.ts +66 -16
  114. package/src/capabilities/react-surface.tsx +5 -6
  115. package/src/compiler/compiler.ts +10 -3
  116. package/src/components/FrameContainer/FrameContainer.tsx +3 -1
  117. package/src/components/NotebookContainer.tsx +14 -17
  118. package/src/components/NotebookStack/NotebookCell.tsx +6 -4
  119. package/src/components/QueryEditor/QueryEditor.stories.tsx +89 -0
  120. package/src/components/QueryEditor/QueryEditor.tsx +47 -0
  121. package/src/components/QueryEditor/index.ts +5 -0
  122. package/src/components/ScriptContainer.tsx +3 -2
  123. package/src/components/Settings/ScriptObjectSettings.tsx +5 -4
  124. package/src/components/TypescriptEditor/TypescriptEditor.stories.tsx +1 -1
  125. package/src/components/TypescriptEditor/TypescriptEditor.tsx +2 -2
  126. package/src/e2e/deploy.test.ts +64 -0
  127. package/src/hooks/deploy.ts +3 -2
  128. package/src/hooks/index.ts +1 -0
  129. package/src/hooks/useCompiler.ts +23 -0
  130. package/src/templates/chess.ts +9 -8
  131. package/src/templates/data-generator.ts +1 -1
  132. package/src/templates/forex-effect.ts +22 -27
  133. package/src/templates/forex.ts +7 -6
  134. package/src/testing/deploy.test.ts +63 -0
  135. package/src/testing/simulator.test.ts +40 -0
  136. package/src/translations.ts +2 -0
  137. package/src/types/Notebook.ts +5 -4
  138. package/src/util/deploy.ts +18 -28
  139. package/src/util/functions.ts +3 -2
  140. package/src/vite-env.d.ts +2 -0
  141. package/dist/lib/browser/DeploymentDialog-MZX4T77L.mjs +0 -14
  142. package/dist/lib/browser/NotebookContainer-RTESC4OV.mjs.map +0 -7
  143. package/dist/lib/browser/ScriptContainer-T2BAZDJ4.mjs.map +0 -7
  144. package/dist/lib/browser/chunk-2G2NA6DQ.mjs.map +0 -7
  145. package/dist/lib/browser/chunk-4M7U2WVT.mjs.map +0 -7
  146. package/dist/lib/browser/chunk-5JSNQYZZ.mjs.map +0 -7
  147. package/dist/lib/browser/chunk-GAFCKEII.mjs.map +0 -7
  148. package/dist/lib/browser/chunk-LNNCD2H4.mjs.map +0 -7
  149. package/dist/lib/browser/compiler-4KHRSX7J.mjs +0 -86
  150. package/dist/lib/browser/compiler-4KHRSX7J.mjs.map +0 -7
  151. package/dist/lib/browser/react-surface-QEQ3QUQA.mjs.map +0 -7
  152. package/dist/lib/node-esm/NotebookContainer-SVD3A3D6.mjs.map +0 -7
  153. package/dist/lib/node-esm/ScriptContainer-2CE3H3JJ.mjs.map +0 -7
  154. package/dist/lib/node-esm/chunk-57JA6XL5.mjs.map +0 -7
  155. package/dist/lib/node-esm/chunk-IQTBVH4L.mjs.map +0 -7
  156. package/dist/lib/node-esm/chunk-KJKZ4KNO.mjs.map +0 -7
  157. package/dist/lib/node-esm/chunk-NNHWLRHT.mjs.map +0 -7
  158. package/dist/lib/node-esm/chunk-YRTA4EHU.mjs.map +0 -7
  159. package/dist/lib/node-esm/compiler-DU5NQISX.mjs +0 -87
  160. package/dist/lib/node-esm/compiler-DU5NQISX.mjs.map +0 -7
  161. package/dist/lib/node-esm/react-surface-U77YT7VF.mjs.map +0 -7
  162. /package/dist/lib/browser/{DeploymentDialog-MZX4T77L.mjs.map → DeploymentDialog-FIHD4UVK.mjs.map} +0 -0
  163. /package/dist/lib/browser/{chunk-3IJASGG5.mjs.map → chunk-75RTLLH4.mjs.map} +0 -0
  164. /package/dist/lib/{node-esm/intent-resolver-A5VVK746.mjs.map → browser/intent-resolver-3B4ESSCU.mjs.map} +0 -0
  165. /package/dist/lib/browser/{settings-LNLSTZM4.mjs.map → settings-4NKLTJTT.mjs.map} +0 -0
  166. /package/dist/lib/node-esm/{DeploymentDialog-GL5AUWMR.mjs.map → DeploymentDialog-5EN2KZE5.mjs.map} +0 -0
  167. /package/dist/lib/node-esm/{chunk-RIE676OW.mjs.map → chunk-535YDI5V.mjs.map} +0 -0
  168. /package/dist/lib/node-esm/{settings-IUFMOCXY.mjs.map → settings-PW5NXWLW.mjs.map} +0 -0
@@ -0,0 +1,89 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useCallback, useMemo, useState } from 'react';
7
+
8
+ import { createDocAccessor } from '@dxos/echo-db';
9
+ import { QuerySandbox } from '@dxos/echo-query';
10
+ import { createObject } from '@dxos/react-client/echo';
11
+ import { Toolbar, useAsyncEffect } from '@dxos/react-ui';
12
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
13
+ import { createDataExtensions } from '@dxos/react-ui-editor';
14
+ import { StackItem } from '@dxos/react-ui-stack';
15
+ import { Json } from '@dxos/react-ui-syntax-highlighter';
16
+ import { trim } from '@dxos/util';
17
+
18
+ import { QueryEditor, type QueryEditorProps } from './QueryEditor';
19
+
20
+ const SCRIPT = trim`
21
+ Query.select(Filter.type('dxos.org/type/Person'))
22
+ `;
23
+
24
+ const DefaultStory = (props: QueryEditorProps) => {
25
+ const object = useMemo(() => createObject({ content: SCRIPT }), []);
26
+ const [result, setResult] = useState<object | undefined>({});
27
+ const [sandbox, setSandbox] = useState<QuerySandbox>();
28
+
29
+ useAsyncEffect(async () => {
30
+ const sandbox = new QuerySandbox();
31
+ await sandbox.open();
32
+ setSandbox(sandbox);
33
+
34
+ return () => {
35
+ void sandbox.close();
36
+ };
37
+ }, []);
38
+
39
+ const extensions = useMemo(
40
+ () => [createDataExtensions({ id: object.id, text: createDocAccessor(object, ['content']) })],
41
+ [],
42
+ );
43
+
44
+ const handleRun = useCallback(async () => {
45
+ try {
46
+ const result = sandbox?.eval(object.content);
47
+
48
+ setResult({
49
+ timestamp: Date.now(),
50
+ result,
51
+ });
52
+ } catch (err) {
53
+ setResult({
54
+ timestamp: Date.now(),
55
+ error: String(err),
56
+ });
57
+ }
58
+ }, [object, sandbox]);
59
+
60
+ return (
61
+ <StackItem.Content toolbar>
62
+ {/* <ScriptToolbar script={script} state={{}} /> */}
63
+ <Toolbar.Root>
64
+ <Toolbar.Button onClick={handleRun}>Run</Toolbar.Button>
65
+ </Toolbar.Root>
66
+ <div role='none' className='grid grid-rows-[1fr_min-content] bs-full overflow-hidden text-sm'>
67
+ <QueryEditor {...props} initialValue={object.content} extensions={extensions} />
68
+ <Json data={result} classNames='shrink-0 p-2 border-t border-subduedSeparator' />
69
+ </div>
70
+ </StackItem.Content>
71
+ );
72
+ };
73
+
74
+ const meta = {
75
+ title: 'plugins/plugin-script/QueryEditor',
76
+ component: QueryEditor,
77
+ render: DefaultStory,
78
+ decorators: [withTheme, withLayout({ container: 'column', classNames: 'is-prose' })],
79
+ } satisfies Meta<typeof DefaultStory>;
80
+
81
+ export default meta;
82
+
83
+ type Story = StoryObj<typeof meta>;
84
+
85
+ export const Default: Story = {
86
+ args: {
87
+ id: 'test',
88
+ },
89
+ };
@@ -0,0 +1,47 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useState } from 'react';
6
+ import { ScriptTarget } from 'typescript';
7
+
8
+ import queryApi from '@dxos/echo-query/api.d.ts?raw';
9
+ import { useAsyncEffect } from '@dxos/react-ui';
10
+
11
+ import { Compiler } from '../../compiler';
12
+ import { TypescriptEditor, type TypescriptEditorProps } from '../TypescriptEditor';
13
+
14
+ const GLOBALS = `
15
+ namespace QueryAPI {
16
+ ${queryApi}
17
+ }
18
+
19
+ declare global {
20
+ const Query: typeof QueryAPI.Query;
21
+ const Filter: typeof QueryAPI.Filter;
22
+ const Order: typeof QueryAPI.Order;
23
+ }
24
+
25
+ export {};
26
+ `;
27
+
28
+ export type QueryEditorProps = Omit<TypescriptEditorProps, 'env'>;
29
+
30
+ export const QueryEditor = (props: QueryEditorProps) => {
31
+ const [compiler, setCompiler] = useState<Compiler>();
32
+
33
+ useAsyncEffect(async () => {
34
+ const compiler = new Compiler({
35
+ lib: ['ES5'],
36
+ target: ScriptTarget.ES2022,
37
+ });
38
+ await compiler.initialize(GLOBALS);
39
+ setCompiler(compiler);
40
+ }, []);
41
+
42
+ if (!compiler) {
43
+ return null;
44
+ }
45
+
46
+ return <TypescriptEditor {...props} env={compiler.environment} />;
47
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './QueryEditor';
@@ -4,8 +4,9 @@
4
4
 
5
5
  import React, { useMemo } from 'react';
6
6
 
7
+ import { createDocAccessor } from '@dxos/echo-db';
7
8
  import { type Script } from '@dxos/functions';
8
- import { createDocAccessor, getSpace } from '@dxos/react-client/echo';
9
+ import { getSpace } from '@dxos/react-client/echo';
9
10
  import { useIdentity } from '@dxos/react-client/halo';
10
11
  import { createDataExtensions, listener, stackItemContentEditorClassNames } from '@dxos/react-ui-editor';
11
12
  import { StackItem } from '@dxos/react-ui-stack';
@@ -42,7 +43,7 @@ export const ScriptContainer = ({ role, script, settings = { editorInputMode: 'v
42
43
  createDataExtensions({
43
44
  id: script.id,
44
45
  text: createDocAccessor(script.source.target, ['content']),
45
- space,
46
+ messenger: space,
46
47
  identity,
47
48
  }),
48
49
  ]
@@ -9,11 +9,12 @@ import { ToolId } from '@dxos/ai';
9
9
  import { SettingsAction, createIntent } from '@dxos/app-framework';
10
10
  import { useIntentDispatcher } from '@dxos/app-framework/react';
11
11
  import { Blueprint, Template } from '@dxos/blueprints';
12
+ import { Filter, Obj, Ref } from '@dxos/echo';
12
13
  import { Function, type Script, getUserFunctionIdInMetadata } from '@dxos/functions';
13
14
  import { getInvocationUrl } from '@dxos/functions-runtime';
14
15
  import { log } from '@dxos/log';
15
16
  import { useClient } from '@dxos/react-client';
16
- import { Filter, Ref, getMeta, getSpace, useQuery } from '@dxos/react-client/echo';
17
+ import { getSpace, useQuery } from '@dxos/react-client/echo';
17
18
  import { Button, Clipboard, Input, useAsyncEffect, useControlledState, useTranslation } from '@dxos/react-ui';
18
19
  import { AccessToken } from '@dxos/types';
19
20
  import { kebabize } from '@dxos/util';
@@ -144,7 +145,7 @@ const Binding = ({ object }: ScriptObjectSettingsProps) => {
144
145
  const space = getSpace(object);
145
146
  const [fn] = useQuery(space, Filter.type(Function.Function, { source: Ref.make(object) }));
146
147
 
147
- const functionId = fn && getUserFunctionIdInMetadata(getMeta(fn));
148
+ const functionId = fn && getUserFunctionIdInMetadata(Obj.getMeta(fn));
148
149
  const functionUrl =
149
150
  functionId &&
150
151
  getInvocationUrl(functionId, client.config.values.runtime?.services?.edge?.url ?? '', {
@@ -207,7 +208,7 @@ const Publishing = ({ object }: ScriptObjectSettingsProps) => {
207
208
  const { dispatchPromise: dispatch } = useIntentDispatcher();
208
209
  const space = getSpace(object);
209
210
  const [githubToken] = useQuery(space, Filter.type(AccessToken.AccessToken, { source: 'github.com' }));
210
- const gistKey = getMeta(object).keys.find(({ source }) => source === 'github.com');
211
+ const gistKey = Obj.getMeta(object).keys.find(({ source }) => source === 'github.com');
211
212
  const [gistUrl, setGistUrl] = useState<string | undefined>();
212
213
 
213
214
  useAsyncEffect(async () => {
@@ -250,7 +251,7 @@ const Publishing = ({ object }: ScriptObjectSettingsProps) => {
250
251
 
251
252
  try {
252
253
  // TODO(wittjosiah): Factor out to intent.
253
- const meta = getMeta(object);
254
+ const meta = Obj.getMeta(object);
254
255
  const githubKey = meta.keys.find(({ source }) => source === 'github.com');
255
256
  const gistId = githubKey?.id;
256
257
  if (gistId) {
@@ -5,7 +5,7 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useCallback, useMemo, useState } from 'react';
7
7
 
8
- import { createDocAccessor } from '@dxos/react-client/echo';
8
+ import { createDocAccessor } from '@dxos/echo-db';
9
9
  import { createObject } from '@dxos/react-client/echo';
10
10
  import { Toolbar } from '@dxos/react-ui';
11
11
  import { withLayout, withTheme } from '@dxos/react-ui/testing';
@@ -86,14 +86,14 @@ export const TypescriptEditor = ({
86
86
 
87
87
  // https://github.com/val-town/codemirror-ts
88
88
  env && [
89
- tsFacet.of({ env, path: `/src/${id}.ts` }),
89
+ tsFacet.of({ env, path: `./src/${id}.ts` }),
90
90
  tsSync(),
91
91
  tsLinter(),
92
92
  tsHover({ renderTooltip: createTooltipRenderer(themeMode) }),
93
93
  ],
94
94
  ].filter(isNonNullable),
95
95
  }),
96
- [id, extensions, themeMode, inputMode, selection, scrollTo],
96
+ [id, extensions, themeMode, inputMode, selection, scrollTo, env],
97
97
  );
98
98
 
99
99
  // TODO(brudon): Use react-ui-editor's Editor component.
@@ -0,0 +1,64 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { readFile } from 'node:fs/promises';
6
+
7
+ import { describe, expect, test } from 'vitest';
8
+
9
+ import { Client, type Config } from '@dxos/client';
10
+ import { createEdgeIdentity } from '@dxos/client/edge';
11
+ import { configPreset } from '@dxos/config';
12
+ import { bundleFunction } from '@dxos/functions-runtime/bundler';
13
+ import { FunctionsServiceClient } from '@dxos/functions-runtime/edge';
14
+ import { invariant } from '@dxos/invariant';
15
+ import { log } from '@dxos/log';
16
+
17
+ describe.runIf(process.env.DX_TEST_TAGS?.includes('functions-e2e'))('Functions deployment', () => {
18
+ test('deploys FOREX (effect) function and invokes it via EDGE (main)', { timeout: 120_000 }, async () => {
19
+ const config = configPreset({ edge: 'main' });
20
+ await testDeploy(config);
21
+ });
22
+
23
+ test('deploys FOREX (effect) function and invokes it via EDGE (production)', { timeout: 120_000 }, async () => {
24
+ const config = configPreset({ edge: 'production' });
25
+ await testDeploy(config);
26
+ });
27
+
28
+ const testDeploy = async (config: Config) => {
29
+ await using client = await new Client({ config }).initialize();
30
+ await client.halo.createIdentity();
31
+
32
+ const space = await client.spaces.create();
33
+ await space.waitUntilReady();
34
+
35
+ // Inline echo function source.
36
+ const source = await readFile(new URL('../templates/forex-effect.ts', import.meta.url), 'utf-8');
37
+
38
+ // Bundle and upload.
39
+ const buildResult = await bundleFunction({ source });
40
+ if ('error' in buildResult) {
41
+ throw buildResult.error ?? new Error('Bundle creation failed');
42
+ }
43
+ const functionsServiceClient = FunctionsServiceClient.fromClient(client);
44
+
45
+ const func = await functionsServiceClient.deploy({
46
+ ownerPublicKey: space.key,
47
+ version: '0.0.1',
48
+ entryPoint: buildResult.entryPoint,
49
+ assets: buildResult.assets,
50
+ });
51
+
52
+ // Invoke deployed function via EDGE directly.
53
+ const edgeClient = client.edge;
54
+ invariant(edgeClient, 'edgeClient is required');
55
+ edgeClient.setIdentity(createEdgeIdentity(client));
56
+
57
+ const input = { from: 'USD', to: 'EUR' };
58
+ const result = await functionsServiceClient.invoke(func, input);
59
+ log.info('>>> result', { result, func });
60
+ const resultNumber = Number(result);
61
+ expect(resultNumber).toBeGreaterThan(0);
62
+ expect(resultNumber).toBeLessThan(100);
63
+ };
64
+ });
@@ -4,10 +4,11 @@
4
4
 
5
5
  import { useEffect, useMemo } from 'react';
6
6
 
7
+ import { Obj, Query, Ref } from '@dxos/echo';
7
8
  import { Function, type Script, getUserFunctionIdInMetadata } from '@dxos/functions';
8
9
  import { log } from '@dxos/log';
9
10
  import { type Client, useClient } from '@dxos/react-client';
10
- import { Query, Ref, type Space, getMeta, getSpace, useQuery } from '@dxos/react-client/echo';
11
+ import { type Space, getSpace, useQuery } from '@dxos/react-client/echo';
11
12
  import { type TFunction } from '@dxos/react-ui';
12
13
  import { createMenuAction } from '@dxos/react-ui-menu';
13
14
  import { errorMessageColors } from '@dxos/react-ui-theme';
@@ -119,6 +120,6 @@ export const useDeployDeps = ({ script }: { script: Script.Script }) => {
119
120
  const client = useClient();
120
121
  const space = getSpace(script);
121
122
  const [fn] = useQuery(space, Query.type(Function.Function, { source: Ref.make(script) }));
122
- const existingFunctionId = useMemo(() => fn && getUserFunctionIdInMetadata(getMeta(fn)), [fn]);
123
+ const existingFunctionId = useMemo(() => fn && getUserFunctionIdInMetadata(Obj.getMeta(fn)), [fn]);
123
124
  return { client, space, fn, existingFunctionId };
124
125
  };
@@ -8,3 +8,4 @@ export * from './template';
8
8
 
9
9
  export * from './useCreateAndDeployScriptTemplates';
10
10
  export * from './useToolbarState';
11
+ export * from './useCompiler';
@@ -0,0 +1,23 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useCapabilities, usePluginManager } from '@dxos/app-framework/react';
6
+ import { useAsyncEffect } from '@dxos/react-ui';
7
+
8
+ import { ScriptCapabilities } from '../capabilities';
9
+ import type { Compiler } from '../compiler';
10
+ import { ScriptEvents } from '../events';
11
+
12
+ /**
13
+ * Asynchronously sets up the compiler and returns it.
14
+ * @returns The compiler instance or undefined if it is not ready.
15
+ */
16
+ export const useCompiler = (): Compiler | undefined => {
17
+ const manager = usePluginManager();
18
+ useAsyncEffect(async () => {
19
+ await manager.activate(ScriptEvents.SetupCompiler);
20
+ }, [manager]);
21
+ const [compiler] = useCapabilities(ScriptCapabilities.Compiler);
22
+ return compiler;
23
+ };
@@ -2,27 +2,28 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- // @ts-ignore
6
- import { S, defineFunction } from 'dxos:functions';
7
- // @ts-ignore
5
+ import * as Schema from 'effect/Schema';
8
6
  import { Chess } from 'https://esm.sh/chess.js@0.13.1?bundle=false';
9
7
 
8
+ import { defineFunction } from '@dxos/functions';
9
+
10
10
  export default defineFunction({
11
11
  key: 'dxos.org/script/chess',
12
12
  name: 'Chess',
13
13
  description: 'Plays a random move in a chess game.',
14
14
 
15
- inputSchema: S.Struct({
16
- changedObjectId: S.String.annotations({
15
+ inputSchema: Schema.Struct({
16
+ changedObjectId: Schema.String.annotations({
17
17
  description: 'The objects to play the game on.',
18
18
  }),
19
- player: S.optional(S.Literal('w', 'b')).annotations({
19
+ player: Schema.optional(Schema.Literal('w', 'b')).annotations({
20
20
  description: 'The player to play the game as.',
21
21
  }),
22
22
  }),
23
23
 
24
- outputSchema: S.Struct({
25
- state: S.String.annotations({
24
+ // @ts-expect-error
25
+ outputSchema: Schema.Struct({
26
+ state: Schema.String.annotations({
26
27
  description: 'The state of the game as an ASCII art board.',
27
28
  }),
28
29
  }),
@@ -23,7 +23,7 @@ export default defineFunction({
23
23
  data: { documentAmount = 1, textSize = 10, mutationAmount = 0, waitAfterCreation = 10_000 },
24
24
  context: { space },
25
25
  }: any) => {
26
- await space.db.graph.schemaRegistry.addSchema([Expando]);
26
+ await space.db.graph.schemaRegistry.register([Expando]);
27
27
  const result: Record<string, any> = {};
28
28
  const objects: Expando[] = [];
29
29
 
@@ -2,41 +2,36 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- // @ts-ignore
6
- import { S, defineFunction } from 'dxos:functions';
7
- import {
8
- FetchHttpClient,
9
- HttpClient,
10
- HttpClientRequest,
11
- // @ts-ignore
12
- } from 'https://esm.sh/@effect/platform@0.89.0?deps=effect@3.17.0&bundle=false';
13
- // @ts-ignore
14
- import * as Effect from 'https://esm.sh/effect@3.17.0/Effect?bundle=false';
15
- // @ts-ignore
16
- import * as Schedule from 'https://esm.sh/effect@3.17.0/Schedule?bundle=false';
5
+ import * as FetchHttpClient from '@effect/platform/FetchHttpClient';
6
+ import * as HttpClient from '@effect/platform/HttpClient';
7
+ import * as HttpClientRequest from '@effect/platform/HttpClientRequest';
8
+ import * as Effect from 'effect/Effect';
9
+ import * as Schedule from 'effect/Schedule';
10
+ import * as Schema from 'effect/Schema';
11
+
12
+ import { defineFunction } from '@dxos/functions';
17
13
 
18
14
  export default defineFunction({
19
15
  key: 'dxos.org/script/forex-effect',
20
16
  name: 'Forex Effect',
21
17
  description: 'Returns the exchange rate between two currencies.',
22
18
 
23
- inputSchema: S.Struct({
24
- from: S.String.annotations({ description: 'The source currency' }),
25
- to: S.String.annotations({ description: 'The target currency' }),
19
+ inputSchema: Schema.Struct({
20
+ from: Schema.String.annotations({ description: 'The source currency' }),
21
+ to: Schema.String.annotations({ description: 'The target currency' }),
26
22
  }),
27
23
 
28
- outputSchema: S.String.annotations({ description: 'The exchange rate between the two currencies' }),
24
+ outputSchema: Schema.String.annotations({ description: 'The exchange rate between the two currencies' }),
29
25
 
30
- handler: async ({ data: { from, to } }: any) =>
31
- Effect.gen(function* () {
32
- const res = yield* HttpClientRequest.get(`https://free.ratesdb.com/v1/rates?from=${from}&to=${to}`).pipe(
33
- HttpClient.execute,
34
- Effect.flatMap((res: any) => res.json),
35
- Effect.timeout('1 second'),
36
- Effect.retry(Schedule.exponential(1_000).pipe(Schedule.compose(Schedule.recurs(3)))),
37
- Effect.scoped,
38
- );
26
+ handler: Effect.fnUntraced(function* ({ data: { from, to } }) {
27
+ const res = yield* HttpClientRequest.get(`https://free.ratesdb.com/v1/rates?from=${from}&to=${to}`).pipe(
28
+ HttpClient.execute,
29
+ Effect.flatMap((res: any) => res.json),
30
+ Effect.timeout('1 second'),
31
+ Effect.retry(Schedule.exponential(1_000).pipe(Schedule.compose(Schedule.recurs(3)))),
32
+ Effect.scoped,
33
+ );
39
34
 
40
- return res.data.rates[to].toString();
41
- }).pipe(Effect.provide(FetchHttpClient.layer)),
35
+ return (res as any).data.rates[to].toString();
36
+ }, Effect.provide(FetchHttpClient.layer)),
42
37
  });
@@ -2,20 +2,21 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- // @ts-ignore
6
- import { S, defineFunction } from 'dxos:functions';
5
+ import * as Schema from 'effect/Schema';
6
+
7
+ import { defineFunction } from '@dxos/functions';
7
8
 
8
9
  export default defineFunction({
9
10
  key: 'dxos.org/script/forex',
10
11
  name: 'Forex',
11
12
  description: 'Returns the exchange rate between two currencies.',
12
13
 
13
- inputSchema: S.Struct({
14
- from: S.String.annotations({ description: 'The source currency' }),
15
- to: S.String.annotations({ description: 'The target currency' }),
14
+ inputSchema: Schema.Struct({
15
+ from: Schema.String.annotations({ description: 'The source currency' }),
16
+ to: Schema.String.annotations({ description: 'The target currency' }),
16
17
  }),
17
18
 
18
- handler: async ({ data: { from, to } }: any) => {
19
+ handler: async ({ data: { from, to } }) => {
19
20
  const res = await fetch(`https://free.ratesdb.com/v1/rates?from=${from}&to=${to}`);
20
21
  const {
21
22
  data: { rates },
@@ -0,0 +1,63 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { readFile } from 'node:fs/promises';
6
+
7
+ import { describe, expect, test } from 'vitest';
8
+
9
+ import { Client } from '@dxos/client';
10
+ import { configPreset } from '@dxos/config';
11
+ import { bundleFunction } from '@dxos/functions-runtime/bundler';
12
+ import { FunctionsServiceClient } from '@dxos/functions-runtime/edge';
13
+ import { FunctionRuntimeKind } from '@dxos/protocols';
14
+
15
+ describe.runIf(process.env.DX_TEST_TAGS?.includes('functions-e2e'))('Script deployment', () => {
16
+ test('deploys FOREX (effect) function and invokes it via EDGE (main)', { timeout: 120_000 }, async () => {
17
+ const config = configPreset({
18
+ edge: 'dev',
19
+ });
20
+ await using client = await new Client({ config }).initialize();
21
+ await client.halo.createIdentity();
22
+
23
+ const space = await client.spaces.create();
24
+ await space.waitUntilReady();
25
+
26
+ // Inline echo function source.
27
+ const source = await readFile(new URL('../templates/forex-effect.ts', import.meta.url), 'utf-8');
28
+
29
+ // Bundle and upload.
30
+ const buildResult = await bundleFunction({ source });
31
+ if ('error' in buildResult) {
32
+ throw buildResult.error ?? new Error('Bundle creation failed');
33
+ }
34
+ // for (const [key, value] of Object.entries(buildResult.assets)) {
35
+ // await writeFile(key, value);
36
+ // console.log(resolve(key));
37
+ // }
38
+ const functionsServiceClient = FunctionsServiceClient.fromClient(client);
39
+ const newFunction = await functionsServiceClient.deploy({
40
+ // TODO(dmaretskyi): Space key or identity key.
41
+ ownerPublicKey: space.key,
42
+ version: '0.0.1',
43
+ entryPoint: buildResult.entryPoint,
44
+ assets: buildResult.assets,
45
+ runtime: FunctionRuntimeKind.enums.WORKER_LOADER,
46
+ });
47
+ console.log(newFunction);
48
+
49
+ expect(newFunction.id).toBeDefined();
50
+
51
+ // // Invoke deployed function via EDGE directly.
52
+ // const edgeClient = client.edge;
53
+ // invariant(edgeClient, 'edgeClient is required');
54
+ // edgeClient.setIdentity(createEdgeIdentity(client));
55
+
56
+ // const input = { from: 'USD', to: 'EUR' };
57
+ // const result = await edgeClient.invokeFunction({ functionId }, input);
58
+ // log.info('>>> result', { result, functionId });
59
+ // const resultNumber = Number(result);
60
+ // expect(resultNumber).toBeGreaterThan(0);
61
+ // expect(resultNumber).toBeLessThan(100);
62
+ });
63
+ });
@@ -0,0 +1,40 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { readFile } from 'node:fs/promises';
6
+
7
+ import * as Record from 'effect/Record';
8
+ import { describe, expect, test } from 'vitest';
9
+
10
+ import { bundleFunction } from '@dxos/functions-runtime/bundler';
11
+ import { FunctionWorker } from '@dxos/functions-simulator-cloudflare';
12
+ import { ErrorCodec } from '@dxos/protocols';
13
+
14
+ // Requires downloading assets from R2
15
+ describe.runIf(process.env.DX_TEST_TAGS?.includes('functions-e2e'))('Run script in sumulator', () => {
16
+ test('forex-effect', { timeout: 120_000 }, async () => {
17
+ const source = await readFile(new URL('../templates/forex-effect.ts', import.meta.url), 'utf-8');
18
+
19
+ // Bundle and upload.
20
+ const buildResult = await bundleFunction({ source });
21
+ if ('error' in buildResult) {
22
+ throw buildResult.error ?? new Error('Bundle creation failed');
23
+ }
24
+
25
+ const worker = new FunctionWorker({
26
+ mainModule: buildResult.entryPoint,
27
+ modules: Record.map(buildResult.assets, (contents, filename) => ({
28
+ contents: contents as Uint8Array<ArrayBuffer>,
29
+ contentType: filename.endsWith('.wasm') ? 'application/wasm' : 'application/javascript',
30
+ })),
31
+ });
32
+
33
+ const result = await worker.invoke({ from: 'USD', to: 'EUR' });
34
+ console.log(result);
35
+ if (result._kind === 'error') {
36
+ throw ErrorCodec.decode(result.error);
37
+ }
38
+ expect(Number(result.result)).toBeGreaterThan(0);
39
+ });
40
+ });
@@ -19,6 +19,7 @@ export const translations = [
19
19
  'object name placeholder': 'New script',
20
20
  'rename object label': 'Rename script',
21
21
  'delete object label': 'Delete script',
22
+ 'object deleted label': 'Script deleted',
22
23
  },
23
24
  [Notebook.Notebook.typename]: {
24
25
  'typename label': 'Notebook',
@@ -28,6 +29,7 @@ export const translations = [
28
29
  'object name placeholder': 'New notebook',
29
30
  'rename object label': 'Rename notebook',
30
31
  'delete object label': 'Delete notebook',
32
+ 'object deleted label': 'Notebook deleted',
31
33
  },
32
34
  [meta.id]: {
33
35
  'plugin name': 'Scripts',
@@ -6,9 +6,10 @@ import * as Schema from 'effect/Schema';
6
6
 
7
7
  import { Prompt } from '@dxos/blueprints';
8
8
  import { Obj, Type } from '@dxos/echo';
9
- import { FormAnnotation } from '@dxos/echo/internal';
9
+ import { FormInputAnnotation } from '@dxos/echo/internal';
10
10
  import { LabelAnnotation } from '@dxos/echo/internal';
11
- import { Text, View } from '@dxos/schema';
11
+ import { Graph } from '@dxos/plugin-explorer/types';
12
+ import { Text } from '@dxos/schema';
12
13
 
13
14
  export type CellType = 'markdown' | 'script' | 'query' | 'prompt' | 'view';
14
15
 
@@ -19,7 +20,7 @@ const Cell_ = Schema.Struct({
19
20
  // TODO(burdon): Union type.
20
21
  source: Schema.optional(Type.Ref(Text.Text)),
21
22
  prompt: Schema.optional(Type.Ref(Prompt.Prompt)),
22
- view: Schema.optional(Type.Ref(View.View)),
23
+ graph: Schema.optional(Type.Ref(Graph.Graph)),
23
24
  }).pipe(Schema.mutable);
24
25
  export interface Cell extends Schema.Schema.Type<typeof Cell_> {}
25
26
  export interface Cell_Encoded extends Schema.Schema.Encoded<typeof Cell_> {}
@@ -27,7 +28,7 @@ export const Cell: Schema.Schema<Cell, Cell_Encoded> = Cell_;
27
28
 
28
29
  export const Notebook = Schema.Struct({
29
30
  name: Schema.String.pipe(Schema.optional),
30
- cells: Cell.pipe(Schema.Array, Schema.mutable, FormAnnotation.set(false)),
31
+ cells: Cell.pipe(Schema.Array, Schema.mutable, FormInputAnnotation.set(false)),
31
32
  }).pipe(
32
33
  Type.Obj({
33
34
  typename: 'dxos.org/type/Notebook',