@dxos/functions-testing 0.8.4-main.69d29f4 → 0.8.4-main.7996785055

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/functions-testing",
3
- "version": "0.8.4-main.69d29f4",
3
+ "version": "0.8.4-main.7996785055",
4
4
  "description": "Functions tests",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -37,17 +37,19 @@
37
37
  "src"
38
38
  ],
39
39
  "dependencies": {
40
- "@effect/platform": "0.93.6",
41
- "@dxos/client": "0.8.4-main.69d29f4",
42
- "@dxos/async": "0.8.4-main.69d29f4",
43
- "@dxos/config": "0.8.4-main.69d29f4",
44
- "@dxos/echo": "0.8.4-main.69d29f4",
45
- "@dxos/functions-runtime-cloudflare": "0.8.4-main.69d29f4",
46
- "@dxos/functions-runtime": "0.8.4-main.69d29f4",
47
- "@dxos/functions": "0.8.4-main.69d29f4",
48
- "@dxos/invariant": "0.8.4-main.69d29f4",
49
- "@dxos/protocols": "0.8.4-main.69d29f4",
50
- "@dxos/log": "0.8.4-main.69d29f4"
40
+ "@effect/platform": "0.94.4",
41
+ "@dxos/config": "0.8.4-main.7996785055",
42
+ "@dxos/async": "0.8.4-main.7996785055",
43
+ "@dxos/client": "0.8.4-main.7996785055",
44
+ "@dxos/context": "0.8.4-main.7996785055",
45
+ "@dxos/functions-runtime": "0.8.4-main.7996785055",
46
+ "@dxos/functions-runtime-cloudflare": "0.8.4-main.7996785055",
47
+ "@dxos/invariant": "0.8.4-main.7996785055",
48
+ "@dxos/echo": "0.8.4-main.7996785055",
49
+ "@dxos/functions": "0.8.4-main.7996785055",
50
+ "@dxos/operation": "0.8.4-main.7996785055",
51
+ "@dxos/protocols": "0.8.4-main.7996785055",
52
+ "@dxos/log": "0.8.4-main.7996785055"
51
53
  },
52
54
  "publishConfig": {
53
55
  "access": "public"
@@ -5,6 +5,7 @@
5
5
  import { describe, test } from 'vitest';
6
6
 
7
7
  import { configPreset } from '@dxos/config';
8
+ import { Context } from '@dxos/context';
8
9
  import { Obj, Ref } from '@dxos/echo';
9
10
  import { Trigger } from '@dxos/functions';
10
11
  import { FunctionRuntimeKind } from '@dxos/protocols';
@@ -26,6 +27,7 @@ describe.runIf(process.env.DX_TEST_TAGS?.includes('functions-e2e'))('CPU limit',
26
27
  FunctionRuntimeKind.enums.WORKERS_FOR_PLATFORMS,
27
28
  );
28
29
  const result = await functionsServiceClient.invoke(
30
+ Context.default(),
29
31
  func,
30
32
  {
31
33
  iterations: 100,
@@ -54,7 +56,7 @@ describe.runIf(process.env.DX_TEST_TAGS?.includes('functions-e2e'))('CPU limit',
54
56
  }),
55
57
  );
56
58
  await sync(space);
57
- const result = await functionsServiceClient.forceRunCronTrigger(space.id, trigger.id);
59
+ const result = await functionsServiceClient.forceRunCronTrigger(Context.default(), space.id, trigger.id);
58
60
  console.log(result);
59
61
  });
60
62
 
@@ -76,21 +78,21 @@ describe.runIf(process.env.DX_TEST_TAGS?.includes('functions-e2e'))('CPU limit',
76
78
  );
77
79
  await sync(space);
78
80
  {
79
- const result = await functionsServiceClient.forceRunCronTrigger(space.id, trigger.id);
81
+ const result = await functionsServiceClient.forceRunCronTrigger(Context.default(), space.id, trigger.id);
80
82
  console.log(result);
81
83
  }
82
84
 
83
85
  {
84
- const result = await functionsServiceClient.forceRunCronTrigger(space.id, trigger.id);
86
+ const result = await functionsServiceClient.forceRunCronTrigger(Context.default(), space.id, trigger.id);
85
87
  console.log(result);
86
88
  }
87
89
 
88
90
  {
89
- Obj.change(trigger, (t) => {
90
- t.input!.iterations = 100;
91
+ Obj.change(trigger, (obj) => {
92
+ obj.input!.iterations = 100;
91
93
  });
92
94
  await sync(space);
93
- const result = await functionsServiceClient.forceRunCronTrigger(space.id, trigger.id);
95
+ const result = await functionsServiceClient.forceRunCronTrigger(Context.default(), space.id, trigger.id);
94
96
  console.log(result);
95
97
  }
96
98
  });
@@ -134,14 +136,14 @@ describe.runIf(process.env.DX_TEST_TAGS?.includes('functions-e2e'))('CPU limit',
134
136
  await sync(space);
135
137
  await observeInvocations(space, 5);
136
138
 
137
- Obj.change(trigger, (t) => {
138
- t.input!.iterations = 1_000_000_000;
139
+ Obj.change(trigger, (obj) => {
140
+ obj.input!.iterations = 1_000_000_000;
139
141
  });
140
142
  await sync(space);
141
143
  await observeInvocations(space, 10);
142
144
 
143
- Obj.change(trigger, (t) => {
144
- t.input!.iterations = 100;
145
+ Obj.change(trigger, (obj) => {
146
+ obj.input!.iterations = 100;
145
147
  });
146
148
  await sync(space);
147
149
  await observeInvocations(space, 1_000);
@@ -0,0 +1,61 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Operation } from '@dxos/operation';
6
+ import * as Schema from 'effect/Schema';
7
+
8
+ import { Database } from '@dxos/echo';
9
+
10
+ export const Fibonacci = Operation.make({
11
+ meta: {
12
+ key: 'example.org/function/fib',
13
+ name: 'Fibonacci',
14
+ description: 'Function that calculates a Fibonacci number',
15
+ },
16
+ input: Schema.Struct({
17
+ iterations: Schema.optional(Schema.Number).annotations({
18
+ description: 'Number of iterations',
19
+ default: 100_000,
20
+ }),
21
+ }),
22
+ output: Schema.Struct({
23
+ result: Schema.String,
24
+ }),
25
+ });
26
+
27
+ export const Reply = Operation.make({
28
+ meta: {
29
+ key: 'example.org/function/reply',
30
+ name: 'Reply',
31
+ description: 'Function that echoes the input',
32
+ },
33
+ input: Schema.Any,
34
+ output: Schema.Any,
35
+ });
36
+
37
+ export const Sleep = Operation.make({
38
+ meta: {
39
+ key: 'example.org/function/sleep',
40
+ name: 'Sleep',
41
+ description: 'Function that sleeps for a given amount of time',
42
+ },
43
+ input: Schema.Struct({
44
+ duration: Schema.optional(Schema.Number).annotations({
45
+ description: 'Milliseconds to sleep',
46
+ default: 100_000,
47
+ }),
48
+ }),
49
+ output: Schema.Void,
50
+ });
51
+
52
+ export const QueryDb = Operation.make({
53
+ meta: {
54
+ key: 'example.org/function/query',
55
+ name: 'Query',
56
+ description: 'Queries the database',
57
+ },
58
+ input: Schema.Any,
59
+ output: Schema.Any,
60
+ services: [Database.Service],
61
+ });
@@ -3,30 +3,21 @@
3
3
  //
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
- import * as Schema from 'effect/Schema';
7
6
 
8
- import { defineFunction } from '@dxos/functions';
7
+ import { Operation } from '@dxos/operation';
9
8
 
10
- export default defineFunction({
11
- key: 'example.org/function/fib',
12
- name: 'Fibonacci',
13
- description: 'Function that calculates a Fibonacci number',
14
- inputSchema: Schema.Struct({
15
- iterations: Schema.optional(Schema.Number).annotations({
16
- description: 'Number of iterations',
17
- default: 100_000,
9
+ import { Fibonacci } from './definitions';
10
+
11
+ export default Fibonacci.pipe(
12
+ Operation.withHandler(
13
+ Effect.fn(function* ({ iterations = 100_000 }) {
14
+ let a = 0n;
15
+ let b = 1n;
16
+ for (let i = 0; i < iterations; i++) {
17
+ a += b;
18
+ b = a - b;
19
+ }
20
+ return { result: a.toString() };
18
21
  }),
19
- }),
20
- outputSchema: Schema.Struct({
21
- result: Schema.String,
22
- }),
23
- handler: Effect.fn(function* ({ data: { iterations = 100_000 } }) {
24
- let a = 0n;
25
- let b = 1n;
26
- for (let i = 0; i < iterations; i++) {
27
- a += b;
28
- b = a - b;
29
- }
30
- return { result: a.toString() };
31
- }),
32
- });
22
+ ),
23
+ );
@@ -10,35 +10,39 @@ import * as Effect from 'effect/Effect';
10
10
  import * as Schedule from 'effect/Schedule';
11
11
  import * as Schema from 'effect/Schema';
12
12
 
13
- import { defineFunction } from '@dxos/functions';
13
+ import { Operation } from '@dxos/operation';
14
14
 
15
- export default defineFunction({
16
- key: 'dxos.org/script/forex-effect',
17
- name: 'Forex Effect',
18
- description: 'Returns the exchange rate between two currencies.',
19
-
20
- inputSchema: Schema.Struct({
15
+ const ForexEffect = Operation.make({
16
+ meta: {
17
+ key: 'org.dxos.script.forex-effect',
18
+ name: 'Forex Effect',
19
+ description: 'Returns the exchange rate between two currencies.',
20
+ },
21
+ input: Schema.Struct({
21
22
  from: Schema.String.annotations({ description: 'The source currency' }),
22
23
  to: Schema.String.annotations({ description: 'The target currency' }),
23
24
  }),
25
+ output: Schema.String.annotations({ description: 'The exchange rate between the two currencies' }),
26
+ });
24
27
 
25
- outputSchema: Schema.String.annotations({ description: 'The exchange rate between the two currencies' }),
26
-
27
- handler: Effect.fnUntraced(function* ({ data: { from, to } }: any) {
28
- const res = yield* HttpClientRequest.get(`https://free.ratesdb.com/v1/rates?from=${from}&to=${to}`).pipe(
29
- HttpClient.execute,
30
- Effect.flatMap(
31
- HttpClientResponse.schemaBodyJson(
32
- Schema.Struct({
33
- data: Schema.Struct({ rates: Schema.Record({ key: Schema.String, value: Schema.Number }) }),
34
- }),
28
+ export default ForexEffect.pipe(
29
+ Operation.withHandler(
30
+ Effect.fnUntraced(function* ({ from, to }) {
31
+ const res = yield* HttpClientRequest.get(`https://free.ratesdb.com/v1/rates?from=${from}&to=${to}`).pipe(
32
+ HttpClient.execute,
33
+ Effect.flatMap(
34
+ HttpClientResponse.schemaBodyJson(
35
+ Schema.Struct({
36
+ data: Schema.Struct({ rates: Schema.Record({ key: Schema.String, value: Schema.Number }) }),
37
+ }),
38
+ ),
35
39
  ),
36
- ),
37
- Effect.timeout('1 second'),
38
- Effect.retry(Schedule.exponential(1_000).pipe(Schedule.compose(Schedule.recurs(3)))),
39
- Effect.scoped,
40
- );
40
+ Effect.timeout('1 second'),
41
+ Effect.retry(Schedule.exponential(1_000).pipe(Schedule.compose(Schedule.recurs(3)))),
42
+ Effect.scoped,
43
+ );
41
44
 
42
- return res.data.rates[to].toString();
43
- }, Effect.provide(FetchHttpClient.layer)),
44
- });
45
+ return res.data.rates[to].toString();
46
+ }, Effect.provide(FetchHttpClient.layer)),
47
+ ),
48
+ );
@@ -3,19 +3,17 @@
3
3
  //
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
- import * as Schema from 'effect/Schema';
7
6
 
8
- import { Database, Filter, Query } from '@dxos/echo';
9
- import { defineFunction } from '@dxos/functions';
7
+ import { Database, Filter, Query as EchoQuery } from '@dxos/echo';
8
+ import { Operation } from '@dxos/operation';
10
9
 
11
- export default defineFunction({
12
- key: 'example.org/function/query',
13
- name: 'Query',
14
- description: 'Queries the database',
15
- inputSchema: Schema.Any,
16
- outputSchema: Schema.Any,
17
- handler: Effect.fn(function* ({ data }) {
18
- const results = yield* Database.Service.runQuery(Query.select(Filter.everything()));
19
- return { count: results.length };
20
- }),
21
- });
10
+ import { QueryDb } from './definitions';
11
+
12
+ export default QueryDb.pipe(
13
+ Operation.withHandler(
14
+ Effect.fn(function* (data) {
15
+ const results = yield* Database.runQuery(EchoQuery.select(Filter.everything()));
16
+ return { count: results.length };
17
+ }),
18
+ ),
19
+ );
@@ -4,18 +4,16 @@
4
4
 
5
5
  import * as Console from 'effect/Console';
6
6
  import * as Effect from 'effect/Effect';
7
- import * as Schema from 'effect/Schema';
8
7
 
9
- import { defineFunction } from '@dxos/functions';
8
+ import { Operation } from '@dxos/operation';
10
9
 
11
- export default defineFunction({
12
- key: 'example.org/function/reply',
13
- name: 'Reply',
14
- description: 'Function that echoes the input',
15
- inputSchema: Schema.Any,
16
- outputSchema: Schema.Any,
17
- handler: Effect.fn(function* ({ data }) {
18
- yield* Console.log('reply', { data });
19
- return data;
20
- }),
21
- });
10
+ import { Reply } from './definitions';
11
+
12
+ export default Reply.pipe(
13
+ Operation.withHandler(
14
+ Effect.fn(function* (data) {
15
+ yield* Console.log('reply', { data });
16
+ return data;
17
+ }),
18
+ ),
19
+ );
@@ -3,22 +3,15 @@
3
3
  //
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
- import * as Schema from 'effect/Schema';
7
6
 
8
- import { defineFunction } from '@dxos/functions';
7
+ import { Operation } from '@dxos/operation';
9
8
 
10
- export default defineFunction({
11
- key: 'example.org/function/sleep',
12
- name: 'Sleep',
13
- description: 'Function that sleeps for a given amount of time',
14
- inputSchema: Schema.Struct({
15
- duration: Schema.optional(Schema.Number).annotations({
16
- description: 'Milliseconds to sleep',
17
- default: 100_000,
9
+ import { Sleep } from './definitions';
10
+
11
+ export default Sleep.pipe(
12
+ Operation.withHandler(
13
+ Effect.fn(function* ({ duration = 100_000 }) {
14
+ yield* Effect.sleep(duration);
18
15
  }),
19
- }),
20
- outputSchema: Schema.Void,
21
- handler: Effect.fn(function* ({ data: { duration = 100_000 } }) {
22
- yield* Effect.sleep(duration);
23
- }),
24
- });
16
+ ),
17
+ );
@@ -7,9 +7,10 @@ import fs from 'node:fs';
7
7
  import { sleep } from '@dxos/async';
8
8
  import { Client, type Config } from '@dxos/client';
9
9
  import { type Space } from '@dxos/client/echo';
10
+ import { Context } from '@dxos/context';
10
11
  import { Filter, Obj, Query } from '@dxos/echo';
11
- import { Function } from '@dxos/functions';
12
12
  import { Trigger } from '@dxos/functions';
13
+ import { Operation } from '@dxos/operation';
13
14
  import { InvocationTraceEndEvent, InvocationTraceStartEvent } from '@dxos/functions-runtime';
14
15
  import { FunctionsServiceClient } from '@dxos/functions-runtime/edge';
15
16
  import { bundleFunction } from '@dxos/functions-runtime/native';
@@ -27,7 +28,7 @@ export const writeBundle = (path: string, bundle: BundleResult) => {
27
28
  export const setup = async (config: Config) => {
28
29
  const client = await new Client({
29
30
  config,
30
- types: [Function.Function, Trigger.Trigger],
31
+ types: [Operation.PersistentOperation, Trigger.Trigger],
31
32
  }).initialize();
32
33
  await client.halo.createIdentity();
33
34
 
@@ -41,7 +42,7 @@ export const setup = async (config: Config) => {
41
42
  };
42
43
 
43
44
  export const sync = async (space: Space) => {
44
- await space.db.flush({ indexes: true });
45
+ await space.db.flush();
45
46
  await space.internal.syncToEdge({
46
47
  onProgress: (state) =>
47
48
  console.log(state ? `${state.unsyncedDocumentCount} documents syncing...` : 'connecting to edge...'),
@@ -53,12 +54,12 @@ export const deployFunction = async (
53
54
  functionsServiceClient: FunctionsServiceClient,
54
55
  entryPoint: string,
55
56
  runtime: FunctionRuntimeKind,
56
- ) => {
57
+ ): Promise<Operation.PersistentOperation> => {
57
58
  const artifact = await bundleFunction({
58
59
  entryPoint,
59
60
  verbose: true,
60
61
  });
61
- const func = await functionsServiceClient.deploy({
62
+ const func = await functionsServiceClient.deploy(Context.default(), {
62
63
  version: '0.0.1',
63
64
  ownerPublicKey: space.key,
64
65
  entryPoint: artifact.entryPoint,