@dxos/functions 0.5.3-main.f9b873d → 0.5.3-main.fffc127

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