@dxos/functions 0.5.3-main.79e0565 → 0.5.3-main.7cd4303

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