@dxos/functions 0.5.3-main.6e12b97 → 0.5.3-main.6f2dfea
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 +422 -663
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +419 -648
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/handler.d.ts +12 -32
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/runtime/dev-server.d.ts +10 -7
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.d.ts +59 -10
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/testing/test/handler.d.ts +0 -1
- package/dist/types/src/testing/test/handler.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +112 -118
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +13 -16
- package/schema/functions.json +103 -122
- package/src/handler.ts +27 -50
- package/src/index.ts +0 -2
- package/src/runtime/dev-server.test.ts +35 -15
- package/src/runtime/dev-server.ts +22 -40
- package/src/runtime/scheduler.test.ts +75 -54
- package/src/runtime/scheduler.ts +300 -67
- package/src/testing/test/handler.ts +2 -8
- package/src/types.ts +40 -56
- package/dist/types/src/registry/function-registry.d.ts +0 -24
- package/dist/types/src/registry/function-registry.d.ts.map +0 -1
- package/dist/types/src/registry/function-registry.test.d.ts +0 -2
- package/dist/types/src/registry/function-registry.test.d.ts.map +0 -1
- package/dist/types/src/registry/index.d.ts +0 -2
- package/dist/types/src/registry/index.d.ts.map +0 -1
- package/dist/types/src/testing/functions-integration.test.d.ts +0 -2
- package/dist/types/src/testing/functions-integration.test.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -4
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/setup.d.ts +0 -5
- package/dist/types/src/testing/setup.d.ts.map +0 -1
- package/dist/types/src/testing/types.d.ts +0 -9
- package/dist/types/src/testing/types.d.ts.map +0 -1
- package/dist/types/src/testing/util.d.ts +0 -3
- package/dist/types/src/testing/util.d.ts.map +0 -1
- package/dist/types/src/trigger/index.d.ts +0 -2
- package/dist/types/src/trigger/index.d.ts.map +0 -1
- package/dist/types/src/trigger/trigger-registry.d.ts +0 -40
- package/dist/types/src/trigger/trigger-registry.d.ts.map +0 -1
- package/dist/types/src/trigger/trigger-registry.test.d.ts +0 -2
- package/dist/types/src/trigger/trigger-registry.test.d.ts.map +0 -1
- package/dist/types/src/trigger/type/index.d.ts +0 -5
- package/dist/types/src/trigger/type/index.d.ts.map +0 -1
- package/dist/types/src/trigger/type/subscription-trigger.d.ts +0 -4
- package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +0 -1
- package/dist/types/src/trigger/type/timer-trigger.d.ts +0 -4
- package/dist/types/src/trigger/type/timer-trigger.d.ts.map +0 -1
- package/dist/types/src/trigger/type/webhook-trigger.d.ts +0 -4
- package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +0 -1
- package/dist/types/src/trigger/type/websocket-trigger.d.ts +0 -13
- package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +0 -1
- package/src/registry/function-registry.test.ts +0 -105
- package/src/registry/function-registry.ts +0 -84
- package/src/registry/index.ts +0 -5
- package/src/testing/functions-integration.test.ts +0 -99
- package/src/testing/index.ts +0 -7
- package/src/testing/setup.ts +0 -45
- package/src/testing/types.ts +0 -9
- package/src/testing/util.ts +0 -16
- package/src/trigger/index.ts +0 -5
- package/src/trigger/trigger-registry.test.ts +0 -229
- package/src/trigger/trigger-registry.ts +0 -176
- package/src/trigger/type/index.ts +0 -8
- package/src/trigger/type/subscription-trigger.ts +0 -73
- package/src/trigger/type/timer-trigger.ts +0 -44
- package/src/trigger/type/webhook-trigger.ts +0 -47
- package/src/trigger/type/websocket-trigger.ts +0 -91
package/dist/lib/node/index.cjs
CHANGED
|
@@ -29,54 +29,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
var node_exports = {};
|
|
30
30
|
__export(node_exports, {
|
|
31
31
|
DevServer: () => DevServer,
|
|
32
|
-
FunctionDef: () => FunctionDef,
|
|
33
32
|
FunctionManifestSchema: () => FunctionManifestSchema,
|
|
34
|
-
FunctionRegistry: () => FunctionRegistry,
|
|
35
|
-
FunctionTrigger: () => FunctionTrigger,
|
|
36
33
|
Scheduler: () => Scheduler,
|
|
37
|
-
TriggerRegistry: () => TriggerRegistry,
|
|
38
34
|
subscriptionHandler: () => subscriptionHandler
|
|
39
35
|
});
|
|
40
36
|
module.exports = __toCommonJS(node_exports);
|
|
41
37
|
var import_client = require("@dxos/client");
|
|
42
38
|
var import_log = require("@dxos/log");
|
|
43
39
|
var import_util = require("@dxos/util");
|
|
44
|
-
var import_async = require("@dxos/async");
|
|
45
|
-
var import_echo = require("@dxos/client/echo");
|
|
46
|
-
var import_context = require("@dxos/context");
|
|
47
|
-
var import_keys = require("@dxos/keys");
|
|
48
|
-
var import_util2 = require("@dxos/util");
|
|
49
|
-
var import_echo_schema = require("@dxos/echo-schema");
|
|
50
40
|
var import_express = __toESM(require("express"));
|
|
51
41
|
var import_get_port_please = require("get-port-please");
|
|
52
42
|
var import_node_path = require("node:path");
|
|
53
|
-
var
|
|
54
|
-
var import_context2 = require("@dxos/context");
|
|
43
|
+
var import_async = require("@dxos/async");
|
|
55
44
|
var import_invariant = require("@dxos/invariant");
|
|
56
45
|
var import_log2 = require("@dxos/log");
|
|
57
|
-
var import_node_path2 = __toESM(require("node:path"));
|
|
58
|
-
var import_context3 = require("@dxos/context");
|
|
59
|
-
var import_log3 = require("@dxos/log");
|
|
60
|
-
var import_async3 = require("@dxos/async");
|
|
61
|
-
var import_echo2 = require("@dxos/client/echo");
|
|
62
|
-
var import_context4 = require("@dxos/context");
|
|
63
|
-
var import_invariant2 = require("@dxos/invariant");
|
|
64
|
-
var import_keys2 = require("@dxos/keys");
|
|
65
|
-
var import_log4 = require("@dxos/log");
|
|
66
|
-
var import_util3 = require("@dxos/util");
|
|
67
|
-
var import_types = require("@braneframe/types");
|
|
68
|
-
var import_async4 = require("@dxos/async");
|
|
69
|
-
var import_echo_db = require("@dxos/echo-db");
|
|
70
|
-
var import_log5 = require("@dxos/log");
|
|
71
46
|
var import_cron = require("cron");
|
|
72
|
-
var import_async5 = require("@dxos/async");
|
|
73
|
-
var import_log6 = require("@dxos/log");
|
|
74
47
|
var import_get_port_please2 = require("get-port-please");
|
|
75
48
|
var import_node_http = __toESM(require("node:http"));
|
|
76
|
-
var
|
|
49
|
+
var import_node_path2 = __toESM(require("node:path"));
|
|
77
50
|
var import_ws = __toESM(require("ws"));
|
|
78
|
-
var
|
|
79
|
-
var
|
|
51
|
+
var import_types = require("@braneframe/types");
|
|
52
|
+
var import_async2 = require("@dxos/async");
|
|
53
|
+
var import_echo = require("@dxos/client/echo");
|
|
54
|
+
var import_context = require("@dxos/context");
|
|
55
|
+
var import_invariant2 = require("@dxos/invariant");
|
|
56
|
+
var import_log3 = require("@dxos/log");
|
|
57
|
+
var import_util2 = require("@dxos/util");
|
|
58
|
+
var S = __toESM(require("@effect/schema/Schema"));
|
|
80
59
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
81
60
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
82
61
|
}) : x)(function(x) {
|
|
@@ -86,16 +65,16 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
86
65
|
});
|
|
87
66
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/handler.ts";
|
|
88
67
|
var subscriptionHandler = (handler) => {
|
|
89
|
-
return ({ event
|
|
68
|
+
return ({ event, context, ...rest }) => {
|
|
90
69
|
const { client } = context;
|
|
91
|
-
const space =
|
|
92
|
-
const objects = space
|
|
93
|
-
if (!!
|
|
70
|
+
const space = event.spaceKey ? client.spaces.get(import_client.PublicKey.from(event.spaceKey)) : void 0;
|
|
71
|
+
const objects = space && event.objects?.map((id) => space.db.getObjectById(id)).filter(import_util.nonNullable);
|
|
72
|
+
if (!!event.spaceKey && !space) {
|
|
94
73
|
import_log.log.warn("invalid space", {
|
|
95
|
-
|
|
74
|
+
event
|
|
96
75
|
}, {
|
|
97
76
|
F: __dxlog_file,
|
|
98
|
-
L:
|
|
77
|
+
L: 68,
|
|
99
78
|
S: void 0,
|
|
100
79
|
C: (f, a) => f(...a)
|
|
101
80
|
});
|
|
@@ -105,168 +84,30 @@ var subscriptionHandler = (handler) => {
|
|
|
105
84
|
objects: objects?.length
|
|
106
85
|
}, {
|
|
107
86
|
F: __dxlog_file,
|
|
108
|
-
L:
|
|
87
|
+
L: 70,
|
|
109
88
|
S: void 0,
|
|
110
89
|
C: (f, a) => f(...a)
|
|
111
90
|
});
|
|
112
91
|
}
|
|
113
92
|
return handler({
|
|
114
93
|
event: {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
space,
|
|
118
|
-
objects
|
|
119
|
-
}
|
|
94
|
+
space,
|
|
95
|
+
objects
|
|
120
96
|
},
|
|
121
97
|
context,
|
|
122
98
|
...rest
|
|
123
99
|
});
|
|
124
100
|
};
|
|
125
101
|
};
|
|
126
|
-
var omitEchoId = (schema) => import_echo_schema.S.make(import_echo_schema.AST.omit(schema.ast, [
|
|
127
|
-
"id"
|
|
128
|
-
]));
|
|
129
|
-
var SubscriptionTriggerSchema = import_echo_schema.S.struct({
|
|
130
|
-
type: import_echo_schema.S.literal("subscription"),
|
|
131
|
-
// TODO(burdon): Define query DSL.
|
|
132
|
-
filter: import_echo_schema.S.array(import_echo_schema.S.struct({
|
|
133
|
-
type: import_echo_schema.S.string,
|
|
134
|
-
props: import_echo_schema.S.optional(import_echo_schema.S.record(import_echo_schema.S.string, import_echo_schema.S.any))
|
|
135
|
-
})),
|
|
136
|
-
options: import_echo_schema.S.optional(import_echo_schema.S.struct({
|
|
137
|
-
// Watch changes to object (not just creation).
|
|
138
|
-
deep: import_echo_schema.S.optional(import_echo_schema.S.boolean),
|
|
139
|
-
// Debounce changes (delay in ms).
|
|
140
|
-
delay: import_echo_schema.S.optional(import_echo_schema.S.number)
|
|
141
|
-
}))
|
|
142
|
-
});
|
|
143
|
-
var TimerTriggerSchema = import_echo_schema.S.struct({
|
|
144
|
-
type: import_echo_schema.S.literal("timer"),
|
|
145
|
-
cron: import_echo_schema.S.string
|
|
146
|
-
});
|
|
147
|
-
var WebhookTriggerSchema = import_echo_schema.S.mutable(import_echo_schema.S.struct({
|
|
148
|
-
type: import_echo_schema.S.literal("webhook"),
|
|
149
|
-
method: import_echo_schema.S.string,
|
|
150
|
-
// Assigned port.
|
|
151
|
-
port: import_echo_schema.S.optional(import_echo_schema.S.number)
|
|
152
|
-
}));
|
|
153
|
-
var WebsocketTriggerSchema = import_echo_schema.S.struct({
|
|
154
|
-
type: import_echo_schema.S.literal("websocket"),
|
|
155
|
-
url: import_echo_schema.S.string,
|
|
156
|
-
init: import_echo_schema.S.optional(import_echo_schema.S.record(import_echo_schema.S.string, import_echo_schema.S.any))
|
|
157
|
-
});
|
|
158
|
-
var TriggerSpecSchema = import_echo_schema.S.union(TimerTriggerSchema, WebhookTriggerSchema, WebsocketTriggerSchema, SubscriptionTriggerSchema);
|
|
159
|
-
var FunctionDef = class extends (0, import_echo_schema.TypedObject)({
|
|
160
|
-
typename: "dxos.org/type/FunctionDef",
|
|
161
|
-
version: "0.1.0"
|
|
162
|
-
})({
|
|
163
|
-
uri: import_echo_schema.S.string,
|
|
164
|
-
description: import_echo_schema.S.optional(import_echo_schema.S.string),
|
|
165
|
-
route: import_echo_schema.S.string,
|
|
166
|
-
// TODO(burdon): NPM/GitHub/Docker/CF URL?
|
|
167
|
-
handler: import_echo_schema.S.string
|
|
168
|
-
}) {
|
|
169
|
-
};
|
|
170
|
-
var FunctionTrigger = class extends (0, import_echo_schema.TypedObject)({
|
|
171
|
-
typename: "dxos.org/type/FunctionTrigger",
|
|
172
|
-
version: "0.1.0"
|
|
173
|
-
})({
|
|
174
|
-
function: import_echo_schema.S.string.pipe(import_echo_schema.S.description("Function ID/URI.")),
|
|
175
|
-
// Context passed to a function.
|
|
176
|
-
meta: import_echo_schema.S.optional(import_echo_schema.S.record(import_echo_schema.S.string, import_echo_schema.S.any)),
|
|
177
|
-
spec: TriggerSpecSchema
|
|
178
|
-
}) {
|
|
179
|
-
};
|
|
180
|
-
var FunctionManifestSchema = import_echo_schema.S.struct({
|
|
181
|
-
functions: import_echo_schema.S.optional(import_echo_schema.S.mutable(import_echo_schema.S.array(omitEchoId(FunctionDef)))),
|
|
182
|
-
triggers: import_echo_schema.S.optional(import_echo_schema.S.mutable(import_echo_schema.S.array(omitEchoId(FunctionTrigger))))
|
|
183
|
-
});
|
|
184
|
-
var FunctionRegistry = class extends import_context.Resource {
|
|
185
|
-
constructor(_client) {
|
|
186
|
-
super();
|
|
187
|
-
this._client = _client;
|
|
188
|
-
this._functionBySpaceKey = new import_util2.ComplexMap(import_keys.PublicKey.hash);
|
|
189
|
-
this.onFunctionsRegistered = new import_async.Event();
|
|
190
|
-
}
|
|
191
|
-
getFunctions(space) {
|
|
192
|
-
return this._functionBySpaceKey.get(space.key) ?? [];
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* The method loads function definitions from the manifest into the space.
|
|
196
|
-
* We first load all the definitions from the space to deduplicate by functionId.
|
|
197
|
-
*/
|
|
198
|
-
// TODO(burdon): This should not be space specific (they are static for the agent).
|
|
199
|
-
async register(space, manifest) {
|
|
200
|
-
if (!manifest.functions?.length) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (!space.db.graph.runtimeSchemaRegistry.isSchemaRegistered(FunctionDef)) {
|
|
204
|
-
space.db.graph.runtimeSchemaRegistry.registerSchema(FunctionDef);
|
|
205
|
-
}
|
|
206
|
-
const { objects: existingDefinitions } = await space.db.query(import_echo.Filter.schema(FunctionDef)).run();
|
|
207
|
-
const newDefinitions = getNewDefinitions(manifest.functions, existingDefinitions);
|
|
208
|
-
const reactiveObjects = newDefinitions.map((template) => (0, import_echo.create)(FunctionDef, {
|
|
209
|
-
...template
|
|
210
|
-
}));
|
|
211
|
-
reactiveObjects.forEach((obj) => space.db.add(obj));
|
|
212
|
-
}
|
|
213
|
-
async _open() {
|
|
214
|
-
const spaceListSubscription = this._client.spaces.subscribe(async (spaces) => {
|
|
215
|
-
for (const space of spaces) {
|
|
216
|
-
if (this._functionBySpaceKey.has(space.key)) {
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
const registered = [];
|
|
220
|
-
this._functionBySpaceKey.set(space.key, registered);
|
|
221
|
-
await space.waitUntilReady();
|
|
222
|
-
if (this._ctx.disposed) {
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
225
|
-
const functionsSubscription = space.db.query(import_echo.Filter.schema(FunctionDef)).subscribe((definitions) => {
|
|
226
|
-
const newFunctions = getNewDefinitions(definitions.objects, registered);
|
|
227
|
-
if (newFunctions.length > 0) {
|
|
228
|
-
registered.push(...newFunctions);
|
|
229
|
-
this.onFunctionsRegistered.emit({
|
|
230
|
-
space,
|
|
231
|
-
newFunctions
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
this._ctx.onDispose(functionsSubscription);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
this._ctx.onDispose(() => spaceListSubscription.unsubscribe());
|
|
239
|
-
}
|
|
240
|
-
async _close(_) {
|
|
241
|
-
this._functionBySpaceKey.clear();
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
var getNewDefinitions = (candidateList, existing) => {
|
|
245
|
-
return candidateList.filter((candidate) => existing.find((def) => def.uri === candidate.uri) == null);
|
|
246
|
-
};
|
|
247
102
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
248
103
|
var DevServer = class {
|
|
249
104
|
// prettier-ignore
|
|
250
|
-
constructor(_client,
|
|
105
|
+
constructor(_client, _options) {
|
|
251
106
|
this._client = _client;
|
|
252
|
-
this._functionsRegistry = _functionsRegistry;
|
|
253
107
|
this._options = _options;
|
|
254
|
-
this._ctx = createContext();
|
|
255
108
|
this._handlers = {};
|
|
256
109
|
this._seq = 0;
|
|
257
|
-
this.update = new
|
|
258
|
-
this._functionsRegistry.onFunctionsRegistered.on(async ({ newFunctions }) => {
|
|
259
|
-
newFunctions.forEach((def) => this._load(def));
|
|
260
|
-
await this._safeUpdateRegistration();
|
|
261
|
-
(0, import_log2.log)("new functions loaded", {
|
|
262
|
-
newFunctions
|
|
263
|
-
}, {
|
|
264
|
-
F: __dxlog_file2,
|
|
265
|
-
L: 53,
|
|
266
|
-
S: this,
|
|
267
|
-
C: (f, a) => f(...a)
|
|
268
|
-
});
|
|
269
|
-
});
|
|
110
|
+
this.update = new import_async.Event();
|
|
270
111
|
}
|
|
271
112
|
get stats() {
|
|
272
113
|
return {
|
|
@@ -276,7 +117,7 @@ var DevServer = class {
|
|
|
276
117
|
get endpoint() {
|
|
277
118
|
(0, import_invariant.invariant)(this._port, void 0, {
|
|
278
119
|
F: __dxlog_file2,
|
|
279
|
-
L:
|
|
120
|
+
L: 54,
|
|
280
121
|
S: this,
|
|
281
122
|
A: [
|
|
282
123
|
"this._port",
|
|
@@ -291,6 +132,20 @@ var DevServer = class {
|
|
|
291
132
|
get functions() {
|
|
292
133
|
return Object.values(this._handlers);
|
|
293
134
|
}
|
|
135
|
+
async initialize() {
|
|
136
|
+
for (const def of this._options.manifest.functions) {
|
|
137
|
+
try {
|
|
138
|
+
await this._load(def);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
import_log2.log.error("parsing function (check manifest)", err, {
|
|
141
|
+
F: __dxlog_file2,
|
|
142
|
+
L: 71,
|
|
143
|
+
S: this,
|
|
144
|
+
C: (f, a) => f(...a)
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
294
149
|
async start() {
|
|
295
150
|
(0, import_invariant.invariant)(!this._server, void 0, {
|
|
296
151
|
F: __dxlog_file2,
|
|
@@ -307,7 +162,6 @@ var DevServer = class {
|
|
|
307
162
|
S: this,
|
|
308
163
|
C: (f, a) => f(...a)
|
|
309
164
|
});
|
|
310
|
-
this._ctx = createContext();
|
|
311
165
|
const app = (0, import_express.default)();
|
|
312
166
|
app.use(import_express.default.json());
|
|
313
167
|
app.post("/:path", async (req, res) => {
|
|
@@ -317,7 +171,7 @@ var DevServer = class {
|
|
|
317
171
|
path: path2
|
|
318
172
|
}, {
|
|
319
173
|
F: __dxlog_file2,
|
|
320
|
-
L:
|
|
174
|
+
L: 87,
|
|
321
175
|
S: this,
|
|
322
176
|
C: (f, a) => f(...a)
|
|
323
177
|
});
|
|
@@ -330,7 +184,7 @@ var DevServer = class {
|
|
|
330
184
|
} catch (err) {
|
|
331
185
|
import_log2.log.catch(err, void 0, {
|
|
332
186
|
F: __dxlog_file2,
|
|
333
|
-
L:
|
|
187
|
+
L: 97,
|
|
334
188
|
S: this,
|
|
335
189
|
C: (f, a) => f(...a)
|
|
336
190
|
});
|
|
@@ -349,7 +203,11 @@ var DevServer = class {
|
|
|
349
203
|
this._server = app.listen(this._port);
|
|
350
204
|
try {
|
|
351
205
|
const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
|
|
352
|
-
endpoint: this.endpoint
|
|
206
|
+
endpoint: this.endpoint,
|
|
207
|
+
functions: this.functions.map(({ def: { id, path: path2 } }) => ({
|
|
208
|
+
id,
|
|
209
|
+
path: path2
|
|
210
|
+
}))
|
|
353
211
|
});
|
|
354
212
|
import_log2.log.info("registered", {
|
|
355
213
|
endpoint
|
|
@@ -361,7 +219,6 @@ var DevServer = class {
|
|
|
361
219
|
});
|
|
362
220
|
this._proxy = endpoint;
|
|
363
221
|
this._functionServiceRegistration = registrationId;
|
|
364
|
-
await this._functionsRegistry.open(this._ctx);
|
|
365
222
|
} catch (err) {
|
|
366
223
|
await this.stop();
|
|
367
224
|
throw new Error("FunctionRegistryService not available (check plugin is configured).");
|
|
@@ -370,7 +227,7 @@ var DevServer = class {
|
|
|
370
227
|
port: this._port
|
|
371
228
|
}, {
|
|
372
229
|
F: __dxlog_file2,
|
|
373
|
-
L:
|
|
230
|
+
L: 121,
|
|
374
231
|
S: this,
|
|
375
232
|
C: (f, a) => f(...a)
|
|
376
233
|
});
|
|
@@ -378,7 +235,7 @@ var DevServer = class {
|
|
|
378
235
|
async stop() {
|
|
379
236
|
(0, import_invariant.invariant)(this._server, void 0, {
|
|
380
237
|
F: __dxlog_file2,
|
|
381
|
-
L:
|
|
238
|
+
L: 125,
|
|
382
239
|
S: this,
|
|
383
240
|
A: [
|
|
384
241
|
"this._server",
|
|
@@ -387,15 +244,15 @@ var DevServer = class {
|
|
|
387
244
|
});
|
|
388
245
|
import_log2.log.info("stopping...", void 0, {
|
|
389
246
|
F: __dxlog_file2,
|
|
390
|
-
L:
|
|
247
|
+
L: 126,
|
|
391
248
|
S: this,
|
|
392
249
|
C: (f, a) => f(...a)
|
|
393
250
|
});
|
|
394
|
-
const trigger = new
|
|
251
|
+
const trigger = new import_async.Trigger();
|
|
395
252
|
this._server.close(async () => {
|
|
396
253
|
import_log2.log.info("server stopped", void 0, {
|
|
397
254
|
F: __dxlog_file2,
|
|
398
|
-
L:
|
|
255
|
+
L: 130,
|
|
399
256
|
S: this,
|
|
400
257
|
C: (f, a) => f(...a)
|
|
401
258
|
});
|
|
@@ -403,7 +260,7 @@ var DevServer = class {
|
|
|
403
260
|
if (this._functionServiceRegistration) {
|
|
404
261
|
(0, import_invariant.invariant)(this._client.services.services.FunctionRegistryService, void 0, {
|
|
405
262
|
F: __dxlog_file2,
|
|
406
|
-
L:
|
|
263
|
+
L: 133,
|
|
407
264
|
S: this,
|
|
408
265
|
A: [
|
|
409
266
|
"this._client.services.services.FunctionRegistryService",
|
|
@@ -417,7 +274,7 @@ var DevServer = class {
|
|
|
417
274
|
registrationId: this._functionServiceRegistration
|
|
418
275
|
}, {
|
|
419
276
|
F: __dxlog_file2,
|
|
420
|
-
L:
|
|
277
|
+
L: 138,
|
|
421
278
|
S: this,
|
|
422
279
|
C: (f, a) => f(...a)
|
|
423
280
|
});
|
|
@@ -434,7 +291,7 @@ var DevServer = class {
|
|
|
434
291
|
this._server = void 0;
|
|
435
292
|
import_log2.log.info("stopped", void 0, {
|
|
436
293
|
F: __dxlog_file2,
|
|
437
|
-
L:
|
|
294
|
+
L: 152,
|
|
438
295
|
S: this,
|
|
439
296
|
C: (f, a) => f(...a)
|
|
440
297
|
});
|
|
@@ -443,14 +300,14 @@ var DevServer = class {
|
|
|
443
300
|
* Load function.
|
|
444
301
|
*/
|
|
445
302
|
async _load(def, force = false) {
|
|
446
|
-
const {
|
|
303
|
+
const { id, path: path2, handler } = def;
|
|
447
304
|
const filePath = (0, import_node_path.join)(this._options.baseDir, handler);
|
|
448
305
|
import_log2.log.info("loading", {
|
|
449
|
-
|
|
306
|
+
id,
|
|
450
307
|
force
|
|
451
308
|
}, {
|
|
452
309
|
F: __dxlog_file2,
|
|
453
|
-
L:
|
|
310
|
+
L: 161,
|
|
454
311
|
S: this,
|
|
455
312
|
C: (f, a) => f(...a)
|
|
456
313
|
});
|
|
@@ -461,40 +318,13 @@ var DevServer = class {
|
|
|
461
318
|
}
|
|
462
319
|
const module2 = __require(filePath);
|
|
463
320
|
if (typeof module2.default !== "function") {
|
|
464
|
-
throw new Error(`Handler must export default function: ${
|
|
321
|
+
throw new Error(`Handler must export default function: ${id}`);
|
|
465
322
|
}
|
|
466
|
-
this._handlers[
|
|
323
|
+
this._handlers[path2] = {
|
|
467
324
|
def,
|
|
468
325
|
handler: module2.default
|
|
469
326
|
};
|
|
470
327
|
}
|
|
471
|
-
async _safeUpdateRegistration() {
|
|
472
|
-
(0, import_invariant.invariant)(this._functionServiceRegistration, void 0, {
|
|
473
|
-
F: __dxlog_file2,
|
|
474
|
-
L: 186,
|
|
475
|
-
S: this,
|
|
476
|
-
A: [
|
|
477
|
-
"this._functionServiceRegistration",
|
|
478
|
-
""
|
|
479
|
-
]
|
|
480
|
-
});
|
|
481
|
-
try {
|
|
482
|
-
await this._client.services.services.FunctionRegistryService.updateRegistration({
|
|
483
|
-
registrationId: this._functionServiceRegistration,
|
|
484
|
-
functions: this.functions.map(({ def: { id, route } }) => ({
|
|
485
|
-
id,
|
|
486
|
-
route
|
|
487
|
-
}))
|
|
488
|
-
});
|
|
489
|
-
} catch (e) {
|
|
490
|
-
import_log2.log.catch(e, void 0, {
|
|
491
|
-
F: __dxlog_file2,
|
|
492
|
-
L: 193,
|
|
493
|
-
S: this,
|
|
494
|
-
C: (f, a) => f(...a)
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
328
|
/**
|
|
499
329
|
* Invoke function.
|
|
500
330
|
*/
|
|
@@ -506,13 +336,11 @@ var DevServer = class {
|
|
|
506
336
|
path: path2
|
|
507
337
|
}, {
|
|
508
338
|
F: __dxlog_file2,
|
|
509
|
-
L:
|
|
339
|
+
L: 188,
|
|
510
340
|
S: this,
|
|
511
341
|
C: (f, a) => f(...a)
|
|
512
342
|
});
|
|
513
|
-
const statusCode = await this._invoke(path2,
|
|
514
|
-
data
|
|
515
|
-
});
|
|
343
|
+
const statusCode = await this._invoke(path2, data);
|
|
516
344
|
import_log2.log.info("res", {
|
|
517
345
|
seq,
|
|
518
346
|
path: path2,
|
|
@@ -520,7 +348,7 @@ var DevServer = class {
|
|
|
520
348
|
duration: Date.now() - now
|
|
521
349
|
}, {
|
|
522
350
|
F: __dxlog_file2,
|
|
523
|
-
L:
|
|
351
|
+
L: 191,
|
|
524
352
|
S: this,
|
|
525
353
|
C: (f, a) => f(...a)
|
|
526
354
|
});
|
|
@@ -531,7 +359,7 @@ var DevServer = class {
|
|
|
531
359
|
const { handler } = this._handlers[path2] ?? {};
|
|
532
360
|
(0, import_invariant.invariant)(handler, `invalid path: ${path2}`, {
|
|
533
361
|
F: __dxlog_file2,
|
|
534
|
-
L:
|
|
362
|
+
L: 198,
|
|
535
363
|
S: this,
|
|
536
364
|
A: [
|
|
537
365
|
"handler",
|
|
@@ -557,93 +385,109 @@ var DevServer = class {
|
|
|
557
385
|
return statusCode;
|
|
558
386
|
}
|
|
559
387
|
};
|
|
560
|
-
var createContext = () => new import_context2.Context({
|
|
561
|
-
name: "DevServer"
|
|
562
|
-
});
|
|
563
388
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
564
389
|
var Scheduler = class {
|
|
565
|
-
constructor(
|
|
566
|
-
this.
|
|
567
|
-
this.
|
|
390
|
+
constructor(_client, _manifest, _options = {}) {
|
|
391
|
+
this._client = _client;
|
|
392
|
+
this._manifest = _manifest;
|
|
568
393
|
this._options = _options;
|
|
569
|
-
this.
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
})
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
});
|
|
394
|
+
this._mounts = new import_util2.ComplexMap(({ spaceKey, id }) => `${spaceKey.toHex()}:${id}`);
|
|
395
|
+
}
|
|
396
|
+
get mounts() {
|
|
397
|
+
return Array.from(this._mounts.values()).reduce((acc, { trigger }) => {
|
|
398
|
+
acc.push(trigger);
|
|
399
|
+
return acc;
|
|
400
|
+
}, []);
|
|
576
401
|
}
|
|
577
402
|
async start() {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
403
|
+
this._client.spaces.subscribe(async (spaces) => {
|
|
404
|
+
for (const space of spaces) {
|
|
405
|
+
await space.waitUntilReady();
|
|
406
|
+
for (const trigger of this._manifest.triggers ?? []) {
|
|
407
|
+
await this.mount(new import_context.Context(), space, trigger);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
});
|
|
582
411
|
}
|
|
583
412
|
async stop() {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
async register(space, manifest) {
|
|
589
|
-
await this.functions.register(space, manifest);
|
|
590
|
-
await this.triggers.register(space, manifest);
|
|
413
|
+
for (const { id, spaceKey } of this._mounts.keys()) {
|
|
414
|
+
await this.unmount(id, spaceKey);
|
|
415
|
+
}
|
|
591
416
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
417
|
+
/**
|
|
418
|
+
* Mount trigger.
|
|
419
|
+
*/
|
|
420
|
+
async mount(ctx, space, trigger) {
|
|
421
|
+
const key = {
|
|
422
|
+
spaceKey: space.key,
|
|
423
|
+
id: trigger.function
|
|
424
|
+
};
|
|
425
|
+
const def = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
426
|
+
(0, import_invariant2.invariant)(def, `Function not found: ${trigger.function}`, {
|
|
427
|
+
F: __dxlog_file3,
|
|
428
|
+
L: 83,
|
|
429
|
+
S: this,
|
|
430
|
+
A: [
|
|
431
|
+
"def",
|
|
432
|
+
"`Function not found: ${trigger.function}`"
|
|
433
|
+
]
|
|
595
434
|
});
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
435
|
+
const exists = this._mounts.get(key);
|
|
436
|
+
if (!exists) {
|
|
437
|
+
this._mounts.set(key, {
|
|
438
|
+
ctx,
|
|
439
|
+
trigger
|
|
440
|
+
});
|
|
441
|
+
(0, import_log3.log)("mount", {
|
|
442
|
+
space: space.key,
|
|
443
|
+
trigger
|
|
603
444
|
}, {
|
|
604
445
|
F: __dxlog_file3,
|
|
605
|
-
L:
|
|
446
|
+
L: 89,
|
|
606
447
|
S: this,
|
|
607
448
|
C: (f, a) => f(...a)
|
|
608
449
|
});
|
|
609
|
-
|
|
450
|
+
if (ctx.disposed) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (trigger.timer) {
|
|
454
|
+
await this._createTimer(ctx, space, def, trigger.timer);
|
|
455
|
+
}
|
|
456
|
+
if (trigger.webhook) {
|
|
457
|
+
await this._createWebhook(ctx, space, def, trigger.webhook);
|
|
458
|
+
}
|
|
459
|
+
if (trigger.websocket) {
|
|
460
|
+
await this._createWebsocket(ctx, space, def, trigger.websocket);
|
|
461
|
+
}
|
|
462
|
+
if (trigger.subscription) {
|
|
463
|
+
await this._createSubscription(ctx, space, def, trigger.subscription);
|
|
464
|
+
}
|
|
610
465
|
}
|
|
611
|
-
await this.triggers.activate({
|
|
612
|
-
space
|
|
613
|
-
}, fnTrigger, async (args) => {
|
|
614
|
-
return this._execFunction(definition, {
|
|
615
|
-
meta: fnTrigger.meta,
|
|
616
|
-
data: {
|
|
617
|
-
...args,
|
|
618
|
-
spaceKey: space.key
|
|
619
|
-
}
|
|
620
|
-
});
|
|
621
|
-
});
|
|
622
|
-
(0, import_log3.log)("activated trigger", {
|
|
623
|
-
space: space.key,
|
|
624
|
-
trigger: fnTrigger
|
|
625
|
-
}, {
|
|
626
|
-
F: __dxlog_file3,
|
|
627
|
-
L: 84,
|
|
628
|
-
S: this,
|
|
629
|
-
C: (f, a) => f(...a)
|
|
630
|
-
});
|
|
631
466
|
}
|
|
632
|
-
async
|
|
633
|
-
|
|
467
|
+
async unmount(id, spaceKey) {
|
|
468
|
+
const key = {
|
|
469
|
+
id,
|
|
470
|
+
spaceKey
|
|
471
|
+
};
|
|
472
|
+
const { ctx } = this._mounts.get(key) ?? {};
|
|
473
|
+
if (ctx) {
|
|
474
|
+
this._mounts.delete(key);
|
|
475
|
+
await ctx.dispose();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
// TODO(burdon): Pass in Space key (common context).
|
|
479
|
+
async _execFunction(def, data) {
|
|
634
480
|
try {
|
|
635
|
-
|
|
636
|
-
meta
|
|
637
|
-
}, data);
|
|
481
|
+
let status = 0;
|
|
638
482
|
const { endpoint, callback } = this._options;
|
|
639
483
|
if (endpoint) {
|
|
640
|
-
const url = import_node_path2.default.join(endpoint, def.
|
|
484
|
+
const url = import_node_path2.default.join(endpoint, def.path);
|
|
641
485
|
import_log3.log.info("exec", {
|
|
642
|
-
function: def.
|
|
486
|
+
function: def.id,
|
|
643
487
|
url
|
|
644
488
|
}, {
|
|
645
489
|
F: __dxlog_file3,
|
|
646
|
-
L:
|
|
490
|
+
L: 133,
|
|
647
491
|
S: this,
|
|
648
492
|
C: (f, a) => f(...a)
|
|
649
493
|
});
|
|
@@ -652,431 +496,358 @@ var Scheduler = class {
|
|
|
652
496
|
headers: {
|
|
653
497
|
"Content-Type": "application/json"
|
|
654
498
|
},
|
|
655
|
-
body: JSON.stringify(
|
|
499
|
+
body: JSON.stringify(data)
|
|
656
500
|
});
|
|
657
501
|
status = response.status;
|
|
658
502
|
} else if (callback) {
|
|
659
503
|
import_log3.log.info("exec", {
|
|
660
|
-
function: def.
|
|
504
|
+
function: def.id
|
|
661
505
|
}, {
|
|
662
506
|
F: __dxlog_file3,
|
|
663
|
-
L:
|
|
507
|
+
L: 144,
|
|
664
508
|
S: this,
|
|
665
509
|
C: (f, a) => f(...a)
|
|
666
510
|
});
|
|
667
|
-
status = await callback(
|
|
511
|
+
status = await callback(data) ?? 200;
|
|
668
512
|
}
|
|
669
513
|
if (status && status >= 400) {
|
|
670
514
|
throw new Error(`Response: ${status}`);
|
|
671
515
|
}
|
|
672
516
|
import_log3.log.info("done", {
|
|
673
|
-
function: def.
|
|
517
|
+
function: def.id,
|
|
674
518
|
status
|
|
675
519
|
}, {
|
|
676
520
|
F: __dxlog_file3,
|
|
677
|
-
L:
|
|
521
|
+
L: 154,
|
|
678
522
|
S: this,
|
|
679
523
|
C: (f, a) => f(...a)
|
|
680
524
|
});
|
|
525
|
+
return status;
|
|
681
526
|
} catch (err) {
|
|
682
527
|
import_log3.log.error("error", {
|
|
683
|
-
function: def.
|
|
528
|
+
function: def.id,
|
|
684
529
|
error: err.message
|
|
685
530
|
}, {
|
|
686
531
|
F: __dxlog_file3,
|
|
687
|
-
L:
|
|
532
|
+
L: 157,
|
|
688
533
|
S: this,
|
|
689
534
|
C: (f, a) => f(...a)
|
|
690
535
|
});
|
|
691
|
-
|
|
536
|
+
return 500;
|
|
692
537
|
}
|
|
693
|
-
return status;
|
|
694
538
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
objects: Array.from(objectIds)
|
|
706
|
-
});
|
|
707
|
-
objectIds.clear();
|
|
708
|
-
}
|
|
709
|
-
});
|
|
710
|
-
const subscriptions = [];
|
|
711
|
-
const subscription = (0, import_echo_db.createSubscription)(({ added, updated }) => {
|
|
712
|
-
import_log5.log.info("updated", {
|
|
713
|
-
added: added.length,
|
|
714
|
-
updated: updated.length
|
|
539
|
+
//
|
|
540
|
+
// Triggers
|
|
541
|
+
//
|
|
542
|
+
/**
|
|
543
|
+
* Cron timer.
|
|
544
|
+
*/
|
|
545
|
+
async _createTimer(ctx, space, def, trigger) {
|
|
546
|
+
import_log3.log.info("timer", {
|
|
547
|
+
space: space.key,
|
|
548
|
+
trigger
|
|
715
549
|
}, {
|
|
716
|
-
F:
|
|
717
|
-
L:
|
|
718
|
-
S:
|
|
550
|
+
F: __dxlog_file3,
|
|
551
|
+
L: 170,
|
|
552
|
+
S: this,
|
|
719
553
|
C: (f, a) => f(...a)
|
|
720
554
|
});
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
objectIds.add(object.id);
|
|
726
|
-
}
|
|
727
|
-
task.schedule();
|
|
728
|
-
});
|
|
729
|
-
subscriptions.push(() => subscription.unsubscribe());
|
|
730
|
-
const { filter, options: { deep, delay } = {} } = spec;
|
|
731
|
-
const update = ({ objects }) => {
|
|
732
|
-
subscription.update(objects);
|
|
733
|
-
if (deep) {
|
|
734
|
-
import_log5.log.info("update", {
|
|
735
|
-
objects: objects.length
|
|
736
|
-
}, {
|
|
737
|
-
F: __dxlog_file4,
|
|
738
|
-
L: 52,
|
|
739
|
-
S: void 0,
|
|
740
|
-
C: (f, a) => f(...a)
|
|
741
|
-
});
|
|
742
|
-
for (const object of objects) {
|
|
743
|
-
const content = object.content;
|
|
744
|
-
if (content instanceof import_types.TextV0Type) {
|
|
745
|
-
subscriptions.push((0, import_echo_db.getAutomergeObjectCore)(content).updates.on((0, import_async4.debounce)(() => subscription.update([
|
|
746
|
-
object
|
|
747
|
-
]), 1e3)));
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
};
|
|
752
|
-
const query = triggerCtx.space.db.query(import_echo_db.Filter.or(filter.map(({ type, props }) => import_echo_db.Filter.typename(type, props))));
|
|
753
|
-
subscriptions.push(query.subscribe(delay ? (0, import_async4.debounce)(update, delay) : update));
|
|
754
|
-
ctx.onDispose(() => {
|
|
755
|
-
subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
756
|
-
});
|
|
757
|
-
};
|
|
758
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/timer-trigger.ts";
|
|
759
|
-
var createTimerTrigger = async (ctx, triggerContext, spec, callback) => {
|
|
760
|
-
const task = new import_async5.DeferredTask(ctx, async () => {
|
|
761
|
-
await callback({});
|
|
762
|
-
});
|
|
763
|
-
let last = 0;
|
|
764
|
-
let run = 0;
|
|
765
|
-
const job = import_cron.CronJob.from({
|
|
766
|
-
cronTime: spec.cron,
|
|
767
|
-
runOnInit: false,
|
|
768
|
-
onTick: () => {
|
|
769
|
-
const now = Date.now();
|
|
770
|
-
const delta = last ? now - last : 0;
|
|
771
|
-
last = now;
|
|
772
|
-
run++;
|
|
773
|
-
import_log6.log.info("tick", {
|
|
774
|
-
space: triggerContext.space.key.truncate(),
|
|
775
|
-
count: run,
|
|
776
|
-
delta
|
|
777
|
-
}, {
|
|
778
|
-
F: __dxlog_file5,
|
|
779
|
-
L: 37,
|
|
780
|
-
S: void 0,
|
|
781
|
-
C: (f, a) => f(...a)
|
|
555
|
+
const { cron } = trigger;
|
|
556
|
+
const task = new import_async2.DeferredTask(ctx, async () => {
|
|
557
|
+
await this._execFunction(def, {
|
|
558
|
+
spaceKey: space.key
|
|
782
559
|
});
|
|
783
|
-
task.schedule();
|
|
784
|
-
}
|
|
785
|
-
});
|
|
786
|
-
job.start();
|
|
787
|
-
ctx.onDispose(() => job.stop());
|
|
788
|
-
};
|
|
789
|
-
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/webhook-trigger.ts";
|
|
790
|
-
var createWebhookTrigger = async (ctx, _, spec, callback) => {
|
|
791
|
-
const server = import_node_http.default.createServer(async (req, res) => {
|
|
792
|
-
if (req.method !== spec.method) {
|
|
793
|
-
res.statusCode = 405;
|
|
794
|
-
return res.end();
|
|
795
|
-
}
|
|
796
|
-
res.statusCode = await callback({});
|
|
797
|
-
res.end();
|
|
798
|
-
});
|
|
799
|
-
const port = await (0, import_get_port_please2.getPort)({
|
|
800
|
-
random: true
|
|
801
|
-
});
|
|
802
|
-
server.listen(port, () => {
|
|
803
|
-
import_log7.log.info("started webhook", {
|
|
804
|
-
port
|
|
805
|
-
}, {
|
|
806
|
-
F: __dxlog_file6,
|
|
807
|
-
L: 40,
|
|
808
|
-
S: void 0,
|
|
809
|
-
C: (f, a) => f(...a)
|
|
810
560
|
});
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
const open = new import_async6.Trigger();
|
|
826
|
-
ws = new import_ws.default(url);
|
|
827
|
-
Object.assign(ws, {
|
|
828
|
-
onopen: () => {
|
|
829
|
-
import_log8.log.info("opened", {
|
|
830
|
-
url
|
|
831
|
-
}, {
|
|
832
|
-
F: __dxlog_file7,
|
|
833
|
-
L: 39,
|
|
834
|
-
S: void 0,
|
|
835
|
-
C: (f, a) => f(...a)
|
|
836
|
-
});
|
|
837
|
-
if (spec.init) {
|
|
838
|
-
ws.send(new TextEncoder().encode(JSON.stringify(init)));
|
|
839
|
-
}
|
|
840
|
-
open.wake(true);
|
|
841
|
-
},
|
|
842
|
-
onclose: (event) => {
|
|
843
|
-
import_log8.log.info("closed", {
|
|
844
|
-
url,
|
|
845
|
-
code: event.code
|
|
561
|
+
let last = 0;
|
|
562
|
+
let run = 0;
|
|
563
|
+
const job = import_cron.CronJob.from({
|
|
564
|
+
cronTime: cron,
|
|
565
|
+
runOnInit: false,
|
|
566
|
+
onTick: () => {
|
|
567
|
+
const now = Date.now();
|
|
568
|
+
const delta = last ? now - last : 0;
|
|
569
|
+
last = now;
|
|
570
|
+
run++;
|
|
571
|
+
import_log3.log.info("tick", {
|
|
572
|
+
space: space.key.truncate(),
|
|
573
|
+
count: run,
|
|
574
|
+
delta
|
|
846
575
|
}, {
|
|
847
|
-
F:
|
|
848
|
-
L:
|
|
849
|
-
S:
|
|
850
|
-
C: (f, a) => f(...a)
|
|
851
|
-
});
|
|
852
|
-
if (event.code === 1006) {
|
|
853
|
-
setTimeout(async () => {
|
|
854
|
-
import_log8.log.info(`reconnecting in ${options.retryDelay}s...`, {
|
|
855
|
-
url
|
|
856
|
-
}, {
|
|
857
|
-
F: __dxlog_file7,
|
|
858
|
-
L: 53,
|
|
859
|
-
S: void 0,
|
|
860
|
-
C: (f, a) => f(...a)
|
|
861
|
-
});
|
|
862
|
-
await createWebsocketTrigger(ctx, triggerCtx, spec, callback, options);
|
|
863
|
-
}, options.retryDelay * 1e3);
|
|
864
|
-
}
|
|
865
|
-
open.wake(false);
|
|
866
|
-
},
|
|
867
|
-
onerror: (event) => {
|
|
868
|
-
import_log8.log.catch(event.error, {
|
|
869
|
-
url
|
|
870
|
-
}, {
|
|
871
|
-
F: __dxlog_file7,
|
|
872
|
-
L: 62,
|
|
873
|
-
S: void 0,
|
|
576
|
+
F: __dxlog_file3,
|
|
577
|
+
L: 190,
|
|
578
|
+
S: this,
|
|
874
579
|
C: (f, a) => f(...a)
|
|
875
580
|
});
|
|
876
|
-
|
|
877
|
-
onmessage: async (event) => {
|
|
878
|
-
try {
|
|
879
|
-
import_log8.log.info("message", void 0, {
|
|
880
|
-
F: __dxlog_file7,
|
|
881
|
-
L: 67,
|
|
882
|
-
S: void 0,
|
|
883
|
-
C: (f, a) => f(...a)
|
|
884
|
-
});
|
|
885
|
-
const data = JSON.parse(new TextDecoder().decode(event.data));
|
|
886
|
-
await callback({
|
|
887
|
-
data
|
|
888
|
-
});
|
|
889
|
-
} catch (err) {
|
|
890
|
-
import_log8.log.catch(err, {
|
|
891
|
-
url
|
|
892
|
-
}, {
|
|
893
|
-
F: __dxlog_file7,
|
|
894
|
-
L: 71,
|
|
895
|
-
S: void 0,
|
|
896
|
-
C: (f, a) => f(...a)
|
|
897
|
-
});
|
|
898
|
-
}
|
|
581
|
+
task.schedule();
|
|
899
582
|
}
|
|
900
583
|
});
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
break;
|
|
904
|
-
} else {
|
|
905
|
-
const wait = Math.pow(attempt, 2) * options.retryDelay;
|
|
906
|
-
if (attempt < options.maxAttempts) {
|
|
907
|
-
import_log8.log.warn(`failed to connect; trying again in ${wait}s`, {
|
|
908
|
-
attempt
|
|
909
|
-
}, {
|
|
910
|
-
F: __dxlog_file7,
|
|
911
|
-
L: 82,
|
|
912
|
-
S: void 0,
|
|
913
|
-
C: (f, a) => f(...a)
|
|
914
|
-
});
|
|
915
|
-
await (0, import_async6.sleep)(wait * 1e3);
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
ctx.onDispose(() => {
|
|
920
|
-
ws?.close();
|
|
921
|
-
});
|
|
922
|
-
};
|
|
923
|
-
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/trigger-registry.ts";
|
|
924
|
-
var triggerHandlers = {
|
|
925
|
-
subscription: createSubscriptionTrigger,
|
|
926
|
-
timer: createTimerTrigger,
|
|
927
|
-
webhook: createWebhookTrigger,
|
|
928
|
-
websocket: createWebsocketTrigger
|
|
929
|
-
};
|
|
930
|
-
var TriggerRegistry = class extends import_context4.Resource {
|
|
931
|
-
constructor(_client, _options) {
|
|
932
|
-
super();
|
|
933
|
-
this._client = _client;
|
|
934
|
-
this._options = _options;
|
|
935
|
-
this._triggersBySpaceKey = new import_util3.ComplexMap(import_keys2.PublicKey.hash);
|
|
936
|
-
this.registered = new import_async3.Event();
|
|
937
|
-
this.removed = new import_async3.Event();
|
|
938
|
-
}
|
|
939
|
-
getActiveTriggers(space) {
|
|
940
|
-
return this._getTriggers(space, (t) => t.activationCtx != null);
|
|
941
|
-
}
|
|
942
|
-
getInactiveTriggers(space) {
|
|
943
|
-
return this._getTriggers(space, (t) => t.activationCtx == null);
|
|
584
|
+
job.start();
|
|
585
|
+
ctx.onDispose(() => job.stop());
|
|
944
586
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
587
|
+
/**
|
|
588
|
+
* Webhook.
|
|
589
|
+
*/
|
|
590
|
+
async _createWebhook(ctx, space, def, trigger) {
|
|
591
|
+
import_log3.log.info("webhook", {
|
|
592
|
+
space: space.key,
|
|
948
593
|
trigger
|
|
949
594
|
}, {
|
|
950
|
-
F:
|
|
951
|
-
L:
|
|
595
|
+
F: __dxlog_file3,
|
|
596
|
+
L: 203,
|
|
952
597
|
S: this,
|
|
953
598
|
C: (f, a) => f(...a)
|
|
954
599
|
});
|
|
955
|
-
const
|
|
956
|
-
|
|
600
|
+
const server = import_node_http.default.createServer(async (req, res) => {
|
|
601
|
+
if (req.method !== trigger.method) {
|
|
602
|
+
res.statusCode = 405;
|
|
603
|
+
return res.end();
|
|
604
|
+
}
|
|
605
|
+
res.statusCode = await this._execFunction(def, {
|
|
606
|
+
spaceKey: space.key
|
|
607
|
+
});
|
|
608
|
+
res.end();
|
|
957
609
|
});
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
610
|
+
const port = await (0, import_get_port_please2.getPort)({
|
|
611
|
+
random: true
|
|
612
|
+
});
|
|
613
|
+
server.listen(port, () => {
|
|
614
|
+
import_log3.log.info("started webhook", {
|
|
615
|
+
port
|
|
616
|
+
}, {
|
|
617
|
+
F: __dxlog_file3,
|
|
618
|
+
L: 226,
|
|
619
|
+
S: this,
|
|
620
|
+
C: (f, a) => f(...a)
|
|
621
|
+
});
|
|
622
|
+
trigger.port = port;
|
|
623
|
+
});
|
|
624
|
+
ctx.onDispose(() => {
|
|
625
|
+
server.close();
|
|
968
626
|
});
|
|
969
|
-
registeredTrigger.activationCtx = activationCtx;
|
|
970
|
-
try {
|
|
971
|
-
const options = this._options?.[trigger.spec.type];
|
|
972
|
-
await triggerHandlers[trigger.spec.type](activationCtx, triggerCtx, trigger.spec, callback, options);
|
|
973
|
-
} catch (err) {
|
|
974
|
-
delete registeredTrigger.activationCtx;
|
|
975
|
-
throw err;
|
|
976
|
-
}
|
|
977
627
|
}
|
|
978
628
|
/**
|
|
979
|
-
*
|
|
629
|
+
* Websocket.
|
|
630
|
+
* NOTE: The port must be unique, so the same hook cannot be used for multiple spaces.
|
|
980
631
|
*/
|
|
981
|
-
async
|
|
982
|
-
|
|
983
|
-
|
|
632
|
+
async _createWebsocket(ctx, space, def, trigger, options = {
|
|
633
|
+
retryDelay: 2,
|
|
634
|
+
maxAttempts: 5
|
|
635
|
+
}) {
|
|
636
|
+
import_log3.log.info("websocket", {
|
|
637
|
+
space: space.key,
|
|
638
|
+
trigger
|
|
984
639
|
}, {
|
|
985
|
-
F:
|
|
986
|
-
L:
|
|
640
|
+
F: __dxlog_file3,
|
|
641
|
+
L: 252,
|
|
987
642
|
S: this,
|
|
988
643
|
C: (f, a) => f(...a)
|
|
989
644
|
});
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
645
|
+
const { url } = trigger;
|
|
646
|
+
let ws;
|
|
647
|
+
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
|
|
648
|
+
const open = new import_async2.Trigger();
|
|
649
|
+
ws = new import_ws.default(url);
|
|
650
|
+
Object.assign(ws, {
|
|
651
|
+
onopen: () => {
|
|
652
|
+
import_log3.log.info("opened", {
|
|
653
|
+
url
|
|
654
|
+
}, {
|
|
655
|
+
F: __dxlog_file3,
|
|
656
|
+
L: 262,
|
|
657
|
+
S: this,
|
|
658
|
+
C: (f, a) => f(...a)
|
|
659
|
+
});
|
|
660
|
+
if (trigger.init) {
|
|
661
|
+
ws.send(new TextEncoder().encode(JSON.stringify(trigger.init)));
|
|
662
|
+
}
|
|
663
|
+
open.wake(true);
|
|
664
|
+
},
|
|
665
|
+
// TODO(burdon): Config retry if server closes?
|
|
666
|
+
onclose: (event) => {
|
|
667
|
+
import_log3.log.info("closed", {
|
|
668
|
+
url,
|
|
669
|
+
code: event.code
|
|
670
|
+
}, {
|
|
671
|
+
F: __dxlog_file3,
|
|
672
|
+
L: 272,
|
|
673
|
+
S: this,
|
|
674
|
+
C: (f, a) => f(...a)
|
|
675
|
+
});
|
|
676
|
+
open.wake(false);
|
|
677
|
+
},
|
|
678
|
+
onerror: (event) => {
|
|
679
|
+
import_log3.log.catch(event.error, {
|
|
680
|
+
url
|
|
681
|
+
}, {
|
|
682
|
+
F: __dxlog_file3,
|
|
683
|
+
L: 277,
|
|
684
|
+
S: this,
|
|
685
|
+
C: (f, a) => f(...a)
|
|
686
|
+
});
|
|
687
|
+
},
|
|
688
|
+
onmessage: async (event) => {
|
|
689
|
+
try {
|
|
690
|
+
const data = JSON.parse(new TextDecoder().decode(event.data));
|
|
691
|
+
await this._execFunction(def, {
|
|
692
|
+
spaceKey: space.key,
|
|
693
|
+
data
|
|
694
|
+
});
|
|
695
|
+
} catch (err) {
|
|
696
|
+
import_log3.log.catch(err, {
|
|
697
|
+
url
|
|
698
|
+
}, {
|
|
699
|
+
F: __dxlog_file3,
|
|
700
|
+
L: 285,
|
|
701
|
+
S: this,
|
|
702
|
+
C: (f, a) => f(...a)
|
|
703
|
+
});
|
|
704
|
+
}
|
|
1006
705
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
706
|
+
});
|
|
707
|
+
const isOpen = await open.wait();
|
|
708
|
+
if (isOpen) {
|
|
709
|
+
break;
|
|
710
|
+
} else {
|
|
711
|
+
const wait = Math.pow(attempt, 2) * options.retryDelay;
|
|
712
|
+
if (attempt < options.maxAttempts) {
|
|
713
|
+
import_log3.log.warn(`failed to connect; trying again in ${wait}s`, {
|
|
714
|
+
attempt
|
|
715
|
+
}, {
|
|
716
|
+
F: __dxlog_file3,
|
|
717
|
+
L: 296,
|
|
718
|
+
S: this,
|
|
719
|
+
C: (f, a) => f(...a)
|
|
720
|
+
});
|
|
721
|
+
await (0, import_async2.sleep)(wait * 1e3);
|
|
1012
722
|
}
|
|
1013
|
-
const functionsSubscription = space.db.query(import_echo2.Filter.schema(FunctionTrigger)).subscribe(async (triggers) => {
|
|
1014
|
-
await this._handleRemovedTriggers(space, triggers.objects, registered);
|
|
1015
|
-
this._handleNewTriggers(space, triggers.objects, registered);
|
|
1016
|
-
});
|
|
1017
|
-
this._ctx.onDispose(functionsSubscription);
|
|
1018
723
|
}
|
|
724
|
+
}
|
|
725
|
+
ctx.onDispose(() => {
|
|
726
|
+
ws?.close();
|
|
1019
727
|
});
|
|
1020
|
-
this._ctx.onDispose(() => spaceListSubscription.unsubscribe());
|
|
1021
|
-
}
|
|
1022
|
-
async _close(_) {
|
|
1023
|
-
this._triggersBySpaceKey.clear();
|
|
1024
728
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
729
|
+
/**
|
|
730
|
+
* ECHO subscription.
|
|
731
|
+
*/
|
|
732
|
+
async _createSubscription(ctx, space, def, trigger) {
|
|
733
|
+
import_log3.log.info("subscription", {
|
|
734
|
+
space: space.key,
|
|
735
|
+
trigger
|
|
736
|
+
}, {
|
|
737
|
+
F: __dxlog_file3,
|
|
738
|
+
L: 311,
|
|
739
|
+
S: this,
|
|
740
|
+
C: (f, a) => f(...a)
|
|
1028
741
|
});
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
}));
|
|
1033
|
-
registered.push(...newRegisteredTriggers);
|
|
1034
|
-
(0, import_log4.log)("registered new triggers", () => ({
|
|
742
|
+
const objectIds = /* @__PURE__ */ new Set();
|
|
743
|
+
const task = new import_async2.DeferredTask(ctx, async () => {
|
|
744
|
+
await this._execFunction(def, {
|
|
1035
745
|
spaceKey: space.key,
|
|
1036
|
-
|
|
1037
|
-
})
|
|
1038
|
-
|
|
1039
|
-
|
|
746
|
+
objects: Array.from(objectIds)
|
|
747
|
+
});
|
|
748
|
+
});
|
|
749
|
+
const subscriptions = [];
|
|
750
|
+
const subscription = (0, import_echo.createSubscription)(({ added, updated }) => {
|
|
751
|
+
import_log3.log.info("updated", {
|
|
752
|
+
added: added.length,
|
|
753
|
+
updated: updated.length
|
|
754
|
+
}, {
|
|
755
|
+
F: __dxlog_file3,
|
|
756
|
+
L: 321,
|
|
1040
757
|
S: this,
|
|
1041
758
|
C: (f, a) => f(...a)
|
|
1042
759
|
});
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
triggers: newTriggers
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
async _handleRemovedTriggers(space, allTriggers, registered) {
|
|
1050
|
-
const removed = [];
|
|
1051
|
-
for (let i = registered.length - 1; i >= 0; i--) {
|
|
1052
|
-
const wasRemoved = allTriggers.find((trigger) => trigger.id === registered[i].trigger.id) == null;
|
|
1053
|
-
if (wasRemoved) {
|
|
1054
|
-
const unregistered = registered.splice(i, 1)[0];
|
|
1055
|
-
await unregistered.activationCtx?.dispose();
|
|
1056
|
-
removed.push(unregistered.trigger);
|
|
760
|
+
for (const object of added) {
|
|
761
|
+
objectIds.add(object.id);
|
|
1057
762
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
763
|
+
for (const object of updated) {
|
|
764
|
+
objectIds.add(object.id);
|
|
765
|
+
}
|
|
766
|
+
task.schedule();
|
|
767
|
+
});
|
|
768
|
+
subscriptions.push(() => subscription.unsubscribe());
|
|
769
|
+
const { filter, options: { deep, delay } = {} } = trigger;
|
|
770
|
+
const update = ({ objects }) => {
|
|
771
|
+
subscription.update(objects);
|
|
772
|
+
if (deep) {
|
|
773
|
+
import_log3.log.info("update", {
|
|
774
|
+
objects: objects.length
|
|
775
|
+
}, {
|
|
776
|
+
F: __dxlog_file3,
|
|
777
|
+
L: 342,
|
|
778
|
+
S: this,
|
|
779
|
+
C: (f, a) => f(...a)
|
|
780
|
+
});
|
|
781
|
+
for (const object of objects) {
|
|
782
|
+
const content = object.content;
|
|
783
|
+
if (content instanceof import_types.TextV0Type) {
|
|
784
|
+
subscriptions.push((0, import_echo.getAutomergeObjectCore)(content).updates.on((0, import_async2.debounce)(() => subscription.update([
|
|
785
|
+
object
|
|
786
|
+
]), 1e3)));
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
const query = space.db.query(import_echo.Filter.or(filter.map(({ type, props }) => import_echo.Filter.typename(type, props))));
|
|
792
|
+
subscriptions.push(query.subscribe(delay ? (0, import_async2.debounce)(update, delay) : update));
|
|
793
|
+
ctx.onDispose(() => {
|
|
794
|
+
subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
795
|
+
});
|
|
1069
796
|
}
|
|
1070
797
|
};
|
|
798
|
+
var TimerTriggerSchema = S.struct({
|
|
799
|
+
cron: S.string
|
|
800
|
+
});
|
|
801
|
+
var WebhookTriggerSchema = S.mutable(S.struct({
|
|
802
|
+
method: S.string,
|
|
803
|
+
// Assigned port.
|
|
804
|
+
port: S.optional(S.number)
|
|
805
|
+
}));
|
|
806
|
+
var WebsocketTriggerSchema = S.struct({
|
|
807
|
+
url: S.string,
|
|
808
|
+
init: S.optional(S.record(S.string, S.any))
|
|
809
|
+
});
|
|
810
|
+
var SubscriptionTriggerSchema = S.struct({
|
|
811
|
+
spaceKey: S.optional(S.string),
|
|
812
|
+
// TODO(burdon): Define query DSL.
|
|
813
|
+
filter: S.array(S.struct({
|
|
814
|
+
type: S.string,
|
|
815
|
+
props: S.optional(S.record(S.string, S.any))
|
|
816
|
+
})),
|
|
817
|
+
options: S.optional(S.struct({
|
|
818
|
+
// Watch changes to object (not just creation).
|
|
819
|
+
deep: S.optional(S.boolean),
|
|
820
|
+
// Debounce changes (delay in ms).
|
|
821
|
+
delay: S.optional(S.number)
|
|
822
|
+
}))
|
|
823
|
+
});
|
|
824
|
+
var FunctionTriggerSchema = S.struct({
|
|
825
|
+
function: S.string.pipe(S.description("Function ID/URI.")),
|
|
826
|
+
// Context passed to function.
|
|
827
|
+
context: S.optional(S.record(S.string, S.any)),
|
|
828
|
+
// Triggers.
|
|
829
|
+
timer: S.optional(TimerTriggerSchema),
|
|
830
|
+
webhook: S.optional(WebhookTriggerSchema),
|
|
831
|
+
websocket: S.optional(WebsocketTriggerSchema),
|
|
832
|
+
subscription: S.optional(SubscriptionTriggerSchema)
|
|
833
|
+
});
|
|
834
|
+
var FunctionDefSchema = S.struct({
|
|
835
|
+
id: S.string,
|
|
836
|
+
// name: S.string,
|
|
837
|
+
description: S.optional(S.string),
|
|
838
|
+
path: S.string,
|
|
839
|
+
// TODO(burdon): NPM/GitHub/Docker/CF URL?
|
|
840
|
+
handler: S.string
|
|
841
|
+
});
|
|
842
|
+
var FunctionManifestSchema = S.struct({
|
|
843
|
+
functions: S.mutable(S.array(FunctionDefSchema)),
|
|
844
|
+
triggers: S.optional(S.mutable(S.array(FunctionTriggerSchema)))
|
|
845
|
+
});
|
|
1071
846
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1072
847
|
0 && (module.exports = {
|
|
1073
848
|
DevServer,
|
|
1074
|
-
FunctionDef,
|
|
1075
849
|
FunctionManifestSchema,
|
|
1076
|
-
FunctionRegistry,
|
|
1077
|
-
FunctionTrigger,
|
|
1078
850
|
Scheduler,
|
|
1079
|
-
TriggerRegistry,
|
|
1080
851
|
subscriptionHandler
|
|
1081
852
|
});
|
|
1082
853
|
//# sourceMappingURL=index.cjs.map
|