@toa.io/extensions.exposition 1.0.0-alpha.272 → 1.0.0-alpha.274
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/CHANGELOG.md +211 -0
- package/components/exposition.atom/manifest.toa.yaml +3 -1
- package/components/exposition.octets/manifest.toa.yaml +28 -10
- package/components/exposition.octets/operations/put.js +20 -5
- package/components/identity.bans/manifest.toa.yaml +26 -7
- package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/manifest.toa.yaml +106 -30
- package/components/identity.basic/operations/authenticate.js +7 -4
- package/components/identity.basic/operations/authenticate.js.map +1 -1
- package/components/identity.basic/operations/incept.js +3 -2
- package/components/identity.basic/operations/incept.js.map +1 -1
- package/components/identity.basic/operations/transit.js +17 -6
- package/components/identity.basic/operations/transit.js.map +1 -1
- package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/operations/types.d.ts +2 -2
- package/components/identity.basic/source/authenticate.ts +8 -4
- package/components/identity.basic/source/incept.ts +3 -2
- package/components/identity.basic/source/transit.ts +20 -6
- package/components/identity.basic/source/types.ts +2 -2
- package/components/identity.credentials/manifest.toa.yaml +34 -13
- package/components/identity.credentials/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/manifest.toa.yaml +120 -28
- package/components/identity.federation/operations/authenticate.js +3 -2
- package/components/identity.federation/operations/authenticate.js.map +1 -1
- package/components/identity.federation/operations/create.js +4 -2
- package/components/identity.federation/operations/create.js.map +1 -1
- package/components/identity.federation/operations/lib/errors.d.ts +70 -11
- package/components/identity.federation/operations/lib/errors.js +40 -11
- package/components/identity.federation/operations/lib/errors.js.map +1 -1
- package/components/identity.federation/operations/lib/exchange.js +2 -2
- package/components/identity.federation/operations/lib/exchange.js.map +1 -1
- package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/operations/types/configuration.d.ts +3 -2
- package/components/identity.federation/source/authenticate.ts +3 -2
- package/components/identity.federation/source/create.ts +4 -2
- package/components/identity.federation/source/lib/errors.ts +49 -12
- package/components/identity.federation/source/lib/exchange.ts +2 -2
- package/components/identity.federation/source/types/configuration.ts +4 -2
- package/components/identity.keys/manifest.toa.yaml +14 -6
- package/components/identity.keys/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.otp/manifest.toa.yaml +44 -15
- package/components/identity.otp/operations/authenticate.js +9 -4
- package/components/identity.otp/operations/authenticate.js.map +1 -1
- package/components/identity.otp/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.otp/source/authenticate.ts +11 -4
- package/components/identity.passkeys/manifest.toa.yaml +38 -8
- package/components/identity.passkeys/operations/authenticate.js +3 -2
- package/components/identity.passkeys/operations/authenticate.js.map +1 -1
- package/components/identity.passkeys/operations/create.js +6 -3
- package/components/identity.passkeys/operations/create.js.map +1 -1
- package/components/identity.passkeys/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.passkeys/operations/use.js +6 -3
- package/components/identity.passkeys/operations/use.js.map +1 -1
- package/components/identity.passkeys/source/authenticate.ts +3 -2
- package/components/identity.passkeys/source/create.ts +7 -3
- package/components/identity.passkeys/source/use.ts +7 -3
- package/components/identity.roles/manifest.toa.yaml +41 -10
- package/components/identity.roles/operations/grant.js +3 -2
- package/components/identity.roles/operations/grant.js.map +1 -1
- package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/source/grant.ts +3 -2
- package/components/identity.tokens/manifest.toa.yaml +99 -39
- package/components/identity.tokens/operations/authenticate.js +6 -3
- package/components/identity.tokens/operations/authenticate.js.map +1 -1
- package/components/identity.tokens/operations/decrypt.js +10 -5
- package/components/identity.tokens/operations/decrypt.js.map +1 -1
- package/components/identity.tokens/operations/encrypt.js +4 -3
- package/components/identity.tokens/operations/encrypt.js.map +1 -1
- package/components/identity.tokens/operations/lib/types.d.ts +3 -2
- package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/source/authenticate.test.ts +7 -2
- package/components/identity.tokens/source/authenticate.ts +7 -3
- package/components/identity.tokens/source/decrypt.test.ts +13 -7
- package/components/identity.tokens/source/decrypt.ts +12 -5
- package/components/identity.tokens/source/encrypt.test.ts +9 -4
- package/components/identity.tokens/source/encrypt.ts +4 -3
- package/components/identity.tokens/source/lib/types.ts +3 -2
- package/context.toa.yaml +2 -2
- package/documentation/components.md +1 -1
- package/documentation/identity.md +4 -1
- package/features/configuration.feature +207 -0
- package/features/cors.feature +1 -1
- package/features/dev.feature +1 -1
- package/features/identity.federation.feature +18 -9
- package/features/{identtiy.tokens.custom.feature → identity.tokens.custom.feature} +39 -0
- package/features/introspection.map.feature +16 -0
- package/features/map.feature +1 -1
- package/features/octets.download.feature +1 -1
- package/features/octets.meta.feature +1 -1
- package/features/passkeys.feature +8 -8
- package/features/require.feature +2 -2
- package/features/response.feature +3 -3
- package/features/steps/Components.ts +41 -4
- package/features/steps/Gateway.ts +61 -23
- package/features/steps/HTTP.ts +3 -5
- package/features/steps/Parameters.ts +2 -3
- package/features/steps/Realtime.ts +4 -4
- package/features/steps/Workspace.ts +8 -3
- package/features/steps/components/audit/manifest.toa.yaml +12 -5
- package/features/steps/components/echo/manifest.toa.yaml +33 -8
- package/features/steps/components/notify/manifest.toa.yaml +12 -5
- package/features/steps/components/octets.tester/manifest.toa.yaml +43 -14
- package/features/steps/components/orders/manifest.toa.yaml +22 -5
- package/features/steps/components/pots/manifest.toa.yaml +71 -17
- package/features/steps/components/pricing/manifest.toa.yaml +8 -2
- package/features/steps/components/sequences/manifest.toa.yaml +3 -1
- package/features/steps/components/users/manifest.toa.yaml +18 -3
- package/features/steps/components/users.properties/manifest.toa.yaml +12 -2
- package/package.json +5 -6
- package/schemas/annotation.cos.yaml +37 -17
- package/schemas/directive.cos.yaml +7 -3
- package/schemas/io/throttle.cos.yaml +47 -8
- package/schemas/method.cos.yaml +21 -9
- package/schemas/node.cos.yaml +22 -7
- package/schemas/octets/delete.cos.yaml +15 -2
- package/schemas/octets/get.cos.yaml +5 -2
- package/schemas/octets/put.cos.yaml +6 -3
- package/schemas/octets/workflow.cos.yaml +0 -1
- package/schemas/query.cos.yaml +31 -14
- package/schemas/querystring.cos.yaml +19 -9
- package/schemas/range.cos.yaml +10 -2
- package/schemas/route.cos.yaml +6 -2
- package/source/Branch.test.ts +37 -0
- package/source/Branch.ts +37 -0
- package/source/Factory.ts +5 -5
- package/source/Gateway.ts +20 -13
- package/source/HTTP/formats/yaml.test.ts +10 -2
- package/source/HTTP/formats/yaml.ts +21 -1
- package/source/RTD/Tree.ts +4 -1
- package/source/Tenant.ts +3 -3
- package/source/deployment.ts +3 -4
- package/source/directives/map/Headers.ts +8 -1
- package/source/directives/octets/Put.ts +6 -3
- package/source/root.ts +2 -2
- package/transpiled/Branch.d.ts +23 -0
- package/transpiled/Branch.js +16 -0
- package/transpiled/Branch.js.map +1 -1
- package/transpiled/Factory.js +4 -4
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.js +17 -7
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/formats/yaml.js +15 -1
- package/transpiled/HTTP/formats/yaml.js.map +1 -1
- package/transpiled/RTD/Tree.js +4 -1
- package/transpiled/RTD/Tree.js.map +1 -1
- package/transpiled/Tenant.d.ts +1 -1
- package/transpiled/Tenant.js +1 -1
- package/transpiled/Tenant.js.map +1 -1
- package/transpiled/deployment.js +3 -4
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/map/Headers.js +7 -1
- package/transpiled/directives/map/Headers.js.map +1 -1
- package/transpiled/directives/octets/Put.js.map +1 -1
- package/transpiled/root.js +1 -1
- package/transpiled/root.js.map +1 -1
- package/transpiled/tsconfig.tsbuildinfo +1 -1
package/features/require.feature
CHANGED
|
@@ -27,7 +27,7 @@ Feature: Request requirements
|
|
|
27
27
|
Then the following reply is sent:
|
|
28
28
|
"""
|
|
29
29
|
201 Created
|
|
30
|
-
etag: ${{ etag }}
|
|
30
|
+
etag: "${{ etag }}"
|
|
31
31
|
|
|
32
32
|
id: ${{ id }}
|
|
33
33
|
"""
|
|
@@ -53,7 +53,7 @@ Feature: Request requirements
|
|
|
53
53
|
host: nex.toa.io
|
|
54
54
|
content-type: application/yaml
|
|
55
55
|
accept: text/plain
|
|
56
|
-
if-match: ${{ etag }}
|
|
56
|
+
if-match: "${{ etag }}"
|
|
57
57
|
|
|
58
58
|
title: Bye
|
|
59
59
|
"""
|
|
@@ -19,8 +19,8 @@ Feature: Response
|
|
|
19
19
|
Then the following reply is sent:
|
|
20
20
|
"""
|
|
21
21
|
200 OK
|
|
22
|
+
vary: origin, accept
|
|
22
23
|
content-type: application/json
|
|
23
|
-
vary: accept
|
|
24
24
|
|
|
25
25
|
{"hello":"world"}
|
|
26
26
|
"""
|
|
@@ -33,8 +33,8 @@ Feature: Response
|
|
|
33
33
|
Then the following reply is sent:
|
|
34
34
|
"""
|
|
35
35
|
200 OK
|
|
36
|
+
vary: origin, accept
|
|
36
37
|
content-type: application/yaml
|
|
37
|
-
vary: accept
|
|
38
38
|
|
|
39
39
|
hello: world
|
|
40
40
|
"""
|
|
@@ -48,8 +48,8 @@ Feature: Response
|
|
|
48
48
|
Then the following reply is sent:
|
|
49
49
|
"""
|
|
50
50
|
200 OK
|
|
51
|
+
vary: origin, accept
|
|
51
52
|
content-type: application/json
|
|
52
|
-
vary: accept
|
|
53
53
|
|
|
54
54
|
{"hello":"world"}
|
|
55
55
|
"""
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import * as assert from 'node:assert'
|
|
2
|
+
import { dirname, join } from 'node:path'
|
|
2
3
|
import { after, binding, given } from 'cucumber-tsflow'
|
|
3
4
|
import * as boot from '@toa.io/boot'
|
|
4
5
|
import { timeout } from '@toa.io/generic'
|
|
5
6
|
import { type Connector } from '@toa.io/core'
|
|
6
|
-
import { parse } from '
|
|
7
|
+
import { load as parse } from 'js-yaml'
|
|
8
|
+
import { Gateway } from './Gateway'
|
|
7
9
|
import { Workspace } from './Workspace'
|
|
8
10
|
import { components as map } from './map'
|
|
9
11
|
|
|
10
12
|
const MAP = 'introspection'
|
|
13
|
+
const VALUES = 'configuration'
|
|
11
14
|
|
|
12
|
-
@binding([Workspace])
|
|
15
|
+
@binding([Workspace, Gateway])
|
|
13
16
|
export class Components {
|
|
14
17
|
private readonly workspace: Workspace
|
|
18
|
+
private readonly gateway: Gateway
|
|
15
19
|
private compositions: Record<string, Connector> = {}
|
|
16
20
|
|
|
17
|
-
public constructor (workspace: Workspace) {
|
|
21
|
+
public constructor (workspace: Workspace, gateway: Gateway) {
|
|
18
22
|
this.workspace = workspace
|
|
23
|
+
this.gateway = gateway
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
@given('the `{word}` is running')
|
|
@@ -25,7 +30,7 @@ export class Components {
|
|
|
25
30
|
|
|
26
31
|
@given('the `{word}` is running with the following manifest:')
|
|
27
32
|
public async patchAndRun (name: string, yaml: string): Promise<void> {
|
|
28
|
-
const manifest = parse(yaml)
|
|
33
|
+
const manifest = parse(yaml) as object
|
|
29
34
|
|
|
30
35
|
await this.runComponent(name, manifest)
|
|
31
36
|
}
|
|
@@ -41,6 +46,25 @@ export class Components {
|
|
|
41
46
|
await timeout(50) // discovery
|
|
42
47
|
}
|
|
43
48
|
|
|
49
|
+
/** The values component, as the configuration extension ships it; the service hosts it alone. */
|
|
50
|
+
@given('the configuration values are running')
|
|
51
|
+
public async runValues (): Promise<void> {
|
|
52
|
+
assert.ok(!(VALUES in this.compositions), `Composition '${VALUES}' is already running`)
|
|
53
|
+
|
|
54
|
+
await this.gateway.start()
|
|
55
|
+
|
|
56
|
+
this.compositions[VALUES] = await boot.composition([values()])
|
|
57
|
+
|
|
58
|
+
await this.compositions[VALUES].connect()
|
|
59
|
+
await timeout(50) // discovery
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** What the deployment would tell the values service, as the scenario needs it. */
|
|
63
|
+
@given('the configuration values are deployed:')
|
|
64
|
+
public deployValues (yaml: string): void {
|
|
65
|
+
process.env.TOA_CONFIGURATION_VALUES = JSON.stringify(parse(yaml))
|
|
66
|
+
}
|
|
67
|
+
|
|
44
68
|
@given('the `{word}` is stopped')
|
|
45
69
|
public async stop (name: string): Promise<void> {
|
|
46
70
|
assert.ok(name in this.compositions, `Composition '${name}' is not running`)
|
|
@@ -54,11 +78,18 @@ export class Components {
|
|
|
54
78
|
const promises = Object.values(this.compositions).map((composition) => composition.disconnect())
|
|
55
79
|
|
|
56
80
|
await Promise.all(promises)
|
|
81
|
+
|
|
82
|
+
delete process.env.TOA_CONFIGURATION_VALUES
|
|
57
83
|
}
|
|
58
84
|
|
|
59
85
|
private async runComponent (name: string, manifest?: object): Promise<void> {
|
|
60
86
|
assert.ok(!(name in this.compositions), `Composition '${name}' is already running`)
|
|
61
87
|
|
|
88
|
+
// the gateway first: a component announces itself when it opens, and that only
|
|
89
|
+
// reaches a gateway that is already listening. Started the other way round, the
|
|
90
|
+
// component waits for a knock, which the request that follows does not.
|
|
91
|
+
await this.gateway.start()
|
|
92
|
+
|
|
62
93
|
const path = await this.workspace.addComponent(name, manifest)
|
|
63
94
|
|
|
64
95
|
this.compositions[name] = await boot.composition([path])
|
|
@@ -67,3 +98,9 @@ export class Components {
|
|
|
67
98
|
await timeout(50) // discovery
|
|
68
99
|
}
|
|
69
100
|
}
|
|
101
|
+
|
|
102
|
+
function values (): string {
|
|
103
|
+
const root = dirname(require.resolve('@toa.io/extensions.configuration/package.json'))
|
|
104
|
+
|
|
105
|
+
return join(root, 'components', 'configuration.values')
|
|
106
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { after, afterAll, binding, given } from 'cucumber-tsflow'
|
|
2
2
|
import * as boot from '@toa.io/boot'
|
|
3
3
|
import { type Connector } from '@toa.io/core'
|
|
4
|
-
import { parse } from '
|
|
5
|
-
import {
|
|
4
|
+
import { load as parse } from 'js-yaml'
|
|
5
|
+
import { timeout } from '@toa.io/generic'
|
|
6
6
|
import { Factory } from '../../source'
|
|
7
7
|
import * as syntax from '../../source/RTD/syntax'
|
|
8
8
|
import { shortcuts } from '../../source/Directive'
|
|
@@ -14,15 +14,16 @@ let instance: Connector | null = null
|
|
|
14
14
|
@binding()
|
|
15
15
|
export class Gateway {
|
|
16
16
|
private default: boolean = true
|
|
17
|
+
private written: string[] = []
|
|
17
18
|
|
|
18
19
|
@given('the annotation:')
|
|
19
20
|
public async annotate (yaml: string): Promise<void> {
|
|
20
|
-
const annotation = parse(yaml)
|
|
21
|
+
const annotation = parse(yaml) as Partial<http.Options> & { '/'?: object }
|
|
21
22
|
|
|
22
|
-
if ('/'
|
|
23
|
+
if (annotation['/'] !== undefined) {
|
|
23
24
|
const tree = syntax.parse(annotation['/'], shortcuts)
|
|
24
25
|
|
|
25
|
-
process.env.TOA_EXPOSITION =
|
|
26
|
+
process.env.TOA_EXPOSITION = JSON.stringify(tree)
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const { debug, authorities } = annotation
|
|
@@ -34,7 +35,7 @@ export class Gateway {
|
|
|
34
35
|
if (authorities !== undefined)
|
|
35
36
|
properties.authorities = authorities
|
|
36
37
|
|
|
37
|
-
process.env.TOA_EXPOSITION_PROPERTIES =
|
|
38
|
+
process.env.TOA_EXPOSITION_PROPERTIES = JSON.stringify(properties)
|
|
38
39
|
|
|
39
40
|
await Gateway.stop()
|
|
40
41
|
|
|
@@ -47,7 +48,15 @@ export class Gateway {
|
|
|
47
48
|
*/
|
|
48
49
|
@given('the annotation of the introspection map')
|
|
49
50
|
public async annotateMap (): Promise<void> {
|
|
50
|
-
|
|
51
|
+
await this.annotateMapUnder()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The same routes under a root of the scenario's own: what an application declares around the map. */
|
|
55
|
+
@given('the annotation of the introspection map under:')
|
|
56
|
+
public async annotateMapUnder (yaml?: string): Promise<void> {
|
|
57
|
+
const tree: syntax.Node = yaml === undefined
|
|
58
|
+
? { routes: [], methods: [], directives: [] }
|
|
59
|
+
: syntax.parse((parse(yaml) as { '/': object })['/'], shortcuts)
|
|
51
60
|
|
|
52
61
|
for (const manifest of await manifests()) {
|
|
53
62
|
const node = manifest.extensions?.[EXPOSITION] as syntax.Node | undefined
|
|
@@ -58,8 +67,8 @@ export class Gateway {
|
|
|
58
67
|
tree.routes.push(...node.routes)
|
|
59
68
|
}
|
|
60
69
|
|
|
61
|
-
process.env.TOA_EXPOSITION =
|
|
62
|
-
process.env.TOA_EXPOSITION_PROPERTIES =
|
|
70
|
+
process.env.TOA_EXPOSITION = JSON.stringify(tree)
|
|
71
|
+
process.env.TOA_EXPOSITION_PROPERTIES = JSON.stringify(DEFAULT_PROPERTIES)
|
|
63
72
|
|
|
64
73
|
await Gateway.stop()
|
|
65
74
|
|
|
@@ -71,10 +80,25 @@ export class Gateway {
|
|
|
71
80
|
const [name, namespace = 'default'] = id.split('.').reverse()
|
|
72
81
|
const key = `TOA_CONFIGURATION_${namespace.toUpperCase()}_${name.toUpperCase()}`
|
|
73
82
|
const def = DEFAULT_CONFIGURATION[id] ?? {}
|
|
74
|
-
const patch
|
|
83
|
+
const patch = parse(yaml) as object
|
|
75
84
|
const configuration = Object.assign({}, def, patch)
|
|
76
85
|
|
|
77
|
-
process.env[key] =
|
|
86
|
+
process.env[key] = JSON.stringify(configuration)
|
|
87
|
+
|
|
88
|
+
await Gateway.stop()
|
|
89
|
+
|
|
90
|
+
this.default = false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The secrets a scenario's configuration refers to. */
|
|
94
|
+
@given('the configuration secrets:')
|
|
95
|
+
public async secrets (yaml: string): Promise<void> {
|
|
96
|
+
const secrets = parse(yaml) as Record<string, string>
|
|
97
|
+
|
|
98
|
+
for (const [name, value] of Object.entries(secrets)) {
|
|
99
|
+
this.written.push(SECRET + name)
|
|
100
|
+
process.env[SECRET + name] = value
|
|
101
|
+
}
|
|
78
102
|
|
|
79
103
|
await Gateway.stop()
|
|
80
104
|
|
|
@@ -96,7 +120,7 @@ export class Gateway {
|
|
|
96
120
|
return
|
|
97
121
|
|
|
98
122
|
process.env.TOA_EXPOSITION ??= DEFAULT_TREE
|
|
99
|
-
process.env.TOA_EXPOSITION_PROPERTIES ??=
|
|
123
|
+
process.env.TOA_EXPOSITION_PROPERTIES ??= JSON.stringify(DEFAULT_PROPERTIES)
|
|
100
124
|
|
|
101
125
|
this.writeConfiguration()
|
|
102
126
|
|
|
@@ -116,6 +140,11 @@ export class Gateway {
|
|
|
116
140
|
public async cleanup (): Promise<void> {
|
|
117
141
|
delete process.env.__TESTING_EXPOSITION_BRANCH_TTL
|
|
118
142
|
|
|
143
|
+
for (const key of this.written)
|
|
144
|
+
delete process.env[key]
|
|
145
|
+
|
|
146
|
+
this.written = []
|
|
147
|
+
|
|
119
148
|
if (this.default)
|
|
120
149
|
return
|
|
121
150
|
|
|
@@ -136,14 +165,18 @@ export class Gateway {
|
|
|
136
165
|
const [name, namespace = 'default'] = id.split('.').reverse()
|
|
137
166
|
const key = `TOA_CONFIGURATION_${namespace.toUpperCase()}_${name.toUpperCase()}`
|
|
138
167
|
|
|
139
|
-
process.env[key] ??=
|
|
168
|
+
process.env[key] ??= JSON.stringify(configuration)
|
|
140
169
|
}
|
|
170
|
+
|
|
171
|
+
for (const [name, value] of Object.entries(DEFAULT_SECRETS))
|
|
172
|
+
process.env[SECRET + name] ??= value
|
|
141
173
|
}
|
|
142
174
|
}
|
|
143
175
|
|
|
144
176
|
const EXPOSITION = '@toa.io/extensions.exposition'
|
|
177
|
+
const SECRET = 'TOA_CONFIGURATION__'
|
|
145
178
|
|
|
146
|
-
const DEFAULT_TREE =
|
|
179
|
+
const DEFAULT_TREE = JSON.stringify({
|
|
147
180
|
routes: [],
|
|
148
181
|
methods: [],
|
|
149
182
|
directives: [
|
|
@@ -161,18 +194,23 @@ const DEFAULT_PROPERTIES: Partial<http.Options> = {
|
|
|
161
194
|
}
|
|
162
195
|
}
|
|
163
196
|
|
|
197
|
+
// the identity components boot inside the gateway, and without a variable each would wait
|
|
198
|
+
// for the values service, which these features do not run
|
|
164
199
|
const DEFAULT_CONFIGURATION: Record<string, object> = {
|
|
200
|
+
'identity.basic': {},
|
|
201
|
+
'identity.federation': {},
|
|
202
|
+
'identity.otp': {},
|
|
203
|
+
'identity.passkeys': {},
|
|
165
204
|
'identity.tokens': {
|
|
166
205
|
keys: [
|
|
167
|
-
{
|
|
168
|
-
|
|
169
|
-
key: 'sTxL6qVOadKkUJwh3FveU53XgTEo3Sdfg7k2FfiIKfs'
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
id: 'legacy0',
|
|
173
|
-
key: 'k3.local.pIZT8-9Fa6U_QtfQHOSStfGtmyzPINyKQq2Xk-hd7vA',
|
|
174
|
-
format: 'paseto'
|
|
175
|
-
}
|
|
206
|
+
{ id: 'key0', key: '$IDENTITY_TOKENS_KEY0' },
|
|
207
|
+
{ id: 'legacy0', key: '$IDENTITY_TOKENS_LEGACY0', format: 'paseto' }
|
|
176
208
|
]
|
|
177
209
|
}
|
|
178
210
|
}
|
|
211
|
+
|
|
212
|
+
// a secret is given as a reference, and comes to the component as an object
|
|
213
|
+
const DEFAULT_SECRETS: Record<string, string> = {
|
|
214
|
+
IDENTITY_TOKENS_KEY0: 'sTxL6qVOadKkUJwh3FveU53XgTEo3Sdfg7k2FfiIKfs',
|
|
215
|
+
IDENTITY_TOKENS_LEGACY0: 'k3.local.pIZT8-9Fa6U_QtfQHOSStfGtmyzPINyKQq2Xk-hd7vA'
|
|
216
|
+
}
|
package/features/steps/HTTP.ts
CHANGED
|
@@ -13,7 +13,6 @@ import type { Readable } from 'node:stream'
|
|
|
13
13
|
@binding([Gateway, Parameters, Captures])
|
|
14
14
|
export class HTTP extends http.Agent {
|
|
15
15
|
private readonly gateway: Gateway
|
|
16
|
-
private fetched: Response | null = null
|
|
17
16
|
|
|
18
17
|
public constructor (gateway: Gateway, parameters: Parameters, captures: Captures) {
|
|
19
18
|
super(parameters.origin, captures)
|
|
@@ -24,7 +23,7 @@ export class HTTP extends http.Agent {
|
|
|
24
23
|
public override async request (input: string): Promise<any> {
|
|
25
24
|
await this.gateway.start()
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
await super.request(input)
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
@then('the following reply is sent:')
|
|
@@ -34,10 +33,9 @@ export class HTTP extends http.Agent {
|
|
|
34
33
|
|
|
35
34
|
@then('response body contains {word}-encoded value:')
|
|
36
35
|
public async bodyIs (format: string, yaml: string): Promise<void> {
|
|
37
|
-
assert.ok(this.
|
|
36
|
+
assert.ok(this.bytes !== null, 'Response body is not available')
|
|
38
37
|
|
|
39
|
-
const
|
|
40
|
-
const value = encoders[format]?.(buf as unknown as Buffer)
|
|
38
|
+
const value = encoders[format]?.(this.bytes)
|
|
41
39
|
const expected = YAML.load(yaml)
|
|
42
40
|
|
|
43
41
|
assert.deepEqual(value, expected, 'Values are not equal')
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
2
|
import * as dotenv from 'dotenv'
|
|
3
3
|
import { setDefaultTimeout } from '@cucumber/cucumber'
|
|
4
|
-
import { encode } from '@toa.io/generic'
|
|
5
4
|
|
|
6
5
|
dotenv.config({ path: join(__dirname, '.env') })
|
|
7
6
|
|
|
@@ -19,14 +18,14 @@ process.env.TOA_DEV = '1'
|
|
|
19
18
|
|
|
20
19
|
// export traces to the local Tempo (`docker compose up tempo grafana`),
|
|
21
20
|
// unavailability of the endpoint is harmless
|
|
22
|
-
process.env.TOA_TELEMETRY_TRACES ??=
|
|
21
|
+
process.env.TOA_TELEMETRY_TRACES ??= JSON.stringify({
|
|
23
22
|
exporters: {
|
|
24
23
|
console: null,
|
|
25
24
|
otlp: { endpoint: 'http://localhost:4318' }
|
|
26
25
|
}
|
|
27
26
|
})
|
|
28
27
|
|
|
29
|
-
process.env.TOA_STORAGES =
|
|
28
|
+
process.env.TOA_STORAGES = JSON.stringify({
|
|
30
29
|
octets: {
|
|
31
30
|
provider: 'tmp',
|
|
32
31
|
directory: Math.random().toString(36).substring(2)
|
|
@@ -3,8 +3,8 @@ import * as assert from 'node:assert'
|
|
|
3
3
|
import { after, binding, given, afterAll, then } from 'cucumber-tsflow'
|
|
4
4
|
import { Factory } from '@toa.io/extensions.realtime'
|
|
5
5
|
import * as boot from '@toa.io/boot'
|
|
6
|
-
import {
|
|
7
|
-
import { parse } from '
|
|
6
|
+
import { match } from '@toa.io/generic'
|
|
7
|
+
import { load as parse } from 'js-yaml'
|
|
8
8
|
import { Agent } from '@toa.io/agent'
|
|
9
9
|
import { Parameters } from './Parameters'
|
|
10
10
|
import { Gateway } from './Gateway'
|
|
@@ -29,13 +29,13 @@ export class Realtime {
|
|
|
29
29
|
public async start (yaml: string): Promise<void> {
|
|
30
30
|
await Realtime.stop()
|
|
31
31
|
|
|
32
|
-
const annotation = parse(yaml)
|
|
32
|
+
const annotation = parse(yaml) as Record<string, string>
|
|
33
33
|
const routes = []
|
|
34
34
|
|
|
35
35
|
for (const [event, property] of Object.entries(annotation))
|
|
36
36
|
routes.push({ event, properties: [property] })
|
|
37
37
|
|
|
38
|
-
process.env.TOA_REALTIME =
|
|
38
|
+
process.env.TOA_REALTIME = JSON.stringify(routes)
|
|
39
39
|
|
|
40
40
|
const factory = new Factory(boot)
|
|
41
41
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
2
|
import { tmpdir, devNull } from 'node:os'
|
|
3
|
-
import { mkdtemp, cp } from 'node:fs/promises'
|
|
4
|
-
import
|
|
3
|
+
import { mkdtemp, cp, readFile, writeFile } from 'node:fs/promises'
|
|
4
|
+
import { load, dump } from 'js-yaml'
|
|
5
|
+
import { overwrite } from '@toa.io/generic'
|
|
5
6
|
|
|
6
7
|
export class Workspace {
|
|
7
8
|
private root: string = devNull
|
|
@@ -35,6 +36,10 @@ export class Workspace {
|
|
|
35
36
|
private async patchManifest (target: string, patch: object): Promise<void> {
|
|
36
37
|
const path = join(target, 'manifest.toa.yaml')
|
|
37
38
|
|
|
38
|
-
await
|
|
39
|
+
const manifest = load(await readFile(path, 'utf8')) as object
|
|
40
|
+
|
|
41
|
+
overwrite(manifest, patch)
|
|
42
|
+
|
|
43
|
+
await writeFile(path, dump(manifest, { noRefs: true, lineWidth: -1 }), 'utf8')
|
|
39
44
|
}
|
|
40
45
|
}
|
|
@@ -3,11 +3,18 @@ name: audit
|
|
|
3
3
|
operations:
|
|
4
4
|
record:
|
|
5
5
|
input:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
properties:
|
|
7
|
+
id:
|
|
8
|
+
type: string
|
|
9
|
+
title:
|
|
10
|
+
type: string
|
|
11
|
+
volume:
|
|
12
|
+
type: number
|
|
13
|
+
price:
|
|
14
|
+
type: number
|
|
15
|
+
type: object
|
|
16
|
+
output:
|
|
17
|
+
{}
|
|
11
18
|
|
|
12
19
|
receivers:
|
|
13
20
|
orders.created: record
|
|
@@ -3,24 +3,48 @@ name: echo
|
|
|
3
3
|
operations:
|
|
4
4
|
compute:
|
|
5
5
|
input:
|
|
6
|
-
|
|
6
|
+
properties:
|
|
7
|
+
name:
|
|
8
|
+
type: string
|
|
9
|
+
type: object
|
|
10
|
+
required:
|
|
11
|
+
- name
|
|
7
12
|
affect:
|
|
8
13
|
input:
|
|
9
|
-
|
|
14
|
+
properties:
|
|
15
|
+
name:
|
|
16
|
+
type: string
|
|
17
|
+
type: object
|
|
18
|
+
required:
|
|
19
|
+
- name
|
|
10
20
|
identity:
|
|
11
21
|
input:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
properties:
|
|
23
|
+
identity:
|
|
24
|
+
properties:
|
|
25
|
+
id:
|
|
26
|
+
type: string
|
|
27
|
+
roles:
|
|
28
|
+
type: array
|
|
29
|
+
items:
|
|
30
|
+
type: string
|
|
31
|
+
type: object
|
|
32
|
+
type: object
|
|
15
33
|
parameters:
|
|
16
|
-
input:
|
|
34
|
+
input:
|
|
35
|
+
type: object
|
|
36
|
+
properties:
|
|
37
|
+
a:
|
|
38
|
+
type: string
|
|
39
|
+
b:
|
|
40
|
+
type: string
|
|
41
|
+
output:
|
|
17
42
|
type: object
|
|
18
43
|
properties:
|
|
19
44
|
a:
|
|
20
45
|
type: string
|
|
21
46
|
b:
|
|
22
47
|
type: string
|
|
23
|
-
output: *parameters
|
|
24
48
|
echo:
|
|
25
49
|
input:
|
|
26
50
|
type: object
|
|
@@ -28,4 +52,5 @@ operations:
|
|
|
28
52
|
input:
|
|
29
53
|
type: object
|
|
30
54
|
properties:
|
|
31
|
-
buf:
|
|
55
|
+
buf:
|
|
56
|
+
type: string
|
|
@@ -3,11 +3,18 @@ name: notify
|
|
|
3
3
|
operations:
|
|
4
4
|
send:
|
|
5
5
|
input:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
properties:
|
|
7
|
+
id:
|
|
8
|
+
type: string
|
|
9
|
+
title:
|
|
10
|
+
type: string
|
|
11
|
+
volume:
|
|
12
|
+
type: number
|
|
13
|
+
price:
|
|
14
|
+
type: number
|
|
15
|
+
type: object
|
|
16
|
+
output:
|
|
17
|
+
{}
|
|
11
18
|
|
|
12
19
|
receivers:
|
|
13
20
|
orders.created: send
|
|
@@ -6,13 +6,27 @@ storages: octets
|
|
|
6
6
|
operations:
|
|
7
7
|
foo: &operation
|
|
8
8
|
input:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
properties:
|
|
10
|
+
identity:
|
|
11
|
+
type: string
|
|
12
|
+
parameters:
|
|
13
|
+
type: object
|
|
14
|
+
steps:
|
|
15
|
+
type: object
|
|
16
|
+
authority:
|
|
17
|
+
type: string
|
|
18
|
+
storage:
|
|
19
|
+
type: string
|
|
20
|
+
path:
|
|
21
|
+
type: string
|
|
22
|
+
entry:
|
|
23
|
+
type: object
|
|
24
|
+
type: object
|
|
25
|
+
required:
|
|
26
|
+
- authority
|
|
27
|
+
- storage
|
|
28
|
+
- path
|
|
29
|
+
- entry
|
|
16
30
|
bar: *operation
|
|
17
31
|
baz: *operation
|
|
18
32
|
err: *operation
|
|
@@ -25,18 +39,33 @@ operations:
|
|
|
25
39
|
identity: *operation
|
|
26
40
|
redirect:
|
|
27
41
|
input:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
properties:
|
|
43
|
+
parameters:
|
|
44
|
+
type: object
|
|
45
|
+
patternProperties:
|
|
46
|
+
^.+$:
|
|
47
|
+
type: string
|
|
48
|
+
authority:
|
|
49
|
+
type: string
|
|
50
|
+
path:
|
|
51
|
+
type: string
|
|
52
|
+
type: object
|
|
53
|
+
required:
|
|
54
|
+
- authority
|
|
55
|
+
- path
|
|
31
56
|
output:
|
|
32
57
|
type: object
|
|
33
58
|
properties:
|
|
34
|
-
url:
|
|
59
|
+
url:
|
|
60
|
+
type: string
|
|
35
61
|
options:
|
|
36
62
|
type: object
|
|
37
63
|
properties:
|
|
38
|
-
method:
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
method:
|
|
65
|
+
type: string
|
|
66
|
+
headers:
|
|
67
|
+
type: object
|
|
68
|
+
body:
|
|
69
|
+
type: string
|
|
41
70
|
required:
|
|
42
71
|
- url
|
|
@@ -2,14 +2,31 @@ name: orders
|
|
|
2
2
|
|
|
3
3
|
entity:
|
|
4
4
|
schema:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
properties:
|
|
6
|
+
title:
|
|
7
|
+
type: string
|
|
8
|
+
volume:
|
|
9
|
+
type: number
|
|
10
|
+
price:
|
|
11
|
+
type: number
|
|
12
|
+
type: object
|
|
13
|
+
required:
|
|
14
|
+
- title
|
|
15
|
+
- volume
|
|
8
16
|
|
|
9
17
|
operations:
|
|
10
18
|
create:
|
|
11
19
|
concurrency: retry
|
|
12
20
|
query: false
|
|
13
21
|
input:
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
properties:
|
|
23
|
+
title:
|
|
24
|
+
type: string
|
|
25
|
+
default: .
|
|
26
|
+
volume:
|
|
27
|
+
type: string
|
|
28
|
+
default: .
|
|
29
|
+
type: object
|
|
30
|
+
required:
|
|
31
|
+
- title
|
|
32
|
+
- volume
|