@clayroach/effect 3.19.14-source-capture.8 → 3.19.14-source-trace.2
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/SourceLocation/package.json +6 -0
- package/dist/cjs/Effect.js +2 -28
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/FiberRef.js +12 -1
- package/dist/cjs/FiberRef.js.map +1 -1
- package/dist/cjs/Layer.js +2 -24
- package/dist/cjs/Layer.js.map +1 -1
- package/dist/cjs/RuntimeFlags.js +1 -29
- package/dist/cjs/RuntimeFlags.js.map +1 -1
- package/dist/cjs/SourceLocation.js +60 -0
- package/dist/cjs/SourceLocation.js.map +1 -0
- package/dist/cjs/Tracer.js +1 -15
- package/dist/cjs/Tracer.js.map +1 -1
- package/dist/cjs/Utils.js +1 -1
- package/dist/cjs/Utils.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/clock.js +1 -1
- package/dist/cjs/internal/clock.js.map +1 -1
- package/dist/cjs/internal/core.js +17 -50
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/effect/circular.js +18 -30
- package/dist/cjs/internal/effect/circular.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +16 -65
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/layer/circular.js +1 -5
- package/dist/cjs/internal/layer/circular.js.map +1 -1
- package/dist/cjs/internal/layer.js +1 -3
- package/dist/cjs/internal/layer.js.map +1 -1
- package/dist/cjs/internal/logger.js +25 -2
- package/dist/cjs/internal/logger.js.map +1 -1
- package/dist/cjs/internal/runtimeFlags.js +2 -11
- package/dist/cjs/internal/runtimeFlags.js.map +1 -1
- package/dist/cjs/internal/tracer.js +1 -114
- package/dist/cjs/internal/tracer.js.map +1 -1
- package/dist/dts/Config.d.ts +2 -2
- package/dist/dts/Config.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +8 -29
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/FiberRef.d.ts +12 -0
- package/dist/dts/FiberRef.d.ts.map +1 -1
- package/dist/dts/Layer.d.ts +0 -22
- package/dist/dts/Layer.d.ts.map +1 -1
- package/dist/dts/RuntimeFlags.d.ts +0 -28
- package/dist/dts/RuntimeFlags.d.ts.map +1 -1
- package/dist/dts/SourceLocation.d.ts +88 -0
- package/dist/dts/SourceLocation.d.ts.map +1 -0
- package/dist/dts/Tracer.d.ts +0 -15
- package/dist/dts/Tracer.d.ts.map +1 -1
- package/dist/dts/index.d.ts +6 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/core.d.ts.map +1 -1
- package/dist/dts/internal/layer.d.ts.map +1 -1
- package/dist/dts/internal/runtimeFlags.d.ts.map +1 -1
- package/dist/esm/Effect.js +0 -26
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/FiberRef.js +11 -0
- package/dist/esm/FiberRef.js.map +1 -1
- package/dist/esm/Layer.js +0 -22
- package/dist/esm/Layer.js.map +1 -1
- package/dist/esm/RuntimeFlags.js +0 -28
- package/dist/esm/RuntimeFlags.js.map +1 -1
- package/dist/esm/SourceLocation.js +51 -0
- package/dist/esm/SourceLocation.js.map +1 -0
- package/dist/esm/Tracer.js +0 -14
- package/dist/esm/Tracer.js.map +1 -1
- package/dist/esm/Utils.js +1 -1
- package/dist/esm/Utils.js.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/clock.js +1 -1
- package/dist/esm/internal/clock.js.map +1 -1
- package/dist/esm/internal/core.js +12 -45
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/effect/circular.js +18 -30
- package/dist/esm/internal/effect/circular.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +13 -60
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/layer/circular.js +0 -4
- package/dist/esm/internal/layer/circular.js.map +1 -1
- package/dist/esm/internal/layer.js +0 -2
- package/dist/esm/internal/layer.js.map +1 -1
- package/dist/esm/internal/logger.js +25 -2
- package/dist/esm/internal/logger.js.map +1 -1
- package/dist/esm/internal/runtimeFlags.js +1 -9
- package/dist/esm/internal/runtimeFlags.js.map +1 -1
- package/dist/esm/internal/tracer.js +0 -111
- package/dist/esm/internal/tracer.js.map +1 -1
- package/package.json +12 -1
- package/src/Arbitrary.ts +1101 -0
- package/src/Array.ts +3589 -0
- package/src/BigDecimal.ts +1349 -0
- package/src/BigInt.ts +643 -0
- package/src/Boolean.ts +287 -0
- package/src/Brand.ts +360 -0
- package/src/Cache.ts +281 -0
- package/src/Cause.ts +1555 -0
- package/src/Channel.ts +2355 -0
- package/src/ChildExecutorDecision.ts +146 -0
- package/src/Chunk.ts +1495 -0
- package/src/Clock.ts +111 -0
- package/src/Config.ts +542 -0
- package/src/ConfigError.ts +270 -0
- package/src/ConfigProvider.ts +333 -0
- package/src/ConfigProviderPathPatch.ts +100 -0
- package/src/Console.ts +226 -0
- package/src/Context.ts +585 -0
- package/src/Cron.ts +706 -0
- package/src/Data.ts +596 -0
- package/src/DateTime.ts +1686 -0
- package/src/DefaultServices.ts +34 -0
- package/src/Deferred.ts +301 -0
- package/src/Differ.ts +450 -0
- package/src/Duration.ts +1000 -0
- package/src/Effect.ts +14817 -0
- package/src/Effectable.ts +107 -0
- package/src/Either.ts +1040 -0
- package/src/Encoding.ts +195 -0
- package/src/Equal.ts +98 -0
- package/src/Equivalence.ts +235 -0
- package/src/ExecutionPlan.ts +308 -0
- package/src/ExecutionStrategy.ts +119 -0
- package/src/Exit.ts +467 -0
- package/src/FastCheck.ts +9 -0
- package/src/Fiber.ts +744 -0
- package/src/FiberHandle.ts +540 -0
- package/src/FiberId.ts +195 -0
- package/src/FiberMap.ts +656 -0
- package/src/FiberRef.ts +444 -0
- package/src/FiberRefs.ts +204 -0
- package/src/FiberRefsPatch.ts +105 -0
- package/src/FiberSet.ts +491 -0
- package/src/FiberStatus.ts +108 -0
- package/src/Function.ts +1222 -0
- package/src/GlobalValue.ts +53 -0
- package/src/Graph.ts +3732 -0
- package/src/GroupBy.ts +103 -0
- package/src/HKT.ts +45 -0
- package/src/Hash.ts +195 -0
- package/src/HashMap.ts +519 -0
- package/src/HashRing.ts +317 -0
- package/src/HashSet.ts +2346 -0
- package/src/Inspectable.ts +287 -0
- package/src/Iterable.ts +1119 -0
- package/src/JSONSchema.ts +1044 -0
- package/src/KeyedPool.ts +167 -0
- package/src/Layer.ts +1228 -0
- package/src/LayerMap.ts +436 -0
- package/src/List.ts +977 -0
- package/src/LogLevel.ts +285 -0
- package/src/LogSpan.ts +25 -0
- package/src/Logger.ts +702 -0
- package/src/Mailbox.ts +268 -0
- package/src/ManagedRuntime.ts +180 -0
- package/src/Match.ts +1477 -0
- package/src/MergeDecision.ts +95 -0
- package/src/MergeState.ts +172 -0
- package/src/MergeStrategy.ts +107 -0
- package/src/Metric.ts +780 -0
- package/src/MetricBoundaries.ts +69 -0
- package/src/MetricHook.ts +151 -0
- package/src/MetricKey.ts +224 -0
- package/src/MetricKeyType.ts +262 -0
- package/src/MetricLabel.ts +47 -0
- package/src/MetricPair.ts +71 -0
- package/src/MetricPolling.ts +148 -0
- package/src/MetricRegistry.ts +48 -0
- package/src/MetricState.ts +257 -0
- package/src/Micro.ts +4405 -0
- package/src/ModuleVersion.ts +18 -0
- package/src/MutableHashMap.ts +411 -0
- package/src/MutableHashSet.ts +706 -0
- package/src/MutableList.ts +297 -0
- package/src/MutableQueue.ts +227 -0
- package/src/MutableRef.ts +202 -0
- package/src/NonEmptyIterable.ts +32 -0
- package/src/Number.ts +1071 -0
- package/src/Option.ts +2170 -0
- package/src/Order.ts +373 -0
- package/src/Ordering.ts +111 -0
- package/src/ParseResult.ts +2031 -0
- package/src/PartitionedSemaphore.ts +200 -0
- package/src/Pipeable.ts +566 -0
- package/src/Pool.ts +204 -0
- package/src/Predicate.ts +1405 -0
- package/src/Pretty.ts +205 -0
- package/src/PrimaryKey.ts +23 -0
- package/src/PubSub.ts +182 -0
- package/src/Queue.ts +644 -0
- package/src/Random.ts +204 -0
- package/src/RateLimiter.ts +138 -0
- package/src/RcMap.ts +141 -0
- package/src/RcRef.ts +122 -0
- package/src/Readable.ts +93 -0
- package/src/Record.ts +1274 -0
- package/src/RedBlackTree.ts +421 -0
- package/src/Redacted.ts +144 -0
- package/src/Ref.ts +180 -0
- package/src/RegExp.ts +38 -0
- package/src/Reloadable.ts +127 -0
- package/src/Request.ts +347 -0
- package/src/RequestBlock.ts +118 -0
- package/src/RequestResolver.ts +366 -0
- package/src/Resource.ts +119 -0
- package/src/Runtime.ts +383 -0
- package/src/RuntimeFlags.ts +336 -0
- package/src/RuntimeFlagsPatch.ts +183 -0
- package/src/STM.ts +2045 -0
- package/src/Schedule.ts +2219 -0
- package/src/ScheduleDecision.ts +62 -0
- package/src/ScheduleInterval.ts +151 -0
- package/src/ScheduleIntervals.ts +122 -0
- package/src/Scheduler.ts +353 -0
- package/src/Schema.ts +10914 -0
- package/src/SchemaAST.ts +3043 -0
- package/src/Scope.ts +204 -0
- package/src/ScopedCache.ts +151 -0
- package/src/ScopedRef.ts +117 -0
- package/src/Secret.ts +88 -0
- package/src/SingleProducerAsyncInput.ts +67 -0
- package/src/Sink.ts +1461 -0
- package/src/SortedMap.ts +287 -0
- package/src/SortedSet.ts +390 -0
- package/src/SourceLocation.ts +108 -0
- package/src/Stream.ts +6468 -0
- package/src/StreamEmit.ts +136 -0
- package/src/StreamHaltStrategy.ts +123 -0
- package/src/Streamable.ts +45 -0
- package/src/String.ts +778 -0
- package/src/Struct.ts +243 -0
- package/src/Subscribable.ts +100 -0
- package/src/SubscriptionRef.ts +298 -0
- package/src/Supervisor.ts +240 -0
- package/src/Symbol.ts +29 -0
- package/src/SynchronizedRef.ts +270 -0
- package/src/TArray.ts +495 -0
- package/src/TDeferred.ts +100 -0
- package/src/TMap.ts +515 -0
- package/src/TPriorityQueue.ts +223 -0
- package/src/TPubSub.ts +200 -0
- package/src/TQueue.ts +432 -0
- package/src/TRandom.ts +129 -0
- package/src/TReentrantLock.ts +224 -0
- package/src/TRef.ts +178 -0
- package/src/TSemaphore.ts +129 -0
- package/src/TSet.ts +365 -0
- package/src/TSubscriptionRef.ts +192 -0
- package/src/Take.ts +258 -0
- package/src/TestAnnotation.ts +158 -0
- package/src/TestAnnotationMap.ts +119 -0
- package/src/TestAnnotations.ts +117 -0
- package/src/TestClock.ts +556 -0
- package/src/TestConfig.ts +47 -0
- package/src/TestContext.ts +36 -0
- package/src/TestLive.ts +53 -0
- package/src/TestServices.ts +390 -0
- package/src/TestSized.ts +55 -0
- package/src/Tracer.ts +182 -0
- package/src/Trie.ts +840 -0
- package/src/Tuple.ts +305 -0
- package/src/Types.ts +353 -0
- package/src/Unify.ts +113 -0
- package/src/UpstreamPullRequest.ts +117 -0
- package/src/UpstreamPullStrategy.ts +121 -0
- package/src/Utils.ts +809 -0
- package/src/index.ts +1568 -0
- package/src/internal/array.ts +8 -0
- package/src/internal/blockedRequests.ts +520 -0
- package/src/internal/cache.ts +733 -0
- package/src/internal/cause.ts +1050 -0
- package/src/internal/channel/channelExecutor.ts +1200 -0
- package/src/internal/channel/channelState.ts +134 -0
- package/src/internal/channel/childExecutorDecision.ts +96 -0
- package/src/internal/channel/continuation.ts +200 -0
- package/src/internal/channel/mergeDecision.ts +113 -0
- package/src/internal/channel/mergeState.ts +120 -0
- package/src/internal/channel/mergeStrategy.ts +72 -0
- package/src/internal/channel/singleProducerAsyncInput.ts +259 -0
- package/src/internal/channel/subexecutor.ts +229 -0
- package/src/internal/channel/upstreamPullRequest.ts +84 -0
- package/src/internal/channel/upstreamPullStrategy.ts +87 -0
- package/src/internal/channel.ts +2603 -0
- package/src/internal/clock.ts +95 -0
- package/src/internal/completedRequestMap.ts +9 -0
- package/src/internal/concurrency.ts +54 -0
- package/src/internal/config.ts +716 -0
- package/src/internal/configError.ts +304 -0
- package/src/internal/configProvider/pathPatch.ts +97 -0
- package/src/internal/configProvider.ts +799 -0
- package/src/internal/console.ts +153 -0
- package/src/internal/context.ts +337 -0
- package/src/internal/core-effect.ts +2293 -0
- package/src/internal/core-stream.ts +998 -0
- package/src/internal/core.ts +3189 -0
- package/src/internal/data.ts +36 -0
- package/src/internal/dataSource.ts +327 -0
- package/src/internal/dateTime.ts +1277 -0
- package/src/internal/defaultServices/console.ts +100 -0
- package/src/internal/defaultServices.ts +163 -0
- package/src/internal/deferred.ts +46 -0
- package/src/internal/differ/chunkPatch.ts +211 -0
- package/src/internal/differ/contextPatch.ts +232 -0
- package/src/internal/differ/hashMapPatch.ts +220 -0
- package/src/internal/differ/hashSetPatch.ts +176 -0
- package/src/internal/differ/orPatch.ts +311 -0
- package/src/internal/differ/readonlyArrayPatch.ts +210 -0
- package/src/internal/differ.ts +200 -0
- package/src/internal/doNotation.ts +80 -0
- package/src/internal/effect/circular.ts +895 -0
- package/src/internal/effectable.ts +131 -0
- package/src/internal/either.ts +110 -0
- package/src/internal/encoding/base64.ts +286 -0
- package/src/internal/encoding/base64Url.ts +29 -0
- package/src/internal/encoding/common.ts +51 -0
- package/src/internal/encoding/hex.ts +315 -0
- package/src/internal/errors.ts +7 -0
- package/src/internal/executionPlan.ts +114 -0
- package/src/internal/executionStrategy.ts +74 -0
- package/src/internal/fiber.ts +388 -0
- package/src/internal/fiberId.ts +267 -0
- package/src/internal/fiberMessage.ts +82 -0
- package/src/internal/fiberRefs/patch.ts +144 -0
- package/src/internal/fiberRefs.ts +297 -0
- package/src/internal/fiberRuntime.ts +3842 -0
- package/src/internal/fiberScope.ts +71 -0
- package/src/internal/fiberStatus.ts +119 -0
- package/src/internal/groupBy.ts +530 -0
- package/src/internal/hashMap/array.ts +49 -0
- package/src/internal/hashMap/bitwise.ts +32 -0
- package/src/internal/hashMap/config.ts +14 -0
- package/src/internal/hashMap/keySet.ts +8 -0
- package/src/internal/hashMap/node.ts +391 -0
- package/src/internal/hashMap.ts +586 -0
- package/src/internal/hashSet.ts +323 -0
- package/src/internal/keyedPool.ts +244 -0
- package/src/internal/layer/circular.ts +214 -0
- package/src/internal/layer.ts +1483 -0
- package/src/internal/logSpan.ts +20 -0
- package/src/internal/logger-circular.ts +24 -0
- package/src/internal/logger.ts +522 -0
- package/src/internal/mailbox.ts +561 -0
- package/src/internal/managedRuntime/circular.ts +6 -0
- package/src/internal/managedRuntime.ts +134 -0
- package/src/internal/matcher.ts +652 -0
- package/src/internal/metric/boundaries.ts +75 -0
- package/src/internal/metric/hook.ts +483 -0
- package/src/internal/metric/key.ts +167 -0
- package/src/internal/metric/keyType.ts +238 -0
- package/src/internal/metric/label.ts +41 -0
- package/src/internal/metric/pair.ts +48 -0
- package/src/internal/metric/polling.ts +149 -0
- package/src/internal/metric/registry.ts +187 -0
- package/src/internal/metric/state.ts +290 -0
- package/src/internal/metric.ts +577 -0
- package/src/internal/opCodes/cause.ts +35 -0
- package/src/internal/opCodes/channel.ts +83 -0
- package/src/internal/opCodes/channelChildExecutorDecision.ts +17 -0
- package/src/internal/opCodes/channelMergeDecision.ts +11 -0
- package/src/internal/opCodes/channelMergeState.ts +17 -0
- package/src/internal/opCodes/channelMergeStrategy.ts +11 -0
- package/src/internal/opCodes/channelState.ts +23 -0
- package/src/internal/opCodes/channelUpstreamPullRequest.ts +11 -0
- package/src/internal/opCodes/channelUpstreamPullStrategy.ts +11 -0
- package/src/internal/opCodes/config.ts +65 -0
- package/src/internal/opCodes/configError.ts +35 -0
- package/src/internal/opCodes/continuation.ts +11 -0
- package/src/internal/opCodes/deferred.ts +11 -0
- package/src/internal/opCodes/effect.ts +89 -0
- package/src/internal/opCodes/layer.ts +59 -0
- package/src/internal/opCodes/streamHaltStrategy.ts +23 -0
- package/src/internal/option.ts +80 -0
- package/src/internal/pool.ts +432 -0
- package/src/internal/pubsub.ts +1762 -0
- package/src/internal/query.ts +204 -0
- package/src/internal/queue.ts +766 -0
- package/src/internal/random.ts +161 -0
- package/src/internal/rateLimiter.ts +93 -0
- package/src/internal/rcMap.ts +285 -0
- package/src/internal/rcRef.ts +192 -0
- package/src/internal/redBlackTree/iterator.ts +200 -0
- package/src/internal/redBlackTree/node.ts +68 -0
- package/src/internal/redBlackTree.ts +1245 -0
- package/src/internal/redacted.ts +73 -0
- package/src/internal/ref.ts +171 -0
- package/src/internal/reloadable.ts +140 -0
- package/src/internal/request.ts +177 -0
- package/src/internal/resource.ts +76 -0
- package/src/internal/ringBuffer.ts +68 -0
- package/src/internal/runtime.ts +558 -0
- package/src/internal/runtimeFlags.ts +178 -0
- package/src/internal/runtimeFlagsPatch.ts +103 -0
- package/src/internal/schedule/decision.ts +47 -0
- package/src/internal/schedule/interval.ts +101 -0
- package/src/internal/schedule/intervals.ts +180 -0
- package/src/internal/schedule.ts +2199 -0
- package/src/internal/schema/errors.ts +191 -0
- package/src/internal/schema/schemaId.ts +106 -0
- package/src/internal/schema/util.ts +50 -0
- package/src/internal/scopedCache.ts +644 -0
- package/src/internal/scopedRef.ts +118 -0
- package/src/internal/secret.ts +89 -0
- package/src/internal/singleShotGen.ts +35 -0
- package/src/internal/sink.ts +2120 -0
- package/src/internal/stack.ts +10 -0
- package/src/internal/stm/core.ts +817 -0
- package/src/internal/stm/entry.ts +59 -0
- package/src/internal/stm/journal.ts +123 -0
- package/src/internal/stm/opCodes/stm.ts +71 -0
- package/src/internal/stm/opCodes/stmState.ts +17 -0
- package/src/internal/stm/opCodes/strategy.ts +17 -0
- package/src/internal/stm/opCodes/tExit.ts +29 -0
- package/src/internal/stm/opCodes/tryCommit.ts +11 -0
- package/src/internal/stm/stm.ts +1453 -0
- package/src/internal/stm/stmState.ts +136 -0
- package/src/internal/stm/tArray.ts +550 -0
- package/src/internal/stm/tDeferred.ts +81 -0
- package/src/internal/stm/tExit.ts +190 -0
- package/src/internal/stm/tMap.ts +824 -0
- package/src/internal/stm/tPriorityQueue.ts +267 -0
- package/src/internal/stm/tPubSub.ts +551 -0
- package/src/internal/stm/tQueue.ts +393 -0
- package/src/internal/stm/tRandom.ts +140 -0
- package/src/internal/stm/tReentrantLock.ts +352 -0
- package/src/internal/stm/tRef.ts +195 -0
- package/src/internal/stm/tSemaphore.ts +113 -0
- package/src/internal/stm/tSet.ts +259 -0
- package/src/internal/stm/tSubscriptionRef.ts +286 -0
- package/src/internal/stm/tryCommit.ts +34 -0
- package/src/internal/stm/txnId.ts +14 -0
- package/src/internal/stm/versioned.ts +4 -0
- package/src/internal/stream/debounceState.ts +57 -0
- package/src/internal/stream/emit.ts +123 -0
- package/src/internal/stream/haltStrategy.ts +94 -0
- package/src/internal/stream/handoff.ts +187 -0
- package/src/internal/stream/handoffSignal.ts +59 -0
- package/src/internal/stream/pull.ts +34 -0
- package/src/internal/stream/sinkEndReason.ts +30 -0
- package/src/internal/stream/zipAllState.ts +88 -0
- package/src/internal/stream/zipChunksState.ts +56 -0
- package/src/internal/stream.ts +8801 -0
- package/src/internal/string-utils.ts +107 -0
- package/src/internal/subscriptionRef.ts +138 -0
- package/src/internal/supervisor/patch.ts +190 -0
- package/src/internal/supervisor.ts +303 -0
- package/src/internal/synchronizedRef.ts +114 -0
- package/src/internal/take.ts +199 -0
- package/src/internal/testing/sleep.ts +27 -0
- package/src/internal/testing/suspendedWarningData.ts +85 -0
- package/src/internal/testing/warningData.ts +94 -0
- package/src/internal/tracer.ts +150 -0
- package/src/internal/trie.ts +722 -0
- package/src/internal/version.ts +7 -0
package/src/TestClock.ts
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 2.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Chunk from "./Chunk.js"
|
|
5
|
+
import type * as Clock from "./Clock.js"
|
|
6
|
+
import * as Context from "./Context.js"
|
|
7
|
+
import * as DateTime from "./DateTime.js"
|
|
8
|
+
import type * as Deferred from "./Deferred.js"
|
|
9
|
+
import * as Duration from "./Duration.js"
|
|
10
|
+
import type * as Effect from "./Effect.js"
|
|
11
|
+
import * as Equal from "./Equal.js"
|
|
12
|
+
import type * as Fiber from "./Fiber.js"
|
|
13
|
+
import type * as FiberId from "./FiberId.js"
|
|
14
|
+
import * as FiberStatus from "./FiberStatus.js"
|
|
15
|
+
import { constVoid, dual, identity, pipe } from "./Function.js"
|
|
16
|
+
import * as HashMap from "./HashMap.js"
|
|
17
|
+
import * as clock from "./internal/clock.js"
|
|
18
|
+
import * as effect from "./internal/core-effect.js"
|
|
19
|
+
import * as core from "./internal/core.js"
|
|
20
|
+
import * as defaultServices from "./internal/defaultServices.js"
|
|
21
|
+
import * as circular from "./internal/effect/circular.js"
|
|
22
|
+
import * as fiberRuntime from "./internal/fiberRuntime.js"
|
|
23
|
+
import * as layer from "./internal/layer.js"
|
|
24
|
+
import * as ref from "./internal/ref.js"
|
|
25
|
+
import * as synchronized from "./internal/synchronizedRef.js"
|
|
26
|
+
import * as SuspendedWarningData from "./internal/testing/suspendedWarningData.js"
|
|
27
|
+
import * as WarningData from "./internal/testing/warningData.js"
|
|
28
|
+
import type * as Layer from "./Layer.js"
|
|
29
|
+
import * as number from "./Number.js"
|
|
30
|
+
import * as Option from "./Option.js"
|
|
31
|
+
import * as Order from "./Order.js"
|
|
32
|
+
import type * as Ref from "./Ref.js"
|
|
33
|
+
import type * as SortedSet from "./SortedSet.js"
|
|
34
|
+
import type * as Synchronized from "./SynchronizedRef.js"
|
|
35
|
+
import * as Annotations from "./TestAnnotations.js"
|
|
36
|
+
import * as Live from "./TestLive.js"
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A `TestClock` makes it easy to deterministically and efficiently test effects
|
|
40
|
+
* involving the passage of time.
|
|
41
|
+
*
|
|
42
|
+
* Instead of waiting for actual time to pass, `sleep` and methods implemented
|
|
43
|
+
* in terms of it schedule effects to take place at a given clock time. Users
|
|
44
|
+
* can adjust the clock time using the `adjust` and `setTime` methods, and all
|
|
45
|
+
* effects scheduled to take place on or before that time will automatically be
|
|
46
|
+
* run in order.
|
|
47
|
+
*
|
|
48
|
+
* For example, here is how we can test `Effect.timeout` using `TestClock`:
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* import * as assert from "node:assert"
|
|
52
|
+
* import { Duration, Effect, Fiber, TestClock, Option, pipe } from "effect"
|
|
53
|
+
*
|
|
54
|
+
* Effect.gen(function*() {
|
|
55
|
+
* const fiber = yield* pipe(
|
|
56
|
+
* Effect.sleep(Duration.minutes(5)),
|
|
57
|
+
* Effect.timeout(Duration.minutes(1)),
|
|
58
|
+
* Effect.fork
|
|
59
|
+
* )
|
|
60
|
+
* yield* TestClock.adjust(Duration.minutes(1))
|
|
61
|
+
* const result = yield* Fiber.join(fiber)
|
|
62
|
+
* assert.deepStrictEqual(result, Option.none())
|
|
63
|
+
* })
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Note how we forked the fiber that `sleep` was invoked on. Calls to `sleep`
|
|
67
|
+
* and methods derived from it will semantically block until the time is set to
|
|
68
|
+
* on or after the time they are scheduled to run. If we didn't fork the fiber
|
|
69
|
+
* on which we called sleep we would never get to set the time on the line
|
|
70
|
+
* below. Thus, a useful pattern when using `TestClock` is to fork the effect
|
|
71
|
+
* being tested, then adjust the clock time, and finally verify that the
|
|
72
|
+
* expected effects have been performed.
|
|
73
|
+
*
|
|
74
|
+
* @since 2.0.0
|
|
75
|
+
*/
|
|
76
|
+
export interface TestClock extends Clock.Clock {
|
|
77
|
+
adjust(duration: Duration.DurationInput): Effect.Effect<void>
|
|
78
|
+
adjustWith(duration: Duration.DurationInput): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
|
|
79
|
+
readonly save: Effect.Effect<Effect.Effect<void>>
|
|
80
|
+
setTime(time: number): Effect.Effect<void>
|
|
81
|
+
readonly sleeps: Effect.Effect<Chunk.Chunk<number>>
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* `Data` represents the state of the `TestClock`, including the clock time.
|
|
86
|
+
*
|
|
87
|
+
* @since 2.0.1
|
|
88
|
+
*/
|
|
89
|
+
export interface Data {
|
|
90
|
+
readonly instant: number
|
|
91
|
+
readonly sleeps: Chunk.Chunk<readonly [number, Deferred.Deferred<void>]>
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @since 2.0.0
|
|
96
|
+
*/
|
|
97
|
+
export const makeData = (
|
|
98
|
+
instant: number,
|
|
99
|
+
sleeps: Chunk.Chunk<readonly [number, Deferred.Deferred<void>]>
|
|
100
|
+
): Data => ({
|
|
101
|
+
instant,
|
|
102
|
+
sleeps
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @since 2.0.0
|
|
107
|
+
*/
|
|
108
|
+
export const TestClock: Context.Tag<TestClock, TestClock> = Context.GenericTag<TestClock>("effect/TestClock")
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The warning message that will be displayed if a test is using time but is
|
|
112
|
+
* not advancing the `TestClock`.
|
|
113
|
+
*
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
const warning = "Warning: A test is using time, but is not advancing " +
|
|
117
|
+
"the test clock, which may result in the test hanging. Use TestClock.adjust to " +
|
|
118
|
+
"manually advance the time."
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The warning message that will be displayed if a test is advancing the clock
|
|
122
|
+
* but a fiber is still running.
|
|
123
|
+
*
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
126
|
+
const suspendedWarning = "Warning: A test is advancing the test clock, " +
|
|
127
|
+
"but a fiber is not suspending, which may result in the test hanging. Use " +
|
|
128
|
+
"TestAspect.diagnose to identity the fiber that is not suspending."
|
|
129
|
+
|
|
130
|
+
/** @internal */
|
|
131
|
+
export class TestClockImpl implements TestClock {
|
|
132
|
+
[clock.ClockTypeId]: Clock.ClockTypeId = clock.ClockTypeId
|
|
133
|
+
constructor(
|
|
134
|
+
readonly clockState: Ref.Ref<Data>,
|
|
135
|
+
readonly live: Live.TestLive,
|
|
136
|
+
readonly annotations: Annotations.TestAnnotations,
|
|
137
|
+
readonly warningState: Synchronized.SynchronizedRef<WarningData.WarningData>,
|
|
138
|
+
readonly suspendedWarningState: Synchronized.SynchronizedRef<SuspendedWarningData.SuspendedWarningData>
|
|
139
|
+
) {
|
|
140
|
+
this.currentTimeMillis = core.map(
|
|
141
|
+
ref.get(this.clockState),
|
|
142
|
+
(data) => data.instant
|
|
143
|
+
)
|
|
144
|
+
this.currentTimeNanos = core.map(
|
|
145
|
+
ref.get(this.clockState),
|
|
146
|
+
(data) => BigInt(data.instant * 1000000)
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Unsafely returns the current time in milliseconds.
|
|
152
|
+
*/
|
|
153
|
+
unsafeCurrentTimeMillis(): number {
|
|
154
|
+
return ref.unsafeGet(this.clockState).instant
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Unsafely returns the current time in nanoseconds.
|
|
159
|
+
*/
|
|
160
|
+
unsafeCurrentTimeNanos(): bigint {
|
|
161
|
+
return BigInt(ref.unsafeGet(this.clockState).instant * 1000000)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Returns the current clock time in milliseconds.
|
|
166
|
+
*/
|
|
167
|
+
currentTimeMillis: Effect.Effect<number>
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Returns the current clock time in nanoseconds.
|
|
171
|
+
*/
|
|
172
|
+
currentTimeNanos: Effect.Effect<bigint>
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Saves the `TestClock`'s current state in an effect which, when run, will
|
|
176
|
+
* restore the `TestClock` state to the saved state.
|
|
177
|
+
*/
|
|
178
|
+
get save(): Effect.Effect<Effect.Effect<void>> {
|
|
179
|
+
return core.map(ref.get(this.clockState), (data) => ref.set(this.clockState, data))
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Sets the current clock time to the specified instant. Any effects that
|
|
183
|
+
* were scheduled to occur on or before the new time will be run in order.
|
|
184
|
+
*/
|
|
185
|
+
setTime(instant: number): Effect.Effect<void> {
|
|
186
|
+
return core.zipRight(this.warningDone(), this.run(() => instant))
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Semantically blocks the current fiber until the clock time is equal to or
|
|
190
|
+
* greater than the specified duration. Once the clock time is adjusted to
|
|
191
|
+
* on or after the duration, the fiber will automatically be resumed.
|
|
192
|
+
*/
|
|
193
|
+
sleep(durationInput: Duration.DurationInput): Effect.Effect<void> {
|
|
194
|
+
const duration = Duration.decode(durationInput)
|
|
195
|
+
return core.flatMap(core.deferredMake<void>(), (deferred) =>
|
|
196
|
+
pipe(
|
|
197
|
+
ref.modify(this.clockState, (data) => {
|
|
198
|
+
const end = data.instant + Duration.toMillis(duration)
|
|
199
|
+
if (end > data.instant) {
|
|
200
|
+
return [
|
|
201
|
+
true,
|
|
202
|
+
makeData(data.instant, pipe(data.sleeps, Chunk.prepend([end, deferred] as const)))
|
|
203
|
+
] as const
|
|
204
|
+
}
|
|
205
|
+
return [false, data] as const
|
|
206
|
+
}),
|
|
207
|
+
core.flatMap((shouldAwait) =>
|
|
208
|
+
shouldAwait ?
|
|
209
|
+
pipe(this.warningStart(), core.zipRight(core.deferredAwait(deferred))) :
|
|
210
|
+
pipe(core.deferredSucceed(deferred, void 0), core.asVoid)
|
|
211
|
+
)
|
|
212
|
+
))
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Returns a list of the times at which all queued effects are scheduled to
|
|
216
|
+
* resume.
|
|
217
|
+
*/
|
|
218
|
+
get sleeps(): Effect.Effect<Chunk.Chunk<number>> {
|
|
219
|
+
return core.map(
|
|
220
|
+
ref.get(this.clockState),
|
|
221
|
+
(data) => Chunk.map(data.sleeps, (_) => _[0])
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Increments the current clock time by the specified duration. Any effects
|
|
226
|
+
* that were scheduled to occur on or before the new time will be run in
|
|
227
|
+
* order.
|
|
228
|
+
*/
|
|
229
|
+
adjust(durationInput: Duration.DurationInput): Effect.Effect<void> {
|
|
230
|
+
const duration = Duration.decode(durationInput)
|
|
231
|
+
return core.zipRight(this.warningDone(), this.run((n) => n + Duration.toMillis(duration)))
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Increments the current clock time by the specified duration. Any effects
|
|
235
|
+
* that were scheduled to occur on or before the new time will be run in
|
|
236
|
+
* order.
|
|
237
|
+
*/
|
|
238
|
+
adjustWith(durationInput: Duration.DurationInput) {
|
|
239
|
+
const duration = Duration.decode(durationInput)
|
|
240
|
+
return <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
241
|
+
fiberRuntime.zipLeftOptions(effect, this.adjust(duration), { concurrent: true })
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Returns a set of all fibers in this test.
|
|
245
|
+
*/
|
|
246
|
+
supervisedFibers(): Effect.Effect<SortedSet.SortedSet<Fiber.RuntimeFiber<unknown, unknown>>> {
|
|
247
|
+
return this.annotations.supervisedFibers
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Captures a "snapshot" of the identifier and status of all fibers in this
|
|
251
|
+
* test other than the current fiber. Fails with the `void` value if any of
|
|
252
|
+
* these fibers are not done or suspended. Note that because we cannot
|
|
253
|
+
* synchronize on the status of multiple fibers at the same time this
|
|
254
|
+
* snapshot may not be fully consistent.
|
|
255
|
+
*/
|
|
256
|
+
freeze(): Effect.Effect<HashMap.HashMap<FiberId.FiberId, FiberStatus.FiberStatus>, void> {
|
|
257
|
+
return core.flatMap(this.supervisedFibers(), (fibers) =>
|
|
258
|
+
pipe(
|
|
259
|
+
fibers,
|
|
260
|
+
effect.reduce(HashMap.empty<FiberId.FiberId, FiberStatus.FiberStatus>(), (map, fiber) =>
|
|
261
|
+
pipe(
|
|
262
|
+
fiber.status,
|
|
263
|
+
core.flatMap((status) => {
|
|
264
|
+
if (FiberStatus.isDone(status)) {
|
|
265
|
+
return core.succeed(HashMap.set(map, fiber.id() as FiberId.FiberId, status as FiberStatus.FiberStatus))
|
|
266
|
+
}
|
|
267
|
+
if (FiberStatus.isSuspended(status)) {
|
|
268
|
+
return core.succeed(HashMap.set(map, fiber.id() as FiberId.FiberId, status as FiberStatus.FiberStatus))
|
|
269
|
+
}
|
|
270
|
+
return core.fail(void 0)
|
|
271
|
+
})
|
|
272
|
+
))
|
|
273
|
+
))
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Forks a fiber that will display a warning message if a test is using time
|
|
277
|
+
* but is not advancing the `TestClock`.
|
|
278
|
+
*/
|
|
279
|
+
warningStart(): Effect.Effect<void> {
|
|
280
|
+
return synchronized.updateSomeEffect(this.warningState, (data) =>
|
|
281
|
+
WarningData.isStart(data) ?
|
|
282
|
+
Option.some(
|
|
283
|
+
pipe(
|
|
284
|
+
this.live.provide(
|
|
285
|
+
pipe(effect.logWarning(warning), effect.delay(Duration.seconds(5)))
|
|
286
|
+
),
|
|
287
|
+
core.interruptible,
|
|
288
|
+
fiberRuntime.fork,
|
|
289
|
+
core.map((fiber) => WarningData.pending(fiber))
|
|
290
|
+
)
|
|
291
|
+
) :
|
|
292
|
+
Option.none())
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Cancels the warning message that is displayed if a test is using time but
|
|
296
|
+
* is not advancing the `TestClock`.
|
|
297
|
+
*/
|
|
298
|
+
warningDone(): Effect.Effect<void> {
|
|
299
|
+
return synchronized.updateSomeEffect(this.warningState, (warningData) => {
|
|
300
|
+
if (WarningData.isStart(warningData)) {
|
|
301
|
+
return Option.some(core.succeed(WarningData.done))
|
|
302
|
+
}
|
|
303
|
+
if (WarningData.isPending(warningData)) {
|
|
304
|
+
return Option.some(pipe(core.interruptFiber(warningData.fiber), core.as(WarningData.done)))
|
|
305
|
+
}
|
|
306
|
+
return Option.none()
|
|
307
|
+
})
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private yieldTimer = core.async<void>((resume) => {
|
|
311
|
+
const timer = setTimeout(() => {
|
|
312
|
+
resume(core.void)
|
|
313
|
+
}, 0)
|
|
314
|
+
return core.sync(() => clearTimeout(timer))
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Returns whether all descendants of this fiber are done or suspended.
|
|
319
|
+
*/
|
|
320
|
+
suspended(): Effect.Effect<HashMap.HashMap<FiberId.FiberId, FiberStatus.FiberStatus>, void> {
|
|
321
|
+
return pipe(
|
|
322
|
+
this.freeze(),
|
|
323
|
+
core.zip(pipe(this.yieldTimer, core.zipRight(this.freeze()))),
|
|
324
|
+
core.flatMap(([first, last]) =>
|
|
325
|
+
Equal.equals(first, last) ?
|
|
326
|
+
core.succeed(first) :
|
|
327
|
+
core.fail(void 0)
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Polls until all descendants of this fiber are done or suspended.
|
|
333
|
+
*/
|
|
334
|
+
awaitSuspended(): Effect.Effect<void> {
|
|
335
|
+
return pipe(
|
|
336
|
+
this.suspendedWarningStart(),
|
|
337
|
+
core.zipRight(
|
|
338
|
+
pipe(
|
|
339
|
+
this.suspended(),
|
|
340
|
+
core.zipWith(
|
|
341
|
+
pipe(this.yieldTimer, core.zipRight(this.suspended())),
|
|
342
|
+
Equal.equals
|
|
343
|
+
),
|
|
344
|
+
effect.filterOrFail(identity, constVoid),
|
|
345
|
+
effect.eventually
|
|
346
|
+
)
|
|
347
|
+
),
|
|
348
|
+
core.zipRight(this.suspendedWarningDone())
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Forks a fiber that will display a warning message if a test is advancing
|
|
353
|
+
* the `TestClock` but a fiber is not suspending.
|
|
354
|
+
*/
|
|
355
|
+
suspendedWarningStart(): Effect.Effect<void> {
|
|
356
|
+
return synchronized.updateSomeEffect(this.suspendedWarningState, (suspendedWarningData) => {
|
|
357
|
+
if (SuspendedWarningData.isStart(suspendedWarningData)) {
|
|
358
|
+
return Option.some(
|
|
359
|
+
pipe(
|
|
360
|
+
this.live.provide(
|
|
361
|
+
pipe(
|
|
362
|
+
effect.logWarning(suspendedWarning),
|
|
363
|
+
core.zipRight(ref.set(this.suspendedWarningState, SuspendedWarningData.done)),
|
|
364
|
+
effect.delay(Duration.seconds(5))
|
|
365
|
+
)
|
|
366
|
+
),
|
|
367
|
+
core.interruptible,
|
|
368
|
+
fiberRuntime.fork,
|
|
369
|
+
core.map((fiber) => SuspendedWarningData.pending(fiber))
|
|
370
|
+
)
|
|
371
|
+
)
|
|
372
|
+
}
|
|
373
|
+
return Option.none()
|
|
374
|
+
})
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Cancels the warning message that is displayed if a test is advancing the
|
|
378
|
+
* `TestClock` but a fiber is not suspending.
|
|
379
|
+
*/
|
|
380
|
+
suspendedWarningDone(): Effect.Effect<void> {
|
|
381
|
+
return synchronized.updateSomeEffect(this.suspendedWarningState, (suspendedWarningData) => {
|
|
382
|
+
if (SuspendedWarningData.isPending(suspendedWarningData)) {
|
|
383
|
+
return Option.some(pipe(core.interruptFiber(suspendedWarningData.fiber), core.as(SuspendedWarningData.start)))
|
|
384
|
+
}
|
|
385
|
+
return Option.none()
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Runs all effects scheduled to occur on or before the specified instant,
|
|
390
|
+
* which may depend on the current time, in order.
|
|
391
|
+
*/
|
|
392
|
+
run(f: (instant: number) => number): Effect.Effect<void> {
|
|
393
|
+
return pipe(
|
|
394
|
+
this.awaitSuspended(),
|
|
395
|
+
core.zipRight(pipe(
|
|
396
|
+
ref.modify(this.clockState, (data) => {
|
|
397
|
+
const end = f(data.instant)
|
|
398
|
+
const sorted = pipe(
|
|
399
|
+
data.sleeps,
|
|
400
|
+
Chunk.sort<readonly [number, Deferred.Deferred<void>]>(
|
|
401
|
+
pipe(number.Order, Order.mapInput((_) => _[0]))
|
|
402
|
+
)
|
|
403
|
+
)
|
|
404
|
+
if (Chunk.isNonEmpty(sorted)) {
|
|
405
|
+
const [instant, deferred] = Chunk.headNonEmpty(sorted)
|
|
406
|
+
if (instant <= end) {
|
|
407
|
+
return [
|
|
408
|
+
Option.some([end, deferred] as const),
|
|
409
|
+
makeData(instant, Chunk.tailNonEmpty(sorted))
|
|
410
|
+
] as const
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return [Option.none(), makeData(end, data.sleeps)] as const
|
|
414
|
+
}),
|
|
415
|
+
core.flatMap((option) => {
|
|
416
|
+
switch (option._tag) {
|
|
417
|
+
case "None": {
|
|
418
|
+
return core.void
|
|
419
|
+
}
|
|
420
|
+
case "Some": {
|
|
421
|
+
const [end, deferred] = option.value
|
|
422
|
+
return pipe(
|
|
423
|
+
core.deferredSucceed(deferred, void 0),
|
|
424
|
+
core.zipRight(core.yieldNow()),
|
|
425
|
+
core.zipRight(this.run(() => end))
|
|
426
|
+
)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
})
|
|
430
|
+
))
|
|
431
|
+
)
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* @since 2.0.0
|
|
437
|
+
*/
|
|
438
|
+
export const live = (data: Data): Layer.Layer<TestClock, never, Annotations.TestAnnotations | Live.TestLive> =>
|
|
439
|
+
layer.scoped(
|
|
440
|
+
TestClock,
|
|
441
|
+
core.gen(function*() {
|
|
442
|
+
const live = yield* Live.TestLive
|
|
443
|
+
const annotations = yield* Annotations.TestAnnotations
|
|
444
|
+
const clockState = yield* core.sync(() => ref.unsafeMake(data))
|
|
445
|
+
const warningState = yield* circular.makeSynchronized(WarningData.start)
|
|
446
|
+
const suspendedWarningState = yield* circular.makeSynchronized(SuspendedWarningData.start)
|
|
447
|
+
const testClock = new TestClockImpl(clockState, live, annotations, warningState, suspendedWarningState)
|
|
448
|
+
yield* fiberRuntime.withClockScoped(testClock)
|
|
449
|
+
yield* fiberRuntime.addFinalizer(
|
|
450
|
+
() => core.zipRight(testClock.warningDone(), testClock.suspendedWarningDone())
|
|
451
|
+
)
|
|
452
|
+
return testClock
|
|
453
|
+
})
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* @since 2.0.0
|
|
458
|
+
*/
|
|
459
|
+
export const defaultTestClock: Layer.Layer<TestClock, never, Annotations.TestAnnotations | Live.TestLive> = live(
|
|
460
|
+
makeData(new Date(0).getTime(), Chunk.empty())
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Accesses a `TestClock` instance in the context and increments the time
|
|
465
|
+
* by the specified duration, running any actions scheduled for on or before
|
|
466
|
+
* the new time in order.
|
|
467
|
+
*
|
|
468
|
+
* @since 2.0.0
|
|
469
|
+
*/
|
|
470
|
+
export const adjust = (durationInput: Duration.DurationInput): Effect.Effect<void> => {
|
|
471
|
+
const duration = Duration.decode(durationInput)
|
|
472
|
+
return testClockWith((testClock) => testClock.adjust(duration))
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* @since 2.0.0
|
|
477
|
+
*/
|
|
478
|
+
export const adjustWith = dual<
|
|
479
|
+
(duration: Duration.DurationInput) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
|
|
480
|
+
<A, E, R>(effect: Effect.Effect<A, E, R>, duration: Duration.DurationInput) => Effect.Effect<A, E, R>
|
|
481
|
+
>(2, (effect, durationInput) => {
|
|
482
|
+
const duration = Duration.decode(durationInput)
|
|
483
|
+
return testClockWith((testClock) => testClock.adjustWith(duration)(effect))
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Accesses a `TestClock` instance in the context and saves the clock
|
|
488
|
+
* state in an effect which, when run, will restore the `TestClock` to the
|
|
489
|
+
* saved state.
|
|
490
|
+
*
|
|
491
|
+
* @since 2.0.0
|
|
492
|
+
*/
|
|
493
|
+
export const save = (): Effect.Effect<Effect.Effect<void>> => testClockWith((testClock) => testClock.save)
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Accesses a `TestClock` instance in the context and sets the clock time
|
|
497
|
+
* to the specified `Instant` or `Date`, running any actions scheduled for on or before
|
|
498
|
+
* the new time in order.
|
|
499
|
+
*
|
|
500
|
+
* @since 2.0.0
|
|
501
|
+
*/
|
|
502
|
+
export const setTime = (input: DateTime.DateTime.Input): Effect.Effect<void> =>
|
|
503
|
+
testClockWith((testClock) =>
|
|
504
|
+
testClock.setTime(
|
|
505
|
+
typeof input === "number"
|
|
506
|
+
? input
|
|
507
|
+
: DateTime.unsafeMake(input).epochMillis
|
|
508
|
+
)
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Semantically blocks the current fiber until the clock time is equal to or
|
|
513
|
+
* greater than the specified duration. Once the clock time is adjusted to
|
|
514
|
+
* on or after the duration, the fiber will automatically be resumed.
|
|
515
|
+
*
|
|
516
|
+
* @since 2.0.0
|
|
517
|
+
*/
|
|
518
|
+
export const sleep = (durationInput: Duration.DurationInput): Effect.Effect<void> => {
|
|
519
|
+
const duration = Duration.decode(durationInput)
|
|
520
|
+
return testClockWith((testClock) => testClock.sleep(duration))
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Accesses a `TestClock` instance in the context and returns a list of
|
|
525
|
+
* times that effects are scheduled to run.
|
|
526
|
+
*
|
|
527
|
+
* @since 2.0.0
|
|
528
|
+
*/
|
|
529
|
+
export const sleeps = (): Effect.Effect<Chunk.Chunk<number>> => testClockWith((testClock) => testClock.sleeps)
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Retrieves the `TestClock` service for this test.
|
|
533
|
+
*
|
|
534
|
+
* @since 2.0.0
|
|
535
|
+
*/
|
|
536
|
+
export const testClock = (): Effect.Effect<TestClock> => testClockWith(core.succeed)
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Retrieves the `TestClock` service for this test and uses it to run the
|
|
540
|
+
* specified workflow.
|
|
541
|
+
*
|
|
542
|
+
* @since 2.0.0
|
|
543
|
+
*/
|
|
544
|
+
export const testClockWith = <A, E, R>(f: (testClock: TestClock) => Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
545
|
+
core.fiberRefGetWith(
|
|
546
|
+
defaultServices.currentServices,
|
|
547
|
+
(services) => f(pipe(services, Context.get(clock.clockTag)) as TestClock)
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Accesses the current time of a `TestClock` instance in the context in
|
|
552
|
+
* milliseconds.
|
|
553
|
+
*
|
|
554
|
+
* @since 2.0.0
|
|
555
|
+
*/
|
|
556
|
+
export const currentTimeMillis: Effect.Effect<number> = testClockWith((testClock) => testClock.currentTimeMillis)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 2.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Context from "./Context.js"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The `TestConfig` service provides access to default configuration settings
|
|
8
|
+
* used by tests, including the number of times to repeat tests to ensure
|
|
9
|
+
* they are stable, the number of times to retry flaky tests, the sufficient
|
|
10
|
+
* number of samples to check from a random variable, and the maximum number of
|
|
11
|
+
* shrinkings to minimize large failures.
|
|
12
|
+
*
|
|
13
|
+
* @since 2.0.0
|
|
14
|
+
*/
|
|
15
|
+
export interface TestConfig {
|
|
16
|
+
/**
|
|
17
|
+
* The number of times to repeat tests to ensure they are stable.
|
|
18
|
+
*/
|
|
19
|
+
readonly repeats: number
|
|
20
|
+
/**
|
|
21
|
+
* The number of times to retry flaky tests.
|
|
22
|
+
*/
|
|
23
|
+
readonly retries: number
|
|
24
|
+
/**
|
|
25
|
+
* The number of sufficient samples to check for a random variable.
|
|
26
|
+
*/
|
|
27
|
+
readonly samples: number
|
|
28
|
+
/**
|
|
29
|
+
* The maximum number of shrinkings to minimize large failures
|
|
30
|
+
*/
|
|
31
|
+
readonly shrinks: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @since 2.0.0
|
|
36
|
+
*/
|
|
37
|
+
export const TestConfig: Context.Tag<TestConfig, TestConfig> = Context.GenericTag<TestConfig>("effect/TestConfig")
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @since 2.0.0
|
|
41
|
+
*/
|
|
42
|
+
export const make = (params: {
|
|
43
|
+
readonly repeats: number
|
|
44
|
+
readonly retries: number
|
|
45
|
+
readonly samples: number
|
|
46
|
+
readonly shrinks: number
|
|
47
|
+
}): TestConfig => params
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 2.0.0
|
|
3
|
+
*/
|
|
4
|
+
import type * as DefaultServices from "./DefaultServices.js"
|
|
5
|
+
import { pipe } from "./Function.js"
|
|
6
|
+
import * as defaultServices from "./internal/defaultServices.js"
|
|
7
|
+
import * as layer from "./internal/layer.js"
|
|
8
|
+
import type * as Layer from "./Layer.js"
|
|
9
|
+
import * as TestClock from "./TestClock.js"
|
|
10
|
+
import * as TestServices from "./TestServices.js"
|
|
11
|
+
|
|
12
|
+
/** @internal */
|
|
13
|
+
export const live: Layer.Layer<TestServices.TestServices, never, DefaultServices.DefaultServices> = pipe(
|
|
14
|
+
TestServices.annotationsLayer(),
|
|
15
|
+
layer.merge(TestServices.liveLayer()),
|
|
16
|
+
layer.merge(TestServices.sizedLayer(100)),
|
|
17
|
+
layer.merge(pipe(
|
|
18
|
+
TestClock.defaultTestClock,
|
|
19
|
+
layer.provideMerge(
|
|
20
|
+
layer.merge(TestServices.liveLayer(), TestServices.annotationsLayer())
|
|
21
|
+
)
|
|
22
|
+
)),
|
|
23
|
+
layer.merge(TestServices.testConfigLayer({ repeats: 100, retries: 100, samples: 200, shrinks: 1000 }))
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @since 2.0.0
|
|
28
|
+
*/
|
|
29
|
+
export const LiveContext: Layer.Layer<DefaultServices.DefaultServices> = layer.syncContext(() =>
|
|
30
|
+
defaultServices.liveServices
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @since 2.0.0
|
|
35
|
+
*/
|
|
36
|
+
export const TestContext: Layer.Layer<TestServices.TestServices> = layer.provideMerge(live, LiveContext)
|
package/src/TestLive.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 2.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Context from "./Context.js"
|
|
5
|
+
import type * as DefaultServices from "./DefaultServices.js"
|
|
6
|
+
import type * as Effect from "./Effect.js"
|
|
7
|
+
import * as core from "./internal/core.js"
|
|
8
|
+
import * as defaultServices from "./internal/defaultServices.js"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @since 2.0.0
|
|
12
|
+
*/
|
|
13
|
+
export const TestLiveTypeId: unique symbol = Symbol.for("effect/TestLive")
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @since 2.0.0
|
|
17
|
+
*/
|
|
18
|
+
export type TestLiveTypeId = typeof TestLiveTypeId
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The `Live` trait provides access to the "live" default Effect services from
|
|
22
|
+
* within tests for workflows such as printing test results to the console or
|
|
23
|
+
* timing out tests where it is necessary to access the real implementations of
|
|
24
|
+
* these services.
|
|
25
|
+
*
|
|
26
|
+
* @since 2.0.0
|
|
27
|
+
*/
|
|
28
|
+
export interface TestLive {
|
|
29
|
+
readonly [TestLiveTypeId]: TestLiveTypeId
|
|
30
|
+
provide<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @since 2.0.0
|
|
35
|
+
*/
|
|
36
|
+
export const TestLive: Context.Tag<TestLive, TestLive> = Context.GenericTag<TestLive>("effect/TestLive")
|
|
37
|
+
|
|
38
|
+
/** @internal */
|
|
39
|
+
class LiveImpl implements TestLive {
|
|
40
|
+
readonly [TestLiveTypeId]: TestLiveTypeId = TestLiveTypeId
|
|
41
|
+
constructor(readonly services: Context.Context<DefaultServices.DefaultServices>) {}
|
|
42
|
+
provide<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> {
|
|
43
|
+
return core.fiberRefLocallyWith(
|
|
44
|
+
defaultServices.currentServices,
|
|
45
|
+
Context.merge(this.services)
|
|
46
|
+
)(effect)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @since 2.0.0
|
|
52
|
+
*/
|
|
53
|
+
export const make = (services: Context.Context<DefaultServices.DefaultServices>): TestLive => new LiveImpl(services)
|