@voidhash/mimic-effect 0.0.9 → 1.0.0-beta.2

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 (227) hide show
  1. package/.turbo/turbo-build.log +136 -90
  2. package/README.md +385 -0
  3. package/dist/ColdStorage.cjs +60 -0
  4. package/dist/ColdStorage.d.cts +53 -0
  5. package/dist/ColdStorage.d.cts.map +1 -0
  6. package/dist/ColdStorage.d.mts +53 -0
  7. package/dist/ColdStorage.d.mts.map +1 -0
  8. package/dist/ColdStorage.mjs +60 -0
  9. package/dist/ColdStorage.mjs.map +1 -0
  10. package/dist/DocumentManager.cjs +263 -82
  11. package/dist/DocumentManager.d.cts +44 -22
  12. package/dist/DocumentManager.d.cts.map +1 -1
  13. package/dist/DocumentManager.d.mts +44 -22
  14. package/dist/DocumentManager.d.mts.map +1 -1
  15. package/dist/DocumentManager.mjs +259 -67
  16. package/dist/DocumentManager.mjs.map +1 -1
  17. package/dist/Errors.cjs +54 -0
  18. package/dist/Errors.d.cts +96 -0
  19. package/dist/Errors.d.cts.map +1 -0
  20. package/dist/Errors.d.mts +96 -0
  21. package/dist/Errors.d.mts.map +1 -0
  22. package/dist/Errors.mjs +48 -0
  23. package/dist/Errors.mjs.map +1 -0
  24. package/dist/HotStorage.cjs +100 -0
  25. package/dist/HotStorage.d.cts +70 -0
  26. package/dist/HotStorage.d.cts.map +1 -0
  27. package/dist/HotStorage.d.mts +70 -0
  28. package/dist/HotStorage.d.mts.map +1 -0
  29. package/dist/HotStorage.mjs +100 -0
  30. package/dist/HotStorage.mjs.map +1 -0
  31. package/dist/Metrics.cjs +143 -0
  32. package/dist/Metrics.d.cts +31 -0
  33. package/dist/Metrics.d.cts.map +1 -0
  34. package/dist/Metrics.d.mts +31 -0
  35. package/dist/Metrics.d.mts.map +1 -0
  36. package/dist/Metrics.mjs +126 -0
  37. package/dist/Metrics.mjs.map +1 -0
  38. package/dist/MimicAuthService.cjs +61 -45
  39. package/dist/MimicAuthService.d.cts +61 -48
  40. package/dist/MimicAuthService.d.cts.map +1 -1
  41. package/dist/MimicAuthService.d.mts +61 -48
  42. package/dist/MimicAuthService.d.mts.map +1 -1
  43. package/dist/MimicAuthService.mjs +60 -36
  44. package/dist/MimicAuthService.mjs.map +1 -1
  45. package/dist/MimicClusterServerEngine.cjs +521 -0
  46. package/dist/MimicClusterServerEngine.d.cts +17 -0
  47. package/dist/MimicClusterServerEngine.d.cts.map +1 -0
  48. package/dist/MimicClusterServerEngine.d.mts +17 -0
  49. package/dist/MimicClusterServerEngine.d.mts.map +1 -0
  50. package/dist/MimicClusterServerEngine.mjs +523 -0
  51. package/dist/MimicClusterServerEngine.mjs.map +1 -0
  52. package/dist/MimicServer.cjs +205 -96
  53. package/dist/MimicServer.d.cts +9 -110
  54. package/dist/MimicServer.d.cts.map +1 -1
  55. package/dist/MimicServer.d.mts +9 -110
  56. package/dist/MimicServer.d.mts.map +1 -1
  57. package/dist/MimicServer.mjs +206 -90
  58. package/dist/MimicServer.mjs.map +1 -1
  59. package/dist/MimicServerEngine.cjs +97 -0
  60. package/dist/MimicServerEngine.d.cts +78 -0
  61. package/dist/MimicServerEngine.d.cts.map +1 -0
  62. package/dist/MimicServerEngine.d.mts +78 -0
  63. package/dist/MimicServerEngine.d.mts.map +1 -0
  64. package/dist/MimicServerEngine.mjs +97 -0
  65. package/dist/MimicServerEngine.mjs.map +1 -0
  66. package/dist/PresenceManager.cjs +75 -91
  67. package/dist/PresenceManager.d.cts +17 -66
  68. package/dist/PresenceManager.d.cts.map +1 -1
  69. package/dist/PresenceManager.d.mts +17 -66
  70. package/dist/PresenceManager.d.mts.map +1 -1
  71. package/dist/PresenceManager.mjs +74 -78
  72. package/dist/PresenceManager.mjs.map +1 -1
  73. package/dist/Protocol.cjs +146 -0
  74. package/dist/Protocol.d.cts +203 -0
  75. package/dist/Protocol.d.cts.map +1 -0
  76. package/dist/Protocol.d.mts +203 -0
  77. package/dist/Protocol.d.mts.map +1 -0
  78. package/dist/Protocol.mjs +132 -0
  79. package/dist/Protocol.mjs.map +1 -0
  80. package/dist/Types.d.cts +172 -0
  81. package/dist/Types.d.cts.map +1 -0
  82. package/dist/Types.d.mts +172 -0
  83. package/dist/Types.d.mts.map +1 -0
  84. package/dist/_virtual/rolldown_runtime.cjs +1 -25
  85. package/dist/_virtual/rolldown_runtime.mjs +4 -1
  86. package/dist/index.cjs +37 -75
  87. package/dist/index.d.cts +13 -12
  88. package/dist/index.d.mts +13 -12
  89. package/dist/index.mjs +12 -12
  90. package/dist/testing/ColdStorageTestSuite.cjs +508 -0
  91. package/dist/testing/ColdStorageTestSuite.d.cts +36 -0
  92. package/dist/testing/ColdStorageTestSuite.d.cts.map +1 -0
  93. package/dist/testing/ColdStorageTestSuite.d.mts +36 -0
  94. package/dist/testing/ColdStorageTestSuite.d.mts.map +1 -0
  95. package/dist/testing/ColdStorageTestSuite.mjs +508 -0
  96. package/dist/testing/ColdStorageTestSuite.mjs.map +1 -0
  97. package/dist/testing/FailingStorage.cjs +135 -0
  98. package/dist/testing/FailingStorage.d.cts +43 -0
  99. package/dist/testing/FailingStorage.d.cts.map +1 -0
  100. package/dist/testing/FailingStorage.d.mts +43 -0
  101. package/dist/testing/FailingStorage.d.mts.map +1 -0
  102. package/dist/testing/FailingStorage.mjs +136 -0
  103. package/dist/testing/FailingStorage.mjs.map +1 -0
  104. package/dist/testing/HotStorageTestSuite.cjs +585 -0
  105. package/dist/testing/HotStorageTestSuite.d.cts +40 -0
  106. package/dist/testing/HotStorageTestSuite.d.cts.map +1 -0
  107. package/dist/testing/HotStorageTestSuite.d.mts +40 -0
  108. package/dist/testing/HotStorageTestSuite.d.mts.map +1 -0
  109. package/dist/testing/HotStorageTestSuite.mjs +585 -0
  110. package/dist/testing/HotStorageTestSuite.mjs.map +1 -0
  111. package/dist/testing/StorageIntegrationTestSuite.cjs +349 -0
  112. package/dist/testing/StorageIntegrationTestSuite.d.cts +35 -0
  113. package/dist/testing/StorageIntegrationTestSuite.d.cts.map +1 -0
  114. package/dist/testing/StorageIntegrationTestSuite.d.mts +35 -0
  115. package/dist/testing/StorageIntegrationTestSuite.d.mts.map +1 -0
  116. package/dist/testing/StorageIntegrationTestSuite.mjs +349 -0
  117. package/dist/testing/StorageIntegrationTestSuite.mjs.map +1 -0
  118. package/dist/testing/assertions.cjs +114 -0
  119. package/dist/testing/assertions.mjs +109 -0
  120. package/dist/testing/assertions.mjs.map +1 -0
  121. package/dist/testing/index.cjs +14 -0
  122. package/dist/testing/index.d.cts +6 -0
  123. package/dist/testing/index.d.mts +6 -0
  124. package/dist/testing/index.mjs +7 -0
  125. package/dist/testing/types.cjs +15 -0
  126. package/dist/testing/types.d.cts +90 -0
  127. package/dist/testing/types.d.cts.map +1 -0
  128. package/dist/testing/types.d.mts +90 -0
  129. package/dist/testing/types.d.mts.map +1 -0
  130. package/dist/testing/types.mjs +16 -0
  131. package/dist/testing/types.mjs.map +1 -0
  132. package/package.json +18 -3
  133. package/src/ColdStorage.ts +136 -0
  134. package/src/DocumentManager.ts +550 -190
  135. package/src/Errors.ts +114 -0
  136. package/src/HotStorage.ts +239 -0
  137. package/src/Metrics.ts +187 -0
  138. package/src/MimicAuthService.ts +126 -64
  139. package/src/MimicClusterServerEngine.ts +946 -0
  140. package/src/MimicServer.ts +448 -195
  141. package/src/MimicServerEngine.ts +276 -0
  142. package/src/PresenceManager.ts +169 -240
  143. package/src/Protocol.ts +350 -0
  144. package/src/Types.ts +231 -0
  145. package/src/index.ts +57 -23
  146. package/src/testing/ColdStorageTestSuite.ts +589 -0
  147. package/src/testing/FailingStorage.ts +286 -0
  148. package/src/testing/HotStorageTestSuite.ts +762 -0
  149. package/src/testing/StorageIntegrationTestSuite.ts +504 -0
  150. package/src/testing/assertions.ts +181 -0
  151. package/src/testing/index.ts +83 -0
  152. package/src/testing/types.ts +100 -0
  153. package/tests/ColdStorage.test.ts +24 -0
  154. package/tests/DocumentManager.test.ts +158 -287
  155. package/tests/HotStorage.test.ts +24 -0
  156. package/tests/MimicAuthService.test.ts +102 -134
  157. package/tests/MimicClusterServerEngine.test.ts +587 -0
  158. package/tests/MimicServer.test.ts +90 -226
  159. package/tests/MimicServerEngine.test.ts +521 -0
  160. package/tests/PresenceManager.test.ts +22 -63
  161. package/tests/Protocol.test.ts +190 -0
  162. package/tests/StorageIntegration.test.ts +259 -0
  163. package/tsconfig.json +1 -1
  164. package/tsdown.config.ts +1 -1
  165. package/dist/DocumentProtocol.cjs +0 -94
  166. package/dist/DocumentProtocol.d.cts +0 -113
  167. package/dist/DocumentProtocol.d.cts.map +0 -1
  168. package/dist/DocumentProtocol.d.mts +0 -113
  169. package/dist/DocumentProtocol.d.mts.map +0 -1
  170. package/dist/DocumentProtocol.mjs +0 -89
  171. package/dist/DocumentProtocol.mjs.map +0 -1
  172. package/dist/MimicConfig.cjs +0 -60
  173. package/dist/MimicConfig.d.cts +0 -141
  174. package/dist/MimicConfig.d.cts.map +0 -1
  175. package/dist/MimicConfig.d.mts +0 -141
  176. package/dist/MimicConfig.d.mts.map +0 -1
  177. package/dist/MimicConfig.mjs +0 -50
  178. package/dist/MimicConfig.mjs.map +0 -1
  179. package/dist/MimicDataStorage.cjs +0 -83
  180. package/dist/MimicDataStorage.d.cts +0 -113
  181. package/dist/MimicDataStorage.d.cts.map +0 -1
  182. package/dist/MimicDataStorage.d.mts +0 -113
  183. package/dist/MimicDataStorage.d.mts.map +0 -1
  184. package/dist/MimicDataStorage.mjs +0 -74
  185. package/dist/MimicDataStorage.mjs.map +0 -1
  186. package/dist/WebSocketHandler.cjs +0 -365
  187. package/dist/WebSocketHandler.d.cts +0 -34
  188. package/dist/WebSocketHandler.d.cts.map +0 -1
  189. package/dist/WebSocketHandler.d.mts +0 -34
  190. package/dist/WebSocketHandler.d.mts.map +0 -1
  191. package/dist/WebSocketHandler.mjs +0 -355
  192. package/dist/WebSocketHandler.mjs.map +0 -1
  193. package/dist/auth/NoAuth.cjs +0 -43
  194. package/dist/auth/NoAuth.d.cts +0 -22
  195. package/dist/auth/NoAuth.d.cts.map +0 -1
  196. package/dist/auth/NoAuth.d.mts +0 -22
  197. package/dist/auth/NoAuth.d.mts.map +0 -1
  198. package/dist/auth/NoAuth.mjs +0 -36
  199. package/dist/auth/NoAuth.mjs.map +0 -1
  200. package/dist/errors.cjs +0 -74
  201. package/dist/errors.d.cts +0 -89
  202. package/dist/errors.d.cts.map +0 -1
  203. package/dist/errors.d.mts +0 -89
  204. package/dist/errors.d.mts.map +0 -1
  205. package/dist/errors.mjs +0 -67
  206. package/dist/errors.mjs.map +0 -1
  207. package/dist/storage/InMemoryDataStorage.cjs +0 -57
  208. package/dist/storage/InMemoryDataStorage.d.cts +0 -19
  209. package/dist/storage/InMemoryDataStorage.d.cts.map +0 -1
  210. package/dist/storage/InMemoryDataStorage.d.mts +0 -19
  211. package/dist/storage/InMemoryDataStorage.d.mts.map +0 -1
  212. package/dist/storage/InMemoryDataStorage.mjs +0 -48
  213. package/dist/storage/InMemoryDataStorage.mjs.map +0 -1
  214. package/src/DocumentProtocol.ts +0 -112
  215. package/src/MimicConfig.ts +0 -211
  216. package/src/MimicDataStorage.ts +0 -157
  217. package/src/WebSocketHandler.ts +0 -735
  218. package/src/auth/NoAuth.ts +0 -46
  219. package/src/errors.ts +0 -113
  220. package/src/storage/InMemoryDataStorage.ts +0 -66
  221. package/tests/DocumentProtocol.test.ts +0 -113
  222. package/tests/InMemoryDataStorage.test.ts +0 -190
  223. package/tests/MimicConfig.test.ts +0 -290
  224. package/tests/MimicDataStorage.test.ts +0 -190
  225. package/tests/NoAuth.test.ts +0 -94
  226. package/tests/WebSocketHandler.test.ts +0 -321
  227. package/tests/errors.test.ts +0 -77
@@ -0,0 +1,78 @@
1
+ import { MimicServerEngineConfig, PresenceEntry, PresenceEvent, PresenceSnapshot, ResolvedConfig } from "./Types.mjs";
2
+ import { ServerMessage } from "./Protocol.mjs";
3
+ import { ColdStorageTag } from "./ColdStorage.mjs";
4
+ import { HotStorageTag } from "./HotStorage.mjs";
5
+ import { MimicAuthServiceTag } from "./MimicAuthService.mjs";
6
+ import { DocumentManagerError, SubmitResult } from "./DocumentManager.mjs";
7
+ import { Context, Effect, Layer, Scope, Stream } from "effect";
8
+ import { Primitive, Transaction } from "@voidhash/mimic";
9
+
10
+ //#region src/MimicServerEngine.d.ts
11
+
12
+ /**
13
+ * MimicServerEngine service interface.
14
+ *
15
+ * Provides document management operations for Mimic collaboration.
16
+ * Use MimicServer.layerHttpLayerRouter() to create WebSocket routes.
17
+ */
18
+ interface MimicServerEngine {
19
+ /**
20
+ * Submit a transaction to a document.
21
+ * Authorization is checked against the auth service.
22
+ * May fail with DocumentManagerError if storage is unavailable.
23
+ */
24
+ readonly submit: (documentId: string, transaction: Transaction.Transaction) => Effect.Effect<SubmitResult, DocumentManagerError>;
25
+ /**
26
+ * Get document snapshot (current state and version).
27
+ * May fail with DocumentManagerError if storage is unavailable.
28
+ */
29
+ readonly getSnapshot: (documentId: string) => Effect.Effect<{
30
+ state: unknown;
31
+ version: number;
32
+ }, DocumentManagerError>;
33
+ /**
34
+ * Subscribe to document broadcasts (transactions).
35
+ * Returns a stream of server messages.
36
+ * Requires a Scope for cleanup when the subscription ends.
37
+ * May fail with DocumentManagerError if storage is unavailable.
38
+ */
39
+ readonly subscribe: (documentId: string) => Effect.Effect<Stream.Stream<ServerMessage, never, never>, DocumentManagerError, Scope.Scope>;
40
+ /**
41
+ * Touch document to prevent idle garbage collection.
42
+ */
43
+ readonly touch: (documentId: string) => Effect.Effect<void, never>;
44
+ /**
45
+ * Get presence snapshot for a document.
46
+ */
47
+ readonly getPresenceSnapshot: (documentId: string) => Effect.Effect<PresenceSnapshot, never>;
48
+ /**
49
+ * Set presence for a connection.
50
+ */
51
+ readonly setPresence: (documentId: string, connectionId: string, entry: PresenceEntry) => Effect.Effect<void, never>;
52
+ /**
53
+ * Remove presence for a connection.
54
+ */
55
+ readonly removePresence: (documentId: string, connectionId: string) => Effect.Effect<void, never>;
56
+ /**
57
+ * Subscribe to presence events for a document.
58
+ * Requires a Scope for cleanup when the subscription ends.
59
+ */
60
+ readonly subscribePresence: (documentId: string) => Effect.Effect<Stream.Stream<PresenceEvent, never, never>, never, Scope.Scope>;
61
+ /**
62
+ * Resolved engine configuration.
63
+ * Used by route layer to access schema, presence config, etc.
64
+ */
65
+ readonly config: ResolvedConfig<Primitive.AnyPrimitive>;
66
+ }
67
+ declare const MimicServerEngineTag_base: Context.TagClass<MimicServerEngineTag, "@voidhash/mimic-effect/MimicServerEngine", MimicServerEngine>;
68
+ /**
69
+ * Context tag for MimicServerEngine
70
+ */
71
+ declare class MimicServerEngineTag extends MimicServerEngineTag_base {}
72
+ declare const MimicServerEngine: {
73
+ Tag: typeof MimicServerEngineTag;
74
+ make: <TSchema extends Primitive.AnyPrimitive>(config: MimicServerEngineConfig<TSchema>) => Layer.Layer<MimicServerEngineTag, never, ColdStorageTag | HotStorageTag | MimicAuthServiceTag>;
75
+ };
76
+ //#endregion
77
+ export { MimicServerEngine, MimicServerEngineTag };
78
+ //# sourceMappingURL=MimicServerEngine.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MimicServerEngine.d.mts","names":[],"sources":["../src/MimicServerEngine.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;AAkF0C,UAhCzB,iBAAA,CAgCgC;EAO5B;;;;;EAyBc,SAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,WAAA,EAxDlB,WAAA,CAAY,WAwDM,EAAA,GAvD5B,MAAA,CAAO,MAuDqB,CAvDd,YAuDc,EAvDA,oBAuDA,CAAA;EAAd;;;;EAMF,SAAA,WAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GArDZ,MAAA,CAAO,MAqDK,CAAA;IAAc,KAAA,EAAA,OAAA;IAChC,OAAA,EAAA,MAAA;KAtDyD;;;;AA+D1D;AAwIA;;EAjEqC,SAAU,SAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GA5HxC,MAAA,CAAO,MA4HiC,CA5H1B,MAAA,CAAO,MA4HmB,CA5HZ,aA4HY,EAAA,KAAA,EAAA,KAAA,CAAA,EA5H2B,oBA4H3B,EA5HiD,KAAA,CAAM,KA4HvD,CAAA;EACb;;;EAIhC,SAAA,KAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GA5HwC,MAAA,CAAO,MA4H/C,CAAA,IAAA,EAAA,KAAA,CAAA;EAAiB;;;EAHL,SAAA,mBAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GAlHP,MAAA,CAAO,MAkHA,CAlHO,gBAkHP,EAAA,KAAA,CAAA;;;;0EA1GH,kBACJ,MAAA,CAAO;;;;yEAQP,MAAA,CAAO;;;;;sDAQP,MAAA,CAAO,OAAO,MAAA,CAAO,OAAO,qCAAqC,KAAA,CAAM;;;;;mBAM3D,eAAe,SAAA,CAAU;;cAC3C;;;;cASY,oBAAA,SAA6B,yBAAA;cAwI7B;;yBAjEwB,SAAA,CAAU,sBACrC,wBAAwB,aAC/B,KAAA,CAAM,MACP,6BAEA,iBAAiB,gBAAgB"}
@@ -0,0 +1,97 @@
1
+ import { DocumentManagerConfigTag, DocumentManagerTag, layer } from "./DocumentManager.mjs";
2
+ import { PresenceManagerTag, layer as layer$1 } from "./PresenceManager.mjs";
3
+ import { Context, Duration, Effect, Layer } from "effect";
4
+
5
+ //#region src/MimicServerEngine.ts
6
+ /**
7
+ * @voidhash/mimic-effect - MimicServerEngine
8
+ *
9
+ * Core document management service for Mimic real-time collaboration.
10
+ * Handles document lifecycle, storage, presence, and transaction processing.
11
+ *
12
+ * This is the engine layer - for WebSocket routes, use MimicServer.layerHttpLayerRouter().
13
+ */
14
+ /**
15
+ * Context tag for MimicServerEngine
16
+ */
17
+ var MimicServerEngineTag = class extends Context.Tag("@voidhash/mimic-effect/MimicServerEngine")() {};
18
+ const DEFAULT_MAX_IDLE_TIME = Duration.minutes(5);
19
+ const DEFAULT_MAX_TRANSACTION_HISTORY = 1e3;
20
+ const DEFAULT_SNAPSHOT_INTERVAL = Duration.minutes(5);
21
+ const DEFAULT_SNAPSHOT_THRESHOLD = 100;
22
+ /**
23
+ * Resolve configuration with defaults
24
+ */
25
+ const resolveConfig = (config) => {
26
+ var _config$maxTransactio, _config$snapshot, _config$snapshot$tran, _config$snapshot2;
27
+ return {
28
+ schema: config.schema,
29
+ initial: config.initial,
30
+ presence: config.presence,
31
+ maxIdleTime: config.maxIdleTime ? Duration.decode(config.maxIdleTime) : DEFAULT_MAX_IDLE_TIME,
32
+ maxTransactionHistory: (_config$maxTransactio = config.maxTransactionHistory) !== null && _config$maxTransactio !== void 0 ? _config$maxTransactio : DEFAULT_MAX_TRANSACTION_HISTORY,
33
+ snapshot: {
34
+ interval: ((_config$snapshot = config.snapshot) === null || _config$snapshot === void 0 ? void 0 : _config$snapshot.interval) ? Duration.decode(config.snapshot.interval) : DEFAULT_SNAPSHOT_INTERVAL,
35
+ transactionThreshold: (_config$snapshot$tran = (_config$snapshot2 = config.snapshot) === null || _config$snapshot2 === void 0 ? void 0 : _config$snapshot2.transactionThreshold) !== null && _config$snapshot$tran !== void 0 ? _config$snapshot$tran : DEFAULT_SNAPSHOT_THRESHOLD
36
+ }
37
+ };
38
+ };
39
+ /**
40
+ * Create a MimicServerEngine layer.
41
+ *
42
+ * This creates the core document management service. To expose it via WebSocket,
43
+ * use MimicServer.layerHttpLayerRouter().
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // 1. Create the engine
48
+ * const Engine = MimicServerEngine.make({
49
+ * schema: DocSchema,
50
+ * initial: { title: "Untitled" },
51
+ * presence: CursorPresence,
52
+ * maxIdleTime: "5 minutes",
53
+ * snapshot: { interval: "5 minutes", transactionThreshold: 100 },
54
+ * })
55
+ *
56
+ * // 2. Create the WebSocket route
57
+ * const MimicRoute = MimicServer.layerHttpLayerRouter({
58
+ * path: "/mimic",
59
+ * })
60
+ *
61
+ * // 3. Wire together
62
+ * const MimicLive = MimicRoute.pipe(
63
+ * Layer.provide(Engine),
64
+ * Layer.provide(ColdStorage.InMemory.make()),
65
+ * Layer.provide(HotStorage.InMemory.make()),
66
+ * Layer.provide(MimicAuthService.NoAuth.make()),
67
+ * )
68
+ * ```
69
+ */
70
+ const make = (config) => {
71
+ const resolvedConfig = resolveConfig(config);
72
+ const configLayer = Layer.succeed(DocumentManagerConfigTag, resolvedConfig);
73
+ const internalLayers = Layer.mergeAll(layer.pipe(Layer.provide(configLayer)), layer$1);
74
+ return Layer.scoped(MimicServerEngineTag, Effect.gen(function* () {
75
+ const documentManager = yield* DocumentManagerTag;
76
+ const presenceManager = yield* PresenceManagerTag;
77
+ return {
78
+ submit: (documentId, transaction) => documentManager.submit(documentId, transaction),
79
+ getSnapshot: (documentId) => documentManager.getSnapshot(documentId),
80
+ subscribe: (documentId) => documentManager.subscribe(documentId),
81
+ touch: (documentId) => documentManager.touch(documentId),
82
+ getPresenceSnapshot: (documentId) => presenceManager.getSnapshot(documentId),
83
+ setPresence: (documentId, connectionId, entry) => presenceManager.set(documentId, connectionId, entry),
84
+ removePresence: (documentId, connectionId) => presenceManager.remove(documentId, connectionId),
85
+ subscribePresence: (documentId) => presenceManager.subscribe(documentId),
86
+ config: resolvedConfig
87
+ };
88
+ })).pipe(Layer.provide(internalLayers));
89
+ };
90
+ const MimicServerEngine = {
91
+ Tag: MimicServerEngineTag,
92
+ make
93
+ };
94
+
95
+ //#endregion
96
+ export { MimicServerEngine, MimicServerEngineTag };
97
+ //# sourceMappingURL=MimicServerEngine.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MimicServerEngine.mjs","names":["documentManagerLayer","presenceManagerLayer"],"sources":["../src/MimicServerEngine.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect - MimicServerEngine\n *\n * Core document management service for Mimic real-time collaboration.\n * Handles document lifecycle, storage, presence, and transaction processing.\n *\n * This is the engine layer - for WebSocket routes, use MimicServer.layerHttpLayerRouter().\n */\nimport {\n Context,\n Duration,\n Effect,\n Layer,\n Scope,\n Stream,\n} from \"effect\";\nimport type { Presence, Primitive, Transaction } from \"@voidhash/mimic\";\nimport type {\n MimicServerEngineConfig,\n PresenceEntry,\n PresenceEvent,\n PresenceSnapshot,\n ResolvedConfig,\n} from \"./Types\";\nimport type * as Protocol from \"./Protocol\";\nimport { ColdStorageTag } from \"./ColdStorage\";\nimport { HotStorageTag } from \"./HotStorage\";\nimport { MimicAuthServiceTag } from \"./MimicAuthService\";\nimport {\n DocumentManagerTag,\n DocumentManagerConfigTag,\n layer as documentManagerLayer,\n type SubmitResult,\n type DocumentManagerError,\n} from \"./DocumentManager\";\nimport {\n PresenceManagerTag,\n layer as presenceManagerLayer,\n} from \"./PresenceManager\";\n\n// =============================================================================\n// MimicServerEngine Interface\n// =============================================================================\n\n/**\n * MimicServerEngine service interface.\n *\n * Provides document management operations for Mimic collaboration.\n * Use MimicServer.layerHttpLayerRouter() to create WebSocket routes.\n */\nexport interface MimicServerEngine {\n /**\n * Submit a transaction to a document.\n * Authorization is checked against the auth service.\n * May fail with DocumentManagerError if storage is unavailable.\n */\n readonly submit: (\n documentId: string,\n transaction: Transaction.Transaction\n ) => Effect.Effect<SubmitResult, DocumentManagerError>;\n\n /**\n * Get document snapshot (current state and version).\n * May fail with DocumentManagerError if storage is unavailable.\n */\n readonly getSnapshot: (\n documentId: string\n ) => Effect.Effect<{ state: unknown; version: number }, DocumentManagerError>;\n\n /**\n * Subscribe to document broadcasts (transactions).\n * Returns a stream of server messages.\n * Requires a Scope for cleanup when the subscription ends.\n * May fail with DocumentManagerError if storage is unavailable.\n */\n readonly subscribe: (\n documentId: string\n ) => Effect.Effect<Stream.Stream<Protocol.ServerMessage, never, never>, DocumentManagerError, Scope.Scope>;\n\n /**\n * Touch document to prevent idle garbage collection.\n */\n readonly touch: (documentId: string) => Effect.Effect<void, never>;\n\n /**\n * Get presence snapshot for a document.\n */\n readonly getPresenceSnapshot: (\n documentId: string\n ) => Effect.Effect<PresenceSnapshot, never>;\n\n /**\n * Set presence for a connection.\n */\n readonly setPresence: (\n documentId: string,\n connectionId: string,\n entry: PresenceEntry\n ) => Effect.Effect<void, never>;\n\n /**\n * Remove presence for a connection.\n */\n readonly removePresence: (\n documentId: string,\n connectionId: string\n ) => Effect.Effect<void, never>;\n\n /**\n * Subscribe to presence events for a document.\n * Requires a Scope for cleanup when the subscription ends.\n */\n readonly subscribePresence: (\n documentId: string\n ) => Effect.Effect<Stream.Stream<PresenceEvent, never, never>, never, Scope.Scope>;\n\n /**\n * Resolved engine configuration.\n * Used by route layer to access schema, presence config, etc.\n */\n readonly config: ResolvedConfig<Primitive.AnyPrimitive>;\n}\n\n// =============================================================================\n// Context Tag\n// =============================================================================\n\n/**\n * Context tag for MimicServerEngine\n */\nexport class MimicServerEngineTag extends Context.Tag(\n \"@voidhash/mimic-effect/MimicServerEngine\"\n)<MimicServerEngineTag, MimicServerEngine>() {}\n\n// =============================================================================\n// Default Configuration\n// =============================================================================\n\nconst DEFAULT_MAX_IDLE_TIME = Duration.minutes(5);\nconst DEFAULT_MAX_TRANSACTION_HISTORY = 1000;\nconst DEFAULT_SNAPSHOT_INTERVAL = Duration.minutes(5);\nconst DEFAULT_SNAPSHOT_THRESHOLD = 100;\n\n/**\n * Resolve configuration with defaults\n */\nconst resolveConfig = <TSchema extends Primitive.AnyPrimitive>(\n config: MimicServerEngineConfig<TSchema>\n): ResolvedConfig<TSchema> => ({\n schema: config.schema,\n initial: config.initial,\n presence: config.presence,\n maxIdleTime: config.maxIdleTime\n ? Duration.decode(config.maxIdleTime)\n : DEFAULT_MAX_IDLE_TIME,\n maxTransactionHistory:\n config.maxTransactionHistory ?? DEFAULT_MAX_TRANSACTION_HISTORY,\n snapshot: {\n interval: config.snapshot?.interval\n ? Duration.decode(config.snapshot.interval)\n : DEFAULT_SNAPSHOT_INTERVAL,\n transactionThreshold:\n config.snapshot?.transactionThreshold ?? DEFAULT_SNAPSHOT_THRESHOLD,\n },\n});\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a MimicServerEngine layer.\n *\n * This creates the core document management service. To expose it via WebSocket,\n * use MimicServer.layerHttpLayerRouter().\n *\n * @example\n * ```typescript\n * // 1. Create the engine\n * const Engine = MimicServerEngine.make({\n * schema: DocSchema,\n * initial: { title: \"Untitled\" },\n * presence: CursorPresence,\n * maxIdleTime: \"5 minutes\",\n * snapshot: { interval: \"5 minutes\", transactionThreshold: 100 },\n * })\n *\n * // 2. Create the WebSocket route\n * const MimicRoute = MimicServer.layerHttpLayerRouter({\n * path: \"/mimic\",\n * })\n *\n * // 3. Wire together\n * const MimicLive = MimicRoute.pipe(\n * Layer.provide(Engine),\n * Layer.provide(ColdStorage.InMemory.make()),\n * Layer.provide(HotStorage.InMemory.make()),\n * Layer.provide(MimicAuthService.NoAuth.make()),\n * )\n * ```\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n config: MimicServerEngineConfig<TSchema>\n): Layer.Layer<\n MimicServerEngineTag,\n never,\n ColdStorageTag | HotStorageTag | MimicAuthServiceTag\n> => {\n const resolvedConfig = resolveConfig(config);\n\n // Create config layer for DocumentManager\n const configLayer = Layer.succeed(\n DocumentManagerConfigTag,\n resolvedConfig as ResolvedConfig<Primitive.AnyPrimitive>\n );\n\n // Create internal layers\n const internalLayers = Layer.mergeAll(\n documentManagerLayer.pipe(Layer.provide(configLayer)),\n presenceManagerLayer\n );\n\n return Layer.scoped(\n MimicServerEngineTag,\n Effect.gen(function* () {\n const documentManager = yield* DocumentManagerTag;\n const presenceManager = yield* PresenceManagerTag;\n\n const engine: MimicServerEngine = {\n submit: (documentId, transaction) =>\n documentManager.submit(documentId, transaction),\n\n getSnapshot: (documentId) => documentManager.getSnapshot(documentId),\n\n subscribe: (documentId) =>\n documentManager.subscribe(documentId) as Effect.Effect<\n Stream.Stream<Protocol.ServerMessage, never, never>,\n never\n >,\n\n touch: (documentId) => documentManager.touch(documentId),\n\n getPresenceSnapshot: (documentId) =>\n presenceManager.getSnapshot(documentId),\n\n setPresence: (documentId, connectionId, entry) =>\n presenceManager.set(documentId, connectionId, entry),\n\n removePresence: (documentId, connectionId) =>\n presenceManager.remove(documentId, connectionId),\n\n subscribePresence: (documentId) =>\n presenceManager.subscribe(documentId),\n\n config: resolvedConfig as ResolvedConfig<Primitive.AnyPrimitive>,\n };\n\n return engine;\n })\n ).pipe(Layer.provide(internalLayers));\n};\n\n// =============================================================================\n// Re-export namespace\n// =============================================================================\n\nexport const MimicServerEngine = {\n Tag: MimicServerEngineTag,\n make,\n};\n\n// =============================================================================\n// Re-export SubmitResult type\n// =============================================================================\n\nexport type { SubmitResult };\n"],"mappings":";;;;;;;;;;;;;;;;AAkIA,IAAa,uBAAb,cAA0C,QAAQ,IAChD,2CACD,EAA2C,CAAC;AAM7C,MAAM,wBAAwB,SAAS,QAAQ,EAAE;AACjD,MAAM,kCAAkC;AACxC,MAAM,4BAA4B,SAAS,QAAQ,EAAE;AACrD,MAAM,6BAA6B;;;;AAKnC,MAAM,iBACJ,WAC4B;;QAAC;EAC7B,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,UAAU,OAAO;EACjB,aAAa,OAAO,cAChB,SAAS,OAAO,OAAO,YAAY,GACnC;EACJ,gDACE,OAAO,8FAAyB;EAClC,UAAU;GACR,+BAAU,OAAO,8EAAU,YACvB,SAAS,OAAO,OAAO,SAAS,SAAS,GACzC;GACJ,oEACE,OAAO,gFAAU,6FAAwB;GAC5C;EACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCD,MAAa,QACX,WAKG;CACH,MAAM,iBAAiB,cAAc,OAAO;CAG5C,MAAM,cAAc,MAAM,QACxB,0BACA,eACD;CAGD,MAAM,iBAAiB,MAAM,SAC3BA,MAAqB,KAAK,MAAM,QAAQ,YAAY,CAAC,EACrDC,QACD;AAED,QAAO,MAAM,OACX,sBACA,OAAO,IAAI,aAAa;EACtB,MAAM,kBAAkB,OAAO;EAC/B,MAAM,kBAAkB,OAAO;AA+B/B,SA7BkC;GAChC,SAAS,YAAY,gBACnB,gBAAgB,OAAO,YAAY,YAAY;GAEjD,cAAc,eAAe,gBAAgB,YAAY,WAAW;GAEpE,YAAY,eACV,gBAAgB,UAAU,WAAW;GAKvC,QAAQ,eAAe,gBAAgB,MAAM,WAAW;GAExD,sBAAsB,eACpB,gBAAgB,YAAY,WAAW;GAEzC,cAAc,YAAY,cAAc,UACtC,gBAAgB,IAAI,YAAY,cAAc,MAAM;GAEtD,iBAAiB,YAAY,iBAC3B,gBAAgB,OAAO,YAAY,aAAa;GAElD,oBAAoB,eAClB,gBAAgB,UAAU,WAAW;GAEvC,QAAQ;GACT;GAGD,CACH,CAAC,KAAK,MAAM,QAAQ,eAAe,CAAC;;AAOvC,MAAa,oBAAoB;CAC/B,KAAK;CACL;CACD"}
@@ -1,108 +1,92 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
- let effect_Effect = require("effect/Effect");
3
- effect_Effect = require_rolldown_runtime.__toESM(effect_Effect);
4
- let effect_Layer = require("effect/Layer");
5
- effect_Layer = require_rolldown_runtime.__toESM(effect_Layer);
6
- let effect_PubSub = require("effect/PubSub");
7
- effect_PubSub = require_rolldown_runtime.__toESM(effect_PubSub);
8
- let effect_Ref = require("effect/Ref");
9
- effect_Ref = require_rolldown_runtime.__toESM(effect_Ref);
10
- let effect_HashMap = require("effect/HashMap");
11
- effect_HashMap = require_rolldown_runtime.__toESM(effect_HashMap);
12
- let effect_Context = require("effect/Context");
13
- effect_Context = require_rolldown_runtime.__toESM(effect_Context);
14
- let effect_Stream = require("effect/Stream");
15
- effect_Stream = require_rolldown_runtime.__toESM(effect_Stream);
1
+ const require_Metrics = require('./Metrics.cjs');
2
+ const require_objectSpread2 = require('./_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.cjs');
3
+ let effect = require("effect");
16
4
 
17
5
  //#region src/PresenceManager.ts
18
6
  /**
19
- * @since 0.0.1
20
- * Presence manager for ephemeral per-connection state.
21
- * Handles in-memory storage and broadcasting of presence updates.
7
+ * @voidhash/mimic-effect - PresenceManager
8
+ *
9
+ * Internal service for managing presence state per document.
22
10
  */
23
- var PresenceManager_exports = /* @__PURE__ */ require_rolldown_runtime.__export({
24
- PresenceManagerTag: () => PresenceManagerTag,
25
- layer: () => layer,
26
- layerDefault: () => layerDefault
27
- });
28
11
  /**
29
- * Context tag for PresenceManager.
12
+ * Context tag for PresenceManager service
30
13
  */
31
- var PresenceManagerTag = class extends effect_Context.Tag("@voidhash/mimic-server-effect/PresenceManager")() {};
14
+ var PresenceManagerTag = class extends effect.Context.Tag("@voidhash/mimic-effect/PresenceManager")() {};
32
15
  /**
33
- * Create the PresenceManager service.
16
+ * Create the PresenceManager layer.
34
17
  */
35
- const makePresenceManager = effect_Effect.gen(function* () {
36
- const documents = yield* effect_Ref.make(effect_HashMap.empty());
37
- const getOrCreateDocument = (documentId) => effect_Effect.gen(function* () {
38
- const current = yield* effect_Ref.get(documents);
39
- const existing = effect_HashMap.get(current, documentId);
18
+ const layer = effect.Layer.effect(PresenceManagerTag, effect.Effect.gen(function* () {
19
+ const store = yield* effect.Ref.make(effect.HashMap.empty());
20
+ /**
21
+ * Get or create presence state for a document
22
+ */
23
+ const getOrCreateDocumentState = (documentId) => effect.Effect.gen(function* () {
24
+ const current = yield* effect.Ref.get(store);
25
+ const existing = effect.HashMap.get(current, documentId);
40
26
  if (existing._tag === "Some") return existing.value;
41
- const docPresence = {
42
- entries: yield* effect_Ref.make(effect_HashMap.empty()),
43
- pubsub: yield* effect_PubSub.unbounded()
27
+ const pubsub = yield* effect.PubSub.unbounded();
28
+ const state = {
29
+ presences: effect.HashMap.empty(),
30
+ pubsub
44
31
  };
45
- yield* effect_Ref.update(documents, (map) => effect_HashMap.set(map, documentId, docPresence));
46
- return docPresence;
47
- });
48
- const getSnapshot = (documentId) => effect_Effect.gen(function* () {
49
- const docPresence = yield* getOrCreateDocument(documentId);
50
- const entriesMap = yield* effect_Ref.get(docPresence.entries);
51
- const presences = {};
52
- for (const [id, entry] of entriesMap) presences[id] = entry;
53
- return { presences };
54
- });
55
- const set = (documentId, connectionId, entry) => effect_Effect.gen(function* () {
56
- const docPresence = yield* getOrCreateDocument(documentId);
57
- yield* effect_Ref.update(docPresence.entries, (map) => effect_HashMap.set(map, connectionId, entry));
58
- yield* effect_PubSub.publish(docPresence.pubsub, {
59
- type: "presence_update",
60
- id: connectionId,
61
- data: entry.data,
62
- userId: entry.userId
63
- });
64
- });
65
- const remove = (documentId, connectionId) => effect_Effect.gen(function* () {
66
- const current = yield* effect_Ref.get(documents);
67
- const existing = effect_HashMap.get(current, documentId);
68
- if (existing._tag === "None") return;
69
- const docPresence = existing.value;
70
- const entries = yield* effect_Ref.get(docPresence.entries);
71
- if (!effect_HashMap.has(entries, connectionId)) return;
72
- yield* effect_Ref.update(docPresence.entries, (map) => effect_HashMap.remove(map, connectionId));
73
- yield* effect_PubSub.publish(docPresence.pubsub, {
74
- type: "presence_remove",
75
- id: connectionId
76
- });
77
- });
78
- const subscribe = (documentId) => effect_Effect.gen(function* () {
79
- const docPresence = yield* getOrCreateDocument(documentId);
80
- const queue = yield* effect_PubSub.subscribe(docPresence.pubsub);
81
- return effect_Stream.fromQueue(queue);
32
+ yield* effect.Ref.update(store, (map) => effect.HashMap.set(map, documentId, state));
33
+ return state;
82
34
  });
83
35
  return {
84
- getSnapshot,
85
- set,
86
- remove,
87
- subscribe
36
+ getSnapshot: (documentId) => effect.Effect.gen(function* () {
37
+ const current = yield* effect.Ref.get(store);
38
+ const existing = effect.HashMap.get(current, documentId);
39
+ if (existing._tag === "None") return { presences: {} };
40
+ const presences = {};
41
+ for (const [id, entry] of existing.value.presences) presences[id] = entry;
42
+ return { presences };
43
+ }),
44
+ set: (documentId, connectionId, entry) => effect.Effect.gen(function* () {
45
+ const state = yield* getOrCreateDocumentState(documentId);
46
+ yield* effect.Ref.update(store, (map) => {
47
+ const existing = effect.HashMap.get(map, documentId);
48
+ if (existing._tag === "None") return map;
49
+ return effect.HashMap.set(map, documentId, require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, existing.value), {}, { presences: effect.HashMap.set(existing.value.presences, connectionId, entry) }));
50
+ });
51
+ yield* effect.Metric.increment(require_Metrics.presenceUpdates);
52
+ yield* effect.Metric.incrementBy(require_Metrics.presenceActive, 1);
53
+ const event = {
54
+ type: "presence_update",
55
+ id: connectionId,
56
+ data: entry.data,
57
+ userId: entry.userId
58
+ };
59
+ yield* effect.PubSub.publish(state.pubsub, event);
60
+ }),
61
+ remove: (documentId, connectionId) => effect.Effect.gen(function* () {
62
+ const current = yield* effect.Ref.get(store);
63
+ const existing = effect.HashMap.get(current, documentId);
64
+ if (existing._tag === "None") return;
65
+ if (!effect.HashMap.has(existing.value.presences, connectionId)) return;
66
+ yield* effect.Ref.update(store, (map) => {
67
+ const docState = effect.HashMap.get(map, documentId);
68
+ if (docState._tag === "None") return map;
69
+ return effect.HashMap.set(map, documentId, require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, docState.value), {}, { presences: effect.HashMap.remove(docState.value.presences, connectionId) }));
70
+ });
71
+ yield* effect.Metric.incrementBy(require_Metrics.presenceActive, -1);
72
+ const event = {
73
+ type: "presence_remove",
74
+ id: connectionId
75
+ };
76
+ yield* effect.PubSub.publish(existing.value.pubsub, event);
77
+ }),
78
+ subscribe: (documentId) => effect.Effect.gen(function* () {
79
+ const state = yield* getOrCreateDocumentState(documentId);
80
+ return effect.Stream.fromPubSub(state.pubsub);
81
+ })
88
82
  };
89
- });
90
- /**
91
- * Layer that provides PresenceManager.
92
- */
93
- const layer = effect_Layer.effect(PresenceManagerTag, makePresenceManager);
94
- /**
95
- * Default layer that provides PresenceManager.
96
- * Uses the default priority for layer composition.
97
- */
98
- const layerDefault = effect_Layer.effectDiscard(effect_Effect.succeed(void 0)).pipe(effect_Layer.provideMerge(layer));
83
+ }));
84
+ const PresenceManager = {
85
+ Tag: PresenceManagerTag,
86
+ layer
87
+ };
99
88
 
100
89
  //#endregion
90
+ exports.PresenceManager = PresenceManager;
101
91
  exports.PresenceManagerTag = PresenceManagerTag;
102
- Object.defineProperty(exports, 'PresenceManager_exports', {
103
- enumerable: true,
104
- get: function () {
105
- return PresenceManager_exports;
106
- }
107
- });
108
92
  exports.layer = layer;
@@ -1,91 +1,42 @@
1
- import * as Effect from "effect/Effect";
2
- import * as Layer from "effect/Layer";
3
- import * as Context from "effect/Context";
4
- import * as Scope from "effect/Scope";
5
- import * as Stream from "effect/Stream";
1
+ import { PresenceEntry, PresenceEvent, PresenceSnapshot } from "./Types.cjs";
2
+ import { Context, Effect, Layer, Scope, Stream } from "effect";
6
3
 
7
4
  //#region src/PresenceManager.d.ts
8
- declare namespace PresenceManager_d_exports {
9
- export { PresenceEntry, PresenceEvent, PresenceManager, PresenceManagerTag, PresenceRemoveEvent, PresenceSnapshot, PresenceUpdateEvent, layer, layerDefault };
10
- }
11
- /**
12
- * A presence entry stored in the manager.
13
- */
14
- interface PresenceEntry {
15
- /** The presence data */
16
- readonly data: unknown;
17
- /** Optional user ID from authentication */
18
- readonly userId?: string;
19
- }
20
- /**
21
- * Event emitted when a presence is updated.
22
- */
23
- interface PresenceUpdateEvent {
24
- readonly type: "presence_update";
25
- /** The connection ID of the user who updated */
26
- readonly id: string;
27
- /** The presence data */
28
- readonly data: unknown;
29
- /** Optional user ID from authentication */
30
- readonly userId?: string;
31
- }
32
- /**
33
- * Event emitted when a presence is removed (user disconnected).
34
- */
35
- interface PresenceRemoveEvent {
36
- readonly type: "presence_remove";
37
- /** The connection ID of the user who disconnected */
38
- readonly id: string;
39
- }
40
- /**
41
- * Union of all presence events.
42
- */
43
- type PresenceEvent = PresenceUpdateEvent | PresenceRemoveEvent;
44
- /**
45
- * A snapshot of all presence entries for a document.
46
- */
47
- interface PresenceSnapshot {
48
- /** Map of connectionId to presence entry */
49
- readonly presences: Record<string, PresenceEntry>;
50
- }
5
+
51
6
  /**
52
- * Service interface for the PresenceManager.
7
+ * Internal service for managing presence state per document.
8
+ *
9
+ * Presence is ephemeral state associated with connections, not persisted.
10
+ * Each document has its own set of presences, keyed by connectionId.
53
11
  */
54
12
  interface PresenceManager {
55
13
  /**
56
- * Get a snapshot of all presences for a document.
14
+ * Get snapshot of all presences for a document.
57
15
  */
58
16
  readonly getSnapshot: (documentId: string) => Effect.Effect<PresenceSnapshot>;
59
17
  /**
60
18
  * Set/update presence for a connection.
61
- * Broadcasts the update to all subscribers.
62
19
  */
63
20
  readonly set: (documentId: string, connectionId: string, entry: PresenceEntry) => Effect.Effect<void>;
64
21
  /**
65
- * Remove presence for a connection (e.g., on disconnect).
66
- * Broadcasts the removal to all subscribers.
22
+ * Remove presence for a connection (on disconnect).
67
23
  */
68
24
  readonly remove: (documentId: string, connectionId: string) => Effect.Effect<void>;
69
25
  /**
70
26
  * Subscribe to presence events for a document.
71
- * Returns a Stream of presence events.
27
+ * Returns a stream of presence update/remove events.
72
28
  */
73
29
  readonly subscribe: (documentId: string) => Effect.Effect<Stream.Stream<PresenceEvent>, never, Scope.Scope>;
74
30
  }
75
- declare const PresenceManagerTag_base: Context.TagClass<PresenceManagerTag, "@voidhash/mimic-server-effect/PresenceManager", PresenceManager>;
31
+ declare const PresenceManagerTag_base: Context.TagClass<PresenceManagerTag, "@voidhash/mimic-effect/PresenceManager", PresenceManager>;
76
32
  /**
77
- * Context tag for PresenceManager.
33
+ * Context tag for PresenceManager service
78
34
  */
79
35
  declare class PresenceManagerTag extends PresenceManagerTag_base {}
80
- /**
81
- * Layer that provides PresenceManager.
82
- */
83
- declare const layer: Layer.Layer<PresenceManagerTag>;
84
- /**
85
- * Default layer that provides PresenceManager.
86
- * Uses the default priority for layer composition.
87
- */
88
- declare const layerDefault: Layer.Layer<PresenceManagerTag>;
36
+ declare const PresenceManager: {
37
+ Tag: typeof PresenceManagerTag;
38
+ layer: Layer.Layer<PresenceManagerTag, never, never>;
39
+ };
89
40
  //#endregion
90
- export { PresenceManagerTag, PresenceManager_d_exports };
41
+ export { PresenceManager, PresenceManagerTag };
91
42
  //# sourceMappingURL=PresenceManager.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PresenceManager.d.cts","names":[],"sources":["../src/PresenceManager.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;UAsBiB,aAAA;;;;;;AAAjB;AAcA;AAaA;AASY,UAtBK,mBAAA,CAsBW;EASX,SAAA,IAAA,EAAA,iBAEoB;EAwBpB;EAMI,SAAA,EAAA,EAAA,MAAA;EAAd;EASI,SAAA,IAAA,EAAA,OAAA;EACJ;EASA,SAAO,MAAA,CAAA,EAAA,MAAA;;;;;AAQM,UA7EH,mBAAA,CA6EG;EAKnB,SAAA,IAAA,EAAA,iBAAA;;;;;AAKD;AAoJA;AASa,KA3OD,aAAA,GAAgB,mBA2OW,GA3OW,mBA2OZ;;;;UAlOrB,gBAAA;;sBAEK,eAAe;;;;;UAwBpB,eAAA;;;;gDAMV,MAAA,CAAO,OAAO;;;;;kEASV,kBACJ,MAAA,CAAO;;;;;iEASP,MAAA,CAAO;;;;;8CAQP,MAAA,CAAO,OACV,MAAA,CAAO,OAAO,uBAEd,KAAA,CAAM;;cAET;;;;cAKY,kBAAA,SAA2B,uBAAA;;;;cAoJ3B,OAAO,KAAA,CAAM,MAAM;;;;;cASnB,cAAc,KAAA,CAAM,MAAM"}
1
+ {"version":3,"file":"PresenceManager.d.cts","names":[],"sources":["../src/PresenceManager.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AAgEO,UA/BU,eAAA,CA+BH;EAAM;AACnB;;gDA1BM,MAAA,CAAO,OAAO;;;AAmCrB;EAoJa,SAAA,GAAA,EAAA,CAAA,UAGZ,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,KAAA,EAlLU,aAkLV,EAAA,GAjLM,MAAA,CAAO,MAiLb,CAAA,IAAA,CAAA;;;;iEAzKM,MAAA,CAAO;;;;;8CAQP,MAAA,CAAO,OAAO,MAAA,CAAO,OAAO,uBAAuB,KAAA,CAAM;;cAC/D;;;;cASY,kBAAA,SAA2B,uBAAA;cAoJ3B"}
@@ -1,91 +1,42 @@
1
- import * as Effect from "effect/Effect";
2
- import * as Layer from "effect/Layer";
3
- import * as Context from "effect/Context";
4
- import * as Stream from "effect/Stream";
5
- import * as Scope from "effect/Scope";
1
+ import { PresenceEntry, PresenceEvent, PresenceSnapshot } from "./Types.mjs";
2
+ import { Context, Effect, Layer, Scope, Stream } from "effect";
6
3
 
7
4
  //#region src/PresenceManager.d.ts
8
- declare namespace PresenceManager_d_exports {
9
- export { PresenceEntry, PresenceEvent, PresenceManager, PresenceManagerTag, PresenceRemoveEvent, PresenceSnapshot, PresenceUpdateEvent, layer, layerDefault };
10
- }
11
- /**
12
- * A presence entry stored in the manager.
13
- */
14
- interface PresenceEntry {
15
- /** The presence data */
16
- readonly data: unknown;
17
- /** Optional user ID from authentication */
18
- readonly userId?: string;
19
- }
20
- /**
21
- * Event emitted when a presence is updated.
22
- */
23
- interface PresenceUpdateEvent {
24
- readonly type: "presence_update";
25
- /** The connection ID of the user who updated */
26
- readonly id: string;
27
- /** The presence data */
28
- readonly data: unknown;
29
- /** Optional user ID from authentication */
30
- readonly userId?: string;
31
- }
32
- /**
33
- * Event emitted when a presence is removed (user disconnected).
34
- */
35
- interface PresenceRemoveEvent {
36
- readonly type: "presence_remove";
37
- /** The connection ID of the user who disconnected */
38
- readonly id: string;
39
- }
40
- /**
41
- * Union of all presence events.
42
- */
43
- type PresenceEvent = PresenceUpdateEvent | PresenceRemoveEvent;
44
- /**
45
- * A snapshot of all presence entries for a document.
46
- */
47
- interface PresenceSnapshot {
48
- /** Map of connectionId to presence entry */
49
- readonly presences: Record<string, PresenceEntry>;
50
- }
5
+
51
6
  /**
52
- * Service interface for the PresenceManager.
7
+ * Internal service for managing presence state per document.
8
+ *
9
+ * Presence is ephemeral state associated with connections, not persisted.
10
+ * Each document has its own set of presences, keyed by connectionId.
53
11
  */
54
12
  interface PresenceManager {
55
13
  /**
56
- * Get a snapshot of all presences for a document.
14
+ * Get snapshot of all presences for a document.
57
15
  */
58
16
  readonly getSnapshot: (documentId: string) => Effect.Effect<PresenceSnapshot>;
59
17
  /**
60
18
  * Set/update presence for a connection.
61
- * Broadcasts the update to all subscribers.
62
19
  */
63
20
  readonly set: (documentId: string, connectionId: string, entry: PresenceEntry) => Effect.Effect<void>;
64
21
  /**
65
- * Remove presence for a connection (e.g., on disconnect).
66
- * Broadcasts the removal to all subscribers.
22
+ * Remove presence for a connection (on disconnect).
67
23
  */
68
24
  readonly remove: (documentId: string, connectionId: string) => Effect.Effect<void>;
69
25
  /**
70
26
  * Subscribe to presence events for a document.
71
- * Returns a Stream of presence events.
27
+ * Returns a stream of presence update/remove events.
72
28
  */
73
29
  readonly subscribe: (documentId: string) => Effect.Effect<Stream.Stream<PresenceEvent>, never, Scope.Scope>;
74
30
  }
75
- declare const PresenceManagerTag_base: Context.TagClass<PresenceManagerTag, "@voidhash/mimic-server-effect/PresenceManager", PresenceManager>;
31
+ declare const PresenceManagerTag_base: Context.TagClass<PresenceManagerTag, "@voidhash/mimic-effect/PresenceManager", PresenceManager>;
76
32
  /**
77
- * Context tag for PresenceManager.
33
+ * Context tag for PresenceManager service
78
34
  */
79
35
  declare class PresenceManagerTag extends PresenceManagerTag_base {}
80
- /**
81
- * Layer that provides PresenceManager.
82
- */
83
- declare const layer: Layer.Layer<PresenceManagerTag>;
84
- /**
85
- * Default layer that provides PresenceManager.
86
- * Uses the default priority for layer composition.
87
- */
88
- declare const layerDefault: Layer.Layer<PresenceManagerTag>;
36
+ declare const PresenceManager: {
37
+ Tag: typeof PresenceManagerTag;
38
+ layer: Layer.Layer<PresenceManagerTag, never, never>;
39
+ };
89
40
  //#endregion
90
- export { PresenceManagerTag, PresenceManager_d_exports };
41
+ export { PresenceManager, PresenceManagerTag };
91
42
  //# sourceMappingURL=PresenceManager.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PresenceManager.d.mts","names":[],"sources":["../src/PresenceManager.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;UAsBiB,aAAA;;;;;;AAAjB;AAcA;AAaA;AASY,UAtBK,mBAAA,CAsBW;EASX,SAAA,IAAA,EAAA,iBAEoB;EAwBpB;EAMI,SAAA,EAAA,EAAA,MAAA;EAAd;EASI,SAAA,IAAA,EAAA,OAAA;EACJ;EASA,SAAO,MAAA,CAAA,EAAA,MAAA;;;;;AAQM,UA7EH,mBAAA,CA6EG;EAKnB,SAAA,IAAA,EAAA,iBAAA;;;;;AAKD;AAoJA;AASa,KA3OD,aAAA,GAAgB,mBA2OW,GA3OW,mBA2OZ;;;;UAlOrB,gBAAA;;sBAEK,eAAe;;;;;UAwBpB,eAAA;;;;gDAMV,MAAA,CAAO,OAAO;;;;;kEASV,kBACJ,MAAA,CAAO;;;;;iEASP,MAAA,CAAO;;;;;8CAQP,MAAA,CAAO,OACV,MAAA,CAAO,OAAO,uBAEd,KAAA,CAAM;;cAET;;;;cAKY,kBAAA,SAA2B,uBAAA;;;;cAoJ3B,OAAO,KAAA,CAAM,MAAM;;;;;cASnB,cAAc,KAAA,CAAM,MAAM"}
1
+ {"version":3,"file":"PresenceManager.d.mts","names":[],"sources":["../src/PresenceManager.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AAgEO,UA/BU,eAAA,CA+BH;EAAM;AACnB;;gDA1BM,MAAA,CAAO,OAAO;;;AAmCrB;EAoJa,SAAA,GAAA,EAAA,CAAA,UAGZ,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,KAAA,EAlLU,aAkLV,EAAA,GAjLM,MAAA,CAAO,MAiLb,CAAA,IAAA,CAAA;;;;iEAzKM,MAAA,CAAO;;;;;8CAQP,MAAA,CAAO,OAAO,MAAA,CAAO,OAAO,uBAAuB,KAAA,CAAM;;cAC/D;;;;cASY,kBAAA,SAA2B,uBAAA;cAoJ3B"}