@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,276 @@
1
+ /**
2
+ * @voidhash/mimic-effect - MimicServerEngine
3
+ *
4
+ * Core document management service for Mimic real-time collaboration.
5
+ * Handles document lifecycle, storage, presence, and transaction processing.
6
+ *
7
+ * This is the engine layer - for WebSocket routes, use MimicServer.layerHttpLayerRouter().
8
+ */
9
+ import {
10
+ Context,
11
+ Duration,
12
+ Effect,
13
+ Layer,
14
+ Scope,
15
+ Stream,
16
+ } from "effect";
17
+ import type { Presence, Primitive, Transaction } from "@voidhash/mimic";
18
+ import type {
19
+ MimicServerEngineConfig,
20
+ PresenceEntry,
21
+ PresenceEvent,
22
+ PresenceSnapshot,
23
+ ResolvedConfig,
24
+ } from "./Types";
25
+ import type * as Protocol from "./Protocol";
26
+ import { ColdStorageTag } from "./ColdStorage";
27
+ import { HotStorageTag } from "./HotStorage";
28
+ import { MimicAuthServiceTag } from "./MimicAuthService";
29
+ import {
30
+ DocumentManagerTag,
31
+ DocumentManagerConfigTag,
32
+ layer as documentManagerLayer,
33
+ type SubmitResult,
34
+ type DocumentManagerError,
35
+ } from "./DocumentManager";
36
+ import {
37
+ PresenceManagerTag,
38
+ layer as presenceManagerLayer,
39
+ } from "./PresenceManager";
40
+
41
+ // =============================================================================
42
+ // MimicServerEngine Interface
43
+ // =============================================================================
44
+
45
+ /**
46
+ * MimicServerEngine service interface.
47
+ *
48
+ * Provides document management operations for Mimic collaboration.
49
+ * Use MimicServer.layerHttpLayerRouter() to create WebSocket routes.
50
+ */
51
+ export interface MimicServerEngine {
52
+ /**
53
+ * Submit a transaction to a document.
54
+ * Authorization is checked against the auth service.
55
+ * May fail with DocumentManagerError if storage is unavailable.
56
+ */
57
+ readonly submit: (
58
+ documentId: string,
59
+ transaction: Transaction.Transaction
60
+ ) => Effect.Effect<SubmitResult, DocumentManagerError>;
61
+
62
+ /**
63
+ * Get document snapshot (current state and version).
64
+ * May fail with DocumentManagerError if storage is unavailable.
65
+ */
66
+ readonly getSnapshot: (
67
+ documentId: string
68
+ ) => Effect.Effect<{ state: unknown; version: number }, DocumentManagerError>;
69
+
70
+ /**
71
+ * Subscribe to document broadcasts (transactions).
72
+ * Returns a stream of server messages.
73
+ * Requires a Scope for cleanup when the subscription ends.
74
+ * May fail with DocumentManagerError if storage is unavailable.
75
+ */
76
+ readonly subscribe: (
77
+ documentId: string
78
+ ) => Effect.Effect<Stream.Stream<Protocol.ServerMessage, never, never>, DocumentManagerError, Scope.Scope>;
79
+
80
+ /**
81
+ * Touch document to prevent idle garbage collection.
82
+ */
83
+ readonly touch: (documentId: string) => Effect.Effect<void, never>;
84
+
85
+ /**
86
+ * Get presence snapshot for a document.
87
+ */
88
+ readonly getPresenceSnapshot: (
89
+ documentId: string
90
+ ) => Effect.Effect<PresenceSnapshot, never>;
91
+
92
+ /**
93
+ * Set presence for a connection.
94
+ */
95
+ readonly setPresence: (
96
+ documentId: string,
97
+ connectionId: string,
98
+ entry: PresenceEntry
99
+ ) => Effect.Effect<void, never>;
100
+
101
+ /**
102
+ * Remove presence for a connection.
103
+ */
104
+ readonly removePresence: (
105
+ documentId: string,
106
+ connectionId: string
107
+ ) => Effect.Effect<void, never>;
108
+
109
+ /**
110
+ * Subscribe to presence events for a document.
111
+ * Requires a Scope for cleanup when the subscription ends.
112
+ */
113
+ readonly subscribePresence: (
114
+ documentId: string
115
+ ) => Effect.Effect<Stream.Stream<PresenceEvent, never, never>, never, Scope.Scope>;
116
+
117
+ /**
118
+ * Resolved engine configuration.
119
+ * Used by route layer to access schema, presence config, etc.
120
+ */
121
+ readonly config: ResolvedConfig<Primitive.AnyPrimitive>;
122
+ }
123
+
124
+ // =============================================================================
125
+ // Context Tag
126
+ // =============================================================================
127
+
128
+ /**
129
+ * Context tag for MimicServerEngine
130
+ */
131
+ export class MimicServerEngineTag extends Context.Tag(
132
+ "@voidhash/mimic-effect/MimicServerEngine"
133
+ )<MimicServerEngineTag, MimicServerEngine>() {}
134
+
135
+ // =============================================================================
136
+ // Default Configuration
137
+ // =============================================================================
138
+
139
+ const DEFAULT_MAX_IDLE_TIME = Duration.minutes(5);
140
+ const DEFAULT_MAX_TRANSACTION_HISTORY = 1000;
141
+ const DEFAULT_SNAPSHOT_INTERVAL = Duration.minutes(5);
142
+ const DEFAULT_SNAPSHOT_THRESHOLD = 100;
143
+
144
+ /**
145
+ * Resolve configuration with defaults
146
+ */
147
+ const resolveConfig = <TSchema extends Primitive.AnyPrimitive>(
148
+ config: MimicServerEngineConfig<TSchema>
149
+ ): ResolvedConfig<TSchema> => ({
150
+ schema: config.schema,
151
+ initial: config.initial,
152
+ presence: config.presence,
153
+ maxIdleTime: config.maxIdleTime
154
+ ? Duration.decode(config.maxIdleTime)
155
+ : DEFAULT_MAX_IDLE_TIME,
156
+ maxTransactionHistory:
157
+ config.maxTransactionHistory ?? DEFAULT_MAX_TRANSACTION_HISTORY,
158
+ snapshot: {
159
+ interval: config.snapshot?.interval
160
+ ? Duration.decode(config.snapshot.interval)
161
+ : DEFAULT_SNAPSHOT_INTERVAL,
162
+ transactionThreshold:
163
+ config.snapshot?.transactionThreshold ?? DEFAULT_SNAPSHOT_THRESHOLD,
164
+ },
165
+ });
166
+
167
+ // =============================================================================
168
+ // Factory
169
+ // =============================================================================
170
+
171
+ /**
172
+ * Create a MimicServerEngine layer.
173
+ *
174
+ * This creates the core document management service. To expose it via WebSocket,
175
+ * use MimicServer.layerHttpLayerRouter().
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * // 1. Create the engine
180
+ * const Engine = MimicServerEngine.make({
181
+ * schema: DocSchema,
182
+ * initial: { title: "Untitled" },
183
+ * presence: CursorPresence,
184
+ * maxIdleTime: "5 minutes",
185
+ * snapshot: { interval: "5 minutes", transactionThreshold: 100 },
186
+ * })
187
+ *
188
+ * // 2. Create the WebSocket route
189
+ * const MimicRoute = MimicServer.layerHttpLayerRouter({
190
+ * path: "/mimic",
191
+ * })
192
+ *
193
+ * // 3. Wire together
194
+ * const MimicLive = MimicRoute.pipe(
195
+ * Layer.provide(Engine),
196
+ * Layer.provide(ColdStorage.InMemory.make()),
197
+ * Layer.provide(HotStorage.InMemory.make()),
198
+ * Layer.provide(MimicAuthService.NoAuth.make()),
199
+ * )
200
+ * ```
201
+ */
202
+ export const make = <TSchema extends Primitive.AnyPrimitive>(
203
+ config: MimicServerEngineConfig<TSchema>
204
+ ): Layer.Layer<
205
+ MimicServerEngineTag,
206
+ never,
207
+ ColdStorageTag | HotStorageTag | MimicAuthServiceTag
208
+ > => {
209
+ const resolvedConfig = resolveConfig(config);
210
+
211
+ // Create config layer for DocumentManager
212
+ const configLayer = Layer.succeed(
213
+ DocumentManagerConfigTag,
214
+ resolvedConfig as ResolvedConfig<Primitive.AnyPrimitive>
215
+ );
216
+
217
+ // Create internal layers
218
+ const internalLayers = Layer.mergeAll(
219
+ documentManagerLayer.pipe(Layer.provide(configLayer)),
220
+ presenceManagerLayer
221
+ );
222
+
223
+ return Layer.scoped(
224
+ MimicServerEngineTag,
225
+ Effect.gen(function* () {
226
+ const documentManager = yield* DocumentManagerTag;
227
+ const presenceManager = yield* PresenceManagerTag;
228
+
229
+ const engine: MimicServerEngine = {
230
+ submit: (documentId, transaction) =>
231
+ documentManager.submit(documentId, transaction),
232
+
233
+ getSnapshot: (documentId) => documentManager.getSnapshot(documentId),
234
+
235
+ subscribe: (documentId) =>
236
+ documentManager.subscribe(documentId) as Effect.Effect<
237
+ Stream.Stream<Protocol.ServerMessage, never, never>,
238
+ never
239
+ >,
240
+
241
+ touch: (documentId) => documentManager.touch(documentId),
242
+
243
+ getPresenceSnapshot: (documentId) =>
244
+ presenceManager.getSnapshot(documentId),
245
+
246
+ setPresence: (documentId, connectionId, entry) =>
247
+ presenceManager.set(documentId, connectionId, entry),
248
+
249
+ removePresence: (documentId, connectionId) =>
250
+ presenceManager.remove(documentId, connectionId),
251
+
252
+ subscribePresence: (documentId) =>
253
+ presenceManager.subscribe(documentId),
254
+
255
+ config: resolvedConfig as ResolvedConfig<Primitive.AnyPrimitive>,
256
+ };
257
+
258
+ return engine;
259
+ })
260
+ ).pipe(Layer.provide(internalLayers));
261
+ };
262
+
263
+ // =============================================================================
264
+ // Re-export namespace
265
+ // =============================================================================
266
+
267
+ export const MimicServerEngine = {
268
+ Tag: MimicServerEngineTag,
269
+ make,
270
+ };
271
+
272
+ // =============================================================================
273
+ // Re-export SubmitResult type
274
+ // =============================================================================
275
+
276
+ export type { SubmitResult };