@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.
Files changed (85) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/package.json +8 -7
  3. package/src/.component/.expand/bridge.js +2 -6
  4. package/src/.component/.expand/entity.js +2 -9
  5. package/src/.component/.expand/events.js +2 -6
  6. package/src/.component/.expand/extensions.js +5 -8
  7. package/src/.component/.expand/index.js +8 -19
  8. package/src/.component/.expand/operations.js +2 -9
  9. package/src/.component/.expand/properties.js +2 -6
  10. package/src/.component/.expand/receivers.js +4 -7
  11. package/src/.component/.expand/version.js +38 -28
  12. package/src/.component/.normalize/entity.js +7 -0
  13. package/src/.component/.normalize/events.js +15 -5
  14. package/src/.component/.normalize/index.js +4 -9
  15. package/src/.component/.normalize/operations.js +10 -6
  16. package/src/.component/.normalize/receivers.js +4 -5
  17. package/src/.component/collapse.js +60 -9
  18. package/src/.component/defaults.js +16 -10
  19. package/src/.component/dependencies.js +14 -10
  20. package/src/.component/dereference.js +20 -18
  21. package/src/.component/expand.js +3 -7
  22. package/src/.component/extensions.js +15 -8
  23. package/src/.component/index.js +10 -21
  24. package/src/.component/merge.js +24 -13
  25. package/src/.component/migrations.js +57 -0
  26. package/src/.component/normalize.js +10 -6
  27. package/src/.component/schema.yaml +108 -71
  28. package/src/.component/validate.js +36 -17
  29. package/src/.context/.dependencies/connectors.js +5 -9
  30. package/src/.context/.dependencies/describe.js +4 -5
  31. package/src/.context/.dependencies/extensions.js +62 -20
  32. package/src/.context/.dependencies/index.js +3 -9
  33. package/src/.context/.dependencies/load.js +17 -14
  34. package/src/.context/.dependencies/resolve.js +23 -6
  35. package/src/.context/complete.js +1 -5
  36. package/src/.context/dependencies.js +2 -6
  37. package/src/.context/dereference.js +11 -6
  38. package/src/.context/expand.js +8 -6
  39. package/src/.context/index.js +6 -15
  40. package/src/.context/normalize.js +7 -5
  41. package/src/.context/schema.yaml +132 -11
  42. package/src/.context/validate.js +8 -14
  43. package/src/component.js +36 -17
  44. package/src/context.js +26 -14
  45. package/src/entity.js +15 -0
  46. package/src/index.js +4 -9
  47. package/src/shortcuts.js +8 -13
  48. package/test/component/collapse.fixtures.js +30 -39
  49. package/test/component/collapse.test.js +90 -10
  50. package/test/component/dependencies.test.js +16 -14
  51. package/test/component/dereference.fixtures.js +15 -24
  52. package/test/component/dereference.test.js +18 -8
  53. package/test/component/dummies/extension/index.js +1 -5
  54. package/test/component/dummies/migrations/conflicting/migrations/0001-one.yaml +2 -0
  55. package/test/component/dummies/migrations/conflicting/migrations/0001-one.yml +2 -0
  56. package/test/component/dummies/migrations/malformed/migrations/0001-one.yaml +1 -0
  57. package/test/component/dummies/migrations/ordered/migrations/0001-first.yml +4 -0
  58. package/test/component/dummies/migrations/ordered/migrations/0002-second.yaml +4 -0
  59. package/test/component/dummies/migrations/ordered/migrations/0010-third.json +1 -0
  60. package/test/component/dummies/migrations/stateless/migrations/0001-one.yaml +2 -0
  61. package/test/component/expand.fixtures.js +13 -13
  62. package/test/component/expand.test.js +25 -10
  63. package/test/component/migrations.test.js +62 -0
  64. package/test/component/normalize.fixtures.js +3 -7
  65. package/test/component/normalize.test.js +86 -28
  66. package/test/component/validate.fixtures.js +15 -13
  67. package/test/component/validate.test.js +162 -109
  68. package/test/context/complete.fixtures.js +2 -8
  69. package/test/context/complete.test.js +14 -8
  70. package/test/context/dependencies.load.test.js +13 -12
  71. package/test/context/dereference.fixtures.js +3 -9
  72. package/test/context/dereference.test.js +18 -7
  73. package/test/context/expand.fixtures.js +1 -5
  74. package/test/context/expand.test.js +36 -8
  75. package/test/context/normalize.fixtures.js +2 -7
  76. package/test/context/normalize.test.js +33 -9
  77. package/test/context/validate.fixtures.js +1 -6
  78. package/test/context/validate.test.js +81 -37
  79. package/test/shortcuts.fixtures.js +4 -9
  80. package/test/shortcuts.test.js +17 -15
  81. package/types/component.d.ts +17 -3
  82. package/types/context/declaration.d.ts +26 -3
  83. package/types/context.d.ts +15 -13
  84. package/types/entity.d.ts +7 -0
  85. package/types/index.d.ts +4 -3
@@ -1,17 +1,15 @@
1
- 'use strict'
1
+ import { merge } from '@toa.io/generic'
2
2
 
3
- const { merge } = require('@toa.io/generic')
4
-
5
- const dereference = (manifest) => {
3
+ export const dereference = (manifest) => {
6
4
  // schemas
7
- const resolver = createResolver(manifest.entity?.schema?.properties)
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 ('operations' in manifest)
13
- operations(manifest, resolver)
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 (manifest, resolver) {
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
- if (operation.output !== undefined) operation.output = schema(operation.output, resolver)
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] === '.') return resolve(object.default.substring(1))
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 === '.') object.properties[name] = resolve(name)
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) throw new Error(`Referenced operation '${operation.forward}' is not defined`)
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
@@ -1,6 +1,4 @@
1
- 'use strict'
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
- } = require('./.expand')
10
+ } from './.expand/index.js'
13
11
 
14
- async function expand (manifest) {
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
- 'use strict'
1
+ import { find } from '@toa.io/generic'
2
+ import { resolve } from '../shortcuts.js'
2
3
 
3
- const { directory: { find } } = require('@toa.io/filesystem')
4
- const { resolve } = require('../shortcuts')
4
+ const cache = {}
5
5
 
6
- const extensions = (manifest) => {
7
- if (manifest.extensions === undefined) return
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
- const extension = require(key)
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) throw new Error(`Extension '${reference}' hasn't returned manifest`)
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
- exports.extensions = extensions
35
+ const PREDEFINED = {
36
+ '@toa.io/extensions.telemetry': null,
37
+ '@toa.io/extensions.fetch': null,
38
+ '@toa.io/extensions.introspection': null
39
+ }
@@ -1,21 +1,10 @@
1
- 'use strict'
2
-
3
- const { collapse } = require('./collapse')
4
- const { defaults } = require('./defaults')
5
- const { dependencies } = require('./dependencies')
6
- const { dereference } = require('./dereference')
7
- const { expand } = require('./expand')
8
- const { merge } = require('./merge')
9
- const { normalize } = require('./normalize')
10
- const { validate } = require('./validate')
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'
@@ -1,12 +1,11 @@
1
- 'use strict'
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 } = require(bridge)
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
- if (declared === undefined) manifest[property][endpoint] = item
48
- else merge(declared, item)
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 } = require(bridge)
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
- exports.merge = bridge
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
- 'use strict'
1
+ import { entity, events, operations, receivers } from './.normalize/index.js'
2
2
 
3
- const { events, operations, receivers } = require('./.normalize')
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
- const normalize = (component) => {
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: '@toa.io/bindings.loop' # loop is for system use only
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: '#/properties/prototype'
20
+ $ref: "#/properties/prototype"
21
21
  path:
22
22
  type: string
23
23
  operations:
24
24
  type: object
25
25
  propertyNames:
26
- $ref: '#/definitions/name'
26
+ $ref: "#/definitions/name"
27
27
  patternProperties:
28
- '.*':
28
+ ".*":
29
29
  type: object
30
30
  properties:
31
31
  bridge:
32
- $ref: '#/properties/bridge'
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
- $ref: 'definitions#/definitions/locator'
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
- $ref: 'definitions#/definitions/label'
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
- $ref: 'definitions#/definitions/token'
48
+ type: string
49
+ pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
47
50
 
48
51
  namespace:
49
- $ref: 'definitions#/definitions/token'
50
- default: 'default'
52
+ type: string
53
+ pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
51
54
  not:
52
55
  oneOf:
53
- - const: 'system'
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
- default: '@toa.io/storages.mongodb'
70
- schema:
71
- $ref: 'definitions#/definitions/schema'
74
+ properties:
72
75
  type: object
73
- properties:
74
- type:
75
- default: object
76
- const: object
77
- properties:
78
- type: object
79
- propertyNames:
80
- oneOf:
81
- - $ref: '#/definitions/name'
82
- - enum: [_version, _created, _updated, _deleted]
83
- unique:
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
- patternProperties:
86
- '.*':
87
- type: array
88
- items:
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
- index:
91
- type: object
92
- patternProperties:
93
- '.*':
94
- type: object
95
- patternProperties:
96
- '.*':
97
- type: string
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
- default: false
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: '#/definitions/binding'
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: '#/definitions/name'
127
+ $ref: "#/definitions/name"
121
128
  patternProperties:
122
- '.*':
129
+ ".*":
123
130
  type: object
124
131
  properties:
125
132
  type:
126
- enum: [transition, observation, assignment, computation, effect]
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: '#/definitions/name'
147
+ $ref: "#/definitions/name"
133
148
  bridge:
134
149
  type: string
135
150
  bindings:
136
- $ref: '#/properties/bindings'
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: 'definitions#/definitions/schema'
156
+ $ref: https://json-schema.org/draft/2019-09/schema
139
157
  output:
140
- $ref: 'definitions#/definitions/schema'
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: # transition query: false
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
- const: computation
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
- const: none
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: 'definitions#/definitions/name'
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: '#/definitions/binding'
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: 'definitions#/definitions/name'
272
+ $ref: "#/definitions/name"
247
273
  bridge:
248
274
  type: string
249
275
  binding:
250
276
  type: string
251
277
  source:
252
- $ref: 'definitions#/definitions/name'
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
- default: false
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