@clayroach/effect 3.19.14-source-capture.8 → 3.19.14-source-trace.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/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/Record.ts
ADDED
|
@@ -0,0 +1,1274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module provides utility functions for working with records in TypeScript.
|
|
3
|
+
*
|
|
4
|
+
* @since 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Either } from "./Either.js"
|
|
8
|
+
import * as E from "./Either.js"
|
|
9
|
+
import * as Equal from "./Equal.js"
|
|
10
|
+
import type { Equivalence } from "./Equivalence.js"
|
|
11
|
+
import { dual, identity } from "./Function.js"
|
|
12
|
+
import type { TypeLambda } from "./HKT.js"
|
|
13
|
+
import * as Option from "./Option.js"
|
|
14
|
+
import type { NoInfer } from "./Types.js"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @category models
|
|
18
|
+
* @since 2.0.0
|
|
19
|
+
*/
|
|
20
|
+
export type ReadonlyRecord<in out K extends string | symbol, out A> = {
|
|
21
|
+
readonly [P in K]: A
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @since 2.0.0
|
|
26
|
+
*/
|
|
27
|
+
export declare namespace ReadonlyRecord {
|
|
28
|
+
type IsFiniteString<T extends string> = T extends "" ? true :
|
|
29
|
+
[T] extends [`${infer Head}${infer Rest}`]
|
|
30
|
+
? string extends Head ? false : `${number}` extends Head ? false : Rest extends "" ? true : IsFiniteString<Rest>
|
|
31
|
+
: false
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @since 2.0.0
|
|
35
|
+
*/
|
|
36
|
+
export type NonLiteralKey<K extends string | symbol> = K extends string ? IsFiniteString<K> extends true ? string : K
|
|
37
|
+
: symbol
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @since 2.0.0
|
|
41
|
+
*/
|
|
42
|
+
export type IntersectKeys<K1 extends string, K2 extends string> = [string] extends [K1 | K2] ?
|
|
43
|
+
NonLiteralKey<K1> & NonLiteralKey<K2>
|
|
44
|
+
: K1 & K2
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @category type lambdas
|
|
49
|
+
* @since 2.0.0
|
|
50
|
+
*/
|
|
51
|
+
export interface ReadonlyRecordTypeLambda<K extends string = string> extends TypeLambda {
|
|
52
|
+
readonly type: ReadonlyRecord<K, this["Target"]>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new, empty record.
|
|
57
|
+
*
|
|
58
|
+
* @category constructors
|
|
59
|
+
* @since 2.0.0
|
|
60
|
+
*/
|
|
61
|
+
export const empty = <K extends string | symbol = never, V = never>(): Record<
|
|
62
|
+
ReadonlyRecord.NonLiteralKey<K>,
|
|
63
|
+
V
|
|
64
|
+
> => ({} as any)
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Determine if a record is empty.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import * as assert from "node:assert"
|
|
72
|
+
* import { isEmptyRecord } from "effect/Record"
|
|
73
|
+
*
|
|
74
|
+
* assert.deepStrictEqual(isEmptyRecord({}), true);
|
|
75
|
+
* assert.deepStrictEqual(isEmptyRecord({ a: 3 }), false);
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @category guards
|
|
79
|
+
* @since 2.0.0
|
|
80
|
+
*/
|
|
81
|
+
export const isEmptyRecord = <K extends string, A>(self: Record<K, A>): self is Record<K, never> =>
|
|
82
|
+
keys(self).length === 0
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Determine if a record is empty.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import * as assert from "node:assert"
|
|
90
|
+
* import { isEmptyReadonlyRecord } from "effect/Record"
|
|
91
|
+
*
|
|
92
|
+
* assert.deepStrictEqual(isEmptyReadonlyRecord({}), true);
|
|
93
|
+
* assert.deepStrictEqual(isEmptyReadonlyRecord({ a: 3 }), false);
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @category guards
|
|
97
|
+
* @since 2.0.0
|
|
98
|
+
*/
|
|
99
|
+
export const isEmptyReadonlyRecord: <K extends string, A>(
|
|
100
|
+
self: ReadonlyRecord<K, A>
|
|
101
|
+
) => self is ReadonlyRecord<K, never> = isEmptyRecord
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Takes an iterable and a projection function and returns a record.
|
|
105
|
+
* The projection function maps each value of the iterable to a tuple of a key and a value, which is then added to the resulting record.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* import * as assert from "node:assert"
|
|
110
|
+
* import { fromIterableWith } from "effect/Record"
|
|
111
|
+
*
|
|
112
|
+
* const input = [1, 2, 3, 4]
|
|
113
|
+
*
|
|
114
|
+
* assert.deepStrictEqual(
|
|
115
|
+
* fromIterableWith(input, a => [String(a), a * 2]),
|
|
116
|
+
* { '1': 2, '2': 4, '3': 6, '4': 8 }
|
|
117
|
+
* )
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @category constructors
|
|
121
|
+
* @since 2.0.0
|
|
122
|
+
*/
|
|
123
|
+
export const fromIterableWith: {
|
|
124
|
+
<A, K extends string | symbol, B>(
|
|
125
|
+
f: (a: A) => readonly [K, B]
|
|
126
|
+
): (self: Iterable<A>) => Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
127
|
+
<A, K extends string | symbol, B>(
|
|
128
|
+
self: Iterable<A>,
|
|
129
|
+
f: (a: A) => readonly [K, B]
|
|
130
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
131
|
+
} = dual(
|
|
132
|
+
2,
|
|
133
|
+
<A, K extends string, B>(
|
|
134
|
+
self: Iterable<A>,
|
|
135
|
+
f: (a: A) => readonly [K, B]
|
|
136
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, B> => {
|
|
137
|
+
const out: Record<string, B> = empty()
|
|
138
|
+
for (const a of self) {
|
|
139
|
+
const [k, b] = f(a)
|
|
140
|
+
out[k] = b
|
|
141
|
+
}
|
|
142
|
+
return out
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Creates a new record from an iterable, utilizing the provided function to determine the key for each element.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* import * as assert from "node:assert"
|
|
152
|
+
* import { fromIterableBy } from "effect/Record"
|
|
153
|
+
*
|
|
154
|
+
* const users = [
|
|
155
|
+
* { id: "2", name: "name2" },
|
|
156
|
+
* { id: "1", name: "name1" }
|
|
157
|
+
* ]
|
|
158
|
+
*
|
|
159
|
+
* assert.deepStrictEqual(
|
|
160
|
+
* fromIterableBy(users, user => user.id),
|
|
161
|
+
* {
|
|
162
|
+
* "2": { id: "2", name: "name2" },
|
|
163
|
+
* "1": { id: "1", name: "name1" }
|
|
164
|
+
* }
|
|
165
|
+
* )
|
|
166
|
+
* ```
|
|
167
|
+
*
|
|
168
|
+
* @category constructors
|
|
169
|
+
* @since 2.0.0
|
|
170
|
+
*/
|
|
171
|
+
export const fromIterableBy = <A, K extends string | symbol>(
|
|
172
|
+
items: Iterable<A>,
|
|
173
|
+
f: (a: A) => K
|
|
174
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, A> => fromIterableWith(items, (a) => [f(a), a])
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Builds a record from an iterable of key-value pairs.
|
|
178
|
+
*
|
|
179
|
+
* If there are conflicting keys when using `fromEntries`, the last occurrence of the key/value pair will overwrite the
|
|
180
|
+
* previous ones. So the resulting record will only have the value of the last occurrence of each key.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* import * as assert from "node:assert"
|
|
185
|
+
* import { fromEntries } from "effect/Record"
|
|
186
|
+
*
|
|
187
|
+
* const input: Array<[string, number]> = [["a", 1], ["b", 2]]
|
|
188
|
+
*
|
|
189
|
+
* assert.deepStrictEqual(fromEntries(input), { a: 1, b: 2 })
|
|
190
|
+
* ```
|
|
191
|
+
*
|
|
192
|
+
* @since 2.0.0
|
|
193
|
+
* @category constructors
|
|
194
|
+
*/
|
|
195
|
+
export const fromEntries: <Entry extends readonly [string | symbol, any]>(
|
|
196
|
+
entries: Iterable<Entry>
|
|
197
|
+
) => Record<ReadonlyRecord.NonLiteralKey<Entry[0]>, Entry[1]> = Object.fromEntries
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Transforms the values of a record into an `Array` with a custom mapping function.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```ts
|
|
204
|
+
* import * as assert from "node:assert"
|
|
205
|
+
* import { collect } from "effect/Record"
|
|
206
|
+
*
|
|
207
|
+
* const x = { a: 1, b: 2, c: 3 }
|
|
208
|
+
* assert.deepStrictEqual(collect(x, (key, n) => [key, n]), [["a", 1], ["b", 2], ["c", 3]])
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @category conversions
|
|
212
|
+
* @since 2.0.0
|
|
213
|
+
*/
|
|
214
|
+
export const collect: {
|
|
215
|
+
<K extends string, A, B>(f: (key: K, a: A) => B): (self: ReadonlyRecord<K, A>) => Array<B>
|
|
216
|
+
<K extends string, A, B>(self: ReadonlyRecord<K, A>, f: (key: K, a: A) => B): Array<B>
|
|
217
|
+
} = dual(
|
|
218
|
+
2,
|
|
219
|
+
<K extends string, A, B>(self: ReadonlyRecord<K, A>, f: (key: K, a: A) => B): Array<B> => {
|
|
220
|
+
const out: Array<B> = []
|
|
221
|
+
for (const key of keys(self)) {
|
|
222
|
+
out.push(f(key, self[key]))
|
|
223
|
+
}
|
|
224
|
+
return out
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Takes a record and returns an array of tuples containing its keys and values.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* import * as assert from "node:assert"
|
|
234
|
+
* import { toEntries } from "effect/Record"
|
|
235
|
+
*
|
|
236
|
+
* const x = { a: 1, b: 2, c: 3 }
|
|
237
|
+
* assert.deepStrictEqual(toEntries(x), [["a", 1], ["b", 2], ["c", 3]])
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @category conversions
|
|
241
|
+
* @since 2.0.0
|
|
242
|
+
*/
|
|
243
|
+
export const toEntries: <K extends string, A>(self: ReadonlyRecord<K, A>) => Array<[K, A]> = collect((
|
|
244
|
+
key,
|
|
245
|
+
value
|
|
246
|
+
) => [key, value])
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Returns the number of key/value pairs in a record.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```ts
|
|
253
|
+
* import * as assert from "node:assert"
|
|
254
|
+
* import { size } from "effect/Record";
|
|
255
|
+
*
|
|
256
|
+
* assert.deepStrictEqual(size({ a: "a", b: 1, c: true }), 3);
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* @since 2.0.0
|
|
260
|
+
*/
|
|
261
|
+
export const size = <K extends string, A>(self: ReadonlyRecord<K, A>): number => keys(self).length
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Check if a given `key` exists in a record.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```ts
|
|
268
|
+
* import * as assert from "node:assert"
|
|
269
|
+
* import { empty, has } from "effect/Record"
|
|
270
|
+
*
|
|
271
|
+
* assert.deepStrictEqual(has({ a: 1, b: 2 }, "a"), true);
|
|
272
|
+
* assert.deepStrictEqual(has(empty<string>(), "c"), false);
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @since 2.0.0
|
|
276
|
+
*/
|
|
277
|
+
export const has: {
|
|
278
|
+
<K extends string | symbol>(
|
|
279
|
+
key: NoInfer<K>
|
|
280
|
+
): <A>(self: ReadonlyRecord<K, A>) => boolean
|
|
281
|
+
<K extends string | symbol, A>(
|
|
282
|
+
self: ReadonlyRecord<K, A>,
|
|
283
|
+
key: NoInfer<K>
|
|
284
|
+
): boolean
|
|
285
|
+
} = dual(
|
|
286
|
+
2,
|
|
287
|
+
<K extends string | symbol, A>(
|
|
288
|
+
self: ReadonlyRecord<K, A>,
|
|
289
|
+
key: NoInfer<K>
|
|
290
|
+
): boolean => Object.prototype.hasOwnProperty.call(self, key)
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Retrieve a value at a particular key from a record, returning it wrapped in an `Option`.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* ```ts
|
|
298
|
+
* import * as assert from "node:assert"
|
|
299
|
+
* import { Record as R, Option } from "effect"
|
|
300
|
+
*
|
|
301
|
+
* const person: Record<string, unknown> = { name: "John Doe", age: 35 }
|
|
302
|
+
*
|
|
303
|
+
* assert.deepStrictEqual(R.get(person, "name"), Option.some("John Doe"))
|
|
304
|
+
* assert.deepStrictEqual(R.get(person, "email"), Option.none())
|
|
305
|
+
* ```
|
|
306
|
+
*
|
|
307
|
+
* @since 2.0.0
|
|
308
|
+
*/
|
|
309
|
+
export const get: {
|
|
310
|
+
<K extends string | symbol>(key: NoInfer<K>): <A>(self: ReadonlyRecord<K, A>) => Option.Option<A>
|
|
311
|
+
<K extends string | symbol, A>(self: ReadonlyRecord<K, A>, key: NoInfer<K>): Option.Option<A>
|
|
312
|
+
} = dual(
|
|
313
|
+
2,
|
|
314
|
+
<K extends string | symbol, A>(self: ReadonlyRecord<K, A>, key: NoInfer<K>): Option.Option<A> =>
|
|
315
|
+
has(self, key) ? Option.some(self[key]) : Option.none()
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Apply a function to the element at the specified key, creating a new record.
|
|
320
|
+
* If the key does not exist, the record is returned unchanged.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* import * as assert from "node:assert"
|
|
325
|
+
* import { Record as R } from "effect"
|
|
326
|
+
*
|
|
327
|
+
* const f = (x: number) => x * 2
|
|
328
|
+
*
|
|
329
|
+
* assert.deepStrictEqual(
|
|
330
|
+
* R.modify({ a: 3 }, 'a', f),
|
|
331
|
+
* { a: 6 }
|
|
332
|
+
* )
|
|
333
|
+
* assert.deepStrictEqual(
|
|
334
|
+
* R.modify({ a: 3 } as Record<string, number>, 'b', f),
|
|
335
|
+
* { a: 3 }
|
|
336
|
+
* )
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
339
|
+
* @since 2.0.0
|
|
340
|
+
*/
|
|
341
|
+
export const modify: {
|
|
342
|
+
<K extends string | symbol, A, B>(
|
|
343
|
+
key: NoInfer<K>,
|
|
344
|
+
f: (a: A) => B
|
|
345
|
+
): (self: ReadonlyRecord<K, A>) => Record<K, A | B>
|
|
346
|
+
<K extends string | symbol, A, B>(self: ReadonlyRecord<K, A>, key: NoInfer<K>, f: (a: A) => B): Record<K, A | B>
|
|
347
|
+
} = dual(
|
|
348
|
+
3,
|
|
349
|
+
<K extends string | symbol, A, B>(self: ReadonlyRecord<K, A>, key: NoInfer<K>, f: (a: A) => B): Record<K, A | B> => {
|
|
350
|
+
if (!has(self, key)) {
|
|
351
|
+
return { ...self }
|
|
352
|
+
}
|
|
353
|
+
return { ...self, [key]: f(self[key]) }
|
|
354
|
+
}
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Apply a function to the element at the specified key, creating a new record,
|
|
359
|
+
* or return `None` if the key doesn't exist.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* import * as assert from "node:assert"
|
|
364
|
+
* import { Record as R, Option } from "effect"
|
|
365
|
+
*
|
|
366
|
+
* const f = (x: number) => x * 2
|
|
367
|
+
*
|
|
368
|
+
* assert.deepStrictEqual(
|
|
369
|
+
* R.modifyOption({ a: 3 }, 'a', f),
|
|
370
|
+
* Option.some({ a: 6 })
|
|
371
|
+
* )
|
|
372
|
+
* assert.deepStrictEqual(
|
|
373
|
+
* R.modifyOption({ a: 3 } as Record<string, number>, 'b', f),
|
|
374
|
+
* Option.none()
|
|
375
|
+
* )
|
|
376
|
+
* ```
|
|
377
|
+
*
|
|
378
|
+
* @since 2.0.0
|
|
379
|
+
*/
|
|
380
|
+
export const modifyOption: {
|
|
381
|
+
<K extends string | symbol, A, B>(
|
|
382
|
+
key: NoInfer<K>,
|
|
383
|
+
f: (a: A) => B
|
|
384
|
+
): (self: ReadonlyRecord<K, A>) => Option.Option<Record<K, A | B>>
|
|
385
|
+
<K extends string | symbol, A, B>(
|
|
386
|
+
self: ReadonlyRecord<K, A>,
|
|
387
|
+
key: NoInfer<K>,
|
|
388
|
+
f: (a: A) => B
|
|
389
|
+
): Option.Option<Record<K, A | B>>
|
|
390
|
+
} = dual(
|
|
391
|
+
3,
|
|
392
|
+
<K extends string | symbol, A, B>(
|
|
393
|
+
self: ReadonlyRecord<K, A>,
|
|
394
|
+
key: NoInfer<K>,
|
|
395
|
+
f: (a: A) => B
|
|
396
|
+
): Option.Option<Record<K, A | B>> => {
|
|
397
|
+
if (!has(self, key)) {
|
|
398
|
+
return Option.none()
|
|
399
|
+
}
|
|
400
|
+
return Option.some({ ...self, [key]: f(self[key]) })
|
|
401
|
+
}
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Replaces a value in the record with the new value passed as parameter.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```ts
|
|
409
|
+
* import * as assert from "node:assert"
|
|
410
|
+
* import { Record, Option } from "effect"
|
|
411
|
+
*
|
|
412
|
+
* assert.deepStrictEqual(
|
|
413
|
+
* Record.replaceOption({ a: 1, b: 2, c: 3 }, 'a', 10),
|
|
414
|
+
* Option.some({ a: 10, b: 2, c: 3 })
|
|
415
|
+
* )
|
|
416
|
+
* assert.deepStrictEqual(Record.replaceOption(Record.empty<string>(), 'a', 10), Option.none())
|
|
417
|
+
* ```
|
|
418
|
+
*
|
|
419
|
+
* @since 2.0.0
|
|
420
|
+
*/
|
|
421
|
+
export const replaceOption: {
|
|
422
|
+
<K extends string | symbol, B>(
|
|
423
|
+
key: NoInfer<K>,
|
|
424
|
+
b: B
|
|
425
|
+
): <A>(self: ReadonlyRecord<K, A>) => Option.Option<Record<K, A | B>>
|
|
426
|
+
<K extends string | symbol, A, B>(
|
|
427
|
+
self: ReadonlyRecord<K, A>,
|
|
428
|
+
key: NoInfer<K>,
|
|
429
|
+
b: B
|
|
430
|
+
): Option.Option<Record<K, A | B>>
|
|
431
|
+
} = dual(
|
|
432
|
+
3,
|
|
433
|
+
<K extends string | symbol, A, B>(
|
|
434
|
+
self: ReadonlyRecord<K, A>,
|
|
435
|
+
key: NoInfer<K>,
|
|
436
|
+
b: B
|
|
437
|
+
): Option.Option<Record<K, A | B>> => modifyOption(self, key, () => b)
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* If the given key exists in the record, returns a new record with the key removed,
|
|
442
|
+
* otherwise returns a copy of the original record.
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```ts
|
|
446
|
+
* import * as assert from "node:assert"
|
|
447
|
+
* import { remove } from "effect/Record"
|
|
448
|
+
*
|
|
449
|
+
* assert.deepStrictEqual(remove({ a: 1, b: 2 }, "a"), { b: 2 })
|
|
450
|
+
* ```
|
|
451
|
+
*
|
|
452
|
+
* @since 2.0.0
|
|
453
|
+
*/
|
|
454
|
+
export const remove: {
|
|
455
|
+
<K extends string | symbol, X extends K>(key: X): <A>(self: ReadonlyRecord<K, A>) => Record<Exclude<K, X>, A>
|
|
456
|
+
<K extends string | symbol, A, X extends K>(self: ReadonlyRecord<K, A>, key: X): Record<Exclude<K, X>, A>
|
|
457
|
+
} = dual(
|
|
458
|
+
2,
|
|
459
|
+
<K extends string | symbol, A, X extends K>(self: ReadonlyRecord<K, A>, key: X): Record<Exclude<K, X>, A> => {
|
|
460
|
+
if (!has(self, key)) {
|
|
461
|
+
return { ...self }
|
|
462
|
+
}
|
|
463
|
+
const out = { ...self }
|
|
464
|
+
delete out[key]
|
|
465
|
+
return out
|
|
466
|
+
}
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Retrieves the value of the property with the given `key` from a record and returns an `Option`
|
|
471
|
+
* of a tuple with the value and the record with the removed property.
|
|
472
|
+
* If the key is not present, returns `O.none`.
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* import * as assert from "node:assert"
|
|
477
|
+
* import { Record as R, Option } from "effect"
|
|
478
|
+
*
|
|
479
|
+
* assert.deepStrictEqual(R.pop({ a: 1, b: 2 }, "a"), Option.some([1, { b: 2 }]))
|
|
480
|
+
* assert.deepStrictEqual(R.pop({ a: 1, b: 2 } as Record<string, number>, "c"), Option.none())
|
|
481
|
+
* ```
|
|
482
|
+
*
|
|
483
|
+
* @category record
|
|
484
|
+
* @since 2.0.0
|
|
485
|
+
*/
|
|
486
|
+
export const pop: {
|
|
487
|
+
<K extends string | symbol, X extends K>(
|
|
488
|
+
key: X
|
|
489
|
+
): <A>(self: ReadonlyRecord<K, A>) => Option.Option<[A, Record<Exclude<K, X>, A>]>
|
|
490
|
+
<K extends string | symbol, A, X extends K>(
|
|
491
|
+
self: ReadonlyRecord<K, A>,
|
|
492
|
+
key: X
|
|
493
|
+
): Option.Option<[A, Record<Exclude<K, X>, A>]>
|
|
494
|
+
} = dual(2, <K extends string | symbol, A, X extends K>(
|
|
495
|
+
self: ReadonlyRecord<K, A>,
|
|
496
|
+
key: X
|
|
497
|
+
): Option.Option<[A, Record<Exclude<K, X>, A>]> =>
|
|
498
|
+
has(self, key) ? Option.some([self[key], remove(self, key)]) : Option.none())
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Maps a record into another record by applying a transformation function to each of its values.
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* ```ts
|
|
505
|
+
* import * as assert from "node:assert"
|
|
506
|
+
* import { map } from "effect/Record"
|
|
507
|
+
*
|
|
508
|
+
* const f = (n: number) => `-${n}`
|
|
509
|
+
*
|
|
510
|
+
* assert.deepStrictEqual(map({ a: 3, b: 5 }, f), { a: "-3", b: "-5" })
|
|
511
|
+
*
|
|
512
|
+
* const g = (n: number, key: string) => `${key.toUpperCase()}-${n}`
|
|
513
|
+
*
|
|
514
|
+
* assert.deepStrictEqual(map({ a: 3, b: 5 }, g), { a: "A-3", b: "B-5" })
|
|
515
|
+
* ```
|
|
516
|
+
*
|
|
517
|
+
* @category mapping
|
|
518
|
+
* @since 2.0.0
|
|
519
|
+
*/
|
|
520
|
+
export const map: {
|
|
521
|
+
<K extends string, A, B>(f: (a: A, key: NoInfer<K>) => B): (self: ReadonlyRecord<K, A>) => Record<K, B>
|
|
522
|
+
<K extends string, A, B>(self: ReadonlyRecord<K, A>, f: (a: A, key: NoInfer<K>) => B): Record<K, B>
|
|
523
|
+
} = dual(
|
|
524
|
+
2,
|
|
525
|
+
<K extends string, A, B>(self: ReadonlyRecord<K, A>, f: (a: A, key: NoInfer<K>) => B): Record<K, B> => {
|
|
526
|
+
const out: Record<K, B> = { ...self } as any
|
|
527
|
+
for (const key of keys(self)) {
|
|
528
|
+
out[key] = f(self[key], key)
|
|
529
|
+
}
|
|
530
|
+
return out
|
|
531
|
+
}
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Maps the keys of a `ReadonlyRecord` while preserving the corresponding values.
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* ```ts
|
|
539
|
+
* import * as assert from "node:assert"
|
|
540
|
+
* import { mapKeys } from "effect/Record"
|
|
541
|
+
*
|
|
542
|
+
* assert.deepStrictEqual(mapKeys({ a: 3, b: 5 }, (key) => key.toUpperCase()), { A: 3, B: 5 })
|
|
543
|
+
* ```
|
|
544
|
+
*
|
|
545
|
+
* @category mapping
|
|
546
|
+
* @since 2.0.0
|
|
547
|
+
*/
|
|
548
|
+
export const mapKeys: {
|
|
549
|
+
<K extends string, A, K2 extends string>(
|
|
550
|
+
f: (key: K, a: A) => K2
|
|
551
|
+
): (self: ReadonlyRecord<K, A>) => Record<K2, A>
|
|
552
|
+
<K extends string, A, K2 extends string>(
|
|
553
|
+
self: ReadonlyRecord<K, A>,
|
|
554
|
+
f: (key: K, a: A) => K2
|
|
555
|
+
): Record<K2, A>
|
|
556
|
+
} = dual(
|
|
557
|
+
2,
|
|
558
|
+
<K extends string, A, K2 extends string>(
|
|
559
|
+
self: ReadonlyRecord<K, A>,
|
|
560
|
+
f: (key: K, a: A) => K2
|
|
561
|
+
): Record<K2, A> => {
|
|
562
|
+
const out: Record<K2, A> = {} as any
|
|
563
|
+
for (const key of keys(self)) {
|
|
564
|
+
const a = self[key]
|
|
565
|
+
out[f(key, a)] = a
|
|
566
|
+
}
|
|
567
|
+
return out
|
|
568
|
+
}
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Maps entries of a `ReadonlyRecord` using the provided function, allowing modification of both keys and corresponding values.
|
|
573
|
+
*
|
|
574
|
+
* @example
|
|
575
|
+
* ```ts
|
|
576
|
+
* import * as assert from "node:assert"
|
|
577
|
+
* import { mapEntries } from "effect/Record"
|
|
578
|
+
*
|
|
579
|
+
* assert.deepStrictEqual(mapEntries({ a: 3, b: 5 }, (a, key) => [key.toUpperCase(), a + 1]), { A: 4, B: 6 })
|
|
580
|
+
* ```
|
|
581
|
+
*
|
|
582
|
+
* @category mapping
|
|
583
|
+
* @since 2.0.0
|
|
584
|
+
*/
|
|
585
|
+
export const mapEntries: {
|
|
586
|
+
<K extends string, A, K2 extends string, B>(
|
|
587
|
+
f: (a: A, key: K) => readonly [K2, B]
|
|
588
|
+
): (self: ReadonlyRecord<K, A>) => Record<K2, B>
|
|
589
|
+
<K extends string, A, K2 extends string, B>(
|
|
590
|
+
self: ReadonlyRecord<K, A>,
|
|
591
|
+
f: (a: A, key: K) => [K2, B]
|
|
592
|
+
): Record<K2, B>
|
|
593
|
+
} = dual(
|
|
594
|
+
2,
|
|
595
|
+
<K extends string, A, K2 extends string, B>(
|
|
596
|
+
self: ReadonlyRecord<K, A>,
|
|
597
|
+
f: (a: A, key: K) => [K2, B]
|
|
598
|
+
): Record<K2, B> => {
|
|
599
|
+
const out = <Record<K2, B>> {}
|
|
600
|
+
for (const key of keys(self)) {
|
|
601
|
+
const [k, b] = f(self[key], key)
|
|
602
|
+
out[k] = b
|
|
603
|
+
}
|
|
604
|
+
return out
|
|
605
|
+
}
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Transforms a record into a record by applying the function `f` to each key and value in the original record.
|
|
610
|
+
* If the function returns `Some`, the key-value pair is included in the output record.
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* ```ts
|
|
614
|
+
* import * as assert from "node:assert"
|
|
615
|
+
* import { Record, Option } from "effect"
|
|
616
|
+
*
|
|
617
|
+
* const x = { a: 1, b: 2, c: 3 }
|
|
618
|
+
* const f = (a: number, key: string) => a > 2 ? Option.some(a * 2) : Option.none()
|
|
619
|
+
* assert.deepStrictEqual(Record.filterMap(x, f), { c: 6 })
|
|
620
|
+
* ```
|
|
621
|
+
*
|
|
622
|
+
* @since 2.0.0
|
|
623
|
+
*/
|
|
624
|
+
export const filterMap: {
|
|
625
|
+
<K extends string, A, B>(
|
|
626
|
+
f: (a: A, key: K) => Option.Option<B>
|
|
627
|
+
): (self: ReadonlyRecord<K, A>) => Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
628
|
+
<K extends string, A, B>(
|
|
629
|
+
self: ReadonlyRecord<K, A>,
|
|
630
|
+
f: (a: A, key: K) => Option.Option<B>
|
|
631
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
632
|
+
} = dual(
|
|
633
|
+
2,
|
|
634
|
+
<K extends string, A, B>(
|
|
635
|
+
self: ReadonlyRecord<K, A>,
|
|
636
|
+
f: (a: A, key: K) => Option.Option<B>
|
|
637
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, B> => {
|
|
638
|
+
const out: Record<string, B> = empty()
|
|
639
|
+
for (const key of keys(self)) {
|
|
640
|
+
const o = f(self[key], key)
|
|
641
|
+
if (Option.isSome(o)) {
|
|
642
|
+
out[key] = o.value
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return out
|
|
646
|
+
}
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Selects properties from a record whose values match the given predicate.
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```ts
|
|
654
|
+
* import * as assert from "node:assert"
|
|
655
|
+
* import { filter } from "effect/Record"
|
|
656
|
+
*
|
|
657
|
+
* const x = { a: 1, b: 2, c: 3, d: 4 }
|
|
658
|
+
* assert.deepStrictEqual(filter(x, (n) => n > 2), { c: 3, d: 4 })
|
|
659
|
+
* ```
|
|
660
|
+
*
|
|
661
|
+
* @category filtering
|
|
662
|
+
* @since 2.0.0
|
|
663
|
+
*/
|
|
664
|
+
export const filter: {
|
|
665
|
+
<K extends string, A, B extends A>(
|
|
666
|
+
refinement: (a: NoInfer<A>, key: K) => a is B
|
|
667
|
+
): (self: ReadonlyRecord<K, A>) => Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
668
|
+
<K extends string, A>(
|
|
669
|
+
predicate: (A: NoInfer<A>, key: K) => boolean
|
|
670
|
+
): (self: ReadonlyRecord<K, A>) => Record<ReadonlyRecord.NonLiteralKey<K>, A>
|
|
671
|
+
<K extends string, A, B extends A>(
|
|
672
|
+
self: ReadonlyRecord<K, A>,
|
|
673
|
+
refinement: (a: A, key: K) => a is B
|
|
674
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
675
|
+
<K extends string, A>(
|
|
676
|
+
self: ReadonlyRecord<K, A>,
|
|
677
|
+
predicate: (a: A, key: K) => boolean
|
|
678
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, A>
|
|
679
|
+
} = dual(
|
|
680
|
+
2,
|
|
681
|
+
<K extends string, A>(
|
|
682
|
+
self: ReadonlyRecord<K, A>,
|
|
683
|
+
predicate: (a: A, key: K) => boolean
|
|
684
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, A> => {
|
|
685
|
+
const out: Record<string, A> = empty()
|
|
686
|
+
for (const key of keys(self)) {
|
|
687
|
+
if (predicate(self[key], key)) {
|
|
688
|
+
out[key] = self[key]
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return out
|
|
692
|
+
}
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Given a record with `Option` values, returns a new record containing only the `Some` values, preserving the original keys.
|
|
697
|
+
*
|
|
698
|
+
* @example
|
|
699
|
+
* ```ts
|
|
700
|
+
* import * as assert from "node:assert"
|
|
701
|
+
* import { Record, Option } from "effect"
|
|
702
|
+
*
|
|
703
|
+
* assert.deepStrictEqual(
|
|
704
|
+
* Record.getSomes({ a: Option.some(1), b: Option.none(), c: Option.some(2) }),
|
|
705
|
+
* { a: 1, c: 2 }
|
|
706
|
+
* )
|
|
707
|
+
* ```
|
|
708
|
+
*
|
|
709
|
+
* @category filtering
|
|
710
|
+
* @since 2.0.0
|
|
711
|
+
*/
|
|
712
|
+
export const getSomes: <K extends string, A>(
|
|
713
|
+
self: ReadonlyRecord<K, Option.Option<A>>
|
|
714
|
+
) => Record<ReadonlyRecord.NonLiteralKey<K>, A> = filterMap(
|
|
715
|
+
identity
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Given a record with `Either` values, returns a new record containing only the `Left` values, preserving the original keys.
|
|
720
|
+
*
|
|
721
|
+
* @example
|
|
722
|
+
* ```ts
|
|
723
|
+
* import * as assert from "node:assert"
|
|
724
|
+
* import { Record, Either } from "effect"
|
|
725
|
+
*
|
|
726
|
+
* assert.deepStrictEqual(
|
|
727
|
+
* Record.getLefts({ a: Either.right(1), b: Either.left("err"), c: Either.right(2) }),
|
|
728
|
+
* { b: "err" }
|
|
729
|
+
* )
|
|
730
|
+
* ```
|
|
731
|
+
*
|
|
732
|
+
* @category filtering
|
|
733
|
+
* @since 2.0.0
|
|
734
|
+
*/
|
|
735
|
+
export const getLefts = <K extends string, R, L>(
|
|
736
|
+
self: ReadonlyRecord<K, Either<R, L>>
|
|
737
|
+
): Record<ReadonlyRecord.NonLiteralKey<K>, L> => {
|
|
738
|
+
const out: Record<string, L> = empty()
|
|
739
|
+
for (const key of keys(self)) {
|
|
740
|
+
const value = self[key]
|
|
741
|
+
if (E.isLeft(value)) {
|
|
742
|
+
out[key] = value.left
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
return out
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Given a record with `Either` values, returns a new record containing only the `Right` values, preserving the original keys.
|
|
751
|
+
*
|
|
752
|
+
* @example
|
|
753
|
+
* ```ts
|
|
754
|
+
* import * as assert from "node:assert"
|
|
755
|
+
* import { Record, Either } from "effect"
|
|
756
|
+
*
|
|
757
|
+
* assert.deepStrictEqual(
|
|
758
|
+
* Record.getRights({ a: Either.right(1), b: Either.left("err"), c: Either.right(2) }),
|
|
759
|
+
* { a: 1, c: 2 }
|
|
760
|
+
* )
|
|
761
|
+
* ```
|
|
762
|
+
*
|
|
763
|
+
* @category filtering
|
|
764
|
+
* @since 2.0.0
|
|
765
|
+
*/
|
|
766
|
+
export const getRights = <K extends string, R, L>(
|
|
767
|
+
self: ReadonlyRecord<K, Either<R, L>>
|
|
768
|
+
): Record<string, R> => {
|
|
769
|
+
const out: Record<string, R> = empty()
|
|
770
|
+
for (const key of keys(self)) {
|
|
771
|
+
const value = self[key]
|
|
772
|
+
if (E.isRight(value)) {
|
|
773
|
+
out[key] = value.right
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
return out
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Partitions the elements of a record into two groups: those that match a predicate, and those that don't.
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* ```ts
|
|
785
|
+
* import * as assert from "node:assert"
|
|
786
|
+
* import { Record, Either } from "effect"
|
|
787
|
+
*
|
|
788
|
+
* const x = { a: 1, b: 2, c: 3 }
|
|
789
|
+
* const f = (n: number) => (n % 2 === 0 ? Either.right(n) : Either.left(n))
|
|
790
|
+
* assert.deepStrictEqual(Record.partitionMap(x, f), [{ a: 1, c: 3 }, { b: 2}])
|
|
791
|
+
* ```
|
|
792
|
+
*
|
|
793
|
+
* @category filtering
|
|
794
|
+
* @since 2.0.0
|
|
795
|
+
*/
|
|
796
|
+
export const partitionMap: {
|
|
797
|
+
<K extends string, A, B, C>(
|
|
798
|
+
f: (a: A, key: K) => Either<C, B>
|
|
799
|
+
): (
|
|
800
|
+
self: ReadonlyRecord<K, A>
|
|
801
|
+
) => [left: Record<ReadonlyRecord.NonLiteralKey<K>, B>, right: Record<ReadonlyRecord.NonLiteralKey<K>, C>]
|
|
802
|
+
<K extends string, A, B, C>(
|
|
803
|
+
self: ReadonlyRecord<K, A>,
|
|
804
|
+
f: (a: A, key: K) => Either<C, B>
|
|
805
|
+
): [left: Record<ReadonlyRecord.NonLiteralKey<K>, B>, right: Record<ReadonlyRecord.NonLiteralKey<K>, C>]
|
|
806
|
+
} = dual(
|
|
807
|
+
2,
|
|
808
|
+
<K extends string, A, B, C>(
|
|
809
|
+
self: ReadonlyRecord<K, A>,
|
|
810
|
+
f: (a: A, key: K) => Either<C, B>
|
|
811
|
+
): [left: Record<ReadonlyRecord.NonLiteralKey<K>, B>, right: Record<ReadonlyRecord.NonLiteralKey<K>, C>] => {
|
|
812
|
+
const left: Record<string, B> = empty()
|
|
813
|
+
const right: Record<string, C> = empty()
|
|
814
|
+
for (const key of keys(self)) {
|
|
815
|
+
const e = f(self[key], key)
|
|
816
|
+
if (E.isLeft(e)) {
|
|
817
|
+
left[key] = e.left
|
|
818
|
+
} else {
|
|
819
|
+
right[key] = e.right
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
return [left, right]
|
|
823
|
+
}
|
|
824
|
+
)
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Partitions a record of `Either` values into two separate records,
|
|
828
|
+
* one with the `Left` values and one with the `Right` values.
|
|
829
|
+
*
|
|
830
|
+
* @example
|
|
831
|
+
* ```ts
|
|
832
|
+
* import * as assert from "node:assert"
|
|
833
|
+
* import { Record, Either } from "effect"
|
|
834
|
+
*
|
|
835
|
+
* assert.deepStrictEqual(
|
|
836
|
+
* Record.separate({ a: Either.left("e"), b: Either.right(1) }),
|
|
837
|
+
* [{ a: "e" }, { b: 1 }]
|
|
838
|
+
* )
|
|
839
|
+
* ```
|
|
840
|
+
*
|
|
841
|
+
* @category filtering
|
|
842
|
+
* @since 2.0.0
|
|
843
|
+
*/
|
|
844
|
+
export const separate: <K extends string, A, B>(
|
|
845
|
+
self: ReadonlyRecord<K, Either<B, A>>
|
|
846
|
+
) => [Record<ReadonlyRecord.NonLiteralKey<K>, A>, Record<ReadonlyRecord.NonLiteralKey<K>, B>] = partitionMap(identity)
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Partitions a record into two separate records based on the result of a predicate function.
|
|
850
|
+
*
|
|
851
|
+
* @example
|
|
852
|
+
* ```ts
|
|
853
|
+
* import * as assert from "node:assert"
|
|
854
|
+
* import { partition } from "effect/Record"
|
|
855
|
+
*
|
|
856
|
+
* assert.deepStrictEqual(
|
|
857
|
+
* partition({ a: 1, b: 3 }, (n) => n > 2),
|
|
858
|
+
* [{ a: 1 }, { b: 3 }]
|
|
859
|
+
* )
|
|
860
|
+
* ```
|
|
861
|
+
*
|
|
862
|
+
* @category filtering
|
|
863
|
+
* @since 2.0.0
|
|
864
|
+
*/
|
|
865
|
+
export const partition: {
|
|
866
|
+
<K extends string, A, B extends A>(refinement: (a: NoInfer<A>, key: K) => a is B): (
|
|
867
|
+
self: ReadonlyRecord<K, A>
|
|
868
|
+
) => [
|
|
869
|
+
excluded: Record<ReadonlyRecord.NonLiteralKey<K>, Exclude<A, B>>,
|
|
870
|
+
satisfying: Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
871
|
+
]
|
|
872
|
+
<K extends string, A>(
|
|
873
|
+
predicate: (a: NoInfer<A>, key: K) => boolean
|
|
874
|
+
): (
|
|
875
|
+
self: ReadonlyRecord<K, A>
|
|
876
|
+
) => [excluded: Record<ReadonlyRecord.NonLiteralKey<K>, A>, satisfying: Record<ReadonlyRecord.NonLiteralKey<K>, A>]
|
|
877
|
+
<K extends string, A, B extends A>(
|
|
878
|
+
self: ReadonlyRecord<K, A>,
|
|
879
|
+
refinement: (a: A, key: K) => a is B
|
|
880
|
+
): [
|
|
881
|
+
excluded: Record<ReadonlyRecord.NonLiteralKey<K>, Exclude<A, B>>,
|
|
882
|
+
satisfying: Record<ReadonlyRecord.NonLiteralKey<K>, B>
|
|
883
|
+
]
|
|
884
|
+
<K extends string, A>(
|
|
885
|
+
self: ReadonlyRecord<K, A>,
|
|
886
|
+
predicate: (a: A, key: K) => boolean
|
|
887
|
+
): [excluded: Record<ReadonlyRecord.NonLiteralKey<K>, A>, satisfying: Record<ReadonlyRecord.NonLiteralKey<K>, A>]
|
|
888
|
+
} = dual(
|
|
889
|
+
2,
|
|
890
|
+
<K extends string, A>(
|
|
891
|
+
self: ReadonlyRecord<K, A>,
|
|
892
|
+
predicate: (a: A, key: K) => boolean
|
|
893
|
+
): [excluded: Record<ReadonlyRecord.NonLiteralKey<K>, A>, satisfying: Record<ReadonlyRecord.NonLiteralKey<K>, A>] => {
|
|
894
|
+
const left: Record<string, A> = empty()
|
|
895
|
+
const right: Record<string, A> = empty()
|
|
896
|
+
for (const key of keys(self)) {
|
|
897
|
+
if (predicate(self[key], key)) {
|
|
898
|
+
right[key] = self[key]
|
|
899
|
+
} else {
|
|
900
|
+
left[key] = self[key]
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return [left, right]
|
|
904
|
+
}
|
|
905
|
+
)
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* Retrieve the keys of a given record as an array.
|
|
909
|
+
*
|
|
910
|
+
* @since 2.0.0
|
|
911
|
+
*/
|
|
912
|
+
export const keys = <K extends string | symbol, A>(self: ReadonlyRecord<K, A>): Array<K & string> =>
|
|
913
|
+
Object.keys(self) as Array<K & string>
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Retrieve the values of a given record as an array.
|
|
917
|
+
*
|
|
918
|
+
* @since 2.0.0
|
|
919
|
+
*/
|
|
920
|
+
export const values = <K extends string, A>(self: ReadonlyRecord<K, A>): Array<A> => collect(self, (_, a) => a)
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* Add a new key-value pair or update an existing key's value in a record.
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* ```ts
|
|
927
|
+
* import * as assert from "node:assert"
|
|
928
|
+
* import { set } from "effect/Record"
|
|
929
|
+
*
|
|
930
|
+
* assert.deepStrictEqual(set("a", 5)({ a: 1, b: 2 }), { a: 5, b: 2 });
|
|
931
|
+
* assert.deepStrictEqual(set("c", 5)({ a: 1, b: 2 }), { a: 1, b: 2, c: 5 });
|
|
932
|
+
* ```
|
|
933
|
+
*
|
|
934
|
+
* @since 2.0.0
|
|
935
|
+
*/
|
|
936
|
+
export const set: {
|
|
937
|
+
<K extends string | symbol, K1 extends K | ((string | symbol) & {}), B>(
|
|
938
|
+
key: K1,
|
|
939
|
+
value: B
|
|
940
|
+
): <A>(self: ReadonlyRecord<K, A>) => Record<K | K1, A | B>
|
|
941
|
+
<K extends string | symbol, A, K1 extends K | ((string | symbol) & {}), B>(
|
|
942
|
+
self: ReadonlyRecord<K, A>,
|
|
943
|
+
key: K1,
|
|
944
|
+
value: B
|
|
945
|
+
): Record<K | K1, A | B>
|
|
946
|
+
} = dual(
|
|
947
|
+
3,
|
|
948
|
+
<K extends string | symbol, A, K1 extends K | ((string | symbol) & {}), B>(
|
|
949
|
+
self: ReadonlyRecord<K, A>,
|
|
950
|
+
key: K1,
|
|
951
|
+
value: B
|
|
952
|
+
): Record<K | K1, A | B> => {
|
|
953
|
+
return { ...self, [key]: value } as any
|
|
954
|
+
}
|
|
955
|
+
)
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Replace a key's value in a record and return the updated record.
|
|
959
|
+
* If the key does not exist in the record, a copy of the original record is returned.
|
|
960
|
+
*
|
|
961
|
+
* @example
|
|
962
|
+
* ```ts
|
|
963
|
+
* import * as assert from "node:assert"
|
|
964
|
+
* import { Record } from "effect"
|
|
965
|
+
*
|
|
966
|
+
* assert.deepStrictEqual(Record.replace("a", 3)({ a: 1, b: 2 }), { a: 3, b: 2 });
|
|
967
|
+
* assert.deepStrictEqual(Record.replace("c", 3)({ a: 1, b: 2 }), { a: 1, b: 2 });
|
|
968
|
+
* ```
|
|
969
|
+
*
|
|
970
|
+
* @since 2.0.0
|
|
971
|
+
*/
|
|
972
|
+
export const replace: {
|
|
973
|
+
<K extends string | symbol, B>(key: NoInfer<K>, value: B): <A>(self: ReadonlyRecord<K, A>) => Record<K, A | B>
|
|
974
|
+
<K extends string | symbol, A, B>(self: ReadonlyRecord<K, A>, key: NoInfer<K>, value: B): Record<K, A | B>
|
|
975
|
+
} = dual(
|
|
976
|
+
3,
|
|
977
|
+
<K extends string | symbol, A, B>(self: ReadonlyRecord<K, A>, key: NoInfer<K>, value: B): Record<K, A | B> => {
|
|
978
|
+
if (has(self, key)) {
|
|
979
|
+
return { ...self, [key]: value }
|
|
980
|
+
}
|
|
981
|
+
return { ...self }
|
|
982
|
+
}
|
|
983
|
+
)
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* Check if all the keys and values in one record are also found in another record.
|
|
987
|
+
*
|
|
988
|
+
* @since 2.0.0
|
|
989
|
+
*/
|
|
990
|
+
export const isSubrecordBy = <A>(equivalence: Equivalence<A>): {
|
|
991
|
+
<K extends string>(that: ReadonlyRecord<K, A>): (self: ReadonlyRecord<K, A>) => boolean
|
|
992
|
+
<K extends string>(self: ReadonlyRecord<K, A>, that: ReadonlyRecord<K, A>): boolean
|
|
993
|
+
} =>
|
|
994
|
+
dual(2, <K extends string>(self: ReadonlyRecord<K, A>, that: ReadonlyRecord<K, A>): boolean => {
|
|
995
|
+
for (const key of keys(self)) {
|
|
996
|
+
if (!has(that, key) || !equivalence(self[key], that[key])) {
|
|
997
|
+
return false
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
return true
|
|
1001
|
+
})
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* Check if one record is a subrecord of another, meaning it contains all the keys and values found in the second record.
|
|
1005
|
+
* This comparison uses default equality checks (`Equal.equivalence()`).
|
|
1006
|
+
*
|
|
1007
|
+
* @since 2.0.0
|
|
1008
|
+
*/
|
|
1009
|
+
export const isSubrecord: {
|
|
1010
|
+
<K extends string, A>(that: ReadonlyRecord<K, A>): (self: ReadonlyRecord<K, A>) => boolean
|
|
1011
|
+
<K extends string, A>(self: ReadonlyRecord<K, A>, that: ReadonlyRecord<K, A>): boolean
|
|
1012
|
+
} = isSubrecordBy(Equal.equivalence())
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Reduce a record to a single value by combining its entries with a specified function.
|
|
1016
|
+
*
|
|
1017
|
+
* @category folding
|
|
1018
|
+
* @since 2.0.0
|
|
1019
|
+
*/
|
|
1020
|
+
export const reduce: {
|
|
1021
|
+
<Z, V, K extends string>(
|
|
1022
|
+
zero: Z,
|
|
1023
|
+
f: (accumulator: Z, value: V, key: K) => Z
|
|
1024
|
+
): (self: ReadonlyRecord<K, V>) => Z
|
|
1025
|
+
<K extends string, V, Z>(self: ReadonlyRecord<K, V>, zero: Z, f: (accumulator: Z, value: V, key: K) => Z): Z
|
|
1026
|
+
} = dual(
|
|
1027
|
+
3,
|
|
1028
|
+
<K extends string, V, Z>(
|
|
1029
|
+
self: ReadonlyRecord<K, V>,
|
|
1030
|
+
zero: Z,
|
|
1031
|
+
f: (accumulator: Z, value: V, key: K) => Z
|
|
1032
|
+
): Z => {
|
|
1033
|
+
let out: Z = zero
|
|
1034
|
+
for (const key of keys(self)) {
|
|
1035
|
+
out = f(out, self[key], key)
|
|
1036
|
+
}
|
|
1037
|
+
return out
|
|
1038
|
+
}
|
|
1039
|
+
)
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Check if all entries in a record meet a specific condition.
|
|
1043
|
+
*
|
|
1044
|
+
* @since 2.0.0
|
|
1045
|
+
*/
|
|
1046
|
+
export const every: {
|
|
1047
|
+
<A, K extends string, B extends A>(
|
|
1048
|
+
refinement: (value: A, key: K) => value is B
|
|
1049
|
+
): (self: ReadonlyRecord<K, A>) => self is ReadonlyRecord<K, B>
|
|
1050
|
+
<A, K extends string>(predicate: (value: A, key: K) => boolean): (self: ReadonlyRecord<K, A>) => boolean
|
|
1051
|
+
<A, K extends string, B extends A>(
|
|
1052
|
+
self: ReadonlyRecord<K, A>,
|
|
1053
|
+
refinement: (value: A, key: K) => value is B
|
|
1054
|
+
): self is ReadonlyRecord<K, B>
|
|
1055
|
+
<K extends string, A>(self: ReadonlyRecord<K, A>, predicate: (value: A, key: K) => boolean): boolean
|
|
1056
|
+
} = dual(
|
|
1057
|
+
2,
|
|
1058
|
+
<A, K extends string, B extends A>(
|
|
1059
|
+
self: ReadonlyRecord<K, A>,
|
|
1060
|
+
refinement: (value: A, key: K) => value is B
|
|
1061
|
+
): self is ReadonlyRecord<K, B> => {
|
|
1062
|
+
for (const key of keys(self)) {
|
|
1063
|
+
if (!refinement(self[key], key)) {
|
|
1064
|
+
return false
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return true
|
|
1068
|
+
}
|
|
1069
|
+
)
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Check if any entry in a record meets a specific condition.
|
|
1073
|
+
*
|
|
1074
|
+
* @since 2.0.0
|
|
1075
|
+
*/
|
|
1076
|
+
export const some: {
|
|
1077
|
+
<A, K extends string>(predicate: (value: A, key: K) => boolean): (self: ReadonlyRecord<K, A>) => boolean
|
|
1078
|
+
<K extends string, A>(self: ReadonlyRecord<K, A>, predicate: (value: A, key: K) => boolean): boolean
|
|
1079
|
+
} = dual(
|
|
1080
|
+
2,
|
|
1081
|
+
<K extends string, A>(self: ReadonlyRecord<K, A>, predicate: (value: A, key: K) => boolean): boolean => {
|
|
1082
|
+
for (const key of keys(self)) {
|
|
1083
|
+
if (predicate(self[key], key)) {
|
|
1084
|
+
return true
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
return false
|
|
1088
|
+
}
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Merge two records, preserving entries that exist in either of the records.
|
|
1093
|
+
*
|
|
1094
|
+
* @since 2.0.0
|
|
1095
|
+
*/
|
|
1096
|
+
export const union: {
|
|
1097
|
+
<K1 extends string, A, B, C>(
|
|
1098
|
+
that: ReadonlyRecord<K1, B>,
|
|
1099
|
+
combine: (selfValue: A, thatValue: B) => C
|
|
1100
|
+
): <K0 extends string>(self: ReadonlyRecord<K0, A>) => Record<K0 | K1, A | B | C>
|
|
1101
|
+
<K0 extends string, A, K1 extends string, B, C>(
|
|
1102
|
+
self: ReadonlyRecord<K0, A>,
|
|
1103
|
+
that: ReadonlyRecord<K1, B>,
|
|
1104
|
+
combine: (selfValue: A, thatValue: B) => C
|
|
1105
|
+
): Record<K0 | K1, A | B | C>
|
|
1106
|
+
} = dual(
|
|
1107
|
+
3,
|
|
1108
|
+
<K0 extends string, A, K1 extends string, B, C>(
|
|
1109
|
+
self: ReadonlyRecord<K0, A>,
|
|
1110
|
+
that: ReadonlyRecord<K1, B>,
|
|
1111
|
+
combine: (selfValue: A, thatValue: B) => C
|
|
1112
|
+
): Record<K0 | K1, A | B | C> => {
|
|
1113
|
+
if (isEmptyRecord(self)) {
|
|
1114
|
+
return { ...that } as any
|
|
1115
|
+
}
|
|
1116
|
+
if (isEmptyRecord(that)) {
|
|
1117
|
+
return { ...self } as any
|
|
1118
|
+
}
|
|
1119
|
+
const out: Record<string, A | B | C> = empty()
|
|
1120
|
+
for (const key of keys(self)) {
|
|
1121
|
+
if (has(that, key as any)) {
|
|
1122
|
+
out[key] = combine(self[key], that[key as unknown as K1])
|
|
1123
|
+
} else {
|
|
1124
|
+
out[key] = self[key]
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
for (const key of keys(that)) {
|
|
1128
|
+
if (!has(out, key)) {
|
|
1129
|
+
out[key] = that[key]
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
return out
|
|
1133
|
+
}
|
|
1134
|
+
)
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* Merge two records, retaining only the entries that exist in both records.
|
|
1138
|
+
*
|
|
1139
|
+
* @since 2.0.0
|
|
1140
|
+
*/
|
|
1141
|
+
export const intersection: {
|
|
1142
|
+
<K1 extends string, A, B, C>(
|
|
1143
|
+
that: ReadonlyRecord<K1, B>,
|
|
1144
|
+
combine: (selfValue: A, thatValue: B) => C
|
|
1145
|
+
): <K0 extends string>(self: ReadonlyRecord<K0, A>) => Record<ReadonlyRecord.IntersectKeys<K0, K1>, C>
|
|
1146
|
+
<K0 extends string, A, K1 extends string, B, C>(
|
|
1147
|
+
self: ReadonlyRecord<K0, A>,
|
|
1148
|
+
that: ReadonlyRecord<K1, B>,
|
|
1149
|
+
combine: (selfValue: A, thatValue: B) => C
|
|
1150
|
+
): Record<ReadonlyRecord.IntersectKeys<K0, K1>, C>
|
|
1151
|
+
} = dual(
|
|
1152
|
+
3,
|
|
1153
|
+
<K0 extends string, A, K1 extends string, B, C>(
|
|
1154
|
+
self: ReadonlyRecord<K0, A>,
|
|
1155
|
+
that: ReadonlyRecord<K1, B>,
|
|
1156
|
+
combine: (selfValue: A, thatValue: B) => C
|
|
1157
|
+
): Record<ReadonlyRecord.IntersectKeys<K0, K1>, C> => {
|
|
1158
|
+
const out: Record<string, C> = empty()
|
|
1159
|
+
if (isEmptyRecord(self) || isEmptyRecord(that)) {
|
|
1160
|
+
return out
|
|
1161
|
+
}
|
|
1162
|
+
for (const key of keys(self)) {
|
|
1163
|
+
if (has(that, key as any)) {
|
|
1164
|
+
out[key] = combine(self[key], that[key as unknown as K1])
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
return out
|
|
1168
|
+
}
|
|
1169
|
+
)
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Merge two records, preserving only the entries that are unique to each record.
|
|
1173
|
+
*
|
|
1174
|
+
* @since 2.0.0
|
|
1175
|
+
*/
|
|
1176
|
+
export const difference: {
|
|
1177
|
+
<K1 extends string, B>(
|
|
1178
|
+
that: ReadonlyRecord<K1, B>
|
|
1179
|
+
): <K0 extends string, A>(self: ReadonlyRecord<K0, A>) => Record<K0 | K1, A | B>
|
|
1180
|
+
<K0 extends string, A, K1 extends string, B>(
|
|
1181
|
+
self: ReadonlyRecord<K0, A>,
|
|
1182
|
+
that: ReadonlyRecord<K1, B>
|
|
1183
|
+
): Record<K0 | K1, A | B>
|
|
1184
|
+
} = dual(2, <K0 extends string, A, K1 extends string, B>(
|
|
1185
|
+
self: ReadonlyRecord<K0, A>,
|
|
1186
|
+
that: ReadonlyRecord<K1, B>
|
|
1187
|
+
): Record<K0 | K1, A | B> => {
|
|
1188
|
+
if (isEmptyRecord(self)) {
|
|
1189
|
+
return { ...that } as any
|
|
1190
|
+
}
|
|
1191
|
+
if (isEmptyRecord(that)) {
|
|
1192
|
+
return { ...self } as any
|
|
1193
|
+
}
|
|
1194
|
+
const out = <Record<K0 | K1, A | B>> {}
|
|
1195
|
+
for (const key of keys(self)) {
|
|
1196
|
+
if (!has(that, key as any)) {
|
|
1197
|
+
out[key] = self[key]
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
for (const key of keys(that)) {
|
|
1201
|
+
if (!has(self, key as any)) {
|
|
1202
|
+
out[key] = that[key]
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
return out
|
|
1206
|
+
})
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Create an `Equivalence` for records using the provided `Equivalence` for values.
|
|
1210
|
+
*
|
|
1211
|
+
* @category instances
|
|
1212
|
+
* @since 2.0.0
|
|
1213
|
+
*/
|
|
1214
|
+
export const getEquivalence = <K extends string, A>(
|
|
1215
|
+
equivalence: Equivalence<A>
|
|
1216
|
+
): Equivalence<ReadonlyRecord<K, A>> => {
|
|
1217
|
+
const is = isSubrecordBy(equivalence)
|
|
1218
|
+
return (self, that) => is(self, that) && is(that, self)
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* Create a non-empty record from a single element.
|
|
1223
|
+
*
|
|
1224
|
+
* @category constructors
|
|
1225
|
+
* @since 2.0.0
|
|
1226
|
+
*/
|
|
1227
|
+
export const singleton = <K extends string | symbol, A>(key: K, value: A): Record<K, A> => ({
|
|
1228
|
+
[key]: value
|
|
1229
|
+
} as any)
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* Returns the first entry that satisfies the specified
|
|
1233
|
+
* predicate, or `None` if no such entry exists.
|
|
1234
|
+
*
|
|
1235
|
+
* @example
|
|
1236
|
+
* ```ts
|
|
1237
|
+
* import { Record, Option } from "effect"
|
|
1238
|
+
*
|
|
1239
|
+
* const record = { a: 1, b: 2, c: 3 }
|
|
1240
|
+
* const result = Record.findFirst(record, (value, key) => value > 1 && key !== "b")
|
|
1241
|
+
* console.log(result) // Option.Some(["c", 3])
|
|
1242
|
+
* ```
|
|
1243
|
+
*
|
|
1244
|
+
* @category elements
|
|
1245
|
+
* @since 3.14.0
|
|
1246
|
+
*/
|
|
1247
|
+
export const findFirst: {
|
|
1248
|
+
<K extends string | symbol, V, V2 extends V>(
|
|
1249
|
+
refinement: (value: NoInfer<V>, key: NoInfer<K>) => value is V2
|
|
1250
|
+
): (self: ReadonlyRecord<K, V>) => Option.Option<[K, V2]>
|
|
1251
|
+
<K extends string | symbol, V>(
|
|
1252
|
+
predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean
|
|
1253
|
+
): (self: ReadonlyRecord<K, V>) => Option.Option<[K, V]>
|
|
1254
|
+
<K extends string | symbol, V, V2 extends V>(
|
|
1255
|
+
self: ReadonlyRecord<K, V>,
|
|
1256
|
+
refinement: (value: NoInfer<V>, key: NoInfer<K>) => value is V2
|
|
1257
|
+
): Option.Option<[K, V2]>
|
|
1258
|
+
<K extends string | symbol, V>(
|
|
1259
|
+
self: ReadonlyRecord<K, V>,
|
|
1260
|
+
predicate: (value: NoInfer<V>, key: NoInfer<K>) => boolean
|
|
1261
|
+
): Option.Option<[K, V]>
|
|
1262
|
+
} = dual(
|
|
1263
|
+
2,
|
|
1264
|
+
<K extends string | symbol, V>(self: ReadonlyRecord<K, V>, f: (value: V, key: K) => boolean) => {
|
|
1265
|
+
const k = keys(self)
|
|
1266
|
+
for (let i = 0; i < k.length; i++) {
|
|
1267
|
+
const key = k[i]
|
|
1268
|
+
if (f(self[key], key)) {
|
|
1269
|
+
return Option.some([key, self[key]])
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
return Option.none()
|
|
1273
|
+
}
|
|
1274
|
+
)
|