@toa.io/extensions.realtime 1.0.0-alpha.284 → 1.0.0-alpha.286
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.
- package/components/realtime.streams/manifest.toa.yaml +4 -2
- package/components/realtime.streams/operations/create.js +1 -1
- package/components/realtime.streams/operations/lib/Stash.js +1 -1
- package/components/realtime.streams/operations/lib/Stream.js +1 -1
- package/components/realtime.streams/operations/push.js +1 -1
- package/components/realtime.streams/source/create.ts +7 -10
- package/components/realtime.streams/source/lib/Stash.ts +24 -26
- package/components/realtime.streams/source/lib/Stream.ts +9 -7
- package/components/realtime.streams/source/push.ts +5 -3
- package/components/realtime.streams/tsconfig.tsbuildinfo +1 -1
- package/context.toa.yaml +2 -2
- package/cucumber.mjs +3 -0
- package/features/steps/Components.ts +8 -7
- package/features/steps/Realtime.ts +4 -5
- package/features/steps/Streams.ts +9 -12
- package/features/steps/components/messages/manifest.toa.yaml +16 -18
- package/package.json +4 -4
- package/source/Composition.ts +5 -5
- package/source/Factory.ts +5 -4
- package/source/Realtime.ts +16 -11
- package/source/Receiver.ts +29 -20
- package/source/Routes.ts +10 -8
- package/source/extension.ts +20 -10
- package/transpiled/Composition.js.map +1 -1
- package/transpiled/Factory.d.ts +1 -1
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Realtime.js.map +1 -1
- package/transpiled/Receiver.d.ts +2 -1
- package/transpiled/Receiver.js +5 -3
- package/transpiled/Receiver.js.map +1 -1
- package/transpiled/Routes.js +1 -2
- package/transpiled/Routes.js.map +1 -1
- package/transpiled/extension.d.ts +3 -0
- package/transpiled/extension.js +10 -3
- package/transpiled/extension.js.map +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/CHANGELOG.md +0 -344
package/cucumber.mjs
CHANGED
|
@@ -4,7 +4,8 @@ import tsflow from 'cucumber-tsflow'
|
|
|
4
4
|
|
|
5
5
|
import { load as parse } from 'js-yaml'
|
|
6
6
|
import * as stage from '@toa.io/userland/stage'
|
|
7
|
-
import { type Component
|
|
7
|
+
import { type Component } from '@toa.io/core'
|
|
8
|
+
import type { Request } from '@toa.io/core/types'
|
|
8
9
|
import { timeout } from '@toa.io/generic'
|
|
9
10
|
import { parse as parseRoutes, type Declaration } from '../../source/extension.js'
|
|
10
11
|
import { Realtime } from './Realtime.js'
|
|
@@ -16,12 +17,12 @@ export class Components {
|
|
|
16
17
|
private readonly realtime: Realtime
|
|
17
18
|
private remotes: Record<string, Component> = {}
|
|
18
19
|
|
|
19
|
-
public constructor
|
|
20
|
+
public constructor(realtime: Realtime) {
|
|
20
21
|
this.realtime = realtime
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
@given('the `{word}` component is running with routes:')
|
|
24
|
-
public async run
|
|
25
|
+
public async run(component: string, yaml: string): Promise<void> {
|
|
25
26
|
const declaration = parse(yaml) as Declaration
|
|
26
27
|
const [name, namespace = 'default'] = component.split('.').reverse()
|
|
27
28
|
const routes = parseRoutes(declaration)
|
|
@@ -34,7 +35,7 @@ export class Components {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
@when('the `{word}` is called with:')
|
|
37
|
-
public async call
|
|
38
|
+
public async call(endpoint: string, yaml: string): Promise<void> {
|
|
38
39
|
const request = parse(yaml) as Request
|
|
39
40
|
const [operation, component, namespace = 'default'] = endpoint.split('.').reverse()
|
|
40
41
|
const id = `${namespace}.${component}`
|
|
@@ -46,21 +47,21 @@ export class Components {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
@before()
|
|
49
|
-
private async compose
|
|
50
|
+
private async compose(): Promise<void> {
|
|
50
51
|
const paths = componentPaths()
|
|
51
52
|
|
|
52
53
|
await stage.compose(paths)
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
@after()
|
|
56
|
-
private async shutdown
|
|
57
|
+
private async shutdown(): Promise<void> {
|
|
57
58
|
this.remotes = {}
|
|
58
59
|
|
|
59
60
|
await stage.shutdown()
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
function componentPaths
|
|
64
|
+
function componentPaths(): string[] {
|
|
64
65
|
const entries = readdirSync(ROOT, { withFileTypes: true })
|
|
65
66
|
|
|
66
67
|
return entries
|
|
@@ -15,19 +15,18 @@ export class Realtime {
|
|
|
15
15
|
private connected = false
|
|
16
16
|
|
|
17
17
|
@after()
|
|
18
|
-
public async shutdown
|
|
18
|
+
public async shutdown(): Promise<void> {
|
|
19
19
|
this.connected = false
|
|
20
20
|
|
|
21
21
|
await this.service?.disconnect()
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
public declare
|
|
24
|
+
public declare(event: string, properties: string[], expose?: string[]): void {
|
|
25
25
|
this.routes.push({ event, properties, expose })
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
public async serve
|
|
29
|
-
if (this.connected)
|
|
30
|
-
return
|
|
28
|
+
public async serve(): Promise<void> {
|
|
29
|
+
if (this.connected) return
|
|
31
30
|
|
|
32
31
|
process.env.TOA_REALTIME = JSON.stringify(this.routes)
|
|
33
32
|
|
|
@@ -18,12 +18,12 @@ export class Streams {
|
|
|
18
18
|
private streams: Record<string, Readable> = {}
|
|
19
19
|
private events: Record<string, Event[]> = {}
|
|
20
20
|
|
|
21
|
-
public constructor
|
|
21
|
+
public constructor(realtime: Realtime) {
|
|
22
22
|
this.realtime = realtime
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
@given('the stream `{word}` is consumed', { timeout: 30_000 })
|
|
26
|
-
public async consume
|
|
26
|
+
public async consume(key: string): Promise<void> {
|
|
27
27
|
await this.realtime.serve()
|
|
28
28
|
|
|
29
29
|
this.remote ??= await stage.remote('realtime.streams')
|
|
@@ -33,26 +33,24 @@ export class Streams {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
@then('an event is received from the stream `{word}`:')
|
|
36
|
-
public async received
|
|
36
|
+
public async received(key: string, yaml: string): Promise<void> {
|
|
37
37
|
await setTimeout(100)
|
|
38
38
|
|
|
39
39
|
const expected = parse(yaml) as object
|
|
40
40
|
|
|
41
|
-
for (const event of this.events[key])
|
|
42
|
-
if (match(event, expected))
|
|
43
|
-
return
|
|
41
|
+
for (const event of this.events[key]) if (match(event, expected)) return
|
|
44
42
|
|
|
45
43
|
throw new Error('No matching event received')
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
@then('the consumer `{word}` is disconnected')
|
|
49
|
-
public disconnected
|
|
47
|
+
public disconnected(key: string): void {
|
|
50
48
|
this.streams[key]?.destroy()
|
|
51
49
|
delete this.streams[key]
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
@then('the consumer `{word}` is reconnected')
|
|
55
|
-
public async reconnected
|
|
53
|
+
public async reconnected(key: string): Promise<void> {
|
|
56
54
|
const last = this.events[key].findLast((event) => event.event === 'token')
|
|
57
55
|
|
|
58
56
|
assert.ok(last, `No last event found for stream ${key}`)
|
|
@@ -61,9 +59,8 @@ export class Streams {
|
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
@after()
|
|
64
|
-
public async shutdown
|
|
65
|
-
for (const stream of Object.values(this.streams))
|
|
66
|
-
stream.destroy()
|
|
62
|
+
public async shutdown(): Promise<void> {
|
|
63
|
+
for (const stream of Object.values(this.streams)) stream.destroy()
|
|
67
64
|
|
|
68
65
|
this.streams = {}
|
|
69
66
|
this.events = {}
|
|
@@ -71,7 +68,7 @@ export class Streams {
|
|
|
71
68
|
await setTimeout(100)
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
private async createStream
|
|
71
|
+
private async createStream(key: string, token?: string): Promise<void> {
|
|
75
72
|
this.streams[key] = await this.remote!.invoke('create', { input: { key, token } })
|
|
76
73
|
this.streams[key].on('data', (event: Event) => {
|
|
77
74
|
console.log('[TEST] Received event', event)
|
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
name: messages
|
|
2
2
|
|
|
3
3
|
entity:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
items:
|
|
9
|
-
type: string
|
|
10
|
-
maxLength: 32
|
|
11
|
-
sender:
|
|
12
|
-
type: string
|
|
13
|
-
maxLength: 32
|
|
14
|
-
recipient:
|
|
4
|
+
properties:
|
|
5
|
+
watchers:
|
|
6
|
+
type: array
|
|
7
|
+
items:
|
|
15
8
|
type: string
|
|
16
9
|
maxLength: 32
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
sender:
|
|
11
|
+
type: string
|
|
12
|
+
maxLength: 32
|
|
13
|
+
recipient:
|
|
14
|
+
type: string
|
|
15
|
+
maxLength: 32
|
|
16
|
+
text:
|
|
17
|
+
type: string
|
|
18
|
+
required:
|
|
19
|
+
- sender
|
|
20
|
+
- recipient
|
|
21
|
+
- text
|
|
24
22
|
|
|
25
23
|
operations:
|
|
26
24
|
create:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.realtime",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.286",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Toa Realtime",
|
|
6
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"access": "public"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
22
|
-
"openspan": "1.0.0-alpha.
|
|
21
|
+
"@toa.io/core": "1.0.0-alpha.286",
|
|
22
|
+
"openspan": "1.0.0-alpha.286"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"transpile": "npx tsc && npx tsc -p ./components/realtime.streams",
|
|
26
26
|
"features": "TSX_TSCONFIG_PATH=features/steps/tsconfig.json NODE_OPTIONS=--import=tsx cucumber-js"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "81f3d0688f17668b902be336d1749cc715edcdb6"
|
|
29
29
|
}
|
package/source/Composition.ts
CHANGED
|
@@ -6,12 +6,12 @@ import { type Host } from './Factory.js'
|
|
|
6
6
|
export class Composition extends Connector {
|
|
7
7
|
private readonly host: Host
|
|
8
8
|
|
|
9
|
-
public constructor
|
|
9
|
+
public constructor(host: Host) {
|
|
10
10
|
super()
|
|
11
11
|
this.host = host
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
protected override async open
|
|
14
|
+
protected override async open(): Promise<void> {
|
|
15
15
|
const paths = find()
|
|
16
16
|
const composition = await this.host.composition(paths)
|
|
17
17
|
|
|
@@ -21,17 +21,17 @@ export class Composition extends Connector {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function find
|
|
24
|
+
export function find(): string[] {
|
|
25
25
|
return entries().map((entry) => resolve(ROOT, entry.name))
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function entries
|
|
28
|
+
function entries(): Dirent[] {
|
|
29
29
|
const entries = readdirSync(ROOT, { withFileTypes: true })
|
|
30
30
|
|
|
31
31
|
return entries.filter((entry) => entry.isDirectory())
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export function components
|
|
34
|
+
export function components(): Components {
|
|
35
35
|
const labels: string[] = []
|
|
36
36
|
const paths: string[] = []
|
|
37
37
|
|
package/source/Factory.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type Component,
|
|
1
|
+
import { type Component, Locator } from '@toa.io/core'
|
|
2
|
+
import type { extensions } from '@toa.io/core/types'
|
|
2
3
|
import { Realtime } from './Realtime.js'
|
|
3
4
|
import { Composition } from './Composition.js'
|
|
4
5
|
import { Routes } from './Routes.js'
|
|
@@ -6,11 +7,11 @@ import { Routes } from './Routes.js'
|
|
|
6
7
|
export class Factory implements extensions.Factory {
|
|
7
8
|
private readonly host: Host
|
|
8
9
|
|
|
9
|
-
public constructor
|
|
10
|
+
public constructor(host: Host) {
|
|
10
11
|
this.host = host
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
public service
|
|
14
|
+
public service(): Realtime {
|
|
14
15
|
const routes = new Routes(this.host)
|
|
15
16
|
const composition = new Composition(this.host)
|
|
16
17
|
const realtime = new Realtime(routes, async () => await this.discovery())
|
|
@@ -21,7 +22,7 @@ export class Factory implements extensions.Factory {
|
|
|
21
22
|
return realtime
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
private async discovery
|
|
25
|
+
private async discovery(): Promise<Component> {
|
|
25
26
|
const locator = new Locator('streams', 'realtime')
|
|
26
27
|
|
|
27
28
|
return await this.host.remote(locator, { service: 'realtime' })
|
package/source/Realtime.ts
CHANGED
|
@@ -7,7 +7,7 @@ export class Realtime extends Connector {
|
|
|
7
7
|
private readonly discovery: () => Promise<Component>
|
|
8
8
|
private streams: Component | null = null
|
|
9
9
|
|
|
10
|
-
public constructor
|
|
10
|
+
public constructor(routes: Routes, discovery: () => Promise<Component>) {
|
|
11
11
|
super()
|
|
12
12
|
|
|
13
13
|
this.discovery = discovery
|
|
@@ -15,7 +15,7 @@ export class Realtime extends Connector {
|
|
|
15
15
|
routes.events.on('data', this.push.bind(this))
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
protected override async open
|
|
18
|
+
protected override async open(): Promise<void> {
|
|
19
19
|
// the lookup belongs here, not in the constructor: dependencies connect before
|
|
20
20
|
// open, so the composition that serves realtime.streams is up to answer it. Asked
|
|
21
21
|
// any earlier the lookup goes unanswered, and it waits without a bound.
|
|
@@ -27,19 +27,20 @@ export class Realtime extends Connector {
|
|
|
27
27
|
console.info('Realtime service started')
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
protected override dispose
|
|
30
|
+
protected override dispose(): void {
|
|
31
31
|
console.info('Realtime service shutdown complete')
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
private push
|
|
35
|
-
const processing =
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
private push({ telemetry, ...event }: Push): void {
|
|
35
|
+
const processing =
|
|
36
|
+
telemetry === null
|
|
37
|
+
? this.deliver(event)
|
|
38
|
+
: run(telemetry, async () => await this.deliver(event))
|
|
38
39
|
|
|
39
40
|
void processing.catch((error) => console.error('Realtime push failed', error))
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
private async deliver
|
|
43
|
+
private async deliver(event: Omit<Push, 'telemetry'>): Promise<void> {
|
|
43
44
|
/*
|
|
44
45
|
* The delivery span is created on behalf of the messaging destination
|
|
45
46
|
* (same as the core Receiver), so that service graphs display the fan-out:
|
|
@@ -59,8 +60,12 @@ export class Realtime extends Connector {
|
|
|
59
60
|
attributes: { 'messaging.destination.name': event.event }
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
await console.span(
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
await console.span(
|
|
64
|
+
delivery,
|
|
65
|
+
async () =>
|
|
66
|
+
await console.span(options, async () => {
|
|
67
|
+
await this.streams?.invoke('push', { input: event })
|
|
68
|
+
})
|
|
69
|
+
)
|
|
65
70
|
}
|
|
66
71
|
}
|
package/source/Receiver.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { console, decode, run } from 'openspan'
|
|
2
|
-
import { Connector
|
|
2
|
+
import { Connector } from '@toa.io/core'
|
|
3
|
+
import type { Message } from '@toa.io/core/types'
|
|
3
4
|
import type { SpanContext } from 'openspan'
|
|
4
5
|
import type { Readable } from 'node:stream'
|
|
5
6
|
|
|
@@ -9,7 +10,12 @@ export class Receiver extends Connector {
|
|
|
9
10
|
private readonly expose?: string[]
|
|
10
11
|
private readonly stream: Readable
|
|
11
12
|
|
|
12
|
-
public constructor
|
|
13
|
+
public constructor({
|
|
14
|
+
event,
|
|
15
|
+
properties,
|
|
16
|
+
stream,
|
|
17
|
+
expose
|
|
18
|
+
}: {
|
|
13
19
|
event: string
|
|
14
20
|
properties: string[]
|
|
15
21
|
stream: Readable
|
|
@@ -23,49 +29,52 @@ export class Receiver extends Connector {
|
|
|
23
29
|
this.stream = stream
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
public async receive
|
|
32
|
+
public async receive(message: Message<Record<string, string>>): Promise<void> {
|
|
27
33
|
// the push continues the trace from the producer
|
|
28
34
|
const telemetry = message.telemetry === undefined ? null : decode(message.telemetry)
|
|
29
35
|
|
|
30
|
-
if (telemetry === null)
|
|
31
|
-
|
|
32
|
-
else
|
|
33
|
-
run(telemetry, () => this.process(message, telemetry))
|
|
36
|
+
if (telemetry === null) this.process(message, telemetry)
|
|
37
|
+
else run(telemetry, () => this.process(message, telemetry))
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
private process
|
|
40
|
+
private process(
|
|
41
|
+
message: Message<Record<string, string>>,
|
|
42
|
+
telemetry: SpanContext | null
|
|
43
|
+
): void {
|
|
37
44
|
const data = this.fit(message.payload)
|
|
38
45
|
|
|
39
46
|
for (const property of this.properties) {
|
|
40
47
|
const key = message.payload[property]
|
|
41
48
|
|
|
42
49
|
if (key === undefined) {
|
|
43
|
-
console.debug('Event does not contain key property',
|
|
44
|
-
|
|
50
|
+
console.debug('Event does not contain key property', {
|
|
51
|
+
property,
|
|
52
|
+
event: this.event
|
|
53
|
+
})
|
|
45
54
|
|
|
46
55
|
continue
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
if (Array.isArray(key))
|
|
50
59
|
// eslint-disable-next-line max-depth
|
|
51
|
-
for (const k of key as string[])
|
|
52
|
-
|
|
53
|
-
else
|
|
54
|
-
this.push(key, data, telemetry)
|
|
60
|
+
for (const k of key as string[]) this.push(k, data, telemetry)
|
|
61
|
+
else this.push(key, data, telemetry)
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
64
|
|
|
58
|
-
private fit
|
|
59
|
-
if (this.expose === undefined)
|
|
60
|
-
return payload
|
|
65
|
+
private fit(payload: Record<string, string>): Record<string, string> {
|
|
66
|
+
if (this.expose === undefined) return payload
|
|
61
67
|
|
|
62
|
-
const entries = Object.entries(payload)
|
|
63
|
-
.filter(([key]) => this.expose!.includes(key))
|
|
68
|
+
const entries = Object.entries(payload).filter(([key]) => this.expose!.includes(key))
|
|
64
69
|
|
|
65
70
|
return Object.fromEntries(entries)
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
private push
|
|
73
|
+
private push(
|
|
74
|
+
key: string | null,
|
|
75
|
+
data: Record<string, string>,
|
|
76
|
+
telemetry: SpanContext | null
|
|
77
|
+
): void {
|
|
69
78
|
if (key === null || typeof key === 'undefined') {
|
|
70
79
|
console.debug('Key is null or undefined, skipping', { key, event: this.event })
|
|
71
80
|
|
package/source/Routes.ts
CHANGED
|
@@ -10,25 +10,28 @@ export class Routes extends Connector {
|
|
|
10
10
|
|
|
11
11
|
private readonly host: Host
|
|
12
12
|
|
|
13
|
-
public constructor
|
|
13
|
+
public constructor(host: Host) {
|
|
14
14
|
super()
|
|
15
15
|
|
|
16
16
|
this.host = host
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
private static read
|
|
19
|
+
private static read(): Route[] {
|
|
20
20
|
if (process.env.TOA_REALTIME === undefined)
|
|
21
21
|
throw new Error('TOA_REALTIME is not defined')
|
|
22
22
|
|
|
23
23
|
return JSON.parse(process.env.TOA_REALTIME) as Route[]
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
public override async open
|
|
26
|
+
public override async open(): Promise<void> {
|
|
27
27
|
const routes = Routes.read()
|
|
28
28
|
const creating = []
|
|
29
29
|
|
|
30
30
|
for (const { event, properties, expose } of routes) {
|
|
31
|
-
const consumer = this.host.receive(
|
|
31
|
+
const consumer = this.host.receive(
|
|
32
|
+
event,
|
|
33
|
+
new Receiver({ event, properties, stream: this.events, expose })
|
|
34
|
+
)
|
|
32
35
|
|
|
33
36
|
creating.push(consumer)
|
|
34
37
|
}
|
|
@@ -44,18 +47,17 @@ export class Routes extends Connector {
|
|
|
44
47
|
console.info('Event sources connected', { count: creating.length })
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
public override async close
|
|
50
|
+
public override async close(): Promise<void> {
|
|
48
51
|
console.info('Event sources disconnected')
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
class Events extends Readable {
|
|
53
|
-
public constructor
|
|
56
|
+
public constructor() {
|
|
54
57
|
super({ objectMode: true })
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
public override _read
|
|
58
|
-
}
|
|
60
|
+
public override _read(): void {}
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
export type { Route }
|
package/source/extension.ts
CHANGED
|
@@ -2,16 +2,22 @@ import { readFileSync } from 'node:fs'
|
|
|
2
2
|
import { components } from './Composition.js'
|
|
3
3
|
import type { Dependency, Instances, Resources, Service } from '@toa.io/operations'
|
|
4
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
|
+
|
|
5
9
|
export const standalone = true
|
|
6
10
|
export { components } from './Composition.js'
|
|
7
11
|
|
|
8
|
-
export function deployment
|
|
12
|
+
export function deployment(
|
|
13
|
+
instances: Instances<Declaration>,
|
|
14
|
+
annotation?: Declaration & Annotation
|
|
15
|
+
): Dependency {
|
|
9
16
|
const routes = []
|
|
10
17
|
const { resources, ...annotatedRoutes } = annotation ?? {}
|
|
11
18
|
const labels = components().labels
|
|
12
19
|
|
|
13
|
-
if (annotatedRoutes !== undefined)
|
|
14
|
-
routes.push(...parse(annotatedRoutes))
|
|
20
|
+
if (annotatedRoutes !== undefined) routes.push(...parse(annotatedRoutes))
|
|
15
21
|
|
|
16
22
|
for (const instance of instances) {
|
|
17
23
|
const completed: Declaration = {}
|
|
@@ -28,20 +34,24 @@ export function deployment (instances: Instances<Declaration>, annotation?: Decl
|
|
|
28
34
|
const service: Service = {
|
|
29
35
|
group: 'realtime',
|
|
30
36
|
name: 'streams',
|
|
37
|
+
image,
|
|
31
38
|
|
|
32
|
-
version: JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
39
|
+
version: JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
40
|
+
.version,
|
|
33
41
|
components: labels,
|
|
34
42
|
resources,
|
|
35
|
-
variables: [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
variables: [
|
|
44
|
+
{
|
|
45
|
+
name: 'TOA_REALTIME',
|
|
46
|
+
value: JSON.stringify(routes)
|
|
47
|
+
}
|
|
48
|
+
]
|
|
39
49
|
}
|
|
40
50
|
|
|
41
51
|
return { services: [service], events: routes.map((route) => route.event) }
|
|
42
52
|
}
|
|
43
53
|
|
|
44
|
-
export function parse
|
|
54
|
+
export function parse(declaration: Declaration): Route[] {
|
|
45
55
|
const routes: Route[] = []
|
|
46
56
|
|
|
47
57
|
for (const [event, value] of Object.entries(declaration))
|
|
@@ -58,7 +68,7 @@ export function parse (declaration: Declaration): Route[] {
|
|
|
58
68
|
return routes
|
|
59
69
|
}
|
|
60
70
|
|
|
61
|
-
function isObject
|
|
71
|
+
function isObject(value: Entry): value is RouteDeclaration {
|
|
62
72
|
return typeof value === 'object' && !Array.isArray(value)
|
|
63
73
|
}
|
|
64
74
|
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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"}
|
package/transpiled/Factory.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Factory.js","sourceRoot":"","sources":["../source/Factory.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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 +1 @@
|
|
|
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,
|
|
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"}
|
package/transpiled/Receiver.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Connector
|
|
1
|
+
import { Connector } from '@toa.io/core';
|
|
2
|
+
import type { Message } from '@toa.io/core/types';
|
|
2
3
|
import type { SpanContext } from 'openspan';
|
|
3
4
|
import type { Readable } from 'node:stream';
|
|
4
5
|
export declare class Receiver extends Connector {
|
package/transpiled/Receiver.js
CHANGED
|
@@ -25,7 +25,10 @@ export class Receiver extends Connector {
|
|
|
25
25
|
for (const property of this.properties) {
|
|
26
26
|
const key = message.payload[property];
|
|
27
27
|
if (key === undefined) {
|
|
28
|
-
console.debug('Event does not contain key property', {
|
|
28
|
+
console.debug('Event does not contain key property', {
|
|
29
|
+
property,
|
|
30
|
+
event: this.event
|
|
31
|
+
});
|
|
29
32
|
continue;
|
|
30
33
|
}
|
|
31
34
|
if (Array.isArray(key))
|
|
@@ -39,8 +42,7 @@ export class Receiver extends Connector {
|
|
|
39
42
|
fit(payload) {
|
|
40
43
|
if (this.expose === undefined)
|
|
41
44
|
return payload;
|
|
42
|
-
const entries = Object.entries(payload)
|
|
43
|
-
.filter(([key]) => this.expose.includes(key));
|
|
45
|
+
const entries = Object.entries(payload).filter(([key]) => this.expose.includes(key));
|
|
44
46
|
return Object.fromEntries(entries);
|
|
45
47
|
}
|
|
46
48
|
push(key, data, telemetry) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Receiver.js","sourceRoot":"","sources":["../source/Receiver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"Receiver.js","sourceRoot":"","sources":["../source/Receiver.ts"],"names":[],"mappings":"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"}
|