@toa.io/core 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 (304) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/package.json +22 -12
  3. package/source/assignment.ts +27 -0
  4. package/source/call.ts +63 -0
  5. package/source/cascade.ts +32 -0
  6. package/source/component.ts +83 -0
  7. package/source/composition.ts +27 -0
  8. package/source/connector.ts +217 -0
  9. package/source/context.ts +68 -0
  10. package/source/contract/contract.ts +23 -0
  11. package/source/contract/index.ts +2 -0
  12. package/source/contract/reply.ts +56 -0
  13. package/source/contract/request.ts +140 -0
  14. package/source/contract/schemas.ts +39 -0
  15. package/source/discovery.ts +53 -0
  16. package/source/effect.ts +14 -0
  17. package/source/emission.ts +21 -0
  18. package/source/entities/changeset.ts +37 -0
  19. package/source/entities/entity.ts +137 -0
  20. package/source/entities/factory.ts +52 -0
  21. package/source/entities/index.ts +4 -0
  22. package/source/entities/newid.ts +9 -0
  23. package/source/entities/set.ts +27 -0
  24. package/source/event.ts +57 -0
  25. package/source/exceptions.ts +133 -0
  26. package/source/exposition.ts +33 -0
  27. package/source/guard.ts +16 -0
  28. package/source/index.ts +36 -0
  29. package/source/locator.ts +37 -0
  30. package/source/observation.ts +16 -0
  31. package/source/operation.ts +139 -0
  32. package/source/outbox/index.ts +1 -0
  33. package/source/outbox/outbox.ts +341 -0
  34. package/source/query/criteria.ts +90 -0
  35. package/source/query/options.ts +35 -0
  36. package/source/query.ts +67 -0
  37. package/source/receiver.ts +120 -0
  38. package/source/reflection.ts +20 -0
  39. package/source/remote.ts +20 -0
  40. package/source/state.ts +179 -0
  41. package/source/transition.ts +79 -0
  42. package/source/transmission.ts +38 -0
  43. package/source/types/atomicity.ts +63 -0
  44. package/source/types/bindings.ts +59 -0
  45. package/source/types/bridges.ts +54 -0
  46. package/source/types/extensions.ts +89 -0
  47. package/source/types/index.ts +14 -0
  48. package/{types/message.d.ts → source/types/message.ts} +2 -0
  49. package/source/types/operations.ts +31 -0
  50. package/source/types/outbox.ts +35 -0
  51. package/source/types/receiver.ts +10 -0
  52. package/source/types/request.ts +54 -0
  53. package/source/types/state.ts +9 -0
  54. package/source/types/storages.ts +134 -0
  55. package/source/unmanaged.ts +8 -0
  56. package/test/call.fixtures.js +10 -12
  57. package/test/call.test.js +42 -9
  58. package/test/component.fixtures.js +5 -8
  59. package/test/component.test.js +27 -10
  60. package/test/connector.fixtures.js +29 -13
  61. package/test/connector.test.js +128 -38
  62. package/test/context.fixtures.js +8 -12
  63. package/test/context.test.js +19 -8
  64. package/test/contract/conditions.test.js +15 -9
  65. package/test/contract/contract.fixtures.js +11 -16
  66. package/test/contract/request.test.js +130 -46
  67. package/test/discovery.test.js +71 -0
  68. package/test/emission.fixtures.js +6 -10
  69. package/test/emission.test.js +37 -12
  70. package/test/entities/entity.fixtures.js +11 -16
  71. package/test/entities/entity.test.js +105 -50
  72. package/test/entities/factory.fixtures.js +26 -13
  73. package/test/entities/factory.test.js +68 -17
  74. package/test/entities/set.fixtures.js +6 -8
  75. package/test/entities/set.test.js +6 -5
  76. package/test/event.fixtures.js +9 -14
  77. package/test/event.test.js +78 -34
  78. package/test/locator.test.js +32 -25
  79. package/test/outbox.test.js +202 -0
  80. package/test/query.fixtures.js +1 -5
  81. package/test/query.test.js +111 -14
  82. package/test/receiver.fixtures.js +9 -12
  83. package/test/receiver.test.js +80 -31
  84. package/test/reflection.test.js +9 -8
  85. package/test/state.fixtures.js +33 -31
  86. package/test/state.test.js +135 -19
  87. package/test/transmission.fixtures.js +4 -6
  88. package/test/transmission.test.js +47 -16
  89. package/transpiled/assignment.d.ts +6 -0
  90. package/transpiled/assignment.js +20 -0
  91. package/transpiled/assignment.js.map +1 -0
  92. package/transpiled/call.d.ts +10 -0
  93. package/transpiled/call.js +52 -0
  94. package/transpiled/call.js.map +1 -0
  95. package/transpiled/cascade.d.ts +7 -0
  96. package/transpiled/cascade.js +28 -0
  97. package/transpiled/cascade.js.map +1 -0
  98. package/transpiled/component.d.ts +15 -0
  99. package/transpiled/component.js +61 -0
  100. package/transpiled/component.js.map +1 -0
  101. package/transpiled/composition.d.ts +6 -0
  102. package/transpiled/composition.js +23 -0
  103. package/transpiled/composition.js.map +1 -0
  104. package/transpiled/connector.d.ts +47 -0
  105. package/transpiled/connector.js +185 -0
  106. package/transpiled/connector.js.map +1 -0
  107. package/transpiled/context.d.ts +18 -0
  108. package/transpiled/context.js +42 -0
  109. package/transpiled/context.js.map +1 -0
  110. package/transpiled/contract/contract.d.ts +10 -0
  111. package/transpiled/contract/contract.js +14 -0
  112. package/transpiled/contract/contract.js.map +1 -0
  113. package/transpiled/contract/index.d.ts +2 -0
  114. package/transpiled/contract/index.js +3 -0
  115. package/transpiled/contract/index.js.map +1 -0
  116. package/transpiled/contract/reply.d.ts +7 -0
  117. package/transpiled/contract/reply.js +48 -0
  118. package/transpiled/contract/reply.js.map +1 -0
  119. package/transpiled/contract/request.d.ts +29 -0
  120. package/transpiled/contract/request.js +103 -0
  121. package/transpiled/contract/request.js.map +1 -0
  122. package/transpiled/contract/schemas.d.ts +4 -0
  123. package/transpiled/contract/schemas.js +36 -0
  124. package/transpiled/contract/schemas.js.map +1 -0
  125. package/transpiled/discovery.d.ts +12 -0
  126. package/transpiled/discovery.js +34 -0
  127. package/transpiled/discovery.js.map +1 -0
  128. package/transpiled/effect.d.ts +5 -0
  129. package/transpiled/effect.js +11 -0
  130. package/transpiled/effect.js.map +1 -0
  131. package/transpiled/emission.d.ts +8 -0
  132. package/transpiled/emission.js +14 -0
  133. package/transpiled/emission.js.map +1 -0
  134. package/transpiled/entities/changeset.d.ts +10 -0
  135. package/transpiled/entities/changeset.js +27 -0
  136. package/transpiled/entities/changeset.js.map +1 -0
  137. package/transpiled/entities/entity.d.ts +19 -0
  138. package/transpiled/entities/entity.js +109 -0
  139. package/transpiled/entities/entity.js.map +1 -0
  140. package/transpiled/entities/factory.d.ts +22 -0
  141. package/transpiled/entities/factory.js +34 -0
  142. package/transpiled/entities/factory.js.map +1 -0
  143. package/transpiled/entities/index.d.ts +4 -0
  144. package/transpiled/entities/index.js +5 -0
  145. package/transpiled/entities/index.js.map +1 -0
  146. package/transpiled/entities/newid.d.ts +1 -0
  147. package/transpiled/entities/newid.js +7 -0
  148. package/transpiled/entities/newid.js.map +1 -0
  149. package/transpiled/entities/set.d.ts +10 -0
  150. package/transpiled/entities/set.js +19 -0
  151. package/transpiled/entities/set.js.map +1 -0
  152. package/transpiled/event.d.ts +14 -0
  153. package/transpiled/event.js +38 -0
  154. package/transpiled/event.js.map +1 -0
  155. package/transpiled/exceptions.d.ts +61 -0
  156. package/transpiled/exceptions.js +93 -0
  157. package/transpiled/exceptions.js.map +1 -0
  158. package/transpiled/exposition.d.ts +18 -0
  159. package/transpiled/exposition.js +18 -0
  160. package/transpiled/exposition.js.map +1 -0
  161. package/transpiled/guard.d.ts +7 -0
  162. package/transpiled/guard.js +12 -0
  163. package/transpiled/guard.js.map +1 -0
  164. package/transpiled/index.d.ts +35 -0
  165. package/transpiled/index.js +29 -0
  166. package/transpiled/index.js.map +1 -0
  167. package/transpiled/locator.d.ts +12 -0
  168. package/transpiled/locator.js +32 -0
  169. package/transpiled/locator.js.map +1 -0
  170. package/transpiled/observation.d.ts +5 -0
  171. package/transpiled/observation.js +12 -0
  172. package/transpiled/observation.js.map +1 -0
  173. package/transpiled/operation.d.ts +49 -0
  174. package/transpiled/operation.js +78 -0
  175. package/transpiled/operation.js.map +1 -0
  176. package/transpiled/outbox/index.d.ts +1 -0
  177. package/transpiled/outbox/index.js +2 -0
  178. package/transpiled/outbox/index.js.map +1 -0
  179. package/transpiled/outbox/outbox.d.ts +46 -0
  180. package/transpiled/outbox/outbox.js +268 -0
  181. package/transpiled/outbox/outbox.js.map +1 -0
  182. package/transpiled/query/criteria.d.ts +6 -0
  183. package/transpiled/query/criteria.js +74 -0
  184. package/transpiled/query/criteria.js.map +1 -0
  185. package/transpiled/query/options.d.ts +3 -0
  186. package/transpiled/query/options.js +27 -0
  187. package/transpiled/query/options.js.map +1 -0
  188. package/transpiled/query.d.ts +9 -0
  189. package/transpiled/query.js +57 -0
  190. package/transpiled/query.js.map +1 -0
  191. package/transpiled/receiver.d.ts +20 -0
  192. package/transpiled/receiver.js +92 -0
  193. package/transpiled/receiver.js.map +1 -0
  194. package/transpiled/reflection.d.ts +9 -0
  195. package/transpiled/reflection.js +13 -0
  196. package/transpiled/reflection.js.map +1 -0
  197. package/transpiled/remote.d.ts +10 -0
  198. package/transpiled/remote.js +12 -0
  199. package/transpiled/remote.js.map +1 -0
  200. package/transpiled/state.d.ts +33 -0
  201. package/transpiled/state.js +126 -0
  202. package/transpiled/state.js.map +1 -0
  203. package/transpiled/transition.d.ts +14 -0
  204. package/transpiled/transition.js +51 -0
  205. package/transpiled/transition.js.map +1 -0
  206. package/transpiled/transmission.d.ts +8 -0
  207. package/transpiled/transmission.js +30 -0
  208. package/transpiled/transmission.js.map +1 -0
  209. package/transpiled/types/atomicity.d.ts +56 -0
  210. package/transpiled/types/atomicity.js +2 -0
  211. package/transpiled/types/atomicity.js.map +1 -0
  212. package/transpiled/types/bindings.d.ts +42 -0
  213. package/transpiled/types/bindings.js +2 -0
  214. package/transpiled/types/bindings.js.map +1 -0
  215. package/transpiled/types/bridges.d.ts +38 -0
  216. package/transpiled/types/bridges.js +2 -0
  217. package/transpiled/types/bridges.js.map +1 -0
  218. package/transpiled/types/extensions.d.ts +62 -0
  219. package/transpiled/types/extensions.js +2 -0
  220. package/transpiled/types/extensions.js.map +1 -0
  221. package/transpiled/types/index.d.ts +13 -0
  222. package/transpiled/types/index.js +8 -0
  223. package/transpiled/types/index.js.map +1 -0
  224. package/transpiled/types/message.d.ts +5 -0
  225. package/transpiled/types/message.js +2 -0
  226. package/transpiled/types/message.js.map +1 -0
  227. package/transpiled/types/operations.d.ts +15 -0
  228. package/transpiled/types/operations.js +2 -0
  229. package/transpiled/types/operations.js.map +1 -0
  230. package/transpiled/types/outbox.d.ts +28 -0
  231. package/transpiled/types/outbox.js +2 -0
  232. package/transpiled/types/outbox.js.map +1 -0
  233. package/transpiled/types/receiver.d.ts +9 -0
  234. package/transpiled/types/receiver.js +2 -0
  235. package/transpiled/types/receiver.js.map +1 -0
  236. package/transpiled/types/request.d.ts +55 -0
  237. package/transpiled/types/request.js +2 -0
  238. package/transpiled/types/request.js.map +1 -0
  239. package/transpiled/types/state.d.ts +9 -0
  240. package/transpiled/types/state.js +2 -0
  241. package/transpiled/types/state.js.map +1 -0
  242. package/transpiled/types/storages.d.ts +111 -0
  243. package/transpiled/types/storages.js +2 -0
  244. package/transpiled/types/storages.js.map +1 -0
  245. package/transpiled/unmanaged.d.ts +5 -0
  246. package/transpiled/unmanaged.js +7 -0
  247. package/transpiled/unmanaged.js.map +1 -0
  248. package/tsconfig.json +10 -0
  249. package/tsconfig.tsbuildinfo +1 -0
  250. package/src/assignment.js +0 -31
  251. package/src/call.js +0 -42
  252. package/src/cascade.js +0 -36
  253. package/src/component.js +0 -41
  254. package/src/composition.js +0 -25
  255. package/src/connector.js +0 -183
  256. package/src/context.js +0 -55
  257. package/src/contract/conditions.js +0 -21
  258. package/src/contract/index.js +0 -7
  259. package/src/contract/reply.js +0 -25
  260. package/src/contract/request.js +0 -67
  261. package/src/contract/schemas/error.yaml +0 -9
  262. package/src/contract/schemas/index.js +0 -7
  263. package/src/contract/schemas/query.yaml +0 -30
  264. package/src/discovery.js +0 -44
  265. package/src/emission.js +0 -23
  266. package/src/entities/changeset.js +0 -43
  267. package/src/entities/entity.js +0 -73
  268. package/src/entities/factory.js +0 -33
  269. package/src/entities/index.js +0 -5
  270. package/src/entities/set.js +0 -15
  271. package/src/event.js +0 -40
  272. package/src/exceptions.js +0 -100
  273. package/src/exposition.js +0 -27
  274. package/src/index.js +0 -47
  275. package/src/locator.js +0 -54
  276. package/src/observation.js +0 -20
  277. package/src/operation.js +0 -69
  278. package/src/query/criteria.js +0 -41
  279. package/src/query/options.js +0 -40
  280. package/src/query.js +0 -41
  281. package/src/receiver.js +0 -65
  282. package/src/reflection.js +0 -28
  283. package/src/remote.js +0 -17
  284. package/src/state.js +0 -99
  285. package/src/transition.js +0 -73
  286. package/src/transmission.js +0 -33
  287. package/types/bindings.d.ts +0 -40
  288. package/types/bridges.ts +0 -30
  289. package/types/component.d.ts +0 -9
  290. package/types/connector.d.ts +0 -18
  291. package/types/context.d.ts +0 -21
  292. package/types/entity.d.ts +0 -46
  293. package/types/event.d.ts +0 -11
  294. package/types/exception.d.ts +0 -4
  295. package/types/extensions.d.ts +0 -29
  296. package/types/index.ts +0 -14
  297. package/types/locator.d.ts +0 -13
  298. package/types/operations.d.ts +0 -2
  299. package/types/query.d.ts +0 -15
  300. package/types/receiver.d.ts +0 -12
  301. package/types/reflection.d.ts +0 -14
  302. package/types/request.d.ts +0 -23
  303. package/types/state.d.ts +0 -35
  304. package/types/storages.d.ts +0 -71
@@ -1,6 +1,9 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const fixtures = require('./connector.fixtures')
4
+ import { timeout } from '@toa.io/generic'
5
+
6
+ import * as fixtures from './connector.fixtures.js'
4
7
 
5
8
  let sequence
6
9
 
@@ -17,14 +20,14 @@ describe('callbacks', () => {
17
20
 
18
21
  it('should call connection', async () => {
19
22
  await a.connect()
20
- expect(sequence).toEqual(['+a'])
23
+ assert.deepStrictEqual(sequence, ['+a'])
21
24
  })
22
25
 
23
26
  it('should call disconnection', async () => {
24
27
  await a.connect()
25
28
  await a.disconnect()
26
29
 
27
- expect(sequence.indexOf('+a')).toBeLessThan(sequence.indexOf('-a'))
30
+ assert.ok(sequence.indexOf('+a') < sequence.indexOf('-a'))
28
31
  })
29
32
 
30
33
  it('should reconnect', async () => {
@@ -32,7 +35,7 @@ describe('callbacks', () => {
32
35
  await a.reconnect()
33
36
  await a.reconnect()
34
37
 
35
- expect(sequence).toEqual(['+a', '-a', '*a', '+a', '-a', '*a', '+a'])
38
+ assert.deepStrictEqual(sequence, ['+a', '-a', '*a', '+a', '-a', '*a', '+a'])
36
39
  })
37
40
  })
38
41
 
@@ -55,9 +58,9 @@ describe('dependencies', () => {
55
58
 
56
59
  await a.connect()
57
60
 
58
- expect(sequence.indexOf('+c')).toBeLessThan(sequence.indexOf('+b'))
59
- expect(sequence.indexOf('+b')).toBeLessThan(sequence.indexOf('+a'))
60
- expect(sequence.indexOf('+d')).toBeLessThan(sequence.indexOf('+a'))
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'))
61
64
  })
62
65
 
63
66
  it('should wait array of connectors', async () => {
@@ -67,10 +70,10 @@ describe('dependencies', () => {
67
70
 
68
71
  await a.connect()
69
72
 
70
- expect(sequence.indexOf('+c')).toBeLessThan(sequence.indexOf('+b'))
71
- expect(sequence.indexOf('+c')).toBeLessThan(sequence.indexOf('+d'))
72
- expect(sequence.indexOf('+b')).toBeLessThan(sequence.indexOf('+a'))
73
- expect(sequence.indexOf('+d')).toBeLessThan(sequence.indexOf('+a'))
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'))
74
77
  })
75
78
 
76
79
  it('should wait array(1) of connectors', async () => {
@@ -79,12 +82,15 @@ describe('dependencies', () => {
79
82
 
80
83
  await a.connect()
81
84
 
82
- expect(sequence.indexOf('+c')).toBeLessThan(sequence.indexOf('+b'))
83
- expect(sequence.indexOf('+b')).toBeLessThan(sequence.indexOf('+a'))
85
+ assert.ok(sequence.indexOf('+c') < sequence.indexOf('+b'))
86
+ assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
84
87
  })
85
88
 
86
89
  it('should throw on empty array', async () => {
87
- expect(() => a.depends([])).toThrow(/must not be empty/)
90
+ assert.throws(
91
+ () => a.depends([]),
92
+ (error) => /must not be empty/.test(error.message)
93
+ )
88
94
  })
89
95
 
90
96
  it('should await 2-way dependencies', async () => {
@@ -93,23 +99,24 @@ describe('dependencies', () => {
93
99
 
94
100
  await a.connect()
95
101
 
96
- expect(sequence.indexOf('+b')).toBeLessThan(sequence.indexOf('+a'))
97
- expect(sequence.indexOf('+c')).toBeLessThan(sequence.indexOf('+a'))
98
- expect(sequence.indexOf('+d')).toBeLessThan(sequence.indexOf('+a'))
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'))
99
105
 
100
- expect(sequence.indexOf('+b')).toBeLessThan(sequence.indexOf('+d'))
101
- expect(sequence.indexOf('+c')).toBeLessThan(sequence.indexOf('+d'))
106
+ assert.ok(sequence.indexOf('+b') < sequence.indexOf('+d'))
107
+ assert.ok(sequence.indexOf('+c') < sequence.indexOf('+d'))
102
108
  })
103
109
 
104
110
  it('should disconnect before dependencies', async () => {
105
111
  a.depends(b).depends(c)
106
112
  b.depends(d)
107
113
 
114
+ await a.connect()
108
115
  await a.disconnect()
109
116
 
110
- expect(sequence.indexOf('-a')).toBeLessThan(sequence.indexOf('-b'))
111
- expect(sequence.indexOf('-b')).toBeLessThan(sequence.indexOf('-c'))
112
- expect(sequence.indexOf('-b')).toBeLessThan(sequence.indexOf('-d'))
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'))
113
120
  })
114
121
 
115
122
  it('should call disconnected', async () => {
@@ -118,10 +125,10 @@ describe('dependencies', () => {
118
125
 
119
126
  await a.disconnect()
120
127
 
121
- expect(sequence.indexOf('*c')).toBeLessThan(sequence.indexOf('*b'))
122
- expect(sequence.indexOf('*b')).toBeLessThan(sequence.indexOf('*a'))
123
- expect(sequence.indexOf('*d')).toBeLessThan(sequence.indexOf('*b'))
124
- expect(sequence.indexOf('*a')).toBe(sequence.length - 1)
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)
125
132
  })
126
133
 
127
134
  it('should disconnect if no parents left', async () => {
@@ -131,19 +138,102 @@ describe('dependencies', () => {
131
138
  await a.connect()
132
139
  await b.connect()
133
140
 
134
- expect(sequence).toEqual(['+c', '+a', '+b'])
141
+ assert.deepStrictEqual(sequence, ['+c', '+a', '+b'])
135
142
 
136
143
  await a.disconnect()
137
144
 
138
- expect(sequence).toEqual(['+c', '+a', '+b', '-a', '*a'])
145
+ assert.deepStrictEqual(sequence, ['+c', '+a', '+b', '-a', '*a'])
139
146
 
140
147
  await b.disconnect()
141
148
 
142
- expect(sequence).toEqual(['+c', '+a', '+b', '-a', '*a', '-b', '-c', '*c', '*b'])
149
+ assert.deepStrictEqual(sequence, [
150
+ '+c',
151
+ '+a',
152
+ '+b',
153
+ '-a',
154
+ '*a',
155
+ '-b',
156
+ '-c',
157
+ '*c',
158
+ '*b'
159
+ ])
143
160
  })
144
161
 
145
162
  it('should throw if depends not on Connector', async () => {
146
- expect(() => a.depends({})).toThrow()
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'))
147
237
  })
148
238
 
149
239
  describe('errors', () => {
@@ -156,21 +246,21 @@ describe('dependencies', () => {
156
246
  it('should disconnect on fail', async () => {
157
247
  f.depends(b).depends(c)
158
248
 
159
- await expect(f.connect()).rejects.toThrow('FailingConnector')
160
- expect(sequence).toEqual(['+c', '+b', '-b', '-c', '*c', '*b'])
249
+ await assert.rejects(f.connect(), (error) => /FailingConnector/.test(error.message))
250
+ assert.deepStrictEqual(sequence, ['+c', '+b', '-b', '-c', '*c', '*b'])
161
251
  })
162
252
 
163
253
  it('should interrupt connection chain', async () => {
164
254
  a.depends(f).depends(c)
165
255
  f.depends(d)
166
256
 
167
- await expect(a.connect()).rejects.toThrow('FailingConnector')
257
+ await assert.rejects(a.connect(), (error) => /FailingConnector/.test(error.message))
168
258
 
169
- expect(sequence.indexOf('+c')).toBeLessThan(sequence.indexOf('-c'))
170
- expect(sequence.indexOf('+d')).toBeLessThan(sequence.indexOf('-d'))
259
+ assert.ok(sequence.indexOf('+c') < sequence.indexOf('-c'))
260
+ assert.ok(sequence.indexOf('+d') < sequence.indexOf('-d'))
171
261
 
172
- expect(sequence.indexOf('+a')).toBe(-1)
173
- expect(sequence.indexOf('-a')).toBe(-1)
262
+ assert.strictEqual(sequence.indexOf('+a'), -1)
263
+ assert.strictEqual(sequence.indexOf('-a'), -1)
174
264
  })
175
265
  })
176
266
  })
@@ -1,18 +1,14 @@
1
- 'use strict'
1
+ import { mock } from 'node:test'
2
2
 
3
- const { Connector } = require('../src/connector')
3
+ import { Connector } from '../source/connector.js'
4
4
 
5
- const local = {
6
- link: jest.fn()
5
+ export const local = {
6
+ link: mock.fn()
7
7
  }
8
8
 
9
- const discover = jest.fn(() => ({
10
- invoke: jest.fn(),
11
- link: jest.fn()
9
+ export const discover = mock.fn(() => ({
10
+ invoke: mock.fn(),
11
+ link: mock.fn()
12
12
  }))
13
13
 
14
- const aspects = [new Connector(), new Connector()]
15
-
16
- exports.local = local
17
- exports.discover = discover
18
- exports.aspects = aspects
14
+ export const aspects = [new Connector(), new Connector()]
@@ -1,20 +1,21 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const fixtures = require('./context.fixtures')
4
- const { Context } = require('../src/context')
4
+ import * as fixtures from './context.fixtures.js'
5
+ import { Context } from '../source/context.js'
5
6
 
6
- /** @type {toa.core.Context} */
7
+ /** @type {import('@toa.io/core').Context} */
7
8
  let context
8
9
 
9
10
  beforeEach(() => {
10
- jest.clearAllMocks()
11
+ resetCalls()
11
12
 
12
13
  context = new Context(fixtures.local, fixtures.discover, fixtures.aspects)
13
14
  })
14
15
 
15
16
  it('should expose aspects', () => {
16
- expect(context.aspects).toBeDefined()
17
- expect(context.aspects).toStrictEqual(fixtures.aspects)
17
+ assert.notStrictEqual(context.aspects, undefined)
18
+ assert.deepStrictEqual(context.aspects, fixtures.aspects)
18
19
  })
19
20
 
20
21
  describe('call', () => {
@@ -24,6 +25,16 @@ describe('call', () => {
24
25
  await context.call('a', 'b', 'c', request)
25
26
  await context.call('a', 'b', 'c', request)
26
27
 
27
- expect(fixtures.discover).toHaveBeenCalledTimes(1)
28
+ assert.strictEqual(fixtures.discover.mock.callCount(), 1)
28
29
  })
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,26 +1,32 @@
1
- 'use strict'
1
+ import { it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { isDeepStrictEqual } from 'node:util'
2
4
 
3
- const { generate } = require('randomstring')
5
+ import { generate } from 'randomstring'
4
6
 
5
- const { Conditions } = require('../../src/contract/conditions')
6
- const fixtures = require('./contract.fixtures')
7
+ import { Contract } from '../../source/contract/contract.js'
8
+ import * as fixtures from './contract.fixtures.js'
7
9
 
8
- let conditions
10
+ let contract
9
11
 
10
12
  beforeEach(() => {
11
- conditions = new Conditions(fixtures.schema)
13
+ contract = new Contract(fixtures.schema)
12
14
  })
13
15
 
14
16
  it('should fit value', () => {
15
17
  const value = { foo: generate() }
16
18
 
17
- conditions.fit(value)
19
+ contract.fit(value)
18
20
 
19
- expect(fixtures.schema.fit).toHaveBeenCalledWith(value)
21
+ assert.ok(
22
+ fixtures.schema.fit.mock.calls.some(
23
+ (call) => call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], value)
24
+ )
25
+ )
20
26
  })
21
27
 
22
28
  it('should throw on invalid value', () => {
23
29
  const value = { invalid: true }
24
30
 
25
- expect(() => conditions.fit(value)).toThrow()
31
+ assert.throws(() => contract.fit(value))
26
32
  })
@@ -1,33 +1,28 @@
1
- 'use strict'
1
+ import { mock } from 'node:test'
2
2
 
3
- const { generate } = require('randomstring')
4
- const { load } = require('@toa.io/yaml')
5
- const { resolve } = require('path')
3
+ import { generate } from 'randomstring'
4
+
5
+ import { query as querySchema } from '../../source/contract/schemas.js'
6
6
 
7
7
  // noinspection JSCheckFunctionSignatures
8
- const schema = {
9
- fit: jest.fn((input) => (input.invalid ? { message: generate() } : null))
8
+ export const schema = {
9
+ fit: mock.fn((input) => (input.invalid ? { message: generate() } : null))
10
10
  }
11
11
 
12
- const query = {
13
- parse: jest.fn(() => ({ [generate()]: generate() }))
12
+ export const query = {
13
+ parse: mock.fn(() => ({ [generate()]: generate() }))
14
14
  }
15
15
 
16
- const declaration = {}
16
+ export const declaration = {}
17
17
 
18
- const schemas = {
18
+ export const schemas = {
19
19
  request: {
20
20
  type: 'object',
21
21
  properties: {
22
22
  input: { type: 'null' },
23
- query: load.sync(resolve(__dirname, '../../src/contract/schemas/query.yaml')),
23
+ query: querySchema,
24
24
  authentic: { type: 'boolean' }
25
25
  },
26
26
  additionalProperties: true
27
27
  }
28
28
  }
29
-
30
- exports.schema = schema
31
- exports.query = query
32
- exports.declaration = declaration
33
- exports.schemas = schemas
@@ -1,27 +1,32 @@
1
- 'use strict'
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'
2
5
 
3
- const clone = require('clone-deep')
4
- const { generate } = require('randomstring')
6
+ import clone from 'clone-deep'
7
+ import { generate } from 'randomstring'
5
8
 
6
- jest.mock('../../src/contract/conditions')
9
+ import { Request } from '../../source/contract/request.js'
10
+ import { Contract } from '../../source/contract/contract.js'
11
+ import * as fixtures from './contract.fixtures.js'
7
12
 
8
- const { Request } = require('../../src/contract/request')
9
- const { Conditions } = require('../../src/contract/conditions')
10
- const fixtures = require('./contract.fixtures')
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)
11
15
 
12
16
  let contract
13
17
 
14
18
  beforeEach(() => {
15
- jest.clearAllMocks()
19
+ resetCalls()
20
+ fit.mock.resetCalls()
16
21
 
17
- contract = new Request(fixtures.schema)
22
+ contract = new Request(fixtures.schema, {})
18
23
  })
19
24
 
20
- const dummy = { schema: { properties: {} } }
25
+ const dummy = { properties: {} }
21
26
 
22
27
  it('should extend Conditions', () => {
23
- expect(contract).toBeInstanceOf(Conditions)
24
- expect(Conditions).toHaveBeenCalledWith(fixtures.schema)
28
+ assert.ok(contract instanceof Contract)
29
+ assert.strictEqual(contract.schema, fixtures.schema)
25
30
  })
26
31
 
27
32
  it('should fit request', () => {
@@ -29,7 +34,11 @@ it('should fit request', () => {
29
34
 
30
35
  contract.fit(request)
31
36
 
32
- expect(Conditions.mock.instances[0].fit).toHaveBeenCalledWith(request)
37
+ assert.ok(
38
+ fit.mock.calls.some(
39
+ (call) => call.this === contract && isDeepStrictEqual(call.arguments[0], request)
40
+ )
41
+ )
33
42
  })
34
43
 
35
44
  describe('schema', () => {
@@ -40,73 +49,148 @@ describe('schema', () => {
40
49
  })
41
50
 
42
51
  it('should provide schema', () => {
43
- expect(Request.schema({}, dummy)).toBeDefined()
52
+ assert.notStrictEqual(Request.schema({}, dummy), undefined)
44
53
  })
45
54
 
46
55
  it('should add required input if defined', () => {
47
56
  const input = { type: 'number' }
48
57
 
49
- expect(Request.schema({ input }, dummy).properties.input).toStrictEqual(input)
58
+ assert.deepStrictEqual(Request.schema({ input }, dummy).properties.input, input)
50
59
  })
51
60
 
52
61
  it('should set input as null if undefined', async () => {
53
- expect(Request.schema({}, dummy).properties.input).toStrictEqual({ type: 'null' })
62
+ assert.deepStrictEqual(Request.schema({}, dummy).properties.input, { type: 'null' })
54
63
  })
55
64
 
56
65
  it('should contain query if declaration.query is not defined', () => {
57
- expect(Request.schema({}, dummy).properties.query).toBeDefined()
66
+ assert.notStrictEqual(Request.schema({}, dummy).properties.query, undefined)
58
67
  })
59
68
 
60
69
  it('should not contain query if declaration.query is false', () => {
61
70
  schema.properties.query = { type: 'null' }
62
- expect(Request.schema({ query: false }, dummy)).toStrictEqual(schema)
71
+ assert.partialDeepStrictEqual(Request.schema({ query: false }, dummy), schema)
63
72
  })
64
73
 
65
74
  it('should require query if declaration.query is true', () => {
66
75
  schema.required = ['query']
67
- expect(Request.schema({ query: true }, dummy).required).toStrictEqual(expect.arrayContaining(['query']))
76
+ assert.ok(
77
+ ['query'].every((item) =>
78
+ Request.schema({ query: true }, dummy).required.some((candidate) =>
79
+ isDeepStrictEqual(candidate, item)
80
+ )
81
+ )
82
+ )
68
83
  })
69
84
 
70
85
  it('should forbid projection for non observations', () => {
71
- expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.projection)
72
- .toBe(undefined)
73
-
74
- expect(Request.schema({ type: 'assignment' }, dummy).properties.query.properties.projection)
75
- .toBe(undefined)
76
-
77
- expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.projection)
78
- .toBeDefined()
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
+ )
79
103
  })
80
104
 
81
105
  it('should forbid version for observations', () => {
82
- expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.version)
83
- .toBeDefined()
84
-
85
- expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.version)
86
- .toBe(undefined)
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
+ )
87
115
  })
88
116
 
89
117
  it('should allow omit, limit only for set observations', () => {
90
118
  const schema = Request.schema({ type: 'transition' }, dummy)
91
119
  const transition = schema.properties.query.properties
92
120
 
93
- expect(transition.omit).toBeUndefined()
94
- expect(transition.limit).toBeUndefined()
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))
95
151
 
96
- const object = Request.schema({
97
- type: 'observation',
98
- scope: 'object'
99
- }, dummy).properties.query.properties
152
+ it('should not hold source to a schema', () => {
153
+ const schema = Request.schema({}, dummy)
100
154
 
101
- expect(object.omit).toBeUndefined()
102
- expect(object.limit).toBeUndefined()
155
+ assert.strictEqual(schema.properties.source, undefined)
156
+ })
103
157
 
104
- const objects = Request.schema({
105
- type: 'observation',
106
- scope: 'objects'
107
- }, dummy).properties.query.properties
158
+ it('should pass known source variants', () => {
159
+ const schema = compile({}, undefined)
108
160
 
109
- expect(objects.omit).toBeDefined()
110
- expect(objects.limit).toBeDefined()
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' })
111
185
  })
112
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
+ }