@dxos/compute 0.8.4-main.f5c0578 → 0.8.4-main.fcfe5033a5

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 (58) hide show
  1. package/dist/lib/{browser/chunk-X2FWMHD4.mjs → neutral/chunk-JRV42MW3.mjs} +88 -94
  2. package/dist/lib/neutral/chunk-JRV42MW3.mjs.map +7 -0
  3. package/dist/lib/{browser → neutral}/index.mjs +1 -1
  4. package/dist/lib/neutral/meta.json +1 -0
  5. package/dist/lib/{browser → neutral}/testing/index.mjs +49 -6
  6. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  7. package/dist/types/src/compute-graph-registry.d.ts +9 -6
  8. package/dist/types/src/compute-graph-registry.d.ts.map +1 -1
  9. package/dist/types/src/compute-graph-registry.test.d.ts +2 -0
  10. package/dist/types/src/compute-graph-registry.test.d.ts.map +1 -0
  11. package/dist/types/src/compute-graph.d.ts +10 -7
  12. package/dist/types/src/compute-graph.d.ts.map +1 -1
  13. package/dist/types/src/compute-node.d.ts +1 -2
  14. package/dist/types/src/compute-node.d.ts.map +1 -1
  15. package/dist/types/src/functions/async-function.d.ts +13 -11
  16. package/dist/types/src/functions/async-function.d.ts.map +1 -1
  17. package/dist/types/src/functions/edge-function.d.ts +3 -3
  18. package/dist/types/src/functions/edge-function.d.ts.map +1 -1
  19. package/dist/types/src/index.d.ts.map +1 -1
  20. package/dist/types/src/testing/index.d.ts +1 -0
  21. package/dist/types/src/testing/index.d.ts.map +1 -1
  22. package/dist/types/src/testing/test-builder.d.ts +1 -1
  23. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  24. package/dist/types/src/testing/test-plugin.d.ts +4 -5
  25. package/dist/types/src/testing/test-plugin.d.ts.map +1 -1
  26. package/dist/types/src/testing/test-runtime.d.ts +10 -0
  27. package/dist/types/src/testing/test-runtime.d.ts.map +1 -0
  28. package/dist/types/src/types/hyperformula.d.ts +3 -6
  29. package/dist/types/src/types/hyperformula.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +29 -34
  32. package/src/compute-graph-registry.test.ts +167 -0
  33. package/src/compute-graph-registry.ts +19 -13
  34. package/src/compute-graph.test.ts +63 -13
  35. package/src/compute-graph.ts +41 -36
  36. package/src/compute-node.ts +2 -5
  37. package/src/functions/async-function.ts +20 -15
  38. package/src/functions/edge-function.ts +28 -32
  39. package/src/hyperformula.test.ts +1 -1
  40. package/src/index.ts +0 -27
  41. package/src/testing/index.ts +1 -0
  42. package/src/testing/test-builder.ts +7 -2
  43. package/src/testing/test-plugin.ts +2 -5
  44. package/src/testing/test-runtime.ts +53 -0
  45. package/src/testing/util.ts +1 -1
  46. package/src/types/hyperformula.ts +8 -8
  47. package/dist/lib/browser/chunk-X2FWMHD4.mjs.map +0 -7
  48. package/dist/lib/browser/meta.json +0 -1
  49. package/dist/lib/browser/testing/index.mjs.map +0 -7
  50. package/dist/lib/node-esm/chunk-RP7HSSCA.mjs +0 -3109
  51. package/dist/lib/node-esm/chunk-RP7HSSCA.mjs.map +0 -7
  52. package/dist/lib/node-esm/index.mjs +0 -56
  53. package/dist/lib/node-esm/index.mjs.map +0 -7
  54. package/dist/lib/node-esm/meta.json +0 -1
  55. package/dist/lib/node-esm/testing/index.mjs +0 -177
  56. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  57. package/dist/vendor/hyperformula.mjs +0 -36400
  58. /package/dist/lib/{browser → neutral}/index.mjs.map +0 -0
@@ -2,17 +2,18 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type SimpleCellAddress } from 'hyperformula/typings/Cell';
6
- import { type InterpreterState } from 'hyperformula/typings/interpreter/InterpreterState';
7
- import { type InterpreterValue } from 'hyperformula/typings/interpreter/InterpreterValue';
8
- import { type ProcedureAst } from 'hyperformula/typings/parser';
5
+ import type * as ManagedRuntime from 'effect/ManagedRuntime';
9
6
  import defaultsDeep from 'lodash.defaultsdeep';
10
7
 
11
8
  import { type CleanupFn, debounce } from '@dxos/async';
12
- import { type Space } from '@dxos/client/echo';
9
+ import type { Space } from '@dxos/client/echo';
13
10
  import { log } from '@dxos/log';
14
-
15
- import { CellError, EmptyValue, ErrorType, FunctionPlugin, type HyperFormula } from '#hyperformula';
11
+ import type { Operation } from '@dxos/operation';
12
+ import type { RawInterpreterValue, SimpleCellAddress } from '@dxos/vendor-hyperformula';
13
+ import type { InterpreterState } from '@dxos/vendor-hyperformula';
14
+ import type { InterpreterValue } from '@dxos/vendor-hyperformula';
15
+ import type { ProcedureAst } from '@dxos/vendor-hyperformula';
16
+ import { CellError, EmptyValue, ErrorType, FunctionPlugin, type HyperFormula } from '@dxos/vendor-hyperformula';
16
17
 
17
18
  // TODO(burdon): Create API gateways:
18
19
  // https://publicapis.io
@@ -34,14 +35,12 @@ export type FunctionOptions = {
34
35
  export type FunctionContextOptions = {
35
36
  defaultTtl: number;
36
37
  debounceDelay: number;
37
- remoteFunctionUrl: string;
38
38
  onUpdate?: (update: FunctionUpdateEvent) => void;
39
39
  };
40
40
 
41
- export const defaultFunctionContextOptions: FunctionContextOptions = {
41
+ export const defaultFunctionContextOptions: Pick<FunctionContextOptions, 'defaultTtl' | 'debounceDelay'> = {
42
42
  defaultTtl: 5_000,
43
43
  debounceDelay: 200,
44
- remoteFunctionUrl: 'https://edge.dxos.workers.dev/functions', // TODO(burdon): Config.
45
44
  };
46
45
 
47
46
  /**
@@ -78,6 +77,7 @@ export class FunctionContext {
78
77
 
79
78
  constructor(
80
79
  private readonly _hf: HyperFormula,
80
+ private readonly _runtime: ManagedRuntime.ManagedRuntime<Operation.Service, never>,
81
81
  private readonly _space: Space | undefined,
82
82
  _options?: Partial<FunctionContextOptions>,
83
83
  ) {
@@ -94,14 +94,14 @@ export class FunctionContext {
94
94
  return this._space;
95
95
  }
96
96
 
97
- get remoteFunctionUrl() {
98
- return this._options.remoteFunctionUrl;
99
- }
100
-
101
97
  get info() {
102
98
  return { cache: this._cache.size, invocations: this._invocations };
103
99
  }
104
100
 
101
+ get runtime() {
102
+ return this._runtime;
103
+ }
104
+
105
105
  flush(): void {
106
106
  this._cache.clear();
107
107
  this._invocations = {};
@@ -169,7 +169,12 @@ export class AsyncFunctionPlugin extends FunctionPlugin {
169
169
  /**
170
170
  * Immediately returns cached value then runs the async function.
171
171
  */
172
- protected runAsyncFunction(ast: ProcedureAst, state: InterpreterState, cb: AsyncFunction, options?: FunctionOptions) {
172
+ protected runAsyncFunction(
173
+ ast: ProcedureAst,
174
+ state: InterpreterState,
175
+ cb: AsyncFunction,
176
+ options?: FunctionOptions,
177
+ ): RawInterpreterValue {
173
178
  const { procedureName } = ast;
174
179
  const metadata = this.metadata(procedureName);
175
180
  return this.runFunction(ast.args, state, metadata, (...args: any) => {
@@ -2,18 +2,17 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { effect } from '@preact/signals-core';
6
- import { SchemaAST } from 'effect';
7
- import { type InterpreterState } from 'hyperformula/typings/interpreter/InterpreterState';
8
- import { type ProcedureAst } from 'hyperformula/typings/parser';
5
+ import * as Effect from 'effect/Effect';
6
+ import * as SchemaAST from 'effect/SchemaAST';
9
7
 
10
- import { Filter, getMeta } from '@dxos/client/echo';
11
- import { toEffectSchema } from '@dxos/echo-schema';
12
- import { FunctionType, getUserFunctionUrlInMetadata } from '@dxos/functions';
8
+ import { Filter } from '@dxos/client/echo';
9
+ import { JsonSchema, Obj } from '@dxos/echo';
13
10
  import { log } from '@dxos/log';
11
+ import { Operation } from '@dxos/operation';
14
12
  import { isNonNullable } from '@dxos/util';
15
-
16
- import { CellError, ErrorType, FunctionArgumentType } from '#hyperformula';
13
+ import { type ProcedureAst } from '@dxos/vendor-hyperformula';
14
+ import { type InterpreterState } from '@dxos/vendor-hyperformula';
15
+ import { CellError, ErrorType, FunctionArgumentType } from '@dxos/vendor-hyperformula';
17
16
 
18
17
  import { type AsyncFunction, AsyncFunctionPlugin } from './async-function';
19
18
 
@@ -35,49 +34,46 @@ export class EdgeFunctionPlugin extends AsyncFunctionPlugin {
35
34
  return new CellError(ErrorType.REF, 'Missing space');
36
35
  }
37
36
 
38
- const {
39
- objects: [fn],
40
- } = await space.db.query(Filter.type(FunctionType, { binding })).run();
37
+ const [fn] = await space.db.query(Filter.type(Operation.PersistentOperation, { binding })).run();
41
38
  if (!fn) {
42
39
  log.info('Function not found', { binding });
43
40
  return new CellError(ErrorType.REF, 'Function not found');
44
41
  }
45
42
 
46
43
  if (subscribe) {
47
- const unsubscribe = effect(() => {
44
+ const unsubscribe = Obj.subscribe(fn, () => {
48
45
  log('function changed', { fn });
49
- const _ = fn?.version;
50
-
51
46
  // TODO(wittjosiah): `ttl` should be 0 to force a recalculation when a new version is deployed.
52
47
  // This needs a ttl to prevent a binding change from causing the function not to be found.
53
- this.runAsyncFunction(ast, state, handler(false), { ttl: FUNCTION_TTL });
48
+ this.runAsyncFunction(ast, state, handler(false), {
49
+ ttl: FUNCTION_TTL,
50
+ });
54
51
  });
55
52
 
56
53
  this.context.createSubscription(ast.procedureName, unsubscribe);
57
54
  }
58
55
 
59
- const body: Record<string, any> = {};
56
+ const runtime = this.context.runtime;
57
+ const functionDef = Operation.deserialize(fn);
58
+ // If input schema exists, construct an object from args using the schema props order, otherwise pass { args }.
59
+ let input: any;
60
60
  if (fn.inputSchema) {
61
- const schema = toEffectSchema(fn.inputSchema);
62
- SchemaAST.getPropertySignatures(schema.ast).forEach(({ name }, index) => {
63
- body[name.toString()] = args[index];
61
+ const schema = JsonSchema.toEffectSchema(fn.inputSchema);
62
+ const props = SchemaAST.getPropertySignatures(schema.ast);
63
+ input = {} as any;
64
+ props.forEach(({ name }, index) => {
65
+ input[name.toString()] = args[index];
64
66
  });
65
67
  } else {
66
- body.args = args.filter(isNonNullable);
68
+ input = { args: args.filter(isNonNullable) };
67
69
  }
68
- const path = getUserFunctionUrlInMetadata(getMeta(fn));
69
- const response = await fetch(`${this.context.remoteFunctionUrl}${path}`, {
70
- method: 'POST',
71
- headers: { 'Content-Type': 'application/json' },
72
- body: JSON.stringify(body),
73
- });
74
- const result = await response.text();
75
- log('function executed', { result });
76
-
77
- return result;
70
+ const result = runtime.runPromise(Operation.invoke(functionDef, input).pipe(Effect.orDie));
71
+ return result as any;
78
72
  };
79
73
 
80
- return this.runAsyncFunction(ast, state, handler(true), { ttl: FUNCTION_TTL });
74
+ return this.runAsyncFunction(ast, state, handler(true), {
75
+ ttl: FUNCTION_TTL,
76
+ });
81
77
  }
82
78
  }
83
79
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { describe, expect, test } from 'vitest';
6
6
 
7
- import { HyperFormula } from '#hyperformula';
7
+ import { HyperFormula } from '@dxos/vendor-hyperformula';
8
8
 
9
9
  describe('hyperformula', () => {
10
10
  test('sanity test', async () => {
package/src/index.ts CHANGED
@@ -2,33 +2,6 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- // TODO(burdon): Separate hyperformula (client compute) from remote/edge functions.
6
-
7
- // TODO(burdon): Reconcile: types.
8
- // - dxos/graph
9
- // - dxos/compute
10
- // - dxos/functions
11
- // - dxos/assistant
12
- // - dxos/plugin-automation
13
- // - dxos/plugin-script
14
- // - dxos/plugin-sheet
15
-
16
- // TODO(burdon): Tech debt.
17
- // - move hyperformula defs from sheet to compute.
18
- // - standard from ./types exports for plugins.
19
- // - dxos/agent
20
- // - dxos/agent-functions
21
- // - dxos/mosaic, dxos-card
22
-
23
- // TODO(burdon): Reconcile UX.
24
- // - dxos/plugin-explorer
25
- // - dxos/plugin-canvas
26
- // - dxos/gem-*
27
-
28
- // TODO(burdon): Next
29
- // - dxos/plugin-search
30
- // - dxos/plugin-threads
31
-
32
5
  export * from './compute-graph';
33
6
  export * from './compute-graph-registry';
34
7
  export * from './compute-node';
@@ -5,3 +5,4 @@
5
5
  export * from './test-builder';
6
6
  export * from './test-plugin';
7
7
  export * from './util';
8
+ export * from './test-runtime';
@@ -7,8 +7,9 @@ import { type Context, Resource } from '@dxos/context';
7
7
  import { invariant } from '@dxos/invariant';
8
8
 
9
9
  import { type ComputeGraphOptions, ComputeGraphRegistry } from '../compute-graph-registry';
10
+ import { createMockedComputeRuntimeProvider } from './test-runtime';
10
11
 
11
- export type TestBuilderOptions = ClientOptions & ComputeGraphOptions;
12
+ export type TestBuilderOptions = ClientOptions & Partial<ComputeGraphOptions>;
12
13
 
13
14
  // TODO(burdon): Reconcile with @dxos/client/testing.
14
15
  export class TestBuilder extends Resource {
@@ -43,7 +44,11 @@ export class TestBuilder extends Resource {
43
44
  this._client = undefined;
44
45
  });
45
46
 
46
- const registry = new ComputeGraphRegistry(this._options);
47
+ const registry = new ComputeGraphRegistry({
48
+ ...this._options,
49
+ // Provide a default runtime provider for tests if not supplied.
50
+ computeRuntime: this._options.computeRuntime ?? createMockedComputeRuntimeProvider(),
51
+ });
47
52
  await registry.open();
48
53
  this._registry = registry;
49
54
  this._ctx.onDispose(async () => {
@@ -2,12 +2,9 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type InterpreterState } from 'hyperformula/typings/interpreter/InterpreterState';
6
- import { type ProcedureAst } from 'hyperformula/typings/parser';
7
-
8
5
  import { getDeep } from '@dxos/util';
9
-
10
- import { FunctionArgumentType } from '#hyperformula';
6
+ import { type InterpreterState, type ProcedureAst } from '@dxos/vendor-hyperformula';
7
+ import { FunctionArgumentType } from '@dxos/vendor-hyperformula';
11
8
 
12
9
  import { type ComputeGraphPlugin } from '../compute-graph-registry';
13
10
  import { type AsyncFunction, AsyncFunctionPlugin } from '../functions';
@@ -0,0 +1,53 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Layer from 'effect/Layer';
7
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
8
+
9
+ import { type SpaceId } from '@dxos/client/echo';
10
+ import { Operation, OperationHandlerSet } from '@dxos/operation';
11
+
12
+ import { type FunctionsRuntimeProvider } from '../compute-graph-registry';
13
+
14
+ /**
15
+ * Minimal compute runtime provider for tests and Storybook.
16
+ * Will cause errors if used for actual runtime.
17
+ */
18
+ export const createMockedComputeRuntimeProvider = ({
19
+ functions,
20
+ }: { functions?: OperationHandlerSet.OperationHandlerSet } = {}): FunctionsRuntimeProvider => {
21
+ return {
22
+ getRuntime: (_spaceId: SpaceId) =>
23
+ ManagedRuntime.make(
24
+ functions
25
+ ? Layer.effect(
26
+ Operation.Service,
27
+ Effect.gen(function* () {
28
+ const handlers = yield* functions.handlers;
29
+ return {
30
+ invoke: (op: any, ...args: any[]) => {
31
+ const handler = handlers.find((h: any) => h.meta.key === op.meta.key);
32
+ if (!handler) {
33
+ return Effect.die(`No handler found for operation: ${op.meta.key}`);
34
+ }
35
+ const result = handler.handler(args[0]);
36
+ if (Effect.isEffect(result)) {
37
+ return result as Effect.Effect<unknown>;
38
+ }
39
+ return Effect.promise(() => Promise.resolve(result));
40
+ },
41
+ schedule: () => Effect.void,
42
+ invokePromise: async () => ({ error: new Error('Not implemented in test runtime') }),
43
+ } as Operation.OperationService;
44
+ }),
45
+ )
46
+ : Layer.succeed(Operation.Service, {
47
+ invoke: () => Effect.die('Operation.Service not available in test.'),
48
+ schedule: () => Effect.die('Operation.Service not available in test.'),
49
+ invokePromise: async () => ({ error: new Error('Not available') }),
50
+ } as any),
51
+ ),
52
+ };
53
+ };
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { HyperFormula } from 'hyperformula';
5
+ import { HyperFormula } from '@dxos/vendor-hyperformula';
6
6
 
7
7
  export const getRegisteredFunctionNames = () => {
8
8
  return HyperFormula.buildEmpty({ licenseKey: 'gpl-v3' }).getRegisteredFunctionNames();
@@ -2,16 +2,16 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type SimpleCellRange } from 'hyperformula/typings/AbsoluteCellRange';
6
- import { type SimpleCellAddress } from 'hyperformula/typings/Cell';
7
- import { type SimpleDate, type SimpleDateTime } from 'hyperformula/typings/DateTimeHelper';
8
-
9
- // TODO(burdon): Explain special import.
10
- import { DetailedCellError, ExportedCellChange } from '#hyperformula';
5
+ import {
6
+ type SimpleCellAddress,
7
+ type SimpleCellRange,
8
+ type SimpleDate,
9
+ type SimpleDateTime,
10
+ } from '@dxos/vendor-hyperformula';
11
+ import { DetailedCellError, ExportedCellChange } from '@dxos/vendor-hyperformula';
11
12
 
12
13
  /**
13
- * Hyperformula had issues during bundling with vite,
14
- * so we pre-bundle hyperformula and place it in the vendor directory of this package.
14
+ * Re-exported from vendored hyperformula package.
15
15
  */
16
16
 
17
17
  export { DetailedCellError, ExportedCellChange };