effect 4.0.0-beta.15 → 4.0.0-beta.16

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/src/Schema.ts CHANGED
@@ -153,6 +153,7 @@ export interface Bottom<
153
153
  * @throws {Error} The issue is contained in the error cause.
154
154
  */
155
155
  makeUnsafe(input: this["~type.make.in"], options?: MakeOptions): this["Type"]
156
+ makeOption(input: this["~type.make.in"], options?: MakeOptions): Option_.Option<this["Type"]>
156
157
  }
157
158
 
158
159
  /**
@@ -5419,6 +5420,63 @@ export function OptionFromNullOr<S extends Top>(schema: S): OptionFromNullOr<S>
5419
5420
  ))
5420
5421
  }
5421
5422
 
5423
+ /**
5424
+ * @since 4.0.0
5425
+ */
5426
+ export interface OptionFromUndefinedOr<S extends Top> extends decodeTo<Option<toType<S>>, UndefinedOr<S>> {}
5427
+
5428
+ /**
5429
+ * Decodes an undefined-or value `T` to a required `Option<T>` value.
5430
+ *
5431
+ * Decoding:
5432
+ * - `undefined` is decoded as `None`
5433
+ * - other values are decoded as `Some`
5434
+ *
5435
+ * Encoding:
5436
+ * - `None` is encoded as `undefined`
5437
+ * - `Some` is encoded as the value
5438
+ *
5439
+ * @category Option
5440
+ * @since 4.0.0
5441
+ */
5442
+ export function OptionFromUndefinedOr<S extends Top>(schema: S): OptionFromUndefinedOr<S> {
5443
+ return UndefinedOr(schema).pipe(decodeTo(
5444
+ Option(toType(schema)),
5445
+ Transformation.optionFromUndefinedOr()
5446
+ ))
5447
+ }
5448
+
5449
+ /**
5450
+ * @since 4.0.0
5451
+ */
5452
+ export interface OptionFromNullishOr<S extends Top> extends decodeTo<Option<toType<S>>, NullishOr<S>> {}
5453
+
5454
+ /**
5455
+ * Decodes a nullish value `T` to a required `Option<T>` value.
5456
+ *
5457
+ * Decoding:
5458
+ * - `null` and `undefined` are decoded as `None`
5459
+ * - other values are decoded as `Some`
5460
+ *
5461
+ * Encoding:
5462
+ * - `None` is encoded as `null` or `undefined` depending on the provided `options.onNoneEncoding` (defaults to `undefined`)
5463
+ * - `Some` is encoded as the value
5464
+ *
5465
+ * @category Option
5466
+ * @since 4.0.0
5467
+ */
5468
+ export function OptionFromNullishOr<S extends Top>(
5469
+ schema: S,
5470
+ options?: {
5471
+ onNoneEncoding: null | undefined
5472
+ }
5473
+ ): OptionFromNullishOr<S> {
5474
+ return NullishOr(schema).pipe(decodeTo(
5475
+ Option(toType(schema)),
5476
+ Transformation.optionFromNullishOr(options)
5477
+ ))
5478
+ }
5479
+
5422
5480
  /**
5423
5481
  * @since 4.0.0
5424
5482
  */
@@ -7978,6 +8036,9 @@ function makeClass<
7978
8036
  static makeUnsafe(input: S["~type.make.in"], options?: MakeOptions): Self {
7979
8037
  return new this(input, options)
7980
8038
  }
8039
+ static makeOption(input: S["~type.make.in"], options?: MakeOptions): Option_.Option<Self> {
8040
+ return Parser.makeOption(getClassSchema(this) as any)(input, options) as any
8041
+ }
7981
8042
  static annotate(annotations: Annotations.Declaration<Self, readonly [S]>) {
7982
8043
  return this.rebuild(AST.annotate(this.ast, annotations))
7983
8044
  }
@@ -53,6 +53,17 @@ export function makeEffect<S extends Schema.Top>(schema: S) {
53
53
  }
54
54
  }
55
55
 
56
+ /**
57
+ * @category Constructing
58
+ * @since 4.0.0
59
+ */
60
+ export function makeOption<S extends Schema.Top>(schema: S) {
61
+ const parser = makeEffect(schema)
62
+ return (input: S["~type.make.in"], options?: Schema.MakeOptions): Option.Option<S["Type"]> => {
63
+ return Exit.getSuccess(Effect.runSyncExit(parser(input, options) as any))
64
+ }
65
+ }
66
+
56
67
  /**
57
68
  * @category Constructing
58
69
  * @since 4.0.0
@@ -1006,8 +1006,7 @@ export const errorFromErrorJsonEncoded = (options?: {
1006
1006
  * ```
1007
1007
  *
1008
1008
  * See also:
1009
- * - {@link optionFromOptionalKey}
1010
- * - {@link optionFromOptional}
1009
+ * - {@link optionFromNullishOr}
1011
1010
  *
1012
1011
  * @since 4.0.0
1013
1012
  */
@@ -1018,6 +1017,88 @@ export function optionFromNullOr<T>(): Transformation<Option.Option<T>, T | null
1018
1017
  })
1019
1018
  }
1020
1019
 
1020
+ /**
1021
+ * Decodes `T | undefined` into `Option<T>` and encodes `Option<T>` back
1022
+ * to `T | undefined`.
1023
+ *
1024
+ * When to use this:
1025
+ * - Converting undefined-or API fields to `Option`.
1026
+ *
1027
+ * Behavior:
1028
+ * - Decode: `undefined` → `Option.none()`, non-undefined → `Option.some(value)`.
1029
+ * - Encode: `Option.none()` → `undefined`, `Option.some(value)` → `value`.
1030
+ * - Pure and synchronous.
1031
+ *
1032
+ * **Example** (Option from undefined-or)
1033
+ *
1034
+ * ```ts
1035
+ * import { Schema, SchemaTransformation } from "effect"
1036
+ *
1037
+ * const schema = Schema.UndefinedOr(Schema.String).pipe(
1038
+ * Schema.decodeTo(
1039
+ * Schema.Option(Schema.String),
1040
+ * SchemaTransformation.optionFromUndefinedOr()
1041
+ * )
1042
+ * )
1043
+ * ```
1044
+ *
1045
+ * See also:
1046
+ * - {@link optionFromOptionalKey}
1047
+ * - {@link optionFromOptional}
1048
+ *
1049
+ * @since 4.0.0
1050
+ */
1051
+ export function optionFromUndefinedOr<T>(): Transformation<Option.Option<T>, T | undefined> {
1052
+ return transform({
1053
+ decode: Option.fromUndefinedOr,
1054
+ encode: Option.getOrUndefined
1055
+ })
1056
+ }
1057
+
1058
+ /**
1059
+ * Decodes `T | null | undefined` into `Option<T>` and encodes `Option<T>`
1060
+ * back to `T | null` or `T | undefined` depending on the provided `options.onNoneEncoding` (defaults to `undefined`).
1061
+ *
1062
+ * When to use this:
1063
+ * - Converting nullish API fields to `Option` when both `null` and
1064
+ * `undefined` represent absence.
1065
+ *
1066
+ * Behavior:
1067
+ * - Decode: `null` or `undefined` → `Option.none()`, otherwise → `Option.some(value)`.
1068
+ * - Encode: `Option.none()` → `null` or `undefined` (per `options.onNoneEncoding`),
1069
+ * `Option.some(value)` → `value`.
1070
+ * - Pure and synchronous.
1071
+ *
1072
+ * **Example** (Option from nullish, encoding None as null)
1073
+ *
1074
+ * ```ts
1075
+ * import { Schema, SchemaTransformation } from "effect"
1076
+ *
1077
+ * const schema = Schema.NullishOr(Schema.String).pipe(
1078
+ * Schema.decodeTo(
1079
+ * Schema.Option(Schema.String),
1080
+ * SchemaTransformation.optionFromNullishOr({ onNoneEncoding: null })
1081
+ * )
1082
+ * )
1083
+ * ```
1084
+ *
1085
+ * See also:
1086
+ * - {@link optionFromNullOr}
1087
+ * - {@link optionFromUndefinedOr}
1088
+ *
1089
+ * @since 4.0.0
1090
+ */
1091
+ export function optionFromNullishOr<T>(
1092
+ options?: {
1093
+ onNoneEncoding: null | undefined
1094
+ }
1095
+ ): Transformation<Option.Option<T>, T | null | undefined> {
1096
+ return transform({
1097
+ decode: Option.fromNullishOr,
1098
+ encode: options?.onNoneEncoding === null ? Option.getOrNull : Option.getOrUndefined
1099
+ })
1100
+ }
1101
+
1021
1102
  /**
1022
1103
  * Decodes an optional struct key into `Option<T>` and encodes `Option<T>`
1023
1104
  * back to an optional key.
@@ -1047,8 +1128,8 @@ export function optionFromNullOr<T>(): Transformation<Option.Option<T>, T | null
1047
1128
  * ```
1048
1129
  *
1049
1130
  * See also:
1050
- * - {@link optionFromNullOr}
1051
1131
  * - {@link optionFromOptional}
1132
+ * - {@link optionFromUndefinedOr}
1052
1133
  * - {@link transformOptional}
1053
1134
  *
1054
1135
  * @since 4.0.0
@@ -1088,8 +1169,8 @@ export function optionFromOptionalKey<T>(): Transformation<Option.Option<T>, T>
1088
1169
  * ```
1089
1170
  *
1090
1171
  * See also:
1091
- * - {@link optionFromNullOr}
1092
1172
  * - {@link optionFromOptionalKey}
1173
+ * - {@link optionFromUndefinedOr}
1093
1174
  * - {@link transformOptional}
1094
1175
  *
1095
1176
  * @since 4.0.0
@@ -31,5 +31,6 @@ export function make<S extends Schema.Top>(ast: S["ast"], options?: object): S {
31
31
  self.ast = ast
32
32
  self.rebuild = (ast: AST.AST) => make(ast, options)
33
33
  self.makeUnsafe = Parser.makeUnsafe(self)
34
+ self.makeOption = Parser.makeOption(self)
34
35
  return self
35
36
  }
@@ -635,9 +635,26 @@ function toEncodingAST(ast: AST.AST, _tag: HttpApiSchema.Encoding["_tag"]): AST.
635
635
  return Schema.String.ast
636
636
  case "FormUrlEncoded":
637
637
  case "Json":
638
- case "Multipart":
639
638
  return ast
639
+ case "Multipart":
640
+ return persistedFileToBinaryEncoding(ast)
641
+ }
642
+ }
643
+
644
+ function persistedFileToBinaryEncoding(ast: AST.AST): AST.AST {
645
+ if (
646
+ AST.isDeclaration(ast) &&
647
+ ((ast.annotations as (Schema.Annotations.Declaration<unknown, readonly []> | undefined))?.typeConstructor?._tag ===
648
+ "effect/http/PersistedFile")
649
+ ) {
650
+ return Uint8ArrayEncoding.ast
651
+ }
652
+
653
+ if (typeof (ast as any)?.recur === "function") {
654
+ return (ast as any).recur(persistedFileToBinaryEncoding)
640
655
  }
656
+
657
+ return ast
641
658
  }
642
659
 
643
660
  const makeSecurityScheme = (security: HttpApiSecurity): OpenAPISecurityScheme => {