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/SchemaAST.ts
CHANGED
|
@@ -3394,7 +3394,8 @@ export function collectSentinels(ast: AST): ReadonlyArray<Sentinel> {
|
|
|
3394
3394
|
}
|
|
3395
3395
|
}
|
|
3396
3396
|
|
|
3397
|
-
|
|
3397
|
+
/** @internal */
|
|
3398
|
+
export type CandidateIndex = (input: any, isConstructor: boolean) => ReadonlyArray<number>
|
|
3398
3399
|
type SentinelEntry = readonly [
|
|
3399
3400
|
byValue: Map<LiteralValue | symbol, Set<number>>,
|
|
3400
3401
|
all: Set<number>
|
|
@@ -3409,15 +3410,17 @@ const getRuntimeType = (input: unknown): Type => input === null ? "null" : Array
|
|
|
3409
3410
|
const hasPropertySignature = (input: object, key: PropertyKey): boolean =>
|
|
3410
3411
|
key === "__proto__" ? Object.hasOwn(input, key) : key in input
|
|
3411
3412
|
|
|
3412
|
-
|
|
3413
|
+
/** @internal */
|
|
3414
|
+
export function getCandidateIndex(types: ReadonlyArray<AST>): CandidateIndex {
|
|
3413
3415
|
let index = candidateIndexCache.get(types)
|
|
3414
3416
|
if (index) return index
|
|
3415
3417
|
|
|
3416
3418
|
let bySentinel: SentinelIndex | undefined
|
|
3417
3419
|
let sentinelCandidateCount = 0
|
|
3418
3420
|
let otherwise: { [K in Type]?: Array<number> } | undefined
|
|
3419
|
-
let literalCandidates: Map<LiteralValue | symbol, Array<
|
|
3421
|
+
let literalCandidates: Map<LiteralValue | symbol, Array<number>> | undefined
|
|
3420
3422
|
let onlyLiterals = true
|
|
3423
|
+
const literalOf: Array<LiteralValue | symbol | undefined> = []
|
|
3421
3424
|
for (let i = 0; i < types.length; i++) {
|
|
3422
3425
|
const a = types[i]
|
|
3423
3426
|
const encoded = toCandidate(a)
|
|
@@ -3426,9 +3429,10 @@ function getIndex(types: ReadonlyArray<AST>): CandidateIndex {
|
|
|
3426
3429
|
if (isLiteral(encoded) || isUniqueSymbol(encoded)) {
|
|
3427
3430
|
literalCandidates ??= new Map()
|
|
3428
3431
|
const literal = isLiteral(encoded) ? encoded.literal : encoded.symbol
|
|
3432
|
+
literalOf[i] = literal
|
|
3429
3433
|
let arr = literalCandidates.get(literal)
|
|
3430
3434
|
if (!arr) literalCandidates.set(literal, arr = [])
|
|
3431
|
-
arr.push(
|
|
3435
|
+
arr.push(i)
|
|
3432
3436
|
} else {
|
|
3433
3437
|
onlyLiterals = false
|
|
3434
3438
|
}
|
|
@@ -3454,24 +3458,25 @@ function getIndex(types: ReadonlyArray<AST>): CandidateIndex {
|
|
|
3454
3458
|
}
|
|
3455
3459
|
|
|
3456
3460
|
// Non-discriminated members are grouped by runtime type once and reused by every decode.
|
|
3457
|
-
const fallbacks: { [K in Type]?: ReadonlyArray<
|
|
3458
|
-
const getFallback = (type: Type): ReadonlyArray<
|
|
3459
|
-
fallbacks[type] ??= Object.freeze(
|
|
3461
|
+
const fallbacks: { [K in Type]?: ReadonlyArray<number> } = {}
|
|
3462
|
+
const getFallback = (type: Type): ReadonlyArray<number> =>
|
|
3463
|
+
fallbacks[type] ??= Object.freeze(otherwise?.[type] ?? emptyCandidates)
|
|
3460
3464
|
|
|
3461
3465
|
if (onlyLiterals && literalCandidates) {
|
|
3462
3466
|
literalCandidates.forEach(Object.freeze)
|
|
3463
3467
|
index = (input) => literalCandidates.get(input) ?? emptyCandidates
|
|
3464
3468
|
} else if (bySentinel?.size === 1 && !otherwise) {
|
|
3465
3469
|
const [key, [byValue]] = bySentinel.entries().next().value!
|
|
3466
|
-
const candidates =
|
|
3470
|
+
const candidates = new Map<LiteralValue | symbol, ReadonlyArray<number>>()
|
|
3467
3471
|
for (const [literal, indexes] of byValue) {
|
|
3468
|
-
candidates.set(literal, Object.freeze(Array.from(indexes
|
|
3472
|
+
candidates.set(literal, Object.freeze(Array.from(indexes)))
|
|
3469
3473
|
}
|
|
3474
|
+
const all = Object.freeze(types.map((_, i) => i))
|
|
3470
3475
|
index = (input, isConstructor) => {
|
|
3471
3476
|
if (Predicate.isObjectKeyword(input)) {
|
|
3472
3477
|
const value = hasPropertySignature(input, key) ? (input as any)[key] : undefined
|
|
3473
3478
|
if (value !== undefined) return candidates.get(value) ?? emptyCandidates
|
|
3474
|
-
if (isConstructor) return
|
|
3479
|
+
if (isConstructor) return all
|
|
3475
3480
|
}
|
|
3476
3481
|
return emptyCandidates
|
|
3477
3482
|
}
|
|
@@ -3538,12 +3543,12 @@ function getIndex(types: ReadonlyArray<AST>): CandidateIndex {
|
|
|
3538
3543
|
}
|
|
3539
3544
|
}
|
|
3540
3545
|
}
|
|
3541
|
-
return Array.from(selected).sort((a, b) => a - b)
|
|
3546
|
+
return Array.from(selected).sort((a, b) => a - b)
|
|
3542
3547
|
}
|
|
3543
3548
|
} else {
|
|
3544
3549
|
index = (input) => {
|
|
3545
3550
|
const fallback = getFallback(getRuntimeType(input))
|
|
3546
|
-
return literalCandidates ? fallback.filter(
|
|
3551
|
+
return literalCandidates ? fallback.filter((i) => literalOf[i] === undefined || literalOf[i] === input) : fallback
|
|
3547
3552
|
}
|
|
3548
3553
|
}
|
|
3549
3554
|
|
|
@@ -3551,31 +3556,6 @@ function getIndex(types: ReadonlyArray<AST>): CandidateIndex {
|
|
|
3551
3556
|
return index
|
|
3552
3557
|
}
|
|
3553
3558
|
|
|
3554
|
-
function filterLiterals(input: any) {
|
|
3555
|
-
return (ast: AST) => {
|
|
3556
|
-
const encoded = toCandidate(ast)
|
|
3557
|
-
return encoded._tag === "Literal" ?
|
|
3558
|
-
encoded.literal === input
|
|
3559
|
-
: encoded._tag === "UniqueSymbol" ?
|
|
3560
|
-
encoded.symbol === input
|
|
3561
|
-
: true
|
|
3562
|
-
}
|
|
3563
|
-
}
|
|
3564
|
-
|
|
3565
|
-
/**
|
|
3566
|
-
* The goal is to reduce the number of a union members that will be checked.
|
|
3567
|
-
* This is useful to reduce the number of issues that will be returned.
|
|
3568
|
-
*
|
|
3569
|
-
* @internal
|
|
3570
|
-
*/
|
|
3571
|
-
export function getCandidates(
|
|
3572
|
-
input: any,
|
|
3573
|
-
types: ReadonlyArray<AST>,
|
|
3574
|
-
isConstructor = false
|
|
3575
|
-
): ReadonlyArray<AST> {
|
|
3576
|
-
return getIndex(types)(input, isConstructor)
|
|
3577
|
-
}
|
|
3578
|
-
|
|
3579
3559
|
/**
|
|
3580
3560
|
* AST node representing a union of schemas.
|
|
3581
3561
|
*
|
|
@@ -3680,43 +3660,28 @@ export const Union: new<A extends AST = AST>(
|
|
|
3680
3660
|
): SchemaParser.Parser {
|
|
3681
3661
|
// oxlint-disable-next-line @typescript-eslint/no-this-alias
|
|
3682
3662
|
const ast = this
|
|
3663
|
+
const isConstructor = compileField !== undefined
|
|
3664
|
+
const parsers: Array<SchemaParser.Parser> = []
|
|
3665
|
+
const parser = (i: number): SchemaParser.Parser => parsers[i] ??= compile(ast.types[i])
|
|
3666
|
+
let index: CandidateIndex | undefined
|
|
3683
3667
|
|
|
3684
3668
|
return (input, options) => {
|
|
3685
3669
|
if (input === InternalParser.missing) {
|
|
3686
3670
|
return InternalParser.missingExit
|
|
3687
3671
|
}
|
|
3688
|
-
const candidates =
|
|
3672
|
+
const candidates = (index ??= getCandidateIndex(ast.types))(input, isConstructor)
|
|
3689
3673
|
|
|
3690
3674
|
if (candidates.length === 0) {
|
|
3691
3675
|
return Effect.fail(new SchemaIssue.AnyOf(ast, [], input, options))
|
|
3692
3676
|
}
|
|
3693
3677
|
if (candidates.length === 1) {
|
|
3694
|
-
const result =
|
|
3678
|
+
const result = parser(candidates[0])(input, options)
|
|
3695
3679
|
if ((result as Exit.Exit<unknown, SchemaIssue.Issue>)._tag === "Success") return result
|
|
3696
3680
|
return effectIsExit(result)
|
|
3697
3681
|
? failSingleUnionCandidate(ast, (result as Exit.Failure<unknown, SchemaIssue.Issue>).cause, input, options)
|
|
3698
|
-
:
|
|
3699
|
-
}
|
|
3700
|
-
|
|
3701
|
-
const state = {
|
|
3702
|
-
ast,
|
|
3703
|
-
compile,
|
|
3704
|
-
input,
|
|
3705
|
-
out: undefined,
|
|
3706
|
-
successes: ast.options?.mode === "oneOf" ? [] : undefined,
|
|
3707
|
-
issues: undefined as Arr.NonEmptyArray<SchemaIssue.Issue> | undefined,
|
|
3708
|
-
options
|
|
3709
|
-
}
|
|
3710
|
-
const eff = parseUnion(state, candidates)
|
|
3711
|
-
if (!eff) {
|
|
3712
|
-
if (state.out) return state.out
|
|
3713
|
-
return Effect.fail(new SchemaIssue.AnyOf(ast, state.issues ?? [], input, options))
|
|
3682
|
+
: catchSingleUnionCandidate(ast, result, input, options)
|
|
3714
3683
|
}
|
|
3715
|
-
return
|
|
3716
|
-
if (state.out === InternalParser.sameExit) return Effect.succeed(input)
|
|
3717
|
-
if (state.out) return state.out
|
|
3718
|
-
return Effect.fail(new SchemaIssue.AnyOf(ast, state.issues ?? [], input, options))
|
|
3719
|
-
})
|
|
3684
|
+
return parseUnionCandidates(ast, parser, candidates, input, options)
|
|
3720
3685
|
}
|
|
3721
3686
|
}
|
|
3722
3687
|
private _rebuild(
|
|
@@ -3795,20 +3760,65 @@ function failSingleUnionCandidate(
|
|
|
3795
3760
|
return Exit.fail(new SchemaIssue.AnyOf(ast, [issue], input, options))
|
|
3796
3761
|
}
|
|
3797
3762
|
|
|
3798
|
-
|
|
3799
|
-
|
|
3763
|
+
function catchSingleUnionCandidate(
|
|
3764
|
+
ast: Union,
|
|
3765
|
+
result: Effect.Effect<unknown, SchemaIssue.Issue, unknown>,
|
|
3766
|
+
input: unknown,
|
|
3767
|
+
options: ParseOptions
|
|
3768
|
+
) {
|
|
3769
|
+
return Effect.catchCause(result, (cause) => failSingleUnionCandidate(ast, cause, input, options))
|
|
3770
|
+
}
|
|
3771
|
+
|
|
3772
|
+
type UnionParserState = {
|
|
3773
|
+
readonly parser: (i: number) => SchemaParser.Parser
|
|
3800
3774
|
readonly ast: Union
|
|
3801
3775
|
readonly input: unknown
|
|
3802
3776
|
readonly options: ParseOptions
|
|
3803
3777
|
out: Exit.Success<unknown, SchemaIssue.Issue> | undefined
|
|
3804
3778
|
readonly successes: Array<AST> | undefined
|
|
3805
3779
|
issues: Array<SchemaIssue.Issue> | undefined
|
|
3806
|
-
}
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3782
|
+
function parseUnionCandidates(
|
|
3783
|
+
ast: Union,
|
|
3784
|
+
parser: (i: number) => SchemaParser.Parser,
|
|
3785
|
+
candidates: ReadonlyArray<number>,
|
|
3786
|
+
input: unknown,
|
|
3787
|
+
options: ParseOptions
|
|
3788
|
+
): Effect.Effect<unknown, SchemaIssue.Issue, any> {
|
|
3789
|
+
const state: UnionParserState = {
|
|
3790
|
+
ast,
|
|
3791
|
+
parser,
|
|
3792
|
+
input,
|
|
3793
|
+
out: undefined,
|
|
3794
|
+
successes: ast.options?.mode === "oneOf" ? [] : undefined,
|
|
3795
|
+
issues: undefined,
|
|
3796
|
+
options
|
|
3797
|
+
}
|
|
3798
|
+
const eff = parseUnion(state, candidates)
|
|
3799
|
+
if (!eff) {
|
|
3800
|
+
if (state.out) return state.out
|
|
3801
|
+
return Effect.fail(new SchemaIssue.AnyOf(ast, state.issues ?? [], input, options))
|
|
3802
|
+
}
|
|
3803
|
+
return resumeUnion(eff, state)
|
|
3804
|
+
}
|
|
3805
|
+
|
|
3806
|
+
function resumeUnion(
|
|
3807
|
+
eff: Effect.Effect<void, SchemaIssue.Issue, any>,
|
|
3808
|
+
state: UnionParserState
|
|
3809
|
+
): Effect.Effect<unknown, SchemaIssue.Issue, any> {
|
|
3810
|
+
return Effect.flatMapEager(eff, (_) => {
|
|
3811
|
+
if (state.out === InternalParser.sameExit) return Effect.succeed(state.input)
|
|
3812
|
+
if (state.out) return state.out
|
|
3813
|
+
return Effect.fail(new SchemaIssue.AnyOf(state.ast, state.issues ?? [], state.input, state.options))
|
|
3814
|
+
})
|
|
3815
|
+
}
|
|
3816
|
+
|
|
3817
|
+
const parseUnion = iterateEager<UnionParserState, number>()({
|
|
3818
|
+
onItem(s, i) {
|
|
3819
|
+
return s.parser(i)(s.input, s.options)
|
|
3810
3820
|
},
|
|
3811
|
-
step(s,
|
|
3821
|
+
step(s, i, exit) {
|
|
3812
3822
|
if (exit._tag === "Failure") {
|
|
3813
3823
|
const issue = InternalSchemaCause.getSchemaIssue(exit.cause)
|
|
3814
3824
|
if (issue === undefined) {
|
|
@@ -3818,12 +3828,12 @@ const parseUnion = iterateEager<{
|
|
|
3818
3828
|
else s.issues = [issue]
|
|
3819
3829
|
} else {
|
|
3820
3830
|
if (s.out && s.successes) {
|
|
3821
|
-
s.successes.push(
|
|
3831
|
+
s.successes.push(s.ast.types[i])
|
|
3822
3832
|
return Exit.fail(new SchemaIssue.OneOf(s.ast, s.successes, s.input, s.options))
|
|
3823
3833
|
}
|
|
3824
3834
|
s.out = exit
|
|
3825
3835
|
if (s.successes) {
|
|
3826
|
-
s.successes.push(
|
|
3836
|
+
s.successes.push(s.ast.types[i])
|
|
3827
3837
|
} else {
|
|
3828
3838
|
return Exit.void
|
|
3829
3839
|
}
|
|
@@ -4220,26 +4230,33 @@ export function isPattern(regExp: globalThis.RegExp, annotations?: Schema.Annota
|
|
|
4220
4230
|
)
|
|
4221
4231
|
}
|
|
4222
4232
|
|
|
4223
|
-
|
|
4233
|
+
// Copies that update only context or encoding share a body.
|
|
4234
|
+
// All other fields describe the body itself, including child contexts.
|
|
4235
|
+
const bodyOwners = new WeakMap<AST, AST>()
|
|
4236
|
+
|
|
4237
|
+
function copy<A extends AST>(ast: A, changes: Partial<AST>): A {
|
|
4224
4238
|
// AST copies preserve the prototype and enumerable values, not property descriptors.
|
|
4225
|
-
|
|
4239
|
+
const out = Object.assign(Object.create(Object.getPrototypeOf(ast)), ast, changes) as A
|
|
4240
|
+
if (Reflect.ownKeys(changes).every((key) => key === "context" || key === "encoding")) {
|
|
4241
|
+
bodyOwners.set(out, getContextOwner(ast))
|
|
4242
|
+
}
|
|
4243
|
+
return out
|
|
4226
4244
|
}
|
|
4227
4245
|
|
|
4228
|
-
const contextOwners = new WeakMap<AST, AST>()
|
|
4229
|
-
|
|
4230
4246
|
/** @internal */
|
|
4231
|
-
export function getContextOwner(ast:
|
|
4232
|
-
|
|
4247
|
+
export function getContextOwner<A extends AST>(ast: A): A {
|
|
4248
|
+
const existing = bodyOwners.get(ast)
|
|
4249
|
+
if (existing !== undefined) return existing as A
|
|
4250
|
+
if (ast.encoding === undefined) return ast
|
|
4251
|
+
// A body representative must not expose or retain the node's own codec.
|
|
4252
|
+
const owner = Object.assign(Object.create(Object.getPrototypeOf(ast)), ast, { encoding: undefined }) as A
|
|
4253
|
+
bodyOwners.set(ast, owner)
|
|
4254
|
+
return owner
|
|
4233
4255
|
}
|
|
4234
4256
|
|
|
4235
4257
|
/** @internal */
|
|
4236
4258
|
export function replaceEncoding<A extends AST>(ast: A, encoding: Encoding | undefined): A {
|
|
4237
|
-
|
|
4238
|
-
return ast
|
|
4239
|
-
}
|
|
4240
|
-
const out = copy(ast)
|
|
4241
|
-
out.encoding = encoding
|
|
4242
|
-
return out
|
|
4259
|
+
return ast.encoding === encoding ? ast : copy(ast, { encoding })
|
|
4243
4260
|
}
|
|
4244
4261
|
|
|
4245
4262
|
/** @internal */
|
|
@@ -4248,13 +4265,10 @@ export function replaceContext<A extends AST>(ast: A, context: Context | undefin
|
|
|
4248
4265
|
return ast
|
|
4249
4266
|
}
|
|
4250
4267
|
const owner = getContextOwner(ast)
|
|
4251
|
-
if (owner.context === context) {
|
|
4252
|
-
return owner
|
|
4268
|
+
if (owner.context === context && owner.encoding === ast.encoding) {
|
|
4269
|
+
return owner
|
|
4253
4270
|
}
|
|
4254
|
-
|
|
4255
|
-
out.context = context
|
|
4256
|
-
contextOwners.set(out as A, owner)
|
|
4257
|
-
return out
|
|
4271
|
+
return copy(ast, { context })
|
|
4258
4272
|
}
|
|
4259
4273
|
|
|
4260
4274
|
/** @internal */
|
|
@@ -4268,9 +4282,7 @@ export function annotate<A extends AST>(ast: A, annotations: Schema.Annotations.
|
|
|
4268
4282
|
const last = ast.checks[ast.checks.length - 1]
|
|
4269
4283
|
return replaceChecks(ast, Arr.append(ast.checks.slice(0, -1), last.annotate(annotations)))
|
|
4270
4284
|
}
|
|
4271
|
-
|
|
4272
|
-
out.annotations = { ...ast.annotations, ...annotations }
|
|
4273
|
-
return out
|
|
4285
|
+
return copy(ast, { annotations: { ...ast.annotations, ...annotations } })
|
|
4274
4286
|
}
|
|
4275
4287
|
|
|
4276
4288
|
/** @internal */
|
|
@@ -4281,9 +4293,7 @@ export function replaceChecks<A extends AST>(ast: A, checks: Checks | undefined)
|
|
|
4281
4293
|
if (ast.checks === checks) {
|
|
4282
4294
|
return ast
|
|
4283
4295
|
}
|
|
4284
|
-
|
|
4285
|
-
out.checks = checks
|
|
4286
|
-
return out
|
|
4296
|
+
return copy(ast, { checks })
|
|
4287
4297
|
}
|
|
4288
4298
|
|
|
4289
4299
|
/** @internal */
|
|
@@ -4364,13 +4374,6 @@ function appendTransformation<A extends AST>(
|
|
|
4364
4374
|
return replaceEncoding(to, to.encoding ? [...to.encoding, link] : [link])
|
|
4365
4375
|
}
|
|
4366
4376
|
|
|
4367
|
-
/** @internal */
|
|
4368
|
-
export function brand(ast: AST, brand: string): AST {
|
|
4369
|
-
const existing = InternalAnnotations.resolveBrands(ast)
|
|
4370
|
-
const brands = existing ? [...existing, brand] : [brand]
|
|
4371
|
-
return annotate(ast, { brands })
|
|
4372
|
-
}
|
|
4373
|
-
|
|
4374
4377
|
/**
|
|
4375
4378
|
* Maps over the array but will return the original array if no changes occur.
|
|
4376
4379
|
* @internal
|
|
@@ -4555,6 +4558,17 @@ function extractStructuralChecks(checks: Checks): Checks | undefined {
|
|
|
4555
4558
|
return Arr.isArrayNonEmpty(out) ? out : undefined
|
|
4556
4559
|
}
|
|
4557
4560
|
|
|
4561
|
+
function canPreserveEncodingChecks(ast: AST): boolean {
|
|
4562
|
+
let preserve = true
|
|
4563
|
+
function visit(child: AST): AST {
|
|
4564
|
+
preserve = preserve && !child.encoding && !isSuspend(child)
|
|
4565
|
+
if (preserve && "recur" in child) child.recur(visit)
|
|
4566
|
+
return child
|
|
4567
|
+
}
|
|
4568
|
+
if ("recur" in ast) ast.recur(visit)
|
|
4569
|
+
return preserve
|
|
4570
|
+
}
|
|
4571
|
+
|
|
4558
4572
|
/**
|
|
4559
4573
|
* Strips all encoding transformations from an AST, returning the decoded
|
|
4560
4574
|
* (type-level) representation.
|
|
@@ -4581,22 +4595,24 @@ function extractStructuralChecks(checks: Checks): Checks | undefined {
|
|
|
4581
4595
|
* @since 4.0.0
|
|
4582
4596
|
*/
|
|
4583
4597
|
export const toType = memoizeIdempotent(<A extends AST>(ast: A): A => {
|
|
4584
|
-
const
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4598
|
+
const owner = getContextOwner(ast)
|
|
4599
|
+
if (owner !== ast) {
|
|
4600
|
+
const type = toType(owner)
|
|
4601
|
+
return type === owner && ast.encoding === undefined ? ast : replaceContext(type, ast.context)
|
|
4602
|
+
}
|
|
4603
|
+
const type = ("recur" in ast ? ast.recur(toType) : ast) as A
|
|
4604
|
+
if ("encodingChecks" in type && type.encodingChecks) {
|
|
4605
|
+
const checks = canPreserveEncodingChecks(ast)
|
|
4606
|
+
? type.encodingChecks
|
|
4590
4607
|
: isArrays(type) || isObjects(type) || isDeclaration(type) && type.typeParameters.length > 0
|
|
4591
|
-
? extractStructuralChecks(encodingChecks)
|
|
4608
|
+
? extractStructuralChecks(type.encodingChecks)
|
|
4592
4609
|
: undefined
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
return copyOfType
|
|
4610
|
+
return copy(type, {
|
|
4611
|
+
encodingChecks: undefined,
|
|
4612
|
+
checks: combineChecks(type.checks, checks)
|
|
4613
|
+
})
|
|
4598
4614
|
}
|
|
4599
|
-
return type
|
|
4615
|
+
return type
|
|
4600
4616
|
})
|
|
4601
4617
|
|
|
4602
4618
|
/**
|
|
@@ -4668,8 +4684,12 @@ export const flip = memoize((ast: AST): AST => {
|
|
|
4668
4684
|
if (ast.encoding) {
|
|
4669
4685
|
return flipEncoding(ast, ast.encoding)
|
|
4670
4686
|
}
|
|
4671
|
-
const
|
|
4672
|
-
|
|
4687
|
+
const owner = getContextOwner(ast)
|
|
4688
|
+
if (owner !== ast) {
|
|
4689
|
+
const flipped = flip(owner)
|
|
4690
|
+
return flipped === owner ? ast : replaceContext(flipped, ast.context)
|
|
4691
|
+
}
|
|
4692
|
+
return "flip" in ast ? ast.flip(flip) : "recur" in ast ? ast.recur(flip) : ast
|
|
4673
4693
|
})
|
|
4674
4694
|
|
|
4675
4695
|
/** @internal */
|
|
@@ -2432,7 +2432,9 @@ export interface ToRepresentationOptions {
|
|
|
2432
2432
|
* **Details**
|
|
2433
2433
|
*
|
|
2434
2434
|
* Apply `SchemaAST.toType` to the AST first to lower its type side instead. The optional reference policy controls which
|
|
2435
|
-
* candidates are moved into the document's shared reference table.
|
|
2435
|
+
* candidates are moved into the document's shared reference table. TypeScript-only
|
|
2436
|
+
* distinctions such as those added by `Schema.brand` are absent from the AST
|
|
2437
|
+
* and cannot be reconstructed from the resulting document.
|
|
2436
2438
|
*
|
|
2437
2439
|
* @see {@link toRepresentations} for multiple roots sharing one reference table
|
|
2438
2440
|
*
|
package/src/ScopedCache.ts
CHANGED
|
@@ -317,7 +317,7 @@ export const get: {
|
|
|
317
317
|
// Move the entry to the end of the map to keep it fresh
|
|
318
318
|
MutableHashMap.remove(state.map, key)
|
|
319
319
|
MutableHashMap.set(state.map, key, oentry.value)
|
|
320
|
-
return awaitEntry(oentry.value, restore)
|
|
320
|
+
return awaitEntry(self, key, oentry.value, restore)
|
|
321
321
|
}
|
|
322
322
|
const scope = Scope.makeUnsafe()
|
|
323
323
|
const deferred = Deferred.makeUnsafe</**
|
|
@@ -380,41 +380,46 @@ export const get: {
|
|
|
380
380
|
entry.fiber = effect.forkUnsafe(
|
|
381
381
|
fiber,
|
|
382
382
|
effect.onExit(effect.suspend(() => Scope.provide(self.lookup(key), scope)), (exit) => {
|
|
383
|
-
Deferred.doneUnsafe(deferred, exit)
|
|
384
383
|
if (effect.exitHasInterrupts(exit)) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if (Option.isSome(current) && current.value === entry) MutableHashMap.remove(self.state.map, key)
|
|
388
|
-
}
|
|
384
|
+
removeEntry(self, key, entry)
|
|
385
|
+
Deferred.doneUnsafe(deferred, exit)
|
|
389
386
|
return Scope.close(scope, exit)
|
|
390
387
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
388
|
+
try {
|
|
389
|
+
const ttl = self.timeToLive(exit, key)
|
|
390
|
+
if (Duration.isFinite(ttl)) {
|
|
391
|
+
entry.expiresAt = fiber.getRef(effect.ClockRef).currentTimeMillisUnsafe() + Duration.toMillis(ttl)
|
|
392
|
+
}
|
|
393
|
+
} finally {
|
|
394
|
+
Deferred.doneUnsafe(deferred, exit)
|
|
394
395
|
}
|
|
395
396
|
return effect.void
|
|
396
397
|
}),
|
|
397
398
|
true,
|
|
398
399
|
true
|
|
399
400
|
)
|
|
400
|
-
return awaitEntry(entry, restore)
|
|
401
|
+
return awaitEntry(self, key, entry, restore)
|
|
401
402
|
})
|
|
402
403
|
)
|
|
403
404
|
})
|
|
404
405
|
)
|
|
405
406
|
)
|
|
406
407
|
|
|
407
|
-
const awaitEntry = <A, E>(
|
|
408
|
+
const awaitEntry = <Key, A, E, R>(
|
|
409
|
+
self: ScopedCache<Key, A, E, R>,
|
|
410
|
+
key: Key,
|
|
408
411
|
entry: Entry<A, E>,
|
|
409
412
|
restore: <X, Y, Z>(effect: Effect.Effect<X, Y, Z>) => Effect.Effect<X, Y, Z>
|
|
410
413
|
): Effect.Effect<A, E> => {
|
|
411
|
-
|
|
412
|
-
if (fiber === undefined || Deferred.isDoneUnsafe(entry.deferred)) return restore(Deferred.await(entry.deferred))
|
|
414
|
+
if (Deferred.isDoneUnsafe(entry.deferred)) return restore(Deferred.await(entry.deferred))
|
|
413
415
|
entry.awaiters++
|
|
414
416
|
// Install cleanup before restore so a pending interrupt cannot skip the decrement.
|
|
415
417
|
return effect.onExit(restore(Deferred.await(entry.deferred)), () => {
|
|
416
418
|
entry.awaiters--
|
|
417
|
-
|
|
419
|
+
const fiber = entry.fiber
|
|
420
|
+
if (entry.awaiters > 0 || fiber === undefined || Deferred.isDoneUnsafe(entry.deferred)) return effect.void
|
|
421
|
+
// Detach before interruption so callers arriving during finalization start fresh.
|
|
422
|
+
removeEntry(self, key, entry)
|
|
418
423
|
return effect.flatMap(effect.fiberInterrupt(fiber), () => {
|
|
419
424
|
const exit = fiber.pollUnsafe()!
|
|
420
425
|
return Exit.isFailure(exit) && Cause.hasDies(exit.cause) ? effect.failCause(exit.cause) : effect.void
|
|
@@ -422,6 +427,12 @@ const awaitEntry = <A, E>(
|
|
|
422
427
|
})
|
|
423
428
|
}
|
|
424
429
|
|
|
430
|
+
const removeEntry = <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key, entry: Entry<A, E>): void => {
|
|
431
|
+
if (self.state._tag !== "Open") return
|
|
432
|
+
const current = MutableHashMap.get(self.state.map, key)
|
|
433
|
+
if (Option.isSome(current) && current.value === entry) MutableHashMap.remove(self.state.map, key)
|
|
434
|
+
}
|
|
435
|
+
|
|
425
436
|
const hasExpired = <A, E>(entry: Entry<A, E>, fiber: Fiber.Fiber<unknown, unknown>): boolean => {
|
|
426
437
|
if (entry.expiresAt === undefined) {
|
|
427
438
|
return false
|
|
@@ -518,7 +529,7 @@ export const getOption: {
|
|
|
518
529
|
core.withFiber((fiber) =>
|
|
519
530
|
effect.flatMap(
|
|
520
531
|
getImpl(self, key, fiber),
|
|
521
|
-
(entry) => entry ? effect.asSome(awaitEntry(entry, restore)) : effect.succeedNone
|
|
532
|
+
(entry) => entry ? effect.asSome(awaitEntry(self, key, entry, restore)) : effect.succeedNone
|
|
522
533
|
)
|
|
523
534
|
)
|
|
524
535
|
)
|
|
@@ -1004,7 +1015,7 @@ export const invalidateWhen: {
|
|
|
1004
1015
|
if (entry === undefined) {
|
|
1005
1016
|
return effect.succeed(false)
|
|
1006
1017
|
}
|
|
1007
|
-
return awaitEntry(entry, restore).pipe(
|
|
1018
|
+
return awaitEntry(self, key, entry, restore).pipe(
|
|
1008
1019
|
effect.flatMap((value) => {
|
|
1009
1020
|
if (self.state._tag === "Closed") {
|
|
1010
1021
|
return effect.succeed(false)
|