@dxos/functions 0.8.4-main.dedc0f3 → 0.8.4-main.e8ec1fe
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/dist/lib/browser/index.mjs +732 -1070
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +732 -1070
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/errors.d.ts +47 -55
- package/dist/types/src/errors.d.ts.map +1 -1
- package/dist/types/src/{examples → example}/fib.d.ts +1 -1
- package/dist/types/src/example/fib.d.ts.map +1 -0
- package/dist/types/src/example/forex-effect.d.ts +3 -0
- package/dist/types/src/example/forex-effect.d.ts.map +1 -0
- package/dist/types/src/example/index.d.ts +12 -0
- package/dist/types/src/example/index.d.ts.map +1 -0
- package/dist/types/src/{examples → example}/reply.d.ts +1 -1
- package/dist/types/src/example/reply.d.ts.map +1 -0
- package/dist/types/src/{examples → example}/sleep.d.ts +1 -1
- package/dist/types/src/example/sleep.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +4 -8
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/protocol/index.d.ts +2 -0
- package/dist/types/src/protocol/index.d.ts.map +1 -0
- package/dist/types/src/protocol/protocol.d.ts +7 -0
- package/dist/types/src/protocol/protocol.d.ts.map +1 -0
- package/dist/types/src/protocol/protocol.test.d.ts +2 -0
- package/dist/types/src/protocol/protocol.test.d.ts.map +1 -0
- package/dist/types/src/sdk.d.ts +89 -0
- package/dist/types/src/sdk.d.ts.map +1 -0
- package/dist/types/src/services/credentials.d.ts +7 -3
- package/dist/types/src/services/credentials.d.ts.map +1 -1
- package/dist/types/src/services/event-logger.d.ts +20 -5
- package/dist/types/src/services/event-logger.d.ts.map +1 -1
- package/dist/types/src/services/function-invocation-service.d.ts +11 -0
- package/dist/types/src/services/function-invocation-service.d.ts.map +1 -0
- package/dist/types/src/services/index.d.ts +6 -6
- package/dist/types/src/services/index.d.ts.map +1 -1
- package/dist/types/src/services/queues.d.ts +3 -1
- package/dist/types/src/services/queues.d.ts.map +1 -1
- package/dist/types/src/services/tracing.d.ts +9 -12
- package/dist/types/src/services/tracing.d.ts.map +1 -1
- package/dist/types/src/types/Function.d.ts +58 -0
- package/dist/types/src/types/Function.d.ts.map +1 -0
- package/dist/types/src/types/Script.d.ts +28 -0
- package/dist/types/src/types/Script.d.ts.map +1 -0
- package/dist/types/src/types/Trigger.d.ts +139 -0
- package/dist/types/src/types/Trigger.d.ts.map +1 -0
- package/dist/types/src/types/TriggerEvent.d.ts +44 -0
- package/dist/types/src/types/TriggerEvent.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +6 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/{url.d.ts → types/url.d.ts} +1 -10
- package/dist/types/src/types/url.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -70
- package/src/errors.ts +9 -9
- package/src/{examples → example}/fib.ts +5 -3
- package/src/example/forex-effect.ts +40 -0
- package/src/example/index.ts +13 -0
- package/src/{examples → example}/reply.ts +6 -3
- package/src/{examples → example}/sleep.ts +5 -3
- package/src/index.ts +4 -8
- package/src/{executor → protocol}/index.ts +1 -1
- package/src/protocol/protocol.test.ts +59 -0
- package/src/protocol/protocol.ts +145 -0
- package/src/sdk.ts +226 -0
- package/src/services/credentials.ts +12 -6
- package/src/services/event-logger.ts +12 -3
- package/src/services/function-invocation-service.ts +23 -0
- package/src/services/index.ts +7 -6
- package/src/services/queues.ts +3 -1
- package/src/services/tracing.ts +24 -56
- package/src/{schema.ts → types/Function.ts} +20 -26
- package/src/types/Script.ts +33 -0
- package/src/types/Trigger.ts +139 -0
- package/src/types/TriggerEvent.ts +62 -0
- package/src/types/index.ts +9 -0
- package/src/types/url.ts +31 -0
- package/dist/lib/browser/bundler/index.mjs +0 -265
- package/dist/lib/browser/bundler/index.mjs.map +0 -7
- package/dist/lib/browser/chunk-ANP3DFCO.mjs +0 -623
- package/dist/lib/browser/chunk-ANP3DFCO.mjs.map +0 -7
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/browser/edge/index.mjs +0 -83
- package/dist/lib/browser/edge/index.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -129
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/bundler/index.mjs +0 -266
- package/dist/lib/node-esm/bundler/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-MPKVY7ZR.mjs +0 -625
- package/dist/lib/node-esm/chunk-MPKVY7ZR.mjs.map +0 -7
- package/dist/lib/node-esm/edge/index.mjs +0 -84
- package/dist/lib/node-esm/edge/index.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -130
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/bundler/bundler.d.ts +0 -49
- package/dist/types/src/bundler/bundler.d.ts.map +0 -1
- package/dist/types/src/bundler/bundler.test.d.ts +0 -2
- package/dist/types/src/bundler/bundler.test.d.ts.map +0 -1
- package/dist/types/src/bundler/index.d.ts +0 -2
- package/dist/types/src/bundler/index.d.ts.map +0 -1
- package/dist/types/src/edge/functions.d.ts +0 -17
- package/dist/types/src/edge/functions.d.ts.map +0 -1
- package/dist/types/src/edge/index.d.ts +0 -2
- package/dist/types/src/edge/index.d.ts.map +0 -1
- package/dist/types/src/examples/fib.d.ts.map +0 -1
- package/dist/types/src/examples/index.d.ts +0 -4
- package/dist/types/src/examples/index.d.ts.map +0 -1
- package/dist/types/src/examples/reply.d.ts.map +0 -1
- package/dist/types/src/examples/sleep.d.ts.map +0 -1
- package/dist/types/src/executor/executor.d.ts +0 -11
- package/dist/types/src/executor/executor.d.ts.map +0 -1
- package/dist/types/src/executor/index.d.ts +0 -2
- package/dist/types/src/executor/index.d.ts.map +0 -1
- package/dist/types/src/handler.d.ts +0 -94
- package/dist/types/src/handler.d.ts.map +0 -1
- package/dist/types/src/schema.d.ts +0 -43
- package/dist/types/src/schema.d.ts.map +0 -1
- package/dist/types/src/services/database.d.ts +0 -98
- package/dist/types/src/services/database.d.ts.map +0 -1
- package/dist/types/src/services/local-function-execution.d.ts +0 -25
- package/dist/types/src/services/local-function-execution.d.ts.map +0 -1
- package/dist/types/src/services/remote-function-execution-service.d.ts +0 -15
- package/dist/types/src/services/remote-function-execution-service.d.ts.map +0 -1
- package/dist/types/src/services/service-container.d.ts +0 -56
- package/dist/types/src/services/service-container.d.ts.map +0 -1
- package/dist/types/src/services/service-registry.d.ts +0 -29
- package/dist/types/src/services/service-registry.d.ts.map +0 -1
- package/dist/types/src/services/service-registry.test.d.ts +0 -2
- package/dist/types/src/services/service-registry.test.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/layer.d.ts +0 -15
- package/dist/types/src/testing/layer.d.ts.map +0 -1
- package/dist/types/src/testing/logger.d.ts +0 -5
- package/dist/types/src/testing/logger.d.ts.map +0 -1
- package/dist/types/src/testing/persist-database.test.d.ts +0 -2
- package/dist/types/src/testing/persist-database.test.d.ts.map +0 -1
- package/dist/types/src/testing/services.d.ts +0 -59
- package/dist/types/src/testing/services.d.ts.map +0 -1
- package/dist/types/src/trace.d.ts +0 -122
- package/dist/types/src/trace.d.ts.map +0 -1
- package/dist/types/src/translations.d.ts +0 -12
- package/dist/types/src/translations.d.ts.map +0 -1
- package/dist/types/src/triggers/index.d.ts +0 -4
- package/dist/types/src/triggers/index.d.ts.map +0 -1
- package/dist/types/src/triggers/input-builder.d.ts +0 -3
- package/dist/types/src/triggers/input-builder.d.ts.map +0 -1
- package/dist/types/src/triggers/invocation-tracer.d.ts +0 -35
- package/dist/types/src/triggers/invocation-tracer.d.ts.map +0 -1
- package/dist/types/src/triggers/trigger-dispatcher.d.ts +0 -75
- package/dist/types/src/triggers/trigger-dispatcher.d.ts.map +0 -1
- package/dist/types/src/triggers/trigger-dispatcher.test.d.ts +0 -2
- package/dist/types/src/triggers/trigger-dispatcher.test.d.ts.map +0 -1
- package/dist/types/src/triggers/trigger-state-store.d.ts +0 -27
- package/dist/types/src/triggers/trigger-state-store.d.ts.map +0 -1
- package/dist/types/src/types.d.ts +0 -211
- package/dist/types/src/types.d.ts.map +0 -1
- package/dist/types/src/url.d.ts.map +0 -1
- package/src/bundler/bundler.test.ts +0 -58
- package/src/bundler/bundler.ts +0 -291
- package/src/bundler/index.ts +0 -5
- package/src/edge/functions.ts +0 -67
- package/src/edge/index.ts +0 -9
- package/src/examples/index.ts +0 -7
- package/src/executor/executor.ts +0 -54
- package/src/handler.ts +0 -201
- package/src/services/database.ts +0 -170
- package/src/services/local-function-execution.ts +0 -114
- package/src/services/remote-function-execution-service.ts +0 -46
- package/src/services/service-container.ts +0 -114
- package/src/services/service-registry.test.ts +0 -42
- package/src/services/service-registry.ts +0 -59
- package/src/testing/index.ts +0 -6
- package/src/testing/layer.ts +0 -111
- package/src/testing/logger.ts +0 -16
- package/src/testing/persist-database.test.ts +0 -87
- package/src/testing/services.ts +0 -115
- package/src/trace.ts +0 -178
- package/src/translations.ts +0 -20
- package/src/triggers/index.ts +0 -7
- package/src/triggers/input-builder.ts +0 -35
- package/src/triggers/invocation-tracer.ts +0 -99
- package/src/triggers/trigger-dispatcher.test.ts +0 -652
- package/src/triggers/trigger-dispatcher.ts +0 -512
- package/src/triggers/trigger-state-store.ts +0 -60
- package/src/types.ts +0 -200
- package/src/url.ts +0 -55
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/functions",
|
|
3
|
-
"version": "0.8.4-main.
|
|
4
|
-
"description": "Functions API
|
|
3
|
+
"version": "0.8.4-main.e8ec1fe",
|
|
4
|
+
"description": "Functions API.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
7
|
"license": "MIT",
|
|
@@ -14,83 +14,29 @@
|
|
|
14
14
|
"types": "./dist/types/src/index.d.ts",
|
|
15
15
|
"browser": "./dist/lib/browser/index.mjs",
|
|
16
16
|
"node": "./dist/lib/node-esm/index.mjs"
|
|
17
|
-
},
|
|
18
|
-
"./bundler": {
|
|
19
|
-
"source": "./src/bundler/index.ts",
|
|
20
|
-
"types": "./dist/types/src/bundler/index.d.ts",
|
|
21
|
-
"browser": "./dist/lib/browser/bundler/index.mjs",
|
|
22
|
-
"node": "./dist/lib/node-esm/bundler/index.mjs"
|
|
23
|
-
},
|
|
24
|
-
"./edge": {
|
|
25
|
-
"source": "./src/edge/index.ts",
|
|
26
|
-
"types": "./dist/types/src/edge/index.d.ts",
|
|
27
|
-
"browser": "./dist/lib/browser/edge/index.mjs",
|
|
28
|
-
"node": "./dist/lib/node-esm/edge/index.mjs"
|
|
29
|
-
},
|
|
30
|
-
"./testing": {
|
|
31
|
-
"source": "./src/testing/index.ts",
|
|
32
|
-
"types": "./dist/types/src/testing/index.d.ts",
|
|
33
|
-
"browser": "./dist/lib/browser/testing/index.mjs",
|
|
34
|
-
"node": "./dist/lib/node-esm/testing/index.mjs"
|
|
35
17
|
}
|
|
36
18
|
},
|
|
37
19
|
"types": "dist/types/src/index.d.ts",
|
|
38
|
-
"typesVersions": {
|
|
39
|
-
"*": {
|
|
40
|
-
"bundler": [
|
|
41
|
-
"dist/types/src/bundler/index.d.ts"
|
|
42
|
-
],
|
|
43
|
-
"edge": [
|
|
44
|
-
"dist/types/src/edge/index.d.ts"
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
20
|
"files": [
|
|
49
21
|
"dist",
|
|
50
22
|
"schema",
|
|
51
23
|
"src"
|
|
52
24
|
],
|
|
53
25
|
"dependencies": {
|
|
54
|
-
"@effect/platform": "0.
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"effect": "
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"@dxos/
|
|
66
|
-
"@dxos/
|
|
67
|
-
"@dxos/
|
|
68
|
-
"@dxos/client": "0.8.4-main.dedc0f3",
|
|
69
|
-
"@dxos/client-protocol": "0.8.4-main.dedc0f3",
|
|
70
|
-
"@dxos/crypto": "0.8.4-main.dedc0f3",
|
|
71
|
-
"@dxos/debug": "0.8.4-main.dedc0f3",
|
|
72
|
-
"@dxos/echo-db": "0.8.4-main.dedc0f3",
|
|
73
|
-
"@dxos/echo": "0.8.4-main.dedc0f3",
|
|
74
|
-
"@dxos/echo-pipeline": "0.8.4-main.dedc0f3",
|
|
75
|
-
"@dxos/echo-protocol": "0.8.4-main.dedc0f3",
|
|
76
|
-
"@dxos/echo-schema": "0.8.4-main.dedc0f3",
|
|
77
|
-
"@dxos/edge-client": "0.8.4-main.dedc0f3",
|
|
78
|
-
"@dxos/invariant": "0.8.4-main.dedc0f3",
|
|
79
|
-
"@dxos/effect": "0.8.4-main.dedc0f3",
|
|
80
|
-
"@dxos/errors": "0.8.4-main.dedc0f3",
|
|
81
|
-
"@dxos/keys": "0.8.4-main.dedc0f3",
|
|
82
|
-
"@dxos/kv-store": "0.8.4-main.dedc0f3",
|
|
83
|
-
"@dxos/live-object": "0.8.4-main.dedc0f3",
|
|
84
|
-
"@dxos/log": "0.8.4-main.dedc0f3",
|
|
85
|
-
"@dxos/node-std": "0.8.4-main.dedc0f3",
|
|
86
|
-
"@dxos/protocols": "0.8.4-main.dedc0f3",
|
|
87
|
-
"@dxos/util": "0.8.4-main.dedc0f3",
|
|
88
|
-
"@dxos/schema": "0.8.4-main.dedc0f3"
|
|
89
|
-
},
|
|
90
|
-
"devDependencies": {
|
|
91
|
-
"@types/express": "^4.17.17",
|
|
92
|
-
"@types/ws": "^7.4.0",
|
|
93
|
-
"@dxos/agent": "0.8.4-main.dedc0f3"
|
|
26
|
+
"@effect/platform": "0.92.1",
|
|
27
|
+
"effect": "3.18.3",
|
|
28
|
+
"@dxos/ai": "0.8.4-main.e8ec1fe",
|
|
29
|
+
"@dxos/echo-db": "0.8.4-main.e8ec1fe",
|
|
30
|
+
"@dxos/effect": "0.8.4-main.e8ec1fe",
|
|
31
|
+
"@dxos/errors": "0.8.4-main.e8ec1fe",
|
|
32
|
+
"@dxos/invariant": "0.8.4-main.e8ec1fe",
|
|
33
|
+
"@dxos/echo": "0.8.4-main.e8ec1fe",
|
|
34
|
+
"@dxos/keys": "0.8.4-main.e8ec1fe",
|
|
35
|
+
"@dxos/node-std": "0.8.4-main.e8ec1fe",
|
|
36
|
+
"@dxos/log": "0.8.4-main.e8ec1fe",
|
|
37
|
+
"@dxos/schema": "0.8.4-main.e8ec1fe",
|
|
38
|
+
"@dxos/types": "0.8.4-main.e8ec1fe",
|
|
39
|
+
"@dxos/protocols": "0.8.4-main.e8ec1fe"
|
|
94
40
|
},
|
|
95
41
|
"publishConfig": {
|
|
96
42
|
"access": "public"
|
package/src/errors.ts
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { BaseError } from '@dxos/errors';
|
|
5
|
+
import { BaseError, type BaseErrorOptions } from '@dxos/errors';
|
|
6
6
|
|
|
7
|
-
export class ServiceNotAvailableError extends BaseError.extend('SERVICE_NOT_AVAILABLE') {
|
|
8
|
-
constructor(
|
|
9
|
-
super(
|
|
7
|
+
export class ServiceNotAvailableError extends BaseError.extend('SERVICE_NOT_AVAILABLE', 'Service not available') {
|
|
8
|
+
constructor(service: string, options?: Omit<BaseErrorOptions, 'context'>) {
|
|
9
|
+
super({ context: { service }, ...options });
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export class FunctionNotFoundError extends BaseError.extend('FUNCTION_NOT_FOUND') {
|
|
14
|
-
constructor(functionKey: string) {
|
|
15
|
-
super(
|
|
13
|
+
export class FunctionNotFoundError extends BaseError.extend('FUNCTION_NOT_FOUND', 'Function not found') {
|
|
14
|
+
constructor(functionKey: string, options?: Omit<BaseErrorOptions, 'context'>) {
|
|
15
|
+
super({ context: { function: functionKey }, ...options });
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export class FunctionError extends BaseError.extend('FUNCTION_ERROR') {}
|
|
19
|
+
export class FunctionError extends BaseError.extend('FUNCTION_ERROR', 'Function invocation error') {}
|
|
20
20
|
|
|
21
|
-
export class TriggerStateNotFoundError extends BaseError.extend('TRIGGER_STATE_NOT_FOUND') {}
|
|
21
|
+
export class TriggerStateNotFoundError extends BaseError.extend('TRIGGER_STATE_NOT_FOUND', 'Trigger state not found') {}
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
6
7
|
|
|
7
|
-
import { defineFunction } from '../
|
|
8
|
+
import { defineFunction } from '../sdk';
|
|
8
9
|
|
|
9
10
|
export default defineFunction({
|
|
10
|
-
|
|
11
|
+
key: 'example.org/function/fib',
|
|
12
|
+
name: 'Fibonacci',
|
|
11
13
|
description: 'Function that calculates a Fibonacci number',
|
|
12
14
|
inputSchema: Schema.Struct({
|
|
13
15
|
iterations: Schema.optional(Schema.Number).annotations({
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
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 { Effect, Schedule } from 'https://esm.sh/effect@3.17.0?bundle=false';
|
|
15
|
+
|
|
16
|
+
export default defineFunction({
|
|
17
|
+
key: 'dxos.org/script/forex-effect',
|
|
18
|
+
name: 'Forex Effect',
|
|
19
|
+
description: 'Returns the exchange rate between two currencies.',
|
|
20
|
+
|
|
21
|
+
inputSchema: S.Struct({
|
|
22
|
+
from: S.String.annotations({ description: 'The source currency' }),
|
|
23
|
+
to: S.String.annotations({ description: 'The target currency' }),
|
|
24
|
+
}),
|
|
25
|
+
|
|
26
|
+
outputSchema: S.String.annotations({ description: 'The exchange rate between the two currencies' }),
|
|
27
|
+
|
|
28
|
+
handler: async ({ data: { from, to } }: any) =>
|
|
29
|
+
Effect.gen(function* () {
|
|
30
|
+
const res = yield* HttpClientRequest.get(`https://free.ratesdb.com/v1/rates?from=${from}&to=${to}`).pipe(
|
|
31
|
+
HttpClient.execute,
|
|
32
|
+
Effect.flatMap((res: any) => res.json),
|
|
33
|
+
Effect.timeout('1 second'),
|
|
34
|
+
Effect.retry(Schedule.exponential(1_000).pipe(Schedule.compose(Schedule.recurs(3)))),
|
|
35
|
+
Effect.scoped,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return res.data.rates[to].toString();
|
|
39
|
+
}).pipe(Effect.provide(FetchHttpClient.layer)),
|
|
40
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { default as fib$ } from './fib';
|
|
6
|
+
import { default as reply$ } from './reply';
|
|
7
|
+
import { default as sleep$ } from './sleep';
|
|
8
|
+
|
|
9
|
+
export namespace Example {
|
|
10
|
+
export const fib = fib$;
|
|
11
|
+
export const reply = reply$;
|
|
12
|
+
export const sleep = sleep$;
|
|
13
|
+
}
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Console from 'effect/Console';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
import * as Schema from 'effect/Schema';
|
|
6
8
|
|
|
7
|
-
import { defineFunction } from '../
|
|
9
|
+
import { defineFunction } from '../sdk';
|
|
8
10
|
|
|
9
11
|
export default defineFunction({
|
|
10
|
-
|
|
12
|
+
key: 'example.org/function/reply',
|
|
13
|
+
name: 'Reply',
|
|
11
14
|
description: 'Function that echoes the input',
|
|
12
15
|
inputSchema: Schema.Any,
|
|
13
16
|
outputSchema: Schema.Any,
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
6
7
|
|
|
7
|
-
import { defineFunction } from '../
|
|
8
|
+
import { defineFunction } from '../sdk';
|
|
8
9
|
|
|
9
10
|
export default defineFunction({
|
|
10
|
-
|
|
11
|
+
key: 'example.org/function/sleep',
|
|
12
|
+
name: 'Sleep',
|
|
11
13
|
description: 'Function that sleeps for a given amount of time',
|
|
12
14
|
inputSchema: Schema.Struct({
|
|
13
15
|
duration: Schema.optional(Schema.Number).annotations({
|
package/src/index.ts
CHANGED
|
@@ -3,12 +3,8 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
export * from './errors';
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './trace';
|
|
9
|
-
export * from './types';
|
|
10
|
-
export * from './url';
|
|
11
|
-
export * from './triggers';
|
|
6
|
+
export * from './example';
|
|
7
|
+
export * from './sdk';
|
|
12
8
|
export * from './services';
|
|
13
|
-
export * from './
|
|
14
|
-
export *
|
|
9
|
+
export * from './types';
|
|
10
|
+
export * from './protocol';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { FunctionError } from '../errors';
|
|
8
|
+
import fibFunc from '../example/fib';
|
|
9
|
+
import replyFunc from '../example/reply';
|
|
10
|
+
|
|
11
|
+
import { wrapFunctionHandler } from './protocol';
|
|
12
|
+
|
|
13
|
+
describe('wrapFunctionHandler', () => {
|
|
14
|
+
test('wraps reply function and executes handler', async ({ expect }) => {
|
|
15
|
+
const wrapped = wrapFunctionHandler(replyFunc);
|
|
16
|
+
|
|
17
|
+
expect(wrapped.meta.key).toBe('example.org/function/reply');
|
|
18
|
+
expect(wrapped.meta.name).toBe('Reply');
|
|
19
|
+
|
|
20
|
+
const testData = { message: 'hello' };
|
|
21
|
+
const result = await wrapped.handler({
|
|
22
|
+
data: testData,
|
|
23
|
+
context: {
|
|
24
|
+
services: {},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(result).toEqual(testData);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('wraps fibonacci function with valid input', async ({ expect }) => {
|
|
32
|
+
const wrapped = wrapFunctionHandler(fibFunc);
|
|
33
|
+
|
|
34
|
+
expect(wrapped.meta.key).toBe('example.org/function/fib');
|
|
35
|
+
expect(wrapped.meta.name).toBe('Fibonacci');
|
|
36
|
+
|
|
37
|
+
const result = await wrapped.handler({
|
|
38
|
+
data: { iterations: 10 },
|
|
39
|
+
context: {
|
|
40
|
+
services: {},
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(result).toEqual({ result: '55' });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('throws FunctionError on invalid input schema for fibonacci', async ({ expect }) => {
|
|
48
|
+
const wrapped = wrapFunctionHandler(fibFunc);
|
|
49
|
+
|
|
50
|
+
await expect(
|
|
51
|
+
wrapped.handler({
|
|
52
|
+
data: { iterations: 'invalid' },
|
|
53
|
+
context: {
|
|
54
|
+
services: {},
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
).rejects.toThrow(FunctionError);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
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 Schema from 'effect/Schema';
|
|
8
|
+
import * as SchemaAST from 'effect/SchemaAST';
|
|
9
|
+
|
|
10
|
+
import { AiService } from '@dxos/ai';
|
|
11
|
+
import { Type } from '@dxos/echo';
|
|
12
|
+
import { EchoClient } from '@dxos/echo-db';
|
|
13
|
+
import { acquireReleaseResource } from '@dxos/effect';
|
|
14
|
+
import { failedInvariant, invariant } from '@dxos/invariant';
|
|
15
|
+
import { PublicKey } from '@dxos/keys';
|
|
16
|
+
import { type FunctionProtocol } from '@dxos/protocols';
|
|
17
|
+
|
|
18
|
+
import { FunctionError } from '../errors';
|
|
19
|
+
import { FunctionDefinition, type FunctionServices } from '../sdk';
|
|
20
|
+
import { CredentialsService, DatabaseService, FunctionInvocationService, TracingService } from '../services';
|
|
21
|
+
import { QueueService } from '../services';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Wraps a function handler made with `defineFunction` to a protocol that the functions-runtime expects.
|
|
25
|
+
*/
|
|
26
|
+
export const wrapFunctionHandler = (func: FunctionDefinition): FunctionProtocol.Func => {
|
|
27
|
+
if (!FunctionDefinition.isFunction(func)) {
|
|
28
|
+
throw new TypeError('Invalid function definition');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
meta: {
|
|
33
|
+
key: func.key,
|
|
34
|
+
name: func.name,
|
|
35
|
+
description: func.description,
|
|
36
|
+
inputSchema: Type.toJsonSchema(func.inputSchema),
|
|
37
|
+
outputSchema: func.outputSchema === undefined ? undefined : Type.toJsonSchema(func.outputSchema),
|
|
38
|
+
services: func.services,
|
|
39
|
+
},
|
|
40
|
+
handler: async ({ data, context }) => {
|
|
41
|
+
if (
|
|
42
|
+
(func.services.includes(DatabaseService.key) || func.services.includes(QueueService.key)) &&
|
|
43
|
+
(!context.services.dataService || !context.services.queryService)
|
|
44
|
+
) {
|
|
45
|
+
throw new FunctionError({
|
|
46
|
+
message: 'Services not provided: dataService, queryService',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
if (!SchemaAST.isAnyKeyword(func.inputSchema.ast)) {
|
|
52
|
+
Schema.validateSync(func.inputSchema)(data);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let result = await func.handler({
|
|
56
|
+
// TODO(dmaretskyi): Fix the types.
|
|
57
|
+
context: context as any,
|
|
58
|
+
data,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (Effect.isEffect(result)) {
|
|
62
|
+
result = await Effect.runPromise(
|
|
63
|
+
(result as Effect.Effect<unknown, unknown, FunctionServices>).pipe(
|
|
64
|
+
Effect.orDie,
|
|
65
|
+
Effect.provide(createServiceLayer(context)),
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (func.outputSchema && !SchemaAST.isAnyKeyword(func.outputSchema.ast)) {
|
|
71
|
+
Schema.validateSync(func.outputSchema)(result);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return result;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (FunctionError.is(error)) {
|
|
77
|
+
throw error;
|
|
78
|
+
} else {
|
|
79
|
+
throw new FunctionError({
|
|
80
|
+
cause: error,
|
|
81
|
+
context: { func: func.key },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Creates a layer of services for the function.
|
|
91
|
+
*/
|
|
92
|
+
const createServiceLayer = (context: FunctionProtocol.Context): Layer.Layer<FunctionServices> => {
|
|
93
|
+
return Layer.unwrapScoped(
|
|
94
|
+
Effect.gen(function* () {
|
|
95
|
+
let client: EchoClient | undefined;
|
|
96
|
+
|
|
97
|
+
if (context.services.dataService && context.services.queryService) {
|
|
98
|
+
client = yield* acquireReleaseResource(() => {
|
|
99
|
+
invariant(context.services.dataService && context.services.queryService);
|
|
100
|
+
// TODO(dmaretskyi): Queues service.
|
|
101
|
+
return new EchoClient().connectToService({
|
|
102
|
+
dataService: context.services.dataService,
|
|
103
|
+
queryService: context.services.queryService,
|
|
104
|
+
queueService: context.services.queueService,
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const db =
|
|
110
|
+
client && context.spaceId
|
|
111
|
+
? yield* acquireReleaseResource(() =>
|
|
112
|
+
client.constructDatabase({
|
|
113
|
+
spaceId: context.spaceId ?? failedInvariant(),
|
|
114
|
+
spaceKey: PublicKey.fromHex(context.spaceKey ?? failedInvariant('spaceKey missing in context')),
|
|
115
|
+
reactiveSchemaQuery: false,
|
|
116
|
+
}),
|
|
117
|
+
)
|
|
118
|
+
: undefined;
|
|
119
|
+
|
|
120
|
+
if (db) {
|
|
121
|
+
console.log('Setting space root', context.spaceRootUrl);
|
|
122
|
+
yield* Effect.promise(() =>
|
|
123
|
+
db!.setSpaceRoot(context.spaceRootUrl ?? failedInvariant('spaceRootUrl missing in context')),
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const queues = client && context.spaceId ? client.constructQueueFactory(context.spaceId) : undefined;
|
|
128
|
+
|
|
129
|
+
const dbLayer = db ? DatabaseService.layer(db) : DatabaseService.notAvailable;
|
|
130
|
+
const queuesLayer = queues ? QueueService.layer(queues) : QueueService.notAvailable;
|
|
131
|
+
const credentials = dbLayer
|
|
132
|
+
? CredentialsService.layerFromDatabase().pipe(Layer.provide(dbLayer))
|
|
133
|
+
: CredentialsService.configuredLayer([]);
|
|
134
|
+
const functionInvocationService = MockedFunctionInvocationService;
|
|
135
|
+
const aiService = AiService.notAvailable;
|
|
136
|
+
const tracing = TracingService.layerNoop;
|
|
137
|
+
|
|
138
|
+
return Layer.mergeAll(dbLayer, queuesLayer, credentials, functionInvocationService, aiService, tracing);
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const MockedFunctionInvocationService = Layer.succeed(FunctionInvocationService, {
|
|
144
|
+
invokeFunction: () => Effect.die('Calling functions from functions is not implemented yet.'),
|
|
145
|
+
});
|