effect 4.0.0-beta.104 → 4.0.0-beta.106
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/AGENTS.md +381 -0
- package/CLAUDE.md +381 -0
- package/ai-docs/README.md +44 -0
- package/ai-docs/package.json +36 -0
- package/ai-docs/src/01_effect/01_basics/01_effect-gen.ts +30 -0
- package/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +39 -0
- package/ai-docs/src/01_effect/01_basics/10_creating-effects.ts +74 -0
- package/ai-docs/src/01_effect/01_basics/index.md +5 -0
- package/ai-docs/src/01_effect/02_schema/10_schema-basics.ts +43 -0
- package/ai-docs/src/01_effect/02_schema/index.md +7 -0
- package/ai-docs/src/01_effect/03_services/01_service.ts +45 -0
- package/ai-docs/src/01_effect/03_services/10_reference.ts +10 -0
- package/ai-docs/src/01_effect/03_services/20_layer-composition.ts +70 -0
- package/ai-docs/src/01_effect/03_services/20_layer-unwrap.ts +66 -0
- package/ai-docs/src/01_effect/03_services/index.md +5 -0
- package/ai-docs/src/01_effect/04_errors/01_error-handling.ts +30 -0
- package/ai-docs/src/01_effect/04_errors/10_catch-tags.ts +24 -0
- package/ai-docs/src/01_effect/04_errors/20_reason-errors.ts +64 -0
- package/ai-docs/src/01_effect/04_errors/index.md +1 -0
- package/ai-docs/src/01_effect/05_resources/10_acquire-release.ts +105 -0
- package/ai-docs/src/01_effect/05_resources/20_layer-side-effects.ts +31 -0
- package/ai-docs/src/01_effect/05_resources/30_layer-map.ts +86 -0
- package/ai-docs/src/01_effect/05_resources/index.md +3 -0
- package/ai-docs/src/01_effect/06_running/10_run-main.ts +30 -0
- package/ai-docs/src/01_effect/06_running/20_layer-launch.ts +27 -0
- package/ai-docs/src/01_effect/06_running/index.md +1 -0
- package/ai-docs/src/01_effect/07_pubsub/10_pubsub.ts +56 -0
- package/ai-docs/src/01_effect/07_pubsub/index.md +3 -0
- package/ai-docs/src/03_stream/10_creating-streams.ts +103 -0
- package/ai-docs/src/03_stream/20_consuming-streams.ts +137 -0
- package/ai-docs/src/03_stream/30_encoding.ts +165 -0
- package/ai-docs/src/03_stream/index.md +4 -0
- package/ai-docs/src/04_integration/10_managed-runtime.ts +129 -0
- package/ai-docs/src/04_integration/index.md +5 -0
- package/ai-docs/src/05_batching/10_request-resolver.ts +89 -0
- package/ai-docs/src/05_batching/index.md +3 -0
- package/ai-docs/src/06_schedule/10_schedules.ts +110 -0
- package/ai-docs/src/06_schedule/index.md +3 -0
- package/ai-docs/src/07_datetime/10_creating-and-formatting.ts +30 -0
- package/ai-docs/src/07_datetime/20_time-zones.ts +44 -0
- package/ai-docs/src/07_datetime/index.md +5 -0
- package/ai-docs/src/08_observability/10_logging.ts +66 -0
- package/ai-docs/src/08_observability/20_otlp-tracing.ts +95 -0
- package/ai-docs/src/08_observability/index.md +7 -0
- package/ai-docs/src/09_testing/10_effect-tests.ts +55 -0
- package/ai-docs/src/09_testing/20_layer-tests.ts +138 -0
- package/ai-docs/src/09_testing/index.md +1 -0
- package/ai-docs/src/10_predicate/01_basics.ts +14 -0
- package/ai-docs/src/10_predicate/index.md +9 -0
- package/ai-docs/src/50_http-client/10_basics.ts +102 -0
- package/ai-docs/src/50_http-client/index.md +3 -0
- package/ai-docs/src/51_http-server/10_basics.ts +116 -0
- package/ai-docs/src/51_http-server/fixtures/api/Api.ts +14 -0
- package/ai-docs/src/51_http-server/fixtures/api/Authorization.ts +36 -0
- package/ai-docs/src/51_http-server/fixtures/api/System.ts +10 -0
- package/ai-docs/src/51_http-server/fixtures/api/Users.ts +91 -0
- package/ai-docs/src/51_http-server/fixtures/domain/User.ts +12 -0
- package/ai-docs/src/51_http-server/fixtures/domain/UserErrors.ts +22 -0
- package/ai-docs/src/51_http-server/fixtures/server/Authorization.ts +36 -0
- package/ai-docs/src/51_http-server/fixtures/server/Users/http.ts +71 -0
- package/ai-docs/src/51_http-server/fixtures/server/Users.ts +62 -0
- package/ai-docs/src/51_http-server/index.md +3 -0
- package/ai-docs/src/60_child-process/10_working-with-child-processes.ts +117 -0
- package/ai-docs/src/60_child-process/index.md +3 -0
- package/ai-docs/src/70_cli/10_basics.ts +136 -0
- package/ai-docs/src/70_cli/index.md +5 -0
- package/ai-docs/src/71_ai/10_language-model.ts +156 -0
- package/ai-docs/src/71_ai/20_tools.ts +226 -0
- package/ai-docs/src/71_ai/30_chat.ts +158 -0
- package/ai-docs/src/71_ai/fixtures/domain/LaunchPlan.ts +9 -0
- package/ai-docs/src/71_ai/index.md +5 -0
- package/ai-docs/src/80_cluster/10_entities.ts +97 -0
- package/ai-docs/src/80_cluster/index.md +4 -0
- package/ai-docs/src/index.md +10 -0
- package/ai-docs/tsconfig.json +24 -0
- package/dist/Brand.d.ts +3 -3
- package/dist/Brand.d.ts.map +1 -1
- package/dist/Brand.js +4 -3
- package/dist/Brand.js.map +1 -1
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js +5 -4
- package/dist/Config.js.map +1 -1
- package/dist/ConfigProvider.d.ts +35 -3
- package/dist/ConfigProvider.d.ts.map +1 -1
- package/dist/ConfigProvider.js +41 -8
- package/dist/ConfigProvider.js.map +1 -1
- package/dist/Context.d.ts +0 -1
- package/dist/Context.d.ts.map +1 -1
- package/dist/Context.js +1 -22
- package/dist/Context.js.map +1 -1
- package/dist/Cron.d.ts +31 -0
- package/dist/Cron.d.ts.map +1 -1
- package/dist/Cron.js +58 -2
- package/dist/Cron.js.map +1 -1
- package/dist/Fiber.d.ts +1 -1
- package/dist/Fiber.d.ts.map +1 -1
- package/dist/Function.d.ts +26 -0
- package/dist/Function.d.ts.map +1 -1
- package/dist/Function.js +36 -0
- package/dist/Function.js.map +1 -1
- package/dist/JsonSchema.d.ts.map +1 -1
- package/dist/JsonSchema.js +34 -17
- package/dist/JsonSchema.js.map +1 -1
- package/dist/Optic.d.ts +35 -21
- package/dist/Optic.d.ts.map +1 -1
- package/dist/Optic.js +33 -34
- package/dist/Optic.js.map +1 -1
- package/dist/Schema.d.ts +105 -109
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +141 -104
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaAST.d.ts +32 -17
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js +79 -60
- package/dist/SchemaAST.js.map +1 -1
- package/dist/SchemaError.d.ts +8 -8
- package/dist/SchemaError.d.ts.map +1 -1
- package/dist/SchemaError.js +7 -6
- package/dist/SchemaError.js.map +1 -1
- package/dist/SchemaGetter.d.ts +8 -5
- package/dist/SchemaGetter.d.ts.map +1 -1
- package/dist/SchemaGetter.js +41 -37
- package/dist/SchemaGetter.js.map +1 -1
- package/dist/SchemaIssue.d.ts +195 -38
- package/dist/SchemaIssue.d.ts.map +1 -1
- package/dist/SchemaIssue.js +243 -68
- package/dist/SchemaIssue.js.map +1 -1
- package/dist/SchemaParser.d.ts +30 -0
- package/dist/SchemaParser.d.ts.map +1 -1
- package/dist/SchemaParser.js +39 -9
- package/dist/SchemaParser.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +15 -3
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +8 -2
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +2 -2
- package/dist/SchemaTransformation.d.ts.map +1 -1
- package/dist/SchemaTransformation.js +26 -26
- package/dist/SchemaTransformation.js.map +1 -1
- package/dist/ScopedRef.d.ts.map +1 -1
- package/dist/ScopedRef.js +1 -1
- package/dist/ScopedRef.js.map +1 -1
- package/dist/Stdio.d.ts +17 -4
- package/dist/Stdio.d.ts.map +1 -1
- package/dist/Stdio.js +6 -3
- package/dist/Stdio.js.map +1 -1
- package/dist/TxQueue.js +1 -1
- package/dist/TxQueue.js.map +1 -1
- package/dist/internal/effect.js +2 -4
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/executionPlan.js +3 -2
- package/dist/internal/executionPlan.js.map +1 -1
- package/dist/internal/rcRef.js +18 -13
- package/dist/internal/rcRef.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +10 -6
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/internal/schema/schema.js +1 -9
- package/dist/internal/schema/schema.js.map +1 -1
- package/dist/internal/schema/toArbitrary.d.ts +1 -4
- package/dist/internal/schema/toArbitrary.d.ts.map +1 -1
- package/dist/internal/schema/toArbitrary.js +0 -74
- package/dist/internal/schema/toArbitrary.js.map +1 -1
- package/dist/internal/schema/toJsonSchemaDocument.js +18 -4
- package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
- package/dist/internal/schema/toRepresentation.js +45 -43
- package/dist/internal/schema/toRepresentation.js.map +1 -1
- package/dist/testing/TestSchema.d.ts +1 -1
- package/dist/testing/TestSchema.d.ts.map +1 -1
- package/dist/testing/TestSchema.js +10 -9
- package/dist/testing/TestSchema.js.map +1 -1
- package/dist/unstable/ai/McpSchema.d.ts +110 -110
- package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +23 -11
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/ai/Prompt.d.ts +4 -3
- package/dist/unstable/ai/Prompt.d.ts.map +1 -1
- package/dist/unstable/ai/Prompt.js +42 -17
- package/dist/unstable/ai/Prompt.js.map +1 -1
- package/dist/unstable/cluster/Entity.d.ts +2 -2
- package/dist/unstable/cluster/Entity.d.ts.map +1 -1
- package/dist/unstable/cluster/Entity.js.map +1 -1
- package/dist/unstable/cluster/EntityProxy.d.ts +3 -3
- package/dist/unstable/cluster/EntityProxy.d.ts.map +1 -1
- package/dist/unstable/cluster/EntityProxy.js +4 -3
- package/dist/unstable/cluster/EntityProxy.js.map +1 -1
- package/dist/unstable/cluster/Reply.js +4 -4
- package/dist/unstable/cluster/Reply.js.map +1 -1
- package/dist/unstable/cluster/Sharding.d.ts +2 -2
- package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
- package/dist/unstable/cluster/Sharding.js +14 -5
- package/dist/unstable/cluster/Sharding.js.map +1 -1
- package/dist/unstable/encoding/Msgpack.d.ts.map +1 -1
- package/dist/unstable/encoding/Msgpack.js +6 -6
- package/dist/unstable/encoding/Msgpack.js.map +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.d.ts +6 -5
- package/dist/unstable/eventlog/EventLogEncryption.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.js +14 -12
- package/dist/unstable/eventlog/EventLogEncryption.js.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.d.ts +3 -3
- package/dist/unstable/eventlog/EventLogMessage.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.js +2 -3
- package/dist/unstable/eventlog/EventLogMessage.js.map +1 -1
- package/dist/unstable/eventlog/EventLogRemote.js +4 -4
- package/dist/unstable/eventlog/EventLogRemote.js.map +1 -1
- package/dist/unstable/eventlog/EventLogServerEncrypted.js +3 -2
- package/dist/unstable/eventlog/EventLogServerEncrypted.js.map +1 -1
- package/dist/unstable/http/HttpClient.d.ts +59 -3
- package/dist/unstable/http/HttpClient.d.ts.map +1 -1
- package/dist/unstable/http/HttpClient.js +33 -19
- package/dist/unstable/http/HttpClient.js.map +1 -1
- package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerRequest.js +7 -1
- package/dist/unstable/http/HttpServerRequest.js.map +1 -1
- package/dist/unstable/http/MultipartParser/internal/multipart.d.ts.map +1 -1
- package/dist/unstable/http/MultipartParser/internal/multipart.js +18 -6
- package/dist/unstable/http/MultipartParser/internal/multipart.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js +10 -10
- package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiClient.js +9 -9
- package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
- package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/OpenApi.js +1 -1
- package/dist/unstable/httpapi/OpenApi.js.map +1 -1
- package/dist/unstable/reactivity/AsyncResult.d.ts.map +1 -1
- package/dist/unstable/reactivity/AsyncResult.js +4 -4
- package/dist/unstable/reactivity/AsyncResult.js.map +1 -1
- package/dist/unstable/reactivity/Atom.d.ts +26 -11
- package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
- package/dist/unstable/reactivity/Atom.js +9 -22
- package/dist/unstable/reactivity/Atom.js.map +1 -1
- package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcClient.js +8 -1
- package/dist/unstable/rpc/RpcClient.js.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +3 -2
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/dist/unstable/sql/SqlResolver.d.ts.map +1 -1
- package/dist/unstable/sql/SqlResolver.js +20 -16
- package/dist/unstable/sql/SqlResolver.js.map +1 -1
- package/dist/unstable/workers/Worker.d.ts.map +1 -1
- package/dist/unstable/workers/Worker.js +11 -12
- package/dist/unstable/workers/Worker.js.map +1 -1
- package/dist/unstable/workflow/Workflow.d.ts.map +1 -1
- package/dist/unstable/workflow/Workflow.js +2 -2
- package/dist/unstable/workflow/Workflow.js.map +1 -1
- package/package.json +5 -2
- package/src/Brand.ts +4 -4
- package/src/Config.ts +6 -4
- package/src/ConfigProvider.ts +43 -8
- package/src/Context.ts +1 -23
- package/src/Cron.ts +65 -2
- package/src/Fiber.ts +1 -1
- package/src/Function.ts +37 -0
- package/src/JsonSchema.ts +43 -42
- package/src/Optic.ts +59 -58
- package/src/Schema.ts +213 -217
- package/src/SchemaAST.ts +135 -78
- package/src/SchemaError.ts +9 -9
- package/src/SchemaGetter.ts +89 -30
- package/src/SchemaIssue.ts +285 -80
- package/src/SchemaParser.ts +51 -17
- package/src/SchemaRepresentation.ts +15 -3
- package/src/SchemaTransformation.ts +66 -18
- package/src/ScopedRef.ts +3 -1
- package/src/Stdio.ts +23 -4
- package/src/TxQueue.ts +1 -1
- package/src/internal/effect.ts +3 -6
- package/src/internal/executionPlan.ts +3 -2
- package/src/internal/rcRef.ts +24 -16
- package/src/internal/schema/fromJsonSchemaDocument.ts +19 -14
- package/src/internal/schema/schema.ts +1 -17
- package/src/internal/schema/toArbitrary.ts +0 -72
- package/src/internal/schema/toJsonSchemaDocument.ts +24 -4
- package/src/internal/schema/toRepresentation.ts +66 -48
- package/src/testing/TestSchema.ts +10 -10
- package/src/unstable/ai/McpServer.ts +23 -11
- package/src/unstable/ai/Prompt.ts +51 -19
- package/src/unstable/cluster/Entity.ts +7 -2
- package/src/unstable/cluster/EntityProxy.ts +12 -5
- package/src/unstable/cluster/Reply.ts +4 -4
- package/src/unstable/cluster/Sharding.ts +29 -17
- package/src/unstable/encoding/Msgpack.ts +12 -8
- package/src/unstable/eventlog/EventLogEncryption.ts +15 -16
- package/src/unstable/eventlog/EventLogMessage.ts +2 -3
- package/src/unstable/eventlog/EventLogRemote.ts +4 -4
- package/src/unstable/eventlog/EventLogServerEncrypted.ts +2 -2
- package/src/unstable/http/HttpClient.ts +132 -23
- package/src/unstable/http/HttpServerRequest.ts +8 -3
- package/src/unstable/http/MultipartParser/internal/multipart.ts +19 -6
- package/src/unstable/httpapi/HttpApiBuilder.ts +32 -13
- package/src/unstable/httpapi/HttpApiClient.ts +26 -8
- package/src/unstable/httpapi/OpenApi.ts +4 -1
- package/src/unstable/reactivity/AsyncResult.ts +11 -6
- package/src/unstable/reactivity/Atom.ts +44 -25
- package/src/unstable/rpc/RpcClient.ts +9 -1
- package/src/unstable/rpc/RpcServer.ts +4 -2
- package/src/unstable/sql/SqlResolver.ts +28 -20
- package/src/unstable/workers/Worker.ts +13 -14
- package/src/unstable/workflow/Workflow.ts +2 -5
package/src/SchemaIssue.ts
CHANGED
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import type { StandardSchemaV1 } from "@standard-schema/spec"
|
|
13
13
|
import * as Arr from "./Array.ts"
|
|
14
|
-
import { formatPath, type Formatter as FormatterI } from "./Formatter.ts"
|
|
14
|
+
import { format, formatPath, type Formatter as FormatterI } from "./Formatter.ts"
|
|
15
15
|
import * as InternalAnnotations from "./internal/schema/annotations.ts"
|
|
16
|
+
import * as InternalParser from "./internal/schema/parser.ts"
|
|
16
17
|
import { hasProperty } from "./Predicate.ts"
|
|
17
18
|
import type * as Schema from "./Schema.ts"
|
|
18
19
|
import type * as SchemaAST from "./SchemaAST.ts"
|
|
@@ -51,6 +52,39 @@ export function isIssue(u: unknown): u is Issue {
|
|
|
51
52
|
return hasProperty(u, TypeId) && u[TypeId] === TypeId
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Returns `true` when an issue contains an input reported by the schema parser.
|
|
57
|
+
*
|
|
58
|
+
* **When to use**
|
|
59
|
+
*
|
|
60
|
+
* Use when reading `Issue.input`, especially when `undefined` is a valid input
|
|
61
|
+
* value.
|
|
62
|
+
*
|
|
63
|
+
* **Details**
|
|
64
|
+
*
|
|
65
|
+
* Reported input is stored as an own property. This guard checks for that
|
|
66
|
+
* property and narrows `input` from optional to required.
|
|
67
|
+
*
|
|
68
|
+
* **Example** (Reading a reported input)
|
|
69
|
+
*
|
|
70
|
+
* ```ts import.meta.vitest
|
|
71
|
+
* import { Result, Schema, SchemaIssue } from "effect"
|
|
72
|
+
*
|
|
73
|
+
* const result = Schema.decodeUnknownResult(Schema.String)(1, { reportInput: true })
|
|
74
|
+
* if (Result.isFailure(result) && SchemaIssue.hasInput(result.failure.issue)) {
|
|
75
|
+
* result.failure.issue.input // => 1
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @see {@link Issue} for the complete issue model
|
|
80
|
+
*
|
|
81
|
+
* @category guards
|
|
82
|
+
* @since 4.0.0
|
|
83
|
+
*/
|
|
84
|
+
export function hasInput(issue: Issue): issue is Issue & { readonly input: unknown } {
|
|
85
|
+
return Object.hasOwn(issue, "input")
|
|
86
|
+
}
|
|
87
|
+
|
|
54
88
|
/**
|
|
55
89
|
* Union of all terminal (leaf) issue types that have no inner `Issue` children.
|
|
56
90
|
*
|
|
@@ -91,15 +125,17 @@ export type Leaf =
|
|
|
91
125
|
* Every node has a `_tag` field for pattern-matching. The union includes both
|
|
92
126
|
* terminal {@link Leaf} types and composite types that wrap inner issues:
|
|
93
127
|
* {@link Filter}, {@link Encoding}, {@link Pointer}, {@link Composite},
|
|
94
|
-
* {@link AnyOf}.
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* supplied and remain the
|
|
128
|
+
* {@link AnyOf}. Use {@link makeFormatterDefault} when a human-readable
|
|
129
|
+
* representation is needed. When parsing with `reportInput: true`,
|
|
130
|
+
* value-bearing issues expose the rejected value through an enumerable `input`
|
|
131
|
+
* field. Built-in formatters may include reported input in default messages. This
|
|
132
|
+
* is not a general sanitization boundary: paths, ASTs, union successes, and
|
|
133
|
+
* custom annotations or messages are preserved as supplied and remain the
|
|
134
|
+
* caller's responsibility.
|
|
100
135
|
*
|
|
101
136
|
* @see {@link Leaf} — the terminal subset
|
|
102
137
|
* @see {@link isIssue} — type guard
|
|
138
|
+
* @see {@link hasInput} — checks whether an issue reports an input
|
|
103
139
|
* @category models
|
|
104
140
|
* @since 4.0.0
|
|
105
141
|
*/
|
|
@@ -114,8 +150,15 @@ export type Issue =
|
|
|
114
150
|
|
|
115
151
|
class Base {
|
|
116
152
|
readonly [TypeId] = TypeId
|
|
117
|
-
|
|
118
|
-
|
|
153
|
+
/**
|
|
154
|
+
* The input reported by the schema parser, when input reporting is enabled
|
|
155
|
+
* and the issue is associated with a present value.
|
|
156
|
+
*/
|
|
157
|
+
declare readonly input?: unknown
|
|
158
|
+
constructor(input?: unknown, options?: SchemaAST.ParseOptions) {
|
|
159
|
+
if (options?.reportInput === true && input !== InternalParser.missing) {
|
|
160
|
+
this.input = input
|
|
161
|
+
}
|
|
119
162
|
}
|
|
120
163
|
}
|
|
121
164
|
|
|
@@ -137,11 +180,13 @@ class Base {
|
|
|
137
180
|
* ```ts import.meta.vitest
|
|
138
181
|
* import { SchemaAST, SchemaIssue } from "effect"
|
|
139
182
|
*
|
|
183
|
+
* const formatIssue = SchemaIssue.makeFormatterDefault()
|
|
184
|
+
*
|
|
140
185
|
* function describe(issue: SchemaIssue.Issue): string {
|
|
141
186
|
* if (issue._tag === "Filter") {
|
|
142
|
-
* return `Filter failed: ${
|
|
187
|
+
* return `Filter failed: ${formatIssue(issue.issue)}`
|
|
143
188
|
* }
|
|
144
|
-
* return
|
|
189
|
+
* return formatIssue(issue)
|
|
145
190
|
* }
|
|
146
191
|
*
|
|
147
192
|
* const issue = new SchemaIssue.Filter(
|
|
@@ -176,9 +221,18 @@ export class Filter extends Base {
|
|
|
176
221
|
/**
|
|
177
222
|
* The issue that occurred.
|
|
178
223
|
*/
|
|
179
|
-
issue: Issue
|
|
224
|
+
issue: Issue,
|
|
225
|
+
/**
|
|
226
|
+
* The present input associated with the issue. It is retained only when
|
|
227
|
+
* `options.reportInput` is `true`.
|
|
228
|
+
*/
|
|
229
|
+
input?: unknown,
|
|
230
|
+
/**
|
|
231
|
+
* The effective parse options controlling input retention.
|
|
232
|
+
*/
|
|
233
|
+
options?: SchemaAST.ParseOptions
|
|
180
234
|
) {
|
|
181
|
-
super()
|
|
235
|
+
super(input, options)
|
|
182
236
|
this.filter = filter
|
|
183
237
|
this.issue = issue
|
|
184
238
|
}
|
|
@@ -222,9 +276,18 @@ export class Encoding extends Base {
|
|
|
222
276
|
/**
|
|
223
277
|
* The issue that occurred.
|
|
224
278
|
*/
|
|
225
|
-
issue: Issue
|
|
279
|
+
issue: Issue,
|
|
280
|
+
/**
|
|
281
|
+
* The present input associated with the issue. It is retained only when
|
|
282
|
+
* `options.reportInput` is `true`.
|
|
283
|
+
*/
|
|
284
|
+
input?: unknown,
|
|
285
|
+
/**
|
|
286
|
+
* The effective parse options controlling input retention.
|
|
287
|
+
*/
|
|
288
|
+
options?: SchemaAST.ParseOptions
|
|
226
289
|
) {
|
|
227
|
-
super()
|
|
290
|
+
super(input, options)
|
|
228
291
|
this.ast = ast
|
|
229
292
|
this.issue = issue
|
|
230
293
|
}
|
|
@@ -325,7 +388,8 @@ export class MissingKey extends Base {
|
|
|
325
388
|
*
|
|
326
389
|
* - `ast` is the schema that was being validated against.
|
|
327
390
|
* - `annotations` on `ast` may contain a custom `messageUnexpectedKey`.
|
|
328
|
-
* - The default formatter renders this as `"Expected no excess property"
|
|
391
|
+
* - The default formatter renders this as `"Expected no excess property"`, or
|
|
392
|
+
* `"Unexpected key with value <input>"` when the issue reports an input.
|
|
329
393
|
*
|
|
330
394
|
* @see {@link MissingKey} — the opposite case (required key absent)
|
|
331
395
|
* @see {@link Pointer} — wraps this issue with the unexpected key's path
|
|
@@ -343,9 +407,18 @@ export class UnexpectedKey extends Base {
|
|
|
343
407
|
/**
|
|
344
408
|
* The schema that caused the issue.
|
|
345
409
|
*/
|
|
346
|
-
ast: SchemaAST.AST
|
|
410
|
+
ast: SchemaAST.AST,
|
|
411
|
+
/**
|
|
412
|
+
* The present input associated with the issue. It is retained only when
|
|
413
|
+
* `options.reportInput` is `true`.
|
|
414
|
+
*/
|
|
415
|
+
input?: unknown,
|
|
416
|
+
/**
|
|
417
|
+
* The effective parse options controlling input retention.
|
|
418
|
+
*/
|
|
419
|
+
options?: SchemaAST.ParseOptions
|
|
347
420
|
) {
|
|
348
|
-
super()
|
|
421
|
+
super(input, options)
|
|
349
422
|
this.ast = ast
|
|
350
423
|
}
|
|
351
424
|
}
|
|
@@ -388,9 +461,18 @@ export class Composite extends Base {
|
|
|
388
461
|
/**
|
|
389
462
|
* The issues that occurred.
|
|
390
463
|
*/
|
|
391
|
-
issues: readonly [Issue, ...Array<Issue>]
|
|
464
|
+
issues: readonly [Issue, ...Array<Issue>],
|
|
465
|
+
/**
|
|
466
|
+
* The present input associated with the issue. It is retained only when
|
|
467
|
+
* `options.reportInput` is `true`.
|
|
468
|
+
*/
|
|
469
|
+
input?: unknown,
|
|
470
|
+
/**
|
|
471
|
+
* The effective parse options controlling input retention.
|
|
472
|
+
*/
|
|
473
|
+
options?: SchemaAST.ParseOptions
|
|
392
474
|
) {
|
|
393
|
-
super()
|
|
475
|
+
super(input, options)
|
|
394
476
|
this.ast = ast
|
|
395
477
|
this.issues = issues
|
|
396
478
|
}
|
|
@@ -408,15 +490,17 @@ export class Composite extends Base {
|
|
|
408
490
|
* **Details**
|
|
409
491
|
*
|
|
410
492
|
* - `ast` is the schema node that expected a different type.
|
|
411
|
-
* - The default formatter renders this as `"Expected <type>"
|
|
493
|
+
* - The default formatter renders this as `"Expected <type>"`, adding
|
|
494
|
+
* `", got <input>"` when the issue reports an input.
|
|
412
495
|
*
|
|
413
496
|
* **Example** (Formatting a type mismatch)
|
|
414
497
|
*
|
|
415
498
|
* ```ts import.meta.vitest
|
|
416
499
|
* import { Schema, SchemaIssue } from "effect"
|
|
417
500
|
*
|
|
501
|
+
* const formatIssue = SchemaIssue.makeFormatterDefault()
|
|
418
502
|
* const issue = new SchemaIssue.InvalidType(Schema.String.ast)
|
|
419
|
-
*
|
|
503
|
+
* formatIssue(issue) // => "Expected string"
|
|
420
504
|
* ```
|
|
421
505
|
*
|
|
422
506
|
* @see {@link InvalidValue} — the input has the right type but fails a value constraint
|
|
@@ -434,9 +518,18 @@ export class InvalidType extends Base {
|
|
|
434
518
|
/**
|
|
435
519
|
* The schema that caused the issue.
|
|
436
520
|
*/
|
|
437
|
-
ast: SchemaAST.AST
|
|
521
|
+
ast: SchemaAST.AST,
|
|
522
|
+
/**
|
|
523
|
+
* The present input associated with the issue. It is retained only when
|
|
524
|
+
* `options.reportInput` is `true`.
|
|
525
|
+
*/
|
|
526
|
+
input?: unknown,
|
|
527
|
+
/**
|
|
528
|
+
* The effective parse options controlling input retention.
|
|
529
|
+
*/
|
|
530
|
+
options?: SchemaAST.ParseOptions
|
|
438
531
|
) {
|
|
439
|
-
super()
|
|
532
|
+
super(input, options)
|
|
440
533
|
this.ast = ast
|
|
441
534
|
}
|
|
442
535
|
}
|
|
@@ -452,17 +545,22 @@ export class InvalidType extends Base {
|
|
|
452
545
|
*
|
|
453
546
|
* **Details**
|
|
454
547
|
*
|
|
455
|
-
* - `
|
|
456
|
-
*
|
|
457
|
-
*
|
|
548
|
+
* - A `message` annotation is returned unchanged and takes precedence over all
|
|
549
|
+
* other default formatting.
|
|
550
|
+
* - Without `message`, an `expected` annotation is formatted as
|
|
551
|
+
* `"Expected <expected>"`, adding `", got <input>"` when input is reported.
|
|
552
|
+
* - Without either annotation, the default formatter renders
|
|
553
|
+
* `"Expected a valid value"`, or `"Invalid data <input>"` when input is
|
|
554
|
+
* reported.
|
|
458
555
|
*
|
|
459
556
|
* **Example** (Returning InvalidValue from a custom filter)
|
|
460
557
|
*
|
|
461
558
|
* ```ts import.meta.vitest
|
|
462
559
|
* import { SchemaIssue } from "effect"
|
|
463
560
|
*
|
|
561
|
+
* const formatIssue = SchemaIssue.makeFormatterDefault()
|
|
464
562
|
* const issue = new SchemaIssue.InvalidValue({ message: "must not be empty" })
|
|
465
|
-
*
|
|
563
|
+
* formatIssue(issue) // => "must not be empty"
|
|
466
564
|
* ```
|
|
467
565
|
*
|
|
468
566
|
* @see {@link InvalidType} — the input has the wrong type entirely
|
|
@@ -479,13 +577,41 @@ export class InvalidValue extends Base {
|
|
|
479
577
|
readonly annotations: Schema.Annotations.Issue | undefined
|
|
480
578
|
|
|
481
579
|
constructor(
|
|
482
|
-
|
|
580
|
+
/**
|
|
581
|
+
* The metadata for the issue.
|
|
582
|
+
*/
|
|
583
|
+
annotations?: Schema.Annotations.Issue | undefined,
|
|
584
|
+
/**
|
|
585
|
+
* The present input associated with the issue. It is retained only when
|
|
586
|
+
* `options.reportInput` is `true`.
|
|
587
|
+
*/
|
|
588
|
+
input?: unknown,
|
|
589
|
+
/**
|
|
590
|
+
* The effective parse options controlling input retention.
|
|
591
|
+
*/
|
|
592
|
+
options?: SchemaAST.ParseOptions
|
|
483
593
|
) {
|
|
484
|
-
super()
|
|
594
|
+
super(input, options)
|
|
485
595
|
this.annotations = annotations
|
|
486
596
|
}
|
|
487
597
|
}
|
|
488
598
|
|
|
599
|
+
/** @internal */
|
|
600
|
+
export function makeCompositeAtKey(
|
|
601
|
+
compositeAst: SchemaAST.AST,
|
|
602
|
+
pointerKey: PropertyKey,
|
|
603
|
+
pointerIssue: Issue,
|
|
604
|
+
compositeInput: unknown,
|
|
605
|
+
parseOptions?: SchemaAST.ParseOptions
|
|
606
|
+
): Composite {
|
|
607
|
+
return new Composite(
|
|
608
|
+
compositeAst,
|
|
609
|
+
[new Pointer([pointerKey], pointerIssue)],
|
|
610
|
+
compositeInput,
|
|
611
|
+
parseOptions
|
|
612
|
+
)
|
|
613
|
+
}
|
|
614
|
+
|
|
489
615
|
/**
|
|
490
616
|
* Represents a schema issue produced when a forbidden operation is encountered during parsing,
|
|
491
617
|
* such as an asynchronous Effect running inside `Schema.decodeUnknownSync`.
|
|
@@ -505,10 +631,11 @@ export class InvalidValue extends Base {
|
|
|
505
631
|
* ```ts import.meta.vitest
|
|
506
632
|
* import { SchemaIssue } from "effect"
|
|
507
633
|
*
|
|
634
|
+
* const formatIssue = SchemaIssue.makeFormatterDefault()
|
|
508
635
|
* const issue = new SchemaIssue.Forbidden(
|
|
509
636
|
* { message: "async operation not allowed in sync context" }
|
|
510
637
|
* )
|
|
511
|
-
*
|
|
638
|
+
* formatIssue(issue) // => "async operation not allowed in sync context"
|
|
512
639
|
* ```
|
|
513
640
|
*
|
|
514
641
|
* @see {@link InvalidValue} — for value-constraint failures (not operation failures)
|
|
@@ -527,9 +654,18 @@ export class Forbidden extends Base {
|
|
|
527
654
|
/**
|
|
528
655
|
* The metadata for the issue.
|
|
529
656
|
*/
|
|
530
|
-
annotations: Schema.Annotations.Issue | undefined
|
|
657
|
+
annotations: Schema.Annotations.Issue | undefined,
|
|
658
|
+
/**
|
|
659
|
+
* The present input associated with the issue. It is retained only when
|
|
660
|
+
* `options.reportInput` is `true`.
|
|
661
|
+
*/
|
|
662
|
+
input?: unknown,
|
|
663
|
+
/**
|
|
664
|
+
* The effective parse options controlling input retention.
|
|
665
|
+
*/
|
|
666
|
+
options?: SchemaAST.ParseOptions
|
|
531
667
|
) {
|
|
532
|
-
super()
|
|
668
|
+
super(input, options)
|
|
533
669
|
this.annotations = annotations
|
|
534
670
|
}
|
|
535
671
|
}
|
|
@@ -550,7 +686,8 @@ export class Forbidden extends Base {
|
|
|
550
686
|
* **Gotchas**
|
|
551
687
|
*
|
|
552
688
|
* `issues` is empty when no union member was applicable. In that case, the
|
|
553
|
-
* default formatter reports the expected type for the union
|
|
689
|
+
* default formatter reports the expected type for the union and appends
|
|
690
|
+
* `", got <input>"` when input is reported.
|
|
554
691
|
*
|
|
555
692
|
* @see {@link OneOf} — the opposite: *too many* members matched
|
|
556
693
|
* @see {@link Composite} — groups multiple issues under a non-union schema
|
|
@@ -577,9 +714,18 @@ export class AnyOf extends Base {
|
|
|
577
714
|
/**
|
|
578
715
|
* The issues that occurred.
|
|
579
716
|
*/
|
|
580
|
-
issues: ReadonlyArray<Issue
|
|
717
|
+
issues: ReadonlyArray<Issue>,
|
|
718
|
+
/**
|
|
719
|
+
* The present input associated with the issue. It is retained only when
|
|
720
|
+
* `options.reportInput` is `true`.
|
|
721
|
+
*/
|
|
722
|
+
input?: unknown,
|
|
723
|
+
/**
|
|
724
|
+
* The effective parse options controlling input retention.
|
|
725
|
+
*/
|
|
726
|
+
options?: SchemaAST.ParseOptions
|
|
581
727
|
) {
|
|
582
|
-
super()
|
|
728
|
+
super(input, options)
|
|
583
729
|
this.ast = ast
|
|
584
730
|
this.issues = issues
|
|
585
731
|
}
|
|
@@ -599,7 +745,9 @@ export class AnyOf extends Base {
|
|
|
599
745
|
* - `ast` is the `Union` AST node.
|
|
600
746
|
* - `successes` lists the AST nodes of each member that accepted the input.
|
|
601
747
|
* - The default formatter renders this as
|
|
602
|
-
* `"Expected exactly one member to match"
|
|
748
|
+
* `"Expected exactly one member to match"`, or
|
|
749
|
+
* `"Expected exactly one member to match the input <input>"` when input is
|
|
750
|
+
* reported.
|
|
603
751
|
*
|
|
604
752
|
* @see {@link AnyOf} — the opposite: *no* members matched
|
|
605
753
|
*
|
|
@@ -625,52 +773,71 @@ export class OneOf extends Base {
|
|
|
625
773
|
/**
|
|
626
774
|
* The schemas that were successful.
|
|
627
775
|
*/
|
|
628
|
-
successes: ReadonlyArray<SchemaAST.AST
|
|
776
|
+
successes: ReadonlyArray<SchemaAST.AST>,
|
|
777
|
+
/**
|
|
778
|
+
* The present input associated with the issue. It is retained only when
|
|
779
|
+
* `options.reportInput` is `true`.
|
|
780
|
+
*/
|
|
781
|
+
input?: unknown,
|
|
782
|
+
/**
|
|
783
|
+
* The effective parse options controlling input retention.
|
|
784
|
+
*/
|
|
785
|
+
options?: SchemaAST.ParseOptions
|
|
629
786
|
) {
|
|
630
|
-
super()
|
|
787
|
+
super(input, options)
|
|
631
788
|
this.ast = ast
|
|
632
789
|
this.successes = successes
|
|
633
790
|
}
|
|
634
791
|
}
|
|
635
792
|
|
|
636
|
-
function makeFilterIssue(
|
|
793
|
+
function makeFilterIssue(
|
|
794
|
+
entry: Schema.FilterIssue,
|
|
795
|
+
input?: unknown,
|
|
796
|
+
options?: SchemaAST.ParseOptions
|
|
797
|
+
): Issue {
|
|
637
798
|
if (isIssue(entry)) {
|
|
638
799
|
return entry
|
|
639
800
|
}
|
|
640
801
|
if (typeof entry === "string") {
|
|
641
|
-
return new InvalidValue({ message: entry })
|
|
802
|
+
return new InvalidValue({ message: entry }, input, options)
|
|
642
803
|
}
|
|
643
804
|
const inner = typeof entry.issue === "string"
|
|
644
|
-
? new InvalidValue({ message: entry.issue })
|
|
805
|
+
? new InvalidValue({ message: entry.issue }, input, options)
|
|
645
806
|
: entry.issue
|
|
646
807
|
return new Pointer(entry.path, inner)
|
|
647
808
|
}
|
|
648
809
|
|
|
649
810
|
/** @internal */
|
|
650
|
-
export function makeSingle(
|
|
811
|
+
export function makeSingle(
|
|
812
|
+
out: undefined | boolean | Schema.FilterIssue,
|
|
813
|
+
input?: unknown,
|
|
814
|
+
options?: SchemaAST.ParseOptions
|
|
815
|
+
): Issue | undefined {
|
|
651
816
|
if (out === undefined) {
|
|
652
817
|
return undefined
|
|
653
818
|
}
|
|
654
819
|
if (typeof out === "boolean") {
|
|
655
|
-
return out ? undefined : new InvalidValue()
|
|
820
|
+
return out ? undefined : new InvalidValue(undefined, input, options)
|
|
656
821
|
}
|
|
657
|
-
return makeFilterIssue(out)
|
|
822
|
+
return makeFilterIssue(out, input, options)
|
|
658
823
|
}
|
|
659
824
|
|
|
660
825
|
/** @internal */
|
|
661
826
|
export function normalizeFilterOutput(
|
|
662
827
|
ast: SchemaAST.AST,
|
|
663
|
-
out: Schema.FilterOutput
|
|
828
|
+
out: Schema.FilterOutput,
|
|
829
|
+
input?: unknown,
|
|
830
|
+
options?: SchemaAST.ParseOptions
|
|
664
831
|
): Issue | undefined {
|
|
665
832
|
if (Array.isArray(out)) {
|
|
666
833
|
if (!Arr.isReadonlyArrayNonEmpty(out)) {
|
|
667
834
|
return undefined
|
|
668
835
|
}
|
|
669
836
|
return out.length === 1
|
|
670
|
-
? makeFilterIssue(out[0])
|
|
671
|
-
: new Composite(ast, Arr.map(out, makeFilterIssue))
|
|
837
|
+
? makeFilterIssue(out[0], input, options)
|
|
838
|
+
: new Composite(ast, Arr.map(out, (entry) => makeFilterIssue(entry, input, options)), input, options)
|
|
672
839
|
}
|
|
673
|
-
return makeSingle(out as undefined | boolean | Schema.FilterIssue)
|
|
840
|
+
return makeSingle(out as undefined | boolean | Schema.FilterIssue, input, options)
|
|
674
841
|
}
|
|
675
842
|
|
|
676
843
|
/**
|
|
@@ -712,13 +879,18 @@ export type LeafHook = (issue: Leaf) => string
|
|
|
712
879
|
* **Details**
|
|
713
880
|
*
|
|
714
881
|
* - Checks for a `message` annotation first; returns it if present.
|
|
715
|
-
* -
|
|
716
|
-
*
|
|
717
|
-
*
|
|
882
|
+
* - For `InvalidValue`, an `expected` annotation uses the standard expected
|
|
883
|
+
* value message and includes reported input when available.
|
|
884
|
+
* - Otherwise generates a default message per `_tag`. When the issue reports
|
|
885
|
+
* input, the message includes its formatted value where applicable:
|
|
886
|
+
* - `InvalidType` → `"Expected <type>"` or `"Expected <type>, got <input>"`
|
|
887
|
+
* - `InvalidValue` → `"Expected a valid value"` or `"Invalid data <input>"`
|
|
718
888
|
* - `MissingKey` → `"Missing key"`
|
|
719
|
-
* - `UnexpectedKey` → `"Expected no excess property"`
|
|
889
|
+
* - `UnexpectedKey` → `"Expected no excess property"` or
|
|
890
|
+
* `"Unexpected key with value <input>"`
|
|
720
891
|
* - `Forbidden` → `"Forbidden operation"`
|
|
721
|
-
* - `OneOf` → `"Expected exactly one member to match"`
|
|
892
|
+
* - `OneOf` → `"Expected exactly one member to match"` or
|
|
893
|
+
* `"Expected exactly one member to match the input <input>"`
|
|
722
894
|
*
|
|
723
895
|
* **Example** (Formatting Standard Schema issues with defaultLeafHook)
|
|
724
896
|
*
|
|
@@ -742,17 +914,27 @@ export const defaultLeafHook: LeafHook = (issue): string => {
|
|
|
742
914
|
if (message !== undefined) return message
|
|
743
915
|
switch (issue._tag) {
|
|
744
916
|
case "InvalidType":
|
|
745
|
-
return getExpectedMessage(InternalAnnotations.getExpected(issue.ast))
|
|
746
|
-
case "InvalidValue":
|
|
747
|
-
|
|
917
|
+
return getExpectedMessage(InternalAnnotations.getExpected(issue.ast), issue)
|
|
918
|
+
case "InvalidValue": {
|
|
919
|
+
const expected = findExpected(issue)
|
|
920
|
+
if (expected !== undefined) return getExpectedMessage(expected, issue)
|
|
921
|
+
const input = formatInput(issue)
|
|
922
|
+
return input === undefined ? "Expected a valid value" : `Invalid data ${input}`
|
|
923
|
+
}
|
|
748
924
|
case "MissingKey":
|
|
749
925
|
return "Missing key"
|
|
750
|
-
case "UnexpectedKey":
|
|
751
|
-
|
|
926
|
+
case "UnexpectedKey": {
|
|
927
|
+
const input = formatInput(issue)
|
|
928
|
+
return input === undefined ? "Expected no excess property" : `Unexpected key with value ${input}`
|
|
929
|
+
}
|
|
752
930
|
case "Forbidden":
|
|
753
931
|
return "Forbidden operation"
|
|
754
|
-
case "OneOf":
|
|
755
|
-
|
|
932
|
+
case "OneOf": {
|
|
933
|
+
const input = formatInput(issue)
|
|
934
|
+
return input === undefined
|
|
935
|
+
? "Expected exactly one member to match"
|
|
936
|
+
: `Expected exactly one member to match the input ${input}`
|
|
937
|
+
}
|
|
756
938
|
}
|
|
757
939
|
}
|
|
758
940
|
|
|
@@ -768,8 +950,6 @@ export const defaultLeafHook: LeafHook = (issue): string => {
|
|
|
768
950
|
*
|
|
769
951
|
* - Returns `string` to override the message, or `undefined` to fall back to
|
|
770
952
|
* the default formatting.
|
|
771
|
-
* - Built-in issues have no `actual` field.
|
|
772
|
-
*
|
|
773
953
|
* @see {@link defaultCheckHook} — the built-in implementation
|
|
774
954
|
* @see {@link Filter} — the issue type this hook formats
|
|
775
955
|
*
|
|
@@ -790,7 +970,8 @@ export type CheckHook = (issue: Filter) => string | undefined
|
|
|
790
970
|
* - Looks for a `message` annotation on the inner issue first, then on the
|
|
791
971
|
* filter itself.
|
|
792
972
|
* - Returns `undefined` when no annotation is found, causing the formatter to
|
|
793
|
-
* fall back to `"Expected <filter>"
|
|
973
|
+
* fall back to `"Expected <filter>"` or, when the filter reports input,
|
|
974
|
+
* `"Expected <filter>, got <input>"`.
|
|
794
975
|
*
|
|
795
976
|
* @see {@link CheckHook}
|
|
796
977
|
* @see {@link makeFormatterStandardSchemaV1}
|
|
@@ -798,9 +979,7 @@ export type CheckHook = (issue: Filter) => string | undefined
|
|
|
798
979
|
* @category formatting
|
|
799
980
|
* @since 4.0.0
|
|
800
981
|
*/
|
|
801
|
-
export const defaultCheckHook: CheckHook = (issue): string | undefined =>
|
|
802
|
-
return findMessage(issue.issue) ?? findMessage(issue)
|
|
803
|
-
}
|
|
982
|
+
export const defaultCheckHook: CheckHook = (issue): string | undefined => findMessage(issue.issue) ?? findMessage(issue)
|
|
804
983
|
|
|
805
984
|
/**
|
|
806
985
|
* Creates a {@link Formatter} that produces a `StandardSchemaV1.FailureResult`.
|
|
@@ -818,6 +997,15 @@ export const defaultCheckHook: CheckHook = (issue): string | undefined => {
|
|
|
818
997
|
* - `Pointer` paths are accumulated to produce full property paths.
|
|
819
998
|
* - Falls back to {@link defaultLeafHook} / {@link defaultCheckHook} when no
|
|
820
999
|
* hooks are provided.
|
|
1000
|
+
* - Default messages include reported input when the issue that produces the
|
|
1001
|
+
* message has an `input` field. The returned Standard Schema issues do not
|
|
1002
|
+
* receive an `input` field.
|
|
1003
|
+
*
|
|
1004
|
+
* **Gotchas**
|
|
1005
|
+
*
|
|
1006
|
+
* Reported input can appear inside the Standard Schema `message` string even
|
|
1007
|
+
* though it is not exposed as a separate property. Custom hooks control their
|
|
1008
|
+
* complete message and are not modified.
|
|
821
1009
|
*
|
|
822
1010
|
* **Example** (Creating a Standard Schema V1 formatter)
|
|
823
1011
|
*
|
|
@@ -850,8 +1038,18 @@ type DefaultIssue = {
|
|
|
850
1038
|
readonly path: ReadonlyArray<PropertyKey>
|
|
851
1039
|
}
|
|
852
1040
|
|
|
853
|
-
function
|
|
854
|
-
return
|
|
1041
|
+
function formatInput(issue: Issue): string | undefined {
|
|
1042
|
+
return hasInput(issue) ? format(issue.input) : undefined
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
function findExpected(issue: InvalidValue): string | undefined {
|
|
1046
|
+
const expected = issue.annotations?.expected
|
|
1047
|
+
return typeof expected === "string" ? expected : undefined
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
function getExpectedMessage(expected: string, issue: Issue): string {
|
|
1051
|
+
const input = formatInput(issue)
|
|
1052
|
+
return input === undefined ? `Expected ${expected}` : `Expected ${expected}, got ${input}`
|
|
855
1053
|
}
|
|
856
1054
|
|
|
857
1055
|
function toDefaultIssues(
|
|
@@ -866,15 +1064,16 @@ function toDefaultIssues(
|
|
|
866
1064
|
if (message !== undefined) {
|
|
867
1065
|
return [{ path, message }]
|
|
868
1066
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
return [{
|
|
872
|
-
path,
|
|
873
|
-
message: getExpectedMessage(formatCheck(issue.filter))
|
|
874
|
-
}]
|
|
875
|
-
default:
|
|
876
|
-
return toDefaultIssues(issue.issue, path, leafHook, checkHook)
|
|
1067
|
+
if (issue.issue._tag !== "InvalidValue") {
|
|
1068
|
+
return toDefaultIssues(issue.issue, path, leafHook, checkHook)
|
|
877
1069
|
}
|
|
1070
|
+
const expected = findExpected(issue.issue)
|
|
1071
|
+
return [{
|
|
1072
|
+
path,
|
|
1073
|
+
message: expected === undefined
|
|
1074
|
+
? getExpectedMessage(formatCheck(issue.filter), issue)
|
|
1075
|
+
: getExpectedMessage(expected, issue.issue)
|
|
1076
|
+
}]
|
|
878
1077
|
}
|
|
879
1078
|
case "Encoding":
|
|
880
1079
|
return toDefaultIssues(issue.issue, path, leafHook, checkHook)
|
|
@@ -886,7 +1085,7 @@ function toDefaultIssues(
|
|
|
886
1085
|
if (issue.issues.length === 0) {
|
|
887
1086
|
return [{
|
|
888
1087
|
path,
|
|
889
|
-
message: findMessage(issue) ?? getExpectedMessage(InternalAnnotations.getExpected(issue.ast))
|
|
1088
|
+
message: findMessage(issue) ?? getExpectedMessage(InternalAnnotations.getExpected(issue.ast), issue)
|
|
890
1089
|
}]
|
|
891
1090
|
}
|
|
892
1091
|
return issue.issues.flatMap((issue) => toDefaultIssues(issue, path, leafHook, checkHook))
|
|
@@ -919,13 +1118,19 @@ function formatCheck<T>(check: SchemaAST.Check<T>): string {
|
|
|
919
1118
|
*
|
|
920
1119
|
* **Details**
|
|
921
1120
|
*
|
|
922
|
-
* This is the default formatter used by `SchemaIssue.toString()`.
|
|
923
|
-
*
|
|
924
1121
|
* - Flattens the issue tree into `{ message, path }` entries using
|
|
925
1122
|
* {@link defaultLeafHook} and {@link defaultCheckHook}.
|
|
1123
|
+
* - Includes reported input in default messages when the node producing the
|
|
1124
|
+
* message has an `input` field.
|
|
926
1125
|
* - Each entry is rendered as `"<message>"` or `"<message>\n at <path>"`.
|
|
927
1126
|
* - Multiple entries are joined with newlines.
|
|
928
1127
|
*
|
|
1128
|
+
* **Gotchas**
|
|
1129
|
+
*
|
|
1130
|
+
* Formatting an issue can disclose input retained with `reportInput: true`.
|
|
1131
|
+
* Wrapper inputs are not inherited by child messages, and custom messages are
|
|
1132
|
+
* returned unchanged.
|
|
1133
|
+
*
|
|
929
1134
|
* **Example** (Formatting an issue as a string)
|
|
930
1135
|
*
|
|
931
1136
|
* ```ts import.meta.vitest
|