@dxos/functions 0.5.3-main.bc67fdb → 0.5.3-main.c8ad1bb
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 +642 -424
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +627 -421
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/registry/function-registry.d.ts +24 -0
- package/dist/types/src/registry/function-registry.d.ts.map +1 -0
- package/dist/types/src/registry/function-registry.test.d.ts +2 -0
- package/dist/types/src/registry/function-registry.test.d.ts.map +1 -0
- package/dist/types/src/registry/index.d.ts +2 -0
- package/dist/types/src/registry/index.d.ts.map +1 -0
- package/dist/types/src/runtime/dev-server.d.ts +7 -10
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.d.ts +10 -59
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/testing/functions-integration.test.d.ts +2 -0
- package/dist/types/src/testing/functions-integration.test.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +4 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/setup.d.ts +5 -0
- package/dist/types/src/testing/setup.d.ts.map +1 -0
- package/dist/types/src/testing/test/handler.d.ts +1 -0
- package/dist/types/src/testing/test/handler.d.ts.map +1 -1
- package/dist/types/src/testing/types.d.ts +9 -0
- package/dist/types/src/testing/types.d.ts.map +1 -0
- package/dist/types/src/testing/util.d.ts +3 -0
- package/dist/types/src/testing/util.d.ts.map +1 -0
- package/dist/types/src/trigger/index.d.ts +2 -0
- package/dist/types/src/trigger/index.d.ts.map +1 -0
- package/dist/types/src/trigger/trigger-registry.d.ts +40 -0
- package/dist/types/src/trigger/trigger-registry.d.ts.map +1 -0
- package/dist/types/src/trigger/trigger-registry.test.d.ts +2 -0
- package/dist/types/src/trigger/trigger-registry.test.d.ts.map +1 -0
- package/dist/types/src/trigger/type/index.d.ts +5 -0
- package/dist/types/src/trigger/type/index.d.ts.map +1 -0
- package/dist/types/src/trigger/type/subscription-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/timer-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/timer-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/webhook-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/websocket-trigger.d.ts +13 -0
- package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +118 -112
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +16 -13
- package/schema/functions.json +121 -107
- package/src/index.ts +2 -0
- package/src/registry/function-registry.test.ts +105 -0
- package/src/registry/function-registry.ts +84 -0
- package/src/registry/index.ts +5 -0
- package/src/runtime/dev-server.test.ts +15 -35
- package/src/runtime/dev-server.ts +36 -18
- package/src/runtime/scheduler.test.ts +54 -75
- package/src/runtime/scheduler.ts +58 -298
- package/src/testing/functions-integration.test.ts +99 -0
- package/src/testing/index.ts +7 -0
- package/src/testing/setup.ts +45 -0
- package/src/testing/test/handler.ts +8 -2
- package/src/testing/types.ts +9 -0
- package/src/testing/util.ts +16 -0
- package/src/trigger/index.ts +5 -0
- package/src/trigger/trigger-registry.test.ts +229 -0
- package/src/trigger/trigger-registry.ts +176 -0
- package/src/trigger/type/index.ts +8 -0
- package/src/trigger/type/subscription-trigger.ts +73 -0
- package/src/trigger/type/timer-trigger.ts +44 -0
- package/src/trigger/type/webhook-trigger.ts +47 -0
- package/src/trigger/type/websocket-trigger.ts +91 -0
- package/src/types.ts +56 -42
package/dist/lib/node/index.cjs
CHANGED
|
@@ -29,33 +29,54 @@ 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,
|
|
32
33
|
FunctionManifestSchema: () => FunctionManifestSchema,
|
|
34
|
+
FunctionRegistry: () => FunctionRegistry,
|
|
35
|
+
FunctionTrigger: () => FunctionTrigger,
|
|
33
36
|
Scheduler: () => Scheduler,
|
|
37
|
+
TriggerRegistry: () => TriggerRegistry,
|
|
34
38
|
subscriptionHandler: () => subscriptionHandler
|
|
35
39
|
});
|
|
36
40
|
module.exports = __toCommonJS(node_exports);
|
|
37
41
|
var import_client = require("@dxos/client");
|
|
38
42
|
var import_log = require("@dxos/log");
|
|
39
43
|
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");
|
|
40
50
|
var import_express = __toESM(require("express"));
|
|
41
51
|
var import_get_port_please = require("get-port-please");
|
|
42
52
|
var import_node_path = require("node:path");
|
|
43
|
-
var
|
|
53
|
+
var import_async2 = require("@dxos/async");
|
|
54
|
+
var import_context2 = require("@dxos/context");
|
|
44
55
|
var import_invariant = require("@dxos/invariant");
|
|
45
56
|
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");
|
|
46
71
|
var import_cron = require("cron");
|
|
72
|
+
var import_async5 = require("@dxos/async");
|
|
73
|
+
var import_log6 = require("@dxos/log");
|
|
47
74
|
var import_get_port_please2 = require("get-port-please");
|
|
48
75
|
var import_node_http = __toESM(require("node:http"));
|
|
49
|
-
var
|
|
76
|
+
var import_log7 = require("@dxos/log");
|
|
50
77
|
var import_ws = __toESM(require("ws"));
|
|
51
|
-
var
|
|
52
|
-
var
|
|
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"));
|
|
78
|
+
var import_async6 = require("@dxos/async");
|
|
79
|
+
var import_log8 = require("@dxos/log");
|
|
59
80
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
60
81
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
61
82
|
}) : x)(function(x) {
|
|
@@ -102,15 +123,150 @@ var subscriptionHandler = (handler) => {
|
|
|
102
123
|
});
|
|
103
124
|
};
|
|
104
125
|
};
|
|
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.hasSchema(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
|
+
};
|
|
105
247
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
106
248
|
var DevServer = class {
|
|
107
249
|
// prettier-ignore
|
|
108
|
-
constructor(_client, _options) {
|
|
250
|
+
constructor(_client, _functionsRegistry, _options) {
|
|
109
251
|
this._client = _client;
|
|
252
|
+
this._functionsRegistry = _functionsRegistry;
|
|
110
253
|
this._options = _options;
|
|
254
|
+
this._ctx = createContext();
|
|
111
255
|
this._handlers = {};
|
|
112
256
|
this._seq = 0;
|
|
113
|
-
this.update = new
|
|
257
|
+
this.update = new import_async2.Event();
|
|
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
|
+
});
|
|
114
270
|
}
|
|
115
271
|
get stats() {
|
|
116
272
|
return {
|
|
@@ -120,7 +276,7 @@ var DevServer = class {
|
|
|
120
276
|
get endpoint() {
|
|
121
277
|
(0, import_invariant.invariant)(this._port, void 0, {
|
|
122
278
|
F: __dxlog_file2,
|
|
123
|
-
L:
|
|
279
|
+
L: 64,
|
|
124
280
|
S: this,
|
|
125
281
|
A: [
|
|
126
282
|
"this._port",
|
|
@@ -135,20 +291,6 @@ var DevServer = class {
|
|
|
135
291
|
get functions() {
|
|
136
292
|
return Object.values(this._handlers);
|
|
137
293
|
}
|
|
138
|
-
async initialize() {
|
|
139
|
-
for (const def of this._options.manifest.functions) {
|
|
140
|
-
try {
|
|
141
|
-
await this._load(def);
|
|
142
|
-
} catch (err) {
|
|
143
|
-
import_log2.log.error("parsing function (check manifest)", err, {
|
|
144
|
-
F: __dxlog_file2,
|
|
145
|
-
L: 71,
|
|
146
|
-
S: this,
|
|
147
|
-
C: (f, a) => f(...a)
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
294
|
async start() {
|
|
153
295
|
(0, import_invariant.invariant)(!this._server, void 0, {
|
|
154
296
|
F: __dxlog_file2,
|
|
@@ -165,6 +307,7 @@ var DevServer = class {
|
|
|
165
307
|
S: this,
|
|
166
308
|
C: (f, a) => f(...a)
|
|
167
309
|
});
|
|
310
|
+
this._ctx = createContext();
|
|
168
311
|
const app = (0, import_express.default)();
|
|
169
312
|
app.use(import_express.default.json());
|
|
170
313
|
app.post("/:path", async (req, res) => {
|
|
@@ -174,7 +317,7 @@ var DevServer = class {
|
|
|
174
317
|
path: path2
|
|
175
318
|
}, {
|
|
176
319
|
F: __dxlog_file2,
|
|
177
|
-
L:
|
|
320
|
+
L: 88,
|
|
178
321
|
S: this,
|
|
179
322
|
C: (f, a) => f(...a)
|
|
180
323
|
});
|
|
@@ -187,7 +330,7 @@ var DevServer = class {
|
|
|
187
330
|
} catch (err) {
|
|
188
331
|
import_log2.log.catch(err, void 0, {
|
|
189
332
|
F: __dxlog_file2,
|
|
190
|
-
L:
|
|
333
|
+
L: 98,
|
|
191
334
|
S: this,
|
|
192
335
|
C: (f, a) => f(...a)
|
|
193
336
|
});
|
|
@@ -206,11 +349,7 @@ var DevServer = class {
|
|
|
206
349
|
this._server = app.listen(this._port);
|
|
207
350
|
try {
|
|
208
351
|
const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
|
|
209
|
-
endpoint: this.endpoint
|
|
210
|
-
functions: this.functions.map(({ def: { id, path: path2 } }) => ({
|
|
211
|
-
id,
|
|
212
|
-
path: path2
|
|
213
|
-
}))
|
|
352
|
+
endpoint: this.endpoint
|
|
214
353
|
});
|
|
215
354
|
import_log2.log.info("registered", {
|
|
216
355
|
endpoint
|
|
@@ -222,6 +361,7 @@ var DevServer = class {
|
|
|
222
361
|
});
|
|
223
362
|
this._proxy = endpoint;
|
|
224
363
|
this._functionServiceRegistration = registrationId;
|
|
364
|
+
await this._functionsRegistry.open(this._ctx);
|
|
225
365
|
} catch (err) {
|
|
226
366
|
await this.stop();
|
|
227
367
|
throw new Error("FunctionRegistryService not available (check plugin is configured).");
|
|
@@ -230,7 +370,7 @@ var DevServer = class {
|
|
|
230
370
|
port: this._port
|
|
231
371
|
}, {
|
|
232
372
|
F: __dxlog_file2,
|
|
233
|
-
L:
|
|
373
|
+
L: 124,
|
|
234
374
|
S: this,
|
|
235
375
|
C: (f, a) => f(...a)
|
|
236
376
|
});
|
|
@@ -238,7 +378,7 @@ var DevServer = class {
|
|
|
238
378
|
async stop() {
|
|
239
379
|
(0, import_invariant.invariant)(this._server, void 0, {
|
|
240
380
|
F: __dxlog_file2,
|
|
241
|
-
L:
|
|
381
|
+
L: 128,
|
|
242
382
|
S: this,
|
|
243
383
|
A: [
|
|
244
384
|
"this._server",
|
|
@@ -247,15 +387,15 @@ var DevServer = class {
|
|
|
247
387
|
});
|
|
248
388
|
import_log2.log.info("stopping...", void 0, {
|
|
249
389
|
F: __dxlog_file2,
|
|
250
|
-
L:
|
|
390
|
+
L: 129,
|
|
251
391
|
S: this,
|
|
252
392
|
C: (f, a) => f(...a)
|
|
253
393
|
});
|
|
254
|
-
const trigger = new
|
|
394
|
+
const trigger = new import_async2.Trigger();
|
|
255
395
|
this._server.close(async () => {
|
|
256
396
|
import_log2.log.info("server stopped", void 0, {
|
|
257
397
|
F: __dxlog_file2,
|
|
258
|
-
L:
|
|
398
|
+
L: 133,
|
|
259
399
|
S: this,
|
|
260
400
|
C: (f, a) => f(...a)
|
|
261
401
|
});
|
|
@@ -263,7 +403,7 @@ var DevServer = class {
|
|
|
263
403
|
if (this._functionServiceRegistration) {
|
|
264
404
|
(0, import_invariant.invariant)(this._client.services.services.FunctionRegistryService, void 0, {
|
|
265
405
|
F: __dxlog_file2,
|
|
266
|
-
L:
|
|
406
|
+
L: 136,
|
|
267
407
|
S: this,
|
|
268
408
|
A: [
|
|
269
409
|
"this._client.services.services.FunctionRegistryService",
|
|
@@ -277,7 +417,7 @@ var DevServer = class {
|
|
|
277
417
|
registrationId: this._functionServiceRegistration
|
|
278
418
|
}, {
|
|
279
419
|
F: __dxlog_file2,
|
|
280
|
-
L:
|
|
420
|
+
L: 141,
|
|
281
421
|
S: this,
|
|
282
422
|
C: (f, a) => f(...a)
|
|
283
423
|
});
|
|
@@ -294,7 +434,7 @@ var DevServer = class {
|
|
|
294
434
|
this._server = void 0;
|
|
295
435
|
import_log2.log.info("stopped", void 0, {
|
|
296
436
|
F: __dxlog_file2,
|
|
297
|
-
L:
|
|
437
|
+
L: 155,
|
|
298
438
|
S: this,
|
|
299
439
|
C: (f, a) => f(...a)
|
|
300
440
|
});
|
|
@@ -303,14 +443,14 @@ var DevServer = class {
|
|
|
303
443
|
* Load function.
|
|
304
444
|
*/
|
|
305
445
|
async _load(def, force = false) {
|
|
306
|
-
const {
|
|
446
|
+
const { uri, route, handler } = def;
|
|
307
447
|
const filePath = (0, import_node_path.join)(this._options.baseDir, handler);
|
|
308
448
|
import_log2.log.info("loading", {
|
|
309
|
-
|
|
449
|
+
uri,
|
|
310
450
|
force
|
|
311
451
|
}, {
|
|
312
452
|
F: __dxlog_file2,
|
|
313
|
-
L:
|
|
453
|
+
L: 164,
|
|
314
454
|
S: this,
|
|
315
455
|
C: (f, a) => f(...a)
|
|
316
456
|
});
|
|
@@ -321,13 +461,40 @@ var DevServer = class {
|
|
|
321
461
|
}
|
|
322
462
|
const module2 = __require(filePath);
|
|
323
463
|
if (typeof module2.default !== "function") {
|
|
324
|
-
throw new Error(`Handler must export default function: ${
|
|
464
|
+
throw new Error(`Handler must export default function: ${uri}`);
|
|
325
465
|
}
|
|
326
|
-
this._handlers[
|
|
466
|
+
this._handlers[route] = {
|
|
327
467
|
def,
|
|
328
468
|
handler: module2.default
|
|
329
469
|
};
|
|
330
470
|
}
|
|
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
|
+
}
|
|
331
498
|
/**
|
|
332
499
|
* Invoke function.
|
|
333
500
|
*/
|
|
@@ -339,7 +506,7 @@ var DevServer = class {
|
|
|
339
506
|
path: path2
|
|
340
507
|
}, {
|
|
341
508
|
F: __dxlog_file2,
|
|
342
|
-
L:
|
|
509
|
+
L: 204,
|
|
343
510
|
S: this,
|
|
344
511
|
C: (f, a) => f(...a)
|
|
345
512
|
});
|
|
@@ -353,7 +520,7 @@ var DevServer = class {
|
|
|
353
520
|
duration: Date.now() - now
|
|
354
521
|
}, {
|
|
355
522
|
F: __dxlog_file2,
|
|
356
|
-
L:
|
|
523
|
+
L: 207,
|
|
357
524
|
S: this,
|
|
358
525
|
C: (f, a) => f(...a)
|
|
359
526
|
});
|
|
@@ -364,7 +531,7 @@ var DevServer = class {
|
|
|
364
531
|
const { handler } = this._handlers[path2] ?? {};
|
|
365
532
|
(0, import_invariant.invariant)(handler, `invalid path: ${path2}`, {
|
|
366
533
|
F: __dxlog_file2,
|
|
367
|
-
L:
|
|
534
|
+
L: 214,
|
|
368
535
|
S: this,
|
|
369
536
|
A: [
|
|
370
537
|
"handler",
|
|
@@ -390,111 +557,93 @@ var DevServer = class {
|
|
|
390
557
|
return statusCode;
|
|
391
558
|
}
|
|
392
559
|
};
|
|
560
|
+
var createContext = () => new import_context2.Context({
|
|
561
|
+
name: "DevServer"
|
|
562
|
+
});
|
|
393
563
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
394
564
|
var Scheduler = class {
|
|
395
|
-
constructor(
|
|
396
|
-
this.
|
|
397
|
-
this.
|
|
565
|
+
constructor(functions, triggers, _options = {}) {
|
|
566
|
+
this.functions = functions;
|
|
567
|
+
this.triggers = triggers;
|
|
398
568
|
this._options = _options;
|
|
399
|
-
this.
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
569
|
+
this._ctx = createContext2();
|
|
570
|
+
this.functions.onFunctionsRegistered.on(async ({ space, newFunctions }) => {
|
|
571
|
+
await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), newFunctions);
|
|
572
|
+
});
|
|
573
|
+
this.triggers.registered.on(async ({ space, triggers: triggers2 }) => {
|
|
574
|
+
await this._safeActivateTriggers(space, triggers2, this.functions.getFunctions(space));
|
|
575
|
+
});
|
|
406
576
|
}
|
|
407
577
|
async start() {
|
|
408
|
-
this.
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
await this.mount(new import_context.Context(), space, trigger);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
});
|
|
578
|
+
await this._ctx.dispose();
|
|
579
|
+
this._ctx = createContext2();
|
|
580
|
+
await this.functions.open(this._ctx);
|
|
581
|
+
await this.triggers.open(this._ctx);
|
|
416
582
|
}
|
|
417
583
|
async stop() {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
584
|
+
await this._ctx.dispose();
|
|
585
|
+
await this.functions.close();
|
|
586
|
+
await this.triggers.close();
|
|
421
587
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
};
|
|
430
|
-
const def = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
431
|
-
(0, import_invariant2.invariant)(def, `Function not found: ${trigger.function}`, {
|
|
432
|
-
F: __dxlog_file3,
|
|
433
|
-
L: 76,
|
|
434
|
-
S: this,
|
|
435
|
-
A: [
|
|
436
|
-
"def",
|
|
437
|
-
"`Function not found: ${trigger.function}`"
|
|
438
|
-
]
|
|
588
|
+
async register(space, manifest) {
|
|
589
|
+
await this.functions.register(space, manifest);
|
|
590
|
+
await this.triggers.register(space, manifest);
|
|
591
|
+
}
|
|
592
|
+
async _safeActivateTriggers(space, triggers, functions) {
|
|
593
|
+
const mountTasks = triggers.map((trigger) => {
|
|
594
|
+
return this.activate(space, functions, trigger);
|
|
439
595
|
});
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
space: space.key,
|
|
448
|
-
trigger
|
|
596
|
+
await Promise.all(mountTasks).catch(import_log3.log.catch);
|
|
597
|
+
}
|
|
598
|
+
async activate(space, functions, fnTrigger) {
|
|
599
|
+
const definition = functions.find((def) => def.uri === fnTrigger.function);
|
|
600
|
+
if (!definition) {
|
|
601
|
+
import_log3.log.info("function is not found for trigger", {
|
|
602
|
+
fnTrigger
|
|
449
603
|
}, {
|
|
450
604
|
F: __dxlog_file3,
|
|
451
|
-
L:
|
|
605
|
+
L: 74,
|
|
452
606
|
S: this,
|
|
453
607
|
C: (f, a) => f(...a)
|
|
454
608
|
});
|
|
455
|
-
|
|
456
|
-
return;
|
|
457
|
-
}
|
|
458
|
-
if (trigger.timer) {
|
|
459
|
-
await this._createTimer(ctx, space, def, trigger);
|
|
460
|
-
}
|
|
461
|
-
if (trigger.webhook) {
|
|
462
|
-
await this._createWebhook(ctx, space, def, trigger);
|
|
463
|
-
}
|
|
464
|
-
if (trigger.websocket) {
|
|
465
|
-
await this._createWebsocket(ctx, space, def, trigger);
|
|
466
|
-
}
|
|
467
|
-
if (trigger.subscription) {
|
|
468
|
-
await this._createSubscription(ctx, space, def, trigger);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
async unmount(id, spaceKey) {
|
|
473
|
-
const key = {
|
|
474
|
-
id,
|
|
475
|
-
spaceKey
|
|
476
|
-
};
|
|
477
|
-
const { ctx } = this._mounts.get(key) ?? {};
|
|
478
|
-
if (ctx) {
|
|
479
|
-
this._mounts.delete(key);
|
|
480
|
-
await ctx.dispose();
|
|
609
|
+
return;
|
|
481
610
|
}
|
|
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
|
+
});
|
|
482
631
|
}
|
|
483
|
-
async _execFunction(def,
|
|
632
|
+
async _execFunction(def, { data, meta }) {
|
|
484
633
|
let status = 0;
|
|
485
634
|
try {
|
|
486
|
-
const payload = Object.assign({}, {
|
|
487
|
-
meta
|
|
635
|
+
const payload = Object.assign({}, meta && {
|
|
636
|
+
meta
|
|
488
637
|
}, data);
|
|
489
638
|
const { endpoint, callback } = this._options;
|
|
490
639
|
if (endpoint) {
|
|
491
|
-
const url = import_node_path2.default.join(endpoint, def.
|
|
640
|
+
const url = import_node_path2.default.join(endpoint, def.route);
|
|
492
641
|
import_log3.log.info("exec", {
|
|
493
|
-
function: def.
|
|
642
|
+
function: def.uri,
|
|
494
643
|
url
|
|
495
644
|
}, {
|
|
496
645
|
F: __dxlog_file3,
|
|
497
|
-
L:
|
|
646
|
+
L: 100,
|
|
498
647
|
S: this,
|
|
499
648
|
C: (f, a) => f(...a)
|
|
500
649
|
});
|
|
@@ -508,10 +657,10 @@ var Scheduler = class {
|
|
|
508
657
|
status = response.status;
|
|
509
658
|
} else if (callback) {
|
|
510
659
|
import_log3.log.info("exec", {
|
|
511
|
-
function: def.
|
|
660
|
+
function: def.uri
|
|
512
661
|
}, {
|
|
513
662
|
F: __dxlog_file3,
|
|
514
|
-
L:
|
|
663
|
+
L: 111,
|
|
515
664
|
S: this,
|
|
516
665
|
C: (f, a) => f(...a)
|
|
517
666
|
});
|
|
@@ -521,21 +670,21 @@ var Scheduler = class {
|
|
|
521
670
|
throw new Error(`Response: ${status}`);
|
|
522
671
|
}
|
|
523
672
|
import_log3.log.info("done", {
|
|
524
|
-
function: def.
|
|
673
|
+
function: def.uri,
|
|
525
674
|
status
|
|
526
675
|
}, {
|
|
527
676
|
F: __dxlog_file3,
|
|
528
|
-
L:
|
|
677
|
+
L: 121,
|
|
529
678
|
S: this,
|
|
530
679
|
C: (f, a) => f(...a)
|
|
531
680
|
});
|
|
532
681
|
} catch (err) {
|
|
533
682
|
import_log3.log.error("error", {
|
|
534
|
-
function: def.
|
|
683
|
+
function: def.uri,
|
|
535
684
|
error: err.message
|
|
536
685
|
}, {
|
|
537
686
|
F: __dxlog_file3,
|
|
538
|
-
L:
|
|
687
|
+
L: 123,
|
|
539
688
|
S: this,
|
|
540
689
|
C: (f, a) => f(...a)
|
|
541
690
|
});
|
|
@@ -543,334 +692,391 @@ var Scheduler = class {
|
|
|
543
692
|
}
|
|
544
693
|
return status;
|
|
545
694
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
695
|
+
};
|
|
696
|
+
var createContext2 = () => new import_context3.Context({
|
|
697
|
+
name: "FunctionScheduler"
|
|
698
|
+
});
|
|
699
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/subscription-trigger.ts";
|
|
700
|
+
var createSubscriptionTrigger = async (ctx, triggerCtx, spec, callback) => {
|
|
701
|
+
const objectIds = /* @__PURE__ */ new Set();
|
|
702
|
+
const task = new import_async4.DeferredTask(ctx, async () => {
|
|
703
|
+
if (objectIds.size > 0) {
|
|
704
|
+
await callback({
|
|
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
|
|
556
715
|
}, {
|
|
557
|
-
F:
|
|
558
|
-
L:
|
|
559
|
-
S:
|
|
716
|
+
F: __dxlog_file4,
|
|
717
|
+
L: 32,
|
|
718
|
+
S: void 0,
|
|
560
719
|
C: (f, a) => f(...a)
|
|
561
720
|
});
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
721
|
+
for (const object of added) {
|
|
722
|
+
objectIds.add(object.id);
|
|
723
|
+
}
|
|
724
|
+
for (const object of updated) {
|
|
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)
|
|
566
782
|
});
|
|
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)
|
|
567
810
|
});
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
811
|
+
spec.port = port;
|
|
812
|
+
});
|
|
813
|
+
ctx.onDispose(() => {
|
|
814
|
+
server.close();
|
|
815
|
+
});
|
|
816
|
+
};
|
|
817
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/websocket-trigger.ts";
|
|
818
|
+
var createWebsocketTrigger = async (ctx, triggerCtx, spec, callback, options = {
|
|
819
|
+
retryDelay: 2,
|
|
820
|
+
maxAttempts: 5
|
|
821
|
+
}) => {
|
|
822
|
+
const { url, init } = spec;
|
|
823
|
+
let ws;
|
|
824
|
+
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
|
|
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
|
|
582
831
|
}, {
|
|
583
|
-
F:
|
|
584
|
-
L:
|
|
585
|
-
S:
|
|
832
|
+
F: __dxlog_file7,
|
|
833
|
+
L: 39,
|
|
834
|
+
S: void 0,
|
|
586
835
|
C: (f, a) => f(...a)
|
|
587
836
|
});
|
|
588
|
-
|
|
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
|
|
846
|
+
}, {
|
|
847
|
+
F: __dxlog_file7,
|
|
848
|
+
L: 48,
|
|
849
|
+
S: void 0,
|
|
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,
|
|
874
|
+
C: (f, a) => f(...a)
|
|
875
|
+
});
|
|
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
|
+
}
|
|
589
899
|
}
|
|
590
900
|
});
|
|
591
|
-
|
|
592
|
-
|
|
901
|
+
const isOpen = await open.wait();
|
|
902
|
+
if (isOpen) {
|
|
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
|
+
}
|
|
593
918
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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);
|
|
944
|
+
}
|
|
945
|
+
async activate(triggerCtx, trigger, callback) {
|
|
946
|
+
(0, import_log4.log)("activate", {
|
|
947
|
+
space: triggerCtx.space.key,
|
|
600
948
|
trigger
|
|
601
949
|
}, {
|
|
602
|
-
F:
|
|
603
|
-
L:
|
|
950
|
+
F: __dxlog_file8,
|
|
951
|
+
L: 73,
|
|
604
952
|
S: this,
|
|
605
953
|
C: (f, a) => f(...a)
|
|
606
954
|
});
|
|
607
|
-
const
|
|
608
|
-
|
|
609
|
-
if (req.method !== spec.method) {
|
|
610
|
-
res.statusCode = 405;
|
|
611
|
-
return res.end();
|
|
612
|
-
}
|
|
613
|
-
res.statusCode = await this._execFunction(def, trigger, {
|
|
614
|
-
spaceKey: space.key
|
|
615
|
-
});
|
|
616
|
-
res.end();
|
|
617
|
-
});
|
|
618
|
-
const port = await (0, import_get_port_please2.getPort)({
|
|
619
|
-
random: true
|
|
620
|
-
});
|
|
621
|
-
server.listen(port, () => {
|
|
622
|
-
import_log3.log.info("started webhook", {
|
|
623
|
-
port
|
|
624
|
-
}, {
|
|
625
|
-
F: __dxlog_file3,
|
|
626
|
-
L: 223,
|
|
627
|
-
S: this,
|
|
628
|
-
C: (f, a) => f(...a)
|
|
629
|
-
});
|
|
630
|
-
spec.port = port;
|
|
955
|
+
const activationCtx = new import_context4.Context({
|
|
956
|
+
name: `trigger_${trigger.function}`
|
|
631
957
|
});
|
|
632
|
-
|
|
633
|
-
|
|
958
|
+
this._ctx.onDispose(() => activationCtx.dispose());
|
|
959
|
+
const registeredTrigger = this._triggersBySpaceKey.get(triggerCtx.space.key)?.find((reg) => reg.trigger.id === trigger.id);
|
|
960
|
+
(0, import_invariant2.invariant)(registeredTrigger, `Trigger is not registered: ${trigger.function}`, {
|
|
961
|
+
F: __dxlog_file8,
|
|
962
|
+
L: 79,
|
|
963
|
+
S: this,
|
|
964
|
+
A: [
|
|
965
|
+
"registeredTrigger",
|
|
966
|
+
"`Trigger is not registered: ${trigger.function}`"
|
|
967
|
+
]
|
|
634
968
|
});
|
|
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
|
+
}
|
|
635
977
|
}
|
|
636
978
|
/**
|
|
637
|
-
*
|
|
638
|
-
* NOTE: The port must be unique, so the same hook cannot be used for multiple spaces.
|
|
979
|
+
* Loads triggers from the manifest into the space.
|
|
639
980
|
*/
|
|
640
|
-
async
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}) {
|
|
644
|
-
import_log3.log.info("websocket", {
|
|
645
|
-
space: space.key,
|
|
646
|
-
trigger
|
|
981
|
+
async register(space, manifest) {
|
|
982
|
+
(0, import_log4.log)("register", {
|
|
983
|
+
space: space.key
|
|
647
984
|
}, {
|
|
648
|
-
F:
|
|
649
|
-
L:
|
|
985
|
+
F: __dxlog_file8,
|
|
986
|
+
L: 95,
|
|
650
987
|
S: this,
|
|
651
988
|
C: (f, a) => f(...a)
|
|
652
989
|
});
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
if (spec.init) {
|
|
670
|
-
ws.send(new TextEncoder().encode(JSON.stringify(init)));
|
|
671
|
-
}
|
|
672
|
-
open.wake(true);
|
|
673
|
-
},
|
|
674
|
-
onclose: (event) => {
|
|
675
|
-
import_log3.log.info("closed", {
|
|
676
|
-
url,
|
|
677
|
-
code: event.code
|
|
678
|
-
}, {
|
|
679
|
-
F: __dxlog_file3,
|
|
680
|
-
L: 269,
|
|
681
|
-
S: this,
|
|
682
|
-
C: (f, a) => f(...a)
|
|
683
|
-
});
|
|
684
|
-
if (event.code === 1006) {
|
|
685
|
-
setTimeout(async () => {
|
|
686
|
-
import_log3.log.info(`reconnecting in ${options.retryDelay}s...`, {
|
|
687
|
-
url
|
|
688
|
-
}, {
|
|
689
|
-
F: __dxlog_file3,
|
|
690
|
-
L: 274,
|
|
691
|
-
S: this,
|
|
692
|
-
C: (f, a) => f(...a)
|
|
693
|
-
});
|
|
694
|
-
await this._createWebsocket(ctx, space, def, trigger, options);
|
|
695
|
-
}, options.retryDelay * 1e3);
|
|
696
|
-
}
|
|
697
|
-
open.wake(false);
|
|
698
|
-
},
|
|
699
|
-
onerror: (event) => {
|
|
700
|
-
import_log3.log.catch(event.error, {
|
|
701
|
-
url
|
|
702
|
-
}, {
|
|
703
|
-
F: __dxlog_file3,
|
|
704
|
-
L: 283,
|
|
705
|
-
S: this,
|
|
706
|
-
C: (f, a) => f(...a)
|
|
707
|
-
});
|
|
708
|
-
},
|
|
709
|
-
onmessage: async (event) => {
|
|
710
|
-
try {
|
|
711
|
-
const data = JSON.parse(new TextDecoder().decode(event.data));
|
|
712
|
-
await this._execFunction(def, trigger, {
|
|
713
|
-
spaceKey: space.key,
|
|
714
|
-
data
|
|
715
|
-
});
|
|
716
|
-
} catch (err) {
|
|
717
|
-
import_log3.log.catch(err, {
|
|
718
|
-
url
|
|
719
|
-
}, {
|
|
720
|
-
F: __dxlog_file3,
|
|
721
|
-
L: 291,
|
|
722
|
-
S: this,
|
|
723
|
-
C: (f, a) => f(...a)
|
|
724
|
-
});
|
|
725
|
-
}
|
|
990
|
+
if (!manifest.triggers?.length) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
if (!space.db.graph.runtimeSchemaRegistry.hasSchema(FunctionTrigger)) {
|
|
994
|
+
space.db.graph.runtimeSchemaRegistry.registerSchema(FunctionTrigger);
|
|
995
|
+
}
|
|
996
|
+
const reactiveObjects = manifest.triggers.map((template) => (0, import_echo2.create)(FunctionTrigger, {
|
|
997
|
+
...template
|
|
998
|
+
}));
|
|
999
|
+
reactiveObjects.forEach((obj) => space.db.add(obj));
|
|
1000
|
+
}
|
|
1001
|
+
async _open() {
|
|
1002
|
+
const spaceListSubscription = this._client.spaces.subscribe(async (spaces) => {
|
|
1003
|
+
for (const space of spaces) {
|
|
1004
|
+
if (this._triggersBySpaceKey.has(space.key)) {
|
|
1005
|
+
continue;
|
|
726
1006
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
const wait = Math.pow(attempt, 2) * options.retryDelay;
|
|
733
|
-
if (attempt < options.maxAttempts) {
|
|
734
|
-
import_log3.log.warn(`failed to connect; trying again in ${wait}s`, {
|
|
735
|
-
attempt
|
|
736
|
-
}, {
|
|
737
|
-
F: __dxlog_file3,
|
|
738
|
-
L: 302,
|
|
739
|
-
S: this,
|
|
740
|
-
C: (f, a) => f(...a)
|
|
741
|
-
});
|
|
742
|
-
await (0, import_async2.sleep)(wait * 1e3);
|
|
1007
|
+
const registered = [];
|
|
1008
|
+
this._triggersBySpaceKey.set(space.key, registered);
|
|
1009
|
+
await space.waitUntilReady();
|
|
1010
|
+
if (this._ctx.disposed) {
|
|
1011
|
+
break;
|
|
743
1012
|
}
|
|
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);
|
|
744
1018
|
}
|
|
745
|
-
}
|
|
746
|
-
ctx.onDispose(() => {
|
|
747
|
-
ws?.close();
|
|
748
1019
|
});
|
|
1020
|
+
this._ctx.onDispose(() => spaceListSubscription.unsubscribe());
|
|
749
1021
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
trigger
|
|
757
|
-
}, {
|
|
758
|
-
F: __dxlog_file3,
|
|
759
|
-
L: 317,
|
|
760
|
-
S: this,
|
|
761
|
-
C: (f, a) => f(...a)
|
|
1022
|
+
async _close(_) {
|
|
1023
|
+
this._triggersBySpaceKey.clear();
|
|
1024
|
+
}
|
|
1025
|
+
_handleNewTriggers(space, allTriggers, registered) {
|
|
1026
|
+
const newTriggers = allTriggers.filter((candidate) => {
|
|
1027
|
+
return registered.find((reg) => reg.trigger.id === candidate.id) == null;
|
|
762
1028
|
});
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
1029
|
+
if (newTriggers.length > 0) {
|
|
1030
|
+
const newRegisteredTriggers = newTriggers.map((trigger) => ({
|
|
1031
|
+
trigger
|
|
1032
|
+
}));
|
|
1033
|
+
registered.push(...newRegisteredTriggers);
|
|
1034
|
+
(0, import_log4.log)("registered new triggers", () => ({
|
|
767
1035
|
spaceKey: space.key,
|
|
768
|
-
|
|
769
|
-
})
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
const subscription = (0, import_echo.createSubscription)(({ added, updated }) => {
|
|
773
|
-
import_log3.log.info("updated", {
|
|
774
|
-
added: added.length,
|
|
775
|
-
updated: updated.length
|
|
776
|
-
}, {
|
|
777
|
-
F: __dxlog_file3,
|
|
778
|
-
L: 329,
|
|
1036
|
+
functions: newTriggers.map((t) => t.function)
|
|
1037
|
+
}), {
|
|
1038
|
+
F: __dxlog_file8,
|
|
1039
|
+
L: 146,
|
|
779
1040
|
S: this,
|
|
780
1041
|
C: (f, a) => f(...a)
|
|
781
1042
|
});
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
objects: objects.length
|
|
797
|
-
}, {
|
|
798
|
-
F: __dxlog_file3,
|
|
799
|
-
L: 349,
|
|
800
|
-
S: this,
|
|
801
|
-
C: (f, a) => f(...a)
|
|
802
|
-
});
|
|
803
|
-
for (const object of objects) {
|
|
804
|
-
const content = object.content;
|
|
805
|
-
if (content instanceof import_types.TextV0Type) {
|
|
806
|
-
subscriptions.push((0, import_echo.getAutomergeObjectCore)(content).updates.on((0, import_async2.debounce)(() => subscription.update([
|
|
807
|
-
object
|
|
808
|
-
]), 1e3)));
|
|
809
|
-
}
|
|
810
|
-
}
|
|
1043
|
+
this.registered.emit({
|
|
1044
|
+
space,
|
|
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);
|
|
811
1057
|
}
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1058
|
+
}
|
|
1059
|
+
if (removed.length > 0) {
|
|
1060
|
+
this.removed.emit({
|
|
1061
|
+
space,
|
|
1062
|
+
triggers: removed
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
_getTriggers(space, predicate) {
|
|
1067
|
+
const allSpaceTriggers = this._triggersBySpaceKey.get(space.key) ?? [];
|
|
1068
|
+
return allSpaceTriggers.filter(predicate).map((trigger) => trigger.trigger);
|
|
818
1069
|
}
|
|
819
1070
|
};
|
|
820
|
-
var TimerTriggerSchema = S.struct({
|
|
821
|
-
cron: S.string
|
|
822
|
-
});
|
|
823
|
-
var WebhookTriggerSchema = S.mutable(S.struct({
|
|
824
|
-
method: S.string,
|
|
825
|
-
// Assigned port.
|
|
826
|
-
port: S.optional(S.number)
|
|
827
|
-
}));
|
|
828
|
-
var WebsocketTriggerSchema = S.struct({
|
|
829
|
-
url: S.string,
|
|
830
|
-
init: S.optional(S.record(S.string, S.any))
|
|
831
|
-
});
|
|
832
|
-
var SubscriptionTriggerSchema = S.struct({
|
|
833
|
-
spaceKey: S.optional(S.string),
|
|
834
|
-
// TODO(burdon): Define query DSL.
|
|
835
|
-
filter: S.array(S.struct({
|
|
836
|
-
type: S.string,
|
|
837
|
-
props: S.optional(S.record(S.string, S.any))
|
|
838
|
-
})),
|
|
839
|
-
options: S.optional(S.struct({
|
|
840
|
-
// Watch changes to object (not just creation).
|
|
841
|
-
deep: S.optional(S.boolean),
|
|
842
|
-
// Debounce changes (delay in ms).
|
|
843
|
-
delay: S.optional(S.number)
|
|
844
|
-
}))
|
|
845
|
-
});
|
|
846
|
-
var FunctionTriggerSchema = S.struct({
|
|
847
|
-
function: S.string.pipe(S.description("Function ID/URI.")),
|
|
848
|
-
// Context passed to function.
|
|
849
|
-
meta: S.optional(S.record(S.string, S.any)),
|
|
850
|
-
// Triggers.
|
|
851
|
-
timer: S.optional(TimerTriggerSchema),
|
|
852
|
-
webhook: S.optional(WebhookTriggerSchema),
|
|
853
|
-
websocket: S.optional(WebsocketTriggerSchema),
|
|
854
|
-
subscription: S.optional(SubscriptionTriggerSchema)
|
|
855
|
-
});
|
|
856
|
-
var FunctionDefSchema = S.struct({
|
|
857
|
-
id: S.string,
|
|
858
|
-
// name: S.string,
|
|
859
|
-
description: S.optional(S.string),
|
|
860
|
-
// TODO(burdon): Rename route?
|
|
861
|
-
path: S.string,
|
|
862
|
-
// TODO(burdon): NPM/GitHub/Docker/CF URL?
|
|
863
|
-
handler: S.string
|
|
864
|
-
});
|
|
865
|
-
var FunctionManifestSchema = S.struct({
|
|
866
|
-
functions: S.mutable(S.array(FunctionDefSchema)),
|
|
867
|
-
triggers: S.optional(S.mutable(S.array(FunctionTriggerSchema)))
|
|
868
|
-
});
|
|
869
1071
|
// Annotate the CommonJS export names for ESM import in node:
|
|
870
1072
|
0 && (module.exports = {
|
|
871
1073
|
DevServer,
|
|
1074
|
+
FunctionDef,
|
|
872
1075
|
FunctionManifestSchema,
|
|
1076
|
+
FunctionRegistry,
|
|
1077
|
+
FunctionTrigger,
|
|
873
1078
|
Scheduler,
|
|
1079
|
+
TriggerRegistry,
|
|
874
1080
|
subscriptionHandler
|
|
875
1081
|
});
|
|
876
1082
|
//# sourceMappingURL=index.cjs.map
|