Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⬆️ Update dependency effect to v3 #126

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented Apr 16, 2024

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
effect (source) 2.2.5 -> 3.14.2 age adoption passing confidence

Release Notes

Effect-TS/effect (effect)

v3.14.2

Compare Source

Patch Changes
  • #​4646 f87991b Thanks @​gcanti! - SchemaAST: add missing getSchemaIdAnnotation API

  • #​4646 f87991b Thanks @​gcanti! - Arbitrary: fix bug where annotations were ignored.

    Before

    import { Arbitrary, Schema } from "effect"
    
    const schema = Schema.Int.annotations({
      arbitrary: (_, ctx) => (fc) => {
        console.log("context: ", ctx)
        return fc.integer()
      }
    }).pipe(Schema.greaterThan(0), Schema.lessThan(10))
    
    Arbitrary.make(schema)
    // No output ❌

    After

    import { Arbitrary, Schema } from "effect"
    
    const schema = Schema.Int.annotations({
      arbitrary: (_, ctx) => (fc) => {
        console.log("context: ", ctx)
        return fc.integer()
      }
    }).pipe(Schema.greaterThan(0), Schema.lessThan(10))
    
    Arbitrary.make(schema)
    /*
    context:  {
      maxDepth: 2,
      constraints: {
        _tag: 'NumberConstraints',
        constraints: { min: 0, minExcluded: true, max: 10, maxExcluded: true },
        isInteger: true
      }
    }
    */
  • #​4648 0a3e3e1 Thanks @​gcanti! - Schema: standardSchemaV1 now includes the schema, closes #​4494.

    This update fixes an issue where passing Schema.standardSchemaV1(...) directly to JSONSchema.make would throw a TypeError. The schema was missing from the returned object, causing the JSON schema generation to fail.

    Now standardSchemaV1 includes the schema itself, so it can be used with JSONSchema.make without issues.

    Example

    import { JSONSchema, Schema } from "effect"
    
    const Person = Schema.Struct({
      name: Schema.optionalWith(Schema.NonEmptyString, { exact: true })
    })
    
    const standardSchema = Schema.standardSchemaV1(Person)
    
    console.log(JSONSchema.make(standardSchema))
    /*
    {
      '$schema': 'http://json-schema.org/draft-07/schema#',
      '$defs': {
        NonEmptyString: {
          type: 'string',
          description: 'a non empty string',
          title: 'nonEmptyString',
          minLength: 1
        }
      },
      type: 'object',
      required: [],
      properties: { name: { '$ref': '#/$defs/NonEmptyString' } },
      additionalProperties: false
    }
    */

v3.14.1

Compare Source

Patch Changes

v3.14.0

Compare Source

Minor Changes
  • #​4469 1f47e4e Thanks @​vinassefranche! - Add DateTime.nowAsDate creator

  • #​4469 26dd75f Thanks @​tim-smart! - expose the Layer.MemoMap via Layer.CurrentMemoMap to the layers being built

  • #​4469 04dff2d Thanks @​tim-smart! - add Tracer Span.addLinks, for dynamically linking spans

  • #​4469 c7fac0c Thanks @​LaureRC! - Add HashMap.every

  • #​4469 ffaa3f3 Thanks @​vinassefranche! - Add Either.transposeOption

  • #​4469 ab957c1 Thanks @​vinassefranche! - Make TestClock.setTime accept a DateTime.Input

  • #​4469 35db9ce Thanks @​LaureRC! - Add Effect.transposeMapOption

  • #​4469 cf77ea9 Thanks @​f15u! - Add Array.window function

  • #​4469 26dd75f Thanks @​tim-smart! - add LayerMap module

    A LayerMap allows you to create a map of Layer's that can be used to
    dynamically access resources based on a key.

    Here is an example of how you can use a LayerMap to create a service that
    provides access to multiple OpenAI completions services.

    import { Completions } from "@​effect/ai"
    import { OpenAiClient, OpenAiCompletions } from "@​effect/ai-openai"
    import { FetchHttpClient } from "@​effect/platform"
    import { NodeRuntime } from "@​effect/platform-node"
    import { Config, Effect, Layer, LayerMap } from "effect"
    
    // create the openai client layer
    const OpenAiLayer = OpenAiClient.layerConfig({
      apiKey: Config.redacted("OPENAI_API_KEY")
    }).pipe(Layer.provide(FetchHttpClient.layer))
    
    // create a service that wraps a LayerMap
    class AiClients extends LayerMap.Service<AiClients>()("AiClients", {
      // this LayerMap will provide the ai Completions service
      provides: Completions.Completions,
    
      // define the lookup function for the layer map
      //
      // The returned Layer will be used to provide the Completions service for the
      // given model.
      lookup: (model: OpenAiCompletions.Model) =>
        OpenAiCompletions.layer({ model }),
    
      // If a layer is not used for a certain amount of time, it can be removed
      idleTimeToLive: "5 seconds",
    
      // Supply the dependencies for the layers in the LayerMap
      dependencies: [OpenAiLayer]
    }) {}
    
    // usage
    Effect.gen(function* () {
      // access and use the generic Completions service
      const ai = yield* Completions.Completions
      const response = yield* ai.create("Hello, world!")
      console.log(response.text)
    }).pipe(
      // use the AiClients service to provide a variant of the Completions service
      AiClients.provide("gpt-4o"),
      // provide the LayerMap service
      Effect.provide(AiClients.Default),
      NodeRuntime.runMain
    )
  • #​4469 baaab60 Thanks @​vinassefranche! - Make Runtime.run* apis dual

Patch Changes

v3.13.12

Compare Source

Patch Changes
  • #​4610 0c4803f Thanks @​gcanti! - Preserve specific annotations (e.g., arbitrary) when using Schema.typeSchema, closes #​4609.

    Previously, annotations such as arbitrary were lost when calling Schema.typeSchema on a transformation. This update ensures that certain annotations, which depend only on the "to" side of the transformation, are preserved.

    Annotations that are now retained:

    • examples
    • default
    • jsonSchema
    • arbitrary
    • pretty
    • equivalence

    Example

    Before

    import { Arbitrary, FastCheck, Schema } from "effect"
    
    const schema = Schema.NumberFromString.annotations({
      arbitrary: () => (fc) => fc.constant(1)
    })
    
    const to = Schema.typeSchema(schema) // ❌ Annotation is lost
    
    console.log(FastCheck.sample(Arbitrary.make(to), 5))
    /*
    [
      2.5223372357846707e-44,
      -2.145443957806771e+25,
      -3.4028179901346956e+38,
      5.278086259208735e+29,
      1.8216880036222622e-44
    ]
    */

    After

    import { Arbitrary, FastCheck, Schema } from "effect"
    
    const schema = Schema.NumberFromString.annotations({
      arbitrary: () => (fc) => fc.constant(1)
    })
    
    const to = Schema.typeSchema(schema) // ✅ Annotation is now preserved
    
    console.log(FastCheck.sample(Arbitrary.make(to), 5))
    /*
    [ 1, 1, 1, 1, 1 ]
    */
  • #​4607 6f65ac4 Thanks @​gcanti! - Add support for jsonSchema annotations on SymbolFromSelf index signatures.

    Before

    import { JSONSchema, Schema } from "effect"
    
    const schema = Schema.Record({
      key: Schema.SymbolFromSelf.annotations({ jsonSchema: { type: "string" } }),
      value: Schema.Number
    })
    
    JSONSchema.make(schema)
    /*
    throws:
    Error: Unsupported index signature parameter
    schema (SymbolKeyword): symbol
    */

    After

    import { JSONSchema, Schema } from "effect"
    
    const schema = Schema.Record({
      key: Schema.SymbolFromSelf.annotations({ jsonSchema: { type: "string" } }),
      value: Schema.Number
    })
    
    console.log(JSON.stringify(JSONSchema.make(schema), null, 2))
    /*
    Output:
    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "required": [],
      "properties": {},
      "additionalProperties": {
        "type": "number"
      },
      "propertyNames": {
        "type": "string"
      }
    }
    */

v3.13.11

Compare Source

Patch Changes
  • #​4601 fad8cca Thanks @​gcanti! - Schema: enhance the internal formatUnknown function to handle various types including iterables, classes, and additional edge cases.

    Before

    import { Schema } from "effect"
    
    const schema = Schema.Array(Schema.Number)
    
    Schema.decodeUnknownSync(schema)(new Set([1, 2]))
    // throws Expected ReadonlyArray<number>, actual {}
    
    class A {
      constructor(readonly a: number) {}
    }
    
    Schema.decodeUnknownSync(schema)(new A(1))
    // throws Expected ReadonlyArray<number>, actual {"a":1}

    After

    import { Schema } from "effect"
    
    const schema = Schema.Array(Schema.Number)
    
    Schema.decodeUnknownSync(schema)(new Set([1, 2]))
    // throws Expected ReadonlyArray<number>, actual Set([1,2])
    
    class A {
      constructor(readonly a: number) {}
    }
    
    Schema.decodeUnknownSync(schema)(new A(1))
    // throws Expected ReadonlyArray<number>, actual A({"a":1})
  • #​4606 4296293 Thanks @​gcanti! - Fix issue with generic filters when generating arbitraries, closes #​4605.

    Previously, applying a filter to a schema when generating arbitraries could cause a TypeError due to missing properties. This fix ensures that arbitraries are generated correctly when filters are used.

    Before

    import { Arbitrary, Schema } from "effect"
    
    const schema = Schema.BigIntFromSelf.pipe(Schema.filter(() => true))
    
    Arbitrary.make(schema)
    // TypeError: Cannot read properties of undefined (reading 'min')

    After

    import { Arbitrary, Schema } from "effect"
    
    const schema = Schema.BigIntFromSelf.pipe(Schema.filter(() => true))
    
    const result = Arbitrary.make(schema) // Works correctly
  • #​4587 9c241ab Thanks @​gcanti! - Schema: simplify Struct and Record return types.

  • #​4591 082b0c1 Thanks @​IMax153! - Improve clarity of the TimeoutException error message

  • #​4604 be12983 Thanks @​gcanti! - Add support for refinements to Schema.omit, closes #​4603.

    Before

    import { Schema } from "effect"
    
    const schema = Schema.Struct({
      a: Schema.String,
      b: Schema.String
    })
    
    const omitted = schema.pipe(
      Schema.filter(() => true),
      Schema.omit("a")
    )
    
    console.log(String(omitted.ast))
    // {} ❌

    After

    import { Schema } from "effect"
    
    const schema = Schema.Struct({
      a: Schema.String,
      b: Schema.String
    })
    
    const omitted = schema.pipe(
      Schema.filter(() => true),
      Schema.omit("a")
    )
    
    console.log(String(omitted.ast))
    // { readonly b: string }
  • #​4593 de88127 Thanks @​gcanti! - Schema: export Field type.

    Useful for creating a type that can be used to add custom constraints to the fields of a struct.

    import { Schema } from "effect"
    
    const f = <Fields extends Record<"a" | "b", Schema.Struct.Field>>(
      schema: Schema.Struct<Fields>
    ) => {
      return schema.omit("a")
    }
    
    //      ┌─── Schema.Struct<{ b: typeof Schema.Number; }>
    //      ▼
    const result = f(Schema.Struct({ a: Schema.String, b: Schema.Number }))

v3.13.10

Compare Source

Patch Changes
  • #​4578 527c964 Thanks @​gcanti! - Allow toString Method to Be Overridden in Schema Classes, closes #​4577.

    Previously, attempting to override the toString method in schema classes caused a TypeError in the browser because the property was set as read-only (writable: false). This fix makes toString writable, allowing developers to override it when needed.

v3.13.9

Compare Source

Patch Changes

v3.13.8

Compare Source

Patch Changes
  • #​4567 c65d336 Thanks @​rehos! - Schema: standardSchemaV1 now returns all errors by default and supports custom options.

    The standardSchemaV1 now returns all validation errors by default (ParseOptions = { errors: "all" }). Additionally, it now accepts an optional overrideOptions parameter, allowing you to customize the default parsing behavior as needed.

  • #​4565 22d2ebb Thanks @​gcanti! - ParseResult.ArrayFormatter: correct _tag fields for Refinement and Transformation issues, closes #​4564.

    This update fixes an issue where ParseResult.ArrayFormatter incorrectly labeled Refinement and Transformation errors as Type in the output.

    Before

    import { Effect, ParseResult, Schema } from "effect"
    
    const schema = Schema.Struct({
      a: Schema.NonEmptyString,
      b: Schema.NumberFromString
    })
    
    const input = { a: "", b: "" }
    
    const program = Schema.decodeUnknown(schema, { errors: "all" })(input).pipe(
      Effect.catchTag("ParseError", (err) =>
        ParseResult.ArrayFormatter.formatError(err).pipe(
          Effect.map((err) => JSON.stringify(err, null, 2))
        )
      )
    )
    
    program.pipe(Effect.runPromise).then(console.log)
    /*
    [
      {
        "_tag": "Type", ❌
        "path": [
          "a"
        ],
        "message": "Expected a non empty string, actual \"\""
      },
      {
        "_tag": "Type", ❌
        "path": [
          "b"
        ],
        "message": "Unable to decode \"\" into a number"
      }
    ]
    */

    After

    import { Effect, ParseResult, Schema } from "effect"
    
    const schema = Schema.Struct({
      a: Schema.NonEmptyString,
      b: Schema.NumberFromString
    })
    
    const input = { a: "", b: "" }
    
    const program = Schema.decodeUnknown(schema, { errors: "all" })(input).pipe(
      Effect.catchTag("ParseError", (err) =>
        ParseResult.ArrayFormatter.formatError(err).pipe(
          Effect.map((err) => JSON.stringify(err, null, 2))
        )
      )
    )
    
    program.pipe(Effect.runPromise).then(console.log)
    /*
    [
      {
        "_tag": "Refinement", ✅
        "path": [
          "a"
        ],
        "message": "Expected a non empty string, actual \"\""
      },
      {
        "_tag": "Transformation", ✅
        "path": [
          "b"
        ],
        "message": "Unable to decode \"\" into a number"
      }
    ]
    */

v3.13.7

Compare Source

Patch Changes
  • #​4540 840cc73 Thanks @​gcanti! - Add additionalPropertiesStrategy option to OpenApi.fromApi, closes #​4531.

    This update introduces the additionalPropertiesStrategy option in OpenApi.fromApi, allowing control over how additional properties are handled in the generated OpenAPI schema.

    • When "strict" (default), additional properties are disallowed ("additionalProperties": false).
    • When "allow", additional properties are allowed ("additionalProperties": true), making APIs more flexible.

    The additionalPropertiesStrategy option has also been added to:

    • JSONSchema.fromAST
    • OpenApiJsonSchema.makeWithDefs

    Example

    import {
      HttpApi,
      HttpApiEndpoint,
      HttpApiGroup,
      OpenApi
    } from "@&#8203;effect/platform"
    import { Schema } from "effect"
    
    const api = HttpApi.make("api").add(
      HttpApiGroup.make("group").add(
        HttpApiEndpoint.get("get", "/").addSuccess(
          Schema.Struct({ a: Schema.String })
        )
      )
    )
    
    const schema = OpenApi.fromApi(api, {
      additionalPropertiesStrategy: "allow"
    })
    
    console.log(JSON.stringify(schema, null, 2))
    /*
    {
      "openapi": "3.1.0",
      "info": {
        "title": "Api",
        "version": "0.0.1"
      },
      "paths": {
        "/": {
          "get": {
            "tags": [
              "group"
            ],
            "operationId": "group.get",
            "parameters": [],
            "security": [],
            "responses": {
              "200": {
                "description": "Success",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "required": [
                        "a"
                      ],
                      "properties": {
                        "a": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              },
              "400": {
                "description": "The request did not match the expected schema",
                "content": {
                  "application/json": {
                    "schema": {
                      "$ref": "#/components/schemas/HttpApiDecodeError"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "components": {
        "schemas": {
          "HttpApiDecodeError": {
            "type": "object",
            "required": [
              "issues",
              "message",
              "_tag"
            ],
            "properties": {
              "issues": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Issue"
                }
              },
              "message": {
                "type": "string"
              },
              "_tag": {
                "type": "string",
                "enum": [
                  "HttpApiDecodeError"
                ]
              }
            },
            "additionalProperties": true,
            "description": "The request did not match the expected schema"
          },
          "Issue": {
            "type": "object",
            "required": [
              "_tag",
              "path",
              "message"
            ],
            "properties": {
              "_tag": {
                "type": "string",
                "enum": [
                  "Pointer",
                  "Unexpected",
                  "Missing",
                  "Composite",
                  "Refinement",
                  "Transformation",
                  "Type",
                  "Forbidden"
                ],
                "description": "The tag identifying the type of parse issue"
              },
              "path": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PropertyKey"
                },
                "description": "The path to the property where the issue occurred"
              },
              "message": {
                "type": "string",
                "description": "A descriptive message explaining the issue"
              }
            },
            "additionalProperties": true,
            "description": "Represents an error encountered while parsing a value to match the schema"
          },
          "PropertyKey": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "object",
                "required": [
                  "_tag",
                  "key"
                ],
                "properties": {
                  "_tag": {
                    "type": "string",
                    "enum": [
                      "symbol"
                    ]
                  },
                  "key": {
                    "type": "string"
                  }
                },
                "additionalProperties": true,
                "description": "an object to be decoded into a globally shared symbol"
              }
            ]
          }
        },
        "securitySchemes": {}
      },
      "security": [],
      "tags": [
        {
          "name": "group"
        }
      ]
    }
    */
  • #​4541 9bf8a74 Thanks @​fubhy! - Disallowed excess properties for various function options

  • #​4554 87ba23c Thanks @​gcanti! - ConfigProvider: fromEnv: add missing Partial modifier.

v3.13.6

Compare Source

Patch Changes
  • #​4551 3154ce4 Thanks @​gcanti! - Arbitrary: make called on Schema.Class now respects property annotations, closes #​4550.

    Previously, when calling Arbitrary.make on a Schema.Class, property-specific annotations (such as arbitrary) were ignored, leading to unexpected values in generated instances.

    Before

    Even though a had an arbitrary annotation, the generated values were random:

    import { Arbitrary, FastCheck, Schema } from "effect"
    
    class Class extends Schema.Class<Class>("Class")({
      a: Schema.NumberFromString.annotations({
        arbitrary: () => (fc) => fc.constant(1)
      })
    }) {}
    
    console.log(FastCheck.sample(Arbitrary.make(Class), 5))
    /*
    Example Output:
    [
      Class { a: 2.6624670822171524e-44 },
      Class { a: 3.4028177873105996e+38 },
      Class { a: 3.402820626847944e+38 },
      Class { a: 3.783505853677006e-44 },
      Class { a: 3243685 }
    ]
    */

    After

    Now, the values respect the arbitrary annotation and return the expected constant:

    import { Arbitrary, FastCheck, Schema } from "effect"
    
    class Class extends Schema.Class<Class>("Class")({
      a: Schema.NumberFromString.annotations({
        arbitrary: () => (fc) => fc.constant(1)
      })
    }) {}
    
    console.log(FastCheck.sample(Arbitrary.make(Class), 5))
    /*
    [
      Class { a: 1 },
      Class { a: 1 },
      Class { a: 1 },
      Class { a: 1 },
      Class { a: 1 }
    ]
    */

v3.13.4

Compare Source

Patch Changes

v3.13.3

Compare Source

Patch Changes
  • #​4502 cc5588d Thanks @​gcanti! - Schema: More Accurate Return Types for DataFromSelf and Data.

    This update refines the return types of DataFromSelf and Data, making them clearer and more specific, especially when working with structured schemas.

    Before

    The return types were more generic, making it harder to see the underlying structure:

    import { Schema } from "effect"
    
    const struct = Schema.Struct({ a: Schema.NumberFromString })
    
    //       ┌─── Schema.DataFromSelf<Schema<{ readonly a: number; }, { readonly a: string; }>>
    //       ▼
    const schema1 = Schema.DataFromSelf(struct)
    
    //       ┌─── Schema.Data<Schema<{ readonly a: number; }, { readonly a: string; }>>
    //       ▼
    const schema2 = Schema.Data(struct)

    After

    Now, the return types clearly reflect the original schema structure:

    import { Schema } from "effect"
    
    const struct = Schema.Struct({ a: Schema.NumberFromString })
    
    //       ┌─── Schema.DataFromSelf<Schema.Struct<{ a: typeof Schema.NumberFromString; }>>
    //       ▼
    const schema1 = Schema.DataFromSelf(struct)
    
    //       ┌─── Schema.Data<Schema.Struct<{ a: typeof Schema.NumberFromString; }>>
    //       ▼
    const schema2 = Schema.Data(struct)
  • #​4510 623c8cd Thanks @​gcanti! - Schema: More Accurate Return Type for compose.

    Before

    import { Schema } from "effect"
    
    //      ┌─── SchemaClass<number | null, string>
    //      ▼
    const schema = Schema.compose(
      Schema.NumberFromString,
      Schema.NullOr(Schema.Number)
    )
    
    // @&#8203;ts-expect-error: Property 'from' does not exist
    schema.from
    
    // @&#8203;ts-expect-error: Property 'to' does not exist
    schema.to

    After

    import { Schema } from "effect"
    
    //      ┌─── transform<typeof Schema.NumberFromString, Schema.NullOr<typeof Schema.Number>>
    //      ▼
    const schema = Schema.compose(
      Schema.NumberFromString,
      Schema.NullOr(Schema.Number)
    )
    
    //      ┌─── typeof Schema.NumberFromString
    //      ▼
    schema.from
    
    //      ┌─── Schema.NullOr<typeof Schema.Number>
    //      ▼
    schema.to
  • #​4488 00b4eb1 Thanks @​gcanti! - Schema: more precise return types when filters are involved.

    Example (with Schema.maxLength)

    Before

    import { Schema } from "effect"
    
    //      ┌─── Schema.filter<Schema.Schema<string, string, never>>
    //      ▼
    const schema = Schema.String.pipe(Schema.maxLength(10))
    
    // Schema<string, string, never>
    schema.from

    After

    import { Schema } from "effect"
    
    //      ┌─── Schema.filter<typeof Schema.String>
    //      ▼
    const schema = Schema.String.pipe(Schema.maxLength(10))
    
    // typeof Schema.String
    schema.from

    String filters:

    • maxLength
    • minLength
    • length
    • pattern
    • startsWith
    • endsWith
    • includes
    • lowercased
    • capitalized
    • uncapitalized
    • uppercased
    • nonEmptyString
    • trimmed

    Number filters:

    • finite
    • greaterThan
    • greaterThanOrEqualTo
    • lessThan
    • lessThanOrEqualTo
    • int
    • multipleOf
    • between
    • nonNaN
    • positive
    • negative
    • nonPositive
    • nonNegative

    BigInt filters:

    • greaterThanBigInt
    • greaterThanOrEqualToBigInt
    • lessThanBigInt
    • lessThanOrEqualToBigInt
    • betweenBigInt
    • positiveBigInt
    • negativeBigInt
    • nonNegativeBigInt
    • nonPositiveBigInt

    Duration filters:

    • lessThanDuration
    • lessThanOrEqualToDuration
    • greaterThanDuration
    • greaterThanOrEqualToDuration
    • betweenDuration

    Array filters:

    • minItems
    • maxItems
    • itemsCount

    Date filters:

    • validDate
    • lessThanDate
    • lessThanOrEqualToDate
    • greaterThanDate
    • greaterThanOrEqualToDate
    • betweenDate

    BigDecimal filters:

    • greaterThanBigDecimal
    • greaterThanOrEqualToBigDecimal
    • lessThanBigDecimal
    • lessThanOrEqualToBigDecimal
    • positiveBigDecimal
    • nonNegativeBigDecimal
    • negativeBigDecimal
    • nonPositiveBigDecimal
    • betweenBigDecimal
  • #​4508 f2aee98 Thanks @​gcanti! - Schema: More Accurate Return Types for ArrayEnsure and NonEmptyArrayEnsure.

    Before

    import { Schema } from "effect"
    
    const schema1 = Schema.ArrayEnsure(Schema.String)
    
    // @&#8203;ts-expect-error: Property 'from' does not exist
    schema1.from
    
    const schema2 = Schema.NonEmptyArrayEnsure(Schema.String)
    
    // @&#8203;ts-expect-error: Property 'from' does not exist
    schema2.from

    After

    import { Schema } from "effect"
    
    const schema1 = Schema.ArrayEnsure(Schema.String)
    
    //        ┌─── Schema.Union<[typeof Schema.String, Schema.Array$<typeof Schema.String>]>
    //        ▼
    schema1.from
    
    const schema2 = Schema.NonEmptyArrayEnsure(Schema.String)
    
    //        ┌─── Schema.Union<[typeof Schema.String, Schema.NonEmptyArray<typeof Schema.String>]>
    //        ▼
    schema2.from
  • #​4509 fb798eb Thanks @​gcanti! - Schema: More Accurate Return Types for:

    • transformLiteral
    • clamp
    • clampBigInt
    • clampDuration
    • clampBigDecimal
    • head
    • headNonEmpty
    • headOrElse
  • #​4524 2251b15 Thanks @​gcanti! - Schema: More Accurate Return Type for parseNumber.

    Before

    import { Schema } from "effect"
    
    const schema = Schema.parseNumber(Schema.String)
    
    //      ┌─── Schema<string>
    //      ▼
    schema.from

    After

    import { Schema } from "effect"
    
    const schema = Schema.parseNumber(Schema.String)
    
    //      ┌─── typeof Schema.String
    //      ▼
    schema.from
  • #​4483 2e15c1e Thanks @​mikearnaldi! - Fix nested batching

  • #​4514 a4979db Thanks @​gcanti! - Schema: add missing from property to brand interface.

    Before

    import { Schema } from "effect"
    
    const schema = Schema.String.pipe(Schema.brand("my-brand"))
    
    // @&#8203;ts-expect-error: Property 'from' does not exist
    schema.from

    After

    import { Schema } from "effect"
    
    const schema = Schema.String.pipe(Schema.brand("my-brand"))
    
    //      ┌─── typeof Schema.String
    //      ▼
    schema.from
  • #​4496 b74255a Thanks @​tim-smart! - ensure fibers can't be added to Fiber{Handle,Set,Map} during closing

  • #​4419 d7f6a5c Thanks @​KhraksMamtsov! - Fix Context.Tag unification

  • #​4495 9dd8979 Thanks @​KhraksMamtsov! - Simplify sortWith, sort, reverse, sortBy, unzip, dedupe signatures in Array module

  • #​4507 477b488 Thanks @​gcanti! - Schema: More Accurate Return Type for parseJson(schema).

    Before

    import { Schema } from "effect"
    
    //      ┌─── Schema.SchemaClass<{ readonly a: number; }, string>
    //      ▼
    const schema = Schema.parseJson(
      Schema.Struct({
        a: Schema.NumberFromString
      })
    )
    
    // @&#8203;ts-expect-error: Property 'to' does not exist
    schema.to

    After

    import { Schema } from "effect"
    
    //      ┌─── Schema.transform<Schema.SchemaClass<unknown, string, never>, Schema.Struct<{ a: typeof Schema.NumberFromString; }>>
    //      ▼
    const schema = Schema.parseJson(
      Schema.Struct({
        a: Schema.NumberFromString
      })
    )
    
    //      ┌─── Schema.Struct<{ a: typeof Schema.NumberFromString; }>
    //      ▼
    schema.to
  • #​4519 10932cb Thanks @​gcanti! - Refactor JSONSchema to use additionalProperties instead of patternProperties for simple records, closes #​4518.

    This update improves how records are represented in JSON Schema by replacing patternProperties with additionalProperties, resolving issues in OpenAPI schema generation.

    Why the change?

    • Fixes OpenAPI issues – Previously, records were represented using patternProperties, which caused problems with OpenAPI tools.
    • Better schema compatibility – Some tools, like openapi-ts, struggled with patternProperties, generating Record<string, never> instead of the correct type.
    • Fixes missing example values – When using patternProperties, OpenAPI failed to generate proper response examples, displaying only {}.
    • Simplifies schema modification – Users previously had to manually fix schemas with OpenApi.Transform, which was messy and lacked type safety.

    Before

    import { JSONSchema, Schema } from "effect"
    
    const schema = Schema.Record({ key: Schema.String, value: Schema.Number })
    
    console.log(JSON.stringify(JSONSchema.make(schema), null, 2))
    /*
    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "required": [],
      "properties": {},
      "patternProperties": {
        "": { // ❌ Empty string pattern
          "type": "number"
        }
      }
    }
    */

    After

    Now, additionalProperties is used instead, which properly represents an open-ended record:

    import { JSONSchema, Schema } from "effect"
    
    const schema = Schema.Record({ key: Schema.String, value: Schema.Number })
    
    console.log(JSON.stringify(JSONSchema.make(schema), null, 2))
    /*
    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "required": [],
      "properties": {},
      "additionalProperties": { // ✅ Represents unrestricted record keys
        "type": "number"
      }
    }
    */
  • #​4501 9f6c784 Thanks @​gcanti! - Schema: Add Missing declare API Interface to Expose Type Parameters.

    Example

    import { Schema } from "effect"
    
    const schema = Schema.OptionFromSelf(Schema.String)
    
    //       ┌─── readonly [typeof Schema.String]
    //       ▼
    schema.typeParameters
  • #​4487 2c639ec Thanks @​gcanti! - Schema: more precise return types when transformations are involved.

    • Chunk
    • NonEmptyChunk
    • Redacted
    • Option
    • OptionFromNullOr
    • OptionFromUndefinedOr
    • OptionFromNullishOr
    • Either
    • EitherFromUnion
    • ReadonlyMap
    • Map
    • HashMap
    • ReadonlySet
    • Set
    • HashSet
    • List
    • Cause
    • Exit
    • SortedSet
    • head
    • headNonEmpty
    • headOrElse

    Example (with Schema.Chunk)

    Before

    import { Schema } from "effect"
    
    const schema = Schema.Chunk(Schema.Number)
    
    // Property 'from' does not exist on type 'Chunk<typeof Number$>'
    schema.from

    After

    import { Schema } from "effect"
    
    const schema = Schema.Chunk(Schema.Number)
    
    // Schema.Array$<typeof Schema.Number>
    schema.from
  • #​4492 886aaa8 Thanks @​gcanti! - Schema: Improve Literal return type — now returns SchemaClass instead of Schema

v3.13.2

Compare Source

Patch Changes
  • #​4472 31be72a Thanks @​gcanti! - Fix Schema.Enums toString() method to display correct enum values.

    Now, toString() correctly displays the actual enum values instead of internal numeric indices.

    Before

    import { Schema } from "effect"
    
    enum Fruits {
      Apple = "apple",
      Banana = "banana",
      Cantaloupe = 0
    }
    
    const schema = Schema.Enums(Fruits)
    
    console.log(String(schema))
    // Output: <enum 3 value(s): 0 | 1 | 2> ❌ (incorrect)

    After

    import { Schema } from "effect"
    
    enum Fruits {
      Apple = "apple",
      Banana = "banana",
      Cantaloupe = 0
    }
    
    const schema = Schema.Enums(Fruits)
    
    console.log(String(schema))
    // Output: <enum 3 value(s): "apple" | "banana" | 0> ✅ (correct)

v3.13.1

Compare Source

Patch Changes

v3.13.0

Compare Source

Minor Changes
  • #​4280 8baef83 Thanks @​tim-smart! - add Promise based apis to Fiber{Handle,Set,Map} modules

  • #​4280 655bfe2 Thanks @​gcanti! - Add Effect.transposeOption, closes #​3142.

    Converts an Option of an Effect into an Effect of an Option.

    Details

    This function transforms an Option<Effect<A, E, R>> into an
    Effect<Option<A>, E, R>. If the Option is None, the resulting Effect
    will immediately succeed with a None value. If the Option is Some, the
    inner Effect will be executed, and its result wrapped in a Some.

    Example

    import { Effect, Option } from "effect"
    
    //      ┌─── Option<Effect<number, never, never>>
    //      ▼
    const maybe = Option.some(Effect.succeed(42))
    
    //      ┌─── Effect<Option<number>, never, never>
    //      ▼
    const result = Effect.transposeOption(maybe)
    
    console.log(Effect.runSync(result))
    // Output: { _id: 'Option', _tag: 'Some', value: 42 }
  • #​4280 d90cbc2 Thanks @​indietyp! - Add Effect.whenLogLevel, which conditionally executes an effect if the specified log level is enabled

  • #​4280 75632bd Thanks @​tim-smart! - add RcMap.touch, for reseting the idle timeout for an item

  • #​4280 c874a2e Thanks @​LaureRC! - Add HashMap.some

  • #​4280 bf865e5 Thanks @​tim-smart! - allow accessing args in Effect.fn pipe

  • #​4280 f98b2b7 Thanks @​tim-smart! - add RcMap.invalidate api, for removing a resource from an RcMap

  • #​4280 de8ce92 Thanks @​mikearnaldi! - Add Layer.updateService mirroring Effect.updateService

  • #​4280 db426a5 Thanks @​KhraksMamtsov! - Differ implements Pipeable

  • #​4280 6862444 Thanks @​thewilkybarkid! - Make it easy to convert a DateTime.Zoned to a DateTime.Utc

  • #​4280 5fc8a90 Thanks @​gcanti! - Add missing Either.void constructor.

  • #​4280 546a492 Thanks @​vinassefranche! - Add HashMap.toValues and HashSet.toValues getters

  • #​4280 65c4796 Thanks @​tim-smart! - add {FiberHandle,FiberSet,FiberMap}.awaitEmpty apis

  • #​4280 9760fdc Thanks @​gcanti! - Schema: Add standardSchemaV1 API to Generate a Standard Schema v1.

    Example

    import { Schema } from "effect"
    
    const schema = Schema.Struct({
      name: Schema.String
    })
    
    //      ┌─── StandardSchemaV1<{ readonly name: string; }>
    //      ▼
    const standardSchema = Schema.standardSchemaV1(schema)
  • #​4280 5b471e7 Thanks @​fubhy! - Added Duration.formatIso and Duration.fromIso for formatting and parsing ISO8601 durations.

  • #​4280 4f810cc Thanks @​tim-smart! - add Effect.filterEffect* apis

Effect.filterEffectOrElse

Filters an effect with an effectful predicate, falling back to an alternative
effect if the predicate fails.

import { Effect, pipe } from "effect"

// Define a user interface
interface User {
  readonly name: string
}

// Simulate an asynchronous authentication function
declare const auth: () => Promise<User | null>

const program = pipe(
  Effect.promise(() => auth()),
  // Use filterEffectOrElse with an effectful predicate
  Effect.filterEffectOrElse({
    predicate: (user) => Effect.succeed(user !== null),
    orElse: (user) => Effect.fail(new Error(`Unauthorized user: ${user}`))
  })
)
Effect.filterEffectOrFail

Filters an effect with an effectful predicate, failing with a custom error if the predicate fails.

import { Effect, pipe } from "effect"

// Define a user interface
interface User {
  readonly name: string
}

// Simulate an asynchronous authentication function
declare const auth: () => Promise<User | null>

const program = pipe(
  Effect.promise(() => auth()),
  // Use filterEffectOrFail with an effectful predicate
  Effect.filterEffectOrFail({
    predicate: (user) => Effect.succeed(user !== null),
    orFailWith: (user) => Effect.fail(new Error(`Unauthorized user: ${user}`))
  })
)
Patch Changes
  • #​4280 cf8b2dd Thanks @​KhraksMamtsov! - Trie<out A> type annotations have been aligned. The type parameter was made covariant because the structure is immutable.

v3.12.12

Compare Source

Patch Changes
  • #​4440 4018eae Thanks @​gcanti! - Schema: add missing support for tuple annotations in TaggedRequest.

  • #​4439 543d36d Thanks @​gcanti! - Schedule: fix unsafe tapOutput signature.

    Previously, tapOutput allowed using an output type that wasn't properly inferred, leading to potential runtime errors. Now, TypeScript correctly detects mismatches at compile time, preventing unexpected crashes.

    Before (Unsafe, Causes Runtime Error)

    import { Effect, Schedule, Console } from "effect"
    
    const schedule = Schedule.once.pipe(
      Schedule.as<number | string>(1),
      Schedule.tapOutput((s: string) => Console.log(s.trim())) // ❌ Runtime error
    )
    
    Effect.runPromise(Effect.void.pipe(Effect.schedule(schedule)))
    // throws: TypeError: s.trim is not a function

    After (Safe, Catches Type Error at Compile Time)

    import { Console, Schedule } from "effect"
    
    const schedule = Schedule.once.pipe(
      Schedule.as<number | string>(1),
      // ✅ Type Error: Type 'number' is not assignable to type 'string'
      Schedule.tapOutput((s: string) => Console.log(s.trim()))
    )
  • #​4447 f70a65a Thanks @​gcanti! - Preserve function length property in Effect.fn / Effect.fnUntraced, closes #​4435

    Previously, functions created with Effect.fn and Effect.fnUntraced always had a .length of 0, regardless of their actual number of parameters. This has been fixed so that the length property correctly reflects the ex


Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot added renovate upgrade Any kind of dependency updates labels Apr 16, 2024
Copy link
Contributor Author

renovate bot commented Apr 16, 2024

⚠ Artifact update problem

Renovate failed to update an artifact related to this branch. You probably do not want to merge this PR as-is.

♻ Renovate will retry this branch, including artifacts, only when one of the following happens:

  • any of the package files in this branch needs updating, or
  • the branch becomes conflicted, or
  • you click the rebase/retry checkbox if found above, or
  • you rename this PR's title to start with "rebase!" to trigger it manually

The artifact failure details are included below:

File name: package-lock.json
npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: @effect/[email protected]
npm error Found: [email protected]
npm error node_modules/effect
npm error   effect@"3.1.3" from the root project
npm error
npm error Could not resolve dependency:
npm error peer effect@"^2.1.1" from @effect/[email protected]
npm error node_modules/@effect/schema
npm error   @effect/schema@"0.60.4" from the root project
npm error
npm error Conflicting peer dependency: [email protected]
npm error node_modules/effect
npm error   peer effect@"^2.1.1" from @effect/[email protected]
npm error   node_modules/@effect/schema
npm error     @effect/schema@"0.60.4" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps
npm error to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error
npm error For a full report see:
npm error /tmp/renovate/cache/others/npm/_logs/2024-05-08T22_22_18_081Z-eresolve-report.txt

npm error A complete log of this run can be found in: /tmp/renovate/cache/others/npm/_logs/2024-05-08T22_22_18_081Z-debug-0.log

@renovate renovate bot force-pushed the renovate/effect-3.x branch 8 times, most recently from ac64789 to 5c44085 Compare April 25, 2024 04:19
@renovate renovate bot force-pushed the renovate/effect-3.x branch 10 times, most recently from 9d2cf0f to d4fa257 Compare May 2, 2024 22:37
@renovate renovate bot force-pushed the renovate/effect-3.x branch 9 times, most recently from b3879b8 to a7c2703 Compare May 8, 2024 22:22
@renovate renovate bot force-pushed the renovate/effect-3.x branch 8 times, most recently from 0810296 to 610e42f Compare March 3, 2025 06:04
@renovate renovate bot force-pushed the renovate/effect-3.x branch 7 times, most recently from 0da6388 to e3ce61b Compare March 10, 2025 05:53
@renovate renovate bot force-pushed the renovate/effect-3.x branch 5 times, most recently from b2b77fd to 050c448 Compare March 17, 2025 22:42
@renovate renovate bot force-pushed the renovate/effect-3.x branch 8 times, most recently from 5180932 to 29c2f74 Compare March 25, 2025 03:58
@renovate renovate bot force-pushed the renovate/effect-3.x branch from 29c2f74 to 1b668a3 Compare March 25, 2025 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
renovate upgrade Any kind of dependency updates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants