@livestore/utils 0.4.0 → 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 -1
- package/dist/NoopTracer.d.ts +7 -8
- package/dist/NoopTracer.d.ts.map +1 -1
- package/dist/NoopTracer.js +3 -18
- 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/browser/Opfs/Opfs.d.ts +179 -29
- package/dist/browser/Opfs/Opfs.d.ts.map +1 -1
- package/dist/browser/Opfs/Opfs.js +132 -307
- package/dist/browser/Opfs/Opfs.js.map +1 -1
- package/dist/browser/Opfs/debug-utils.d.ts.map +1 -1
- package/dist/browser/Opfs/debug-utils.js +5 -4
- package/dist/browser/Opfs/debug-utils.js.map +1 -1
- package/dist/browser/Opfs/utils.d.ts +8 -8
- package/dist/browser/Opfs/utils.d.ts.map +1 -1
- package/dist/browser/Opfs/utils.js +35 -26
- package/dist/browser/Opfs/utils.js.map +1 -1
- package/dist/browser/QuotaExceededError.d.ts +10 -9
- package/dist/browser/QuotaExceededError.d.ts.map +1 -1
- package/dist/browser/WebChannelBrowser.d.ts.map +1 -1
- package/dist/browser/WebChannelBrowser.js +21 -10
- package/dist/browser/WebChannelBrowser.js.map +1 -1
- package/dist/browser/WebError.d.ts +54 -86
- package/dist/browser/WebError.d.ts.map +1 -1
- package/dist/browser/WebError.js +91 -84
- package/dist/browser/WebError.js.map +1 -1
- package/dist/browser/WebError.test.js +6 -6
- package/dist/browser/WebError.test.js.map +1 -1
- package/dist/browser/WebLock.d.ts.map +1 -1
- package/dist/browser/WebLock.js +13 -13
- package/dist/browser/WebLock.js.map +1 -1
- package/dist/effect/Debug.d.ts +4 -7
- package/dist/effect/Debug.d.ts.map +1 -1
- package/dist/effect/Debug.js +32 -36
- package/dist/effect/Debug.js.map +1 -1
- package/dist/effect/Effect.d.ts +31 -22
- package/dist/effect/Effect.d.ts.map +1 -1
- package/dist/effect/Effect.js +51 -47
- 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/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 +72 -52
- 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 +5 -7
- 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 -20
- 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 +9 -9
- 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 +7 -7
- package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
- package/dist/effect/WebChannel/WebChannel.js +64 -43
- package/dist/effect/WebChannel/WebChannel.js.map +1 -1
- package/dist/effect/WebChannel/WebChannel.test.js +15 -15
- 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 +16 -9
- package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
- package/dist/effect/WebChannel/common.d.ts +16 -17
- package/dist/effect/WebChannel/common.d.ts.map +1 -1
- package/dist/effect/WebChannel/common.js +6 -6
- 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 +4 -4
- 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 +13 -15
- package/dist/effect/mod.d.ts.map +1 -1
- package/dist/effect/mod.js +13 -18
- package/dist/effect/mod.js.map +1 -1
- package/dist/effect/spanEvent.d.ts.map +1 -1
- package/dist/effect/spanEvent.js +2 -2
- package/dist/effect/spanEvent.js.map +1 -1
- package/dist/effect/spanEvent.test.js +10 -13
- package/dist/effect/spanEvent.test.js.map +1 -1
- package/dist/fast-deep-equal.d.ts.map +1 -1
- package/dist/fast-deep-equal.js +1 -2
- package/dist/fast-deep-equal.js.map +1 -1
- package/dist/misc.js +2 -2
- package/dist/misc.js.map +1 -1
- package/dist/mod.d.ts +0 -35
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +0 -8
- package/dist/mod.js.map +1 -1
- package/dist/node/mod.d.ts +17 -11
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +23 -16
- 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/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 +18 -36
- package/src/NoopTracer.test.ts +20 -0
- package/src/NoopTracer.ts +18 -41
- package/src/browser/Opfs/Opfs.ts +304 -277
- package/src/browser/Opfs/debug-utils.ts +7 -6
- package/src/browser/Opfs/utils.ts +36 -26
- package/src/browser/QuotaExceededError.ts +13 -10
- package/src/browser/WebChannelBrowser.ts +25 -11
- package/src/browser/WebError.test.ts +6 -6
- package/src/browser/WebError.ts +107 -133
- package/src/browser/WebLock.ts +13 -14
- package/src/effect/Debug.ts +66 -59
- package/src/effect/Effect.test.ts +117 -0
- package/src/effect/Effect.ts +84 -71
- package/src/effect/Logger.ts +0 -48
- package/src/effect/OtelTracer.ts +2 -3
- package/src/effect/RpcClient.ts +80 -61
- package/src/effect/Schedule.ts +4 -5
- package/src/effect/Schema/debug-diff.test.ts +6 -6
- package/src/effect/Schema/debug-diff.ts +6 -8
- package/src/effect/Schema/index.ts +122 -61
- package/src/effect/Stream.test.ts +9 -9
- package/src/effect/Stream.ts +23 -16
- package/src/effect/Subscribable.ts +31 -42
- package/src/effect/SubscriptionRef.ts +8 -12
- package/src/effect/TaskTracing.ts +13 -16
- package/src/effect/WebChannel/WebChannel.test.ts +23 -23
- package/src/effect/WebChannel/WebChannel.ts +87 -55
- package/src/effect/WebChannel/broadcastChannelWithAck.ts +21 -11
- package/src/effect/WebChannel/common.ts +14 -15
- package/src/effect/WebSocket.test.ts +2 -2
- package/src/effect/WebSocket.ts +9 -6
- package/src/effect/mod.browser-build.test.ts +19 -0
- package/src/effect/mod.ts +35 -69
- package/src/effect/spanEvent.test.ts +10 -13
- package/src/effect/spanEvent.ts +5 -3
- package/src/fast-deep-equal.ts +1 -2
- package/src/misc.ts +2 -2
- package/src/mod.ts +0 -36
- package/src/node/mod.ts +26 -20
- package/src/object/index.ts +0 -24
- package/src/string.ts +0 -3
- 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/guards.d.ts +0 -20
- package/dist/guards.d.ts.map +0 -1
- package/dist/guards.js +0 -20
- 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 -128
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts +0 -10
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts.map +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +0 -217
- 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 -23
- package/src/node/ChildProcessRunner/ChildProcessRunner.ts +0 -148
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +0 -311
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +0 -78
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +0 -65
- package/src/node/ChildProcessRunner/ChildProcessWorker.ts +0 -169
- package/src/object/omit.ts +0 -17
- package/src/object/pick.ts +0 -27
- package/src/time.ts +0 -25
package/src/effect/Debug.ts
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as Context from 'effect/Context'
|
|
3
|
-
import * as Effect from 'effect/Effect'
|
|
4
|
-
import type * as Exit from 'effect/Exit'
|
|
5
|
-
import type * as Fiber from 'effect/Fiber'
|
|
6
|
-
import * as Graph from 'effect/Graph'
|
|
7
|
-
import * as Option from 'effect/Option'
|
|
8
|
-
import * as RuntimeFlags from 'effect/RuntimeFlags'
|
|
9
|
-
import * as Scope from 'effect/Scope'
|
|
10
|
-
import type * as Tracer from 'effect/Tracer'
|
|
1
|
+
import { Cause, Context, Effect, type Exit, type Fiber, Graph, Option, Scope, Tracer } from 'effect'
|
|
11
2
|
|
|
12
3
|
/**
|
|
13
4
|
* How to use:
|
|
@@ -47,7 +38,7 @@ const ensureSpan = (traceId: string, spanId: string): [MutableSpanGraph, number]
|
|
|
47
38
|
let nodeId = info.nodeIdBySpanId.get(spanId)
|
|
48
39
|
if (nodeId === undefined) {
|
|
49
40
|
nodeId = Graph.addNode(info.graph, {
|
|
50
|
-
span: { _tag: 'ExternalSpan', spanId, traceId, sampled: false,
|
|
41
|
+
span: { _tag: 'ExternalSpan', spanId, traceId, sampled: false, annotations: Context.empty() },
|
|
51
42
|
events: [],
|
|
52
43
|
exitTag: undefined,
|
|
53
44
|
})
|
|
@@ -88,7 +79,7 @@ const addEvent = (traceId: string, spanId: string, event: SpanEvent) => {
|
|
|
88
79
|
const addNodeExit = (traceId: string, spanId: string, exit: Exit.Exit<any, any>) => {
|
|
89
80
|
const [mutableGraph, nodeId] = ensureSpan(traceId, spanId)
|
|
90
81
|
Graph.updateNode(mutableGraph, nodeId, (previousInfo) => {
|
|
91
|
-
const isInterruptedOnly = exit._tag === 'Failure' && Cause.
|
|
82
|
+
const isInterruptedOnly = exit._tag === 'Failure' && Cause.hasInterruptsOnly(exit.cause)
|
|
92
83
|
return {
|
|
93
84
|
...previousInfo,
|
|
94
85
|
exitTag: isInterruptedOnly === true ? ('Interrupted' as const) : exit._tag,
|
|
@@ -136,7 +127,7 @@ const createPropertyInterceptor = <T extends object, K extends keyof T>(
|
|
|
136
127
|
type EffectDevtoolsHookEvent =
|
|
137
128
|
| {
|
|
138
129
|
_tag: 'FiberAllocated'
|
|
139
|
-
fiber: Fiber.
|
|
130
|
+
fiber: Fiber.Fiber<any, any>
|
|
140
131
|
}
|
|
141
132
|
| {
|
|
142
133
|
_tag: 'ScopeAllocated'
|
|
@@ -144,45 +135,62 @@ type EffectDevtoolsHookEvent =
|
|
|
144
135
|
}
|
|
145
136
|
|
|
146
137
|
type GlobalWithFiberCurrent = {
|
|
147
|
-
'effect/
|
|
138
|
+
['~effect/Fiber/currentFiber']: Fiber.Fiber<any, any> | undefined
|
|
148
139
|
'effect/DevtoolsHook'?: {
|
|
149
140
|
onEvent: (event: EffectDevtoolsHookEvent) => void
|
|
150
141
|
}
|
|
151
142
|
}
|
|
152
143
|
|
|
144
|
+
type MutableTracer = {
|
|
145
|
+
span: Tracer.Tracer['span']
|
|
146
|
+
context?: Tracer.Tracer['context']
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
type EvaluatablePrimitive<X> = Tracer.EffectPrimitive<X> & {
|
|
150
|
+
readonly ['~effect/Effect/evaluate']: (fiber: Fiber.Fiber<any, any>) => X
|
|
151
|
+
}
|
|
152
|
+
|
|
153
153
|
const patchedTracer = new WeakSet<Tracer.Tracer>()
|
|
154
|
-
const ensureTracerPatched = (
|
|
155
|
-
if (patchedTracer.has(
|
|
154
|
+
const ensureTracerPatched = (tracer: Tracer.Tracer) => {
|
|
155
|
+
if (patchedTracer.has(tracer) === true) {
|
|
156
156
|
return
|
|
157
157
|
}
|
|
158
|
-
patchedTracer.add(
|
|
158
|
+
patchedTracer.add(tracer)
|
|
159
|
+
|
|
160
|
+
// Effect v4 exposes the tracer context as readonly and caches it on fibers, so keep mutation localized here.
|
|
161
|
+
const mutableTracer = tracer as MutableTracer
|
|
159
162
|
|
|
160
|
-
const oldSpanConstructor =
|
|
161
|
-
|
|
162
|
-
const span = oldSpanConstructor.
|
|
163
|
+
const oldSpanConstructor: Tracer.Tracer['span'] = tracer.span
|
|
164
|
+
mutableTracer.span = function (this: Tracer.Tracer, options: Parameters<Tracer.Tracer['span']>[0]): Tracer.Span {
|
|
165
|
+
const span = oldSpanConstructor.call(this, options)
|
|
163
166
|
addNode(span)
|
|
164
167
|
|
|
165
168
|
const oldSpanEnd = span.end
|
|
166
|
-
span.end = function (endTime, exit
|
|
167
|
-
oldSpanEnd.
|
|
169
|
+
span.end = function (this: Tracer.Span, endTime, exit) {
|
|
170
|
+
oldSpanEnd.call(this, endTime, exit)
|
|
168
171
|
addNodeExit(this.traceId, this.spanId, exit)
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
const oldSpanEvent = span.event
|
|
172
|
-
span.event = function (name, startTime, attributes
|
|
173
|
-
oldSpanEvent.
|
|
175
|
+
span.event = function (this: Tracer.Span, name, startTime, attributes) {
|
|
176
|
+
oldSpanEvent.call(this, name, startTime, attributes)
|
|
174
177
|
addEvent(this.traceId, this.spanId, { name, startTime, attributes: attributes ?? {} })
|
|
175
178
|
}
|
|
176
179
|
|
|
177
180
|
return span
|
|
178
181
|
}
|
|
179
182
|
|
|
180
|
-
const oldContext =
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
const oldContext = tracer.context
|
|
184
|
+
mutableTracer.context = function <X>(
|
|
185
|
+
this: Tracer.Tracer,
|
|
186
|
+
primitive: Tracer.EffectPrimitive<X>,
|
|
187
|
+
fiber: Fiber.Fiber<any, any>,
|
|
188
|
+
) {
|
|
183
189
|
ensureFiberPatched(fiber)
|
|
184
|
-
|
|
185
|
-
|
|
190
|
+
if (oldContext !== undefined) {
|
|
191
|
+
return oldContext(primitive, fiber)
|
|
192
|
+
}
|
|
193
|
+
return (primitive as EvaluatablePrimitive<X>)['~effect/Effect/evaluate'](fiber)
|
|
186
194
|
}
|
|
187
195
|
}
|
|
188
196
|
|
|
@@ -190,7 +198,7 @@ interface ScopeImpl extends Scope.Scope {
|
|
|
190
198
|
readonly state:
|
|
191
199
|
| {
|
|
192
200
|
readonly _tag: 'Open'
|
|
193
|
-
readonly finalizers: Map<{},
|
|
201
|
+
readonly finalizers: Map<{}, (exit: Exit.Exit<unknown, unknown>) => Effect.Effect<unknown>>
|
|
194
202
|
}
|
|
195
203
|
| {
|
|
196
204
|
readonly _tag: 'Closed'
|
|
@@ -200,10 +208,10 @@ interface ScopeImpl extends Scope.Scope {
|
|
|
200
208
|
|
|
201
209
|
const knownScopes = new Map<
|
|
202
210
|
ScopeImpl,
|
|
203
|
-
{ id: number; allocationFiber: Fiber.
|
|
211
|
+
{ id: number; allocationFiber: Fiber.Fiber<any, any> | undefined; allocationSpan: Tracer.AnySpan | undefined }
|
|
204
212
|
>()
|
|
205
213
|
let lastScopeId = 0
|
|
206
|
-
const ensureScopePatched = (scope: ScopeImpl, allocationFiber: Fiber.
|
|
214
|
+
const ensureScopePatched = (scope: ScopeImpl, allocationFiber: Fiber.Fiber<any, any> | undefined) => {
|
|
207
215
|
if (scope.state._tag === 'Closed') return
|
|
208
216
|
if (knownScopes.has(scope) === true) return
|
|
209
217
|
const id = lastScopeId++
|
|
@@ -233,12 +241,12 @@ const cleanupScopes = () => {
|
|
|
233
241
|
}
|
|
234
242
|
}
|
|
235
243
|
|
|
236
|
-
const knownFibers = new Set<Fiber.
|
|
237
|
-
const ensureFiberPatched = (fiber: Fiber.
|
|
244
|
+
const knownFibers = new Set<Fiber.Fiber<any, any>>()
|
|
245
|
+
const ensureFiberPatched = (fiber: Fiber.Fiber<any, any>) => {
|
|
238
246
|
// patch tracer
|
|
239
|
-
ensureTracerPatched(fiber.
|
|
247
|
+
ensureTracerPatched(fiber.getRef(Tracer.Tracer))
|
|
240
248
|
// patch scope
|
|
241
|
-
const currentScope = Context.getOrElse(fiber.
|
|
249
|
+
const currentScope = Context.getOrElse(fiber.context, Scope.Scope, () => undefined)
|
|
242
250
|
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- casting Scope to ScopeImpl; internal Effect type not publicly exported
|
|
243
251
|
if (currentScope !== undefined) ensureScopePatched(currentScope as any as ScopeImpl, undefined)
|
|
244
252
|
// patch fiber
|
|
@@ -251,18 +259,18 @@ const ensureFiberPatched = (fiber: Fiber.RuntimeFiber<any, any>) => {
|
|
|
251
259
|
}
|
|
252
260
|
|
|
253
261
|
let patchScopeClose = false
|
|
254
|
-
let onFiberResumed: undefined | ((fiber: Fiber.
|
|
255
|
-
let onFiberSuspended: undefined | ((fiber: Fiber.
|
|
256
|
-
let onFiberCompleted: undefined | ((fiber: Fiber.
|
|
262
|
+
let onFiberResumed: undefined | ((fiber: Fiber.Fiber<any, any>) => void)
|
|
263
|
+
let onFiberSuspended: undefined | ((fiber: Fiber.Fiber<any, any>) => void)
|
|
264
|
+
let onFiberCompleted: undefined | ((fiber: Fiber.Fiber<any, any>, exit: Exit.Exit<any, any>) => void)
|
|
257
265
|
export const attachSlowDebugInstrumentation = (options: {
|
|
258
266
|
/** If set to true, the scope prototype will be patched to attach a span to visualize pending scope closing */
|
|
259
267
|
readonly patchScopeClose?: boolean
|
|
260
268
|
/** An optional callback that will be called when any fiber resumes performing a run loop */
|
|
261
|
-
readonly onFiberResumed?: (fiber: Fiber.
|
|
269
|
+
readonly onFiberResumed?: (fiber: Fiber.Fiber<any, any>) => void
|
|
262
270
|
/** An optional callback that will be called when any fiber stops performing a run loop */
|
|
263
|
-
readonly onFiberSuspended?: (fiber: Fiber.
|
|
271
|
+
readonly onFiberSuspended?: (fiber: Fiber.Fiber<any, any>) => void
|
|
264
272
|
/** An optional callback that will be called when any fiber completes with a exit */
|
|
265
|
-
readonly onFiberCompleted?: (fiber: Fiber.
|
|
273
|
+
readonly onFiberCompleted?: (fiber: Fiber.Fiber<any, any>, exit: Exit.Exit<any, any>) => void
|
|
266
274
|
}): void => {
|
|
267
275
|
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- accessing Effect's global fiber tracking via well-known symbol keys
|
|
268
276
|
const _globalThis = globalThis as any as GlobalWithFiberCurrent
|
|
@@ -275,9 +283,9 @@ export const attachSlowDebugInstrumentation = (options: {
|
|
|
275
283
|
onFiberResumed = options.onFiberResumed
|
|
276
284
|
onFiberSuspended = options.onFiberSuspended
|
|
277
285
|
onFiberCompleted = options.onFiberCompleted
|
|
278
|
-
let lastFiber: undefined | Fiber.
|
|
286
|
+
let lastFiber: undefined | Fiber.Fiber<any, any>
|
|
279
287
|
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- accessing Effect's global fiber tracking via well-known symbol keys
|
|
280
|
-
createPropertyInterceptor(globalThis as any as GlobalWithFiberCurrent, 'effect/
|
|
288
|
+
createPropertyInterceptor(globalThis as any as GlobalWithFiberCurrent, '~effect/Fiber/currentFiber', (value) => {
|
|
281
289
|
if (value !== undefined && knownFibers.has(value) === true) onFiberResumed?.(value)
|
|
282
290
|
if (value !== undefined) ensureFiberPatched(value)
|
|
283
291
|
if (value == null && lastFiber !== undefined && knownFibers.has(lastFiber) === true) onFiberSuspended?.(lastFiber)
|
|
@@ -289,7 +297,7 @@ export const attachSlowDebugInstrumentation = (options: {
|
|
|
289
297
|
switch (event._tag) {
|
|
290
298
|
case 'ScopeAllocated':
|
|
291
299
|
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- casting Scope to ScopeImpl; internal Effect type not publicly exported
|
|
292
|
-
ensureScopePatched(event.scope as any as ScopeImpl, _globalThis['effect/
|
|
300
|
+
ensureScopePatched(event.scope as any as ScopeImpl, _globalThis['~effect/Fiber/currentFiber'])
|
|
293
301
|
break
|
|
294
302
|
case 'FiberAllocated':
|
|
295
303
|
ensureFiberPatched(event.fiber)
|
|
@@ -327,9 +335,9 @@ const getSpanDuration = (span: Tracer.AnySpan): string => {
|
|
|
327
335
|
}
|
|
328
336
|
|
|
329
337
|
const filterGraphKeepAncestors = <N, E>(
|
|
330
|
-
graph: Graph.Graph<N, E>,
|
|
338
|
+
graph: Graph.Graph<N, E, 'directed'>,
|
|
331
339
|
predicate: (nodeData: N, nodeId: number) => boolean,
|
|
332
|
-
): Graph.Graph<N, E> => {
|
|
340
|
+
): Graph.Graph<N, E, 'directed'> => {
|
|
333
341
|
// Find all root nodes (nodes with no incoming edges)
|
|
334
342
|
const rootNodes = Array.from(Graph.indices(Graph.externals(graph, { direction: 'incoming' })))
|
|
335
343
|
const shouldInclude = new Set<number>()
|
|
@@ -351,14 +359,15 @@ const filterGraphKeepAncestors = <N, E>(
|
|
|
351
359
|
|
|
352
360
|
// Create a filtered copy of the graph
|
|
353
361
|
return Graph.mutate(graph, (mutable) => {
|
|
354
|
-
|
|
362
|
+
const nodeIds = Array.from(Graph.indices(Graph.nodes(mutable)))
|
|
363
|
+
for (const nodeId of nodeIds) {
|
|
355
364
|
if (shouldInclude.has(nodeId) === true) continue
|
|
356
365
|
Graph.removeNode(mutable, nodeId)
|
|
357
366
|
}
|
|
358
367
|
})
|
|
359
368
|
}
|
|
360
369
|
|
|
361
|
-
const renderSpanNode = (graph: Graph.Graph<GraphNodeInfo, void>, nodeId: number): string[] => {
|
|
370
|
+
const renderSpanNode = (graph: Graph.Graph<GraphNodeInfo, void, 'directed'>, nodeId: number): string[] => {
|
|
362
371
|
const node = Graph.getNode(graph, nodeId)
|
|
363
372
|
if (Option.isNone(node) === true) return []
|
|
364
373
|
const info = node.value
|
|
@@ -371,17 +380,17 @@ const renderSpanNode = (graph: Graph.Graph<GraphNodeInfo, void>, nodeId: number)
|
|
|
371
380
|
.filter(
|
|
372
381
|
(fiber) => fiber.currentSpan?.spanId === info.span.spanId && fiber.currentSpan?.traceId === info.span.traceId,
|
|
373
382
|
)
|
|
374
|
-
.map((fiber) => `#${fiber.id
|
|
383
|
+
.map((fiber) => `#${fiber.id}`)
|
|
375
384
|
.join(', ')
|
|
376
385
|
const runningOnFibers = fiberIds.length > 0 ? ` [fibers ${fiberIds}]` : ''
|
|
377
386
|
|
|
378
387
|
return [` ${status} ${name}${durationStr}${runningOnFibers}`]
|
|
379
388
|
}
|
|
380
389
|
|
|
381
|
-
const renderTree = <N, E
|
|
382
|
-
graph: Graph.Graph<N, E,
|
|
390
|
+
const renderTree = <N, E>(
|
|
391
|
+
graph: Graph.Graph<N, E, 'directed'>,
|
|
383
392
|
nodeIds: Array<number>,
|
|
384
|
-
renderNode: (graph: Graph.Graph<N, E,
|
|
393
|
+
renderNode: (graph: Graph.Graph<N, E, 'directed'>, nodeId: number) => string[],
|
|
385
394
|
): string[] => {
|
|
386
395
|
let lines: string[] = []
|
|
387
396
|
for (let childIndex = 0; childIndex < nodeIds.length; childIndex++) {
|
|
@@ -422,9 +431,7 @@ export const logDebug = (options: LogDebugOptions = {}) => {
|
|
|
422
431
|
// fibers
|
|
423
432
|
lines = [...lines, 'Active Fibers:']
|
|
424
433
|
for (const fiber of knownFibers) {
|
|
425
|
-
|
|
426
|
-
const interruptible = RuntimeFlags.interruptible((fiber as any).currentRuntimeFlags)
|
|
427
|
-
lines = [...lines, `- #${fiber.id().id}${interruptible === false ? ' [uninterruptible]' : ''}`]
|
|
434
|
+
lines = [...lines, `- #${fiber.id}`]
|
|
428
435
|
}
|
|
429
436
|
if (knownFibers.size === 0) {
|
|
430
437
|
lines = [...lines, '- No active effect fibers']
|
|
@@ -451,12 +458,12 @@ export const logDebug = (options: LogDebugOptions = {}) => {
|
|
|
451
458
|
lines = [...lines, 'Open Scopes:']
|
|
452
459
|
for (const [scope, info] of knownScopes) {
|
|
453
460
|
const fiberIds = Array.from(knownFibers)
|
|
454
|
-
.filter((fiber) => Context.getOrElse(fiber.
|
|
455
|
-
.map((fiber) => `#${fiber.id
|
|
461
|
+
.filter((fiber) => Context.getOrElse(fiber.context, Scope.Scope, () => undefined) === scope)
|
|
462
|
+
.map((fiber) => `#${fiber.id}`)
|
|
456
463
|
.join(', ')
|
|
457
464
|
const usedByFibers = fiberIds.length > 0 ? ` [used by: ${fiberIds}]` : ''
|
|
458
465
|
const allocationFiber =
|
|
459
|
-
info.allocationFiber !== undefined ? ` [allocated in fiber #${info.allocationFiber.id
|
|
466
|
+
info.allocationFiber !== undefined ? ` [allocated in fiber #${info.allocationFiber.id}]` : ''
|
|
460
467
|
const allocationSpan =
|
|
461
468
|
info.allocationSpan !== undefined ? ` [allocated in span: ${getSpanName(info.allocationSpan)}]` : ''
|
|
462
469
|
lines = [...lines, `- #${info.id}${usedByFibers}${allocationFiber}${allocationSpan}`]
|
|
@@ -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
|
+
})
|