Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/http-client-response-schema-json-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"effect": patch
---

Fix `HttpClientResponse.schemaJson` and `HttpClientResponse.schemaNoBody` to apply parse options when decoding response
schemas.
23 changes: 23 additions & 0 deletions .changeset/schema-interpreter-backports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
"effect": patch
---

Align Schema construction and parsing semantics, simplify parse options, accept inherited declared fields, and move Union settings into a node-local options object.

### Breaking changes

- `Class.make`, `Class.makeOption`, and `Class.makeEffect` now return an existing instance unchanged. This avoids duplicate initialization and makes the construction APIs consistent. Use `new MyClass(input)` when a distinct instance is required.

- `Literal(0)` and `Literal(-0)` continue to accept either signed zero, but decoding and encoding now preserve the input sign. Add an explicit transformation when a canonical sign is required.

- `parseOptions` annotations no longer affect parsing. Options passed when creating or calling a decoder, encoder, or constructor adapter now apply to the complete operation. Move operation-wide settings from annotations to the relevant parser API.

- `propertyOrder` has been removed from `ParseOptions` because preserving input order required a separate, rarely used object reconstruction path. Schema parsing no longer guarantees that decoded object keys follow their input order. Remove the option and apply any required presentation or serialization order after parsing.

- `concurrency` now applies only to product children: tuple elements, array elements, struct fields, record entries, and structs with rest. It follows `Effect.forEach` semantics, defaults to sequential execution, and applies independently at every nested product. Union candidates remain sequential because speculative candidate evaluation can run transformations that are not selected. Existing product parsing can keep the option. Replace code that relied on concurrent Union candidates with explicitly coordinated parser calls. With concurrent Record key transformations, completion order determines the retained value when transformed keys collide.

- `onExcessProperty: "preserve"` has been removed because it allowed unvalidated values absent from the schema type to cross the parsing boundary. Model additional properties with `Record` or `StructWithRest`; `"ignore"` and `"error"` remain available.

- Declared `Struct` fields may now be inherited and are copied to own properties in the output. Dynamic `Record` index signatures remain own-only, while finite literal record keys are declared and may be inherited. The `__proto__` field remains own-only. Check ownership before parsing when every declared field must be own.

- `SchemaAST.Union.mode` moved to `SchemaAST.Union.options?.mode` so node-local constructor settings live in one options object instead of special top-level fields. An absent value defaults to `"anyOf"`. `SchemaRepresentation.Union` now serializes `{ options: { mode: "oneOf" } }`; update direct AST access and regenerate or migrate persisted representation documents. The public `Schema.Union(members, { mode })` call is unchanged.
32 changes: 16 additions & 16 deletions migration/annotations/effect__SchemaAST.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
note: "The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model."
"effect/SchemaAST#BatchingAnnotation":
replacement: "none"
note: "Per-schema batching annotations were removed; control asynchronous parsing with ParseOptions.concurrency."
note: "Per-schema batching annotations were removed. They have no direct replacement. ParseOptions.concurrency controls product child parsing only; configure request batching separately."
"effect/SchemaAST#BatchingAnnotationId":
replacement: "none"
note: "Symbol annotation IDs were removed and batching is no longer a schema annotation."
Expand Down Expand Up @@ -53,11 +53,11 @@
replacement: "SchemaAST.Encoding"
note: "The marker transformation was replaced by explicit SchemaAST.Link encoding chains."
"effect/SchemaAST#ConcurrencyAnnotation":
replacement: "SchemaAST.ParseOptions[\"concurrency\"]"
note: "Concurrency is now a parse option rather than its own annotation type."
replacement: "SchemaAST.ParseOptions"
note: "Per-schema concurrency annotations were removed. Pass concurrency in runtime ParseOptions when creating or calling a decoder, encoder, or constructor. It applies independently to each tuple, array, struct, record, or struct-with-rest node and does not make Union candidates concurrent."
"effect/SchemaAST#ConcurrencyAnnotationId":
replacement: "Schema.Annotations.Bottom[\"parseOptions\"]"
note: "Symbol annotation IDs were removed; put concurrency inside the parseOptions annotation."
replacement: "SchemaAST.ParseOptions"
note: "The annotation ID was removed. Pass concurrency in runtime ParseOptions; product parsing follows Effect.forEach concurrency semantics while Union candidates remain sequential."
"effect/SchemaAST#Declaration":
replacement: "SchemaAST.Declaration"
note: "The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model."
Expand Down Expand Up @@ -117,16 +117,16 @@
note: "Resolve string-keyed annotations with resolveAt, or use resolveIdentifier, resolveTitle, and resolveDescription."
"effect/SchemaAST#getBatchingAnnotation":
replacement: "none"
note: "Batching annotations were removed; read ParseOptions.concurrency when controlling asynchronous parsing."
note: "Batching annotations were removed. ParseOptions.concurrency controls product child parsing only; configure request batching separately."
"effect/SchemaAST#getBrandAnnotation":
replacement: "SchemaAST.resolveAt(\"brands\")"
note: "Resolve the string-keyed brands annotation."
"effect/SchemaAST#getCompiler":
replacement: "none"
note: "The Match-based compiler was removed; traverse SchemaAST.AST directly or use the relevant Schema derivation API."
"effect/SchemaAST#getConcurrencyAnnotation":
replacement: "SchemaAST.resolveAt(\"parseOptions\")"
note: "Resolve parseOptions and read concurrency from it."
replacement: "SchemaAST.ParseOptions"
note: "Concurrency is no longer read from schema annotations. Pass it in runtime ParseOptions when creating or calling a parser. It applies to product children, not Union candidates."
"effect/SchemaAST#getDecodingFallbackAnnotation":
replacement: "none"
note: "Fallbacks are encoding middleware in v4, not readable annotations; attach them with Schema.catchDecoding."
Expand Down Expand Up @@ -164,8 +164,8 @@
replacement: "none"
note: "Issue-title callbacks were removed; use message or expected annotations and SchemaIssue formatters."
"effect/SchemaAST#getParseOptionsAnnotation":
replacement: "SchemaAST.resolveAt(\"parseOptions\")"
note: "Resolve the string-keyed parseOptions annotation."
replacement: "none"
note: "Parse options are no longer schema annotations. Pass options when creating or calling a decoder or encoder; there is no annotation-based override for nested schemas."
"effect/SchemaAST#getPropertySignatures":
replacement: "SchemaAST.Objects.propertySignatures"
note: "Narrow to Objects and read propertySignatures directly."
Expand Down Expand Up @@ -330,10 +330,10 @@
note: "Use the built-in JSON string codec instead of checking the old schema ID."
"effect/SchemaAST#ParseOptions":
replacement: "SchemaAST.ParseOptions"
note: "The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model."
note: "Pass parsing options at runtime. onExcessProperty supports ignore or error, not preserve; model extra values with an explicit Record or StructWithRest. propertyOrder was removed. concurrency follows Effect.forEach semantics for tuple, array, struct, record, and struct-with-rest children, applies independently at each nested product, and does not make Union candidates concurrent. Output key order is unspecified, including in values passed to checks. Handle required presentation or serialization order explicitly outside the parser."
"effect/SchemaAST#ParseOptionsAnnotationId":
replacement: "Schema.Annotations.Bottom[\"parseOptions\"]"
note: "Symbol annotation IDs were removed; use the parseOptions key."
replacement: "none"
note: "Parse options are no longer schema annotations. Pass options when creating or calling a decoder or encoder; there is no annotation-based override for nested schemas."
"effect/SchemaAST#partial":
replacement: "Schema.mapFields + Struct.map(Schema.optional)"
note: "Partial object transforms moved to schema field transforms."
Expand Down Expand Up @@ -399,7 +399,7 @@
note: "Transformation implementations moved to SchemaTransformation and are stored on SchemaAST.Link."
"effect/SchemaAST#TupleType":
replacement: "SchemaAST.Arrays"
note: "The v4 SchemaAST redesign renamed this primitive, collection, or guard while preserving its role."
note: "Use Arrays(isMutable, elements, rest, annotations?, checks?, encoding?, context?, encodingChecks?)."
"effect/SchemaAST#Type":
replacement: "SchemaAST.AST"
note: "The tuple-element Type wrapper was removed; optionality and mutability moved to Context."
Expand All @@ -414,7 +414,7 @@
note: "Symbol annotation IDs were removed; use declaration codec annotation keys."
"effect/SchemaAST#TypeLiteral":
replacement: "SchemaAST.Objects"
note: "The v4 SchemaAST redesign renamed this primitive, collection, or guard while preserving its role."
note: "Use Objects(propertySignatures, indexSignatures, annotations?, checks?, encoding?, context?, encodingChecks?). Output key order is unspecified."
"effect/SchemaAST#TypeLiteralTransformation":
replacement: "SchemaAST.Encoding"
note: "Object transformations are encoding links; use Schema.encodeKeys for key mappings."
Expand All @@ -426,7 +426,7 @@
note: "The v4 SchemaAST redesign renamed this primitive, collection, or guard while preserving its role."
"effect/SchemaAST#Union":
replacement: "SchemaAST.Union"
note: "The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model."
note: "Pass member ASTs and an optional options object: new SchemaAST.Union(types, { mode: 'oneOf' }). Read options?.mode ?? 'anyOf' instead of a direct mode field."
"effect/SchemaAST#UniqueSymbol":
replacement: "SchemaAST.UniqueSymbol"
note: "The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model."
Expand Down
24 changes: 12 additions & 12 deletions migration/v3-to-v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Base: `origin/v3` (`2e471d9cec31889cd6548aa5423b64c2b85238be`)

Head: `agent/bob/738d126b22f9` (`b4773df70eb78ac7c222b236ff5a0605e6632ac6`)
Head: `HEAD` (`303c58f2c1b9d9f2e25ad4554b80af193852fbec`)

This file is generated from the API diff and `migration/annotations/*.yaml`.

Expand Down Expand Up @@ -14939,7 +14939,7 @@ Schema.toFormatter(schema)

- `SchemaAST.ArbitraryAnnotationId` -> `Schema.Annotations.ToArbitrary`: Symbol annotation IDs were removed. Declarations use the toCodecArbitrary annotation; filters use arbitraryConstraint.

- `SchemaAST.BatchingAnnotation` -> `none`: Per-schema batching annotations were removed; control asynchronous parsing with ParseOptions.concurrency.
- `SchemaAST.BatchingAnnotation` -> `none`: Per-schema batching annotations were removed. They have no direct replacement. ParseOptions.concurrency controls product child parsing only; configure request batching separately.

- `SchemaAST.BatchingAnnotationId` -> `none`: Symbol annotation IDs were removed and batching is no longer a schema annotation.

Expand All @@ -14955,9 +14955,9 @@ Schema.toFormatter(schema)

- `SchemaAST.ComposeTransformation` -> `SchemaAST.Encoding`: The marker transformation was replaced by explicit SchemaAST.Link encoding chains.

- `SchemaAST.ConcurrencyAnnotation` -> `SchemaAST.ParseOptions["concurrency"]`: Concurrency is now a parse option rather than its own annotation type.
- `SchemaAST.ConcurrencyAnnotation` -> `SchemaAST.ParseOptions`: Per-schema concurrency annotations were removed. Pass concurrency in runtime ParseOptions when creating or calling a decoder, encoder, or constructor. It applies independently to each tuple, array, struct, record, or struct-with-rest node and does not make Union candidates concurrent.

- `SchemaAST.ConcurrencyAnnotationId` -> `Schema.Annotations.Bottom["parseOptions"]`: Symbol annotation IDs were removed; put concurrency inside the parseOptions annotation.
- `SchemaAST.ConcurrencyAnnotationId` -> `SchemaAST.ParseOptions`: The annotation ID was removed. Pass concurrency in runtime ParseOptions; product parsing follows Effect.forEach concurrency semantics while Union candidates remain sequential.

- `SchemaAST.Declaration` -> `SchemaAST.Declaration`: The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model.

Expand Down Expand Up @@ -15033,9 +15033,9 @@ Schema.toFormatter(schema)

- `SchemaAST.ParseJsonSchemaId` -> `Schema.UnknownFromJsonString`: Use the built-in JSON string codec instead of checking the old schema ID.

- `SchemaAST.ParseOptions` -> `SchemaAST.ParseOptions`: The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model.
- `SchemaAST.ParseOptions` -> `SchemaAST.ParseOptions`: Pass parsing options at runtime. onExcessProperty supports ignore or error, not preserve; model extra values with an explicit Record or StructWithRest. propertyOrder was removed. concurrency follows Effect.forEach semantics for tuple, array, struct, record, and struct-with-rest children, applies independently at each nested product, and does not make Union candidates concurrent. Output key order is unspecified, including in values passed to checks. Handle required presentation or serialization order explicitly outside the parser.

- `SchemaAST.ParseOptionsAnnotationId` -> `Schema.Annotations.Bottom["parseOptions"]`: Symbol annotation IDs were removed; use the parseOptions key.
- `SchemaAST.ParseOptionsAnnotationId` -> `none`: Parse options are no longer schema annotations. Pass options when creating or calling a decoder or encoder; there is no annotation-based override for nested schemas.

- `SchemaAST.PrettyAnnotationId` -> `Schema.overrideToFormatter`: The symbol annotation was removed; attach custom formatters with Schema.overrideToFormatter.

Expand Down Expand Up @@ -15071,21 +15071,21 @@ Schema.toFormatter(schema)

- `SchemaAST.TransformationKind` -> `SchemaTransformation.Transformation`: Transformation implementations moved to SchemaTransformation and are stored on SchemaAST.Link.

- `SchemaAST.TupleType` -> `SchemaAST.Arrays`: The v4 SchemaAST redesign renamed this primitive, collection, or guard while preserving its role.
- `SchemaAST.TupleType` -> `SchemaAST.Arrays`: Use Arrays(isMutable, elements, rest, annotations?, checks?, encoding?, context?, encodingChecks?).

- `SchemaAST.Type` -> `SchemaAST.AST`: The tuple-element Type wrapper was removed; optionality and mutability moved to Context.

- `SchemaAST.TypeConstructorAnnotation` -> `Schema.Annotations.Declaration["toCodec"]`: Type-constructor behavior moved to declaration codec annotations.

- `SchemaAST.TypeConstructorAnnotationId` -> `Schema.Annotations.Declaration["toCodec"]`: Symbol annotation IDs were removed; use declaration codec annotation keys.

- `SchemaAST.TypeLiteral` -> `SchemaAST.Objects`: The v4 SchemaAST redesign renamed this primitive, collection, or guard while preserving its role.
- `SchemaAST.TypeLiteral` -> `SchemaAST.Objects`: Use Objects(propertySignatures, indexSignatures, annotations?, checks?, encoding?, context?, encodingChecks?). Output key order is unspecified.

- `SchemaAST.TypeLiteralTransformation` -> `SchemaAST.Encoding`: Object transformations are encoding links; use Schema.encodeKeys for key mappings.

- `SchemaAST.UndefinedKeyword` -> `SchemaAST.Undefined`: The v4 SchemaAST redesign renamed this primitive, collection, or guard while preserving its role.

- `SchemaAST.Union` -> `SchemaAST.Union`: The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model.
- `SchemaAST.Union` -> `SchemaAST.Union`: Pass member ASTs and an optional options object: new SchemaAST.Union(types, { mode: 'oneOf' }). Read options?.mode ?? 'anyOf' instead of a direct mode field.

- `SchemaAST.UniqueSymbol` -> `SchemaAST.UniqueSymbol`: The name remains, but its constructor and fields changed in the v4 Base/check/context/encoding model.

Expand All @@ -15111,13 +15111,13 @@ Schema.toFormatter(schema)

- `SchemaAST.getAnnotation` -> `SchemaAST.resolveAt`: Resolve string-keyed annotations with resolveAt, or use resolveIdentifier, resolveTitle, and resolveDescription.

- `SchemaAST.getBatchingAnnotation` -> `none`: Batching annotations were removed; read ParseOptions.concurrency when controlling asynchronous parsing.
- `SchemaAST.getBatchingAnnotation` -> `none`: Batching annotations were removed. ParseOptions.concurrency controls product child parsing only; configure request batching separately.

- `SchemaAST.getBrandAnnotation` -> `SchemaAST.resolveAt("brands")`: Resolve the string-keyed brands annotation.

- `SchemaAST.getCompiler` -> `none`: The Match-based compiler was removed; traverse SchemaAST.AST directly or use the relevant Schema derivation API.

- `SchemaAST.getConcurrencyAnnotation` -> `SchemaAST.resolveAt("parseOptions")`: Resolve parseOptions and read concurrency from it.
- `SchemaAST.getConcurrencyAnnotation` -> `SchemaAST.ParseOptions`: Concurrency is no longer read from schema annotations. Pass it in runtime ParseOptions when creating or calling a parser. It applies to product children, not Union candidates.

- `SchemaAST.getDecodingFallbackAnnotation` -> `none`: Fallbacks are encoding middleware in v4, not readable annotations; attach them with Schema.catchDecoding.

Expand All @@ -15143,7 +15143,7 @@ Schema.toFormatter(schema)

- `SchemaAST.getParseIssueTitleAnnotation` -> `none`: Issue-title callbacks were removed; use message or expected annotations and SchemaIssue formatters.

- `SchemaAST.getParseOptionsAnnotation` -> `SchemaAST.resolveAt("parseOptions")`: Resolve the string-keyed parseOptions annotation.
- `SchemaAST.getParseOptionsAnnotation` -> `none`: Parse options are no longer schema annotations. Pass options when creating or calling a decoder or encoder; there is no annotation-based override for nested schemas.

- `SchemaAST.getPropertySignatures` -> `SchemaAST.Objects.propertySignatures`: Narrow to Objects and read propertySignatures directly.

Expand Down
Loading
Loading