diff --git a/.changeset/forty-rats-decide.md b/.changeset/forty-rats-decide.md new file mode 100644 index 000000000..0a6d39184 --- /dev/null +++ b/.changeset/forty-rats-decide.md @@ -0,0 +1,5 @@ +--- +"@effect/schema": minor +--- + +Schema: refactor `parseJson` to replace `ParseJson` and `fromJson` diff --git a/.changeset/ten-queens-know.md b/.changeset/ten-queens-know.md new file mode 100644 index 000000000..60dc3c5d3 --- /dev/null +++ b/.changeset/ten-queens-know.md @@ -0,0 +1,5 @@ +--- +"@effect/schema": minor +--- + +Schema: simplify `split` parameters to only accept `separator` diff --git a/.changeset/wise-bikes-kick.md b/.changeset/wise-bikes-kick.md new file mode 100644 index 000000000..fd404c2b7 --- /dev/null +++ b/.changeset/wise-bikes-kick.md @@ -0,0 +1,25 @@ +--- +"@effect/schema": minor +--- + +Schema: remove useless combinators + +- `lowercase` +- `uppercase` +- `trim` +- `numberFromString` +- `symbolFromString` +- `bigintFromString` +- `bigintFromNumber` +- `secret` +- `durationFromHrTime` +- `durationFromMillis` +- `durationFromNanos` +- `uint8ArrayFromNumbers` +- `base64` +- `base64url` +- `hex` +- `dateFromString` +- `bigDecimalFromNumber` +- `bigDecimalFromString` +- `not` diff --git a/docs/modules/Schema.ts.md b/docs/modules/Schema.ts.md index b8b904f9b..b1e0cc206 100644 --- a/docs/modules/Schema.ts.md +++ b/docs/modules/Schema.ts.md @@ -13,11 +13,7 @@ Added in v1.0.0

Table of contents

- [BigDecimal constructors](#bigdecimal-constructors) - - [BigDecimal](#bigdecimal) - - [BigDecimalFromNumber](#bigdecimalfromnumber) - [BigDecimalFromSelf](#bigdecimalfromself) - - [bigDecimalFromNumber](#bigdecimalfromnumber-1) - - [bigDecimalFromString](#bigdecimalfromstring) - [BigDecimal filters](#bigdecimal-filters) - [betweenBigDecimal](#betweenbigdecimal) - [greaterThanBigDecimal](#greaterthanbigdecimal) @@ -29,12 +25,15 @@ Added in v1.0.0 - [nonPositiveBigDecimal](#nonpositivebigdecimal) - [positiveBigDecimal](#positivebigdecimal) - [BigDecimal transformations](#bigdecimal-transformations) + - [BigDecimal](#bigdecimal) + - [BigDecimalFromNumber](#bigdecimalfromnumber) - [clampBigDecimal](#clampbigdecimal) - [negateBigDecimal](#negatebigdecimal) -- [Cause](#cause) - - [CauseFrom (type alias)](#causefrom-type-alias) - - [cause](#cause-1) +- [Cause transformations](#cause-transformations) + - [cause](#cause) - [causeFromSelf](#causefromself) +- [Cause utils](#cause-utils) + - [CauseFrom (type alias)](#causefrom-type-alias) - [Chunk transformations](#chunk-transformations) - [chunk](#chunk) - [chunkFromSelf](#chunkfromself) @@ -42,18 +41,14 @@ Added in v1.0.0 - [data](#data) - [dataFromSelf](#datafromself) - [Date constructors](#date-constructors) - - [Date](#date) - [DateFromSelf](#datefromself) - - [DateFromString](#datefromstring) - [ValidDateFromSelf](#validdatefromself) - [Date filters](#date-filters) - [validDate](#validdate) - [Date transformations](#date-transformations) - - [dateFromString](#datefromstring-1) + - [Date](#date) + - [DateFromString](#datefromstring) - [Duration constructors](#duration-constructors) - - [Duration](#duration) - - [DurationFromMillis](#durationfrommillis) - - [DurationFromNanos](#durationfromnanos) - [DurationFromSelf](#durationfromself) - [Duration filters](#duration-filters) - [betweenDuration](#betweenduration) @@ -62,47 +57,55 @@ Added in v1.0.0 - [lessThanDuration](#lessthanduration) - [lessThanOrEqualToDuration](#lessthanorequaltoduration) - [Duration transformations](#duration-transformations) + - [Duration](#duration) + - [DurationFromMillis](#durationfrommillis) + - [DurationFromNanos](#durationfromnanos) - [clampDuration](#clampduration) - - [durationFromHrTime](#durationfromhrtime) - - [durationFromMillis](#durationfrommillis-1) - - [durationFromNanos](#durationfromnanos-1) - [Either transformations](#either-transformations) - - [EitherFrom (type alias)](#eitherfrom-type-alias) - [either](#either) - [eitherFromSelf](#eitherfromself) -- [Exit](#exit) - - [ExitFrom (type alias)](#exitfrom-type-alias) - - [exit](#exit-1) +- [Either utils](#either-utils) + - [EitherFrom (type alias)](#eitherfrom-type-alias) +- [Encoding transformations](#encoding-transformations) + - [Base64](#base64) + - [Base64Url](#base64url) + - [Hex](#hex) +- [Exit transformations](#exit-transformations) + - [exit](#exit) - [exitFromSelf](#exitfromself) +- [Exit utils](#exit-utils) + - [ExitFrom (type alias)](#exitfrom-type-alias) - [FiberId](#fiberid) - - [FiberId](#fiberid-1) - [FiberIdFrom (type alias)](#fiberidfrom-type-alias) +- [FiberId constructors](#fiberid-constructors) - [FiberIdFromSelf](#fiberidfromself) +- [FiberId transformations](#fiberid-transformations) + - [FiberId](#fiberid-1) - [Option transformations](#option-transformations) - - [OptionFrom (type alias)](#optionfrom-type-alias) - [option](#option) - [optionFromNullable](#optionfromnullable) - [optionFromNullish](#optionfromnullish) - [optionFromSelf](#optionfromself) +- [Option utils](#option-utils) + - [OptionFrom (type alias)](#optionfrom-type-alias) - [ReadonlyArray filters](#readonlyarray-filters) - [itemsCount](#itemscount) - [maxItems](#maxitems) - [minItems](#minitems) - [ReadonlyMap transformations](#readonlymap-transformations) - [readonlyMap](#readonlymap) + - [readonlyMapFromSelf](#readonlymapfromself) - [ReadonlySet transformations](#readonlyset-transformations) - [readonlySet](#readonlyset) - [readonlySetFromSelf](#readonlysetfromself) - [Secret constructors](#secret-constructors) - - [Secret](#secret) - [SecretFromSelf](#secretfromself) - [Secret transformations](#secret-transformations) - - [secret](#secret-1) + - [Secret](#secret) - [Uint8Array constructors](#uint8array-constructors) - - [Uint8Array](#uint8array) - [Uint8ArrayFromSelf](#uint8arrayfromself) - [Uint8Array transformations](#uint8array-transformations) - - [uint8ArrayFromNumbers](#uint8arrayfromnumbers) + - [Uint8Array](#uint8array) - [annotations](#annotations) - [annotations](#annotations-1) - [default](#default) @@ -115,7 +118,6 @@ Added in v1.0.0 - [message](#message) - [title](#title) - [bigint constructors](#bigint-constructors) - - [BigintFromNumber](#bigintfromnumber) - [NegativeBigint](#negativebigint) - [NegativeBigintFromSelf](#negativebigintfromself) - [NonNegativeBigint](#nonnegativebigint) @@ -124,7 +126,6 @@ Added in v1.0.0 - [NonPositiveBigintFromSelf](#nonpositivebigintfromself) - [PositiveBigint](#positivebigint) - [PositiveBigintFromSelf](#positivebigintfromself) - - [bigint](#bigint) - [bigint filters](#bigint-filters) - [betweenBigint](#betweenbigint) - [greaterThanBigint](#greaterthanbigint) @@ -136,13 +137,11 @@ Added in v1.0.0 - [nonPositiveBigint](#nonpositivebigint-1) - [positiveBigint](#positivebigint-1) - [bigint transformations](#bigint-transformations) - - [bigintFromNumber](#bigintfromnumber-1) - - [bigintFromString](#bigintfromstring) + - [BigintFromNumber](#bigintfromnumber) + - [bigint](#bigint) - [clampBigint](#clampbigint) -- [boolean constructors](#boolean-constructors) - - [Not](#not) - [boolean transformations](#boolean-transformations) - - [not](#not-1) + - [Not](#not) - [classes](#classes) - [Class](#class) - [Class (interface)](#class-interface) @@ -202,14 +201,6 @@ Added in v1.0.0 - [encodeOption](#encodeoption) - [encodePromise](#encodepromise) - [encodeSync](#encodesync) -- [encoding constructors](#encoding-constructors) - - [Base64](#base64) - - [Base64Url](#base64url) - - [Hex](#hex) -- [encoding transformations](#encoding-transformations) - - [base64](#base64-1) - - [base64url](#base64url-1) - - [hex](#hex-1) - [guards](#guards) - [isSchema](#isschema) - [model](#model) @@ -241,7 +232,6 @@ Added in v1.0.0 - [positive](#positive-1) - [number transformations](#number-transformations) - [clamp](#clamp) - - [numberFromString](#numberfromstring-1) - [optional](#optional) - [optionalToRequired](#optionaltorequired) - [parsing](#parsing) @@ -267,8 +257,6 @@ Added in v1.0.0 - [rename](#rename) - [string constructors](#string-constructors) - [NonEmpty](#nonempty) - - [ParseJson](#parsejson) - - [Trim](#trim) - [Trimmed](#trimmed) - [ULID](#ulid) - [UUID](#uuid) @@ -286,20 +274,15 @@ Added in v1.0.0 - [uppercased](#uppercased) - [string transformations](#string-transformations) - [Lowercase](#lowercase) + - [Trim](#trim) - [Uppercase](#uppercase) - - [fromJson](#fromjson) - - [lowercase](#lowercase-1) - - [parseJson](#parsejson-1) + - [parseJson](#parsejson) - [split](#split) - - [trim](#trim-1) - - [uppercase](#uppercase-1) - [symbol](#symbol) - [TypeId](#typeid) - [TypeId (type alias)](#typeid-type-alias) -- [symbol constructors](#symbol-constructors) - - [symbol](#symbol-1) - [symbol transformations](#symbol-transformations) - - [symbolFromString](#symbolfromstring) + - [symbol](#symbol-1) - [type id](#type-id) - [BetweenBigDecimalTypeId](#betweenbigdecimaltypeid) - [BetweenBigintTypeId](#betweenbiginttypeid) @@ -371,7 +354,7 @@ Added in v1.0.0 - [FromOptionalKeys (type alias)](#fromoptionalkeys-type-alias) - [FromStruct (type alias)](#fromstruct-type-alias) - [Join (type alias)](#join-type-alias) - - [JsonOptions (type alias)](#jsonoptions-type-alias) + - [ParseJsonOptions (type alias)](#parsejsonoptions-type-alias) - [PropertySignature (interface)](#propertysignature-interface) - [Schema (namespace)](#schema-namespace) - [Variance (interface)](#variance-interface) @@ -384,7 +367,6 @@ Added in v1.0.0 - [from](#from) - [optional](#optional-1) - [propertySignatureAnnotations](#propertysignatureannotations) - - [readonlyMapFromSelf](#readonlymapfromself) - [to](#to) - [validation](#validation) - [asserts](#asserts) @@ -399,29 +381,6 @@ Added in v1.0.0 # BigDecimal constructors -## BigDecimal - -**Signature** - -```ts -export declare const BigDecimal: Schema -``` - -Added in v1.0.0 - -## BigDecimalFromNumber - -A schema that transforms a `number` into a `BigDecimal`. -When encoding, this Schema will produce incorrect results if the BigDecimal exceeds the 64-bit range of a number. - -**Signature** - -```ts -export declare const BigDecimalFromNumber: Schema -``` - -Added in v1.0.0 - ## BigDecimalFromSelf **Signature** @@ -432,31 +391,6 @@ export declare const BigDecimalFromSelf: Schema(self: Schema) => Schema -``` - -Added in v1.0.0 - -## bigDecimalFromString - -A schema that transforms a `string` into a `BigDecimal`. - -**Signature** - -```ts -export declare const bigDecimalFromString: (self: Schema) => Schema -``` - -Added in v1.0.0 - # BigDecimal filters ## betweenBigDecimal @@ -575,6 +509,29 @@ Added in v1.0.0 # BigDecimal transformations +## BigDecimal + +**Signature** + +```ts +export declare const BigDecimal: Schema +``` + +Added in v1.0.0 + +## BigDecimalFromNumber + +A schema that transforms a `number` into a `BigDecimal`. +When encoding, this Schema will produce incorrect results if the BigDecimal exceeds the 64-bit range of a number. + +**Signature** + +```ts +export declare const BigDecimalFromNumber: Schema +``` + +Added in v1.0.0 + ## clampBigDecimal Clamps a `BigDecimal` between a minimum and a maximum value. @@ -602,7 +559,35 @@ export declare const negateBigDecimal: (self Added in v1.0.0 -# Cause +# Cause transformations + +## cause + +**Signature** + +```ts +export declare const cause: ( + error: Schema, + defect?: Schema +) => Schema, Cause.Cause> +``` + +Added in v1.0.0 + +## causeFromSelf + +**Signature** + +```ts +export declare const causeFromSelf: ( + error: Schema, + defect?: Schema +) => Schema, Cause.Cause> +``` + +Added in v1.0.0 + +# Cause utils ## CauseFrom (type alias) @@ -639,32 +624,6 @@ export type CauseFrom = Added in v1.0.0 -## cause - -**Signature** - -```ts -export declare const cause: ( - error: Schema, - defect?: Schema -) => Schema, Cause.Cause> -``` - -Added in v1.0.0 - -## causeFromSelf - -**Signature** - -```ts -export declare const causeFromSelf: ( - error: Schema, - defect?: Schema -) => Schema, Cause.Cause> -``` - -Added in v1.0.0 - # Chunk transformations ## chunk @@ -721,18 +680,6 @@ Added in v1.0.0 # Date constructors -## Date - -A schema that transforms a `string` into a **valid** `Date`, ensuring that invalid dates, such as `new Date("Invalid Date")`, are rejected. - -**Signature** - -```ts -export declare const Date: Schema -``` - -Added in v1.0.0 - ## DateFromSelf Represents a schema for handling potentially **invalid** `Date` instances (e.g., `new Date("Invalid Date")` is not rejected). @@ -745,18 +692,6 @@ export declare const DateFromSelf: Schema Added in v1.0.0 -## DateFromString - -Represents a schema that converts a `string` into a (potentially invalid) `Date` (e.g., `new Date("Invalid Date")` is not rejected). - -**Signature** - -```ts -export declare const DateFromString: Schema -``` - -Added in v1.0.0 - ## ValidDateFromSelf Represents a schema for handling only **valid** dates. For example, `new Date("Invalid Date")` is rejected, even though it is an instance of `Date`. @@ -785,57 +720,31 @@ Added in v1.0.0 # Date transformations -## dateFromString - -A combinator that converts a `string` into a potentially **invalid** `Date` (e.g., `new Date("Invalid Date")` is not rejected). - -**Signature** - -```ts -export declare const dateFromString: (self: Schema) => Schema -``` - -Added in v1.0.0 - -# Duration constructors - -## Duration +## Date -A schema that transforms a `[number, number]` tuple into a `Duration`. +A schema that transforms a `string` into a **valid** `Date`, ensuring that invalid dates, such as `new Date("Invalid Date")`, are rejected. **Signature** ```ts -export declare const Duration: Schema +export declare const Date: Schema ``` Added in v1.0.0 -## DurationFromMillis +## DateFromString -A schema that transforms a `number` tuple into a `Duration`. -Treats the value as the number of milliseconds. +Represents a schema that converts a `string` into a (potentially invalid) `Date` (e.g., `new Date("Invalid Date")` is not rejected). **Signature** ```ts -export declare const DurationFromMillis: Schema +export declare const DateFromString: Schema ``` Added in v1.0.0 -## DurationFromNanos - -A schema that transforms a `bigint` tuple into a `Duration`. -Treats the value as the number of nanoseconds. - -**Signature** - -```ts -export declare const DurationFromNanos: Schema -``` - -Added in v1.0.0 +# Duration constructors ## DurationFromSelf @@ -917,63 +826,89 @@ Added in v1.0.0 # Duration transformations -## clampDuration +## Duration -Clamps a `Duration` between a minimum and a maximum value. +A schema that transforms a `[number, number]` tuple into a `Duration`. **Signature** ```ts -export declare const clampDuration: ( - minimum: Duration.DurationInput, - maximum: Duration.DurationInput -) => (self: Schema) => Schema +export declare const Duration: Schema ``` Added in v1.0.0 -## durationFromHrTime +## DurationFromMillis -A combinator that transforms a `[number, number]` tuple into a `Duration`. +A schema that transforms a `number` tuple into a `Duration`. +Treats the value as the number of milliseconds. **Signature** ```ts -export declare const durationFromHrTime: ( - self: Schema -) => Schema +export declare const DurationFromMillis: Schema ``` Added in v1.0.0 -## durationFromMillis +## DurationFromNanos -A combinator that transforms a `number` into a `Duration`. -Treats the value as the number of milliseconds. +A schema that transforms a `bigint` tuple into a `Duration`. +Treats the value as the number of nanoseconds. **Signature** ```ts -export declare const durationFromMillis: (self: Schema) => Schema +export declare const DurationFromNanos: Schema ``` Added in v1.0.0 -## durationFromNanos +## clampDuration -A combinator that transforms a `bigint` into a `Duration`. -Treats the value as the number of nanoseconds. +Clamps a `Duration` between a minimum and a maximum value. **Signature** ```ts -export declare const durationFromNanos: (self: Schema) => Schema +export declare const clampDuration: ( + minimum: Duration.DurationInput, + maximum: Duration.DurationInput +) => (self: Schema) => Schema ``` Added in v1.0.0 # Either transformations +## either + +**Signature** + +```ts +export declare const either: ( + left: Schema, + right: Schema +) => Schema, Either.Either> +``` + +Added in v1.0.0 + +## eitherFromSelf + +**Signature** + +```ts +export declare const eitherFromSelf: ( + left: Schema, + right: Schema +) => Schema, Either.Either> +``` + +Added in v1.0.0 + +# Either utils + ## EitherFrom (type alias) **Signature** @@ -992,52 +927,40 @@ export type EitherFrom = Added in v1.0.0 -## either +# Encoding transformations + +## Base64 **Signature** ```ts -export declare const either: ( - left: Schema, - right: Schema -) => Schema, Either.Either> +export declare const Base64: Schema ``` Added in v1.0.0 -## eitherFromSelf +## Base64Url **Signature** ```ts -export declare const eitherFromSelf: ( - left: Schema, - right: Schema -) => Schema, Either.Either> +export declare const Base64Url: Schema ``` Added in v1.0.0 -# Exit - -## ExitFrom (type alias) +## Hex **Signature** ```ts -export type ExitFrom = - | { - readonly _tag: "Failure" - readonly cause: CauseFrom - } - | { - readonly _tag: "Success" - readonly value: A - } +export declare const Hex: Schema ``` Added in v1.0.0 +# Exit transformations + ## exit **Signature** @@ -1066,18 +989,28 @@ export declare const exitFromSelf: ( Added in v1.0.0 -# FiberId +# Exit utils -## FiberId +## ExitFrom (type alias) **Signature** ```ts -export declare const FiberId: Schema +export type ExitFrom = + | { + readonly _tag: "Failure" + readonly cause: CauseFrom + } + | { + readonly _tag: "Success" + readonly value: A + } ``` Added in v1.0.0 +# FiberId + ## FiberIdFrom (type alias) **Signature** @@ -1101,6 +1034,8 @@ export type FiberIdFrom = Added in v1.0.0 +# FiberId constructors + ## FiberIdFromSelf **Signature** @@ -1111,25 +1046,20 @@ export declare const FiberIdFromSelf: Schema Added in v1.0.0 -# Option transformations +# FiberId transformations -## OptionFrom (type alias) +## FiberId **Signature** ```ts -export type OptionFrom = - | { - readonly _tag: "None" - } - | { - readonly _tag: "Some" - readonly value: I - } +export declare const FiberId: Schema ``` Added in v1.0.0 +# Option transformations + ## option **Signature** @@ -1163,12 +1093,31 @@ export declare const optionFromNullish: ( Added in v1.0.0 -## optionFromSelf +## optionFromSelf + +**Signature** + +```ts +export declare const optionFromSelf: (value: Schema) => Schema, Option.Option> +``` + +Added in v1.0.0 + +# Option utils + +## OptionFrom (type alias) **Signature** ```ts -export declare const optionFromSelf: (value: Schema) => Schema, Option.Option> +export type OptionFrom = + | { + readonly _tag: "None" + } + | { + readonly _tag: "Some" + readonly value: I + } ``` Added in v1.0.0 @@ -1229,42 +1178,43 @@ export declare const readonlyMap: ( Added in v1.0.0 -# ReadonlySet transformations - -## readonlySet +## readonlyMapFromSelf **Signature** ```ts -export declare const readonlySet: (item: Schema) => Schema> +export declare const readonlyMapFromSelf: ( + key: Schema, + value: Schema +) => Schema, ReadonlyMap> ``` Added in v1.0.0 -## readonlySetFromSelf +# ReadonlySet transformations + +## readonlySet **Signature** ```ts -export declare const readonlySetFromSelf: (item: Schema) => Schema, ReadonlySet> +export declare const readonlySet: (item: Schema) => Schema> ``` Added in v1.0.0 -# Secret constructors - -## Secret - -A schema that transforms a `string` into a `Secret`. +## readonlySetFromSelf **Signature** ```ts -export declare const Secret: Schema +export declare const readonlySetFromSelf: (item: Schema) => Schema, ReadonlySet> ``` Added in v1.0.0 +# Secret constructors + ## SecretFromSelf **Signature** @@ -1277,32 +1227,20 @@ Added in v1.0.0 # Secret transformations -## secret +## Secret -A combinator that transforms a `string` into a `Secret`. +A schema that transforms a `string` into a `Secret`. **Signature** ```ts -export declare const secret: (self: Schema) => Schema +export declare const Secret: Schema ``` Added in v1.0.0 # Uint8Array constructors -## Uint8Array - -A schema that transforms a `number` array into a `Uint8Array`. - -**Signature** - -```ts -export declare const Uint8Array: Schema -``` - -Added in v1.0.0 - ## Uint8ArrayFromSelf **Signature** @@ -1315,16 +1253,14 @@ Added in v1.0.0 # Uint8Array transformations -## uint8ArrayFromNumbers +## Uint8Array -A combinator that transforms a `number` array into a `Uint8Array`. +A schema that transforms a `number` array into a `Uint8Array`. **Signature** ```ts -export declare const uint8ArrayFromNumbers: ( - self: Schema -) => Schema +export declare const Uint8Array: Schema ``` Added in v1.0.0 @@ -1441,20 +1377,6 @@ Added in v1.0.0 # bigint constructors -## BigintFromNumber - -This schema transforms a `number` into a `bigint` by parsing the number using the `BigInt` function. - -It returns an error if the value can't be safely encoded as a `number` due to being out of range. - -**Signature** - -```ts -export declare const BigintFromNumber: Schema -``` - -Added in v1.0.0 - ## NegativeBigint **Signature** @@ -1535,20 +1457,6 @@ export declare const PositiveBigintFromSelf: Schema Added in v1.0.0 -## bigint - -This schema transforms a `string` into a `bigint` by parsing the string using the `BigInt` function. - -It returns an error if the value can't be converted (for example when non-numeric characters are provided). - -**Signature** - -```ts -export declare const bigint: Schema -``` - -Added in v1.0.0 - # bigint filters ## betweenBigint @@ -1667,30 +1575,30 @@ Added in v1.0.0 # bigint transformations -## bigintFromNumber +## BigintFromNumber -This combinator transforms a `number` into a `bigint` by parsing the number using the `BigInt` function. +This schema transforms a `number` into a `bigint` by parsing the number using the `BigInt` function. It returns an error if the value can't be safely encoded as a `number` due to being out of range. **Signature** ```ts -export declare const bigintFromNumber: (self: Schema) => Schema +export declare const BigintFromNumber: Schema ``` Added in v1.0.0 -## bigintFromString +## bigint -This combinator transforms a `string` into a `bigint` by parsing the string using the `BigInt` function. +This schema transforms a `string` into a `bigint` by parsing the string using the `BigInt` function. It returns an error if the value can't be converted (for example when non-numeric characters are provided). **Signature** ```ts -export declare const bigintFromString: (self: Schema) => Schema +export declare const bigint: Schema ``` Added in v1.0.0 @@ -1710,7 +1618,7 @@ export declare const clampBigint: ( Added in v1.0.0 -# boolean constructors +# boolean transformations ## Not @@ -1722,20 +1630,6 @@ export declare const Not: Schema Added in v1.0.0 -# boolean transformations - -## not - -Negates a boolean value - -**Signature** - -```ts -export declare const not: (self: Schema) => Schema -``` - -Added in v1.0.0 - # classes ## Class @@ -2630,76 +2524,6 @@ export declare const encodeSync: (schema: Schema) => (a: A, options? Added in v1.0.0 -# encoding constructors - -## Base64 - -**Signature** - -```ts -export declare const Base64: Schema -``` - -Added in v1.0.0 - -## Base64Url - -**Signature** - -```ts -export declare const Base64Url: Schema -``` - -Added in v1.0.0 - -## Hex - -**Signature** - -```ts -export declare const Hex: Schema -``` - -Added in v1.0.0 - -# encoding transformations - -## base64 - -Transforms a base64 `string` into a `Uint8Array`. - -**Signature** - -```ts -export declare const base64: (self: Schema) => Schema -``` - -Added in v1.0.0 - -## base64url - -Transforms a base64url `string` into a `Uint8Array`. - -**Signature** - -```ts -export declare const base64url: (self: Schema) => Schema -``` - -Added in v1.0.0 - -## hex - -Transforms a hex `string` into a `Uint8Array`. - -**Signature** - -```ts -export declare const hex: (self: Schema) => Schema -``` - -Added in v1.0.0 - # guards ## isSchema @@ -3035,22 +2859,6 @@ export declare const clamp: ( Added in v1.0.0 -## numberFromString - -This combinator transforms a `string` into a `number` by parsing the string using the `Number` function. - -It returns an error if the value can't be converted (for example when non-numeric characters are provided). - -The following special string values are supported: "NaN", "Infinity", "-Infinity". - -**Signature** - -```ts -export declare const numberFromString: (self: Schema) => Schema -``` - -Added in v1.0.0 - # optional ## optionalToRequired @@ -3294,31 +3102,6 @@ export declare const NonEmpty: Schema Added in v1.0.0 -## ParseJson - -The `ParseJson` schema offers a method to convert JSON strings into the `unknown` type using the underlying -functionality of `JSON.parse`. It also employs `JSON.stringify` for encoding. - -**Signature** - -```ts -export declare const ParseJson: Schema -``` - -Added in v1.0.0 - -## Trim - -This schema allows removing whitespaces from the beginning and end of a string. - -**Signature** - -```ts -export declare const Trim: Schema -``` - -Added in v1.0.0 - ## Trimmed **Signature** @@ -3392,10 +3175,7 @@ Added in v1.0.0 ## lowercased -Verifies that a string is lowercased - -Note. This combinator does not make any transformations, it only validates. -If what you were looking for was a combinator to lowercase strings, then check out the `lowercase` combinator. +Verifies that a string is lowercased. **Signature** @@ -3490,10 +3270,7 @@ Added in v1.0.0 ## uppercased -Verifies that a string is uppercased - -Note. This combinator does not make any transformations, it only validates. -If what you were looking for was a combinator to uppercase strings, then check out the `uppercase` combinator. +Verifies that a string is uppercased. **Signature** @@ -3509,7 +3286,7 @@ Added in v1.0.0 ## Lowercase -This combinator converts a string to lowercase +This schema converts a string to lowercase. **Signature** @@ -3519,91 +3296,67 @@ export declare const Lowercase: Schema Added in v1.0.0 -## Uppercase - -This combinator converts a string to uppercase - -**Signature** - -```ts -export declare const Uppercase: Schema -``` - -Added in v1.0.0 - -## fromJson +## Trim -The `fromJson` combinator offers a method to convert JSON strings into the `A` type using the underlying -functionality of `JSON.parse`. It also employs `JSON.stringify` for encoding. +This schema allows removing whitespaces from the beginning and end of a string. **Signature** ```ts -export declare const fromJson: (schema: Schema, options?: JsonOptions) => Schema +export declare const Trim: Schema ``` Added in v1.0.0 -## lowercase +## Uppercase -This combinator converts a string to lowercase +This schema converts a string to uppercase. **Signature** ```ts -export declare const lowercase: (self: Schema) => Schema +export declare const Uppercase: Schema ``` Added in v1.0.0 ## parseJson -The `parseJson` combinator offers a method to convert JSON strings into the `unknown` type using the underlying -functionality of `JSON.parse`. It also employs `JSON.stringify` for encoding. - -**Signature** - -```ts -export declare const parseJson: (self: Schema, options?: JsonOptions) => Schema -``` - -Added in v1.0.0 +The `parseJson` combinator provides a method to convert JSON strings into the `unknown` type using the underlying +functionality of `JSON.parse`. It also utilizes `JSON.stringify` for encoding. -## split +You can optionally provide a `ParseJsonOptions` to configure both `JSON.parse` and `JSON.stringify` executions. -This combinator allows splitting a string into an array of strings. +Optionally, you can pass a schema `Schema` to obtain an `A` type instead of `unknown`. **Signature** ```ts -export declare const split: { - (separator: string): (self: Schema) => Schema - (self: Schema, separator: string): Schema +export declare const parseJson: { + (schema: Schema, options?: ParseJsonOptions): Schema + (options?: ParseJsonOptions): Schema } ``` -Added in v1.0.0 - -## trim - -This combinator allows removing whitespaces from the beginning and end of a string. - -**Signature** +**Example** ```ts -export declare const trim: (self: Schema) => Schema +import * as S from "@effect/schema/Schema" + +assert.deepStrictEqual(S.parseSync(S.parseJson())(`{"a":"1"}`), { a: "1" }) +assert.deepStrictEqual(S.parseSync(S.parseJson(S.struct({ a: S.NumberFromString })))(`{"a":"1"}`), { a: 1 }) ``` Added in v1.0.0 -## uppercase +## split -This combinator converts a string to uppercase +Returns a achema that allows splitting a string into an array of strings. **Signature** ```ts -export declare const uppercase: (self: Schema) => Schema +export declare const split: (separator: string) => Schema> ``` Added in v1.0.0 @@ -3630,7 +3383,7 @@ export type TypeId = typeof TypeId Added in v1.0.0 -# symbol constructors +# symbol transformations ## symbol @@ -3644,20 +3397,6 @@ export declare const symbol: Schema Added in v1.0.0 -# symbol transformations - -## symbolFromString - -This combinator transforms a `string` into a `symbol`. - -**Signature** - -```ts -export declare const symbolFromString: (self: Schema) => Schema -``` - -Added in v1.0.0 - # type id ## BetweenBigDecimalTypeId @@ -4381,12 +4120,12 @@ export type Join = T extends [infer Head, ...infer Tail] Added in v1.0.0 -## JsonOptions (type alias) +## ParseJsonOptions (type alias) **Signature** ```ts -export type JsonOptions = { +export type ParseJsonOptions = { readonly reviver?: Parameters[1] readonly replacer?: Parameters[1] readonly space?: Parameters[2] @@ -4578,19 +4317,6 @@ export declare const propertySignatureAnnotations: ( Added in v1.0.0 -## readonlyMapFromSelf - -**Signature** - -```ts -export declare const readonlyMapFromSelf: ( - key: Schema, - value: Schema -) => Schema, ReadonlyMap> -``` - -Added in v1.0.0 - ## to **Signature** diff --git a/dtslint/Schema.ts b/dtslint/Schema.ts index 59af16a2b..ddda99165 100644 --- a/dtslint/Schema.ts +++ b/dtslint/Schema.ts @@ -659,10 +659,10 @@ pipe(S.number, S.filter((n): n is number & Brand.Brand<"MyNumber"> => n > 0)) // plain // $ExpectType Schema -S.compose(S.split(S.string, ","), S.array(S.NumberFromString)) +S.compose(S.split(","), S.array(S.NumberFromString)) // $ExpectType Schema -S.split(S.string, ",").pipe(S.compose(S.array(S.NumberFromString))) +S.split(",").pipe(S.compose(S.array(S.NumberFromString))) // decoding @@ -781,14 +781,6 @@ S.transformLiteral(0, "a") // $ExpectType Schema<0 | 1, "a" | "b"> S.transformLiterals([0, "a"], [1, "b"]) -// --------------------------------------------- -// split -// --------------------------------------------- - -// should support subtypes of `string` -// $ExpectType Schema<`a${string}`, readonly string[]> -S.templateLiteral(S.literal("a"), S.string).pipe(S.split(":")) - // --------------------------------------------- // Class // --------------------------------------------- @@ -837,15 +829,9 @@ S.BigDecimal // $ExpectType Schema S.BigDecimalFromSelf -// $ExpectType Schema -S.bigDecimalFromNumber(S.number) - // $ExpectType Schema S.BigDecimalFromNumber -// $ExpectType Schema -S.bigDecimalFromString(S.string) - // --------------------------------------------- // Duration // --------------------------------------------- @@ -856,15 +842,9 @@ S.Duration // $ExpectType Schema S.DurationFromSelf -// $ExpectType Schema -S.durationFromMillis(S.number) - // $ExpectType Schema S.DurationFromMillis -// $ExpectType Schema -S.durationFromNanos(S.bigintFromSelf) - // $ExpectType Schema S.DurationFromNanos @@ -878,9 +858,6 @@ S.Secret // $ExpectType Schema S.SecretFromSelf -// $ExpectType Schema -S.secret(S.string) - // --------------------------------------------- // propertySignatureAnnotations // --------------------------------------------- diff --git a/src/Schema.ts b/src/Schema.ts index bc7177640..747a91fe1 100644 --- a/src/Schema.ts +++ b/src/Schema.ts @@ -43,10 +43,6 @@ import * as ParseResult from "./ParseResult.js" import * as Pretty from "./Pretty.js" import type * as Serializable from "./Serializable.js" -// --------------------------------------------- -// model -// --------------------------------------------- - /** * @since 1.0.0 * @category symbol @@ -113,10 +109,6 @@ export const from = (schema: Schema): Schema => make(AST.from(sch */ export const to = (schema: Schema): Schema => make(AST.to(schema.ast)) -// --------------------------------------------- -// decoding / encoding / parsing / validating / asserts / guards -// --------------------------------------------- - /* c8 ignore start */ export { /** @@ -232,10 +224,6 @@ export { } from "./Parser.js" /* c8 ignore end */ -// --------------------------------------------- -// guards -// --------------------------------------------- - /** * Tests if a value is a `Schema`. * @@ -245,10 +233,6 @@ export { export const isSchema = (u: unknown): u is Schema => Predicate.isObject(u) && TypeId in u && "ast" in u -// --------------------------------------------- -// constructors -// --------------------------------------------- - const variance = { From: (_: any) => _, To: (_: any) => _ @@ -455,10 +439,6 @@ export const instanceOf = any>( ) } -// --------------------------------------------- -// primitives -// --------------------------------------------- - const _undefined: Schema = make(AST.undefinedKeyword) const _void: Schema = make(AST.voidKeyword) @@ -537,10 +517,6 @@ export const symbolFromSelf: Schema = make(AST.symbolKeyword) */ export const object: Schema = make(AST.objectKeyword) -// --------------------------------------------- -// combinators -// --------------------------------------------- - /** * @category combinators * @since 1.0.0 @@ -1539,10 +1515,6 @@ export const attachPropertySignature: { ) ))) -// --------------------------------------------- -// annotations -// --------------------------------------------- - const toAnnotations = ( options?: FilterAnnotations ): Mutable => { @@ -1706,10 +1678,6 @@ export const equivalence = (equivalence: Equivalence.Equivalence) => (self: Schema): Schema => make(AST.setAnnotation(self.ast, hooks.EquivalenceHookId, () => equivalence)) -// --------------------------------------------- -// property signature renaming -// --------------------------------------------- - type Rename = { [ K in keyof A as K extends keyof M ? M[K] extends PropertyKey ? M[K] @@ -1757,10 +1725,6 @@ export const rename: { } ) -// --------------------------------------------- -// string filters -// --------------------------------------------- - /** * @category type id * @since 1.0.0 @@ -1974,10 +1938,7 @@ export const includes = ( export const LowercasedTypeId = Symbol.for("@effect/schema/TypeId/Lowercased") /** - * Verifies that a string is lowercased - * - * Note. This combinator does not make any transformations, it only validates. - * If what you were looking for was a combinator to lowercase strings, then check out the `lowercase` combinator. + * Verifies that a string is lowercased. * * @category string filters * @since 1.0.0 @@ -1999,10 +1960,7 @@ export const lowercased = export const UppercasedTypeId = Symbol.for("@effect/schema/TypeId/Uppercased") /** - * Verifies that a string is uppercased - * - * Note. This combinator does not make any transformations, it only validates. - * If what you were looking for was a combinator to uppercase strings, then check out the `uppercase` combinator. + * Verifies that a string is uppercased. * * @category string filters * @since 1.0.0 @@ -2059,114 +2017,95 @@ export const nonEmpty = ( ...options }) -// --------------------------------------------- -// string transformations -// --------------------------------------------- - /** - * This combinator converts a string to lowercase + * This schema converts a string to lowercase. * * @category string transformations * @since 1.0.0 */ -export const lowercase = (self: Schema): Schema => - transform( - self, - to(self).pipe(lowercased()), - (s) => s.toLowerCase(), - identity, - { strict: false } - ) - -/** - * This combinator converts a string to lowercase - * - * @category string transformations - * @since 1.0.0 - */ -export const Lowercase: Schema = lowercase(string) +export const Lowercase: Schema = transform( + string, + string.pipe(lowercased()), + (s) => s.toLowerCase(), + identity +) /** - * This combinator converts a string to uppercase + * This schema converts a string to uppercase. * * @category string transformations * @since 1.0.0 */ -export const uppercase = (self: Schema): Schema => - transform( - self, - to(self).pipe(uppercased()), - (s) => s.toUpperCase(), - identity, - { strict: false } - ) +export const Uppercase: Schema = transform( + string, + string.pipe(uppercased()), + (s) => s.toUpperCase(), + identity +) /** - * This combinator converts a string to uppercase + * This schema allows removing whitespaces from the beginning and end of a string. * * @category string transformations * @since 1.0.0 */ -export const Uppercase: Schema = uppercase(string) +export const Trim: Schema = transform( + string, + string.pipe(trimmed()), + (s) => s.trim(), + identity +) /** - * This combinator allows removing whitespaces from the beginning and end of a string. + * Returns a achema that allows splitting a string into an array of strings. * * @category string transformations * @since 1.0.0 */ -export const trim = (self: Schema): Schema => +export const split = (separator: string): Schema> => transform( - self, - to(self).pipe(trimmed()), - (s) => s.trim(), - identity, - { strict: false } + string, + array(string), + S.split(separator), + ReadonlyArray.join(separator) ) -/** - * This combinator allows splitting a string into an array of strings. - * - * @category string transformations - * @since 1.0.0 - */ -export const split: { - (separator: string): (self: Schema) => Schema> - (self: Schema, separator: string): Schema> -} = dual( - 2, - (self: Schema, separator: string): Schema> => - transform( - self, - array(string), - S.split(separator), - ReadonlyArray.join(separator), - { strict: false } - ) -) - /** * @since 1.0.0 */ -export type JsonOptions = { +export type ParseJsonOptions = { readonly reviver?: Parameters[1] readonly replacer?: Parameters[1] readonly space?: Parameters[2] } /** - * The `parseJson` combinator offers a method to convert JSON strings into the `unknown` type using the underlying - * functionality of `JSON.parse`. It also employs `JSON.stringify` for encoding. + * The `parseJson` combinator provides a method to convert JSON strings into the `unknown` type using the underlying + * functionality of `JSON.parse`. It also utilizes `JSON.stringify` for encoding. + * + * You can optionally provide a `ParseJsonOptions` to configure both `JSON.parse` and `JSON.stringify` executions. + * + * Optionally, you can pass a schema `Schema` to obtain an `A` type instead of `unknown`. + * + * @example + * import * as S from "@effect/schema/Schema" + * + * assert.deepStrictEqual(S.parseSync(S.parseJson())(`{"a":"1"}`), { a: "1" }) + * assert.deepStrictEqual(S.parseSync(S.parseJson(S.struct({ a: S.NumberFromString })))(`{"a":"1"}`), { a: 1 }) * * @category string transformations * @since 1.0.0 */ -export const parseJson = ( - self: Schema, - options?: JsonOptions -): Schema => { +export const parseJson: { + (schema: Schema, options?: ParseJsonOptions): Schema + (options?: ParseJsonOptions): Schema +} = (schema?: Schema | ParseJsonOptions, o?: ParseJsonOptions) => { + if (isSchema(schema)) { + return compose(parseJson(o), schema) + } + const options: ParseJsonOptions | undefined = schema as any return transformOrFail( - self, + string, unknown, (s, _, ast) => ParseResult.try({ @@ -2177,27 +2116,10 @@ export const parseJson = ( ParseResult.try({ try: () => JSON.stringify(u, options?.replacer, options?.space), catch: (e: any) => ParseResult.parseError([ParseResult.type(ast, u, e.message)]) - }), - { strict: false } + }) ) } -/** - * The `fromJson` combinator offers a method to convert JSON strings into the `A` type using the underlying - * functionality of `JSON.parse`. It also employs `JSON.stringify` for encoding. - * - * @category string transformations - * @since 1.0.0 - */ -export const fromJson = ( - schema: Schema, - options?: JsonOptions -): Schema => compose(parseJson(string, options), schema) - -// --------------------------------------------- -// string constructors -// --------------------------------------------- - /** * @category string constructors * @since 1.0.0 @@ -2252,27 +2174,6 @@ export const ULID: Schema = string.pipe( }) ) -/** - * This schema allows removing whitespaces from the beginning and end of a string. - * - * @category string constructors - * @since 1.0.0 - */ -export const Trim: Schema = trim(string) - -/** - * The `ParseJson` schema offers a method to convert JSON strings into the `unknown` type using the underlying - * functionality of `JSON.parse`. It also employs `JSON.stringify` for encoding. - * - * @category string constructors - * @since 1.0.0 - */ -export const ParseJson: Schema = parseJson(string) - -// --------------------------------------------- -// number filters -// --------------------------------------------- - /** * @category type id * @since 1.0.0 @@ -2546,10 +2447,6 @@ export const nonNegative = ( options?: FilterAnnotations ): (self: Schema) => Schema => greaterThanOrEqualTo(0, options) -// --------------------------------------------- -// number transformations -// --------------------------------------------- - /** * Clamps a number between a minimum and a maximum value. * @@ -2567,47 +2464,38 @@ export const clamp = ) /** - * This combinator transforms a `string` into a `number` by parsing the string using the `Number` function. + * This schema transforms a `string` into a `number` by parsing the string using the `Number` function. * * It returns an error if the value can't be converted (for example when non-numeric characters are provided). * * The following special string values are supported: "NaN", "Infinity", "-Infinity". * - * @param self - The schema representing the input string - * - * @category number transformations + * @category number constructors * @since 1.0.0 */ -export const numberFromString = (self: Schema): Schema => { - return transformOrFail( - self, - number, - (s, _, ast) => { - if (s === "NaN") { - return ParseResult.succeed(NaN) - } - if (s === "Infinity") { - return ParseResult.succeed(Infinity) - } - if (s === "-Infinity") { - return ParseResult.succeed(-Infinity) - } - if (s.trim() === "") { - return ParseResult.fail(ParseResult.type(ast, s)) - } - const n = Number(s) - return Number.isNaN(n) - ? ParseResult.fail(ParseResult.type(ast, s)) - : ParseResult.succeed(n) - }, - (n) => ParseResult.succeed(String(n)), - { strict: false } - ) -} - -// --------------------------------------------- -// number constructors -// --------------------------------------------- +export const NumberFromString: Schema = transformOrFail( + string, + number, + (s, _, ast) => { + if (s === "NaN") { + return ParseResult.succeed(NaN) + } + if (s === "Infinity") { + return ParseResult.succeed(Infinity) + } + if (s === "-Infinity") { + return ParseResult.succeed(-Infinity) + } + if (s.trim() === "") { + return ParseResult.fail(ParseResult.type(ast, s)) + } + const n = Number(s) + return Number.isNaN(n) + ? ParseResult.fail(ParseResult.type(ast, s)) + : ParseResult.succeed(n) + }, + (n) => ParseResult.succeed(String(n)) +) /** * @category number constructors @@ -2651,18 +2539,6 @@ export const NonPositive: Schema = number.pipe(nonPositive()) */ export const NonNegative: Schema = number.pipe(nonNegative()) -/** - * This schema transforms a `string` into a `number` by parsing the string using the `Number` function. - * - * It returns an error if the value can't be converted (for example when non-numeric characters are provided). - * - * The following special string values are supported: "NaN", "Infinity", "-Infinity". - * - * @category number constructors - * @since 1.0.0 - */ -export const NumberFromString: Schema = numberFromString(string) - /** * @category type id * @since 1.0.0 @@ -2696,71 +2572,30 @@ export const JsonNumber: Schema = number.pipe( }) ) -// --------------------------------------------- -// boolean transformations -// --------------------------------------------- - /** - * Negates a boolean value - * * @category boolean transformations * @since 1.0.0 */ -export const not = (self: Schema): Schema => - transform( - self, - to(self), - (self) => !self, - (self) => !self - ) - -// --------------------------------------------- -// boolean constructors -// --------------------------------------------- - -/** - * @category boolean constructors - * @since 1.0.0 - */ -export const Not: Schema = not(boolean) - -// --------------------------------------------- -// symbol transformations -// --------------------------------------------- - -/** - * This combinator transforms a `string` into a `symbol`. - * - * @param self - The schema representing the input string - * - * @category symbol transformations - * @since 1.0.0 - */ -export const symbolFromString = (self: Schema): Schema => { - return transform( - self, - symbolFromSelf, - (s) => Symbol.for(s), - (sym) => sym.description, - { strict: false } - ) -} - -// --------------------------------------------- -// symbol constructors -// --------------------------------------------- +export const Not: Schema = transform( + boolean, + boolean, + (self) => !self, + (self) => !self +) /** * This schema transforms a `string` into a `symbol`. * - * @category symbol constructors + * @category symbol transformations * @since 1.0.0 */ -export const symbol: Schema = symbolFromString(string) - -// --------------------------------------------- -// bigint filters -// --------------------------------------------- +export const symbol: Schema = transform( + string, + symbolFromSelf, + (s) => Symbol.for(s), + (sym) => sym.description, + { strict: false } +) /** * @category type id @@ -2943,10 +2778,6 @@ export const nonPositiveBigint = ( options?: FilterAnnotations ): (self: Schema) => Schema => lessThanOrEqualToBigint(0n, options) -// --------------------------------------------- -// bigint transformations -// --------------------------------------------- - /** * Clamps a bigint between a minimum and a maximum value. * @@ -2964,77 +2795,28 @@ export const clampBigint = ) /** - * This combinator transforms a `string` into a `bigint` by parsing the string using the `BigInt` function. + * This schema transforms a `string` into a `bigint` by parsing the string using the `BigInt` function. * * It returns an error if the value can't be converted (for example when non-numeric characters are provided). * - * @param self - The schema representing the input string - * * @category bigint transformations * @since 1.0.0 */ -export const bigintFromString = (self: Schema): Schema => { - return transformOrFail( - self, - bigintFromSelf, - (s, _, ast) => { - if (s.trim() === "") { - return ParseResult.fail(ParseResult.type(ast, s)) - } - - return ParseResult.try({ - try: () => BigInt(s), - catch: () => ParseResult.parseError([ParseResult.type(ast, s)]) - }) - }, - (n) => ParseResult.succeed(String(n)), - { strict: false } - ) -} - -/** - * This combinator transforms a `number` into a `bigint` by parsing the number using the `BigInt` function. - * - * It returns an error if the value can't be safely encoded as a `number` due to being out of range. - * - * @param self - The schema representing the input number - * - * @category bigint transformations - * @since 1.0.0 - */ -export const bigintFromNumber = (self: Schema): Schema => { - return transformOrFail( - self, - bigintFromSelf, - (n, _, ast) => - ParseResult.try({ - try: () => BigInt(n), - catch: () => ParseResult.parseError([ParseResult.type(ast, n)]) - }), - (b, _, ast) => { - if (b > InternalBigInt.maxSafeInteger || b < InternalBigInt.minSafeInteger) { - return ParseResult.fail(ParseResult.type(ast, b)) - } - - return ParseResult.succeed(Number(b)) - }, - { strict: false } - ) -} - -// --------------------------------------------- -// bigint constructors -// --------------------------------------------- +export const bigint: Schema = transformOrFail( + string, + bigintFromSelf, + (s, _, ast) => { + if (s.trim() === "") { + return ParseResult.fail(ParseResult.type(ast, s)) + } -/** - * This schema transforms a `string` into a `bigint` by parsing the string using the `BigInt` function. - * - * It returns an error if the value can't be converted (for example when non-numeric characters are provided). - * - * @category bigint constructors - * @since 1.0.0 - */ -export const bigint: Schema = bigintFromString(string) + return ParseResult.try({ + try: () => BigInt(s), + catch: () => ParseResult.parseError([ParseResult.type(ast, s)]) + }) + }, + (n) => ParseResult.succeed(String(n)) +) /** * @category bigint constructors @@ -3097,14 +2879,25 @@ export const NonNegativeBigint: Schema = bigint.pipe( * * It returns an error if the value can't be safely encoded as a `number` due to being out of range. * - * @category bigint constructors + * @category bigint transformations * @since 1.0.0 */ -export const BigintFromNumber: Schema = bigintFromNumber(number) +export const BigintFromNumber: Schema = transformOrFail( + number, + bigintFromSelf, + (n, _, ast) => + ParseResult.try({ + try: () => BigInt(n), + catch: () => ParseResult.parseError([ParseResult.type(ast, n)]) + }), + (b, _, ast) => { + if (b > InternalBigInt.maxSafeInteger || b < InternalBigInt.minSafeInteger) { + return ParseResult.fail(ParseResult.type(ast, b)) + } -// --------------------------------------------- -// Secret -// --------------------------------------------- + return ParseResult.succeed(Number(b)) + } +) /** * @category Secret constructors @@ -3125,39 +2918,24 @@ export const SecretFromSelf: Schema = declare( } ) -/** - * A combinator that transforms a `string` into a `Secret`. - * - * @category Secret transformations - * @since 1.0.0 - */ -export const secret = ( - self: Schema -): Schema => - transform( - self, - SecretFromSelf, - (str) => Secret.fromString(str), - (secret) => Secret.value(secret), - { strict: false } - ) - -const _Secret: Schema = secret(string) +const _Secret: Schema = transform( + string, + SecretFromSelf, + (str) => Secret.fromString(str), + (secret) => Secret.value(secret), + { strict: false } +) export { /** * A schema that transforms a `string` into a `Secret`. * - * @category Secret constructors + * @category Secret transformations * @since 1.0.0 */ _Secret as Secret } -// --------------------------------------------- -// Duration constructors -// --------------------------------------------- - /** * @category Duration constructors * @since 1.0.0 @@ -3202,90 +2980,43 @@ export const DurationFromSelf: Schema = declare( } ) -// --------------------------------------------- -// Duration transformations -// --------------------------------------------- - -/** - * A combinator that transforms a `[number, number]` tuple into a `Duration`. - * - * @category Duration transformations - * @since 1.0.0 - */ -export const durationFromHrTime = ( - self: Schema -): Schema => - transform( - self, - DurationFromSelf, - ([seconds, nanos]) => Duration.nanos(BigInt(seconds) * BigInt(1e9) + BigInt(nanos)), - (duration) => Duration.toHrTime(duration), - { strict: false } - ) - -/** - * A combinator that transforms a `bigint` into a `Duration`. - * Treats the value as the number of nanoseconds. - * - * @category Duration transformations - * @since 1.0.0 - */ -export const durationFromNanos = ( - self: Schema -): Schema => - transformOrFail( - self, - DurationFromSelf, - (nanos) => ParseResult.succeed(Duration.nanos(nanos)), - (duration, _, ast) => - Option.match(Duration.toNanos(duration), { - onNone: () => ParseResult.fail(ParseResult.type(ast, duration)), - onSome: (val) => ParseResult.succeed(val) - }), - { strict: false } - ) - /** * A schema that transforms a `bigint` tuple into a `Duration`. * Treats the value as the number of nanoseconds. * - * @category Duration constructors + * @category Duration transformations * @since 1.0.0 */ export const DurationFromNanos: Schema< bigint, Duration.Duration -> = durationFromNanos(bigintFromSelf) - -/** - * A combinator that transforms a `number` into a `Duration`. - * Treats the value as the number of milliseconds. - * - * @category Duration transformations - * @since 1.0.0 - */ -export const durationFromMillis = ( - self: Schema -): Schema => - transform( - self, - DurationFromSelf, - (ms) => Duration.millis(ms), - (n) => Duration.toMillis(n), - { strict: false } - ) +> = transformOrFail( + bigintFromSelf, + DurationFromSelf, + (nanos) => ParseResult.succeed(Duration.nanos(nanos)), + (duration, _, ast) => + Option.match(Duration.toNanos(duration), { + onNone: () => ParseResult.fail(ParseResult.type(ast, duration)), + onSome: (val) => ParseResult.succeed(val) + }) +) /** * A schema that transforms a `number` tuple into a `Duration`. * Treats the value as the number of milliseconds. * - * @category Duration constructors + * @category Duration transformations * @since 1.0.0 */ export const DurationFromMillis: Schema< number, Duration.Duration -> = durationFromMillis(number) +> = transform( + number, + DurationFromSelf, + (ms) => Duration.millis(ms), + (n) => Duration.toMillis(n) +) const hrTime: Schema = tuple( NonNegative.pipe( @@ -3307,14 +3038,18 @@ const hrTime: Schema = tuple( [AST.DescriptionAnnotationId]: "a high resolution time tuple" })) -const _Duration: Schema = - durationFromHrTime(hrTime) +const _Duration: Schema = transform( + hrTime, + DurationFromSelf, + ([seconds, nanos]) => Duration.nanos(BigInt(seconds) * BigInt(1e9) + BigInt(nanos)), + (duration) => Duration.toHrTime(duration) +) export { /** * A schema that transforms a `[number, number]` tuple into a `Duration`. * - * @category Duration constructors + * @category Duration transformations * @since 1.0.0 */ _Duration as Duration @@ -3337,10 +3072,6 @@ export const clampDuration = { strict: false } ) -// --------------------------------------------- -// Duration filters -// --------------------------------------------- - /** * @category type id * @since 1.0.0 @@ -3461,10 +3192,6 @@ export const betweenDuration = ( }) ) -// --------------------------------------------- -// Uint8Array constructors -// --------------------------------------------- - /** * @category Uint8Array constructors * @since 1.0.0 @@ -3485,61 +3212,36 @@ export const Uint8ArrayFromSelf: Schema = declare( } ) -// --------------------------------------------- -// Uint8Array transformations -// --------------------------------------------- - -/** - * A combinator that transforms a `number` array into a `Uint8Array`. - * - * @category Uint8Array transformations - * @since 1.0.0 - */ -export const uint8ArrayFromNumbers = >( - self: Schema -): Schema => - transform( - self, - Uint8ArrayFromSelf, - (a) => Uint8Array.from(a), - (arr) => Array.from(arr), - { strict: false } - ) - -const _Uint8Array: Schema, Uint8Array> = uint8ArrayFromNumbers( +const _Uint8Array: Schema, Uint8Array> = transform( array(number.pipe( between(0, 255, { title: "8-bit unsigned integer", description: "a 8-bit unsigned integer" }) - )) + )), + Uint8ArrayFromSelf, + (a) => Uint8Array.from(a), + (arr) => Array.from(arr) ) export { /** * A schema that transforms a `number` array into a `Uint8Array`. * - * @category Uint8Array constructors + * @category Uint8Array transformations * @since 1.0.0 */ _Uint8Array as Uint8Array } -// --------------------------------------------- -// Encoding transformations -// --------------------------------------------- - -const makeEncodingTransform = ( +const makeEncodingTransformation = ( id: string, - decode: (s: A) => Either.Either, + decode: (s: string) => Either.Either, encode: (u: Uint8Array) => string, arbitrary: Arbitrary -) => -( - self: Schema -): Schema => +): Schema => transformOrFail( - self, + string, Uint8ArrayFromSelf, (s, _, ast) => Either.mapLeft( @@ -3556,72 +3258,37 @@ const makeEncodingTransform = ( })) /** - * Transforms a base64 `string` into a `Uint8Array`. - * - * @category encoding transformations - * @since 1.0.0 - */ -export const base64: (self: Schema) => Schema = - makeEncodingTransform( - "Base64", - Encoding.decodeBase64, - Encoding.encodeBase64, - (fc) => fc.base64String().map((s) => Either.getOrThrow(Encoding.decodeBase64(s))) - ) - -/** - * Transforms a base64url `string` into a `Uint8Array`. - * - * @category encoding transformations - * @since 1.0.0 - */ -export const base64url: (self: Schema) => Schema = - makeEncodingTransform( - "Base64Url", - Encoding.decodeBase64Url, - Encoding.encodeBase64Url, - (fc) => fc.base64String().map((s) => Either.getOrThrow(Encoding.decodeBase64Url(s))) - ) - -/** - * Transforms a hex `string` into a `Uint8Array`. - * - * @category encoding transformations - * @since 1.0.0 - */ -export const hex: (self: Schema) => Schema = - makeEncodingTransform( - "Hex", - Encoding.decodeHex, - Encoding.encodeHex, - (fc) => fc.hexaString().map((s) => Either.getOrThrow(Encoding.decodeHex(s))) - ) - -// --------------------------------------------- -// Encoding constructors -// --------------------------------------------- - -/** - * @category encoding constructors + * @category Encoding transformations * @since 1.0.0 */ -export const Base64: Schema = base64(string) +export const Base64: Schema = makeEncodingTransformation( + "Base64", + Encoding.decodeBase64, + Encoding.encodeBase64, + (fc) => fc.base64String().map((s) => Either.getOrThrow(Encoding.decodeBase64(s))) +) /** - * @category encoding constructors + * @category Encoding transformations * @since 1.0.0 */ -export const Base64Url: Schema = base64url(string) +export const Base64Url: Schema = makeEncodingTransformation( + "Base64Url", + Encoding.decodeBase64Url, + Encoding.encodeBase64Url, + (fc) => fc.base64String().map((s) => Either.getOrThrow(Encoding.decodeBase64Url(s))) +) /** - * @category encoding constructors + * @category Encoding transformations * @since 1.0.0 */ -export const Hex: Schema = hex(string) - -// --------------------------------------------- -// ReadonlyArray filters -// --------------------------------------------- +export const Hex: Schema = makeEncodingTransformation( + "Hex", + Encoding.decodeHex, + Encoding.encodeHex, + (fc) => fc.hexaString().map((s) => Either.getOrThrow(Encoding.decodeHex(s))) +) /** * @category type id @@ -3713,10 +3380,6 @@ export const itemsCount = ( }) ) -// --------------------------------------------- -// Date filters -// --------------------------------------------- - /** * @category type id * @since 1.0.0 @@ -3739,10 +3402,6 @@ export const validDate = }) ) -// --------------------------------------------- -// Date constructors -// --------------------------------------------- - const dateArbitrary = (): Arbitrary => (fc) => fc.date({ noInvalidDate: false }) const datePretty = (): Pretty.Pretty => (date) => `new Date(${JSON.stringify(date)})` @@ -3778,32 +3437,18 @@ export const DateFromSelf: Schema = declare( */ export const ValidDateFromSelf: Schema = DateFromSelf.pipe(validDate()) -// --------------------------------------------- -// Date transformations -// --------------------------------------------- - -/** - * A combinator that converts a `string` into a potentially **invalid** `Date` (e.g., `new Date("Invalid Date")` is not rejected). - * - * @category Date transformations - * @since 1.0.0 - */ -export const dateFromString = (self: Schema): Schema => - transform( - self, - DateFromSelf, - (s) => new Date(s), - (n) => n.toISOString(), - { strict: false } - ) - /** * Represents a schema that converts a `string` into a (potentially invalid) `Date` (e.g., `new Date("Invalid Date")` is not rejected). * - * @category Date constructors + * @category Date transformations * @since 1.0.0 */ -export const DateFromString: Schema = dateFromString(string) +export const DateFromString: Schema = transform( + string, + DateFromSelf, + (s) => new Date(s), + (n) => n.toISOString() +) const _Date: Schema = DateFromString.pipe(validDate()) @@ -3811,18 +3456,14 @@ export { /** * A schema that transforms a `string` into a **valid** `Date`, ensuring that invalid dates, such as `new Date("Invalid Date")`, are rejected. * - * @category Date constructors + * @category Date transformations * @since 1.0.0 */ _Date as Date } -// --------------------------------------------- -// Option transformations -// --------------------------------------------- - /** - * @category Option transformations + * @category Option utils * @since 1.0.0 */ export type OptionFrom = @@ -3928,12 +3569,8 @@ export const optionFromNullish = ( onNoneEncoding === null ? Option.getOrNull : Option.getOrUndefined ) -// --------------------------------------------- -// Either transformations -// --------------------------------------------- - /** - * @category Either transformations + * @category Either utils * @since 1.0.0 */ export type EitherFrom = @@ -4029,10 +3666,6 @@ export const either = ( }) ) -// --------------------------------------------- -// ReadonlyMap transformations -// --------------------------------------------- - const isMap = (u: unknown): u is Map => u instanceof Map const readonlyMapArbitrary = ( @@ -4065,6 +3698,7 @@ const readonlyMapEquivalence = ( } /** + * @category ReadonlyMap transformations * @since 1.0.0 */ export const readonlyMapFromSelf = ( @@ -4109,10 +3743,6 @@ export const readonlyMap = ( (map) => Array.from(map.entries()) ) -// --------------------------------------------- -// ReadonlySet transformations -// --------------------------------------------- - const isSet = (u: unknown): u is Set => u instanceof Set const readonlySetArbitrary = (item: Arbitrary): Arbitrary> => (fc) => @@ -4172,10 +3802,6 @@ export const readonlySet = (item: Schema): Schema, (set) => Array.from(set) ) -// --------------------------------------------- -// BigDecimal transformations -// --------------------------------------------- - const bigDecimalPretty = (): Pretty.Pretty => (val) => `BigDecimal(${BigDecimal.format(BigDecimal.normalize(val))})` @@ -4204,50 +3830,20 @@ export const BigDecimalFromSelf: Schema = declare( } ) -/** - * A schema that transforms a `number` into a `BigDecimal`. - * When encoding, this Schema will produce incorrect results if the BigDecimal exceeds the 64-bit range of a number. - * - * @category BigDecimal constructors - * @since 1.0.0 - */ -export const bigDecimalFromNumber = ( - self: Schema -): Schema => - transformOrFail( - self, - BigDecimalFromSelf, - (num) => ParseResult.succeed(BigDecimal.fromNumber(num)), - (val) => ParseResult.succeed(BigDecimal.unsafeToNumber(val)), - { strict: false } - ) - -/** - * A schema that transforms a `string` into a `BigDecimal`. - * - * @category BigDecimal constructors - * @since 1.0.0 - */ -export const bigDecimalFromString = ( - self: Schema -): Schema => - transformOrFail( - self, - BigDecimalFromSelf, - (num, _, ast) => - BigDecimal.fromString(num).pipe(Option.match({ - onNone: () => ParseResult.fail(ParseResult.type(ast, num)), - onSome: (val) => ParseResult.succeed(BigDecimal.normalize(val)) - })), - (val) => ParseResult.succeed(BigDecimal.format(BigDecimal.normalize(val))), - { strict: false } - ) - -const _BigDecimal: Schema = bigDecimalFromString(string) +const _BigDecimal: Schema = transformOrFail( + string, + BigDecimalFromSelf, + (num, _, ast) => + BigDecimal.fromString(num).pipe(Option.match({ + onNone: () => ParseResult.fail(ParseResult.type(ast, num)), + onSome: (val) => ParseResult.succeed(BigDecimal.normalize(val)) + })), + (val) => ParseResult.succeed(BigDecimal.format(BigDecimal.normalize(val))) +) export { /** - * @category BigDecimal constructors + * @category BigDecimal transformations * @since 1.0.0 */ _BigDecimal as BigDecimal @@ -4257,11 +3853,14 @@ export { * A schema that transforms a `number` into a `BigDecimal`. * When encoding, this Schema will produce incorrect results if the BigDecimal exceeds the 64-bit range of a number. * - * @category BigDecimal constructors + * @category BigDecimal transformations * @since 1.0.0 */ -export const BigDecimalFromNumber: Schema = bigDecimalFromNumber( - number +export const BigDecimalFromNumber: Schema = transformOrFail( + number, + BigDecimalFromSelf, + (num) => ParseResult.succeed(BigDecimal.fromNumber(num)), + (val) => ParseResult.succeed(BigDecimal.unsafeToNumber(val)) ) /** @@ -4516,10 +4115,6 @@ export const negateBigDecimal = ( { strict: false } ) -// --------------------------------------------- -// Chunk transformations -// --------------------------------------------- - const chunkArbitrary = (item: Arbitrary): Arbitrary> => (fc) => fc.array(item(fc)).map(Chunk.fromIterable) @@ -4569,10 +4164,6 @@ export const chunk = (item: Schema): Schema, Chunk. Chunk.toReadonlyArray ) -// --------------------------------------------- -// Data transformations -// --------------------------------------------- - const toData = > | ReadonlyArray>(a: A): Data.Data => Array.isArray(a) ? Data.array(a) : Data.struct(a) @@ -4633,10 +4224,6 @@ export const data = < { strict: false } ) -// --------------------------------------------- -// classes -// --------------------------------------------- - type MissingSelfGeneric = `Missing \`Self\` generic - use \`class Self extends ${Usage}()(${Params}{ ... })\`` @@ -4928,10 +4515,6 @@ const makeClass = ( } } -// --------------------------------------------- -// FiberId -// --------------------------------------------- - /** * @category FiberId * @since 1.0.0 @@ -4990,7 +4573,7 @@ const fiberIdPretty: Pretty.Pretty = (fiberId) => { } /** - * @category FiberId + * @category FiberId constructors * @since 1.0.0 */ export const FiberIdFromSelf: Schema = declare( @@ -5043,18 +4626,14 @@ const _FiberId: Schema = transform( export { /** - * @category FiberId + * @category FiberId transformations * @since 1.0.0 */ _FiberId as FiberId } -// --------------------------------------------- -// Cause -// --------------------------------------------- - /** - * @category Cause + * @category Cause utils * @since 1.0.0 */ export type CauseFrom = @@ -5147,7 +4726,7 @@ const causePretty = (error: Pretty.Pretty): Pretty.Pretty> } /** - * @category Cause + * @category Cause transformations * @since 1.0.0 */ export const causeFromSelf = ( @@ -5230,7 +4809,7 @@ const causeDefectPretty: Schema = transform( ) /** - * @category Cause + * @category Cause transformations * @since 1.0.0 */ export const cause = ( @@ -5244,12 +4823,8 @@ export const cause = ( causeEncode ) -// --------------------------------------------- -// Exit -// --------------------------------------------- - /** - * @category Exit + * @category Exit utils * @since 1.0.0 */ export type ExitFrom = @@ -5306,7 +4881,7 @@ const exitPretty = : `Exit.succeed(${value(exit.value)})` /** - * @category Exit + * @category Exit transformations * @since 1.0.0 */ export const exitFromSelf = ( @@ -5337,7 +4912,7 @@ export const exitFromSelf = ( ) /** - * @category Exit + * @category Exit transformations * @since 1.0.0 */ export const exit = ( diff --git a/test/AST/guards.test.ts b/test/AST/guards.test.ts index 896c64efd..b79e08d45 100644 --- a/test/AST/guards.test.ts +++ b/test/AST/guards.test.ts @@ -23,7 +23,7 @@ describe("AST/guards", () => { }) it("isTransform", () => { - expect(AST.isTransform(S.string.pipe(S.trim).ast)).toEqual(true) + expect(AST.isTransform(S.Trim.ast)).toEqual(true) expect(AST.isTransform(S.number.ast)).toEqual(false) }) diff --git a/test/ArrayFormatter.test.ts b/test/ArrayFormatter.test.ts index d08750184..576a6bfa1 100644 --- a/test/ArrayFormatter.test.ts +++ b/test/ArrayFormatter.test.ts @@ -126,8 +126,7 @@ describe("ArrayFormatter", () => { }) it("real world example", () => { - const Name = S.string.pipe( - S.trim, + const Name = S.Trim.pipe( S.minLength(2, { message: () => "We expect a name of at least 2 characters" }), S.maxLength(100, { message: () => "We expect a name with a maximum of 100 characters" }) ) diff --git a/test/Pretty.test.ts b/test/Pretty.test.ts index d7b23237c..fc11fdc6e 100644 --- a/test/Pretty.test.ts +++ b/test/Pretty.test.ts @@ -381,7 +381,7 @@ describe("Pretty", () => { }) it("Transform", () => { - const pretty = P.to(S.string.pipe(S.trim)) + const pretty = P.to(S.Trim) expect(pretty("a")).toEqual(`"a"`) }) diff --git a/test/Schema/allErrors.test.ts b/test/Schema/allErrors.test.ts index 73798aafa..2fd7d2fde 100644 --- a/test/Schema/allErrors.test.ts +++ b/test/Schema/allErrors.test.ts @@ -112,12 +112,6 @@ describe("Schema/allErrors option", () => { }) describe("encoding", () => { - // raises an error while encoding from a number if the string is not a char - const NumberFromChar = S.string.pipe(S.length(1), S.numberFromString) - - // raises an error while encoding if the string is not a char - const Char = S.string.pipe(S.length(1)) - describe("tuple", () => { it("unexpected indexes", async () => { const schema = S.tuple() @@ -130,7 +124,7 @@ describe("Schema/allErrors option", () => { }) it("wrong type for elements", async () => { - const schema = S.tuple(NumberFromChar, NumberFromChar) + const schema = S.tuple(Util.NumberFromChar, Util.NumberFromChar) await Util.expectEncodeFailure( schema, [10, 10], @@ -140,7 +134,7 @@ describe("Schema/allErrors option", () => { }) it("wrong type for rest", async () => { - const schema = S.array(NumberFromChar) + const schema = S.array(Util.NumberFromChar) await Util.expectEncodeFailure( schema, [10, 10], @@ -150,7 +144,10 @@ describe("Schema/allErrors option", () => { }) it("wrong type for values post rest elements", async () => { - const schema = S.array(S.string).pipe(S.element(NumberFromChar), S.element(NumberFromChar)) + const schema = S.array(S.string).pipe( + S.element(Util.NumberFromChar), + S.element(Util.NumberFromChar) + ) await Util.expectEncodeFailure( schema, [10, 10], @@ -162,7 +159,7 @@ describe("Schema/allErrors option", () => { describe("struct", () => { it("wrong type for values", async () => { - const schema = S.struct({ a: NumberFromChar, b: NumberFromChar }) + const schema = S.struct({ a: Util.NumberFromChar, b: Util.NumberFromChar }) await Util.expectEncodeFailure( schema, { a: 10, b: 10 }, @@ -174,7 +171,7 @@ describe("Schema/allErrors option", () => { describe("record", () => { it("all key errors", async () => { - const schema = S.record(Char, S.string) + const schema = S.record(Util.Char, S.string) await Util.expectEncodeFailure( schema, { aa: "a", bb: "bb" }, @@ -184,7 +181,7 @@ describe("Schema/allErrors option", () => { }) it("all value errors", async () => { - const schema = S.record(S.string, Char) + const schema = S.record(S.string, Util.Char) await Util.expectEncodeFailure( schema, { a: "aa", b: "bb" }, diff --git a/test/Schema/brand.test.ts b/test/Schema/brand.test.ts index 7e1911fe3..623933981 100644 --- a/test/Schema/brand.test.ts +++ b/test/Schema/brand.test.ts @@ -54,7 +54,7 @@ describe("Schema/brand", () => { }) it("the constructor should throw on invalid values", () => { - const Int = S.string.pipe(S.numberFromString, S.int(), S.brand("Int")) + const Int = S.NumberFromString.pipe(S.int(), S.brand("Int")) expect(Int(1)).toEqual(1) expect(() => Int(1.2)).toThrow( new Error(`error(s) found @@ -63,13 +63,13 @@ describe("Schema/brand", () => { }) it("option", () => { - const Int = S.string.pipe(S.numberFromString, S.int(), S.brand("Int")) + const Int = S.NumberFromString.pipe(S.int(), S.brand("Int")) expect(Int.option(1)).toEqual(Option.some(1)) expect(Int.option(1.2)).toEqual(Option.none()) }) it("either", () => { - const Int = S.string.pipe(S.numberFromString, S.int(), S.brand("Int")) + const Int = S.NumberFromString.pipe(S.int(), S.brand("Int")) expect(Int.either(1)).toEqual(Either.right(1)) expect(Int.either(1.2)).toEqual(Either.left([{ meta: [], @@ -78,7 +78,7 @@ describe("Schema/brand", () => { }) it("is", () => { - const Int = S.string.pipe(S.numberFromString, S.int(), S.brand("Int")) + const Int = S.NumberFromString.pipe(S.int(), S.brand("Int")) expect(Int.is(1)).toEqual(true) expect(Int.is(1.2)).toEqual(false) }) @@ -89,7 +89,7 @@ describe("Schema/brand", () => { const positive = (self: S.Schema) => self.pipe(S.positive(), S.brand("Positive")) - const PositiveInt = S.string.pipe(S.numberFromString, int, positive) + const PositiveInt = S.NumberFromString.pipe(int, positive) expect(PositiveInt.is(1)).toEqual(true) expect(PositiveInt.is(-1)).toEqual(false) @@ -98,7 +98,7 @@ describe("Schema/brand", () => { describe("decoding", () => { it("string brand", async () => { - const schema = S.string.pipe(S.numberFromString, S.int(), S.brand("Int")) + const schema = S.NumberFromString.pipe(S.int(), S.brand("Int")) await Util.expectParseSuccess(schema, "1", 1 as any) await Util.expectParseFailure( schema, @@ -109,7 +109,7 @@ describe("Schema/brand", () => { it("symbol brand", async () => { const Int = Symbol.for("Int") - const schema = S.string.pipe(S.numberFromString, S.int(), S.brand(Int)) + const schema = S.NumberFromString.pipe(S.int(), S.brand(Int)) await Util.expectParseSuccess(schema, "1", 1 as any) await Util.expectParseFailure( schema, diff --git a/test/Schema/compose.test.ts b/test/Schema/compose.test.ts index 21eff4b7d..7654bd375 100644 --- a/test/Schema/compose.test.ts +++ b/test/Schema/compose.test.ts @@ -4,9 +4,9 @@ import { describe, it } from "vitest" describe("Schema/compose", async () => { it("B = C", async () => { - const schema1 = S.compose(S.split(S.string, ","), S.array(S.NumberFromString)) + const schema1 = S.compose(S.split(","), S.array(S.NumberFromString)) await Util.expectParseSuccess(schema1, "1,2,3", [1, 2, 3]) - const schema2 = S.split(S.string, ",").pipe(S.compose(S.array(S.NumberFromString))) + const schema2 = S.split(",").pipe(S.compose(S.array(S.NumberFromString))) await Util.expectParseSuccess(schema2, "1,2,3", [1, 2, 3]) }) diff --git a/test/Schema/encodeOption.test.ts b/test/Schema/encodeOption.test.ts index 4c8af629f..ab59e5f0c 100644 --- a/test/Schema/encodeOption.test.ts +++ b/test/Schema/encodeOption.test.ts @@ -5,7 +5,7 @@ import { describe, expect, it } from "vitest" describe("Schema/encodeOption", () => { it("should return none for invalid values", () => { - const schema = S.string.pipe(S.maxLength(1), S.numberFromString) + const schema = S.string.pipe(S.maxLength(1), S.compose(S.NumberFromString)) expect(P.encodeOption(schema)(1)).toEqual(O.some("1")) expect(P.encodeOption(schema)(10)).toEqual(O.none()) }) diff --git a/test/Schema/encodeSync.test.ts b/test/Schema/encodeSync.test.ts index f6c408f12..9710ffdcc 100644 --- a/test/Schema/encodeSync.test.ts +++ b/test/Schema/encodeSync.test.ts @@ -1,13 +1,10 @@ import * as P from "@effect/schema/Parser" -import * as S from "@effect/schema/Schema" +import * as Util from "@effect/schema/test/util" import { describe, expect, it } from "vitest" -// raises an error while encoding from a number if the string is not a char -const NumberFromChar = S.string.pipe(S.length(1), S.numberFromString) - describe("Schema/encodeSync", () => { it("should raise an error for invalid values", () => { - const schema = NumberFromChar + const schema = Util.NumberFromChar expect(P.encodeSync(schema)(1)).toEqual("1") expect(() => P.encodeSync(schema)(10)).toThrow( new Error(`error(s) found diff --git a/test/Schema/exports.test.ts b/test/Schema/exports.test.ts index 0a662cf50..9795e962d 100644 --- a/test/Schema/exports.test.ts +++ b/test/Schema/exports.test.ts @@ -49,16 +49,5 @@ describe("Schema/exports", () => { expect(S.IncludesTypeId).exist expect(S.UUIDTypeId).exist expect(S.ULIDTypeId).exist - - expect(S.nullable).exist - - expect(S.partial).exist - expect(S.required).exist - - expect(S.numberFromString).exist - expect(S.dateFromString).exist - expect(S.trim).exist - expect(S.clamp).exist - expect(S.clampBigint).exist }) }) diff --git a/test/Schema/extend.test.ts b/test/Schema/extend.test.ts index abc62e27c..4796f14cb 100644 --- a/test/Schema/extend.test.ts +++ b/test/Schema/extend.test.ts @@ -271,12 +271,9 @@ describe("Schema/extend", () => { }) describe("encoding", () => { - // raises an error while encoding from a number if the string is not a char - const NumberFromChar = S.string.pipe(S.length(1), S.numberFromString) - it("struct + record(string, NumberFromChar)", async () => { const schema = S.struct({ a: S.number }).pipe( - S.extend(S.record(S.string, NumberFromChar)) + S.extend(S.record(S.string, Util.NumberFromChar)) ) await Util.expectEncodeSuccess(schema, { a: 1 }, { a: 1 }) await Util.expectEncodeSuccess(schema, { a: 1, b: 1 }, { a: 1, b: "1" }) @@ -285,7 +282,7 @@ describe("Schema/extend", () => { it("struct + record(symbol, NumberFromChar)", async () => { const b = Symbol.for("@effect/schema/test/b") const schema = S.struct({ a: S.number }).pipe( - S.extend(S.record(S.symbolFromSelf, NumberFromChar)) + S.extend(S.record(S.symbolFromSelf, Util.NumberFromChar)) ) await Util.expectEncodeSuccess(schema, { a: 1 }, { a: 1 }) await Util.expectEncodeSuccess(schema, { a: 1, [b]: 1 }, { a: 1, [b]: "1" }) diff --git a/test/Schema/fromJson.test.ts b/test/Schema/fromJson.test.ts deleted file mode 100644 index f202a8c30..000000000 --- a/test/Schema/fromJson.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/util" -import { describe, it } from "vitest" - -describe("Schema/fromJson", () => { - it("decoding", async () => { - const schema = S.fromJson(S.struct({ a: S.number })) - await Util.expectParseSuccess(schema, `{"a":1}`, { a: 1 }) - await Util.expectParseFailure( - schema, - `{"a"}`, - Util.isBun - ? `JSON Parse error: Expected ':' before value in object property definition` - : `Expected ':' after property name in JSON at position 4` - ) - await Util.expectParseFailure(schema, `{"a":"b"}`, `/a Expected number, actual "b"`) - }) - - it("reviver", async () => { - const schema = S.fromJson(S.struct({ a: S.number, b: S.string }), { - reviver: (key, value) => key === "a" ? value + 1 : value - }) - await Util.expectParseSuccess(schema, `{"a":1,"b":"b"}`, { a: 2, b: "b" }) - }) - - it("encoding", async () => { - const schema = S.ParseJson.pipe(S.compose(S.struct({ a: S.number }))) - await Util.expectEncodeSuccess(schema, { a: 1 }, `{"a":1}`) - }) - - it("replacer", async () => { - const schema = S.fromJson(S.struct({ a: S.number, b: S.string }), { replacer: ["b"] }) - await Util.expectEncodeSuccess( - schema, - { a: 1, b: "b" }, - `{"b":"b"}` - ) - }) - - it("space", async () => { - const schema = S.fromJson(S.struct({ a: S.number }), { space: 2 }) - await Util.expectEncodeSuccess( - schema, - { a: 1 }, - `{ - "a": 1 -}` - ) - }) -}) diff --git a/test/Schema/isSchema.test.ts b/test/Schema/isSchema.test.ts index 5597378a5..e57b48393 100644 --- a/test/Schema/isSchema.test.ts +++ b/test/Schema/isSchema.test.ts @@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest" describe("isSchema", () => { it("Schema", () => { expect(S.isSchema(S.string)).toBe(true) - expect(S.isSchema(S.numberFromString)).toBe(false) + expect(S.isSchema(S.parseJson)).toBe(false) }) it("BrandSchema", () => { diff --git a/test/Schema/parseJson.test.ts b/test/Schema/parseJson.test.ts index a7e9f72c0..258be03bf 100644 --- a/test/Schema/parseJson.test.ts +++ b/test/Schema/parseJson.test.ts @@ -2,62 +2,99 @@ import * as S from "@effect/schema/Schema" import * as Util from "@effect/schema/test/util" import { describe, it } from "vitest" -describe("Schema/parseJson", () => { - it("decoding", async () => { - const schema = S.ParseJson - await Util.expectParseSuccess(schema, "{}", {}) - await Util.expectParseSuccess(schema, `{"a":"b"}`, { "a": "b" }) - - await Util.expectParseFailure( - schema, - "", - Util.isBun ? `JSON Parse error: Unexpected EOF` : `Unexpected end of JSON input` - ) - await Util.expectParseFailure( - schema, - "a", - Util.isBun - ? `JSON Parse error: Unexpected identifier "a"` - : `Unexpected token 'a', "a" is not valid JSON` - ) - await Util.expectParseFailure( - schema, - "{", - Util.isBun - ? `JSON Parse error: Expected '}'` - : `Expected property name or '}' in JSON at position 1` - ) - }) +describe("Schema > parseJson", () => { + describe("parseJson()", () => { + it("decoding", async () => { + const schema = S.parseJson() + await Util.expectParseSuccess(schema, "{}", {}) + await Util.expectParseSuccess(schema, `{"a":"b"}`, { "a": "b" }) + + await Util.expectParseFailure( + schema, + "", + Util.isBun ? `JSON Parse error: Unexpected EOF` : `Unexpected end of JSON input` + ) + await Util.expectParseFailure( + schema, + "a", + Util.isBun + ? `JSON Parse error: Unexpected identifier "a"` + : `Unexpected token 'a', "a" is not valid JSON` + ) + await Util.expectParseFailure( + schema, + "{", + Util.isBun + ? `JSON Parse error: Expected '}'` + : `Expected property name or '}' in JSON at position 1` + ) + }) - it("encoding", async () => { - const schema = S.ParseJson - await Util.expectEncodeSuccess(schema, "a", `"a"`) - await Util.expectEncodeSuccess(schema, { a: "b" }, `{"a":"b"}`) - - const bad: any = { a: 0 } - bad["a"] = bad - await Util.expectEncodeFailure( - schema, - bad, - Util.isBun ? - `JSON.stringify cannot serialize cyclic structures.` : - `Converting circular structure to JSON + it("encoding", async () => { + const schema = S.parseJson() + await Util.expectEncodeSuccess(schema, "a", `"a"`) + await Util.expectEncodeSuccess(schema, { a: "b" }, `{"a":"b"}`) + + const bad: any = { a: 0 } + bad["a"] = bad + await Util.expectEncodeFailure( + schema, + bad, + Util.isBun ? + `JSON.stringify cannot serialize cyclic structures.` : + `Converting circular structure to JSON --> starting at object with constructor 'Object' --- property 'a' closes the circle` - ) + ) + }) + }) + + describe("parseJson(schema)", () => { + it("decoding", async () => { + const schema = S.parseJson(S.struct({ a: S.number })) + await Util.expectParseSuccess(schema, `{"a":1}`, { a: 1 }) + await Util.expectParseFailure( + schema, + `{"a"}`, + Util.isBun + ? `JSON Parse error: Expected ':' before value in object property definition` + : `Expected ':' after property name in JSON at position 4` + ) + await Util.expectParseFailure(schema, `{"a":"b"}`, `/a Expected number, actual "b"`) + }) + + it("encoding", async () => { + const schema = S.parseJson(S.struct({ a: S.number })) + await Util.expectEncodeSuccess(schema, { a: 1 }, `{"a":1}`) + }) }) - it("compose", async () => { - const schema = S.ParseJson.pipe(S.compose(S.struct({ a: S.number }))) - await Util.expectParseSuccess(schema, `{"a":1}`, { a: 1 }) - await Util.expectParseFailure( - schema, - `{"a"}`, - Util.isBun - ? `JSON Parse error: Expected ':' before value in object property definition` - : `Expected ':' after property name in JSON at position 4` - ) - await Util.expectParseFailure(schema, `{"a":"b"}`, `/a Expected number, actual "b"`) - await Util.expectEncodeSuccess(schema, { a: 1 }, `{"a":1}`) + describe("parseJson(schema, options)", () => { + it("reviver", async () => { + const schema = S.parseJson(S.struct({ a: S.number, b: S.string }), { + reviver: (key, value) => key === "a" ? value + 1 : value + }) + await Util.expectParseSuccess(schema, `{"a":1,"b":"b"}`, { a: 2, b: "b" }) + }) + + it("replacer", async () => { + const schema = S.parseJson(S.struct({ a: S.number, b: S.string }), { replacer: ["b"] }) + await Util.expectEncodeSuccess( + schema, + { a: 1, b: "b" }, + `{"b":"b"}` + ) + }) + + it("space", async () => { + const schema = S.parseJson(S.struct({ a: S.number }), { space: 2 }) + await Util.expectEncodeSuccess( + schema, + { a: 1 }, + `{ + "a": 1 +}` + ) + }) }) }) diff --git a/test/Schema/pipe.test.ts b/test/Schema/pipe.test.ts index 4444585ab..bdceba764 100644 --- a/test/Schema/pipe.test.ts +++ b/test/Schema/pipe.test.ts @@ -8,7 +8,7 @@ describe("Schema/pipe", () => { const positive = (self: S.Schema) => self.pipe(S.positive(), S.brand("Positive")) - const PositiveInt = S.string.pipe(S.numberFromString, int, positive) + const PositiveInt = S.NumberFromString.pipe(int, positive) expect(PositiveInt.is(1)).toEqual(true) expect(PositiveInt.is(-1)).toEqual(false) diff --git a/test/Schema/record.test.ts b/test/Schema/record.test.ts index 284c8649f..934c0b62b 100644 --- a/test/Schema/record.test.ts +++ b/test/Schema/record.test.ts @@ -223,10 +223,8 @@ describe("Schema/record", () => { }) describe("encoding", () => { - const Char = S.string.pipe(S.length(1)) - it("key error", async () => { - const schema = S.record(Char, S.string) + const schema = S.record(Util.Char, S.string) await Util.expectEncodeFailure( schema, { aa: "a" }, @@ -236,7 +234,7 @@ describe("Schema/record", () => { }) it("value error", async () => { - const schema = S.record(S.string, Char) + const schema = S.record(S.string, Util.Char) await Util.expectEncodeFailure( schema, { a: "aa" }, diff --git a/test/Schema/suspend.test.ts b/test/Schema/suspend.test.ts index aa1d6e4c9..e000d3921 100644 --- a/test/Schema/suspend.test.ts +++ b/test/Schema/suspend.test.ts @@ -88,9 +88,6 @@ describe("Schema/suspend", () => { }) describe("encoding", () => { - // raises an error while encoding from a number if the string is not a char - const NumberFromChar = S.string.pipe(S.length(1), S.numberFromString) - it("suspend", async () => { interface A { readonly a: number @@ -101,7 +98,7 @@ describe("Schema/suspend", () => { readonly as: ReadonlyArray } const schema: S.Schema = S.struct({ - a: NumberFromChar, + a: Util.NumberFromChar, as: S.array(S.suspend(() => schema)) }) await Util.expectEncodeSuccess(schema, { a: 1, as: [] }, { a: "1", as: [] }) diff --git a/test/Schema/tuple.test.ts b/test/Schema/tuple.test.ts index 5ed3adfab..edb9bd3f4 100644 --- a/test/Schema/tuple.test.ts +++ b/test/Schema/tuple.test.ts @@ -197,16 +197,13 @@ describe("Schema/tuple", () => { }) describe("encoding", () => { - // raises an error while encoding from a number if the string is not a char - const NumberFromChar = S.string.pipe(S.length(1), S.numberFromString) - it("empty", async () => { const schema = S.tuple() await Util.expectEncodeSuccess(schema, [], []) }) it("e", async () => { - const schema = S.tuple(NumberFromChar) + const schema = S.tuple(Util.NumberFromChar) await Util.expectEncodeSuccess(schema, [1], ["1"]) await Util.expectEncodeFailure( schema, @@ -217,14 +214,14 @@ describe("Schema/tuple", () => { }) it("e with undefined", async () => { - const schema = S.tuple(S.union(NumberFromChar, S.undefined)) + const schema = S.tuple(S.union(Util.NumberFromChar, S.undefined)) await Util.expectEncodeSuccess(schema, [1], ["1"]) await Util.expectEncodeSuccess(schema, [undefined], [undefined]) await Util.expectEncodeFailure(schema, [1, "b"] as any, `/1 is unexpected`) }) it("e?", async () => { - const schema = S.tuple().pipe(S.optionalElement(NumberFromChar)) + const schema = S.tuple().pipe(S.optionalElement(Util.NumberFromChar)) await Util.expectEncodeSuccess(schema, [], []) await Util.expectEncodeSuccess(schema, [1], ["1"]) await Util.expectEncodeFailure( @@ -236,7 +233,7 @@ describe("Schema/tuple", () => { }) it("e? with undefined", async () => { - const schema = S.tuple().pipe(S.optionalElement(S.union(NumberFromChar, S.undefined))) + const schema = S.tuple().pipe(S.optionalElement(S.union(Util.NumberFromChar, S.undefined))) await Util.expectEncodeSuccess(schema, [], []) await Util.expectEncodeSuccess(schema, [1], ["1"]) await Util.expectEncodeSuccess(schema, [undefined], [undefined]) @@ -244,20 +241,20 @@ describe("Schema/tuple", () => { }) it("e + e?", async () => { - const schema = S.tuple(S.string).pipe(S.optionalElement(NumberFromChar)) + const schema = S.tuple(S.string).pipe(S.optionalElement(Util.NumberFromChar)) await Util.expectEncodeSuccess(schema, ["a"], ["a"]) await Util.expectEncodeSuccess(schema, ["a", 1], ["a", "1"]) }) it("e + r", async () => { - const schema = S.tuple(S.string).pipe(S.rest(NumberFromChar)) + const schema = S.tuple(S.string).pipe(S.rest(Util.NumberFromChar)) await Util.expectEncodeSuccess(schema, ["a"], ["a"]) await Util.expectEncodeSuccess(schema, ["a", 1], ["a", "1"]) await Util.expectEncodeSuccess(schema, ["a", 1, 2], ["a", "1", "2"]) }) it("e? + r", async () => { - const schema = S.tuple().pipe(S.optionalElement(S.string), S.rest(NumberFromChar)) + const schema = S.tuple().pipe(S.optionalElement(S.string), S.rest(Util.NumberFromChar)) await Util.expectEncodeSuccess(schema, [], []) await Util.expectEncodeSuccess(schema, ["a"], ["a"]) await Util.expectEncodeSuccess(schema, ["a", 1], ["a", "1"]) @@ -265,7 +262,7 @@ describe("Schema/tuple", () => { }) it("r", async () => { - const schema = S.array(NumberFromChar) + const schema = S.array(Util.NumberFromChar) await Util.expectEncodeSuccess(schema, [], []) await Util.expectEncodeSuccess(schema, [1], ["1"]) await Util.expectEncodeSuccess(schema, [1, 2], ["1", "2"]) @@ -277,7 +274,7 @@ describe("Schema/tuple", () => { }) it("r + e", async () => { - const schema = S.array(S.string).pipe(S.element(NumberFromChar)) + const schema = S.array(S.string).pipe(S.element(Util.NumberFromChar)) await Util.expectEncodeSuccess(schema, [1], ["1"]) await Util.expectEncodeSuccess(schema, ["a", 1], ["a", "1"]) await Util.expectEncodeSuccess(schema, ["a", "b", 1], ["a", "b", "1"]) @@ -290,7 +287,7 @@ describe("Schema/tuple", () => { }) it("e + r + e", async () => { - const schema = S.tuple(S.string).pipe(S.rest(NumberFromChar), S.element(S.boolean)) + const schema = S.tuple(S.string).pipe(S.rest(Util.NumberFromChar), S.element(S.boolean)) await Util.expectEncodeSuccess(schema, ["a", true], ["a", true]) await Util.expectEncodeSuccess(schema, ["a", 1, true], ["a", "1", true]) await Util.expectEncodeSuccess(schema, ["a", 1, 2, true], ["a", "1", "2", true]) diff --git a/test/Schema/union.test.ts b/test/Schema/union.test.ts index 26b3761a3..66d01faa5 100644 --- a/test/Schema/union.test.ts +++ b/test/Schema/union.test.ts @@ -99,11 +99,8 @@ describe("Schema/literal", () => { }) describe("encoding", () => { - // raises an error while encoding from a number if the string is not a char - const NumberFromChar = S.string.pipe(S.length(1), S.numberFromString) - it("union", async () => { - const schema = S.union(S.string, NumberFromChar) + const schema = S.union(S.string, Util.NumberFromChar) await Util.expectEncodeSuccess(schema, "a", "a") await Util.expectEncodeSuccess(schema, 1, "1") }) diff --git a/test/boolean/not.test.ts b/test/boolean/not.test.ts index c7771d1b2..2acc67ae3 100644 --- a/test/boolean/not.test.ts +++ b/test/boolean/not.test.ts @@ -3,7 +3,7 @@ import * as Util from "@effect/schema/test/util" import { describe, it } from "vitest" describe("boolean/not", () => { - const schema = S.boolean.pipe(S.not) + const schema = S.Not it("decoding", async () => { await Util.expectParseSuccess(schema, true, false) await Util.expectParseSuccess(schema, false, true) diff --git a/test/string/lowercase.test.ts b/test/string/lowercase.test.ts index 39ca45cf2..49acc2d49 100644 --- a/test/string/lowercase.test.ts +++ b/test/string/lowercase.test.ts @@ -21,14 +21,14 @@ describe("string/lowercase", () => { }) it("decoding", async () => { - const schema = S.string.pipe(S.lowercase) + const schema = S.Lowercase await Util.expectParseSuccess(schema, "a", "a") await Util.expectParseSuccess(schema, "A ", "a ") await Util.expectParseSuccess(schema, " A ", " a ") }) it("encoding", async () => { - const schema = S.string.pipe(S.lowercase) + const schema = S.Lowercase await Util.expectEncodeSuccess(schema, "", "") await Util.expectEncodeSuccess(schema, "a", "a") diff --git a/test/string/split.test.ts b/test/string/split.test.ts index c3dc3a135..f15607be6 100644 --- a/test/string/split.test.ts +++ b/test/string/split.test.ts @@ -4,7 +4,7 @@ import { describe, it } from "vitest" describe("string/split", () => { it("split (data-last)", async () => { - const schema = S.string.pipe(S.split(",")) + const schema = S.split(",") Util.roundtrip(schema) @@ -25,10 +25,4 @@ describe("string/split", () => { await Util.expectEncodeSuccess(schema, ["a", ""], "a,") await Util.expectEncodeSuccess(schema, ["a", "b"], "a,b") }) - - it("split (data-first)", async () => { - const schema = S.split(S.string, ",") - - await Util.expectParseSuccess(schema, "a,b", ["a", "b"]) - }) }) diff --git a/test/string/trim.test.ts b/test/string/trim.test.ts index 758a43e7e..e72b3e051 100644 --- a/test/string/trim.test.ts +++ b/test/string/trim.test.ts @@ -21,16 +21,12 @@ describe("string/trim", () => { }) it("decoding", async () => { - const schema = S.string.pipe(S.minLength(1), S.trim) + const schema = S.string.pipe(S.minLength(1), S.compose(S.Trim)) await Util.expectParseSuccess(schema, "a", "a") await Util.expectParseSuccess(schema, "a ", "a") await Util.expectParseSuccess(schema, " a ", "a") + await Util.expectParseSuccess(schema, " ", "") - await Util.expectParseFailure( - schema, - " ", - `Expected a string at least 1 character(s) long, actual ""` - ) await Util.expectParseFailure( schema, "", @@ -39,7 +35,7 @@ describe("string/trim", () => { }) it("encoding", async () => { - const schema = S.string.pipe(S.minLength(1), S.trim) + const schema = S.string.pipe(S.minLength(1), S.compose(S.Trim)) await Util.expectEncodeSuccess(schema, "a", "a") await Util.expectEncodeFailure( diff --git a/test/string/uppercase.test.ts b/test/string/uppercase.test.ts index 0d9756afa..b14e22606 100644 --- a/test/string/uppercase.test.ts +++ b/test/string/uppercase.test.ts @@ -21,14 +21,14 @@ describe("string/uppercase", () => { }) it("decoding", async () => { - const schema = S.string.pipe(S.uppercase) + const schema = S.Uppercase await Util.expectParseSuccess(schema, "A", "A") await Util.expectParseSuccess(schema, "a ", "A ") await Util.expectParseSuccess(schema, " a ", " A ") }) it("encoding", async () => { - const schema = S.string.pipe(S.uppercase) + const schema = S.Uppercase await Util.expectEncodeSuccess(schema, "", "") await Util.expectEncodeSuccess(schema, "A", "A") diff --git a/test/util.ts b/test/util.ts index ae8c5e7d9..9af9e7b4c 100644 --- a/test/util.ts +++ b/test/util.ts @@ -356,3 +356,7 @@ export const sample = (schema: S.Schema, n: number) => { const arb = arbitrary(fc) console.log(JSON.stringify(fc.sample(arb, n), null, 2)) } + +export const NumberFromChar = S.string.pipe(S.length(1), S.compose(S.NumberFromString)) + +export const Char = S.string.pipe(S.length(1))