@toa.io/extensions.configuration 1.0.0-alpha.291 → 1.0.0-alpha.292
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 +7 -0
- package/package.json +6 -5
- package/source/Aspect.test.ts +1 -1
- package/source/Aspect.ts +2 -2
- package/source/Client.test.ts +1 -1
- package/source/Client.ts +1 -1
- package/source/Composition.ts +1 -1
- package/source/Factory.ts +1 -1
- package/source/UI.ts +1 -1
- package/source/configuration.test.ts +1 -1
- package/source/configuration.ts +2 -2
- package/source/epoch.test.ts +1 -1
- package/source/index.ts +0 -5
- package/transpiled/Aspect.d.ts +1 -1
- package/transpiled/Aspect.js +1 -1
- package/transpiled/Aspect.js.map +1 -1
- package/transpiled/Client.js +1 -1
- package/transpiled/Client.js.map +1 -1
- package/transpiled/Composition.js +1 -1
- package/transpiled/Composition.js.map +1 -1
- package/transpiled/Factory.d.ts +1 -1
- package/transpiled/UI.js +1 -1
- package/transpiled/UI.js.map +1 -1
- package/transpiled/configuration.d.ts +1 -1
- package/transpiled/configuration.js +1 -1
- package/transpiled/configuration.js.map +1 -1
- package/transpiled/index.d.ts +0 -3
- package/transpiled/index.js +0 -4
- package/transpiled/index.js.map +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/ui/dist/_app/immutable/chunks/{CNZAv2Es.js → -d-dxcbq.js} +1 -1
- package/ui/dist/_app/immutable/chunks/{BV5cDXGB.js → 64H_hMtE.js} +1 -1
- package/ui/dist/_app/immutable/chunks/{vl8APhvf.js → BeorVtKF.js} +2 -2
- package/ui/dist/_app/immutable/chunks/{3Kbn_1Vv.js → C1Pl1PSE.js} +1 -1
- package/ui/dist/_app/immutable/chunks/{B_CH3nFk.js → DzmF9ykx.js} +1 -1
- package/ui/dist/_app/immutable/entry/{app.CK-db-gz.js → app.D5YrjA4l.js} +2 -2
- package/ui/dist/_app/immutable/entry/start.CKkVSyXd.js +1 -0
- package/ui/dist/_app/immutable/nodes/{0.vPwVABRs.js → 0.Cm3Z3YNE.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{1.DS63PME5.js → 1.e2aDXaPj.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{2.KRpWYBfz.js → 2.Blh7Ex_K.js} +1 -1
- package/ui/dist/_app/immutable/nodes/3.61NbGuZc.js +1 -0
- package/ui/dist/_app/immutable/nodes/{4.D8lluH3u.js → 4.B6OdRyVa.js} +1 -1
- package/ui/dist/_app/version.json +1 -1
- package/ui/dist/index.html +10 -10
- package/schemas/annotation.cos.yaml +0 -29
- package/schemas/manifest.cos.yaml +0 -9
- package/source/const.ts +0 -30
- package/source/context.ts +0 -13
- package/source/deployment.test.ts +0 -112
- package/source/deployment.ts +0 -160
- package/source/epoch.ts +0 -22
- package/source/manifest.test.ts +0 -24
- package/source/manifest.ts +0 -13
- package/source/schemas.ts +0 -9
- package/transpiled/const.d.ts +0 -18
- package/transpiled/const.js +0 -22
- package/transpiled/const.js.map +0 -1
- package/transpiled/context.d.ts +0 -4
- package/transpiled/context.js +0 -9
- package/transpiled/context.js.map +0 -1
- package/transpiled/deployment.d.ts +0 -17
- package/transpiled/deployment.js +0 -107
- package/transpiled/deployment.js.map +0 -1
- package/transpiled/epoch.d.ts +0 -2
- package/transpiled/epoch.js +0 -19
- package/transpiled/epoch.js.map +0 -1
- package/transpiled/manifest.d.ts +0 -6
- package/transpiled/manifest.js +0 -6
- package/transpiled/manifest.js.map +0 -1
- package/transpiled/schemas.d.ts +0 -3
- package/transpiled/schemas.js +0 -7
- package/transpiled/schemas.js.map +0 -1
- package/ui/dist/_app/immutable/entry/start.Bs7xr9Ne.js +0 -1
- package/ui/dist/_app/immutable/nodes/3.DCxORePS.js +0 -1
package/source/deployment.ts
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs'
|
|
2
|
-
import assert from 'node:assert'
|
|
3
|
-
import {
|
|
4
|
-
type Dependency,
|
|
5
|
-
type Resources,
|
|
6
|
-
type Service,
|
|
7
|
-
type Variable,
|
|
8
|
-
type Variables
|
|
9
|
-
} from '@toa.io/operations'
|
|
10
|
-
import { add } from '@toa.io/generic'
|
|
11
|
-
import { components } from './Composition.js'
|
|
12
|
-
import { EVENT, PREFIX, SECRET_RX, UI_PATH, UI_PORT, VALUES } from './const.js'
|
|
13
|
-
import { epoch } from './epoch.js'
|
|
14
|
-
import * as validators from './schemas.js'
|
|
15
|
-
import type { Manifest } from './manifest.js'
|
|
16
|
-
import type { context } from '@toa.io/norm'
|
|
17
|
-
|
|
18
|
-
/** Where Toa's release publishes this service's image. An application takes it
|
|
19
|
-
* instead of building one when its context says `registry.services: published`. */
|
|
20
|
-
export const image = 'ghcr.io/toa-io/extension-configuration-values'
|
|
21
|
-
|
|
22
|
-
export function deployment(
|
|
23
|
-
instances: Instance[],
|
|
24
|
-
annotation: Annotation = {}
|
|
25
|
-
): Dependency {
|
|
26
|
-
const { resources, values } = split(annotation)
|
|
27
|
-
|
|
28
|
-
annotation = prepare(values, instances)
|
|
29
|
-
|
|
30
|
-
const variables: Variables = {}
|
|
31
|
-
|
|
32
|
-
for (const instance of instances) {
|
|
33
|
-
const values = annotation[instance.locator.id]
|
|
34
|
-
|
|
35
|
-
if (values === undefined) continue
|
|
36
|
-
|
|
37
|
-
const secrets = createSecrets(values)
|
|
38
|
-
|
|
39
|
-
if (secrets.length > 0) variables[instance.locator.label] = secrets
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const service: Service = {
|
|
43
|
-
group: 'configuration',
|
|
44
|
-
name: 'values',
|
|
45
|
-
image,
|
|
46
|
-
version: JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
47
|
-
.version,
|
|
48
|
-
components: components().labels,
|
|
49
|
-
resources,
|
|
50
|
-
// the service that holds the values also serves the page that reads them
|
|
51
|
-
port: UI_PORT,
|
|
52
|
-
ingress: { path: UI_PATH },
|
|
53
|
-
variables: [
|
|
54
|
-
{
|
|
55
|
-
name: VALUES,
|
|
56
|
-
value: JSON.stringify(describe(instances, annotation))
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return { services: [service], variables, events: [EVENT] }
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** What the values service is given: the epoch, the schema and the defaults of every component. */
|
|
65
|
-
export function describe(instances: Instance[], annotation: Annotation = {}): Values {
|
|
66
|
-
annotation = prepare(split(annotation).values, instances)
|
|
67
|
-
|
|
68
|
-
const values: Values = {}
|
|
69
|
-
|
|
70
|
-
for (const { locator, manifest } of instances) {
|
|
71
|
-
const deployed = annotation[locator.id]
|
|
72
|
-
|
|
73
|
-
values[locator.id] = {
|
|
74
|
-
epoch: epoch(manifest.schema),
|
|
75
|
-
schema: manifest.schema,
|
|
76
|
-
// what the Context says stands over what the manifest declares, value by value: a
|
|
77
|
-
// deployment that names one of them does not thereby unset the rest
|
|
78
|
-
defaults:
|
|
79
|
-
deployed === undefined
|
|
80
|
-
? manifest.defaults
|
|
81
|
-
: add(structuredClone(deployed), manifest.defaults ?? {})
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return values
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function createSecrets(values: object): Variable[] {
|
|
89
|
-
const secrets: Variable[] = []
|
|
90
|
-
|
|
91
|
-
for (const value of Object.values(values)) {
|
|
92
|
-
if (typeof value === 'object' && value !== null)
|
|
93
|
-
secrets.push(...createSecrets(value as object))
|
|
94
|
-
|
|
95
|
-
if (typeof value !== 'string') continue
|
|
96
|
-
|
|
97
|
-
const match = value.match(SECRET_RX)
|
|
98
|
-
|
|
99
|
-
if (match === null) continue
|
|
100
|
-
|
|
101
|
-
const name = match.groups?.variable
|
|
102
|
-
|
|
103
|
-
assert.ok(name !== undefined)
|
|
104
|
-
|
|
105
|
-
secrets.push({
|
|
106
|
-
name: PREFIX + '_' + name,
|
|
107
|
-
secret: {
|
|
108
|
-
name: 'toa-configuration',
|
|
109
|
-
key: name
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return secrets
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* The service's own resources, and the component values that are the rest of the annotation.
|
|
119
|
-
*
|
|
120
|
-
* Every key here names a component, so the one option the service has of its own needs a
|
|
121
|
-
* name that cannot be mistaken for one. `resources` is reserved: a component actually
|
|
122
|
-
* called that is written with its namespace, `default.resources`, which is what an id is
|
|
123
|
-
* anyway — the bare form is the shorthand.
|
|
124
|
-
*/
|
|
125
|
-
function split(annotation: Annotation): { resources?: Resources; values: Annotation } {
|
|
126
|
-
validators.annotation.validate(annotation)
|
|
127
|
-
|
|
128
|
-
const { resources, ...values } = annotation as Annotation & { resources?: Resources }
|
|
129
|
-
|
|
130
|
-
return { resources, values }
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/** Validated, keyed by full component ids, and checked against the components that ask. */
|
|
134
|
-
function prepare(annotation: Annotation, instances: Instance[]): Annotation {
|
|
135
|
-
const normalized: Annotation = {}
|
|
136
|
-
const requested = instances.map((instance) => instance.locator.id)
|
|
137
|
-
|
|
138
|
-
for (const [key, values] of Object.entries(annotation)) {
|
|
139
|
-
const id = key.includes('.') ? key : 'default.' + key
|
|
140
|
-
|
|
141
|
-
assert.ok(
|
|
142
|
-
requested.includes(id),
|
|
143
|
-
`Component '${id}' does not request configuration or does not exist.`
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
normalized[id] = values
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return normalized
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export type Annotation = Record<string, object>
|
|
153
|
-
export type Instance = context.Dependency<Manifest>
|
|
154
|
-
export type Values = Record<string, Entry>
|
|
155
|
-
|
|
156
|
-
export interface Entry {
|
|
157
|
-
epoch: string
|
|
158
|
-
schema: object
|
|
159
|
-
defaults?: object
|
|
160
|
-
}
|
package/source/epoch.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
|
|
3
|
-
/** The same for the same schema, whatever the key order it was written in. */
|
|
4
|
-
export function epoch(schema: object): string {
|
|
5
|
-
return createHash('sha256').update(canonical(schema)).digest('hex')
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function canonical(value: unknown): string {
|
|
9
|
-
if (Array.isArray(value)) return '[' + value.map(canonical).join(',') + ']'
|
|
10
|
-
|
|
11
|
-
if (value !== null && typeof value === 'object') {
|
|
12
|
-
const object = value as Record<string, unknown>
|
|
13
|
-
const keys = Object.keys(object)
|
|
14
|
-
.filter((key) => object[key] !== undefined)
|
|
15
|
-
.sort()
|
|
16
|
-
const entries = keys.map((key) => JSON.stringify(key) + ':' + canonical(object[key]))
|
|
17
|
-
|
|
18
|
-
return '{' + entries.join(',') + '}'
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return JSON.stringify(value) ?? 'null'
|
|
22
|
-
}
|
package/source/manifest.test.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { type Manifest, manifest } from './manifest.js'
|
|
5
|
-
|
|
6
|
-
it('should validate', async () => {
|
|
7
|
-
const additional = { schema: {}, foo: 'bar' } as unknown as Manifest
|
|
8
|
-
|
|
9
|
-
assert.throws(
|
|
10
|
-
() => {
|
|
11
|
-
manifest(additional)
|
|
12
|
-
},
|
|
13
|
-
(error: any) => /not expected/.test(error.message)
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
const wrongType = { schema: 'not ok' } as unknown as Manifest
|
|
17
|
-
|
|
18
|
-
assert.throws(
|
|
19
|
-
() => {
|
|
20
|
-
manifest(wrongType)
|
|
21
|
-
},
|
|
22
|
-
(error: any) => /object/.test(error.message)
|
|
23
|
-
)
|
|
24
|
-
})
|
package/source/manifest.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import * as schemas from './schemas.js'
|
|
2
|
-
import { type Node } from './configuration.js'
|
|
3
|
-
|
|
4
|
-
export function manifest(manifest: Manifest): Manifest {
|
|
5
|
-
schemas.manifest.validate(manifest)
|
|
6
|
-
|
|
7
|
-
return manifest
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface Manifest {
|
|
11
|
-
schema: object
|
|
12
|
-
defaults?: Node
|
|
13
|
-
}
|
package/source/schemas.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path'
|
|
2
|
-
import * as schemas from '@toa.io/schemas'
|
|
3
|
-
import type { Schema } from '@toa.io/schemas'
|
|
4
|
-
|
|
5
|
-
const path = resolve(import.meta.dirname, '../schemas')
|
|
6
|
-
const namespace = schemas.namespace(path)
|
|
7
|
-
|
|
8
|
-
export const manifest: Schema<any> = namespace.schema('manifest')
|
|
9
|
-
export const annotation: Schema<any> = namespace.schema('annotation')
|
package/transpiled/const.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Source } from '@toa.io/core/types';
|
|
2
|
-
/** Per-component variables: the local override and the secrets. */
|
|
3
|
-
export declare const PREFIX = "TOA_CONFIGURATION_";
|
|
4
|
-
/** The map of every configured component, on the values service. */
|
|
5
|
-
export declare const VALUES = "TOA_CONFIGURATION_VALUES";
|
|
6
|
-
export declare const SECRET_RX: RegExp;
|
|
7
|
-
/** Where the UI is mounted; `/configuration/*` belongs to the component's own API. */
|
|
8
|
-
export declare const UI_PATH = "/.configuration";
|
|
9
|
-
export declare const UI_PORT = 8003;
|
|
10
|
-
/**
|
|
11
|
-
* The port the UI is served on. `UI_PORT` is what a deployment publishes and what the chart
|
|
12
|
-
* renders; the variable is for a machine that runs more than one Toa process — a Toa checkout
|
|
13
|
-
* beside an application, or two applications — where one of them has to give it up.
|
|
14
|
-
*/
|
|
15
|
-
export declare const UI_PORT_ENV = "TOA_CONFIGURATION_UI_PORT";
|
|
16
|
-
export declare function uiPort(): number;
|
|
17
|
-
export declare const EVENT = "configuration.values.created";
|
|
18
|
-
export declare const SOURCE: Source;
|
package/transpiled/const.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { environment } from '@toa.io/generic';
|
|
2
|
-
/** Per-component variables: the local override and the secrets. */
|
|
3
|
-
export const PREFIX = 'TOA_CONFIGURATION_';
|
|
4
|
-
/** The map of every configured component, on the values service. */
|
|
5
|
-
export const VALUES = 'TOA_CONFIGURATION_VALUES';
|
|
6
|
-
export const SECRET_RX = /^\$(?<variable>[A-Z0-9_]{1,32})$/;
|
|
7
|
-
/** Where the UI is mounted; `/configuration/*` belongs to the component's own API. */
|
|
8
|
-
export const UI_PATH = '/.configuration';
|
|
9
|
-
export const UI_PORT = 8003;
|
|
10
|
-
/**
|
|
11
|
-
* The port the UI is served on. `UI_PORT` is what a deployment publishes and what the chart
|
|
12
|
-
* renders; the variable is for a machine that runs more than one Toa process — a Toa checkout
|
|
13
|
-
* beside an application, or two applications — where one of them has to give it up.
|
|
14
|
-
*/
|
|
15
|
-
export const UI_PORT_ENV = 'TOA_CONFIGURATION_UI_PORT';
|
|
16
|
-
export function uiPort() {
|
|
17
|
-
const value = environment.get(UI_PORT_ENV);
|
|
18
|
-
return value === undefined ? UI_PORT : Number(value);
|
|
19
|
-
}
|
|
20
|
-
export const EVENT = 'configuration.values.created';
|
|
21
|
-
export const SOURCE = { service: 'configuration' };
|
|
22
|
-
//# sourceMappingURL=const.js.map
|
package/transpiled/const.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"const.js","sourceRoot":"","sources":["../source/const.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG7C,mEAAmE;AACnE,MAAM,CAAC,MAAM,MAAM,GAAG,oBAAoB,CAAA;AAE1C,oEAAoE;AACpE,MAAM,CAAC,MAAM,MAAM,GAAG,0BAA0B,CAAA;AAEhD,MAAM,CAAC,MAAM,SAAS,GAAG,kCAAkC,CAAA;AAE3D,sFAAsF;AACtF,MAAM,CAAC,MAAM,OAAO,GAAG,iBAAiB,CAAA;AACxC,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAA;AAE3B;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,2BAA2B,CAAA;AACtD,MAAM,UAAU,MAAM;IACpB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IAE1C,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACtD,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,8BAA8B,CAAA;AAEnD,MAAM,CAAC,MAAM,MAAM,GAAW,EAAE,OAAO,EAAE,eAAe,EAAE,CAAA"}
|
package/transpiled/context.d.ts
DELETED
package/transpiled/context.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** What this extension puts on the context of a component that declares it. */
|
|
2
|
-
export function context(declaration) {
|
|
3
|
-
const contribution = { name: 'configuration', schema: declaration.schema };
|
|
4
|
-
// a value the schema declares a secret is one on the context, not a string
|
|
5
|
-
if (JSON.stringify(declaration.schema).includes('"secret"'))
|
|
6
|
-
contribution.imports = { '@toa.io/extensions.configuration': ['Secret'] };
|
|
7
|
-
return contribution;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../source/context.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,MAAM,UAAU,OAAO,CAAC,WAAqB;IAC3C,MAAM,YAAY,GAAiB,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAA;IAExF,2EAA2E;IAC3E,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;QACzD,YAAY,CAAC,OAAO,GAAG,EAAE,kCAAkC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAA;IAE3E,OAAO,YAAY,CAAA;AACrB,CAAC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type Dependency } from '@toa.io/operations';
|
|
2
|
-
import type { Manifest } from './manifest.js';
|
|
3
|
-
import type { context } from '@toa.io/norm';
|
|
4
|
-
/** Where Toa's release publishes this service's image. An application takes it
|
|
5
|
-
* instead of building one when its context says `registry.services: published`. */
|
|
6
|
-
export declare const image = "ghcr.io/toa-io/extension-configuration-values";
|
|
7
|
-
export declare function deployment(instances: Instance[], annotation?: Annotation): Dependency;
|
|
8
|
-
/** What the values service is given: the epoch, the schema and the defaults of every component. */
|
|
9
|
-
export declare function describe(instances: Instance[], annotation?: Annotation): Values;
|
|
10
|
-
export type Annotation = Record<string, object>;
|
|
11
|
-
export type Instance = context.Dependency<Manifest>;
|
|
12
|
-
export type Values = Record<string, Entry>;
|
|
13
|
-
export interface Entry {
|
|
14
|
-
epoch: string;
|
|
15
|
-
schema: object;
|
|
16
|
-
defaults?: object;
|
|
17
|
-
}
|
package/transpiled/deployment.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import assert from 'node:assert';
|
|
3
|
-
import { add } from '@toa.io/generic';
|
|
4
|
-
import { components } from './Composition.js';
|
|
5
|
-
import { EVENT, PREFIX, SECRET_RX, UI_PATH, UI_PORT, VALUES } from './const.js';
|
|
6
|
-
import { epoch } from './epoch.js';
|
|
7
|
-
import * as validators from './schemas.js';
|
|
8
|
-
/** Where Toa's release publishes this service's image. An application takes it
|
|
9
|
-
* instead of building one when its context says `registry.services: published`. */
|
|
10
|
-
export const image = 'ghcr.io/toa-io/extension-configuration-values';
|
|
11
|
-
export function deployment(instances, annotation = {}) {
|
|
12
|
-
const { resources, values } = split(annotation);
|
|
13
|
-
annotation = prepare(values, instances);
|
|
14
|
-
const variables = {};
|
|
15
|
-
for (const instance of instances) {
|
|
16
|
-
const values = annotation[instance.locator.id];
|
|
17
|
-
if (values === undefined)
|
|
18
|
-
continue;
|
|
19
|
-
const secrets = createSecrets(values);
|
|
20
|
-
if (secrets.length > 0)
|
|
21
|
-
variables[instance.locator.label] = secrets;
|
|
22
|
-
}
|
|
23
|
-
const service = {
|
|
24
|
-
group: 'configuration',
|
|
25
|
-
name: 'values',
|
|
26
|
-
image,
|
|
27
|
-
version: JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
28
|
-
.version,
|
|
29
|
-
components: components().labels,
|
|
30
|
-
resources,
|
|
31
|
-
// the service that holds the values also serves the page that reads them
|
|
32
|
-
port: UI_PORT,
|
|
33
|
-
ingress: { path: UI_PATH },
|
|
34
|
-
variables: [
|
|
35
|
-
{
|
|
36
|
-
name: VALUES,
|
|
37
|
-
value: JSON.stringify(describe(instances, annotation))
|
|
38
|
-
}
|
|
39
|
-
]
|
|
40
|
-
};
|
|
41
|
-
return { services: [service], variables, events: [EVENT] };
|
|
42
|
-
}
|
|
43
|
-
/** What the values service is given: the epoch, the schema and the defaults of every component. */
|
|
44
|
-
export function describe(instances, annotation = {}) {
|
|
45
|
-
annotation = prepare(split(annotation).values, instances);
|
|
46
|
-
const values = {};
|
|
47
|
-
for (const { locator, manifest } of instances) {
|
|
48
|
-
const deployed = annotation[locator.id];
|
|
49
|
-
values[locator.id] = {
|
|
50
|
-
epoch: epoch(manifest.schema),
|
|
51
|
-
schema: manifest.schema,
|
|
52
|
-
// what the Context says stands over what the manifest declares, value by value: a
|
|
53
|
-
// deployment that names one of them does not thereby unset the rest
|
|
54
|
-
defaults: deployed === undefined
|
|
55
|
-
? manifest.defaults
|
|
56
|
-
: add(structuredClone(deployed), manifest.defaults ?? {})
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return values;
|
|
60
|
-
}
|
|
61
|
-
function createSecrets(values) {
|
|
62
|
-
const secrets = [];
|
|
63
|
-
for (const value of Object.values(values)) {
|
|
64
|
-
if (typeof value === 'object' && value !== null)
|
|
65
|
-
secrets.push(...createSecrets(value));
|
|
66
|
-
if (typeof value !== 'string')
|
|
67
|
-
continue;
|
|
68
|
-
const match = value.match(SECRET_RX);
|
|
69
|
-
if (match === null)
|
|
70
|
-
continue;
|
|
71
|
-
const name = match.groups?.variable;
|
|
72
|
-
assert.ok(name !== undefined);
|
|
73
|
-
secrets.push({
|
|
74
|
-
name: PREFIX + '_' + name,
|
|
75
|
-
secret: {
|
|
76
|
-
name: 'toa-configuration',
|
|
77
|
-
key: name
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
return secrets;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* The service's own resources, and the component values that are the rest of the annotation.
|
|
85
|
-
*
|
|
86
|
-
* Every key here names a component, so the one option the service has of its own needs a
|
|
87
|
-
* name that cannot be mistaken for one. `resources` is reserved: a component actually
|
|
88
|
-
* called that is written with its namespace, `default.resources`, which is what an id is
|
|
89
|
-
* anyway — the bare form is the shorthand.
|
|
90
|
-
*/
|
|
91
|
-
function split(annotation) {
|
|
92
|
-
validators.annotation.validate(annotation);
|
|
93
|
-
const { resources, ...values } = annotation;
|
|
94
|
-
return { resources, values };
|
|
95
|
-
}
|
|
96
|
-
/** Validated, keyed by full component ids, and checked against the components that ask. */
|
|
97
|
-
function prepare(annotation, instances) {
|
|
98
|
-
const normalized = {};
|
|
99
|
-
const requested = instances.map((instance) => instance.locator.id);
|
|
100
|
-
for (const [key, values] of Object.entries(annotation)) {
|
|
101
|
-
const id = key.includes('.') ? key : 'default.' + key;
|
|
102
|
-
assert.ok(requested.includes(id), `Component '${id}' does not request configuration or does not exist.`);
|
|
103
|
-
normalized[id] = values;
|
|
104
|
-
}
|
|
105
|
-
return normalized;
|
|
106
|
-
}
|
|
107
|
-
//# sourceMappingURL=deployment.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deployment.js","sourceRoot":"","sources":["../source/deployment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,MAAM,MAAM,aAAa,CAAA;AAQhC,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,KAAK,UAAU,MAAM,cAAc,CAAA;AAI1C;oFACoF;AACpF,MAAM,CAAC,MAAM,KAAK,GAAG,+CAA+C,CAAA;AAEpE,MAAM,UAAU,UAAU,CACxB,SAAqB,EACrB,UAAU,GAAe,EAAE;IAE3B,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;IAE/C,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAEvC,MAAM,SAAS,GAAc,EAAE,CAAA;IAE/B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAE9C,IAAI,MAAM,KAAK,SAAS;YAAE,SAAQ;QAElC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;QAErC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAA;IACrE,CAAC;IAED,MAAM,OAAO,GAAY;QACvB,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,QAAQ;QACd,KAAK;QACL,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;aACnF,OAAO;QACV,UAAU,EAAE,UAAU,EAAE,CAAC,MAAM;QAC/B,SAAS;QACT,yEAAyE;QACzE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QAC1B,SAAS,EAAE;YACT;gBACE,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;aACvD;SACF;KACF,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAA;AAC5D,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,QAAQ,CAAC,SAAqB,EAAE,UAAU,GAAe,EAAE;IACzE,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAEzD,MAAM,MAAM,GAAW,EAAE,CAAA;IAEzB,KAAK,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,SAAS,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAEvC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG;YACnB,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,kFAAkF;YAClF,oEAAoE;YACpE,QAAQ,EACN,QAAQ,KAAK,SAAS;gBACpB,CAAC,CAAC,QAAQ,CAAC,QAAQ;gBACnB,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;SAC9D,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,OAAO,GAAe,EAAE,CAAA;IAE9B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAC7C,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,KAAe,CAAC,CAAC,CAAA;QAEjD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAQ;QAEvC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAEpC,IAAI,KAAK,KAAK,IAAI;YAAE,SAAQ;QAE5B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAA;QAEnC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;QAE7B,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;YACzB,MAAM,EAAE;gBACN,IAAI,EAAE,mBAAmB;gBACzB,GAAG,EAAE,IAAI;aACV;SACF,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,KAAK,CAAC,UAAsB;IACnC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;IAE1C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,UAAoD,CAAA;IAErF,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;AAC9B,CAAC;AAED,2FAA2F;AAC3F,SAAS,OAAO,CAAC,UAAsB,EAAE,SAAqB;IAC5D,MAAM,UAAU,GAAe,EAAE,CAAA;IACjC,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAElE,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACvD,MAAM,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAA;QAErD,MAAM,CAAC,EAAE,CACP,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EACtB,cAAc,EAAE,qDAAqD,CACtE,CAAA;QAED,UAAU,CAAC,EAAE,CAAC,GAAG,MAAM,CAAA;IACzB,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC"}
|
package/transpiled/epoch.d.ts
DELETED
package/transpiled/epoch.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
/** The same for the same schema, whatever the key order it was written in. */
|
|
3
|
-
export function epoch(schema) {
|
|
4
|
-
return createHash('sha256').update(canonical(schema)).digest('hex');
|
|
5
|
-
}
|
|
6
|
-
function canonical(value) {
|
|
7
|
-
if (Array.isArray(value))
|
|
8
|
-
return '[' + value.map(canonical).join(',') + ']';
|
|
9
|
-
if (value !== null && typeof value === 'object') {
|
|
10
|
-
const object = value;
|
|
11
|
-
const keys = Object.keys(object)
|
|
12
|
-
.filter((key) => object[key] !== undefined)
|
|
13
|
-
.sort();
|
|
14
|
-
const entries = keys.map((key) => JSON.stringify(key) + ':' + canonical(object[key]));
|
|
15
|
-
return '{' + entries.join(',') + '}';
|
|
16
|
-
}
|
|
17
|
-
return JSON.stringify(value) ?? 'null';
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=epoch.js.map
|
package/transpiled/epoch.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"epoch.js","sourceRoot":"","sources":["../source/epoch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,8EAA8E;AAC9E,MAAM,UAAU,KAAK,CAAC,MAAc;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACrE,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IAE3E,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,KAAgC,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aAC7B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;aAC1C,IAAI,EAAE,CAAA;QACT,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAErF,OAAO,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IACtC,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAA;AACxC,CAAC"}
|
package/transpiled/manifest.d.ts
DELETED
package/transpiled/manifest.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../source/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAGvC,MAAM,UAAU,QAAQ,CAAC,QAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAEnC,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
package/transpiled/schemas.d.ts
DELETED
package/transpiled/schemas.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import * as schemas from '@toa.io/schemas';
|
|
3
|
-
const path = resolve(import.meta.dirname, '../schemas');
|
|
4
|
-
const namespace = schemas.namespace(path);
|
|
5
|
-
export const manifest = namespace.schema('manifest');
|
|
6
|
-
export const annotation = namespace.schema('annotation');
|
|
7
|
-
//# sourceMappingURL=schemas.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../source/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAA;AAG1C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;AACvD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;AAEzC,MAAM,CAAC,MAAM,QAAQ,GAAgB,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AACjE,MAAM,CAAC,MAAM,UAAU,GAAgB,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e,r as t}from"../chunks/3Kbn_1Vv.js";export{e as load_css,t as start};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Et as e,Q as t,j as n,k as r}from"../chunks/CcD_ISxM.js";import"../chunks/xihTtKlq.js";import{r as i}from"../chunks/BV5cDXGB.js";var a=n(`<div class="mx-auto h-full max-w-7xl overflow-auto px-4 pb-12"><!></div>`);function o(n){var o=a(),s=t(o);i(s,{}),e(o),r(n,o)}export{o as component};
|