@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,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
+ // Subpath barrel for the in-process `ModelService` facade contract. The
26
+ // implementation lives in `@hydranium/core`; this package owns the
27
+ // argument types so both the framework facade and the data-server wire
28
+ // protocol can structurally agree on the lifecycle shape.
29
+ __exportStar(require("./args"), exports);
30
+ __exportStar(require("./reference-candidate"), exports);
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/model-service/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,wEAAwE;AACxE,mEAAmE;AACnE,uEAAuE;AACvE,0DAA0D;AAE1D,yCAAuB;AACvB,wDAAsC"}
@@ -0,0 +1,56 @@
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 { TransferElement } from '../transfer-element';
10
+ /**
11
+ * UI-facing descriptor of an AST element that may be assigned as the value
12
+ * of a reference. Carries the URI of the owning document, the AST type, the
13
+ * display label, and the persisted reference value.
14
+ *
15
+ * Produced by the reference-candidate pipeline in `@hydranium/core`
16
+ * (`ReferenceCandidateProvider.find`). Consumed by UI surfaces —
17
+ * command-palettes, drop-target action providers, completion popups — that
18
+ * present ranked, deduped reference candidates to the user.
19
+ *
20
+ * **Why two label fields**: `label` is what the user sees in the dropdown;
21
+ * `value` is what gets persisted as the reference's `$refText` when the
22
+ * user selects this element. Separating them lets the server present a
23
+ * human-readable display name (e.g. `node.name`) while storing the
24
+ * canonical reference identifier (e.g. `node.id`). Both fields are
25
+ * required — producers without a display/value distinction set the same
26
+ * string in both, so consumers never need to remember a fallback rule.
27
+ */
28
+ export interface ReferenceCandidate {
29
+ /** URI of the document declaring the referenced element. */
30
+ uri: string;
31
+ /** AST `$type` of the referenced element — useful for icon dispatch. */
32
+ type: string;
33
+ /** Display label shown to the user in dropdowns and chips. */
34
+ label: string;
35
+ /** String stored as `$refText` when the user selects this element. */
36
+ value: string;
37
+ }
38
+ /**
39
+ * Result of resolving a `ReferenceRequest` to its target — a
40
+ * {@link ReferenceCandidate} plus the resolved node's transfer subtree.
41
+ *
42
+ * A candidate and a target are the same kind of thing (an addressable
43
+ * reference target): `find` lists candidates, `resolveReference` returns the
44
+ * one a value matched. The target additionally carries `element` because it
45
+ * is a single result that can afford the payload, where candidates come as a
46
+ * list and stay lightweight. The encoded `element` is just the resolved
47
+ * node's subtree, NOT the whole document root — callers that want the full
48
+ * document fetch it via `getModelDocument(uri)`.
49
+ *
50
+ * Generic over the transfer root type so adopters get their typed overlay.
51
+ */
52
+ export interface ReferenceTarget<TTransfer extends TransferElement = TransferElement> extends ReferenceCandidate {
53
+ /** The resolved target node, encoded as a transfer subtree. */
54
+ element: TTransfer;
55
+ }
56
+ //# sourceMappingURL=reference-candidate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference-candidate.d.ts","sourceRoot":"","sources":["../../src/model-service/reference-candidate.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,kBAAkB;IAChC,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe,CAAC,SAAS,SAAS,eAAe,GAAG,eAAe,CAAE,SAAQ,kBAAkB;IAC7G,+DAA+D;IAC/D,OAAO,EAAE,SAAS,CAAC;CACrB"}
@@ -0,0 +1,11 @@
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
+ //# sourceMappingURL=reference-candidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference-candidate.js","sourceRoot":"","sources":["../../src/model-service/reference-candidate.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF"}
@@ -0,0 +1,25 @@
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 { AbstractLogger } from './abstract-logger';
10
+ import { type LogLevel, type Logger } from './logger';
11
+ /**
12
+ * {@link Logger} implementation that discards every message. Intended for
13
+ * programmatic / in-process consumers (test harnesses, non-LSP hosts) that
14
+ * use the framework services but don't have a vscode-jsonrpc connection to
15
+ * forward log output through.
16
+ *
17
+ * Chaining methods (`for`, `sub`, `with`) return a noop instance of the same
18
+ * class; `withUri` short-circuits to the same instance.
19
+ */
20
+ export declare class NoopLogger extends AbstractLogger implements Logger {
21
+ protected emit(_level: LogLevel, _label: string, _message: string, _args: readonly unknown[]): void;
22
+ withUri(_uri: string): this;
23
+ protected derive(component: string): this;
24
+ }
25
+ //# sourceMappingURL=noop-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop-logger.d.ts","sourceRoot":"","sources":["../src/noop-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAEtD;;;;;;;;GAQG;AACH,qBAAa,UAAW,SAAQ,cAAe,YAAW,MAAM;IAC7D,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI;IAI1F,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKpC,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAI3C"}
@@ -0,0 +1,36 @@
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.NoopLogger = void 0;
12
+ const abstract_logger_1 = require("./abstract-logger");
13
+ /**
14
+ * {@link Logger} implementation that discards every message. Intended for
15
+ * programmatic / in-process consumers (test harnesses, non-LSP hosts) that
16
+ * use the framework services but don't have a vscode-jsonrpc connection to
17
+ * forward log output through.
18
+ *
19
+ * Chaining methods (`for`, `sub`, `with`) return a noop instance of the same
20
+ * class; `withUri` short-circuits to the same instance.
21
+ */
22
+ class NoopLogger extends abstract_logger_1.AbstractLogger {
23
+ emit(_level, _label, _message, _args) {
24
+ // noop — every message is discarded.
25
+ }
26
+ withUri(_uri) {
27
+ // Composing a no-op label is wasted work — return the same instance.
28
+ return this;
29
+ }
30
+ derive(component) {
31
+ const Subclass = this.constructor;
32
+ return new Subclass(component);
33
+ }
34
+ }
35
+ exports.NoopLogger = NoopLogger;
36
+ //# sourceMappingURL=noop-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop-logger.js","sourceRoot":"","sources":["../src/noop-logger.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,uDAAmD;AAGnD;;;;;;;;GAQG;AACH,MAAa,UAAW,SAAQ,gCAAc;IACjC,IAAI,CAAC,MAAgB,EAAE,MAAc,EAAE,QAAgB,EAAE,KAAyB;QACzF,qCAAqC;IACxC,CAAC;IAEQ,OAAO,CAAC,IAAY;QAC1B,qEAAqE;QACrE,OAAO,IAAI,CAAC;IACf,CAAC;IAES,MAAM,CAAC,SAAiB;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAA+C,CAAC;QACtE,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;CACH;AAdD,gCAcC"}
@@ -0,0 +1,72 @@
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 } from 'vscode-jsonrpc';
10
+ /**
11
+ * A value that may change over the connection lifetime. `value` is the
12
+ * current snapshot; `onChange` fires when the snapshot is replaced.
13
+ *
14
+ * The dynamic source in practice is always a user-configurable setting (see
15
+ * the `Settings` producers, which bind one to a Langium configuration
16
+ * section), but the type is source-agnostic — a constant wrapped via
17
+ * {@link ObservableValue.of} is still an `ObservableValue`; its `onChange`
18
+ * simply never fires. Recognised structurally by {@link isObservableValue}.
19
+ */
20
+ export interface ObservableValue<T> {
21
+ /**
22
+ * `readonly` means the holder cannot assign it, NOT that it is stable —
23
+ * a live cell backs this with a getter, so it must be read at the point of
24
+ * use. Copying it into a field at construction pins the snapshot and
25
+ * silently defeats the whole type. A setting-bound cell answers its declared
26
+ * default until the client's configuration fetch resolves, so an early read
27
+ * is a legitimate value rather than an error.
28
+ */
29
+ readonly value: T;
30
+ /**
31
+ * Fires when {@link value} is replaced, deduplicated by `Object.is`, so an
32
+ * unchanged push is not re-announced. Subscribing is OPTIONAL and usually
33
+ * unnecessary — reading `.value` per use already sees every change; the
34
+ * event is for consumers that must re-arm something a later read cannot fix
35
+ * (a timer already scheduled, a listener already registered).
36
+ *
37
+ * It never fires at all for a constant cell, so logic that lives only in an
38
+ * `onChange` handler does nothing when an adopter passes a plain value.
39
+ * Dispose what subscribing returns.
40
+ */
41
+ readonly onChange: Event<T>;
42
+ }
43
+ /**
44
+ * What a service option accepts: either a plain constant (one-shot, never
45
+ * changes) or an {@link ObservableValue}. Consumers normalise to a cell once
46
+ * via {@link ObservableValue.from} and read `.value` at the point of use.
47
+ */
48
+ export type MaybeObservableValue<T> = T | ObservableValue<T>;
49
+ /**
50
+ * Type-guard discriminating a {@link MaybeObservableValue} into its {@link ObservableValue}
51
+ * arm. Returns `false` for primitives, `null`, and any non-object payload; for
52
+ * objects, requires both a `value` property and a callable `onChange` accessor
53
+ * (vscode-jsonrpc events are exposed as callable subscribers).
54
+ */
55
+ export declare function isObservableValue<T>(input: MaybeObservableValue<T>): input is ObservableValue<T>;
56
+ export declare namespace ObservableValue {
57
+ /**
58
+ * Wrap a constant as an {@link ObservableValue} whose `onChange` never
59
+ * fires. Adopters rarely need this — the constant arm of {@link MaybeObservableValue}
60
+ * already accepts a bare value; it exists for {@link from} and for tests
61
+ * that want an explicit cell.
62
+ */
63
+ function of<T>(value: T): ObservableValue<T>;
64
+ /**
65
+ * Normalise a {@link MaybeObservableValue} to an {@link ObservableValue}. Identity for a
66
+ * cell (preserving its live `value` getter + `onChange`); wraps a constant
67
+ * via {@link of}. The combinator a consumer calls once in its constructor
68
+ * so the rest of the class reads `.value` uniformly.
69
+ */
70
+ function from<T>(input: MaybeObservableValue<T>): ObservableValue<T>;
71
+ }
72
+ //# sourceMappingURL=observable-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observable-value.d.ts","sourceRoot":"","sources":["../src/observable-value.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAmB,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE7D;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;AAO7D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,eAAe,CAAC,CAAC,CAAC,CAMhG;AAED,yBAAiB,eAAe,CAAC;IAC9B;;;;;OAKG;IACH,SAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAElD;IAED;;;;;OAKG;IACH,SAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAE1E;CACH"}
@@ -0,0 +1,52 @@
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.ObservableValue = void 0;
12
+ exports.isObservableValue = isObservableValue;
13
+ const NOOP_DISPOSABLE = Object.freeze({ dispose: () => undefined });
14
+ /** An {@link Event} that never fires — the `onChange` of a constant cell. */
15
+ const NEVER_EVENT = () => NOOP_DISPOSABLE;
16
+ /**
17
+ * Type-guard discriminating a {@link MaybeObservableValue} into its {@link ObservableValue}
18
+ * arm. Returns `false` for primitives, `null`, and any non-object payload; for
19
+ * objects, requires both a `value` property and a callable `onChange` accessor
20
+ * (vscode-jsonrpc events are exposed as callable subscribers).
21
+ */
22
+ function isObservableValue(input) {
23
+ if (input === null || typeof input !== 'object') {
24
+ return false;
25
+ }
26
+ const candidate = input;
27
+ return 'value' in candidate && typeof candidate.onChange === 'function';
28
+ }
29
+ var ObservableValue;
30
+ (function (ObservableValue) {
31
+ /**
32
+ * Wrap a constant as an {@link ObservableValue} whose `onChange` never
33
+ * fires. Adopters rarely need this — the constant arm of {@link MaybeObservableValue}
34
+ * already accepts a bare value; it exists for {@link from} and for tests
35
+ * that want an explicit cell.
36
+ */
37
+ function of(value) {
38
+ return { value, onChange: NEVER_EVENT };
39
+ }
40
+ ObservableValue.of = of;
41
+ /**
42
+ * Normalise a {@link MaybeObservableValue} to an {@link ObservableValue}. Identity for a
43
+ * cell (preserving its live `value` getter + `onChange`); wraps a constant
44
+ * via {@link of}. The combinator a consumer calls once in its constructor
45
+ * so the rest of the class reads `.value` uniformly.
46
+ */
47
+ function from(input) {
48
+ return isObservableValue(input) ? input : of(input);
49
+ }
50
+ ObservableValue.from = from;
51
+ })(ObservableValue || (exports.ObservableValue = ObservableValue = {}));
52
+ //# sourceMappingURL=observable-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observable-value.js","sourceRoot":"","sources":["../src/observable-value.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAwDlF,8CAMC;AAjBD,MAAM,eAAe,GAAe,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;AAEhF,6EAA6E;AAC7E,MAAM,WAAW,GAAiB,GAAG,EAAE,CAAC,eAAe,CAAC;AAExD;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAI,KAA8B;IAChE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IAChB,CAAC;IACD,MAAM,SAAS,GAAG,KAAoC,CAAC;IACvD,OAAO,OAAO,IAAI,SAAS,IAAI,OAAO,SAAS,CAAC,QAAQ,KAAK,UAAU,CAAC;AAC3E,CAAC;AAED,IAAiB,eAAe,CAoB/B;AApBD,WAAiB,eAAe;IAC7B;;;;;OAKG;IACH,SAAgB,EAAE,CAAI,KAAQ;QAC3B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAuB,EAAE,CAAC;IACvD,CAAC;IAFe,kBAAE,KAEjB,CAAA;IAED;;;;;OAKG;IACH,SAAgB,IAAI,CAAI,KAA8B;QACnD,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IAFe,oBAAI,OAEnB,CAAA;AACJ,CAAC,EApBgB,eAAe,+BAAf,eAAe,QAoB/B"}
@@ -0,0 +1,123 @@
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 Operation as JsonPatchOperation } from 'fast-json-patch';
10
+ /**
11
+ * Augment a user-intent JSON patch (computed `baseline → attempted`) with
12
+ * `test` ops so a strict `applyPatch` against freshly-fetched server state
13
+ * fails loudly when a foreign writer changed a path the user also changed.
14
+ *
15
+ * `fast-json-patch`'s `validateOperation: true` validates op structure and
16
+ * path resolvability but NOT the pre-existing value — a plain `replace` /
17
+ * `remove` silently overwrites whatever the foreign writer put there. For each
18
+ * `replace` / `remove` op we prepend a `test` op carrying the baseline value at
19
+ * that path, so a same-path divergence becomes a `TEST_OPERATION_FAILED` throw.
20
+ * The caller treats that as a real field-level conflict (drop + refetch) rather
21
+ * than silently clobbering the foreign edit.
22
+ *
23
+ * `add` ops are left unguarded: the path is new, so there is no baseline value
24
+ * to test against, and add-vs-add overlaps are out of scope for this floor.
25
+ *
26
+ * Used behind the framework's `ConflictError` contract by every reconcile
27
+ * path — the GLSP recording command's undo/redo and forward-write, via
28
+ * {@link ReconcilingConflictResolver}, and an adopter's form-widget save — so
29
+ * they share one collision-detection rule.
30
+ */
31
+ export declare function augmentWithTestOps(baseline: object, userPatch: ReadonlyArray<JsonPatchOperation>): JsonPatchOperation[];
32
+ /**
33
+ * Outcome of {@link reconcileByPatchReplay}. The caller persists / re-baselines
34
+ * on `merged`, drops + surfaces the `fresh` root on `conflict`, and decides its
35
+ * own fallback (e.g. force-retry) on `no-op` / `unavailable`.
36
+ */
37
+ export type ReconcileOutcome<T> = {
38
+ /** The replay succeeded: the foreign writer touched no path the user did. */
39
+ status: 'merged';
40
+ /**
41
+ * A fresh root built on the refetched server state, carrying both
42
+ * intents. It is NOT the caller's `attempted` root — re-baseline on
43
+ * this value, or the next write diffs against state the server never
44
+ * had.
45
+ */
46
+ merged: T;
47
+ } | {
48
+ /**
49
+ * The user's root already equalled the baseline, so the version gate
50
+ * fired on drift that changed nothing. No refetch was performed and
51
+ * there is nothing to persist — retrying the same write reproduces it.
52
+ */
53
+ status: 'no-op';
54
+ } | {
55
+ /** A guarded `test` op tripped: user and foreign writer touched one path. */
56
+ status: 'conflict';
57
+ /**
58
+ * The server's current root, refetched and unmodified — the user's
59
+ * intent was NOT applied to it. Surface it and drop the write; treating
60
+ * it as a merge result silently discards what the user typed.
61
+ */
62
+ fresh: T;
63
+ } | {
64
+ /**
65
+ * The refetch produced nothing, so reconciliation could not be
66
+ * attempted at all. This says nothing about whether a conflict exists;
67
+ * the caller picks its own fallback (force-write, retry, surface).
68
+ */
69
+ status: 'unavailable';
70
+ };
71
+ /**
72
+ * Shared three-way reconcile for a `ConflictError`: diff the user's intent
73
+ * (`baseline → attempted`), refetch the server's current root, and replay the
74
+ * intent on top under strict, {@link augmentWithTestOps}-guarded `applyPatch`.
75
+ *
76
+ * - `no-op` — the user's root equals the baseline, so the gate fired on a
77
+ * benign version drift; nothing to replay (refetch is skipped).
78
+ * - `unavailable` — the refetch produced nothing; caller falls back.
79
+ * - `merged` — the foreign writer touched only paths the user did not; the
80
+ * merged root carries both intents.
81
+ * - `conflict` — a same-path divergence tripped a `test` op; caller drops the
82
+ * write and surfaces `fresh`.
83
+ *
84
+ * I/O is the caller's: `refetch` supplies the current root, and applying the
85
+ * `merged` result (update vs save, re-baseline, UI refresh) stays at the call
86
+ * site so form and GLSP paths keep their own persistence semantics.
87
+ */
88
+ export declare function reconcileByPatchReplay<T extends object>(baseline: T, attempted: T, refetch: () => Promise<T | undefined>): Promise<ReconcileOutcome<T>>;
89
+ /**
90
+ * Strategy for resolving a write that raced a foreign edit. One declarative
91
+ * choice covers every conflict site — `execute` forward-write `(before,
92
+ * after)`, `undo` `(after, before)`, `redo` `(before, after)`, and form / GLSP
93
+ * save `(lastSynced, newRoot)` — so adopters pick reconcile-vs-force once
94
+ * (by binding a resolver) rather than per call site.
95
+ */
96
+ export interface ConflictResolver {
97
+ /**
98
+ * Reconcile the user's `baseline → attempted` intent against the current
99
+ * server state (`refetch`), returning a {@link ReconcileOutcome} the caller
100
+ * acts on (persist `merged`, drop on `conflict`, fall back on `no-op` /
101
+ * `unavailable`).
102
+ */
103
+ resolve<T extends object>(baseline: T, attempted: T, refetch: () => Promise<T | undefined>): Promise<ReconcileOutcome<T>>;
104
+ }
105
+ /**
106
+ * Default {@link ConflictResolver}: field-level three-way merge via
107
+ * {@link reconcileByPatchReplay}. A foreign edit to a different field is
108
+ * merged; a same-field collision is reported as a conflict rather than
109
+ * clobbered.
110
+ */
111
+ export declare class ReconcilingConflictResolver implements ConflictResolver {
112
+ resolve<T extends object>(baseline: T, attempted: T, refetch: () => Promise<T | undefined>): Promise<ReconcileOutcome<T>>;
113
+ }
114
+ /**
115
+ * Last-writer-wins {@link ConflictResolver}: always reports the `attempted`
116
+ * state as merged, without refetching or guarding. Suitable for single-client
117
+ * tools or always-regenerated artifacts where a concurrent foreign edit may be
118
+ * overwritten. A foreign edit to any field is clobbered.
119
+ */
120
+ export declare class ForceConflictResolver implements ConflictResolver {
121
+ resolve<T extends object>(_baseline: T, attempted: T, _refetch: () => Promise<T | undefined>): Promise<ReconcileOutcome<T>>;
122
+ }
123
+ //# sourceMappingURL=patch-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-merge.d.ts","sourceRoot":"","sources":["../src/patch-merge.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAqD,KAAK,SAAS,IAAI,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1H;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,EAAE,CASvH;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IACzB;IACG,6EAA6E;IAC7E,MAAM,EAAE,QAAQ,CAAC;IACjB;;;;;OAKG;IACH,MAAM,EAAE,CAAC,CAAC;CACZ,GACD;IACG;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC;CAClB,GACD;IACG,6EAA6E;IAC7E,MAAM,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,KAAK,EAAE,CAAC,CAAC;CACX,GACD;IACG;;;;OAIG;IACH,MAAM,EAAE,aAAa,CAAC;CACxB,CAAC;AAEP;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAC1D,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,CAAC,EACZ,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GACrC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAe9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC9B;;;;;OAKG;IACH,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5H;AAED;;;;;GAKG;AACH,qBAAa,2BAA4B,YAAW,gBAAgB;IACjE,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAG3H;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,gBAAgB;IACrD,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAGnI"}
@@ -0,0 +1,104 @@
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.ForceConflictResolver = exports.ReconcilingConflictResolver = void 0;
12
+ exports.augmentWithTestOps = augmentWithTestOps;
13
+ exports.reconcileByPatchReplay = reconcileByPatchReplay;
14
+ const fast_json_patch_1 = require("fast-json-patch");
15
+ /**
16
+ * Augment a user-intent JSON patch (computed `baseline → attempted`) with
17
+ * `test` ops so a strict `applyPatch` against freshly-fetched server state
18
+ * fails loudly when a foreign writer changed a path the user also changed.
19
+ *
20
+ * `fast-json-patch`'s `validateOperation: true` validates op structure and
21
+ * path resolvability but NOT the pre-existing value — a plain `replace` /
22
+ * `remove` silently overwrites whatever the foreign writer put there. For each
23
+ * `replace` / `remove` op we prepend a `test` op carrying the baseline value at
24
+ * that path, so a same-path divergence becomes a `TEST_OPERATION_FAILED` throw.
25
+ * The caller treats that as a real field-level conflict (drop + refetch) rather
26
+ * than silently clobbering the foreign edit.
27
+ *
28
+ * `add` ops are left unguarded: the path is new, so there is no baseline value
29
+ * to test against, and add-vs-add overlaps are out of scope for this floor.
30
+ *
31
+ * Used behind the framework's `ConflictError` contract by every reconcile
32
+ * path — the GLSP recording command's undo/redo and forward-write, via
33
+ * {@link ReconcilingConflictResolver}, and an adopter's form-widget save — so
34
+ * they share one collision-detection rule.
35
+ */
36
+ function augmentWithTestOps(baseline, userPatch) {
37
+ const augmented = [];
38
+ for (const op of userPatch) {
39
+ if (op.op === 'replace' || op.op === 'remove') {
40
+ augmented.push({ op: 'test', path: op.path, value: (0, fast_json_patch_1.getValueByPointer)(baseline, op.path) });
41
+ }
42
+ augmented.push(op);
43
+ }
44
+ return augmented;
45
+ }
46
+ /**
47
+ * Shared three-way reconcile for a `ConflictError`: diff the user's intent
48
+ * (`baseline → attempted`), refetch the server's current root, and replay the
49
+ * intent on top under strict, {@link augmentWithTestOps}-guarded `applyPatch`.
50
+ *
51
+ * - `no-op` — the user's root equals the baseline, so the gate fired on a
52
+ * benign version drift; nothing to replay (refetch is skipped).
53
+ * - `unavailable` — the refetch produced nothing; caller falls back.
54
+ * - `merged` — the foreign writer touched only paths the user did not; the
55
+ * merged root carries both intents.
56
+ * - `conflict` — a same-path divergence tripped a `test` op; caller drops the
57
+ * write and surfaces `fresh`.
58
+ *
59
+ * I/O is the caller's: `refetch` supplies the current root, and applying the
60
+ * `merged` result (update vs save, re-baseline, UI refresh) stays at the call
61
+ * site so form and GLSP paths keep their own persistence semantics.
62
+ */
63
+ async function reconcileByPatchReplay(baseline, attempted, refetch) {
64
+ const userPatch = (0, fast_json_patch_1.compare)(baseline, attempted);
65
+ if (userPatch.length === 0) {
66
+ return { status: 'no-op' };
67
+ }
68
+ const fresh = await refetch();
69
+ if (!fresh) {
70
+ return { status: 'unavailable' };
71
+ }
72
+ try {
73
+ const merged = (0, fast_json_patch_1.applyPatch)((0, fast_json_patch_1.deepClone)(fresh), augmentWithTestOps(baseline, userPatch), true).newDocument;
74
+ return { status: 'merged', merged };
75
+ }
76
+ catch {
77
+ return { status: 'conflict', fresh };
78
+ }
79
+ }
80
+ /**
81
+ * Default {@link ConflictResolver}: field-level three-way merge via
82
+ * {@link reconcileByPatchReplay}. A foreign edit to a different field is
83
+ * merged; a same-field collision is reported as a conflict rather than
84
+ * clobbered.
85
+ */
86
+ class ReconcilingConflictResolver {
87
+ resolve(baseline, attempted, refetch) {
88
+ return reconcileByPatchReplay(baseline, attempted, refetch);
89
+ }
90
+ }
91
+ exports.ReconcilingConflictResolver = ReconcilingConflictResolver;
92
+ /**
93
+ * Last-writer-wins {@link ConflictResolver}: always reports the `attempted`
94
+ * state as merged, without refetching or guarding. Suitable for single-client
95
+ * tools or always-regenerated artifacts where a concurrent foreign edit may be
96
+ * overwritten. A foreign edit to any field is clobbered.
97
+ */
98
+ class ForceConflictResolver {
99
+ async resolve(_baseline, attempted, _refetch) {
100
+ return { status: 'merged', merged: attempted };
101
+ }
102
+ }
103
+ exports.ForceConflictResolver = ForceConflictResolver;
104
+ //# sourceMappingURL=patch-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-merge.js","sourceRoot":"","sources":["../src/patch-merge.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAyBlF,gDASC;AA+DD,wDAmBC;AAlHD,qDAA0H;AAE1H;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,kBAAkB,CAAC,QAAgB,EAAE,SAA4C;IAC9F,MAAM,SAAS,GAAyB,EAAE,CAAC;IAC3C,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,EAAE,CAAC,EAAE,KAAK,SAAS,IAAI,EAAE,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC7C,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAA,mCAAiB,EAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9F,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,SAAS,CAAC;AACpB,CAAC;AA8CD;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,sBAAsB,CACzC,QAAW,EACX,SAAY,EACZ,OAAqC;IAErC,MAAM,SAAS,GAAG,IAAA,yBAAO,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC/C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,OAAO,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;QACV,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACpC,CAAC;IACD,IAAI,CAAC;QACF,MAAM,MAAM,GAAG,IAAA,4BAAU,EAAC,IAAA,2BAAS,EAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC;QACvG,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACN,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACxC,CAAC;AACJ,CAAC;AAmBD;;;;;GAKG;AACH,MAAa,2BAA2B;IACrC,OAAO,CAAmB,QAAW,EAAE,SAAY,EAAE,OAAqC;QACvF,OAAO,sBAAsB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;CACH;AAJD,kEAIC;AAED;;;;;GAKG;AACH,MAAa,qBAAqB;IAC/B,KAAK,CAAC,OAAO,CAAmB,SAAY,EAAE,SAAY,EAAE,QAAsC;QAC/F,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAClD,CAAC;CACH;AAJD,sDAIC"}
@@ -0,0 +1,87 @@
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 Clock, type Stopwatch } from './clock';
10
+ import { Logger, type LogThreshold } from './logger';
11
+ /** One aggregated row of a {@link ProfileSession}: a scope id and its totals. */
12
+ export interface ProfileRecord {
13
+ /** The scope id passed to {@link ProfileSession.scope}. */
14
+ id: string;
15
+ /** How many times a scope with this id ran. */
16
+ count: number;
17
+ /** Summed self-time across those runs (wall-clock minus nested scopes). */
18
+ selfMs: number;
19
+ /** Self-time as a percentage of the session's total wall-clock. */
20
+ selfPct: number;
21
+ }
22
+ /**
23
+ * An aggregating, parent-exclusive self-time profiler scoped to one operation.
24
+ *
25
+ * Unlike `Tracer.time`, which emits one log line per
26
+ * call and keeps the timeline, a {@link ProfileSession} collapses many
27
+ * {@link scope} calls into a compact per-id aggregate (count + self-time +
28
+ * self-%), then dumps it as line-based output through a {@link Logger}. It is
29
+ * the in-house analogue of Langium's `ProfilingTask` (per-rule / per-node-type
30
+ * self-time) but for the framework's own passes — integrity rules, GModel
31
+ * construction, the save/reconcile chain — that Langium's profiler does not
32
+ * cover.
33
+ *
34
+ * Spawned per operation via `tracer.profile(id)`, used, reported, discarded —
35
+ * it is stateful and op-scoped, which is why it is not a method on the
36
+ * long-lived {@link Logger}/`Tracer`.
37
+ */
38
+ export interface ProfileSession {
39
+ /**
40
+ * Run `fn` as a measured task `id`, accumulating its self-time = wall-clock
41
+ * minus any nested {@link scope} calls. Re-entrant: an inner scope nests and
42
+ * its full duration is excluded from the enclosing id's self-time
43
+ * (parent-exclusive). Async `fn` is awaited so timing covers the full
44
+ * settle. Returns `fn`'s result unchanged; rethrows after recording the
45
+ * elapsed time of a throwing scope.
46
+ */
47
+ scope<T>(id: string, fn: () => Promise<T>): Promise<T>;
48
+ scope<T>(id: string, fn: () => T): T;
49
+ /**
50
+ * Emit the aggregate through the bound {@link Logger}: one line per id,
51
+ * sorted by self-time descending, plus an "unaccounted" remainder (the
52
+ * session wall-clock not attributed to any top-level scope). No-op when
53
+ * `logLevel` is suppressed by the global threshold (incl. `'off'`).
54
+ */
55
+ report(logLevel?: LogThreshold): void;
56
+ /** The same aggregate as structured records, for tests / programmatic use. */
57
+ records(): readonly ProfileRecord[];
58
+ }
59
+ interface ScopeFrame {
60
+ readonly id: string;
61
+ /** Session-stopwatch reading when this scope began. */
62
+ readonly start: number;
63
+ /** Wall-time consumed by nested scopes, excluded from this scope's self-time. */
64
+ childMs: number;
65
+ }
66
+ /**
67
+ * Default {@link ProfileSession}. Times against an injected {@link Clock} (so
68
+ * it is fake-clock deterministic in tests, unlike a raw `performance.now`) and
69
+ * dumps through an injected {@link Logger}.
70
+ */
71
+ export declare class DefaultProfileSession implements ProfileSession {
72
+ protected readonly logger: Logger;
73
+ protected readonly identifier: string;
74
+ /** Single monotonic timeline for the whole session; per-scope readings are deltas off it. */
75
+ protected readonly sessionStopwatch: Stopwatch;
76
+ protected readonly stack: ScopeFrame[];
77
+ protected readonly entries: Map<string, number[]>;
78
+ constructor(logger: Logger, clock: Clock, identifier: string);
79
+ scope<T>(id: string, fn: () => Promise<T>): Promise<T>;
80
+ scope<T>(id: string, fn: () => T): T;
81
+ /** Pop `frame`, charge its full duration to the parent, and record its self-time. */
82
+ protected closeFrame(frame: ScopeFrame): void;
83
+ records(): readonly ProfileRecord[];
84
+ report(logLevel?: LogThreshold): void;
85
+ }
86
+ export {};
87
+ //# sourceMappingURL=profile-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-session.d.ts","sourceRoot":"","sources":["../src/profile-session.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAU,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7D,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC3B,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,cAAc;IAC5B;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvD,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAErC;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAEtC,8EAA8E;IAC9E,OAAO,IAAI,SAAS,aAAa,EAAE,CAAC;CACtC;AAED,UAAU,UAAU;IACjB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAOtD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAEjC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM;IARxC,6FAA6F;IAC7F,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,SAAS,CAAC;IAC/C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,CAAM;IAC5C,SAAS,CAAC,QAAQ,CAAC,OAAO,wBAA+B;gBAGnC,MAAM,EAAE,MAAM,EACjC,KAAK,EAAE,KAAK,EACO,UAAU,EAAE,MAAM;IAKxC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACtD,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IA2BpC,qFAAqF;IACrF,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAgB7C,OAAO,IAAI,SAAS,aAAa,EAAE;IAUnC,MAAM,CAAC,QAAQ,GAAE,YAAsB,GAAG,IAAI;CAiBhD"}