@dxos/functions 0.8.3 → 0.8.4-main.1da679c
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/bundler/index.mjs +73 -44
- package/dist/lib/browser/bundler/index.mjs.map +3 -3
- package/dist/lib/browser/chunk-D2XO7XXY.mjs +611 -0
- package/dist/lib/browser/chunk-D2XO7XXY.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/edge/index.mjs +24 -10
- package/dist/lib/browser/edge/index.mjs.map +3 -3
- package/dist/lib/browser/index.mjs +981 -137
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +110 -9
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/bundler/index.mjs +72 -44
- package/dist/lib/node-esm/bundler/index.mjs.map +3 -3
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-Z4CJ62WS.mjs +613 -0
- package/dist/lib/node-esm/chunk-Z4CJ62WS.mjs.map +7 -0
- package/dist/lib/node-esm/edge/index.mjs +23 -10
- package/dist/lib/node-esm/edge/index.mjs.map +3 -3
- package/dist/lib/node-esm/index.mjs +981 -137
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +110 -9
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/bundler/bundler.d.ts +12 -14
- package/dist/types/src/bundler/bundler.d.ts.map +1 -1
- package/dist/types/src/edge/functions.d.ts +4 -3
- package/dist/types/src/edge/functions.d.ts.map +1 -1
- package/dist/types/src/errors.d.ts +137 -0
- package/dist/types/src/errors.d.ts.map +1 -0
- package/dist/types/src/examples/fib.d.ts +7 -0
- package/dist/types/src/examples/fib.d.ts.map +1 -0
- package/dist/types/src/examples/index.d.ts +4 -0
- package/dist/types/src/examples/index.d.ts.map +1 -0
- package/dist/types/src/examples/reply.d.ts +3 -0
- package/dist/types/src/examples/reply.d.ts.map +1 -0
- package/dist/types/src/examples/sleep.d.ts +5 -0
- package/dist/types/src/examples/sleep.d.ts.map +1 -0
- package/dist/types/src/executor/executor.d.ts +4 -1
- package/dist/types/src/executor/executor.d.ts.map +1 -1
- package/dist/types/src/handler.d.ts +46 -16
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/schema.d.ts +8 -3
- package/dist/types/src/schema.d.ts.map +1 -1
- package/dist/types/src/services/credentials.d.ts +18 -4
- package/dist/types/src/services/credentials.d.ts.map +1 -1
- package/dist/types/src/services/database.d.ts +55 -3
- package/dist/types/src/services/database.d.ts.map +1 -1
- package/dist/types/src/services/event-logger.d.ts +65 -30
- package/dist/types/src/services/event-logger.d.ts.map +1 -1
- package/dist/types/src/services/index.d.ts +2 -2
- package/dist/types/src/services/index.d.ts.map +1 -1
- package/dist/types/src/services/local-function-execution.d.ts +25 -0
- package/dist/types/src/services/local-function-execution.d.ts.map +1 -0
- package/dist/types/src/services/queues.d.ts +33 -6
- package/dist/types/src/services/queues.d.ts.map +1 -1
- package/dist/types/src/services/remote-function-execution-service.d.ts +15 -0
- package/dist/types/src/services/remote-function-execution-service.d.ts.map +1 -0
- package/dist/types/src/services/service-container.d.ts +29 -17
- package/dist/types/src/services/service-container.d.ts.map +1 -1
- package/dist/types/src/services/service-registry.d.ts +29 -0
- package/dist/types/src/services/service-registry.d.ts.map +1 -0
- package/dist/types/src/services/service-registry.test.d.ts +2 -0
- package/dist/types/src/services/service-registry.test.d.ts.map +1 -0
- package/dist/types/src/services/tracing.d.ts +46 -4
- package/dist/types/src/services/tracing.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/layer.d.ts +15 -0
- package/dist/types/src/testing/layer.d.ts.map +1 -0
- package/dist/types/src/testing/logger.d.ts +3 -3
- package/dist/types/src/testing/logger.d.ts.map +1 -1
- package/dist/types/src/testing/persist-database.test.d.ts +2 -0
- package/dist/types/src/testing/persist-database.test.d.ts.map +1 -0
- package/dist/types/src/testing/services.d.ts +55 -9
- package/dist/types/src/testing/services.d.ts.map +1 -1
- package/dist/types/src/trace.d.ts +20 -22
- package/dist/types/src/trace.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +9 -9
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/triggers/index.d.ts +4 -0
- package/dist/types/src/triggers/index.d.ts.map +1 -0
- package/dist/types/src/triggers/input-builder.d.ts +3 -0
- package/dist/types/src/triggers/input-builder.d.ts.map +1 -0
- package/dist/types/src/triggers/invocation-tracer.d.ts +35 -0
- package/dist/types/src/triggers/invocation-tracer.d.ts.map +1 -0
- package/dist/types/src/triggers/trigger-dispatcher.d.ts +75 -0
- package/dist/types/src/triggers/trigger-dispatcher.d.ts.map +1 -0
- package/dist/types/src/triggers/trigger-dispatcher.test.d.ts +2 -0
- package/dist/types/src/triggers/trigger-dispatcher.test.d.ts.map +1 -0
- package/dist/types/src/triggers/trigger-state-store.d.ts +27 -0
- package/dist/types/src/triggers/trigger-state-store.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +55 -245
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/url.d.ts +10 -6
- package/dist/types/src/url.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -25
- package/src/bundler/bundler.test.ts +9 -10
- package/src/bundler/bundler.ts +56 -35
- package/src/edge/functions.ts +9 -6
- package/src/errors.ts +21 -0
- package/src/examples/fib.ts +30 -0
- package/src/examples/index.ts +7 -0
- package/src/examples/reply.ts +18 -0
- package/src/examples/sleep.ts +22 -0
- package/src/executor/executor.ts +22 -15
- package/src/handler.ts +117 -27
- package/src/index.ts +3 -2
- package/src/schema.ts +11 -0
- package/src/services/credentials.ts +87 -5
- package/src/services/database.ts +146 -3
- package/src/services/event-logger.ts +68 -37
- package/src/services/index.ts +2 -2
- package/src/services/local-function-execution.ts +127 -0
- package/src/services/queues.ts +56 -11
- package/src/services/remote-function-execution-service.ts +46 -0
- package/src/services/service-container.ts +47 -42
- package/src/services/service-registry.test.ts +42 -0
- package/src/services/service-registry.ts +59 -0
- package/src/services/tracing.ts +118 -5
- package/src/testing/index.ts +1 -0
- package/src/testing/layer.ts +111 -0
- package/src/testing/logger.ts +4 -4
- package/src/testing/persist-database.test.ts +87 -0
- package/src/testing/services.ts +97 -14
- package/src/trace.ts +17 -19
- package/src/translations.ts +4 -4
- package/src/triggers/index.ts +7 -0
- package/src/triggers/input-builder.ts +35 -0
- package/src/triggers/invocation-tracer.ts +99 -0
- package/src/triggers/trigger-dispatcher.test.ts +652 -0
- package/src/triggers/trigger-dispatcher.ts +516 -0
- package/src/triggers/trigger-state-store.ts +60 -0
- package/src/types.ts +39 -36
- package/src/url.ts +13 -10
- package/dist/lib/browser/chunk-WEFZUEL2.mjs +0 -300
- package/dist/lib/browser/chunk-WEFZUEL2.mjs.map +0 -7
- package/dist/lib/node/bundler/index.cjs +0 -260
- package/dist/lib/node/bundler/index.cjs.map +0 -7
- package/dist/lib/node/chunk-IJAE7FZK.cjs +0 -320
- package/dist/lib/node/chunk-IJAE7FZK.cjs.map +0 -7
- package/dist/lib/node/edge/index.cjs +0 -94
- package/dist/lib/node/edge/index.cjs.map +0 -7
- package/dist/lib/node/index.cjs +0 -522
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/lib/node/testing/index.cjs +0 -43
- package/dist/lib/node/testing/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-LIYPMWNQ.mjs +0 -302
- package/dist/lib/node-esm/chunk-LIYPMWNQ.mjs.map +0 -7
- package/dist/types/src/services/ai.d.ts +0 -12
- package/dist/types/src/services/ai.d.ts.map +0 -1
- package/dist/types/src/services/function-call-service.d.ts +0 -16
- package/dist/types/src/services/function-call-service.d.ts.map +0 -1
- package/src/services/ai.ts +0 -32
- package/src/services/function-call-service.ts +0 -64
|
@@ -1,47 +1,74 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
ComputeEvent,
|
|
3
|
+
ComputeEventLogger,
|
|
4
|
+
ComputeEventPayload,
|
|
3
5
|
ConfiguredCredentialsService,
|
|
6
|
+
ContextQueueService,
|
|
4
7
|
CredentialsService,
|
|
5
8
|
DatabaseService,
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
FUNCTIONS_META_KEY,
|
|
10
|
+
FUNCTIONS_PRESET_META_KEY,
|
|
11
|
+
MESSAGE_PROPERTY_TOOL_CALL_ID,
|
|
8
12
|
QueueService,
|
|
13
|
+
RemoteFunctionExecutionService,
|
|
9
14
|
SERVICE_TAGS,
|
|
10
15
|
ServiceContainer,
|
|
11
16
|
TracingService,
|
|
12
17
|
createDefectLogger,
|
|
13
18
|
createEventLogger,
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
getInvocationUrl,
|
|
20
|
+
getUserFunctionIdInMetadata,
|
|
21
|
+
logCustomEvent,
|
|
22
|
+
setUserFunctionIdInMetadata,
|
|
23
|
+
withAuthorization
|
|
24
|
+
} from "./chunk-D2XO7XXY.mjs";
|
|
25
|
+
import {
|
|
26
|
+
__export
|
|
27
|
+
} from "./chunk-J5LGTIGS.mjs";
|
|
16
28
|
|
|
17
|
-
//
|
|
18
|
-
import {
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
// src/errors.ts
|
|
30
|
+
import { BaseError } from "@dxos/errors";
|
|
31
|
+
var ServiceNotAvailableError = class extends BaseError.extend("SERVICE_NOT_AVAILABLE", "Service not available") {
|
|
32
|
+
constructor(service, options) {
|
|
33
|
+
super({
|
|
34
|
+
context: {
|
|
35
|
+
service
|
|
36
|
+
},
|
|
37
|
+
...options
|
|
38
|
+
});
|
|
22
39
|
}
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
};
|
|
41
|
+
var FunctionNotFoundError = class extends BaseError.extend("FUNCTION_NOT_FOUND", "Function not found") {
|
|
42
|
+
constructor(functionKey, options) {
|
|
43
|
+
super({
|
|
44
|
+
context: {
|
|
45
|
+
function: functionKey
|
|
46
|
+
},
|
|
47
|
+
...options
|
|
48
|
+
});
|
|
25
49
|
}
|
|
26
|
-
return {
|
|
27
|
-
description: params.description,
|
|
28
|
-
inputSchema: params.inputSchema,
|
|
29
|
-
outputSchema: params.outputSchema ?? Schema.Any,
|
|
30
|
-
handler: params.handler
|
|
31
|
-
};
|
|
32
50
|
};
|
|
51
|
+
var FunctionError = class extends BaseError.extend("FUNCTION_ERROR", "Function invocation error") {
|
|
52
|
+
};
|
|
53
|
+
var TriggerStateNotFoundError = class extends BaseError.extend("TRIGGER_STATE_NOT_FOUND", "Trigger state not found") {
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// src/handler.ts
|
|
57
|
+
import { Effect, Schema as Schema2 } from "effect";
|
|
58
|
+
import { Obj, Type as Type2 } from "@dxos/echo";
|
|
59
|
+
import { assertArgument } from "@dxos/invariant";
|
|
33
60
|
|
|
34
|
-
//
|
|
35
|
-
import { Schema
|
|
61
|
+
// src/schema.ts
|
|
62
|
+
import { Schema } from "effect";
|
|
36
63
|
import { Type } from "@dxos/echo";
|
|
37
64
|
import { JsonSchemaType, LabelAnnotation, Ref } from "@dxos/echo-schema";
|
|
38
65
|
import { DataType } from "@dxos/schema";
|
|
39
|
-
var ScriptType =
|
|
40
|
-
name:
|
|
41
|
-
description:
|
|
66
|
+
var ScriptType = Schema.Struct({
|
|
67
|
+
name: Schema.optional(Schema.String),
|
|
68
|
+
description: Schema.optional(Schema.String),
|
|
42
69
|
// TODO(burdon): Change to hash of deployed content.
|
|
43
70
|
// Whether source has changed since last deploy.
|
|
44
|
-
changed:
|
|
71
|
+
changed: Schema.optional(Schema.Boolean),
|
|
45
72
|
source: Ref(DataType.Text)
|
|
46
73
|
}).pipe(Type.Obj({
|
|
47
74
|
typename: "dxos.org/type/Script",
|
|
@@ -49,18 +76,28 @@ var ScriptType = Schema2.Struct({
|
|
|
49
76
|
}), LabelAnnotation.set([
|
|
50
77
|
"name"
|
|
51
78
|
]));
|
|
52
|
-
var FunctionType =
|
|
79
|
+
var FunctionType = Schema.Struct({
|
|
80
|
+
/**
|
|
81
|
+
* Global registry ID.
|
|
82
|
+
* NOTE: The `key` property refers to the original registry entry.
|
|
83
|
+
*/
|
|
84
|
+
// TODO(burdon): Create Format type for DXN-like ids, such as this and schema type.
|
|
85
|
+
// TODO(dmaretskyi): Consider making it part of ECHO meta.
|
|
86
|
+
// TODO(dmaretskyi): Make required.
|
|
87
|
+
key: Schema.optional(Schema.String).annotations({
|
|
88
|
+
description: "Unique registration key for the blueprint"
|
|
89
|
+
}),
|
|
53
90
|
// TODO(burdon): Rename to id/uri?
|
|
54
|
-
name:
|
|
55
|
-
version:
|
|
56
|
-
description:
|
|
91
|
+
name: Schema.NonEmptyString,
|
|
92
|
+
version: Schema.String,
|
|
93
|
+
description: Schema.optional(Schema.String),
|
|
57
94
|
// Reference to a source script if it exists within ECHO.
|
|
58
95
|
// TODO(burdon): Don't ref ScriptType directly (core).
|
|
59
|
-
source:
|
|
60
|
-
inputSchema:
|
|
61
|
-
outputSchema:
|
|
96
|
+
source: Schema.optional(Ref(ScriptType)),
|
|
97
|
+
inputSchema: Schema.optional(JsonSchemaType),
|
|
98
|
+
outputSchema: Schema.optional(JsonSchemaType),
|
|
62
99
|
// Local binding to a function name.
|
|
63
|
-
binding:
|
|
100
|
+
binding: Schema.optional(Schema.String)
|
|
64
101
|
}).pipe(Type.Obj({
|
|
65
102
|
typename: "dxos.org/type/Function",
|
|
66
103
|
version: "0.1.0"
|
|
@@ -68,25 +105,107 @@ var FunctionType = Schema2.Struct({
|
|
|
68
105
|
"name"
|
|
69
106
|
]));
|
|
70
107
|
|
|
71
|
-
//
|
|
108
|
+
// src/handler.ts
|
|
109
|
+
var typeId = Symbol.for("@dxos/functions/FunctionDefinition");
|
|
110
|
+
var defineFunction = ({ key, name, description, inputSchema, outputSchema = Schema2.Any, handler }) => {
|
|
111
|
+
if (!Schema2.isSchema(inputSchema)) {
|
|
112
|
+
throw new Error("Input schema must be a valid schema");
|
|
113
|
+
}
|
|
114
|
+
if (typeof handler !== "function") {
|
|
115
|
+
throw new Error("Handler must be a function");
|
|
116
|
+
}
|
|
117
|
+
const limit = Error.stackTraceLimit;
|
|
118
|
+
Error.stackTraceLimit = 2;
|
|
119
|
+
const traceError = new Error();
|
|
120
|
+
Error.stackTraceLimit = limit;
|
|
121
|
+
let cache = false;
|
|
122
|
+
const captureStackTrace = () => {
|
|
123
|
+
if (cache !== false) {
|
|
124
|
+
return cache;
|
|
125
|
+
}
|
|
126
|
+
if (traceError.stack !== void 0) {
|
|
127
|
+
const stack = traceError.stack.split("\n");
|
|
128
|
+
if (stack[2] !== void 0) {
|
|
129
|
+
cache = stack[2].trim();
|
|
130
|
+
return cache;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const handlerWithSpan = (...args) => {
|
|
135
|
+
const result = handler(...args);
|
|
136
|
+
if (Effect.isEffect(result)) {
|
|
137
|
+
return Effect.withSpan(result, `${key ?? name}`, {
|
|
138
|
+
captureStackTrace
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
142
|
+
};
|
|
143
|
+
return {
|
|
144
|
+
[typeId]: true,
|
|
145
|
+
key: key ?? name,
|
|
146
|
+
name,
|
|
147
|
+
description,
|
|
148
|
+
inputSchema,
|
|
149
|
+
outputSchema,
|
|
150
|
+
handler: handlerWithSpan
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
var FunctionDefinition = {
|
|
154
|
+
make: defineFunction,
|
|
155
|
+
isFunction: (value) => {
|
|
156
|
+
return typeof value === "object" && value !== null && Symbol.for("@dxos/functions/FunctionDefinition") in value;
|
|
157
|
+
},
|
|
158
|
+
serialize: (functionDef) => {
|
|
159
|
+
assertArgument(FunctionDefinition.isFunction(functionDef), "functionDef");
|
|
160
|
+
return serializeFunction(functionDef);
|
|
161
|
+
},
|
|
162
|
+
deserialize: (functionObj) => {
|
|
163
|
+
assertArgument(Obj.instanceOf(FunctionType, functionObj), "functionObj");
|
|
164
|
+
return deserializeFunction(functionObj);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
var serializeFunction = (functionDef) => Obj.make(FunctionType, {
|
|
168
|
+
key: functionDef.name,
|
|
169
|
+
name: functionDef.name,
|
|
170
|
+
version: "0.1.0",
|
|
171
|
+
description: functionDef.description,
|
|
172
|
+
inputSchema: Type2.toJsonSchema(functionDef.inputSchema),
|
|
173
|
+
outputSchema: !functionDef.outputSchema ? void 0 : Type2.toJsonSchema(functionDef.outputSchema)
|
|
174
|
+
});
|
|
175
|
+
var deserializeFunction = (functionObj) => {
|
|
176
|
+
return {
|
|
177
|
+
[typeId]: true,
|
|
178
|
+
// TODO(dmaretskyi): Fix key.
|
|
179
|
+
key: functionObj.key ?? functionObj.name,
|
|
180
|
+
name: functionObj.name,
|
|
181
|
+
description: functionObj.description,
|
|
182
|
+
inputSchema: !functionObj.inputSchema ? Schema2.Unknown : Type2.toEffectSchema(functionObj.inputSchema),
|
|
183
|
+
outputSchema: !functionObj.outputSchema ? void 0 : Type2.toEffectSchema(functionObj.outputSchema),
|
|
184
|
+
// TODO(dmaretskyi): This should throw error.
|
|
185
|
+
handler: () => {
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/trace.ts
|
|
72
191
|
import { Schema as Schema4 } from "effect";
|
|
73
|
-
import { Type as
|
|
192
|
+
import { Type as Type4 } from "@dxos/echo";
|
|
74
193
|
import { Queue } from "@dxos/echo-db";
|
|
75
194
|
import { ObjectId } from "@dxos/echo-schema";
|
|
76
195
|
import { log } from "@dxos/log";
|
|
77
196
|
|
|
78
|
-
//
|
|
197
|
+
// src/types.ts
|
|
79
198
|
import { Schema as Schema3, SchemaAST } from "effect";
|
|
80
|
-
import {
|
|
199
|
+
import { Obj as Obj2, QueryAST, Type as Type3 } from "@dxos/echo";
|
|
200
|
+
import { Expando, OptionsAnnotationId, RawObject, Ref as Ref2 } from "@dxos/echo-schema";
|
|
81
201
|
import { DXN } from "@dxos/keys";
|
|
82
|
-
var
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}({});
|
|
202
|
+
var TriggerKinds = [
|
|
203
|
+
"timer",
|
|
204
|
+
"webhook",
|
|
205
|
+
"subscription",
|
|
206
|
+
"email",
|
|
207
|
+
"queue"
|
|
208
|
+
];
|
|
90
209
|
var kindLiteralAnnotations = {
|
|
91
210
|
title: "Kind"
|
|
92
211
|
};
|
|
@@ -104,6 +223,7 @@ var EmailTriggerSchema = Schema3.Struct({
|
|
|
104
223
|
}).pipe(Schema3.mutable);
|
|
105
224
|
var QueueTriggerSchema = Schema3.Struct({
|
|
106
225
|
kind: Schema3.Literal("queue").annotations(kindLiteralAnnotations),
|
|
226
|
+
// TODO(dmaretskyi): Change to a reference.
|
|
107
227
|
queue: DXN.Schema
|
|
108
228
|
}).pipe(Schema3.mutable);
|
|
109
229
|
var WebhookTriggerSchema = Schema3.Struct({
|
|
@@ -119,21 +239,11 @@ var WebhookTriggerSchema = Schema3.Struct({
|
|
|
119
239
|
title: "Port"
|
|
120
240
|
}))
|
|
121
241
|
}).pipe(Schema3.mutable);
|
|
122
|
-
var QuerySchema = Schema3.Struct({
|
|
123
|
-
type: Schema3.optional(Schema3.String.annotations({
|
|
124
|
-
title: "Type"
|
|
125
|
-
})),
|
|
126
|
-
props: Schema3.optional(Schema3.Record({
|
|
127
|
-
key: Schema3.String,
|
|
128
|
-
value: Schema3.Any
|
|
129
|
-
}))
|
|
130
|
-
}).annotations({
|
|
131
|
-
title: "Query"
|
|
132
|
-
});
|
|
133
242
|
var SubscriptionTriggerSchema = Schema3.Struct({
|
|
134
243
|
kind: Schema3.Literal("subscription").annotations(kindLiteralAnnotations),
|
|
135
|
-
|
|
136
|
-
|
|
244
|
+
query: QueryAST.Query.annotations({
|
|
245
|
+
title: "Query"
|
|
246
|
+
}),
|
|
137
247
|
options: Schema3.optional(Schema3.Struct({
|
|
138
248
|
// Watch changes to object (not just creation).
|
|
139
249
|
deep: Schema3.optional(Schema3.Boolean.annotations({
|
|
@@ -171,14 +281,25 @@ var QueueTriggerOutput = Schema3.mutable(Schema3.Struct({
|
|
|
171
281
|
item: Schema3.Any,
|
|
172
282
|
cursor: Schema3.String
|
|
173
283
|
}));
|
|
174
|
-
var SubscriptionTriggerOutput = Schema3.
|
|
284
|
+
var SubscriptionTriggerOutput = Schema3.Struct({
|
|
285
|
+
/**
|
|
286
|
+
* Type of the mutation.
|
|
287
|
+
*/
|
|
288
|
+
// TODO(dmaretskyi): Specify enum.
|
|
175
289
|
type: Schema3.String,
|
|
176
|
-
|
|
177
|
-
|
|
290
|
+
/**
|
|
291
|
+
* Reference to the object that was changed or created.
|
|
292
|
+
*/
|
|
293
|
+
subject: Type3.Ref(Obj2.Any),
|
|
294
|
+
/**
|
|
295
|
+
* @deprecated
|
|
296
|
+
*/
|
|
297
|
+
changedObjectId: Schema3.optional(Schema3.String)
|
|
298
|
+
}).pipe(Schema3.mutable);
|
|
178
299
|
var TimerTriggerOutput = Schema3.mutable(Schema3.Struct({
|
|
179
300
|
tick: Schema3.Number
|
|
180
301
|
}));
|
|
181
|
-
var
|
|
302
|
+
var FunctionTrigger_ = Schema3.Struct({
|
|
182
303
|
/**
|
|
183
304
|
* Function or workflow to invoke.
|
|
184
305
|
*/
|
|
@@ -213,12 +334,11 @@ var FunctionTriggerSchema = Schema3.Struct({
|
|
|
213
334
|
key: Schema3.String,
|
|
214
335
|
value: Schema3.Any
|
|
215
336
|
})))
|
|
216
|
-
})
|
|
217
|
-
var FunctionTrigger = class extends TypedObject({
|
|
337
|
+
}).pipe(Type3.Obj({
|
|
218
338
|
typename: "dxos.org/type/FunctionTrigger",
|
|
219
339
|
version: "0.2.0"
|
|
220
|
-
})
|
|
221
|
-
|
|
340
|
+
}));
|
|
341
|
+
var FunctionTrigger = FunctionTrigger_;
|
|
222
342
|
var FunctionManifestSchema = Schema3.Struct({
|
|
223
343
|
functions: Schema3.optional(Schema3.mutable(Schema3.Array(RawObject(FunctionType)))),
|
|
224
344
|
triggers: Schema3.optional(Schema3.mutable(Schema3.Array(RawObject(FunctionTrigger))))
|
|
@@ -228,21 +348,21 @@ var FUNCTION_TYPES = [
|
|
|
228
348
|
FunctionTrigger
|
|
229
349
|
];
|
|
230
350
|
|
|
231
|
-
//
|
|
232
|
-
var __dxlog_file = "/
|
|
233
|
-
var InvocationOutcome = /* @__PURE__ */ function(InvocationOutcome2) {
|
|
351
|
+
// src/trace.ts
|
|
352
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/core/functions/src/trace.ts";
|
|
353
|
+
var InvocationOutcome = /* @__PURE__ */ (function(InvocationOutcome2) {
|
|
234
354
|
InvocationOutcome2["SUCCESS"] = "success";
|
|
235
355
|
InvocationOutcome2["FAILURE"] = "failure";
|
|
236
356
|
InvocationOutcome2["PENDING"] = "pending";
|
|
237
357
|
return InvocationOutcome2;
|
|
238
|
-
}({});
|
|
239
|
-
var InvocationTraceEventType = /* @__PURE__ */ function(InvocationTraceEventType2) {
|
|
358
|
+
})({});
|
|
359
|
+
var InvocationTraceEventType = /* @__PURE__ */ (function(InvocationTraceEventType2) {
|
|
240
360
|
InvocationTraceEventType2["START"] = "start";
|
|
241
361
|
InvocationTraceEventType2["END"] = "end";
|
|
242
362
|
return InvocationTraceEventType2;
|
|
243
|
-
}({});
|
|
363
|
+
})({});
|
|
244
364
|
var TraceEventException = Schema4.Struct({
|
|
245
|
-
|
|
365
|
+
timestamp: Schema4.Number,
|
|
246
366
|
message: Schema4.String,
|
|
247
367
|
name: Schema4.String,
|
|
248
368
|
stack: Schema4.optional(Schema4.String)
|
|
@@ -260,7 +380,7 @@ var InvocationTraceStartEvent = Schema4.Struct({
|
|
|
260
380
|
/**
|
|
261
381
|
* Event generation time.
|
|
262
382
|
*/
|
|
263
|
-
|
|
383
|
+
timestamp: Schema4.Number,
|
|
264
384
|
/**
|
|
265
385
|
* Data passed to function / workflow as an argument.
|
|
266
386
|
*/
|
|
@@ -269,16 +389,16 @@ var InvocationTraceStartEvent = Schema4.Struct({
|
|
|
269
389
|
/**
|
|
270
390
|
* Queue for function/workflow invocation events.
|
|
271
391
|
*/
|
|
272
|
-
invocationTraceQueue:
|
|
392
|
+
invocationTraceQueue: Schema4.optional(Type4.Ref(Queue)),
|
|
273
393
|
/**
|
|
274
394
|
* DXN of the invoked function/workflow.
|
|
275
395
|
*/
|
|
276
|
-
invocationTarget:
|
|
396
|
+
invocationTarget: Schema4.optional(Type4.Ref(Type4.Expando)),
|
|
277
397
|
/**
|
|
278
398
|
* Present for automatic invocations.
|
|
279
399
|
*/
|
|
280
|
-
trigger: Schema4.optional(
|
|
281
|
-
}).pipe(
|
|
400
|
+
trigger: Schema4.optional(Type4.Ref(FunctionTrigger))
|
|
401
|
+
}).pipe(Type4.Obj({
|
|
282
402
|
typename: "dxos.org/type/InvocationTraceStart",
|
|
283
403
|
version: "0.1.0"
|
|
284
404
|
}));
|
|
@@ -296,15 +416,15 @@ var InvocationTraceEndEvent = Schema4.Struct({
|
|
|
296
416
|
* Event generation time.
|
|
297
417
|
*/
|
|
298
418
|
// TODO(burdon): Remove ms suffix.
|
|
299
|
-
|
|
419
|
+
timestamp: Schema4.Number,
|
|
300
420
|
outcome: Schema4.Enums(InvocationOutcome),
|
|
301
421
|
exception: Schema4.optional(TraceEventException)
|
|
302
|
-
}).pipe(
|
|
422
|
+
}).pipe(Type4.Obj({
|
|
303
423
|
typename: "dxos.org/type/InvocationTraceEnd",
|
|
304
424
|
version: "0.1.0"
|
|
305
425
|
}));
|
|
306
426
|
var TraceEventLog = Schema4.Struct({
|
|
307
|
-
|
|
427
|
+
timestamp: Schema4.Number,
|
|
308
428
|
level: Schema4.String,
|
|
309
429
|
message: Schema4.String,
|
|
310
430
|
context: Schema4.optional(Schema4.Object)
|
|
@@ -314,13 +434,11 @@ var TraceEvent = Schema4.Struct({
|
|
|
314
434
|
// TODO(burdon): Need enum/numeric result (not string).
|
|
315
435
|
outcome: Schema4.String,
|
|
316
436
|
truncated: Schema4.Boolean,
|
|
317
|
-
/**
|
|
318
|
-
|
|
319
|
-
*/
|
|
320
|
-
ingestionTimestampMs: Schema4.Number,
|
|
437
|
+
/** Time when the event was persisted. */
|
|
438
|
+
ingestionTimestamp: Schema4.Number,
|
|
321
439
|
logs: Schema4.Array(TraceEventLog),
|
|
322
440
|
exceptions: Schema4.Array(TraceEventException)
|
|
323
|
-
}).pipe(
|
|
441
|
+
}).pipe(Type4.Obj({
|
|
324
442
|
typename: "dxos.org/type/TraceEvent",
|
|
325
443
|
version: "0.1.0"
|
|
326
444
|
}));
|
|
@@ -353,7 +471,7 @@ var createInvocationSpans = (items) => {
|
|
|
353
471
|
invocationId
|
|
354
472
|
}, {
|
|
355
473
|
F: __dxlog_file,
|
|
356
|
-
L:
|
|
474
|
+
L: 158,
|
|
357
475
|
S: void 0,
|
|
358
476
|
C: (f, a) => f(...a)
|
|
359
477
|
});
|
|
@@ -362,8 +480,8 @@ var createInvocationSpans = (items) => {
|
|
|
362
480
|
const isInProgress = end === void 0;
|
|
363
481
|
result.push({
|
|
364
482
|
id: invocationId,
|
|
365
|
-
|
|
366
|
-
|
|
483
|
+
timestamp: start.timestamp,
|
|
484
|
+
duration: isInProgress ? now - start.timestamp : end.timestamp - start.timestamp,
|
|
367
485
|
outcome: end?.outcome ?? "pending",
|
|
368
486
|
exception: end?.exception,
|
|
369
487
|
input: start.input,
|
|
@@ -375,112 +493,838 @@ var createInvocationSpans = (items) => {
|
|
|
375
493
|
return result;
|
|
376
494
|
};
|
|
377
495
|
|
|
378
|
-
//
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
496
|
+
// src/triggers/invocation-tracer.ts
|
|
497
|
+
import { Context as Context2, Effect as Effect3, Layer as Layer2 } from "effect";
|
|
498
|
+
import { Obj as Obj3, Ref as Ref3 } from "@dxos/echo";
|
|
499
|
+
import { DXN as DXN2, ObjectId as ObjectId2 } from "@dxos/keys";
|
|
500
|
+
|
|
501
|
+
// src/services/local-function-execution.ts
|
|
502
|
+
import { Context, Effect as Effect2, Layer, Schema as Schema5 } from "effect";
|
|
503
|
+
import { todo } from "@dxos/debug";
|
|
504
|
+
import { log as log2 } from "@dxos/log";
|
|
505
|
+
function _define_property(obj, key, value) {
|
|
506
|
+
if (key in obj) {
|
|
507
|
+
Object.defineProperty(obj, key, {
|
|
508
|
+
value,
|
|
509
|
+
enumerable: true,
|
|
510
|
+
configurable: true,
|
|
511
|
+
writable: true
|
|
512
|
+
});
|
|
513
|
+
} else {
|
|
514
|
+
obj[key] = value;
|
|
515
|
+
}
|
|
516
|
+
return obj;
|
|
517
|
+
}
|
|
518
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/core/functions/src/services/local-function-execution.ts";
|
|
519
|
+
var _Context_Tag;
|
|
520
|
+
var LocalFunctionExecutionService = class extends (_Context_Tag = Context.Tag("@dxos/functions/LocalFunctionExecutionService")()) {
|
|
383
521
|
};
|
|
384
|
-
|
|
385
|
-
|
|
522
|
+
_define_property(LocalFunctionExecutionService, "layer", Layer.succeed(LocalFunctionExecutionService, {
|
|
523
|
+
invokeFunction: (functionDef, input) => invokeFunction(functionDef, input)
|
|
524
|
+
}));
|
|
525
|
+
_define_property(LocalFunctionExecutionService, "layerLive", Layer.effect(LocalFunctionExecutionService, Effect2.gen(function* () {
|
|
526
|
+
const resolver = yield* FunctionImplementationResolver;
|
|
527
|
+
return {
|
|
528
|
+
invokeFunction: Effect2.fn("invokeFunction")(function* (functionDef, input) {
|
|
529
|
+
const resolved = yield* resolver.resolveFunctionImplementation(functionDef).pipe(Effect2.orDie);
|
|
530
|
+
return yield* invokeFunction(resolved, input);
|
|
531
|
+
})
|
|
532
|
+
};
|
|
533
|
+
})));
|
|
534
|
+
_define_property(LocalFunctionExecutionService, "invokeFunction", Effect2.serviceFunctionEffect(LocalFunctionExecutionService, (_) => _.invokeFunction));
|
|
535
|
+
var invokeFunction = (functionDef, input) => Effect2.gen(function* () {
|
|
536
|
+
try {
|
|
537
|
+
const assertInput = functionDef.inputSchema.pipe(Schema5.asserts);
|
|
538
|
+
assertInput(input);
|
|
539
|
+
} catch (e) {
|
|
540
|
+
throw new FunctionError({
|
|
541
|
+
message: "Invalid function input",
|
|
542
|
+
context: {
|
|
543
|
+
name: functionDef.name
|
|
544
|
+
},
|
|
545
|
+
cause: e
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
const context = {
|
|
549
|
+
space: void 0,
|
|
550
|
+
getService: () => todo(),
|
|
551
|
+
getSpace: async (_spaceId) => {
|
|
552
|
+
throw new Error("Not available. Use the database service instead.");
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
log2.info("Invoking function", {
|
|
556
|
+
name: functionDef.name,
|
|
557
|
+
input
|
|
558
|
+
}, {
|
|
559
|
+
F: __dxlog_file2,
|
|
560
|
+
L: 72,
|
|
561
|
+
S: this,
|
|
562
|
+
C: (f, a) => f(...a)
|
|
563
|
+
});
|
|
564
|
+
const data = yield* Effect2.gen(function* () {
|
|
565
|
+
const result = functionDef.handler({
|
|
566
|
+
context,
|
|
567
|
+
data: input
|
|
568
|
+
});
|
|
569
|
+
if (Effect2.isEffect(result)) {
|
|
570
|
+
return yield* result.pipe(Effect2.orDie);
|
|
571
|
+
} else if (typeof result === "object" && result !== null && "then" in result && typeof result.then === "function") {
|
|
572
|
+
return yield* Effect2.promise(() => result);
|
|
573
|
+
} else {
|
|
574
|
+
return result;
|
|
575
|
+
}
|
|
576
|
+
}).pipe(Effect2.orDie, Effect2.catchAllDefect((defect) => Effect2.die(new FunctionError({
|
|
577
|
+
context: {
|
|
578
|
+
name: functionDef.name
|
|
579
|
+
},
|
|
580
|
+
cause: defect
|
|
581
|
+
}))));
|
|
582
|
+
log2.info("Function completed", {
|
|
583
|
+
name: functionDef.name,
|
|
584
|
+
input,
|
|
585
|
+
data
|
|
586
|
+
}, {
|
|
587
|
+
F: __dxlog_file2,
|
|
588
|
+
L: 96,
|
|
589
|
+
S: this,
|
|
590
|
+
C: (f, a) => f(...a)
|
|
591
|
+
});
|
|
592
|
+
try {
|
|
593
|
+
const assertOutput = functionDef.outputSchema?.pipe(Schema5.asserts);
|
|
594
|
+
assertOutput(data);
|
|
595
|
+
} catch (e) {
|
|
596
|
+
throw new FunctionError({
|
|
597
|
+
message: "Invalid function output",
|
|
598
|
+
context: {
|
|
599
|
+
name: functionDef.name
|
|
600
|
+
},
|
|
601
|
+
cause: e
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
return data;
|
|
605
|
+
}).pipe(Effect2.withSpan("invokeFunction", {
|
|
606
|
+
attributes: {
|
|
607
|
+
name: functionDef.name
|
|
608
|
+
}
|
|
609
|
+
}));
|
|
610
|
+
var _Context_Tag1;
|
|
611
|
+
var FunctionImplementationResolver = class extends (_Context_Tag1 = Context.Tag("@dxos/functions/FunctionImplementationResolver")()) {
|
|
386
612
|
};
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
if (
|
|
391
|
-
|
|
613
|
+
_define_property(FunctionImplementationResolver, "layerTest", ({ functions }) => Layer.succeed(FunctionImplementationResolver, {
|
|
614
|
+
resolveFunctionImplementation: (functionDef) => {
|
|
615
|
+
const resolved = functions.find((f) => f.name === functionDef.name);
|
|
616
|
+
if (!resolved) {
|
|
617
|
+
return Effect2.fail(new FunctionNotFoundError(functionDef.name));
|
|
392
618
|
}
|
|
619
|
+
return Effect2.succeed(resolved);
|
|
620
|
+
}
|
|
621
|
+
}));
|
|
622
|
+
|
|
623
|
+
// src/triggers/invocation-tracer.ts
|
|
624
|
+
function _define_property2(obj, key, value) {
|
|
625
|
+
if (key in obj) {
|
|
626
|
+
Object.defineProperty(obj, key, {
|
|
627
|
+
value,
|
|
628
|
+
enumerable: true,
|
|
629
|
+
configurable: true,
|
|
630
|
+
writable: true
|
|
631
|
+
});
|
|
393
632
|
} else {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
633
|
+
obj[key] = value;
|
|
634
|
+
}
|
|
635
|
+
return obj;
|
|
636
|
+
}
|
|
637
|
+
var _Context_Tag2;
|
|
638
|
+
var InvocationTracer = class extends (_Context_Tag2 = Context2.Tag("@dxos/functions/InvocationTracer")()) {
|
|
639
|
+
};
|
|
640
|
+
_define_property2(InvocationTracer, "layerLive", (opts) => Layer2.effect(InvocationTracer, Effect3.gen(function* () {
|
|
641
|
+
return {
|
|
642
|
+
traceInvocationStart: Effect3.fn("traceInvocationStart")(function* ({ payload, target }) {
|
|
643
|
+
const invocationId = ObjectId2.random();
|
|
644
|
+
const invocationTraceQueue = yield* QueueService.createQueue({
|
|
645
|
+
subspaceTag: "trace"
|
|
646
|
+
});
|
|
647
|
+
const now = Date.now();
|
|
648
|
+
const traceEvent = Obj3.make(InvocationTraceStartEvent, {
|
|
649
|
+
type: InvocationTraceEventType.START,
|
|
650
|
+
invocationId,
|
|
651
|
+
timestamp: now,
|
|
652
|
+
// TODO(dmaretskyi): Not json-stringifying this makes ECHO fail when one ECHO object becomes embedded in another ECHO object.
|
|
653
|
+
input: JSON.parse(JSON.stringify(payload.data ?? {})),
|
|
654
|
+
invocationTraceQueue: Ref3.fromDXN(invocationTraceQueue.dxn),
|
|
655
|
+
invocationTarget: target ? Ref3.fromDXN(target) : void 0,
|
|
656
|
+
trigger: payload.trigger ? Ref3.fromDXN(DXN2.fromLocalObjectId(payload.trigger.id)) : void 0
|
|
657
|
+
});
|
|
658
|
+
yield* QueueService.append(opts.invocationTraceQueue, [
|
|
659
|
+
traceEvent
|
|
660
|
+
]);
|
|
661
|
+
return {
|
|
662
|
+
invocationId,
|
|
663
|
+
invocationTraceQueue
|
|
664
|
+
};
|
|
665
|
+
}),
|
|
666
|
+
traceInvocationEnd: Effect3.fn("traceInvocationEnd")(function* ({ trace, exception }) {
|
|
667
|
+
const now = Date.now();
|
|
668
|
+
const traceEvent = Obj3.make(InvocationTraceEndEvent, {
|
|
669
|
+
type: InvocationTraceEventType.END,
|
|
670
|
+
invocationId: trace.invocationId,
|
|
671
|
+
timestamp: now,
|
|
672
|
+
outcome: exception ? InvocationOutcome.FAILURE : InvocationOutcome.SUCCESS,
|
|
673
|
+
exception: exception ? {
|
|
674
|
+
name: exception.constructor.name,
|
|
675
|
+
timestamp: now,
|
|
676
|
+
message: exception?.message ?? "Unknown error",
|
|
677
|
+
stack: exception?.stack
|
|
678
|
+
} : void 0
|
|
679
|
+
});
|
|
680
|
+
yield* QueueService.append(opts.invocationTraceQueue, [
|
|
681
|
+
traceEvent
|
|
682
|
+
]);
|
|
683
|
+
})
|
|
684
|
+
};
|
|
685
|
+
})));
|
|
686
|
+
_define_property2(InvocationTracer, "layerTest", Layer2.unwrapEffect(Effect3.gen(function* () {
|
|
687
|
+
const queue = yield* QueueService.createQueue({
|
|
688
|
+
subspaceTag: "trace"
|
|
689
|
+
});
|
|
690
|
+
return InvocationTracer.layerLive({
|
|
691
|
+
invocationTraceQueue: queue
|
|
692
|
+
});
|
|
693
|
+
})));
|
|
694
|
+
|
|
695
|
+
// src/triggers/trigger-dispatcher.ts
|
|
696
|
+
import { Cause, Context as Context4, Cron, Duration, Effect as Effect5, Either, Exit, Fiber, Layer as Layer4, Option as Option2, Record, Schedule } from "effect";
|
|
697
|
+
import { DXN as DXN3, Filter, Obj as Obj4, Query } from "@dxos/echo";
|
|
698
|
+
import { causeToError } from "@dxos/effect";
|
|
699
|
+
import { invariant } from "@dxos/invariant";
|
|
700
|
+
import { log as log3 } from "@dxos/log";
|
|
701
|
+
import { KEY_QUEUE_POSITION } from "@dxos/protocols";
|
|
702
|
+
|
|
703
|
+
// src/triggers/input-builder.ts
|
|
704
|
+
var createInvocationPayload = (trigger, event) => {
|
|
705
|
+
if (!trigger.input) {
|
|
706
|
+
return event;
|
|
707
|
+
}
|
|
708
|
+
const payload = {};
|
|
709
|
+
for (const [key, value] of Object.entries(trigger.input)) {
|
|
710
|
+
if (typeof value !== "string" || !(value.startsWith("{{") && value.endsWith("}}"))) {
|
|
711
|
+
payload[key] = value;
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
const propertyPath = value.slice(2, -2);
|
|
715
|
+
let valueSubstitution = propertyPath.startsWith("trigger.") ? trigger : propertyPath.startsWith("event.") ? event : void 0;
|
|
716
|
+
for (const pathSegment of propertyPath.split(".").slice(1)) {
|
|
717
|
+
if (valueSubstitution && typeof valueSubstitution === "object") {
|
|
718
|
+
valueSubstitution = valueSubstitution[pathSegment];
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
payload[key] = valueSubstitution;
|
|
722
|
+
}
|
|
723
|
+
return payload;
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
// src/triggers/trigger-state-store.ts
|
|
727
|
+
import { KeyValueStore } from "@effect/platform";
|
|
728
|
+
import { Context as Context3 } from "effect";
|
|
729
|
+
import { Schema as Schema6 } from "effect";
|
|
730
|
+
import { Effect as Effect4, Layer as Layer3 } from "effect";
|
|
731
|
+
import { Option } from "effect";
|
|
732
|
+
import { ObjectId as ObjectId3 } from "@dxos/keys";
|
|
733
|
+
function _define_property3(obj, key, value) {
|
|
734
|
+
if (key in obj) {
|
|
735
|
+
Object.defineProperty(obj, key, {
|
|
736
|
+
value,
|
|
737
|
+
enumerable: true,
|
|
738
|
+
configurable: true,
|
|
739
|
+
writable: true
|
|
397
740
|
});
|
|
741
|
+
} else {
|
|
742
|
+
obj[key] = value;
|
|
398
743
|
}
|
|
744
|
+
return obj;
|
|
745
|
+
}
|
|
746
|
+
var TriggerState = Schema6.Struct({
|
|
747
|
+
version: Schema6.Literal("1"),
|
|
748
|
+
triggerId: Schema6.String,
|
|
749
|
+
state: Schema6.optional(Schema6.Union(Schema6.TaggedStruct("subscription", {
|
|
750
|
+
processedVersions: Schema6.Record({
|
|
751
|
+
key: ObjectId3,
|
|
752
|
+
value: Schema6.String
|
|
753
|
+
})
|
|
754
|
+
})))
|
|
755
|
+
});
|
|
756
|
+
var _Context_Tag3;
|
|
757
|
+
var TriggerStateStore = class extends (_Context_Tag3 = Context3.Tag("@dxos/functions/TriggerStateStore")()) {
|
|
399
758
|
};
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
759
|
+
_define_property3(TriggerStateStore, "getState", Effect4.serviceFunctionEffect(TriggerStateStore, (_) => _.getState));
|
|
760
|
+
_define_property3(TriggerStateStore, "saveState", Effect4.serviceFunctionEffect(TriggerStateStore, (_) => _.saveState));
|
|
761
|
+
_define_property3(TriggerStateStore, "layerKv", Layer3.effect(TriggerStateStore, Effect4.gen(function* () {
|
|
762
|
+
const kv = yield* KeyValueStore.KeyValueStore;
|
|
763
|
+
const schemaStore = kv.forSchema(Schema6.parseJson(TriggerState));
|
|
764
|
+
const store = {
|
|
765
|
+
getState: Effect4.fn("TriggerStateStore.getState")(function* (triggerId) {
|
|
766
|
+
const valueOption = yield* schemaStore.get(triggerId).pipe(Effect4.orDie);
|
|
767
|
+
if (Option.isNone(valueOption)) {
|
|
768
|
+
return yield* Effect4.fail(new TriggerStateNotFoundError());
|
|
769
|
+
}
|
|
770
|
+
return valueOption.value;
|
|
771
|
+
}),
|
|
772
|
+
saveState: Effect4.fn("TriggerStateStore.saveState")(function* (state) {
|
|
773
|
+
yield* schemaStore.set(state.triggerId, state).pipe(Effect4.orDie);
|
|
774
|
+
})
|
|
775
|
+
};
|
|
776
|
+
return store;
|
|
777
|
+
})));
|
|
778
|
+
_define_property3(TriggerStateStore, "layerMemory", TriggerStateStore.layerKv.pipe(Layer3.provide(KeyValueStore.layerMemory)));
|
|
779
|
+
|
|
780
|
+
// src/triggers/trigger-dispatcher.ts
|
|
781
|
+
function _define_property4(obj, key, value) {
|
|
782
|
+
if (key in obj) {
|
|
783
|
+
Object.defineProperty(obj, key, {
|
|
784
|
+
value,
|
|
785
|
+
enumerable: true,
|
|
786
|
+
configurable: true,
|
|
787
|
+
writable: true
|
|
788
|
+
});
|
|
789
|
+
} else {
|
|
790
|
+
obj[key] = value;
|
|
791
|
+
}
|
|
792
|
+
return obj;
|
|
793
|
+
}
|
|
794
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/core/functions/src/triggers/trigger-dispatcher.ts";
|
|
795
|
+
var _Context_Tag4;
|
|
796
|
+
var TriggerDispatcher = class extends (_Context_Tag4 = Context4.Tag("@dxos/functions/TriggerDispatcher")()) {
|
|
797
|
+
};
|
|
798
|
+
_define_property4(TriggerDispatcher, "layer", (options) => Layer4.effect(TriggerDispatcher, Effect5.gen(function* () {
|
|
799
|
+
return new TriggerDispatcherImpl(options);
|
|
800
|
+
})));
|
|
801
|
+
var TriggerDispatcherImpl = class {
|
|
802
|
+
get running() {
|
|
803
|
+
return this._running;
|
|
804
|
+
}
|
|
805
|
+
constructor(options) {
|
|
806
|
+
_define_property4(this, "livePollInterval", void 0);
|
|
807
|
+
_define_property4(this, "timeControl", void 0);
|
|
808
|
+
_define_property4(this, "_running", false);
|
|
809
|
+
_define_property4(this, "_internalTime", void 0);
|
|
810
|
+
_define_property4(this, "_timerFiber", void 0);
|
|
811
|
+
_define_property4(this, "_scheduledTriggers", /* @__PURE__ */ new Map());
|
|
812
|
+
_define_property4(this, "start", () => Effect5.gen(this, function* () {
|
|
813
|
+
if (this._running) {
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
this._running = true;
|
|
817
|
+
if (this.timeControl === "natural") {
|
|
818
|
+
this._timerFiber = yield* this._startNaturalTimeProcessing().pipe(Effect5.tapErrorCause((cause) => {
|
|
819
|
+
const error = causeToError(cause);
|
|
820
|
+
log3.error("trigger dispatcher error", {
|
|
821
|
+
error
|
|
822
|
+
}, {
|
|
823
|
+
F: __dxlog_file3,
|
|
824
|
+
L: 170,
|
|
825
|
+
S: this,
|
|
826
|
+
C: (f, a) => f(...a)
|
|
827
|
+
});
|
|
828
|
+
this._running = false;
|
|
829
|
+
return Effect5.void;
|
|
830
|
+
}), Effect5.forkDaemon);
|
|
831
|
+
} else {
|
|
832
|
+
return yield* Effect5.dieMessage("TriggerDispatcher started in manual time control mode");
|
|
833
|
+
}
|
|
834
|
+
log3.info("TriggerDispatcher started", {
|
|
835
|
+
timeControl: this.timeControl
|
|
836
|
+
}, {
|
|
837
|
+
F: __dxlog_file3,
|
|
838
|
+
L: 180,
|
|
839
|
+
S: this,
|
|
840
|
+
C: (f, a) => f(...a)
|
|
841
|
+
});
|
|
842
|
+
}));
|
|
843
|
+
_define_property4(this, "stop", () => Effect5.gen(this, function* () {
|
|
844
|
+
if (!this._running) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
this._running = false;
|
|
848
|
+
if (this._timerFiber) {
|
|
849
|
+
yield* Fiber.interrupt(this._timerFiber);
|
|
850
|
+
this._timerFiber = void 0;
|
|
851
|
+
}
|
|
852
|
+
this._scheduledTriggers.clear();
|
|
853
|
+
log3.info("TriggerDispatcher stopped", void 0, {
|
|
854
|
+
F: __dxlog_file3,
|
|
855
|
+
L: 200,
|
|
856
|
+
S: this,
|
|
857
|
+
C: (f, a) => f(...a)
|
|
858
|
+
});
|
|
859
|
+
}));
|
|
860
|
+
_define_property4(this, "invokeTrigger", (options2) => Effect5.gen(this, function* () {
|
|
861
|
+
const { trigger, event } = options2;
|
|
862
|
+
log3.info("running trigger", {
|
|
863
|
+
triggerId: trigger.id,
|
|
864
|
+
spec: trigger.spec,
|
|
865
|
+
event
|
|
866
|
+
}, {
|
|
867
|
+
F: __dxlog_file3,
|
|
868
|
+
L: 208,
|
|
869
|
+
S: this,
|
|
870
|
+
C: (f, a) => f(...a)
|
|
871
|
+
});
|
|
872
|
+
const tracer = yield* InvocationTracer;
|
|
873
|
+
const trace = yield* tracer.traceInvocationStart({
|
|
874
|
+
target: trigger.function?.dxn,
|
|
875
|
+
payload: {
|
|
876
|
+
trigger: {
|
|
877
|
+
id: trigger.id,
|
|
878
|
+
// TODO(dmaretskyi): Is `spec` always there>
|
|
879
|
+
kind: trigger.spec.kind
|
|
880
|
+
},
|
|
881
|
+
data: event
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
const result = yield* Effect5.gen(this, function* () {
|
|
885
|
+
if (!trigger.enabled) {
|
|
886
|
+
return yield* Effect5.dieMessage("Attempting to invoke disabled trigger");
|
|
887
|
+
}
|
|
888
|
+
if (!trigger.function) {
|
|
889
|
+
return yield* Effect5.dieMessage("Trigger has no function reference");
|
|
890
|
+
}
|
|
891
|
+
const serialiedFunction = yield* DatabaseService.load(trigger.function).pipe(Effect5.orDie);
|
|
892
|
+
invariant(Obj4.instanceOf(FunctionType, serialiedFunction), void 0, {
|
|
893
|
+
F: __dxlog_file3,
|
|
894
|
+
L: 235,
|
|
895
|
+
S: this,
|
|
896
|
+
A: [
|
|
897
|
+
"Obj.instanceOf(FunctionType, serialiedFunction)",
|
|
898
|
+
""
|
|
899
|
+
]
|
|
900
|
+
});
|
|
901
|
+
const functionDef = deserializeFunction(serialiedFunction);
|
|
902
|
+
const inputData = this._prepareInputData(trigger, event);
|
|
903
|
+
return yield* LocalFunctionExecutionService.invokeFunction(functionDef, inputData).pipe(Effect5.provide(ComputeEventLogger.layerFromTracing.pipe(Layer4.provideMerge(TracingService.layerQueue(trace.invocationTraceQueue)))));
|
|
904
|
+
}).pipe(Effect5.exit);
|
|
905
|
+
const triggerExecutionResult = {
|
|
906
|
+
triggerId: trigger.id,
|
|
907
|
+
result
|
|
908
|
+
};
|
|
909
|
+
if (Exit.isSuccess(result)) {
|
|
910
|
+
log3.info("trigger execution success", {
|
|
911
|
+
triggerId: trigger.id
|
|
912
|
+
}, {
|
|
913
|
+
F: __dxlog_file3,
|
|
914
|
+
L: 256,
|
|
915
|
+
S: this,
|
|
916
|
+
C: (f, a) => f(...a)
|
|
917
|
+
});
|
|
918
|
+
} else {
|
|
919
|
+
log3.error("trigger execution failure", {
|
|
920
|
+
error: causeToError(result.cause)
|
|
921
|
+
}, {
|
|
922
|
+
F: __dxlog_file3,
|
|
923
|
+
L: 260,
|
|
924
|
+
S: this,
|
|
925
|
+
C: (f, a) => f(...a)
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
yield* tracer.traceInvocationEnd({
|
|
929
|
+
trace,
|
|
930
|
+
// TODO(dmaretskyi): Might miss errors.
|
|
931
|
+
exception: Exit.isFailure(result) ? Cause.prettyErrors(result.cause)[0] : void 0
|
|
932
|
+
});
|
|
933
|
+
return triggerExecutionResult;
|
|
934
|
+
}));
|
|
935
|
+
_define_property4(this, "invokeScheduledTriggers", ({ kinds = [
|
|
936
|
+
"timer",
|
|
937
|
+
"queue",
|
|
938
|
+
"subscription"
|
|
939
|
+
] } = {}) => Effect5.gen(this, function* () {
|
|
940
|
+
const invocations = [];
|
|
941
|
+
for (const kind of kinds) {
|
|
942
|
+
switch (kind) {
|
|
943
|
+
case "timer":
|
|
944
|
+
{
|
|
945
|
+
yield* this.refreshTriggers();
|
|
946
|
+
const now = this.getCurrentTime();
|
|
947
|
+
const triggersToInvoke = [];
|
|
948
|
+
for (const [triggerId, scheduledTrigger] of this._scheduledTriggers.entries()) {
|
|
949
|
+
if (scheduledTrigger.nextExecution <= now) {
|
|
950
|
+
triggersToInvoke.push(scheduledTrigger.trigger);
|
|
951
|
+
scheduledTrigger.nextExecution = Cron.next(scheduledTrigger.cron, now);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
invocations.push(...yield* Effect5.forEach(triggersToInvoke, (trigger) => this.invokeTrigger({
|
|
955
|
+
trigger,
|
|
956
|
+
event: {
|
|
957
|
+
tick: now.getTime()
|
|
958
|
+
}
|
|
959
|
+
}), {
|
|
960
|
+
concurrency: 1
|
|
961
|
+
}));
|
|
962
|
+
}
|
|
963
|
+
break;
|
|
964
|
+
case "queue": {
|
|
965
|
+
const triggers = yield* this._fetchTriggers();
|
|
966
|
+
for (const trigger of triggers) {
|
|
967
|
+
const spec = trigger.spec;
|
|
968
|
+
if (spec?.kind !== "queue") {
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
const cursor = Obj4.getKeys(trigger, KEY_QUEUE_CURSOR).at(0)?.id;
|
|
972
|
+
const queue = yield* QueueService.getQueue(DXN3.parse(spec.queue));
|
|
973
|
+
const objects = yield* Effect5.promise(() => queue.queryObjects());
|
|
974
|
+
for (const object of objects) {
|
|
975
|
+
const objectPos = Obj4.getKeys(object, KEY_QUEUE_POSITION).at(0)?.id;
|
|
976
|
+
if (!objectPos || cursor && parseInt(cursor) >= parseInt(objectPos)) {
|
|
977
|
+
continue;
|
|
978
|
+
}
|
|
979
|
+
invocations.push(yield* this.invokeTrigger({
|
|
980
|
+
trigger,
|
|
981
|
+
event: {
|
|
982
|
+
queue: spec.queue,
|
|
983
|
+
item: object,
|
|
984
|
+
cursor: objectPos
|
|
985
|
+
}
|
|
986
|
+
}));
|
|
987
|
+
Obj4.deleteKeys(trigger, KEY_QUEUE_CURSOR);
|
|
988
|
+
Obj4.getMeta(trigger).keys.push({
|
|
989
|
+
source: KEY_QUEUE_CURSOR,
|
|
990
|
+
id: objectPos
|
|
991
|
+
});
|
|
992
|
+
yield* DatabaseService.flush();
|
|
993
|
+
break;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
break;
|
|
997
|
+
}
|
|
998
|
+
case "subscription": {
|
|
999
|
+
const triggers = yield* this._fetchTriggers();
|
|
1000
|
+
for (const trigger of triggers) {
|
|
1001
|
+
const spec = Obj4.getSnapshot(trigger).spec;
|
|
1002
|
+
if (spec?.kind !== "subscription") {
|
|
1003
|
+
continue;
|
|
1004
|
+
}
|
|
1005
|
+
const { objects } = yield* DatabaseService.runQuery(Query.fromAst(spec.query));
|
|
1006
|
+
const state = yield* TriggerStateStore.getState(trigger.id).pipe(Effect5.catchTag("TRIGGER_STATE_NOT_FOUND", () => Effect5.succeed({
|
|
1007
|
+
version: "1",
|
|
1008
|
+
triggerId: trigger.id,
|
|
1009
|
+
state: {
|
|
1010
|
+
_tag: "subscription",
|
|
1011
|
+
processedVersions: {}
|
|
1012
|
+
}
|
|
1013
|
+
})));
|
|
1014
|
+
invariant(state.state?._tag === "subscription", void 0, {
|
|
1015
|
+
F: __dxlog_file3,
|
|
1016
|
+
L: 373,
|
|
1017
|
+
S: this,
|
|
1018
|
+
A: [
|
|
1019
|
+
"state.state?._tag === 'subscription'",
|
|
1020
|
+
""
|
|
1021
|
+
]
|
|
1022
|
+
});
|
|
1023
|
+
let updated = false;
|
|
1024
|
+
for (const object of objects) {
|
|
1025
|
+
const existingVersion = Record.get(state.state.processedVersions, object.id).pipe(Option2.map(Obj4.decodeVersion));
|
|
1026
|
+
const currentVersion = Obj4.version(object);
|
|
1027
|
+
const run = Option2.isNone(existingVersion) || Obj4.compareVersions(currentVersion, existingVersion.value) === "different";
|
|
1028
|
+
if (!run) {
|
|
1029
|
+
continue;
|
|
1030
|
+
}
|
|
1031
|
+
const { db } = yield* DatabaseService;
|
|
1032
|
+
invocations.push(yield* this.invokeTrigger({
|
|
1033
|
+
trigger,
|
|
1034
|
+
event: {
|
|
1035
|
+
// TODO(dmaretskyi): Change type not supported.
|
|
1036
|
+
type: "unknown",
|
|
1037
|
+
subject: db.ref(Obj4.getDXN(object)),
|
|
1038
|
+
changedObjectId: object.id
|
|
1039
|
+
}
|
|
1040
|
+
}));
|
|
1041
|
+
state.state.processedVersions[object.id] = Obj4.encodeVersion(currentVersion);
|
|
1042
|
+
updated = true;
|
|
1043
|
+
}
|
|
1044
|
+
if (updated) {
|
|
1045
|
+
yield* TriggerStateStore.saveState(state);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
break;
|
|
1049
|
+
}
|
|
1050
|
+
default: {
|
|
1051
|
+
return yield* Effect5.dieMessage(`Unknown trigger kind: ${kind}`);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return invocations;
|
|
1056
|
+
}));
|
|
1057
|
+
_define_property4(this, "advanceTime", (duration) => Effect5.gen(this, function* () {
|
|
1058
|
+
if (this.timeControl !== "manual") {
|
|
1059
|
+
return yield* Effect5.dieMessage("advanceTime can only be used in manual time control mode");
|
|
1060
|
+
}
|
|
1061
|
+
const millis = Duration.toMillis(duration);
|
|
1062
|
+
this._internalTime = new Date(this._internalTime.getTime() + millis);
|
|
1063
|
+
log3("Advanced internal time", {
|
|
1064
|
+
newTime: this._internalTime,
|
|
1065
|
+
advancedBy: Duration.format(duration)
|
|
1066
|
+
}, {
|
|
1067
|
+
F: __dxlog_file3,
|
|
1068
|
+
L: 430,
|
|
1069
|
+
S: this,
|
|
1070
|
+
C: (f, a) => f(...a)
|
|
1071
|
+
});
|
|
1072
|
+
}).pipe(Effect5.orDie));
|
|
1073
|
+
_define_property4(this, "getCurrentTime", () => {
|
|
1074
|
+
if (this.timeControl === "natural") {
|
|
1075
|
+
return /* @__PURE__ */ new Date();
|
|
1076
|
+
} else {
|
|
1077
|
+
return new Date(this._internalTime);
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
_define_property4(this, "refreshTriggers", () => Effect5.gen(this, function* () {
|
|
1081
|
+
const triggers = yield* this._fetchTriggers();
|
|
1082
|
+
const currentTriggerIds = new Set(triggers.map((t) => t.id));
|
|
1083
|
+
for (const triggerId of this._scheduledTriggers.keys()) {
|
|
1084
|
+
if (!currentTriggerIds.has(triggerId)) {
|
|
1085
|
+
this._scheduledTriggers.delete(triggerId);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
for (const trigger of triggers) {
|
|
1089
|
+
if (trigger.spec?.kind === "timer" && trigger.enabled) {
|
|
1090
|
+
const timerSpec = trigger.spec;
|
|
1091
|
+
const cronEither = Cron.parse(timerSpec.cron);
|
|
1092
|
+
if (Either.isRight(cronEither)) {
|
|
1093
|
+
const cron = cronEither.right;
|
|
1094
|
+
const existing = this._scheduledTriggers.get(trigger.id);
|
|
1095
|
+
const now = this.getCurrentTime();
|
|
1096
|
+
const nextExecution = existing?.nextExecution ?? Cron.next(cron, now);
|
|
1097
|
+
log3("Updated scheduled trigger", {
|
|
1098
|
+
triggerId: trigger.id,
|
|
1099
|
+
cron: timerSpec.cron,
|
|
1100
|
+
nextExecution,
|
|
1101
|
+
now
|
|
1102
|
+
}, {
|
|
1103
|
+
F: __dxlog_file3,
|
|
1104
|
+
L: 470,
|
|
1105
|
+
S: this,
|
|
1106
|
+
C: (f, a) => f(...a)
|
|
1107
|
+
});
|
|
1108
|
+
this._scheduledTriggers.set(trigger.id, {
|
|
1109
|
+
trigger,
|
|
1110
|
+
cron,
|
|
1111
|
+
nextExecution
|
|
1112
|
+
});
|
|
1113
|
+
} else {
|
|
1114
|
+
log3.error("Invalid cron expression", {
|
|
1115
|
+
triggerId: trigger.id,
|
|
1116
|
+
cron: timerSpec.cron,
|
|
1117
|
+
error: cronEither.left.message
|
|
1118
|
+
}, {
|
|
1119
|
+
F: __dxlog_file3,
|
|
1120
|
+
L: 482,
|
|
1121
|
+
S: this,
|
|
1122
|
+
C: (f, a) => f(...a)
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
log3("Updated scheduled triggers", {
|
|
1128
|
+
count: this._scheduledTriggers.size
|
|
1129
|
+
}, {
|
|
1130
|
+
F: __dxlog_file3,
|
|
1131
|
+
L: 491,
|
|
1132
|
+
S: this,
|
|
1133
|
+
C: (f, a) => f(...a)
|
|
1134
|
+
});
|
|
1135
|
+
}).pipe(Effect5.withSpan("TriggerDispatcher.refreshTriggers")));
|
|
1136
|
+
_define_property4(this, "_fetchTriggers", () => Effect5.gen(this, function* () {
|
|
1137
|
+
const { objects } = yield* DatabaseService.runQuery(Filter.type(FunctionTrigger));
|
|
1138
|
+
return objects;
|
|
1139
|
+
}).pipe(Effect5.withSpan("TriggerDispatcher.fetchTriggers")));
|
|
1140
|
+
_define_property4(this, "_startNaturalTimeProcessing", () => Effect5.gen(this, function* () {
|
|
1141
|
+
yield* this.invokeScheduledTriggers();
|
|
1142
|
+
}).pipe(Effect5.repeat(Schedule.fixed(this.livePollInterval)), Effect5.asVoid));
|
|
1143
|
+
_define_property4(this, "_prepareInputData", (trigger, event) => {
|
|
1144
|
+
return createInvocationPayload(trigger, event);
|
|
1145
|
+
});
|
|
1146
|
+
this.timeControl = options.timeControl;
|
|
1147
|
+
this.livePollInterval = options.livePollInterval ?? Duration.seconds(1);
|
|
1148
|
+
this._internalTime = options.startingTime ?? /* @__PURE__ */ new Date();
|
|
1149
|
+
}
|
|
409
1150
|
};
|
|
1151
|
+
var KEY_QUEUE_CURSOR = "dxos.org/key/local-trigger-dispatcher/queue-cursor";
|
|
410
1152
|
|
|
411
|
-
//
|
|
412
|
-
import { Effect, Schema as
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
1153
|
+
// src/executor/executor.ts
|
|
1154
|
+
import { Effect as Effect6, Schema as Schema7 } from "effect";
|
|
1155
|
+
import { runAndForwardErrors } from "@dxos/effect";
|
|
1156
|
+
function _define_property5(obj, key, value) {
|
|
1157
|
+
if (key in obj) {
|
|
1158
|
+
Object.defineProperty(obj, key, {
|
|
1159
|
+
value,
|
|
1160
|
+
enumerable: true,
|
|
1161
|
+
configurable: true,
|
|
1162
|
+
writable: true
|
|
1163
|
+
});
|
|
1164
|
+
} else {
|
|
1165
|
+
obj[key] = value;
|
|
416
1166
|
}
|
|
1167
|
+
return obj;
|
|
1168
|
+
}
|
|
1169
|
+
var FunctionExecutor = class {
|
|
1170
|
+
/**
|
|
1171
|
+
* Invoke function.
|
|
1172
|
+
*/
|
|
417
1173
|
// TODO(dmaretskyi): Invocation context: queue, space, etc...
|
|
418
|
-
async invoke(
|
|
419
|
-
const assertInput =
|
|
1174
|
+
async invoke(functionDef, input) {
|
|
1175
|
+
const assertInput = functionDef.inputSchema.pipe(Schema7.asserts);
|
|
420
1176
|
assertInput(input);
|
|
421
1177
|
const context = {
|
|
1178
|
+
space: void 0,
|
|
422
1179
|
getService: this._services.getService.bind(this._services),
|
|
423
1180
|
getSpace: async (_spaceId) => {
|
|
424
1181
|
throw new Error("Not available. Use the database service instead.");
|
|
425
|
-
},
|
|
426
|
-
space: void 0,
|
|
427
|
-
get ai() {
|
|
428
|
-
throw new Error("Not available. Use the ai service instead.");
|
|
429
1182
|
}
|
|
430
1183
|
};
|
|
431
|
-
const result =
|
|
1184
|
+
const result = functionDef.handler({
|
|
432
1185
|
context,
|
|
433
1186
|
data: input
|
|
434
1187
|
});
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
1188
|
+
let data;
|
|
1189
|
+
if (Effect6.isEffect(result)) {
|
|
1190
|
+
data = await result.pipe(Effect6.provide(this._services.createLayer()), runAndForwardErrors);
|
|
1191
|
+
} else {
|
|
1192
|
+
data = await result;
|
|
439
1193
|
}
|
|
440
|
-
|
|
1194
|
+
const assertOutput = functionDef.outputSchema?.pipe(Schema7.asserts);
|
|
1195
|
+
assertOutput(data);
|
|
1196
|
+
return data;
|
|
1197
|
+
}
|
|
1198
|
+
constructor(_services) {
|
|
1199
|
+
_define_property5(this, "_services", void 0);
|
|
1200
|
+
this._services = _services;
|
|
441
1201
|
}
|
|
442
1202
|
};
|
|
1203
|
+
|
|
1204
|
+
// src/examples/index.ts
|
|
1205
|
+
var examples_exports = {};
|
|
1206
|
+
__export(examples_exports, {
|
|
1207
|
+
fib: () => fib_default,
|
|
1208
|
+
reply: () => reply_default,
|
|
1209
|
+
sleep: () => sleep_default
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1212
|
+
// src/examples/fib.ts
|
|
1213
|
+
import { Effect as Effect7, Schema as Schema8 } from "effect";
|
|
1214
|
+
var fib_default = defineFunction({
|
|
1215
|
+
name: "example.org/function/fib",
|
|
1216
|
+
description: "Function that calculates a Fibonacci number",
|
|
1217
|
+
inputSchema: Schema8.Struct({
|
|
1218
|
+
iterations: Schema8.optional(Schema8.Number).annotations({
|
|
1219
|
+
description: "Number of iterations",
|
|
1220
|
+
default: 1e5
|
|
1221
|
+
})
|
|
1222
|
+
}),
|
|
1223
|
+
outputSchema: Schema8.Struct({
|
|
1224
|
+
result: Schema8.String
|
|
1225
|
+
}),
|
|
1226
|
+
handler: Effect7.fn(function* ({ data: { iterations = 1e5 } }) {
|
|
1227
|
+
let a = 0n;
|
|
1228
|
+
let b = 1n;
|
|
1229
|
+
for (let i = 0; i < iterations; i++) {
|
|
1230
|
+
a += b;
|
|
1231
|
+
b = a - b;
|
|
1232
|
+
}
|
|
1233
|
+
return {
|
|
1234
|
+
result: a.toString()
|
|
1235
|
+
};
|
|
1236
|
+
})
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
// src/examples/reply.ts
|
|
1240
|
+
import { Console, Effect as Effect8, Schema as Schema9 } from "effect";
|
|
1241
|
+
var reply_default = defineFunction({
|
|
1242
|
+
name: "example.org/function/reply",
|
|
1243
|
+
description: "Function that echoes the input",
|
|
1244
|
+
inputSchema: Schema9.Any,
|
|
1245
|
+
outputSchema: Schema9.Any,
|
|
1246
|
+
handler: Effect8.fn(function* ({ data }) {
|
|
1247
|
+
yield* Console.log("reply", {
|
|
1248
|
+
data
|
|
1249
|
+
});
|
|
1250
|
+
return data;
|
|
1251
|
+
})
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
// src/examples/sleep.ts
|
|
1255
|
+
import { Effect as Effect9, Schema as Schema10 } from "effect";
|
|
1256
|
+
var sleep_default = defineFunction({
|
|
1257
|
+
name: "example.org/function/sleep",
|
|
1258
|
+
description: "Function that sleeps for a given amount of time",
|
|
1259
|
+
inputSchema: Schema10.Struct({
|
|
1260
|
+
duration: Schema10.optional(Schema10.Number).annotations({
|
|
1261
|
+
description: "Milliseconds to sleep",
|
|
1262
|
+
default: 1e5
|
|
1263
|
+
})
|
|
1264
|
+
}),
|
|
1265
|
+
outputSchema: Schema10.Void,
|
|
1266
|
+
handler: Effect9.fn(function* ({ data: { duration = 1e5 } }) {
|
|
1267
|
+
yield* Effect9.sleep(duration);
|
|
1268
|
+
})
|
|
1269
|
+
});
|
|
443
1270
|
export {
|
|
444
|
-
|
|
1271
|
+
ComputeEvent,
|
|
1272
|
+
ComputeEventLogger,
|
|
1273
|
+
ComputeEventPayload,
|
|
445
1274
|
ConfiguredCredentialsService,
|
|
1275
|
+
ContextQueueService,
|
|
446
1276
|
CredentialsService,
|
|
447
1277
|
DatabaseService,
|
|
448
1278
|
EmailTriggerOutput,
|
|
449
|
-
|
|
1279
|
+
FUNCTIONS_META_KEY,
|
|
450
1280
|
FUNCTIONS_PRESET_META_KEY,
|
|
451
1281
|
FUNCTION_TYPES,
|
|
452
|
-
|
|
1282
|
+
FunctionDefinition,
|
|
1283
|
+
FunctionError,
|
|
453
1284
|
FunctionExecutor,
|
|
1285
|
+
FunctionImplementationResolver,
|
|
454
1286
|
FunctionManifestSchema,
|
|
1287
|
+
FunctionNotFoundError,
|
|
455
1288
|
FunctionTrigger,
|
|
456
|
-
FunctionTriggerSchema,
|
|
457
1289
|
FunctionType,
|
|
458
1290
|
InvocationOutcome,
|
|
459
1291
|
InvocationTraceEndEvent,
|
|
460
1292
|
InvocationTraceEventType,
|
|
461
1293
|
InvocationTraceStartEvent,
|
|
1294
|
+
InvocationTracer,
|
|
1295
|
+
LocalFunctionExecutionService,
|
|
1296
|
+
MESSAGE_PROPERTY_TOOL_CALL_ID,
|
|
462
1297
|
QueueService,
|
|
463
1298
|
QueueTriggerOutput,
|
|
1299
|
+
RemoteFunctionExecutionService,
|
|
464
1300
|
SERVICE_TAGS,
|
|
465
1301
|
ScriptType,
|
|
466
1302
|
ServiceContainer,
|
|
1303
|
+
ServiceNotAvailableError,
|
|
467
1304
|
SubscriptionTriggerOutput,
|
|
468
1305
|
TimerTriggerOutput,
|
|
469
1306
|
TraceEvent,
|
|
470
1307
|
TraceEventException,
|
|
471
1308
|
TraceEventLog,
|
|
472
1309
|
TracingService,
|
|
473
|
-
|
|
1310
|
+
TriggerDispatcher,
|
|
1311
|
+
TriggerKinds,
|
|
474
1312
|
TriggerSchema,
|
|
1313
|
+
TriggerState,
|
|
1314
|
+
TriggerStateNotFoundError,
|
|
1315
|
+
TriggerStateStore,
|
|
475
1316
|
WebhookTriggerOutput,
|
|
476
1317
|
createDefectLogger,
|
|
477
1318
|
createEventLogger,
|
|
478
1319
|
createInvocationSpans,
|
|
479
1320
|
defineFunction,
|
|
1321
|
+
deserializeFunction,
|
|
1322
|
+
examples_exports as exampleFunctions,
|
|
480
1323
|
getInvocationUrl,
|
|
481
|
-
|
|
1324
|
+
getUserFunctionIdInMetadata,
|
|
482
1325
|
logCustomEvent,
|
|
483
|
-
|
|
484
|
-
|
|
1326
|
+
serializeFunction,
|
|
1327
|
+
setUserFunctionIdInMetadata,
|
|
1328
|
+
withAuthorization
|
|
485
1329
|
};
|
|
486
1330
|
//# sourceMappingURL=index.mjs.map
|