@voidhash/mimic 0.0.1 → 0.0.3

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 (278) hide show
  1. package/.turbo/turbo-build.log +257 -42
  2. package/dist/Document.cjs +152 -0
  3. package/dist/Document.d.cts +67 -0
  4. package/dist/Document.d.cts.map +1 -0
  5. package/dist/Document.d.mts +68 -0
  6. package/dist/Document.d.mts.map +1 -0
  7. package/dist/Document.mjs +147 -0
  8. package/dist/Document.mjs.map +1 -0
  9. package/dist/EffectSchema.cjs +180 -0
  10. package/dist/EffectSchema.d.cts +84 -0
  11. package/dist/EffectSchema.d.cts.map +1 -0
  12. package/dist/EffectSchema.d.mts +84 -0
  13. package/dist/EffectSchema.d.mts.map +1 -0
  14. package/dist/EffectSchema.mjs +176 -0
  15. package/dist/EffectSchema.mjs.map +1 -0
  16. package/dist/FractionalIndex.cjs +365 -0
  17. package/dist/FractionalIndex.mjs +364 -0
  18. package/dist/FractionalIndex.mjs.map +1 -0
  19. package/dist/Operation.cjs +53 -0
  20. package/dist/Operation.d.cts +39 -0
  21. package/dist/Operation.d.cts.map +1 -0
  22. package/dist/Operation.d.mts +39 -0
  23. package/dist/Operation.d.mts.map +1 -0
  24. package/dist/Operation.mjs +46 -0
  25. package/dist/Operation.mjs.map +1 -0
  26. package/dist/OperationDefinition.cjs +13 -0
  27. package/dist/OperationDefinition.d.cts +12 -0
  28. package/dist/OperationDefinition.d.cts.map +1 -0
  29. package/dist/OperationDefinition.d.mts +12 -0
  30. package/dist/OperationDefinition.d.mts.map +1 -0
  31. package/dist/OperationDefinition.mjs +13 -0
  32. package/dist/OperationDefinition.mjs.map +1 -0
  33. package/dist/OperationPath.cjs +148 -0
  34. package/dist/OperationPath.d.cts +60 -0
  35. package/dist/OperationPath.d.cts.map +1 -0
  36. package/dist/OperationPath.d.mts +60 -0
  37. package/dist/OperationPath.d.mts.map +1 -0
  38. package/dist/OperationPath.mjs +138 -0
  39. package/dist/OperationPath.mjs.map +1 -0
  40. package/dist/{Presence-gWrmGBeu.cjs → Presence.cjs} +4 -39
  41. package/dist/{Presence-N8u7Eppr.d.mts → Presence.d.cts} +2 -2
  42. package/dist/Presence.d.cts.map +1 -0
  43. package/dist/{Presence-DKKP4v5X.d.cts → Presence.d.mts} +2 -2
  44. package/dist/Presence.d.mts.map +1 -0
  45. package/dist/{Presence-DdMVKcOv.mjs → Presence.mjs} +3 -28
  46. package/dist/Presence.mjs.map +1 -0
  47. package/dist/Primitive.cjs +52 -0
  48. package/dist/Primitive.d.cts +20 -0
  49. package/dist/Primitive.d.cts.map +1 -0
  50. package/dist/Primitive.d.mts +20 -0
  51. package/dist/Primitive.d.mts.map +1 -0
  52. package/dist/Primitive.mjs +48 -0
  53. package/dist/Primitive.mjs.map +1 -0
  54. package/dist/ProxyEnvironment.cjs +34 -0
  55. package/dist/ProxyEnvironment.d.cts +31 -0
  56. package/dist/ProxyEnvironment.d.cts.map +1 -0
  57. package/dist/ProxyEnvironment.d.mts +31 -0
  58. package/dist/ProxyEnvironment.d.mts.map +1 -0
  59. package/dist/ProxyEnvironment.mjs +29 -0
  60. package/dist/ProxyEnvironment.mjs.map +1 -0
  61. package/dist/Transaction.cjs +66 -0
  62. package/dist/Transaction.d.cts +56 -0
  63. package/dist/Transaction.d.cts.map +1 -0
  64. package/dist/Transaction.d.mts +56 -0
  65. package/dist/Transaction.d.mts.map +1 -0
  66. package/dist/Transaction.mjs +58 -0
  67. package/dist/Transaction.mjs.map +1 -0
  68. package/dist/Transform.cjs +11 -0
  69. package/dist/Transform.d.cts +21 -0
  70. package/dist/Transform.d.cts.map +1 -0
  71. package/dist/Transform.d.mts +21 -0
  72. package/dist/Transform.d.mts.map +1 -0
  73. package/dist/Transform.mjs +6 -0
  74. package/dist/Transform.mjs.map +1 -0
  75. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/defineProperty.cjs +14 -0
  76. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/defineProperty.mjs +14 -0
  77. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.cjs +27 -0
  78. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.mjs +27 -0
  79. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPrimitive.cjs +16 -0
  80. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPrimitive.mjs +16 -0
  81. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPropertyKey.cjs +11 -0
  82. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPropertyKey.mjs +11 -0
  83. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/typeof.cjs +18 -0
  84. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/typeof.mjs +12 -0
  85. package/dist/_virtual/rolldown_runtime.cjs +43 -0
  86. package/dist/{chunk-CLMFDpHK.mjs → _virtual/rolldown_runtime.mjs} +1 -1
  87. package/dist/client/ClientDocument.cjs +590 -0
  88. package/dist/client/ClientDocument.d.cts +161 -0
  89. package/dist/client/ClientDocument.d.cts.map +1 -0
  90. package/dist/client/ClientDocument.d.mts +162 -0
  91. package/dist/client/ClientDocument.d.mts.map +1 -0
  92. package/dist/client/ClientDocument.mjs +586 -0
  93. package/dist/client/ClientDocument.mjs.map +1 -0
  94. package/dist/client/Rebase.cjs +204 -0
  95. package/dist/client/Rebase.d.cts +87 -0
  96. package/dist/client/Rebase.d.cts.map +1 -0
  97. package/dist/client/Rebase.d.mts +88 -0
  98. package/dist/client/Rebase.d.mts.map +1 -0
  99. package/dist/client/Rebase.mjs +198 -0
  100. package/dist/client/Rebase.mjs.map +1 -0
  101. package/dist/client/StateMonitor.cjs +133 -0
  102. package/dist/client/StateMonitor.d.cts +122 -0
  103. package/dist/client/StateMonitor.d.cts.map +1 -0
  104. package/dist/client/StateMonitor.d.mts +122 -0
  105. package/dist/client/StateMonitor.d.mts.map +1 -0
  106. package/dist/client/StateMonitor.mjs +129 -0
  107. package/dist/client/StateMonitor.mjs.map +1 -0
  108. package/dist/client/Transport.cjs +11 -0
  109. package/dist/client/Transport.d.cts +237 -0
  110. package/dist/client/Transport.d.cts.map +1 -0
  111. package/dist/client/Transport.d.mts +237 -0
  112. package/dist/client/Transport.d.mts.map +1 -0
  113. package/dist/client/Transport.mjs +6 -0
  114. package/dist/client/Transport.mjs.map +1 -0
  115. package/dist/client/WebSocketTransport.cjs +396 -0
  116. package/dist/client/WebSocketTransport.d.cts +29 -0
  117. package/dist/client/WebSocketTransport.d.cts.map +1 -0
  118. package/dist/client/WebSocketTransport.d.mts +29 -0
  119. package/dist/client/WebSocketTransport.d.mts.map +1 -0
  120. package/dist/client/WebSocketTransport.mjs +392 -0
  121. package/dist/client/WebSocketTransport.mjs.map +1 -0
  122. package/dist/client/errors.cjs +135 -0
  123. package/dist/client/errors.d.cts +87 -0
  124. package/dist/client/errors.d.cts.map +1 -0
  125. package/dist/client/errors.d.mts +87 -0
  126. package/dist/client/errors.d.mts.map +1 -0
  127. package/dist/client/errors.mjs +127 -0
  128. package/dist/client/errors.mjs.map +1 -0
  129. package/dist/client/index.cjs +22 -1424
  130. package/dist/client/index.d.cts +8 -692
  131. package/dist/client/index.d.mts +8 -692
  132. package/dist/client/index.mjs +9 -1413
  133. package/dist/index.cjs +30 -2529
  134. package/dist/index.d.cts +12 -143
  135. package/dist/index.d.mts +12 -143
  136. package/dist/index.mjs +13 -2526
  137. package/dist/primitives/Array.cjs +302 -0
  138. package/dist/primitives/Array.d.cts +95 -0
  139. package/dist/primitives/Array.d.cts.map +1 -0
  140. package/dist/primitives/Array.d.mts +95 -0
  141. package/dist/primitives/Array.d.mts.map +1 -0
  142. package/dist/primitives/Array.mjs +301 -0
  143. package/dist/primitives/Array.mjs.map +1 -0
  144. package/dist/primitives/Boolean.cjs +95 -0
  145. package/dist/primitives/Boolean.d.cts +44 -0
  146. package/dist/primitives/Boolean.d.cts.map +1 -0
  147. package/dist/primitives/Boolean.d.mts +44 -0
  148. package/dist/primitives/Boolean.d.mts.map +1 -0
  149. package/dist/primitives/Boolean.mjs +94 -0
  150. package/dist/primitives/Boolean.mjs.map +1 -0
  151. package/dist/primitives/Either.cjs +200 -0
  152. package/dist/primitives/Either.d.cts +113 -0
  153. package/dist/primitives/Either.d.cts.map +1 -0
  154. package/dist/primitives/Either.d.mts +113 -0
  155. package/dist/primitives/Either.d.mts.map +1 -0
  156. package/dist/primitives/Either.mjs +199 -0
  157. package/dist/primitives/Either.mjs.map +1 -0
  158. package/dist/primitives/Lazy.cjs +46 -0
  159. package/dist/primitives/Lazy.d.cts +46 -0
  160. package/dist/primitives/Lazy.d.cts.map +1 -0
  161. package/dist/primitives/Lazy.d.mts +46 -0
  162. package/dist/primitives/Lazy.d.mts.map +1 -0
  163. package/dist/primitives/Lazy.mjs +46 -0
  164. package/dist/primitives/Lazy.mjs.map +1 -0
  165. package/dist/primitives/Literal.cjs +91 -0
  166. package/dist/primitives/Literal.d.cts +46 -0
  167. package/dist/primitives/Literal.d.cts.map +1 -0
  168. package/dist/primitives/Literal.d.mts +46 -0
  169. package/dist/primitives/Literal.d.mts.map +1 -0
  170. package/dist/primitives/Literal.mjs +90 -0
  171. package/dist/primitives/Literal.mjs.map +1 -0
  172. package/dist/primitives/Number.cjs +115 -0
  173. package/dist/primitives/Number.d.cts +54 -0
  174. package/dist/primitives/Number.d.cts.map +1 -0
  175. package/dist/primitives/Number.d.mts +54 -0
  176. package/dist/primitives/Number.d.mts.map +1 -0
  177. package/dist/primitives/Number.mjs +114 -0
  178. package/dist/primitives/Number.mjs.map +1 -0
  179. package/dist/primitives/String.cjs +127 -0
  180. package/dist/primitives/String.d.cts +56 -0
  181. package/dist/primitives/String.d.cts.map +1 -0
  182. package/dist/primitives/String.d.mts +56 -0
  183. package/dist/primitives/String.d.mts.map +1 -0
  184. package/dist/primitives/String.mjs +126 -0
  185. package/dist/primitives/String.mjs.map +1 -0
  186. package/dist/primitives/Struct.cjs +207 -0
  187. package/dist/primitives/Struct.d.cts +96 -0
  188. package/dist/primitives/Struct.d.cts.map +1 -0
  189. package/dist/primitives/Struct.d.mts +97 -0
  190. package/dist/primitives/Struct.d.mts.map +1 -0
  191. package/dist/primitives/Struct.mjs +206 -0
  192. package/dist/primitives/Struct.mjs.map +1 -0
  193. package/dist/primitives/Tree.cjs +575 -0
  194. package/dist/primitives/Tree.d.cts +185 -0
  195. package/dist/primitives/Tree.d.cts.map +1 -0
  196. package/dist/primitives/Tree.d.mts +185 -0
  197. package/dist/primitives/Tree.d.mts.map +1 -0
  198. package/dist/primitives/Tree.mjs +574 -0
  199. package/dist/primitives/Tree.mjs.map +1 -0
  200. package/dist/primitives/TreeNode.cjs +73 -0
  201. package/dist/primitives/TreeNode.d.cts +92 -0
  202. package/dist/primitives/TreeNode.d.cts.map +1 -0
  203. package/dist/primitives/TreeNode.d.mts +93 -0
  204. package/dist/primitives/TreeNode.d.mts.map +1 -0
  205. package/dist/primitives/TreeNode.mjs +72 -0
  206. package/dist/primitives/TreeNode.mjs.map +1 -0
  207. package/dist/primitives/Union.cjs +170 -0
  208. package/dist/primitives/Union.d.cts +81 -0
  209. package/dist/primitives/Union.d.cts.map +1 -0
  210. package/dist/primitives/Union.d.mts +81 -0
  211. package/dist/primitives/Union.d.mts.map +1 -0
  212. package/dist/primitives/Union.mjs +169 -0
  213. package/dist/primitives/Union.mjs.map +1 -0
  214. package/dist/primitives/shared.cjs +60 -0
  215. package/dist/primitives/shared.d.cts +147 -0
  216. package/dist/primitives/shared.d.cts.map +1 -0
  217. package/dist/primitives/shared.d.mts +147 -0
  218. package/dist/primitives/shared.d.mts.map +1 -0
  219. package/dist/primitives/shared.mjs +58 -0
  220. package/dist/primitives/shared.mjs.map +1 -0
  221. package/dist/server/ServerDocument.cjs +110 -0
  222. package/dist/server/ServerDocument.d.cts +98 -0
  223. package/dist/server/ServerDocument.d.cts.map +1 -0
  224. package/dist/server/ServerDocument.d.mts +99 -0
  225. package/dist/server/ServerDocument.d.mts.map +1 -0
  226. package/dist/server/ServerDocument.mjs +106 -0
  227. package/dist/server/ServerDocument.mjs.map +1 -0
  228. package/dist/server/errors.cjs +85 -0
  229. package/dist/server/errors.d.cts +53 -0
  230. package/dist/server/errors.d.cts.map +1 -0
  231. package/dist/server/errors.d.mts +53 -0
  232. package/dist/server/errors.d.mts.map +1 -0
  233. package/dist/server/errors.mjs +81 -0
  234. package/dist/server/errors.mjs.map +1 -0
  235. package/dist/server/index.cjs +9 -185
  236. package/dist/server/index.d.cts +3 -148
  237. package/dist/server/index.d.mts +3 -148
  238. package/dist/server/index.mjs +3 -181
  239. package/dist/types/index.cjs +16 -0
  240. package/dist/types/index.d.cts +16 -0
  241. package/dist/types/index.d.cts.map +1 -0
  242. package/dist/types/index.d.mts +16 -0
  243. package/dist/types/index.d.mts.map +1 -0
  244. package/dist/types/index.mjs +12 -0
  245. package/dist/types/index.mjs.map +1 -0
  246. package/dist/utils/tree-helpers.cjs +443 -0
  247. package/dist/utils/tree-helpers.d.cts +280 -0
  248. package/dist/utils/tree-helpers.d.cts.map +1 -0
  249. package/dist/utils/tree-helpers.d.mts +280 -0
  250. package/dist/utils/tree-helpers.d.mts.map +1 -0
  251. package/dist/utils/tree-helpers.mjs +439 -0
  252. package/dist/utils/tree-helpers.mjs.map +1 -0
  253. package/package.json +2 -2
  254. package/src/index.ts +2 -0
  255. package/src/primitives/shared.ts +7 -1
  256. package/src/types/index.ts +137 -0
  257. package/src/utils/index.ts +7 -0
  258. package/src/utils/tree-helpers.ts +648 -0
  259. package/tsdown.config.ts +1 -1
  260. package/dist/Document-ChuFrTk1.cjs +0 -571
  261. package/dist/Document-CwiAFTIq.mjs +0 -438
  262. package/dist/Document-CwiAFTIq.mjs.map +0 -1
  263. package/dist/Presence-DKKP4v5X.d.cts.map +0 -1
  264. package/dist/Presence-DdMVKcOv.mjs.map +0 -1
  265. package/dist/Presence-N8u7Eppr.d.mts.map +0 -1
  266. package/dist/Primitive-CvFVxR8_.d.cts +0 -1175
  267. package/dist/Primitive-CvFVxR8_.d.cts.map +0 -1
  268. package/dist/Primitive-lEhQyGVL.d.mts +0 -1175
  269. package/dist/Primitive-lEhQyGVL.d.mts.map +0 -1
  270. package/dist/client/index.d.cts.map +0 -1
  271. package/dist/client/index.d.mts.map +0 -1
  272. package/dist/client/index.mjs.map +0 -1
  273. package/dist/index.d.cts.map +0 -1
  274. package/dist/index.d.mts.map +0 -1
  275. package/dist/index.mjs.map +0 -1
  276. package/dist/server/index.d.cts.map +0 -1
  277. package/dist/server/index.d.mts.map +0 -1
  278. package/dist/server/index.mjs.map +0 -1
@@ -0,0 +1,129 @@
1
+ import { __export } from "../_virtual/rolldown_runtime.mjs";
2
+
3
+ //#region src/client/StateMonitor.ts
4
+ var StateMonitor_exports = /* @__PURE__ */ __export({
5
+ determineRecoveryAction: () => determineRecoveryAction,
6
+ make: () => make
7
+ });
8
+ /**
9
+ * Creates a new StateMonitor.
10
+ */
11
+ const make = (options = {}) => {
12
+ const { onEvent, healthCheckInterval = 5e3, stalePendingThreshold = 1e4, maxVersionGap = 10 } = options;
13
+ let _expectedVersion = 0;
14
+ let _pendingMap = /* @__PURE__ */ new Map();
15
+ let _isRecovering = false;
16
+ let _healthCheckHandle = null;
17
+ /**
18
+ * Emits an event if handler is provided.
19
+ */
20
+ const emit = (event) => {
21
+ onEvent === null || onEvent === void 0 || onEvent(event);
22
+ };
23
+ /**
24
+ * Checks if there's a version gap indicating drift.
25
+ */
26
+ const checkVersionGap = (receivedVersion) => {
27
+ const expectedNext = _expectedVersion + 1;
28
+ if (receivedVersion < expectedNext) return true;
29
+ if (receivedVersion > expectedNext + maxVersionGap) {
30
+ emit({
31
+ type: "drift_detected",
32
+ expectedVersion: expectedNext,
33
+ receivedVersion
34
+ });
35
+ return false;
36
+ }
37
+ return true;
38
+ };
39
+ /**
40
+ * Runs a health check.
41
+ */
42
+ const runHealthCheck = () => {
43
+ const now = Date.now();
44
+ let oldestPendingMs = null;
45
+ for (const [id, info] of _pendingMap) {
46
+ const elapsed = now - info.sentAt;
47
+ if (oldestPendingMs === null || elapsed > oldestPendingMs) oldestPendingMs = elapsed;
48
+ if (elapsed > stalePendingThreshold) emit({
49
+ type: "pending_timeout",
50
+ transactionId: id,
51
+ elapsedMs: elapsed
52
+ });
53
+ }
54
+ emit({
55
+ type: "health_check",
56
+ pendingCount: _pendingMap.size,
57
+ oldestPendingMs
58
+ });
59
+ };
60
+ return {
61
+ onServerVersion: (version) => {
62
+ const isValid = checkVersionGap(version);
63
+ if (isValid) _expectedVersion = Math.max(_expectedVersion, version);
64
+ return isValid;
65
+ },
66
+ trackPending: (info) => {
67
+ _pendingMap.set(info.id, info);
68
+ },
69
+ untrackPending: (id) => {
70
+ _pendingMap.delete(id);
71
+ },
72
+ getStalePending: () => {
73
+ const now = Date.now();
74
+ const stale = [];
75
+ for (const info of _pendingMap.values()) if (now - info.sentAt > stalePendingThreshold) stale.push(info);
76
+ return stale;
77
+ },
78
+ getStatus: () => {
79
+ const now = Date.now();
80
+ let oldestPendingMs = null;
81
+ for (const info of _pendingMap.values()) {
82
+ const elapsed = now - info.sentAt;
83
+ if (oldestPendingMs === null || elapsed > oldestPendingMs) oldestPendingMs = elapsed;
84
+ }
85
+ const isHealthy = !_isRecovering && (oldestPendingMs === null || oldestPendingMs < stalePendingThreshold * 2);
86
+ return {
87
+ expectedVersion: _expectedVersion,
88
+ pendingCount: _pendingMap.size,
89
+ oldestPendingMs,
90
+ isHealthy,
91
+ isRecovering: _isRecovering
92
+ };
93
+ },
94
+ start: () => {
95
+ if (_healthCheckHandle !== null) return;
96
+ _healthCheckHandle = setInterval(runHealthCheck, healthCheckInterval);
97
+ },
98
+ stop: () => {
99
+ if (_healthCheckHandle !== null) {
100
+ clearInterval(_healthCheckHandle);
101
+ _healthCheckHandle = null;
102
+ }
103
+ },
104
+ reset: (newVersion) => {
105
+ _expectedVersion = newVersion;
106
+ _pendingMap.clear();
107
+ _isRecovering = false;
108
+ emit({
109
+ type: "recovery_completed",
110
+ version: newVersion
111
+ });
112
+ }
113
+ };
114
+ };
115
+ /**
116
+ * Determines the appropriate recovery action based on current state.
117
+ */
118
+ const determineRecoveryAction = (status, stalePending) => {
119
+ if (!status.isHealthy || stalePending.length > 3) return { type: "request_snapshot" };
120
+ if (stalePending.length > 0) return {
121
+ type: "drop_pending",
122
+ transactionIds: stalePending.map((p) => p.id)
123
+ };
124
+ return { type: "request_snapshot" };
125
+ };
126
+
127
+ //#endregion
128
+ export { StateMonitor_exports };
129
+ //# sourceMappingURL=StateMonitor.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateMonitor.mjs","names":["_healthCheckHandle: ReturnType<typeof setInterval> | null","oldestPendingMs: number | null","stale: PendingInfo[]"],"sources":["../../src/client/StateMonitor.ts"],"sourcesContent":["import { StateDriftError } from \"./errors\";\n\n// =============================================================================\n// State Monitor Types\n// =============================================================================\n\n/**\n * Events emitted by the state monitor.\n */\nexport type StateMonitorEvent =\n | { type: \"drift_detected\"; expectedVersion: number; receivedVersion: number }\n | { type: \"recovery_started\" }\n | { type: \"recovery_completed\"; version: number }\n | { type: \"recovery_failed\"; error: Error }\n | { type: \"pending_timeout\"; transactionId: string; elapsedMs: number }\n | { type: \"health_check\"; pendingCount: number; oldestPendingMs: number | null };\n\n/**\n * Handler for state monitor events.\n */\nexport type StateMonitorEventHandler = (event: StateMonitorEvent) => void;\n\n/**\n * Options for creating a StateMonitor.\n */\nexport interface StateMonitorOptions {\n /** Handler for monitor events */\n readonly onEvent?: StateMonitorEventHandler;\n /** Interval for health checks in ms (default: 5000) */\n readonly healthCheckInterval?: number;\n /** Threshold for considering a pending transaction \"stale\" in ms (default: 10000) */\n readonly stalePendingThreshold?: number;\n /** Maximum allowed version gap before triggering recovery (default: 10) */\n readonly maxVersionGap?: number;\n}\n\n/**\n * Pending transaction info for monitoring.\n */\nexport interface PendingInfo {\n readonly id: string;\n readonly sentAt: number;\n}\n\n/**\n * A StateMonitor watches for state drift and triggers recovery.\n */\nexport interface StateMonitor {\n /**\n * Called when a server transaction is received.\n * Returns true if the version is valid, false if drift is detected.\n */\n readonly onServerVersion: (version: number) => boolean;\n\n /**\n * Called when a pending transaction is added.\n */\n readonly trackPending: (info: PendingInfo) => void;\n\n /**\n * Called when a pending transaction is confirmed or rejected.\n */\n readonly untrackPending: (id: string) => void;\n\n /**\n * Returns pending transactions that have exceeded the stale threshold.\n */\n readonly getStalePending: () => PendingInfo[];\n\n /**\n * Returns current monitoring status.\n */\n readonly getStatus: () => StateMonitorStatus;\n\n /**\n * Starts the health check loop.\n */\n readonly start: () => void;\n\n /**\n * Stops the health check loop.\n */\n readonly stop: () => void;\n\n /**\n * Resets the monitor state (called after recovery).\n */\n readonly reset: (newVersion: number) => void;\n}\n\n/**\n * Current monitoring status.\n */\nexport interface StateMonitorStatus {\n readonly expectedVersion: number;\n readonly pendingCount: number;\n readonly oldestPendingMs: number | null;\n readonly isHealthy: boolean;\n readonly isRecovering: boolean;\n}\n\n// =============================================================================\n// State Monitor Implementation\n// =============================================================================\n\n/**\n * Creates a new StateMonitor.\n */\nexport const make = (options: StateMonitorOptions = {}): StateMonitor => {\n const {\n onEvent,\n healthCheckInterval = 5000,\n stalePendingThreshold = 10000,\n maxVersionGap = 10,\n } = options;\n\n // Internal state\n let _expectedVersion = 0;\n let _pendingMap = new Map<string, PendingInfo>();\n let _isRecovering = false;\n let _healthCheckHandle: ReturnType<typeof setInterval> | null = null;\n\n /**\n * Emits an event if handler is provided.\n */\n const emit = (event: StateMonitorEvent): void => {\n onEvent?.(event);\n };\n\n /**\n * Checks if there's a version gap indicating drift.\n */\n const checkVersionGap = (receivedVersion: number): boolean => {\n // Expected next version is current + 1\n const expectedNext = _expectedVersion + 1;\n\n if (receivedVersion < expectedNext) {\n // Duplicate or out-of-order - might be OK\n return true;\n }\n\n if (receivedVersion > expectedNext + maxVersionGap) {\n // Large gap - drift detected\n emit({\n type: \"drift_detected\",\n expectedVersion: expectedNext,\n receivedVersion,\n });\n return false;\n }\n\n // Small gap - could be network reordering, allow it\n return true;\n };\n\n /**\n * Runs a health check.\n */\n const runHealthCheck = (): void => {\n const now = Date.now();\n let oldestPendingMs: number | null = null;\n\n // Find stale pending transactions\n for (const [id, info] of _pendingMap) {\n const elapsed = now - info.sentAt;\n\n if (oldestPendingMs === null || elapsed > oldestPendingMs) {\n oldestPendingMs = elapsed;\n }\n\n if (elapsed > stalePendingThreshold) {\n emit({\n type: \"pending_timeout\",\n transactionId: id,\n elapsedMs: elapsed,\n });\n }\n }\n\n emit({\n type: \"health_check\",\n pendingCount: _pendingMap.size,\n oldestPendingMs,\n });\n };\n\n const monitor: StateMonitor = {\n onServerVersion: (version: number): boolean => {\n const isValid = checkVersionGap(version);\n\n if (isValid) {\n // Update expected version\n _expectedVersion = Math.max(_expectedVersion, version);\n }\n\n return isValid;\n },\n\n trackPending: (info: PendingInfo): void => {\n _pendingMap.set(info.id, info);\n },\n\n untrackPending: (id: string): void => {\n _pendingMap.delete(id);\n },\n\n getStalePending: (): PendingInfo[] => {\n const now = Date.now();\n const stale: PendingInfo[] = [];\n\n for (const info of _pendingMap.values()) {\n if (now - info.sentAt > stalePendingThreshold) {\n stale.push(info);\n }\n }\n\n return stale;\n },\n\n getStatus: (): StateMonitorStatus => {\n const now = Date.now();\n let oldestPendingMs: number | null = null;\n\n for (const info of _pendingMap.values()) {\n const elapsed = now - info.sentAt;\n if (oldestPendingMs === null || elapsed > oldestPendingMs) {\n oldestPendingMs = elapsed;\n }\n }\n\n // Consider unhealthy if recovering or has very stale pending\n const isHealthy =\n !_isRecovering &&\n (oldestPendingMs === null || oldestPendingMs < stalePendingThreshold * 2);\n\n return {\n expectedVersion: _expectedVersion,\n pendingCount: _pendingMap.size,\n oldestPendingMs,\n isHealthy,\n isRecovering: _isRecovering,\n };\n },\n\n start: (): void => {\n if (_healthCheckHandle !== null) return;\n\n _healthCheckHandle = setInterval(runHealthCheck, healthCheckInterval);\n },\n\n stop: (): void => {\n if (_healthCheckHandle !== null) {\n clearInterval(_healthCheckHandle);\n _healthCheckHandle = null;\n }\n },\n\n reset: (newVersion: number): void => {\n _expectedVersion = newVersion;\n _pendingMap.clear();\n _isRecovering = false;\n\n emit({\n type: \"recovery_completed\",\n version: newVersion,\n });\n },\n };\n\n return monitor;\n};\n\n// =============================================================================\n// Recovery Strategy\n// =============================================================================\n\n/**\n * Recovery actions that can be taken.\n */\nexport type RecoveryAction =\n | { type: \"request_snapshot\" }\n | { type: \"retry_pending\"; transactionIds: string[] }\n | { type: \"drop_pending\"; transactionIds: string[] };\n\n/**\n * Determines the appropriate recovery action based on current state.\n */\nexport const determineRecoveryAction = (\n status: StateMonitorStatus,\n stalePending: PendingInfo[]\n): RecoveryAction => {\n // If recovering or unhealthy with stale pending, request full snapshot\n if (!status.isHealthy || stalePending.length > 3) {\n return { type: \"request_snapshot\" };\n }\n\n // If just a few stale pending, drop them\n if (stalePending.length > 0) {\n return {\n type: \"drop_pending\",\n transactionIds: stalePending.map((p) => p.id),\n };\n }\n\n // Default: request snapshot for safety\n return { type: \"request_snapshot\" };\n};\n"],"mappings":";;;;;;;;;;AA4GA,MAAa,QAAQ,UAA+B,EAAE,KAAmB;CACvE,MAAM,EACJ,SACA,sBAAsB,KACtB,wBAAwB,KACxB,gBAAgB,OACd;CAGJ,IAAI,mBAAmB;CACvB,IAAI,8BAAc,IAAI,KAA0B;CAChD,IAAI,gBAAgB;CACpB,IAAIA,qBAA4D;;;;CAKhE,MAAM,QAAQ,UAAmC;AAC/C,oDAAU,MAAM;;;;;CAMlB,MAAM,mBAAmB,oBAAqC;EAE5D,MAAM,eAAe,mBAAmB;AAExC,MAAI,kBAAkB,aAEpB,QAAO;AAGT,MAAI,kBAAkB,eAAe,eAAe;AAElD,QAAK;IACH,MAAM;IACN,iBAAiB;IACjB;IACD,CAAC;AACF,UAAO;;AAIT,SAAO;;;;;CAMT,MAAM,uBAA6B;EACjC,MAAM,MAAM,KAAK,KAAK;EACtB,IAAIC,kBAAiC;AAGrC,OAAK,MAAM,CAAC,IAAI,SAAS,aAAa;GACpC,MAAM,UAAU,MAAM,KAAK;AAE3B,OAAI,oBAAoB,QAAQ,UAAU,gBACxC,mBAAkB;AAGpB,OAAI,UAAU,sBACZ,MAAK;IACH,MAAM;IACN,eAAe;IACf,WAAW;IACZ,CAAC;;AAIN,OAAK;GACH,MAAM;GACN,cAAc,YAAY;GAC1B;GACD,CAAC;;AAsFJ,QAnF8B;EAC5B,kBAAkB,YAA6B;GAC7C,MAAM,UAAU,gBAAgB,QAAQ;AAExC,OAAI,QAEF,oBAAmB,KAAK,IAAI,kBAAkB,QAAQ;AAGxD,UAAO;;EAGT,eAAe,SAA4B;AACzC,eAAY,IAAI,KAAK,IAAI,KAAK;;EAGhC,iBAAiB,OAAqB;AACpC,eAAY,OAAO,GAAG;;EAGxB,uBAAsC;GACpC,MAAM,MAAM,KAAK,KAAK;GACtB,MAAMC,QAAuB,EAAE;AAE/B,QAAK,MAAM,QAAQ,YAAY,QAAQ,CACrC,KAAI,MAAM,KAAK,SAAS,sBACtB,OAAM,KAAK,KAAK;AAIpB,UAAO;;EAGT,iBAAqC;GACnC,MAAM,MAAM,KAAK,KAAK;GACtB,IAAID,kBAAiC;AAErC,QAAK,MAAM,QAAQ,YAAY,QAAQ,EAAE;IACvC,MAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,oBAAoB,QAAQ,UAAU,gBACxC,mBAAkB;;GAKtB,MAAM,YACJ,CAAC,kBACA,oBAAoB,QAAQ,kBAAkB,wBAAwB;AAEzE,UAAO;IACL,iBAAiB;IACjB,cAAc,YAAY;IAC1B;IACA;IACA,cAAc;IACf;;EAGH,aAAmB;AACjB,OAAI,uBAAuB,KAAM;AAEjC,wBAAqB,YAAY,gBAAgB,oBAAoB;;EAGvE,YAAkB;AAChB,OAAI,uBAAuB,MAAM;AAC/B,kBAAc,mBAAmB;AACjC,yBAAqB;;;EAIzB,QAAQ,eAA6B;AACnC,sBAAmB;AACnB,eAAY,OAAO;AACnB,mBAAgB;AAEhB,QAAK;IACH,MAAM;IACN,SAAS;IACV,CAAC;;EAEL;;;;;AAoBH,MAAa,2BACX,QACA,iBACmB;AAEnB,KAAI,CAAC,OAAO,aAAa,aAAa,SAAS,EAC7C,QAAO,EAAE,MAAM,oBAAoB;AAIrC,KAAI,aAAa,SAAS,EACxB,QAAO;EACL,MAAM;EACN,gBAAgB,aAAa,KAAK,MAAM,EAAE,GAAG;EAC9C;AAIH,QAAO,EAAE,MAAM,oBAAoB"}
@@ -0,0 +1,11 @@
1
+
2
+ //#region src/client/Transport.ts
3
+ var Transport_exports = {};
4
+
5
+ //#endregion
6
+ Object.defineProperty(exports, 'Transport_exports', {
7
+ enumerable: true,
8
+ get: function () {
9
+ return Transport_exports;
10
+ }
11
+ });
@@ -0,0 +1,237 @@
1
+ import { EncodedTransaction, Transaction } from "../Transaction.cjs";
2
+
3
+ //#region src/client/Transport.d.ts
4
+ declare namespace Transport_d_exports {
5
+ export { AuthMessage, AuthResultMessage, ClientMessage, EncodedClientMessage, EncodedServerMessage, EncodedSubmitTransactionMessage, EncodedTransactionMessage, ErrorMessage, PingMessage, PongMessage, PresenceClearMessage, PresenceEntry, PresenceRemoveMessage, PresenceSetMessage, PresenceSnapshotMessage, PresenceUpdateMessage, RequestSnapshotMessage, ServerMessage, SnapshotMessage, SubmitTransactionMessage, TransactionMessage, Transport, TransportEvent, TransportEventHandler, TransportOptions };
6
+ }
7
+ /**
8
+ * Message received when the server broadcasts a committed transaction.
9
+ */
10
+ interface TransactionMessage {
11
+ readonly type: "transaction";
12
+ readonly transaction: Transaction;
13
+ /** Server-assigned version number for ordering */
14
+ readonly version: number;
15
+ }
16
+ /**
17
+ * Message received when requesting or receiving a full state snapshot.
18
+ */
19
+ interface SnapshotMessage {
20
+ readonly type: "snapshot";
21
+ readonly state: unknown;
22
+ readonly version: number;
23
+ }
24
+ /**
25
+ * Message received when the server rejects a transaction.
26
+ */
27
+ interface ErrorMessage {
28
+ readonly type: "error";
29
+ readonly transactionId: string;
30
+ readonly reason: string;
31
+ }
32
+ /**
33
+ * Message received in response to a ping (heartbeat).
34
+ */
35
+ interface PongMessage {
36
+ readonly type: "pong";
37
+ }
38
+ /**
39
+ * Message received after authentication attempt.
40
+ */
41
+ interface AuthResultMessage {
42
+ readonly type: "auth_result";
43
+ readonly success: boolean;
44
+ readonly error?: string;
45
+ }
46
+ /**
47
+ * A presence entry as transmitted.
48
+ */
49
+ interface PresenceEntry {
50
+ /** The presence data */
51
+ readonly data: unknown;
52
+ /** Optional user ID from authentication */
53
+ readonly userId?: string;
54
+ }
55
+ /**
56
+ * Message received with initial presence state after authentication.
57
+ */
58
+ interface PresenceSnapshotMessage {
59
+ readonly type: "presence_snapshot";
60
+ /** This connection's ID (used to identify self) */
61
+ readonly selfId: string;
62
+ /** Map of connectionId to presence entry */
63
+ readonly presences: Record<string, PresenceEntry>;
64
+ }
65
+ /**
66
+ * Message received when another user updates their presence.
67
+ */
68
+ interface PresenceUpdateMessage {
69
+ readonly type: "presence_update";
70
+ /** The connection ID of the user who updated */
71
+ readonly id: string;
72
+ /** The presence data */
73
+ readonly data: unknown;
74
+ /** Optional user ID from authentication */
75
+ readonly userId?: string;
76
+ }
77
+ /**
78
+ * Message received when another user's presence is removed (disconnect).
79
+ */
80
+ interface PresenceRemoveMessage {
81
+ readonly type: "presence_remove";
82
+ /** The connection ID of the user who disconnected */
83
+ readonly id: string;
84
+ }
85
+ /**
86
+ * Union of all possible server messages.
87
+ */
88
+ type ServerMessage = TransactionMessage | SnapshotMessage | ErrorMessage | PongMessage | AuthResultMessage | PresenceSnapshotMessage | PresenceUpdateMessage | PresenceRemoveMessage;
89
+ /**
90
+ * Message sent to submit a transaction to the server.
91
+ */
92
+ interface SubmitTransactionMessage {
93
+ readonly type: "submit";
94
+ readonly transaction: Transaction;
95
+ }
96
+ /**
97
+ * Message sent to request a full state snapshot.
98
+ */
99
+ interface RequestSnapshotMessage {
100
+ readonly type: "request_snapshot";
101
+ }
102
+ /**
103
+ * Message sent as heartbeat ping.
104
+ */
105
+ interface PingMessage {
106
+ readonly type: "ping";
107
+ }
108
+ /**
109
+ * Message sent to authenticate with the server.
110
+ */
111
+ interface AuthMessage {
112
+ readonly type: "auth";
113
+ readonly token: string;
114
+ }
115
+ /**
116
+ * Message sent to set/update this client's presence.
117
+ */
118
+ interface PresenceSetMessage {
119
+ readonly type: "presence_set";
120
+ /** The presence data (validated against schema on client before sending) */
121
+ readonly data: unknown;
122
+ }
123
+ /**
124
+ * Message sent to clear this client's presence.
125
+ */
126
+ interface PresenceClearMessage {
127
+ readonly type: "presence_clear";
128
+ }
129
+ /**
130
+ * Union of all possible client messages.
131
+ */
132
+ type ClientMessage = SubmitTransactionMessage | RequestSnapshotMessage | PingMessage | AuthMessage | PresenceSetMessage | PresenceClearMessage;
133
+ /**
134
+ * Encoded transaction message for network transport.
135
+ */
136
+ interface EncodedTransactionMessage {
137
+ readonly type: "transaction";
138
+ readonly transaction: EncodedTransaction;
139
+ readonly version: number;
140
+ }
141
+ /**
142
+ * Encoded submit message for network transport.
143
+ */
144
+ interface EncodedSubmitTransactionMessage {
145
+ readonly type: "submit";
146
+ readonly transaction: EncodedTransaction;
147
+ }
148
+ /**
149
+ * Union of all possible encoded server messages (for network transport).
150
+ */
151
+ type EncodedServerMessage = EncodedTransactionMessage | SnapshotMessage | ErrorMessage | PongMessage | AuthResultMessage | PresenceSnapshotMessage | PresenceUpdateMessage | PresenceRemoveMessage;
152
+ /**
153
+ * Union of all possible encoded client messages (for network transport).
154
+ */
155
+ type EncodedClientMessage = EncodedSubmitTransactionMessage | RequestSnapshotMessage | PingMessage | AuthMessage | PresenceSetMessage | PresenceClearMessage;
156
+ /**
157
+ * Abstract transport interface for server communication.
158
+ * Implementations can use WebSocket, HTTP, or any other protocol.
159
+ */
160
+ interface Transport {
161
+ /**
162
+ * Sends a transaction to the server for processing.
163
+ * @param transaction - The transaction to submit
164
+ */
165
+ readonly send: (transaction: Transaction) => void;
166
+ /**
167
+ * Requests a full state snapshot from the server.
168
+ * Used for initial sync or recovery from drift.
169
+ */
170
+ readonly requestSnapshot: () => void;
171
+ /**
172
+ * Subscribes to messages from the server.
173
+ * @param handler - Callback invoked for each server message
174
+ * @returns Unsubscribe function
175
+ */
176
+ readonly subscribe: (handler: (message: ServerMessage) => void) => () => void;
177
+ /**
178
+ * Establishes connection to the server.
179
+ * @returns Promise that resolves when connected
180
+ */
181
+ readonly connect: () => Promise<void>;
182
+ /**
183
+ * Disconnects from the server.
184
+ */
185
+ readonly disconnect: () => void;
186
+ /**
187
+ * Returns whether the transport is currently connected.
188
+ */
189
+ readonly isConnected: () => boolean;
190
+ /**
191
+ * Sends presence data to the server.
192
+ * The data should be validated against the presence schema before calling.
193
+ * @param data - The presence data to set
194
+ */
195
+ readonly sendPresenceSet: (data: unknown) => void;
196
+ /**
197
+ * Clears this client's presence on the server.
198
+ */
199
+ readonly sendPresenceClear: () => void;
200
+ }
201
+ /**
202
+ * Events emitted by the transport for connection status.
203
+ */
204
+ type TransportEvent = {
205
+ type: "connected";
206
+ } | {
207
+ type: "disconnected";
208
+ reason?: string;
209
+ } | {
210
+ type: "reconnecting";
211
+ attempt: number;
212
+ } | {
213
+ type: "error";
214
+ error: Error;
215
+ };
216
+ /**
217
+ * Handler for transport events.
218
+ */
219
+ type TransportEventHandler = (event: TransportEvent) => void;
220
+ /**
221
+ * Options for creating a transport.
222
+ */
223
+ interface TransportOptions {
224
+ /** Handler for transport lifecycle events */
225
+ readonly onEvent?: TransportEventHandler;
226
+ /** Timeout in milliseconds for connection attempts */
227
+ readonly connectionTimeout?: number;
228
+ /** Whether to automatically reconnect on disconnect */
229
+ readonly autoReconnect?: boolean;
230
+ /** Maximum number of reconnection attempts */
231
+ readonly maxReconnectAttempts?: number;
232
+ /** Base delay between reconnection attempts (ms) */
233
+ readonly reconnectDelay?: number;
234
+ }
235
+ //#endregion
236
+ export { Transport, TransportOptions, Transport_d_exports };
237
+ //# sourceMappingURL=Transport.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transport.d.cts","names":[],"sources":["../../src/client/Transport.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UASiB,kBAAA;;wBAEO;;;;;;;UAQP,eAAA;;;;;;;;UASA,YAAA;;;;;;;;UASA,WAAA;;AA5BjB;AAUA;AASA;AASA;AAOiB,UAAA,iBAAA,CAAiB;EAajB,SAAA,IAAA,EAAA,aAAa;EAUb,SAAA,OAAA,EAAA,OAAA;EAWA,SAAA,KAAA,CAAA,EAAA,MAAA;AAajB;AASA;;;AAGI,UA9Ca,aAAA,CA8Cb;EACA;EACA,SAAA,IAAA,EAAA,OAAA;EACA;EACA,SAAA,MAAA,CAAA,EAAA,MAAA;;;AAUJ;AAQA;AAOiB,UAjEA,uBAAA,CAiEW;EAOX,SAAA,IAAA,EAAW,mBAAA;EAYX;EASA,SAAA,MAAA,EAAA,MAAoB;EAOzB;EACR,SAAA,SAAA,EAhGkB,MAgGlB,CAAA,MAAA,EAhGiC,aAgGjC,CAAA;;;;;AAKA,UA/Fa,qBAAA,CA+Fb;EAAoB,SAAA,IAAA,EAAA,iBAAA;EASP;EASA,SAAA,EAAA,EAAA,MAAA;EAQL;EACR,SAAA,IAAA,EAAA,OAAA;EACA;EACA,SAAA,MAAA,CAAA,EAAA,MAAA;;;;;AAKA,UApHa,qBAAA,CAoHb;EAAqB,SAAA,IAAA,EAAA,iBAAA;EAKb;EACR,SAAA,EAAA,EAAA,MAAA;;;;;AAKA,KAtHQ,aAAA,GACR,kBAqHA,GApHA,eAoHA,GAnHA,YAmHA,GAlHA,WAkHA,GAjHA,iBAiHA,GAhHA,uBAgHA,GA/GA,qBA+GA,GA9GA,qBA8GA;;AAUJ;;AAkB0C,UAjIzB,wBAAA,CAiIyB;EAMhB,SAAA,IAAA,EAAA,QAAA;EAAO,SAAA,WAAA,EArIT,WAqIS;AAoCjC;AASA;AASA;;UArLiB,sBAAA;;;;;;UAOA,WAAA;;;;;;UAOA,WAAA;;;;;;;UAYA,kBAAA;;;;;;;;UASA,oBAAA;;;;;;KAOL,aAAA,GACR,2BACA,yBACA,cACA,cACA,qBACA;;;;UASa,yBAAA;;wBAEO;;;;;;UAOP,+BAAA;;wBAEO;;;;;KAMZ,oBAAA,GACR,4BACA,kBACA,eACA,cACA,oBACA,0BACA,wBACA;;;;KAKQ,oBAAA,GACR,kCACA,yBACA,cACA,cACA,qBACA;;;;;UAUa,SAAA;;;;;+BAKc;;;;;;;;;;;0CAaW;;;;;0BAMhB;;;;;;;;;;;;;;;;;;;;;;;KAoCd,cAAA;;;;;;;;;;SAIgB;;;;;KAKhB,qBAAA,WAAgC;;;;UAS3B,gBAAA;;qBAEI"}
@@ -0,0 +1,237 @@
1
+ import { EncodedTransaction, Transaction } from "../Transaction.mjs";
2
+
3
+ //#region src/client/Transport.d.ts
4
+ declare namespace Transport_d_exports {
5
+ export { AuthMessage, AuthResultMessage, ClientMessage, EncodedClientMessage, EncodedServerMessage, EncodedSubmitTransactionMessage, EncodedTransactionMessage, ErrorMessage, PingMessage, PongMessage, PresenceClearMessage, PresenceEntry, PresenceRemoveMessage, PresenceSetMessage, PresenceSnapshotMessage, PresenceUpdateMessage, RequestSnapshotMessage, ServerMessage, SnapshotMessage, SubmitTransactionMessage, TransactionMessage, Transport, TransportEvent, TransportEventHandler, TransportOptions };
6
+ }
7
+ /**
8
+ * Message received when the server broadcasts a committed transaction.
9
+ */
10
+ interface TransactionMessage {
11
+ readonly type: "transaction";
12
+ readonly transaction: Transaction;
13
+ /** Server-assigned version number for ordering */
14
+ readonly version: number;
15
+ }
16
+ /**
17
+ * Message received when requesting or receiving a full state snapshot.
18
+ */
19
+ interface SnapshotMessage {
20
+ readonly type: "snapshot";
21
+ readonly state: unknown;
22
+ readonly version: number;
23
+ }
24
+ /**
25
+ * Message received when the server rejects a transaction.
26
+ */
27
+ interface ErrorMessage {
28
+ readonly type: "error";
29
+ readonly transactionId: string;
30
+ readonly reason: string;
31
+ }
32
+ /**
33
+ * Message received in response to a ping (heartbeat).
34
+ */
35
+ interface PongMessage {
36
+ readonly type: "pong";
37
+ }
38
+ /**
39
+ * Message received after authentication attempt.
40
+ */
41
+ interface AuthResultMessage {
42
+ readonly type: "auth_result";
43
+ readonly success: boolean;
44
+ readonly error?: string;
45
+ }
46
+ /**
47
+ * A presence entry as transmitted.
48
+ */
49
+ interface PresenceEntry {
50
+ /** The presence data */
51
+ readonly data: unknown;
52
+ /** Optional user ID from authentication */
53
+ readonly userId?: string;
54
+ }
55
+ /**
56
+ * Message received with initial presence state after authentication.
57
+ */
58
+ interface PresenceSnapshotMessage {
59
+ readonly type: "presence_snapshot";
60
+ /** This connection's ID (used to identify self) */
61
+ readonly selfId: string;
62
+ /** Map of connectionId to presence entry */
63
+ readonly presences: Record<string, PresenceEntry>;
64
+ }
65
+ /**
66
+ * Message received when another user updates their presence.
67
+ */
68
+ interface PresenceUpdateMessage {
69
+ readonly type: "presence_update";
70
+ /** The connection ID of the user who updated */
71
+ readonly id: string;
72
+ /** The presence data */
73
+ readonly data: unknown;
74
+ /** Optional user ID from authentication */
75
+ readonly userId?: string;
76
+ }
77
+ /**
78
+ * Message received when another user's presence is removed (disconnect).
79
+ */
80
+ interface PresenceRemoveMessage {
81
+ readonly type: "presence_remove";
82
+ /** The connection ID of the user who disconnected */
83
+ readonly id: string;
84
+ }
85
+ /**
86
+ * Union of all possible server messages.
87
+ */
88
+ type ServerMessage = TransactionMessage | SnapshotMessage | ErrorMessage | PongMessage | AuthResultMessage | PresenceSnapshotMessage | PresenceUpdateMessage | PresenceRemoveMessage;
89
+ /**
90
+ * Message sent to submit a transaction to the server.
91
+ */
92
+ interface SubmitTransactionMessage {
93
+ readonly type: "submit";
94
+ readonly transaction: Transaction;
95
+ }
96
+ /**
97
+ * Message sent to request a full state snapshot.
98
+ */
99
+ interface RequestSnapshotMessage {
100
+ readonly type: "request_snapshot";
101
+ }
102
+ /**
103
+ * Message sent as heartbeat ping.
104
+ */
105
+ interface PingMessage {
106
+ readonly type: "ping";
107
+ }
108
+ /**
109
+ * Message sent to authenticate with the server.
110
+ */
111
+ interface AuthMessage {
112
+ readonly type: "auth";
113
+ readonly token: string;
114
+ }
115
+ /**
116
+ * Message sent to set/update this client's presence.
117
+ */
118
+ interface PresenceSetMessage {
119
+ readonly type: "presence_set";
120
+ /** The presence data (validated against schema on client before sending) */
121
+ readonly data: unknown;
122
+ }
123
+ /**
124
+ * Message sent to clear this client's presence.
125
+ */
126
+ interface PresenceClearMessage {
127
+ readonly type: "presence_clear";
128
+ }
129
+ /**
130
+ * Union of all possible client messages.
131
+ */
132
+ type ClientMessage = SubmitTransactionMessage | RequestSnapshotMessage | PingMessage | AuthMessage | PresenceSetMessage | PresenceClearMessage;
133
+ /**
134
+ * Encoded transaction message for network transport.
135
+ */
136
+ interface EncodedTransactionMessage {
137
+ readonly type: "transaction";
138
+ readonly transaction: EncodedTransaction;
139
+ readonly version: number;
140
+ }
141
+ /**
142
+ * Encoded submit message for network transport.
143
+ */
144
+ interface EncodedSubmitTransactionMessage {
145
+ readonly type: "submit";
146
+ readonly transaction: EncodedTransaction;
147
+ }
148
+ /**
149
+ * Union of all possible encoded server messages (for network transport).
150
+ */
151
+ type EncodedServerMessage = EncodedTransactionMessage | SnapshotMessage | ErrorMessage | PongMessage | AuthResultMessage | PresenceSnapshotMessage | PresenceUpdateMessage | PresenceRemoveMessage;
152
+ /**
153
+ * Union of all possible encoded client messages (for network transport).
154
+ */
155
+ type EncodedClientMessage = EncodedSubmitTransactionMessage | RequestSnapshotMessage | PingMessage | AuthMessage | PresenceSetMessage | PresenceClearMessage;
156
+ /**
157
+ * Abstract transport interface for server communication.
158
+ * Implementations can use WebSocket, HTTP, or any other protocol.
159
+ */
160
+ interface Transport {
161
+ /**
162
+ * Sends a transaction to the server for processing.
163
+ * @param transaction - The transaction to submit
164
+ */
165
+ readonly send: (transaction: Transaction) => void;
166
+ /**
167
+ * Requests a full state snapshot from the server.
168
+ * Used for initial sync or recovery from drift.
169
+ */
170
+ readonly requestSnapshot: () => void;
171
+ /**
172
+ * Subscribes to messages from the server.
173
+ * @param handler - Callback invoked for each server message
174
+ * @returns Unsubscribe function
175
+ */
176
+ readonly subscribe: (handler: (message: ServerMessage) => void) => () => void;
177
+ /**
178
+ * Establishes connection to the server.
179
+ * @returns Promise that resolves when connected
180
+ */
181
+ readonly connect: () => Promise<void>;
182
+ /**
183
+ * Disconnects from the server.
184
+ */
185
+ readonly disconnect: () => void;
186
+ /**
187
+ * Returns whether the transport is currently connected.
188
+ */
189
+ readonly isConnected: () => boolean;
190
+ /**
191
+ * Sends presence data to the server.
192
+ * The data should be validated against the presence schema before calling.
193
+ * @param data - The presence data to set
194
+ */
195
+ readonly sendPresenceSet: (data: unknown) => void;
196
+ /**
197
+ * Clears this client's presence on the server.
198
+ */
199
+ readonly sendPresenceClear: () => void;
200
+ }
201
+ /**
202
+ * Events emitted by the transport for connection status.
203
+ */
204
+ type TransportEvent = {
205
+ type: "connected";
206
+ } | {
207
+ type: "disconnected";
208
+ reason?: string;
209
+ } | {
210
+ type: "reconnecting";
211
+ attempt: number;
212
+ } | {
213
+ type: "error";
214
+ error: Error;
215
+ };
216
+ /**
217
+ * Handler for transport events.
218
+ */
219
+ type TransportEventHandler = (event: TransportEvent) => void;
220
+ /**
221
+ * Options for creating a transport.
222
+ */
223
+ interface TransportOptions {
224
+ /** Handler for transport lifecycle events */
225
+ readonly onEvent?: TransportEventHandler;
226
+ /** Timeout in milliseconds for connection attempts */
227
+ readonly connectionTimeout?: number;
228
+ /** Whether to automatically reconnect on disconnect */
229
+ readonly autoReconnect?: boolean;
230
+ /** Maximum number of reconnection attempts */
231
+ readonly maxReconnectAttempts?: number;
232
+ /** Base delay between reconnection attempts (ms) */
233
+ readonly reconnectDelay?: number;
234
+ }
235
+ //#endregion
236
+ export { Transport, TransportOptions, Transport_d_exports };
237
+ //# sourceMappingURL=Transport.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transport.d.mts","names":[],"sources":["../../src/client/Transport.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UASiB,kBAAA;;wBAEO;;;;;;;UAQP,eAAA;;;;;;;;UASA,YAAA;;;;;;;;UASA,WAAA;;AA5BjB;AAUA;AASA;AASA;AAOiB,UAAA,iBAAA,CAAiB;EAajB,SAAA,IAAA,EAAA,aAAa;EAUb,SAAA,OAAA,EAAA,OAAA;EAWA,SAAA,KAAA,CAAA,EAAA,MAAA;AAajB;AASA;;;AAGI,UA9Ca,aAAA,CA8Cb;EACA;EACA,SAAA,IAAA,EAAA,OAAA;EACA;EACA,SAAA,MAAA,CAAA,EAAA,MAAA;;;AAUJ;AAQA;AAOiB,UAjEA,uBAAA,CAiEW;EAOX,SAAA,IAAA,EAAW,mBAAA;EAYX;EASA,SAAA,MAAA,EAAA,MAAoB;EAOzB;EACR,SAAA,SAAA,EAhGkB,MAgGlB,CAAA,MAAA,EAhGiC,aAgGjC,CAAA;;;;;AAKA,UA/Fa,qBAAA,CA+Fb;EAAoB,SAAA,IAAA,EAAA,iBAAA;EASP;EASA,SAAA,EAAA,EAAA,MAAA;EAQL;EACR,SAAA,IAAA,EAAA,OAAA;EACA;EACA,SAAA,MAAA,CAAA,EAAA,MAAA;;;;;AAKA,UApHa,qBAAA,CAoHb;EAAqB,SAAA,IAAA,EAAA,iBAAA;EAKb;EACR,SAAA,EAAA,EAAA,MAAA;;;;;AAKA,KAtHQ,aAAA,GACR,kBAqHA,GApHA,eAoHA,GAnHA,YAmHA,GAlHA,WAkHA,GAjHA,iBAiHA,GAhHA,uBAgHA,GA/GA,qBA+GA,GA9GA,qBA8GA;;AAUJ;;AAkB0C,UAjIzB,wBAAA,CAiIyB;EAMhB,SAAA,IAAA,EAAA,QAAA;EAAO,SAAA,WAAA,EArIT,WAqIS;AAoCjC;AASA;AASA;;UArLiB,sBAAA;;;;;;UAOA,WAAA;;;;;;UAOA,WAAA;;;;;;;UAYA,kBAAA;;;;;;;;UASA,oBAAA;;;;;;KAOL,aAAA,GACR,2BACA,yBACA,cACA,cACA,qBACA;;;;UASa,yBAAA;;wBAEO;;;;;;UAOP,+BAAA;;wBAEO;;;;;KAMZ,oBAAA,GACR,4BACA,kBACA,eACA,cACA,oBACA,0BACA,wBACA;;;;KAKQ,oBAAA,GACR,kCACA,yBACA,cACA,cACA,qBACA;;;;;UAUa,SAAA;;;;;+BAKc;;;;;;;;;;;0CAaW;;;;;0BAMhB;;;;;;;;;;;;;;;;;;;;;;;KAoCd,cAAA;;;;;;;;;;SAIgB;;;;;KAKhB,qBAAA,WAAgC;;;;UAS3B,gBAAA;;qBAEI"}
@@ -0,0 +1,6 @@
1
+ //#region src/client/Transport.ts
2
+ var Transport_exports = {};
3
+
4
+ //#endregion
5
+ export { Transport_exports };
6
+ //# sourceMappingURL=Transport.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Transport.mjs","names":[],"sources":["../../src/client/Transport.ts"],"sourcesContent":["import type * as Transaction from \"../Transaction\";\n\n// =============================================================================\n// Server Messages\n// =============================================================================\n\n/**\n * Message received when the server broadcasts a committed transaction.\n */\nexport interface TransactionMessage {\n readonly type: \"transaction\";\n readonly transaction: Transaction.Transaction;\n /** Server-assigned version number for ordering */\n readonly version: number;\n}\n\n/**\n * Message received when requesting or receiving a full state snapshot.\n */\nexport interface SnapshotMessage {\n readonly type: \"snapshot\";\n readonly state: unknown;\n readonly version: number;\n}\n\n/**\n * Message received when the server rejects a transaction.\n */\nexport interface ErrorMessage {\n readonly type: \"error\";\n readonly transactionId: string;\n readonly reason: string;\n}\n\n/**\n * Message received in response to a ping (heartbeat).\n */\nexport interface PongMessage {\n readonly type: \"pong\";\n}\n\n/**\n * Message received after authentication attempt.\n */\nexport interface AuthResultMessage {\n readonly type: \"auth_result\";\n readonly success: boolean;\n readonly error?: string;\n}\n\n// =============================================================================\n// Presence Server Messages\n// =============================================================================\n\n/**\n * A presence entry as transmitted.\n */\nexport interface PresenceEntry {\n /** The presence data */\n readonly data: unknown;\n /** Optional user ID from authentication */\n readonly userId?: string;\n}\n\n/**\n * Message received with initial presence state after authentication.\n */\nexport interface PresenceSnapshotMessage {\n readonly type: \"presence_snapshot\";\n /** This connection's ID (used to identify self) */\n readonly selfId: string;\n /** Map of connectionId to presence entry */\n readonly presences: Record<string, PresenceEntry>;\n}\n\n/**\n * Message received when another user updates their presence.\n */\nexport interface PresenceUpdateMessage {\n readonly type: \"presence_update\";\n /** The connection ID of the user who updated */\n readonly id: string;\n /** The presence data */\n readonly data: unknown;\n /** Optional user ID from authentication */\n readonly userId?: string;\n}\n\n/**\n * Message received when another user's presence is removed (disconnect).\n */\nexport interface PresenceRemoveMessage {\n readonly type: \"presence_remove\";\n /** The connection ID of the user who disconnected */\n readonly id: string;\n}\n\n/**\n * Union of all possible server messages.\n */\nexport type ServerMessage =\n | TransactionMessage\n | SnapshotMessage\n | ErrorMessage\n | PongMessage\n | AuthResultMessage\n | PresenceSnapshotMessage\n | PresenceUpdateMessage\n | PresenceRemoveMessage;\n\n// =============================================================================\n// Client Messages\n// =============================================================================\n\n/**\n * Message sent to submit a transaction to the server.\n */\nexport interface SubmitTransactionMessage {\n readonly type: \"submit\";\n readonly transaction: Transaction.Transaction;\n}\n\n/**\n * Message sent to request a full state snapshot.\n */\nexport interface RequestSnapshotMessage {\n readonly type: \"request_snapshot\";\n}\n\n/**\n * Message sent as heartbeat ping.\n */\nexport interface PingMessage {\n readonly type: \"ping\";\n}\n\n/**\n * Message sent to authenticate with the server.\n */\nexport interface AuthMessage {\n readonly type: \"auth\";\n readonly token: string;\n}\n\n// =============================================================================\n// Presence Client Messages\n// =============================================================================\n\n/**\n * Message sent to set/update this client's presence.\n */\nexport interface PresenceSetMessage {\n readonly type: \"presence_set\";\n /** The presence data (validated against schema on client before sending) */\n readonly data: unknown;\n}\n\n/**\n * Message sent to clear this client's presence.\n */\nexport interface PresenceClearMessage {\n readonly type: \"presence_clear\";\n}\n\n/**\n * Union of all possible client messages.\n */\nexport type ClientMessage =\n | SubmitTransactionMessage\n | RequestSnapshotMessage\n | PingMessage\n | AuthMessage\n | PresenceSetMessage\n | PresenceClearMessage;\n\n// =============================================================================\n// Encoded Message Types (for network transport)\n// =============================================================================\n\n/**\n * Encoded transaction message for network transport.\n */\nexport interface EncodedTransactionMessage {\n readonly type: \"transaction\";\n readonly transaction: Transaction.EncodedTransaction;\n readonly version: number;\n}\n\n/**\n * Encoded submit message for network transport.\n */\nexport interface EncodedSubmitTransactionMessage {\n readonly type: \"submit\";\n readonly transaction: Transaction.EncodedTransaction;\n}\n\n/**\n * Union of all possible encoded server messages (for network transport).\n */\nexport type EncodedServerMessage =\n | EncodedTransactionMessage\n | SnapshotMessage\n | ErrorMessage\n | PongMessage\n | AuthResultMessage\n | PresenceSnapshotMessage\n | PresenceUpdateMessage\n | PresenceRemoveMessage;\n\n/**\n * Union of all possible encoded client messages (for network transport).\n */\nexport type EncodedClientMessage =\n | EncodedSubmitTransactionMessage\n | RequestSnapshotMessage\n | PingMessage\n | AuthMessage\n | PresenceSetMessage\n | PresenceClearMessage;\n\n// =============================================================================\n// Transport Interface\n// =============================================================================\n\n/**\n * Abstract transport interface for server communication.\n * Implementations can use WebSocket, HTTP, or any other protocol.\n */\nexport interface Transport {\n /**\n * Sends a transaction to the server for processing.\n * @param transaction - The transaction to submit\n */\n readonly send: (transaction: Transaction.Transaction) => void;\n\n /**\n * Requests a full state snapshot from the server.\n * Used for initial sync or recovery from drift.\n */\n readonly requestSnapshot: () => void;\n\n /**\n * Subscribes to messages from the server.\n * @param handler - Callback invoked for each server message\n * @returns Unsubscribe function\n */\n readonly subscribe: (handler: (message: ServerMessage) => void) => () => void;\n\n /**\n * Establishes connection to the server.\n * @returns Promise that resolves when connected\n */\n readonly connect: () => Promise<void>;\n\n /**\n * Disconnects from the server.\n */\n readonly disconnect: () => void;\n\n /**\n * Returns whether the transport is currently connected.\n */\n readonly isConnected: () => boolean;\n\n // ===========================================================================\n // Presence Methods\n // ===========================================================================\n\n /**\n * Sends presence data to the server.\n * The data should be validated against the presence schema before calling.\n * @param data - The presence data to set\n */\n readonly sendPresenceSet: (data: unknown) => void;\n\n /**\n * Clears this client's presence on the server.\n */\n readonly sendPresenceClear: () => void;\n}\n\n// =============================================================================\n// Transport Events\n// =============================================================================\n\n/**\n * Events emitted by the transport for connection status.\n */\nexport type TransportEvent =\n | { type: \"connected\" }\n | { type: \"disconnected\"; reason?: string }\n | { type: \"reconnecting\"; attempt: number }\n | { type: \"error\"; error: Error };\n\n/**\n * Handler for transport events.\n */\nexport type TransportEventHandler = (event: TransportEvent) => void;\n\n// =============================================================================\n// Transport Options\n// =============================================================================\n\n/**\n * Options for creating a transport.\n */\nexport interface TransportOptions {\n /** Handler for transport lifecycle events */\n readonly onEvent?: TransportEventHandler;\n /** Timeout in milliseconds for connection attempts */\n readonly connectionTimeout?: number;\n /** Whether to automatically reconnect on disconnect */\n readonly autoReconnect?: boolean;\n /** Maximum number of reconnection attempts */\n readonly maxReconnectAttempts?: number;\n /** Base delay between reconnection attempts (ms) */\n readonly reconnectDelay?: number;\n}\n"],"mappings":""}