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