@toa.io/core 1.0.0-alpha.0 → 1.0.0-alpha.107

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 (48) hide show
  1. package/package.json +7 -8
  2. package/src/assignment.js +11 -2
  3. package/src/call.js +4 -0
  4. package/src/cascade.js +2 -3
  5. package/src/component.js +15 -18
  6. package/src/composition.js +1 -1
  7. package/src/connector.js +3 -8
  8. package/src/contract/contract.js +23 -0
  9. package/src/contract/reply.js +26 -9
  10. package/src/contract/request.js +33 -14
  11. package/src/contract/schemas/index.js +2 -3
  12. package/src/contract/schemas/query.yaml +2 -4
  13. package/src/discovery.js +2 -5
  14. package/src/effect.js +19 -0
  15. package/src/entities/changeset.js +8 -15
  16. package/src/entities/entity.js +31 -12
  17. package/src/entities/factory.js +6 -0
  18. package/src/exceptions.js +21 -19
  19. package/src/exposition.js +3 -2
  20. package/src/index.js +2 -0
  21. package/src/locator.js +7 -2
  22. package/src/observation.js +1 -13
  23. package/src/operation.js +29 -7
  24. package/src/query/criteria.js +3 -3
  25. package/src/query/options.js +3 -0
  26. package/src/receiver.js +13 -10
  27. package/src/remote.js +5 -7
  28. package/src/state.js +63 -45
  29. package/src/transition.js +9 -7
  30. package/src/transmission.js +12 -3
  31. package/test/component.test.js +2 -1
  32. package/test/contract/conditions.test.js +5 -5
  33. package/test/contract/request.test.js +30 -28
  34. package/test/entities/entity.fixtures.js +5 -2
  35. package/test/entities/entity.test.js +7 -46
  36. package/types/bindings.d.ts +3 -1
  37. package/types/bridges.ts +30 -0
  38. package/types/component.d.ts +4 -1
  39. package/types/context.d.ts +12 -18
  40. package/types/extensions.d.ts +4 -3
  41. package/types/index.ts +15 -0
  42. package/types/locator.d.ts +2 -1
  43. package/types/operations.d.ts +6 -0
  44. package/types/remote.d.ts +18 -0
  45. package/types/request.d.ts +1 -0
  46. package/src/contract/conditions.js +0 -21
  47. package/types/bridges.d.ts +0 -41
  48. package/types/index.d.ts +0 -14
package/src/exposition.js CHANGED
@@ -20,8 +20,9 @@ class Exposition extends Connector {
20
20
  }
21
21
 
22
22
  const expose = (manifest) => {
23
- const { namespace, name, operations, events } = manifest
24
- return { namespace, name, operations, events }
23
+ const { namespace, name, entity, operations, events } = manifest
24
+
25
+ return { namespace, name, entity, operations, events }
25
26
  }
26
27
 
27
28
  exports.Exposition = Exposition
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ const { Composition } = require('./composition')
5
5
  const { Connector } = require('./connector')
6
6
  const { Context } = require('./context')
7
7
  const { Discovery } = require('./discovery')
8
+ const { Effect } = require('./effect')
8
9
  const { Emission } = require('./emission')
9
10
  const { Event } = require('./event')
10
11
  const { Exposition } = require('./exposition')
@@ -32,6 +33,7 @@ exports.Composition = Composition
32
33
  exports.Connector = Connector
33
34
  exports.Context = Context
34
35
  exports.Discovery = Discovery
36
+ exports.Effect = Effect
35
37
  exports.Emission = Emission
36
38
  exports.Event = Event
37
39
  exports.Exposition = Exposition
package/src/locator.js CHANGED
@@ -12,6 +12,7 @@ class Locator {
12
12
  id
13
13
  label
14
14
  uppercase
15
+ lowercase
15
16
 
16
17
  /**
17
18
  * @param {string} name
@@ -26,6 +27,7 @@ class Locator {
26
27
  this.id = concat(namespace, '.') + name
27
28
  this.label = (concat(namespace, '-') + name).toLowerCase()
28
29
  this.uppercase = (concat(namespace, '_') + name).toUpperCase()
30
+ this.lowercase = (concat(namespace, '_') + name).toLowerCase()
29
31
  }
30
32
 
31
33
  hostname (prefix) {
@@ -39,8 +41,11 @@ class Locator {
39
41
  static parse (string) {
40
42
  const [namespace, name] = string.split(DOT)
41
43
 
42
- if (name === undefined) return new Locator(namespace)
43
- else return new Locator(name, namespace)
44
+ if (name === undefined) {
45
+ return new Locator(namespace)
46
+ } else {
47
+ return new Locator(name, namespace)
48
+ }
44
49
  }
45
50
  }
46
51
 
@@ -1,22 +1,10 @@
1
1
  'use strict'
2
2
 
3
- const { freeze } = require('@toa.io/generic')
4
-
5
3
  const { Operation } = require('./operation')
6
4
 
7
5
  class Observation extends Operation {
8
- async acquire (store) {
9
- const scope = await this.query(store.request.query)
10
- const state = scope === null ? null : scope.get()
11
-
12
- freeze(state)
13
-
14
- store.scope = scope
15
- store.state = state
16
- }
17
-
18
6
  async run (store) {
19
- if (store.scope === null) store.reply = null
7
+ if (store.scope === null || store.scope?.deleted === true) store.reply = null
20
8
  else await super.run(store)
21
9
  }
22
10
  }
package/src/operation.js CHANGED
@@ -1,7 +1,9 @@
1
1
  'use strict'
2
2
 
3
+ const { console } = require('openspan')
3
4
  const { Connector } = require('./connector')
4
- const { SystemException } = require('./exceptions')
5
+ const { SystemException, RequestContractException } = require('./exceptions')
6
+ const { Readable } = require('node:stream')
5
7
 
6
8
  class Operation extends Connector {
7
9
  scope
@@ -26,8 +28,15 @@ class Operation extends Connector {
26
28
 
27
29
  async invoke (request) {
28
30
  try {
29
- if (request.authentic !== true) this.#contracts.request.fit(request)
30
- if ('query' in request) request.query = this.#query.parse(request.query)
31
+ if (request.authentic !== true)
32
+ this.#contracts.request.fit(request)
33
+
34
+ if ('query' in request)
35
+ request.query = this.#query.parse(request.query)
36
+
37
+ // validate entity
38
+ if ('entity' in request)
39
+ this.scope.fit(request.entity)
31
40
 
32
41
  const store = { request }
33
42
 
@@ -47,14 +56,24 @@ class Operation extends Connector {
47
56
  return store.reply
48
57
  }
49
58
 
50
- async acquire () {}
59
+ async acquire (store) {
60
+ if (this.#scope === 'none')
61
+ return
62
+
63
+ const scope = await this.query(store.request.query)
64
+ const raw = scope === null || scope instanceof Readable
65
+
66
+ store.scope = scope
67
+ store.state = raw ? scope : scope.get()
68
+ }
51
69
 
52
70
  async run (store) {
53
71
  const { request, state } = store
54
- // noinspection UnnecessaryLocalVariableJS
55
- const reply = await this.#cascade.run(request.input, state) || {}
72
+ const reply = await this.#cascade.run(request.input, state)
56
73
 
57
- // this.#contracts.reply.fit(reply)
74
+ // validate reply only on local environments
75
+ if (process.env.TOA_ENV === 'local' && !(reply instanceof Readable))
76
+ this.#contracts.reply.fit(reply)
58
77
 
59
78
  store.reply = reply
60
79
  }
@@ -62,6 +81,9 @@ class Operation extends Connector {
62
81
  async commit () {}
63
82
 
64
83
  async query (query) {
84
+ if (query === undefined)
85
+ throw new RequestContractException('Request query is required')
86
+
65
87
  return this.scope[this.#scope](query)
66
88
  }
67
89
  }
@@ -33,9 +33,9 @@ const coerce = (node, properties) => {
33
33
  }
34
34
 
35
35
  const COERCE = {
36
- number: Number,
37
- integer: parseInt,
38
- boolean: Boolean
36
+ number: Number.parseFloat,
37
+ integer: Number.parseInt,
38
+ boolean: (value) => value === 'true'
39
39
  }
40
40
 
41
41
  exports.criteria = criteria
@@ -32,6 +32,9 @@ const projection = (projection, properties) => {
32
32
  throw new QuerySyntaxException(`Projection property '${property}' is not defined`)
33
33
  }
34
34
  }
35
+
36
+ if (projection.includes('_version') === false)
37
+ projection.push('_version')
35
38
  }
36
39
 
37
40
  exports.options = options
package/src/receiver.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { console } = require('openspan')
3
4
  const { add } = require('@toa.io/generic')
4
5
  const { Connector } = require('./connector')
5
6
 
@@ -16,18 +17,13 @@ class Receiver extends Connector {
16
17
  /** @type {string} */
17
18
  #endpoint
18
19
 
19
- /** @type {toa.core.Component} */
20
+ /** @type {unknown[]} */
21
+ #arguments
22
+
20
23
  #local
21
24
 
22
- /** @type {toa.core.bridges.Receiver} */
23
25
  #bridge
24
26
 
25
- /**
26
- *
27
- * @param {toa.norm.component.Receiver} definition
28
- * @param {toa.core.Component} local
29
- * @param {toa.core.bridges.Receiver} bridge
30
- */
31
27
  constructor (definition, local, bridge) {
32
28
  super()
33
29
 
@@ -36,6 +32,7 @@ class Receiver extends Connector {
36
32
  this.#conditioned = conditioned
37
33
  this.#adaptive = adaptive
38
34
  this.#endpoint = operation
35
+ this.#arguments = definition.arguments
39
36
 
40
37
  this.#local = local
41
38
  this.#bridge = bridge
@@ -54,11 +51,17 @@ class Receiver extends Connector {
54
51
 
55
52
  add(request, extensions)
56
53
 
57
- await this.#local.invoke(this.#endpoint, request)
54
+ try {
55
+ await this.#local.invoke(this.#endpoint, request)
56
+ } catch (error) {
57
+ console.error('Receiver error', error)
58
+
59
+ throw error
60
+ }
58
61
  }
59
62
 
60
63
  async #request (payload) {
61
- return this.#adaptive ? await this.#bridge.request(payload) : { input: payload }
64
+ return this.#adaptive ? await this.#bridge.request(payload, ...(this.#arguments ?? [])) : { input: payload }
62
65
  }
63
66
  }
64
67
 
package/src/remote.js CHANGED
@@ -1,16 +1,14 @@
1
1
  'use strict'
2
2
 
3
- const { console } = require('@toa.io/console')
4
-
3
+ const assert = require('node:assert')
5
4
  const { Component } = require('./component')
6
5
 
7
6
  class Remote extends Component {
8
- async open () {
9
- console.info(`Remote '${this.locator.id}' connected`)
10
- }
7
+ explain (endpoint) {
8
+ assert.ok(endpoint in this.operations,
9
+ `Endpoint '${endpoint}' is not provided by '${this.locator.id}'`)
11
10
 
12
- async dispose () {
13
- console.info(`Remote '${this.locator.id}' disconnected`)
11
+ return this.operations[endpoint].explain()
14
12
  }
15
13
  }
16
14
 
package/src/state.js CHANGED
@@ -1,68 +1,83 @@
1
1
  'use strict'
2
2
 
3
- const { empty } = require('@toa.io/generic')
3
+ const { empty, newid } = require('@toa.io/generic')
4
+ const { StatePreconditionException, StateNotFoundException } = require('./exceptions')
4
5
 
5
- const {
6
- StatePreconditionException,
7
- StateNotFoundException,
8
- StateInitializationException
9
- } = require('./exceptions')
10
-
11
- /**
12
- * @implements {toa.core.State}
13
- */
14
6
  class State {
15
- /** @type {toa.core.Storage} */
7
+ #associated
16
8
  #storage
17
-
18
- /** @type {toa.core.entity.Factory} */
19
- #entity
9
+ #entities
20
10
  #emission
21
- #initialized
22
11
 
23
- constructor (storage, entity, emission, initialized) {
12
+ constructor (storage, entity, emission, associated) {
24
13
  this.#storage = storage
25
- this.#entity = entity
14
+ this.#entities = entity
26
15
  this.#emission = emission
27
- this.#initialized = initialized
16
+ this.#associated = associated === true
28
17
  }
29
18
 
30
19
  init (id) {
31
- // if (this.#initialized === true && id === undefined) {
32
- // throw new StateInitializationException('Cannot initialize entity which is initialized. Use request.query.id to access.')
33
- // }
20
+ return this.#entities.init(id)
21
+ }
34
22
 
35
- return this.#entity.init(id)
23
+ fit (values) {
24
+ return this.#entities.fit(values)
36
25
  }
37
26
 
38
27
  async object (query) {
39
28
  const record = await this.#storage.get(query)
40
29
 
41
30
  if (record === null) {
42
- if (this.#initialized && query.id !== undefined && query.version === undefined) return this.init(query.id)
43
- else if (query.version !== undefined) throw new StatePreconditionException()
44
- }
45
-
46
- if (record === null) return null
47
- else return this.#entity.object(record)
31
+ if (this.#associated && query.id !== undefined && query.criteria === undefined && query.version === undefined)
32
+ return this.init(query.id)
33
+ else if (query.version !== undefined)
34
+ throw new StatePreconditionException()
35
+
36
+ return null
37
+ } else
38
+ return this.#entities.object(record)
48
39
  }
49
40
 
50
41
  async objects (query) {
51
42
  const recordset = await this.#storage.find(query)
52
43
 
53
- return this.#entity.objects(recordset)
44
+ return this.#entities.objects(recordset)
45
+ }
46
+
47
+ async stream (query) {
48
+ return this.#storage.stream(query)
54
49
  }
55
50
 
56
51
  changeset (query) {
57
- return this.#entity.changeset(query)
52
+ return this.#entities.changeset(query)
58
53
  }
59
54
 
60
55
  none () {
61
56
  return null
62
57
  }
63
58
 
64
- async commit (state) {
65
- const event = state.event()
59
+ async ensure (query, properties, input) {
60
+ const object = this.#entities.init()
61
+ const blank = object.get()
62
+
63
+ Object.assign(blank, properties)
64
+
65
+ object.set(blank)
66
+
67
+ const record = await this.#storage.ensure(query, properties, object.get())
68
+
69
+ if (record.id !== blank.id) // exists
70
+ return this.#entities.object(record)
71
+
72
+ const event = object.event(input)
73
+
74
+ await this.#emission.emit(event)
75
+
76
+ return object
77
+ }
78
+
79
+ async commit (state, input) {
80
+ const event = state.event(input)
66
81
 
67
82
  let ok = true
68
83
 
@@ -72,30 +87,33 @@ class State {
72
87
  ok = await this.#storage.store(object)
73
88
 
74
89
  // #20
75
- await this.#emission.emit(event)
90
+ if (ok === true)
91
+ await this.#emission.emit(event)
76
92
  }
77
93
 
78
94
  return ok
79
95
  }
80
96
 
81
97
  async apply (state) {
82
- const { changeset, insert } = state.export()
83
-
84
- let upsert
85
-
86
- if (this.#initialized && state.query.id !== undefined && state.query.version === undefined) {
87
- upsert = insert
88
- }
98
+ const changeset = state.export()
89
99
 
90
- const result = await this.#storage.upsert(state.query, changeset, upsert)
100
+ const result = await this.#storage.upsert(state.query, changeset)
91
101
 
92
102
  if (result === null) {
93
- if (state.query.version !== undefined) throw new StatePreconditionException()
94
- else throw new StateNotFoundException()
103
+ if (state.query.version !== undefined) {
104
+ throw new StatePreconditionException()
105
+ } else {
106
+ throw new StateNotFoundException()
107
+ }
108
+ } else {
109
+ // same as above
110
+ await this.#emission.emit({
111
+ changeset,
112
+ state: result
113
+ })
95
114
  }
96
115
 
97
- // same as above
98
- await this.#emission.emit({ changeset, state: result })
116
+ return result
99
117
  }
100
118
  }
101
119
 
package/src/transition.js CHANGED
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  const { retry } = require('@toa.io/generic')
4
-
5
4
  const { Operation } = require('./operation')
6
5
  const { StateConcurrencyException, StateNotFoundException } = require('./exceptions')
7
6
 
@@ -23,7 +22,8 @@ class Transition extends Operation {
23
22
 
24
23
  store.scope = request.query ? await this.query(request.query) : this.scope.init()
25
24
 
26
- if (store.scope === null) throw new StateNotFoundException()
25
+ if (store.scope === null || store.scope.deleted === true)
26
+ throw new StateNotFoundException()
27
27
 
28
28
  store.state = store.scope.get()
29
29
  }
@@ -35,11 +35,13 @@ class Transition extends Operation {
35
35
 
36
36
  scope.set(state)
37
37
 
38
- const ok = await this.scope.commit(scope)
38
+ const result = await this.scope.commit(scope, store.request.input)
39
39
 
40
- if (ok !== true) {
41
- if (this.#concurrency === 'retry') retry()
42
- else throw new StateConcurrencyException()
40
+ if (result === false) {
41
+ if (this.#concurrency === 'retry')
42
+ return retry()
43
+ else
44
+ throw new StateConcurrencyException()
43
45
  }
44
46
  }
45
47
 
@@ -54,7 +56,7 @@ const RETRY = {
54
56
  base: 10,
55
57
  max: 5000,
56
58
  dispersion: 1,
57
- retries: Infinity
59
+ retries: 32
58
60
  }
59
61
 
60
62
  exports.Transition = Transition
@@ -18,13 +18,22 @@ class Transmission extends Connector {
18
18
  let i = 0
19
19
 
20
20
  while (reply === false && i < this.#bindings.length) {
21
- reply = await this.#bindings[i].request(request)
21
+ const binding = this.#bindings[i]
22
+
22
23
  i++
24
+
25
+ if (request?.task === true) {
26
+ if (binding.task === undefined)
27
+ continue
28
+
29
+ await binding.task(request)
30
+ reply = null
31
+ } else
32
+ reply = await binding.request(request)
23
33
  }
24
34
 
25
- if (reply === false) {
35
+ if (reply === false)
26
36
  throw new TransmissionException(`All (${this.#bindings.length}) bindings rejected.`)
27
- }
28
37
 
29
38
  return reply
30
39
  }
@@ -3,6 +3,7 @@
3
3
  const { Component } = require('../src/component')
4
4
  const { codes } = require('../src/exceptions')
5
5
  const fixtures = require('./component.fixtures')
6
+ const { AssertionError } = require('node:assert')
6
7
 
7
8
  describe('Invocations', () => {
8
9
  const name = ['foo', 'bar'][Math.floor(2 * Math.random())]
@@ -21,7 +22,7 @@ describe('Invocations', () => {
21
22
 
22
23
  it('should throw on unknown invocation name', async () => {
23
24
  await expect(() => component.invoke('baz'))
24
- .rejects.toMatchObject({ code: codes.NotImplemented })
25
+ .rejects.toThrow(AssertionError)
25
26
  })
26
27
 
27
28
  it('should invoke input and query', async () => {
@@ -2,19 +2,19 @@
2
2
 
3
3
  const { generate } = require('randomstring')
4
4
 
5
- const { Conditions } = require('../../src/contract/conditions')
5
+ const { Contract } = require('../../src/contract/contract')
6
6
  const fixtures = require('./contract.fixtures')
7
7
 
8
- let conditions
8
+ let contract
9
9
 
10
10
  beforeEach(() => {
11
- conditions = new Conditions(fixtures.schema)
11
+ contract = new Contract(fixtures.schema)
12
12
  })
13
13
 
14
14
  it('should fit value', () => {
15
15
  const value = { foo: generate() }
16
16
 
17
- conditions.fit(value)
17
+ contract.fit(value)
18
18
 
19
19
  expect(fixtures.schema.fit).toHaveBeenCalledWith(value)
20
20
  })
@@ -22,5 +22,5 @@ it('should fit value', () => {
22
22
  it('should throw on invalid value', () => {
23
23
  const value = { invalid: true }
24
24
 
25
- expect(() => conditions.fit(value)).toThrow()
25
+ expect(() => contract.fit(value)).toThrow()
26
26
  })
@@ -3,10 +3,10 @@
3
3
  const clone = require('clone-deep')
4
4
  const { generate } = require('randomstring')
5
5
 
6
- jest.mock('../../src/contract/conditions')
6
+ jest.mock('../../src/contract/contract')
7
7
 
8
8
  const { Request } = require('../../src/contract/request')
9
- const { Conditions } = require('../../src/contract/conditions')
9
+ const { Contract } = require('../../src/contract/contract')
10
10
  const fixtures = require('./contract.fixtures')
11
11
 
12
12
  let contract
@@ -14,12 +14,14 @@ let contract
14
14
  beforeEach(() => {
15
15
  jest.clearAllMocks()
16
16
 
17
- contract = new Request(fixtures.schema)
17
+ contract = new Request(fixtures.schema, {})
18
18
  })
19
19
 
20
+ const dummy = { schema: { properties: {} } }
21
+
20
22
  it('should extend Conditions', () => {
21
- expect(contract).toBeInstanceOf(Conditions)
22
- expect(Conditions).toHaveBeenCalledWith(fixtures.schema)
23
+ expect(contract).toBeInstanceOf(Contract)
24
+ expect(Contract).toHaveBeenCalledWith(fixtures.schema)
23
25
  })
24
26
 
25
27
  it('should fit request', () => {
@@ -27,7 +29,7 @@ it('should fit request', () => {
27
29
 
28
30
  contract.fit(request)
29
31
 
30
- expect(Conditions.mock.instances[0].fit).toHaveBeenCalledWith(request)
32
+ expect(Contract.mock.instances[0].fit).toHaveBeenCalledWith(request)
31
33
  })
32
34
 
33
35
  describe('schema', () => {
@@ -38,73 +40,73 @@ describe('schema', () => {
38
40
  })
39
41
 
40
42
  it('should provide schema', () => {
41
- expect(Request.schema({})).toBeDefined()
43
+ expect(Request.schema({}, dummy)).toBeDefined()
42
44
  })
43
45
 
44
46
  it('should add required input if defined', () => {
45
47
  const input = { type: 'number' }
46
48
 
47
- expect(Request.schema({ input }).properties.input).toStrictEqual(input)
49
+ expect(Request.schema({ input }, dummy).properties.input).toStrictEqual(input)
48
50
  })
49
51
 
50
52
  it('should set input as null if undefined', async () => {
51
- expect(Request.schema({}).properties.input).toStrictEqual({ type: 'null' })
53
+ expect(Request.schema({}, dummy).properties.input).toStrictEqual({ type: 'null' })
52
54
  })
53
55
 
54
56
  it('should contain query if declaration.query is not defined', () => {
55
- expect(Request.schema({}).properties.query).toBeDefined()
57
+ expect(Request.schema({}, dummy).properties.query).toBeDefined()
56
58
  })
57
59
 
58
60
  it('should not contain query if declaration.query is false', () => {
59
- delete schema.properties.query
60
- schema.not = { required: ['query'] }
61
- expect(Request.schema({ query: false })).toStrictEqual(schema)
61
+ schema.properties.query = { type: 'null' }
62
+ expect(Request.schema({ query: false }, dummy)).toMatchObject(schema)
62
63
  })
63
64
 
64
65
  it('should require query if declaration.query is true', () => {
65
66
  schema.required = ['query']
66
- expect(Request.schema({ query: true }).required).toStrictEqual(expect.arrayContaining(['query']))
67
+ expect(Request.schema({ query: true }, dummy).required).toStrictEqual(expect.arrayContaining(['query']))
67
68
  })
68
69
 
69
70
  it('should forbid projection for non observations', () => {
70
- expect(Request.schema({ type: 'transition' }).properties.query.properties.projection)
71
+ expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.projection)
71
72
  .toBe(undefined)
72
73
 
73
- expect(Request.schema({ type: 'assignment' }).properties.query.properties.projection)
74
+ expect(Request.schema({ type: 'assignment' }, dummy).properties.query.properties.projection)
74
75
  .toBe(undefined)
75
76
 
76
- expect(Request.schema({ type: 'observation' }).properties.query.properties.projection)
77
+ expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.projection)
77
78
  .toBeDefined()
78
79
  })
79
80
 
80
81
  it('should forbid version for observations', () => {
81
- expect(Request.schema({ type: 'transition' }).properties.query.properties.version)
82
+ expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.version)
82
83
  .toBeDefined()
83
84
 
84
- expect(Request.schema({ type: 'observation' }).properties.query.properties.version)
85
+ expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.version)
85
86
  .toBe(undefined)
86
87
  })
87
88
 
88
89
  it('should allow omit, limit only for set observations', () => {
89
- const transition = Request.schema({ type: 'transition' }).properties.query.properties
90
+ const schema = Request.schema({ type: 'transition' }, dummy)
91
+ const transition = schema.properties.query.properties
90
92
 
91
93
  expect(transition.omit).toBeUndefined()
92
94
  expect(transition.limit).toBeUndefined()
93
95
 
94
- const entity = Request.schema({
96
+ const object = Request.schema({
95
97
  type: 'observation',
96
98
  scope: 'object'
97
- }).properties.query.properties
99
+ }, dummy).properties.query.properties
98
100
 
99
- expect(entity.omit).toBeUndefined()
100
- expect(entity.limit).toBeUndefined()
101
+ expect(object.omit).toBeUndefined()
102
+ expect(object.limit).toBeUndefined()
101
103
 
102
- const set = Request.schema({
104
+ const objects = Request.schema({
103
105
  type: 'observation',
104
106
  scope: 'objects'
105
- }).properties.query.properties
107
+ }, dummy).properties.query.properties
106
108
 
107
- expect(set.omit).toBeDefined()
108
- expect(set.limit).toBeDefined()
109
+ expect(objects.omit).toBeDefined()
110
+ expect(objects.limit).toBeDefined()
109
111
  })
110
112
  })