@dxos/functions 0.6.13 → 0.6.14-main.1366248

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 (52) hide show
  1. package/dist/lib/browser/{chunk-CRAAIWU6.mjs → chunk-2O2MAZE4.mjs} +28 -14
  2. package/dist/lib/browser/chunk-2O2MAZE4.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-2I75VGHZ.mjs → chunk-TNNXVSUN.mjs} +16 -12
  4. package/dist/lib/browser/chunk-TNNXVSUN.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +7 -5
  6. package/dist/lib/browser/index.mjs.map +2 -2
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +9 -9
  9. package/dist/lib/browser/testing/index.mjs.map +3 -3
  10. package/dist/lib/browser/types.mjs +1 -1
  11. package/dist/lib/node/{chunk-JV3VNH5X.cjs → chunk-O44VB3FE.cjs} +19 -8
  12. package/dist/lib/node/chunk-O44VB3FE.cjs.map +7 -0
  13. package/dist/lib/node/{chunk-OGLDVNFE.cjs → chunk-SCSHB4MF.cjs} +42 -37
  14. package/dist/lib/node/chunk-SCSHB4MF.cjs.map +7 -0
  15. package/dist/lib/node/index.cjs +16 -14
  16. package/dist/lib/node/index.cjs.map +2 -2
  17. package/dist/lib/node/meta.json +1 -1
  18. package/dist/lib/node/testing/index.cjs +15 -15
  19. package/dist/lib/node/testing/index.cjs.map +3 -3
  20. package/dist/lib/node/types.cjs +5 -5
  21. package/dist/lib/node/types.cjs.map +1 -1
  22. package/dist/lib/node-esm/chunk-AM7SW4YW.mjs +604 -0
  23. package/dist/lib/node-esm/chunk-AM7SW4YW.mjs.map +7 -0
  24. package/dist/lib/node-esm/chunk-TJ4S5QZ3.mjs +90 -0
  25. package/dist/lib/node-esm/chunk-TJ4S5QZ3.mjs.map +7 -0
  26. package/dist/lib/node-esm/index.mjs +94 -0
  27. package/dist/lib/node-esm/index.mjs.map +7 -0
  28. package/dist/lib/node-esm/meta.json +1 -0
  29. package/dist/lib/node-esm/testing/index.mjs +666 -0
  30. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  31. package/dist/lib/node-esm/types.mjs +14 -0
  32. package/dist/lib/node-esm/types.mjs.map +7 -0
  33. package/dist/types/src/handler.d.ts +2 -2
  34. package/dist/types/src/handler.d.ts.map +1 -1
  35. package/dist/types/src/testing/setup.d.ts.map +1 -1
  36. package/dist/types/src/trigger/type/websocket-trigger.d.ts +1 -0
  37. package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +1 -1
  38. package/dist/types/src/types.d.ts +2 -2
  39. package/package.json +23 -27
  40. package/src/function/function-registry.test.ts +3 -2
  41. package/src/handler.ts +3 -2
  42. package/src/runtime/dev-server.test.ts +7 -6
  43. package/src/runtime/scheduler.test.ts +9 -6
  44. package/src/testing/functions-integration.test.ts +7 -5
  45. package/src/testing/setup.ts +10 -3
  46. package/src/trigger/trigger-registry.test.ts +3 -5
  47. package/src/trigger/type/websocket-trigger.ts +22 -6
  48. package/src/types.ts +4 -4
  49. package/dist/lib/browser/chunk-2I75VGHZ.mjs.map +0 -7
  50. package/dist/lib/browser/chunk-CRAAIWU6.mjs.map +0 -7
  51. package/dist/lib/node/chunk-JV3VNH5X.cjs.map +0 -7
  52. package/dist/lib/node/chunk-OGLDVNFE.cjs.map +0 -7
@@ -0,0 +1,666 @@
1
+ import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
+ import {
3
+ FunctionRegistry,
4
+ TriggerRegistry
5
+ } from "../chunk-AM7SW4YW.mjs";
6
+ import {
7
+ FunctionDef,
8
+ FunctionTrigger,
9
+ __require
10
+ } from "../chunk-TJ4S5QZ3.mjs";
11
+
12
+ // packages/core/functions/src/testing/setup.ts
13
+ import { getRandomPort } from "get-port-please";
14
+ import path2 from "node:path";
15
+ import { waitForCondition } from "@dxos/async";
16
+ import { Client, Config } from "@dxos/client";
17
+ import { range } from "@dxos/util";
18
+
19
+ // packages/core/functions/src/testing/types.ts
20
+ import { S, TypedObject } from "@dxos/echo-schema";
21
+ var TestType = class extends TypedObject({
22
+ typename: "example.com/type/Test",
23
+ version: "0.1.0"
24
+ })({
25
+ title: S.String
26
+ }) {
27
+ };
28
+
29
+ // packages/core/functions/src/runtime/dev-server.ts
30
+ import express from "express";
31
+ import { getPort } from "get-port-please";
32
+ import { join } from "node:path";
33
+ import { asyncTimeout, Event, Trigger } from "@dxos/async";
34
+ import { Context } from "@dxos/context";
35
+ import { invariant } from "@dxos/invariant";
36
+ import { log } from "@dxos/log";
37
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
38
+ var FN_TIMEOUT = 2e4;
39
+ var DevServer = class {
40
+ constructor(_client, _functionsRegistry, _options) {
41
+ this._client = _client;
42
+ this._functionsRegistry = _functionsRegistry;
43
+ this._options = _options;
44
+ this._ctx = createContext();
45
+ this._handlers = {};
46
+ this._seq = 0;
47
+ this.update = new Event();
48
+ }
49
+ get stats() {
50
+ return {
51
+ seq: this._seq
52
+ };
53
+ }
54
+ get endpoint() {
55
+ invariant(this._port, void 0, {
56
+ F: __dxlog_file,
57
+ L: 60,
58
+ S: this,
59
+ A: [
60
+ "this._port",
61
+ ""
62
+ ]
63
+ });
64
+ return `http://localhost:${this._port}`;
65
+ }
66
+ get proxy() {
67
+ return this._proxy;
68
+ }
69
+ get functions() {
70
+ return Object.values(this._handlers);
71
+ }
72
+ async start() {
73
+ invariant(!this._server, void 0, {
74
+ F: __dxlog_file,
75
+ L: 73,
76
+ S: this,
77
+ A: [
78
+ "!this._server",
79
+ ""
80
+ ]
81
+ });
82
+ log.info("starting...", void 0, {
83
+ F: __dxlog_file,
84
+ L: 74,
85
+ S: this,
86
+ C: (f, a) => f(...a)
87
+ });
88
+ this._ctx = createContext();
89
+ const app = express();
90
+ app.use(express.json());
91
+ app.post("/:path", async (req, res) => {
92
+ const { path: path3 } = req.params;
93
+ try {
94
+ log.info("calling", {
95
+ path: path3
96
+ }, {
97
+ F: __dxlog_file,
98
+ L: 84,
99
+ S: this,
100
+ C: (f, a) => f(...a)
101
+ });
102
+ if (this._options.reload) {
103
+ const { def } = this._handlers["/" + path3];
104
+ await this._load(def, true);
105
+ }
106
+ res.statusCode = await asyncTimeout(this.invoke("/" + path3, req.body), FN_TIMEOUT);
107
+ res.end();
108
+ } catch (err) {
109
+ log.catch(err, void 0, {
110
+ F: __dxlog_file,
111
+ L: 94,
112
+ S: this,
113
+ C: (f, a) => f(...a)
114
+ });
115
+ res.statusCode = 500;
116
+ res.end();
117
+ }
118
+ });
119
+ this._port = this._options.port ?? await getPort({
120
+ host: "localhost",
121
+ port: 7200,
122
+ portRange: [
123
+ 7200,
124
+ 7299
125
+ ]
126
+ });
127
+ this._server = app.listen(this._port);
128
+ try {
129
+ const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
130
+ endpoint: this.endpoint
131
+ });
132
+ log.info("registered", {
133
+ endpoint
134
+ }, {
135
+ F: __dxlog_file,
136
+ L: 109,
137
+ S: this,
138
+ C: (f, a) => f(...a)
139
+ });
140
+ this._proxy = endpoint;
141
+ this._functionServiceRegistration = registrationId;
142
+ await this._handleNewFunctions(this._functionsRegistry.getUniqueByUri());
143
+ this._ctx.onDispose(this._functionsRegistry.registered.on(({ added }) => this._handleNewFunctions(added)));
144
+ } catch (err) {
145
+ await this.stop();
146
+ throw new Error("FunctionRegistryService not available (check plugin is configured).");
147
+ }
148
+ log.info("started", {
149
+ port: this._port
150
+ }, {
151
+ F: __dxlog_file,
152
+ L: 121,
153
+ S: this,
154
+ C: (f, a) => f(...a)
155
+ });
156
+ }
157
+ async stop() {
158
+ if (!this._server) {
159
+ return;
160
+ }
161
+ log.info("stopping...", void 0, {
162
+ F: __dxlog_file,
163
+ L: 129,
164
+ S: this,
165
+ C: (f, a) => f(...a)
166
+ });
167
+ await this._ctx.dispose();
168
+ const trigger = new Trigger();
169
+ this._server.close(async () => {
170
+ log.info("server stopped", void 0, {
171
+ F: __dxlog_file,
172
+ L: 134,
173
+ S: this,
174
+ C: (f, a) => f(...a)
175
+ });
176
+ try {
177
+ if (this._functionServiceRegistration) {
178
+ invariant(this._client.services.services.FunctionRegistryService, void 0, {
179
+ F: __dxlog_file,
180
+ L: 137,
181
+ S: this,
182
+ A: [
183
+ "this._client.services.services.FunctionRegistryService",
184
+ ""
185
+ ]
186
+ });
187
+ await this._client.services.services.FunctionRegistryService.unregister({
188
+ registrationId: this._functionServiceRegistration
189
+ });
190
+ log.info("unregistered", {
191
+ registrationId: this._functionServiceRegistration
192
+ }, {
193
+ F: __dxlog_file,
194
+ L: 142,
195
+ S: this,
196
+ C: (f, a) => f(...a)
197
+ });
198
+ this._functionServiceRegistration = void 0;
199
+ this._proxy = void 0;
200
+ }
201
+ trigger.wake();
202
+ } catch (err) {
203
+ trigger.throw(err);
204
+ }
205
+ });
206
+ await trigger.wait();
207
+ this._port = void 0;
208
+ this._server = void 0;
209
+ log.info("stopped", void 0, {
210
+ F: __dxlog_file,
211
+ L: 156,
212
+ S: this,
213
+ C: (f, a) => f(...a)
214
+ });
215
+ }
216
+ async _handleNewFunctions(newFunctions) {
217
+ newFunctions.forEach((def) => this._load(def));
218
+ await this._safeUpdateRegistration();
219
+ log("new functions loaded", {
220
+ newFunctions
221
+ }, {
222
+ F: __dxlog_file,
223
+ L: 162,
224
+ S: this,
225
+ C: (f, a) => f(...a)
226
+ });
227
+ }
228
+ /**
229
+ * Load function.
230
+ */
231
+ async _load(def, force) {
232
+ const { uri, route, handler } = def;
233
+ const filePath = join(this._options.baseDir, handler);
234
+ log.info("loading", {
235
+ uri,
236
+ force
237
+ }, {
238
+ F: __dxlog_file,
239
+ L: 171,
240
+ S: this,
241
+ C: (f, a) => f(...a)
242
+ });
243
+ if (force) {
244
+ Object.keys(__require.cache).filter((key) => key.startsWith(filePath)).forEach((key) => {
245
+ delete __require.cache[key];
246
+ });
247
+ }
248
+ const module = __require(filePath);
249
+ if (typeof module.default !== "function") {
250
+ throw new Error(`Handler must export default function: ${uri}`);
251
+ }
252
+ this._handlers[route] = {
253
+ def,
254
+ handler: module.default
255
+ };
256
+ }
257
+ async _safeUpdateRegistration() {
258
+ invariant(this._functionServiceRegistration, void 0, {
259
+ F: __dxlog_file,
260
+ L: 193,
261
+ S: this,
262
+ A: [
263
+ "this._functionServiceRegistration",
264
+ ""
265
+ ]
266
+ });
267
+ try {
268
+ await this._client.services.services.FunctionRegistryService.updateRegistration({
269
+ registrationId: this._functionServiceRegistration,
270
+ functions: this.functions.map(({ def: { id, route } }) => ({
271
+ id,
272
+ route
273
+ }))
274
+ });
275
+ } catch (err) {
276
+ log.catch(err, void 0, {
277
+ F: __dxlog_file,
278
+ L: 200,
279
+ S: this,
280
+ C: (f, a) => f(...a)
281
+ });
282
+ }
283
+ }
284
+ /**
285
+ * Invoke function.
286
+ */
287
+ async invoke(path3, data) {
288
+ const seq = ++this._seq;
289
+ const now = Date.now();
290
+ log.info("req", {
291
+ seq,
292
+ path: path3
293
+ }, {
294
+ F: __dxlog_file,
295
+ L: 211,
296
+ S: this,
297
+ C: (f, a) => f(...a)
298
+ });
299
+ const statusCode = await this._invoke(path3, {
300
+ data
301
+ });
302
+ log.info("res", {
303
+ seq,
304
+ path: path3,
305
+ statusCode,
306
+ duration: Date.now() - now
307
+ }, {
308
+ F: __dxlog_file,
309
+ L: 214,
310
+ S: this,
311
+ C: (f, a) => f(...a)
312
+ });
313
+ this.update.emit(statusCode);
314
+ return statusCode;
315
+ }
316
+ async _invoke(path3, event) {
317
+ const { handler } = this._handlers[path3] ?? {};
318
+ invariant(handler, `invalid path: ${path3}`, {
319
+ F: __dxlog_file,
320
+ L: 221,
321
+ S: this,
322
+ A: [
323
+ "handler",
324
+ "`invalid path: ${path}`"
325
+ ]
326
+ });
327
+ const context = {
328
+ client: this._client,
329
+ dataDir: this._options.dataDir
330
+ };
331
+ let statusCode = 200;
332
+ const response = {
333
+ status: (code) => {
334
+ statusCode = code;
335
+ return response;
336
+ }
337
+ };
338
+ await handler({
339
+ context,
340
+ event,
341
+ response
342
+ });
343
+ return statusCode;
344
+ }
345
+ };
346
+ var createContext = () => new Context({
347
+ name: "DevServer"
348
+ }, {
349
+ F: __dxlog_file,
350
+ L: 240
351
+ });
352
+
353
+ // packages/core/functions/src/runtime/scheduler.ts
354
+ import path from "node:path";
355
+ import { Mutex } from "@dxos/async";
356
+ import { loadObjectReferences } from "@dxos/client/echo";
357
+ import { Context as Context2 } from "@dxos/context";
358
+ import { Reference } from "@dxos/echo-protocol";
359
+ import { log as log2 } from "@dxos/log";
360
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
361
+ var Scheduler = class {
362
+ constructor(functions, triggers, _options = {}) {
363
+ this.functions = functions;
364
+ this.triggers = triggers;
365
+ this._options = _options;
366
+ this._ctx = createContext2();
367
+ this._functionUriToCallMutex = /* @__PURE__ */ new Map();
368
+ this.functions.registered.on(async ({ space, added }) => {
369
+ await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), added);
370
+ });
371
+ this.triggers.registered.on(async ({ space, triggers: triggers2 }) => {
372
+ await this._safeActivateTriggers(space, triggers2, this.functions.getFunctions(space));
373
+ });
374
+ }
375
+ async start() {
376
+ await this._ctx.dispose();
377
+ this._ctx = createContext2();
378
+ await this.functions.open(this._ctx);
379
+ await this.triggers.open(this._ctx);
380
+ }
381
+ async stop() {
382
+ await this._ctx.dispose();
383
+ await this.functions.close();
384
+ await this.triggers.close();
385
+ }
386
+ // TODO(burdon): Remove and update registries directly?
387
+ async register(space, manifest) {
388
+ await this.functions.register(space, manifest.functions);
389
+ await this.triggers.register(space, manifest);
390
+ }
391
+ async _safeActivateTriggers(space, triggers, functions) {
392
+ const mountTasks = triggers.map((trigger) => {
393
+ return this.activate(space, functions, trigger);
394
+ });
395
+ await Promise.all(mountTasks).catch(log2.catch);
396
+ }
397
+ /**
398
+ * Activate trigger.
399
+ */
400
+ // TODO(burdon): How are triggers deactivated?
401
+ async activate(space, functions, trigger) {
402
+ const definition = functions.find((def) => def.uri === trigger.function);
403
+ if (!definition) {
404
+ log2.info("function is not found for trigger", {
405
+ trigger
406
+ }, {
407
+ F: __dxlog_file2,
408
+ L: 85,
409
+ S: this,
410
+ C: (f, a) => f(...a)
411
+ });
412
+ return;
413
+ }
414
+ const execFunction = async (args) => {
415
+ const mutex = this._functionUriToCallMutex.get(definition.uri) ?? new Mutex();
416
+ this._functionUriToCallMutex.set(definition.uri, mutex);
417
+ log2.info("function triggered, waiting for mutex", {
418
+ uri: definition.uri
419
+ }, {
420
+ F: __dxlog_file2,
421
+ L: 93,
422
+ S: this,
423
+ C: (f, a) => f(...a)
424
+ });
425
+ return mutex.executeSynchronized(async () => {
426
+ log2.info("mutex acquired", {
427
+ uri: definition.uri
428
+ }, {
429
+ F: __dxlog_file2,
430
+ L: 95,
431
+ S: this,
432
+ C: (f, a) => f(...a)
433
+ });
434
+ await loadObjectReferences(trigger, (t) => Object.values(t.meta ?? {}));
435
+ const meta = {};
436
+ for (const [key, value] of Object.entries(trigger.meta ?? {})) {
437
+ if (value instanceof Reference) {
438
+ const object = await space.db.loadObjectById(value.objectId);
439
+ if (object) {
440
+ meta[key] = object;
441
+ }
442
+ } else {
443
+ meta[key] = value;
444
+ }
445
+ }
446
+ return this._execFunction(definition, trigger, {
447
+ meta,
448
+ data: {
449
+ ...args,
450
+ spaceKey: space.key
451
+ }
452
+ });
453
+ });
454
+ };
455
+ await this.triggers.activate(space, trigger, execFunction);
456
+ log2("activated trigger", {
457
+ space: space.key,
458
+ trigger
459
+ }, {
460
+ F: __dxlog_file2,
461
+ L: 119,
462
+ S: this,
463
+ C: (f, a) => f(...a)
464
+ });
465
+ }
466
+ /**
467
+ * Invoke function RPC.
468
+ */
469
+ async _execFunction(def, trigger, { meta, data }) {
470
+ let status = 0;
471
+ try {
472
+ const payload = Object.assign({}, meta && {
473
+ meta
474
+ }, data);
475
+ const { endpoint, callback } = this._options;
476
+ if (endpoint) {
477
+ const url = path.join(endpoint, def.route);
478
+ log2.info("exec", {
479
+ function: def.uri,
480
+ url,
481
+ triggerType: trigger.spec.type
482
+ }, {
483
+ F: __dxlog_file2,
484
+ L: 139,
485
+ S: this,
486
+ C: (f, a) => f(...a)
487
+ });
488
+ const response = await fetch(url, {
489
+ method: "POST",
490
+ headers: {
491
+ "Content-Type": "application/json"
492
+ },
493
+ body: JSON.stringify(payload)
494
+ });
495
+ status = response.status;
496
+ } else if (callback) {
497
+ log2.info("exec", {
498
+ function: def.uri
499
+ }, {
500
+ F: __dxlog_file2,
501
+ L: 150,
502
+ S: this,
503
+ C: (f, a) => f(...a)
504
+ });
505
+ status = await callback(payload) ?? 200;
506
+ }
507
+ if (status && status >= 400) {
508
+ throw new Error(`Response: ${status}`);
509
+ }
510
+ log2.info("done", {
511
+ function: def.uri,
512
+ status
513
+ }, {
514
+ F: __dxlog_file2,
515
+ L: 160,
516
+ S: this,
517
+ C: (f, a) => f(...a)
518
+ });
519
+ } catch (err) {
520
+ log2.error("error", {
521
+ function: def.uri,
522
+ error: err.message
523
+ }, {
524
+ F: __dxlog_file2,
525
+ L: 162,
526
+ S: this,
527
+ C: (f, a) => f(...a)
528
+ });
529
+ status = 500;
530
+ }
531
+ return status;
532
+ }
533
+ };
534
+ var createContext2 = () => new Context2({
535
+ name: "FunctionScheduler"
536
+ }, {
537
+ F: __dxlog_file2,
538
+ L: 170
539
+ });
540
+
541
+ // packages/core/functions/src/testing/setup.ts
542
+ var createInitializedClients = async (testBuilder, count = 1, config) => {
543
+ const clients = range(count).map(() => new Client({
544
+ config,
545
+ services: testBuilder.createLocalClientServices(),
546
+ types: [
547
+ FunctionDef,
548
+ FunctionTrigger,
549
+ TestType
550
+ ]
551
+ }));
552
+ testBuilder.ctx.onDispose(() => Promise.all(clients.map((client) => client.destroy())));
553
+ return Promise.all(clients.map(async (client, index) => {
554
+ await client.initialize();
555
+ await client.halo.createIdentity({
556
+ displayName: `Peer ${index}`
557
+ });
558
+ await client.spaces.waitUntilReady();
559
+ return client;
560
+ }));
561
+ };
562
+ var createFunctionRuntime = async (testBuilder, pluginInitializer) => {
563
+ const functionsPort = await getRandomPort("127.0.0.1");
564
+ const config = new Config({
565
+ runtime: {
566
+ agent: {
567
+ plugins: [
568
+ {
569
+ id: "dxos.org/agent/plugin/functions",
570
+ config: {
571
+ port: functionsPort
572
+ }
573
+ }
574
+ ]
575
+ }
576
+ }
577
+ });
578
+ const [client] = await createInitializedClients(testBuilder, 1, config);
579
+ const plugin = await pluginInitializer(client);
580
+ testBuilder.ctx.onDispose(() => plugin.close());
581
+ return client;
582
+ };
583
+ var startFunctionsHost = async (testBuilder, pluginInitializer, options) => {
584
+ const functionRuntime = await createFunctionRuntime(testBuilder, pluginInitializer);
585
+ const functionsRegistry = new FunctionRegistry(functionRuntime);
586
+ const devServer = await startDevServer(testBuilder, functionRuntime, functionsRegistry, options);
587
+ const scheduler = await startScheduler(testBuilder, functionRuntime, devServer, functionsRegistry);
588
+ return {
589
+ scheduler,
590
+ client: functionRuntime,
591
+ waitForActiveTriggers: async (space) => {
592
+ await waitForCondition({
593
+ condition: () => scheduler.triggers.getActiveTriggers(space).length > 0
594
+ });
595
+ }
596
+ };
597
+ };
598
+ var startScheduler = async (testBuilder, client, devServer, functionRegistry) => {
599
+ const triggerRegistry = new TriggerRegistry(client);
600
+ const scheduler = new Scheduler(functionRegistry, triggerRegistry, {
601
+ endpoint: devServer.endpoint
602
+ });
603
+ await scheduler.start();
604
+ testBuilder.ctx.onDispose(() => scheduler.stop());
605
+ return scheduler;
606
+ };
607
+ var startDevServer = async (testBuilder, client, functionRegistry, options) => {
608
+ const server = new DevServer(client, functionRegistry, {
609
+ baseDir: path2.join(__dirname, "../testing"),
610
+ port: await getRandomPort("127.0.0.1"),
611
+ ...options
612
+ });
613
+ await server.start();
614
+ testBuilder.ctx.onDispose(() => server.stop());
615
+ return server;
616
+ };
617
+
618
+ // packages/core/functions/src/testing/util.ts
619
+ import { Filter } from "@dxos/client/echo";
620
+ import { performInvitation } from "@dxos/client/testing";
621
+ import { invariant as invariant2 } from "@dxos/invariant";
622
+ import { Invitation } from "@dxos/protocols/proto/dxos/client/services";
623
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/functions/src/testing/util.ts";
624
+ var triggerWebhook = async (space, uri) => {
625
+ const trigger = (await space.db.query(Filter.schema(FunctionTrigger, (t) => t.function === uri)).run()).objects[0];
626
+ invariant2(trigger.spec.type === "webhook", void 0, {
627
+ F: __dxlog_file3,
628
+ L: 17,
629
+ S: void 0,
630
+ A: [
631
+ "trigger.spec.type === 'webhook'",
632
+ ""
633
+ ]
634
+ });
635
+ void fetch(`http://localhost:${trigger.spec.port}`);
636
+ };
637
+ var inviteMember = async (host, guest) => {
638
+ const [{ invitation: hostInvitation }] = await Promise.all(performInvitation({
639
+ host,
640
+ guest: guest.spaces
641
+ }));
642
+ if (hostInvitation?.state !== Invitation.State.SUCCESS) {
643
+ throw new Error(`Expected ${hostInvitation?.state} to be ${Invitation.State.SUCCESS}.`);
644
+ }
645
+ };
646
+
647
+ // packages/core/functions/src/testing/manifest.ts
648
+ var testFunctionManifest = {
649
+ functions: [
650
+ {
651
+ uri: "example.com/function/test",
652
+ route: "test",
653
+ handler: "test"
654
+ }
655
+ ]
656
+ };
657
+ export {
658
+ TestType,
659
+ createFunctionRuntime,
660
+ createInitializedClients,
661
+ inviteMember,
662
+ startFunctionsHost,
663
+ testFunctionManifest,
664
+ triggerWebhook
665
+ };
666
+ //# sourceMappingURL=index.mjs.map