@toa.io/norm 1.0.0-alpha.29 → 1.0.0-alpha.291
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/package.json +8 -7
- package/src/.component/.expand/bridge.js +2 -6
- package/src/.component/.expand/entity.js +2 -9
- package/src/.component/.expand/events.js +2 -6
- package/src/.component/.expand/extensions.js +5 -8
- package/src/.component/.expand/index.js +8 -19
- package/src/.component/.expand/operations.js +2 -9
- package/src/.component/.expand/properties.js +2 -6
- package/src/.component/.expand/receivers.js +4 -7
- package/src/.component/.expand/version.js +38 -28
- package/src/.component/.normalize/entity.js +7 -0
- package/src/.component/.normalize/events.js +15 -5
- package/src/.component/.normalize/index.js +4 -9
- package/src/.component/.normalize/operations.js +10 -6
- package/src/.component/.normalize/receivers.js +4 -5
- package/src/.component/collapse.js +60 -9
- package/src/.component/defaults.js +16 -10
- package/src/.component/dependencies.js +14 -10
- package/src/.component/dereference.js +20 -18
- package/src/.component/expand.js +3 -7
- package/src/.component/extensions.js +15 -8
- package/src/.component/index.js +10 -21
- package/src/.component/merge.js +24 -13
- package/src/.component/migrations.js +57 -0
- package/src/.component/normalize.js +10 -6
- package/src/.component/schema.yaml +108 -71
- package/src/.component/validate.js +36 -17
- package/src/.context/.dependencies/connectors.js +5 -9
- package/src/.context/.dependencies/describe.js +4 -5
- package/src/.context/.dependencies/extensions.js +62 -20
- package/src/.context/.dependencies/index.js +3 -9
- package/src/.context/.dependencies/load.js +17 -14
- package/src/.context/.dependencies/resolve.js +23 -6
- package/src/.context/complete.js +1 -5
- package/src/.context/dependencies.js +2 -6
- package/src/.context/dereference.js +11 -6
- package/src/.context/expand.js +8 -6
- package/src/.context/index.js +6 -15
- package/src/.context/normalize.js +7 -5
- package/src/.context/schema.yaml +132 -11
- package/src/.context/validate.js +8 -14
- package/src/component.js +36 -17
- package/src/context.js +26 -14
- package/src/entity.js +15 -0
- package/src/index.js +4 -9
- package/src/shortcuts.js +8 -13
- package/test/component/collapse.fixtures.js +30 -39
- package/test/component/collapse.test.js +90 -10
- package/test/component/dependencies.test.js +16 -14
- package/test/component/dereference.fixtures.js +15 -24
- package/test/component/dereference.test.js +18 -8
- package/test/component/dummies/extension/index.js +1 -5
- package/test/component/dummies/migrations/conflicting/migrations/0001-one.yaml +2 -0
- package/test/component/dummies/migrations/conflicting/migrations/0001-one.yml +2 -0
- package/test/component/dummies/migrations/malformed/migrations/0001-one.yaml +1 -0
- package/test/component/dummies/migrations/ordered/migrations/0001-first.yml +4 -0
- package/test/component/dummies/migrations/ordered/migrations/0002-second.yaml +4 -0
- package/test/component/dummies/migrations/ordered/migrations/0010-third.json +1 -0
- package/test/component/dummies/migrations/stateless/migrations/0001-one.yaml +2 -0
- package/test/component/expand.fixtures.js +13 -13
- package/test/component/expand.test.js +25 -10
- package/test/component/migrations.test.js +62 -0
- package/test/component/normalize.fixtures.js +3 -7
- package/test/component/normalize.test.js +86 -28
- package/test/component/validate.fixtures.js +15 -13
- package/test/component/validate.test.js +162 -109
- package/test/context/complete.fixtures.js +2 -8
- package/test/context/complete.test.js +14 -8
- package/test/context/dependencies.load.test.js +13 -12
- package/test/context/dereference.fixtures.js +3 -9
- package/test/context/dereference.test.js +18 -7
- package/test/context/expand.fixtures.js +1 -5
- package/test/context/expand.test.js +36 -8
- package/test/context/normalize.fixtures.js +2 -7
- package/test/context/normalize.test.js +33 -9
- package/test/context/validate.fixtures.js +1 -6
- package/test/context/validate.test.js +81 -37
- package/test/shortcuts.fixtures.js +4 -9
- package/test/shortcuts.test.js +17 -15
- package/types/component.d.ts +17 -3
- package/types/context/declaration.d.ts +26 -3
- package/types/context.d.ts +15 -13
- package/types/entity.d.ts +7 -0
- package/types/index.d.ts +4 -3
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { merge } from '@toa.io/generic'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const dereference = (manifest) => {
|
|
3
|
+
export const dereference = (manifest) => {
|
|
6
4
|
// schemas
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
if (manifest.entity !== undefined)
|
|
10
|
-
schema(manifest.entity.schema, resolver)
|
|
5
|
+
const properties = manifest.entity?.properties
|
|
6
|
+
const resolver = createResolver(properties)
|
|
11
7
|
|
|
12
|
-
if (
|
|
13
|
-
|
|
8
|
+
if (properties !== undefined)
|
|
9
|
+
for (const [name, property] of Object.entries(properties))
|
|
10
|
+
properties[name] = schema(property, resolver)
|
|
14
11
|
|
|
12
|
+
if ('operations' in manifest) operations(manifest, resolver)
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
const createResolver = (properties) => (property) => {
|
|
@@ -22,10 +20,14 @@ const createResolver = (properties) => (property) => {
|
|
|
22
20
|
return properties[property]
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
function operations
|
|
23
|
+
function operations(manifest, resolver) {
|
|
26
24
|
for (const operation of Object.values(manifest.operations)) {
|
|
27
25
|
if (operation.input !== undefined) operation.input = schema(operation.input, resolver)
|
|
28
|
-
|
|
26
|
+
|
|
27
|
+
if (operation.output !== undefined)
|
|
28
|
+
if (Array.isArray(operation.output) && operation.output.length === 1)
|
|
29
|
+
operation.output = [schema(operation.output[0], resolver)]
|
|
30
|
+
else operation.output = schema(operation.output, resolver)
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
// forwarding
|
|
@@ -36,18 +38,19 @@ function operations (manifest, resolver) {
|
|
|
36
38
|
for (const operation of Object.values(manifest.operations)) {
|
|
37
39
|
delete operation.forwarded
|
|
38
40
|
}
|
|
39
|
-
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
const schema = (object, resolve) => {
|
|
43
44
|
if (object === undefined || object === null || typeof object !== 'object') return
|
|
44
|
-
if (object.type === 'string' && object.default?.[0] === '.')
|
|
45
|
+
if (object.type === 'string' && object.default?.[0] === '.')
|
|
46
|
+
return resolve(object.default.substring(1))
|
|
45
47
|
|
|
46
48
|
if (object.type === 'array') {
|
|
47
49
|
object.items = schema(object.items, resolve)
|
|
48
50
|
} else if (object.properties !== undefined) {
|
|
49
51
|
for (const [name, value] of Object.entries(object.properties)) {
|
|
50
|
-
if (value?.type === 'string' && value.default === '.')
|
|
52
|
+
if (value?.type === 'string' && value.default === '.')
|
|
53
|
+
object.properties[name] = resolve(name)
|
|
51
54
|
else object.properties[name] = schema(value, resolve)
|
|
52
55
|
}
|
|
53
56
|
}
|
|
@@ -58,7 +61,8 @@ const schema = (object, resolve) => {
|
|
|
58
61
|
const forward = (operation, operations) => {
|
|
59
62
|
const target = operations[operation.forward]
|
|
60
63
|
|
|
61
|
-
if (target === undefined)
|
|
64
|
+
if (target === undefined)
|
|
65
|
+
throw new Error(`Referenced operation '${operation.forward}' is not defined`)
|
|
62
66
|
|
|
63
67
|
if (target.forward !== undefined) {
|
|
64
68
|
if (target.forwarded !== true) forward(target, operations)
|
|
@@ -72,5 +76,3 @@ const forward = (operation, operations) => {
|
|
|
72
76
|
|
|
73
77
|
merge(operation, real)
|
|
74
78
|
}
|
|
75
|
-
|
|
76
|
-
exports.dereference = dereference
|
package/src/.component/expand.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const {
|
|
1
|
+
import {
|
|
4
2
|
entity,
|
|
5
3
|
bridge,
|
|
6
4
|
operations,
|
|
@@ -9,9 +7,9 @@ const {
|
|
|
9
7
|
extensions,
|
|
10
8
|
properties,
|
|
11
9
|
version
|
|
12
|
-
}
|
|
10
|
+
} from './.expand/index.js'
|
|
13
11
|
|
|
14
|
-
async function expand
|
|
12
|
+
export async function expand(manifest) {
|
|
15
13
|
entity(manifest)
|
|
16
14
|
bridge(manifest)
|
|
17
15
|
operations(manifest)
|
|
@@ -22,5 +20,3 @@ async function expand (manifest) {
|
|
|
22
20
|
|
|
23
21
|
await version(manifest)
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
exports.expand = expand
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { find } from '@toa.io/generic'
|
|
2
|
+
import { resolve } from '../shortcuts.js'
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
const { resolve } = require('../shortcuts')
|
|
4
|
+
const cache = {}
|
|
5
5
|
|
|
6
|
-
const extensions = (manifest) => {
|
|
7
|
-
|
|
6
|
+
export const extensions = async (manifest) => {
|
|
7
|
+
manifest.extensions = Object.assign({}, PREDEFINED, manifest.extensions)
|
|
8
8
|
|
|
9
9
|
const extensions = manifest.extensions
|
|
10
10
|
|
|
@@ -14,12 +14,15 @@ const extensions = (manifest) => {
|
|
|
14
14
|
// relative path
|
|
15
15
|
if (key[0] === '.') key = find(key, manifest.path)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
cache[key] ??= import(key)
|
|
18
|
+
|
|
19
|
+
const extension = await cache[key]
|
|
18
20
|
|
|
19
21
|
if (extension.manifest !== undefined) {
|
|
20
22
|
declaration = extension.manifest(declaration, manifest)
|
|
21
23
|
|
|
22
|
-
if (declaration === undefined)
|
|
24
|
+
if (declaration === undefined)
|
|
25
|
+
throw new Error(`Extension '${reference}' hasn't returned manifest`)
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
extensions[key] = declaration
|
|
@@ -29,4 +32,8 @@ const extensions = (manifest) => {
|
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
const PREDEFINED = {
|
|
36
|
+
'@toa.io/extensions.telemetry': null,
|
|
37
|
+
'@toa.io/extensions.fetch': null,
|
|
38
|
+
'@toa.io/extensions.introspection': null
|
|
39
|
+
}
|
package/src/.component/index.js
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const { extensions } = require('./extensions')
|
|
12
|
-
|
|
13
|
-
exports.collapse = collapse
|
|
14
|
-
exports.defaults = defaults
|
|
15
|
-
exports.dependencies = dependencies
|
|
16
|
-
exports.dereference = dereference
|
|
17
|
-
exports.expand = expand
|
|
18
|
-
exports.merge = merge
|
|
19
|
-
exports.normalize = normalize
|
|
20
|
-
exports.validate = validate
|
|
21
|
-
exports.extensions = extensions
|
|
1
|
+
export { collapse } from './collapse.js'
|
|
2
|
+
export { defaults } from './defaults.js'
|
|
3
|
+
export { dependencies } from './dependencies.js'
|
|
4
|
+
export { dereference } from './dereference.js'
|
|
5
|
+
export { expand } from './expand.js'
|
|
6
|
+
export { merge } from './merge.js'
|
|
7
|
+
export { migrations } from './migrations.js'
|
|
8
|
+
export { normalize } from './normalize.js'
|
|
9
|
+
export { validate } from './validate.js'
|
|
10
|
+
export { extensions } from './extensions.js'
|
package/src/.component/merge.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { merge } = require('@toa.io/generic')
|
|
1
|
+
import { merge } from '@toa.io/generic'
|
|
4
2
|
|
|
5
3
|
const bridge = async (root, manifest) => {
|
|
6
4
|
await Promise.all([
|
|
7
5
|
define(root, manifest, 'operations'),
|
|
8
6
|
define(root, manifest, 'events'),
|
|
9
|
-
define(root, manifest, 'receivers')
|
|
7
|
+
define(root, manifest, 'receivers'),
|
|
8
|
+
define(root, manifest, 'guards')
|
|
10
9
|
])
|
|
11
10
|
}
|
|
12
11
|
|
|
@@ -19,7 +18,7 @@ const define = async (root, manifest, property) => {
|
|
|
19
18
|
if (item.bridge === undefined || item.bridge === manifest.bridge) continue // default bridge later
|
|
20
19
|
|
|
21
20
|
const bridge = item.bridge || manifest.bridge
|
|
22
|
-
const { define } =
|
|
21
|
+
const { define } = await req(bridge)
|
|
23
22
|
const definition = await define[singular](root, endpoint)
|
|
24
23
|
|
|
25
24
|
merge(item, definition)
|
|
@@ -29,8 +28,7 @@ const define = async (root, manifest, property) => {
|
|
|
29
28
|
// default bridge
|
|
30
29
|
const definition = await scan(manifest.bridge, root, property)
|
|
31
30
|
|
|
32
|
-
if (definition === undefined)
|
|
33
|
-
return
|
|
31
|
+
if (definition === undefined) return
|
|
34
32
|
|
|
35
33
|
const items = Object.entries(definition)
|
|
36
34
|
|
|
@@ -44,18 +42,31 @@ const define = async (root, manifest, property) => {
|
|
|
44
42
|
|
|
45
43
|
const declared = manifest[property][endpoint]
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
try {
|
|
46
|
+
if (declared === undefined) manifest[property][endpoint] = item
|
|
47
|
+
else merge(declared, item)
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error(`Error merging ${singular} '${endpoint}' in ${root}`)
|
|
50
|
+
throw error
|
|
51
|
+
}
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
56
|
+
const cache = {}
|
|
57
|
+
|
|
58
|
+
// the promise is what is remembered, so a bridge is loaded once
|
|
59
|
+
function req(mod) {
|
|
60
|
+
cache[mod] ??= import(mod)
|
|
61
|
+
|
|
62
|
+
return cache[mod]
|
|
63
|
+
}
|
|
64
|
+
|
|
53
65
|
const scan = async (bridge, root, property) => {
|
|
54
|
-
const { define } =
|
|
66
|
+
const { define } = await req(bridge)
|
|
55
67
|
|
|
56
|
-
if (property in define)
|
|
57
|
-
return define[property](root)
|
|
68
|
+
if (property in define) return define[property](root)
|
|
58
69
|
else return undefined
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
|
|
72
|
+
export { bridge as merge }
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { basename, extname, resolve } from 'node:path'
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
|
|
4
|
+
import glob from 'fast-glob'
|
|
5
|
+
import { yaml } from '@toa.io/generic'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The migrations a component declares, in the order they are applied. The file name without its
|
|
9
|
+
* extension is the migration's id, and sorting those ids is what orders them — so a name is
|
|
10
|
+
* written to sort: `0001-indexes`, then `0002-default-role`.
|
|
11
|
+
*
|
|
12
|
+
* What a file contains is the storage's business; this reads it and hands it over.
|
|
13
|
+
*/
|
|
14
|
+
export const migrations = async (root, manifest) => {
|
|
15
|
+
const paths = await glob(resolve(root, DIRECTORY, '*' + EXTENSIONS), GLOB)
|
|
16
|
+
|
|
17
|
+
if (paths.length === 0) return
|
|
18
|
+
|
|
19
|
+
if (manifest.entity === undefined)
|
|
20
|
+
throw new Error(`Component at '${root}' declares migrations but stores nothing`)
|
|
21
|
+
|
|
22
|
+
const ids = new Map()
|
|
23
|
+
|
|
24
|
+
// sorted, so the two files a conflict names are the same two on every machine
|
|
25
|
+
for (const path of paths.sort()) {
|
|
26
|
+
const id = basename(path, extname(path))
|
|
27
|
+
const found = ids.get(id)
|
|
28
|
+
|
|
29
|
+
if (found !== undefined)
|
|
30
|
+
throw new Error(
|
|
31
|
+
`Component at '${root}' has more than one ${DIRECTORY}/${id}: ` +
|
|
32
|
+
`${basename(found)} and ${basename(path)}`
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
ids.set(id, path)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
manifest.entity.migrations = await Promise.all(
|
|
39
|
+
Array.from(ids, async ([id, path]) => ({ id, steps: await read(path) }))
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A migration is a list of steps. A file that is not one is refused here rather than at the
|
|
45
|
+
* storage, where the component it belongs to is no longer known.
|
|
46
|
+
*/
|
|
47
|
+
async function read(path) {
|
|
48
|
+
const steps = yaml.load(await readFile(path, 'utf8'))
|
|
49
|
+
|
|
50
|
+
if (!Array.isArray(steps)) throw new Error(`Migration '${path}' is not a list of steps`)
|
|
51
|
+
|
|
52
|
+
return steps
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const DIRECTORY = 'migrations'
|
|
56
|
+
const EXTENSIONS = '.{yaml,yml,json}'
|
|
57
|
+
const GLOB = { onlyFiles: true, absolute: true }
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { entity, events, operations, receivers } from './.normalize/index.js'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* What a manifest does not say but the runtime needs said. The schema states what a value may
|
|
5
|
+
* be; what it is where nothing was written is decided here, so that validating a manifest is
|
|
6
|
+
* reading it rather than completing it.
|
|
7
|
+
*/
|
|
8
|
+
export const normalize = async (component) => {
|
|
9
|
+
component.namespace ??= 'default'
|
|
4
10
|
|
|
5
|
-
|
|
11
|
+
entity(component)
|
|
6
12
|
operations(component)
|
|
7
|
-
events(component)
|
|
13
|
+
await events(component)
|
|
8
14
|
receivers(component)
|
|
9
15
|
}
|
|
10
|
-
|
|
11
|
-
exports.normalize = normalize
|
|
@@ -8,7 +8,7 @@ definitions:
|
|
|
8
8
|
binding:
|
|
9
9
|
type: string
|
|
10
10
|
not:
|
|
11
|
-
const:
|
|
11
|
+
const: "@toa.io/bindings.loop" # loop is for system use only
|
|
12
12
|
|
|
13
13
|
type: object
|
|
14
14
|
properties:
|
|
@@ -17,19 +17,19 @@ properties:
|
|
|
17
17
|
nullable: true
|
|
18
18
|
properties:
|
|
19
19
|
prototype:
|
|
20
|
-
$ref:
|
|
20
|
+
$ref: "#/properties/prototype"
|
|
21
21
|
path:
|
|
22
22
|
type: string
|
|
23
23
|
operations:
|
|
24
24
|
type: object
|
|
25
25
|
propertyNames:
|
|
26
|
-
$ref:
|
|
26
|
+
$ref: "#/definitions/name"
|
|
27
27
|
patternProperties:
|
|
28
|
-
|
|
28
|
+
".*":
|
|
29
29
|
type: object
|
|
30
30
|
properties:
|
|
31
31
|
bridge:
|
|
32
|
-
$ref:
|
|
32
|
+
$ref: "#/properties/bridge"
|
|
33
33
|
|
|
34
34
|
path:
|
|
35
35
|
type: string
|
|
@@ -38,19 +38,22 @@ properties:
|
|
|
38
38
|
type: object
|
|
39
39
|
properties:
|
|
40
40
|
id:
|
|
41
|
-
|
|
41
|
+
type: string
|
|
42
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(\.([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))$
|
|
42
43
|
label:
|
|
43
|
-
|
|
44
|
+
type: string
|
|
45
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(-([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))*$
|
|
44
46
|
|
|
45
47
|
name:
|
|
46
|
-
|
|
48
|
+
type: string
|
|
49
|
+
pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
|
|
47
50
|
|
|
48
51
|
namespace:
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
type: string
|
|
53
|
+
pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
|
|
51
54
|
not:
|
|
52
55
|
oneOf:
|
|
53
|
-
- const:
|
|
56
|
+
- const: "system"
|
|
54
57
|
|
|
55
58
|
version:
|
|
56
59
|
type: string
|
|
@@ -60,56 +63,60 @@ properties:
|
|
|
60
63
|
properties:
|
|
61
64
|
image:
|
|
62
65
|
type: string
|
|
66
|
+
run:
|
|
67
|
+
type: string
|
|
63
68
|
|
|
64
69
|
entity:
|
|
65
70
|
type: object
|
|
66
71
|
properties:
|
|
67
72
|
storage:
|
|
68
73
|
type: string
|
|
69
|
-
|
|
70
|
-
schema:
|
|
71
|
-
$ref: 'definitions#/definitions/schema'
|
|
74
|
+
properties:
|
|
72
75
|
type: object
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
# a system property is named like any other, so nothing is enumerated beside them
|
|
77
|
+
propertyNames:
|
|
78
|
+
$ref: "#/definitions/name"
|
|
79
|
+
additionalProperties:
|
|
80
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
81
|
+
required:
|
|
82
|
+
type: array
|
|
83
|
+
uniqueItems: true
|
|
84
|
+
items:
|
|
85
|
+
$ref: "#/definitions/name"
|
|
86
|
+
blank:
|
|
87
|
+
# what a record holds before anything is written to it; a system property is the
|
|
88
|
+
# runtime's to write, so none may be named here
|
|
84
89
|
type: object
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
propertyNames:
|
|
91
|
+
not:
|
|
92
|
+
enum: [id, VERSION, CREATED, UPDATED, DELETED]
|
|
93
|
+
migrations:
|
|
94
|
+
type: array
|
|
95
|
+
items:
|
|
96
|
+
type: object
|
|
97
|
+
properties:
|
|
98
|
+
id:
|
|
89
99
|
type: string
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
enum: [asc, desc, hash]
|
|
100
|
+
# what a step means belongs to the storage, which is the only thing that reads it
|
|
101
|
+
steps:
|
|
102
|
+
type: array
|
|
103
|
+
# the prototype it is inherited from; absent on the component's own
|
|
104
|
+
prototype:
|
|
105
|
+
type: string
|
|
106
|
+
required: [id, steps]
|
|
107
|
+
additionalProperties: false
|
|
99
108
|
associated:
|
|
100
109
|
type: boolean
|
|
101
|
-
default: false
|
|
102
110
|
custom:
|
|
103
111
|
type: boolean
|
|
104
|
-
|
|
105
|
-
required: [schema]
|
|
112
|
+
required: [properties]
|
|
106
113
|
additionalProperties: false
|
|
107
114
|
|
|
108
115
|
bindings:
|
|
109
116
|
type: array
|
|
110
117
|
uniqueItems: true
|
|
111
118
|
items:
|
|
112
|
-
$ref:
|
|
119
|
+
$ref: "#/definitions/binding"
|
|
113
120
|
|
|
114
121
|
bridge:
|
|
115
122
|
type: string
|
|
@@ -117,27 +124,43 @@ properties:
|
|
|
117
124
|
operations:
|
|
118
125
|
type: object
|
|
119
126
|
propertyNames:
|
|
120
|
-
$ref:
|
|
127
|
+
$ref: "#/definitions/name"
|
|
121
128
|
patternProperties:
|
|
122
|
-
|
|
129
|
+
".*":
|
|
123
130
|
type: object
|
|
124
131
|
properties:
|
|
125
132
|
type:
|
|
126
|
-
enum:
|
|
133
|
+
enum:
|
|
134
|
+
[
|
|
135
|
+
transition,
|
|
136
|
+
observation,
|
|
137
|
+
assignment,
|
|
138
|
+
computation,
|
|
139
|
+
effect,
|
|
140
|
+
unmanaged,
|
|
141
|
+
]
|
|
127
142
|
scope:
|
|
128
|
-
enum: [object, objects, changeset, none]
|
|
143
|
+
enum: [object, objects, changeset, stream, none]
|
|
129
144
|
concurrency:
|
|
130
145
|
enum: [none, retry]
|
|
131
146
|
forward:
|
|
132
|
-
$ref:
|
|
147
|
+
$ref: "#/definitions/name"
|
|
133
148
|
bridge:
|
|
134
149
|
type: string
|
|
135
150
|
bindings:
|
|
136
|
-
$ref:
|
|
151
|
+
$ref: "#/properties/bindings"
|
|
152
|
+
description:
|
|
153
|
+
# what the operation is, for whoever reads it: a generated type, an OPTIONS, a model
|
|
154
|
+
type: string
|
|
137
155
|
input:
|
|
138
|
-
$ref:
|
|
156
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
139
157
|
output:
|
|
140
|
-
$ref:
|
|
158
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
159
|
+
errors:
|
|
160
|
+
# what a reply may carry as a code: the error schema allows either
|
|
161
|
+
type: array
|
|
162
|
+
items:
|
|
163
|
+
type: [string, integer]
|
|
141
164
|
query:
|
|
142
165
|
type: boolean
|
|
143
166
|
required: [type, scope, bindings]
|
|
@@ -149,8 +172,8 @@ properties:
|
|
|
149
172
|
then:
|
|
150
173
|
properties:
|
|
151
174
|
scope:
|
|
152
|
-
enum: [object]
|
|
153
|
-
if: #
|
|
175
|
+
enum: [object, objects]
|
|
176
|
+
if: # not query: false
|
|
154
177
|
not:
|
|
155
178
|
properties:
|
|
156
179
|
query:
|
|
@@ -158,6 +181,17 @@ properties:
|
|
|
158
181
|
required: [query]
|
|
159
182
|
then:
|
|
160
183
|
required: [concurrency]
|
|
184
|
+
- if: # transition and scope=objects
|
|
185
|
+
properties:
|
|
186
|
+
type:
|
|
187
|
+
const: transition
|
|
188
|
+
scope:
|
|
189
|
+
const: objects
|
|
190
|
+
then:
|
|
191
|
+
properties:
|
|
192
|
+
query:
|
|
193
|
+
not:
|
|
194
|
+
const: false
|
|
161
195
|
- if: # not transition
|
|
162
196
|
not:
|
|
163
197
|
properties:
|
|
@@ -174,7 +208,7 @@ properties:
|
|
|
174
208
|
then:
|
|
175
209
|
properties:
|
|
176
210
|
scope:
|
|
177
|
-
enum: [object, objects, none]
|
|
211
|
+
enum: [object, objects, stream, none]
|
|
178
212
|
query:
|
|
179
213
|
not:
|
|
180
214
|
const: false
|
|
@@ -189,15 +223,13 @@ properties:
|
|
|
189
223
|
- if: # computation
|
|
190
224
|
properties:
|
|
191
225
|
type:
|
|
192
|
-
|
|
226
|
+
enum: [computation, unmanaged]
|
|
193
227
|
then:
|
|
194
228
|
properties:
|
|
195
229
|
scope:
|
|
196
230
|
const: none
|
|
197
|
-
default: none
|
|
198
231
|
query:
|
|
199
232
|
const: false
|
|
200
|
-
default: false
|
|
201
233
|
- if: # effect
|
|
202
234
|
properties:
|
|
203
235
|
type:
|
|
@@ -205,20 +237,16 @@ properties:
|
|
|
205
237
|
then:
|
|
206
238
|
properties:
|
|
207
239
|
scope:
|
|
208
|
-
|
|
209
|
-
default: none
|
|
210
|
-
query:
|
|
211
|
-
const: false
|
|
212
|
-
default: false
|
|
240
|
+
enum: [object, objects, stream, none]
|
|
213
241
|
additionalProperties: false
|
|
214
242
|
additionalProperties: false
|
|
215
243
|
|
|
216
244
|
events:
|
|
217
245
|
type: object
|
|
218
246
|
propertyNames:
|
|
219
|
-
$ref:
|
|
247
|
+
$ref: "#/definitions/name"
|
|
220
248
|
patternProperties:
|
|
221
|
-
|
|
249
|
+
".*":
|
|
222
250
|
type: object
|
|
223
251
|
properties:
|
|
224
252
|
bridge:
|
|
@@ -226,43 +254,52 @@ properties:
|
|
|
226
254
|
path:
|
|
227
255
|
type: string
|
|
228
256
|
binding:
|
|
229
|
-
$ref:
|
|
257
|
+
$ref: "#/definitions/binding"
|
|
230
258
|
conditioned:
|
|
231
259
|
type: boolean
|
|
232
|
-
default: false
|
|
233
260
|
subjective:
|
|
234
261
|
type: boolean
|
|
235
|
-
default: false
|
|
236
262
|
required: [bridge, path]
|
|
237
263
|
additionalProperties: false
|
|
238
264
|
|
|
239
265
|
receivers:
|
|
240
266
|
type: object
|
|
241
267
|
patternProperties:
|
|
242
|
-
|
|
268
|
+
".*":
|
|
243
269
|
type: object
|
|
244
270
|
properties:
|
|
245
271
|
operation:
|
|
246
|
-
$ref:
|
|
272
|
+
$ref: "#/definitions/name"
|
|
247
273
|
bridge:
|
|
248
274
|
type: string
|
|
249
275
|
binding:
|
|
250
276
|
type: string
|
|
251
277
|
source:
|
|
252
|
-
$ref:
|
|
278
|
+
$ref: "#/definitions/name"
|
|
253
279
|
not:
|
|
254
280
|
const: context
|
|
255
281
|
path:
|
|
256
282
|
type: string
|
|
257
283
|
conditioned:
|
|
258
284
|
type: boolean
|
|
259
|
-
default: false
|
|
260
285
|
adaptive:
|
|
261
286
|
type: boolean
|
|
262
|
-
|
|
287
|
+
arguments:
|
|
288
|
+
type: array
|
|
263
289
|
required: [operation]
|
|
264
290
|
additionalProperties: false
|
|
265
291
|
|
|
292
|
+
guards:
|
|
293
|
+
type: object
|
|
294
|
+
patternProperties:
|
|
295
|
+
".*":
|
|
296
|
+
type: object
|
|
297
|
+
properties:
|
|
298
|
+
bridge: { type: string }
|
|
299
|
+
path: { type: string }
|
|
300
|
+
required: [bridge, path]
|
|
301
|
+
additionalProperties: false
|
|
302
|
+
|
|
266
303
|
extensions:
|
|
267
304
|
type: object
|
|
268
305
|
|