@zlink-systems/framework 0.30.0 → 0.30.1

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 (245) hide show
  1. package/LICENSE +150 -68
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
  4. package/dist/contracts/Channels/Calls.d.ts +2 -1
  5. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  6. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  7. package/dist/contracts/Handlers/Attributes.js +7 -11
  8. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  9. package/dist/contracts/Handlers/JsonContract.js +4 -153
  10. package/dist/contracts/Spots/Contracts.d.ts +2 -1
  11. package/dist/nest-integration.d.ts +1 -1
  12. package/dist/nest-integration.js +2 -1
  13. package/dist/runtime/actors/actor-client.d.ts +1 -1
  14. package/dist/runtime/actors/actor-client.js +14 -12
  15. package/dist/runtime/actors/actor-handoff.d.ts +1 -1
  16. package/dist/runtime/actors/actor-handoff.js +7 -4
  17. package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
  18. package/dist/runtime/actors/actor-local-native-join.js +9 -12
  19. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  20. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  21. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  22. package/dist/runtime/actors/index.d.ts +2 -1
  23. package/dist/runtime/actors/index.js +18 -6
  24. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  25. package/dist/runtime/admission.d.ts +1 -1
  26. package/dist/runtime/admission.js +15 -5
  27. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
  28. package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
  29. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +2 -1
  30. package/dist/runtime/application-jobs/application-job-queue-scope.js +37 -22
  31. package/dist/runtime/application-jobs/contracts.d.ts +10 -1
  32. package/dist/runtime/backend/contracts/index.d.ts +18 -9
  33. package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
  34. package/dist/runtime/backend/mesh-completion-table.js +149 -49
  35. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
  36. package/dist/runtime/backend/mesh-dispatch-pump.js +32 -11
  37. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  38. package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
  39. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  40. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  41. package/dist/runtime/backend/node/node-raw-binding-port.js +42 -22
  42. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +13 -5
  43. package/dist/runtime/backend/node/node-raw-mesh-backend.js +69 -51
  44. package/dist/runtime/backend/node/node-socket-backend-adapter.js +6 -6
  45. package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
  46. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  47. package/dist/runtime/backend/runtime-message.js +5 -0
  48. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  49. package/dist/runtime/backend/runtime-values.js +2 -1
  50. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  51. package/dist/runtime/channels/channel-clients.js +58 -21
  52. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
  53. package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
  54. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  55. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  56. package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
  57. package/dist/runtime/channels/channel-dispatchers.js +27 -26
  58. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  59. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  60. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  61. package/dist/runtime/channels/channel-envelope.js +83 -8
  62. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  63. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  64. package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
  65. package/dist/runtime/channels/channel-runtime-manager.js +12 -12
  66. package/dist/runtime/channels/channel-transports.d.ts +18 -15
  67. package/dist/runtime/channels/channel-transports.js +48 -31
  68. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  69. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  70. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  71. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  72. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  73. package/dist/runtime/channels/source-spot-router.js +4 -4
  74. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  75. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  76. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  77. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  78. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  79. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  80. package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
  81. package/dist/runtime/execution/serial-execution-queue.js +1 -0
  82. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  83. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  84. package/dist/runtime/foundation/durable-service-request.js +98 -0
  85. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  86. package/dist/runtime/foundation/operation-identity.js +5 -1
  87. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +22 -5
  88. package/dist/runtime/foundation/raw-service-mesh-runtime.js +356 -232
  89. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
  90. package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
  91. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  92. package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
  93. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
  94. package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -4
  95. package/dist/runtime/foundation/service-stateful-runtime.js +44 -103
  96. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -5
  97. package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
  98. package/dist/runtime/foundation/service-topology-registry.js +61 -27
  99. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
  100. package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
  101. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  102. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  103. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  104. package/dist/runtime/host/application-job-queue.d.ts +19 -7
  105. package/dist/runtime/host/application-job-queue.js +150 -42
  106. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  107. package/dist/runtime/host/entry-actor-runtime.js +3 -0
  108. package/dist/runtime/host/index.d.ts +7 -1
  109. package/dist/runtime/host/index.js +142 -118
  110. package/dist/runtime/host/remote-bound-session-relay.js +2 -18
  111. package/dist/runtime/host/route-mesh-runtime.js +1 -1
  112. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  113. package/dist/runtime/host/service-relocation-control.js +10 -4
  114. package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
  115. package/dist/runtime/host/service-relocation-host-runtime.js +213 -241
  116. package/dist/runtime/host/spot-address-transport.js +3 -2
  117. package/dist/runtime/host/spot-runtime-options-factory.js +1 -0
  118. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  119. package/dist/runtime/locations/actor-location-claims.js +34 -19
  120. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  121. package/dist/runtime/locations/lifecycle.js +2 -5
  122. package/dist/runtime/locations/runtime.d.ts +1 -1
  123. package/dist/runtime/locations/runtime.js +24 -23
  124. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  125. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  126. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  127. package/dist/runtime/messaging/packet-name.js +8 -24
  128. package/dist/runtime/messaging/request-result.d.ts +2 -0
  129. package/dist/runtime/messaging/request-result.js +54 -0
  130. package/dist/runtime/messaging/submission-result.d.ts +1 -0
  131. package/dist/runtime/messaging/submission-result.js +5 -2
  132. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
  133. package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
  134. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
  135. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
  136. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
  137. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
  138. package/dist/runtime/spots/index.d.ts +3 -0
  139. package/dist/runtime/spots/index.js +9 -2
  140. package/dist/runtime/spots/spot-activation.d.ts +1 -0
  141. package/dist/runtime/spots/spot-activation.js +17 -8
  142. package/dist/runtime/spots/spot-entry-activation.js +6 -2
  143. package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
  144. package/dist/runtime/spots/spot-handler-registry.js +18 -8
  145. package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
  146. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  147. package/dist/runtime/spots/spot-outbound.js +24 -15
  148. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  149. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  150. package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -0
  151. package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
  152. package/dist/runtime/spots/spot-timer.js +1 -0
  153. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  154. package/dist/runtime/streams/stream-session-runtime.js +13 -27
  155. package/package.json +2 -2
  156. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  157. package/src/contracts/Channels/Calls.ts +2 -1
  158. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  159. package/src/contracts/Handlers/Attributes.ts +14 -21
  160. package/src/contracts/Handlers/JsonContract.ts +8 -216
  161. package/src/contracts/Spots/Contracts.ts +2 -1
  162. package/src/nest-integration.ts +1 -0
  163. package/src/runtime/actors/actor-client.ts +40 -16
  164. package/src/runtime/actors/actor-handoff.ts +9 -4
  165. package/src/runtime/actors/actor-join-relocation.ts +1 -0
  166. package/src/runtime/actors/actor-local-native-join.ts +17 -26
  167. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  168. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  169. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  170. package/src/runtime/actors/index.ts +19 -5
  171. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  172. package/src/runtime/admission.ts +18 -5
  173. package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
  174. package/src/runtime/application-jobs/application-job-queue-scope.ts +51 -22
  175. package/src/runtime/application-jobs/contracts.ts +14 -1
  176. package/src/runtime/backend/contracts/index.ts +53 -14
  177. package/src/runtime/backend/mesh-completion-table.ts +156 -57
  178. package/src/runtime/backend/mesh-dispatch-pump.ts +40 -10
  179. package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
  180. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  181. package/src/runtime/backend/node/node-raw-binding-port.ts +57 -30
  182. package/src/runtime/backend/node/node-raw-mesh-backend.ts +128 -65
  183. package/src/runtime/backend/node/node-socket-backend-adapter.ts +21 -6
  184. package/src/runtime/backend/raw-binding-port.ts +7 -2
  185. package/src/runtime/backend/runtime-message.ts +6 -0
  186. package/src/runtime/backend/runtime-values.ts +1 -0
  187. package/src/runtime/channels/channel-clients.ts +90 -41
  188. package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
  189. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  190. package/src/runtime/channels/channel-dispatchers.ts +29 -27
  191. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  192. package/src/runtime/channels/channel-envelope.ts +133 -8
  193. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  194. package/src/runtime/channels/channel-runtime-manager.ts +29 -12
  195. package/src/runtime/channels/channel-transports.ts +128 -60
  196. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  197. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  198. package/src/runtime/channels/source-spot-router.ts +8 -4
  199. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  200. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  201. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  202. package/src/runtime/execution/serial-execution-queue.ts +2 -0
  203. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  204. package/src/runtime/foundation/durable-service-request.ts +137 -0
  205. package/src/runtime/foundation/operation-identity.ts +5 -1
  206. package/src/runtime/foundation/raw-service-mesh-runtime.ts +484 -293
  207. package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
  208. package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
  209. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  210. package/src/runtime/foundation/service-stateful-runtime.ts +67 -125
  211. package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -5
  212. package/src/runtime/foundation/service-topology-registry.ts +91 -36
  213. package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
  214. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  215. package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
  216. package/src/runtime/host/application-job-queue.ts +175 -41
  217. package/src/runtime/host/entry-actor-runtime.ts +4 -0
  218. package/src/runtime/host/index.ts +201 -156
  219. package/src/runtime/host/remote-bound-session-relay.ts +2 -23
  220. package/src/runtime/host/route-mesh-runtime.ts +1 -1
  221. package/src/runtime/host/service-relocation-control.ts +11 -5
  222. package/src/runtime/host/service-relocation-host-runtime.ts +315 -291
  223. package/src/runtime/host/spot-address-transport.ts +4 -2
  224. package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
  225. package/src/runtime/locations/actor-location-claims.ts +52 -30
  226. package/src/runtime/locations/lifecycle.ts +8 -26
  227. package/src/runtime/locations/runtime.ts +28 -24
  228. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  229. package/src/runtime/messaging/packet-name.ts +5 -25
  230. package/src/runtime/messaging/request-result.ts +58 -0
  231. package/src/runtime/messaging/submission-result.ts +5 -1
  232. package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
  233. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  234. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +43 -23
  235. package/src/runtime/spots/index.ts +14 -2
  236. package/src/runtime/spots/spot-activation.ts +28 -10
  237. package/src/runtime/spots/spot-entry-activation.ts +9 -2
  238. package/src/runtime/spots/spot-handler-registry.ts +41 -8
  239. package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
  240. package/src/runtime/spots/spot-outbound.ts +36 -16
  241. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  242. package/src/runtime/spots/spot-runtime-ports.ts +1 -0
  243. package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
  244. package/src/runtime/spots/spot-timer.ts +5 -1
  245. package/src/runtime/streams/stream-session-runtime.ts +12 -29
@@ -1,216 +1,8 @@
1
- const MAX_CONTRACT_SCHEMA_DEPTH = 64;
2
-
3
- /** Describes the fields accepted by the default framework-json-v1 serializer. */
4
- export type ZLinkJsonSchema =
5
- | { readonly type: 'boolean' }
6
- | { readonly type: 'string' }
7
- | { readonly type: 'number' }
8
- | { readonly type: 'int32' }
9
- | { readonly type: 'uint32' }
10
- | { readonly type: 'int64' }
11
- | { readonly type: 'uint64' }
12
- | { readonly type: 'bytes' }
13
- | { readonly type: 'enum'; readonly names: readonly string[] }
14
- | { readonly type: 'nullable'; readonly value: ZLinkJsonSchema }
15
- | { readonly type: 'array'; readonly items: ZLinkJsonSchema }
16
- | { readonly type: 'record'; readonly values: ZLinkJsonSchema }
17
- | {
18
- readonly type: 'object';
19
- readonly properties: Readonly<Record<string, ZLinkJsonSchema>>;
20
- readonly required: readonly string[];
21
- /** Unknown properties are ignored during decoding unless this is false. */
22
- readonly additionalProperties?: boolean;
23
- };
24
-
25
- /**
26
- * Describes the request and optional reply fields carried under one packet
27
- * name by the default JSON serializer.
28
- */
29
- export interface ZLinkPacketJsonContract {
30
- readonly payload: ZLinkJsonSchema;
31
- readonly reply?: ZLinkJsonSchema;
32
- }
33
-
34
- const ZLINK_PACKET_JSON_CONTRACTS = Symbol.for('@zlink-systems/framework:packet-json-contracts');
35
-
36
- export function defineZLinkPacketJsonContract(
37
- packetName: string,
38
- contract: ZLinkPacketJsonContract
39
- ): ZLinkPacketJsonContract {
40
- if (packetName.trim().length === 0) {
41
- throw new TypeError('ZLink packet name must not be empty.');
42
- }
43
- const runtimeContract: unknown = contract;
44
- if (typeof runtimeContract !== 'object' || runtimeContract === null) {
45
- throw new TypeError('ZLink packet JSON contract must be an object.');
46
- }
47
- const normalizedContract = runtimeContract as ZLinkPacketJsonContract;
48
- const normalized = Object.freeze({
49
- payload: normalizeJsonSchema(normalizedContract.payload, new Set(), 0),
50
- ...(normalizedContract.reply === undefined
51
- ? {}
52
- : { reply: normalizeJsonSchema(normalizedContract.reply, new Set(), 0) })
53
- });
54
- const contracts = packetJsonContracts();
55
- const current = contracts.get(packetName);
56
- if (current !== undefined && canonicalContract(current) !== canonicalContract(normalized)) {
57
- throw new TypeError(
58
- `ZLink packet '${packetName}' has conflicting JSON contracts in one process.`
59
- );
60
- }
61
- if (current !== undefined) return current;
62
- contracts.set(packetName, normalized);
63
- return normalized;
64
- }
65
-
66
- export function readZLinkPacketJsonContract(
67
- packetName: string
68
- ): ZLinkPacketJsonContract | undefined {
69
- return packetJsonContracts().get(packetName);
70
- }
71
-
72
- function normalizeJsonSchema(
73
- schema: ZLinkJsonSchema,
74
- parents: Set<object>,
75
- depth: number
76
- ): ZLinkJsonSchema {
77
- // Keep the runtime boundary defensive for JavaScript callers even though
78
- // the TypeScript signature describes the accepted shape.
79
- const runtimeSchema: unknown = schema;
80
- if (
81
- typeof runtimeSchema !== 'object' ||
82
- runtimeSchema === null ||
83
- depth > MAX_CONTRACT_SCHEMA_DEPTH
84
- ) {
85
- throw new TypeError(
86
- `ZLink packet JSON schema must be an acyclic object with at most ${MAX_CONTRACT_SCHEMA_DEPTH} levels.`
87
- );
88
- }
89
- const normalizedSchema = runtimeSchema as ZLinkJsonSchema;
90
- if (parents.has(normalizedSchema))
91
- throw new TypeError('ZLink packet JSON schema must not contain a cycle.');
92
- const nextParents = new Set(parents).add(normalizedSchema);
93
- switch (normalizedSchema.type) {
94
- case 'boolean':
95
- case 'string':
96
- case 'number':
97
- case 'int32':
98
- case 'uint32':
99
- case 'int64':
100
- case 'uint64':
101
- case 'bytes':
102
- return Object.freeze({ type: normalizedSchema.type });
103
- case 'enum': {
104
- if (
105
- !Array.isArray(normalizedSchema.names) ||
106
- normalizedSchema.names.length === 0 ||
107
- normalizedSchema.names.some((name) => typeof name !== 'string' || name.length === 0)
108
- ) {
109
- throw new TypeError('ZLink packet enum schema requires non-empty string names.');
110
- }
111
- if (new Set(normalizedSchema.names).size !== normalizedSchema.names.length) {
112
- throw new TypeError('ZLink packet enum schema names must be unique.');
113
- }
114
- return Object.freeze({ type: 'enum', names: Object.freeze([...normalizedSchema.names]) });
115
- }
116
- case 'nullable':
117
- return Object.freeze({
118
- type: 'nullable',
119
- value: normalizeJsonSchema(normalizedSchema.value, nextParents, depth + 1)
120
- });
121
- case 'array':
122
- return Object.freeze({
123
- type: 'array',
124
- items: normalizeJsonSchema(normalizedSchema.items, nextParents, depth + 1)
125
- });
126
- case 'record':
127
- return Object.freeze({
128
- type: 'record',
129
- values: normalizeJsonSchema(normalizedSchema.values, nextParents, depth + 1)
130
- });
131
- case 'object': {
132
- const runtimeProperties: unknown = normalizedSchema.properties;
133
- if (
134
- typeof runtimeProperties !== 'object' ||
135
- runtimeProperties === null ||
136
- Array.isArray(runtimeProperties)
137
- ) {
138
- throw new TypeError('ZLink packet object schema properties must be an object.');
139
- }
140
- if (
141
- !Array.isArray(normalizedSchema.required) ||
142
- normalizedSchema.required.some((name) => typeof name !== 'string' || name.length === 0)
143
- ) {
144
- throw new TypeError('ZLink packet object schema required must contain property names.');
145
- }
146
- if (
147
- normalizedSchema.additionalProperties !== undefined &&
148
- typeof normalizedSchema.additionalProperties !== 'boolean'
149
- ) {
150
- throw new TypeError('ZLink packet object schema additionalProperties must be boolean.');
151
- }
152
- const properties: Record<string, ZLinkJsonSchema> = {};
153
- for (const [name, property] of Object.entries(
154
- runtimeProperties as Record<string, ZLinkJsonSchema>
155
- )) {
156
- if (isPrototypeKey(name)) {
157
- throw new TypeError(`ZLink packet JSON property '${name}' is not allowed.`);
158
- }
159
- properties[name] = normalizeJsonSchema(property, nextParents, depth + 1);
160
- }
161
- if (new Set(normalizedSchema.required).size !== normalizedSchema.required.length) {
162
- throw new TypeError('ZLink packet JSON required properties must be unique.');
163
- }
164
- for (const name of normalizedSchema.required) {
165
- if (isPrototypeKey(name)) {
166
- throw new TypeError(`ZLink packet JSON property '${name}' is not allowed.`);
167
- }
168
- if (!Object.prototype.hasOwnProperty.call(properties, name)) {
169
- throw new TypeError(
170
- `ZLink packet JSON required property '${name}' has no property schema.`
171
- );
172
- }
173
- }
174
- return Object.freeze({
175
- type: 'object',
176
- properties: Object.freeze(properties),
177
- required: Object.freeze([...normalizedSchema.required]),
178
- ...(normalizedSchema.additionalProperties === undefined
179
- ? {}
180
- : { additionalProperties: normalizedSchema.additionalProperties })
181
- });
182
- }
183
- }
184
- throw new TypeError(
185
- `ZLink packet JSON schema type '${String((normalizedSchema as { type?: unknown }).type)}' is not supported.`
186
- );
187
- }
188
-
189
- function packetJsonContracts(): Map<string, ZLinkPacketJsonContract> {
190
- const root = globalThis as typeof globalThis & Record<symbol, unknown>;
191
- let contracts = root[ZLINK_PACKET_JSON_CONTRACTS] as
192
- Map<string, ZLinkPacketJsonContract> | undefined;
193
- if (contracts === undefined) {
194
- contracts = new Map();
195
- Object.defineProperty(root, ZLINK_PACKET_JSON_CONTRACTS, {
196
- configurable: false,
197
- enumerable: false,
198
- value: contracts,
199
- writable: false
200
- });
201
- }
202
- return contracts;
203
- }
204
-
205
- function canonicalContract(value: unknown): string {
206
- if (Array.isArray(value)) return `[${value.map(canonicalContract).join(',')}]`;
207
- if (typeof value !== 'object' || value === null) return JSON.stringify(value);
208
- return `{${Object.entries(value as Record<string, unknown>)
209
- .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
210
- .map(([key, item]) => `${JSON.stringify(key)}:${canonicalContract(item)}`)
211
- .join(',')}}`;
212
- }
213
-
214
- function isPrototypeKey(name: string): boolean {
215
- return name === '__proto__' || name === 'prototype' || name === 'constructor';
216
- }
1
+ export {
2
+ defineZLinkPacketJsonContract,
3
+ readZLinkPacketJsonContract
4
+ } from '@zlink-systems/stream-wire/internal/json';
5
+ export type {
6
+ ZLinkJsonSchema,
7
+ ZLinkPacketJsonContract
8
+ } from '@zlink-systems/stream-wire/internal/json';
@@ -2,6 +2,7 @@ import type { ZLinkActor } from '../Actors';
2
2
  import type { ZLinkChannelRequestCall, ZLinkPublishCall, ZLinkSendCall } from '../Channels';
3
3
  import type { RoutingId, SpotId, Type, ZLinkMessageMetadata } from '../Common';
4
4
  import type { ZLinkSpotTimerHandler } from '../Handlers';
5
+ import type { ZLinkRequest } from '../Handlers/Attributes';
5
6
  import type { ZLinkTimer, ZLinkTimerOptions } from '../Timers';
6
7
  import type {
7
8
  ZLinkEntrySpot,
@@ -106,7 +107,7 @@ export interface ZLinkSpotRequestCall {
106
107
  instanceSpot(instanceSpotType: string): this;
107
108
  inMesh(meshName: string): this;
108
109
  timeout(timeoutMs: number): this;
109
- submit<TReply>(signal?: AbortSignal): Promise<TReply>;
110
+ submit<TReply>(signal?: AbortSignal): ZLinkRequest<TReply>;
110
111
  yield<TReply>(signal?: AbortSignal): Promise<TReply>;
111
112
  }
112
113
 
@@ -77,6 +77,7 @@ export {
77
77
  type ZLinkHandlerFilterScopeRunner
78
78
  } from './runtime/channels/handler-filter-scope';
79
79
  export {
80
+ registerHandlerInstanceScopeFactory as registerIntegrationHandlerInstanceScopeFactory,
80
81
  disposeOwnedInstance as disposeIntegrationHandler,
81
82
  disposeOwnedInstances as disposeIntegrationHandlers
82
83
  } from './runtime/handlers/handler-instance-scope';
@@ -1,4 +1,6 @@
1
1
  import { ZlinkStreamContentType } from '@zlink-systems/stream-wire';
2
+ import { createZLinkRequest } from '../messaging/request-result';
3
+ import type { ZLinkRequest } from '../../contracts/Handlers/Attributes';
2
4
  import {
3
5
  type ActorRef,
4
6
  type RoutingId,
@@ -89,7 +91,8 @@ export interface ZLinkActorClientOptions {
89
91
  parts: readonly Message[],
90
92
  returnResponse: boolean,
91
93
  actor: ActorRef,
92
- deadlineUnixMs?: number
94
+ deadlineUnixMs?: number,
95
+ onAdmitted?: () => void
93
96
  ) => Promise<unknown> | undefined;
94
97
  readonly sendErrorReporter?: (error: unknown) => void;
95
98
  readonly routeTransport?: ZLinkActorRoutedJoinTransport;
@@ -118,8 +121,17 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
118
121
  requestToActor(actorId: string, request: unknown): ZLinkActorRequestCall {
119
122
  requireActorId(actorId);
120
123
  return new DefaultZLinkActorRequestCall(
121
- (packetName, timeoutMs, metadata, signal) =>
122
- this.request(actorId, packetName, request, timeoutMs, metadata, signal, 'async'),
124
+ (packetName, timeoutMs, metadata, signal, onAdmitted) =>
125
+ this.request(
126
+ actorId,
127
+ packetName,
128
+ request,
129
+ timeoutMs,
130
+ metadata,
131
+ signal,
132
+ 'async',
133
+ onAdmitted
134
+ ),
123
135
  (packetName, timeoutMs, metadata, signal) =>
124
136
  this.request(actorId, packetName, request, timeoutMs, metadata, signal, 'yield'),
125
137
  actorId,
@@ -211,7 +223,8 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
211
223
  timeoutMs: number | undefined,
212
224
  metadata: ReadonlyMap<string, string>,
213
225
  signal?: AbortSignal,
214
- waitPolicy: 'async' | 'yield' = 'async'
226
+ waitPolicy: 'async' | 'yield' = 'async',
227
+ onAdmitted?: () => void
215
228
  ): Promise<TReply> {
216
229
  throwIfAborted(signal);
217
230
  const sourceSpotId = currentZLinkActorExecution()?.spotId ?? currentZLinkSpotSerialSourceId();
@@ -267,7 +280,8 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
267
280
  parts,
268
281
  true,
269
282
  routedActor,
270
- deadlineUnixMs
283
+ deadlineUnixMs,
284
+ onAdmitted
271
285
  );
272
286
  if (handoff !== undefined) {
273
287
  const submissions = [handoff];
@@ -278,7 +292,8 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
278
292
  parts,
279
293
  true,
280
294
  routedActor,
281
- deadlineUnixMs
295
+ deadlineUnixMs,
296
+ onAdmitted
282
297
  );
283
298
  if (duplicate !== undefined) submissions.push(duplicate);
284
299
  }
@@ -297,7 +312,8 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
297
312
  remainingActorRequestTimeout(actorId, deadlineMs),
298
313
  signal,
299
314
  route,
300
- messageFollow
315
+ messageFollow,
316
+ onAdmitted
301
317
  );
302
318
  } catch (error) {
303
319
  if (isStaleActorError(error)) {
@@ -423,7 +439,8 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
423
439
  timeoutMs: number | undefined,
424
440
  signal?: AbortSignal,
425
441
  route?: ZLinkResolvedActorRoute,
426
- messageFollowContext?: ZLinkActorMessageFollowContext
442
+ messageFollowContext?: ZLinkActorMessageFollowContext,
443
+ onAdmitted?: () => void
427
444
  ): Promise<TReply> {
428
445
  const node = this.requireNode(meshName);
429
446
  if (
@@ -459,7 +476,7 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
459
476
  this.options.routeTransport,
460
477
  remoteActorRouteTarget(route),
461
478
  relay,
462
- { timeoutMs, signal },
479
+ { timeoutMs, signal, onAdmitted },
463
480
  `Remote Actor request is not available for '${actor.actorId}'.`,
464
481
  (replyParts) => JSON.parse(replyParts[0]?.getString('utf8') ?? '{}')
465
482
  );
@@ -481,7 +498,8 @@ export class DefaultZLinkActorClient implements ZLinkActorClient {
481
498
  () =>
482
499
  node.requestToActor(actor, toMessageLikeParts(parts), {
483
500
  flags: ZLINK_BACKEND_SEND_NONE,
484
- timeoutMs
501
+ timeoutMs,
502
+ onAdmitted
485
503
  }),
486
504
  signal
487
505
  );
@@ -700,7 +718,8 @@ class DefaultZLinkActorRequestCall implements ZLinkActorRequestCall {
700
718
  packetName: string | undefined,
701
719
  timeoutMs: number | undefined,
702
720
  metadata: ReadonlyMap<string, string>,
703
- signal?: AbortSignal
721
+ signal?: AbortSignal,
722
+ onAdmitted?: () => void
704
723
  ) => Promise<TReply>,
705
724
  private readonly yieldSubmitter: <TReply>(
706
725
  packetName: string | undefined,
@@ -728,8 +747,9 @@ class DefaultZLinkActorRequestCall implements ZLinkActorRequestCall {
728
747
  return this;
729
748
  }
730
749
 
731
- submit<TReply>(signal?: AbortSignal): Promise<TReply> {
732
- return this.execute<TReply>('async', signal);
750
+ submit<TReply>(signal?: AbortSignal): ZLinkRequest<TReply> {
751
+ this.rejectSelfActorRequest();
752
+ return createZLinkRequest((onAdmitted) => this.execute<TReply>('async', signal, onAdmitted));
733
753
  }
734
754
 
735
755
  yield<TReply>(signal?: AbortSignal): Promise<TReply> {
@@ -739,9 +759,12 @@ class DefaultZLinkActorRequestCall implements ZLinkActorRequestCall {
739
759
  return turn.yieldPromise(pending);
740
760
  }
741
761
 
742
- private execute<TReply>(waitPolicy: 'async' | 'yield', signal?: AbortSignal): Promise<TReply> {
762
+ private execute<TReply>(
763
+ waitPolicy: 'async' | 'yield',
764
+ signal?: AbortSignal,
765
+ onAdmitted?: () => void
766
+ ): Promise<TReply> {
743
767
  ensureSingleSubmit(this.executed);
744
- this.rejectSelfActorRequest();
745
768
  this.executed = true;
746
769
  throwIfAborted(signal);
747
770
  const submitter = waitPolicy === 'async' ? this.asyncSubmitter : this.yieldSubmitter;
@@ -749,7 +772,8 @@ class DefaultZLinkActorRequestCall implements ZLinkActorRequestCall {
749
772
  this.packet ?? resolveFrameworkPacketName(this.request, undefined, 'Actor'),
750
773
  this.timeoutMs ?? this.defaultRequestTimeoutMs,
751
774
  this.selectedMetadata,
752
- signal
775
+ signal,
776
+ onAdmitted
753
777
  );
754
778
  }
755
779
 
@@ -776,7 +776,8 @@ export class ZLinkActorHandoffCoordinator {
776
776
  fallbackActorRef?: ActorRef,
777
777
  deadlineUnixMs?: number,
778
778
  messageFollowOrigin?: ZLinkMessageFollowOrigin,
779
- provisionalReplay?: ZLinkActorHandoffDispatch
779
+ provisionalReplay?: ZLinkActorHandoffDispatch,
780
+ onAdmitted?: () => void
780
781
  ): Promise<unknown> | undefined {
781
782
  const incomingContext = actorMessageFollowContext(fallbackActorRef);
782
783
  const originalDeadlineUnixMs =
@@ -871,6 +872,7 @@ export class ZLinkActorHandoffCoordinator {
871
872
  });
872
873
  });
873
874
  releaseApplicationJobPermitForDurableHandoff();
875
+ onAdmitted?.();
874
876
  if (handoff.prefixRelease !== undefined) {
875
877
  try {
876
878
  this.admitPendingPrefix(actorId, handoff, handoff.prefixRelease);
@@ -916,7 +918,7 @@ export class ZLinkActorHandoffCoordinator {
916
918
  incomingContext,
917
919
  messageFollowOrigin
918
920
  );
919
- return this.enqueueMessageFollow(followRoute, actorId, packet);
921
+ return this.enqueueMessageFollow(followRoute, actorId, packet, onAdmitted);
920
922
  }
921
923
  this.options.onMarker?.('message_follow_rejected', actorId);
922
924
  return Promise.reject(actorLocationStale(actorId));
@@ -973,7 +975,7 @@ export class ZLinkActorHandoffCoordinator {
973
975
  context,
974
976
  messageFollowOrigin
975
977
  );
976
- return this.enqueueMessageFollow(followRoute, actorId, packet);
978
+ return this.enqueueMessageFollow(followRoute, actorId, packet, onAdmitted);
977
979
  }
978
980
 
979
981
  snapshot(actorId: string): readonly ZLinkActorHandoffPacket[] {
@@ -1440,7 +1442,8 @@ export class ZLinkActorHandoffCoordinator {
1440
1442
  private enqueueMessageFollow(
1441
1443
  entry: MessageFollowRoute,
1442
1444
  actorId: string,
1443
- packet: ZLinkActorHandoffPacket
1445
+ packet: ZLinkActorHandoffPacket,
1446
+ onAdmitted?: () => void
1444
1447
  ): Promise<unknown> {
1445
1448
  const context = packet.messageFollowContext;
1446
1449
  const duplicate = entry.operations.get(context.operationId);
@@ -1453,6 +1456,7 @@ export class ZLinkActorHandoffCoordinator {
1453
1456
  this.options.onMarker?.('message_follow_rejected', actorId);
1454
1457
  return Promise.reject(actorLocationStale(actorId));
1455
1458
  }
1459
+ onAdmitted?.();
1456
1460
  return duplicate.result;
1457
1461
  }
1458
1462
  const bytes = packetBytes(packet);
@@ -1474,6 +1478,7 @@ export class ZLinkActorHandoffCoordinator {
1474
1478
  replyRouteId: context.replyRouteId,
1475
1479
  result
1476
1480
  });
1481
+ onAdmitted?.();
1477
1482
  entry.tail = entry.tail.then(async () => {
1478
1483
  try {
1479
1484
  resolve(await this.relayMessageFollow(actorId, entry, packet));
@@ -30,6 +30,7 @@ export interface ZLinkActorJoinRelocation {
30
30
  };
31
31
  /** Target's advertised relocation state chunk cap from the accepted admission reply. */
32
32
  readonly advertisedReceiveChunkLimitBytes?: number;
33
+ readonly deadlineAtMs?: number;
33
34
  readonly signal?: AbortSignal;
34
35
  }): Promise<{
35
36
  readonly actorRef: ZLinkBackendActorRef;
@@ -199,33 +199,24 @@ export class ZLinkLocalNativeActorJoin {
199
199
  );
200
200
  }
201
201
  const membershipEpoch = location.membershipEpoch + 1n;
202
+ const currentActor = toFrameworkActorRef(actorRef, meshName);
203
+ const authorityOwnerGeneration = state.locationGeneration ?? actorRef.generation;
202
204
  const commit = async (spot?: ZLinkSpot): Promise<void> => {
203
205
  throwIfAborted(signal);
204
- if (target.spotKind === ZLinkSpotKind.Entry) {
205
- await this.options.locationLifecycle?.notifyActorLeftSpot(
206
- actorType,
207
- actor.context.actorId,
208
- storeSpotId,
209
- spotGeneration,
210
- membershipEpoch,
211
- node.status().lifecycleGeneration
212
- );
213
- } else {
214
- await this.options.locationLifecycle?.notifyActorJoinedSpot(
215
- actorType,
216
- actor.context.actorId,
217
- meshName,
218
- storeSpotId,
219
- spotGeneration,
220
- membershipEpoch,
221
- node.status().lifecycleGeneration
222
- );
223
- }
206
+ await this.options.locationLifecycle?.commitActorMembership(
207
+ actorType,
208
+ currentActor,
209
+ authorityOwnerGeneration,
210
+ storeSpotId,
211
+ spotGeneration,
212
+ target.spotKind === ZLinkSpotKind.Entry ? ZLinkSpotKind.Entry : ZLinkSpotKind.User,
213
+ node.status().lifecycleGeneration
214
+ );
224
215
  const committedActor = node.restoreActorAuthority!(
225
216
  actor.context.actorId,
226
217
  actorType,
227
218
  actorRef.generation,
228
- state.locationGeneration ?? actorRef.generation,
219
+ authorityOwnerGeneration,
229
220
  target.spotKind === ZLinkSpotKind.Entry ? undefined : String(target.spotId),
230
221
  spotGeneration,
231
222
  membershipEpoch
@@ -297,6 +288,7 @@ export class ZLinkLocalNativeActorJoin {
297
288
  completionOperationId: ZLinkActorJoinOperationId | undefined,
298
289
  entrySpot: boolean
299
290
  ): Promise<ZLinkActorJoinRuntimeResult<Message>> {
291
+ const deadlineAtMs = timeoutMs === undefined ? undefined : performance.now() + timeoutMs;
300
292
  const actorType = state.actorType;
301
293
  if (actorType === undefined) {
302
294
  throw createInternalFrameworkException(
@@ -443,6 +435,7 @@ export class ZLinkLocalNativeActorJoin {
443
435
  target,
444
436
  relocationId,
445
437
  completionOperationId,
438
+ deadlineAtMs,
446
439
  ...(control.canonicalHandoffId === undefined || canonicalAdmission === undefined
447
440
  ? {}
448
441
  : {
@@ -456,11 +449,9 @@ export class ZLinkLocalNativeActorJoin {
456
449
  },
457
450
  requestContentType: canonicalAdmission.request.contentType,
458
451
  request: Buffer.from(canonicalAdmission.request.payload),
459
- ...(completionOperationId === undefined
452
+ ...(completionOperationId === undefined || control.replyContentType === undefined
460
453
  ? {}
461
- : {
462
- replyContentType: control.replyContentType ?? ZlinkStreamContentType.Raw
463
- }),
454
+ : { replyContentType: control.replyContentType }),
464
455
  reply:
465
456
  completionOperationId === undefined
466
457
  ? Buffer.alloc(0)
@@ -469,7 +460,7 @@ export class ZLinkLocalNativeActorJoin {
469
460
  expectedOwnerLeaseGeneration: actorAuthorityFence!.ownerLeaseGeneration,
470
461
  targetNodeGeneration: target.targetNodeGeneration!,
471
462
  targetSpotGeneration: control.location.spotGeneration,
472
- targetAuthorityOwnerGeneration: actorAuthorityFence!.authorityOwnerGeneration + 1n,
463
+ targetAuthorityOwnerGeneration: actorAuthorityFence!.authorityOwnerGeneration,
473
464
  targetSpotAuthorityOwnerGeneration: target.authorityOwnerGeneration ?? 1n
474
465
  }
475
466
  }),
@@ -21,9 +21,26 @@ export interface ZLinkRemoteActorSourceLeaveTerminal {
21
21
  readonly succeeded: boolean;
22
22
  }
23
23
 
24
+ const JSON_OBJECT_START = '{'.charCodeAt(0);
25
+ const JSON_SPACE = ' '.charCodeAt(0);
26
+ const JSON_TAB = '\t'.charCodeAt(0);
27
+ const JSON_LINE_FEED = '\n'.charCodeAt(0);
28
+ const JSON_CARRIAGE_RETURN = '\r'.charCodeAt(0);
29
+
24
30
  export function decodeRemoteActorSourceLeaveTerminal(
25
31
  payload: Buffer
26
32
  ): ZLinkRemoteActorSourceLeaveTerminal | undefined {
33
+ // A SourceLeave terminal is a JSON object. Binary channel frames and JSON
34
+ // primitives cannot be terminals, so do not materialize or parse them.
35
+ let offset = 0;
36
+ while (
37
+ payload[offset] === JSON_SPACE ||
38
+ payload[offset] === JSON_TAB ||
39
+ payload[offset] === JSON_LINE_FEED ||
40
+ payload[offset] === JSON_CARRIAGE_RETURN
41
+ )
42
+ offset++;
43
+ if (payload[offset] !== JSON_OBJECT_START) return undefined;
27
44
  let decoded: unknown;
28
45
  try {
29
46
  decoded = JSON.parse(payload.toString());
@@ -19,13 +19,13 @@ export interface ZLinkActorRoutedJoinTransport {
19
19
  targetNodeRid: string,
20
20
  packetName: string | undefined,
21
21
  message: unknown
22
- ): Promise<ZLinkSubmitResult>;
22
+ ): ZLinkSubmitResult | Promise<ZLinkSubmitResult>;
23
23
  submitInfrastructure?(
24
24
  routerChannelId: string,
25
25
  targetNodeRid: string,
26
26
  packetName: string | undefined,
27
27
  message: unknown
28
- ): Promise<ZLinkSubmitResult>;
28
+ ): ZLinkSubmitResult | Promise<ZLinkSubmitResult>;
29
29
  sendToSpot(
30
30
  spotRouteTarget: ZLinkSpotRouteTarget,
31
31
  message: unknown,
@@ -34,7 +34,11 @@ export interface ZLinkActorRoutedJoinTransport {
34
34
  requestRawToSpot?(
35
35
  spotRouteTarget: ZLinkSpotRouteTarget,
36
36
  request: Message,
37
- options: { readonly timeoutMs?: number; readonly signal?: AbortSignal }
37
+ options: {
38
+ readonly timeoutMs?: number;
39
+ readonly signal?: AbortSignal;
40
+ readonly onAdmitted?: () => void;
41
+ }
38
42
  ): Promise<readonly Message[]>;
39
43
  requestToSpot<TReply = unknown>(
40
44
  spotRouteTarget: ZLinkSpotRouteTarget,
@@ -43,6 +47,7 @@ export interface ZLinkActorRoutedJoinTransport {
43
47
  readonly packetName?: string;
44
48
  readonly timeoutMs?: number;
45
49
  readonly signal?: AbortSignal;
50
+ readonly onAdmitted?: () => void;
46
51
  }
47
52
  ): Promise<TReply>;
48
53
  requestFromSpotToSpot?<TReply = unknown>(
@@ -53,12 +58,17 @@ export interface ZLinkActorRoutedJoinTransport {
53
58
  readonly packetName?: string;
54
59
  readonly timeoutMs?: number;
55
60
  readonly signal?: AbortSignal;
61
+ readonly onAdmitted?: () => void;
56
62
  }
57
63
  ): Promise<TReply>;
58
64
  requestRawFromSpotToSpot?(
59
65
  sourceSpot: ZLinkBackendSpot,
60
66
  spotRouteTarget: ZLinkSpotRouteTarget,
61
67
  request: Message,
62
- options: { readonly timeoutMs?: number; readonly signal?: AbortSignal }
68
+ options: {
69
+ readonly timeoutMs?: number;
70
+ readonly signal?: AbortSignal;
71
+ readonly onAdmitted?: () => void;
72
+ }
63
73
  ): Promise<readonly Message[]>;
64
74
  }
@@ -7,7 +7,11 @@ export async function tryRequestRoutedJson(
7
7
  transport: ZLinkActorRoutedJoinTransport,
8
8
  target: ZLinkSpotRouteTarget,
9
9
  payload: unknown,
10
- options: { readonly timeoutMs?: number; readonly signal?: AbortSignal }
10
+ options: {
11
+ readonly timeoutMs?: number;
12
+ readonly signal?: AbortSignal;
13
+ readonly onAdmitted?: () => void;
14
+ }
11
15
  ): Promise<boolean> {
12
16
  const request = transport.requestRawToSpot;
13
17
  if (request === undefined) return false;
@@ -24,7 +28,11 @@ export async function requestRoutedJsonReply<T>(
24
28
  transport: ZLinkActorRoutedJoinTransport,
25
29
  target: ZLinkSpotRouteTarget,
26
30
  payload: unknown,
27
- options: { readonly timeoutMs?: number; readonly signal?: AbortSignal },
31
+ options: {
32
+ readonly timeoutMs?: number;
33
+ readonly signal?: AbortSignal;
34
+ readonly onAdmitted?: () => void;
35
+ },
28
36
  unavailableMessage: string,
29
37
  decode: (replyParts: readonly Message[]) => T
30
38
  ): Promise<T> {