@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,286 @@
1
+ /**
2
+ * @voidhash/mimic-effect/testing - FailingStorage
3
+ *
4
+ * Mock storage implementations that simulate failures for testing error handling.
5
+ * Use these to verify that your application correctly handles storage unavailability.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { FailingStorage } from "@voidhash/mimic-effect/testing";
10
+ *
11
+ * // Create a ColdStorage that fails on load
12
+ * const failingCold = FailingStorage.makeColdStorage({ failLoad: true });
13
+ *
14
+ * // Create a HotStorage that fails after 3 successful appends
15
+ * const failingHot = FailingStorage.makeHotStorage({ failAfterN: 3, failAppend: true });
16
+ * ```
17
+ */
18
+ import { Effect, Layer, Ref, HashMap } from "effect";
19
+ import { ColdStorageTag, type ColdStorage } from "../ColdStorage";
20
+ import { HotStorageTag, type HotStorage } from "../HotStorage";
21
+ import { ColdStorageError, HotStorageError } from "../Errors";
22
+ import type { StoredDocument, WalEntry } from "../Types";
23
+
24
+ // =============================================================================
25
+ // Configuration Types
26
+ // =============================================================================
27
+
28
+ /**
29
+ * Configuration for failing ColdStorage
30
+ */
31
+ export interface FailingColdStorageConfig {
32
+ /** Fail load operations */
33
+ readonly failLoad?: boolean;
34
+ /** Fail save operations */
35
+ readonly failSave?: boolean;
36
+ /** Fail delete operations */
37
+ readonly failDelete?: boolean;
38
+ /** Fail after N successful operations (total across all operation types) */
39
+ readonly failAfterN?: number;
40
+ /** Custom error message */
41
+ readonly errorMessage?: string;
42
+ }
43
+
44
+ /**
45
+ * Configuration for failing HotStorage
46
+ */
47
+ export interface FailingHotStorageConfig {
48
+ /** Fail append operations */
49
+ readonly failAppend?: boolean;
50
+ /** Fail getEntries operations */
51
+ readonly failGetEntries?: boolean;
52
+ /** Fail truncate operations */
53
+ readonly failTruncate?: boolean;
54
+ /** Fail after N successful operations (total across all operation types) */
55
+ readonly failAfterN?: number;
56
+ /** Custom error message */
57
+ readonly errorMessage?: string;
58
+ }
59
+
60
+ // =============================================================================
61
+ // Failing ColdStorage
62
+ // =============================================================================
63
+
64
+ /**
65
+ * Create a ColdStorage layer that simulates failures.
66
+ * Wraps an in-memory storage and fails according to configuration.
67
+ */
68
+ export const makeColdStorage = (
69
+ config: FailingColdStorageConfig = {}
70
+ ): Layer.Layer<ColdStorageTag> =>
71
+ Layer.effect(
72
+ ColdStorageTag,
73
+ Effect.gen(function* () {
74
+ const store = yield* Ref.make(HashMap.empty<string, StoredDocument>());
75
+ const operationCount = yield* Ref.make(0);
76
+
77
+ const errorMessage = config.errorMessage ?? "Simulated storage failure";
78
+
79
+ const shouldFail = (operation: "load" | "save" | "delete") =>
80
+ Effect.gen(function* () {
81
+ // Check if this specific operation should fail
82
+ const opFails =
83
+ (operation === "load" && config.failLoad) ||
84
+ (operation === "save" && config.failSave) ||
85
+ (operation === "delete" && config.failDelete);
86
+
87
+ // If failAfterN is set, count operations first
88
+ if (config.failAfterN !== undefined) {
89
+ const count = yield* Ref.get(operationCount);
90
+ yield* Ref.update(operationCount, (n) => n + 1);
91
+
92
+ // Only start failing after N successful operations
93
+ if (count < config.failAfterN) {
94
+ return false;
95
+ }
96
+ // After N operations, fail if the specific op flag is set
97
+ return opFails;
98
+ }
99
+
100
+ // No failAfterN - fail immediately if op flag is set
101
+ return opFails;
102
+ });
103
+
104
+ const storage: ColdStorage = {
105
+ load: (documentId) =>
106
+ Effect.gen(function* () {
107
+ const fail = yield* shouldFail("load");
108
+ if (fail) {
109
+ return yield* Effect.fail(
110
+ new ColdStorageError({
111
+ documentId,
112
+ operation: "load",
113
+ cause: new Error(errorMessage),
114
+ })
115
+ );
116
+ }
117
+
118
+ const current = yield* Ref.get(store);
119
+ const doc = HashMap.get(current, documentId);
120
+ return doc._tag === "Some" ? doc.value : undefined;
121
+ }),
122
+
123
+ save: (documentId, document) =>
124
+ Effect.gen(function* () {
125
+ const fail = yield* shouldFail("save");
126
+ if (fail) {
127
+ return yield* Effect.fail(
128
+ new ColdStorageError({
129
+ documentId,
130
+ operation: "save",
131
+ cause: new Error(errorMessage),
132
+ })
133
+ );
134
+ }
135
+
136
+ yield* Ref.update(store, (map) =>
137
+ HashMap.set(map, documentId, document)
138
+ );
139
+ }),
140
+
141
+ delete: (documentId) =>
142
+ Effect.gen(function* () {
143
+ const fail = yield* shouldFail("delete");
144
+ if (fail) {
145
+ return yield* Effect.fail(
146
+ new ColdStorageError({
147
+ documentId,
148
+ operation: "delete",
149
+ cause: new Error(errorMessage),
150
+ })
151
+ );
152
+ }
153
+
154
+ yield* Ref.update(store, (map) => HashMap.remove(map, documentId));
155
+ }),
156
+ };
157
+
158
+ return storage;
159
+ })
160
+ );
161
+
162
+ // =============================================================================
163
+ // Failing HotStorage
164
+ // =============================================================================
165
+
166
+ /**
167
+ * Create a HotStorage layer that simulates failures.
168
+ * Wraps an in-memory storage and fails according to configuration.
169
+ */
170
+ export const makeHotStorage = (
171
+ config: FailingHotStorageConfig = {}
172
+ ): Layer.Layer<HotStorageTag> =>
173
+ Layer.effect(
174
+ HotStorageTag,
175
+ Effect.gen(function* () {
176
+ const store = yield* Ref.make(HashMap.empty<string, WalEntry[]>());
177
+ const operationCount = yield* Ref.make(0);
178
+
179
+ const errorMessage = config.errorMessage ?? "Simulated storage failure";
180
+
181
+ const shouldFail = (operation: "append" | "getEntries" | "truncate") =>
182
+ Effect.gen(function* () {
183
+ // Check if this specific operation should fail
184
+ const opFails =
185
+ (operation === "append" && config.failAppend) ||
186
+ (operation === "getEntries" && config.failGetEntries) ||
187
+ (operation === "truncate" && config.failTruncate);
188
+
189
+ // If failAfterN is set, count operations first
190
+ if (config.failAfterN !== undefined) {
191
+ const count = yield* Ref.get(operationCount);
192
+ yield* Ref.update(operationCount, (n) => n + 1);
193
+
194
+ // Only start failing after N successful operations
195
+ if (count < config.failAfterN) {
196
+ return false;
197
+ }
198
+ // After N operations, fail if the specific op flag is set
199
+ return opFails;
200
+ }
201
+
202
+ // No failAfterN - fail immediately if op flag is set
203
+ return opFails;
204
+ });
205
+
206
+ const storage: HotStorage = {
207
+ append: (documentId, entry) =>
208
+ Effect.gen(function* () {
209
+ const fail = yield* shouldFail("append");
210
+ if (fail) {
211
+ return yield* Effect.fail(
212
+ new HotStorageError({
213
+ documentId,
214
+ operation: "append",
215
+ cause: new Error(errorMessage),
216
+ })
217
+ );
218
+ }
219
+
220
+ yield* Ref.update(store, (map) => {
221
+ const current = HashMap.get(map, documentId);
222
+ const entries = current._tag === "Some" ? current.value : [];
223
+ return HashMap.set(map, documentId, [...entries, entry]);
224
+ });
225
+ }),
226
+
227
+ getEntries: (documentId, sinceVersion) =>
228
+ Effect.gen(function* () {
229
+ const fail = yield* shouldFail("getEntries");
230
+ if (fail) {
231
+ return yield* Effect.fail(
232
+ new HotStorageError({
233
+ documentId,
234
+ operation: "getEntries",
235
+ cause: new Error(errorMessage),
236
+ })
237
+ );
238
+ }
239
+
240
+ const current = yield* Ref.get(store);
241
+ const existing = HashMap.get(current, documentId);
242
+ const entries = existing._tag === "Some" ? existing.value : [];
243
+
244
+ return entries
245
+ .filter((e) => e.version > sinceVersion)
246
+ .sort((a, b) => a.version - b.version);
247
+ }),
248
+
249
+ truncate: (documentId, upToVersion) =>
250
+ Effect.gen(function* () {
251
+ const fail = yield* shouldFail("truncate");
252
+ if (fail) {
253
+ return yield* Effect.fail(
254
+ new HotStorageError({
255
+ documentId,
256
+ operation: "truncate",
257
+ cause: new Error(errorMessage),
258
+ })
259
+ );
260
+ }
261
+
262
+ yield* Ref.update(store, (map) => {
263
+ const existing = HashMap.get(map, documentId);
264
+ if (existing._tag === "None") {
265
+ return map;
266
+ }
267
+ const filtered = existing.value.filter(
268
+ (e) => e.version > upToVersion
269
+ );
270
+ return HashMap.set(map, documentId, filtered);
271
+ });
272
+ }),
273
+ };
274
+
275
+ return storage;
276
+ })
277
+ );
278
+
279
+ // =============================================================================
280
+ // Export Namespace
281
+ // =============================================================================
282
+
283
+ export const FailingStorage = {
284
+ makeColdStorage,
285
+ makeHotStorage,
286
+ };