@livestore/utils 0.4.0 → 0.5.0-dev.1
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/Deferred.d.ts.map +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 +29 -0
- package/dist/NoopTracer.test.js.map +1 -0
- package/dist/base64.d.ts.map +1 -1
- package/dist/binary.d.ts.map +1 -1
- 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 +134 -309
- 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 +6 -5
- package/dist/browser/Opfs/debug-utils.js.map +1 -1
- package/dist/browser/Opfs/mod.js +3 -3
- 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 +25 -14
- package/dist/browser/WebChannelBrowser.js.map +1 -1
- package/dist/browser/WebError.d.ts +55 -87
- package/dist/browser/WebError.d.ts.map +1 -1
- package/dist/browser/WebError.js +92 -85
- package/dist/browser/WebError.js.map +1 -1
- package/dist/browser/WebError.test.js +7 -7
- package/dist/browser/WebError.test.js.map +1 -1
- package/dist/browser/WebLock.d.ts +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/browser/mod.js +6 -6
- package/dist/cuid/cuid.browser.d.ts.map +1 -1
- package/dist/cuid/cuid.node.d.ts.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 +34 -40
- 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 +54 -50
- 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 +9 -9
- package/dist/effect/RpcClient.d.ts.map +1 -1
- package/dist/effect/RpcClient.js +113 -84
- 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 +8 -5
- 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 +56 -29
- 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 +10 -10
- 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 +69 -48
- 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 +18 -11
- 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/WebChannel/mod.js +3 -3
- 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 +3 -3
- 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 +28 -33
- 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 +11 -14
- package/dist/effect/spanEvent.test.js.map +1 -1
- 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 +1 -2
- package/dist/fast-deep-equal.js.map +1 -1
- package/dist/misc.d.ts.map +1 -1
- package/dist/misc.js +3 -3
- package/dist/misc.js.map +1 -1
- package/dist/mod.d.ts +1 -36
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +19 -27
- package/dist/mod.js.map +1 -1
- package/dist/node/mod.d.ts +11 -36
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +17 -42
- 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 +1 -10
- package/dist/object/index.js.map +1 -1
- package/dist/object/stringify-object.d.ts.map +1 -1
- package/dist/object/stringify-object.test.js +1 -1
- package/dist/promise.d.ts.map +1 -1
- package/dist/qr.d.ts.map +1 -1
- package/dist/set.d.ts.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 +38 -56
- package/src/NoopTracer.test.ts +36 -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 +69 -78
- package/src/effect/Effect.test.ts +117 -0
- package/src/effect/Effect.ts +86 -73
- package/src/effect/Logger.ts +0 -48
- package/src/effect/OtelTracer.ts +2 -3
- package/src/effect/RpcClient.ts +126 -93
- 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 -56
- 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 +37 -69
- package/src/effect/spanEvent.test.ts +10 -13
- package/src/effect/spanEvent.ts +5 -3
- package/src/fast-deep-equal.ts +4 -5
- package/src/misc.ts +3 -3
- package/src/mod.ts +5 -41
- package/src/node/mod.ts +20 -46
- 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,66 +135,71 @@ 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
|
|
|
189
|
-
interface ScopeImpl extends Scope.Scope {
|
|
190
|
-
readonly state:
|
|
191
|
-
| {
|
|
192
|
-
readonly _tag: 'Open'
|
|
193
|
-
readonly finalizers: Map<{}, Scope.Scope.Finalizer>
|
|
194
|
-
}
|
|
195
|
-
| {
|
|
196
|
-
readonly _tag: 'Closed'
|
|
197
|
-
readonly exit: Exit.Exit<unknown, unknown>
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
197
|
const knownScopes = new Map<
|
|
202
|
-
|
|
203
|
-
{ id: number; allocationFiber: Fiber.
|
|
198
|
+
Scope.Scope,
|
|
199
|
+
{ id: number; allocationFiber: Fiber.Fiber<any, any> | undefined; allocationSpan: Tracer.AnySpan | undefined }
|
|
204
200
|
>()
|
|
205
201
|
let lastScopeId = 0
|
|
206
|
-
const ensureScopePatched = (scope:
|
|
202
|
+
const ensureScopePatched = (scope: Scope.Scope, allocationFiber: Fiber.Fiber<any, any> | undefined) => {
|
|
207
203
|
if (scope.state._tag === 'Closed') return
|
|
208
204
|
if (knownScopes.has(scope) === true) return
|
|
209
205
|
const id = lastScopeId++
|
|
@@ -224,7 +220,7 @@ const ensureScopePatched = (scope: ScopeImpl, allocationFiber: Fiber.RuntimeFibe
|
|
|
224
220
|
} else {
|
|
225
221
|
cleanupScopes()
|
|
226
222
|
}
|
|
227
|
-
const allocationSpan = allocationFiber?.
|
|
223
|
+
const allocationSpan = allocationFiber?.cache.span
|
|
228
224
|
knownScopes.set(scope, { id, allocationFiber, allocationSpan })
|
|
229
225
|
}
|
|
230
226
|
const cleanupScopes = () => {
|
|
@@ -233,14 +229,13 @@ const cleanupScopes = () => {
|
|
|
233
229
|
}
|
|
234
230
|
}
|
|
235
231
|
|
|
236
|
-
const knownFibers = new Set<Fiber.
|
|
237
|
-
const ensureFiberPatched = (fiber: Fiber.
|
|
232
|
+
const knownFibers = new Set<Fiber.Fiber<any, any>>()
|
|
233
|
+
const ensureFiberPatched = (fiber: Fiber.Fiber<any, any>) => {
|
|
238
234
|
// patch tracer
|
|
239
|
-
ensureTracerPatched(fiber.
|
|
235
|
+
ensureTracerPatched(fiber.getRef(Tracer.Tracer))
|
|
240
236
|
// patch scope
|
|
241
|
-
const currentScope = Context.getOrElse(fiber.
|
|
242
|
-
|
|
243
|
-
if (currentScope !== undefined) ensureScopePatched(currentScope as any as ScopeImpl, undefined)
|
|
237
|
+
const currentScope = Context.getOrElse(fiber.context, Scope.Scope, () => undefined)
|
|
238
|
+
if (currentScope !== undefined) ensureScopePatched(currentScope, undefined)
|
|
244
239
|
// patch fiber
|
|
245
240
|
if (knownFibers.has(fiber) === true) return
|
|
246
241
|
knownFibers.add(fiber)
|
|
@@ -251,18 +246,18 @@ const ensureFiberPatched = (fiber: Fiber.RuntimeFiber<any, any>) => {
|
|
|
251
246
|
}
|
|
252
247
|
|
|
253
248
|
let patchScopeClose = false
|
|
254
|
-
let onFiberResumed: undefined | ((fiber: Fiber.
|
|
255
|
-
let onFiberSuspended: undefined | ((fiber: Fiber.
|
|
256
|
-
let onFiberCompleted: undefined | ((fiber: Fiber.
|
|
249
|
+
let onFiberResumed: undefined | ((fiber: Fiber.Fiber<any, any>) => void)
|
|
250
|
+
let onFiberSuspended: undefined | ((fiber: Fiber.Fiber<any, any>) => void)
|
|
251
|
+
let onFiberCompleted: undefined | ((fiber: Fiber.Fiber<any, any>, exit: Exit.Exit<any, any>) => void)
|
|
257
252
|
export const attachSlowDebugInstrumentation = (options: {
|
|
258
253
|
/** If set to true, the scope prototype will be patched to attach a span to visualize pending scope closing */
|
|
259
254
|
readonly patchScopeClose?: boolean
|
|
260
255
|
/** An optional callback that will be called when any fiber resumes performing a run loop */
|
|
261
|
-
readonly onFiberResumed?: (fiber: Fiber.
|
|
256
|
+
readonly onFiberResumed?: (fiber: Fiber.Fiber<any, any>) => void
|
|
262
257
|
/** An optional callback that will be called when any fiber stops performing a run loop */
|
|
263
|
-
readonly onFiberSuspended?: (fiber: Fiber.
|
|
258
|
+
readonly onFiberSuspended?: (fiber: Fiber.Fiber<any, any>) => void
|
|
264
259
|
/** An optional callback that will be called when any fiber completes with a exit */
|
|
265
|
-
readonly onFiberCompleted?: (fiber: Fiber.
|
|
260
|
+
readonly onFiberCompleted?: (fiber: Fiber.Fiber<any, any>, exit: Exit.Exit<any, any>) => void
|
|
266
261
|
}): void => {
|
|
267
262
|
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- accessing Effect's global fiber tracking via well-known symbol keys
|
|
268
263
|
const _globalThis = globalThis as any as GlobalWithFiberCurrent
|
|
@@ -275,9 +270,9 @@ export const attachSlowDebugInstrumentation = (options: {
|
|
|
275
270
|
onFiberResumed = options.onFiberResumed
|
|
276
271
|
onFiberSuspended = options.onFiberSuspended
|
|
277
272
|
onFiberCompleted = options.onFiberCompleted
|
|
278
|
-
let lastFiber: undefined | Fiber.
|
|
273
|
+
let lastFiber: undefined | Fiber.Fiber<any, any>
|
|
279
274
|
// 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/
|
|
275
|
+
createPropertyInterceptor(globalThis as any as GlobalWithFiberCurrent, '~effect/Fiber/currentFiber', (value) => {
|
|
281
276
|
if (value !== undefined && knownFibers.has(value) === true) onFiberResumed?.(value)
|
|
282
277
|
if (value !== undefined) ensureFiberPatched(value)
|
|
283
278
|
if (value == null && lastFiber !== undefined && knownFibers.has(lastFiber) === true) onFiberSuspended?.(lastFiber)
|
|
@@ -288,8 +283,7 @@ export const attachSlowDebugInstrumentation = (options: {
|
|
|
288
283
|
console.log('onEvent', event)
|
|
289
284
|
switch (event._tag) {
|
|
290
285
|
case 'ScopeAllocated':
|
|
291
|
-
|
|
292
|
-
ensureScopePatched(event.scope as any as ScopeImpl, _globalThis['effect/FiberCurrent'])
|
|
286
|
+
ensureScopePatched(event.scope, _globalThis['~effect/Fiber/currentFiber'])
|
|
293
287
|
break
|
|
294
288
|
case 'FiberAllocated':
|
|
295
289
|
ensureFiberPatched(event.fiber)
|
|
@@ -327,9 +321,9 @@ const getSpanDuration = (span: Tracer.AnySpan): string => {
|
|
|
327
321
|
}
|
|
328
322
|
|
|
329
323
|
const filterGraphKeepAncestors = <N, E>(
|
|
330
|
-
graph: Graph.Graph<N, E>,
|
|
324
|
+
graph: Graph.Graph<N, E, 'directed'>,
|
|
331
325
|
predicate: (nodeData: N, nodeId: number) => boolean,
|
|
332
|
-
): Graph.Graph<N, E> => {
|
|
326
|
+
): Graph.Graph<N, E, 'directed'> => {
|
|
333
327
|
// Find all root nodes (nodes with no incoming edges)
|
|
334
328
|
const rootNodes = Array.from(Graph.indices(Graph.externals(graph, { direction: 'incoming' })))
|
|
335
329
|
const shouldInclude = new Set<number>()
|
|
@@ -351,14 +345,15 @@ const filterGraphKeepAncestors = <N, E>(
|
|
|
351
345
|
|
|
352
346
|
// Create a filtered copy of the graph
|
|
353
347
|
return Graph.mutate(graph, (mutable) => {
|
|
354
|
-
|
|
348
|
+
const nodeIds = Array.from(Graph.indices(Graph.nodes(mutable)))
|
|
349
|
+
for (const nodeId of nodeIds) {
|
|
355
350
|
if (shouldInclude.has(nodeId) === true) continue
|
|
356
351
|
Graph.removeNode(mutable, nodeId)
|
|
357
352
|
}
|
|
358
353
|
})
|
|
359
354
|
}
|
|
360
355
|
|
|
361
|
-
const renderSpanNode = (graph: Graph.Graph<GraphNodeInfo, void>, nodeId: number): string[] => {
|
|
356
|
+
const renderSpanNode = (graph: Graph.Graph<GraphNodeInfo, void, 'directed'>, nodeId: number): string[] => {
|
|
362
357
|
const node = Graph.getNode(graph, nodeId)
|
|
363
358
|
if (Option.isNone(node) === true) return []
|
|
364
359
|
const info = node.value
|
|
@@ -368,20 +363,18 @@ const renderSpanNode = (graph: Graph.Graph<GraphNodeInfo, void>, nodeId: number)
|
|
|
368
363
|
const durationStr = duration !== undefined ? ` ${duration}` : ''
|
|
369
364
|
|
|
370
365
|
const fiberIds = Array.from(knownFibers)
|
|
371
|
-
.filter(
|
|
372
|
-
|
|
373
|
-
)
|
|
374
|
-
.map((fiber) => `#${fiber.id().id}`)
|
|
366
|
+
.filter((fiber) => fiber.cache.span?.spanId === info.span.spanId && fiber.cache.span?.traceId === info.span.traceId)
|
|
367
|
+
.map((fiber) => `#${fiber.id}`)
|
|
375
368
|
.join(', ')
|
|
376
369
|
const runningOnFibers = fiberIds.length > 0 ? ` [fibers ${fiberIds}]` : ''
|
|
377
370
|
|
|
378
371
|
return [` ${status} ${name}${durationStr}${runningOnFibers}`]
|
|
379
372
|
}
|
|
380
373
|
|
|
381
|
-
const renderTree = <N, E
|
|
382
|
-
graph: Graph.Graph<N, E,
|
|
374
|
+
const renderTree = <N, E>(
|
|
375
|
+
graph: Graph.Graph<N, E, 'directed'>,
|
|
383
376
|
nodeIds: Array<number>,
|
|
384
|
-
renderNode: (graph: Graph.Graph<N, E,
|
|
377
|
+
renderNode: (graph: Graph.Graph<N, E, 'directed'>, nodeId: number) => string[],
|
|
385
378
|
): string[] => {
|
|
386
379
|
let lines: string[] = []
|
|
387
380
|
for (let childIndex = 0; childIndex < nodeIds.length; childIndex++) {
|
|
@@ -422,9 +415,7 @@ export const logDebug = (options: LogDebugOptions = {}) => {
|
|
|
422
415
|
// fibers
|
|
423
416
|
lines = [...lines, 'Active Fibers:']
|
|
424
417
|
for (const fiber of knownFibers) {
|
|
425
|
-
|
|
426
|
-
const interruptible = RuntimeFlags.interruptible((fiber as any).currentRuntimeFlags)
|
|
427
|
-
lines = [...lines, `- #${fiber.id().id}${interruptible === false ? ' [uninterruptible]' : ''}`]
|
|
418
|
+
lines = [...lines, `- #${fiber.id}`]
|
|
428
419
|
}
|
|
429
420
|
if (knownFibers.size === 0) {
|
|
430
421
|
lines = [...lines, '- No active effect fibers']
|
|
@@ -451,12 +442,12 @@ export const logDebug = (options: LogDebugOptions = {}) => {
|
|
|
451
442
|
lines = [...lines, 'Open Scopes:']
|
|
452
443
|
for (const [scope, info] of knownScopes) {
|
|
453
444
|
const fiberIds = Array.from(knownFibers)
|
|
454
|
-
.filter((fiber) => Context.getOrElse(fiber.
|
|
455
|
-
.map((fiber) => `#${fiber.id
|
|
445
|
+
.filter((fiber) => Context.getOrElse(fiber.context, Scope.Scope, () => undefined) === scope)
|
|
446
|
+
.map((fiber) => `#${fiber.id}`)
|
|
456
447
|
.join(', ')
|
|
457
448
|
const usedByFibers = fiberIds.length > 0 ? ` [used by: ${fiberIds}]` : ''
|
|
458
449
|
const allocationFiber =
|
|
459
|
-
info.allocationFiber !== undefined ? ` [allocated in fiber #${info.allocationFiber.id
|
|
450
|
+
info.allocationFiber !== undefined ? ` [allocated in fiber #${info.allocationFiber.id}]` : ''
|
|
460
451
|
const allocationSpan =
|
|
461
452
|
info.allocationSpan !== undefined ? ` [allocated in span: ${getSpanName(info.allocationSpan)}]` : ''
|
|
462
453
|
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 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
|
+
})
|