@toa.io/extensions.realtime 1.0.0-alpha.29 → 1.0.0-alpha.291

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 (77) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/components/realtime.streams/manifest.toa.yaml +49 -0
  3. package/components/realtime.streams/operations/create.js +65 -0
  4. package/components/realtime.streams/operations/lib/Stash.js +86 -0
  5. package/components/realtime.streams/operations/lib/Stream.js +43 -0
  6. package/components/realtime.streams/operations/lib/index.js +3 -0
  7. package/components/realtime.streams/operations/push.js +10 -0
  8. package/components/realtime.streams/source/create.ts +94 -0
  9. package/components/realtime.streams/source/lib/Stash.ts +131 -0
  10. package/components/realtime.streams/source/lib/Stream.ts +58 -0
  11. package/components/realtime.streams/source/lib/index.ts +2 -0
  12. package/components/realtime.streams/source/push.ts +14 -0
  13. package/components/{streams → realtime.streams}/tsconfig.json +2 -1
  14. package/components/realtime.streams/tsconfig.tsbuildinfo +1 -0
  15. package/components/realtime.streams/types/index.d.ts +20 -0
  16. package/components/realtime.streams/types/toa.d.ts +29 -0
  17. package/{components/context.toa.yaml → context.toa.yaml} +2 -3
  18. package/cucumber.mjs +8 -0
  19. package/features/static.feature +120 -0
  20. package/features/steps/Components.ts +22 -21
  21. package/features/steps/Realtime.ts +18 -21
  22. package/features/steps/Streams.ts +55 -20
  23. package/features/steps/components/messages/manifest.toa.yaml +36 -7
  24. package/features/steps/config.ts +15 -1
  25. package/package.json +9 -7
  26. package/readme.md +33 -7
  27. package/source/Composition.ts +26 -15
  28. package/source/Factory.ts +15 -16
  29. package/source/Realtime.ts +48 -15
  30. package/source/Receiver.ts +95 -0
  31. package/source/Routes.ts +26 -45
  32. package/source/extension.ts +92 -0
  33. package/source/index.ts +2 -1
  34. package/transpiled/Composition.d.ts +10 -4
  35. package/transpiled/Composition.js +21 -20
  36. package/transpiled/Composition.js.map +1 -1
  37. package/transpiled/Factory.d.ts +5 -5
  38. package/transpiled/Factory.js +13 -18
  39. package/transpiled/Factory.js.map +1 -1
  40. package/transpiled/Realtime.d.ts +3 -2
  41. package/transpiled/Realtime.js +36 -11
  42. package/transpiled/Realtime.js.map +1 -1
  43. package/transpiled/Receiver.d.ts +26 -0
  44. package/transpiled/Receiver.js +57 -0
  45. package/transpiled/Receiver.js.map +1 -0
  46. package/transpiled/Routes.d.ts +5 -10
  47. package/transpiled/Routes.js +18 -34
  48. package/transpiled/Routes.js.map +1 -1
  49. package/transpiled/extension.d.ts +22 -0
  50. package/transpiled/extension.js +55 -0
  51. package/transpiled/extension.js.map +1 -0
  52. package/transpiled/index.d.ts +2 -1
  53. package/transpiled/index.js +2 -5
  54. package/transpiled/index.js.map +1 -1
  55. package/tsconfig.json +2 -1
  56. package/tsconfig.tsbuildinfo +1 -0
  57. package/components/streams/manifest.toa.yaml +0 -21
  58. package/components/streams/operations/create.d.ts +0 -14
  59. package/components/streams/operations/create.js +0 -29
  60. package/components/streams/operations/create.js.map +0 -1
  61. package/components/streams/operations/lib/stream.d.ts +0 -10
  62. package/components/streams/operations/lib/stream.js +0 -31
  63. package/components/streams/operations/lib/stream.js.map +0 -1
  64. package/components/streams/operations/push.d.ts +0 -2
  65. package/components/streams/operations/push.js +0 -8
  66. package/components/streams/operations/push.js.map +0 -1
  67. package/components/streams/operations/tsconfig.tsbuildinfo +0 -1
  68. package/components/streams/operations/types.d.ts +0 -11
  69. package/components/streams/operations/types.js +0 -3
  70. package/components/streams/operations/types.js.map +0 -1
  71. package/components/streams/source/create.ts +0 -38
  72. package/components/streams/source/lib/stream.ts +0 -37
  73. package/components/streams/source/push.ts +0 -5
  74. package/components/streams/source/types.ts +0 -13
  75. package/cucumber.js +0 -8
  76. package/stage/streams.test.ts +0 -128
  77. package/transpiled/tsconfig.tsbuildinfo +0 -1
package/source/Routes.ts CHANGED
@@ -1,32 +1,39 @@
1
1
  import { Readable } from 'node:stream'
2
- import { Connector, type Message } from '@toa.io/core'
3
- import { decode } from '@toa.io/generic'
4
- import { type Bootloader } from './Factory'
2
+ import { console } from 'openspan'
3
+ import { Connector } from '@toa.io/core'
4
+ import { Receiver } from './Receiver.js'
5
+ import { environment } from '@toa.io/generic'
6
+ import type { Route } from './extension.js'
7
+ import type { Host } from './Factory.js'
5
8
 
6
9
  export class Routes extends Connector {
7
10
  public events = new Events()
8
11
 
9
- private readonly boot: Bootloader
12
+ private readonly host: Host
10
13
 
11
- public constructor (boot: Bootloader) {
14
+ public constructor(host: Host) {
12
15
  super()
13
16
 
14
- this.boot = boot
17
+ this.host = host
15
18
  }
16
19
 
17
- private static read (): Route[] {
18
- if (process.env.TOA_REALTIME === undefined)
19
- throw new Error('TOA_REALTIME is not defined')
20
+ private static read(): Route[] {
21
+ const value = environment.get('TOA_REALTIME')
20
22
 
21
- return decode<Route[]>(process.env.TOA_REALTIME)
23
+ if (value === undefined) throw new Error('TOA_REALTIME is not defined')
24
+
25
+ return JSON.parse(value) as Route[]
22
26
  }
23
27
 
24
- public override async open (): Promise<void> {
28
+ public override async open(): Promise<void> {
25
29
  const routes = Routes.read()
26
30
  const creating = []
27
31
 
28
- for (const { event, properties } of routes) {
29
- const consumer = this.boot.receive(event, this.getReceiver(event, properties))
32
+ for (const { event, properties, expose } of routes) {
33
+ const consumer = this.host.receive(
34
+ event,
35
+ new Receiver({ event, properties, stream: this.events, expose })
36
+ )
30
37
 
31
38
  creating.push(consumer)
32
39
  }
@@ -39,46 +46,20 @@ export class Routes extends Connector {
39
46
  await Promise.all(connecting)
40
47
  this.depends(consumers)
41
48
 
42
- console.log(`Event sources (${creating.length}) connected.`)
49
+ console.info('Event sources connected', { count: creating.length })
43
50
  }
44
51
 
45
- public override async close (): Promise<void> {
46
- console.log('Event sources disconnected.')
47
- }
48
-
49
- private getReceiver (event: string, properties: string[]): Receiver {
50
- return {
51
- receive: (message: Message<Record<string, string>>) => {
52
- for (const property of properties) {
53
- const key = message.payload[property]
54
-
55
- if (key === undefined) {
56
- console.error(`Event '${event}' does not contain the '${property}' property.`)
57
-
58
- return
59
- }
60
-
61
- this.events.push({ key, event, data: message.payload })
62
- }
63
- }
64
- }
52
+ public override async close(): Promise<void> {
53
+ console.info('Event sources disconnected')
65
54
  }
66
55
  }
67
56
 
68
57
  class Events extends Readable {
69
- public constructor () {
58
+ public constructor() {
70
59
  super({ objectMode: true })
71
60
  }
72
61
 
73
- public override _read (): void {
74
- }
62
+ public override _read(): void {}
75
63
  }
76
64
 
77
- export interface Route {
78
- event: string
79
- properties: string[]
80
- }
81
-
82
- interface Receiver {
83
- receive: (message: Message<Record<string, string>>) => void
84
- }
65
+ export type { Route }
@@ -0,0 +1,92 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { components } from './Composition.js'
3
+ import type { Dependency, Instances, Resources, Service } from '@toa.io/operations'
4
+
5
+ /** Where Toa's release publishes this service's image. An application takes it
6
+ * instead of building one when its context says `registry.services: published`. */
7
+ export const image = 'ghcr.io/toa-io/extension-realtime-streams'
8
+
9
+ export const standalone = true
10
+ export { components } from './Composition.js'
11
+
12
+ export function deployment(
13
+ instances: Instances<Declaration>,
14
+ annotation?: Declaration & Annotation
15
+ ): Dependency {
16
+ const routes = []
17
+ const { resources, ...annotatedRoutes } = annotation ?? {}
18
+ const labels = components().labels
19
+
20
+ if (annotatedRoutes !== undefined) routes.push(...parse(annotatedRoutes))
21
+
22
+ for (const instance of instances) {
23
+ const completed: Declaration = {}
24
+
25
+ for (const [key, value] of Object.entries(instance.manifest)) {
26
+ const event = instance.locator.id + '.' + key
27
+
28
+ completed[event] = value
29
+ }
30
+
31
+ routes.push(...parse(completed))
32
+ }
33
+
34
+ const service: Service = {
35
+ group: 'realtime',
36
+ name: 'streams',
37
+ image,
38
+
39
+ version: JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
40
+ .version,
41
+ components: labels,
42
+ resources,
43
+ variables: [
44
+ {
45
+ name: 'TOA_REALTIME',
46
+ value: JSON.stringify(routes)
47
+ }
48
+ ]
49
+ }
50
+
51
+ return { services: [service], events: routes.map((route) => route.event) }
52
+ }
53
+
54
+ export function parse(declaration: Declaration): Route[] {
55
+ const routes: Route[] = []
56
+
57
+ for (const [event, value] of Object.entries(declaration))
58
+ if (isObject(value)) {
59
+ const properties = Array.isArray(value.key) ? value.key : [value.key]
60
+
61
+ routes.push({ event, properties, expose: value.expose })
62
+ } else {
63
+ const properties = Array.isArray(value) ? value : [value]
64
+
65
+ routes.push({ event, properties })
66
+ }
67
+
68
+ return routes
69
+ }
70
+
71
+ function isObject(value: Entry): value is RouteDeclaration {
72
+ return typeof value === 'object' && !Array.isArray(value)
73
+ }
74
+
75
+ export type Entry = string | string[] | RouteDeclaration
76
+
77
+ export type Declaration = Record<string, Entry>
78
+
79
+ export interface RouteDeclaration {
80
+ key: string | string[]
81
+ expose?: string[]
82
+ }
83
+
84
+ export interface Route {
85
+ event: string
86
+ properties: string[]
87
+ expose?: string[]
88
+ }
89
+
90
+ interface Annotation {
91
+ resources?: Resources
92
+ }
package/source/index.ts CHANGED
@@ -1 +1,2 @@
1
- export { Factory } from './Factory'
1
+ export { Factory } from './Factory.js'
2
+ export * from './extension.js'
@@ -1,8 +1,14 @@
1
1
  import { Connector } from '@toa.io/core';
2
- import { type Bootloader } from './Factory';
2
+ import { type Host } from './Factory.js';
3
3
  export declare class Composition extends Connector {
4
- private readonly boot;
5
- constructor(boot: Bootloader);
4
+ private readonly host;
5
+ constructor(host: Host);
6
6
  protected open(): Promise<void>;
7
- protected dispose(): void;
8
7
  }
8
+ export declare function find(): string[];
9
+ export declare function components(): Components;
10
+ interface Components {
11
+ labels: string[];
12
+ paths: string[];
13
+ }
14
+ export {};
@@ -1,33 +1,34 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Composition = void 0;
4
- const node_fs_1 = require("node:fs");
5
- const node_path_1 = require("node:path");
6
- const core_1 = require("@toa.io/core");
7
- class Composition extends core_1.Connector {
8
- boot;
9
- constructor(boot) {
1
+ import { readdirSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { Connector } from '@toa.io/core';
4
+ export class Composition extends Connector {
5
+ host;
6
+ constructor(host) {
10
7
  super();
11
- this.boot = boot;
8
+ this.host = host;
12
9
  }
13
10
  async open() {
14
11
  const paths = find();
15
- const composition = await this.boot.composition(paths);
12
+ const composition = await this.host.composition(paths);
16
13
  await composition.connect();
17
14
  this.depends(composition);
18
- console.info('Composition complete.');
19
- }
20
- dispose() {
21
- console.info('Composition shutdown complete.');
22
15
  }
23
16
  }
24
- exports.Composition = Composition;
25
- function find() {
26
- return entries().map((entry) => (0, node_path_1.resolve)(ROOT, entry.name));
17
+ export function find() {
18
+ return entries().map((entry) => resolve(ROOT, entry.name));
27
19
  }
28
20
  function entries() {
29
- const entries = (0, node_fs_1.readdirSync)(ROOT, { withFileTypes: true });
21
+ const entries = readdirSync(ROOT, { withFileTypes: true });
30
22
  return entries.filter((entry) => entry.isDirectory());
31
23
  }
32
- const ROOT = (0, node_path_1.resolve)(__dirname, '../components/');
24
+ export function components() {
25
+ const labels = [];
26
+ const paths = [];
27
+ for (const entry of entries()) {
28
+ labels.push(entry.name.replace('.', '-'));
29
+ paths.push(resolve(ROOT, entry.name));
30
+ }
31
+ return { labels, paths };
32
+ }
33
+ const ROOT = resolve(import.meta.dirname, '../components/');
33
34
  //# sourceMappingURL=Composition.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Composition.js","sourceRoot":"","sources":["../source/Composition.ts"],"names":[],"mappings":";;;AAAA,qCAAkD;AAClD,yCAAmC;AACnC,uCAAwC;AAGxC,MAAa,WAAY,SAAQ,gBAAS;IACvB,IAAI,CAAY;IAEjC,YAAoB,IAAgB;QAClC,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEkB,KAAK,CAAC,IAAI;QAC3B,MAAM,KAAK,GAAG,IAAI,EAAE,CAAA;QACpB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAEtD,MAAM,WAAW,CAAC,OAAO,EAAE,CAAA;QAE3B,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;QAEzB,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;IACvC,CAAC;IAEkB,OAAO;QACxB,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;IAChD,CAAC;CACF;AAtBD,kCAsBC;AAED,SAAS,IAAI;IACX,OAAO,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,mBAAO,EAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,OAAO;IACd,MAAM,OAAO,GAAG,IAAA,qBAAW,EAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;IAE1D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;AACvD,CAAC;AAED,MAAM,IAAI,GAAG,IAAA,mBAAO,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAA"}
1
+ {"version":3,"file":"Composition.js","sourceRoot":"","sources":["../source/Composition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAGxC,MAAM,OAAO,WAAY,SAAQ,SAAS;IACvB,IAAI,CAAM;IAE3B,YAAmB,IAAU;QAC3B,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEkB,KAAK,CAAC,IAAI;QAC3B,MAAM,KAAK,GAAG,IAAI,EAAE,CAAA;QACpB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAEtD,MAAM,WAAW,CAAC,OAAO,EAAE,CAAA;QAE3B,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,OAAO;IACd,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;IAE1D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;AACvD,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;QACzC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IACvC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;AAC1B,CAAC;AAOD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAA"}
@@ -1,9 +1,9 @@
1
- import { type extensions } from '@toa.io/core';
2
- import { Realtime } from './Realtime';
1
+ import type { extensions } from '@toa.io/core/types';
2
+ import { Realtime } from './Realtime.js';
3
3
  export declare class Factory implements extensions.Factory {
4
- private readonly boot;
5
- constructor(boot: Bootloader);
4
+ private readonly host;
5
+ constructor(host: Host);
6
6
  service(): Realtime;
7
7
  private discovery;
8
8
  }
9
- export type Bootloader = typeof import('@toa.io/boot');
9
+ export type Host = extensions.Host;
@@ -1,28 +1,23 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Factory = void 0;
4
- const core_1 = require("@toa.io/core");
5
- const Realtime_1 = require("./Realtime");
6
- const Composition_1 = require("./Composition");
7
- const Routes_1 = require("./Routes");
8
- class Factory {
9
- boot;
10
- constructor(boot) {
11
- this.boot = boot;
1
+ import { Locator } from '@toa.io/core';
2
+ import { Realtime } from './Realtime.js';
3
+ import { Composition } from './Composition.js';
4
+ import { Routes } from './Routes.js';
5
+ export class Factory {
6
+ host;
7
+ constructor(host) {
8
+ this.host = host;
12
9
  }
13
10
  service() {
14
- const discovery = this.discovery();
15
- const routes = new Routes_1.Routes(this.boot);
16
- const composition = new Composition_1.Composition(this.boot);
17
- const realtime = new Realtime_1.Realtime(routes, discovery);
11
+ const routes = new Routes(this.host);
12
+ const composition = new Composition(this.host);
13
+ const realtime = new Realtime(routes, async () => await this.discovery());
18
14
  realtime.depends(routes);
19
15
  realtime.depends(composition);
20
16
  return realtime;
21
17
  }
22
18
  async discovery() {
23
- const locator = new core_1.Locator('streams', 'realtime');
24
- return await this.boot.remote(locator);
19
+ const locator = new Locator('streams', 'realtime');
20
+ return await this.host.remote(locator, { service: 'realtime' });
25
21
  }
26
22
  }
27
- exports.Factory = Factory;
28
23
  //# sourceMappingURL=Factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Factory.js","sourceRoot":"","sources":["../source/Factory.ts"],"names":[],"mappings":";;;AAAA,uCAAuE;AACvE,yCAAqC;AACrC,+CAA2C;AAC3C,qCAAiC;AAEjC,MAAa,OAAO;IACD,IAAI,CAAY;IAEjC,YAAoB,IAAgB;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,OAAO;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAClC,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpC,MAAM,WAAW,GAAG,IAAI,yBAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9C,MAAM,QAAQ,GAAG,IAAI,mBAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAEhD,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;QAE7B,OAAO,QAAQ,CAAA;IACjB,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,MAAM,OAAO,GAAG,IAAI,cAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;QAElD,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACxC,CAAC;CACF;AAxBD,0BAwBC"}
1
+ {"version":3,"file":"Factory.js","sourceRoot":"","sources":["../source/Factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,OAAO,OAAO;IACD,IAAI,CAAM;IAE3B,YAAmB,IAAU;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,OAAO;QACZ,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9C,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;QAEzE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;QAE7B,OAAO,QAAQ,CAAA;IACjB,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;QAElD,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAA;IACjE,CAAC;CACF"}
@@ -1,10 +1,11 @@
1
1
  import { type Component, Connector } from '@toa.io/core';
2
- import { type Routes } from './Routes';
2
+ import { type Routes } from './Routes.js';
3
3
  export declare class Realtime extends Connector {
4
4
  private readonly discovery;
5
5
  private streams;
6
- constructor(routes: Routes, discovery: Promise<Component>);
6
+ constructor(routes: Routes, discovery: () => Promise<Component>);
7
7
  protected open(): Promise<void>;
8
8
  protected dispose(): void;
9
9
  private push;
10
+ private deliver;
10
11
  }
@@ -1,8 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Realtime = void 0;
4
- const core_1 = require("@toa.io/core");
5
- class Realtime extends core_1.Connector {
1
+ import { console, run } from 'openspan';
2
+ import { Connector } from '@toa.io/core';
3
+ export class Realtime extends Connector {
6
4
  discovery;
7
5
  streams = null;
8
6
  constructor(routes, discovery) {
@@ -11,17 +9,44 @@ class Realtime extends core_1.Connector {
11
9
  routes.events.on('data', this.push.bind(this));
12
10
  }
13
11
  async open() {
14
- this.streams = await this.discovery;
12
+ // the lookup belongs here, not in the constructor: dependencies connect before
13
+ // open, so the composition that serves realtime.streams is up to answer it. Asked
14
+ // any earlier the lookup goes unanswered, and it waits without a bound.
15
+ this.streams = await this.discovery();
15
16
  this.depends(this.streams);
16
17
  await this.streams.connect();
17
- console.log('Realtime has started.');
18
+ console.info('Realtime service started');
18
19
  }
19
20
  dispose() {
20
- console.log('Realtime shutdown complete.');
21
+ console.info('Realtime service shutdown complete');
21
22
  }
22
- push(event) {
23
- void this.streams?.invoke('push', { input: event });
23
+ push({ telemetry, ...event }) {
24
+ const processing = telemetry === null
25
+ ? this.deliver(event)
26
+ : run(telemetry, async () => await this.deliver(event));
27
+ void processing.catch((error) => console.error('Realtime push failed', error));
28
+ }
29
+ async deliver(event) {
30
+ /*
31
+ * The delivery span is created on behalf of the messaging destination
32
+ * (same as the core Receiver), so that service graphs display the fan-out:
33
+ * producer -> destination -> realtime
34
+ */
35
+ const delivery = {
36
+ name: `${event.event} deliver`,
37
+ kind: 'producer',
38
+ service: event.event,
39
+ attributes: { 'messaging.destination.name': event.event }
40
+ };
41
+ const options = {
42
+ name: `${event.event} push`,
43
+ kind: 'consumer',
44
+ service: 'realtime',
45
+ attributes: { 'messaging.destination.name': event.event }
46
+ };
47
+ await console.span(delivery, async () => await console.span(options, async () => {
48
+ await this.streams?.invoke('push', { input: event });
49
+ }));
24
50
  }
25
51
  }
26
- exports.Realtime = Realtime;
27
52
  //# sourceMappingURL=Realtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Realtime.js","sourceRoot":"","sources":["../source/Realtime.ts"],"names":[],"mappings":";;;AAAA,uCAAwD;AAGxD,MAAa,QAAS,SAAQ,gBAAS;IACpB,SAAS,CAAoB;IACtC,OAAO,GAAqB,IAAI,CAAA;IAExC,YAAoB,MAAc,EAAE,SAA6B;QAC/D,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAChD,CAAC;IAEkB,KAAK,CAAC,IAAI;QAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAA;QACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAE1B,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;QAE5B,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;IACtC,CAAC;IAEkB,OAAO;QACxB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;IAC5C,CAAC;IAEO,IAAI,CAAE,KAAY;QACxB,KAAK,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;IACrD,CAAC;CACF;AA5BD,4BA4BC"}
1
+ {"version":3,"file":"Realtime.js","sourceRoot":"","sources":["../source/Realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAkB,SAAS,EAAE,MAAM,cAAc,CAAA;AAIxD,MAAM,OAAO,QAAS,SAAQ,SAAS;IACpB,SAAS,CAA0B;IAC5C,OAAO,GAAqB,IAAI,CAAA;IAExC,YAAmB,MAAc,EAAE,SAAmC;QACpE,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAChD,CAAC;IAEkB,KAAK,CAAC,IAAI;QAC3B,+EAA+E;QAC/E,kFAAkF;QAClF,wEAAwE;QACxE,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAA;QACrC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAE1B,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;QAE5B,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;IAC1C,CAAC;IAEkB,OAAO;QACxB,OAAO,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAA;IACpD,CAAC;IAEO,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAQ;QACxC,MAAM,UAAU,GACd,SAAS,KAAK,IAAI;YAChB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACrB,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAE3D,KAAK,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAAA;IAChF,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,KAA8B;QAClD;;;;WAIG;QACH,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,UAAU;YAC9B,IAAI,EAAE,UAAmB;YACzB,OAAO,EAAE,KAAK,CAAC,KAAK;YACpB,UAAU,EAAE,EAAE,4BAA4B,EAAE,KAAK,CAAC,KAAK,EAAE;SAC1D,CAAA;QAED,MAAM,OAAO,GAAG;YACd,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,OAAO;YAC3B,IAAI,EAAE,UAAmB;YACzB,OAAO,EAAE,UAAU;YACnB,UAAU,EAAE,EAAE,4BAA4B,EAAE,KAAK,CAAC,KAAK,EAAE;SAC1D,CAAA;QAED,MAAM,OAAO,CAAC,IAAI,CAChB,QAAQ,EACR,KAAK,IAAI,EAAE,CACT,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;YACrC,MAAM,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;QACtD,CAAC,CAAC,CACL,CAAA;IACH,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import { Connector } from '@toa.io/core';
2
+ import type { Message } from '@toa.io/core/types';
3
+ import type { SpanContext } from 'openspan';
4
+ import type { Readable } from 'node:stream';
5
+ export declare class Receiver extends Connector {
6
+ private readonly event;
7
+ private readonly properties;
8
+ private readonly expose?;
9
+ private readonly stream;
10
+ constructor({ event, properties, stream, expose }: {
11
+ event: string;
12
+ properties: string[];
13
+ stream: Readable;
14
+ expose?: string[];
15
+ });
16
+ receive(message: Message<Record<string, string>>): Promise<void>;
17
+ private process;
18
+ private fit;
19
+ private push;
20
+ }
21
+ export interface Push {
22
+ key: string;
23
+ event: string;
24
+ data: Record<string, string>;
25
+ telemetry: SpanContext | null;
26
+ }
@@ -0,0 +1,57 @@
1
+ import { console, decode, run } from 'openspan';
2
+ import { Connector } from '@toa.io/core';
3
+ export class Receiver extends Connector {
4
+ event;
5
+ properties;
6
+ expose;
7
+ stream;
8
+ constructor({ event, properties, stream, expose }) {
9
+ super();
10
+ this.event = event;
11
+ this.properties = properties;
12
+ this.expose = expose;
13
+ this.stream = stream;
14
+ }
15
+ async receive(message) {
16
+ // the push continues the trace from the producer
17
+ const telemetry = message.telemetry === undefined ? null : decode(message.telemetry);
18
+ if (telemetry === null)
19
+ this.process(message, telemetry);
20
+ else
21
+ run(telemetry, () => this.process(message, telemetry));
22
+ }
23
+ process(message, telemetry) {
24
+ const data = this.fit(message.payload);
25
+ for (const property of this.properties) {
26
+ const key = message.payload[property];
27
+ if (key === undefined) {
28
+ console.debug('Event does not contain key property', {
29
+ property,
30
+ event: this.event
31
+ });
32
+ continue;
33
+ }
34
+ if (Array.isArray(key))
35
+ // eslint-disable-next-line max-depth
36
+ for (const k of key)
37
+ this.push(k, data, telemetry);
38
+ else
39
+ this.push(key, data, telemetry);
40
+ }
41
+ }
42
+ fit(payload) {
43
+ if (this.expose === undefined)
44
+ return payload;
45
+ const entries = Object.entries(payload).filter(([key]) => this.expose.includes(key));
46
+ return Object.fromEntries(entries);
47
+ }
48
+ push(key, data, telemetry) {
49
+ if (key === null || typeof key === 'undefined') {
50
+ console.debug('Key is null or undefined, skipping', { key, event: this.event });
51
+ return;
52
+ }
53
+ console.debug('Pushing event to stream', { key, event: this.event, data });
54
+ this.stream.push({ key, event: this.event, data, telemetry });
55
+ }
56
+ }
57
+ //# sourceMappingURL=Receiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Receiver.js","sourceRoot":"","sources":["../source/Receiver.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,17 @@
1
- /// <reference types="node" />
2
1
  import { Readable } from 'node:stream';
3
2
  import { Connector } from '@toa.io/core';
4
- import { type Bootloader } from './Factory';
3
+ import type { Route } from './extension.js';
4
+ import type { Host } from './Factory.js';
5
5
  export declare class Routes extends Connector {
6
6
  events: Events;
7
- private readonly boot;
8
- constructor(boot: Bootloader);
7
+ private readonly host;
8
+ constructor(host: Host);
9
9
  private static read;
10
10
  open(): Promise<void>;
11
11
  close(): Promise<void>;
12
- private getReceiver;
13
12
  }
14
13
  declare class Events extends Readable {
15
14
  constructor();
16
15
  _read(): void;
17
16
  }
18
- export interface Route {
19
- event: string;
20
- properties: string[];
21
- }
22
- export {};
17
+ export type { Route };
@@ -1,26 +1,26 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Routes = void 0;
4
- const node_stream_1 = require("node:stream");
5
- const core_1 = require("@toa.io/core");
6
- const generic_1 = require("@toa.io/generic");
7
- class Routes extends core_1.Connector {
1
+ import { Readable } from 'node:stream';
2
+ import { console } from 'openspan';
3
+ import { Connector } from '@toa.io/core';
4
+ import { Receiver } from './Receiver.js';
5
+ import { environment } from '@toa.io/generic';
6
+ export class Routes extends Connector {
8
7
  events = new Events();
9
- boot;
10
- constructor(boot) {
8
+ host;
9
+ constructor(host) {
11
10
  super();
12
- this.boot = boot;
11
+ this.host = host;
13
12
  }
14
13
  static read() {
15
- if (process.env.TOA_REALTIME === undefined)
14
+ const value = environment.get('TOA_REALTIME');
15
+ if (value === undefined)
16
16
  throw new Error('TOA_REALTIME is not defined');
17
- return (0, generic_1.decode)(process.env.TOA_REALTIME);
17
+ return JSON.parse(value);
18
18
  }
19
19
  async open() {
20
20
  const routes = Routes.read();
21
21
  const creating = [];
22
- for (const { event, properties } of routes) {
23
- const consumer = this.boot.receive(event, this.getReceiver(event, properties));
22
+ for (const { event, properties, expose } of routes) {
23
+ const consumer = this.host.receive(event, new Receiver({ event, properties, stream: this.events, expose }));
24
24
  creating.push(consumer);
25
25
  }
26
26
  const consumers = await Promise.all(creating);
@@ -28,32 +28,16 @@ class Routes extends core_1.Connector {
28
28
  const connecting = consumers.map((consumer) => consumer.connect());
29
29
  await Promise.all(connecting);
30
30
  this.depends(consumers);
31
- console.log(`Event sources (${creating.length}) connected.`);
31
+ console.info('Event sources connected', { count: creating.length });
32
32
  }
33
33
  async close() {
34
- console.log('Event sources disconnected.');
35
- }
36
- getReceiver(event, properties) {
37
- return {
38
- receive: (message) => {
39
- for (const property of properties) {
40
- const key = message.payload[property];
41
- if (key === undefined) {
42
- console.error(`Event '${event}' does not contain the '${property}' property.`);
43
- return;
44
- }
45
- this.events.push({ key, event, data: message.payload });
46
- }
47
- }
48
- };
34
+ console.info('Event sources disconnected');
49
35
  }
50
36
  }
51
- exports.Routes = Routes;
52
- class Events extends node_stream_1.Readable {
37
+ class Events extends Readable {
53
38
  constructor() {
54
39
  super({ objectMode: true });
55
40
  }
56
- _read() {
57
- }
41
+ _read() { }
58
42
  }
59
43
  //# sourceMappingURL=Routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Routes.js","sourceRoot":"","sources":["../source/Routes.ts"],"names":[],"mappings":";;;AAAA,6CAAsC;AACtC,uCAAsD;AACtD,6CAAwC;AAGxC,MAAa,MAAO,SAAQ,gBAAS;IAC5B,MAAM,GAAG,IAAI,MAAM,EAAE,CAAA;IAEX,IAAI,CAAY;IAEjC,YAAoB,IAAgB;QAClC,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEO,MAAM,CAAC,IAAI;QACjB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,SAAS;YACxC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;QAEhD,OAAO,IAAA,gBAAM,EAAU,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IAClD,CAAC;IAEe,KAAK,CAAC,IAAI;QACxB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;QAC5B,MAAM,QAAQ,GAAG,EAAE,CAAA;QAEnB,KAAK,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAA;YAE9E,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACzB,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAE7C,qEAAqE;QACrE,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;QAElE,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAC7B,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAEvB,OAAO,CAAC,GAAG,CAAC,kBAAkB,QAAQ,CAAC,MAAM,cAAc,CAAC,CAAA;IAC9D,CAAC;IAEe,KAAK,CAAC,KAAK;QACzB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;IAC5C,CAAC;IAEO,WAAW,CAAE,KAAa,EAAE,UAAoB;QACtD,OAAO;YACL,OAAO,EAAE,CAAC,OAAwC,EAAE,EAAE;gBACpD,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;oBAClC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;oBAErC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;wBACtB,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,2BAA2B,QAAQ,aAAa,CAAC,CAAA;wBAE9E,OAAM;oBACR,CAAC;oBAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;gBACzD,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF;AA5DD,wBA4DC;AAED,MAAM,MAAO,SAAQ,sBAAQ;IAC3B;QACE,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7B,CAAC;IAEe,KAAK;IACrB,CAAC;CACF"}
1
+ {"version":3,"file":"Routes.js","sourceRoot":"","sources":["../source/Routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAI7C,MAAM,OAAO,MAAO,SAAQ,SAAS;IAC5B,MAAM,GAAG,IAAI,MAAM,EAAE,CAAA;IAEX,IAAI,CAAM;IAE3B,YAAmB,IAAU;QAC3B,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEO,MAAM,CAAC,IAAI;QACjB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;QAE7C,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;QAEvE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAY,CAAA;IACrC,CAAC;IAEe,KAAK,CAAC,IAAI;QACxB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;QAC5B,MAAM,QAAQ,GAAG,EAAE,CAAA;QAEnB,KAAK,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAChC,KAAK,EACL,IAAI,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CACjE,CAAA;YAED,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACzB,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAE7C,qEAAqE;QACrE,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;QAElE,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAC7B,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAEvB,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACrE,CAAC;IAEe,KAAK,CAAC,KAAK;QACzB,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;IAC5C,CAAC;CACF;AAED,MAAM,MAAO,SAAQ,QAAQ;IAC3B;QACE,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7B,CAAC;IAEe,KAAK,KAAU,CAAC;CACjC"}