@livestore/utils 0.4.0-dev.8 → 0.4.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.map +1 -1
- package/dist/NoopTracer.js +17 -4
- package/dist/NoopTracer.js.map +1 -1
- package/dist/binary.js +1 -1
- package/dist/binary.js.map +1 -1
- package/dist/browser/Opfs/Opfs.d.ts +51 -0
- package/dist/browser/Opfs/Opfs.d.ts.map +1 -0
- package/dist/browser/Opfs/Opfs.js +345 -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 +94 -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 +218 -0
- package/dist/browser/Opfs/utils.js.map +1 -0
- package/dist/browser/QuotaExceededError.d.ts +59 -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 +76 -0
- package/dist/browser/WebChannelBrowser.js.map +1 -0
- package/dist/browser/WebError.d.ts +421 -0
- package/dist/browser/WebError.d.ts.map +1 -0
- package/dist/browser/WebError.js +416 -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 +9 -9
- 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/BucketQueue.d.ts +1 -1
- package/dist/effect/BucketQueue.d.ts.map +1 -1
- package/dist/effect/BucketQueue.js.map +1 -1
- package/dist/effect/Debug.d.ts +41 -0
- package/dist/effect/Debug.d.ts.map +1 -0
- package/dist/effect/Debug.js +354 -0
- package/dist/effect/Debug.js.map +1 -0
- package/dist/effect/Effect.d.ts +72 -12
- package/dist/effect/Effect.d.ts.map +1 -1
- package/dist/effect/Effect.js +96 -12
- package/dist/effect/Effect.js.map +1 -1
- package/dist/effect/Error.js +1 -1
- package/dist/effect/Error.js.map +1 -1
- package/dist/effect/Logger.js +2 -2
- package/dist/effect/Logger.js.map +1 -1
- package/dist/effect/RpcClient.d.ts.map +1 -1
- package/dist/effect/RpcClient.js +11 -4
- package/dist/effect/RpcClient.js.map +1 -1
- package/dist/effect/Schema/debug-diff.js +5 -4
- package/dist/effect/Schema/debug-diff.js.map +1 -1
- package/dist/effect/Schema/debug-diff.test.js +1 -1
- package/dist/effect/Schema/debug-diff.test.js.map +1 -1
- package/dist/effect/Schema/index.d.ts +5 -3
- package/dist/effect/Schema/index.d.ts.map +1 -1
- package/dist/effect/Schema/index.js +2 -2
- package/dist/effect/Schema/index.js.map +1 -1
- package/dist/effect/ServiceContext.js +6 -6
- package/dist/effect/ServiceContext.js.map +1 -1
- package/dist/effect/Stream.test.js +3 -3
- package/dist/effect/Stream.test.js.map +1 -1
- package/dist/effect/SubscriptionRef.d.ts +4 -4
- package/dist/effect/SubscriptionRef.d.ts.map +1 -1
- package/dist/effect/WebChannel/WebChannel.d.ts +4 -23
- package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
- package/dist/effect/WebChannel/WebChannel.js +9 -85
- package/dist/effect/WebChannel/WebChannel.js.map +1 -1
- package/dist/effect/WebChannel/WebChannel.test.js +1 -1
- package/dist/effect/WebChannel/WebChannel.test.js.map +1 -1
- package/dist/effect/WebChannel/broadcastChannelWithAck.js +4 -4
- package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
- package/dist/effect/WebChannel/common.d.ts +2 -2
- package/dist/effect/WebChannel/common.d.ts.map +1 -1
- package/dist/effect/WebChannel/common.js +2 -2
- package/dist/effect/WebChannel/common.js.map +1 -1
- package/dist/effect/WebSocket.d.ts.map +1 -1
- package/dist/effect/WebSocket.js +14 -14
- package/dist/effect/WebSocket.js.map +1 -1
- package/dist/effect/{index.d.ts → mod.d.ts} +4 -4
- package/dist/effect/mod.d.ts.map +1 -0
- package/dist/effect/{index.js → mod.js} +5 -5
- 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 +82 -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.js +9 -9
- 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/guards.d.ts +14 -0
- package/dist/guards.d.ts.map +1 -1
- package/dist/guards.js +14 -0
- package/dist/guards.js.map +1 -1
- package/dist/misc.d.ts +9 -1
- package/dist/misc.d.ts.map +1 -1
- package/dist/misc.js +11 -3
- package/dist/misc.js.map +1 -1
- package/dist/mod.d.ts +197 -5
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +162 -17
- package/dist/mod.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js +15 -9
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts +8 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +16 -17
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +4 -4
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +3 -3
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js +4 -4
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +1 -1
- package/dist/node/mod.d.ts +34 -1
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +37 -2
- package/dist/node/mod.js.map +1 -1
- package/dist/object/index.d.ts.map +1 -1
- package/dist/object/index.js.map +1 -1
- package/dist/object/omit.js +1 -1
- package/dist/object/omit.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/time.js +1 -1
- package/dist/time.js.map +1 -1
- package/package.json +78 -54
- package/src/NoopTracer.ts +22 -8
- package/src/binary.ts +1 -1
- package/src/browser/Opfs/Opfs.ts +436 -0
- package/src/browser/Opfs/debug-utils.ts +153 -0
- package/src/browser/Opfs/mod.ts +3 -0
- package/src/browser/Opfs/utils.ts +287 -0
- package/src/browser/QuotaExceededError.ts +57 -0
- package/src/browser/WebChannelBrowser.ts +131 -0
- package/src/browser/WebError.test.ts +66 -0
- package/src/browser/WebError.ts +613 -0
- package/src/{effect → browser}/WebLock.ts +15 -15
- 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/BucketQueue.ts +1 -1
- package/src/effect/Debug.ts +470 -0
- package/src/effect/Effect.ts +118 -36
- package/src/effect/Error.ts +1 -1
- package/src/effect/Logger.ts +2 -2
- package/src/effect/RpcClient.ts +14 -6
- package/src/effect/Schema/debug-diff.test.ts +2 -2
- package/src/effect/Schema/debug-diff.ts +6 -5
- package/src/effect/Schema/index.ts +10 -7
- package/src/effect/ServiceContext.ts +6 -6
- package/src/effect/Stream.test.ts +5 -4
- package/src/effect/SubscriptionRef.ts +5 -5
- package/src/effect/WebChannel/WebChannel.test.ts +1 -1
- package/src/effect/WebChannel/WebChannel.ts +19 -141
- package/src/effect/WebChannel/broadcastChannelWithAck.ts +4 -4
- package/src/effect/WebChannel/common.ts +5 -5
- package/src/effect/WebSocket.ts +13 -12
- package/src/effect/{index.ts → mod.ts} +10 -2
- package/src/effect/spanEvent.test.ts +95 -0
- package/src/effect/spanEvent.ts +15 -0
- package/src/env.ts +2 -1
- package/src/fast-deep-equal.ts +9 -9
- package/src/global.ts +4 -2
- package/src/guards.ts +15 -0
- package/src/misc.ts +12 -4
- package/src/mod.ts +209 -17
- package/src/node/ChildProcessRunner/ChildProcessRunner.ts +23 -10
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +30 -21
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +10 -11
- package/src/node/ChildProcessRunner/ChildProcessWorker.ts +5 -4
- package/src/node/mod.ts +41 -2
- package/src/object/index.ts +1 -1
- package/src/object/omit.ts +1 -1
- 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/time.ts +1 -1
- package/dist/.tsbuildinfo.json +0 -1
- package/dist/browser.d.ts.map +0 -1
- package/dist/browser.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.map +0 -1
- package/dist/effect/index.js.map +0 -1
- /package/dist/{effect → browser}/WebLock.d.ts +0 -0
package/src/effect/Effect.ts
CHANGED
|
@@ -6,9 +6,6 @@ import {
|
|
|
6
6
|
Duration,
|
|
7
7
|
Effect,
|
|
8
8
|
Fiber,
|
|
9
|
-
FiberRef,
|
|
10
|
-
HashSet,
|
|
11
|
-
Logger,
|
|
12
9
|
pipe,
|
|
13
10
|
Scope,
|
|
14
11
|
type Stream,
|
|
@@ -18,10 +15,11 @@ import { log } from 'effect/Console'
|
|
|
18
15
|
import { dual, type LazyArg } from 'effect/Function'
|
|
19
16
|
import type { Predicate, Refinement } from 'effect/Predicate'
|
|
20
17
|
|
|
21
|
-
import { isPromise } from '../mod.ts'
|
|
18
|
+
import { isDevEnv, isPromise, objectToString } from '../mod.ts'
|
|
22
19
|
import { UnknownError } from './Error.ts'
|
|
23
20
|
|
|
24
21
|
export * from 'effect/Effect'
|
|
22
|
+
export { spanEvent } from './spanEvent.ts'
|
|
25
23
|
|
|
26
24
|
// export const log = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
|
|
27
25
|
// Effect.sync(() => {
|
|
@@ -57,16 +55,16 @@ export type SyncOrPromiseOrEffect<TResult, TError = never, TContext = never> =
|
|
|
57
55
|
|
|
58
56
|
export const tryAll = <Res>(
|
|
59
57
|
fn: () => Res,
|
|
60
|
-
): Res extends Effect.Effect<infer A, infer E
|
|
61
|
-
? Effect.Effect<A, E | UnknownException
|
|
58
|
+
): Res extends Effect.Effect<infer A, infer E>
|
|
59
|
+
? Effect.Effect<A, E | UnknownException>
|
|
62
60
|
: Res extends Promise<infer A>
|
|
63
|
-
? Effect.Effect<A, UnknownException
|
|
64
|
-
: Effect.Effect<Res, UnknownException
|
|
61
|
+
? Effect.Effect<A, UnknownException>
|
|
62
|
+
: Effect.Effect<Res, UnknownException> =>
|
|
65
63
|
Effect.try(() => fn()).pipe(
|
|
66
64
|
Effect.andThen((fnRes) =>
|
|
67
|
-
Effect.isEffect(fnRes)
|
|
65
|
+
Effect.isEffect(fnRes) === true
|
|
68
66
|
? (fnRes as any as Effect.Effect<any>)
|
|
69
|
-
: isPromise(fnRes)
|
|
67
|
+
: isPromise(fnRes) === true
|
|
70
68
|
? Effect.promise(() => fnRes)
|
|
71
69
|
: Effect.succeed(fnRes),
|
|
72
70
|
),
|
|
@@ -89,7 +87,7 @@ export const logBefore =
|
|
|
89
87
|
export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
90
88
|
Effect.tapErrorCause(eff, (cause) =>
|
|
91
89
|
Effect.gen(function* () {
|
|
92
|
-
if (Cause.isInterruptedOnly(cause)) {
|
|
90
|
+
if (Cause.isInterruptedOnly(cause) === true) {
|
|
93
91
|
// console.log('interrupted', Cause.pretty(err), err)
|
|
94
92
|
return
|
|
95
93
|
}
|
|
@@ -107,6 +105,47 @@ export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.
|
|
|
107
105
|
}),
|
|
108
106
|
)
|
|
109
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Creates a defect, pausing at a breakpoint in development.
|
|
110
|
+
*
|
|
111
|
+
* @param msg - The error message to include in the defect.
|
|
112
|
+
* @param args - Arbitrary arguments available for inspection during debugging.
|
|
113
|
+
*
|
|
114
|
+
* @see {@link shouldNeverHappen} for the non-Effect equivalent that throws synchronously.
|
|
115
|
+
* @see {@link orDieDebugger}
|
|
116
|
+
*/
|
|
117
|
+
export const dieDebugger = (msg: string, ...args: ReadonlyArray<unknown>): Effect.Effect<never> =>
|
|
118
|
+
Effect.suspend(() => {
|
|
119
|
+
if (isDevEnv() === true) {
|
|
120
|
+
// oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint during development
|
|
121
|
+
debugger
|
|
122
|
+
void args // Keeps the variable in scope so it's inspectable when the debugger pauses
|
|
123
|
+
}
|
|
124
|
+
return Effect.dieMessage(msg)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Converts a failure into a defect, pausing at a breakpoint in development.
|
|
129
|
+
*
|
|
130
|
+
* @param self - The effect on which to apply the operation.
|
|
131
|
+
*
|
|
132
|
+
* @see {@link Effect.orDie}
|
|
133
|
+
* @see {@link dieDebugger}
|
|
134
|
+
*/
|
|
135
|
+
export const orDieDebugger = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, never, R> =>
|
|
136
|
+
Effect.matchEffect(self, {
|
|
137
|
+
onFailure: (error) =>
|
|
138
|
+
// Keep the debugger hook so that `debugger` runs only when the wrapped effect actually fails, not while building the wrapper.
|
|
139
|
+
Effect.dieSync(() => {
|
|
140
|
+
if (isDevEnv() === true) {
|
|
141
|
+
// oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint for impossible states during development
|
|
142
|
+
debugger
|
|
143
|
+
}
|
|
144
|
+
return error
|
|
145
|
+
}),
|
|
146
|
+
onSuccess: Effect.succeed,
|
|
147
|
+
})
|
|
148
|
+
|
|
110
149
|
export const ignoreIf: {
|
|
111
150
|
<E, EB extends E>(
|
|
112
151
|
refinement: Refinement<NoInfer<E>, EB>,
|
|
@@ -124,11 +163,11 @@ export const ignoreIf: {
|
|
|
124
163
|
export const eventListener = <TEvent = unknown>(
|
|
125
164
|
target: Stream.EventListener<TEvent>,
|
|
126
165
|
type: string,
|
|
127
|
-
handler: (event: TEvent) => Effect.Effect<void
|
|
166
|
+
handler: (event: TEvent) => Effect.Effect<void>,
|
|
128
167
|
options?: { once?: boolean },
|
|
129
168
|
) =>
|
|
130
169
|
Effect.gen(function* () {
|
|
131
|
-
const runtime = yield* Effect.runtime
|
|
170
|
+
const runtime = yield* Effect.runtime()
|
|
132
171
|
|
|
133
172
|
const handlerFn = (event: TEvent) => handler(event).pipe(Effect.provide(runtime), Effect.runFork)
|
|
134
173
|
|
|
@@ -137,16 +176,11 @@ export const eventListener = <TEvent = unknown>(
|
|
|
137
176
|
yield* Effect.addFinalizer(() => Effect.sync(() => target.removeEventListener(type, handlerFn)))
|
|
138
177
|
})
|
|
139
178
|
|
|
140
|
-
export const spanEvent = (message: any, attributes?: Record<string, any>) =>
|
|
141
|
-
Effect.locallyWith(Effect.log(message).pipe(Effect.annotateLogs(attributes ?? {})), FiberRef.currentLoggers, () =>
|
|
142
|
-
HashSet.make(Logger.tracerLogger),
|
|
143
|
-
)
|
|
144
|
-
|
|
145
179
|
export const logWarnIfTakesLongerThan =
|
|
146
180
|
({ label, duration }: { label: string; duration: Duration.DurationInput }) =>
|
|
147
181
|
<R, E, A>(eff: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
148
182
|
Effect.gen(function* () {
|
|
149
|
-
const runtime = yield* Effect.runtime
|
|
183
|
+
const runtime = yield* Effect.runtime()
|
|
150
184
|
|
|
151
185
|
let tookLongerThanTimer = false
|
|
152
186
|
|
|
@@ -154,7 +188,7 @@ export const logWarnIfTakesLongerThan =
|
|
|
154
188
|
Effect.tap(() => {
|
|
155
189
|
tookLongerThanTimer = true
|
|
156
190
|
// TODO include span info
|
|
157
|
-
return Effect.logWarning(`${label}: Took longer than ${duration}ms`)
|
|
191
|
+
return Effect.logWarning(`${label}: Took longer than ${objectToString(duration)}ms`)
|
|
158
192
|
}),
|
|
159
193
|
Effect.provide(runtime),
|
|
160
194
|
Effect.runFork,
|
|
@@ -169,13 +203,14 @@ export const logWarnIfTakesLongerThan =
|
|
|
169
203
|
|
|
170
204
|
yield* Fiber.interrupt(timeoutFiber)
|
|
171
205
|
|
|
172
|
-
if (tookLongerThanTimer) {
|
|
206
|
+
if (tookLongerThanTimer === true) {
|
|
173
207
|
yield* Effect.logWarning(`${label}: Interrupted after ${end - start}ms`)
|
|
174
208
|
}
|
|
175
209
|
}),
|
|
176
210
|
),
|
|
177
211
|
)
|
|
178
212
|
|
|
213
|
+
// eslint-disable-next-line overeng/explicit-boolean-compare -- mutated in forked fiber; TS can't see the mutation
|
|
179
214
|
if (tookLongerThanTimer) {
|
|
180
215
|
const end = Date.now()
|
|
181
216
|
yield* Effect.logWarning(`${label}: Actual duration: ${end - start}ms`)
|
|
@@ -208,19 +243,61 @@ export const debugLogEnv = (msg?: string): Effect.Effect<Context.Context<never>>
|
|
|
208
243
|
Effect.tap((env) => log(msg ?? 'debugLogEnv', env)),
|
|
209
244
|
)
|
|
210
245
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Enforces a time limit on an effect, triggering a defect on timeout.
|
|
248
|
+
*
|
|
249
|
+
* @remarks
|
|
250
|
+
*
|
|
251
|
+
* This function allows you to enforce a time limit on the execution of an
|
|
252
|
+
* effect. If the effect does not complete within the given duration, it dies
|
|
253
|
+
* with a {@link Cause.TimeoutException} as an unchecked defect. Unlike
|
|
254
|
+
* {@link Effect.timeout}, which adds `TimeoutException` to the error channel,
|
|
255
|
+
* this function keeps the error channel unchanged by treating the timeout as
|
|
256
|
+
* a defect.
|
|
257
|
+
*
|
|
258
|
+
* The returned effect will either:
|
|
259
|
+
* - Succeed with the original effect's result if it completes within the
|
|
260
|
+
* specified duration.
|
|
261
|
+
* - Die with a {@link Cause.TimeoutException} defect if the time limit is exceeded.
|
|
262
|
+
*
|
|
263
|
+
* @see {@link timeoutOrDieMessage} for a version with a custom message.
|
|
264
|
+
* @see {@link Effect.timeout} for a version that raises a `TimeoutException` as a typed error.
|
|
265
|
+
* @see {@link Effect.timeoutFailCause} for a version that raises a custom defect.
|
|
266
|
+
*/
|
|
267
|
+
export const timeoutOrDie = (duration: Duration.DurationInput) =>
|
|
268
|
+
<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
269
|
+
Effect.timeoutFailCause(self, {
|
|
270
|
+
duration,
|
|
271
|
+
onTimeout: () => Cause.die(new Cause.TimeoutException())
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Enforces a time limit on an effect, triggering a defect with a custom
|
|
276
|
+
* message on timeout.
|
|
277
|
+
*
|
|
278
|
+
* @remarks
|
|
279
|
+
*
|
|
280
|
+
* This function behaves like {@link timeoutOrDie}, but allows you to provide
|
|
281
|
+
* a custom message for the {@link Cause.TimeoutException} defect. This is useful
|
|
282
|
+
* for adding context about which operation timed out, making it easier to
|
|
283
|
+
* diagnose issues in logs or error reports.
|
|
284
|
+
*
|
|
285
|
+
* The returned effect will either:
|
|
286
|
+
* - Succeed with the original effect's result if it completes within the
|
|
287
|
+
* specified duration.
|
|
288
|
+
* - Die with a {@link Cause.TimeoutException} defect containing the provided
|
|
289
|
+
* message if the time limit is exceeded.
|
|
290
|
+
*
|
|
291
|
+
* @see {@link timeoutOrDie} for a version without a custom message.
|
|
292
|
+
* @see {@link Effect.timeout} for a version that raises a `TimeoutException` as a typed error.
|
|
293
|
+
* @see {@link Effect.timeoutFailCause} for a version that raises a custom defect.
|
|
294
|
+
*/
|
|
295
|
+
export const timeoutOrDieMessage = (duration: Duration.DurationInput, message: string) =>
|
|
296
|
+
<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
297
|
+
Effect.timeoutFailCause(self, {
|
|
298
|
+
duration,
|
|
299
|
+
onTimeout: () => Cause.die(new Cause.TimeoutException(message))
|
|
300
|
+
})
|
|
224
301
|
|
|
225
302
|
export const toForkedDeferred = <R, E, A>(
|
|
226
303
|
eff: Effect.Effect<A, E, R>,
|
|
@@ -274,7 +351,12 @@ const getSpanTrace = () => {
|
|
|
274
351
|
|
|
275
352
|
const logSpanTrace = () => console.log(getSpanTrace())
|
|
276
353
|
|
|
277
|
-
|
|
354
|
+
declare global {
|
|
355
|
+
/** Debug helper: returns the current Effect span trace */
|
|
356
|
+
var getSpanTrace: () => string
|
|
357
|
+
/** Debug helper: logs the current Effect span trace */
|
|
358
|
+
var logSpanTrace: () => void
|
|
359
|
+
}
|
|
360
|
+
|
|
278
361
|
globalThis.getSpanTrace = getSpanTrace
|
|
279
|
-
// @ts-expect-error TODO fix types
|
|
280
362
|
globalThis.logSpanTrace = logSpanTrace
|
package/src/effect/Error.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schema } from 'effect'
|
|
2
2
|
|
|
3
|
-
export class UnknownError extends Schema.TaggedError<UnknownError>()('UnknownError', {
|
|
3
|
+
export class UnknownError extends Schema.TaggedError<UnknownError>('~@livestore/utils/UnknownError')('UnknownError', {
|
|
4
4
|
cause: Schema.Any,
|
|
5
5
|
payload: Schema.optional(Schema.Any),
|
|
6
6
|
}) {}
|
package/src/effect/Logger.ts
CHANGED
|
@@ -23,7 +23,7 @@ export const consoleLogger = (threadName: string) =>
|
|
|
23
23
|
const consoleFn =
|
|
24
24
|
logLevel === LogLevel.Debug
|
|
25
25
|
? // Cloudflare Workers doesn't support console.debug 🤷
|
|
26
|
-
isCloudflareWorker
|
|
26
|
+
isCloudflareWorker === true
|
|
27
27
|
? console.log
|
|
28
28
|
: console.debug
|
|
29
29
|
: logLevel === LogLevel.Info
|
|
@@ -34,7 +34,7 @@ export const consoleLogger = (threadName: string) =>
|
|
|
34
34
|
|
|
35
35
|
const annotationsObj = Object.fromEntries(HashMap.entries(annotations))
|
|
36
36
|
|
|
37
|
-
const messages = Array.isArray(message) ? message : [message]
|
|
37
|
+
const messages = Array.isArray(message) === true ? message : [message]
|
|
38
38
|
if (Cause.isEmpty(cause) === false) {
|
|
39
39
|
messages.push(Cause.pretty(cause, { renderErrorCause: true }))
|
|
40
40
|
}
|
package/src/effect/RpcClient.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Protocol } from '@effect/rpc/RpcClient'
|
|
|
6
6
|
import { constPing, type FromServerEncoded } from '@effect/rpc/RpcMessage'
|
|
7
7
|
import { Cause, Deferred, Effect, Layer, Option, Schedule, type Scope } from 'effect'
|
|
8
8
|
import { constVoid, identity } from 'effect/Function'
|
|
9
|
+
|
|
9
10
|
import * as SubscriptionRef from './SubscriptionRef.ts'
|
|
10
11
|
|
|
11
12
|
// This is based on `makeProtocolSocket` / `layerProtocolSocket` from `@effect/rpc` in order to:
|
|
@@ -40,6 +41,10 @@ export const makeProtocolSocketWithIsConnected = (options: {
|
|
|
40
41
|
const pinger = yield* makePinger(write(parser.encode(constPing)!), options?.pingSchedule)
|
|
41
42
|
|
|
42
43
|
yield* Effect.suspend(() => {
|
|
44
|
+
// We rely on the heartbeat watchdog while streaming arbitrarily long payloads.
|
|
45
|
+
// Reset the timer as soon as _any_ frame arrives so that large batches which
|
|
46
|
+
// don't contain explicit `Pong` messages don't trigger the open-timeout defect.
|
|
47
|
+
// (The actual pong handler still calls `onPong()` to resolve manual pings.)
|
|
43
48
|
// CHANGED: don't reset parser on every message
|
|
44
49
|
// parser = serialization.unsafeMake()
|
|
45
50
|
pinger.reset()
|
|
@@ -53,6 +58,9 @@ export const makeProtocolSocketWithIsConnected = (options: {
|
|
|
53
58
|
while: () => i < responses.length,
|
|
54
59
|
body: () => {
|
|
55
60
|
const response = responses[i++]!
|
|
61
|
+
// Keep extending the watchdog for each data frame to avoid
|
|
62
|
+
// disconnecting mid-stream when the server is busy sending batches.
|
|
63
|
+
pinger.reset()
|
|
56
64
|
if (response._tag === 'Pong') {
|
|
57
65
|
pinger.onPong()
|
|
58
66
|
}
|
|
@@ -112,8 +120,8 @@ export const makeProtocolSocketWithIsConnected = (options: {
|
|
|
112
120
|
|
|
113
121
|
const error = Cause.failureOption(cause)
|
|
114
122
|
if (
|
|
115
|
-
options?.retryTransientErrors &&
|
|
116
|
-
Option.isSome(error) &&
|
|
123
|
+
options?.retryTransientErrors !== undefined &&
|
|
124
|
+
Option.isSome(error) === true &&
|
|
117
125
|
(error.value.reason === 'Open' || error.value.reason === 'OpenTimeout')
|
|
118
126
|
) {
|
|
119
127
|
return
|
|
@@ -130,7 +138,7 @@ export const makeProtocolSocketWithIsConnected = (options: {
|
|
|
130
138
|
}),
|
|
131
139
|
),
|
|
132
140
|
// CHANGED: make configurable via schedule
|
|
133
|
-
options?.retryTransientErrors ? Effect.retry(options.retryTransientErrors) : identity,
|
|
141
|
+
options?.retryTransientErrors !== undefined ? Effect.retry(options.retryTransientErrors) : identity,
|
|
134
142
|
Effect.annotateLogs({
|
|
135
143
|
module: 'RpcClient',
|
|
136
144
|
method: 'makeProtocolSocket',
|
|
@@ -164,7 +172,7 @@ const makePinger = Effect.fnUntraced(function* <A, E, R>(
|
|
|
164
172
|
pingSchedule: Schedule.Schedule<unknown> = Schedule.spaced(10000).pipe(Schedule.addDelay(() => 5000)),
|
|
165
173
|
) {
|
|
166
174
|
// CHANGED: add manual ping deferreds
|
|
167
|
-
const manualPingDeferreds = new Set<Deferred.Deferred<void
|
|
175
|
+
const manualPingDeferreds = new Set<Deferred.Deferred<void>>()
|
|
168
176
|
|
|
169
177
|
let recievedPong = true
|
|
170
178
|
const latch = Effect.unsafeMakeLatch()
|
|
@@ -181,7 +189,7 @@ const makePinger = Effect.fnUntraced(function* <A, E, R>(
|
|
|
181
189
|
}
|
|
182
190
|
yield* Effect.suspend(() => {
|
|
183
191
|
// Starting new ping
|
|
184
|
-
if (
|
|
192
|
+
if (recievedPong === false) return latch.open
|
|
185
193
|
recievedPong = false
|
|
186
194
|
return writePing
|
|
187
195
|
}).pipe(
|
|
@@ -195,7 +203,7 @@ const makePinger = Effect.fnUntraced(function* <A, E, R>(
|
|
|
195
203
|
|
|
196
204
|
// CHANGED: add manual ping
|
|
197
205
|
const ping = Effect.gen(function* () {
|
|
198
|
-
const deferred = yield* Deferred.make<void
|
|
206
|
+
const deferred = yield* Deferred.make<void>()
|
|
199
207
|
manualPingDeferreds.add(deferred)
|
|
200
208
|
yield* deferred
|
|
201
209
|
manualPingDeferreds.delete(deferred)
|
|
@@ -75,8 +75,8 @@ describe('debug-diff', () => {
|
|
|
75
75
|
|
|
76
76
|
test('tagged union', () => {
|
|
77
77
|
const schema = Schema.Union(
|
|
78
|
-
Schema.
|
|
79
|
-
Schema.
|
|
78
|
+
Schema.TaggedStruct('a', { a: Schema.String }),
|
|
79
|
+
Schema.TaggedStruct('b', { b: Schema.Number }),
|
|
80
80
|
)
|
|
81
81
|
const a = { _tag: 'a', a: 'hello' } as const
|
|
82
82
|
const b = { _tag: 'b', b: 1 } as const
|
|
@@ -23,8 +23,8 @@ const debugDiffImpl = (ast: SchemaAST.AST, a: any, b: any, path: string, bag: Di
|
|
|
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,7 +35,7 @@ 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)) {
|
|
38
|
+
} else if (SchemaAST.isTypeLiteral(ast) === true) {
|
|
39
39
|
const props = SchemaAST.getPropertySignatures(ast)
|
|
40
40
|
for (const prop of props) {
|
|
41
41
|
debugDiffImpl(prop.type, a[prop.name], b[prop.name], `${path}.${prop.name.toString()}`, bag)
|
|
@@ -47,12 +47,13 @@ const debugDiffImpl = (ast: SchemaAST.AST, a: any, b: any, path: string, bag: Di
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
const isTaggedUnion = (ast: SchemaAST.AST) => {
|
|
51
|
-
if (SchemaAST.isUnion(ast)) {
|
|
50
|
+
const isTaggedUnion = (ast: SchemaAST.AST): boolean => {
|
|
51
|
+
if (SchemaAST.isUnion(ast) === true) {
|
|
52
52
|
return ast.types.every((type) => {
|
|
53
53
|
if (SchemaAST.isTypeLiteral(type) === false) return false
|
|
54
54
|
const props = SchemaAST.getPropertySignatures(type)
|
|
55
55
|
return props.some((prop) => prop.name.toString() === '_tag')
|
|
56
56
|
})
|
|
57
57
|
}
|
|
58
|
+
return false
|
|
58
59
|
}
|
|
@@ -24,7 +24,7 @@ export const hash = (schema: Schema.Schema<any>) => {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const resolveStructAst = (ast: SchemaAST.AST): SchemaAST.AST => {
|
|
27
|
-
if (SchemaAST.isTransformation(ast)) {
|
|
27
|
+
if (SchemaAST.isTransformation(ast) === true) {
|
|
28
28
|
return resolveStructAst(ast.from)
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -38,9 +38,12 @@ export const getResolvedPropertySignatures = (
|
|
|
38
38
|
return SchemaAST.getPropertySignatures(resolvedAst)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** Objects that can be transferred between contexts (workers, etc.) */
|
|
42
|
+
type TransferableObject = ArrayBuffer | MessagePort
|
|
43
|
+
|
|
41
44
|
export const encodeWithTransferables =
|
|
42
|
-
<A, I, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions
|
|
43
|
-
(a: A, overrideOptions?: ParseOptions
|
|
45
|
+
<A, I, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions) =>
|
|
46
|
+
(a: A, overrideOptions?: ParseOptions): Effect.Effect<[I, TransferableObject[]], ParseError, R> =>
|
|
44
47
|
Effect.gen(function* () {
|
|
45
48
|
const collector = yield* Transferable.makeCollector
|
|
46
49
|
|
|
@@ -48,11 +51,11 @@ export const encodeWithTransferables =
|
|
|
48
51
|
Effect.provideService(Transferable.Collector, collector),
|
|
49
52
|
)
|
|
50
53
|
|
|
51
|
-
return [encoded, collector.unsafeRead() as
|
|
54
|
+
return [encoded, collector.unsafeRead() as TransferableObject[]]
|
|
52
55
|
})
|
|
53
56
|
|
|
54
57
|
export const decodeSyncDebug: <A, I>(
|
|
55
|
-
schema: Schema.Schema<A, I
|
|
58
|
+
schema: Schema.Schema<A, I>,
|
|
56
59
|
options?: SchemaAST.ParseOptions,
|
|
57
60
|
) => (i: I, overrideOptions?: SchemaAST.ParseOptions) => A = (schema, options) => (input, overrideOptions) => {
|
|
58
61
|
const res = Schema.decodeEither(schema, options)(input, overrideOptions)
|
|
@@ -64,7 +67,7 @@ export const decodeSyncDebug: <A, I>(
|
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
export const encodeSyncDebug: <A, I>(
|
|
67
|
-
schema: Schema.Schema<A, I
|
|
70
|
+
schema: Schema.Schema<A, I>,
|
|
68
71
|
options?: SchemaAST.ParseOptions,
|
|
69
72
|
) => (a: A, overrideOptions?: SchemaAST.ParseOptions) => I = (schema, options) => (input, overrideOptions) => {
|
|
70
73
|
const res = Schema.encodeEither(schema, options)(input, overrideOptions)
|
|
@@ -96,4 +99,4 @@ export const JsonValue: Schema.Schema<JsonValue> = Schema.Union(
|
|
|
96
99
|
Schema.Null,
|
|
97
100
|
Schema.Array(Schema.suspend(() => JsonValue)),
|
|
98
101
|
Schema.Record({ key: Schema.String, value: Schema.suspend(() => JsonValue) }),
|
|
99
|
-
).annotations({
|
|
102
|
+
).annotations({ identifier: 'JsonValue' })
|
|
@@ -24,13 +24,13 @@ export const make = <TStaticData, Ctx>(
|
|
|
24
24
|
close: Effect.Effect<void> = Effect.dieMessage('close not implemented'),
|
|
25
25
|
): ServiceContext<Ctx, TStaticData> => {
|
|
26
26
|
return {
|
|
27
|
-
provide: (self) => Effect.provide(runtime)
|
|
28
|
-
runWithErrorLog: <E, A>(self: Effect.Effect<A, E, Ctx>) => runWithErrorLog(Effect.provide(runtime)
|
|
29
|
-
runSync: <E, A>(self: Effect.Effect<A, E, Ctx>) => Effect.runSync(Effect.provide(runtime)
|
|
27
|
+
provide: (self) => self.pipe(Effect.provide(runtime)),
|
|
28
|
+
runWithErrorLog: <E, A>(self: Effect.Effect<A, E, Ctx>) => runWithErrorLog(self.pipe(Effect.provide(runtime))),
|
|
29
|
+
runSync: <E, A>(self: Effect.Effect<A, E, Ctx>) => Effect.runSync(self.pipe(Effect.provide(runtime))),
|
|
30
30
|
runPromiseWithErrorLog: <E, A>(self: Effect.Effect<A, E, Ctx>) =>
|
|
31
|
-
runPromiseWithErrorLog(Effect.provide(runtime)
|
|
32
|
-
runPromiseExit: <E, A>(self: Effect.Effect<A, E, Ctx>) => Effect.runPromiseExit(Effect.provide(runtime)
|
|
33
|
-
runPromise: <E, A>(self: Effect.Effect<A, E, Ctx>) => Effect.runPromise(Effect.provide(runtime)
|
|
31
|
+
runPromiseWithErrorLog(self.pipe(Effect.provide(runtime))),
|
|
32
|
+
runPromiseExit: <E, A>(self: Effect.Effect<A, E, Ctx>) => Effect.runPromiseExit(self.pipe(Effect.provide(runtime))),
|
|
33
|
+
runPromise: <E, A>(self: Effect.Effect<A, E, Ctx>) => Effect.runPromise(self.pipe(Effect.provide(runtime))),
|
|
34
34
|
withRuntime: (fn) => fn(runtime),
|
|
35
35
|
close: close,
|
|
36
36
|
closePromise: () => Effect.runPromise(close),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Effect, Option, 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
|
)
|
|
@@ -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
|
),
|
|
@@ -5,17 +5,17 @@ import type { Predicate, Refinement } from 'effect/Predicate'
|
|
|
5
5
|
export * from 'effect/SubscriptionRef'
|
|
6
6
|
|
|
7
7
|
export const waitUntil: {
|
|
8
|
-
|
|
8
|
+
<A, B extends A>(
|
|
9
9
|
refinement: Refinement<NoInfer<A>, B>,
|
|
10
|
-
): (sref: SubscriptionRef.SubscriptionRef<A>) => Effect.Effect<B
|
|
10
|
+
): (sref: SubscriptionRef.SubscriptionRef<A>) => Effect.Effect<B>
|
|
11
11
|
<A, B extends A>(
|
|
12
12
|
predicate: Predicate<B>,
|
|
13
|
-
): (sref: SubscriptionRef.SubscriptionRef<A>) => Effect.Effect<A
|
|
13
|
+
): (sref: SubscriptionRef.SubscriptionRef<A>) => Effect.Effect<A>
|
|
14
14
|
<A, B extends A>(
|
|
15
15
|
sref: SubscriptionRef.SubscriptionRef<A>,
|
|
16
16
|
refinement: Refinement<NoInfer<A>, B>,
|
|
17
|
-
): Effect.Effect<B
|
|
18
|
-
<A, B extends A>(sref: SubscriptionRef.SubscriptionRef<A>, predicate: Predicate<B>): Effect.Effect<A
|
|
17
|
+
): Effect.Effect<B>
|
|
18
|
+
<A, B extends A>(sref: SubscriptionRef.SubscriptionRef<A>, predicate: Predicate<B>): Effect.Effect<A>
|
|
19
19
|
} = dual(2, <A>(sref: SubscriptionRef.SubscriptionRef<A>, predicate: (a: A) => boolean) =>
|
|
20
20
|
pipe(sref.changes, Stream.filter(predicate), Stream.take(1), Stream.runCollect, Effect.map(Chunk.unsafeHead)),
|
|
21
21
|
)
|
|
@@ -2,7 +2,7 @@ import * as Vitest from '@effect/vitest'
|
|
|
2
2
|
import { Effect, Schema, Stream } from 'effect'
|
|
3
3
|
import { JSDOM } from 'jsdom'
|
|
4
4
|
|
|
5
|
-
import * as WebChannel from '
|
|
5
|
+
import * as WebChannel from '../../browser/WebChannelBrowser.ts'
|
|
6
6
|
|
|
7
7
|
Vitest.describe('WebChannel', () => {
|
|
8
8
|
Vitest.describe('windowChannel', () => {
|