@dxos/functions 0.5.3-main.ce64a40 → 0.5.3-main.d2f7366

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