@livestore/utils 0.4.0-dev.9 → 0.5.0-dev.0

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 (316) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/NoopTracer.d.ts +7 -8
  3. package/dist/NoopTracer.d.ts.map +1 -1
  4. package/dist/NoopTracer.js +13 -15
  5. package/dist/NoopTracer.js.map +1 -1
  6. package/dist/NoopTracer.test.d.ts +2 -0
  7. package/dist/NoopTracer.test.d.ts.map +1 -0
  8. package/dist/NoopTracer.test.js +17 -0
  9. package/dist/NoopTracer.test.js.map +1 -0
  10. package/dist/binary.js +1 -1
  11. package/dist/binary.js.map +1 -1
  12. package/dist/browser/Opfs/Opfs.d.ts +201 -0
  13. package/dist/browser/Opfs/Opfs.d.ts.map +1 -0
  14. package/dist/browser/Opfs/Opfs.js +170 -0
  15. package/dist/browser/Opfs/Opfs.js.map +1 -0
  16. package/dist/browser/Opfs/debug-utils.d.ts +20 -0
  17. package/dist/browser/Opfs/debug-utils.d.ts.map +1 -0
  18. package/dist/browser/Opfs/debug-utils.js +95 -0
  19. package/dist/browser/Opfs/debug-utils.js.map +1 -0
  20. package/dist/browser/Opfs/mod.d.ts +4 -0
  21. package/dist/browser/Opfs/mod.d.ts.map +1 -0
  22. package/dist/browser/Opfs/mod.js +4 -0
  23. package/dist/browser/Opfs/mod.js.map +1 -0
  24. package/dist/browser/Opfs/utils.d.ts +71 -0
  25. package/dist/browser/Opfs/utils.d.ts.map +1 -0
  26. package/dist/browser/Opfs/utils.js +227 -0
  27. package/dist/browser/Opfs/utils.js.map +1 -0
  28. package/dist/browser/QuotaExceededError.d.ts +60 -0
  29. package/dist/browser/QuotaExceededError.d.ts.map +1 -0
  30. package/dist/browser/QuotaExceededError.js +2 -0
  31. package/dist/browser/QuotaExceededError.js.map +1 -0
  32. package/dist/browser/WebChannelBrowser.d.ts +22 -0
  33. package/dist/browser/WebChannelBrowser.d.ts.map +1 -0
  34. package/dist/browser/WebChannelBrowser.js +87 -0
  35. package/dist/browser/WebChannelBrowser.js.map +1 -0
  36. package/dist/browser/WebError.d.ts +389 -0
  37. package/dist/browser/WebError.d.ts.map +1 -0
  38. package/dist/browser/WebError.js +423 -0
  39. package/dist/browser/WebError.js.map +1 -0
  40. package/dist/browser/WebError.test.d.ts +2 -0
  41. package/dist/browser/WebError.test.d.ts.map +1 -0
  42. package/dist/browser/WebError.test.js +46 -0
  43. package/dist/browser/WebError.test.js.map +1 -0
  44. package/dist/browser/WebLock.d.ts.map +1 -0
  45. package/dist/{effect → browser}/WebLock.js +21 -21
  46. package/dist/browser/WebLock.js.map +1 -0
  47. package/dist/{browser.d.ts → browser/detect.d.ts} +1 -1
  48. package/dist/browser/detect.d.ts.map +1 -0
  49. package/dist/{browser.js → browser/detect.js} +7 -7
  50. package/dist/browser/detect.js.map +1 -0
  51. package/dist/browser/mod.d.ts +8 -0
  52. package/dist/browser/mod.d.ts.map +1 -0
  53. package/dist/browser/mod.js +8 -0
  54. package/dist/browser/mod.js.map +1 -0
  55. package/dist/cuid/cuid.browser.js +1 -1
  56. package/dist/cuid/cuid.browser.js.map +1 -1
  57. package/dist/cuid/cuid.node.js +1 -1
  58. package/dist/cuid/cuid.node.js.map +1 -1
  59. package/dist/effect/Debug.d.ts +38 -0
  60. package/dist/effect/Debug.d.ts.map +1 -0
  61. package/dist/effect/Debug.js +350 -0
  62. package/dist/effect/Debug.js.map +1 -0
  63. package/dist/effect/Effect.d.ts +91 -22
  64. package/dist/effect/Effect.d.ts.map +1 -1
  65. package/dist/effect/Effect.js +126 -38
  66. package/dist/effect/Effect.js.map +1 -1
  67. package/dist/effect/Effect.test.d.ts +2 -0
  68. package/dist/effect/Effect.test.d.ts.map +1 -0
  69. package/dist/effect/Effect.test.js +72 -0
  70. package/dist/effect/Effect.test.js.map +1 -0
  71. package/dist/effect/Error.d.ts +4 -6
  72. package/dist/effect/Error.d.ts.map +1 -1
  73. package/dist/effect/Error.js +1 -1
  74. package/dist/effect/Error.js.map +1 -1
  75. package/dist/effect/Logger.d.ts +0 -6
  76. package/dist/effect/Logger.d.ts.map +1 -1
  77. package/dist/effect/Logger.js +0 -32
  78. package/dist/effect/Logger.js.map +1 -1
  79. package/dist/effect/OtelTracer.d.ts +1 -1
  80. package/dist/effect/OtelTracer.d.ts.map +1 -1
  81. package/dist/effect/OtelTracer.js +2 -3
  82. package/dist/effect/OtelTracer.js.map +1 -1
  83. package/dist/effect/RpcClient.d.ts +7 -7
  84. package/dist/effect/RpcClient.d.ts.map +1 -1
  85. package/dist/effect/RpcClient.js +74 -54
  86. package/dist/effect/RpcClient.js.map +1 -1
  87. package/dist/effect/Schedule.d.ts +1 -1
  88. package/dist/effect/Schedule.d.ts.map +1 -1
  89. package/dist/effect/Schedule.js +2 -2
  90. package/dist/effect/Schedule.js.map +1 -1
  91. package/dist/effect/Schema/debug-diff.d.ts +1 -1
  92. package/dist/effect/Schema/debug-diff.d.ts.map +1 -1
  93. package/dist/effect/Schema/debug-diff.js +9 -10
  94. package/dist/effect/Schema/debug-diff.js.map +1 -1
  95. package/dist/effect/Schema/debug-diff.test.js +7 -4
  96. package/dist/effect/Schema/debug-diff.test.js.map +1 -1
  97. package/dist/effect/Schema/index.d.ts +28 -18
  98. package/dist/effect/Schema/index.d.ts.map +1 -1
  99. package/dist/effect/Schema/index.js +55 -28
  100. package/dist/effect/Schema/index.js.map +1 -1
  101. package/dist/effect/Stream.d.ts +13 -5
  102. package/dist/effect/Stream.d.ts.map +1 -1
  103. package/dist/effect/Stream.js +19 -12
  104. package/dist/effect/Stream.js.map +1 -1
  105. package/dist/effect/Stream.test.js +12 -12
  106. package/dist/effect/Stream.test.js.map +1 -1
  107. package/dist/effect/Subscribable.d.ts +9 -3
  108. package/dist/effect/Subscribable.d.ts.map +1 -1
  109. package/dist/effect/Subscribable.js +20 -35
  110. package/dist/effect/Subscribable.js.map +1 -1
  111. package/dist/effect/SubscriptionRef.d.ts +5 -6
  112. package/dist/effect/SubscriptionRef.d.ts.map +1 -1
  113. package/dist/effect/SubscriptionRef.js +2 -3
  114. package/dist/effect/SubscriptionRef.js.map +1 -1
  115. package/dist/effect/TaskTracing.d.ts +1 -1
  116. package/dist/effect/TaskTracing.d.ts.map +1 -1
  117. package/dist/effect/TaskTracing.js +12 -16
  118. package/dist/effect/TaskTracing.js.map +1 -1
  119. package/dist/effect/WebChannel/WebChannel.d.ts +11 -30
  120. package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
  121. package/dist/effect/WebChannel/WebChannel.js +70 -125
  122. package/dist/effect/WebChannel/WebChannel.js.map +1 -1
  123. package/dist/effect/WebChannel/WebChannel.test.js +16 -16
  124. package/dist/effect/WebChannel/WebChannel.test.js.map +1 -1
  125. package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts.map +1 -1
  126. package/dist/effect/WebChannel/broadcastChannelWithAck.js +20 -13
  127. package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
  128. package/dist/effect/WebChannel/common.d.ts +17 -18
  129. package/dist/effect/WebChannel/common.d.ts.map +1 -1
  130. package/dist/effect/WebChannel/common.js +7 -7
  131. package/dist/effect/WebChannel/common.js.map +1 -1
  132. package/dist/effect/WebSocket.d.ts +4 -6
  133. package/dist/effect/WebSocket.d.ts.map +1 -1
  134. package/dist/effect/WebSocket.js +17 -17
  135. package/dist/effect/WebSocket.js.map +1 -1
  136. package/dist/effect/WebSocket.test.js +2 -2
  137. package/dist/effect/WebSocket.test.js.map +1 -1
  138. package/dist/effect/mod.browser-build.test.d.ts +2 -0
  139. package/dist/effect/mod.browser-build.test.d.ts.map +1 -0
  140. package/dist/effect/mod.browser-build.test.js +18 -0
  141. package/dist/effect/mod.browser-build.test.js.map +1 -0
  142. package/dist/effect/mod.d.ts +30 -0
  143. package/dist/effect/mod.d.ts.map +1 -0
  144. package/dist/effect/mod.js +30 -0
  145. package/dist/effect/mod.js.map +1 -0
  146. package/dist/effect/spanEvent.d.ts +12 -0
  147. package/dist/effect/spanEvent.d.ts.map +1 -0
  148. package/dist/effect/spanEvent.js +12 -0
  149. package/dist/effect/spanEvent.js.map +1 -0
  150. package/dist/effect/spanEvent.test.d.ts +2 -0
  151. package/dist/effect/spanEvent.test.d.ts.map +1 -0
  152. package/dist/effect/spanEvent.test.js +79 -0
  153. package/dist/effect/spanEvent.test.js.map +1 -0
  154. package/dist/env.d.ts.map +1 -1
  155. package/dist/env.js +1 -1
  156. package/dist/env.js.map +1 -1
  157. package/dist/fast-deep-equal.d.ts.map +1 -1
  158. package/dist/fast-deep-equal.js +9 -10
  159. package/dist/fast-deep-equal.js.map +1 -1
  160. package/dist/global.d.ts +3 -0
  161. package/dist/global.d.ts.map +1 -1
  162. package/dist/global.js.map +1 -1
  163. package/dist/misc.d.ts +9 -1
  164. package/dist/misc.d.ts.map +1 -1
  165. package/dist/misc.js +12 -4
  166. package/dist/misc.js.map +1 -1
  167. package/dist/mod.d.ts +177 -20
  168. package/dist/mod.d.ts.map +1 -1
  169. package/dist/mod.js +159 -22
  170. package/dist/mod.js.map +1 -1
  171. package/dist/node/mod.d.ts +45 -6
  172. package/dist/node/mod.d.ts.map +1 -1
  173. package/dist/node/mod.js +51 -9
  174. package/dist/node/mod.js.map +1 -1
  175. package/dist/object/index.d.ts +0 -9
  176. package/dist/object/index.d.ts.map +1 -1
  177. package/dist/object/index.js +0 -9
  178. package/dist/object/index.js.map +1 -1
  179. package/dist/object/stringify-object.js +2 -2
  180. package/dist/object/stringify-object.js.map +1 -1
  181. package/dist/object/stringify-object.test.js.map +1 -1
  182. package/dist/qr.d.ts +38 -0
  183. package/dist/qr.d.ts.map +1 -0
  184. package/dist/qr.js +109 -0
  185. package/dist/qr.js.map +1 -0
  186. package/dist/set.js +1 -1
  187. package/dist/set.js.map +1 -1
  188. package/dist/string.d.ts +0 -2
  189. package/dist/string.d.ts.map +1 -1
  190. package/dist/string.js +0 -2
  191. package/dist/string.js.map +1 -1
  192. package/package.json +61 -55
  193. package/src/NoopTracer.test.ts +20 -0
  194. package/src/NoopTracer.ts +28 -37
  195. package/src/binary.ts +1 -1
  196. package/src/browser/Opfs/Opfs.ts +463 -0
  197. package/src/browser/Opfs/debug-utils.ts +154 -0
  198. package/src/browser/Opfs/mod.ts +3 -0
  199. package/src/browser/Opfs/utils.ts +297 -0
  200. package/src/browser/QuotaExceededError.ts +60 -0
  201. package/src/browser/WebChannelBrowser.ts +145 -0
  202. package/src/browser/WebError.test.ts +66 -0
  203. package/src/browser/WebError.ts +587 -0
  204. package/src/{effect → browser}/WebLock.ts +27 -28
  205. package/src/{browser.ts → browser/detect.ts} +6 -6
  206. package/src/browser/mod.ts +8 -0
  207. package/src/cuid/cuid.browser.ts +1 -1
  208. package/src/cuid/cuid.node.ts +1 -1
  209. package/src/effect/Debug.ts +477 -0
  210. package/src/effect/Effect.test.ts +117 -0
  211. package/src/effect/Effect.ts +174 -79
  212. package/src/effect/Error.ts +1 -1
  213. package/src/effect/Logger.ts +0 -48
  214. package/src/effect/OtelTracer.ts +2 -3
  215. package/src/effect/RpcClient.ts +85 -65
  216. package/src/effect/Schedule.ts +4 -5
  217. package/src/effect/Schema/debug-diff.test.ts +7 -7
  218. package/src/effect/Schema/debug-diff.ts +11 -12
  219. package/src/effect/Schema/index.ts +121 -57
  220. package/src/effect/Stream.test.ts +14 -13
  221. package/src/effect/Stream.ts +23 -16
  222. package/src/effect/Subscribable.ts +31 -42
  223. package/src/effect/SubscriptionRef.ts +9 -13
  224. package/src/effect/TaskTracing.ts +13 -16
  225. package/src/effect/WebChannel/WebChannel.test.ts +24 -24
  226. package/src/effect/WebChannel/WebChannel.ts +102 -192
  227. package/src/effect/WebChannel/broadcastChannelWithAck.ts +25 -15
  228. package/src/effect/WebChannel/common.ts +16 -17
  229. package/src/effect/WebSocket.test.ts +2 -2
  230. package/src/effect/WebSocket.ts +20 -16
  231. package/src/effect/mod.browser-build.test.ts +19 -0
  232. package/src/effect/{index.ts → mod.ts} +43 -69
  233. package/src/effect/spanEvent.test.ts +92 -0
  234. package/src/effect/spanEvent.ts +17 -0
  235. package/src/env.ts +2 -1
  236. package/src/fast-deep-equal.ts +9 -10
  237. package/src/global.ts +4 -2
  238. package/src/misc.ts +13 -5
  239. package/src/mod.ts +188 -32
  240. package/src/node/mod.ts +57 -12
  241. package/src/object/index.ts +0 -24
  242. package/src/object/stringify-object.test.ts +1 -0
  243. package/src/object/stringify-object.ts +2 -2
  244. package/src/qr.ts +125 -0
  245. package/src/set.ts +1 -1
  246. package/src/string.ts +0 -3
  247. package/dist/.tsbuildinfo.json +0 -1
  248. package/dist/browser.d.ts.map +0 -1
  249. package/dist/browser.js.map +0 -1
  250. package/dist/effect/BucketQueue.d.ts +0 -20
  251. package/dist/effect/BucketQueue.d.ts.map +0 -1
  252. package/dist/effect/BucketQueue.js +0 -34
  253. package/dist/effect/BucketQueue.js.map +0 -1
  254. package/dist/effect/Scheduler.d.ts +0 -4
  255. package/dist/effect/Scheduler.d.ts.map +0 -1
  256. package/dist/effect/Scheduler.js +0 -9
  257. package/dist/effect/Scheduler.js.map +0 -1
  258. package/dist/effect/ServiceContext.d.ts +0 -37
  259. package/dist/effect/ServiceContext.d.ts.map +0 -1
  260. package/dist/effect/ServiceContext.js +0 -55
  261. package/dist/effect/ServiceContext.js.map +0 -1
  262. package/dist/effect/WebLock.d.ts.map +0 -1
  263. package/dist/effect/WebLock.js.map +0 -1
  264. package/dist/effect/index.d.ts +0 -32
  265. package/dist/effect/index.d.ts.map +0 -1
  266. package/dist/effect/index.js +0 -35
  267. package/dist/effect/index.js.map +0 -1
  268. package/dist/guards.d.ts +0 -6
  269. package/dist/guards.d.ts.map +0 -1
  270. package/dist/guards.js +0 -6
  271. package/dist/guards.js.map +0 -1
  272. package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts +0 -4
  273. package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +0 -1
  274. package/dist/node/ChildProcessRunner/ChildProcessRunner.js +0 -122
  275. package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +0 -1
  276. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts +0 -2
  277. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts.map +0 -1
  278. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +0 -218
  279. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +0 -1
  280. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +0 -84
  281. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts.map +0 -1
  282. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js +0 -68
  283. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js.map +0 -1
  284. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts +0 -2
  285. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts.map +0 -1
  286. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +0 -52
  287. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +0 -1
  288. package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts +0 -23
  289. package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +0 -1
  290. package/dist/node/ChildProcessRunner/ChildProcessWorker.js +0 -138
  291. package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +0 -1
  292. package/dist/object/omit.d.ts +0 -3
  293. package/dist/object/omit.d.ts.map +0 -1
  294. package/dist/object/omit.js +0 -14
  295. package/dist/object/omit.js.map +0 -1
  296. package/dist/object/pick.d.ts +0 -14
  297. package/dist/object/pick.d.ts.map +0 -1
  298. package/dist/object/pick.js +0 -17
  299. package/dist/object/pick.js.map +0 -1
  300. package/dist/time.d.ts +0 -12
  301. package/dist/time.d.ts.map +0 -1
  302. package/dist/time.js +0 -22
  303. package/dist/time.js.map +0 -1
  304. package/src/effect/BucketQueue.ts +0 -49
  305. package/src/effect/Scheduler.ts +0 -13
  306. package/src/effect/ServiceContext.ts +0 -108
  307. package/src/guards.ts +0 -8
  308. package/src/node/ChildProcessRunner/ChildProcessRunner.ts +0 -135
  309. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +0 -302
  310. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +0 -78
  311. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +0 -66
  312. package/src/node/ChildProcessRunner/ChildProcessWorker.ts +0 -168
  313. package/src/object/omit.ts +0 -17
  314. package/src/object/pick.ts +0 -27
  315. package/src/time.ts +0 -25
  316. /package/dist/{effect → browser}/WebLock.d.ts +0 -0
@@ -1,11 +1,11 @@
1
- export * from '@effect/rpc/RpcClient'
2
-
3
- import { Socket } from '@effect/platform'
4
- import { RpcClient, RpcClientError, RpcSerialization } from '@effect/rpc'
5
- import { Protocol } from '@effect/rpc/RpcClient'
6
- import { constPing, type FromServerEncoded } from '@effect/rpc/RpcMessage'
7
- import { Cause, Deferred, Effect, Layer, Option, Schedule, type Scope } from 'effect'
8
- import { constVoid, identity } from 'effect/Function'
1
+ export * from 'effect/unstable/rpc/RpcClient'
2
+
3
+ import { Cause, Deferred, Effect, Function, Latch, Layer, References, Result, Schedule, type Scope } from 'effect'
4
+ import { RpcClient, RpcClientError, RpcSerialization } from 'effect/unstable/rpc'
5
+ import { Protocol } from 'effect/unstable/rpc/RpcClient'
6
+ import { constPing, type FromServerEncoded } from 'effect/unstable/rpc/RpcMessage'
7
+ import { Socket } from 'effect/unstable/socket'
8
+
9
9
  import * as SubscriptionRef from './SubscriptionRef.ts'
10
10
 
11
11
  // This is based on `makeProtocolSocket` / `layerProtocolSocket` from `@effect/rpc` in order to:
@@ -19,7 +19,7 @@ export const layerProtocolSocketWithIsConnected = (options: {
19
19
  readonly isConnected: SubscriptionRef.SubscriptionRef<boolean>
20
20
  readonly pingSchedule?: Schedule.Schedule<unknown> | undefined
21
21
  }): Layer.Layer<Protocol, never, RpcSerialization.RpcSerialization | Socket.Socket> =>
22
- Layer.scoped(Protocol, makeProtocolSocketWithIsConnected(options))
22
+ Layer.effect(Protocol, makeProtocolSocketWithIsConnected(options))
23
23
 
24
24
  export const makeProtocolSocketWithIsConnected = (options: {
25
25
  readonly url: string
@@ -28,16 +28,22 @@ export const makeProtocolSocketWithIsConnected = (options: {
28
28
  readonly isConnected: SubscriptionRef.SubscriptionRef<boolean>
29
29
  // CHANGED: add ping schedule
30
30
  readonly pingSchedule?: Schedule.Schedule<unknown> | undefined
31
- }): Effect.Effect<Protocol['Type'], never, Scope.Scope | RpcSerialization.RpcSerialization | Socket.Socket> =>
31
+ }): Effect.Effect<Protocol['Service'], never, Scope.Scope | RpcSerialization.RpcSerialization | Socket.Socket> =>
32
32
  Protocol.make(
33
- Effect.fnUntraced(function* (writeResponse) {
33
+ Effect.fnUntraced(function* (writeResponse, clientIds) {
34
34
  const socket = yield* Socket.Socket
35
35
  const serialization = yield* RpcSerialization.RpcSerialization
36
+ const requestClientMap = new Map<string | number, number>()
36
37
 
37
38
  const write = yield* socket.writer
38
- const parser = serialization.unsafeMake()
39
+ let parser = serialization.makeUnsafe()
39
40
 
40
41
  const pinger = yield* makePinger(write(parser.encode(constPing)!), options?.pingSchedule)
42
+ let currentError: RpcClientError.RpcClientError | undefined
43
+
44
+ const markConnected = SubscriptionRef.set(options.isConnected, true)
45
+ const broadcast = (response: FromServerEncoded) =>
46
+ Effect.forEach(clientIds, (clientId) => writeResponse(clientId, response))
41
47
 
42
48
  yield* Effect.suspend(() => {
43
49
  // We rely on the heartbeat watchdog while streaming arbitrarily long payloads.
@@ -45,7 +51,8 @@ export const makeProtocolSocketWithIsConnected = (options: {
45
51
  // don't contain explicit `Pong` messages don't trigger the open-timeout defect.
46
52
  // (The actual pong handler still calls `onPong()` to resolve manual pings.)
47
53
  // CHANGED: don't reset parser on every message
48
- // parser = serialization.unsafeMake()
54
+ // parser = serialization.makeUnsafe()
55
+ currentError = undefined
49
56
  pinger.reset()
50
57
  return socket
51
58
  .runRaw((message) => {
@@ -62,94 +69,107 @@ export const makeProtocolSocketWithIsConnected = (options: {
62
69
  pinger.reset()
63
70
  if (response._tag === 'Pong') {
64
71
  pinger.onPong()
72
+ return markConnected
65
73
  }
66
- return writeResponse(response).pipe(
67
- // CHANGED: set isConnected to true on pong
68
- Effect.tap(
69
- Effect.fn(function* () {
70
- if (options?.isConnected !== undefined) {
71
- yield* SubscriptionRef.set(options.isConnected, true)
72
- }
73
- }),
74
- ),
75
- )
74
+ if ('requestId' in response) {
75
+ const clientId = requestClientMap.get(response.requestId)
76
+ if (clientId !== undefined) {
77
+ if (response._tag === 'Exit') {
78
+ requestClientMap.delete(response.requestId)
79
+ }
80
+ return markConnected.pipe(Effect.andThen(writeResponse(clientId, response)))
81
+ }
82
+ }
83
+ return markConnected.pipe(Effect.andThen(broadcast(response)))
76
84
  },
77
- step: constVoid,
85
+ step: Function.constVoid,
78
86
  })
79
87
  } catch (defect) {
80
- return writeResponse({
88
+ return broadcast({
81
89
  _tag: 'ClientProtocolError',
82
90
  error: new RpcClientError.RpcClientError({
83
- reason: 'Protocol',
84
- message: 'Error decoding message',
85
- cause: Cause.fail(defect),
91
+ reason: new RpcClientError.RpcClientDefect({
92
+ message: 'Error decoding message',
93
+ cause: defect,
94
+ }),
86
95
  }),
87
96
  })
88
97
  }
89
98
  })
90
99
  .pipe(
91
100
  Effect.raceFirst(
92
- Effect.zipRight(
93
- pinger.timeout,
101
+ Effect.flatMap(pinger.timeout, () =>
94
102
  Effect.fail(
95
- new Socket.SocketGenericError({
96
- reason: 'OpenTimeout',
97
- cause: new Error('ping timeout'),
103
+ new Socket.SocketError({
104
+ reason: new Socket.SocketOpenError({
105
+ kind: 'Timeout',
106
+ cause: new Error('ping timeout'),
107
+ }),
98
108
  }),
99
109
  ),
100
110
  ),
101
111
  ),
102
112
  )
103
113
  }).pipe(
104
- Effect.zipRight(
114
+ Effect.flatMap(() =>
105
115
  Effect.fail(
106
- new Socket.SocketCloseError({
107
- reason: 'Close',
108
- code: 1000,
109
- closeReason: 'Closing connection',
116
+ new Socket.SocketError({
117
+ reason: new Socket.SocketCloseError({
118
+ code: 1000,
119
+ closeReason: 'Closing connection',
120
+ }),
110
121
  }),
111
122
  ),
112
123
  ),
113
- Effect.tapErrorCause(
124
+ Effect.tapCause(
114
125
  Effect.fn(function* (cause) {
115
126
  // CHANGED: set isConnected to false on error
116
- if (options?.isConnected !== undefined) {
117
- yield* SubscriptionRef.set(options.isConnected, false)
118
- }
127
+ yield* SubscriptionRef.set(options.isConnected, false)
119
128
 
120
- const error = Cause.failureOption(cause)
129
+ const error = Cause.findError(cause)
121
130
  if (
122
- options?.retryTransientErrors &&
123
- Option.isSome(error) &&
124
- (error.value.reason === 'Open' || error.value.reason === 'OpenTimeout')
131
+ options?.retryTransientErrors !== undefined &&
132
+ Result.isSuccess(error) === true &&
133
+ error.success.reason._tag === 'SocketOpenError'
125
134
  ) {
126
135
  return
127
136
  }
128
137
  // yield* Effect.logError('Error in socket', cause)
129
- return yield* writeResponse({
138
+ currentError = new RpcClientError.RpcClientError({
139
+ reason:
140
+ Result.isSuccess(error) === true
141
+ ? error.success.reason
142
+ : new RpcClientError.RpcClientDefect({
143
+ message: 'Unknown socket error',
144
+ cause: Cause.squash(cause),
145
+ }),
146
+ })
147
+ return yield* broadcast({
130
148
  _tag: 'ClientProtocolError',
131
- error: new RpcClientError.RpcClientError({
132
- reason: 'Protocol',
133
- message: 'Error in socket',
134
- cause: Cause.squash(cause),
135
- }),
149
+ error: currentError,
136
150
  })
137
151
  }),
138
152
  ),
139
153
  // CHANGED: make configurable via schedule
140
- options?.retryTransientErrors ? Effect.retry(options.retryTransientErrors) : identity,
154
+ options?.retryTransientErrors !== undefined ? Effect.retry(options.retryTransientErrors) : Function.identity,
141
155
  Effect.annotateLogs({
142
156
  module: 'RpcClient',
143
157
  method: 'makeProtocolSocket',
144
158
  }),
145
159
  Effect.interruptible,
146
160
  Effect.ignore, // Errors are already handled
147
- Effect.provide(Layer.setUnhandledErrorLogLevel(Option.none())),
161
+ Effect.provideService(References.UnhandledLogLevel, undefined),
148
162
  Effect.forkScoped,
149
163
  )
150
164
 
151
165
  return {
152
- send: (request) => {
166
+ send: (clientId, request) => {
167
+ if (currentError !== undefined) {
168
+ return Effect.fail(currentError)
169
+ }
170
+ if (request._tag === 'Request') {
171
+ requestClientMap.set(request.id, clientId)
172
+ }
153
173
  const encoded = parser.encode(request)
154
174
  if (encoded === undefined) return Effect.void
155
175
 
@@ -164,33 +184,33 @@ export const makeProtocolSocketWithIsConnected = (options: {
164
184
 
165
185
  export const SocketPinger = Effect.map(RpcClient.Protocol, (protocol) => (protocol as any).pinger as SocketPinger)
166
186
 
167
- export type SocketPinger = Effect.Effect.Success<ReturnType<typeof makePinger>>
187
+ export type SocketPinger = Effect.Success<ReturnType<typeof makePinger>>
168
188
 
169
189
  const makePinger = Effect.fnUntraced(function* <A, E, R>(
170
190
  writePing: Effect.Effect<A, E, R>,
171
- pingSchedule: Schedule.Schedule<unknown> = Schedule.spaced(10000).pipe(Schedule.addDelay(() => 5000)),
191
+ pingSchedule: Schedule.Schedule<unknown> = Schedule.spaced(10000).pipe(Schedule.addDelay(() => Effect.succeed(5000))),
172
192
  ) {
173
193
  // CHANGED: add manual ping deferreds
174
- const manualPingDeferreds = new Set<Deferred.Deferred<void, never>>()
194
+ const manualPingDeferreds = new Set<Deferred.Deferred<void>>()
175
195
 
176
196
  let recievedPong = true
177
- const latch = Effect.unsafeMakeLatch()
197
+ const latch = Latch.makeUnsafe()
178
198
  const reset = () => {
179
199
  recievedPong = true
180
- latch.unsafeClose()
200
+ latch.closeUnsafe()
181
201
  }
182
202
  const onPong = () => {
183
203
  recievedPong = true
184
204
  // CHANGED: mark all manual ping deferreds as done
185
205
  for (const deferred of manualPingDeferreds) {
186
- Deferred.unsafeDone(deferred, Effect.void)
206
+ Deferred.doneUnsafe(deferred, Effect.void)
187
207
  }
188
208
  }
189
209
  yield* Effect.suspend(() => {
190
210
  // Starting new ping
191
- if (!recievedPong) return latch.open
211
+ if (recievedPong === false) return Effect.asVoid(latch.open)
192
212
  recievedPong = false
193
- return writePing
213
+ return Effect.asVoid(writePing)
194
214
  }).pipe(
195
215
  // CHANGED: make configurable via schedule
196
216
  Effect.schedule(pingSchedule),
@@ -202,9 +222,9 @@ const makePinger = Effect.fnUntraced(function* <A, E, R>(
202
222
 
203
223
  // CHANGED: add manual ping
204
224
  const ping = Effect.gen(function* () {
205
- const deferred = yield* Deferred.make<void, never>()
225
+ const deferred = yield* Deferred.make<void>()
206
226
  manualPingDeferreds.add(deferred)
207
- yield* deferred
227
+ yield* Deferred.await(deferred)
208
228
  manualPingDeferreds.delete(deferred)
209
229
  })
210
230
 
@@ -1,10 +1,9 @@
1
- import { Duration, pipe, Schedule } from 'effect'
1
+ import { Duration, Effect, pipe, Schedule } from 'effect'
2
2
 
3
3
  export * from 'effect/Schedule'
4
4
 
5
- export const exponentialBackoff10Sec: Schedule.Schedule<Duration.DurationInput> = pipe(
5
+ export const exponentialBackoff10Sec = pipe(
6
6
  Schedule.exponential(Duration.millis(10), 4), // 10ms, 40ms, 160ms, 640ms, 2560ms, ...
7
- Schedule.andThenEither(Schedule.spaced(Duration.seconds(1))),
8
- Schedule.compose(Schedule.elapsed),
9
- Schedule.whileOutput(Duration.lessThanOrEqualTo(Duration.seconds(10))), // max 10 seconds
7
+ Schedule.modifyDelay(({ duration }) => Effect.succeed(Duration.min(duration, Duration.seconds(1)))),
8
+ Schedule.upTo({ duration: Duration.seconds(10) }),
10
9
  )
@@ -8,7 +8,7 @@ describe('debug-diff', () => {
8
8
  test('simple object', () => {
9
9
  const schema = Schema.Struct({
10
10
  a: Schema.String,
11
- b: Schema.Number,
11
+ b: Schema.Finite,
12
12
  })
13
13
 
14
14
  const a = { a: 'hello', b: 1 }
@@ -35,7 +35,7 @@ describe('debug-diff', () => {
35
35
  const schema = Schema.Struct({
36
36
  a: Schema.String,
37
37
  b: Schema.Struct({
38
- c: Schema.Number,
38
+ c: Schema.Finite,
39
39
  }),
40
40
  })
41
41
  const a = { a: 'hello', b: { c: 1 } }
@@ -58,7 +58,7 @@ describe('debug-diff', () => {
58
58
  })
59
59
 
60
60
  test('union', () => {
61
- const schema = Schema.Union(Schema.String, Schema.Number)
61
+ const schema = Schema.Union([Schema.String, Schema.Finite])
62
62
  const a = 'hello'
63
63
  const b = 1
64
64
  const diff = debugDiff(schema)(a, b)
@@ -74,10 +74,10 @@ describe('debug-diff', () => {
74
74
  })
75
75
 
76
76
  test('tagged union', () => {
77
- const schema = Schema.Union(
78
- Schema.Struct({ _tag: Schema.Literal('a'), a: Schema.String }),
79
- Schema.Struct({ _tag: Schema.Literal('b'), b: Schema.Number }),
80
- )
77
+ const schema = Schema.Union([
78
+ Schema.TaggedStruct('a', { a: Schema.String }),
79
+ Schema.TaggedStruct('b', { b: Schema.Finite }),
80
+ ])
81
81
  const a = { _tag: 'a', a: 'hello' } as const
82
82
  const b = { _tag: 'b', b: 1 } as const
83
83
  const diff = debugDiff(schema)(a, b)
@@ -11,7 +11,7 @@ export type DiffItem = {
11
11
  * Diffs two values for a given schema and traverses downwards and returns a list of differences.
12
12
  */
13
13
  export const debugDiff =
14
- <A, I, R>(base: Schema.Schema<A, I, R>) =>
14
+ <A, I, R>(base: Schema.Top) =>
15
15
  (a: A, b: A): DiffItem[] => {
16
16
  const bag = [] as DiffItem[]
17
17
  debugDiffImpl(base.ast, a, b, '', bag)
@@ -19,12 +19,12 @@ export const debugDiff =
19
19
  }
20
20
 
21
21
  const debugDiffImpl = (ast: SchemaAST.AST, a: any, b: any, path: string, bag: DiffItem[]) => {
22
- const eq = Schema.equivalence({ ast } as any)
22
+ const eq = Schema.toEquivalence({ ast } as any)
23
23
  if (eq(a, b) === false) {
24
24
  // bag.push({ path, a, b, ast })
25
25
 
26
- if (SchemaAST.isUnion(ast)) {
27
- if (isTaggedUnion(ast)) {
26
+ if (SchemaAST.isUnion(ast) === true) {
27
+ if (isTaggedUnion(ast) === true) {
28
28
  bag.push({ path, a, b, ast })
29
29
  return
30
30
  } else {
@@ -35,9 +35,8 @@ const debugDiffImpl = (ast: SchemaAST.AST, a: any, b: any, path: string, bag: Di
35
35
  } catch {}
36
36
  }
37
37
  }
38
- } else if (SchemaAST.isTypeLiteral(ast)) {
39
- const props = SchemaAST.getPropertySignatures(ast)
40
- for (const prop of props) {
38
+ } else if (SchemaAST.isObjects(ast) === true) {
39
+ for (const prop of ast.propertySignatures) {
41
40
  debugDiffImpl(prop.type, a[prop.name], b[prop.name], `${path}.${prop.name.toString()}`, bag)
42
41
  }
43
42
  } else {
@@ -47,12 +46,12 @@ const debugDiffImpl = (ast: SchemaAST.AST, a: any, b: any, path: string, bag: Di
47
46
  }
48
47
  }
49
48
 
50
- const isTaggedUnion = (ast: SchemaAST.AST) => {
51
- if (SchemaAST.isUnion(ast)) {
49
+ const isTaggedUnion = (ast: SchemaAST.AST): boolean => {
50
+ if (SchemaAST.isUnion(ast) === true) {
52
51
  return ast.types.every((type) => {
53
- if (SchemaAST.isTypeLiteral(type) === false) return false
54
- const props = SchemaAST.getPropertySignatures(type)
55
- return props.some((prop) => prop.name.toString() === '_tag')
52
+ if (SchemaAST.isObjects(type) === false) return false
53
+ return type.propertySignatures.some((prop) => prop.name.toString() === '_tag')
56
54
  })
57
55
  }
56
+ return false
58
57
  }
@@ -1,18 +1,115 @@
1
- import { Transferable } from '@effect/platform'
2
- import { Effect, Hash, ParseResult, Schema } from 'effect'
3
- import type { ParseError } from 'effect/ParseResult'
4
- import type { ParseOptions } from 'effect/SchemaAST'
5
- import * as SchemaAST from 'effect/SchemaAST'
1
+ import {
2
+ Array,
3
+ Effect,
4
+ Function,
5
+ Hash,
6
+ Option,
7
+ Result,
8
+ Schema,
9
+ SchemaAST,
10
+ SchemaGetter,
11
+ SchemaIssue,
12
+ SchemaTransformation,
13
+ Struct,
14
+ } from 'effect'
15
+ import { Transferable } from 'effect/unstable/workers'
6
16
 
7
- import { shouldNeverHappen } from '../../mod.ts'
17
+ import { shouldNeverHappen } from '../../misc.ts'
8
18
 
9
19
  export * from 'effect/Schema'
10
20
  export * from './debug-diff.ts'
11
21
 
22
+ type PluckSchema<Fields extends Schema.Struct.Fields, K extends keyof Fields> = Schema.Codec<
23
+ Fields[K]['Type'],
24
+ Schema.Struct<Pick<Fields, K>>['Encoded'],
25
+ Schema.Struct<Pick<Fields, K>>['DecodingServices'],
26
+ Schema.Struct<Pick<Fields, K>>['EncodingServices']
27
+ >
28
+
29
+ export const pluck =
30
+ <const K extends PropertyKey>(key: K) =>
31
+ <Fields extends { readonly [P in K]: Schema.Top }>(
32
+ schema: Schema.Struct<Fields>,
33
+ ): PluckSchema<Fields, K & keyof Fields> => {
34
+ const field = schema.fields[key] as Fields[K & keyof Fields]
35
+
36
+ return schema.mapFields(Struct.pick([key])).pipe(
37
+ Schema.decodeTo(Schema.toType(field), {
38
+ decode: SchemaGetter.transform((whole: any) => whole[key]),
39
+ encode: SchemaGetter.transform((value) => ({ [key]: value }) as any),
40
+ }),
41
+ ) as unknown as PluckSchema<Fields, K & keyof Fields>
42
+ }
43
+
44
+ /**
45
+ * Like {@link fromJsonString}, but the ENCODED form is an *indented* JSON string
46
+ * (default 2-space) instead of compact — for committed/human-read JSON files
47
+ * (package.json, release plans, CI previews) that must stay diff-friendly while
48
+ * still round-tripping through the schema.
49
+ *
50
+ * Use a concrete schema for known shapes (adds validation) or `Schema.Unknown`
51
+ * for open-ended ones (the indented analogue of `fromJsonString(Schema.Unknown)`).
52
+ *
53
+ * TODO collapse into `fromJsonString(schema, { space })` now that Effect 4 accepts a
54
+ * `space` option; kept separate here to keep the Effect upgrade free of release-tooling changes.
55
+ */
56
+ export const jsonStringIndented = <S extends Schema.Top>(schema: S, space: number | string = 2) =>
57
+ schema.pipe(
58
+ Schema.encodeTo(Schema.String, {
59
+ decode: SchemaGetter.parseJson(),
60
+ encode: SchemaGetter.stringifyJson({ space }),
61
+ }),
62
+ )
63
+
64
+ export const head = <S extends Schema.Top>(
65
+ array: Schema.$Array<S>,
66
+ ): Schema.decodeTo<Schema.Option<Schema.toType<S>>, Schema.$Array<S>> =>
67
+ array.pipe(
68
+ Schema.decodeTo(
69
+ Schema.Option(Schema.toType(array.value)),
70
+ SchemaTransformation.transform({
71
+ decode: Array.head,
72
+ encode: Option.match({
73
+ onNone: () => [],
74
+ onSome: Array.of,
75
+ }),
76
+ }),
77
+ ),
78
+ )
79
+
80
+ type HeadOrElse<S extends Schema.Top> = Schema.decodeTo<Schema.toType<S>, Schema.$Array<S>>
81
+
82
+ export const headOrElse: {
83
+ <S extends Schema.Top>(array: Schema.$Array<S>, orElse?: () => S['Type']): HeadOrElse<S>
84
+ (): <S extends Schema.Top>(array: Schema.$Array<S>) => HeadOrElse<S>
85
+ <S extends Schema.Top>(orElse: () => S['Type']): (array: Schema.$Array<S>) => HeadOrElse<S>
86
+ } = Function.dual(
87
+ (args) => Schema.isSchema(args[0]),
88
+ <S extends Schema.Top>(array: Schema.$Array<S>, orElse?: () => S['Type']): HeadOrElse<S> =>
89
+ array.pipe(
90
+ Schema.decodeTo(
91
+ Schema.toType(array.value),
92
+ SchemaTransformation.transformOrFail({
93
+ decode: (array) =>
94
+ Array.isReadonlyArrayNonEmpty(array) === true
95
+ ? Effect.succeed(Array.headNonEmpty(array))
96
+ : orElse === undefined
97
+ ? Effect.fail(
98
+ new SchemaIssue.InvalidValue({
99
+ message: 'Unable to retrieve the first element of an empty array',
100
+ }),
101
+ )
102
+ : Effect.succeed(orElse()),
103
+ encode: (value) => Effect.succeed(Array.of(value)),
104
+ }),
105
+ ),
106
+ ),
107
+ )
108
+
12
109
  // NOTE this is a temporary workaround until Effect schema has a better way to hash schemas
13
110
  // https://github.com/Effect-TS/effect/issues/2719
14
111
  // TODO remove this once the issue is resolved
15
- export const hash = (schema: Schema.Schema<any>) => {
112
+ export const hash = (schema: Schema.Top) => {
16
113
  try {
17
114
  return Hash.string(JSON.stringify(schema.ast, null, 2))
18
115
  } catch {
@@ -23,77 +120,44 @@ export const hash = (schema: Schema.Schema<any>) => {
23
120
  }
24
121
  }
25
122
 
26
- const resolveStructAst = (ast: SchemaAST.AST): SchemaAST.AST => {
27
- if (SchemaAST.isTransformation(ast)) {
28
- return resolveStructAst(ast.from)
29
- }
30
-
31
- return ast
32
- }
33
-
34
- export const getResolvedPropertySignatures = (
35
- schema: Schema.Schema.AnyNoContext,
36
- ): ReadonlyArray<SchemaAST.PropertySignature> => {
37
- const resolvedAst = resolveStructAst(schema.ast)
38
- return SchemaAST.getPropertySignatures(resolvedAst)
123
+ export const getResolvedPropertySignatures = (schema: Schema.Top): ReadonlyArray<SchemaAST.PropertySignature> => {
124
+ const resolvedAst = SchemaAST.toType(schema.ast)
125
+ return SchemaAST.isObjects(resolvedAst) === true ? resolvedAst.propertySignatures : []
39
126
  }
40
127
 
41
128
  export const encodeWithTransferables =
42
- <A, I, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions | undefined) =>
43
- (a: A, overrideOptions?: ParseOptions | undefined): Effect.Effect<[I, Transferable[]], ParseError, R> =>
129
+ <A, I>(schema: Schema.Codec<A, I>, options?: SchemaAST.ParseOptions) =>
130
+ (a: A, overrideOptions?: SchemaAST.ParseOptions) =>
44
131
  Effect.gen(function* () {
45
132
  const collector = yield* Transferable.makeCollector
46
133
 
47
- const encoded: I = yield* Schema.encode(schema, options)(a, overrideOptions).pipe(
134
+ const encoded = yield* Schema.encodeEffect(schema, options)(a, overrideOptions).pipe(
48
135
  Effect.provideService(Transferable.Collector, collector),
49
136
  )
50
137
 
51
- return [encoded, collector.unsafeRead() as Transferable[]]
138
+ return [encoded, collector.readUnsafe()] as const
52
139
  })
53
140
 
54
141
  export const decodeSyncDebug: <A, I>(
55
- schema: Schema.Schema<A, I, never>,
142
+ schema: Schema.Codec<A, I>,
56
143
  options?: SchemaAST.ParseOptions,
57
144
  ) => (i: I, overrideOptions?: SchemaAST.ParseOptions) => A = (schema, options) => (input, overrideOptions) => {
58
- const res = Schema.decodeEither(schema, options)(input, overrideOptions)
59
- if (res._tag === 'Left') {
60
- return shouldNeverHappen(`decodeSyncDebug failed:`, res.left)
145
+ const res = Schema.decodeResult(schema, options)(input, overrideOptions)
146
+ if (Result.isFailure(res) === true) {
147
+ return shouldNeverHappen(`decodeSyncDebug failed:`, res.failure)
61
148
  } else {
62
- return res.right
149
+ return res.success
63
150
  }
64
151
  }
65
152
 
66
153
  export const encodeSyncDebug: <A, I>(
67
- schema: Schema.Schema<A, I, never>,
154
+ schema: Schema.Codec<A, I>,
68
155
  options?: SchemaAST.ParseOptions,
69
156
  ) => (a: A, overrideOptions?: SchemaAST.ParseOptions) => I = (schema, options) => (input, overrideOptions) => {
70
- const res = Schema.encodeEither(schema, options)(input, overrideOptions)
71
- if (res._tag === 'Left') {
72
- return shouldNeverHappen(`encodeSyncDebug failed:`, res.left)
157
+ const res = Schema.encodeResult(schema, options)(input, overrideOptions)
158
+ if (Result.isFailure(res) === true) {
159
+ return shouldNeverHappen(`encodeSyncDebug failed:`, res.failure)
73
160
  } else {
74
- return res.right
161
+ return res.success
75
162
  }
76
163
  }
77
-
78
- export const swap = <A, I, R>(schema: Schema.Schema<A, I, R>): Schema.Schema<I, A, R> =>
79
- Schema.transformOrFail(Schema.typeSchema(schema), Schema.encodedSchema(schema), {
80
- decode: ParseResult.encode(schema),
81
- encode: ParseResult.decode(schema),
82
- })
83
-
84
- export const Base64FromUint8Array: Schema.Schema<string, Uint8Array> = swap(Schema.Uint8ArrayFromBase64)
85
-
86
- export interface JsonArray extends ReadonlyArray<JsonValue> {}
87
- export interface JsonObject {
88
- [key: string]: JsonValue
89
- }
90
- export type JsonValue = string | number | boolean | null | JsonObject | JsonArray
91
-
92
- export const JsonValue: Schema.Schema<JsonValue> = Schema.Union(
93
- Schema.String,
94
- Schema.Number,
95
- Schema.Boolean,
96
- Schema.Null,
97
- Schema.Array(Schema.suspend(() => JsonValue)),
98
- Schema.Record({ key: Schema.String, value: Schema.suspend(() => JsonValue) }),
99
- ).annotations({ title: 'JsonValue' })
@@ -1,5 +1,6 @@
1
- import { Effect, Option, Stream } from 'effect'
1
+ import { Effect, Option, Result, Stream } from 'effect'
2
2
  import { describe, expect, it } from 'vitest'
3
+
3
4
  import { concatWithLastElement, runCollectReadonlyArray } from './Stream.ts'
4
5
 
5
6
  describe('concatWithLastElement', () => {
@@ -9,7 +10,7 @@ describe('concatWithLastElement', () => {
9
10
  lastElement.pipe(
10
11
  Option.match({
11
12
  onNone: () => Stream.make('no-previous'),
12
- onSome: (last) => Stream.make(`last-was-${last}`, 'continuing'),
13
+ onSome: (last) => Stream.make(`last-was-${String(last)}`, 'continuing'),
13
14
  }),
14
15
  ),
15
16
  )
@@ -24,7 +25,7 @@ describe('concatWithLastElement', () => {
24
25
  lastElement.pipe(
25
26
  Option.match({
26
27
  onNone: () => Stream.make('no-previous-element'),
27
- onSome: (last) => Stream.make(`last-was-${last}`),
28
+ onSome: (last) => Stream.make(`last-was-${String(last)}`),
28
29
  }),
29
30
  ),
30
31
  )
@@ -39,7 +40,7 @@ describe('concatWithLastElement', () => {
39
40
  lastElement.pipe(
40
41
  Option.match({
41
42
  onNone: () => Stream.make('unexpected'),
42
- onSome: (last) => Stream.make(`after-${last}`),
43
+ onSome: (last) => Stream.make(`after-${String(last)}`),
43
44
  }),
44
45
  ),
45
46
  )
@@ -60,10 +61,10 @@ describe('concatWithLastElement', () => {
60
61
  const stream1 = Stream.fail('first-error')
61
62
  const result = concatWithLastElement(stream1, () => Stream.make('should-not-reach'))
62
63
 
63
- const outcome = await Effect.runPromise(Effect.either(runCollectReadonlyArray(result)))
64
- expect(outcome._tag).toBe('Left')
65
- if (outcome._tag === 'Left') {
66
- expect(outcome.left).toBe('first-error')
64
+ const outcome = await Effect.runPromise(Effect.result(runCollectReadonlyArray(result)))
65
+ expect(outcome._tag).toBe('Failure')
66
+ if (Result.isFailure(outcome) === true) {
67
+ expect(outcome.failure).toBe('first-error')
67
68
  }
68
69
  })
69
70
 
@@ -71,10 +72,10 @@ describe('concatWithLastElement', () => {
71
72
  const stream1 = Stream.make(1, 2)
72
73
  const result = concatWithLastElement(stream1, () => Stream.fail('second-error'))
73
74
 
74
- const outcome = await Effect.runPromise(Effect.either(runCollectReadonlyArray(result)))
75
- expect(outcome._tag).toBe('Left')
76
- if (outcome._tag === 'Left') {
77
- expect(outcome.left).toBe('second-error')
75
+ const outcome = await Effect.runPromise(Effect.result(runCollectReadonlyArray(result)))
76
+ expect(outcome._tag).toBe('Failure')
77
+ if (Result.isFailure(outcome) === true) {
78
+ expect(outcome.failure).toBe('second-error')
78
79
  }
79
80
  })
80
81
 
@@ -83,7 +84,7 @@ describe('concatWithLastElement', () => {
83
84
  const result = concatWithLastElement(stream1, (lastElement) =>
84
85
  lastElement.pipe(
85
86
  Option.match({
86
- onNone: () => Stream.make('no-number') as Stream.Stream<number | string, never, never>,
87
+ onNone: () => Stream.make('no-number') as Stream.Stream<number | string>,
87
88
  onSome: (last) => Stream.make(last * 10, last * 100),
88
89
  }),
89
90
  ),