@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
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, expect, expectTypeOf, it } from '@effect/vitest'
|
|
2
|
+
import { Cause, Effect } from 'effect'
|
|
3
|
+
|
|
4
|
+
import { trySyncOrPromiseOrEffect } from './Effect.ts'
|
|
5
|
+
|
|
6
|
+
interface RequiredService {
|
|
7
|
+
readonly RequiredService: unique symbol
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare const contextualEffect: Effect.Effect<number, 'effect-error', RequiredService>
|
|
11
|
+
|
|
12
|
+
describe('trySyncOrPromiseOrEffect', () => {
|
|
13
|
+
it.effect('returns a plain value', () =>
|
|
14
|
+
Effect.gen(function* () {
|
|
15
|
+
const result = yield* trySyncOrPromiseOrEffect(() => 42 as const)
|
|
16
|
+
|
|
17
|
+
expect(result).toBe(42)
|
|
18
|
+
}),
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
it.effect('evaluates the operation lazily for each execution', () =>
|
|
22
|
+
Effect.gen(function* () {
|
|
23
|
+
let executions = 0
|
|
24
|
+
const effect = trySyncOrPromiseOrEffect(() => ++executions)
|
|
25
|
+
|
|
26
|
+
expect(executions).toBe(0)
|
|
27
|
+
expect(yield* effect).toBe(1)
|
|
28
|
+
expect(yield* effect).toBe(2)
|
|
29
|
+
}),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
it.effect('maps a synchronous throw to an UnknownError', () =>
|
|
33
|
+
Effect.gen(function* () {
|
|
34
|
+
const thrown = new Error('thrown')
|
|
35
|
+
const failure = yield* trySyncOrPromiseOrEffect(() => {
|
|
36
|
+
throw thrown
|
|
37
|
+
}).pipe(Effect.flip)
|
|
38
|
+
|
|
39
|
+
expect(failure).toBeInstanceOf(Cause.UnknownError)
|
|
40
|
+
if (failure instanceof Cause.UnknownError) {
|
|
41
|
+
expect(failure.cause).toBe(thrown)
|
|
42
|
+
}
|
|
43
|
+
}),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
it.effect('awaits a resolving Promise', () =>
|
|
47
|
+
Effect.gen(function* () {
|
|
48
|
+
const result = yield* trySyncOrPromiseOrEffect(() => Promise.resolve('resolved'))
|
|
49
|
+
|
|
50
|
+
expect(result).toBe('resolved')
|
|
51
|
+
}),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
it.effect('maps a rejected Promise to an UnknownError', () =>
|
|
55
|
+
Effect.gen(function* () {
|
|
56
|
+
const rejected = new Error('rejected')
|
|
57
|
+
const failure = yield* trySyncOrPromiseOrEffect(() => Promise.reject(rejected)).pipe(Effect.flip)
|
|
58
|
+
|
|
59
|
+
expect(failure).toBeInstanceOf(Cause.UnknownError)
|
|
60
|
+
if (failure instanceof Cause.UnknownError) {
|
|
61
|
+
expect(failure.cause).toBe(rejected)
|
|
62
|
+
}
|
|
63
|
+
}),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
it.effect('maps a throwing Promise-like then getter to an UnknownError', () =>
|
|
67
|
+
Effect.gen(function* () {
|
|
68
|
+
const thrown = new Error('throwing then getter')
|
|
69
|
+
const thenable = {
|
|
70
|
+
// oxlint-disable-next-line eslint-plugin-unicorn(no-thenable) -- intentionally exercises Promise-like classification
|
|
71
|
+
get then(): PromiseLike<never>['then'] {
|
|
72
|
+
throw thrown
|
|
73
|
+
},
|
|
74
|
+
} satisfies PromiseLike<never>
|
|
75
|
+
|
|
76
|
+
const failure = yield* trySyncOrPromiseOrEffect(() => thenable).pipe(Effect.flip)
|
|
77
|
+
|
|
78
|
+
expect(failure).toBeInstanceOf(Cause.UnknownError)
|
|
79
|
+
if (failure instanceof Cause.UnknownError) {
|
|
80
|
+
expect(failure.cause).toBe(thrown)
|
|
81
|
+
}
|
|
82
|
+
}),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
it.effect('executes and returns the value of a returned Effect', () =>
|
|
86
|
+
Effect.gen(function* () {
|
|
87
|
+
const result = yield* trySyncOrPromiseOrEffect(() => Effect.succeed('effect-value'))
|
|
88
|
+
|
|
89
|
+
expect(result).toBe('effect-value')
|
|
90
|
+
}),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
it.effect('preserves a returned Effect failure', () =>
|
|
94
|
+
Effect.gen(function* () {
|
|
95
|
+
const expected = { _tag: 'ExpectedError' as const }
|
|
96
|
+
const failure = yield* trySyncOrPromiseOrEffect(() => Effect.fail(expected)).pipe(Effect.flip)
|
|
97
|
+
|
|
98
|
+
expect(failure).toBe(expected)
|
|
99
|
+
}),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
it('preserves returned Effect success, error, and requirements types', () => {
|
|
103
|
+
const normalized = trySyncOrPromiseOrEffect(() => contextualEffect)
|
|
104
|
+
|
|
105
|
+
expectTypeOf(normalized).toEqualTypeOf<
|
|
106
|
+
Effect.Effect<number, 'effect-error' | Cause.UnknownError, RequiredService>
|
|
107
|
+
>()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('returns an Effect when the operation only throws', () => {
|
|
111
|
+
const normalized = trySyncOrPromiseOrEffect((): never => {
|
|
112
|
+
throw new Error('thrown')
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
expectTypeOf(normalized).toEqualTypeOf<Effect.Effect<never, Cause.UnknownError>>()
|
|
116
|
+
})
|
|
117
|
+
})
|
package/src/effect/Effect.ts
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
import * as OtelTracer from '@effect/opentelemetry/
|
|
1
|
+
import * as OtelTracer from '@effect/opentelemetry/OtelTracer'
|
|
2
2
|
import {
|
|
3
3
|
Cause,
|
|
4
|
+
Console,
|
|
4
5
|
type Context,
|
|
5
6
|
Deferred,
|
|
6
7
|
Duration,
|
|
7
8
|
Effect,
|
|
9
|
+
Function,
|
|
8
10
|
Fiber,
|
|
9
|
-
FiberRef,
|
|
10
|
-
HashSet,
|
|
11
|
-
Logger,
|
|
12
11
|
pipe,
|
|
12
|
+
Predicate,
|
|
13
13
|
Scope,
|
|
14
14
|
type Stream,
|
|
15
15
|
} from 'effect'
|
|
16
|
-
import type { UnknownException } from 'effect/Cause'
|
|
17
|
-
import { log } from 'effect/Console'
|
|
18
|
-
import { dual, type LazyArg } from 'effect/Function'
|
|
19
|
-
import type { Predicate, Refinement } from 'effect/Predicate'
|
|
20
16
|
|
|
21
|
-
import {
|
|
22
|
-
import { UnknownError } from './Error.ts'
|
|
17
|
+
import { isDevEnv, objectToString } from '../misc.ts'
|
|
23
18
|
|
|
24
19
|
export * from 'effect/Effect'
|
|
20
|
+
export { spanEvent } from './spanEvent.ts'
|
|
25
21
|
|
|
26
22
|
// export const log = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
|
|
27
23
|
// Effect.sync(() => {
|
|
@@ -38,16 +34,14 @@ export * from 'effect/Effect'
|
|
|
38
34
|
// console.error(message, ...rest)
|
|
39
35
|
// })
|
|
40
36
|
|
|
41
|
-
/** Same as `Effect.scopeWith` but with a
|
|
37
|
+
/** Same as `Effect.scopeWith` but with a closeable `Scope`. */
|
|
42
38
|
export const scopeWithCloseable = <R, E, A>(
|
|
43
|
-
fn: (scope: Scope.
|
|
39
|
+
fn: (scope: Scope.Closeable) => Effect.Effect<A, E, R | Scope.Scope>,
|
|
44
40
|
): Effect.Effect<A, E, R | Scope.Scope> =>
|
|
45
41
|
Effect.gen(function* () {
|
|
46
|
-
// const parentScope = yield* Scope.Scope
|
|
47
|
-
// const scope = yield* Scope.fork(parentScope, ExecutionStrategy.sequential)
|
|
48
42
|
const scope = yield* Scope.make()
|
|
49
43
|
yield* Effect.addFinalizer((exit) => Scope.close(scope, exit))
|
|
50
|
-
return yield* fn(scope).pipe(Scope.
|
|
44
|
+
return yield* fn(scope).pipe(Scope.provide(scope))
|
|
51
45
|
})
|
|
52
46
|
|
|
53
47
|
export type SyncOrPromiseOrEffect<TResult, TError = never, TContext = never> =
|
|
@@ -55,22 +49,43 @@ export type SyncOrPromiseOrEffect<TResult, TError = never, TContext = never> =
|
|
|
55
49
|
| Promise<TResult>
|
|
56
50
|
| Effect.Effect<TResult, TError, TContext>
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Creates an Effect from an operation that may return a value, a Promise-like value, or another Effect.
|
|
54
|
+
*
|
|
55
|
+
* @remarks
|
|
56
|
+
* Synchronous values succeed directly, and Promise-like values are awaited. Synchronous throws and Promise rejections
|
|
57
|
+
* are mapped to `Cause.UnknownError`. When the operation returns an Effect, that Effect is executed rather than
|
|
58
|
+
* produced as a successful value; its failures and service requirements are preserved.
|
|
59
|
+
*
|
|
60
|
+
* @param operation - A callback that may return a synchronous value, a Promise-like value, or an Effect
|
|
61
|
+
* @returns An Effect representing the normalized outcome of the operation
|
|
62
|
+
*/
|
|
63
|
+
export function trySyncOrPromiseOrEffect<Return>(
|
|
64
|
+
operation: () => Return,
|
|
65
|
+
): Effect.Effect<
|
|
66
|
+
Return extends Effect.Effect<infer A, infer _E, infer _R> ? A : Return extends PromiseLike<infer A> ? A : Return,
|
|
67
|
+
Cause.UnknownError | (Return extends Effect.Effect<infer _A, infer E, infer _R> ? E : never),
|
|
68
|
+
Return extends Effect.Effect<infer _A, infer _E, infer R> ? R : never
|
|
69
|
+
>
|
|
70
|
+
export function trySyncOrPromiseOrEffect(operation: () => unknown): Effect.Effect<unknown, unknown, unknown> {
|
|
71
|
+
return Effect.try({
|
|
72
|
+
try: () => {
|
|
73
|
+
const result = operation()
|
|
74
|
+
|
|
75
|
+
if (Effect.isEffect(result) === true) {
|
|
76
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off -- dynamic implementation boundary; the public overload preserves exact Effect error and requirement channels
|
|
77
|
+
return result
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (Predicate.isPromiseLike(result) === true) {
|
|
81
|
+
return Effect.tryPromise(() => result)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return Effect.succeed(result)
|
|
85
|
+
},
|
|
86
|
+
catch: (cause) => new Cause.UnknownError(cause),
|
|
87
|
+
}).pipe(Effect.flatten)
|
|
88
|
+
}
|
|
74
89
|
|
|
75
90
|
export const acquireReleaseLog = (label: string) =>
|
|
76
91
|
Effect.acquireRelease(Effect.log(`${label} acquire`), (_, ex) => Effect.log(`${label} release`, ex))
|
|
@@ -87,16 +102,11 @@ export const logBefore =
|
|
|
87
102
|
|
|
88
103
|
/** Logs both on errors and defects */
|
|
89
104
|
export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
90
|
-
Effect.
|
|
105
|
+
Effect.tapCause(eff, (cause) =>
|
|
91
106
|
Effect.gen(function* () {
|
|
92
|
-
if (Cause.
|
|
93
|
-
// console.log('interrupted', Cause.pretty(err), err)
|
|
94
|
-
return
|
|
95
|
-
}
|
|
107
|
+
if (Cause.hasInterruptsOnly(cause) === true) return
|
|
96
108
|
|
|
97
|
-
const span = yield* OtelTracer.currentOtelSpan.pipe(
|
|
98
|
-
Effect.catchTag('NoSuchElementException', (_) => Effect.succeed(undefined)),
|
|
99
|
-
)
|
|
109
|
+
const span = yield* OtelTracer.currentOtelSpan.pipe(Effect.catchTag('NoSuchElementError', (_) => Effect.void))
|
|
100
110
|
|
|
101
111
|
const firstErrLine = cause.toString().split('\n')[0]
|
|
102
112
|
yield* Effect.logError(firstErrLine, cause).pipe((_) =>
|
|
@@ -107,46 +117,82 @@ export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.
|
|
|
107
117
|
}),
|
|
108
118
|
)
|
|
109
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Creates a defect, pausing at a breakpoint in development.
|
|
122
|
+
*
|
|
123
|
+
* @param msg - The error message to include in the defect.
|
|
124
|
+
* @param args - Arbitrary arguments available for inspection during debugging.
|
|
125
|
+
*
|
|
126
|
+
* @see {@link shouldNeverHappen} for the non-Effect equivalent that throws synchronously.
|
|
127
|
+
* @see {@link orDieDebugger}
|
|
128
|
+
*/
|
|
129
|
+
export const dieDebugger = (msg: string, ...args: ReadonlyArray<unknown>): Effect.Effect<never> =>
|
|
130
|
+
Effect.suspend(() => {
|
|
131
|
+
if (isDevEnv() === true) {
|
|
132
|
+
// oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint during development
|
|
133
|
+
debugger
|
|
134
|
+
void args // Keeps the variable in scope so it's inspectable when the debugger pauses
|
|
135
|
+
}
|
|
136
|
+
return Effect.die(new Error(msg))
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Converts a failure into a defect, pausing at a breakpoint in development.
|
|
141
|
+
*
|
|
142
|
+
* @param self - The effect on which to apply the operation.
|
|
143
|
+
*
|
|
144
|
+
* @see {@link Effect.orDie}
|
|
145
|
+
* @see {@link dieDebugger}
|
|
146
|
+
*/
|
|
147
|
+
export const orDieDebugger = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, never, R> =>
|
|
148
|
+
Effect.matchEffect(self, {
|
|
149
|
+
onFailure: (error) =>
|
|
150
|
+
// Keep the debugger hook so that `debugger` runs only when the wrapped effect actually fails, not while building the wrapper.
|
|
151
|
+
Effect.suspend(() => {
|
|
152
|
+
if (isDevEnv() === true) {
|
|
153
|
+
// oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint for impossible states during development
|
|
154
|
+
debugger
|
|
155
|
+
}
|
|
156
|
+
return Effect.die(error)
|
|
157
|
+
}),
|
|
158
|
+
onSuccess: Effect.succeed,
|
|
159
|
+
})
|
|
160
|
+
|
|
110
161
|
export const ignoreIf: {
|
|
111
162
|
<E, EB extends E>(
|
|
112
|
-
refinement: Refinement<NoInfer<E>, EB>,
|
|
163
|
+
refinement: Predicate.Refinement<NoInfer<E>, EB>,
|
|
113
164
|
): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, Exclude<E, EB>, R>
|
|
114
|
-
<E>(predicate: Predicate<NoInfer<E>>): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, E, R>
|
|
165
|
+
<E>(predicate: Predicate.Predicate<NoInfer<E>>): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, E, R>
|
|
115
166
|
<A, E, R, EB extends E>(
|
|
116
167
|
self: Effect.Effect<A, E, R>,
|
|
117
|
-
refinement: Refinement<E, EB>,
|
|
168
|
+
refinement: Predicate.Refinement<E, EB>,
|
|
118
169
|
): Effect.Effect<void, Exclude<E, EB>, R>
|
|
119
|
-
<A, E, R>(self: Effect.Effect<A, E, R>, predicate: Predicate<E>): Effect.Effect<void, E, R>
|
|
120
|
-
} = dual(2, <A, E, R>(self: Effect.Effect<A, E, R>, predicate: Predicate<E>) =>
|
|
170
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, predicate: Predicate.Predicate<E>): Effect.Effect<void, E, R>
|
|
171
|
+
} = Function.dual(2, <A, E, R>(self: Effect.Effect<A, E, R>, predicate: Predicate.Predicate<E>) =>
|
|
121
172
|
self.pipe(Effect.catchIf(predicate, () => Effect.void)),
|
|
122
173
|
)
|
|
123
174
|
|
|
124
175
|
export const eventListener = <TEvent = unknown>(
|
|
125
176
|
target: Stream.EventListener<TEvent>,
|
|
126
177
|
type: string,
|
|
127
|
-
handler: (event: TEvent) => Effect.Effect<void
|
|
178
|
+
handler: (event: TEvent) => Effect.Effect<void>,
|
|
128
179
|
options?: { once?: boolean },
|
|
129
180
|
) =>
|
|
130
181
|
Effect.gen(function* () {
|
|
131
|
-
const
|
|
182
|
+
const services = yield* Effect.context()
|
|
132
183
|
|
|
133
|
-
const handlerFn = (event: TEvent) => handler(event).pipe(Effect.
|
|
184
|
+
const handlerFn = (event: TEvent) => handler(event).pipe(Effect.runForkWith(services))
|
|
134
185
|
|
|
135
186
|
target.addEventListener(type, handlerFn, { once: options?.once ?? false })
|
|
136
187
|
|
|
137
188
|
yield* Effect.addFinalizer(() => Effect.sync(() => target.removeEventListener(type, handlerFn)))
|
|
138
189
|
})
|
|
139
190
|
|
|
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
191
|
export const logWarnIfTakesLongerThan =
|
|
146
|
-
({ label, duration }: { label: string; duration: Duration.
|
|
192
|
+
({ label, duration }: { label: string; duration: Duration.Input }) =>
|
|
147
193
|
<R, E, A>(eff: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
148
194
|
Effect.gen(function* () {
|
|
149
|
-
const
|
|
195
|
+
const services = yield* Effect.context()
|
|
150
196
|
|
|
151
197
|
let tookLongerThanTimer = false
|
|
152
198
|
|
|
@@ -154,10 +200,9 @@ export const logWarnIfTakesLongerThan =
|
|
|
154
200
|
Effect.tap(() => {
|
|
155
201
|
tookLongerThanTimer = true
|
|
156
202
|
// TODO include span info
|
|
157
|
-
return Effect.logWarning(`${label}: Took longer than ${duration}ms`)
|
|
203
|
+
return Effect.logWarning(`${label}: Took longer than ${objectToString(duration)}ms`)
|
|
158
204
|
}),
|
|
159
|
-
Effect.
|
|
160
|
-
Effect.runFork,
|
|
205
|
+
Effect.runForkWith(services),
|
|
161
206
|
)
|
|
162
207
|
|
|
163
208
|
const start = Date.now()
|
|
@@ -169,13 +214,14 @@ export const logWarnIfTakesLongerThan =
|
|
|
169
214
|
|
|
170
215
|
yield* Fiber.interrupt(timeoutFiber)
|
|
171
216
|
|
|
172
|
-
if (tookLongerThanTimer) {
|
|
217
|
+
if (tookLongerThanTimer === true) {
|
|
173
218
|
yield* Effect.logWarning(`${label}: Interrupted after ${end - start}ms`)
|
|
174
219
|
}
|
|
175
220
|
}),
|
|
176
221
|
),
|
|
177
222
|
)
|
|
178
223
|
|
|
224
|
+
// eslint-disable-next-line overeng/explicit-boolean-compare -- mutated in forked fiber; TS can't see the mutation
|
|
179
225
|
if (tookLongerThanTimer) {
|
|
180
226
|
const end = Date.now()
|
|
181
227
|
yield* Effect.logWarning(`${label}: Actual duration: ${end - start}ms`)
|
|
@@ -193,7 +239,7 @@ export const logDuration =
|
|
|
193
239
|
const start = Date.now()
|
|
194
240
|
const res = yield* eff
|
|
195
241
|
const end = Date.now()
|
|
196
|
-
yield* Effect.log(`${label}: ${Duration.format(end - start)}`)
|
|
242
|
+
yield* Effect.log(`${label}: ${Duration.format(Duration.millis(end - start))}`)
|
|
197
243
|
return res
|
|
198
244
|
})
|
|
199
245
|
|
|
@@ -205,22 +251,66 @@ export const tapSync =
|
|
|
205
251
|
export const debugLogEnv = (msg?: string): Effect.Effect<Context.Context<never>> =>
|
|
206
252
|
pipe(
|
|
207
253
|
Effect.context<never>(),
|
|
208
|
-
Effect.tap((env) => log(msg ?? 'debugLogEnv', env)),
|
|
254
|
+
Effect.tap((env) => Console.log(msg ?? 'debugLogEnv', env)),
|
|
209
255
|
)
|
|
210
256
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Enforces a time limit on an effect, triggering a defect on timeout.
|
|
259
|
+
*
|
|
260
|
+
* @remarks
|
|
261
|
+
*
|
|
262
|
+
* This function allows you to enforce a time limit on the execution of an
|
|
263
|
+
* effect. If the effect does not complete within the given duration, it dies
|
|
264
|
+
* with a {@link Cause.TimeoutError} as an unchecked defect. Unlike
|
|
265
|
+
* {@link Effect.timeout}, which adds `TimeoutError` to the error channel,
|
|
266
|
+
* this function keeps the error channel unchanged by treating the timeout as
|
|
267
|
+
* a defect.
|
|
268
|
+
*
|
|
269
|
+
* The returned effect will either:
|
|
270
|
+
* - Succeed with the original effect's result if it completes within the
|
|
271
|
+
* specified duration.
|
|
272
|
+
* - Die with a {@link Cause.TimeoutError} defect if the time limit is exceeded.
|
|
273
|
+
*
|
|
274
|
+
* @see {@link timeoutOrDieMessage} for a version with a custom message.
|
|
275
|
+
* @see {@link Effect.timeout} for a version that raises a `TimeoutError` as a typed error.
|
|
276
|
+
* @see {@link Effect.timeoutOrElse} for a version with a custom timeout branch.
|
|
277
|
+
*/
|
|
278
|
+
export const timeoutOrDie =
|
|
279
|
+
(duration: Duration.Input) =>
|
|
280
|
+
<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
281
|
+
Effect.timeoutOrElse(self, {
|
|
282
|
+
duration,
|
|
283
|
+
orElse: () => Effect.die(new Cause.TimeoutError()),
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Enforces a time limit on an effect, triggering a defect with a custom
|
|
288
|
+
* message on timeout.
|
|
289
|
+
*
|
|
290
|
+
* @remarks
|
|
291
|
+
*
|
|
292
|
+
* This function behaves like {@link timeoutOrDie}, but allows you to provide
|
|
293
|
+
* a custom message for the {@link Cause.TimeoutError} defect. This is useful
|
|
294
|
+
* for adding context about which operation timed out, making it easier to
|
|
295
|
+
* diagnose issues in logs or error reports.
|
|
296
|
+
*
|
|
297
|
+
* The returned effect will either:
|
|
298
|
+
* - Succeed with the original effect's result if it completes within the
|
|
299
|
+
* specified duration.
|
|
300
|
+
* - Die with a {@link Cause.TimeoutError} defect containing the provided
|
|
301
|
+
* message if the time limit is exceeded.
|
|
302
|
+
*
|
|
303
|
+
* @see {@link timeoutOrDie} for a version without a custom message.
|
|
304
|
+
* @see {@link Effect.timeout} for a version that raises a `TimeoutError` as a typed error.
|
|
305
|
+
* @see {@link Effect.timeoutOrElse} for a version with a custom timeout branch.
|
|
306
|
+
*/
|
|
307
|
+
export const timeoutOrDieMessage =
|
|
308
|
+
(duration: Duration.Input, message: string) =>
|
|
309
|
+
<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
310
|
+
Effect.timeoutOrElse(self, {
|
|
311
|
+
duration,
|
|
312
|
+
orElse: () => Effect.die(new Cause.TimeoutError(message)),
|
|
313
|
+
})
|
|
224
314
|
|
|
225
315
|
export const toForkedDeferred = <R, E, A>(
|
|
226
316
|
eff: Effect.Effect<A, E, R>,
|
|
@@ -251,16 +341,16 @@ export const withPerformanceMeasure =
|
|
|
251
341
|
)
|
|
252
342
|
|
|
253
343
|
const getSpanTrace = () => {
|
|
254
|
-
const
|
|
255
|
-
if (
|
|
344
|
+
const fiber = Fiber.getCurrent()
|
|
345
|
+
if (fiber === undefined || fiber.currentSpan === undefined) {
|
|
256
346
|
return 'No current fiber'
|
|
257
347
|
}
|
|
258
348
|
|
|
259
349
|
return ''
|
|
260
350
|
// const msg = Effect.runSync(
|
|
261
351
|
// Effect.fail({ message: '' }).pipe(
|
|
262
|
-
// Effect.withParentSpan(
|
|
263
|
-
// Effect.
|
|
352
|
+
// Effect.withParentSpan(fiber.currentSpan),
|
|
353
|
+
// Effect.catchCause((cause) => Effect.succeed(cause.toString())),
|
|
264
354
|
// ),
|
|
265
355
|
// )
|
|
266
356
|
|
|
@@ -274,7 +364,12 @@ const getSpanTrace = () => {
|
|
|
274
364
|
|
|
275
365
|
const logSpanTrace = () => console.log(getSpanTrace())
|
|
276
366
|
|
|
277
|
-
|
|
367
|
+
declare global {
|
|
368
|
+
/** Debug helper: returns the current Effect span trace */
|
|
369
|
+
var getSpanTrace: () => string
|
|
370
|
+
/** Debug helper: logs the current Effect span trace */
|
|
371
|
+
var logSpanTrace: () => void
|
|
372
|
+
}
|
|
373
|
+
|
|
278
374
|
globalThis.getSpanTrace = getSpanTrace
|
|
279
|
-
// @ts-expect-error TODO fix types
|
|
280
375
|
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
|
@@ -1,49 +1 @@
|
|
|
1
|
-
import { Cause, HashMap, Logger, LogLevel } from 'effect'
|
|
2
|
-
|
|
3
1
|
export * from 'effect/Logger'
|
|
4
|
-
|
|
5
|
-
const defaultDateFormat = (date: Date): string =>
|
|
6
|
-
`${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date
|
|
7
|
-
.getSeconds()
|
|
8
|
-
.toString()
|
|
9
|
-
.padStart(2, '0')}.${date.getMilliseconds().toString().padStart(3, '0')}`
|
|
10
|
-
|
|
11
|
-
export const prettyWithThread = (threadName: string, options: { mode?: 'tty' | 'browser' } = {}) =>
|
|
12
|
-
Logger.replace(
|
|
13
|
-
Logger.defaultLogger,
|
|
14
|
-
Logger.prettyLogger({
|
|
15
|
-
formatDate: (date) => `${defaultDateFormat(date)} ${threadName}`,
|
|
16
|
-
mode: options.mode,
|
|
17
|
-
}),
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
export const consoleLogger = (threadName: string) =>
|
|
21
|
-
Logger.make(({ message, annotations, date, logLevel, cause }) => {
|
|
22
|
-
const isCloudflareWorker = typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers'
|
|
23
|
-
const consoleFn =
|
|
24
|
-
logLevel === LogLevel.Debug
|
|
25
|
-
? // Cloudflare Workers doesn't support console.debug 🤷
|
|
26
|
-
isCloudflareWorker
|
|
27
|
-
? console.log
|
|
28
|
-
: console.debug
|
|
29
|
-
: logLevel === LogLevel.Info
|
|
30
|
-
? console.info
|
|
31
|
-
: logLevel === LogLevel.Warning
|
|
32
|
-
? console.warn
|
|
33
|
-
: console.error
|
|
34
|
-
|
|
35
|
-
const annotationsObj = Object.fromEntries(HashMap.entries(annotations))
|
|
36
|
-
|
|
37
|
-
const messages = Array.isArray(message) ? message : [message]
|
|
38
|
-
if (Cause.isEmpty(cause) === false) {
|
|
39
|
-
messages.push(Cause.pretty(cause, { renderErrorCause: true }))
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (Object.keys(annotationsObj).length > 0) {
|
|
43
|
-
messages.push(annotationsObj)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
consoleFn(`[${defaultDateFormat(date)} ${threadName}]`, ...messages)
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
export const consoleWithThread = (threadName: string) => Logger.replace(Logger.defaultLogger, consoleLogger(threadName))
|
package/src/effect/OtelTracer.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { makeExternalSpan } from '@effect/opentelemetry/
|
|
1
|
+
import { makeExternalSpan } from '@effect/opentelemetry/OtelTracer'
|
|
2
2
|
import type { Link as OtelSpanLink } from '@opentelemetry/api'
|
|
3
3
|
import type { SpanLink as EffectSpanLink } from 'effect/Tracer'
|
|
4
4
|
|
|
5
|
-
export * from '@effect/opentelemetry/
|
|
5
|
+
export * from '@effect/opentelemetry/OtelTracer'
|
|
6
6
|
|
|
7
7
|
export const makeSpanLink = (otelSpanLink: OtelSpanLink): EffectSpanLink => ({
|
|
8
|
-
_tag: 'SpanLink',
|
|
9
8
|
span: makeExternalSpan(otelSpanLink.context),
|
|
10
9
|
attributes: otelSpanLink.attributes ?? {},
|
|
11
10
|
})
|