@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.
- package/dist/.tsbuildinfo +1 -0
- package/dist/NoopTracer.d.ts +7 -8
- package/dist/NoopTracer.d.ts.map +1 -1
- package/dist/NoopTracer.js +13 -15
- package/dist/NoopTracer.js.map +1 -1
- package/dist/NoopTracer.test.d.ts +2 -0
- package/dist/NoopTracer.test.d.ts.map +1 -0
- package/dist/NoopTracer.test.js +17 -0
- package/dist/NoopTracer.test.js.map +1 -0
- package/dist/binary.js +1 -1
- package/dist/binary.js.map +1 -1
- package/dist/browser/Opfs/Opfs.d.ts +201 -0
- package/dist/browser/Opfs/Opfs.d.ts.map +1 -0
- package/dist/browser/Opfs/Opfs.js +170 -0
- package/dist/browser/Opfs/Opfs.js.map +1 -0
- package/dist/browser/Opfs/debug-utils.d.ts +20 -0
- package/dist/browser/Opfs/debug-utils.d.ts.map +1 -0
- package/dist/browser/Opfs/debug-utils.js +95 -0
- package/dist/browser/Opfs/debug-utils.js.map +1 -0
- package/dist/browser/Opfs/mod.d.ts +4 -0
- package/dist/browser/Opfs/mod.d.ts.map +1 -0
- package/dist/browser/Opfs/mod.js +4 -0
- package/dist/browser/Opfs/mod.js.map +1 -0
- package/dist/browser/Opfs/utils.d.ts +71 -0
- package/dist/browser/Opfs/utils.d.ts.map +1 -0
- package/dist/browser/Opfs/utils.js +227 -0
- package/dist/browser/Opfs/utils.js.map +1 -0
- package/dist/browser/QuotaExceededError.d.ts +60 -0
- package/dist/browser/QuotaExceededError.d.ts.map +1 -0
- package/dist/browser/QuotaExceededError.js +2 -0
- package/dist/browser/QuotaExceededError.js.map +1 -0
- package/dist/browser/WebChannelBrowser.d.ts +22 -0
- package/dist/browser/WebChannelBrowser.d.ts.map +1 -0
- package/dist/browser/WebChannelBrowser.js +87 -0
- package/dist/browser/WebChannelBrowser.js.map +1 -0
- package/dist/browser/WebError.d.ts +389 -0
- package/dist/browser/WebError.d.ts.map +1 -0
- package/dist/browser/WebError.js +423 -0
- package/dist/browser/WebError.js.map +1 -0
- package/dist/browser/WebError.test.d.ts +2 -0
- package/dist/browser/WebError.test.d.ts.map +1 -0
- package/dist/browser/WebError.test.js +46 -0
- package/dist/browser/WebError.test.js.map +1 -0
- package/dist/browser/WebLock.d.ts.map +1 -0
- package/dist/{effect → browser}/WebLock.js +21 -21
- package/dist/browser/WebLock.js.map +1 -0
- package/dist/{browser.d.ts → browser/detect.d.ts} +1 -1
- package/dist/browser/detect.d.ts.map +1 -0
- package/dist/{browser.js → browser/detect.js} +7 -7
- package/dist/browser/detect.js.map +1 -0
- package/dist/browser/mod.d.ts +8 -0
- package/dist/browser/mod.d.ts.map +1 -0
- package/dist/browser/mod.js +8 -0
- package/dist/browser/mod.js.map +1 -0
- package/dist/cuid/cuid.browser.js +1 -1
- package/dist/cuid/cuid.browser.js.map +1 -1
- package/dist/cuid/cuid.node.js +1 -1
- package/dist/cuid/cuid.node.js.map +1 -1
- package/dist/effect/Debug.d.ts +38 -0
- package/dist/effect/Debug.d.ts.map +1 -0
- package/dist/effect/Debug.js +350 -0
- package/dist/effect/Debug.js.map +1 -0
- package/dist/effect/Effect.d.ts +91 -22
- package/dist/effect/Effect.d.ts.map +1 -1
- package/dist/effect/Effect.js +126 -38
- package/dist/effect/Effect.js.map +1 -1
- package/dist/effect/Effect.test.d.ts +2 -0
- package/dist/effect/Effect.test.d.ts.map +1 -0
- package/dist/effect/Effect.test.js +72 -0
- package/dist/effect/Effect.test.js.map +1 -0
- package/dist/effect/Error.d.ts +4 -6
- package/dist/effect/Error.d.ts.map +1 -1
- package/dist/effect/Error.js +1 -1
- package/dist/effect/Error.js.map +1 -1
- package/dist/effect/Logger.d.ts +0 -6
- package/dist/effect/Logger.d.ts.map +1 -1
- package/dist/effect/Logger.js +0 -32
- package/dist/effect/Logger.js.map +1 -1
- package/dist/effect/OtelTracer.d.ts +1 -1
- package/dist/effect/OtelTracer.d.ts.map +1 -1
- package/dist/effect/OtelTracer.js +2 -3
- package/dist/effect/OtelTracer.js.map +1 -1
- package/dist/effect/RpcClient.d.ts +7 -7
- package/dist/effect/RpcClient.d.ts.map +1 -1
- package/dist/effect/RpcClient.js +74 -54
- package/dist/effect/RpcClient.js.map +1 -1
- package/dist/effect/Schedule.d.ts +1 -1
- package/dist/effect/Schedule.d.ts.map +1 -1
- package/dist/effect/Schedule.js +2 -2
- package/dist/effect/Schedule.js.map +1 -1
- package/dist/effect/Schema/debug-diff.d.ts +1 -1
- package/dist/effect/Schema/debug-diff.d.ts.map +1 -1
- package/dist/effect/Schema/debug-diff.js +9 -10
- package/dist/effect/Schema/debug-diff.js.map +1 -1
- package/dist/effect/Schema/debug-diff.test.js +7 -4
- package/dist/effect/Schema/debug-diff.test.js.map +1 -1
- package/dist/effect/Schema/index.d.ts +28 -18
- package/dist/effect/Schema/index.d.ts.map +1 -1
- package/dist/effect/Schema/index.js +55 -28
- package/dist/effect/Schema/index.js.map +1 -1
- package/dist/effect/Stream.d.ts +13 -5
- package/dist/effect/Stream.d.ts.map +1 -1
- package/dist/effect/Stream.js +19 -12
- package/dist/effect/Stream.js.map +1 -1
- package/dist/effect/Stream.test.js +12 -12
- package/dist/effect/Stream.test.js.map +1 -1
- package/dist/effect/Subscribable.d.ts +9 -3
- package/dist/effect/Subscribable.d.ts.map +1 -1
- package/dist/effect/Subscribable.js +20 -35
- package/dist/effect/Subscribable.js.map +1 -1
- package/dist/effect/SubscriptionRef.d.ts +5 -6
- package/dist/effect/SubscriptionRef.d.ts.map +1 -1
- package/dist/effect/SubscriptionRef.js +2 -3
- package/dist/effect/SubscriptionRef.js.map +1 -1
- package/dist/effect/TaskTracing.d.ts +1 -1
- package/dist/effect/TaskTracing.d.ts.map +1 -1
- package/dist/effect/TaskTracing.js +12 -16
- package/dist/effect/TaskTracing.js.map +1 -1
- package/dist/effect/WebChannel/WebChannel.d.ts +11 -30
- package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
- package/dist/effect/WebChannel/WebChannel.js +70 -125
- package/dist/effect/WebChannel/WebChannel.js.map +1 -1
- package/dist/effect/WebChannel/WebChannel.test.js +16 -16
- package/dist/effect/WebChannel/WebChannel.test.js.map +1 -1
- package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts.map +1 -1
- package/dist/effect/WebChannel/broadcastChannelWithAck.js +20 -13
- package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
- package/dist/effect/WebChannel/common.d.ts +17 -18
- package/dist/effect/WebChannel/common.d.ts.map +1 -1
- package/dist/effect/WebChannel/common.js +7 -7
- package/dist/effect/WebChannel/common.js.map +1 -1
- package/dist/effect/WebSocket.d.ts +4 -6
- package/dist/effect/WebSocket.d.ts.map +1 -1
- package/dist/effect/WebSocket.js +17 -17
- package/dist/effect/WebSocket.js.map +1 -1
- package/dist/effect/WebSocket.test.js +2 -2
- package/dist/effect/WebSocket.test.js.map +1 -1
- package/dist/effect/mod.browser-build.test.d.ts +2 -0
- package/dist/effect/mod.browser-build.test.d.ts.map +1 -0
- package/dist/effect/mod.browser-build.test.js +18 -0
- package/dist/effect/mod.browser-build.test.js.map +1 -0
- package/dist/effect/mod.d.ts +30 -0
- package/dist/effect/mod.d.ts.map +1 -0
- package/dist/effect/mod.js +30 -0
- package/dist/effect/mod.js.map +1 -0
- package/dist/effect/spanEvent.d.ts +12 -0
- package/dist/effect/spanEvent.d.ts.map +1 -0
- package/dist/effect/spanEvent.js +12 -0
- package/dist/effect/spanEvent.js.map +1 -0
- package/dist/effect/spanEvent.test.d.ts +2 -0
- package/dist/effect/spanEvent.test.d.ts.map +1 -0
- package/dist/effect/spanEvent.test.js +79 -0
- package/dist/effect/spanEvent.test.js.map +1 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +1 -1
- package/dist/env.js.map +1 -1
- package/dist/fast-deep-equal.d.ts.map +1 -1
- package/dist/fast-deep-equal.js +9 -10
- package/dist/fast-deep-equal.js.map +1 -1
- package/dist/global.d.ts +3 -0
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js.map +1 -1
- package/dist/misc.d.ts +9 -1
- package/dist/misc.d.ts.map +1 -1
- package/dist/misc.js +12 -4
- package/dist/misc.js.map +1 -1
- package/dist/mod.d.ts +177 -20
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +159 -22
- package/dist/mod.js.map +1 -1
- package/dist/node/mod.d.ts +45 -6
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +51 -9
- package/dist/node/mod.js.map +1 -1
- package/dist/object/index.d.ts +0 -9
- package/dist/object/index.d.ts.map +1 -1
- package/dist/object/index.js +0 -9
- package/dist/object/index.js.map +1 -1
- package/dist/object/stringify-object.js +2 -2
- package/dist/object/stringify-object.js.map +1 -1
- package/dist/object/stringify-object.test.js.map +1 -1
- package/dist/qr.d.ts +38 -0
- package/dist/qr.d.ts.map +1 -0
- package/dist/qr.js +109 -0
- package/dist/qr.js.map +1 -0
- package/dist/set.js +1 -1
- package/dist/set.js.map +1 -1
- package/dist/string.d.ts +0 -2
- package/dist/string.d.ts.map +1 -1
- package/dist/string.js +0 -2
- package/dist/string.js.map +1 -1
- package/package.json +61 -55
- package/src/NoopTracer.test.ts +20 -0
- package/src/NoopTracer.ts +28 -37
- package/src/binary.ts +1 -1
- package/src/browser/Opfs/Opfs.ts +463 -0
- package/src/browser/Opfs/debug-utils.ts +154 -0
- package/src/browser/Opfs/mod.ts +3 -0
- package/src/browser/Opfs/utils.ts +297 -0
- package/src/browser/QuotaExceededError.ts +60 -0
- package/src/browser/WebChannelBrowser.ts +145 -0
- package/src/browser/WebError.test.ts +66 -0
- package/src/browser/WebError.ts +587 -0
- package/src/{effect → browser}/WebLock.ts +27 -28
- package/src/{browser.ts → browser/detect.ts} +6 -6
- package/src/browser/mod.ts +8 -0
- package/src/cuid/cuid.browser.ts +1 -1
- package/src/cuid/cuid.node.ts +1 -1
- package/src/effect/Debug.ts +477 -0
- package/src/effect/Effect.test.ts +117 -0
- package/src/effect/Effect.ts +174 -79
- package/src/effect/Error.ts +1 -1
- package/src/effect/Logger.ts +0 -48
- package/src/effect/OtelTracer.ts +2 -3
- package/src/effect/RpcClient.ts +85 -65
- package/src/effect/Schedule.ts +4 -5
- package/src/effect/Schema/debug-diff.test.ts +7 -7
- package/src/effect/Schema/debug-diff.ts +11 -12
- package/src/effect/Schema/index.ts +121 -57
- package/src/effect/Stream.test.ts +14 -13
- package/src/effect/Stream.ts +23 -16
- package/src/effect/Subscribable.ts +31 -42
- package/src/effect/SubscriptionRef.ts +9 -13
- package/src/effect/TaskTracing.ts +13 -16
- package/src/effect/WebChannel/WebChannel.test.ts +24 -24
- package/src/effect/WebChannel/WebChannel.ts +102 -192
- package/src/effect/WebChannel/broadcastChannelWithAck.ts +25 -15
- package/src/effect/WebChannel/common.ts +16 -17
- package/src/effect/WebSocket.test.ts +2 -2
- package/src/effect/WebSocket.ts +20 -16
- package/src/effect/mod.browser-build.test.ts +19 -0
- package/src/effect/{index.ts → mod.ts} +43 -69
- package/src/effect/spanEvent.test.ts +92 -0
- package/src/effect/spanEvent.ts +17 -0
- package/src/env.ts +2 -1
- package/src/fast-deep-equal.ts +9 -10
- package/src/global.ts +4 -2
- package/src/misc.ts +13 -5
- package/src/mod.ts +188 -32
- package/src/node/mod.ts +57 -12
- package/src/object/index.ts +0 -24
- package/src/object/stringify-object.test.ts +1 -0
- package/src/object/stringify-object.ts +2 -2
- package/src/qr.ts +125 -0
- package/src/set.ts +1 -1
- package/src/string.ts +0 -3
- package/dist/.tsbuildinfo.json +0 -1
- package/dist/browser.d.ts.map +0 -1
- package/dist/browser.js.map +0 -1
- package/dist/effect/BucketQueue.d.ts +0 -20
- package/dist/effect/BucketQueue.d.ts.map +0 -1
- package/dist/effect/BucketQueue.js +0 -34
- package/dist/effect/BucketQueue.js.map +0 -1
- package/dist/effect/Scheduler.d.ts +0 -4
- package/dist/effect/Scheduler.d.ts.map +0 -1
- package/dist/effect/Scheduler.js +0 -9
- package/dist/effect/Scheduler.js.map +0 -1
- package/dist/effect/ServiceContext.d.ts +0 -37
- package/dist/effect/ServiceContext.d.ts.map +0 -1
- package/dist/effect/ServiceContext.js +0 -55
- package/dist/effect/ServiceContext.js.map +0 -1
- package/dist/effect/WebLock.d.ts.map +0 -1
- package/dist/effect/WebLock.js.map +0 -1
- package/dist/effect/index.d.ts +0 -32
- package/dist/effect/index.d.ts.map +0 -1
- package/dist/effect/index.js +0 -35
- package/dist/effect/index.js.map +0 -1
- package/dist/guards.d.ts +0 -6
- package/dist/guards.d.ts.map +0 -1
- package/dist/guards.js +0 -6
- package/dist/guards.js.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts +0 -4
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js +0 -122
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts +0 -2
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +0 -218
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +0 -84
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js +0 -68
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts +0 -2
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +0 -52
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts +0 -23
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js +0 -138
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +0 -1
- package/dist/object/omit.d.ts +0 -3
- package/dist/object/omit.d.ts.map +0 -1
- package/dist/object/omit.js +0 -14
- package/dist/object/omit.js.map +0 -1
- package/dist/object/pick.d.ts +0 -14
- package/dist/object/pick.d.ts.map +0 -1
- package/dist/object/pick.js +0 -17
- package/dist/object/pick.js.map +0 -1
- package/dist/time.d.ts +0 -12
- package/dist/time.d.ts.map +0 -1
- package/dist/time.js +0 -22
- package/dist/time.js.map +0 -1
- package/src/effect/BucketQueue.ts +0 -49
- package/src/effect/Scheduler.ts +0 -13
- package/src/effect/ServiceContext.ts +0 -108
- package/src/guards.ts +0 -8
- package/src/node/ChildProcessRunner/ChildProcessRunner.ts +0 -135
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +0 -302
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +0 -78
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +0 -66
- package/src/node/ChildProcessRunner/ChildProcessWorker.ts +0 -168
- package/src/object/omit.ts +0 -17
- package/src/object/pick.ts +0 -27
- package/src/time.ts +0 -25
- /package/dist/{effect → browser}/WebLock.d.ts +0 -0
package/src/effect/RpcClient.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export * from '
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import { RpcClient, RpcClientError, RpcSerialization } from '
|
|
5
|
-
import { Protocol } from '
|
|
6
|
-
import { constPing, type FromServerEncoded } from '
|
|
7
|
-
import {
|
|
8
|
-
|
|
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.
|
|
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['
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
88
|
+
return broadcast({
|
|
81
89
|
_tag: 'ClientProtocolError',
|
|
82
90
|
error: new RpcClientError.RpcClientError({
|
|
83
|
-
reason:
|
|
84
|
-
|
|
85
|
-
|
|
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.
|
|
93
|
-
pinger.timeout,
|
|
101
|
+
Effect.flatMap(pinger.timeout, () =>
|
|
94
102
|
Effect.fail(
|
|
95
|
-
new Socket.
|
|
96
|
-
reason:
|
|
97
|
-
|
|
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.
|
|
114
|
+
Effect.flatMap(() =>
|
|
105
115
|
Effect.fail(
|
|
106
|
-
new Socket.
|
|
107
|
-
reason:
|
|
108
|
-
|
|
109
|
-
|
|
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.
|
|
124
|
+
Effect.tapCause(
|
|
114
125
|
Effect.fn(function* (cause) {
|
|
115
126
|
// CHANGED: set isConnected to false on error
|
|
116
|
-
|
|
117
|
-
yield* SubscriptionRef.set(options.isConnected, false)
|
|
118
|
-
}
|
|
127
|
+
yield* SubscriptionRef.set(options.isConnected, false)
|
|
119
128
|
|
|
120
|
-
const error = Cause.
|
|
129
|
+
const error = Cause.findError(cause)
|
|
121
130
|
if (
|
|
122
|
-
options?.retryTransientErrors &&
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
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:
|
|
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.
|
|
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.
|
|
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
|
|
194
|
+
const manualPingDeferreds = new Set<Deferred.Deferred<void>>()
|
|
175
195
|
|
|
176
196
|
let recievedPong = true
|
|
177
|
-
const latch =
|
|
197
|
+
const latch = Latch.makeUnsafe()
|
|
178
198
|
const reset = () => {
|
|
179
199
|
recievedPong = true
|
|
180
|
-
latch.
|
|
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.
|
|
206
|
+
Deferred.doneUnsafe(deferred, Effect.void)
|
|
187
207
|
}
|
|
188
208
|
}
|
|
189
209
|
yield* Effect.suspend(() => {
|
|
190
210
|
// Starting new ping
|
|
191
|
-
if (
|
|
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
|
|
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
|
|
package/src/effect/Schedule.ts
CHANGED
|
@@ -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
|
|
5
|
+
export const exponentialBackoff10Sec = pipe(
|
|
6
6
|
Schedule.exponential(Duration.millis(10), 4), // 10ms, 40ms, 160ms, 640ms, 2560ms, ...
|
|
7
|
-
Schedule.
|
|
8
|
-
Schedule.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
79
|
-
Schema.
|
|
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.
|
|
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.
|
|
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.
|
|
39
|
-
const
|
|
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.
|
|
54
|
-
|
|
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 {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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 '../../
|
|
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.
|
|
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
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
43
|
-
(a: A, overrideOptions?: ParseOptions
|
|
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
|
|
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.
|
|
138
|
+
return [encoded, collector.readUnsafe()] as const
|
|
52
139
|
})
|
|
53
140
|
|
|
54
141
|
export const decodeSyncDebug: <A, I>(
|
|
55
|
-
schema: Schema.
|
|
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.
|
|
59
|
-
if (res
|
|
60
|
-
return shouldNeverHappen(`decodeSyncDebug failed:`, res.
|
|
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.
|
|
149
|
+
return res.success
|
|
63
150
|
}
|
|
64
151
|
}
|
|
65
152
|
|
|
66
153
|
export const encodeSyncDebug: <A, I>(
|
|
67
|
-
schema: Schema.
|
|
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.
|
|
71
|
-
if (res
|
|
72
|
-
return shouldNeverHappen(`encodeSyncDebug failed:`, res.
|
|
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.
|
|
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.
|
|
64
|
-
expect(outcome._tag).toBe('
|
|
65
|
-
if (outcome
|
|
66
|
-
expect(outcome.
|
|
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.
|
|
75
|
-
expect(outcome._tag).toBe('
|
|
76
|
-
if (outcome
|
|
77
|
-
expect(outcome.
|
|
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
|
|
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
|
),
|