@toa.io/extensions.configuration 1.0.0-alpha.31 → 1.0.0-alpha.310
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/configuration.values/manifest.toa.yaml +151 -0
- package/components/configuration.values/migrations/0002-indexes.yaml +7 -0
- package/components/configuration.values/operations/create.js +32 -0
- package/components/configuration.values/operations/fetch.js +13 -0
- package/components/configuration.values/operations/get.js +19 -0
- package/components/configuration.values/operations/lib/map.js +22 -0
- package/components/configuration.values/operations/lib/resolve.js +24 -0
- package/components/configuration.values/operations/list.js +11 -0
- package/components/configuration.values/source/create.ts +56 -0
- package/components/configuration.values/source/fetch.ts +26 -0
- package/components/configuration.values/source/get.ts +32 -0
- package/components/configuration.values/source/lib/map.ts +36 -0
- package/components/configuration.values/source/lib/resolve.ts +57 -0
- package/components/configuration.values/source/list.ts +21 -0
- package/components/configuration.values/tsconfig.json +10 -0
- package/components/configuration.values/types/index.d.ts +3 -0
- package/components/configuration.values/types/toa.d.ts +69 -0
- package/package.json +21 -10
- package/readme.md +178 -50
- package/transpiled/Aspect.d.ts +19 -4
- package/transpiled/Aspect.js +62 -9
- package/transpiled/Aspect.js.map +1 -1
- package/transpiled/Client.d.ts +59 -0
- package/transpiled/Client.js +171 -0
- package/transpiled/Client.js.map +1 -0
- package/transpiled/Composition.d.ts +14 -0
- package/transpiled/Composition.js +38 -0
- package/transpiled/Composition.js.map +1 -0
- package/transpiled/Factory.d.ts +9 -2
- package/transpiled/Factory.js +21 -9
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Secret.d.ts +15 -0
- package/transpiled/Secret.js +26 -0
- package/transpiled/Secret.js.map +1 -0
- package/transpiled/UI.d.ts +25 -0
- package/transpiled/UI.js +173 -0
- package/transpiled/UI.js.map +1 -0
- package/transpiled/configuration.d.ts +7 -2
- package/transpiled/configuration.js +33 -43
- package/transpiled/configuration.js.map +1 -1
- package/transpiled/index.d.ts +3 -3
- package/transpiled/index.js +4 -9
- package/transpiled/index.js.map +1 -1
- package/ui/dist/_app/env.js +1 -0
- package/ui/dist/_app/immutable/assets/0.BGFdDICE.css +2 -0
- package/ui/dist/_app/immutable/assets/ui.BghF56l_.css +1 -0
- package/ui/dist/_app/immutable/chunks/Bjy-W4x2.js +81 -0
- package/ui/dist/_app/immutable/chunks/BkLAzDsj.js +1 -0
- package/ui/dist/_app/immutable/chunks/C_aaOW6e.js +1 -0
- package/ui/dist/_app/immutable/chunks/CcD_ISxM.js +3 -0
- package/ui/dist/_app/immutable/chunks/Ccdp29n0.js +6 -0
- package/ui/dist/_app/immutable/chunks/Dw75U_Lh.js +50 -0
- package/ui/dist/_app/immutable/chunks/sXOccAdQ.js +8 -0
- package/ui/dist/_app/immutable/chunks/xihTtKlq.js +1 -0
- package/ui/dist/_app/immutable/entry/app.DgOXi1S4.js +2 -0
- package/ui/dist/_app/immutable/entry/start.C5YMpV87.js +1 -0
- package/ui/dist/_app/immutable/nodes/0.BGAo0V8q.js +1 -0
- package/ui/dist/_app/immutable/nodes/1.DYGSbNvw.js +1 -0
- package/ui/dist/_app/immutable/nodes/2.nR_WPY04.js +1 -0
- package/ui/dist/_app/immutable/nodes/3.p9Hd9gcE.js +1 -0
- package/ui/dist/_app/immutable/nodes/4.Chf5nqMR.js +1 -0
- package/ui/dist/_app/version.json +1 -0
- package/ui/dist/apple-touch-icon.png +0 -0
- package/ui/dist/favicon-96x96.png +0 -0
- package/ui/dist/favicon.ico +0 -0
- package/ui/dist/index.html +57 -0
- package/ui/dist/robots.txt +3 -0
- package/notes/consistency.md +0 -69
- package/schemas/annotation.cos.yaml +0 -1
- package/schemas/manifest.cos.yaml +0 -2
- package/source/Aspect.test.ts +0 -15
- package/source/Aspect.ts +0 -23
- package/source/Factory.ts +0 -12
- package/source/configuration.test.ts +0 -90
- package/source/configuration.ts +0 -59
- package/source/deployment.test.ts +0 -21
- package/source/deployment.ts +0 -86
- package/source/index.ts +0 -3
- package/source/manifest.test.ts +0 -15
- package/source/manifest.ts +0 -15
- package/source/schemas.ts +0 -9
- package/transpiled/Aspect.test.d.ts +0 -1
- package/transpiled/Aspect.test.js +0 -15
- package/transpiled/Aspect.test.js.map +0 -1
- package/transpiled/configuration.test.d.ts +0 -1
- package/transpiled/configuration.test.js +0 -64
- package/transpiled/configuration.test.js.map +0 -1
- package/transpiled/deployment.d.ts +0 -8
- package/transpiled/deployment.js +0 -88
- package/transpiled/deployment.js.map +0 -1
- package/transpiled/deployment.test.d.ts +0 -1
- package/transpiled/deployment.test.js +0 -18
- package/transpiled/deployment.test.js.map +0 -1
- package/transpiled/manifest.d.ts +0 -6
- package/transpiled/manifest.js +0 -35
- package/transpiled/manifest.js.map +0 -1
- package/transpiled/manifest.test.d.ts +0 -1
- package/transpiled/manifest.test.js +0 -14
- package/transpiled/manifest.test.js.map +0 -1
- package/transpiled/schemas.d.ts +0 -3
- package/transpiled/schemas.js +0 -33
- package/transpiled/schemas.js.map +0 -1
- package/transpiled/tsconfig.tsbuildinfo +0 -1
- package/tsconfig.json +0 -9
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
namespace: configuration
|
|
2
|
+
name: values
|
|
3
|
+
|
|
4
|
+
# One document per configuration created. Documents are immutable: a change is a new
|
|
5
|
+
# document, and the latest one for a component and an epoch is the last created.
|
|
6
|
+
# What every component's epoch, schema and defaults are, the service is told on
|
|
7
|
+
# deployment (`TOA_CONFIGURATION_VALUES`). A created object is published as the
|
|
8
|
+
# prototype's `created` event.
|
|
9
|
+
|
|
10
|
+
entity:
|
|
11
|
+
properties:
|
|
12
|
+
component:
|
|
13
|
+
type: string
|
|
14
|
+
epoch:
|
|
15
|
+
type: string
|
|
16
|
+
configuration:
|
|
17
|
+
type: object
|
|
18
|
+
originator:
|
|
19
|
+
type: string
|
|
20
|
+
required:
|
|
21
|
+
- component
|
|
22
|
+
- epoch
|
|
23
|
+
- configuration
|
|
24
|
+
- originator
|
|
25
|
+
|
|
26
|
+
operations:
|
|
27
|
+
# the latest configuration of a component: created, else deployed defaults, else none
|
|
28
|
+
get:
|
|
29
|
+
query: false
|
|
30
|
+
input:
|
|
31
|
+
type: object
|
|
32
|
+
properties:
|
|
33
|
+
component:
|
|
34
|
+
type: string
|
|
35
|
+
epoch:
|
|
36
|
+
type: string
|
|
37
|
+
required:
|
|
38
|
+
- component
|
|
39
|
+
# the value and the schema it is checked against, so a caller can show and check it
|
|
40
|
+
output:
|
|
41
|
+
type: object
|
|
42
|
+
nullable: true
|
|
43
|
+
properties:
|
|
44
|
+
configuration:
|
|
45
|
+
type: object
|
|
46
|
+
schema:
|
|
47
|
+
type: object
|
|
48
|
+
epoch:
|
|
49
|
+
type: string
|
|
50
|
+
required:
|
|
51
|
+
- configuration
|
|
52
|
+
- epoch
|
|
53
|
+
# the same for many at once, as the aspects of one process ask
|
|
54
|
+
fetch:
|
|
55
|
+
query: false
|
|
56
|
+
input:
|
|
57
|
+
type: array
|
|
58
|
+
items:
|
|
59
|
+
type: object
|
|
60
|
+
properties:
|
|
61
|
+
component:
|
|
62
|
+
type: string
|
|
63
|
+
epoch:
|
|
64
|
+
type: string
|
|
65
|
+
required:
|
|
66
|
+
- component
|
|
67
|
+
- epoch
|
|
68
|
+
output:
|
|
69
|
+
type: array
|
|
70
|
+
items:
|
|
71
|
+
type: object
|
|
72
|
+
properties:
|
|
73
|
+
component:
|
|
74
|
+
type: string
|
|
75
|
+
epoch:
|
|
76
|
+
type: string
|
|
77
|
+
configuration:
|
|
78
|
+
type: object
|
|
79
|
+
nullable: true
|
|
80
|
+
created:
|
|
81
|
+
type: integer
|
|
82
|
+
required:
|
|
83
|
+
- component
|
|
84
|
+
- epoch
|
|
85
|
+
- configuration
|
|
86
|
+
- created
|
|
87
|
+
# every component's configuration for its deployed epoch, by component name
|
|
88
|
+
list:
|
|
89
|
+
query: false
|
|
90
|
+
output:
|
|
91
|
+
type: array
|
|
92
|
+
items:
|
|
93
|
+
type: object
|
|
94
|
+
properties:
|
|
95
|
+
component:
|
|
96
|
+
type: string
|
|
97
|
+
epoch:
|
|
98
|
+
type: string
|
|
99
|
+
schema:
|
|
100
|
+
type: object
|
|
101
|
+
configuration:
|
|
102
|
+
type: object
|
|
103
|
+
required:
|
|
104
|
+
- component
|
|
105
|
+
- epoch
|
|
106
|
+
- schema
|
|
107
|
+
- configuration
|
|
108
|
+
create:
|
|
109
|
+
query: false
|
|
110
|
+
input:
|
|
111
|
+
type: object
|
|
112
|
+
properties:
|
|
113
|
+
component:
|
|
114
|
+
type: string
|
|
115
|
+
configuration:
|
|
116
|
+
type: object
|
|
117
|
+
originator:
|
|
118
|
+
type: object
|
|
119
|
+
properties:
|
|
120
|
+
id:
|
|
121
|
+
type: string
|
|
122
|
+
required:
|
|
123
|
+
- id
|
|
124
|
+
required:
|
|
125
|
+
- component
|
|
126
|
+
- configuration
|
|
127
|
+
- originator
|
|
128
|
+
errors:
|
|
129
|
+
- UNKNOWN_COMPONENT
|
|
130
|
+
- INVALID_CONFIGURATION
|
|
131
|
+
|
|
132
|
+
exposition:
|
|
133
|
+
isolated: true
|
|
134
|
+
/:
|
|
135
|
+
GET:
|
|
136
|
+
io:output: true
|
|
137
|
+
auth:role: system:configuration:get
|
|
138
|
+
endpoint: list
|
|
139
|
+
/:component:
|
|
140
|
+
map:segments:
|
|
141
|
+
component: component
|
|
142
|
+
GET:
|
|
143
|
+
io:output: true
|
|
144
|
+
auth:role: system:configuration:get
|
|
145
|
+
endpoint: get
|
|
146
|
+
POST:
|
|
147
|
+
io:output: [id, epoch]
|
|
148
|
+
auth:rule:
|
|
149
|
+
role: system:configuration:create
|
|
150
|
+
delegate: originator
|
|
151
|
+
endpoint: create
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as schemas from '@toa.io/schemas';
|
|
2
|
+
import { assertSecrets } from '@toa.io/definitions/extensions.configuration';
|
|
3
|
+
import { entry } from './lib/map.js';
|
|
4
|
+
export async function transition(input, object) {
|
|
5
|
+
const known = entry(input.component);
|
|
6
|
+
if (known === undefined)
|
|
7
|
+
return new UnknownComponentError(input.component);
|
|
8
|
+
const configuration = structuredClone(input.configuration);
|
|
9
|
+
const schema = schemas.schema(known.schema);
|
|
10
|
+
try {
|
|
11
|
+
schema.validate(configuration);
|
|
12
|
+
assertSecrets(known.schema, configuration);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
return new InvalidConfigurationError(error.message);
|
|
16
|
+
}
|
|
17
|
+
object.component = input.component;
|
|
18
|
+
object.epoch = known.epoch;
|
|
19
|
+
object.configuration = configuration;
|
|
20
|
+
object.originator = input.originator.id;
|
|
21
|
+
return object;
|
|
22
|
+
}
|
|
23
|
+
class UnknownComponentError extends Error {
|
|
24
|
+
code = 'UNKNOWN_COMPONENT';
|
|
25
|
+
constructor(component) {
|
|
26
|
+
super(`Component '${component}' is not configured`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
class InvalidConfigurationError extends Error {
|
|
30
|
+
code = 'INVALID_CONFIGURATION';
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc291cmNlL2NyZWF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGlCQUFpQixDQUFBO0FBQzFDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQTtBQUM1RSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBR3BDLE1BQU0sQ0FBQyxLQUFLLFVBQVUsVUFBVSxDQUFDLEtBQVksRUFBRSxNQUFjO0lBQzNELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUE7SUFFcEMsSUFBSSxLQUFLLEtBQUssU0FBUztRQUFFLE9BQU8sSUFBSSxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUE7SUFFMUUsTUFBTSxhQUFhLEdBQUcsZUFBZSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQTtJQUUxRCxNQUFNLE1BQU0sR0FBZ0IsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7SUFFeEQsSUFBSSxDQUFDO1FBQ0gsTUFBTSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUM5QixhQUFhLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQTtJQUM1QyxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sSUFBSSx5QkFBeUIsQ0FBRSxLQUFlLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDaEUsQ0FBQztJQUVELE1BQU0sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQTtJQUNsQyxNQUFNLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUE7SUFDMUIsTUFBTSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUE7SUFDcEMsTUFBTSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQTtJQUV2QyxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUM7QUFFRCxNQUFNLHFCQUFzQixTQUFRLEtBQUs7SUFDdkIsSUFBSSxHQUFHLG1CQUFtQixDQUFBO0lBRTFDLFlBQW1CLFNBQWlCO1FBQ2xDLEtBQUssQ0FBQyxjQUFjLFNBQVMscUJBQXFCLENBQUMsQ0FBQTtJQUNyRCxDQUFDO0NBQ0Y7QUFFRCxNQUFNLHlCQUEwQixTQUFRLEtBQUs7SUFDM0IsSUFBSSxHQUFHLHVCQUF1QixDQUFBO0NBQy9DIn0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { resolve } from './lib/resolve.js';
|
|
2
|
+
export async function computation(input, context) {
|
|
3
|
+
return await Promise.all(input.map(async ({ component, epoch }) => {
|
|
4
|
+
const value = await resolve(context, component, epoch);
|
|
5
|
+
return {
|
|
6
|
+
component,
|
|
7
|
+
epoch,
|
|
8
|
+
configuration: value === null ? null : value.configuration,
|
|
9
|
+
created: value === null ? 0 : value.created
|
|
10
|
+
};
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmV0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zb3VyY2UvZmV0Y2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxrQkFBa0IsQ0FBQTtBQUV4RCxNQUFNLENBQUMsS0FBSyxVQUFVLFdBQVcsQ0FBQyxLQUFhLEVBQUUsT0FBZ0I7SUFDL0QsT0FBTyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ3RCLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUU7UUFDdkMsTUFBTSxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQTtRQUV0RCxPQUFPO1lBQ0wsU0FBUztZQUNULEtBQUs7WUFDTCxhQUFhLEVBQUUsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsYUFBYTtZQUMxRCxPQUFPLEVBQUUsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTztTQUM1QyxDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQ0gsQ0FBQTtBQUNILENBQUMifQ==
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { entry } from './lib/map.js';
|
|
2
|
+
import { resolve } from './lib/resolve.js';
|
|
3
|
+
/**
|
|
4
|
+
* The latest configuration of a component, with the schema it is checked against. The
|
|
5
|
+
* schema is the deployment's, so an epoch the deployment does not know has none — the
|
|
6
|
+
* value is still what was stored for it.
|
|
7
|
+
*/
|
|
8
|
+
export async function computation(input, context) {
|
|
9
|
+
const value = await resolve(context, input.component, input.epoch);
|
|
10
|
+
if (value === null)
|
|
11
|
+
return null;
|
|
12
|
+
const known = entry(input.component);
|
|
13
|
+
return {
|
|
14
|
+
configuration: value.configuration,
|
|
15
|
+
schema: known?.schema,
|
|
16
|
+
epoch: input.epoch ?? known.epoch
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc291cmNlL2dldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQ3BDLE9BQU8sRUFBRSxPQUFPLEVBQWdCLE1BQU0sa0JBQWtCLENBQUE7QUFFeEQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVyxDQUFDLEtBQVksRUFBRSxPQUFnQjtJQUM5RCxNQUFNLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFbEUsSUFBSSxLQUFLLEtBQUssSUFBSTtRQUFFLE9BQU8sSUFBSSxDQUFBO0lBRS9CLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUE7SUFFcEMsT0FBTztRQUNMLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYTtRQUNsQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU07UUFDckIsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLElBQUksS0FBTSxDQUFDLEtBQUs7S0FDbkMsQ0FBQTtBQUNILENBQUMifQ==
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { environment } from '@toa.io/generic';
|
|
2
|
+
/** What the deployment told the service about every configured component. */
|
|
3
|
+
export function entry(component) {
|
|
4
|
+
return read()[component];
|
|
5
|
+
}
|
|
6
|
+
/** The configured components, by name. */
|
|
7
|
+
export function components() {
|
|
8
|
+
return Object.keys(read()).sort();
|
|
9
|
+
}
|
|
10
|
+
function read() {
|
|
11
|
+
const source = environment.get(VARIABLE) ?? '{}';
|
|
12
|
+
// read again once the variable changes, as it does between scenarios of one process
|
|
13
|
+
if (source !== parsed) {
|
|
14
|
+
values = JSON.parse(source);
|
|
15
|
+
parsed = source;
|
|
16
|
+
}
|
|
17
|
+
return values;
|
|
18
|
+
}
|
|
19
|
+
let parsed = null;
|
|
20
|
+
let values = {};
|
|
21
|
+
export const VARIABLE = 'TOA_CONFIGURATION_VALUES';
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc291cmNlL2xpYi9tYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBRTdDLDZFQUE2RTtBQUM3RSxNQUFNLFVBQVUsS0FBSyxDQUFDLFNBQWlCO0lBQ3JDLE9BQU8sSUFBSSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDMUIsQ0FBQztBQUVELDBDQUEwQztBQUMxQyxNQUFNLFVBQVUsVUFBVTtJQUN4QixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtBQUNuQyxDQUFDO0FBRUQsU0FBUyxJQUFJO0lBQ1gsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLENBQUE7SUFFaEQsb0ZBQW9GO0lBQ3BGLElBQUksTUFBTSxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQ3RCLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBVyxDQUFBO1FBQ3JDLE1BQU0sR0FBRyxNQUFNLENBQUE7SUFDakIsQ0FBQztJQUVELE9BQU8sTUFBTSxDQUFBO0FBQ2YsQ0FBQztBQUVELElBQUksTUFBTSxHQUFrQixJQUFJLENBQUE7QUFDaEMsSUFBSSxNQUFNLEdBQVcsRUFBRSxDQUFBO0FBRXZCLE1BQU0sQ0FBQyxNQUFNLFFBQVEsR0FBRywwQkFBMEIsQ0FBQSJ9
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { entry } from './map.js';
|
|
2
|
+
/**
|
|
3
|
+
* The latest configuration created for the component and the epoch; the deployed
|
|
4
|
+
* defaults when none was; `null` when the epoch is not the one deployed.
|
|
5
|
+
*/
|
|
6
|
+
export async function resolve(context, component, epoch) {
|
|
7
|
+
const known = entry(component);
|
|
8
|
+
epoch ??= known?.epoch;
|
|
9
|
+
if (epoch === undefined)
|
|
10
|
+
return null;
|
|
11
|
+
// one query per pair, so that a component's latest is never behind another's newer ones
|
|
12
|
+
const query = {
|
|
13
|
+
criteria: `component=="${component}";epoch=="${epoch}"`,
|
|
14
|
+
sort: ['CREATED:desc'],
|
|
15
|
+
limit: 1
|
|
16
|
+
};
|
|
17
|
+
const objects = await context.local.enumerate({ query });
|
|
18
|
+
if (objects.length > 0)
|
|
19
|
+
return { configuration: objects[0].configuration, created: objects[0].CREATED };
|
|
20
|
+
if (known !== undefined && known.epoch === epoch)
|
|
21
|
+
return { configuration: known.defaults ?? {}, created: 0 };
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb2x2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9saWIvcmVzb2x2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBRWhDOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsT0FBTyxDQUMzQixPQUFnQixFQUNoQixTQUFpQixFQUNqQixLQUFjO0lBRWQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBRTlCLEtBQUssS0FBSyxLQUFLLEVBQUUsS0FBSyxDQUFBO0lBRXRCLElBQUksS0FBSyxLQUFLLFNBQVM7UUFBRSxPQUFPLElBQUksQ0FBQTtJQUVwQyx3RkFBd0Y7SUFDeEYsTUFBTSxLQUFLLEdBQVU7UUFDbkIsUUFBUSxFQUFFLGVBQWUsU0FBUyxhQUFhLEtBQUssR0FBRztRQUN2RCxJQUFJLEVBQUUsQ0FBQyxjQUFjLENBQUM7UUFDdEIsS0FBSyxFQUFFLENBQUM7S0FDVCxDQUFBO0lBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUE7SUFFeEQsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDcEIsT0FBTyxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUE7SUFFakYsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssQ0FBQyxLQUFLLEtBQUssS0FBSztRQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQTtJQUU1RCxPQUFPLElBQUksQ0FBQTtBQUNiLENBQUMifQ==
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { components, entry } from './lib/map.js';
|
|
2
|
+
import { resolve } from './lib/resolve.js';
|
|
3
|
+
/** The configuration of every component for its deployed epoch, by component name. */
|
|
4
|
+
export async function computation(_, context) {
|
|
5
|
+
return await Promise.all(components().map(async (component) => {
|
|
6
|
+
const { epoch, schema } = entry(component);
|
|
7
|
+
const value = await resolve(context, component, epoch);
|
|
8
|
+
return { component, epoch, schema, configuration: value.configuration };
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NvdXJjZS9saXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQ2hELE9BQU8sRUFBRSxPQUFPLEVBQWdCLE1BQU0sa0JBQWtCLENBQUE7QUFFeEQsc0ZBQXNGO0FBQ3RGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVyxDQUFDLENBQU8sRUFBRSxPQUFnQjtJQUN6RCxPQUFPLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDdEIsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRTtRQUNuQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUUsQ0FBQTtRQUMzQyxNQUFNLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFBO1FBRXRELE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxhQUFhLEVBQUUsS0FBTSxDQUFDLGFBQWEsRUFBRSxDQUFBO0lBQzFFLENBQUMsQ0FBQyxDQUNILENBQUE7QUFDSCxDQUFDIn0=
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as schemas from '@toa.io/schemas'
|
|
2
|
+
import { assertSecrets } from '@toa.io/definitions/extensions.configuration'
|
|
3
|
+
import { entry } from './lib/map.ts'
|
|
4
|
+
import type { Schema } from '@toa.io/schemas'
|
|
5
|
+
|
|
6
|
+
export async function transition(input: Input, object: Entity): Promise<Entity | Error> {
|
|
7
|
+
const known = entry(input.component)
|
|
8
|
+
|
|
9
|
+
if (known === undefined) return new UnknownComponentError(input.component)
|
|
10
|
+
|
|
11
|
+
const configuration = structuredClone(input.configuration)
|
|
12
|
+
|
|
13
|
+
const schema: Schema<any> = schemas.schema(known.schema)
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
schema.validate(configuration)
|
|
17
|
+
assertSecrets(known.schema, configuration)
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return new InvalidConfigurationError((error as Error).message)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
object.component = input.component
|
|
23
|
+
object.epoch = known.epoch
|
|
24
|
+
object.configuration = configuration
|
|
25
|
+
object.originator = input.originator.id
|
|
26
|
+
|
|
27
|
+
return object
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class UnknownComponentError extends Error {
|
|
31
|
+
public readonly code = 'UNKNOWN_COMPONENT'
|
|
32
|
+
|
|
33
|
+
public constructor(component: string) {
|
|
34
|
+
super(`Component '${component}' is not configured`)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class InvalidConfigurationError extends Error {
|
|
39
|
+
public readonly code = 'INVALID_CONFIGURATION'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface Input {
|
|
43
|
+
component: string
|
|
44
|
+
configuration: object
|
|
45
|
+
originator: {
|
|
46
|
+
id: string
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface Entity {
|
|
51
|
+
id: string
|
|
52
|
+
component: string
|
|
53
|
+
epoch: string
|
|
54
|
+
configuration: object
|
|
55
|
+
originator: string
|
|
56
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { resolve, type Context } from './lib/resolve.ts'
|
|
2
|
+
|
|
3
|
+
export async function computation(input: Pair[], context: Context): Promise<Fetched[]> {
|
|
4
|
+
return await Promise.all(
|
|
5
|
+
input.map(async ({ component, epoch }) => {
|
|
6
|
+
const value = await resolve(context, component, epoch)
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
component,
|
|
10
|
+
epoch,
|
|
11
|
+
configuration: value === null ? null : value.configuration,
|
|
12
|
+
created: value === null ? 0 : value.created
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface Pair {
|
|
19
|
+
component: string
|
|
20
|
+
epoch: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Fetched extends Pair {
|
|
24
|
+
configuration: object | null
|
|
25
|
+
created: number
|
|
26
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { entry } from './lib/map.ts'
|
|
2
|
+
import { resolve, type Context } from './lib/resolve.ts'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The latest configuration of a component, with the schema it is checked against. The
|
|
6
|
+
* schema is the deployment's, so an epoch the deployment does not know has none — the
|
|
7
|
+
* value is still what was stored for it.
|
|
8
|
+
*/
|
|
9
|
+
export async function computation(input: Input, context: Context): Promise<Item | null> {
|
|
10
|
+
const value = await resolve(context, input.component, input.epoch)
|
|
11
|
+
|
|
12
|
+
if (value === null) return null
|
|
13
|
+
|
|
14
|
+
const known = entry(input.component)
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
configuration: value.configuration,
|
|
18
|
+
schema: known?.schema,
|
|
19
|
+
epoch: input.epoch ?? known!.epoch
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Input {
|
|
24
|
+
component: string
|
|
25
|
+
epoch?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface Item {
|
|
29
|
+
configuration: object
|
|
30
|
+
schema?: object
|
|
31
|
+
epoch: string
|
|
32
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { environment } from '@toa.io/generic'
|
|
2
|
+
|
|
3
|
+
/** What the deployment told the service about every configured component. */
|
|
4
|
+
export function entry(component: string): Entry | undefined {
|
|
5
|
+
return read()[component]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** The configured components, by name. */
|
|
9
|
+
export function components(): string[] {
|
|
10
|
+
return Object.keys(read()).sort()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function read(): Values {
|
|
14
|
+
const source = environment.get(VARIABLE) ?? '{}'
|
|
15
|
+
|
|
16
|
+
// read again once the variable changes, as it does between scenarios of one process
|
|
17
|
+
if (source !== parsed) {
|
|
18
|
+
values = JSON.parse(source) as Values
|
|
19
|
+
parsed = source
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return values
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let parsed: string | null = null
|
|
26
|
+
let values: Values = {}
|
|
27
|
+
|
|
28
|
+
export const VARIABLE = 'TOA_CONFIGURATION_VALUES'
|
|
29
|
+
|
|
30
|
+
export interface Entry {
|
|
31
|
+
epoch: string
|
|
32
|
+
schema: object
|
|
33
|
+
defaults?: object
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type Values = Record<string, Entry>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { entry } from './map.ts'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The latest configuration created for the component and the epoch; the deployed
|
|
5
|
+
* defaults when none was; `null` when the epoch is not the one deployed.
|
|
6
|
+
*/
|
|
7
|
+
export async function resolve(
|
|
8
|
+
context: Context,
|
|
9
|
+
component: string,
|
|
10
|
+
epoch?: string
|
|
11
|
+
): Promise<Value | null> {
|
|
12
|
+
const known = entry(component)
|
|
13
|
+
|
|
14
|
+
epoch ??= known?.epoch
|
|
15
|
+
|
|
16
|
+
if (epoch === undefined) return null
|
|
17
|
+
|
|
18
|
+
// one query per pair, so that a component's latest is never behind another's newer ones
|
|
19
|
+
const query: Query = {
|
|
20
|
+
criteria: `component=="${component}";epoch=="${epoch}"`,
|
|
21
|
+
sort: ['CREATED:desc'],
|
|
22
|
+
limit: 1
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const objects = await context.local.enumerate({ query })
|
|
26
|
+
|
|
27
|
+
if (objects.length > 0)
|
|
28
|
+
return { configuration: objects[0].configuration, created: objects[0].CREATED }
|
|
29
|
+
|
|
30
|
+
if (known !== undefined && known.epoch === epoch)
|
|
31
|
+
return { configuration: known.defaults ?? {}, created: 0 }
|
|
32
|
+
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A configuration and when it was created; `0` for the deployed defaults. */
|
|
37
|
+
export interface Value {
|
|
38
|
+
configuration: object
|
|
39
|
+
created: number
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface Context {
|
|
43
|
+
local: {
|
|
44
|
+
enumerate: (request: { query: Query }) => Promise<Stored[]>
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface Query {
|
|
49
|
+
criteria: string
|
|
50
|
+
sort: string[]
|
|
51
|
+
limit: number
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface Stored {
|
|
55
|
+
configuration: object
|
|
56
|
+
CREATED: number
|
|
57
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { components, entry } from './lib/map.ts'
|
|
2
|
+
import { resolve, type Context } from './lib/resolve.ts'
|
|
3
|
+
|
|
4
|
+
/** The configuration of every component for its deployed epoch, by component name. */
|
|
5
|
+
export async function computation(_: null, context: Context): Promise<Item[]> {
|
|
6
|
+
return await Promise.all(
|
|
7
|
+
components().map(async (component) => {
|
|
8
|
+
const { epoch, schema } = entry(component)!
|
|
9
|
+
const value = await resolve(context, component, epoch)
|
|
10
|
+
|
|
11
|
+
return { component, epoch, schema, configuration: value!.configuration }
|
|
12
|
+
})
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface Item {
|
|
17
|
+
component: string
|
|
18
|
+
epoch: string
|
|
19
|
+
schema: object
|
|
20
|
+
configuration: object
|
|
21
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Written by `toa types`. Every run rewrites it.
|
|
2
|
+
// What a manifest does not state belongs in a file of your own.
|
|
3
|
+
|
|
4
|
+
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
|
+
import type { Readable } from 'node:stream'
|
|
6
|
+
|
|
7
|
+
export interface Entity {
|
|
8
|
+
component: string
|
|
9
|
+
epoch: string
|
|
10
|
+
configuration: Record<string, unknown>
|
|
11
|
+
originator: string
|
|
12
|
+
id: string
|
|
13
|
+
VERSION: number
|
|
14
|
+
CREATED: number
|
|
15
|
+
UPDATED: number
|
|
16
|
+
DELETED: number | null
|
|
17
|
+
REGION: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type GetInput = {
|
|
21
|
+
component: string
|
|
22
|
+
epoch?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type GetOutput = {
|
|
26
|
+
configuration: Record<string, unknown>
|
|
27
|
+
schema?: Record<string, unknown>
|
|
28
|
+
epoch: string
|
|
29
|
+
} | null
|
|
30
|
+
|
|
31
|
+
export type FetchInput = Array<{
|
|
32
|
+
component: string
|
|
33
|
+
epoch: string
|
|
34
|
+
}>
|
|
35
|
+
|
|
36
|
+
export type FetchOutput = Array<{
|
|
37
|
+
component: string
|
|
38
|
+
epoch: string
|
|
39
|
+
configuration: Record<string, unknown> | null
|
|
40
|
+
created: number
|
|
41
|
+
}>
|
|
42
|
+
|
|
43
|
+
export type ListOutput = Array<{
|
|
44
|
+
component: string
|
|
45
|
+
epoch: string
|
|
46
|
+
schema: Record<string, unknown>
|
|
47
|
+
configuration: Record<string, unknown>
|
|
48
|
+
}>
|
|
49
|
+
|
|
50
|
+
export type CreateInput = {
|
|
51
|
+
component: string
|
|
52
|
+
configuration: Record<string, unknown>
|
|
53
|
+
originator: {
|
|
54
|
+
id: string
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface Component {
|
|
59
|
+
get: (request: { input: GetInput, task?: boolean }, options?: Options) => Promise<GetOutput>
|
|
60
|
+
fetch: (request: { input: FetchInput, task?: boolean }, options?: Options) => Promise<FetchOutput>
|
|
61
|
+
list: (request: { input?: null, task?: boolean }, options?: Options) => Promise<ListOutput>
|
|
62
|
+
create: (request: { input: CreateInput, task?: boolean }, options?: Options) => Promise<unknown | RemoteError<"UNKNOWN_COMPONENT" | "INVALID_CONFIGURATION">>
|
|
63
|
+
assign: (request: { input?: null, query?: Query<Entity>, task?: boolean }, options?: Options) => Promise<Entity>
|
|
64
|
+
ensure: (request: { input?: null, query?: Query<Entity>, task?: boolean }, options?: Options) => Promise<Entity>
|
|
65
|
+
enumerate: (request: { input?: null, query?: Query<Entity>, task?: boolean }, options?: Options) => Promise<Entity[]>
|
|
66
|
+
observe: (request: { input?: null, query?: Query<Entity>, task?: boolean }, options?: Options) => Promise<Entity | null>
|
|
67
|
+
stream: (request: { input?: null, query?: Query<Entity>, task?: boolean }, options?: Options) => Promise<Readable>
|
|
68
|
+
terminate: (request: { input?: null, query?: Query<Entity>, task?: boolean }, options?: Options) => Promise<Entity>
|
|
69
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.configuration",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.310",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Toa Configuration",
|
|
5
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
7
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -16,17 +17,27 @@
|
|
|
16
17
|
"publishConfig": {
|
|
17
18
|
"access": "public"
|
|
18
19
|
},
|
|
20
|
+
"files": [
|
|
21
|
+
"transpiled",
|
|
22
|
+
"components",
|
|
23
|
+
"ui/dist",
|
|
24
|
+
"readme.md",
|
|
25
|
+
"!**/tsconfig.tsbuildinfo",
|
|
26
|
+
"!**/*.test.*",
|
|
27
|
+
"!**/.env*"
|
|
28
|
+
],
|
|
19
29
|
"scripts": {
|
|
20
|
-
"transpile": "tsc"
|
|
30
|
+
"transpile": "tsc && tsc -p ./components/configuration.values",
|
|
31
|
+
"build:ui": "npm --prefix ui ci && npm --prefix ui run build",
|
|
32
|
+
"prepack": "npm run build:ui",
|
|
33
|
+
"features": "TSX_TSCONFIG_PATH=features/steps/tsconfig.json NODE_OPTIONS=--import=tsx cucumber-js"
|
|
21
34
|
},
|
|
22
|
-
"
|
|
23
|
-
"preset": "ts-jest",
|
|
24
|
-
"testEnvironment": "node"
|
|
25
|
-
},
|
|
26
|
-
"gitHead": "91839a488176853a0731f49abc70dc7103ed7cca",
|
|
35
|
+
"gitHead": "d952c57f77279729e26d52d50c6df47138ad0a4f",
|
|
27
36
|
"dependencies": {
|
|
28
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
29
|
-
"@toa.io/
|
|
30
|
-
"@toa.io/
|
|
37
|
+
"@toa.io/core": "1.0.0-alpha.310",
|
|
38
|
+
"@toa.io/definitions": "1.0.0-alpha.310",
|
|
39
|
+
"@toa.io/generic": "1.0.0-alpha.310",
|
|
40
|
+
"@toa.io/schemas": "1.0.0-alpha.310",
|
|
41
|
+
"openspan": "1.0.0-alpha.305"
|
|
31
42
|
}
|
|
32
43
|
}
|