@dxos/functions 0.5.3-main.3456876 → 0.5.3-main.3b535c7

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.
@@ -22,9 +22,9 @@ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/hand
22
22
  var subscriptionHandler = (handler) => {
23
23
  return ({ event, context, ...rest }) => {
24
24
  const { client } = context;
25
- const space = event.spaceKey ? client.spaces.get(PublicKey.from(event.spaceKey)) : void 0;
25
+ const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : void 0;
26
26
  const objects = space && event.objects?.map((id) => space.db.getObjectById(id)).filter(nonNullable);
27
- if (!!event.spaceKey && !space) {
27
+ if (!!event.space && !space) {
28
28
  log.warn("invalid space", {
29
29
  event
30
30
  }, {
@@ -59,7 +59,7 @@ var subscriptionHandler = (handler) => {
59
59
  import express from "express";
60
60
  import { getPort } from "get-port-please";
61
61
  import { join } from "@dxos/node-std/path";
62
- import { Event, Trigger } from "@dxos/async";
62
+ import { Trigger } from "@dxos/async";
63
63
  import { invariant } from "@dxos/invariant";
64
64
  import { log as log2 } from "@dxos/log";
65
65
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
@@ -70,17 +70,11 @@ var DevServer = class {
70
70
  this._options = _options;
71
71
  this._handlers = {};
72
72
  this._seq = 0;
73
- this.update = new Event();
74
- }
75
- get stats() {
76
- return {
77
- seq: this._seq
78
- };
79
73
  }
80
74
  get endpoint() {
81
75
  invariant(this._port, void 0, {
82
76
  F: __dxlog_file2,
83
- L: 54,
77
+ L: 46,
84
78
  S: this,
85
79
  A: [
86
80
  "this._port",
@@ -102,7 +96,7 @@ var DevServer = class {
102
96
  } catch (err) {
103
97
  log2.error("parsing function (check manifest)", err, {
104
98
  F: __dxlog_file2,
105
- L: 71,
99
+ L: 63,
106
100
  S: this,
107
101
  C: (f, a) => f(...a)
108
102
  });
@@ -110,44 +104,29 @@ var DevServer = class {
110
104
  }
111
105
  }
112
106
  async start() {
113
- invariant(!this._server, void 0, {
114
- F: __dxlog_file2,
115
- L: 77,
116
- S: this,
117
- A: [
118
- "!this._server",
119
- ""
120
- ]
121
- });
122
- log2.info("starting...", void 0, {
123
- F: __dxlog_file2,
124
- L: 78,
125
- S: this,
126
- C: (f, a) => f(...a)
127
- });
128
107
  const app = express();
129
108
  app.use(express.json());
130
- app.post("/:path", async (req, res) => {
131
- const { path: path2 } = req.params;
109
+ app.post("/:name", async (req, res) => {
110
+ const { name } = req.params;
132
111
  try {
133
112
  log2.info("calling", {
134
- path: path2
113
+ name
135
114
  }, {
136
115
  F: __dxlog_file2,
137
- L: 87,
116
+ L: 75,
138
117
  S: this,
139
118
  C: (f, a) => f(...a)
140
119
  });
141
120
  if (this._options.reload) {
142
- const { def } = this._handlers["/" + path2];
121
+ const { def } = this._handlers[name];
143
122
  await this._load(def, true);
144
123
  }
145
- res.statusCode = await this.invoke("/" + path2, req.body);
124
+ res.statusCode = await this._invoke(name, req.body);
146
125
  res.end();
147
126
  } catch (err) {
148
127
  log2.catch(err, void 0, {
149
128
  F: __dxlog_file2,
150
- L: 97,
129
+ L: 84,
151
130
  S: this,
152
131
  C: (f, a) => f(...a)
153
132
  });
@@ -167,168 +146,92 @@ var DevServer = class {
167
146
  try {
168
147
  const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
169
148
  endpoint: this.endpoint,
170
- functions: this.functions.map(({ def: { id, path: path2 } }) => ({
171
- id,
172
- path: path2
149
+ functions: this.functions.map(({ def: { name } }) => ({
150
+ name
173
151
  }))
174
152
  });
175
153
  log2.info("registered", {
154
+ registrationId,
176
155
  endpoint
177
156
  }, {
178
157
  F: __dxlog_file2,
179
- L: 113,
158
+ L: 100,
180
159
  S: this,
181
160
  C: (f, a) => f(...a)
182
161
  });
162
+ this._registrationId = registrationId;
183
163
  this._proxy = endpoint;
184
- this._functionServiceRegistration = registrationId;
185
164
  } catch (err) {
186
165
  await this.stop();
187
166
  throw new Error("FunctionRegistryService not available (check plugin is configured).");
188
167
  }
189
- log2.info("started", {
190
- port: this._port
191
- }, {
192
- F: __dxlog_file2,
193
- L: 121,
194
- S: this,
195
- C: (f, a) => f(...a)
196
- });
197
168
  }
198
169
  async stop() {
199
- invariant(this._server, void 0, {
200
- F: __dxlog_file2,
201
- L: 125,
202
- S: this,
203
- A: [
204
- "this._server",
205
- ""
206
- ]
207
- });
208
- log2.info("stopping...", void 0, {
209
- F: __dxlog_file2,
210
- L: 126,
211
- S: this,
212
- C: (f, a) => f(...a)
213
- });
214
170
  const trigger = new Trigger();
215
- this._server.close(async () => {
216
- log2.info("server stopped", void 0, {
217
- F: __dxlog_file2,
218
- L: 130,
219
- S: this,
220
- C: (f, a) => f(...a)
221
- });
222
- try {
223
- if (this._functionServiceRegistration) {
224
- invariant(this._client.services.services.FunctionRegistryService, void 0, {
225
- F: __dxlog_file2,
226
- L: 133,
227
- S: this,
228
- A: [
229
- "this._client.services.services.FunctionRegistryService",
230
- ""
231
- ]
232
- });
233
- await this._client.services.services.FunctionRegistryService.unregister({
234
- registrationId: this._functionServiceRegistration
235
- });
236
- log2.info("unregistered", {
237
- registrationId: this._functionServiceRegistration
238
- }, {
239
- F: __dxlog_file2,
240
- L: 138,
241
- S: this,
242
- C: (f, a) => f(...a)
243
- });
244
- this._functionServiceRegistration = void 0;
245
- this._proxy = void 0;
246
- }
247
- trigger.wake();
248
- } catch (err) {
249
- trigger.throw(err);
171
+ this._server?.close(async () => {
172
+ if (this._registrationId) {
173
+ await this._client.services.services.FunctionRegistryService.unregister({
174
+ registrationId: this._registrationId
175
+ });
176
+ log2.info("unregistered", {
177
+ registrationId: this._registrationId
178
+ }, {
179
+ F: __dxlog_file2,
180
+ L: 117,
181
+ S: this,
182
+ C: (f, a) => f(...a)
183
+ });
184
+ this._registrationId = void 0;
185
+ this._proxy = void 0;
250
186
  }
187
+ trigger.wake();
251
188
  });
252
189
  await trigger.wait();
253
190
  this._port = void 0;
254
191
  this._server = void 0;
255
- log2.info("stopped", void 0, {
256
- F: __dxlog_file2,
257
- L: 152,
258
- S: this,
259
- C: (f, a) => f(...a)
260
- });
261
192
  }
262
193
  /**
263
194
  * Load function.
264
195
  */
265
- async _load(def, force = false) {
266
- const { id, path: path2, handler } = def;
267
- const filePath = join(this._options.baseDir, handler);
196
+ async _load(def, flush = false) {
197
+ const { id, name, handler } = def;
198
+ const path = join(this._options.directory, handler);
268
199
  log2.info("loading", {
269
- id,
270
- force
200
+ id
271
201
  }, {
272
202
  F: __dxlog_file2,
273
- L: 161,
203
+ L: 136,
274
204
  S: this,
275
205
  C: (f, a) => f(...a)
276
206
  });
277
- if (force) {
278
- Object.keys(__require.cache).filter((key) => key.startsWith(filePath)).forEach((key) => {
279
- delete __require.cache[key];
280
- });
207
+ if (flush) {
208
+ Object.keys(__require.cache).filter((key) => key.startsWith(path)).forEach((key) => delete __require.cache[key]);
281
209
  }
282
- const module = __require(filePath);
210
+ const module = __require(path);
283
211
  if (typeof module.default !== "function") {
284
212
  throw new Error(`Handler must export default function: ${id}`);
285
213
  }
286
- this._handlers[path2] = {
214
+ this._handlers[name] = {
287
215
  def,
288
216
  handler: module.default
289
217
  };
290
218
  }
291
219
  /**
292
- * Invoke function.
220
+ * Invoke function handler.
293
221
  */
294
- async invoke(path2, data) {
222
+ async _invoke(name, event) {
295
223
  const seq = ++this._seq;
296
224
  const now = Date.now();
297
225
  log2.info("req", {
298
226
  seq,
299
- path: path2
300
- }, {
301
- F: __dxlog_file2,
302
- L: 188,
303
- S: this,
304
- C: (f, a) => f(...a)
305
- });
306
- const statusCode = await this._invoke(path2, data);
307
- log2.info("res", {
308
- seq,
309
- path: path2,
310
- statusCode,
311
- duration: Date.now() - now
227
+ name
312
228
  }, {
313
229
  F: __dxlog_file2,
314
- L: 191,
230
+ L: 161,
315
231
  S: this,
316
232
  C: (f, a) => f(...a)
317
233
  });
318
- this.update.emit(statusCode);
319
- return statusCode;
320
- }
321
- async _invoke(path2, event) {
322
- const { handler } = this._handlers[path2] ?? {};
323
- invariant(handler, `invalid path: ${path2}`, {
324
- F: __dxlog_file2,
325
- L: 198,
326
- S: this,
327
- A: [
328
- "handler",
329
- "`invalid path: ${path}`"
330
- ]
331
- });
234
+ const { handler } = this._handlers[name];
332
235
  const context = {
333
236
  client: this._client,
334
237
  dataDir: this._options.dataDir
@@ -345,15 +248,24 @@ var DevServer = class {
345
248
  event,
346
249
  response
347
250
  });
251
+ log2.info("res", {
252
+ seq,
253
+ name,
254
+ statusCode,
255
+ duration: Date.now() - now
256
+ }, {
257
+ F: __dxlog_file2,
258
+ L: 178,
259
+ S: this,
260
+ C: (f, a) => f(...a)
261
+ });
348
262
  return statusCode;
349
263
  }
350
264
  };
351
265
 
352
266
  // packages/core/functions/src/runtime/scheduler.ts
353
267
  import { CronJob } from "cron";
354
- import { getPort as getPort2 } from "get-port-please";
355
268
  import http from "@dxos/node-std/http";
356
- import path from "@dxos/node-std/path";
357
269
  import WebSocket from "ws";
358
270
  import { TextV0Type } from "@braneframe/types";
359
271
  import { debounce, DeferredTask, sleep, Trigger as Trigger2 } from "@dxos/async";
@@ -368,13 +280,7 @@ var Scheduler = class {
368
280
  this._client = _client;
369
281
  this._manifest = _manifest;
370
282
  this._options = _options;
371
- this._mounts = new ComplexMap(({ spaceKey, id }) => `${spaceKey.toHex()}:${id}`);
372
- }
373
- get mounts() {
374
- return Array.from(this._mounts.values()).reduce((acc, { trigger }) => {
375
- acc.push(trigger);
376
- return acc;
377
- }, []);
283
+ this._mounts = new ComplexMap(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);
378
284
  }
379
285
  async start() {
380
286
  this._client.spaces.subscribe(async (spaces) => {
@@ -391,18 +297,15 @@ var Scheduler = class {
391
297
  await this.unmount(id, spaceKey);
392
298
  }
393
299
  }
394
- /**
395
- * Mount trigger.
396
- */
397
300
  async mount(ctx, space, trigger) {
398
301
  const key = {
399
- spaceKey: space.key,
400
- id: trigger.function
302
+ id: trigger.function,
303
+ spaceKey: space.key
401
304
  };
402
305
  const def = this._manifest.functions.find((config) => config.id === trigger.function);
403
306
  invariant2(def, `Function not found: ${trigger.function}`, {
404
307
  F: __dxlog_file3,
405
- L: 83,
308
+ L: 72,
406
309
  S: this,
407
310
  A: [
408
311
  "def",
@@ -420,7 +323,7 @@ var Scheduler = class {
420
323
  trigger
421
324
  }, {
422
325
  F: __dxlog_file3,
423
- L: 89,
326
+ L: 78,
424
327
  S: this,
425
328
  C: (f, a) => f(...a)
426
329
  });
@@ -455,62 +358,44 @@ var Scheduler = class {
455
358
  // TODO(burdon): Pass in Space key (common context).
456
359
  async _execFunction(def, data) {
457
360
  try {
458
- let status = 0;
361
+ log3.info("exec", {
362
+ function: def.id
363
+ }, {
364
+ F: __dxlog_file3,
365
+ L: 117,
366
+ S: this,
367
+ C: (f, a) => f(...a)
368
+ });
459
369
  const { endpoint, callback } = this._options;
460
370
  if (endpoint) {
461
- const url = path.join(endpoint, def.path);
462
- log3.info("exec", {
463
- function: def.id,
464
- url
465
- }, {
466
- F: __dxlog_file3,
467
- L: 133,
468
- S: this,
469
- C: (f, a) => f(...a)
470
- });
471
- const response = await fetch(url, {
371
+ await fetch(`${this._options.endpoint}/${def.name}`, {
472
372
  method: "POST",
473
373
  headers: {
474
374
  "Content-Type": "application/json"
475
375
  },
476
376
  body: JSON.stringify(data)
477
377
  });
478
- status = response.status;
479
378
  } else if (callback) {
480
- log3.info("exec", {
481
- function: def.id
482
- }, {
483
- F: __dxlog_file3,
484
- L: 144,
485
- S: this,
486
- C: (f, a) => f(...a)
487
- });
488
- status = await callback(data) ?? 200;
489
- }
490
- if (status && status >= 400) {
491
- throw new Error(`Response: ${status}`);
379
+ await callback(data);
492
380
  }
493
381
  log3.info("done", {
494
- function: def.id,
495
- status
382
+ function: def.id
496
383
  }, {
497
384
  F: __dxlog_file3,
498
- L: 154,
385
+ L: 133,
499
386
  S: this,
500
387
  C: (f, a) => f(...a)
501
388
  });
502
- return status;
503
389
  } catch (err) {
504
390
  log3.error("error", {
505
391
  function: def.id,
506
392
  error: err.message
507
393
  }, {
508
394
  F: __dxlog_file3,
509
- L: 157,
395
+ L: 135,
510
396
  S: this,
511
397
  C: (f, a) => f(...a)
512
398
  });
513
- return 500;
514
399
  }
515
400
  }
516
401
  //
@@ -525,14 +410,14 @@ var Scheduler = class {
525
410
  trigger
526
411
  }, {
527
412
  F: __dxlog_file3,
528
- L: 170,
413
+ L: 147,
529
414
  S: this,
530
415
  C: (f, a) => f(...a)
531
416
  });
532
417
  const { cron } = trigger;
533
418
  const task = new DeferredTask(ctx, async () => {
534
419
  await this._execFunction(def, {
535
- spaceKey: space.key
420
+ space: space.key
536
421
  });
537
422
  });
538
423
  let last = 0;
@@ -551,7 +436,7 @@ var Scheduler = class {
551
436
  delta
552
437
  }, {
553
438
  F: __dxlog_file3,
554
- L: 190,
439
+ L: 167,
555
440
  S: this,
556
441
  C: (f, a) => f(...a)
557
442
  });
@@ -570,33 +455,25 @@ var Scheduler = class {
570
455
  trigger
571
456
  }, {
572
457
  F: __dxlog_file3,
573
- L: 203,
458
+ L: 180,
574
459
  S: this,
575
460
  C: (f, a) => f(...a)
576
461
  });
462
+ const { port } = trigger;
577
463
  const server = http.createServer(async (req, res) => {
578
- if (req.method !== trigger.method) {
579
- res.statusCode = 405;
580
- return res.end();
581
- }
582
- res.statusCode = await this._execFunction(def, {
583
- spaceKey: space.key
464
+ await this._execFunction(def, {
465
+ space: space.key
584
466
  });
585
- res.end();
586
- });
587
- const port = await getPort2({
588
- random: true
589
467
  });
590
468
  server.listen(port, () => {
591
469
  log3.info("started webhook", {
592
470
  port
593
471
  }, {
594
472
  F: __dxlog_file3,
595
- L: 226,
473
+ L: 189,
596
474
  S: this,
597
475
  C: (f, a) => f(...a)
598
476
  });
599
- trigger.port = port;
600
477
  });
601
478
  ctx.onDispose(() => {
602
479
  server.close();
@@ -604,7 +481,6 @@ var Scheduler = class {
604
481
  }
605
482
  /**
606
483
  * Websocket.
607
- * NOTE: The port must be unique, so the same hook cannot be used for multiple spaces.
608
484
  */
609
485
  async _createWebsocket(ctx, space, def, trigger, options = {
610
486
  retryDelay: 2,
@@ -615,7 +491,7 @@ var Scheduler = class {
615
491
  trigger
616
492
  }, {
617
493
  F: __dxlog_file3,
618
- L: 252,
494
+ L: 213,
619
495
  S: this,
620
496
  C: (f, a) => f(...a)
621
497
  });
@@ -630,7 +506,7 @@ var Scheduler = class {
630
506
  url
631
507
  }, {
632
508
  F: __dxlog_file3,
633
- L: 262,
509
+ L: 223,
634
510
  S: this,
635
511
  C: (f, a) => f(...a)
636
512
  });
@@ -639,14 +515,12 @@ var Scheduler = class {
639
515
  }
640
516
  open.wake(true);
641
517
  },
642
- // TODO(burdon): Config retry if server closes?
643
- onclose: (event) => {
518
+ onclose: () => {
644
519
  log3.info("closed", {
645
- url,
646
- code: event.code
520
+ url
647
521
  }, {
648
522
  F: __dxlog_file3,
649
- L: 272,
523
+ L: 232,
650
524
  S: this,
651
525
  C: (f, a) => f(...a)
652
526
  });
@@ -657,7 +531,7 @@ var Scheduler = class {
657
531
  url
658
532
  }, {
659
533
  F: __dxlog_file3,
660
- L: 277,
534
+ L: 237,
661
535
  S: this,
662
536
  C: (f, a) => f(...a)
663
537
  });
@@ -666,7 +540,7 @@ var Scheduler = class {
666
540
  try {
667
541
  const data = JSON.parse(new TextDecoder().decode(event.data));
668
542
  await this._execFunction(def, {
669
- spaceKey: space.key,
543
+ space: space.key,
670
544
  data
671
545
  });
672
546
  } catch (err) {
@@ -674,7 +548,7 @@ var Scheduler = class {
674
548
  url
675
549
  }, {
676
550
  F: __dxlog_file3,
677
- L: 285,
551
+ L: 245,
678
552
  S: this,
679
553
  C: (f, a) => f(...a)
680
554
  });
@@ -691,7 +565,7 @@ var Scheduler = class {
691
565
  attempt
692
566
  }, {
693
567
  F: __dxlog_file3,
694
- L: 296,
568
+ L: 256,
695
569
  S: this,
696
570
  C: (f, a) => f(...a)
697
571
  });
@@ -712,14 +586,14 @@ var Scheduler = class {
712
586
  trigger
713
587
  }, {
714
588
  F: __dxlog_file3,
715
- L: 311,
589
+ L: 271,
716
590
  S: this,
717
591
  C: (f, a) => f(...a)
718
592
  });
719
593
  const objectIds = /* @__PURE__ */ new Set();
720
594
  const task = new DeferredTask(ctx, async () => {
721
595
  await this._execFunction(def, {
722
- spaceKey: space.key,
596
+ space: space.key,
723
597
  objects: Array.from(objectIds)
724
598
  });
725
599
  });
@@ -730,7 +604,7 @@ var Scheduler = class {
730
604
  updated: updated.length
731
605
  }, {
732
606
  F: __dxlog_file3,
733
- L: 321,
607
+ L: 281,
734
608
  S: this,
735
609
  C: (f, a) => f(...a)
736
610
  });
@@ -751,7 +625,7 @@ var Scheduler = class {
751
625
  objects: objects.length
752
626
  }, {
753
627
  F: __dxlog_file3,
754
- L: 342,
628
+ L: 301,
755
629
  S: this,
756
630
  C: (f, a) => f(...a)
757
631
  });
@@ -778,11 +652,9 @@ import * as S from "@effect/schema/Schema";
778
652
  var TimerTriggerSchema = S.struct({
779
653
  cron: S.string
780
654
  });
781
- var WebhookTriggerSchema = S.mutable(S.struct({
782
- method: S.string,
783
- // Assigned port.
784
- port: S.optional(S.number)
785
- }));
655
+ var WebhookTriggerSchema = S.struct({
656
+ port: S.number
657
+ });
786
658
  var WebsocketTriggerSchema = S.struct({
787
659
  url: S.string,
788
660
  init: S.optional(S.record(S.string, S.any))
@@ -803,9 +675,6 @@ var SubscriptionTriggerSchema = S.struct({
803
675
  });
804
676
  var FunctionTriggerSchema = S.struct({
805
677
  function: S.string.pipe(S.description("Function ID/URI.")),
806
- // Context passed to function.
807
- context: S.optional(S.record(S.string, S.any)),
808
- // Triggers.
809
678
  timer: S.optional(TimerTriggerSchema),
810
679
  webhook: S.optional(WebhookTriggerSchema),
811
680
  websocket: S.optional(WebsocketTriggerSchema),
@@ -813,15 +682,14 @@ var FunctionTriggerSchema = S.struct({
813
682
  });
814
683
  var FunctionDefSchema = S.struct({
815
684
  id: S.string,
816
- // name: S.string,
817
685
  description: S.optional(S.string),
818
- path: S.string,
819
- // TODO(burdon): NPM/GitHub/Docker/CF URL?
686
+ name: S.string,
687
+ // TODO(burdon): NPM/GitHub URL?
820
688
  handler: S.string
821
689
  });
822
690
  var FunctionManifestSchema = S.struct({
823
691
  functions: S.mutable(S.array(FunctionDefSchema)),
824
- triggers: S.optional(S.mutable(S.array(FunctionTriggerSchema)))
692
+ triggers: S.mutable(S.array(FunctionTriggerSchema))
825
693
  });
826
694
  export {
827
695
  DevServer,