@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.
Files changed (265) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/Deferred.d.ts.map +1 -1
  3. package/dist/NoopTracer.d.ts +7 -8
  4. package/dist/NoopTracer.d.ts.map +1 -1
  5. package/dist/NoopTracer.js +3 -18
  6. package/dist/NoopTracer.js.map +1 -1
  7. package/dist/NoopTracer.test.d.ts +2 -0
  8. package/dist/NoopTracer.test.d.ts.map +1 -0
  9. package/dist/NoopTracer.test.js +29 -0
  10. package/dist/NoopTracer.test.js.map +1 -0
  11. package/dist/base64.d.ts.map +1 -1
  12. package/dist/binary.d.ts.map +1 -1
  13. package/dist/browser/Opfs/Opfs.d.ts +179 -29
  14. package/dist/browser/Opfs/Opfs.d.ts.map +1 -1
  15. package/dist/browser/Opfs/Opfs.js +134 -309
  16. package/dist/browser/Opfs/Opfs.js.map +1 -1
  17. package/dist/browser/Opfs/debug-utils.d.ts.map +1 -1
  18. package/dist/browser/Opfs/debug-utils.js +6 -5
  19. package/dist/browser/Opfs/debug-utils.js.map +1 -1
  20. package/dist/browser/Opfs/mod.js +3 -3
  21. package/dist/browser/Opfs/utils.d.ts +8 -8
  22. package/dist/browser/Opfs/utils.d.ts.map +1 -1
  23. package/dist/browser/Opfs/utils.js +35 -26
  24. package/dist/browser/Opfs/utils.js.map +1 -1
  25. package/dist/browser/QuotaExceededError.d.ts +10 -9
  26. package/dist/browser/QuotaExceededError.d.ts.map +1 -1
  27. package/dist/browser/WebChannelBrowser.d.ts.map +1 -1
  28. package/dist/browser/WebChannelBrowser.js +25 -14
  29. package/dist/browser/WebChannelBrowser.js.map +1 -1
  30. package/dist/browser/WebError.d.ts +55 -87
  31. package/dist/browser/WebError.d.ts.map +1 -1
  32. package/dist/browser/WebError.js +92 -85
  33. package/dist/browser/WebError.js.map +1 -1
  34. package/dist/browser/WebError.test.js +7 -7
  35. package/dist/browser/WebError.test.js.map +1 -1
  36. package/dist/browser/WebLock.d.ts +1 -1
  37. package/dist/browser/WebLock.d.ts.map +1 -1
  38. package/dist/browser/WebLock.js +13 -13
  39. package/dist/browser/WebLock.js.map +1 -1
  40. package/dist/browser/mod.js +6 -6
  41. package/dist/cuid/cuid.browser.d.ts.map +1 -1
  42. package/dist/cuid/cuid.node.d.ts.map +1 -1
  43. package/dist/effect/Debug.d.ts +4 -7
  44. package/dist/effect/Debug.d.ts.map +1 -1
  45. package/dist/effect/Debug.js +34 -40
  46. package/dist/effect/Debug.js.map +1 -1
  47. package/dist/effect/Effect.d.ts +31 -22
  48. package/dist/effect/Effect.d.ts.map +1 -1
  49. package/dist/effect/Effect.js +54 -50
  50. package/dist/effect/Effect.js.map +1 -1
  51. package/dist/effect/Effect.test.d.ts +2 -0
  52. package/dist/effect/Effect.test.d.ts.map +1 -0
  53. package/dist/effect/Effect.test.js +72 -0
  54. package/dist/effect/Effect.test.js.map +1 -0
  55. package/dist/effect/Error.d.ts +4 -6
  56. package/dist/effect/Error.d.ts.map +1 -1
  57. package/dist/effect/Logger.d.ts +0 -6
  58. package/dist/effect/Logger.d.ts.map +1 -1
  59. package/dist/effect/Logger.js +0 -32
  60. package/dist/effect/Logger.js.map +1 -1
  61. package/dist/effect/OtelTracer.d.ts +1 -1
  62. package/dist/effect/OtelTracer.d.ts.map +1 -1
  63. package/dist/effect/OtelTracer.js +2 -3
  64. package/dist/effect/OtelTracer.js.map +1 -1
  65. package/dist/effect/RpcClient.d.ts +9 -9
  66. package/dist/effect/RpcClient.d.ts.map +1 -1
  67. package/dist/effect/RpcClient.js +113 -84
  68. package/dist/effect/RpcClient.js.map +1 -1
  69. package/dist/effect/Schedule.d.ts +1 -1
  70. package/dist/effect/Schedule.d.ts.map +1 -1
  71. package/dist/effect/Schedule.js +2 -2
  72. package/dist/effect/Schedule.js.map +1 -1
  73. package/dist/effect/Schema/debug-diff.d.ts +1 -1
  74. package/dist/effect/Schema/debug-diff.d.ts.map +1 -1
  75. package/dist/effect/Schema/debug-diff.js +5 -7
  76. package/dist/effect/Schema/debug-diff.js.map +1 -1
  77. package/dist/effect/Schema/debug-diff.test.js +8 -5
  78. package/dist/effect/Schema/debug-diff.test.js.map +1 -1
  79. package/dist/effect/Schema/index.d.ts +28 -20
  80. package/dist/effect/Schema/index.d.ts.map +1 -1
  81. package/dist/effect/Schema/index.js +56 -29
  82. package/dist/effect/Schema/index.js.map +1 -1
  83. package/dist/effect/Stream.d.ts +13 -5
  84. package/dist/effect/Stream.d.ts.map +1 -1
  85. package/dist/effect/Stream.js +19 -12
  86. package/dist/effect/Stream.js.map +1 -1
  87. package/dist/effect/Stream.test.js +10 -10
  88. package/dist/effect/Stream.test.js.map +1 -1
  89. package/dist/effect/Subscribable.d.ts +9 -3
  90. package/dist/effect/Subscribable.d.ts.map +1 -1
  91. package/dist/effect/Subscribable.js +20 -35
  92. package/dist/effect/Subscribable.js.map +1 -1
  93. package/dist/effect/SubscriptionRef.d.ts +5 -6
  94. package/dist/effect/SubscriptionRef.d.ts.map +1 -1
  95. package/dist/effect/SubscriptionRef.js +2 -3
  96. package/dist/effect/SubscriptionRef.js.map +1 -1
  97. package/dist/effect/TaskTracing.d.ts +1 -1
  98. package/dist/effect/TaskTracing.d.ts.map +1 -1
  99. package/dist/effect/TaskTracing.js +12 -16
  100. package/dist/effect/TaskTracing.js.map +1 -1
  101. package/dist/effect/WebChannel/WebChannel.d.ts +7 -7
  102. package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
  103. package/dist/effect/WebChannel/WebChannel.js +69 -48
  104. package/dist/effect/WebChannel/WebChannel.js.map +1 -1
  105. package/dist/effect/WebChannel/WebChannel.test.js +16 -16
  106. package/dist/effect/WebChannel/WebChannel.test.js.map +1 -1
  107. package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts.map +1 -1
  108. package/dist/effect/WebChannel/broadcastChannelWithAck.js +18 -11
  109. package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
  110. package/dist/effect/WebChannel/common.d.ts +16 -17
  111. package/dist/effect/WebChannel/common.d.ts.map +1 -1
  112. package/dist/effect/WebChannel/common.js +6 -6
  113. package/dist/effect/WebChannel/common.js.map +1 -1
  114. package/dist/effect/WebChannel/mod.js +3 -3
  115. package/dist/effect/WebSocket.d.ts +4 -6
  116. package/dist/effect/WebSocket.d.ts.map +1 -1
  117. package/dist/effect/WebSocket.js +4 -4
  118. package/dist/effect/WebSocket.js.map +1 -1
  119. package/dist/effect/WebSocket.test.js +3 -3
  120. package/dist/effect/WebSocket.test.js.map +1 -1
  121. package/dist/effect/mod.browser-build.test.d.ts +2 -0
  122. package/dist/effect/mod.browser-build.test.d.ts.map +1 -0
  123. package/dist/effect/mod.browser-build.test.js +18 -0
  124. package/dist/effect/mod.browser-build.test.js.map +1 -0
  125. package/dist/effect/mod.d.ts +13 -15
  126. package/dist/effect/mod.d.ts.map +1 -1
  127. package/dist/effect/mod.js +28 -33
  128. package/dist/effect/mod.js.map +1 -1
  129. package/dist/effect/spanEvent.d.ts.map +1 -1
  130. package/dist/effect/spanEvent.js +2 -2
  131. package/dist/effect/spanEvent.js.map +1 -1
  132. package/dist/effect/spanEvent.test.js +11 -14
  133. package/dist/effect/spanEvent.test.js.map +1 -1
  134. package/dist/env.d.ts.map +1 -1
  135. package/dist/env.js +1 -1
  136. package/dist/env.js.map +1 -1
  137. package/dist/fast-deep-equal.d.ts.map +1 -1
  138. package/dist/fast-deep-equal.js +1 -2
  139. package/dist/fast-deep-equal.js.map +1 -1
  140. package/dist/misc.d.ts.map +1 -1
  141. package/dist/misc.js +3 -3
  142. package/dist/misc.js.map +1 -1
  143. package/dist/mod.d.ts +1 -36
  144. package/dist/mod.d.ts.map +1 -1
  145. package/dist/mod.js +19 -27
  146. package/dist/mod.js.map +1 -1
  147. package/dist/node/mod.d.ts +11 -36
  148. package/dist/node/mod.d.ts.map +1 -1
  149. package/dist/node/mod.js +17 -42
  150. package/dist/node/mod.js.map +1 -1
  151. package/dist/object/index.d.ts +0 -9
  152. package/dist/object/index.d.ts.map +1 -1
  153. package/dist/object/index.js +1 -10
  154. package/dist/object/index.js.map +1 -1
  155. package/dist/object/stringify-object.d.ts.map +1 -1
  156. package/dist/object/stringify-object.test.js +1 -1
  157. package/dist/promise.d.ts.map +1 -1
  158. package/dist/qr.d.ts.map +1 -1
  159. package/dist/set.d.ts.map +1 -1
  160. package/dist/string.d.ts +0 -2
  161. package/dist/string.d.ts.map +1 -1
  162. package/dist/string.js +0 -2
  163. package/dist/string.js.map +1 -1
  164. package/package.json +38 -56
  165. package/src/NoopTracer.test.ts +36 -0
  166. package/src/NoopTracer.ts +18 -41
  167. package/src/browser/Opfs/Opfs.ts +304 -277
  168. package/src/browser/Opfs/debug-utils.ts +7 -6
  169. package/src/browser/Opfs/utils.ts +36 -26
  170. package/src/browser/QuotaExceededError.ts +13 -10
  171. package/src/browser/WebChannelBrowser.ts +25 -11
  172. package/src/browser/WebError.test.ts +6 -6
  173. package/src/browser/WebError.ts +107 -133
  174. package/src/browser/WebLock.ts +13 -14
  175. package/src/effect/Debug.ts +69 -78
  176. package/src/effect/Effect.test.ts +117 -0
  177. package/src/effect/Effect.ts +86 -73
  178. package/src/effect/Logger.ts +0 -48
  179. package/src/effect/OtelTracer.ts +2 -3
  180. package/src/effect/RpcClient.ts +126 -93
  181. package/src/effect/Schedule.ts +4 -5
  182. package/src/effect/Schema/debug-diff.test.ts +6 -6
  183. package/src/effect/Schema/debug-diff.ts +6 -8
  184. package/src/effect/Schema/index.ts +122 -61
  185. package/src/effect/Stream.test.ts +9 -9
  186. package/src/effect/Stream.ts +23 -16
  187. package/src/effect/Subscribable.ts +31 -42
  188. package/src/effect/SubscriptionRef.ts +8 -12
  189. package/src/effect/TaskTracing.ts +13 -16
  190. package/src/effect/WebChannel/WebChannel.test.ts +23 -23
  191. package/src/effect/WebChannel/WebChannel.ts +87 -56
  192. package/src/effect/WebChannel/broadcastChannelWithAck.ts +21 -11
  193. package/src/effect/WebChannel/common.ts +14 -15
  194. package/src/effect/WebSocket.test.ts +2 -2
  195. package/src/effect/WebSocket.ts +9 -6
  196. package/src/effect/mod.browser-build.test.ts +19 -0
  197. package/src/effect/mod.ts +37 -69
  198. package/src/effect/spanEvent.test.ts +10 -13
  199. package/src/effect/spanEvent.ts +5 -3
  200. package/src/fast-deep-equal.ts +4 -5
  201. package/src/misc.ts +3 -3
  202. package/src/mod.ts +5 -41
  203. package/src/node/mod.ts +20 -46
  204. package/src/object/index.ts +0 -24
  205. package/src/string.ts +0 -3
  206. package/dist/effect/BucketQueue.d.ts +0 -20
  207. package/dist/effect/BucketQueue.d.ts.map +0 -1
  208. package/dist/effect/BucketQueue.js +0 -34
  209. package/dist/effect/BucketQueue.js.map +0 -1
  210. package/dist/effect/Scheduler.d.ts +0 -4
  211. package/dist/effect/Scheduler.d.ts.map +0 -1
  212. package/dist/effect/Scheduler.js +0 -9
  213. package/dist/effect/Scheduler.js.map +0 -1
  214. package/dist/effect/ServiceContext.d.ts +0 -37
  215. package/dist/effect/ServiceContext.d.ts.map +0 -1
  216. package/dist/effect/ServiceContext.js +0 -55
  217. package/dist/effect/ServiceContext.js.map +0 -1
  218. package/dist/guards.d.ts +0 -20
  219. package/dist/guards.d.ts.map +0 -1
  220. package/dist/guards.js +0 -20
  221. package/dist/guards.js.map +0 -1
  222. package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts +0 -4
  223. package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +0 -1
  224. package/dist/node/ChildProcessRunner/ChildProcessRunner.js +0 -128
  225. package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +0 -1
  226. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts +0 -10
  227. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts.map +0 -1
  228. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +0 -217
  229. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +0 -1
  230. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +0 -84
  231. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts.map +0 -1
  232. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js +0 -68
  233. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js.map +0 -1
  234. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts +0 -2
  235. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts.map +0 -1
  236. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +0 -52
  237. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +0 -1
  238. package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts +0 -23
  239. package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +0 -1
  240. package/dist/node/ChildProcessRunner/ChildProcessWorker.js +0 -138
  241. package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +0 -1
  242. package/dist/object/omit.d.ts +0 -3
  243. package/dist/object/omit.d.ts.map +0 -1
  244. package/dist/object/omit.js +0 -14
  245. package/dist/object/omit.js.map +0 -1
  246. package/dist/object/pick.d.ts +0 -14
  247. package/dist/object/pick.d.ts.map +0 -1
  248. package/dist/object/pick.js +0 -17
  249. package/dist/object/pick.js.map +0 -1
  250. package/dist/time.d.ts +0 -12
  251. package/dist/time.d.ts.map +0 -1
  252. package/dist/time.js +0 -22
  253. package/dist/time.js.map +0 -1
  254. package/src/effect/BucketQueue.ts +0 -49
  255. package/src/effect/Scheduler.ts +0 -13
  256. package/src/effect/ServiceContext.ts +0 -108
  257. package/src/guards.ts +0 -23
  258. package/src/node/ChildProcessRunner/ChildProcessRunner.ts +0 -148
  259. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +0 -311
  260. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +0 -78
  261. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +0 -65
  262. package/src/node/ChildProcessRunner/ChildProcessWorker.ts +0 -169
  263. package/src/object/omit.ts +0 -17
  264. package/src/object/pick.ts +0 -27
  265. package/src/time.ts +0 -25
@@ -1,13 +1,4 @@
1
- import * as Cause from 'effect/Cause'
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, context: Context.empty() },
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.isInterruptedOnly(exit.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.RuntimeFiber<any, any>
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/FiberCurrent': Fiber.RuntimeFiber<any, any> | undefined
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 = (currentTracer: Tracer.Tracer) => {
155
- if (patchedTracer.has(currentTracer) === true) {
154
+ const ensureTracerPatched = (tracer: Tracer.Tracer) => {
155
+ if (patchedTracer.has(tracer) === true) {
156
156
  return
157
157
  }
158
- patchedTracer.add(currentTracer)
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 = currentTracer.span
161
- currentTracer.span = function (...args) {
162
- const span = oldSpanConstructor.apply(this, args)
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, ...args) {
167
- oldSpanEnd.apply(this, [endTime, exit, ...args])
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, ...args) {
173
- oldSpanEvent.apply(this, [name, startTime, attributes, ...args])
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 = currentTracer.context
181
- currentTracer.context = function (f, fiber, ...args) {
182
- const context = oldContext.apply(this, [f, fiber, ...args])
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
- // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Effect Tracer.context return type is opaque; patching requires cast
185
- return context as any
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
- ScopeImpl,
203
- { id: number; allocationFiber: Fiber.RuntimeFiber<any, any> | undefined; allocationSpan: Tracer.AnySpan | undefined }
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: ScopeImpl, allocationFiber: Fiber.RuntimeFiber<any, any> | undefined) => {
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?.currentSpan
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.RuntimeFiber<any, any>>()
237
- const ensureFiberPatched = (fiber: Fiber.RuntimeFiber<any, any>) => {
232
+ const knownFibers = new Set<Fiber.Fiber<any, any>>()
233
+ const ensureFiberPatched = (fiber: Fiber.Fiber<any, any>) => {
238
234
  // patch tracer
239
- ensureTracerPatched(fiber.currentTracer)
235
+ ensureTracerPatched(fiber.getRef(Tracer.Tracer))
240
236
  // patch scope
241
- const currentScope = Context.getOrElse(fiber.currentContext, Scope.Scope, () => undefined)
242
- // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- casting Scope to ScopeImpl; internal Effect type not publicly exported
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.RuntimeFiber<any, any>) => void)
255
- let onFiberSuspended: undefined | ((fiber: Fiber.RuntimeFiber<any, any>) => void)
256
- let onFiberCompleted: undefined | ((fiber: Fiber.RuntimeFiber<any, any>, exit: Exit.Exit<any, any>) => void)
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.RuntimeFiber<any, any>) => void
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.RuntimeFiber<any, any>) => void
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.RuntimeFiber<any, any>, exit: Exit.Exit<any, any>) => void
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.RuntimeFiber<any, any>
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/FiberCurrent', (value) => {
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
- // 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/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
- for (const [nodeId] of mutable.nodes) {
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
- (fiber) => fiber.currentSpan?.spanId === info.span.spanId && fiber.currentSpan?.traceId === info.span.traceId,
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, T extends Graph.Kind>(
382
- graph: Graph.Graph<N, E, T>,
374
+ const renderTree = <N, E>(
375
+ graph: Graph.Graph<N, E, 'directed'>,
383
376
  nodeIds: Array<number>,
384
- renderNode: (graph: Graph.Graph<N, E, T>, nodeId: number) => string[],
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
- // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- accessing fiber.currentRuntimeFlags; internal Effect runtime property
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.currentContext, Scope.Scope, () => undefined) === scope)
455
- .map((fiber) => `#${fiber.id().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().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
+ })