@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,46 +1,162 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { isDeepStrictEqual } from 'node:util'
2
4
 
3
- const { State } = require('../src/state')
4
- const fixtures = require('./state.fixtures')
5
+ import { State } from '../source/state.js'
6
+ import * as fixtures from './state.fixtures.js'
5
7
 
6
8
  let state
7
9
 
8
10
  beforeEach(() => {
9
- jest.clearAllMocks()
11
+ resetCalls()
10
12
 
11
- state = new State(fixtures.storage, fixtures.factory, fixtures.emitter)
13
+ state = new State(fixtures.storage, fixtures.factory, fixtures.outbox)
12
14
  })
13
15
 
14
16
  it('should provide object', async () => {
15
17
  const entity = await state.object(fixtures.query)
16
18
 
17
- expect(fixtures.storage.get).toHaveBeenCalledWith(fixtures.query)
18
- expect(entity).toStrictEqual(fixtures.factory.object.mock.results[0].value)
19
- expect(fixtures.factory.object).toHaveBeenCalledWith(fixtures.storage.get.mock.results[0].value)
19
+ assert.ok(
20
+ fixtures.storage.get.mock.calls.some(
21
+ (call) =>
22
+ call.arguments.length === 1 &&
23
+ isDeepStrictEqual(call.arguments[0], fixtures.query)
24
+ )
25
+ )
26
+ assert.deepStrictEqual(entity, fixtures.factory.object.mock.calls[0].result)
27
+ assert.ok(
28
+ fixtures.factory.object.mock.calls.some(
29
+ (call) =>
30
+ call.arguments.length === 2 &&
31
+ isDeepStrictEqual(call.arguments[0], fixtures.storage.get.mock.calls[0].result) &&
32
+ isDeepStrictEqual(call.arguments[1], true)
33
+ )
34
+ )
20
35
  })
21
36
 
22
- it('should provide objects', async () => {
23
- const set = await state.objects(fixtures.query)
37
+ it('should provide read-only object', async () => {
38
+ await state.object(fixtures.query, false)
24
39
 
25
- expect(fixtures.storage.find).toHaveBeenCalledWith(fixtures.query)
26
- expect(set).toStrictEqual(fixtures.factory.objects.mock.results[0].value)
27
- expect(fixtures.factory.objects).toHaveBeenCalledWith(fixtures.storage.find.mock.results[0].value)
40
+ assert.ok(
41
+ fixtures.factory.object.mock.calls.some(
42
+ (call) =>
43
+ call.arguments.length === 2 &&
44
+ isDeepStrictEqual(call.arguments[0], fixtures.storage.get.mock.calls[0].result) &&
45
+ isDeepStrictEqual(call.arguments[1], false)
46
+ )
47
+ )
48
+ })
49
+
50
+ it('should provide read-only objects', async () => {
51
+ await state.objects(fixtures.query, false)
52
+
53
+ assert.ok(
54
+ fixtures.factory.objects.mock.calls.some(
55
+ (call) =>
56
+ call.arguments.length === 3 &&
57
+ isDeepStrictEqual(
58
+ call.arguments[0],
59
+ fixtures.storage.find.mock.calls[0].result
60
+ ) &&
61
+ isDeepStrictEqual(call.arguments[1], undefined) &&
62
+ isDeepStrictEqual(call.arguments[2], false)
63
+ )
64
+ )
28
65
  })
29
66
 
30
67
  it('should store entity', async () => {
31
68
  await state.commit(fixtures.initial)
32
69
 
33
- expect(fixtures.storage.store).toHaveBeenCalledWith(fixtures.initial.get.mock.results[0].value)
70
+ assert.ok(
71
+ fixtures.storage.store.mock.calls.some(
72
+ (call) =>
73
+ call.arguments.length === 2 &&
74
+ isDeepStrictEqual(call.arguments[0], fixtures.initial.get.mock.calls[0].result) &&
75
+ isDeepStrictEqual(call.arguments[1], fixtures.outbox.row.mock.calls[0].result)
76
+ )
77
+ )
34
78
  })
35
79
 
36
- it('should emit', async () => {
80
+ it('should publish the row', async () => {
37
81
  await state.commit(fixtures.entity)
38
82
 
39
- expect(fixtures.emitter.emit).toHaveBeenCalledWith(fixtures.entity.event.mock.results[0].value)
83
+ assert.ok(
84
+ fixtures.outbox.row.mock.calls.some(
85
+ (call) =>
86
+ call.arguments.length === 1 &&
87
+ isDeepStrictEqual(call.arguments[0], fixtures.entity.event.mock.calls[0].result)
88
+ )
89
+ )
90
+ assert.ok(
91
+ fixtures.outbox.publish.mock.calls.some(
92
+ (call) =>
93
+ call.arguments.length === 1 &&
94
+ isDeepStrictEqual(call.arguments[0], fixtures.outbox.row.mock.calls[0].result)
95
+ )
96
+ )
40
97
  })
41
98
 
42
- it('should not emit if state has not been changed', async () => {
43
- await state.commit(fixtures.unchanged)
99
+ it('should not publish if the write did not happen', async () => {
100
+ fixtures.storage.store.mock.mockImplementationOnce(() => false)
44
101
 
45
- expect(fixtures.emitter.emit).not.toHaveBeenCalled()
102
+ await state.commit(fixtures.entity)
103
+
104
+ assert.strictEqual(fixtures.outbox.publish.mock.callCount(), 0)
46
105
  })
106
+
107
+ it('should build the row before the write', async () => {
108
+ // the storage commits the row in the same transaction, so it must already exist
109
+ fixtures.storage.store.mock.mockImplementationOnce((_, row) => {
110
+ assert.notStrictEqual(row, undefined)
111
+
112
+ return true
113
+ })
114
+
115
+ await state.commit(fixtures.entity)
116
+ })
117
+
118
+ describe('assignment', () => {
119
+ const changeset = { query: 'q', export: () => ({ foo: 1 }) }
120
+
121
+ it('should pass the row to upsert and publish it', async () => {
122
+ const result = await state.apply(changeset, { foo: 1 })
123
+
124
+ assert.ok(
125
+ fixtures.storage.upsert.mock.calls.some(
126
+ (call) =>
127
+ call.arguments.length === 3 &&
128
+ isDeepStrictEqual(call.arguments[0], changeset.query) &&
129
+ isDeepStrictEqual(call.arguments[1], { foo: 1 }) &&
130
+ isDeepStrictEqual(call.arguments[2], fixtures.outbox.row.mock.calls[0].result)
131
+ )
132
+ )
133
+
134
+ assert.ok(
135
+ fixtures.outbox.publish.mock.calls.some(
136
+ (call) =>
137
+ call.arguments.length === 1 &&
138
+ isDeepStrictEqual(call.arguments[0], fixtures.outbox.row.mock.calls[0].result)
139
+ )
140
+ )
141
+ assert.deepStrictEqual(result, fixtures.storage.upsert.mock.calls[0].result)
142
+ })
143
+
144
+ it('should fill the state a storage without the outbox left alone', async () => {
145
+ await state.apply(changeset, { foo: 1 })
146
+
147
+ const row = fixtures.outbox.row.mock.calls[0].result
148
+
149
+ assert.deepStrictEqual(row.event.state, fixtures.storage.upsert.mock.calls[0].result)
150
+ assert.deepStrictEqual(row.event.input, { foo: 1 })
151
+ })
152
+ })
153
+
154
+ function resetCalls(target = [assert, fixtures], seen = new Set()) {
155
+ if (target === null || typeof target !== 'object' || seen.has(target)) return
156
+
157
+ seen.add(target)
158
+
159
+ for (const value of Object.values(target))
160
+ if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
161
+ else resetCalls(value, seen)
162
+ }
@@ -1,15 +1,13 @@
1
- 'use strict'
1
+ import { mock } from 'node:test'
2
2
 
3
- const { generate } = require('randomstring')
3
+ import { generate } from 'randomstring'
4
4
 
5
5
  const binding = (index) => ({
6
- request: jest.fn(async (request) => {
6
+ request: mock.fn(async (request) => {
7
7
  if (request?.pick !== undefined && request.pick !== index) return false
8
8
 
9
9
  return { output: generate() }
10
10
  })
11
11
  })
12
12
 
13
- const bindings = [0, 1, 2, 3, 4].map(binding)
14
-
15
- exports.bindings = bindings
13
+ export const bindings = [0, 1, 2, 3, 4].map(binding)
@@ -1,16 +1,25 @@
1
- 'use strict'
1
+ import { it, beforeEach, mock } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { isDeepStrictEqual } from 'node:util'
2
4
 
3
- jest.mock('../src/connector')
5
+ import { Connector } from '../source/connector.js'
4
6
 
5
- const { Connector } = require('../src/connector')
6
- const { Transmission } = require('../src/transmission')
7
- const { codes } = require('../src/exceptions')
8
- const fixtures = require('./transmission.fixtures')
7
+ // the fixtures are not connectors, so a dependency is recorded rather than linked
8
+ const depends = mock.method(Connector.prototype, 'depends', () => undefined)
9
+
10
+ const dependencies = (instance) =>
11
+ depends.mock.calls
12
+ .filter((call) => call.this === instance)
13
+ .map((call) => call.arguments[0])
14
+ import { Transmission } from '../source/transmission.js'
15
+ import { codes } from '../source/exceptions.js'
16
+ import * as fixtures from './transmission.fixtures.js'
9
17
 
10
18
  let transmission
11
19
 
12
20
  beforeEach(() => {
13
- jest.clearAllMocks()
21
+ resetCalls()
22
+ depends.mock.resetCalls()
14
23
  })
15
24
 
16
25
  beforeEach(() => {
@@ -18,29 +27,51 @@ beforeEach(() => {
18
27
  })
19
28
 
20
29
  it('should be instance of Connector depending on bindings', () => {
21
- expect(transmission).toBeInstanceOf(Connector)
22
- expect(Connector.mock.instances[0].depends).toHaveBeenCalledWith(fixtures.bindings)
30
+ assert.ok(transmission instanceof Connector)
31
+ assert.ok(
32
+ dependencies(transmission).some((one) => isDeepStrictEqual(one, fixtures.bindings))
33
+ )
23
34
  })
24
35
 
25
36
  it('should pass arguments and return value', async () => {
26
37
  const request = { foo: 'bar' }
27
38
  const result = await transmission.request(request)
28
39
 
29
- expect(fixtures.bindings[0].request).toHaveBeenCalledWith(request)
30
- expect(result).toBe(await fixtures.bindings[0].request.mock.results[0].value)
40
+ assert.ok(
41
+ fixtures.bindings[0].request.mock.calls.some(
42
+ (call) =>
43
+ call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], request)
44
+ )
45
+ )
46
+ assert.strictEqual(result, await fixtures.bindings[0].request.mock.calls[0].result)
31
47
  })
32
48
 
33
49
  it('should pick bindings sequentially', async () => {
34
50
  let result = await transmission.request()
35
- expect(result).toBe(await fixtures.bindings[0].request.mock.results[0].value)
51
+ assert.strictEqual(result, await fixtures.bindings[0].request.mock.calls[0].result)
36
52
 
37
53
  result = await transmission.request({ pick: 1 })
38
- expect(result).toBe(await fixtures.bindings[1].request.mock.results[0]?.value)
54
+ assert.strictEqual(result, await fixtures.bindings[1].request.mock.calls[0]?.result)
39
55
  })
40
56
 
41
57
  it('should throw exception if none succeeded', async () => {
42
- await expect(transmission.request({ pick: 5 })).rejects.toMatchObject({ code: codes.Transmission })
58
+ await assert.rejects(transmission.request({ pick: 5 }), (error) => {
59
+ assert.partialDeepStrictEqual(error, { code: codes.Transmission })
60
+ return true
61
+ })
43
62
 
44
- fixtures.bindings.forEach((binding) =>
45
- expect(binding.request).toHaveBeenCalled())
63
+ fixtures.bindings.forEach((binding) => assert.ok(binding.request.mock.callCount() > 0))
46
64
  })
65
+
66
+ function resetCalls(
67
+ target = [assert, depends, dependencies, fixtures],
68
+ seen = new Set()
69
+ ) {
70
+ if (target === null || typeof target !== 'object' || seen.has(target)) return
71
+
72
+ seen.add(target)
73
+
74
+ for (const value of Object.values(target))
75
+ if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
76
+ else resetCalls(value, seen)
77
+ }
@@ -0,0 +1,6 @@
1
+ import { Operation } from './operation.js';
2
+ import type { Store } from './operation.js';
3
+ export declare class Assignment extends Operation {
4
+ protected acquire(store: Store): Promise<void>;
5
+ protected commit(store: Store): Promise<void>;
6
+ }
@@ -0,0 +1,20 @@
1
+ import { Operation } from './operation.js';
2
+ export class Assignment extends Operation {
3
+ async acquire(store) {
4
+ const changeset = this.scope.changeset(store.request.query);
5
+ store.scope = changeset;
6
+ store.state = changeset.get();
7
+ }
8
+ async commit(store) {
9
+ const { scope, state, reply, request } = store;
10
+ if (reply.error !== undefined)
11
+ return;
12
+ const changeset = scope;
13
+ changeset.set(state);
14
+ const output = await this.scope.apply(changeset, request.input);
15
+ // assignment returns new state by default
16
+ if (store.reply.output === undefined)
17
+ store.reply.output = output;
18
+ }
19
+ }
20
+ //# sourceMappingURL=assignment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignment.js","sourceRoot":"","sources":["../source/assignment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI1C,MAAM,OAAO,UAAW,SAAQ,SAAS;IACpB,KAAK,CAAC,OAAO,CAAC,KAAY;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,KAAY,CAAC,CAAA;QAElE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAA;QACvB,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,CAAA;IAC/B,CAAC;IAEkB,KAAK,CAAC,MAAM,CAAC,KAAY;QAC1C,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;QAE9C,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,OAAM;QAErC,MAAM,SAAS,GAAG,KAAkB,CAAA;QAEpC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAEpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;QAE/D,0CAA0C;QAC1C,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;IACnE,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import { Connector } from './connector.js';
2
+ import type { Transmission } from './transmission.js';
3
+ import type { Request as Contract } from './contract/request.js';
4
+ import type { Request, Source } from './types/request.js';
5
+ export declare class Call extends Connector {
6
+ #private;
7
+ constructor(transmitter: Transmission, contract: Contract, source?: Source);
8
+ invoke(request?: Request): Promise<any>;
9
+ explain(): any;
10
+ }
@@ -0,0 +1,52 @@
1
+ import { Readable } from 'node:stream';
2
+ import { current, encode } from 'openspan';
3
+ import { Connector } from './connector.js';
4
+ export class Call extends Connector {
5
+ #transmitter;
6
+ #contract;
7
+ #source;
8
+ constructor(transmitter, contract, source) {
9
+ super();
10
+ this.#transmitter = transmitter;
11
+ this.#contract = contract;
12
+ this.#source = source;
13
+ this.depends(transmitter);
14
+ }
15
+ async invoke(request = {}) {
16
+ // the caller may have attributed the call itself, as the node bridge does
17
+ if (this.#source !== undefined)
18
+ request.source ??= this.#source;
19
+ this.#contract.fit(request);
20
+ // an operation that takes no input still has to send an explicit null
21
+ request.input ??= null;
22
+ // avoid validation on the recipient's side
23
+ request.authentic = true;
24
+ const context = current();
25
+ if (context !== undefined)
26
+ request.telemetry = encode(context);
27
+ const reply = await this.#transmitter.request(request);
28
+ if (reply === null)
29
+ return null;
30
+ else if (reply instanceof Readable)
31
+ return reply;
32
+ else {
33
+ if (reply.exception !== undefined)
34
+ throw reply.exception;
35
+ if (reply.error !== undefined)
36
+ return new RemoteError(reply.error);
37
+ else
38
+ return reply.output;
39
+ }
40
+ }
41
+ explain() {
42
+ return this.#contract.discovery;
43
+ }
44
+ }
45
+ // the remote error as a value: every property it carries, and nothing else enumerable
46
+ class RemoteError extends Error {
47
+ constructor(error) {
48
+ super();
49
+ Object.assign(this, error);
50
+ }
51
+ }
52
+ //# sourceMappingURL=call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call.js","sourceRoot":"","sources":["../source/call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAK1C,MAAM,OAAO,IAAK,SAAQ,SAAS;IACxB,YAAY,CAAc;IAC1B,SAAS,CAAU;IACnB,OAAO,CAAoB;IAEpC,YAAmB,WAAyB,EAAE,QAAkB,EAAE,MAAe;QAC/E,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;QAC/B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QAErB,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC3B,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,OAAO,GAAY,EAAE;QACvC,0EAA0E;QAC1E,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,CAAA;QAE/D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAE3B,sEAAsE;QACtE,OAAO,CAAC,KAAK,KAAK,IAAI,CAAA;QAEtB,2CAA2C;QAC3C,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;QAExB,MAAM,OAAO,GAAG,OAAO,EAAE,CAAA;QAEzB,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;QAE9D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAEtD,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;aAC1B,IAAI,KAAK,YAAY,QAAQ;YAAE,OAAO,KAAK,CAAA;aAC3C,CAAC;YACJ,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;gBAAE,MAAM,KAAK,CAAC,SAAS,CAAA;YAExD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;;gBAC7D,OAAO,KAAK,CAAC,MAAM,CAAA;QAC1B,CAAC;IACH,CAAC;IAEM,OAAO;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAA;IACjC,CAAC;CACF;AAED,sFAAsF;AACtF,MAAM,WAAY,SAAQ,KAAK;IAC7B,YAAmB,KAAa;QAC9B,KAAK,EAAE,CAAA;QAEP,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC5B,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import { Connector } from './connector.js';
2
+ import type { Algorithm } from './types/bridges.js';
3
+ export declare class Cascade extends Connector {
4
+ #private;
5
+ constructor(bridges: Algorithm[], preflight?: Connector);
6
+ run(...args: [any, any?]): Promise<any>;
7
+ }
@@ -0,0 +1,28 @@
1
+ import { Connector } from './connector.js';
2
+ export class Cascade extends Connector {
3
+ #last;
4
+ constructor(bridges, preflight) {
5
+ super();
6
+ // this.#bridges = bridges
7
+ this.#last = bridges[bridges.length - 1];
8
+ if (preflight === undefined)
9
+ this.depends(bridges);
10
+ else
11
+ this.depends(bridges).depends(preflight);
12
+ }
13
+ async run(...args) {
14
+ // const reply = {}
15
+ //
16
+ // for (const bridge of this.#bridges) {
17
+ // const partial = await bridge.execute(...args)
18
+ //
19
+ // if (partial.error) return { error: partial.error }
20
+ //
21
+ // merge(reply, partial)
22
+ // }
23
+ //
24
+ // return reply
25
+ return this.#last.execute(...args);
26
+ }
27
+ }
28
+ //# sourceMappingURL=cascade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascade.js","sourceRoot":"","sources":["../source/cascade.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,MAAM,OAAO,OAAQ,SAAQ,SAAS;IAC3B,KAAK,CAAW;IAEzB,YAAmB,OAAoB,EAAE,SAAqB;QAC5D,KAAK,EAAE,CAAA;QAEP,0BAA0B;QAC1B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAExC,IAAI,SAAS,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;;YAC7C,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC/C,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,GAAG,IAAiB;QACnC,mBAAmB;QACnB,EAAE;QACF,wCAAwC;QACxC,kDAAkD;QAClD,EAAE;QACF,uDAAuD;QACvD,EAAE;QACF,0BAA0B;QAC1B,IAAI;QACJ,EAAE;QACF,eAAe;QAEf,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;IACpC,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ import { Connector } from './connector.js';
2
+ import type { Locator } from './locator.js';
3
+ import type { Request } from './types/request.js';
4
+ /** What a component holds one of per endpoint: an operation, or the call that stands for it. */
5
+ export interface Invocable extends Connector {
6
+ invoke: (request: Request) => Promise<any>;
7
+ }
8
+ export declare class Component<O extends Invocable = Invocable> extends Connector {
9
+ #private;
10
+ readonly locator: Locator;
11
+ protected readonly operations: Record<string, O>;
12
+ protected kind: 'server' | 'client';
13
+ constructor(locator: Locator, operations: Record<string, O>);
14
+ invoke<T = any>(endpoint: string, request?: Request): Promise<T>;
15
+ }
@@ -0,0 +1,61 @@
1
+ import assert from 'node:assert';
2
+ import { console, current, decode, run } from 'openspan';
3
+ import { Connector } from './connector.js';
4
+ export class Component extends Connector {
5
+ locator;
6
+ operations;
7
+ kind = 'server';
8
+ /** span options per endpoint */
9
+ #spans = {};
10
+ constructor(locator, operations) {
11
+ super();
12
+ this.locator = locator;
13
+ this.operations = operations;
14
+ Object.values(operations).forEach((operation) => this.depends(operation));
15
+ }
16
+ async invoke(endpoint, request) {
17
+ if (!(endpoint in this.operations))
18
+ // `assert.fail`, not `assert.ok`: the message is built only when it is needed
19
+ assert.fail(`Endpoint '${endpoint}' is not provided by '${this.locator.id}'`);
20
+ // if the request carries no telemetry, the trace starts here
21
+ const remote = request?.telemetry === undefined ? null : decode(request.telemetry);
22
+ const task = async () => this.#process(endpoint, request);
23
+ if (remote === null)
24
+ return task();
25
+ else
26
+ return run(remote, task);
27
+ }
28
+ async #process(endpoint, request) {
29
+ return console.span(this.#span(endpoint), async () => {
30
+ const reply = await this.operations[endpoint].invoke(request);
31
+ if (reply?.exception !== undefined) {
32
+ const span = current();
33
+ if (span !== undefined)
34
+ span.status = 'error';
35
+ console.error('Failed to execute operation', {
36
+ endpoint: `${this.locator.id}.${endpoint}`,
37
+ exception: reply.exception
38
+ });
39
+ }
40
+ return reply;
41
+ });
42
+ }
43
+ /**
44
+ * The span of an endpoint never changes, so it is built once. Not in the constructor:
45
+ * `kind` is a field of the subclass, and those are assigned after this one is built.
46
+ *
47
+ */
48
+ #span(endpoint) {
49
+ let options = this.#spans[endpoint];
50
+ if (options === undefined) {
51
+ options = { name: `${this.locator.id}.${endpoint}`, kind: this.kind };
52
+ // the server span is emitted by the component itself, while the client span
53
+ // belongs to the calling service and inherits it from the context
54
+ if (this.kind === 'server')
55
+ options.service = this.locator.id;
56
+ this.#spans[endpoint] = options;
57
+ }
58
+ return options;
59
+ }
60
+ }
61
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../source/component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Connector } from './connector.js';
2
+ export declare class Composition extends Connector {
3
+ constructor(expositions: Connector[], producers: Connector[], receivers: Connector[], tenants: Connector[]);
4
+ protected open(): Promise<void>;
5
+ protected dispose(): Promise<void>;
6
+ }
@@ -0,0 +1,23 @@
1
+ import { console } from 'openspan';
2
+ import { Connector } from './connector.js';
3
+ export class Composition extends Connector {
4
+ // eslint-disable-next-line max-params
5
+ constructor(expositions, producers, receivers, tenants) {
6
+ super();
7
+ if (expositions.length > 0)
8
+ this.depends(expositions);
9
+ if (producers.length > 0)
10
+ this.depends(producers);
11
+ if (receivers.length > 0)
12
+ this.depends(receivers);
13
+ if (tenants.length > 0)
14
+ this.depends(tenants);
15
+ }
16
+ async open() {
17
+ console.info('Composition complete');
18
+ }
19
+ async dispose() {
20
+ console.info('Composition shutdown complete');
21
+ }
22
+ }
23
+ //# sourceMappingURL=composition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition.js","sourceRoot":"","sources":["../source/composition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,OAAO,WAAY,SAAQ,SAAS;IACxC,sCAAsC;IACtC,YACE,WAAwB,EACxB,SAAsB,EACtB,SAAsB,EACtB,OAAoB;QAEpB,KAAK,EAAE,CAAA;QAEP,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;QACrD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACjD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACjD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;IAEkB,KAAK,CAAC,IAAI;QAC3B,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IACtC,CAAC;IAEkB,KAAK,CAAC,OAAO;QAC9B,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;IAC/C,CAAC;CACF"}
@@ -0,0 +1,47 @@
1
+ /** Abstract connections hierarchy */
2
+ export declare class Connector {
3
+ #private;
4
+ readonly id: string;
5
+ connected: boolean;
6
+ constructor();
7
+ /**
8
+ * Creates a dependency and backlink with another Connector or a set of Connectors
9
+ *
10
+ * See .connect() and .disconnect()
11
+ *
12
+ */
13
+ depends(connector: Connector | Connector[]): Connector;
14
+ /**
15
+ * Creates a backlink to another Connector
16
+ *
17
+ * See .connect() and .disconnect()
18
+ *
19
+ */
20
+ link(connector: Connector): void;
21
+ /**
22
+ * Connects dependants then self
23
+ *
24
+ * In case of exception disconnects with current connection interruption
25
+ *
26
+ * Method is idempotent
27
+ *
28
+ */
29
+ connect(): Promise<void>;
30
+ /**
31
+ * Disconnects self then dependants
32
+ *
33
+ * Does nothing if there are connected linked Connectors
34
+ *
35
+ * Method is idempotent
36
+ *
37
+ */
38
+ disconnect(interrupt?: boolean): Promise<void>;
39
+ reconnect(): Promise<void>;
40
+ debug(node?: Record<string, any>): Record<string, any>;
41
+ /** Called on connection */
42
+ protected open(): Promise<void> | void;
43
+ /** Called on disconnection */
44
+ protected close(): Promise<void> | void;
45
+ /** Called after self and dependants disconnection is complete */
46
+ protected dispose(): Promise<void> | void;
47
+ }