effect 4.0.0-rc.118 → 4.0.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/README.md +17 -4
- package/dist/Array.d.ts +25 -25
- package/dist/Array.d.ts.map +1 -1
- package/dist/Array.js +16 -16
- package/dist/Array.js.map +1 -1
- package/dist/Cache.d.ts.map +1 -1
- package/dist/Cache.js +20 -16
- package/dist/Cache.js.map +1 -1
- package/dist/Cause.d.ts.map +1 -1
- package/dist/Cause.js +1 -1
- package/dist/Cause.js.map +1 -1
- package/dist/Chunk.d.ts +26 -26
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Chunk.js +15 -15
- package/dist/Chunk.js.map +1 -1
- package/dist/Effect.d.ts +167 -39
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +16 -10
- package/dist/Effect.js.map +1 -1
- package/dist/HashRing.d.ts.map +1 -1
- package/dist/HashRing.js +13 -5
- package/dist/HashRing.js.map +1 -1
- package/dist/MutableHashMap.d.ts.map +1 -1
- package/dist/MutableHashMap.js +4 -22
- package/dist/MutableHashMap.js.map +1 -1
- package/dist/Option.d.ts +17 -17
- package/dist/Option.d.ts.map +1 -1
- package/dist/Option.js +6 -6
- package/dist/Option.js.map +1 -1
- package/dist/Pool.d.ts +9 -5
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +34 -41
- package/dist/Pool.js.map +1 -1
- package/dist/Queue.d.ts +19 -2
- package/dist/Queue.d.ts.map +1 -1
- package/dist/Queue.js +9 -4
- package/dist/Queue.js.map +1 -1
- package/dist/RcMap.d.ts.map +1 -1
- package/dist/RcMap.js +16 -1
- package/dist/RcMap.js.map +1 -1
- package/dist/Record.d.ts +14 -14
- package/dist/Record.d.ts.map +1 -1
- package/dist/Record.js +10 -10
- package/dist/Record.js.map +1 -1
- package/dist/Schema.d.ts +37 -21
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +29 -10
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js +116 -97
- package/dist/SchemaAST.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +3 -1
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +3 -1
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/ScopedCache.d.ts.map +1 -1
- package/dist/ScopedCache.js +24 -16
- package/dist/ScopedCache.js.map +1 -1
- package/dist/Stream.d.ts +45 -6
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +55 -44
- package/dist/Stream.js.map +1 -1
- package/dist/ai/LanguageModel.d.ts +8 -0
- package/dist/ai/LanguageModel.d.ts.map +1 -1
- package/dist/ai/LanguageModel.js +13 -2
- package/dist/ai/LanguageModel.js.map +1 -1
- package/dist/ai/McpSchema.d.ts +402 -402
- package/dist/ai/McpSchema.d.ts.map +1 -1
- package/dist/ai/McpSchema.js +1 -1
- package/dist/ai/McpSchema.js.map +1 -1
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +11 -3
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Response.d.ts.map +1 -1
- package/dist/ai/Response.js +22 -12
- package/dist/ai/Response.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
- package/dist/ai/internal/mcpSchema/v2024_11_05.js +3 -1
- package/dist/ai/internal/mcpSchema/v2024_11_05.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +16 -3
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/MessageStorage.d.ts +32 -8
- package/dist/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/cluster/MessageStorage.js +2 -1
- package/dist/cluster/MessageStorage.js.map +1 -1
- package/dist/cluster/Sharding.d.ts +5 -2
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +15 -8
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
- package/dist/cluster/SqlMessageStorage.js +36 -16
- package/dist/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/cluster/SqlRunnerStorage.js +30 -44
- package/dist/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +63 -62
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/cluster/internal/interruptors.js +8 -0
- package/dist/cluster/internal/interruptors.js.map +1 -1
- package/dist/cluster/internal/resourceMap.js +39 -14
- package/dist/cluster/internal/resourceMap.js.map +1 -1
- package/dist/cluster/internal/resourceRef.js +168 -87
- package/dist/cluster/internal/resourceRef.js.map +1 -1
- package/dist/http/HttpEffect.d.ts +1 -0
- package/dist/http/HttpEffect.d.ts.map +1 -1
- package/dist/http/HttpEffect.js +29 -22
- package/dist/http/HttpEffect.js.map +1 -1
- package/dist/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/http/HttpMiddleware.js +3 -2
- package/dist/http/HttpMiddleware.js.map +1 -1
- package/dist/http/HttpStaticServer.d.ts.map +1 -1
- package/dist/http/HttpStaticServer.js +14 -0
- package/dist/http/HttpStaticServer.js.map +1 -1
- package/dist/http/HttpTraceContext.d.ts +1 -1
- package/dist/http/HttpTraceContext.d.ts.map +1 -1
- package/dist/http/HttpTraceContext.js +4 -4
- package/dist/http/HttpTraceContext.js.map +1 -1
- package/dist/http-api/HttpApiError.d.ts +1 -0
- package/dist/http-api/HttpApiError.d.ts.map +1 -1
- package/dist/http-api/HttpApiError.js +1 -0
- package/dist/http-api/HttpApiError.js.map +1 -1
- package/dist/internal/core.js +43 -2
- package/dist/internal/core.js.map +1 -1
- package/dist/internal/dateTime.js +1 -1
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +138 -165
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/rcRef.js +59 -23
- package/dist/internal/rcRef.js.map +1 -1
- package/dist/internal/schema/annotations.js +1 -7
- package/dist/internal/schema/annotations.js.map +1 -1
- package/dist/internal/schema/codegen.js +56 -28
- package/dist/internal/schema/codegen.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +11 -8
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/internal/schema/toCodeDocument.js +10 -30
- package/dist/internal/schema/toCodeDocument.js.map +1 -1
- package/dist/internal/schema/toCodec.js +1 -15
- package/dist/internal/schema/toCodec.js.map +1 -1
- package/dist/internal/schema/toEquivalence.js +4 -3
- package/dist/internal/schema/toEquivalence.js.map +1 -1
- package/dist/internal/schema/toFormatter.js +4 -4
- package/dist/internal/schema/toFormatter.js.map +1 -1
- package/dist/reactivity/Atom.d.ts.map +1 -1
- package/dist/reactivity/Atom.js +6 -2
- package/dist/reactivity/Atom.js.map +1 -1
- package/dist/reactivity/AtomRpc.d.ts +3 -3
- package/dist/reactivity/AtomRpc.d.ts.map +1 -1
- package/dist/rpc/Rpc.d.ts +2 -2
- package/dist/rpc/Rpc.d.ts.map +1 -1
- package/dist/rpc/RpcClient.d.ts +7 -7
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +21 -16
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcMessage.d.ts +1 -1
- package/dist/rpc/RpcMessage.d.ts.map +1 -1
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +2 -2
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/rpc/Utils.d.ts +2 -3
- package/dist/rpc/Utils.d.ts.map +1 -1
- package/dist/rpc/Utils.js +3 -4
- package/dist/rpc/Utils.js.map +1 -1
- package/dist/schema/SchemaCompiler/runtime.js +6 -1
- package/dist/schema/SchemaCompiler/runtime.js.map +1 -1
- package/dist/testing/TestSchema.d.ts +234 -6
- package/dist/testing/TestSchema.d.ts.map +1 -1
- package/dist/testing/TestSchema.js +244 -25
- package/dist/testing/TestSchema.js.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/workflow/DurableDeferred.js +1 -1
- package/dist/workflow/DurableDeferred.js.map +1 -1
- package/dist/workflow/Workflow.js +1 -1
- package/dist/workflow/Workflow.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts +2 -0
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +1 -0
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +1 -1
- package/src/Array.ts +31 -31
- package/src/Cache.ts +22 -16
- package/src/Cause.ts +1 -1
- package/src/Chunk.ts +29 -29
- package/src/Effect.ts +170 -39
- package/src/HashRing.ts +14 -5
- package/src/MutableHashMap.ts +4 -24
- package/src/Option.ts +19 -19
- package/src/Pool.ts +28 -36
- package/src/Queue.ts +26 -6
- package/src/RcMap.ts +26 -2
- package/src/Record.ts +20 -20
- package/src/Schema.ts +48 -24
- package/src/SchemaAST.ts +135 -115
- package/src/SchemaRepresentation.ts +3 -1
- package/src/ScopedCache.ts +27 -16
- package/src/Stream.ts +158 -88
- package/src/ai/LanguageModel.ts +27 -2
- package/src/ai/McpSchema.ts +3 -3
- package/src/ai/McpServer.ts +12 -3
- package/src/ai/Response.ts +27 -12
- package/src/ai/internal/mcpProtocol/v2024_11_05.ts +1 -0
- package/src/ai/internal/mcpProtocol/v2025_03_26.ts +1 -0
- package/src/ai/internal/mcpProtocol/v2025_06_18.ts +1 -0
- package/src/ai/internal/mcpProtocol/v2025_11_25.ts +1 -0
- package/src/ai/internal/mcpSchema/v2024_11_05.ts +4 -2
- package/src/cluster/ClusterWorkflowEngine.ts +26 -5
- package/src/cluster/MessageStorage.ts +22 -5
- package/src/cluster/Sharding.ts +32 -28
- package/src/cluster/SqlMessageStorage.ts +45 -21
- package/src/cluster/SqlRunnerStorage.ts +85 -113
- package/src/cluster/internal/entityManager.ts +68 -80
- package/src/cluster/internal/interruptors.ts +13 -0
- package/src/cluster/internal/resourceMap.ts +55 -17
- package/src/cluster/internal/resourceRef.ts +189 -96
- package/src/http/HttpEffect.ts +15 -9
- package/src/http/HttpMiddleware.ts +8 -2
- package/src/http/HttpStaticServer.ts +16 -0
- package/src/http/HttpTraceContext.ts +8 -4
- package/src/http-api/HttpApiError.ts +1 -0
- package/src/internal/core.ts +56 -2
- package/src/internal/dateTime.ts +3 -1
- package/src/internal/effect.ts +146 -173
- package/src/internal/rcRef.ts +83 -33
- package/src/internal/schema/annotations.ts +0 -9
- package/src/internal/schema/codegen.ts +90 -43
- package/src/internal/schema/fromJsonSchemaDocument.ts +5 -3
- package/src/internal/schema/toCodeDocument.ts +10 -47
- package/src/internal/schema/toCodec.ts +3 -16
- package/src/internal/schema/toEquivalence.ts +4 -5
- package/src/internal/schema/toFormatter.ts +4 -6
- package/src/reactivity/Atom.ts +6 -2
- package/src/reactivity/AtomRpc.ts +5 -5
- package/src/rpc/Rpc.ts +2 -2
- package/src/rpc/RpcClient.ts +35 -32
- package/src/rpc/RpcMessage.ts +1 -1
- package/src/rpc/RpcServer.ts +2 -1
- package/src/rpc/Utils.ts +4 -10
- package/src/schema/SchemaCompiler/runtime.ts +17 -1
- package/src/testing/TestSchema.ts +315 -63
- package/src/testing/index.ts +1 -0
- package/src/workflow/DurableDeferred.ts +1 -1
- package/src/workflow/Workflow.ts +1 -1
- package/src/workflow/WorkflowEngine.ts +4 -0
package/src/Pool.ts
CHANGED
|
@@ -19,7 +19,6 @@ import * as Fiber from "./Fiber.ts"
|
|
|
19
19
|
import { constant, dual, identity } from "./Function.ts"
|
|
20
20
|
import * as core from "./internal/core.ts"
|
|
21
21
|
import * as internal from "./internal/effect.ts"
|
|
22
|
-
import * as Iterable from "./Iterable.ts"
|
|
23
22
|
import { type Pipeable, pipeArguments } from "./Pipeable.ts"
|
|
24
23
|
import { hasProperty } from "./Predicate.ts"
|
|
25
24
|
import * as Queue from "./Queue.ts"
|
|
@@ -31,10 +30,12 @@ const TypeId = "~effect/Pool"
|
|
|
31
30
|
|
|
32
31
|
const Acquire = Symbol()
|
|
33
32
|
const AcquireContext = Symbol()
|
|
33
|
+
const PoolClock = Symbol()
|
|
34
34
|
|
|
35
35
|
interface PoolImpl<A, E> extends Pool<A, E> {
|
|
36
36
|
readonly [Acquire]: Effect.Effect<A, E, Scope.Scope>
|
|
37
37
|
readonly [AcquireContext]: Context.Context<Scope.Scope>
|
|
38
|
+
readonly [PoolClock]: Clock
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/**
|
|
@@ -119,7 +120,6 @@ export interface State<A, E> {
|
|
|
119
120
|
isShuttingDown: boolean
|
|
120
121
|
usage: number
|
|
121
122
|
readonly resizeSemaphore: Semaphore.Semaphore
|
|
122
|
-
// Insertion order determines usage-TTL retirement order; reclaimed items move to the back.
|
|
123
123
|
readonly items: Set<PoolItem<A, E>>
|
|
124
124
|
availableHead: PoolItem<A, E> | undefined
|
|
125
125
|
availableTail: PoolItem<A, E> | undefined
|
|
@@ -139,8 +139,8 @@ export interface State<A, E> {
|
|
|
139
139
|
* **Details**
|
|
140
140
|
*
|
|
141
141
|
* Each item stores the acquisition `Exit`, its finalizer, the current
|
|
142
|
-
* reference count, and whether automatic reclaiming
|
|
143
|
-
* the item was invalidated.
|
|
142
|
+
* reference count, when it last became idle, and whether automatic reclaiming
|
|
143
|
+
* has been disabled because the item was invalidated.
|
|
144
144
|
*
|
|
145
145
|
* @see {@link Strategy} for the custom strategy callbacks that receive and return pool items
|
|
146
146
|
* @see {@link State} for the runtime sets that store active, available, and invalidated pool items
|
|
@@ -152,6 +152,8 @@ export interface PoolItem<A, E> {
|
|
|
152
152
|
readonly exit: Exit.Exit<A, E>
|
|
153
153
|
finalizer: Effect.Effect<void>
|
|
154
154
|
refCount: number
|
|
155
|
+
/** Clock time at which the item was acquired or its last borrower released it. */
|
|
156
|
+
idleSince: number
|
|
155
157
|
disableReclaim: boolean
|
|
156
158
|
isAvailable: boolean
|
|
157
159
|
availablePrevious: PoolItem<A, E> | undefined
|
|
@@ -257,9 +259,11 @@ export const make = <A, E, R>(options: {
|
|
|
257
259
|
* pool implementation. A value of `1` waits until existing items are fully
|
|
258
260
|
* utilized before creating more items.
|
|
259
261
|
*
|
|
260
|
-
* `timeToLiveStrategy`
|
|
261
|
-
*
|
|
262
|
-
* `
|
|
262
|
+
* `timeToLiveStrategy` defaults to `"usage"`, which expires idle, unreserved
|
|
263
|
+
* excess items after `timeToLive` since their last borrower released them
|
|
264
|
+
* (or acquisition if never borrowed). It checks once per `timeToLive`, so
|
|
265
|
+
* retirement can take up to twice that duration. `"creation"` measures from
|
|
266
|
+
* item creation instead.
|
|
263
267
|
*
|
|
264
268
|
* **Example** (Creating a connection pool)
|
|
265
269
|
*
|
|
@@ -374,6 +378,7 @@ export const makeWithStrategy = <A, E, R>(options: {
|
|
|
374
378
|
[TypeId]: TypeId,
|
|
375
379
|
[Acquire]: options.acquire as Effect.Effect<A, E, Scope.Scope>,
|
|
376
380
|
[AcquireContext]: services as Context.Context<Scope.Scope>,
|
|
381
|
+
[PoolClock]: yield* Clock,
|
|
377
382
|
config,
|
|
378
383
|
state,
|
|
379
384
|
pipe() {
|
|
@@ -676,6 +681,9 @@ const releaseItem = <A, E>(self: Pool<A, E>, item: PoolItem<A, E>): Effect.Effec
|
|
|
676
681
|
const state = self.state
|
|
677
682
|
item.refCount--
|
|
678
683
|
state.usage--
|
|
684
|
+
if (item.refCount === 0) {
|
|
685
|
+
item.idleSince = (self as PoolImpl<A, E>)[PoolClock].currentTimeMillisUnsafe()
|
|
686
|
+
}
|
|
679
687
|
if (state.invalidated.has(item)) {
|
|
680
688
|
return invalidatePoolItem(self, item)
|
|
681
689
|
}
|
|
@@ -1014,6 +1022,7 @@ const allocate = <A, E>(self: Pool<A, E>): Effect.Effect<PoolItem<A, E>> =>
|
|
|
1014
1022
|
exit,
|
|
1015
1023
|
finalizer: Effect.catchCause(Scope.close(scope, exit), reportUnhandledError),
|
|
1016
1024
|
refCount: 0,
|
|
1025
|
+
idleSince: impl[PoolClock].currentTimeMillisUnsafe(),
|
|
1017
1026
|
disableReclaim: false,
|
|
1018
1027
|
isAvailable: false,
|
|
1019
1028
|
availablePrevious: undefined,
|
|
@@ -1110,19 +1119,21 @@ const strategyCreationTTL = Effect.fnUntraced(function*<A, E>(ttl: Duration.Inpu
|
|
|
1110
1119
|
})
|
|
1111
1120
|
})
|
|
1112
1121
|
|
|
1113
|
-
const strategyUsageTTL =
|
|
1114
|
-
|
|
1122
|
+
const strategyUsageTTL = Effect.fnUntraced(function*<A, E>(ttl: Duration.Input) {
|
|
1123
|
+
const clock = yield* Clock
|
|
1124
|
+
const ttlMillis = Duration.toMillis(Duration.fromInputUnsafe(ttl))
|
|
1125
|
+
return identity<Strategy<A, E>>({
|
|
1115
1126
|
run: (pool) => {
|
|
1116
|
-
// `state.items` iterates in insertion order, so its oldest live entry is
|
|
1117
|
-
// the next to retire. Using it directly means an item stops being
|
|
1118
|
-
// referenced by this strategy as soon as it leaves the pool.
|
|
1119
1127
|
const process: Effect.Effect<void> = Effect.suspend(() => {
|
|
1120
1128
|
if (activeSize(pool) <= targetSize(pool)) return Effect.void
|
|
1129
|
+
const expired = clock.currentTimeMillisUnsafe() - ttlMillis
|
|
1130
|
+
let oldest: PoolItem<A, E> | undefined
|
|
1121
1131
|
for (const item of pool.state.items) {
|
|
1122
|
-
if (
|
|
1123
|
-
|
|
1132
|
+
if (item.refCount > 0 || item.idleSince > expired) continue
|
|
1133
|
+
if (pool.state.invalidated.has(item) || reservations.has(item)) continue
|
|
1134
|
+
if (oldest === undefined || item.idleSince < oldest.idleSince) oldest = item
|
|
1124
1135
|
}
|
|
1125
|
-
return Effect.void
|
|
1136
|
+
return oldest === undefined ? Effect.void : Effect.flatMap(invalidatePoolItem(pool, oldest), () => process)
|
|
1126
1137
|
})
|
|
1127
1138
|
return process.pipe(
|
|
1128
1139
|
Effect.delay(ttl),
|
|
@@ -1130,28 +1141,9 @@ const strategyUsageTTL = <A, E>(ttl: Duration.Input): Effect.Effect<Strategy<A,
|
|
|
1130
1141
|
)
|
|
1131
1142
|
},
|
|
1132
1143
|
onAcquire: (_) => Effect.void,
|
|
1133
|
-
reclaim(
|
|
1134
|
-
return Effect.suspend((): Effect.Effect<PoolItem<A, E> | undefined> => {
|
|
1135
|
-
if (pool.state.invalidated.size === 0) {
|
|
1136
|
-
return Effect.undefined
|
|
1137
|
-
}
|
|
1138
|
-
const item = Iterable.head(
|
|
1139
|
-
Iterable.filter(pool.state.invalidated, (item) => !item.disableReclaim && !reservations.has(item))
|
|
1140
|
-
)
|
|
1141
|
-
if (item._tag === "None") {
|
|
1142
|
-
return Effect.undefined
|
|
1143
|
-
}
|
|
1144
|
-
pool.state.invalidated.delete(item.value)
|
|
1145
|
-
// Re-adding moves the reclaimed item to the back of the retirement order.
|
|
1146
|
-
pool.state.items.delete(item.value)
|
|
1147
|
-
pool.state.items.add(item.value)
|
|
1148
|
-
if (item.value.refCount < pool.config.concurrency) {
|
|
1149
|
-
addAvailable(pool, item.value)
|
|
1150
|
-
}
|
|
1151
|
-
return Effect.succeed(item.value)
|
|
1152
|
-
})
|
|
1153
|
-
}
|
|
1144
|
+
reclaim: (_) => Effect.undefined
|
|
1154
1145
|
})
|
|
1146
|
+
})
|
|
1155
1147
|
|
|
1156
1148
|
const reportUnhandledError = <E>(cause: Cause.Cause<E>) =>
|
|
1157
1149
|
Effect.withFiber<void>((fiber) => {
|
package/src/Queue.ts
CHANGED
|
@@ -344,13 +344,13 @@ export declare namespace Queue {
|
|
|
344
344
|
export type State<A, E> =
|
|
345
345
|
| {
|
|
346
346
|
readonly _tag: "Open"
|
|
347
|
-
readonly takers: Set<
|
|
347
|
+
readonly takers: Set<Taker<E>>
|
|
348
348
|
readonly offers: Set<OfferEntry<A>>
|
|
349
349
|
readonly awaiters: Set<(_: Effect<void, E>) => void>
|
|
350
350
|
}
|
|
351
351
|
| {
|
|
352
352
|
readonly _tag: "Closing"
|
|
353
|
-
readonly takers: Set<
|
|
353
|
+
readonly takers: Set<Taker<E>>
|
|
354
354
|
readonly offers: Set<OfferEntry<A>>
|
|
355
355
|
readonly awaiters: Set<(_: Effect<void, E>) => void>
|
|
356
356
|
readonly exit: Failure<never, E>
|
|
@@ -384,6 +384,24 @@ export declare namespace Queue {
|
|
|
384
384
|
readonly message: A
|
|
385
385
|
readonly resume: (_: Effect<boolean>) => void
|
|
386
386
|
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Represents a suspended take waiting for the queue to become readable.
|
|
390
|
+
*
|
|
391
|
+
* **Details**
|
|
392
|
+
*
|
|
393
|
+
* `ready` reports whether the take can now complete, so a batch take is
|
|
394
|
+
* only resumed once its minimum is available. `resume` completes the
|
|
395
|
+
* suspended take, with `void` to retry or with a failure exit when the queue
|
|
396
|
+
* is done.
|
|
397
|
+
*
|
|
398
|
+
* @category models
|
|
399
|
+
* @since 4.0.0
|
|
400
|
+
*/
|
|
401
|
+
export interface Taker<E> {
|
|
402
|
+
readonly ready: () => boolean
|
|
403
|
+
readonly resume: (_: Effect<void, E>) => void
|
|
404
|
+
}
|
|
387
405
|
}
|
|
388
406
|
|
|
389
407
|
const variance = {
|
|
@@ -2427,8 +2445,9 @@ const releaseTakers = <A, E>(self: Enqueue<A, E>) => {
|
|
|
2427
2445
|
return
|
|
2428
2446
|
}
|
|
2429
2447
|
for (const taker of self.state.takers) {
|
|
2448
|
+
if (!taker.ready()) continue
|
|
2430
2449
|
self.state.takers.delete(taker)
|
|
2431
|
-
taker(internalEffect.exitVoid)
|
|
2450
|
+
taker.resume(internalEffect.exitVoid)
|
|
2432
2451
|
if (self.messages.length === 0) {
|
|
2433
2452
|
break
|
|
2434
2453
|
}
|
|
@@ -2478,9 +2497,10 @@ const awaitTake = <A, E>(self: Dequeue<A, E>, ready: () => boolean) =>
|
|
|
2478
2497
|
internalEffect.callback<void, E>((resume) => {
|
|
2479
2498
|
if (self.state._tag === "Done") return resume(self.state.exit)
|
|
2480
2499
|
if (ready()) return resume(internalEffect.exitVoid)
|
|
2481
|
-
|
|
2500
|
+
const taker = { ready, resume }
|
|
2501
|
+
self.state.takers.add(taker)
|
|
2482
2502
|
return internalEffect.sync(() => {
|
|
2483
|
-
if (self.state._tag !== "Done") self.state.takers.delete(
|
|
2503
|
+
if (self.state._tag !== "Done") self.state.takers.delete(taker)
|
|
2484
2504
|
})
|
|
2485
2505
|
})
|
|
2486
2506
|
|
|
@@ -2577,7 +2597,7 @@ const finalize = <A, E>(self: Enqueue<A, E> | Dequeue<A, E>, exit: Failure<never
|
|
|
2577
2597
|
const openState = self.state
|
|
2578
2598
|
self.state = { _tag: "Done", exit }
|
|
2579
2599
|
for (const taker of openState.takers) {
|
|
2580
|
-
taker(exit)
|
|
2600
|
+
taker.resume(exit)
|
|
2581
2601
|
}
|
|
2582
2602
|
openState.takers.clear()
|
|
2583
2603
|
for (const awaiter of openState.awaiters) {
|
package/src/RcMap.ts
CHANGED
|
@@ -566,10 +566,16 @@ export const get: {
|
|
|
566
566
|
context.set(key, value)
|
|
567
567
|
})
|
|
568
568
|
context.set(Scope.Scope.key, entry.scope)
|
|
569
|
+
const lookupContext: Context.Context<Scope.Scope> = Context.makeUnsafe(context)
|
|
569
570
|
Effect.suspend(() => self.lookup(key)).pipe(
|
|
570
|
-
Effect.runForkWith(
|
|
571
|
+
Effect.runForkWith(lookupContext),
|
|
571
572
|
Fiber.runIn(entry.scope)
|
|
572
|
-
).addObserver((exit) =>
|
|
573
|
+
).addObserver((exit) => {
|
|
574
|
+
// Interruption is abandonment, so the entry is dropped and the next
|
|
575
|
+
// get starts a fresh lookup.
|
|
576
|
+
if (Exit.hasInterrupts(exit)) removeInterrupted(self, key, entry, lookupContext)
|
|
577
|
+
Deferred.doneUnsafe(entry.deferred, exit)
|
|
578
|
+
})
|
|
573
579
|
}
|
|
574
580
|
const scope = Context.getUnsafe(parent.context, Scope.Scope)
|
|
575
581
|
return Scope.addFinalizer(scope, entry.finalizer).pipe(
|
|
@@ -733,6 +739,24 @@ export const getOption: {
|
|
|
733
739
|
})
|
|
734
740
|
)
|
|
735
741
|
|
|
742
|
+
const removeInterrupted = <K, A, E>(
|
|
743
|
+
self: RcMap<K, A, E>,
|
|
744
|
+
key: K,
|
|
745
|
+
entry: State.Entry<A, E>,
|
|
746
|
+
context: Context.Context<Scope.Scope>
|
|
747
|
+
) => {
|
|
748
|
+
if (self.state._tag === "Closed") return
|
|
749
|
+
const o = MutableHashMap.get(self.state.map, key)
|
|
750
|
+
if (o._tag === "None" || o.value !== entry) return
|
|
751
|
+
MutableHashMap.remove(self.state.map, key)
|
|
752
|
+
// Borrowers close the entry on release; an idle entry has none left.
|
|
753
|
+
if (entry.refCount > 0) return
|
|
754
|
+
closeEntry(entry).pipe(
|
|
755
|
+
Effect.runForkWith(context),
|
|
756
|
+
Fiber.runIn(self.scope)
|
|
757
|
+
)
|
|
758
|
+
}
|
|
759
|
+
|
|
736
760
|
const closeEntry = <A, E>(entry: State.Entry<A, E>) =>
|
|
737
761
|
entry.fiber
|
|
738
762
|
? Fiber.interrupt(entry.fiber).pipe(Effect.andThen(Scope.close(entry.scope, Exit.void)))
|
package/src/Record.ts
CHANGED
|
@@ -1372,8 +1372,8 @@ export const getSuccesses = <K extends string, A, E>(
|
|
|
1372
1372
|
*
|
|
1373
1373
|
* **Details**
|
|
1374
1374
|
*
|
|
1375
|
-
*
|
|
1376
|
-
* collected in the
|
|
1375
|
+
* Success values are collected in the first record, and failure values are
|
|
1376
|
+
* collected in the second record, preserving the original keys.
|
|
1377
1377
|
*
|
|
1378
1378
|
* **Example** (Partitioning with Result)
|
|
1379
1379
|
*
|
|
@@ -1382,7 +1382,7 @@ export const getSuccesses = <K extends string, A, E>(
|
|
|
1382
1382
|
*
|
|
1383
1383
|
* const x = { a: 1, b: 2, c: 3 }
|
|
1384
1384
|
* const f = (n: number) => (n % 2 === 0 ? Result.succeed(n) : Result.fail(n))
|
|
1385
|
-
* Record.partition(x, f) // => [{ a: 1, c: 3 }
|
|
1385
|
+
* Record.partition(x, f) // => [{ b: 2 }, { a: 1, c: 3 }]
|
|
1386
1386
|
* ```
|
|
1387
1387
|
*
|
|
1388
1388
|
* @category filtering
|
|
@@ -1395,8 +1395,8 @@ export const partition: {
|
|
|
1395
1395
|
*
|
|
1396
1396
|
* **Details**
|
|
1397
1397
|
*
|
|
1398
|
-
*
|
|
1399
|
-
* collected in the
|
|
1398
|
+
* Success values are collected in the first record, and failure values are
|
|
1399
|
+
* collected in the second record, preserving the original keys.
|
|
1400
1400
|
*
|
|
1401
1401
|
* **Example** (Partitioning with Result)
|
|
1402
1402
|
*
|
|
@@ -1405,7 +1405,7 @@ export const partition: {
|
|
|
1405
1405
|
*
|
|
1406
1406
|
* const x = { a: 1, b: 2, c: 3 }
|
|
1407
1407
|
* const f = (n: number) => (n % 2 === 0 ? Result.succeed(n) : Result.fail(n))
|
|
1408
|
-
* Record.partition(x, f) // => [{ a: 1, c: 3 }
|
|
1408
|
+
* Record.partition(x, f) // => [{ b: 2 }, { a: 1, c: 3 }]
|
|
1409
1409
|
* ```
|
|
1410
1410
|
*
|
|
1411
1411
|
* @category filtering
|
|
@@ -1413,15 +1413,15 @@ export const partition: {
|
|
|
1413
1413
|
*/
|
|
1414
1414
|
<K extends string, A, B, C>(f: (input: A, key: K) => Result<C, B>): (
|
|
1415
1415
|
self: ReadonlyRecord<K, A>
|
|
1416
|
-
) => [
|
|
1416
|
+
) => [passes: Record<ReadonlyRecord.NonLiteralKey<K>, C>, fails: Record<ReadonlyRecord.NonLiteralKey<K>, B>]
|
|
1417
1417
|
/**
|
|
1418
1418
|
* Applies a function to each record entry and partitions the returned `Result`
|
|
1419
1419
|
* values into two records.
|
|
1420
1420
|
*
|
|
1421
1421
|
* **Details**
|
|
1422
1422
|
*
|
|
1423
|
-
*
|
|
1424
|
-
* collected in the
|
|
1423
|
+
* Success values are collected in the first record, and failure values are
|
|
1424
|
+
* collected in the second record, preserving the original keys.
|
|
1425
1425
|
*
|
|
1426
1426
|
* **Example** (Partitioning with Result)
|
|
1427
1427
|
*
|
|
@@ -1430,43 +1430,43 @@ export const partition: {
|
|
|
1430
1430
|
*
|
|
1431
1431
|
* const x = { a: 1, b: 2, c: 3 }
|
|
1432
1432
|
* const f = (n: number) => (n % 2 === 0 ? Result.succeed(n) : Result.fail(n))
|
|
1433
|
-
* Record.partition(x, f) // => [{ a: 1, c: 3 }
|
|
1433
|
+
* Record.partition(x, f) // => [{ b: 2 }, { a: 1, c: 3 }]
|
|
1434
1434
|
* ```
|
|
1435
1435
|
*
|
|
1436
1436
|
* @category filtering
|
|
1437
1437
|
* @since 2.0.0
|
|
1438
1438
|
*/
|
|
1439
|
-
<K extends string, A, B, C>(self: ReadonlyRecord<K, A>, f: (input: A, key: K) => Result<C, B>): [
|
|
1439
|
+
<K extends string, A, B, C>(self: ReadonlyRecord<K, A>, f: (input: A, key: K) => Result<C, B>): [passes: Record<ReadonlyRecord.NonLiteralKey<K>, C>, fails: Record<ReadonlyRecord.NonLiteralKey<K>, B>]
|
|
1440
1440
|
} = dual(
|
|
1441
1441
|
2,
|
|
1442
1442
|
<K extends string, A, B, C>(
|
|
1443
1443
|
self: ReadonlyRecord<K, A>,
|
|
1444
1444
|
f: (input: A, key: K) => Result<C, B>
|
|
1445
|
-
): [
|
|
1446
|
-
const
|
|
1447
|
-
const
|
|
1445
|
+
): [passes: Record<ReadonlyRecord.NonLiteralKey<K>, C>, fails: Record<ReadonlyRecord.NonLiteralKey<K>, B>] => {
|
|
1446
|
+
const passes: Record<string, C> = empty()
|
|
1447
|
+
const fails: Record<string, B> = empty()
|
|
1448
1448
|
for (const key of keys(self)) {
|
|
1449
1449
|
const e = f(self[key], key)
|
|
1450
1450
|
if (R.isFailure(e)) {
|
|
1451
|
-
InternalRecord.assignProperty(
|
|
1451
|
+
InternalRecord.assignProperty(fails, key, e.failure)
|
|
1452
1452
|
} else {
|
|
1453
|
-
InternalRecord.assignProperty(
|
|
1453
|
+
InternalRecord.assignProperty(passes, key, e.success)
|
|
1454
1454
|
}
|
|
1455
1455
|
}
|
|
1456
|
-
return [
|
|
1456
|
+
return [passes, fails]
|
|
1457
1457
|
}
|
|
1458
1458
|
)
|
|
1459
1459
|
|
|
1460
1460
|
/**
|
|
1461
1461
|
* Partitions a record of `Result` values into two separate records,
|
|
1462
|
-
* one with the
|
|
1462
|
+
* one with the success values and one with the failure values.
|
|
1463
1463
|
*
|
|
1464
1464
|
* **Example** (Separating Result values)
|
|
1465
1465
|
*
|
|
1466
1466
|
* ```ts import.meta.vitest
|
|
1467
1467
|
* import { Record, Result } from "effect"
|
|
1468
1468
|
*
|
|
1469
|
-
* Record.separate({ a: Result.fail("e"), b: Result.succeed(1) }) // => [{
|
|
1469
|
+
* Record.separate({ a: Result.fail("e"), b: Result.succeed(1) }) // => [{ b: 1 }, { a: "e" }]
|
|
1470
1470
|
* ```
|
|
1471
1471
|
*
|
|
1472
1472
|
* @category filtering
|
|
@@ -1474,7 +1474,7 @@ export const partition: {
|
|
|
1474
1474
|
*/
|
|
1475
1475
|
export const separate: <K extends string, A, B>(
|
|
1476
1476
|
self: ReadonlyRecord<K, Result<B, A>>
|
|
1477
|
-
) => [Record<ReadonlyRecord.NonLiteralKey<K>,
|
|
1477
|
+
) => [Record<ReadonlyRecord.NonLiteralKey<K>, B>, Record<ReadonlyRecord.NonLiteralKey<K>, A>] = partition(identity)
|
|
1478
1478
|
|
|
1479
1479
|
/**
|
|
1480
1480
|
* Retrieves the keys of a given record as an array.
|
package/src/Schema.ts
CHANGED
|
@@ -77,7 +77,7 @@ import * as SchemaTransformation from "./SchemaTransformation.ts"
|
|
|
77
77
|
import type { StandardJSONSchemaV1, StandardSchemaV1 } from "./StandardSchema.ts"
|
|
78
78
|
import type { Assign, Lambda, Mutable, Simplify } from "./Struct.ts"
|
|
79
79
|
import * as Struct_ from "./Struct.ts"
|
|
80
|
-
import type {
|
|
80
|
+
import type { IsUnion, RequiredKeys } from "./Types.ts"
|
|
81
81
|
import type { Unify } from "./Unify.ts"
|
|
82
82
|
|
|
83
83
|
const TypeId = InternalMake.TypeId
|
|
@@ -5057,14 +5057,19 @@ export function refine<S extends Constraint, T extends S["Type"]>(
|
|
|
5057
5057
|
return (schema: S): refine<T, S> =>
|
|
5058
5058
|
make(SchemaAST.appendChecks(schema.ast, [SchemaAST.makeFilterByGuard(refinement, annotations)]), { schema })
|
|
5059
5059
|
}
|
|
5060
|
-
|
|
5060
|
+
// A concrete key requires a property; broad and open template keys do not.
|
|
5061
|
+
type EnsureSingleBrandKey<K extends PropertyKey> = IsUnion<K> extends false
|
|
5062
|
+
? {} extends Record<K, unknown> ? never : unknown
|
|
5063
|
+
: never
|
|
5064
|
+
// Collect all keys, including those not shared by every union member.
|
|
5065
|
+
type FromBrandKeys<A extends Brand.Brand<any>> = A extends unknown ? Brand.Brand.Keys<A> : never
|
|
5061
5066
|
/**
|
|
5062
5067
|
* Type-level representation returned by {@link brand}.
|
|
5063
5068
|
*
|
|
5064
5069
|
* @category branding
|
|
5065
5070
|
* @since 3.10.0
|
|
5066
5071
|
*/
|
|
5067
|
-
export interface brand<S extends Constraint, B> extends
|
|
5072
|
+
export interface brand<S extends Constraint, B extends string> extends
|
|
5068
5073
|
BottomLazy<
|
|
5069
5074
|
S["ast"],
|
|
5070
5075
|
brand<S, B>,
|
|
@@ -5076,19 +5081,19 @@ export interface brand<S extends Constraint, B> extends
|
|
|
5076
5081
|
S["~encoded.optionality"]
|
|
5077
5082
|
>
|
|
5078
5083
|
{
|
|
5079
|
-
readonly "Type": S["Type"] &
|
|
5084
|
+
readonly "Type": S["Type"] & Brand.Brand<B>
|
|
5080
5085
|
readonly "Encoded": S["Encoded"]
|
|
5081
5086
|
readonly "DecodingServices": S["DecodingServices"]
|
|
5082
5087
|
readonly "EncodingServices": S["EncodingServices"]
|
|
5083
5088
|
readonly "~type.make.in": S["~type.make.in"]
|
|
5084
|
-
readonly "~type.make": S["Type"] &
|
|
5085
|
-
readonly "Iso": S["Type"] &
|
|
5089
|
+
readonly "~type.make": S["Type"] & Brand.Brand<B>
|
|
5090
|
+
readonly "Iso": S["Type"] & Brand.Brand<B>
|
|
5086
5091
|
readonly schema: S
|
|
5087
5092
|
readonly identifier: string
|
|
5088
5093
|
}
|
|
5089
5094
|
/**
|
|
5090
|
-
*
|
|
5091
|
-
*
|
|
5095
|
+
* Intersects a schema's output type with `Brand.Brand<B>` to prevent accidental
|
|
5096
|
+
* mixing of structurally identical types.
|
|
5092
5097
|
*
|
|
5093
5098
|
* **When to use**
|
|
5094
5099
|
*
|
|
@@ -5097,31 +5102,52 @@ export interface brand<S extends Constraint, B> extends
|
|
|
5097
5102
|
*
|
|
5098
5103
|
* **Gotchas**
|
|
5099
5104
|
*
|
|
5100
|
-
* `
|
|
5101
|
-
*
|
|
5105
|
+
* - `identifier` must be a single concrete string literal. Widened strings,
|
|
5106
|
+
* unions, and open template literal types are rejected.
|
|
5107
|
+
* - `brand` only narrows the TypeScript output type. It does not change the
|
|
5108
|
+
* schema's runtime AST or add runtime checks.
|
|
5109
|
+
* - Schema representations and generated schema code omit the brand. Reapply
|
|
5110
|
+
* `brand` after rebuilding or generating a schema when the nominal type is
|
|
5111
|
+
* still required.
|
|
5102
5112
|
*
|
|
5103
|
-
* @see {@link fromBrand} for applying a Brand constructor's checks along with
|
|
5113
|
+
* @see {@link fromBrand} for applying a Brand constructor's checks along with its branded type
|
|
5104
5114
|
*
|
|
5105
5115
|
* @category branding
|
|
5106
5116
|
* @since 3.10.0
|
|
5107
5117
|
*/
|
|
5108
|
-
export function brand<B extends string>(identifier: B) {
|
|
5118
|
+
export function brand<B extends string>(identifier: B & EnsureSingleBrandKey<B>) {
|
|
5109
5119
|
return <S extends ConstraintRebuildable>(schema: S): brand<S["Rebuild"], B> =>
|
|
5110
|
-
make(
|
|
5120
|
+
make(schema.ast, { schema, identifier })
|
|
5111
5121
|
}
|
|
5112
5122
|
/**
|
|
5113
5123
|
* Creates a branded schema from a {@link Brand.Constructor}, applying the
|
|
5114
|
-
* constructor's checks and
|
|
5124
|
+
* constructor's checks and branded type to the underlying schema.
|
|
5125
|
+
*
|
|
5126
|
+
* **When to use**
|
|
5127
|
+
*
|
|
5128
|
+
* Use to reuse the checks from a constructor with one concrete brand key.
|
|
5129
|
+
*
|
|
5130
|
+
* **Gotchas**
|
|
5131
|
+
*
|
|
5132
|
+
* `identifier` must match the constructor's only brand key. Apply `fromBrand`
|
|
5133
|
+
* repeatedly to compose distinct brands, and use {@link Union} to represent
|
|
5134
|
+
* alternatives.
|
|
5135
|
+
*
|
|
5136
|
+
* @see {@link brand} for adding a brand without constructor checks
|
|
5115
5137
|
*
|
|
5116
5138
|
* @category branding
|
|
5117
5139
|
* @since 3.10.0
|
|
5118
5140
|
*/
|
|
5119
|
-
export function fromBrand<A extends Brand.Brand<any>>(
|
|
5141
|
+
export function fromBrand<A extends Brand.Brand<any>>(
|
|
5142
|
+
identifier: Brand.Brand.Keys<A> & string,
|
|
5143
|
+
ctor: Brand.Constructor<A> & EnsureSingleBrandKey<FromBrandKeys<A>>
|
|
5144
|
+
) {
|
|
5145
|
+
type B = Brand.Brand.Keys<A> & string
|
|
5120
5146
|
return <S extends Top & { readonly "Type": Brand.Brand.Unbranded<A> }>(
|
|
5121
5147
|
self: S
|
|
5122
|
-
): brand<S["Rebuild"],
|
|
5123
|
-
|
|
5124
|
-
|
|
5148
|
+
): brand<S["Rebuild"], B> =>
|
|
5149
|
+
// The constructor already guarantees a single concrete brand key.
|
|
5150
|
+
(ctor.checks ? self.check(...ctor.checks) : self).pipe(brand<B>(identifier as B & EnsureSingleBrandKey<B>))
|
|
5125
5151
|
}
|
|
5126
5152
|
/**
|
|
5127
5153
|
* Type-level representation returned by {@link middlewareDecoding}.
|
|
@@ -15695,6 +15721,8 @@ export function toEquivalence<T>(schema: Schema<T>): Equivalence.Equivalence<T>
|
|
|
15695
15721
|
* Use {@link toType} before this function to represent the type side instead.
|
|
15696
15722
|
* The optional reference policy controls which candidates are extracted into the document's reference table. By
|
|
15697
15723
|
* default, only candidates with a resolved identifier become references; recursive candidates always require one.
|
|
15724
|
+
* TypeScript-only distinctions such as those added by {@link brand} are not
|
|
15725
|
+
* part of the schema AST and are therefore omitted.
|
|
15698
15726
|
*
|
|
15699
15727
|
* @see {@link SchemaRepresentation.toRepresentation} for converting a `SchemaAST.AST` directly
|
|
15700
15728
|
*
|
|
@@ -16577,8 +16605,8 @@ export declare namespace Annotations {
|
|
|
16577
16605
|
}
|
|
16578
16606
|
/**
|
|
16579
16607
|
* Base annotations shared by all composite schema nodes. Extends
|
|
16580
|
-
* {@link Documentation} with error messages
|
|
16581
|
-
*
|
|
16608
|
+
* {@link Documentation} with error messages and arbitrary generation hooks.
|
|
16609
|
+
* {@link Declaration} and other annotation
|
|
16582
16610
|
* interfaces build on top of this.
|
|
16583
16611
|
*
|
|
16584
16612
|
* @category models
|
|
@@ -16616,10 +16644,6 @@ export declare namespace Annotations {
|
|
|
16616
16644
|
* filter/refinement instead.
|
|
16617
16645
|
*/
|
|
16618
16646
|
readonly identifier?: string | undefined
|
|
16619
|
-
/**
|
|
16620
|
-
* Accumulated brands when multiple brands are added with `Schema.brand`.
|
|
16621
|
-
*/
|
|
16622
|
-
readonly brands?: ReadonlyArray<string> | undefined
|
|
16623
16647
|
}
|
|
16624
16648
|
/**
|
|
16625
16649
|
* Helpers for projecting declaration type-parameter schemas into decoded or
|