@hydranium/protocol 1.0.0-next.10

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 (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/lib/abstract-logger.d.ts +66 -0
  4. package/lib/abstract-logger.d.ts.map +1 -0
  5. package/lib/abstract-logger.js +110 -0
  6. package/lib/abstract-logger.js.map +1 -0
  7. package/lib/browser-runtime.d.ts +124 -0
  8. package/lib/browser-runtime.d.ts.map +1 -0
  9. package/lib/browser-runtime.js +11 -0
  10. package/lib/browser-runtime.js.map +1 -0
  11. package/lib/client/data-events.d.ts +49 -0
  12. package/lib/client/data-events.d.ts.map +1 -0
  13. package/lib/client/data-events.js +60 -0
  14. package/lib/client/data-events.js.map +1 -0
  15. package/lib/client/data-port.d.ts +95 -0
  16. package/lib/client/data-port.d.ts.map +1 -0
  17. package/lib/client/data-port.js +11 -0
  18. package/lib/client/data-port.js.map +1 -0
  19. package/lib/client/data-session.d.ts +129 -0
  20. package/lib/client/data-session.d.ts.map +1 -0
  21. package/lib/client/data-session.js +179 -0
  22. package/lib/client/data-session.js.map +1 -0
  23. package/lib/client/index.d.ts +39 -0
  24. package/lib/client/index.d.ts.map +1 -0
  25. package/lib/client/index.js +55 -0
  26. package/lib/client/index.js.map +1 -0
  27. package/lib/client/message-relay.d.ts +111 -0
  28. package/lib/client/message-relay.d.ts.map +1 -0
  29. package/lib/client/message-relay.js +139 -0
  30. package/lib/client/message-relay.js.map +1 -0
  31. package/lib/client/post-message-transport.d.ts +77 -0
  32. package/lib/client/post-message-transport.d.ts.map +1 -0
  33. package/lib/client/post-message-transport.js +95 -0
  34. package/lib/client/post-message-transport.js.map +1 -0
  35. package/lib/clock.d.ts +111 -0
  36. package/lib/clock.d.ts.map +1 -0
  37. package/lib/clock.js +74 -0
  38. package/lib/clock.js.map +1 -0
  39. package/lib/data/data-protocol-methods.d.ts +39 -0
  40. package/lib/data/data-protocol-methods.d.ts.map +1 -0
  41. package/lib/data/data-protocol-methods.js +61 -0
  42. package/lib/data/data-protocol-methods.js.map +1 -0
  43. package/lib/data/data-server-protocol.d.ts +264 -0
  44. package/lib/data/data-server-protocol.d.ts.map +1 -0
  45. package/lib/data/data-server-protocol.js +11 -0
  46. package/lib/data/data-server-protocol.js.map +1 -0
  47. package/lib/data/diagnostics.d.ts +97 -0
  48. package/lib/data/diagnostics.d.ts.map +1 -0
  49. package/lib/data/diagnostics.js +25 -0
  50. package/lib/data/diagnostics.js.map +1 -0
  51. package/lib/data/events.d.ts +107 -0
  52. package/lib/data/events.d.ts.map +1 -0
  53. package/lib/data/events.js +11 -0
  54. package/lib/data/events.js.map +1 -0
  55. package/lib/data/index.d.ts +15 -0
  56. package/lib/data/index.d.ts.map +1 -0
  57. package/lib/data/index.js +38 -0
  58. package/lib/data/index.js.map +1 -0
  59. package/lib/data/methods.d.ts +57 -0
  60. package/lib/data/methods.d.ts.map +1 -0
  61. package/lib/data/methods.js +60 -0
  62. package/lib/data/methods.js.map +1 -0
  63. package/lib/data/requests.d.ts +65 -0
  64. package/lib/data/requests.d.ts.map +1 -0
  65. package/lib/data/requests.js +11 -0
  66. package/lib/data/requests.js.map +1 -0
  67. package/lib/debouncer.d.ts +75 -0
  68. package/lib/debouncer.d.ts.map +1 -0
  69. package/lib/debouncer.js +91 -0
  70. package/lib/debouncer.js.map +1 -0
  71. package/lib/errors.d.ts +84 -0
  72. package/lib/errors.d.ts.map +1 -0
  73. package/lib/errors.js +113 -0
  74. package/lib/errors.js.map +1 -0
  75. package/lib/host-diagnostics.d.ts +58 -0
  76. package/lib/host-diagnostics.d.ts.map +1 -0
  77. package/lib/host-diagnostics.js +18 -0
  78. package/lib/host-diagnostics.js.map +1 -0
  79. package/lib/index.d.ts +34 -0
  80. package/lib/index.d.ts.map +1 -0
  81. package/lib/index.js +56 -0
  82. package/lib/index.js.map +1 -0
  83. package/lib/latency-collector.d.ts +126 -0
  84. package/lib/latency-collector.d.ts.map +1 -0
  85. package/lib/latency-collector.js +137 -0
  86. package/lib/latency-collector.js.map +1 -0
  87. package/lib/logger.d.ts +119 -0
  88. package/lib/logger.d.ts.map +1 -0
  89. package/lib/logger.js +126 -0
  90. package/lib/logger.js.map +1 -0
  91. package/lib/model-server.d.ts +352 -0
  92. package/lib/model-server.d.ts.map +1 -0
  93. package/lib/model-server.js +160 -0
  94. package/lib/model-server.js.map +1 -0
  95. package/lib/model-service/args.d.ts +64 -0
  96. package/lib/model-service/args.d.ts.map +1 -0
  97. package/lib/model-service/args.js +11 -0
  98. package/lib/model-service/args.js.map +1 -0
  99. package/lib/model-service/index.d.ts +11 -0
  100. package/lib/model-service/index.d.ts.map +1 -0
  101. package/lib/model-service/index.js +31 -0
  102. package/lib/model-service/index.js.map +1 -0
  103. package/lib/model-service/reference-candidate.d.ts +56 -0
  104. package/lib/model-service/reference-candidate.d.ts.map +1 -0
  105. package/lib/model-service/reference-candidate.js +11 -0
  106. package/lib/model-service/reference-candidate.js.map +1 -0
  107. package/lib/noop-logger.d.ts +25 -0
  108. package/lib/noop-logger.d.ts.map +1 -0
  109. package/lib/noop-logger.js +36 -0
  110. package/lib/noop-logger.js.map +1 -0
  111. package/lib/observable-value.d.ts +72 -0
  112. package/lib/observable-value.d.ts.map +1 -0
  113. package/lib/observable-value.js +52 -0
  114. package/lib/observable-value.js.map +1 -0
  115. package/lib/patch-merge.d.ts +123 -0
  116. package/lib/patch-merge.d.ts.map +1 -0
  117. package/lib/patch-merge.js +104 -0
  118. package/lib/patch-merge.js.map +1 -0
  119. package/lib/profile-session.d.ts +87 -0
  120. package/lib/profile-session.d.ts.map +1 -0
  121. package/lib/profile-session.js +98 -0
  122. package/lib/profile-session.js.map +1 -0
  123. package/lib/profiling.d.ts +83 -0
  124. package/lib/profiling.d.ts.map +1 -0
  125. package/lib/profiling.js +20 -0
  126. package/lib/profiling.js.map +1 -0
  127. package/lib/project.d.ts +121 -0
  128. package/lib/project.d.ts.map +1 -0
  129. package/lib/project.js +34 -0
  130. package/lib/project.js.map +1 -0
  131. package/lib/rpc/bind-rpc-methods.d.ts +100 -0
  132. package/lib/rpc/bind-rpc-methods.d.ts.map +1 -0
  133. package/lib/rpc/bind-rpc-methods.js +110 -0
  134. package/lib/rpc/bind-rpc-methods.js.map +1 -0
  135. package/lib/rpc/create-rpc-proxy.d.ts +188 -0
  136. package/lib/rpc/create-rpc-proxy.d.ts.map +1 -0
  137. package/lib/rpc/create-rpc-proxy.js +158 -0
  138. package/lib/rpc/create-rpc-proxy.js.map +1 -0
  139. package/lib/rpc/index.d.ts +12 -0
  140. package/lib/rpc/index.d.ts.map +1 -0
  141. package/lib/rpc/index.js +31 -0
  142. package/lib/rpc/index.js.map +1 -0
  143. package/lib/rpc/wire-prefix.d.ts +37 -0
  144. package/lib/rpc/wire-prefix.d.ts.map +1 -0
  145. package/lib/rpc/wire-prefix.js +49 -0
  146. package/lib/rpc/wire-prefix.js.map +1 -0
  147. package/lib/testing/data-doubles.d.ts +121 -0
  148. package/lib/testing/data-doubles.d.ts.map +1 -0
  149. package/lib/testing/data-doubles.js +102 -0
  150. package/lib/testing/data-doubles.js.map +1 -0
  151. package/lib/testing/fake-clock.d.ts +35 -0
  152. package/lib/testing/fake-clock.d.ts.map +1 -0
  153. package/lib/testing/fake-clock.js +86 -0
  154. package/lib/testing/fake-clock.js.map +1 -0
  155. package/lib/testing/harness.d.ts +24 -0
  156. package/lib/testing/harness.d.ts.map +1 -0
  157. package/lib/testing/harness.js +11 -0
  158. package/lib/testing/harness.js.map +1 -0
  159. package/lib/testing/index.d.ts +13 -0
  160. package/lib/testing/index.d.ts.map +1 -0
  161. package/lib/testing/index.js +41 -0
  162. package/lib/testing/index.js.map +1 -0
  163. package/lib/testing/node/duplex-connection.d.ts +25 -0
  164. package/lib/testing/node/duplex-connection.d.ts.map +1 -0
  165. package/lib/testing/node/duplex-connection.js +34 -0
  166. package/lib/testing/node/duplex-connection.js.map +1 -0
  167. package/lib/testing/node/duplex-stream.d.ts +32 -0
  168. package/lib/testing/node/duplex-stream.d.ts.map +1 -0
  169. package/lib/testing/node/duplex-stream.js +35 -0
  170. package/lib/testing/node/duplex-stream.js.map +1 -0
  171. package/lib/testing/node/index.d.ts +11 -0
  172. package/lib/testing/node/index.d.ts.map +1 -0
  173. package/lib/testing/node/index.js +37 -0
  174. package/lib/testing/node/index.js.map +1 -0
  175. package/lib/testing/wait-for.d.ts +69 -0
  176. package/lib/testing/wait-for.d.ts.map +1 -0
  177. package/lib/testing/wait-for.js +67 -0
  178. package/lib/testing/wait-for.js.map +1 -0
  179. package/lib/tracer.d.ts +115 -0
  180. package/lib/tracer.d.ts.map +1 -0
  181. package/lib/tracer.js +205 -0
  182. package/lib/tracer.js.map +1 -0
  183. package/lib/transfer-diagnostic.d.ts +73 -0
  184. package/lib/transfer-diagnostic.d.ts.map +1 -0
  185. package/lib/transfer-diagnostic.js +45 -0
  186. package/lib/transfer-diagnostic.js.map +1 -0
  187. package/lib/transfer-document.d.ts +73 -0
  188. package/lib/transfer-document.d.ts.map +1 -0
  189. package/lib/transfer-document.js +46 -0
  190. package/lib/transfer-document.js.map +1 -0
  191. package/lib/transfer-element.d.ts +39 -0
  192. package/lib/transfer-element.d.ts.map +1 -0
  193. package/lib/transfer-element.js +11 -0
  194. package/lib/transfer-element.js.map +1 -0
  195. package/lib/uri.d.ts +62 -0
  196. package/lib/uri.d.ts.map +1 -0
  197. package/lib/uri.js +28 -0
  198. package/lib/uri.js.map +1 -0
  199. package/lib/util.d.ts +147 -0
  200. package/lib/util.d.ts.map +1 -0
  201. package/lib/util.js +211 -0
  202. package/lib/util.js.map +1 -0
  203. package/package.json +100 -0
  204. package/src/abstract-logger.ts +120 -0
  205. package/src/browser-runtime.ts +135 -0
  206. package/src/client/data-events.ts +71 -0
  207. package/src/client/data-port.ts +99 -0
  208. package/src/client/data-session.ts +209 -0
  209. package/src/client/index.ts +40 -0
  210. package/src/client/message-relay.ts +216 -0
  211. package/src/client/post-message-transport.ts +167 -0
  212. package/src/clock.ts +173 -0
  213. package/src/data/data-protocol-methods.ts +79 -0
  214. package/src/data/data-server-protocol.ts +296 -0
  215. package/src/data/diagnostics.ts +116 -0
  216. package/src/data/events.ts +127 -0
  217. package/src/data/index.ts +23 -0
  218. package/src/data/methods.ts +59 -0
  219. package/src/data/requests.ts +70 -0
  220. package/src/debouncer.ts +118 -0
  221. package/src/errors.ts +127 -0
  222. package/src/host-diagnostics.ts +63 -0
  223. package/src/index.ts +41 -0
  224. package/src/latency-collector.ts +231 -0
  225. package/src/logger.ts +172 -0
  226. package/src/model-server.ts +479 -0
  227. package/src/model-service/args.ts +67 -0
  228. package/src/model-service/index.ts +16 -0
  229. package/src/model-service/reference-candidate.ts +58 -0
  230. package/src/noop-logger.ts +36 -0
  231. package/src/observable-value.ts +92 -0
  232. package/src/patch-merge.ts +165 -0
  233. package/src/profile-session.ts +164 -0
  234. package/src/profiling.ts +113 -0
  235. package/src/project.ts +125 -0
  236. package/src/rpc/README.md +163 -0
  237. package/src/rpc/bind-rpc-methods.ts +180 -0
  238. package/src/rpc/create-rpc-proxy.ts +292 -0
  239. package/src/rpc/index.ts +16 -0
  240. package/src/rpc/wire-prefix.ts +48 -0
  241. package/src/testing/data-doubles.ts +178 -0
  242. package/src/testing/fake-clock.ts +106 -0
  243. package/src/testing/harness.ts +24 -0
  244. package/src/testing/index.ts +26 -0
  245. package/src/testing/node/duplex-connection.ts +50 -0
  246. package/src/testing/node/duplex-stream.ts +51 -0
  247. package/src/testing/node/index.ts +22 -0
  248. package/src/testing/wait-for.ts +94 -0
  249. package/src/tracer.ts +277 -0
  250. package/src/transfer-diagnostic.ts +92 -0
  251. package/src/transfer-document.ts +99 -0
  252. package/src/transfer-element.ts +43 -0
  253. package/src/uri.ts +61 -0
  254. package/src/util.ts +250 -0
@@ -0,0 +1,188 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+ import { type Event, type MessageConnection } from 'vscode-jsonrpc';
10
+ import { type BindRpcMethodsOptions } from './bind-rpc-methods';
11
+ /**
12
+ * Lifecycle events surfaced on every {@link createRpcProxy} return — `onDidOpenConnection`
13
+ * fires once after the underlying `MessageConnection` resolves; `onDidCloseConnection`
14
+ * fires when the connection's `onClose` triggers. Useful for proxy-only consumers
15
+ * (widgets, downstream services) that don't hold the `MessageConnection` directly
16
+ * and would otherwise need it threaded through just to react to disconnects.
17
+ *
18
+ * Reconnection is NOT modelled — the framework assumes a single connection
19
+ * lifetime per proxy. If the transport drops, the adopter constructs a new
20
+ * connection + proxy.
21
+ *
22
+ * **Reserved property names on `RpcProxy<T>`.** The proxy's get-trap
23
+ * intercepts four property names — any wire method declared on `T` with
24
+ * one of these names would shadow the reserved behaviour instead of
25
+ * dispatching a wire call. Adopters defining wire-method names should
26
+ * avoid:
27
+ *
28
+ * - `onDidOpenConnection` / `onDidCloseConnection` — return the
29
+ * lifecycle events declared on this interface.
30
+ * - `then` — returns `undefined` so the proxy is not auto-awaited
31
+ * when caught by Promise-detection in the host environment.
32
+ * - `toJSON` — returns `undefined` so JSON serializers do not try to
33
+ * flatten the proxy.
34
+ *
35
+ * Symbol property accesses also return `undefined` (the proxy is not
36
+ * iterable, not a thenable, not serialisable).
37
+ */
38
+ export interface RpcProxyLifecycle {
39
+ /**
40
+ * Fires exactly once, when the underlying connection promise resolves. It
41
+ * does NOT replay: a proxy built over an already-resolved connection fires
42
+ * on the next microtask, so a subscriber attached after that never hears
43
+ * anything. Subscribe in the same synchronous block that builds the proxy,
44
+ * or track readiness yourself.
45
+ *
46
+ * Never fires if the connection promise rejects — a failed transport
47
+ * construction is indistinguishable here from one still pending, and is
48
+ * meant to be observed where the connection is built.
49
+ */
50
+ readonly onDidOpenConnection: Event<void>;
51
+ /**
52
+ * Fires when the transport closes. Reconnection is not modelled, so it fires
53
+ * at most once and is never followed by another open — a consumer that has
54
+ * to survive a drop constructs a new proxy rather than waiting here.
55
+ */
56
+ readonly onDidCloseConnection: Event<void>;
57
+ }
58
+ /** Proxy of `T` plus the framework's connection-lifecycle events. */
59
+ export type RpcProxy<T extends object> = T & RpcProxyLifecycle;
60
+ /**
61
+ * Options controlling how method-name properties on the returned proxy
62
+ * are translated into wire calls.
63
+ *
64
+ * Generic over `TLocal` — the type of an OPTIONAL inbound handler target
65
+ * (see {@link localTarget} / {@link localMethods}). `TLocal` defaults to
66
+ * `never`, so callers that only want an outbound proxy omit the local
67
+ * fields entirely and the proxy behaves exactly as a pure remote proxy.
68
+ */
69
+ export interface CreateRpcProxyOptions<TLocal extends object = never> {
70
+ /**
71
+ * Prefix prepended to the property name to form the JSON-RPC method
72
+ * string. For example, prefix `'data-server/'` turns a property access
73
+ * `proxy.getModelDocument` into the wire method
74
+ * `'data-server/getModelDocument'`. Defaults to the empty string —
75
+ * the property name is the wire name.
76
+ *
77
+ * When {@link localTarget} is supplied, the SAME prefix applies to the
78
+ * inbound handler registrations — both ends of a combined connection
79
+ * share one namespace.
80
+ */
81
+ readonly methodNamespace?: string;
82
+ /**
83
+ * Predicate to discriminate notification methods from request methods
84
+ * by their TS property name. Notification methods lower to
85
+ * `connection.sendNotification` and return `void`; request methods
86
+ * lower to `connection.sendRequest` and return `Promise<TResult>`.
87
+ *
88
+ * Default: property names starting with `'on'` followed by an uppercase
89
+ * letter are notifications. Adopters defining typed contracts in the
90
+ * `DataClientProtocol` style get the right routing without per-method
91
+ * configuration.
92
+ *
93
+ * Applies symmetrically to the {@link localTarget} binding, so the
94
+ * inbound and outbound sides agree on which methods are notifications.
95
+ */
96
+ readonly isNotification?: (methodName: string) => boolean;
97
+ /**
98
+ * OPTIONAL inbound-handler target. When supplied together with
99
+ * {@link localMethods}, `createRpcProxy` ALSO binds those methods of
100
+ * `localTarget` as inbound request/notification handlers on the same
101
+ * connection (delegating to `bindRpcMethods`) — collapsing the common
102
+ * "proxy the remote + handle the local" two-step into one call. The
103
+ * binding is torn down on `connection.onClose`; the return value stays
104
+ * just the remote proxy (no `Disposable` surfaced — there is no use
105
+ * case for unbinding a connection-scoped target before its connection
106
+ * closes). Callers that need the explicit `Disposable` call
107
+ * `bindRpcMethods` directly instead.
108
+ *
109
+ * Omit (the `TLocal = never` default) for a pure outbound proxy.
110
+ */
111
+ readonly localTarget?: TLocal;
112
+ /**
113
+ * Method names of {@link localTarget} to bind as inbound handlers.
114
+ * REQUIRED for the binding to happen (no auto-enumeration — TypeScript
115
+ * access modifiers are erased at runtime, so a class instance's
116
+ * prototype carries internal helpers that must not become wire
117
+ * endpoints; the explicit list is the allowlist). Declare it
118
+ * `as const satisfies keyof TLocal` at the call site for a compile-time
119
+ * drift check; `bindRpcMethods` additionally verifies each name exists
120
+ * on the target at attach time.
121
+ */
122
+ readonly localMethods?: readonly (keyof TLocal & string)[];
123
+ /**
124
+ * Forwarded to the inbound {@link localTarget} binding: when supplied, every
125
+ * inbound handler is timed into this collector under its wire name. Lets a
126
+ * head that owns its server through `createRpcProxy` (rather than a bare
127
+ * `bindRpcMethods` call) still capture per-method latency. Absent by default.
128
+ */
129
+ readonly latency?: BindRpcMethodsOptions['latency'];
130
+ }
131
+ /**
132
+ * Default notification discriminator — `on`-followed-by-an-uppercase-letter
133
+ * methods are notifications (`onProgress`, `onDocumentUpdated`).
134
+ *
135
+ * The uppercase requirement is what keeps the heuristic honest: a
136
+ * request-shaped method that merely *starts* with the letters "on"
137
+ * (`onboardUser`, `onlineCheck`) stays a request, instead of being misrouted
138
+ * as a fire-and-forget notification with its `Promise` result silently
139
+ * dropped. It follows the observer-callback convention the framework's
140
+ * contracts already use, where the capital always marks the event name.
141
+ *
142
+ * Still lexical, so it cannot catch everything — `onDemandRebuild` reads as a
143
+ * request but matches. Supply a custom
144
+ * {@link CreateRpcProxyOptions.isNotification} for contracts that don't fit
145
+ * the convention, and pass the same predicate to both ends.
146
+ */
147
+ export declare function defaultIsNotification(methodName: string): boolean;
148
+ /**
149
+ * Build a typed RPC proxy `T` over a vscode-jsonrpc {@link MessageConnection}.
150
+ * Every method access on the returned object lowers transparently to
151
+ * `connection.sendRequest` (request methods) or `connection.sendNotification`
152
+ * (notification methods, by default `on*`-prefixed). The single-arg
153
+ * payload shape is preserved: `proxy.foo(args)` sends `(method, args)`
154
+ * over the wire and resolves with the response.
155
+ *
156
+ * `on` + an uppercase letter is the only notification marker — see
157
+ * {@link defaultIsNotification}, and pass a custom `isNotification` to both
158
+ * ends for a contract that doesn't fit.
159
+ *
160
+ * **Wire tracing.** The proxy adds no tracing layer of its own, deliberately:
161
+ * vscode-jsonrpc's own `connection.trace` already covers wire method names,
162
+ * params, results and errors, and a second layer here would double every
163
+ * traced line.
164
+ *
165
+ * Accepts either a ready connection or a `Promise<MessageConnection>` —
166
+ * proxy methods called before the promise resolves queue until it does,
167
+ * then dispatch, so adopters can wire the proxy before its underlying
168
+ * transport is available (e.g. before the Langium services finish
169
+ * constructing).
170
+ *
171
+ * A few property names are intercepted rather than dispatched — see
172
+ * {@link RpcProxyLifecycle} for the reserved list and why each is guarded.
173
+ *
174
+ * Each method of `T` dispatches under `<methodNamespace><methodName>`: a
175
+ * request method resolves through `connection.sendRequest`, while one the
176
+ * notification heuristic matches goes out through `sendNotification` and
177
+ * returns nothing, so a caller that awaits it waits on `undefined` rather
178
+ * than on delivery.
179
+ *
180
+ * **Combined proxy + inbound binding.** Supply `localTarget` + `localMethods`
181
+ * to ALSO register inbound handlers on the same connection in one call —
182
+ * the typical both-ends-of-a-bidirectional-connection setup. The remote
183
+ * proxy is still the return value; the inbound binding tears down on
184
+ * `connection.onClose`, so binding twice over one connection leaks the
185
+ * first set of handlers until it closes.
186
+ */
187
+ export declare function createRpcProxy<T extends object, TLocal extends object = never>(connection: MessageConnection | Promise<MessageConnection>, options?: CreateRpcProxyOptions<TLocal>): RpcProxy<T>;
188
+ //# sourceMappingURL=create-rpc-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-rpc-proxy.d.ts","sourceRoot":"","sources":["../../src/rpc/create-rpc-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAW,KAAK,KAAK,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,KAAK,qBAAqB,EAAkB,MAAM,oBAAoB,CAAC;AAGhF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,iBAAiB;IAC/B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,mBAAmB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,qEAAqE;AACrE,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG,iBAAiB,CAAC;AAE/D;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB,CAAC,MAAM,SAAS,MAAM,GAAG,KAAK;IACjE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAElC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAE1D;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;;;;;OASG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAE3D;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC;CACtD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEjE;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,GAAG,KAAK,EAC3E,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,EAC1D,OAAO,GAAE,qBAAqB,CAAC,MAAM,CAAM,GAC3C,QAAQ,CAAC,CAAC,CAAC,CA0Eb"}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
4
+ *
5
+ * This program and the accompanying materials are made available under the
6
+ * terms of the MIT License which is available in the project root.
7
+ *
8
+ * SPDX-License-Identifier: MIT
9
+ ********************************************************************************/
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.defaultIsNotification = defaultIsNotification;
12
+ exports.createRpcProxy = createRpcProxy;
13
+ const vscode_jsonrpc_1 = require("vscode-jsonrpc");
14
+ const bind_rpc_methods_1 = require("./bind-rpc-methods");
15
+ const wire_prefix_1 = require("./wire-prefix");
16
+ /**
17
+ * Default notification discriminator — `on`-followed-by-an-uppercase-letter
18
+ * methods are notifications (`onProgress`, `onDocumentUpdated`).
19
+ *
20
+ * The uppercase requirement is what keeps the heuristic honest: a
21
+ * request-shaped method that merely *starts* with the letters "on"
22
+ * (`onboardUser`, `onlineCheck`) stays a request, instead of being misrouted
23
+ * as a fire-and-forget notification with its `Promise` result silently
24
+ * dropped. It follows the observer-callback convention the framework's
25
+ * contracts already use, where the capital always marks the event name.
26
+ *
27
+ * Still lexical, so it cannot catch everything — `onDemandRebuild` reads as a
28
+ * request but matches. Supply a custom
29
+ * {@link CreateRpcProxyOptions.isNotification} for contracts that don't fit
30
+ * the convention, and pass the same predicate to both ends.
31
+ */
32
+ function defaultIsNotification(methodName) {
33
+ return /^on[A-Z]/.test(methodName);
34
+ }
35
+ /**
36
+ * Runtime enforcement of the single-arg convention. TypeScript catches
37
+ * misuse at compile time for typed contract callers, but loosely-typed
38
+ * callsites (`any` / `unknown` proxy) would silently drop extra args.
39
+ * Throw loudly so the violation is visible.
40
+ */
41
+ function assertSingleArg(wireName, args) {
42
+ if (args.length > 1) {
43
+ throw new Error(`RPC method '${wireName}' called with ${args.length} arguments — typed contracts use a single params object. ` +
44
+ 'Pass a single object instead: proxy.foo({ ...args }).');
45
+ }
46
+ }
47
+ /**
48
+ * Build a typed RPC proxy `T` over a vscode-jsonrpc {@link MessageConnection}.
49
+ * Every method access on the returned object lowers transparently to
50
+ * `connection.sendRequest` (request methods) or `connection.sendNotification`
51
+ * (notification methods, by default `on*`-prefixed). The single-arg
52
+ * payload shape is preserved: `proxy.foo(args)` sends `(method, args)`
53
+ * over the wire and resolves with the response.
54
+ *
55
+ * `on` + an uppercase letter is the only notification marker — see
56
+ * {@link defaultIsNotification}, and pass a custom `isNotification` to both
57
+ * ends for a contract that doesn't fit.
58
+ *
59
+ * **Wire tracing.** The proxy adds no tracing layer of its own, deliberately:
60
+ * vscode-jsonrpc's own `connection.trace` already covers wire method names,
61
+ * params, results and errors, and a second layer here would double every
62
+ * traced line.
63
+ *
64
+ * Accepts either a ready connection or a `Promise<MessageConnection>` —
65
+ * proxy methods called before the promise resolves queue until it does,
66
+ * then dispatch, so adopters can wire the proxy before its underlying
67
+ * transport is available (e.g. before the Langium services finish
68
+ * constructing).
69
+ *
70
+ * A few property names are intercepted rather than dispatched — see
71
+ * {@link RpcProxyLifecycle} for the reserved list and why each is guarded.
72
+ *
73
+ * Each method of `T` dispatches under `<methodNamespace><methodName>`: a
74
+ * request method resolves through `connection.sendRequest`, while one the
75
+ * notification heuristic matches goes out through `sendNotification` and
76
+ * returns nothing, so a caller that awaits it waits on `undefined` rather
77
+ * than on delivery.
78
+ *
79
+ * **Combined proxy + inbound binding.** Supply `localTarget` + `localMethods`
80
+ * to ALSO register inbound handlers on the same connection in one call —
81
+ * the typical both-ends-of-a-bidirectional-connection setup. The remote
82
+ * proxy is still the return value; the inbound binding tears down on
83
+ * `connection.onClose`, so binding twice over one connection leaks the
84
+ * first set of handlers until it closes.
85
+ */
86
+ function createRpcProxy(connection, options = {}) {
87
+ const methodNamespace = options.methodNamespace ?? '';
88
+ (0, wire_prefix_1.assertValidMethodNamespace)(methodNamespace, 'createRpcProxy');
89
+ const isNotification = options.isNotification ?? defaultIsNotification;
90
+ const resolvedConnection = Promise.resolve(connection);
91
+ // Tied to `connection.onClose` so the inbound handlers release with the
92
+ // connection; see `localTarget` for why no `Disposable` is surfaced.
93
+ const { localTarget, localMethods } = options;
94
+ if (localTarget && localMethods && localMethods.length > 0) {
95
+ const binding = (0, bind_rpc_methods_1.bindRpcMethods)(connection, localTarget, localMethods, { methodNamespace, isNotification, latency: options.latency });
96
+ resolvedConnection.then(conn => conn.onClose(() => binding.dispose())).catch(() => undefined);
97
+ }
98
+ const onDidOpenConnectionEmitter = new vscode_jsonrpc_1.Emitter();
99
+ const onDidCloseConnectionEmitter = new vscode_jsonrpc_1.Emitter();
100
+ resolvedConnection
101
+ .then(conn => {
102
+ onDidOpenConnectionEmitter.fire(undefined);
103
+ conn.onClose(() => onDidCloseConnectionEmitter.fire(undefined));
104
+ })
105
+ .catch(() => {
106
+ // Connection promise rejected — treat as never-opened; lifecycle
107
+ // events simply never fire. Adopters observe transport-construction
108
+ // failures through their own connection-construction error handling.
109
+ });
110
+ const target = Object.create(null);
111
+ return new Proxy(target, {
112
+ get(_t, prop) {
113
+ if (typeof prop !== 'string') {
114
+ return undefined;
115
+ }
116
+ // Keep the proxy out of thenable / serializer code paths so it
117
+ // doesn't trigger spurious requests.
118
+ if (prop === 'then' || prop === 'toJSON') {
119
+ return undefined;
120
+ }
121
+ if (prop === 'onDidOpenConnection') {
122
+ return onDidOpenConnectionEmitter.event;
123
+ }
124
+ if (prop === 'onDidCloseConnection') {
125
+ return onDidCloseConnectionEmitter.event;
126
+ }
127
+ const wireName = methodNamespace + prop;
128
+ if (isNotification(prop)) {
129
+ return (...args) => {
130
+ assertSingleArg(wireName, args);
131
+ // Fire-and-forget; rejection (e.g. connection closed) is swallowed
132
+ // to match the notification contract — adopters observe transport
133
+ // failures via the connection's own close / error events, never
134
+ // via a notification's return value.
135
+ void resolvedConnection.then(connection => connection.sendNotification(wireName, args[0])).catch(() => undefined);
136
+ };
137
+ }
138
+ return (...args) => {
139
+ assertSingleArg(wireName, args);
140
+ // Capture the calling stack frame BEFORE the await so debugging gets
141
+ // both client- and server-side stacks on rejection. vscode-jsonrpc's
142
+ // default error envelope surfaces only the server-side stack; without
143
+ // this, a rejected RPC promise looks like it came from "somewhere
144
+ // inside vscode-jsonrpc" rather than from the calling code.
145
+ const capturedError = new Error(`RPC request '${wireName}' failed`);
146
+ return resolvedConnection
147
+ .then(connection => connection.sendRequest(wireName, args[0]))
148
+ .catch((err) => {
149
+ if (err instanceof Error && capturedError.stack) {
150
+ err.stack = `${err.stack ?? err.message}\nCaused by request from:\n${capturedError.stack}`;
151
+ }
152
+ throw err;
153
+ });
154
+ };
155
+ }
156
+ });
157
+ }
158
+ //# sourceMappingURL=create-rpc-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-rpc-proxy.js","sourceRoot":"","sources":["../../src/rpc/create-rpc-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+ export * from './bind-rpc-methods';
10
+ export * from './create-rpc-proxy';
11
+ export * from './wire-prefix';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rpc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAMlF,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
4
+ *
5
+ * This program and the accompanying materials are made available under the
6
+ * terms of the MIT License which is available in the project root.
7
+ *
8
+ * SPDX-License-Identifier: MIT
9
+ ********************************************************************************/
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
22
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ // Generic JSON-RPC primitives shared across the framework's typed
26
+ // protocol heads — see `data/data-protocol-methods.ts` for the
27
+ // specialised composition.
28
+ __exportStar(require("./bind-rpc-methods"), exports);
29
+ __exportStar(require("./create-rpc-proxy"), exports);
30
+ __exportStar(require("./wire-prefix"), exports);
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rpc/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,kEAAkE;AAClE,+DAA+D;AAC/D,2BAA2B;AAE3B,qDAAmC;AACnC,qDAAmC;AACnC,gDAA8B"}
@@ -0,0 +1,37 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+ /**
10
+ * Validates that a wire-name prefix — the `methodNamespace` option shared
11
+ * by `bindRpcMethods` and
12
+ * `createRpcProxy` — carries a
13
+ * trailing `/`.
14
+ *
15
+ * **Why this exists.** Adopters reading the LSP-namespace analogy
16
+ * (`textDocument/*`, `workspace/*`) naturally pass `'mylang'` expecting
17
+ * `'mylang/getModelDocument'` on the wire. Concatenating verbatim instead
18
+ * yields `'mylanggetModelDocument'`, and because the proxy and binding sites
19
+ * pick the wrong prefix in lockstep the mismatch is silent on a single-process
20
+ * adopter, audible only as a per-method "Unhandled method" on the wire log.
21
+ *
22
+ * Throwing is preferred over coercion: coercion would disguise the case where
23
+ * the adopter intended a different separator (`'.'`, `':'`), and throwing at
24
+ * construction time surfaces the bug at the adopter's own callsite rather than
25
+ * at the first wire response.
26
+ *
27
+ * Accepts the empty string (explicit no-prefix mode) or any non-empty string
28
+ * ending with `/`; anything else throws {@link TypeError} synchronously.
29
+ *
30
+ * @param methodNamespace The configured prefix (e.g. `'mylang/'`,
31
+ * `'data-server/'`, `''`).
32
+ * @param caller Name of the validating function, embedded in the thrown
33
+ * message so the error reads as if it came from the adopter-facing
34
+ * function rather than this helper.
35
+ */
36
+ export declare function assertValidMethodNamespace(methodNamespace: string, caller: string): void;
37
+ //# sourceMappingURL=wire-prefix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-prefix.d.ts","sourceRoot":"","sources":["../../src/rpc/wire-prefix.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,0BAA0B,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAWxF"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
4
+ *
5
+ * This program and the accompanying materials are made available under the
6
+ * terms of the MIT License which is available in the project root.
7
+ *
8
+ * SPDX-License-Identifier: MIT
9
+ ********************************************************************************/
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.assertValidMethodNamespace = assertValidMethodNamespace;
12
+ /**
13
+ * Validates that a wire-name prefix — the `methodNamespace` option shared
14
+ * by `bindRpcMethods` and
15
+ * `createRpcProxy` — carries a
16
+ * trailing `/`.
17
+ *
18
+ * **Why this exists.** Adopters reading the LSP-namespace analogy
19
+ * (`textDocument/*`, `workspace/*`) naturally pass `'mylang'` expecting
20
+ * `'mylang/getModelDocument'` on the wire. Concatenating verbatim instead
21
+ * yields `'mylanggetModelDocument'`, and because the proxy and binding sites
22
+ * pick the wrong prefix in lockstep the mismatch is silent on a single-process
23
+ * adopter, audible only as a per-method "Unhandled method" on the wire log.
24
+ *
25
+ * Throwing is preferred over coercion: coercion would disguise the case where
26
+ * the adopter intended a different separator (`'.'`, `':'`), and throwing at
27
+ * construction time surfaces the bug at the adopter's own callsite rather than
28
+ * at the first wire response.
29
+ *
30
+ * Accepts the empty string (explicit no-prefix mode) or any non-empty string
31
+ * ending with `/`; anything else throws {@link TypeError} synchronously.
32
+ *
33
+ * @param methodNamespace The configured prefix (e.g. `'mylang/'`,
34
+ * `'data-server/'`, `''`).
35
+ * @param caller Name of the validating function, embedded in the thrown
36
+ * message so the error reads as if it came from the adopter-facing
37
+ * function rather than this helper.
38
+ */
39
+ function assertValidMethodNamespace(methodNamespace, caller) {
40
+ if (methodNamespace === '' || methodNamespace.endsWith('/')) {
41
+ return;
42
+ }
43
+ throw new TypeError(`${caller}: methodNamespace '${methodNamespace}' must end with '/' (or be empty). ` +
44
+ "Adopters reading the LSP-namespace analogy ('textDocument/*', 'workspace/*') often " +
45
+ `forget the trailing slash, producing wire names like '${methodNamespace}someMethod' ` +
46
+ `that do not match handler bindings under '${methodNamespace}/someMethod'. ` +
47
+ `Either pass '${methodNamespace}/' or use the empty string for no prefix.`);
48
+ }
49
+ //# sourceMappingURL=wire-prefix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-prefix.js","sourceRoot":"","sources":["../../src/rpc/wire-prefix.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AA6BlF,gEAWC;AAtCD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,SAAgB,0BAA0B,CAAC,eAAuB,EAAE,MAAc;IAC/E,IAAI,eAAe,KAAK,EAAE,IAAI,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3D,OAAO;IACV,CAAC;IACD,MAAM,IAAI,SAAS,CAChB,GAAG,MAAM,sBAAsB,eAAe,qCAAqC;QAChF,qFAAqF;QACrF,yDAAyD,eAAe,cAAc;QACtF,6CAA6C,eAAe,gBAAgB;QAC5E,gBAAgB,eAAe,2CAA2C,CAC/E,CAAC;AACL,CAAC"}
@@ -0,0 +1,121 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+ /**
10
+ * The two CLIENT-side doubles of the data head: a {@link DataPort} whose
11
+ * transport the test supplies, and a {@link DataClientProtocol} that records
12
+ * what arrived.
13
+ *
14
+ * # Why standalone, when a harness already builds one
15
+ *
16
+ * `makeDataServerHarness` builds a capturing client too, but fused into a
17
+ * server-bearing harness: taking it means taking a duplex pair, a `DataServer`
18
+ * and a proxy. That is the right shape for testing the server. It is the wrong
19
+ * shape — and not available at all — for testing the CLIENT half: a
20
+ * `DataSession`, a widget model, a host's port adapter. Those need to stand a
21
+ * double on one side of the boundary and something else entirely on the other,
22
+ * which is why both halves get hand-rolled per suite instead.
23
+ *
24
+ * # Runner-agnostic, deliberately
25
+ *
26
+ * No `jest.fn`, no `vi.fn`, no `expect`. The recorded arrays ARE the assertion
27
+ * surface, so the same double works under vitest, jest and a bare script. A
28
+ * mock-framework double would also make "was it called" the observable, when
29
+ * what a data-head test actually asserts is the CONTENT of what arrived —
30
+ * which `sourceClientId`, which version, which reason.
31
+ */
32
+ import { type MessageConnection } from 'vscode-jsonrpc';
33
+ import type { DataPort } from '../client/data-port';
34
+ import type { DataClientProtocol } from '../data/data-server-protocol';
35
+ import type { ProjectsChangedEvent, TransferDocumentSavedEvent, TransferDocumentUpdatedEvent } from '../data/events';
36
+ import type { Project } from '../project';
37
+ import type { TransferDiagnostic } from '../transfer-diagnostic';
38
+ import type { TransferElement } from '../transfer-element';
39
+ /** Inputs to {@link makeFakeDataPort}. */
40
+ export interface FakeDataPortOptions {
41
+ /**
42
+ * Establish one transport generation and hand back a LISTENING connection —
43
+ * the port's whole contract. Called once per generation, so a test that
44
+ * asserts on reconnection must return a FRESH connection each time rather
45
+ * than closing over one.
46
+ *
47
+ * Throwing (or rejecting) here is the transport-construction failure path,
48
+ * which the consumer surfaces through {@link FakeDataPort.reported}.
49
+ */
50
+ connect(): MessageConnection | Promise<MessageConnection>;
51
+ /**
52
+ * Stable client identity. Defaults to `'fake-data-port'`, which avoids the
53
+ * three sentinels the framework reserves (`'language-client'`, `'unknown'`,
54
+ * `'revert-on-close'`); override it when a test needs two distinguishable
55
+ * clients on one server.
56
+ */
57
+ clientId?: string;
58
+ }
59
+ /** A {@link DataPort} that records what passed through it. */
60
+ export interface FakeDataPort extends DataPort {
61
+ /**
62
+ * Every connection {@link FakeDataPortOptions.connect} handed back, in
63
+ * order. Read from outside: "one connection shared across concurrent
64
+ * callers" and "a fresh connection after a teardown" are assertions about
65
+ * this length and about nothing else observable — a session that memoised a
66
+ * rejected promise, for instance, differs from one that retries ONLY here.
67
+ */
68
+ readonly connections: readonly MessageConnection[];
69
+ /**
70
+ * Every {@link DataPort.reportError} call, in order. Read from outside: this
71
+ * is the only place a transport failure surfaces, so a test for the failure
72
+ * path asserts on the `context` string here rather than on a rejection that
73
+ * the consumer may legitimately swallow.
74
+ */
75
+ readonly reported: readonly {
76
+ readonly error: unknown;
77
+ readonly context: string;
78
+ }[];
79
+ /**
80
+ * Fire {@link DataPort.onDispose} — the host tearing the transport down, a
81
+ * language-server restart being the case that forces the event to exist.
82
+ * Drives the consumer's reconnection path, which has no other trigger.
83
+ */
84
+ fireDispose(): void;
85
+ /** Release the emitter. Idempotent; does not close the connections, which the test owns. */
86
+ dispose(): void;
87
+ }
88
+ /**
89
+ * A {@link DataPort} over a transport the caller supplies.
90
+ *
91
+ * It deliberately does not create the transport itself. What varies between the
92
+ * cases worth testing is exactly that: an in-process duplex pair, a socket, a
93
+ * connection with no server behind it, a different one per generation.
94
+ */
95
+ export declare function makeFakeDataPort(options: FakeDataPortOptions): FakeDataPort;
96
+ /** A {@link DataClientProtocol} plus the arrays it records into. */
97
+ export interface CapturingDataClient<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic, TProject extends Project = Project> {
98
+ /** The client to hand to a `DataSession` or bind as an RPC `localTarget`. */
99
+ readonly client: DataClientProtocol<TTransfer, TDiagnostic, TProject>;
100
+ /** Every `onDocumentUpdated` event, in arrival order. */
101
+ readonly updates: TransferDocumentUpdatedEvent<TTransfer, TDiagnostic>[];
102
+ /** Every `onDocumentSaved` event, in arrival order. */
103
+ readonly saves: TransferDocumentSavedEvent<TTransfer, TDiagnostic>[];
104
+ /** Every `onProjectsChanged` event, in arrival order. */
105
+ readonly projectsChanges: ProjectsChangedEvent<TProject>[];
106
+ }
107
+ /**
108
+ * A {@link DataClientProtocol} that records every notification it receives.
109
+ *
110
+ * Recording ALL THREE channels even when a suite reads one is deliberate: an
111
+ * event delivered on the wrong channel is a real defect of the data head, and a
112
+ * double that drops the other two turns it into silence on the one being
113
+ * watched.
114
+ *
115
+ * An override replaces a channel's recording rather than supplementing it, so
116
+ * the corresponding array stays empty — that is what makes an override usable
117
+ * as a barrier (rejecting, counting differently, throwing) rather than only as
118
+ * a spy.
119
+ */
120
+ export declare function makeCapturingDataClient<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic, TProject extends Project = Project>(overrides?: Partial<DataClientProtocol<TTransfer, TDiagnostic, TProject>>): CapturingDataClient<TTransfer, TDiagnostic, TProject>;
121
+ //# sourceMappingURL=data-doubles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-doubles.d.ts","sourceRoot":"","sources":["../../src/testing/data-doubles.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAW,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AACrH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,0CAA0C;AAC1C,MAAM,WAAW,mBAAmB;IACjC;;;;;;;;OAQG;IACH,OAAO,IAAI,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC1D;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,8DAA8D;AAC9D,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC3C;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACnD;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpF;;;;OAIG;IACH,WAAW,IAAI,IAAI,CAAC;IACpB,4FAA4F;IAC5F,OAAO,IAAI,IAAI,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAwB3E;AAED,oEAAoE;AACpE,MAAM,WAAW,mBAAmB,CACjC,SAAS,SAAS,eAAe,EACjC,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,EAC3D,QAAQ,SAAS,OAAO,GAAG,OAAO;IAElC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IACtE,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,CAAC;IACzE,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,0BAA0B,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,CAAC;IACrE,yDAAyD;IACzD,QAAQ,CAAC,eAAe,EAAE,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC;CAC7D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACpC,SAAS,SAAS,eAAe,EACjC,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,EAC3D,QAAQ,SAAS,OAAO,GAAG,OAAO,EACnC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAM,GAAG,mBAAmB,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAsBtI"}