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

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