@dxos/functions 0.5.3-main.d3c5e1f → 0.5.3-main.d7fe7b5

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