@toa.io/core 1.0.0-alpha.291 → 1.0.0-alpha.293
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/package.json +11 -5
- package/CHANGELOG.md +0 -35
- package/source/assignment.ts +0 -27
- package/source/call.ts +0 -63
- package/source/cascade.ts +0 -32
- package/source/component.ts +0 -83
- package/source/composition.ts +0 -27
- package/source/connector.ts +0 -217
- package/source/context.ts +0 -68
- package/source/contract/contract.ts +0 -23
- package/source/contract/index.ts +0 -2
- package/source/contract/reply.ts +0 -56
- package/source/contract/request.ts +0 -140
- package/source/contract/schemas.ts +0 -39
- package/source/discovery.ts +0 -53
- package/source/effect.ts +0 -14
- package/source/emission.ts +0 -21
- package/source/entities/changeset.ts +0 -37
- package/source/entities/entity.ts +0 -137
- package/source/entities/factory.ts +0 -52
- package/source/entities/index.ts +0 -4
- package/source/entities/newid.ts +0 -9
- package/source/entities/set.ts +0 -27
- package/source/event.ts +0 -57
- package/source/exceptions.ts +0 -133
- package/source/exposition.ts +0 -33
- package/source/guard.ts +0 -16
- package/source/index.ts +0 -36
- package/source/locator.ts +0 -37
- package/source/observation.ts +0 -16
- package/source/operation.ts +0 -139
- package/source/outbox/index.ts +0 -1
- package/source/outbox/outbox.ts +0 -341
- package/source/query/criteria.ts +0 -90
- package/source/query/options.ts +0 -35
- package/source/query.ts +0 -67
- package/source/receiver.ts +0 -120
- package/source/reflection.ts +0 -20
- package/source/remote.ts +0 -20
- package/source/state.ts +0 -179
- package/source/transition.ts +0 -79
- package/source/transmission.ts +0 -38
- package/source/types/atomicity.ts +0 -63
- package/source/types/bindings.ts +0 -59
- package/source/types/bridges.ts +0 -54
- package/source/types/extensions.ts +0 -89
- package/source/types/index.ts +0 -14
- package/source/types/message.ts +0 -5
- package/source/types/operations.ts +0 -31
- package/source/types/outbox.ts +0 -35
- package/source/types/receiver.ts +0 -10
- package/source/types/request.ts +0 -54
- package/source/types/state.ts +0 -9
- package/source/types/storages.ts +0 -134
- package/source/unmanaged.ts +0 -8
- package/test/call.fixtures.js +0 -25
- package/test/call.test.js +0 -79
- package/test/component.fixtures.js +0 -18
- package/test/component.test.js +0 -57
- package/test/connector.fixtures.js +0 -56
- package/test/connector.test.js +0 -266
- package/test/context.fixtures.js +0 -14
- package/test/context.test.js +0 -40
- package/test/contract/conditions.test.js +0 -32
- package/test/contract/contract.fixtures.js +0 -28
- package/test/contract/request.test.js +0 -196
- package/test/discovery.test.js +0 -71
- package/test/emission.fixtures.js +0 -13
- package/test/emission.test.js +0 -60
- package/test/entities/entity.fixtures.js +0 -24
- package/test/entities/entity.test.js +0 -137
- package/test/entities/factory.fixtures.js +0 -31
- package/test/entities/factory.test.js +0 -99
- package/test/entities/set.fixtures.js +0 -9
- package/test/entities/set.test.js +0 -13
- package/test/event.fixtures.js +0 -24
- package/test/event.test.js +0 -162
- package/test/locator.test.js +0 -120
- package/test/outbox.test.js +0 -202
- package/test/query.fixtures.js +0 -96
- package/test/query.test.js +0 -183
- package/test/receiver.fixtures.js +0 -20
- package/test/receiver.test.js +0 -144
- package/test/reflection.test.js +0 -31
- package/test/state.fixtures.js +0 -49
- package/test/state.test.js +0 -162
- package/test/transmission.fixtures.js +0 -13
- package/test/transmission.test.js +0 -77
- package/tsconfig.json +0 -10
- package/tsconfig.tsbuildinfo +0 -1
package/test/connector.test.js
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { timeout } from '@toa.io/generic'
|
|
5
|
-
|
|
6
|
-
import * as fixtures from './connector.fixtures.js'
|
|
7
|
-
|
|
8
|
-
let sequence
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
sequence = []
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
describe('callbacks', () => {
|
|
15
|
-
let a
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
a = new fixtures.TestConnector('a', sequence)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('should call connection', async () => {
|
|
22
|
-
await a.connect()
|
|
23
|
-
assert.deepStrictEqual(sequence, ['+a'])
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('should call disconnection', async () => {
|
|
27
|
-
await a.connect()
|
|
28
|
-
await a.disconnect()
|
|
29
|
-
|
|
30
|
-
assert.ok(sequence.indexOf('+a') < sequence.indexOf('-a'))
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should reconnect', async () => {
|
|
34
|
-
await a.connect()
|
|
35
|
-
await a.reconnect()
|
|
36
|
-
await a.reconnect()
|
|
37
|
-
|
|
38
|
-
assert.deepStrictEqual(sequence, ['+a', '-a', '*a', '+a', '-a', '*a', '+a'])
|
|
39
|
-
})
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
describe('dependencies', () => {
|
|
43
|
-
let a
|
|
44
|
-
let b
|
|
45
|
-
let c
|
|
46
|
-
let d
|
|
47
|
-
|
|
48
|
-
beforeEach(() => {
|
|
49
|
-
a = new fixtures.TestConnector('a', sequence)
|
|
50
|
-
b = new fixtures.TestConnector('b', sequence)
|
|
51
|
-
c = new fixtures.TestConnector('c', sequence)
|
|
52
|
-
d = new fixtures.TestConnector('d', sequence)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should wait dependencies on connection', async () => {
|
|
56
|
-
a.depends(b).depends(c)
|
|
57
|
-
a.depends(d)
|
|
58
|
-
|
|
59
|
-
await a.connect()
|
|
60
|
-
|
|
61
|
-
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+b'))
|
|
62
|
-
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
63
|
-
assert.ok(sequence.indexOf('+d') < sequence.indexOf('+a'))
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('should wait array of connectors', async () => {
|
|
67
|
-
a.depends([b, d])
|
|
68
|
-
b.depends(c)
|
|
69
|
-
d.depends(c)
|
|
70
|
-
|
|
71
|
-
await a.connect()
|
|
72
|
-
|
|
73
|
-
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+b'))
|
|
74
|
-
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+d'))
|
|
75
|
-
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
76
|
-
assert.ok(sequence.indexOf('+d') < sequence.indexOf('+a'))
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('should wait array(1) of connectors', async () => {
|
|
80
|
-
a.depends([b])
|
|
81
|
-
b.depends(c)
|
|
82
|
-
|
|
83
|
-
await a.connect()
|
|
84
|
-
|
|
85
|
-
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+b'))
|
|
86
|
-
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('should throw on empty array', async () => {
|
|
90
|
-
assert.throws(
|
|
91
|
-
() => a.depends([]),
|
|
92
|
-
(error) => /must not be empty/.test(error.message)
|
|
93
|
-
)
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('should await 2-way dependencies', async () => {
|
|
97
|
-
a.depends([b, c, d])
|
|
98
|
-
d.depends([b, c])
|
|
99
|
-
|
|
100
|
-
await a.connect()
|
|
101
|
-
|
|
102
|
-
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
103
|
-
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+a'))
|
|
104
|
-
assert.ok(sequence.indexOf('+d') < sequence.indexOf('+a'))
|
|
105
|
-
|
|
106
|
-
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+d'))
|
|
107
|
-
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+d'))
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
it('should disconnect before dependencies', async () => {
|
|
111
|
-
a.depends(b).depends(c)
|
|
112
|
-
b.depends(d)
|
|
113
|
-
|
|
114
|
-
await a.connect()
|
|
115
|
-
await a.disconnect()
|
|
116
|
-
|
|
117
|
-
assert.ok(sequence.indexOf('-a') < sequence.indexOf('-b'))
|
|
118
|
-
assert.ok(sequence.indexOf('-b') < sequence.indexOf('-c'))
|
|
119
|
-
assert.ok(sequence.indexOf('-b') < sequence.indexOf('-d'))
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('should call disconnected', async () => {
|
|
123
|
-
a.depends(b).depends(c)
|
|
124
|
-
b.depends(d)
|
|
125
|
-
|
|
126
|
-
await a.disconnect()
|
|
127
|
-
|
|
128
|
-
assert.ok(sequence.indexOf('*c') < sequence.indexOf('*b'))
|
|
129
|
-
assert.ok(sequence.indexOf('*b') < sequence.indexOf('*a'))
|
|
130
|
-
assert.ok(sequence.indexOf('*d') < sequence.indexOf('*b'))
|
|
131
|
-
assert.strictEqual(sequence.indexOf('*a'), sequence.length - 1)
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
it('should disconnect if no parents left', async () => {
|
|
135
|
-
a.depends(c)
|
|
136
|
-
b.depends(c)
|
|
137
|
-
|
|
138
|
-
await a.connect()
|
|
139
|
-
await b.connect()
|
|
140
|
-
|
|
141
|
-
assert.deepStrictEqual(sequence, ['+c', '+a', '+b'])
|
|
142
|
-
|
|
143
|
-
await a.disconnect()
|
|
144
|
-
|
|
145
|
-
assert.deepStrictEqual(sequence, ['+c', '+a', '+b', '-a', '*a'])
|
|
146
|
-
|
|
147
|
-
await b.disconnect()
|
|
148
|
-
|
|
149
|
-
assert.deepStrictEqual(sequence, [
|
|
150
|
-
'+c',
|
|
151
|
-
'+a',
|
|
152
|
-
'+b',
|
|
153
|
-
'-a',
|
|
154
|
-
'*a',
|
|
155
|
-
'-b',
|
|
156
|
-
'-c',
|
|
157
|
-
'*c',
|
|
158
|
-
'*b'
|
|
159
|
-
])
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
it('should throw if depends not on Connector', async () => {
|
|
163
|
-
assert.throws(() => a.depends({}))
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
it('should disconnect while still connecting', async () => {
|
|
167
|
-
const stuck = new fixtures.StuckConnector()
|
|
168
|
-
|
|
169
|
-
a.depends(stuck).depends(b)
|
|
170
|
-
|
|
171
|
-
void a.connect()
|
|
172
|
-
|
|
173
|
-
while (b.connected !== true) await timeout(1)
|
|
174
|
-
|
|
175
|
-
// `a` never connects, and disconnecting must not wait for it to
|
|
176
|
-
assert.deepStrictEqual(a.connected, false)
|
|
177
|
-
|
|
178
|
-
await a.disconnect()
|
|
179
|
-
|
|
180
|
-
assert.deepStrictEqual(sequence, ['+b', '-b', '*b', '*a'])
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
it('should disconnect a dependency taken on after disconnection', async () => {
|
|
184
|
-
a.depends(b)
|
|
185
|
-
|
|
186
|
-
await a.connect()
|
|
187
|
-
await a.disconnect()
|
|
188
|
-
|
|
189
|
-
// what a lookup that returns once the teardown walk has gone by amounts to
|
|
190
|
-
a.depends(c)
|
|
191
|
-
|
|
192
|
-
await c.connect()
|
|
193
|
-
|
|
194
|
-
assert.strictEqual(c.connected, false)
|
|
195
|
-
assert.ok(sequence.indexOf('*c') > sequence.indexOf('*a'))
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
it('should disconnect a connected dependency taken on after disconnection', async () => {
|
|
199
|
-
a.depends(b)
|
|
200
|
-
|
|
201
|
-
await a.connect()
|
|
202
|
-
await a.disconnect()
|
|
203
|
-
await c.connect()
|
|
204
|
-
|
|
205
|
-
a.depends(c)
|
|
206
|
-
|
|
207
|
-
// the discarding is not something the caller waits for
|
|
208
|
-
for (let i = 0; c.connected && i < 100; i++) await timeout(1)
|
|
209
|
-
|
|
210
|
-
assert.strictEqual(c.connected, false)
|
|
211
|
-
assert.ok(sequence.includes('*c'))
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
it('should not connect what was disconnected while connecting', async () => {
|
|
215
|
-
const late = new fixtures.LateConnector()
|
|
216
|
-
|
|
217
|
-
late.depends(c)
|
|
218
|
-
b.depends(c)
|
|
219
|
-
|
|
220
|
-
await b.connect()
|
|
221
|
-
|
|
222
|
-
const connecting = late.connect()
|
|
223
|
-
|
|
224
|
-
await late.disconnect()
|
|
225
|
-
|
|
226
|
-
late.arrive()
|
|
227
|
-
|
|
228
|
-
await connecting
|
|
229
|
-
|
|
230
|
-
// the connection landed after the disconnection, and nothing is left to say it again
|
|
231
|
-
assert.strictEqual(late.connected, false)
|
|
232
|
-
|
|
233
|
-
await b.disconnect()
|
|
234
|
-
|
|
235
|
-
assert.strictEqual(c.connected, false)
|
|
236
|
-
assert.ok(sequence.includes('*c'))
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
describe('errors', () => {
|
|
240
|
-
let f
|
|
241
|
-
|
|
242
|
-
beforeEach(() => {
|
|
243
|
-
f = new fixtures.FailingConnector()
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
it('should disconnect on fail', async () => {
|
|
247
|
-
f.depends(b).depends(c)
|
|
248
|
-
|
|
249
|
-
await assert.rejects(f.connect(), (error) => /FailingConnector/.test(error.message))
|
|
250
|
-
assert.deepStrictEqual(sequence, ['+c', '+b', '-b', '-c', '*c', '*b'])
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
it('should interrupt connection chain', async () => {
|
|
254
|
-
a.depends(f).depends(c)
|
|
255
|
-
f.depends(d)
|
|
256
|
-
|
|
257
|
-
await assert.rejects(a.connect(), (error) => /FailingConnector/.test(error.message))
|
|
258
|
-
|
|
259
|
-
assert.ok(sequence.indexOf('+c') < sequence.indexOf('-c'))
|
|
260
|
-
assert.ok(sequence.indexOf('+d') < sequence.indexOf('-d'))
|
|
261
|
-
|
|
262
|
-
assert.strictEqual(sequence.indexOf('+a'), -1)
|
|
263
|
-
assert.strictEqual(sequence.indexOf('-a'), -1)
|
|
264
|
-
})
|
|
265
|
-
})
|
|
266
|
-
})
|
package/test/context.fixtures.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { mock } from 'node:test'
|
|
2
|
-
|
|
3
|
-
import { Connector } from '../source/connector.js'
|
|
4
|
-
|
|
5
|
-
export const local = {
|
|
6
|
-
link: mock.fn()
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const discover = mock.fn(() => ({
|
|
10
|
-
invoke: mock.fn(),
|
|
11
|
-
link: mock.fn()
|
|
12
|
-
}))
|
|
13
|
-
|
|
14
|
-
export const aspects = [new Connector(), new Connector()]
|
package/test/context.test.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import * as fixtures from './context.fixtures.js'
|
|
5
|
-
import { Context } from '../source/context.js'
|
|
6
|
-
|
|
7
|
-
/** @type {import('@toa.io/core').Context} */
|
|
8
|
-
let context
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
resetCalls()
|
|
12
|
-
|
|
13
|
-
context = new Context(fixtures.local, fixtures.discover, fixtures.aspects)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('should expose aspects', () => {
|
|
17
|
-
assert.notStrictEqual(context.aspects, undefined)
|
|
18
|
-
assert.deepStrictEqual(context.aspects, fixtures.aspects)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
describe('call', () => {
|
|
22
|
-
it('should discover once', async () => {
|
|
23
|
-
const request = {}
|
|
24
|
-
|
|
25
|
-
await context.call('a', 'b', 'c', request)
|
|
26
|
-
await context.call('a', 'b', 'c', request)
|
|
27
|
-
|
|
28
|
-
assert.strictEqual(fixtures.discover.mock.callCount(), 1)
|
|
29
|
-
})
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
function resetCalls(target = [assert, fixtures], seen = new Set()) {
|
|
33
|
-
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
34
|
-
|
|
35
|
-
seen.add(target)
|
|
36
|
-
|
|
37
|
-
for (const value of Object.values(target))
|
|
38
|
-
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
39
|
-
else resetCalls(value, seen)
|
|
40
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { it, beforeEach } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { isDeepStrictEqual } from 'node:util'
|
|
4
|
-
|
|
5
|
-
import { generate } from 'randomstring'
|
|
6
|
-
|
|
7
|
-
import { Contract } from '../../source/contract/contract.js'
|
|
8
|
-
import * as fixtures from './contract.fixtures.js'
|
|
9
|
-
|
|
10
|
-
let contract
|
|
11
|
-
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
contract = new Contract(fixtures.schema)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('should fit value', () => {
|
|
17
|
-
const value = { foo: generate() }
|
|
18
|
-
|
|
19
|
-
contract.fit(value)
|
|
20
|
-
|
|
21
|
-
assert.ok(
|
|
22
|
-
fixtures.schema.fit.mock.calls.some(
|
|
23
|
-
(call) => call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], value)
|
|
24
|
-
)
|
|
25
|
-
)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('should throw on invalid value', () => {
|
|
29
|
-
const value = { invalid: true }
|
|
30
|
-
|
|
31
|
-
assert.throws(() => contract.fit(value))
|
|
32
|
-
})
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { mock } from 'node:test'
|
|
2
|
-
|
|
3
|
-
import { generate } from 'randomstring'
|
|
4
|
-
|
|
5
|
-
import { query as querySchema } from '../../source/contract/schemas.js'
|
|
6
|
-
|
|
7
|
-
// noinspection JSCheckFunctionSignatures
|
|
8
|
-
export const schema = {
|
|
9
|
-
fit: mock.fn((input) => (input.invalid ? { message: generate() } : null))
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const query = {
|
|
13
|
-
parse: mock.fn(() => ({ [generate()]: generate() }))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const declaration = {}
|
|
17
|
-
|
|
18
|
-
export const schemas = {
|
|
19
|
-
request: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
properties: {
|
|
22
|
-
input: { type: 'null' },
|
|
23
|
-
query: querySchema,
|
|
24
|
-
authentic: { type: 'boolean' }
|
|
25
|
-
},
|
|
26
|
-
additionalProperties: true
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import * as schemas from '@toa.io/schemas'
|
|
2
|
-
import { describe, it, beforeEach, mock } from 'node:test'
|
|
3
|
-
import assert from 'node:assert/strict'
|
|
4
|
-
import { isDeepStrictEqual } from 'node:util'
|
|
5
|
-
|
|
6
|
-
import clone from 'clone-deep'
|
|
7
|
-
import { generate } from 'randomstring'
|
|
8
|
-
|
|
9
|
-
import { Request } from '../../source/contract/request.js'
|
|
10
|
-
import { Contract } from '../../source/contract/contract.js'
|
|
11
|
-
import * as fixtures from './contract.fixtures.js'
|
|
12
|
-
|
|
13
|
-
// the base is real; what it was constructed with and told to fit is observable
|
|
14
|
-
const fit = mock.method(Contract.prototype, 'fit', () => undefined)
|
|
15
|
-
|
|
16
|
-
let contract
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
resetCalls()
|
|
20
|
-
fit.mock.resetCalls()
|
|
21
|
-
|
|
22
|
-
contract = new Request(fixtures.schema, {})
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
const dummy = { properties: {} }
|
|
26
|
-
|
|
27
|
-
it('should extend Conditions', () => {
|
|
28
|
-
assert.ok(contract instanceof Contract)
|
|
29
|
-
assert.strictEqual(contract.schema, fixtures.schema)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('should fit request', () => {
|
|
33
|
-
const request = { [generate()]: generate() }
|
|
34
|
-
|
|
35
|
-
contract.fit(request)
|
|
36
|
-
|
|
37
|
-
assert.ok(
|
|
38
|
-
fit.mock.calls.some(
|
|
39
|
-
(call) => call.this === contract && isDeepStrictEqual(call.arguments[0], request)
|
|
40
|
-
)
|
|
41
|
-
)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
describe('schema', () => {
|
|
45
|
-
let schema
|
|
46
|
-
|
|
47
|
-
beforeEach(() => {
|
|
48
|
-
schema = clone(fixtures.schemas.request)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should provide schema', () => {
|
|
52
|
-
assert.notStrictEqual(Request.schema({}, dummy), undefined)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should add required input if defined', () => {
|
|
56
|
-
const input = { type: 'number' }
|
|
57
|
-
|
|
58
|
-
assert.deepStrictEqual(Request.schema({ input }, dummy).properties.input, input)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('should set input as null if undefined', async () => {
|
|
62
|
-
assert.deepStrictEqual(Request.schema({}, dummy).properties.input, { type: 'null' })
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('should contain query if declaration.query is not defined', () => {
|
|
66
|
-
assert.notStrictEqual(Request.schema({}, dummy).properties.query, undefined)
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('should not contain query if declaration.query is false', () => {
|
|
70
|
-
schema.properties.query = { type: 'null' }
|
|
71
|
-
assert.partialDeepStrictEqual(Request.schema({ query: false }, dummy), schema)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it('should require query if declaration.query is true', () => {
|
|
75
|
-
schema.required = ['query']
|
|
76
|
-
assert.ok(
|
|
77
|
-
['query'].every((item) =>
|
|
78
|
-
Request.schema({ query: true }, dummy).required.some((candidate) =>
|
|
79
|
-
isDeepStrictEqual(candidate, item)
|
|
80
|
-
)
|
|
81
|
-
)
|
|
82
|
-
)
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('should forbid projection for non observations', () => {
|
|
86
|
-
assert.strictEqual(
|
|
87
|
-
Request.schema({ type: 'transition' }, dummy).properties.query.properties
|
|
88
|
-
.projection,
|
|
89
|
-
undefined
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
assert.strictEqual(
|
|
93
|
-
Request.schema({ type: 'assignment' }, dummy).properties.query.properties
|
|
94
|
-
.projection,
|
|
95
|
-
undefined
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
assert.notStrictEqual(
|
|
99
|
-
Request.schema({ type: 'observation' }, dummy).properties.query.properties
|
|
100
|
-
.projection,
|
|
101
|
-
undefined
|
|
102
|
-
)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('should forbid version for observations', () => {
|
|
106
|
-
assert.notStrictEqual(
|
|
107
|
-
Request.schema({ type: 'transition' }, dummy).properties.query.properties.version,
|
|
108
|
-
undefined
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
assert.strictEqual(
|
|
112
|
-
Request.schema({ type: 'observation' }, dummy).properties.query.properties.version,
|
|
113
|
-
undefined
|
|
114
|
-
)
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('should allow omit, limit only for set observations', () => {
|
|
118
|
-
const schema = Request.schema({ type: 'transition' }, dummy)
|
|
119
|
-
const transition = schema.properties.query.properties
|
|
120
|
-
|
|
121
|
-
assert.strictEqual(transition.omit, undefined)
|
|
122
|
-
assert.strictEqual(transition.limit, undefined)
|
|
123
|
-
|
|
124
|
-
const object = Request.schema(
|
|
125
|
-
{
|
|
126
|
-
type: 'observation',
|
|
127
|
-
scope: 'object'
|
|
128
|
-
},
|
|
129
|
-
dummy
|
|
130
|
-
).properties.query.properties
|
|
131
|
-
|
|
132
|
-
assert.strictEqual(object.omit, undefined)
|
|
133
|
-
assert.strictEqual(object.limit, undefined)
|
|
134
|
-
|
|
135
|
-
const objects = Request.schema(
|
|
136
|
-
{
|
|
137
|
-
type: 'observation',
|
|
138
|
-
scope: 'objects'
|
|
139
|
-
},
|
|
140
|
-
dummy
|
|
141
|
-
).properties.query.properties
|
|
142
|
-
|
|
143
|
-
assert.notStrictEqual(objects.omit, undefined)
|
|
144
|
-
assert.notStrictEqual(objects.limit, undefined)
|
|
145
|
-
})
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
describe('source', () => {
|
|
149
|
-
const compile = (definition, entity) =>
|
|
150
|
-
schemas.schema(Request.schema(definition, entity))
|
|
151
|
-
|
|
152
|
-
it('should not hold source to a schema', () => {
|
|
153
|
-
const schema = Request.schema({}, dummy)
|
|
154
|
-
|
|
155
|
-
assert.strictEqual(schema.properties.source, undefined)
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
it('should pass known source variants', () => {
|
|
159
|
-
const schema = compile({}, undefined)
|
|
160
|
-
|
|
161
|
-
for (const source of [
|
|
162
|
-
{ namespace: 'a', component: 'b', operation: 'c' },
|
|
163
|
-
{ namespace: 'a', component: 'b', event: 'c' },
|
|
164
|
-
{ service: 'exposition' }
|
|
165
|
-
]) {
|
|
166
|
-
const request = { input: null, query: null, source }
|
|
167
|
-
|
|
168
|
-
assert.deepStrictEqual(schema.fit(request), null)
|
|
169
|
-
assert.deepStrictEqual(request.source, source)
|
|
170
|
-
}
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
// whatever a peer puts beside the keys this release knows travels through: what reads
|
|
174
|
-
// `source` takes the keys it knows, and the contract does not fail a call over the rest
|
|
175
|
-
it('should pass a source a peer added to', () => {
|
|
176
|
-
const schema = compile({}, undefined)
|
|
177
|
-
const request = {
|
|
178
|
-
input: null,
|
|
179
|
-
query: null,
|
|
180
|
-
source: { service: 'exposition', mystery: 'x' }
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
assert.deepStrictEqual(schema.fit(request), null)
|
|
184
|
-
assert.deepStrictEqual(request.source, { service: 'exposition', mystery: 'x' })
|
|
185
|
-
})
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
function resetCalls(target = [assert, clone, fixtures, dummy], seen = new Set()) {
|
|
189
|
-
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
190
|
-
|
|
191
|
-
seen.add(target)
|
|
192
|
-
|
|
193
|
-
for (const value of Object.values(target))
|
|
194
|
-
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
195
|
-
else resetCalls(value, seen)
|
|
196
|
-
}
|
package/test/discovery.test.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { it, beforeEach, afterEach, mock } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { isDeepStrictEqual } from 'node:util'
|
|
4
|
-
|
|
5
|
-
import { console } from 'openspan'
|
|
6
|
-
import { Connector } from '../source/connector.js'
|
|
7
|
-
import { Discovery } from '../source/discovery.js'
|
|
8
|
-
|
|
9
|
-
class Lookup extends Connector {
|
|
10
|
-
invoke = mock.fn(async () => ({ operations: {} }))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** @type {Lookup} */
|
|
14
|
-
let lookup
|
|
15
|
-
|
|
16
|
-
/** @type {Discovery} */
|
|
17
|
-
let discovery
|
|
18
|
-
|
|
19
|
-
/** @type {import('node:test').Mock<any>} */
|
|
20
|
-
let warn
|
|
21
|
-
|
|
22
|
-
const locator = { id: 'dummies.one' }
|
|
23
|
-
|
|
24
|
-
beforeEach(async () => {
|
|
25
|
-
mock.timers.enable()
|
|
26
|
-
|
|
27
|
-
warn = mock.method(console, 'warn', () => undefined)
|
|
28
|
-
lookup = new Lookup()
|
|
29
|
-
discovery = new Discovery(async () => lookup)
|
|
30
|
-
|
|
31
|
-
await discovery.connect()
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
warn.mock.restore()
|
|
36
|
-
mock.timers.reset()
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('should not warn if a lookup is answered', async () => {
|
|
40
|
-
await discovery.lookup(locator)
|
|
41
|
-
|
|
42
|
-
mock.timers.tick(60_000)
|
|
43
|
-
|
|
44
|
-
assert.strictEqual(warn.mock.callCount(), 0)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('should keep warning while a lookup is unanswered', async () => {
|
|
48
|
-
lookup.invoke.mock.mockImplementation(() => new Promise(() => undefined))
|
|
49
|
-
|
|
50
|
-
void discovery.lookup(locator)
|
|
51
|
-
|
|
52
|
-
// the interval is set after the lookup is resolved, so it has to exist
|
|
53
|
-
// before time is advanced
|
|
54
|
-
await new Promise((resolve) => process.nextTick(resolve))
|
|
55
|
-
|
|
56
|
-
// node:test moves the clock before running the callbacks it releases, so the
|
|
57
|
-
// elapsed time each warning reports is only right when time advances by steps
|
|
58
|
-
mock.timers.tick(5_000)
|
|
59
|
-
mock.timers.tick(5_000)
|
|
60
|
-
|
|
61
|
-
assert.strictEqual(warn.mock.callCount(), 2)
|
|
62
|
-
|
|
63
|
-
assert.ok(
|
|
64
|
-
((call) =>
|
|
65
|
-
call.arguments.length === 2 &&
|
|
66
|
-
isDeepStrictEqual(call.arguments[0], 'Waiting for lookup response') &&
|
|
67
|
-
isDeepStrictEqual(call.arguments[1], { component: locator.id, waiting: 10 }))(
|
|
68
|
-
warn.mock.calls.at(-1) ?? { arguments: [] }
|
|
69
|
-
)
|
|
70
|
-
)
|
|
71
|
-
})
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { mock } from 'node:test'
|
|
2
|
-
|
|
3
|
-
import { generate } from 'randomstring'
|
|
4
|
-
|
|
5
|
-
// noinspection JSCheckFunctionSignatures
|
|
6
|
-
export const events = [0, 1, 2].map((index) => ({
|
|
7
|
-
emit: mock.fn(async (state) => ({ ...state, event: index }))
|
|
8
|
-
}))
|
|
9
|
-
|
|
10
|
-
export const event = {
|
|
11
|
-
origin: { [generate()]: generate() },
|
|
12
|
-
state: { [generate()]: generate() }
|
|
13
|
-
}
|